game2006/server/gameserver/base_agent.cc
aozhiwei bbf5535158 1
2023-03-31 14:27:31 +08:00

182 lines
5.8 KiB
C++

#include "precompile.h"
#include "base_agent.h"
#include "room.h"
#include "creature.h"
#include "human.h"
#include "movement.h"
#include "glmhelper.h"
#include "f8/btmgr.h"
void DumpBt(BaseAgent* agent)
{
static std::string last_bt_name;
static int last_task_id = 0;
std::string data = "CurrentBt: " + f8::BtMgr::Instance()->BtGetCurrent(agent)->GetName() + ": ";
const behaviac::BehaviorTask* curr_task = f8::BtMgr::Instance()->BtGetCurrent(agent)->GetCurrentTask();
if (last_bt_name != f8::BtMgr::Instance()->BtGetCurrent(agent)->GetName() ||
last_task_id != curr_task->GetId()) {
last_bt_name = f8::BtMgr::Instance()->BtGetCurrent(agent)->GetName();
last_task_id = curr_task->GetId();
while (curr_task) {
data += a8::Format("->%d",
{
curr_task->GetId(),
});
curr_task = curr_task->GetCurrentTask();
}
a8::XPrintf("%s\n", {data});
}
}
BaseAgent::BaseAgent():behaviac::Agent()
{
}
BaseAgent::~BaseAgent()
{
}
bool BaseAgent::IsGameOver()
{
return GetOwner()->room->IsGameOver();
}
void BaseAgent::Exec()
{
behaviac::EBTStatus status = f8::BtMgr::Instance()->BtExec(this);
if (status == behaviac::BT_RUNNING && event_cb_) {
#ifdef DEBUG1
DumpBt(this);
#endif
bool has_event = false;
event_cb_(true, has_event);
if (has_event) {
status_= behaviac::BT_INVALID;
runing_cb_ = nullptr;
event_cb_(false, has_event);
event_cb_ = nullptr;
#ifdef DEBUG
a8::XPrintf("FireEvent OnAttacked\n", {});
#endif
}
}
}
bool BaseAgent::HasTarget(float range)
{
Human* enemy = GetOwner()->room->FindEnemy(GetOwner()->AsHuman(), range);
return enemy != nullptr;
}
behaviac::EBTStatus BaseAgent::DoRunningCb()
{
if (status_ != behaviac::BT_RUNNING) {
abort();
}
status_ = runing_cb_();
#ifdef DEBUG1
if ((GetOwner()->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) {
runing_cb_ = nullptr;
}
return status_;
}
behaviac::EBTStatus BaseAgent::StartCoroutine(std::function<behaviac::EBTStatus()> cb,
std::function<void(bool, bool&)> event_cb,
const char* name)
{
#ifdef DEBUG
last_status_ = behaviac::BT_INVALID;
status_frameno_ = GetOwner()->room->GetFrameNo();
status_name_ = name;
#endif
runing_cb_ = std::move(cb);
event_cb_ = std::move(event_cb);
status_ = behaviac::BT_RUNNING;
return status_;
}
behaviac::EBTStatus BaseAgent::CoAttackTarget(int target_id)
{
if (status_ == behaviac::BT_RUNNING) {
return DoRunningCb();
}
Entity* entity = GetOwner()->room->GetEntityByUniId(target_id);
if (!entity || !entity->IsCreature(GetOwner()->room)) {
return behaviac::BT_FAILURE;
}
CreatureWeakPtr target = ((Creature*)entity)->GetWeakPtrRef();
if (target.Get()->dead) {
return behaviac::BT_FAILURE;
}
long long frameno = GetOwner()->room->GetFrameNo();
long long last_pursuit_frameno = GetOwner()->room->GetFrameNo();
return StartCoroutine
(
[this, target, frameno, last_pursuit_frameno] () mutable
{
if (GetOwner()->room->GetFrameNo() - frameno > SERVER_FRAME_RATE * 10 ||
!target.Get() || target.Get()->dead) {
return behaviac::BT_SUCCESS;
} else {
glm::vec3 dir = GetOwner()->GetPos().CalcDir(target.Get()->GetPos());
if (GlmHelper::Norm(dir) <= 1.0f) {
GetOwner()->GetMovement()->CalcTargetPos(60);
last_pursuit_frameno = GetOwner()->room->GetFrameNo();
} else {
bool is_shot = false;
if (GlmHelper::Norm(dir) > 300) {
if (GetOwner()->GetMovement()->GetPathSize() < 1) {
GlmHelper::Normalize(dir);
GetOwner()->SetMoveDir(dir);
GetOwner()->SetAttackDir(dir);
GetOwner()->GetMovement()->CalcTargetPos(200);
last_pursuit_frameno = GetOwner()->room->GetFrameNo();
} else {
if (GetOwner()->room->GetFrameNo() - last_pursuit_frameno > SERVER_FRAME_RATE * 1) {
GlmHelper::Normalize(dir);
GetOwner()->SetMoveDir(dir);
GetOwner()->SetAttackDir(dir);
GetOwner()->GetMovement()->CalcTargetPos(200);
last_pursuit_frameno = GetOwner()->room->GetFrameNo();
}
}
} else {
GlmHelper::Normalize(dir);
is_shot = true;
}
if (is_shot) {
bool shot_ok = false;
glm::vec3 shot_dir = dir;
GetOwner()->SetAttackDir(dir);
GetOwner()->Shot(shot_dir, shot_ok, 0, 0);
}
}
}
return behaviac::BT_RUNNING;
},
[this] (bool is_test, bool& has_event)
{
},
"CoAttackTarget"
);
}
bool BaseAgent::HasBuffEffect(int buff_effect)
{
return owner_->HasBuffEffect(buff_effect);
}