diff --git a/server/gameserver/car.cc b/server/gameserver/car.cc index 61dee03..aadf1e4 100644 --- a/server/gameserver/car.cc +++ b/server/gameserver/car.cc @@ -487,8 +487,8 @@ float Car::GetMaxOil() void Car::DropItems(Obstacle* obstacle) { - if (obstacle->meta->i->drop() != 0) { - room->ScatterDrop(obstacle->GetPos(), obstacle->meta->i->drop()); + if (obstacle->meta->HasDrop()) { + room->ScatterDrop(obstacle->GetPos(), obstacle->meta->RandDrop()); } } diff --git a/server/gameserver/hero.cc b/server/gameserver/hero.cc index 37e3af3..5311018 100644 --- a/server/gameserver/hero.cc +++ b/server/gameserver/hero.cc @@ -389,7 +389,7 @@ void Hero::DropItems(Obstacle* obstacle) if (obstacle->IsEntitySubType(EST_RoomObstacle)) { is_treasure_box = ((RoomObstacle*)obstacle)->is_treasure_box; } - int drop_id = obstacle->meta->i->drop(); + int drop_id = obstacle->meta->RandDrop(); if (drop_id == 0) { return; } diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index e4d3cd6..da42f6c 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -2271,7 +2271,7 @@ void Human::DropItems(Obstacle* obstacle) if (obstacle->IsEntitySubType(EST_RoomObstacle)) { is_treasure_box = ((RoomObstacle*)obstacle)->is_treasure_box; } - int drop_id = obstacle->meta->i->drop(); + int drop_id = obstacle->meta->RandDrop(); if (drop_id == 0) { return; } @@ -2290,7 +2290,7 @@ void Human::DropItems(Obstacle* obstacle) } if (drop_id == 0) { - drop_id = obstacle->meta->i->drop(); + drop_id = obstacle->meta->RandDrop(); } room->ScatterDrop(obstacle->GetPos(), drop_id); if (is_treasure_box) { diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index 9ceed91..3830936 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -207,9 +207,36 @@ namespace MetaData { { std::vector strings; - a8::Split(i->buff_list(), strings, '|'); - for (const std::string& tmp_str : strings) { - buff_list.push_back(a8::XValue(tmp_str)); + a8::Split(i->preexplosion_summon(), strings, '|'); + for (const std::string& str : strings) { + std::vector strings2; + a8::Split(str, strings2, ':'); + assert(strings2.size() == 2); + preexplosion_summon.push_back + (std::make_tuple( + a8::XValue(strings2[0]), + a8::XValue(strings2[1]) + ) + ); + } + } + { + int total_weight = 0; + std::vector strings; + a8::Split(i->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; + drop.push_back + (std::make_tuple( + drop_id, + total_weight + ) + ); } } { @@ -269,6 +296,20 @@ namespace MetaData } } + int MapThing::RandDrop() + { + if (HasDrop()) { + int total_weight = std::get<1>(drop[drop.size() - 1]); + int rnd = rand() % total_weight; + for (auto& tuple : drop) { + if (rnd < std::get<1>(tuple)) { + return std::get<0>(tuple); + } + } + } + return 0; + } + void Equip::Init() { { diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index 86606b7..a48d8a5 100644 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -59,8 +59,12 @@ namespace MetaData float float_param2 = 0; long long sweep_tags = 0; std::vector param2_list; + std::vector> preexplosion_summon; + std::vector> drop; + bool HasDrop() { return !drop.empty();}; void Init(); + int RandDrop(); }; struct SafeArea diff --git a/server/gameserver/obstacle.cc b/server/gameserver/obstacle.cc index 990c2a9..aa0430e 100644 --- a/server/gameserver/obstacle.cc +++ b/server/gameserver/obstacle.cc @@ -577,8 +577,8 @@ void Obstacle::OnExplosionHit(Explosion* e) } if (IsDead(e->GetRoom())) { ProcDieExplosion(e->GetRoom()); - if (meta->i->drop() != 0) { - e->GetRoom()->ScatterDrop(GetPos(), meta->i->drop()); + if (meta->HasDrop()) { + e->GetRoom()->ScatterDrop(GetPos(), meta->RandDrop()); } if (meta->i->thing_type() == kObstacleOilBucket) { MetaData::MapThing* bomb_meta = MetaMgr::Instance()->GetMapThing(meta->int_param1); @@ -707,7 +707,7 @@ int Obstacle::OnCollisionTrigger(Creature* c, ColliderComponent* collider) case kCollisionHitDeadAndDrop: { if (c->room->GetGasData().gas_mode != GasInactive && - meta->i->drop() != 0 && + meta->HasDrop() && c->IsHuman()) { Die(c->room); c->DropItems(this); diff --git a/server/gameserver/roomobstacle.cc b/server/gameserver/roomobstacle.cc index 1950227..978a672 100644 --- a/server/gameserver/roomobstacle.cc +++ b/server/gameserver/roomobstacle.cc @@ -338,6 +338,7 @@ void RoomObstacle::ActiveSelfExplosion() [] (const a8::XParams& param) { RoomObstacle* obstacle = (RoomObstacle*)param.sender.GetUserData(); + obstacle->InstallPreExplostionSummonTimer(); obstacle->room->xtimer.AddRepeatTimerAndAttach ( obstacle->meta->i->explosion_interval() / FRAME_RATE_MS, @@ -678,3 +679,27 @@ void RoomObstacle::PushCollisionObjects() } }); } + +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_ + ); + } + base_time += meta->i->explosion_interval(); + } +} diff --git a/server/gameserver/roomobstacle.h b/server/gameserver/roomobstacle.h index afd4b79..7be8491 100644 --- a/server/gameserver/roomobstacle.h +++ b/server/gameserver/roomobstacle.h @@ -56,6 +56,7 @@ private: void SummonAirDropBox(int box_id); void ProcKeepRangeBuff(); void DetachFromMaster(); + void InstallPreExplostionSummonTimer(); protected: RoomObstacleWeakPtr weak_ptr_; diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index 53fa69f..9760a54 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -51,7 +51,7 @@ message MapThing optional int32 hp = 5; //生命 optional float damage = 6; //伤害 optional float damage_dia = 7; //伤害半径 - optional int32 drop = 8; //掉落 + optional string drop = 8; //掉落 optional int32 is_door = 10; //是否门 optional int32 is_house = 11; //是否房间 optional int32 is_tree = 12; //是否树 @@ -61,6 +61,7 @@ message MapThing optional int32 explosion_interval = 18; optional int32 explosion_times = 19; optional int32 explosion_float = 20; + optional string preexplosion_summon = 35; optional string monster_list = 21; optional string special_damage_type = 22; optional string receive_special_damage_type = 23;