diff --git a/server/gameserver/car.cc b/server/gameserver/car.cc index 082bebb..a0d9f33 100644 --- a/server/gameserver/car.cc +++ b/server/gameserver/car.cc @@ -14,6 +14,7 @@ #include "explosion.h" #include "obstacle.h" #include "ability.h" +#include "entityfactory.h" Car::Car():Creature() { @@ -406,8 +407,8 @@ void Car::BeKill(int killer_id, const std::string& killer_name, int weapon_id) passenger->RemoveBuffByEffectId(kBET_Passenger); room->frame_event.AddCarChg(passenger->GetWeakPtrRef()); } - Explosion explosion; - explosion.IndifferenceAttack( + std::shared_ptr explosion = EntityFactory::Instance()->MakeExplosion(); + explosion->IndifferenceAttack( room, GetPos(), meta->i->explosion_range(), diff --git a/server/gameserver/entityfactory.cc b/server/gameserver/entityfactory.cc index f17c9e4..883bd6d 100644 --- a/server/gameserver/entityfactory.cc +++ b/server/gameserver/entityfactory.cc @@ -12,6 +12,7 @@ #include "hero.h" #include "dummyentity.h" #include "mapblock.h" +#include "explosion.h" void EntityFactory::Init() { @@ -114,3 +115,9 @@ MapBlock* EntityFactory::MakeBlock(int entity_uniid) p->entity_type_ = ET_MapBlock; return p; } + +std::shared_ptr EntityFactory::MakeExplosion() +{ + std::shared_ptr e(new Explosion); + return e; +} diff --git a/server/gameserver/entityfactory.h b/server/gameserver/entityfactory.h index 042802a..c7128d3 100644 --- a/server/gameserver/entityfactory.h +++ b/server/gameserver/entityfactory.h @@ -11,6 +11,7 @@ class Car; class Hero; class DummyEntity; class MapBlock; +class Explosion; class EntityFactory : public a8::Singleton { private: @@ -32,6 +33,7 @@ class EntityFactory : public a8::Singleton Hero* MakeHero(int entity_uniid); DummyEntity* MakeDummy(int entity_uniid); MapBlock* MakeBlock(int entity_uniid); + std::shared_ptr MakeExplosion(); private: }; diff --git a/server/gameserver/explosion.cc b/server/gameserver/explosion.cc index 569a556..44dcebc 100644 --- a/server/gameserver/explosion.cc +++ b/server/gameserver/explosion.cc @@ -50,16 +50,8 @@ void Explosion::EnemyAndObstacleAttack(CreatureWeakPtr& sender, InternalAttack(); } -void Explosion::InternalAttack() +void Explosion::ProcDamage() { - if (explosion_range_ <= 0) { - return; - } - room_->frame_event.AddExplosionEx - (sender_, - 0, - center_, - explosion_effect_); std::set grid_list; room_->grid_service->GetAllCellsByXy ( @@ -85,7 +77,7 @@ void Explosion::InternalAttack() return; } if (type_ == kExplosionEnemyAndObstacle) { - if (sender_.Get()->IsProperTarget(c)) { + if (sender_.Get() && sender_.Get()->IsProperTarget(c)) { if (center_.Distance(c->GetPos()) < explosion_range_) { objects.insert(c); } @@ -128,6 +120,39 @@ void Explosion::InternalAttack() } } +void Explosion::InternalAttack() +{ + if (explosion_range_ <= 0) { + return; + } + room_->frame_event.AddExplosionEx + (sender_, + 0, + center_, + explosion_effect_); + + if (explosion_damage_delay_ <= 0) { + ProcDamage(); + } else { + std::shared_ptr* self = new std::shared_ptr(this); + room_->xtimer.AddDeadLineTimerAndAttach + (explosion_damage_delay_ / FRAME_RATE_MS, + a8::XParams() + .SetSender(self), + [] (const a8::XParams& param) + { + std::shared_ptr* self = (std::shared_ptr*)param.sender.GetUserData(); + (*self)->ProcDamage(); + }, + &room_->xtimer_attacher_.timer_list_, + [] (const a8::XParams& param) + { + std::shared_ptr* self = (std::shared_ptr*)param.sender.GetUserData(); + delete self; + }); + } +} + bool Explosion::IsPreBattleExplosion() { return create_frameno_ <= room_->GetBattleStartFrameNo() || room_->GetBattleStartFrameNo() == 0; diff --git a/server/gameserver/explosion.h b/server/gameserver/explosion.h index bee7045..28be2bc 100644 --- a/server/gameserver/explosion.h +++ b/server/gameserver/explosion.h @@ -3,7 +3,8 @@ #include "weakptr.h" class Room; -class Explosion +class EntityFactory; +class Explosion : public std::enable_shared_from_this { public: int exclude_uniid = 0; @@ -14,6 +15,7 @@ class Explosion long long GetSpecialDamageType() { return special_damage_type_; }; bool IsPreBattleExplosion(); int GetExplosionEffect() { return explosion_effect_; }; + void SetDmageDelay(int delay) { explosion_damage_delay_ = delay; }; void IndifferenceAttack(Room* room, const a8::Vec2& center, @@ -29,8 +31,10 @@ class Explosion long long special_damage_type = 0); void AddForceTarget(CreatureWeakPtr force_target); - private: +protected: + Explosion() {}; void InternalAttack(); + void ProcDamage(); private: int type_ = 0; @@ -39,8 +43,11 @@ class Explosion CreatureWeakPtr force_target_; float explosion_range_ = 0; int explosion_effect_ = 0; + int explosion_damage_delay_ = 0; float dmg_ = 0; a8::Vec2 center_; long long special_damage_type_ = 0; long long create_frameno_ = 0; + + friend class EntityFactory; }; diff --git a/server/gameserver/frag_mitask.cc b/server/gameserver/frag_mitask.cc index 28fc845..b180aab 100644 --- a/server/gameserver/frag_mitask.cc +++ b/server/gameserver/frag_mitask.cc @@ -9,6 +9,7 @@ #include "creature.h" #include "obstacle.h" #include "explosion.h" +#include "entityfactory.h" void FragMiTask::Done() { @@ -18,13 +19,13 @@ void FragMiTask::Done() center = bomb_pos; } - Explosion explosion; + std::shared_ptr explosion = EntityFactory::Instance()->MakeExplosion(); if (force_target.Get()) { - explosion.AddForceTarget(force_target); + explosion->AddForceTarget(force_target); } - explosion.EnemyAndObstacleAttack(sender, - center, - explosion_range, - gun_meta->i->explosion_effect(), - GetAtk()); + explosion->EnemyAndObstacleAttack(sender, + center, + explosion_range, + gun_meta->i->explosion_effect(), + GetAtk()); } diff --git a/server/gameserver/obstacle.cc b/server/gameserver/obstacle.cc index 97c15b4..6017fa8 100644 --- a/server/gameserver/obstacle.cc +++ b/server/gameserver/obstacle.cc @@ -13,6 +13,7 @@ #include "roomobstacle.h" #include "loot.h" #include "explosion.h" +#include "entityfactory.h" enum ObstacleDataFlags_e { @@ -915,13 +916,13 @@ bool Obstacle::ProcSpecEvent(Creature* c, ColliderComponent* collider) void Obstacle::ProcDieExplosion(Room* room) { if (meta->i->damage_dia() > 0.01f) { - Explosion explosion; - explosion.IndifferenceAttack( - room, - GetPos(), - meta->i->damage_dia(), - meta->i->explosion_effect(), - meta->i->damage() - ); + std::shared_ptr explosion = EntityFactory::Instance()->MakeExplosion(); + explosion->IndifferenceAttack( + room, + GetPos(), + meta->i->damage_dia(), + meta->i->explosion_effect(), + meta->i->damage() + ); } } diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index d6c3af6..464f1e4 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -864,6 +864,14 @@ void Player::_CMExecCommand(f8::MsgHdr& hdr, const cs::CMExecCommand& msg) #if DEBUG App::Instance()->debug_params[1] = a8::XValue(cmds[1]); #endif + } else if (cmd == "wudi") { + int buff_uniid = TryAddBuff(this, 1005); + if (buff_uniid != 0) { + Buff* buff = GetBuffByUniId(buff_uniid); + if (buff->remover_timer) { + room->xtimer.ModifyTimer(buff->remover_timer, SERVER_FRAME_RATE * 10000); + } + } } else if (cmd == "reset_skill" && cmds.size() >= 2) { int skill_id = a8::XValue(cmds[1]); Skill* skill = GetSkill(skill_id); diff --git a/server/gameserver/room.h b/server/gameserver/room.h index 2e1d414..ec2e724 100644 --- a/server/gameserver/room.h +++ b/server/gameserver/room.h @@ -79,6 +79,7 @@ public: a8::XTimer xtimer; Plane plane; a8::TimerAttacher timer_attacher; + a8::XTimerAttacher xtimer_attacher_; GridService* grid_service = nullptr; MapService* map_service = nullptr; MapInstance* map_instance = nullptr; @@ -337,7 +338,6 @@ private: long long alive_count_chged_frameno_ = 0; int human_alive_count_ = 0; MetaData::AirLine* airline_ = nullptr; - a8::XTimerAttacher xtimer_attacher_; size_t airdrop_times_ = 0; size_t airraid_times_ = 0; int level0room_born_point_uniid_ = 0; diff --git a/server/gameserver/roomobstacle.cc b/server/gameserver/roomobstacle.cc index 1f5f2ad..0c3d605 100644 --- a/server/gameserver/roomobstacle.cc +++ b/server/gameserver/roomobstacle.cc @@ -11,6 +11,7 @@ #include "mapservice.h" #include "roomobstacle.h" #include "explosion.h" +#include "entityfactory.h" RoomObstacle::RoomObstacle():Obstacle() { @@ -194,15 +195,15 @@ void RoomObstacle::SpecExplosion() bomb_born_offset = bomb_born_offset * a8::RandEx(1, std::max(2, meta->i->explosion_float())); a8::Vec2 bomb_pos = GetPos() + bomb_born_offset; if (room->grid_service->CanAdd(bomb_pos.x, bomb_pos.y)) { - Explosion explosion; - explosion.exclude_uniid = GetUniId(); - explosion.IndifferenceAttack( - room, - bomb_pos, - meta->i->damage_dia(), - meta->i->explosion_effect(), - meta->i->damage() - ); + std::shared_ptr explosion = EntityFactory::Instance()->MakeExplosion(); + explosion->exclude_uniid = GetUniId(); + explosion->IndifferenceAttack( + room, + bomb_pos, + meta->i->damage_dia(), + meta->i->explosion_effect(), + meta->i->damage() + ); if (master.Get()) { std::set target_list; room->grid_service->TraverseCreatures diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index db3557d..e3c2492 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -171,6 +171,7 @@ message Equip optional int32 cast_time = 64; optional int32 auto_switch_weapon_time = 65; optional int32 quality = 66; + optional int32 explosion_damage_delay = 67; optional string inventory_slot = 31; //库存槽位 optional int32 _inventory_slot = 32; //库存槽位