From 5340384caacd68f28e266acd37903a016d55fed4 Mon Sep 17 00:00:00 2001 From: aozhiwei Date: Thu, 12 Aug 2021 11:18:49 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=8A=A8=E5=88=87?= =?UTF-8?q?=E6=9E=AA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/gameserver/creature.cc | 217 +++++++++++++++++------- server/gameserver/creature.h | 3 + server/tools/protobuild/metatable.proto | 1 + 3 files changed, 163 insertions(+), 58 deletions(-) diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index 4b553b5..99adaad 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -1640,6 +1640,7 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) SendDebugMsg(a8::Format("使用武器 %s slot:%d", {GetCurrWeapon()->meta->i->name(), slot_id})); } #endif + bool auto_switch_weapon = false; switch (slot_id) { case IS_FRAG: //手雷 case IS_SMOKE: //烟雾弹 @@ -1652,18 +1653,7 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) DecInventory(slot_id, 1); ++GetCurrWeapon()->ammo; } else { - int weapon_idx = GetCurrWeapon()->weapon_idx; - *GetCurrWeapon() = Weapon(); - GetCurrWeapon()->weapon_idx = weapon_idx; - Weapon* next_weapon = ChooseNextWeapon(slot_id, SPEC1_IS_BEGIN, SPEC1_IS_END); - if (!next_weapon) { - next_weapon = ChooseNextWeapon(SPEC2_IS_BEGIN, SPEC2_IS_BEGIN, SPEC2_IS_END); - } - if (!next_weapon) { - next_weapon = AutoChgWeapon(); - } - SetCurrWeapon(next_weapon); - AutoLoadingBullet(); + auto_switch_weapon = true; } } need_sync_active_player = true; @@ -1683,18 +1673,7 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) DecInventory(slot_id, 1); ++GetCurrWeapon()->ammo; } else { - int weapon_idx = GetCurrWeapon()->weapon_idx; - *GetCurrWeapon() = Weapon(); - GetCurrWeapon()->weapon_idx = weapon_idx; - Weapon* next_weapon = ChooseNextWeapon(slot_id, SPEC2_IS_BEGIN, SPEC2_IS_END); - if (!next_weapon) { - next_weapon = ChooseNextWeapon(SPEC1_IS_BEGIN, SPEC1_IS_BEGIN, SPEC1_IS_END); - } - if (!next_weapon) { - next_weapon = AutoChgWeapon(); - } - SetCurrWeapon(next_weapon); - AutoLoadingBullet(); + auto_switch_weapon = true; } } need_sync_active_player = true; @@ -1714,18 +1693,7 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) DecInventory(slot_id, 1); ++GetCurrWeapon()->ammo; } else { - int weapon_idx = GetCurrWeapon()->weapon_idx; - *GetCurrWeapon() = Weapon(); - GetCurrWeapon()->weapon_idx = weapon_idx; - Weapon* next_weapon = ChooseNextWeapon(slot_id, SPEC3_IS_BEGIN, SPEC3_IS_END); - if (!next_weapon) { - next_weapon = ChooseNextWeapon(SPEC1_IS_BEGIN, SPEC1_IS_BEGIN, SPEC1_IS_END); - } - if (!next_weapon) { - next_weapon = AutoChgWeapon(); - } - SetCurrWeapon(next_weapon); - AutoLoadingBullet(); + auto_switch_weapon = true; } } need_sync_active_player = true; @@ -1737,28 +1705,10 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) } break; } - if (GetCurrWeapon()->weapon_idx != 0 && - GetCurrWeapon()->ammo <= 0) { - if (GetCurrWeapon()->meta->i->reload_delay_time() > 0) { - room->xtimer.AddDeadLineTimerAndAttach - ( - GetCurrWeapon()->meta->i->reload_delay_time() / FRAME_RATE_MS, - a8::XParams() - .SetSender(this) - .SetParam1(GetCurrWeapon()->weapon_id), - [] (const a8::XParams& param) - { - Creature* c = (Creature*)param.sender.GetUserData(); - int weapon_id = param.param1; - if (c->GetCurrWeapon()->weapon_id == weapon_id) { - c->AutoLoadingBullet(); - } - }, - &xtimer_attacher.timer_list_ - ); - } else { - AutoLoadingBullet(); - } + if (auto_switch_weapon) { + AutoSwitchWeapon(); + } else { + CheckLoadingBullet(); } last_shot_frameno_ = room->GetFrameNo(); if ((IsPlayer() || IsCar())) { @@ -2089,6 +2039,9 @@ void Creature::SetCurrWeapon(Weapon* weapon) abort(); } #endif + if (auto_switch_weapon_timer_) { + room->xtimer.DeleteTimer(auto_switch_weapon_timer_); + } if (curr_weapon_ != weapon) { GetTrigger()->TakeonWeapon(curr_weapon_, weapon); } @@ -2653,3 +2606,151 @@ std::string Creature::DebugOutBuffList() } return data; } + +void Creature::AutoSwitchWeapon() +{ + auto switch_func = + [] (const a8::XParams& param) + { + Creature* c = (Creature*)param.sender.GetUserData(); + int weapon_idx = param.param1; + MetaData::Equip* weapon_meta = (MetaData::Equip*)param.param2.GetUserData(); + if (!(c->GetCurrWeapon()->weapon_idx == weapon_idx && + c->GetCurrWeapon()->meta == weapon_meta)) { + return; + } + + bool switch_ok = false; + int slot_id = weapon_meta->i->_inventory_slot(); + switch (slot_id) { + case IS_FRAG: //手雷 + case IS_SMOKE: //烟雾弹 + { + if (c->GetCurrWeapon()->ammo <= 0) { + if (c->GetInventory(slot_id) > 0) { + } else { + int weapon_idx = c->GetCurrWeapon()->weapon_idx; + *c->GetCurrWeapon() = Weapon(); + c->GetCurrWeapon()->weapon_idx = weapon_idx; + Weapon* next_weapon = c->ChooseNextWeapon(slot_id, SPEC1_IS_BEGIN, SPEC1_IS_END); + if (!next_weapon) { + next_weapon = c->ChooseNextWeapon(SPEC2_IS_BEGIN, SPEC2_IS_BEGIN, SPEC2_IS_END); + } + if (!next_weapon) { + next_weapon = c->AutoChgWeapon(); + } + c->SetCurrWeapon(next_weapon); + switch_ok = true; + } + } + } + break; + case IS_POSION_GAS_BOMB: //毒气弹 + case IS_MOLOTOR_COCKTAIL: //燃烧瓶 + case IS_TRAP: //陷井 + case IS_MINE: //地雷 + { + if (c->GetCurrWeapon()->ammo <= 0) { + if (c->GetInventory(slot_id) > 0) { + } else { + int weapon_idx = c->GetCurrWeapon()->weapon_idx; + *c->GetCurrWeapon() = Weapon(); + c->GetCurrWeapon()->weapon_idx = weapon_idx; + Weapon* next_weapon = c->ChooseNextWeapon(slot_id, SPEC2_IS_BEGIN, SPEC2_IS_END); + if (!next_weapon) { + next_weapon = c->ChooseNextWeapon(SPEC1_IS_BEGIN, SPEC1_IS_BEGIN, SPEC1_IS_END); + } + if (!next_weapon) { + next_weapon = c->AutoChgWeapon(); + } + c->SetCurrWeapon(next_weapon); + switch_ok = true; + } + } + } + break; + case IS_C4: + case IS_SHIELD_WALL: + case IS_SINGAL_GUN: + case IS_OIL_BUCKET: + { + if (c->GetCurrWeapon()->ammo <= 0) { + if (c->GetInventory(slot_id) > 0) { + } else { + int weapon_idx = c->GetCurrWeapon()->weapon_idx; + *c->GetCurrWeapon() = Weapon(); + c->GetCurrWeapon()->weapon_idx = weapon_idx; + Weapon* next_weapon = c->ChooseNextWeapon(slot_id, SPEC3_IS_BEGIN, SPEC3_IS_END); + if (!next_weapon) { + next_weapon = c->ChooseNextWeapon(SPEC1_IS_BEGIN, SPEC1_IS_BEGIN, SPEC1_IS_END); + } + if (!next_weapon) { + next_weapon = c->AutoChgWeapon(); + } + c->SetCurrWeapon(next_weapon); + switch_ok = true; + } + } + } + break; + default: + { + } + break; + } + if (switch_ok) { + c->need_sync_active_player = true; + c->SyncAroundPlayers(__FILE__, __LINE__, __func__); + } + c->CheckLoadingBullet(); + }; + a8::XParams param; + param.SetSender(this); + param.SetParam1(GetCurrWeapon()->weapon_idx); + param.SetParam2(GetCurrWeapon()->meta); + if (GetCurrWeapon()->meta->i->auto_switch_weapon_time() > 0) { + if (auto_switch_weapon_timer_) { + room->xtimer.DeleteTimer(auto_switch_weapon_timer_); + } + auto_switch_weapon_timer_ = room->xtimer.AddDeadLineTimerAndAttach + ( + GetCurrWeapon()->meta->i->auto_switch_weapon_time() / FRAME_RATE_MS, + param, + switch_func, + &xtimer_attacher.timer_list_, + [] (const a8::XParams& param) + { + Creature* c = (Creature*)param.sender.GetUserData(); + c->auto_switch_weapon_timer_ = nullptr; + }); + } else { + switch_func(param); + } +} + +void Creature::CheckLoadingBullet() +{ + if (GetCurrWeapon()->weapon_idx != 0 && + GetCurrWeapon()->ammo <= 0) { + if (GetCurrWeapon()->meta->i->reload_delay_time() > 0) { + room->xtimer.AddDeadLineTimerAndAttach + ( + GetCurrWeapon()->meta->i->reload_delay_time() / FRAME_RATE_MS, + a8::XParams() + .SetSender(this) + .SetParam1(GetCurrWeapon()->weapon_id), + [] (const a8::XParams& param) + { + Creature* c = (Creature*)param.sender.GetUserData(); + int weapon_id = param.param1; + if (c->GetCurrWeapon()->weapon_id == weapon_id) { + c->AutoLoadingBullet(); + } + }, + &xtimer_attacher.timer_list_ + ); + } else { + AutoLoadingBullet(); + } + } +} diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index 2319c42..ff1a9b3 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -233,6 +233,8 @@ private: void CheckAbilityUsed(); void ProcOnceChgAttrBuff(MetaData::Buff* buff_meta); Hero* InternalSummonHero(MetaData::Player* hero_meta, a8::Vec2 dir, a8::Vec2 born_pos, bool through_wall ); + void AutoSwitchWeapon(); + void CheckLoadingBullet(); protected: RaceType_e race_ = kHumanRace; @@ -267,6 +269,7 @@ private: std::list buff_list_; std::list> slave_heros_; std::list> slave_things_; + xtimer_list* auto_switch_weapon_timer_ = nullptr; a8::Vec2 skill_dir_; float skill_param1 = 0; diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index cb20500..9257685 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -143,6 +143,7 @@ message Equip optional int32 is_penetrate_thing = 62; optional int32 reload_delay_time = 63; optional int32 cast_time = 64; + optional int32 auto_switch_weapon_time = 65; optional string inventory_slot = 31; //库存槽位 optional int32 _inventory_slot = 32; //库存槽位