aozhiwei 64d87ad396 1
2023-04-01 13:36:09 +08:00

136 lines
4.1 KiB
C++

#include "precompile.h"
#include "airraid.h"
#include "room.h"
#include "player.h"
#include "obstacle.h"
#include "roomobstacle.h"
#include "mt/AirRaid.h"
#include "mt/SafeArea.h"
AirRaid::AirRaid(Room* room)
{
room_ = room;
}
void AirRaid::Init()
{
mt::AirRaid::Traverse
(
[this] (const mt::AirRaid* air_raid, bool& stop)
{
room_->xtimer.SetTimeoutEx
(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_);
});
}
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;
}
auto raid_cb =
[this, raid_meta, center]
(int event, const a8::Args* args)
{
if (a8::TIMER_EXEC_EVENT != event) {
return;
}
if (room_->IsGameOver()) {
return;
}
ExecOneRoundAirRaid(raid_meta, center);
};
room_->xtimer.SetTimeoutEx
(SERVER_FRAME_RATE * raid_meta->appear_time() / 1000.f,
raid_cb,
&room_->xtimer_attacher_);
}
bool AirRaid::GenAirRaidPos(const mt::AirRaid* raid_meta, glm::vec3& center)
{
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
float rnd_rad = rand() % std::max(room_->GetGasData().new_area_meta->rad(), 100);
glm::vec2 v2_center = room_->GetGasData().pos_new + glm::vec2(dir.x, dir.z) * (100.f + rnd_rad);
center = glm::vec3(v2_center.x, 0.0f, v2_center.y);
{
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) {
center = hum->GetPos().ToGlmVec3() + dir * (float)(200 + rand() % 500);
break;
}
}
}
#ifdef DEBUG1
if (humans.size() > 0) {
center = humans[0]->GetPos().ToGlmVec3();
}
#endif
}
room_->frame_event.AddAirRaid(raid_meta->appear_time(), center, raid_meta->rad());
}
void AirRaid::ExecOneRoundAirRaid(const mt::AirRaid* raid_meta, const glm::vec3& pos)
{
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 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, a8::RandAngle());
glm::vec3 pos = born_pos + dir * (50.0f + rand() % 100);
if (room_->grid_service->CanAdd(pos.x, pos.y)) {
for (auto bomb_id : raid_meta->_bomb_ids) {
RoomObstacle* obstacle = room_->CreateObstacle
(
bomb_id,
pos.x,
pos.y,
pos.z
);
obstacle->Active();
}
}
}
};
for (int i = 0; i < num; ++i) {
room_->xtimer.SetTimeoutEx
(delay / FRAME_RATE_MS,
bomb_cb,
&room_->xtimer_attacher_);
}
}
}