381 lines
11 KiB
C++
381 lines
11 KiB
C++
#include "precompile.h"
|
|
|
|
#include "guide.h"
|
|
#include "human.h"
|
|
#include "room.h"
|
|
#include "glmhelper.h"
|
|
#include "hero.h"
|
|
#include "trigger.h"
|
|
#include "skill.h"
|
|
|
|
#include "mt/GuideStep.h"
|
|
#include "mt/Hero.h"
|
|
#include "mt/Skill.h"
|
|
|
|
void Guide::Init(Human* owner)
|
|
{
|
|
owner_ = owner;
|
|
if (!owner_->room->IsNewBieRoom()) {
|
|
return;
|
|
}
|
|
if (mt::GuideStep::_steps.empty()) {
|
|
return;
|
|
}
|
|
curr_step_idx_ = 0;
|
|
UpdateStep();
|
|
}
|
|
|
|
void Guide::UpdateStep()
|
|
{
|
|
curr_step_meta_ = mt::GuideStep::_steps.at(curr_step_idx_);
|
|
#ifdef DEBUG
|
|
a8::XPrintf("UpdateStep idx:%d id:%d target:%d\n",
|
|
{
|
|
curr_step_idx_,
|
|
curr_step_meta_->id(),
|
|
curr_step_meta_->target()
|
|
});
|
|
#endif
|
|
owner_->room->frame_event.AddPropChg
|
|
(
|
|
owner_->GetWeakPtrRef(),
|
|
kPropGuideStep,
|
|
curr_step_meta_->id(),
|
|
0,
|
|
true);
|
|
switch (curr_step_meta_->target()) {
|
|
case mt::MOVE_TARGET_GUIDE_STEP:
|
|
{
|
|
ProcMoveTarget();
|
|
}
|
|
break;
|
|
case mt::PICKUP_GUIDE_STEP:
|
|
{
|
|
ProcPickup();
|
|
}
|
|
break;
|
|
case mt::KILL_ENEMY_GUIDE_STEP:
|
|
{
|
|
ProcKillEnemy();
|
|
}
|
|
break;
|
|
case mt::USE_SKILL_AND_KILL_ENEMY_GUIDE_STEP:
|
|
{
|
|
ProcUseSkillAndKillEnemy();
|
|
}
|
|
break;
|
|
case mt::USE_SKILL_GUIDE_STEP:
|
|
{
|
|
ProcUseSkill();
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
abort();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Guide::ProcMoveTarget()
|
|
{
|
|
owner_->room->xtimer.SetIntervalEx
|
|
(1,
|
|
[this] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
if (!curr_step_meta_->_params.empty()) {
|
|
Position pos;
|
|
pos.FromGlmVec3(std::get<1>(curr_step_meta_->_params.at(0)));
|
|
if (owner_->GetPos().Distance2D2(pos) < 30) {
|
|
NextStep();
|
|
owner_->room->xtimer.DeleteCurrentTimer();
|
|
}
|
|
} else {
|
|
NextStep();
|
|
}
|
|
}
|
|
},
|
|
&owner_->xtimer_attacher);
|
|
}
|
|
|
|
void Guide::ProcPickup()
|
|
{
|
|
if (curr_step_meta_->_params.empty()) {
|
|
NextStep();
|
|
return;
|
|
}
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
std::vector<int> loots;
|
|
);
|
|
|
|
{
|
|
int i = 0;
|
|
for (auto& tuple : curr_step_meta_->_params) {
|
|
int time = std::get<0>(tuple);
|
|
glm::vec3 pos = std::get<1>(tuple);
|
|
int equip_id = std::get<2>(tuple);
|
|
context->loots.push_back(-1);
|
|
owner_->room->xtimer.SetTimeoutEx
|
|
(
|
|
time / FRAME_RATE_MS,
|
|
[this, equip_id, pos, context, i ] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
context->loots[i] = owner_->room->CreateLoot
|
|
(
|
|
equip_id,
|
|
pos,
|
|
1,
|
|
1
|
|
);
|
|
if (context->loots[i] <= 0) {
|
|
abort();
|
|
}
|
|
}
|
|
},
|
|
&owner_->xtimer_attacher);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
owner_->room->xtimer.SetIntervalEx
|
|
(1,
|
|
[this, context] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
bool done = true;
|
|
for (int loot_uniid : context->loots) {
|
|
if (loot_uniid == -1) {
|
|
done = false;
|
|
break;
|
|
}
|
|
if (owner_->room->GetEntityByUniId(loot_uniid)) {
|
|
done = false;
|
|
break;
|
|
}
|
|
}
|
|
if (done) {
|
|
NextStep();
|
|
owner_->room->xtimer.DeleteCurrentTimer();
|
|
}
|
|
}
|
|
},
|
|
&owner_->xtimer_attacher);
|
|
|
|
}
|
|
|
|
void Guide::ProcKillEnemy()
|
|
{
|
|
if (curr_step_meta_->_params.empty()) {
|
|
NextStep();
|
|
return;
|
|
}
|
|
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
std::vector<int> heros;
|
|
);
|
|
|
|
{
|
|
int i = 0;
|
|
for (auto& tuple : curr_step_meta_->_params) {
|
|
int time = std::get<0>(tuple);
|
|
glm::vec3 pos = std::get<1>(tuple);
|
|
int hero_id = std::get<2>(tuple);
|
|
const mt::Hero* hero_meta = mt::Hero::GetById(hero_id);
|
|
if (!hero_meta){
|
|
continue;
|
|
}
|
|
context->heros.push_back(-1);
|
|
owner_->room->xtimer.SetTimeoutEx
|
|
(
|
|
time / FRAME_RATE_MS,
|
|
[this, hero_id, hero_meta, pos, context, i ] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
Hero* hero = owner_->room->CreateHero
|
|
(
|
|
nullptr,
|
|
hero_meta,
|
|
pos,
|
|
pos,
|
|
666
|
|
);
|
|
if (!hero) {
|
|
abort();
|
|
}
|
|
hero->SetHP(0.1f);
|
|
context->heros[i] = hero->GetUniId();
|
|
}
|
|
},
|
|
&owner_->xtimer_attacher);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
owner_->room->xtimer.SetIntervalEx
|
|
(1,
|
|
[this, context] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
bool done = true;
|
|
for (int hero_uniid : context->heros) {
|
|
if (hero_uniid <= 0) {
|
|
done = false;
|
|
break;
|
|
}
|
|
Entity* e = owner_->room->GetEntityByUniId(hero_uniid);
|
|
if (e && e->IsEntityType(ET_Hero)) {
|
|
Hero* hero = (Hero*)e;
|
|
if (!hero->dead) {
|
|
done = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (done) {
|
|
NextStep();
|
|
owner_->room->xtimer.DeleteCurrentTimer();
|
|
}
|
|
}
|
|
},
|
|
&owner_->xtimer_attacher);
|
|
|
|
}
|
|
|
|
void Guide::ProcUseSkillAndKillEnemy()
|
|
{
|
|
if (curr_step_meta_->_params.empty()) {
|
|
NextStep();
|
|
return;
|
|
}
|
|
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
std::vector<int> heros;
|
|
std::vector<std::weak_ptr<EventHandlerPtr>> handlers;
|
|
);
|
|
|
|
{
|
|
int i = 0;
|
|
for (auto& tuple : curr_step_meta_->_params) {
|
|
int time = std::get<0>(tuple);
|
|
glm::vec3 pos = std::get<1>(tuple);
|
|
int hero_id = std::get<2>(tuple);
|
|
const mt::Hero* hero_meta = mt::Hero::GetById(hero_id);
|
|
if (!hero_meta){
|
|
continue;
|
|
}
|
|
context->heros.push_back(-1);
|
|
owner_->room->xtimer.SetTimeoutEx
|
|
(
|
|
time / FRAME_RATE_MS,
|
|
[this, hero_id, hero_meta, pos, context, i ] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
Hero* hero = owner_->room->CreateHero
|
|
(
|
|
nullptr,
|
|
hero_meta,
|
|
pos,
|
|
pos,
|
|
666
|
|
);
|
|
if (!hero) {
|
|
abort();
|
|
}
|
|
hero->SetHP(0.1f);
|
|
context->heros[i] = hero->GetUniId();
|
|
}
|
|
},
|
|
&owner_->xtimer_attacher);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
owner_->room->xtimer.SetIntervalEx
|
|
(1,
|
|
[this, context] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
bool done = true;
|
|
for (int hero_uniid : context->heros) {
|
|
if (hero_uniid <= 0) {
|
|
done = false;
|
|
break;
|
|
}
|
|
Entity* e = owner_->room->GetEntityByUniId(hero_uniid);
|
|
if (e && e->IsEntityType(ET_Hero)) {
|
|
Hero* hero = (Hero*)e;
|
|
if (!hero->dead) {
|
|
done = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (done) {
|
|
NextStep();
|
|
owner_->room->xtimer.DeleteCurrentTimer();
|
|
}
|
|
}
|
|
},
|
|
&owner_->xtimer_attacher);
|
|
|
|
context->handlers.push_back
|
|
(owner_->GetTrigger()->AddListener
|
|
(
|
|
kUseSkillEvent,
|
|
[this, context] (const a8::Args& args) mutable
|
|
{
|
|
Skill* skill = args.Get<Skill*>(0);
|
|
if (curr_step_meta_->_int_param1 == skill->meta->skill_id()) {
|
|
NextStep();
|
|
owner_->GetTrigger()->RemoveEventHandlers(context->handlers);
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
void Guide::ProcUseSkill()
|
|
{
|
|
auto context = A8_MAKE_ANON_STRUCT_SHARED
|
|
(
|
|
std::vector<std::weak_ptr<EventHandlerPtr>> handlers;
|
|
);
|
|
|
|
context->handlers.push_back
|
|
(owner_->GetTrigger()->AddListener
|
|
(
|
|
kUseSkillEvent,
|
|
[this, context] (const a8::Args& args) mutable
|
|
{
|
|
Skill* skill = args.Get<Skill*>(0);
|
|
if (curr_step_meta_->_int_param1 == skill->meta->skill_id()) {
|
|
NextStep();
|
|
owner_->GetTrigger()->RemoveEventHandlers(context->handlers);
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
void Guide::NextStep()
|
|
{
|
|
#ifdef DEBUG
|
|
a8::XPrintf("next step %d\n", {curr_step_idx_});
|
|
#endif
|
|
++curr_step_idx_;
|
|
if (curr_step_idx_ >= mt::GuideStep::_steps.size()) {
|
|
owner_->room->frame_event.AddPropChg
|
|
(
|
|
owner_->GetWeakPtrRef(),
|
|
kPropGuideStep,
|
|
-1,
|
|
0,
|
|
true);
|
|
return;
|
|
}
|
|
UpdateStep();
|
|
}
|