diff --git a/server/gameserver/zombie.ai.cc b/server/gameserver/zombie.ai.cc index 1ef4fc5..b5aba7c 100644 --- a/server/gameserver/zombie.ai.cc +++ b/server/gameserver/zombie.ai.cc @@ -17,6 +17,28 @@ enum ShotType_e kShotHold = 2, }; +class ZombieAINode +{ +public: + ZombieState_e main_state = ZSE_Idle; + long long frameno = 0; + long long exec_frame_num = 0; + long long start_shot_frameno = 0; + long long next_random_move_frameno = 0; + int shot_times = 0; + int total_shot_times = 0; + int next_total_shot_times = 0; + + long long param1 = 0; + Human* target = nullptr; + Human* nearest_human = nullptr; + long long last_check_nearest_human_frameno = 0; + a8::Vec2 shot_dir; + + bool moving = false; + MetaData::AI* ai_meta = nullptr; +}; + /* nn目标:ai可切换,降级/升级(根据系统当前负载) @@ -31,8 +53,14 @@ ai级别 8: 跑动射击 */ +ZombieAI::ZombieAI() +{ + node_ = new ZombieAINode(); +} + ZombieAI::~ZombieAI() { + A8_SAFE_DELETE(node_); } void ZombieAI::Update(int delta_time) @@ -55,10 +83,10 @@ void ZombieAI::Update(int delta_time) float ZombieAI::GetAttackRate() { - if (!ai_meta) { + if (!node_->ai_meta) { return 1; } else { - return ai_meta->i->attack_rate(); + return node_->ai_meta->i->attack_rate(); } } @@ -68,15 +96,15 @@ void ZombieAI::UpdateAI() if (a8::HasBitFlag(hum->status, HS_Disable)) { return; } - if (!ai_meta && GetAiLevel() != 0) { - ai_meta = MetaMgr::Instance()->GetAI(GetAiLevel()); - if (!ai_meta) { + if (!node_->ai_meta && GetAiLevel() != 0) { + node_->ai_meta = MetaMgr::Instance()->GetAI(GetAiLevel()); + if (!node_->ai_meta) { abort(); } } - ++node_.exec_frame_num; + ++node_->exec_frame_num; hum->shot_hold = false; - switch (node_.main_state) { + switch (node_->main_state) { case ZSE_Idle: { UpdateIdle(); @@ -108,7 +136,7 @@ void ZombieAI::UpdateAI() } break; } - if (moving_) { + if (node_->moving) { DoMove(); } } @@ -116,7 +144,7 @@ void ZombieAI::UpdateAI() void ZombieAI::UpdateIdle() { Human* hum = (Human*)owner; - if (hum->room->GetFrameNo() > node_.frameno + node_.param1) { + if (hum->room->GetFrameNo() > node_->frameno + node_->param1) { ChangeToState(ZSE_Thinking); } } @@ -134,10 +162,10 @@ void ZombieAI::UpdateThinking() } else { Human* target = GetTarget(); if (target) { - node_.target = target; + node_->target = target; ChangeToState(ZSE_Attack); } else { - if (hum->room->GetFrameNo() >= node_.next_random_move_frameno) { + if (hum->room->GetFrameNo() >= node_->next_random_move_frameno) { if ((rand() % 7) < 4) { ChangeToState(ZSE_Idle); } else { @@ -145,7 +173,7 @@ void ZombieAI::UpdateThinking() } } else { ChangeToState(ZSE_Idle); - node_.param1 = node_.next_random_move_frameno - hum->room->GetFrameNo(); + node_->param1 = node_->next_random_move_frameno - hum->room->GetFrameNo(); } } } @@ -154,21 +182,21 @@ void ZombieAI::UpdateThinking() void ZombieAI::UpdateAttack() { Human* myself = (Human*)owner; - if (!node_.target || node_.target->dead) { + if (!node_->target || node_->target->dead) { ChangeToState(ZSE_Thinking); return; } - if (node_.exec_frame_num > SERVER_FRAME_RATE * 8) { + if (node_->exec_frame_num > SERVER_FRAME_RATE * 8) { ChangeToState(ZSE_Thinking); return; } - float distance = myself->GetPos().Distance(node_.target->GetPos()); + float distance = myself->GetPos().Distance(node_->target->GetPos()); if (distance > GetAttackRange()) { - if (ai_meta->i->pursuit_radius() <= 0) { + if (node_->ai_meta->i->pursuit_radius() <= 0) { //站桩 ChangeToState(ZSE_Thinking); } else { - if (distance < ai_meta->i->pursuit_radius()) { + if (distance < node_->ai_meta->i->pursuit_radius()) { //追击 ChangeToState(ZSE_Pursuit); } else { @@ -178,16 +206,16 @@ void ZombieAI::UpdateAttack() return; } //攻击逻辑 - switch (ai_meta->i->attack_type()) { + switch (node_->ai_meta->i->attack_type()) { case kShotClick: { - if (ai_meta->i->attack_interval() > 0) { - if (node_.shot_times < GetAttackTimes()) { + if (node_->ai_meta->i->attack_interval() > 0) { + if (node_->shot_times < GetAttackTimes()) { DoShot(); } else { ChangeToState(ZSE_Idle); - node_.next_total_shot_times = node_.total_shot_times; - node_.param1 = ai_meta->i->attack_interval() / 1000 * SERVER_FRAME_RATE; + node_->next_total_shot_times = node_->total_shot_times; + node_->param1 = node_->ai_meta->i->attack_interval() / 1000 * SERVER_FRAME_RATE; } } else { myself->shot_hold = true; @@ -212,7 +240,7 @@ void ZombieAI::UpdateAttack() void ZombieAI::UpdateRandomWalk() { Human* hum = (Human*)owner; - if (hum->room->GetFrameNo() > node_.frameno + node_.param1) { + if (hum->room->GetFrameNo() > node_->frameno + node_->param1) { ChangeToState(ZSE_Thinking); } } @@ -220,11 +248,11 @@ void ZombieAI::UpdateRandomWalk() void ZombieAI::UpdatePursuit() { Human* myself = (Human*)owner; - float distance = myself->GetPos().Distance(node_.target->GetPos()); + float distance = myself->GetPos().Distance(node_->target->GetPos()); if (distance < GetAttackRange()) { ChangeToState(ZSE_Attack); } else { - if (node_.exec_frame_num > 100 * 2) { + if (node_->exec_frame_num > 100 * 2) { ChangeToState(ZSE_RandomWalk); } } @@ -243,11 +271,11 @@ void ZombieAI::DoMove() int speed = std::max(1, (int)hum->GetSpeed()) * 1; hum->_UpdateMove(speed); hum->on_move_collision = nullptr; - if (node_.nearest_human) { - if (node_.main_state != ZSE_Pursuit && - hum->GetPos().ManhattanDistance(node_.nearest_human->GetPos()) < 200) { + if (node_->nearest_human) { + if (node_->main_state != ZSE_Pursuit && + hum->GetPos().ManhattanDistance(node_->nearest_human->GetPos()) < 200) { ChangeToState(ZSE_Thinking); - } else if (hum->GetPos().ManhattanDistance(node_.nearest_human->GetPos()) > 800) { + } else if (hum->GetPos().ManhattanDistance(node_->nearest_human->GetPos()) > 800) { GetTarget(); } } @@ -260,73 +288,73 @@ void ZombieAI::ChangeToState(ZombieState_e to_state) switch (to_state) { case ZSE_Idle: { - node_.target = nullptr; - node_.param1 = 0; - node_.start_shot_frameno = 0; - node_.shot_times = 0; - moving_ = false; + node_->target = nullptr; + node_->param1 = 0; + node_->start_shot_frameno = 0; + node_->shot_times = 0; + node_->moving = false; if (hum->room->GetGasData().gas_mode == GasInactive || hum->room->IsWaitingStart()) { - node_.param1 = rand() % (3 * SERVER_FRAME_RATE); + node_->param1 = rand() % (3 * SERVER_FRAME_RATE); } else { - node_.param1 = rand() % (2 * SERVER_FRAME_RATE); + node_->param1 = rand() % (2 * SERVER_FRAME_RATE); } } break; case ZSE_Thinking: { - node_.target = nullptr; - node_.param1 = 0; - node_.start_shot_frameno = 0; - node_.shot_times = 0; - moving_ = false; + node_->target = nullptr; + node_->param1 = 0; + node_->start_shot_frameno = 0; + node_->shot_times = 0; + node_->moving = false; } break; case ZSE_Attack: { - node_.param1 = 0; - node_.start_shot_frameno = 0; - node_.shot_times = 0; - moving_ = false; - node_.shot_times = 0; + node_->param1 = 0; + node_->start_shot_frameno = 0; + node_->shot_times = 0; + node_->moving = false; + node_->shot_times = 0; } break; case ZSE_RandomWalk: { - moving_ = true; - node_.target = nullptr; + node_->moving = true; + node_->target = nullptr; #if 1 - node_.param1 = SERVER_FRAME_RATE * ai_meta->GetMoveTime(); + node_->param1 = SERVER_FRAME_RATE * node_->ai_meta->GetMoveTime(); #else - node_.param1 = SERVER_FRAME_RATE * 5 + rand() % (SERVER_FRAME_RATE * 3); + node_->param1 = SERVER_FRAME_RATE * 5 + rand() % (SERVER_FRAME_RATE * 3); #endif - node_.start_shot_frameno = 0; - node_.shot_times = 0; - node_.next_random_move_frameno = hum->room->GetFrameNo() + - SERVER_FRAME_RATE * ai_meta->GetMoveIdleTime(); + node_->start_shot_frameno = 0; + node_->shot_times = 0; + node_->next_random_move_frameno = hum->room->GetFrameNo() + + SERVER_FRAME_RATE * node_->ai_meta->GetMoveIdleTime(); 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 (node_.param1 <= 1) { - moving_ = false; + if (node_->param1 <= 1) { + node_->moving = false; } } break; case ZSE_Pursuit: { - moving_ = true; - if (node_.target) { - hum->move_dir = node_.target->GetPos() - hum->GetPos(); + node_->moving = true; + if (node_->target) { + hum->move_dir = node_->target->GetPos() - hum->GetPos(); hum->move_dir.Normalize(); hum->attack_dir = hum->move_dir; } } break; } - node_.main_state = to_state; - node_.frameno = hum->room->GetFrameNo(); - node_.exec_frame_num = 0; + node_->main_state = to_state; + node_->frameno = hum->room->GetFrameNo(); + node_->exec_frame_num = 0; } Human* ZombieAI::GetTarget() @@ -363,8 +391,8 @@ Human* ZombieAI::GetTarget() } }); if (target) { - node_.nearest_human = target; - node_.last_check_nearest_human_frameno = myself->room->GetFrameNo(); + node_->nearest_human = target; + node_->last_check_nearest_human_frameno = myself->room->GetFrameNo(); float distance = myself->GetPos().Distance(target->GetPos()); if (distance > GetAttackRange()) { target = nullptr; @@ -380,29 +408,29 @@ float ZombieAI::GetAttackRange() if (myself->curr_weapon && myself->curr_weapon->meta) { attack_range = myself->curr_weapon->meta->i->range(); } - attack_range = std::min(ai_meta->i->attack_range(), (int)attack_range); + attack_range = std::min(node_->ai_meta->i->attack_range(), (int)attack_range); return attack_range; } void ZombieAI::DoShot() { Human* myself = (Human*)owner; - if (!node_.target) { + if (!node_->target) { return; } bool shot_ok = false; a8::Vec2 shot_dir = myself->attack_dir; - if (node_.total_shot_times >= node_.next_total_shot_times) { - shot_dir = node_.target->GetPos() - myself->GetPos(); - node_.next_total_shot_times += 7 + (rand() % 6); + if (node_->total_shot_times >= node_->next_total_shot_times) { + shot_dir = node_->target->GetPos() - myself->GetPos(); + node_->next_total_shot_times += 7 + (rand() % 6); myself->attack_dir = shot_dir; } if (std::abs(shot_dir.x) > FLT_EPSILON || std::abs(shot_dir.y) > FLT_EPSILON) { shot_dir.Normalize(); - if (ai_meta->i->shot_offset_angle() > 0) { - int shot_offset_angle = a8::RandEx(ai_meta->i->shot_offset_angle(), + if (node_->ai_meta->i->shot_offset_angle() > 0) { + int shot_offset_angle = a8::RandEx(node_->ai_meta->i->shot_offset_angle(), 1); if (rand() % 10 < 3) { shot_dir.Rotate(shot_offset_angle / 180.0f); @@ -415,11 +443,11 @@ void ZombieAI::DoShot() myself->Shot(shot_dir, shot_ok); myself->attack_dir = old_attack_dir; if (shot_ok) { - if (node_.shot_times <= 0) { - node_.start_shot_frameno = myself->room->GetFrameNo(); + if (node_->shot_times <= 0) { + node_->start_shot_frameno = myself->room->GetFrameNo(); } - ++node_.shot_times; - ++node_.total_shot_times; + ++node_->shot_times; + ++node_->total_shot_times; } } } @@ -428,8 +456,8 @@ int ZombieAI::GetAttackTimes() { Human* myself = (Human*)owner; if (myself->curr_weapon) { - return std::min(ai_meta->i->attack_times(), myself->curr_weapon->GetClipVolume()); + return std::min(node_->ai_meta->i->attack_times(), myself->curr_weapon->GetClipVolume()); } else { - return ai_meta->i->attack_times(); + return node_->ai_meta->i->attack_times(); } } diff --git a/server/gameserver/zombie.ai.h b/server/gameserver/zombie.ai.h index 4df64fe..59abe5f 100644 --- a/server/gameserver/zombie.ai.h +++ b/server/gameserver/zombie.ai.h @@ -12,35 +12,12 @@ enum ZombieState_e }; class Human; -class ZombieAINode -{ -public: - ZombieState_e main_state = ZSE_Idle; - long long frameno = 0; - long long exec_frame_num = 0; - long long start_shot_frameno = 0; - long long next_random_move_frameno = 0; - int shot_times = 0; - int total_shot_times = 0; - int next_total_shot_times = 0; - - long long param1 = 0; - Human* target = nullptr; - Human* nearest_human = nullptr; - long long last_check_nearest_human_frameno = 0; - a8::Vec2 shot_dir; -}; - -namespace MetaData -{ - class AI; -} - -class Human; +class ZombieAINode; class ZombieAI : public AIComponent { public: + ZombieAI(); virtual ~ZombieAI() override; virtual void Update(int delta_time) override; float GetAttackRate(); @@ -61,7 +38,5 @@ private: int GetAttackTimes(); private: - MetaData::AI* ai_meta = nullptr; - ZombieAINode node_; - bool moving_ = false; + ZombieAINode* node_ = nullptr; };