4jcraft/targets/minecraft/world/entity/ai/goal/MeleeAttackGoal.cpp

94 lines
3.1 KiB
C++

#include "MeleeAttackGoal.h"
#include <algorithm>
#include "java/Random.h"
#include "minecraft/util/Mth.h"
#include "minecraft/world/entity/LivingEntity.h"
#include "minecraft/world/entity/PathfinderMob.h"
#include "minecraft/world/entity/ai/control/Control.h"
#include "minecraft/world/entity/ai/control/LookControl.h"
#include "minecraft/world/entity/ai/navigation/PathNavigation.h"
#include "minecraft/world/entity/ai/sensing/Sensing.h"
#include "minecraft/world/level/pathfinder/Path.h"
#include "minecraft/world/phys/AABB.h"
void MeleeAttackGoal::_init(PathfinderMob* mob, double speedModifier,
bool trackTarget) {
this->attackType = eTYPE_NOTSET;
this->mob = mob;
level = mob->level;
this->speedModifier = speedModifier;
this->trackTarget = trackTarget;
setRequiredControlFlags(Control::MoveControlFlag |
Control::LookControlFlag);
attackTime = 0;
path = nullptr;
timeToRecalcPath = 0;
}
MeleeAttackGoal::MeleeAttackGoal(PathfinderMob* mob, eINSTANCEOF attackType,
double speedModifier, bool trackTarget) {
_init(mob, speedModifier, trackTarget);
this->attackType = attackType;
}
MeleeAttackGoal::MeleeAttackGoal(PathfinderMob* mob, double speedModifier,
bool trackTarget) {
_init(mob, speedModifier, trackTarget);
}
MeleeAttackGoal::~MeleeAttackGoal() = default;
bool MeleeAttackGoal::canUse() {
std::shared_ptr<LivingEntity> target = mob->getTarget();
if (target == nullptr) return false;
if (!target->isAlive()) return false;
if (attackType != eTYPE_NOTSET && !target->instanceof(attackType))
return false;
path.reset(mob->getNavigation()->createPath(target));
return path != nullptr;
}
bool MeleeAttackGoal::canContinueToUse() {
std::shared_ptr<LivingEntity> target = mob->getTarget();
if (target == nullptr) return false;
if (!target->isAlive()) return false;
if (!trackTarget) return !mob->getNavigation()->isDone();
if (!mob->isWithinRestriction(Mth::floor(target->x), Mth::floor(target->y),
Mth::floor(target->z)))
return false;
return true;
}
void MeleeAttackGoal::start() {
mob->getNavigation()->moveTo(path.release(), speedModifier);
timeToRecalcPath = 0;
}
void MeleeAttackGoal::stop() { mob->getNavigation()->stop(); }
void MeleeAttackGoal::tick() {
std::shared_ptr<LivingEntity> target = mob->getTarget();
mob->getLookControl()->setLookAt(target, 30, 30);
if (trackTarget || mob->getSensing()->canSee(target)) {
if (--timeToRecalcPath <= 0) {
timeToRecalcPath = 4 + mob->getRandom()->nextInt(7);
mob->getNavigation()->moveTo(target, speedModifier);
}
}
attackTime = std::max(attackTime - 1, 0);
double meleeRadiusSqr =
(mob->bbWidth * 2) * (mob->bbWidth * 2) + target->bbWidth;
if (mob->distanceToSqr(target->x, target->bb.y0, target->z) >
meleeRadiusSqr)
return;
if (attackTime > 0) return;
attackTime = 20;
if (mob->getCarriedItem() != nullptr) mob->swing();
mob->doHurtTarget(target);
}