1
This commit is contained in:
parent
714342d4ce
commit
c84de56bbc
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user