diff --git a/server/gameserver/android.ai.cc b/server/gameserver/android.ai.cc index 94d76b5..40cff0d 100644 --- a/server/gameserver/android.ai.cc +++ b/server/gameserver/android.ai.cc @@ -207,7 +207,7 @@ void AndroidNewAI::DoAttackOldAI() shot_dir.Rotate((rand() % 10) / 180.0f); sender->attack_dir = shot_dir; bool shot_ok = false; - sender->Shot(shot_dir, shot_ok); + sender->Shot(shot_dir, shot_ok, DEFAULT_FLY_DISTANCE); } } old_ai_data_.last_target.Attach(enemy); @@ -243,7 +243,7 @@ void AndroidNewAI::UpdateNewBieNpc() shot_dir.Rotate((rand() % 10) / 180.0f); sender->attack_dir = shot_dir; bool shot_ok = false; - sender->Shot(shot_dir, shot_ok); + sender->Shot(shot_dir, shot_ok, DEFAULT_FLY_DISTANCE); } } else { a8::UnSetBitFlag(hum->status, HS_NewBieGuideAndroid); @@ -285,7 +285,7 @@ void AndroidNewAI::UpdateLastNpc() shot_dir.Rotate((rand() % 10) / 180.0f); sender->attack_dir = shot_dir; bool shot_ok = false; - sender->Shot(shot_dir, shot_ok); + sender->Shot(shot_dir, shot_ok, DEFAULT_FLY_DISTANCE); } } else { a8::UnSetBitFlag(hum->status, HS_LastAndroid); @@ -400,7 +400,7 @@ void AndroidNewAI::UpdateNewBieRoomLogic() shot_dir.Rotate((rand() % 10) / 180.0f); sender->attack_dir = shot_dir; bool shot_ok = false; - sender->Shot(shot_dir, shot_ok); + sender->Shot(shot_dir, shot_ok, DEFAULT_FLY_DISTANCE); } } if (old_last_target && old_ai_data_.last_target.Get() && old_last_target == old_ai_data_.last_target.Get()) { @@ -763,7 +763,7 @@ void AndroidNewAI::DoShotNewAI() } a8::Vec2 old_attack_dir = myself->attack_dir; myself->attack_dir = shot_dir; - myself->Shot(shot_dir, shot_ok); + myself->Shot(shot_dir, shot_ok, DEFAULT_FLY_DISTANCE); myself->attack_dir = old_attack_dir; if (shot_ok) { if (node_.shot_times <= 0) { diff --git a/server/gameserver/constant.h b/server/gameserver/constant.h index 534ca97..d835fc3 100755 --- a/server/gameserver/constant.h +++ b/server/gameserver/constant.h @@ -404,6 +404,14 @@ const int GUN_SLOT2 = 2; const int FRAG_SLOT = 3; const int SMOKE_SLOT = 4; +const int SPEC1_IS_BEGIN = IS_FRAG; +const int SPEC1_IS_END = IS_SMOKE; +const int SPEC2_IS_BEGIN = IS_POSION_GAS_BOMB; +const int SPEC2_IS_END = IS_MINE; + +const int SPEC1_SLOT_BEGIN = 3; //手雷 烟雾弹 +const int SPEC2_SLOT_BEGIN = 5; //毒气弹 燃烧瓶 陷井 地雷 + const int DOOR_THING_ID = 61701; const int FIGHTING_MODE_BULLET_NUM = 10000 * 10000; @@ -453,3 +461,4 @@ const int kInGrassBuffId = 7006; const int kInWaterBuffId = 7007; const int kInIceBuffId = 7008; +const float DEFAULT_FLY_DISTANCE = 5.0f; diff --git a/server/gameserver/creature.cc b/server/gameserver/creature.cc index 91a996e..ca244d3 100644 --- a/server/gameserver/creature.cc +++ b/server/gameserver/creature.cc @@ -1137,7 +1137,7 @@ void Creature::UpdatePoisoning() } } -void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok) +void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance) { shot_ok = false; if (!curr_weapon->meta) { @@ -1146,12 +1146,26 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok) if (downed) { return; } + if (!curr_weapon->meta) { + return; + } if (curr_weapon->weapon_idx != 0 && curr_weapon->ammo <= 0) { AutoLoadingBullet(); return; } + + if (action_type == AT_Reload) { + CancelAction(); + } + if (action_type == AT_Reload || + action_type == AT_Rescue || + action_type == AT_UseItem || + action_type == AT_Relive) { + CancelAction(); + } + if ((room->GetFrameNo() - last_shot_frameno_) * (1000 / SERVER_FRAME_RATE) < curr_weapon->GetAttrValue(kHAT_FireRate) ) { @@ -1164,54 +1178,62 @@ void Creature::Shot(a8::Vec2& target_dir, bool& shot_ok) curr_weapon->bullet_meta, curr_weapon->weapon_lv, 0, - 5, + fly_distance, false); - --curr_weapon->ammo; + if (curr_weapon->weapon_idx != 0) { + --curr_weapon->ammo; + } int slot_id = curr_weapon->meta->i->_inventory_slot(); switch (slot_id) { - case 5: + case IS_FRAG: //手雷 + case IS_SMOKE: //烟雾弹 { - //手雷 - if (GetInventory(slot_id) > 0) { - DecInventory(slot_id, 1); - ++curr_weapon->ammo; - } else { - int weapon_idx = curr_weapon->weapon_idx; - *curr_weapon = Weapon(); - curr_weapon->weapon_idx = weapon_idx; - if (weapons[SMOKE_SLOT].weapon_id != 0) { - curr_weapon = &weapons[SMOKE_SLOT]; + if (curr_weapon->ammo <= 0) { + if (GetInventory(slot_id) > 0) { + DecInventory(slot_id, 1); + ++curr_weapon->ammo; } else { - curr_weapon = &weapons[0]; + int weapon_idx = curr_weapon->weapon_idx; + *curr_weapon = Weapon(); + curr_weapon->weapon_idx = weapon_idx; + curr_weapon = ChooseNextWeapon(slot_id, SPEC1_IS_BEGIN, SPEC1_IS_END); + AutoLoadingBullet(); } - AutoLoadingBullet(); } need_sync_active_player = true; SyncAroundPlayers(__FILE__, __LINE__, __func__); } break; - case 6: + case IS_POSION_GAS_BOMB: //毒气弹 + case IS_MOLOTOR_COCKTAIL: //燃烧瓶 + case IS_TRAP: //陷井 + case IS_MINE: //地雷 { - //烟雾弹 - if (GetInventory(slot_id) > 0) { - DecInventory(slot_id, 1); - ++curr_weapon->ammo; - } else { - int weapon_idx = curr_weapon->weapon_idx; - *curr_weapon = Weapon(); - curr_weapon->weapon_idx = weapon_idx; - if (weapons[FRAG_SLOT].weapon_id != 0) { - curr_weapon = &weapons[FRAG_SLOT]; + if (curr_weapon->ammo <= 0) { + if (GetInventory(slot_id) > 0) { + DecInventory(slot_id, 1); + ++curr_weapon->ammo; } else { - curr_weapon = &weapons[0]; + int weapon_idx = curr_weapon->weapon_idx; + *curr_weapon = Weapon(); + curr_weapon->weapon_idx = weapon_idx; + curr_weapon = ChooseNextWeapon(slot_id, SPEC2_IS_BEGIN, SPEC2_IS_END); + AutoLoadingBullet(); } - AutoLoadingBullet(); } need_sync_active_player = true; SyncAroundPlayers(__FILE__, __LINE__, __func__); } break; + default: + { + } + break; + } + if (curr_weapon->weapon_idx != 0 && + curr_weapon->ammo <= 0) { + AutoLoadingBullet(); } last_shot_frameno_ = room->GetFrameNo(); if (!need_sync_active_player && IsPlayer()) { @@ -1461,3 +1483,42 @@ CreatureWeakPtr Creature::AllocWeakPtr() ptr.Attach(this); return ptr; } + +Weapon* Creature::AutoChgWeapon() +{ + if (weapons[GUN_SLOT1].weapon_id != 0) { + curr_weapon = &weapons[GUN_SLOT1]; + } else if (weapons[GUN_SLOT2].weapon_id != 0) { + curr_weapon = &weapons[GUN_SLOT2]; + } else { + curr_weapon = &weapons[0]; + } + return curr_weapon; +} + +Weapon* Creature::ChooseNextWeapon(int curr_weapon_slot_id, int begin_slot_id, int end_slot_id) +{ + if (curr_weapon_slot_id < begin_slot_id) { + abort(); + } + if (curr_weapon_slot_id > end_slot_id) { + abort(); + } + if (begin_slot_id > end_slot_id) { + abort(); + } + if (begin_slot_id < 0 || + end_slot_id < 0) { + abort(); + } + Weapon* next_weapon = nullptr; + for (int i = 1; i <= (end_slot_id - begin_slot_id); ++i) { + int slot_id = begin_slot_id + + (i + curr_weapon_slot_id - begin_slot_id) % (end_slot_id - begin_slot_id + 1); + if (weapons[slot_id].weapon_id != 0) { + next_weapon = &weapons[slot_id]; + break; + } + } + return next_weapon ? next_weapon : AutoChgWeapon(); +} diff --git a/server/gameserver/creature.h b/server/gameserver/creature.h index c229839..8a1df79 100644 --- a/server/gameserver/creature.h +++ b/server/gameserver/creature.h @@ -120,7 +120,7 @@ class Creature : public MoveableEntity void TouchProperTargets(std::function func); CreatureWeakPtrChunk* GetWeakPtrChunk() { return &weak_ptr_chunk_; }; - void Shot(a8::Vec2& target_dir, bool& shot_ok); + void Shot(a8::Vec2& target_dir, bool& shot_ok, float fly_distance); void AutoLoadingBullet(bool manual = false); int GetInventory(int slot_id); @@ -135,6 +135,8 @@ class Creature : public MoveableEntity void FillSkillCasterState(SkillCasterState* caster_state); void RecoverSkillCasterState(SkillCasterState* caster_state); CreatureWeakPtr AllocWeakPtr(); + Weapon* AutoChgWeapon(); + Weapon* ChooseNextWeapon(int curr_weapon_slot_id, int begin_slot_id, int end_slot_id); private: diff --git a/server/gameserver/hero.ai.cc b/server/gameserver/hero.ai.cc index 1079e32..46d5aca 100644 --- a/server/gameserver/hero.ai.cc +++ b/server/gameserver/hero.ai.cc @@ -395,7 +395,7 @@ void HeroAI::DoShotAI() } a8::Vec2 old_attack_dir = myself->attack_dir; myself->attack_dir = shot_dir; - myself->Shot(shot_dir, shot_ok); + myself->Shot(shot_dir, shot_ok, DEFAULT_FLY_DISTANCE); myself->attack_dir = old_attack_dir; if (shot_ok) { if (node_.shot_times <= 0) { diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index c463466..0d11c81 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -2764,17 +2764,6 @@ void Human::Revive() } } -void Human::AutoChgWeapon() -{ - if (weapons[GUN_SLOT1].weapon_id != 0) { - curr_weapon = &weapons[GUN_SLOT1]; - } else if (weapons[GUN_SLOT2].weapon_id != 0) { - curr_weapon = &weapons[GUN_SLOT2]; - } else { - curr_weapon = &weapons[0]; - } -} - void Human::CancelRevive() { if (dead && revive_timer && !real_dead) { diff --git a/server/gameserver/human.h b/server/gameserver/human.h index 0e2c8f5..46ad98c 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -248,7 +248,6 @@ protected: void ProcLootCar(Loot* entity, MetaData::Equip* item_meta); void ProcCamoutflage(Loot* entity, MetaData::Equip* item_meta); void ProcSpoils(Loot* entity, MetaData::Equip* item_meta); - void AutoChgWeapon(); void CancelRevive(); private: diff --git a/server/gameserver/player.cc b/server/gameserver/player.cc index 7f25aba..77b61dc 100644 --- a/server/gameserver/player.cc +++ b/server/gameserver/player.cc @@ -404,6 +404,7 @@ void Player::Shot() return; } + Shot(); if (!curr_weapon->meta) { return; } @@ -691,7 +692,9 @@ void Player::LootInteraction(Loot* entity) case IS_FRAG: case IS_SMOKE: { - Weapon* weapon = &weapons[3 + (item_meta->i->_inventory_slot() - IS_FRAG)]; + Weapon* weapon = &weapons[SPEC1_SLOT_BEGIN + + (item_meta->i->_inventory_slot() - SPEC1_IS_BEGIN) + ]; weapon->weapon_id = entity->item_id; weapon->weapon_lv = 1; weapon->ammo += entity->count; @@ -716,7 +719,9 @@ void Player::LootInteraction(Loot* entity) case IS_TRAP: case IS_MINE: { - Weapon* weapon = &weapons[5 + (item_meta->i->_inventory_slot() - IS_POSION_GAS_BOMB)]; + Weapon* weapon = &weapons[SPEC2_SLOT_BEGIN + + (item_meta->i->_inventory_slot() - SPEC2_IS_BEGIN) + ]; weapon->weapon_id = entity->item_id; weapon->weapon_lv = 1; weapon->ammo += entity->count; diff --git a/server/gameserver/zombiemode.ai.cc b/server/gameserver/zombiemode.ai.cc index eb9ab4c..3e1f63c 100644 --- a/server/gameserver/zombiemode.ai.cc +++ b/server/gameserver/zombiemode.ai.cc @@ -454,7 +454,7 @@ void ZombieModeAI::DoShot() } a8::Vec2 old_attack_dir = myself->attack_dir; myself->attack_dir = shot_dir; - myself->Shot(shot_dir, shot_ok); + myself->Shot(shot_dir, shot_ok, DEFAULT_FLY_DISTANCE); myself->attack_dir = old_attack_dir; if (shot_ok) { if (node_->shot_times <= 0) {