diff --git a/server/gameserver/android.ai.cc b/server/gameserver/android.ai.cc index 4ccba14..a4bac03 100644 --- a/server/gameserver/android.ai.cc +++ b/server/gameserver/android.ai.cc @@ -19,13 +19,12 @@ AndroidAI::~AndroidAI() void AndroidAI::Update(int delta_time) { - Human* hum = (Human*)owner; state_elapsed_time_ += delta_time; - if (hum->dead) { + if (HumMaster()->dead) { return; } - if (hum->playing_skill) { - hum->UpdateSkill(); + if (HumMaster()->playing_skill) { + HumMaster()->UpdateSkill(); } switch (state_) { case AS_thinking: @@ -42,9 +41,22 @@ void AndroidAI::Update(int delta_time) break; case AS_moving: { + bool need_chg = true; if (state_elapsed_time_ < 1000 + rand() % 2000) { DoMove(); - } else { + need_chg = false; + } else if (locked_enemy_ && !locked_enemy_->dead && + HumMaster()->pos.Distance(locked_enemy_->pos) < MetaMgr::Instance()->robot_pursuit_range) { + if (HumMaster()->pos.Distance(locked_enemy_->pos) < MetaMgr::Instance()->robot_attack_range) { + ChangeToState(AS_attack); + } else { + HumMaster()->move_dir = locked_enemy_->pos - HumMaster()->pos; + HumMaster()->move_dir.Normalize(); + DoMove(); + } + need_chg = false; + } + if (need_chg) { int rnd = rand(); if (rnd % 100 < 30) { ChangeToState(AS_thinking); @@ -56,9 +68,20 @@ void AndroidAI::Update(int delta_time) break; case AS_attack: { + bool need_chg = true; if (state_elapsed_time_ < 1000) { DoAttack(); - } else { + need_chg = false; + } else if (locked_enemy_ && locked_enemy_->dead && + HumMaster()->pos.Distance(locked_enemy_->pos) < MetaMgr::Instance()->robot_pursuit_range) { + if (HumMaster()->pos.Distance(locked_enemy_->pos) > MetaMgr::Instance()->robot_attack_range) { + ChangeToState(AS_moving); + } else { + DoAttack(); + } + need_chg = false; + } + if (need_chg) { int rnd = rand(); if (rnd % 100 < 30) { ChangeToState(AS_moving); @@ -68,6 +91,8 @@ void AndroidAI::Update(int delta_time) } } break; + default: + break; } } @@ -105,11 +130,21 @@ void AndroidAI::ChangeToState(AndroidState_e to_state) switch (state_) { case AS_moving: { - Human* hum = (Human*)owner; - hum->move_dir = a8::Vec2(1.0f, 0); - hum->move_dir.Rotate(a8::RandAngle()); - hum->move_dir.Normalize(); - hum->attack_dir = hum->move_dir; + if (locked_enemy_) { + a8::Vec2 move_dir = locked_enemy_->pos - HumMaster()->pos; + if (std::abs(move_dir.x) > 0.00001f || + std::abs(move_dir.y) > 0.00001f) { + HumMaster()->move_dir = move_dir; + HumMaster()->move_dir.Normalize(); + } else { + return; + } + } else { + HumMaster()->move_dir = a8::Vec2(1.0f, 0); + HumMaster()->move_dir.Rotate(a8::RandAngle()); + HumMaster()->move_dir.Normalize(); + } + HumMaster()->attack_dir = HumMaster()->move_dir; } break; default: @@ -119,47 +154,44 @@ void AndroidAI::ChangeToState(AndroidState_e to_state) void AndroidAI::DoMove() { - Human* hum = (Human*)owner; - if (hum->HasBuffEffect(kBET_Vertigo) || hum->HasBuffEffect(kBET_Dcgr)) { + if (HumMaster()->HasBuffEffect(kBET_Vertigo) || HumMaster()->HasBuffEffect(kBET_Dcgr)) { return; } if (owner->updated_times % 2 == 0) { - Human* hum = (Human*)owner; - int speed = std::max(1, (int)hum->GetSpeed()); + int speed = std::max(1, (int)HumMaster()->GetSpeed()); for (int i = 0; i < speed; ++i) { - a8::Vec2 old_pos = hum->pos; - hum->pos = hum->pos + hum->move_dir; - if (hum->IsCollisionInMapService()) { - hum->pos = old_pos; + a8::Vec2 old_pos = HumMaster()->pos; + HumMaster()->pos = HumMaster()->pos + HumMaster()->move_dir; + if (HumMaster()->IsCollisionInMapService()) { + HumMaster()->pos = old_pos; if (i == 0) { - hum->FindPath(); + HumMaster()->FindPath(); } break; } - hum->room->grid_service.MoveHuman(hum); + HumMaster()->room->grid_service.MoveHuman(HumMaster()); } - hum->CheckGrass(); + HumMaster()->CheckGrass(); } } void AndroidAI::DoAttack() { - Human* hum = (Human*)owner; - if (hum->room->gas_data.gas_mode == kGasInactive) { + if (HumMaster()->room->gas_data.gas_mode == kGasInactive) { return; } - if (hum->HasBuffEffect(kBET_Vertigo) || hum->HasBuffEffect(kBET_Dcgr)) { + if (HumMaster()->HasBuffEffect(kBET_Vertigo) || HumMaster()->HasBuffEffect(kBET_Dcgr)) { return; } if (owner->updated_times % 10 == 0) { - Human* enemy = owner->room->FindEnemy((Human*)owner); + Human* enemy = locked_enemy_ ? locked_enemy_ : owner->room->FindEnemy(HumMaster()); if (enemy && !enemy->HasBuffEffect(kBET_Invincible) && !enemy->HasBuffEffect(kBET_Hide) && !enemy->HasBuffEffect(kBET_InGrass) ) { - Human* sender = (Human*)owner; - if (sender->CanUseSkill()) { + if (HumMaster()->CanUseSkill() && + HumMaster()->pos.Distance(enemy->pos) < HumMaster()->tank_meta_->i->atk_range()) { UseSkill(enemy); } else { Shot(enemy); @@ -170,47 +202,61 @@ void AndroidAI::DoAttack() void AndroidAI::Shot(Human* enemy) { - Human* sender = (Human*)owner; - a8::Vec2 shot_dir = enemy->pos - sender->pos; - if (std::abs(shot_dir.x) > FLT_EPSILON || - std::abs(shot_dir.y) > FLT_EPSILON) { - shot_dir.Normalize(); - shot_dir.Rotate((rand() % 10) / 180.0f); - sender->attack_dir = shot_dir; - if (sender->curr_weapon->meta->NeedTrace()) { - sender->shot_target_id = enemy->entity_uniid; - } else { - sender->shot_target_id = 0; + if (enemy->HasBuffEffect(kBET_Hide) || + enemy->HasBuffEffect(kBET_Invincible) || + enemy->dead + ) { + return; + } + if (((HumMaster()->room->frameno - HumMaster()->last_shot_frameno_) * (1000 / kSERVER_FRAME_RATE)) >= + HumMaster()->curr_weapon->meta->i->fire_rate() + ) { + a8::Vec2 shot_dir = enemy->pos - HumMaster()->pos; + if (std::abs(shot_dir.x) > FLT_EPSILON || + std::abs(shot_dir.y) > FLT_EPSILON) { + shot_dir.Normalize(); + shot_dir.Rotate((rand() % 10) / 180.0f); + HumMaster()->attack_dir = shot_dir; + if (HumMaster()->curr_weapon->meta->NeedTrace()) { + HumMaster()->shot_target_id = enemy->entity_uniid; + } else { + HumMaster()->shot_target_id = 0; + } + HumMaster()->Shot(); } - sender->Shot(); } } void AndroidAI::UseSkill(Human* enemy) { - Human* sender = (Human*)owner; - if (!sender->CurrentSkillMeta()) { + if (!HumMaster()->CurrentSkillMeta()) { return; } - if (sender->CurrentSkillMeta()->i->skill_target() == kST_Self) { - sender->curr_skill_phase = 0; - sender->skill_target_id = sender->entity_uniid; - sender->skill_dir = a8::Vec2(); - sender->skill_target_pos = sender->pos; - sender->skill_param1 = 0; - sender->playing_skill = false; - sender->DoSkill(); + if (enemy->HasBuffEffect(kBET_Hide) || + enemy->HasBuffEffect(kBET_Invincible) || + enemy->dead) { + return; + } + + if (HumMaster()->CurrentSkillMeta()->i->skill_target() == kST_Self) { + HumMaster()->curr_skill_phase = 0; + HumMaster()->skill_target_id = HumMaster()->entity_uniid; + HumMaster()->skill_dir = a8::Vec2(); + HumMaster()->skill_target_pos = HumMaster()->pos; + HumMaster()->skill_param1 = 0; + HumMaster()->playing_skill = false; + HumMaster()->DoSkill(); } else { - a8::Vec2 shot_dir = enemy->pos - sender->pos; + a8::Vec2 shot_dir = enemy->pos - HumMaster()->pos; if (std::abs(shot_dir.x) > FLT_EPSILON || std::abs(shot_dir.y) > FLT_EPSILON) { - sender->curr_skill_phase = 0; - sender->skill_target_id = enemy->entity_uniid; - sender->skill_dir = shot_dir; - sender->skill_target_pos = enemy->pos; - sender->skill_param1 = 0; - sender->playing_skill = false; - sender->DoSkill(); + HumMaster()->curr_skill_phase = 0; + HumMaster()->skill_target_id = enemy->entity_uniid; + HumMaster()->skill_dir = shot_dir; + HumMaster()->skill_target_pos = enemy->pos; + HumMaster()->skill_param1 = 0; + HumMaster()->playing_skill = false; + HumMaster()->DoSkill(); } } } diff --git a/server/gameserver/human.cc b/server/gameserver/human.cc index a6b69ed..c9dbd67 100644 --- a/server/gameserver/human.cc +++ b/server/gameserver/human.cc @@ -17,6 +17,7 @@ #include "app.h" #include "roommgr.h" #include "android.h" +#include "android.ai.h" #include "gamelog.h" #include "typeconvert.h" #include "obstacle.h" @@ -501,6 +502,12 @@ void Human::DecHP(float dec_hp, int killer_id, const std::string& killer_name, i last_attacker_name = killer_name; last_attacker_weapon_id = weapon_id; last_attacked_frameno = room->frameno; + if (entity_subtype == kEST_Android) { + Android* android = (Android*)this; + if (android->ai) { + android->ai->LockEnemy(last_attacker_id); + } + } SyncAroundPlayers(); } diff --git a/server/gameserver/human.h b/server/gameserver/human.h index d8b4b61..2581983 100644 --- a/server/gameserver/human.h +++ b/server/gameserver/human.h @@ -264,4 +264,5 @@ private: friend class FrameMaker; friend class FrameEvent; + friend class AndroidAI; }; diff --git a/server/gameserver/metamgr.cc b/server/gameserver/metamgr.cc index 5f70835..5139ee3 100755 --- a/server/gameserver/metamgr.cc +++ b/server/gameserver/metamgr.cc @@ -123,6 +123,14 @@ public: MetaMgr::Instance()->grass_invisible_time = MetaMgr::Instance()->GetSysParamAsInt("grass_invisible_time", 0.5f); MetaMgr::Instance()->grass_show_time = MetaMgr::Instance()->GetSysParamAsInt("grass_show_time", 0.5f); MetaMgr::Instance()->grass_invisible_time2 = MetaMgr::Instance()->GetSysParamAsInt("grass_invisible_time2", 2.0f); + MetaMgr::Instance()->robot_pursuit_range = MetaMgr::Instance()-> + GetSysParamAsInt("robot_pursuit_range", + MetaMgr::Instance()->robot_pursuit_range + ); + MetaMgr::Instance()->robot_attack_range = MetaMgr::Instance()-> + GetSysParamAsInt("robot_attack_range", + MetaMgr::Instance()->robot_attack_range + ); if (MetaMgr::Instance()->K < 0.01f) { abort(); } diff --git a/server/gameserver/metamgr.h b/server/gameserver/metamgr.h index 8cfc453..2b5d580 100755 --- a/server/gameserver/metamgr.h +++ b/server/gameserver/metamgr.h @@ -54,6 +54,8 @@ class MetaMgr : public a8::Singleton float grass_invisible_time = 0.5; float grass_show_time = 0.5f; float grass_invisible_time2 = 2.0f; + float robot_pursuit_range = 800.0f; + float robot_attack_range = 256.0f; private: MetaDataLoader* loader_ = nullptr; diff --git a/server/tools/protobuild/metatable.proto b/server/tools/protobuild/metatable.proto index 0856394..905040e 100755 --- a/server/tools/protobuild/metatable.proto +++ b/server/tools/protobuild/metatable.proto @@ -214,7 +214,8 @@ message Tank required int32 skill_id = 4; required string attr_origin = 5; required string attr_up = 6; - optional int32 type = 7; + required int32 type = 7; + required float atk_range = 8; } message TankSkin