4jcraft/Minecraft.World/AI/Goals/OcelotSitOnTileGoal.cpp
2026-03-21 15:10:07 -05:00

122 lines
3.9 KiB
C++

#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
#include "../../Headers/net.minecraft.world.entity.ai.goal.h"
#include "../../Headers/net.minecraft.world.entity.animal.h"
#include "../../Headers/net.minecraft.world.level.h"
#include "../../Headers/net.minecraft.world.level.tile.h"
#include "../../Headers/net.minecraft.world.level.tile.entity.h"
#include "../../Util/BasicTypeContainers.h"
#include "../../Util/Arrays.h"
#include "OcelotSitOnTileGoal.h"
const int OcelotSitOnTileGoal::GIVE_UP_TICKS =
3 * SharedConstants::TICKS_PER_SECOND;
const int OcelotSitOnTileGoal::SIT_TICKS =
60 * SharedConstants::TICKS_PER_SECOND;
const int OcelotSitOnTileGoal::SEARCH_RANGE = 8;
const double OcelotSitOnTileGoal::SIT_CHANCE = 0.0065f;
OcelotSitOnTileGoal::OcelotSitOnTileGoal(Ocelot* ocelot, double speedModifier) {
_tick = 0;
tryTicks = 0;
maxTicks = 0;
tileX = 0;
tileY = 0;
tileZ = 0;
this->ocelot = ocelot;
this->speedModifier = speedModifier;
setRequiredControlFlags(Control::MoveControlFlag |
Control::JumpControlFlag);
}
bool OcelotSitOnTileGoal::canUse() {
return ocelot->isTame() && !ocelot->isSitting() &&
ocelot->getRandom()->nextDouble() <= SIT_CHANCE && findNearestTile();
}
bool OcelotSitOnTileGoal::canContinueToUse() {
return _tick <= maxTicks && tryTicks <= GIVE_UP_TICKS &&
isValidTarget(ocelot->level, tileX, tileY, tileZ);
}
void OcelotSitOnTileGoal::start() {
ocelot->getNavigation()->moveTo((float)tileX + 0.5, tileY + 1,
(float)tileZ + 0.5, speedModifier);
_tick = 0;
tryTicks = 0;
maxTicks = ocelot->getRandom()->nextInt(
ocelot->getRandom()->nextInt(SIT_TICKS) + SIT_TICKS) +
SIT_TICKS;
ocelot->getSitGoal()->wantToSit(false);
ocelot->setSittingOnTile(true); // 4J-Added.
}
void OcelotSitOnTileGoal::stop() {
ocelot->setSitting(false);
ocelot->setSittingOnTile(false); // 4J-Added.
}
void OcelotSitOnTileGoal::tick() {
_tick++;
ocelot->getSitGoal()->wantToSit(false);
if (ocelot->distanceToSqr(tileX, tileY + 1, tileZ) > 1) {
ocelot->setSitting(false);
ocelot->getNavigation()->moveTo((float)tileX + 0.5, tileY + 1,
(float)tileZ + 0.5, speedModifier);
tryTicks++;
} else if (!ocelot->isSitting()) {
ocelot->setSitting(true);
} else {
tryTicks--;
}
}
bool OcelotSitOnTileGoal::findNearestTile() {
int y = (int)ocelot->y;
double distSqr = Integer::MAX_VALUE;
for (int x = (int)ocelot->x - SEARCH_RANGE; x < ocelot->x + SEARCH_RANGE;
x++) {
for (int z = (int)ocelot->z - SEARCH_RANGE;
z < ocelot->z + SEARCH_RANGE; z++) {
if (isValidTarget(ocelot->level, x, y, z) &&
ocelot->level->isEmptyTile(x, y + 1, z)) {
double dist = ocelot->distanceToSqr(x, y, z);
if (dist < distSqr) {
tileX = x;
tileY = y;
tileZ = z;
distSqr = dist;
}
}
}
}
return distSqr < Integer::MAX_VALUE;
}
bool OcelotSitOnTileGoal::isValidTarget(Level* level, int x, int y, int z) {
int tile = level->getTile(x, y, z);
int data = level->getData(x, y, z);
if (tile == Tile::chest_Id) {
std::shared_ptr<ChestTileEntity> chest =
std::dynamic_pointer_cast<ChestTileEntity>(
level->getTileEntity(x, y, z));
if (chest->openCount < 1) {
return true;
}
} else if (tile == Tile::furnace_lit_Id) {
return true;
} else if (tile == Tile::bed_Id && !BedTile::isHeadPiece(data)) {
return true;
}
return false;
}