添加自动切枪逻辑

This commit is contained in:
aozhiwei 2021-08-12 11:18:49 +00:00
parent bac281edd0
commit 5340384caa
3 changed files with 163 additions and 58 deletions

View File

@ -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_
);
if (auto_switch_weapon) {
AutoSwitchWeapon();
} else {
AutoLoadingBullet();
}
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();
}
}
}

View File

@ -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> buff_list_;
std::list<std::tuple<int, Hero*>> slave_heros_;
std::list<std::tuple<int, RoomObstacle*>> slave_things_;
xtimer_list* auto_switch_weapon_timer_ = nullptr;
a8::Vec2 skill_dir_;
float skill_param1 = 0;

View File

@ -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; //