4jcraft/Minecraft.World/AI/Goals/MeleeAttackGoal.cpp
2026-03-23 18:53:18 +11:00

90 lines
3.1 KiB
C++

#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.entity.monster.h"
#include "../../Headers/net.minecraft.world.level.h"
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
#include "../Navigation/Path.h"
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
#include "../../Headers/net.minecraft.world.phys.h"
#include "MeleeAttackGoal.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 == NULL) 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 == NULL) 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() != NULL) mob->swing();
mob->doHurtTarget(target);
}