2017-09-17 13:43:13 +02:00
|
|
|
#include "AttackEnemyNode.h"
|
|
|
|
#include "BehaviourTree.h"
|
|
|
|
#include "Actor.h"
|
|
|
|
#include "Tilemap.h"
|
|
|
|
#include "Pathfinder.h"
|
2017-09-21 22:17:06 +02:00
|
|
|
#include "FieldOfView.h"
|
2017-09-17 13:43:13 +02:00
|
|
|
|
|
|
|
AttackEnemyNode::AttackEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent){}
|
|
|
|
|
2017-09-26 15:49:11 +02:00
|
|
|
AttackEnemyNode::~AttackEnemyNode() = default;
|
2017-09-17 13:43:13 +02:00
|
|
|
|
|
|
|
BehaviourTreeStatus AttackEnemyNode::tick(BTTick * tick) {
|
2017-09-26 15:49:11 +02:00
|
|
|
bool ishero = tick->target->is_type_of(ACT_HERO);
|
|
|
|
vec2i targetpos = tick->target->get_position();
|
2017-09-17 13:43:13 +02:00
|
|
|
|
2017-09-26 15:49:11 +02:00
|
|
|
auto actors = tick->target->get_map()->get_entities(targetpos.x, targetpos.y, 6, ENTITY_ACTOR);
|
2017-09-17 13:43:13 +02:00
|
|
|
std::vector<Actor*> visibleEnemies;
|
|
|
|
|
2017-09-26 15:49:11 +02:00
|
|
|
for (auto ent : actors) {
|
|
|
|
auto actor = (Actor*)ent;
|
2017-09-17 13:43:13 +02:00
|
|
|
if (actor == tick->target) continue;
|
|
|
|
|
2017-09-26 15:49:11 +02:00
|
|
|
|
|
|
|
if (actor->is_type_of(ACT_HERO) != ishero) {
|
2017-09-21 22:44:05 +02:00
|
|
|
vec2i pos = actor->get_position();
|
2017-09-26 15:49:11 +02:00
|
|
|
if (line_of_sight(tick->target->get_map(), tick->target->get_position(), pos)) {
|
2017-09-17 13:43:13 +02:00
|
|
|
visibleEnemies.push_back(actor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-26 15:49:11 +02:00
|
|
|
if (visibleEnemies.empty()) {
|
2017-09-17 13:43:13 +02:00
|
|
|
return BT_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Actor* closestActor = nullptr;
|
2017-09-26 15:49:11 +02:00
|
|
|
float closestDist = tick->target->get_range();
|
2017-09-17 20:07:38 +02:00
|
|
|
for (Actor* actor : visibleEnemies) {
|
2017-09-21 22:44:05 +02:00
|
|
|
float dist = Pathfinder::distance(tick->target->get_position(), actor->get_position());
|
2017-09-17 13:43:13 +02:00
|
|
|
if (closestActor == nullptr ||
|
|
|
|
dist < closestDist) {
|
|
|
|
closestActor = actor;
|
|
|
|
closestDist = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-26 15:49:11 +02:00
|
|
|
if (closestDist < tick->target->get_range()) {
|
|
|
|
tick->target->attack(closestActor);
|
|
|
|
if (!closestActor->is_alive()) {
|
2017-09-17 13:43:13 +02:00
|
|
|
return BT_SUCCEEDED;
|
|
|
|
}
|
|
|
|
return BT_RUNNING;
|
|
|
|
}
|
|
|
|
else {
|
2017-09-21 22:44:05 +02:00
|
|
|
vec2i pos = tick->target->get_position();
|
|
|
|
vec2i goal = closestActor->get_position();
|
2017-09-26 15:49:11 +02:00
|
|
|
auto path = Pathfinder::aStar(tick->target->get_map(), pos, goal);
|
|
|
|
if (!path.empty()) {
|
2017-09-17 13:43:13 +02:00
|
|
|
//path.pop_back();
|
|
|
|
vec2i dpos = path.back() - pos;
|
2017-09-26 15:49:11 +02:00
|
|
|
if (tick->target->move(dpos.x, dpos.y)) {
|
2017-09-17 13:43:13 +02:00
|
|
|
return BT_RUNNING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return BT_FAILED;
|
|
|
|
}
|
|
|
|
}
|