game2006/server/gameserver/new_hero_agent.cc
aozhiwei e2537a6b1a 1
2023-10-18 11:32:11 +08:00

693 lines
17 KiB
C++

#include "precompile.h"
#include <f8/btmgr.h>
#include "new_hero_agent.h"
#include "hero.h"
#include "room.h"
#include "movement.h"
#include "netdata.h"
#include "glmhelper.h"
#include "target_agent.h"
#include "weapon.h"
#include "mapinstance.h"
#include "collision.h"
#include "human.h"
#include "btcoroutine.h"
#include "btcontext.h"
#include "team.h"
#include "master_agent.h"
#include "team_agent.h"
#include "mt/Hero.h"
#include "mt/Equip.h"
HeroAgent::HeroAgent():BaseAgent()
{
current_target_agent = behaviac::Agent::Create<TargetAgent>();
master_agent = behaviac::Agent::Create<MasterAgent>();
team_agent = behaviac::Agent::Create<TeamAgent>();
}
HeroAgent::~HeroAgent()
{
{
f8::BtMgr::Instance()->BtDestory(current_target_agent);
current_target_agent = nullptr;
}
{
f8::BtMgr::Instance()->BtDestory(master_agent);
master_agent = nullptr;
}
{
f8::BtMgr::Instance()->BtDestory(team_agent);
team_agent = nullptr;
}
}
void HeroAgent::Exec()
{
behaviac::EBTStatus status = f8::BtMgr::Instance()->BtExec(this);
if (status == behaviac::BT_RUNNING &&
coroutine_ &&
coroutine_->GetContext()->HasEvent()) {
status_= behaviac::BT_INVALID;
auto old_coroutine = coroutine_;
coroutine_ = nullptr;
owner_->shot_hold = false;
old_coroutine->GetContext()->FireEvent(this);
old_coroutine = nullptr;
}
}
void HeroAgent::SetOwner(Creature* owner)
{
owner_ = owner;
current_target_agent->SetOwner(owner_);
room_agent = owner_->room->GetRoomAgent();
}
int HeroAgent::GetUniId()
{
return owner_->GetUniId();
}
int HeroAgent::GetAgentType()
{
abort();
}
bool HeroAgent::IsMoving()
{
return owner_->GetMovement()->GetPathSize() > 0;
}
glm::vec3 HeroAgent::GetPos()
{
return owner_->GetPos().ToGlmVec3();
}
bool HeroAgent::IsDead()
{
return owner_->dead;
}
glm::vec3 HeroAgent::GetSafeAreaCenter()
{
return glm::vec3(
owner_->room->GetGasData().pos_new.x,
0.0f,
owner_->room->GetGasData().pos_new.y
);
}
float HeroAgent::GetSafeAreaRadius()
{
return owner_->room->GetGasData().gas_progress;
}
float HeroAgent::GetHp()
{
return owner_->GetHP();
}
float HeroAgent::GetMaxHp()
{
return owner_->GetMaxHP();
}
void HeroAgent::OpenBulletTraceMode()
{
bullet_trace_mode_ = true;
}
void HeroAgent::CloseBulletTraceMode()
{
bullet_trace_mode_ = false;
}
float HeroAgent::CalcDistance(const glm::vec3& target_pos)
{
return owner_->GetPos().DistanceGlmVec3(target_pos);
}
int HeroAgent::GetHeroId()
{
return owner_->GetHeroMeta()->id();
}
int HeroAgent::GetLevel()
{
return owner_->level;
}
bool HeroAgent::CanShot()
{
return owner_->CanShot(false);
}
bool HeroAgent::CanUseSkill()
{
abort();
}
void HeroAgent::UseSkill(int skill_id)
{
abort();
}
void HeroAgent::SendEmote(int emote)
{
owner_->room->frame_event.AddEmote(owner_->GetWeakPtrRef(), emote);
}
int HeroAgent::GetBattleTimes()
{
return owner_->GetBattleContext()->GetBattleTimes();
}
void HeroAgent::SetMoveDir(const glm::vec3& dir)
{
owner_->SetMoveDir(dir);
}
void HeroAgent::SetAttackDir(const glm::vec3& dir)
{
owner_->SetAttackDir(dir);
}
void HeroAgent::ShotNormal(const glm::vec3& dir)
{
if (owner_->dead) {
return;
}
if (owner_->CanShot(true)) {
bool shot_ok = false;
glm::vec3 shot_dir = owner_->GetAttackDir();
if (bullet_trace_mode_) {
owner_->Shot(shot_dir, shot_ok, 0, 0);
} else {
owner_->Shot(shot_dir, shot_ok, 0, 0);
}
}
}
void HeroAgent::ShotTrace()
{
abort();
}
glm::vec3 HeroAgent::GetRandomDir()
{
glm::vec3 dir = owner_->GetAttackDir();
GlmHelper::RotateY(dir, (10 + rand() % 360)/ 180.0f);
return dir;
}
glm::vec3 HeroAgent::GetTargetDir()
{
if (current_target_agent->IsValid()) {
return owner_->GetMoveDir();
}
glm::vec3 dir = current_target_agent->GetPos() - owner_->GetPos().ToGlmVec3();
GlmHelper::Normalize(dir);
return dir;
}
glm::vec3 HeroAgent::RandomPoint(const glm::vec3& center, float range)
{
glm::vec3 hit_point;
bool hit_result = false;
glm::vec3 start = center;
glm::vec3 dir = GlmHelper::UP;
GlmHelper::RotateY(dir, (10 + rand() % 360)/ 180.0f);
GlmHelper::Normalize(dir);
glm::vec3 end = center + dir * range;
owner_->room->map_instance->Scale(start);
owner_->room->map_instance->Scale(end);
if (owner_->room->map_instance->Raycast
(
start,
end,
hit_point,
hit_result
)) {
owner_->room->map_instance->Scale(hit_point);
}
return hit_point;
}
behaviac::EBTStatus HeroAgent::RandomSafeZonePoint(int try_count, int step_len)
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
auto context = MAKE_BTCONTEXT
(
);
auto co = std::make_shared<BtCoroutine>(context, "RandomSafeZonePoint");
co->runing_cb =
[this, context, try_count, step_len] ()
{
if (owner_->dead) {
return behaviac::BT_FAILURE;
}
glm::vec3 gas_center = GlmHelper::Vec2ToVec3(owner_->room->GetGasData().pos_new);
gas_center.y = owner_->GetPos().ToGlmVec3().y;
if (GlmHelper::IsEqual2D(owner_->GetPos().ToGlmVec3(),
gas_center)) {
out_point0 = gas_center;
return behaviac::BT_SUCCESS;
}
glm::vec3 dir = gas_center - owner_->GetPos().ToGlmVec3();
GlmHelper::Normalize(dir);
glm::vec3 center = owner_->GetPos().ToGlmVec3() +
dir * (50.0f + (float)(try_count + 1) * step_len);
owner_->room->map_instance->Scale(center);
glm::vec3 point;
bool ok = owner_->room->map_instance->FindConnectableNearestPoint(center, 50, point);
if (ok) {
owner_->room->map_instance->UnScale(point);
out_point0 = point;
return behaviac::BT_SUCCESS;
}
return behaviac::BT_FAILURE;
};
return StartCoroutine(co);
}
float HeroAgent::GetShotRange()
{
if (owner_->GetCurrWeapon()) {
return owner_->GetCurrWeapon()->meta->range();
}
return 0.0f;
}
void HeroAgent::SetV(int id, int val)
{
auto itr = dyn_hash_.find(id);
if (itr != dyn_hash_.end()) {
itr->second = val;
} else {
dyn_hash_[id] = val;
}
}
int HeroAgent::GetV(int id)
{
auto itr = dyn_hash_.find(id);
if (itr != dyn_hash_.end()) {
return itr->second;
} else {
return 0;
}
}
int HeroAgent::IncV(int id, int val)
{
auto itr = dyn_hash_.find(id);
if (itr != dyn_hash_.end()) {
itr->second += val;
return itr->second;
} else {
dyn_hash_[id] = val;
return val;
}
}
int HeroAgent::DecV(int id, int val)
{
return IncV(id, -val);
}
bool HeroAgent::HasBuffEffect(int effect_id)
{
return owner_->HasBuffEffect(effect_id);
}
bool HeroAgent::IsNearGas(float anti_range)
{
return !Collision::InSquare
(GlmHelper::Vec2ToVec3(owner_->room->GetGasData().pos_old),
owner_->GetPos().ToGlmVec3(),
std::max(owner_->room->GetGasData().rad_new,
owner_->room->GetGasData().gas_progress) * 0.7 -
anti_range);
}
bool HeroAgent::MasterInRange(float range)
{
if (!owner_->IsHero() ||
!owner_->AsHero()->master.Get()) {
return false;
}
return Collision::InSquare
(owner_->AsHero()->master.Get()->GetPos().ToGlmVec3(),
owner_->GetPos().ToGlmVec3(),
range);
}
behaviac::EBTStatus HeroAgent::SearchEnemy(float range)
{
Creature* myself = owner_;
Human* target = nullptr;
float last_distance = range + 1;
owner_->room->TraverseHumanList
(
[myself, &last_distance, &target, range] (Human* hum)
{
if (!hum->dead &&
!a8::HasBitFlag(hum->status, CS_Disable) &&
!hum->HasBuffEffect(kBET_Hide) &&
!hum->HasBuffEffect(kBET_Invincible) &&
hum->team_id != myself->team_id) {
if (a8::HasBitFlag(myself->status, CS_DisableAttackAndroid) &&
hum->IsAndroid()) {
} else {
float distance = hum->GetPos().Distance2D2(myself->GetPos());
if (distance <= range) {
if (distance < last_distance) {
target = hum;
last_distance = distance;
}
}
}
}
return true;
});
return behaviac::BT_FAILURE;
}
behaviac::EBTStatus HeroAgent::CoIdle(int min_val, int max_val)
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
auto context = MAKE_BTCONTEXT
(
int time = 0;
);
context->time = a8::RandEx(min_val, max_val);
auto co = std::make_shared<BtCoroutine>(context, "CoIdle");
co->runing_cb =
[this, context] ()
{
if ((GetRoom()->GetFrameNo() - context->frameno) * FRAME_RATE_MS <
context->time) {
return behaviac::BT_RUNNING;
} else {
return behaviac::BT_SUCCESS;
}
};
return StartCoroutine(co);
}
behaviac::EBTStatus HeroAgent::CoMoveCurrentTargetRaycast()
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
auto context = MAKE_BTCONTEXT
(
);
auto co = std::make_shared<BtCoroutine>(context, "CoMoveCurrentTargetRaycast");
co->runing_cb =
[this, context] ()
{
return behaviac::BT_SUCCESS;
};
return StartCoroutine(co);
}
behaviac::EBTStatus HeroAgent::CoShotCurrentTargetRaycast()
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
auto context = MAKE_BTCONTEXT
(
a8::XTimerWp timer_ptr;
);
context->timer_ptr = owner_->room->xtimer.SetTimeoutWpEx
(
1000 / FRAME_RATE_MS,
[] (int event, const a8::Args* args)
{
},
&owner_->xtimer_attacher);
auto co = std::make_shared<BtCoroutine>(context, "CoShotCurrentTargetRaycast");
co->runing_cb =
[this, context] ()
{
if (!context->timer_ptr.expired()) {
return behaviac::BT_RUNNING;
} else {
return behaviac::BT_SUCCESS;
}
};
return StartCoroutine(co);
}
behaviac::EBTStatus HeroAgent::CoMoveMasterRaycast()
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
auto context = MAKE_BTCONTEXT
(
a8::XTimerWp timer_ptr;
);
context->timer_ptr = owner_->room->xtimer.SetTimeoutWpEx
(
1000 / FRAME_RATE_MS,
[] (int event, const a8::Args* args)
{
},
&owner_->xtimer_attacher);
auto co = std::make_shared<BtCoroutine>(context, "CoMoveMasterRaycast");
co->runing_cb =
[this, context] ()
{
if (!context->timer_ptr.expired()) {
return behaviac::BT_RUNNING;
} else {
return behaviac::BT_SUCCESS;
}
};
return StartCoroutine(co);
}
behaviac::EBTStatus HeroAgent::CoFindPath(const glm::vec3& pos)
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
auto context = MAKE_BTCONTEXT
(
bool find_ok = false;
glm::vec3 target_pos;
);
context->target_pos = pos;
auto co = std::make_shared<BtCoroutine>(context, "CoFindPath");
co->runing_cb =
[this, context, pos] ()
{
if (owner_->dead) {
return behaviac::BT_FAILURE;
}
if (context->find_ok) {
if (owner_->GetMovement()->GetPathSize() <= 0) {
return behaviac::BT_SUCCESS;
} else {
return behaviac::BT_RUNNING;
}
}
bool ret = owner_->GetMovement()->FindPath(context->target_pos, 0);
if (ret) {
context->find_ok = true;
} else {
return behaviac::BT_FAILURE;
}
return behaviac::BT_RUNNING;
};
return StartCoroutine(co);
}
behaviac::EBTStatus HeroAgent::CoFindPathEx(const glm::vec3& pos, float distance)
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
auto context = MAKE_BTCONTEXT
(
a8::XTimerWp timer_ptr;
);
context->timer_ptr = owner_->room->xtimer.SetTimeoutWpEx
(
1000 / FRAME_RATE_MS,
[] (int event, const a8::Args* args)
{
},
&owner_->xtimer_attacher);
auto co = std::make_shared<BtCoroutine>(context, "CoFindPathEx");
co->runing_cb =
[this, context] ()
{
if (!context->timer_ptr.expired()) {
return behaviac::BT_RUNNING;
} else {
return behaviac::BT_SUCCESS;
}
};
return StartCoroutine(co);
}
behaviac::EBTStatus HeroAgent::CoStartMove(int min_val, int max_val)
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
float distance = a8::RandEx(min_val, max_val);
auto context = MAKE_BTCONTEXT
(
);
auto co = std::make_shared<BtCoroutine>(context, "CoStartMove");
co->runing_cb =
[this, context, distance] ()
{
if (!owner_->dead) {
owner_->GetMovement()->CalcTargetPos(distance);
}
return behaviac::BT_SUCCESS;
};
return StartCoroutine(co);
}
behaviac::EBTStatus HeroAgent::CoSleep(int time)
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
auto context = MAKE_BTCONTEXT
(
a8::XTimerWp timer_ptr;
);
context->timer_ptr = owner_->room->xtimer.SetTimeoutWpEx
(
1000 / FRAME_RATE_MS,
[] (int event, const a8::Args* args)
{
},
&owner_->xtimer_attacher);
auto co = std::make_shared<BtCoroutine>(context, "CoSleep");
co->runing_cb =
[this, context] ()
{
if (!context->timer_ptr.expired()) {
return behaviac::BT_RUNNING;
} else {
return behaviac::BT_SUCCESS;
}
};
return StartCoroutine(co);
}
Room* HeroAgent::GetRoom()
{
return owner_->room;
}
bool HeroAgent::HasFlag(int tag)
{
return a8::HasBitFlag(flags_, tag);
}
void HeroAgent::SetFlag(int tag)
{
a8::SetBitFlag(flags_, tag);
}
void HeroAgent::UnSetFlag(int tag)
{
a8::UnSetBitFlag(flags_, tag);
}
behaviac::EBTStatus HeroAgent::DoRunningCb()
{
if (status_ != behaviac::BT_RUNNING) {
abort();
}
if (owner_->room->GetFrameNo() < coroutine_->sleep_end_frameno) {
return behaviac::BT_RUNNING;
}
status_ = coroutine_->runing_cb();
#ifdef DEBUG1
if ((owner_->room->GetFrameNo() - status_frameno_) % SERVER_FRAME_RATE == 0 ||
last_status_ != status_) {
last_status_ = status_;
a8::XPrintf("Running Status:%s %d\n", {status_name_, status_});
}
#endif
if (status_ != behaviac::BT_RUNNING) {
coroutine_ = nullptr;
}
return status_;
}
behaviac::EBTStatus HeroAgent::StartCoroutine(std::shared_ptr<BtCoroutine> coroutine)
{
#ifdef DEBUG1
a8::XPrintf("StartCoroutine:%d %s\n", {owner_->GetUniId(), coroutine->GetName()});
#endif
coroutine_ = coroutine;
#ifdef DEBUG
last_status_ = behaviac::BT_INVALID;
status_frameno_ = owner_->room->GetFrameNo();
status_name_ = coroutine_->GetName();
#endif
status_ = behaviac::BT_RUNNING;
return status_;
}
behaviac::EBTStatus HeroAgent::RegisterEvents(behaviac::vector<BtEvent_e> events)
{
return behaviac::BT_SUCCESS;
}
behaviac::EBTStatus HeroAgent::CoMoveForward(int min_val, int max_val)
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
float distance = a8::RandEx(min_val, max_val);
auto context = MAKE_BTCONTEXT
(
);
owner_->GetMovement()->CalcTargetPos(distance);
auto co = std::make_shared<BtCoroutine>(context, "CoMoveForward");
co->runing_cb =
[this, context] ()
{
if (owner_->GetMovement()->GetPathSize() <= 0) {
return behaviac::BT_SUCCESS;
} else {
return behaviac::BT_RUNNING;
}
};
return StartCoroutine(co);
}
behaviac::EBTStatus HeroAgent::DebugOut(std::string msg, int arg0, int arg1, int arg2)
{
#ifdef DEBUG1
a8::XPrintf((msg+"\n").c_str(), {arg0, arg1, arg2});
#endif
return behaviac::BT_SUCCESS;
}