diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index 6755a6d..c7b14b0 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -2155,9 +2155,9 @@ bool Human::IsEnemy(Human* hum) } } -RoomObstacle* Human::SummonObstacle(int equip_id, const a8::Vec2& pos) +RoomObstacle* Human::SummonObstacle(int id, const a8::Vec2& pos) { - RoomObstacle* obstacle = room->CreateObstacle(equip_id, pos.x, pos.y); + RoomObstacle* obstacle = room->CreateObstacle(id, pos.x, pos.y); if (obstacle) { obstacle->master = this; room->xtimer.AddRepeatTimerAndAttach @@ -2172,6 +2172,20 @@ RoomObstacle* Human::SummonObstacle(int equip_id, const a8::Vec2& pos) }, &obstacle->xtimer_attacher.timer_list_ ); + + room->xtimer.AddRepeatTimerAndAttach + ( + SERVER_FRAME_RATE, + a8::XParams() + .SetSender(obstacle), + [] (const a8::XParams& param) + { + RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData(); + obstacle->UpdateTimerFunc(); + }, + &obstacle->xtimer_attacher.timer_list_ + ); + } else { abort(); } diff --git a/server/gameserver/human.h b/server/gameserver/human.h index 66edeca..b050e4d 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -303,7 +303,7 @@ class Human : public MoveableEntity HumanCar& GetCar() { return car_; } void DeadDrop(); bool IsEnemy(Human* hum); - RoomObstacle* SummonObstacle(int equip_id, const a8::Vec2& pos); + RoomObstacle* SummonObstacle(int id, const a8::Vec2& pos); protected: void _InternalUpdateMove(float speed); diff --git a/server/gameserver/roomobstacle.cc b/server/gameserver/roomobstacle.cc index dc29aa1..9a2ae3b 100644 --- a/server/gameserver/roomobstacle.cc +++ b/server/gameserver/roomobstacle.cc @@ -102,6 +102,7 @@ void RoomObstacle::ActiveTimerFunc() return; } if (!grid_list_) { + temp_through_ = true; grid_list_ = new std::set(); room->grid_service->GetAllCellsByXy(room, GetPos().x, GetPos().y, *grid_list_); } @@ -123,6 +124,119 @@ void RoomObstacle::ActiveTimerFunc() } ); if (!has_hum) { + temp_through_ = false; room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer()); } } + +void RoomObstacle::UpdateTimerFunc() +{ + if (grid_list_ && master) { + std::set human_list; + room->grid_service->TouchAllLayerHumanList + (room->GetRoomIdx(), + *grid_list_, + [this, &human_list] (Human* hum, bool& stop) + { + if (master->team_id != hum->team_id && TestCollision(room, hum)) { + human_list.insert(hum); + } + } + ); + for (Human* hum : human_list) { + + } + if (!human_list.empty()) { + Explosion(); + } + } +} + +void RoomObstacle::Explosion() +{ + float old_rad = self_collider_->rad; + if (self_collider_) { + self_collider_->rad = meta->i->damage_dia(); + } + if (meta->i->damage_dia() > 0.01f && + meta->i->damage() > 0.01f) { + std::set objects; + room->grid_service->TouchAllLayerHumanList + ( + room->GetRoomIdx(), + *grid_list_, + [this, &objects] (Human* hum, bool& stop) + { + if (master->team_id != hum->team_id && TestCollision(room, hum)) { + objects.insert(hum); + } + }); + room->grid_service->TouchAllLayerEntityList + ( + room->GetRoomIdx(), + *grid_list_, + [this, &objects] (Entity* entity, bool& stop) + { + switch (entity->GetEntityType()) { + case ET_Obstacle: + case ET_Building: + { + if (entity != this && TestCollision(room, entity)) { + objects.insert(entity); + } + } + break; + default: + { + } + break; + } + }); + a8::Vec2 bomb_pos = GetPos(); + room->frame_event.AddExplosionEx(master, meta->i->thing_id(), bomb_pos, 0); + for (auto& target : objects) { + switch (target->GetEntityType()) { + case ET_Player: + { + Human* hum = (Human*)target; + if (!hum->dead) { + float dmg = meta->i->damage(); + float def = hum->ability.def; + float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K); + hum->DecHP(finaly_dmg, VP_Mine, TEXT("battle_server_killer_mine", "地雷"), VW_Mine); + } + } + break; + case ET_Obstacle: + { + Obstacle* obstacle = (Obstacle*)target; + if (!obstacle->IsDead(room) && + obstacle->Attackable() && + !obstacle->IsTerminatorAirDropBox(room)) { + float dmg = meta->i->damage(); + float def = 0; + float finaly_dmg = dmg * (1 - def/MetaMgr::Instance()->K); + + obstacle->SetHealth(room, + std::max(0.0f, obstacle->GetHealth(room) - finaly_dmg)); + if (obstacle->GetHealth(room) <= 0.01f) { + obstacle->Die(room); + } + if (obstacle->IsDead(room)) { + #if 0 + bullet->player->DropItems(obstacle); + #endif + } + obstacle->BroadcastFullState(room); + } + } + break; + default: + break; + } + } + } + if (self_collider_) { + self_collider_->rad = old_rad; + } +} diff --git a/server/gameserver/roomobstacle.h b/server/gameserver/roomobstacle.h index 698899d..77c5bf6 100644 --- a/server/gameserver/roomobstacle.h +++ b/server/gameserver/roomobstacle.h @@ -18,6 +18,10 @@ class RoomObstacle : public Obstacle virtual bool IsTerminatorAirDropBox(Room* room) override { return is_terminator_airdrop_box; } virtual bool CanThroughable(Human* hum) override; void ActiveTimerFunc(); + void UpdateTimerFunc(); + +private: + void Explosion(); protected: bool temp_through_ = false; diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index d06f46d..e964e48 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -50,6 +50,7 @@ message MapThing optional int32 is_house = 11; //是否房间 optional int32 is_tree = 12; //是否树 optional int32 house_id = 13; //房间id + repeated int32 buff_list = 14; } message SafeArea