#include "precompile.h" #include #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(); master_agent = behaviac::Agent::Create(); team_agent = behaviac::Agent::Create(); } 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; } 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(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(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(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(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 ( 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(context, "CoFindPath"); 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::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(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(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(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 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 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(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; }