diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index acc1564..a38eec7 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -869,10 +869,7 @@ void Creature::ProcBuffEffect(Creature* caster, Buff* buff) case kBET_SummonHero: { if (!dead) { - SummonHero(buff, - GetPos(), - GetMoveDir(), - buff->meta->hero_infos); + SummonHero(buff, GetPos(), GetMoveDir()); } } break; @@ -1509,8 +1506,12 @@ void Creature::CheckSpecObject() #endif } -RoomObstacle* Creature::SummonObstacle(Buff* buff, int id, const a8::Vec2& pos) +void Creature::SummonObstacle(Buff* buff, int id, const a8::Vec2& pos) { + buff->meta->int_param2 = 2; + if (buff->meta->int_param2 > 0) { + RemoveSurplusObstacle(buff->meta->i->buff_id(), id, buff->meta->int_param2); + } RoomObstacle* obstacle = room->CreateObstacle(id, pos.x, pos.y); if (obstacle) { obstacle->master.Attach(this); @@ -1521,7 +1522,6 @@ RoomObstacle* Creature::SummonObstacle(Buff* buff, int id, const a8::Vec2& pos) } else { abort(); } - return obstacle; } bool Creature::CollisonDetection() @@ -1645,14 +1645,15 @@ void Creature::ResetAllSkillCd() void Creature::SummonHero(Buff* buff, const a8::Vec2& pos, - const a8::Vec2& dir, - std::vector>& infos) + const a8::Vec2& dir + ) { - for (auto& info : infos) { + for (auto& info : buff->meta->hero_infos) { int through_wall = std::get<0>(info); float x = std::get<1>(info); float y = std::get<2>(info) ; int hero_id = std::get<3>(info); + int num = std::get<4>(info); MetaData::Player* hero_meta = MetaMgr::Instance()->GetPlayer(hero_id); if (hero_meta && !dead) { for (int i = 0; i < 4; ++i) { @@ -1671,6 +1672,7 @@ void Creature::SummonHero(Buff* buff, hero_pos, &collider )) { + RemoveSurplusHero(buff->meta->i->buff_id(), hero_id, num); Hero* hero = room->CreateHero (this, hero_meta, diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index 2aca8d7..b534a3f 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -153,11 +153,8 @@ class Creature : public MoveableEntity void CheckSpecObject(); bool CollisonDetection(); - RoomObstacle* SummonObstacle(Buff* buff, int id, const a8::Vec2& pos); - void SummonHero(Buff* buff, - const a8::Vec2& pos, - const a8::Vec2& dir, - std::vector>& infos); + void SummonObstacle(Buff* buff, int id, const a8::Vec2& pos); + void SummonHero(Buff* buff, const a8::Vec2& pos, const a8::Vec2& dir); void FillSkillCasterState(SkillCasterState* caster_state); void RecoverSkillCasterState(SkillCasterState* caster_state); CreatureWeakPtr AllocWeakPtr(); diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index 46864a1..3a6be1f 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -732,9 +732,10 @@ namespace MetaData float x = a8::XValue(strings2[1]).GetDouble(); float y = a8::XValue(strings2[2]).GetDouble(); int hero_id = a8::XValue(strings2[3]); + int num = strings2.size() > 4 ? a8::XValue(strings2[4]).GetInt() : 10000; hero_infos.push_back ( - std::make_tuple(through_wall, x, y, hero_id) + std::make_tuple(through_wall, x, y, hero_id, num) ); } } diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index 5862ac9..39aa66b 100755 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -192,7 +192,7 @@ namespace MetaData std::vector>>> batch_add_list; std::vector>> post_remove_action; std::set immune_buffeffect; - std::vector> hero_infos; + std::vector> hero_infos; }; struct SkillPhase diff --git a/server/gameserver/obstacle.h b/server/gameserver/obstacle.h index 9387a2c..de88ad2 100644 --- a/server/gameserver/obstacle.h +++ b/server/gameserver/obstacle.h @@ -54,7 +54,7 @@ class Obstacle : public Entity void IncDoorOpenTimes(Room* room); float GetHealth(Room* room); void SetHealth(Room* room, float value); - void Die(Room* room); + virtual void Die(Room* room); int GetTeamId(Room* room); void SetTeamId(Room* room, int team_id); int GetMasterId(Room* room); diff --git a/server/gameserver/room.cc b/server/gameserver/room.cc index 7a15df0..0bee13a 100644 --- a/server/gameserver/room.cc +++ b/server/gameserver/room.cc @@ -636,48 +636,65 @@ Hero* Room::CreateHero(Creature* master, } void Room::RemoveObjectLater(RoomEntity* entity) +{ + InternalRemoveObjectLater(entity, entity->xtimer_attacher); +} + +void Room::RemoveObjectLater(RoomObstacle* entity) +{ + InternalRemoveObjectLater(entity, entity->xtimer_attacher); +} + +void Room::InternalRemoveObjectLater(Entity* entity, a8::XTimerAttacher& xtimer_attacher) { auto remove_func = [] (const a8::XParams& param) { - RoomEntity* entity = (RoomEntity*)param.sender.GetUserData(); + Entity* entity = (Entity*)param.sender.GetUserData(); + Room* room = (Room*)param.param1.GetUserData(); switch (entity->GetEntityType()) { case ET_Bullet: { - entity->room->RemoveFromMoveableHash((Bullet*)entity); - entity->room->grid_service->DelBullet((Bullet*)entity); + room->RemoveFromMoveableHash((Bullet*)entity); + room->grid_service->DelBullet((Bullet*)entity); } break; case ET_Loot: { - entity->BroadcastDeleteState(entity->room); - entity->room->grid_service->DelRoomEntity(entity->room, entity); + entity->BroadcastDeleteState(room); + room->grid_service->DelRoomEntity(room, entity); } break; case ET_Player: { - entity->room->RemoveFromMoveableHash((Human*)entity); - entity->room->RemoveFromHuamnHash((Human*)entity); + room->RemoveFromMoveableHash((Human*)entity); + room->RemoveFromHuamnHash((Human*)entity); } break; case ET_Car: { #if 0 - entity->RemoveFromAroundPlayers(entity->room); - entity->BroadcastDeleteState(entity->room); - entity->room->grid_service->RemoveCreature((Car*)entity); + RemoveFromAroundPlayers(entity->room); + BroadcastDeleteState(entity->room); + room->grid_service->RemoveCreature((Car*)entity); #endif - entity->room->RemoveFromMoveableHash((Car*)entity); + room->RemoveFromMoveableHash((Car*)entity); } break; case ET_Hero: { #if 0 - entity->BroadcastDeleteState(entity->room); - entity->RemoveFromAroundPlayers(entity->room); - entity->room->grid_service->RemoveCreature((Hero*)entity); + BroadcastDeleteState(entity->room); + RemoveFromAroundPlayers(entity->room); + room->grid_service->RemoveCreature((Hero*)entity); #endif - entity->room->RemoveFromMoveableHash((Hero*)entity); + room->RemoveFromMoveableHash((Hero*)entity); + } + break; + case ET_Obstacle: + { + entity->BroadcastDeleteState(room); + room->grid_service->DelRoomEntity(room, entity); } break; default: @@ -686,7 +703,7 @@ void Room::RemoveObjectLater(RoomEntity* entity) } break; } - entity->room->RemoveFromEntityHash(entity); + room->RemoveFromEntityHash(entity); #ifdef DEBUG #if 0 a8::UdpLog::Instance()->Debug @@ -701,11 +718,12 @@ void Room::RemoveObjectLater(RoomEntity* entity) #endif delete entity; }; - xtimer.AddDeadLineTimerAndAttach(0, + xtimer.AddDeadLineTimerAndAttach(2, a8::XParams() - .SetSender(entity), + .SetSender(entity) + .SetParam1(this), remove_func, - &entity->xtimer_attacher.timer_list_); + &xtimer_attacher.timer_list_); } void Room::OnHumanDie(Human* hum) diff --git a/server/gameserver/room.h b/server/gameserver/room.h index 4944178..68d33ad 100644 --- a/server/gameserver/room.h +++ b/server/gameserver/room.h @@ -91,6 +91,7 @@ public: Human* FindEnemy(Human* hum); void RemoveObjectLater(RoomEntity* entity); + void RemoveObjectLater(RoomObstacle* entity); void FillSMJoinedNotify(Player* self_hum, cs::SMJoinedNotify& msg); @@ -261,6 +262,7 @@ private: size_t GetRoomMaxPlayerNum(); void InitAndroidAI(); void ForwardGasRing(int n); + void InternalRemoveObjectLater(Entity* entity, a8::XTimerAttacher& entity_xtimer_attacher); #ifdef DEBUG void InitDebugInfo(); diff --git a/server/gameserver/roomobstacle.cc b/server/gameserver/roomobstacle.cc index cb62bc7..d6779a5 100644 --- a/server/gameserver/roomobstacle.cc +++ b/server/gameserver/roomobstacle.cc @@ -31,6 +31,12 @@ RoomObstacle::~RoomObstacle() #endif room->map_service->RemoveCollider(collider); } + if (!detached_) { + if (master.Get()) { + master.Get()->SlaveOnRemove(this); + } + detached_ = true; + } if (!grid_list_) { A8_SAFE_DELETE(grid_list_); } @@ -445,5 +451,25 @@ void RoomObstacle::ActivePosionGas() void RoomObstacle::DetachFromMaster() { - + if (!detached_) { + detached_ = true; + if (master.Get()) { + xtimer_attacher.ClearTimerList(); + master.Get()->SlaveOnRemove(this); + room->grid_service->DelRoomEntity(room, this); + if (!IsDead(room)) { + Die(room); + BroadcastFullState(room); + } + room->RemoveObjectLater(this); + } + } +} + +void RoomObstacle::Die(Room* room) +{ + if (!IsDead(room)) { + Obstacle::Die(room); + DetachFromMaster(); + } } diff --git a/server/gameserver/roomobstacle.h b/server/gameserver/roomobstacle.h index 4acf2eb..abf451f 100644 --- a/server/gameserver/roomobstacle.h +++ b/server/gameserver/roomobstacle.h @@ -22,6 +22,7 @@ class RoomObstacle : public Obstacle void UpdateTimerFunc(); void Active(); void DetachFromMaster(); + virtual void Die(Room* room) override; private: void Explosion(); @@ -35,6 +36,7 @@ protected: bool temp_through_ = false; std::set* grid_list_ = nullptr; int explosion_times_ = 0; + bool detached_ = false; RoomObstacle();