4jcraft/Minecraft.World/Entities/Mobs/Creeper.cpp
2026-03-13 17:06:56 -05:00

143 lines
4.8 KiB
C++

#include "../../Platform/stdafx.h"
#include "../../Headers/net.minecraft.world.level.h"
#include "../../Headers/net.minecraft.world.level.tile.h"
#include "../../Headers/net.minecraft.world.item.h"
#include "../../Headers/net.minecraft.world.entity.h"
#include "../../Headers/net.minecraft.world.entity.ai.goal.h"
#include "../../Headers/net.minecraft.world.entity.ai.goal.target.h"
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
#include "../../Headers/net.minecraft.world.entity.animal.h"
#include "../../Headers/net.minecraft.world.entity.player.h"
#include "../../Headers/net.minecraft.world.damagesource.h"
#include "../../Stats/GeneralStat.h"
#include "Skeleton.h"
#include "Creeper.h"
#include "Arrow.h"
#include "../../../Minecraft.Client/Textures/Textures.h"
#include "../../Util/SoundTypes.h"
void Creeper::_init() {
swell = 0;
oldSwell = 0;
}
Creeper::Creeper(Level* level) : Monster(level) {
// 4J Stu - This function call had to be moved here from the Entity ctor to
// ensure that the derived version of the function is called
this->defineSynchedData();
// 4J Stu - This function call had to be moved here from the Entity ctor to
// ensure that the derived version of the function is called
health = getMaxHealth();
_init();
this->textureIdx = TN_MOB_CREEPER; // 4J was L"/mob/creeper.png";
goalSelector.addGoal(1, new FloatGoal(this));
goalSelector.addGoal(2, new SwellGoal(this));
goalSelector.addGoal(
3, new AvoidPlayerGoal(this, typeid(Ozelot), 6, 0.25f, 0.30f));
goalSelector.addGoal(4, new MeleeAttackGoal(this, 0.25f, false));
goalSelector.addGoal(5, new RandomStrollGoal(this, 0.20f));
goalSelector.addGoal(6, new LookAtPlayerGoal(this, typeid(Player), 8));
goalSelector.addGoal(6, new RandomLookAroundGoal(this));
targetSelector.addGoal(
1, new NearestAttackableTargetGoal(this, typeid(Player), 16, 0, true));
targetSelector.addGoal(2, new HurtByTargetGoal(this, false));
}
bool Creeper::useNewAi() { return true; }
int Creeper::getMaxHealth() { return 20; }
void Creeper::defineSynchedData() {
Monster::defineSynchedData();
entityData->define(DATA_SWELL_DIR, (uint8_t)-1);
entityData->define(DATA_IS_POWERED, (uint8_t)0);
}
void Creeper::addAdditonalSaveData(CompoundTag* entityTag) {
Monster::addAdditonalSaveData(entityTag);
if (entityData->getByte(DATA_IS_POWERED) == 1)
entityTag->putBoolean(L"powered", true);
}
void Creeper::readAdditionalSaveData(CompoundTag* tag) {
Monster::readAdditionalSaveData(tag);
entityData->set(DATA_IS_POWERED,
(uint8_t)(tag->getBoolean(L"powered") ? 1 : 0));
}
void Creeper::tick() {
oldSwell = swell;
if (isAlive()) {
int swellDir = getSwellDir();
if (swellDir > 0 && swell == 0) {
level->playSound(shared_from_this(), eSoundType_RANDOM_FUSE, 1,
0.5f);
}
swell += swellDir;
if (swell < 0) swell = 0;
if (swell >= MAX_SWELL) {
swell = MAX_SWELL;
if (!level->isClientSide) {
bool destroyBlocks =
true; // level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
if (isPowered())
level->explode(shared_from_this(), x, y, z, 6,
destroyBlocks);
else
level->explode(shared_from_this(), x, y, z, 3,
destroyBlocks);
remove();
}
}
}
Monster::tick();
}
int Creeper::getHurtSound() { return eSoundType_MOB_CREEPER_HURT; }
int Creeper::getDeathSound() { return eSoundType_MOB_CREEPER_DEATH; }
void Creeper::die(DamageSource* source) {
Monster::die(source);
if (std::dynamic_pointer_cast<Skeleton>(source->getEntity()) != NULL) {
spawnAtLocation(Item::record_01_Id + random->nextInt(12), 1);
}
std::shared_ptr<Player> player =
std::dynamic_pointer_cast<Player>(source->getEntity());
if ((std::dynamic_pointer_cast<Arrow>(source->getDirectEntity()) != NULL) &&
(player != NULL)) {
player->awardStat(GenericStats::archer(), GenericStats::param_archer());
}
}
bool Creeper::doHurtTarget(std::shared_ptr<Entity> target) { return true; }
bool Creeper::isPowered() { return entityData->getByte(DATA_IS_POWERED) == 1; }
float Creeper::getSwelling(float a) {
return (oldSwell + (swell - oldSwell) * a) / (MAX_SWELL - 2);
}
int Creeper::getDeathLoot() { return Item::sulphur->id; }
int Creeper::getSwellDir() {
return (int)(char)entityData->getByte(DATA_SWELL_DIR);
}
void Creeper::setSwellDir(int dir) {
entityData->set(DATA_SWELL_DIR, (uint8_t)dir);
}
void Creeper::thunderHit(const LightningBolt* lightningBolt) {
Monster::thunderHit(lightningBolt);
entityData->set(DATA_IS_POWERED, (uint8_t)1);
}