diff --git a/server/gameserver/hero.cc b/server/gameserver/hero.cc index 5311018..6860c38 100644 --- a/server/gameserver/hero.cc +++ b/server/gameserver/hero.cc @@ -255,8 +255,8 @@ void Hero::DecHP(float dec_hp, int killer_id, const std::string& killer_name, in void Hero::BeKill(int killer_id, const std::string& killer_name, int weapon_id) { dead = true; - if (meta->i->dead_drop() != 0) { - room->ScatterDrop(GetPos(), meta->i->dead_drop()); + if (meta->HasDrop()) { + room->ScatterDrop(GetPos(), meta->RandDrop()); } room->frame_event.AddDead(GetWeakPtrRef(), 0); room->xtimer.AddDeadLineTimerAndAttach diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index ac44139..575a488 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -578,6 +578,25 @@ namespace MetaData void Player::Init() { + { + int total_weight = 0; + std::vector strings; + a8::Split(i->dead_drop(), strings, '|'); + for (const std::string& str : strings) { + std::vector strings2; + a8::Split(str, strings2, ':'); + assert(strings2.size() == 2); + int drop_id = a8::XValue(strings2[0]); + int weight = a8::XValue(strings2[1]); + total_weight += weight; + dead_drop.push_back + (std::make_tuple( + drop_id, + total_weight + ) + ); + } + } { std::vector strings; a8::Split(i->volume(), strings, '|'); @@ -603,6 +622,20 @@ namespace MetaData } } + int Player::RandDrop() + { + if (HasDrop()) { + int total_weight = std::get<1>(dead_drop[dead_drop.size() - 1]); + int rnd = rand() % total_weight; + for (auto& tuple : dead_drop) { + if (rnd < std::get<1>(tuple)) { + return std::get<0>(tuple); + } + } + } + return 0; + } + void PlayerSkin::Init() { diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index a48d8a5..1de3438 100644 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -131,8 +131,11 @@ namespace MetaData std::array volume = {}; std::vector init_buffs; + std::vector> dead_drop; + bool HasDrop() { return !dead_drop.empty();}; void Init(); + int RandDrop(); }; struct PlayerSkin diff --git a/server/gameserver/roomobstacle.cc b/server/gameserver/roomobstacle.cc index 978a672..0619121 100644 --- a/server/gameserver/roomobstacle.cc +++ b/server/gameserver/roomobstacle.cc @@ -199,8 +199,12 @@ void RoomObstacle::SpecExplosion() room->grid_service->GetAllCellsByXy(room, GetPos().x, GetPos().y, *grid_list_); } a8::Vec2 bomb_born_offset = a8::Vec2::UP; - bomb_born_offset.Rotate(a8::RandAngle()); - bomb_born_offset = bomb_born_offset * a8::RandEx(1, std::max(2, meta->i->explosion_float())); + if (pos_list && explosion_times_ <= pos_list->size()) { + bomb_born_offset = pos_list->at(explosion_times_ - 1); + } else { + bomb_born_offset.Rotate(a8::RandAngle()); + 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)) { std::shared_ptr explosion = EntityFactory::Instance()->MakeExplosion(); @@ -241,12 +245,7 @@ void RoomObstacle::SpecExplosion() } } } - int total_explosion_times = meta->i->explosion_times(); - if (context_ability && context_ability->GetAttrAbs(kHAT_WeaponExplosionContinueTime) > 0.001f) { - total_explosion_times += context_ability->GetAttrAbs(kHAT_WeaponExplosionContinueTime) * 1000 / - meta->i->explosion_interval(); - } - if (explosion_times_ >= total_explosion_times) { + if (explosion_times_ >= total_explosion_times_) { if (room->xtimer.GetRunningTimer()) { room->xtimer.DeleteTimer(room->xtimer.GetRunningTimer()); } @@ -330,6 +329,11 @@ void RoomObstacle::Active() void RoomObstacle::ActiveSelfExplosion() { + total_explosion_times_ = meta->i->explosion_times(); + if (context_ability && context_ability->GetAttrAbs(kHAT_WeaponExplosionContinueTime) > 0.001f) { + total_explosion_times_ += context_ability->GetAttrAbs(kHAT_WeaponExplosionContinueTime) * 1000 / + meta->i->explosion_interval(); + } room->xtimer.AddDeadLineTimerAndAttach ( meta->i->time() / FRAME_RATE_MS, @@ -684,21 +688,35 @@ void RoomObstacle::InstallPreExplostionSummonTimer() { if (!meta->preexplosion_summon.empty()) { int base_time = 0; - for (auto& tuple : meta->preexplosion_summon) { - int time = std::get<0>(tuple); - int obstacle_id = std::get<1>(tuple); - room->xtimer.AddDeadLineTimerAndAttach - ( - (base_time + time) / FRAME_RATE_MS, - a8::XParams() - .SetSender(this) - .SetParam1(obstacle_id), - [] (const a8::XParams& param) - { - RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData(); - }, - &xtimer_attacher.timer_list_ - ); + pos_list = std::make_shared>(); + for (int i = 0; i < total_explosion_times_; ++i) { + for (auto& tuple : meta->preexplosion_summon) { + int time = std::get<0>(tuple); + int obstacle_id = std::get<1>(tuple); + room->xtimer.AddDeadLineTimerAndAttach + ( + (base_time + time) / FRAME_RATE_MS, + a8::XParams() + .SetSender(this) + .SetParam1(obstacle_id), + [] (const a8::XParams& param) + { + RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData(); + }, + &xtimer_attacher.timer_list_ + ); + }//end for tuple + { + a8::Vec2 bomb_born_offset = a8::Vec2::UP; + bomb_born_offset.Rotate(a8::RandAngle()); + 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)) { + pos_list->push_back(bomb_born_offset); + } else { + pos_list->push_back(a8::Vec2()); + } + } } base_time += meta->i->explosion_interval(); } diff --git a/server/gameserver/roomobstacle.h b/server/gameserver/roomobstacle.h index 7be8491..3553d55 100644 --- a/server/gameserver/roomobstacle.h +++ b/server/gameserver/roomobstacle.h @@ -66,6 +66,8 @@ protected: int explosion_times_ = 0; bool detached_ = false; std::map* hit_objects_ = nullptr; + std::shared_ptr> pos_list; + int total_explosion_times_ = 0; RoomObstacle(); diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index 9760a54..ed92562 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -222,7 +222,7 @@ message Player optional string ai_script = 26; optional string init_buffs = 27; optional int32 default_weapon = 28; - optional int32 dead_drop = 29; + optional string dead_drop = 29; optional int32 delay_delete = 39; optional int32 ai = 46; optional int32 delay_remove = 47;