228 lines
6.8 KiB
C++
228 lines
6.8 KiB
C++
#include "precompile.h"
|
|
|
|
#include "airraid.h"
|
|
#include "room.h"
|
|
#include "player.h"
|
|
#include "obstacle.h"
|
|
#include "roomobstacle.h"
|
|
#include "mapinstance.h"
|
|
|
|
#include "mt/AirRaid.h"
|
|
#include "mt/SafeArea.h"
|
|
#include "mt/Map.h"
|
|
|
|
AirRaid::AirRaid(Room* room)
|
|
{
|
|
room_ = room;
|
|
}
|
|
|
|
void AirRaid::Init()
|
|
{
|
|
if (room_->IsPveRoom()) {
|
|
return;
|
|
}
|
|
mt::AirRaid::Traverse
|
|
(
|
|
[this] (const mt::AirRaid* air_raid, bool& stop)
|
|
{
|
|
auto timer_wp = room_->xtimer.SetTimeoutWpEx
|
|
(SERVER_FRAME_RATE * air_raid->time(),
|
|
[this, air_raid] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
if (!room_->IsGameOver()) {
|
|
Exec(air_raid->id());
|
|
}
|
|
}
|
|
},
|
|
&room_->xtimer_attacher_);
|
|
#ifdef DEBUG
|
|
timers_.push_back(timer_wp);
|
|
#endif
|
|
});
|
|
}
|
|
|
|
void AirRaid::Exec(int airraid_id)
|
|
{
|
|
const mt::AirRaid* raid_meta = mt::AirRaid::GetById(airraid_id);
|
|
if (!raid_meta) {
|
|
return;
|
|
}
|
|
glm::vec3 center;
|
|
if (!GenAirRaidPos(raid_meta, center)) {
|
|
return;
|
|
}
|
|
|
|
room_->xtimer.SetTimeoutEx
|
|
(SERVER_FRAME_RATE * raid_meta->appear_time() / 1000.f,
|
|
[this, raid_meta, center]
|
|
(int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
if (room_->IsGameOver()) {
|
|
return;
|
|
}
|
|
ExecOneRoundAirRaid(raid_meta, center);
|
|
}
|
|
},
|
|
&room_->xtimer_attacher_);
|
|
}
|
|
|
|
bool AirRaid::GenAirRaidPos(const mt::AirRaid* raid_meta, glm::vec3& center)
|
|
{
|
|
if (!room_->RandomSafeAreaPoint(center)) {
|
|
return false;
|
|
}
|
|
{
|
|
std::vector<Player*> humans;
|
|
room_->GetAlivePlayers(humans, room_->GetRoomMaxPlayerNum());
|
|
if (humans.size() > 3) {
|
|
std::random_shuffle(humans.begin(), humans.end());
|
|
for (Human* hum : humans) {
|
|
if (!hum->poisoning) {
|
|
glm::vec3 dir = GlmHelper::UP;
|
|
GlmHelper::RotateY(dir, a8::RandAngle());
|
|
center = hum->GetPos().ToGlmVec3() + dir * (float)(200 + rand() % 500);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
if (humans.size() > 0 && room_->debug_params.find(121) != room_->debug_params.end()) {
|
|
center = humans[0]->GetPos().ToGlmVec3();
|
|
}
|
|
#endif
|
|
}
|
|
{
|
|
glm::vec3 point;
|
|
bool ok = room_->FindWalkablePointWithOutHouse
|
|
(
|
|
center,
|
|
10,
|
|
10,
|
|
point
|
|
);
|
|
if (!ok) {
|
|
return false;
|
|
}
|
|
center = point;
|
|
}
|
|
room_->frame_event.AddAirRaid(raid_meta->appear_time(),
|
|
center,
|
|
raid_meta->rad(),
|
|
std::get<0>(raid_meta->_bombing_time)
|
|
);
|
|
return true;
|
|
}
|
|
|
|
void AirRaid::ExecOneRoundAirRaid(const mt::AirRaid* raid_meta, const glm::vec3& pos)
|
|
{
|
|
#if 1
|
|
int continue_time = std::get<0>(raid_meta->_bombing_time);
|
|
int interval_time = std::get<1>(raid_meta->_bombing_time);
|
|
int bomb_times = continue_time / std::max(1, interval_time);
|
|
for (int i = 0; i < bomb_times; ++i) {
|
|
glm::vec3 born_pos = pos;
|
|
int num = 1;
|
|
int delay = i * interval_time * 1000;
|
|
|
|
auto bomb_cb =
|
|
[this, raid_meta, num, delay, born_pos]
|
|
(int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
if (room_->IsGameOver()) {
|
|
return;
|
|
}
|
|
glm::vec3 center = born_pos;
|
|
room_->map_instance->Scale(center);
|
|
glm::vec3 point;
|
|
if (room_->map_instance->FindRandomPointAroundCircle
|
|
(
|
|
center,
|
|
100 * room_->GetMapMeta()->scale(),
|
|
point
|
|
)) {
|
|
room_->map_instance->UnScale(point);
|
|
for (auto bomb_id : raid_meta->_bomb_ids) {
|
|
RoomObstacle* obstacle = room_->CreateObstacle
|
|
(
|
|
bomb_id,
|
|
point.x,
|
|
point.y,
|
|
point.z
|
|
);
|
|
obstacle->Active();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
room_->xtimer.SetTimeoutEx
|
|
(delay / FRAME_RATE_MS,
|
|
bomb_cb,
|
|
&room_->xtimer_attacher_);
|
|
}
|
|
#else
|
|
for (auto& tuple : raid_meta->_raid_waves) {
|
|
int num = std::get<0>(tuple);
|
|
int delay = std::get<1>(tuple);
|
|
glm::vec3 born_pos = pos;
|
|
|
|
auto bomb_cb =
|
|
[this, raid_meta, num, delay, born_pos]
|
|
(int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
if (room_->IsGameOver()) {
|
|
return;
|
|
}
|
|
glm::vec3 center = born_pos;
|
|
room_->map_instance->Scale(center);
|
|
glm::vec3 point;
|
|
if (room_->map_instance->FindRandomPointAroundCircle
|
|
(
|
|
center,
|
|
100 * room_->GetMapMeta()->scale(),
|
|
point
|
|
)) {
|
|
room_->map_instance->UnScale(point);
|
|
for (auto bomb_id : raid_meta->_bomb_ids) {
|
|
RoomObstacle* obstacle = room_->CreateObstacle
|
|
(
|
|
bomb_id,
|
|
point.x,
|
|
point.y,
|
|
point.z
|
|
);
|
|
obstacle->Active();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
for (int i = 0; i < num; ++i) {
|
|
room_->xtimer.SetTimeoutEx
|
|
(delay / FRAME_RATE_MS,
|
|
bomb_cb,
|
|
&room_->xtimer_attacher_);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
void AirRaid::NextRaid()
|
|
{
|
|
for (size_t i = 0; i < timers_.size(); ++i) {
|
|
auto& timer_wp = timers_.at(i);
|
|
if (!timer_wp.expired()) {
|
|
room_->xtimer.ModifyTime(timer_wp, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|