diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index e9f5b08..d9dc80f 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -13,6 +13,77 @@ #include "trigger.h" #include "car.h" +struct BulletInfo +{ + CreatureWeakPtr c; + MetaData::Equip* weapon_meta = nullptr; + MetaData::EquipUpgrade* weapon_upgrade_meta = nullptr; + MetaData::Equip* bullet_meta = nullptr; + a8::Vec2 bullet_born_pos; + a8::Vec2 bullet_dir; + float fly_distance = 0; + bool is_tank_skin = false; + int weapon_lv = 0; + int delay_time = 0; +}; + +static void InternalCreateBullet(BulletInfo& bullet_info) +{ + if (!bullet_info.c.Get()) { + return; + } + if (bullet_info.delay_time <= 0) { + int bullet_uniid = 0; + Creature* c = bullet_info.c.Get(); + if (c->room->BattleStarted() || + (c->room->GetGasData().gas_mode == GasJump && + !c->HasBuffEffect(kBET_Jump))) { + bullet_uniid = c->room->CreateBullet + (c, + c->shot_passenger, + bullet_info.weapon_meta, + bullet_info.weapon_upgrade_meta, + bullet_info.bullet_meta, + bullet_info.bullet_born_pos, + bullet_info.bullet_dir, + bullet_info.fly_distance, + bullet_info.is_tank_skin); + } + if (bullet_uniid == 0) { + bullet_uniid = c->room->AllocUniid(); + } + c->room->frame_event.AddBullet + (bullet_uniid, + c->GetWeakPtrRef(), + bullet_info.weapon_meta, + bullet_info.weapon_lv, + bullet_info.bullet_born_pos, + bullet_info.bullet_dir, + bullet_info.fly_distance); + } else { + BulletInfo* info_copy = new BulletInfo(); + *info_copy = bullet_info; + bullet_info.c.Get()->room->xtimer.AddDeadLineTimerAndAttach + ( + bullet_info.delay_time / FRAME_RATE_MS, + a8::XParams() + .SetSender(info_copy), + [] (const a8::XParams& param) + { + BulletInfo* info_copy = (BulletInfo*)param.sender.GetUserData(); + info_copy->delay_time = 0; + InternalCreateBullet(*info_copy); + }, + &bullet_info.c.Get()->xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + BulletInfo* info_copy = (BulletInfo*)param.sender.GetUserData(); + delete info_copy; + } + ); + } +} + void InternalShot(Creature* c, MetaData::Equip* weapon_meta, MetaData::EquipUpgrade* weapon_upgrade_meta, @@ -60,31 +131,20 @@ void InternalShot(Creature* c, } } bullet_dir.Rotate(bullet_angle / 180.0f); - int bullet_uniid = 0; - if (c->room->BattleStarted() || - (c->room->GetGasData().gas_mode == GasJump && - !c->HasBuffEffect(kBET_Jump))) { - bullet_uniid = c->room->CreateBullet - (c, - c->shot_passenger, - weapon_meta, - weapon_upgrade_meta, - bullet_meta, - bullet_born_pos, - bullet_dir, - fly_distance, - is_tank_skin); + { + BulletInfo bullet_info; + bullet_info.c = c->GetWeakPtrRef(); + bullet_info.weapon_meta = weapon_meta; + bullet_info.weapon_upgrade_meta = weapon_upgrade_meta; + bullet_info.bullet_meta = bullet_meta; + bullet_info.bullet_born_pos = bullet_born_pos; + bullet_info.bullet_dir = bullet_dir; + bullet_info.fly_distance = fly_distance; + bullet_info.is_tank_skin = is_tank_skin; + bullet_info.weapon_lv = weapon_lv; + bullet_info.delay_time = std::get<3>(tuple); + InternalCreateBullet(bullet_info); } - if (bullet_uniid == 0) { - bullet_uniid = c->room->AllocUniid(); - } - c->room->frame_event.AddBullet(bullet_uniid, - c->GetWeakPtrRef(), - weapon_meta, - weapon_lv, - bullet_born_pos, - bullet_dir, - fly_distance); } c->GetTrigger()->Shot(weapon_meta); if (weapon_meta->i->recoil_force() > 0.000001) { diff --git a/server/gameserver/metadata.cc b/server/gameserver/metadata.cc index 21cba3a..e554a7e 100644 --- a/server/gameserver/metadata.cc +++ b/server/gameserver/metadata.cc @@ -189,12 +189,14 @@ namespace MetaData std::vector strings2; a8::Split(str, strings2, ':'); assert(strings2.size() >= 2); - bullet_born_offset.push_back(std::make_tuple( - a8::XValue(strings2[0]).GetDouble(), - a8::XValue(strings2[1]).GetDouble(), - strings2.size() > 2 ? a8::XValue(strings2[2]).GetDouble() : 0 - ) - ); + bullet_born_offset.push_back + (std::make_tuple( + a8::XValue(strings2[0]).GetDouble(), + a8::XValue(strings2[1]).GetDouble(), + strings2.size() > 2 ? a8::XValue(strings2[2]).GetDouble() : 0, + strings2.size() > 3 ? a8::XValue(strings2[3]).GetInt() : 0 + ) + ); } } { diff --git a/server/gameserver/metadata.h b/server/gameserver/metadata.h index e3c96da..d9a7e49 100644 --- a/server/gameserver/metadata.h +++ b/server/gameserver/metadata.h @@ -72,7 +72,7 @@ namespace MetaData { const metatable::Equip* i = nullptr; - std::vector> bullet_born_offset; + std::vector> bullet_born_offset; std::vector> shoot_offsets; std::array volume = {}; int int_param1 = 0;