#include "stdafx.h" #include "com.mojang.nbt.h" #include "net.minecraft.world.h" #include "net.minecraft.world.level.h" #include "net.minecraft.world.phys.h" #include "net.minecraft.world.entity.ai.attributes.h" #include "net.minecraft.world.entity.ai.goal.target.h" #include "net.minecraft.world.entity.player.h" #include "net.minecraft.world.entity.monster.h" #include "net.minecraft.world.entity.npc.h" #include "net.minecraft.world.item.h" #include "net.minecraft.world.effect.h" #include "net.minecraft.world.item.enchantment.h" #include "net.minecraft.world.entity.item.h" #include "net.minecraft.world.damagesource.h" #include "Husk.h" #include "SharedConstants.h" #include "..\Minecraft.Client\Textures.h" #include "SoundTypes.h" void Husk::_init() { registerAttributes(); } Husk::Husk(Level *level) : Zombie( level ) { _init(); targetSelector.addGoal(1, new HurtByTargetGoal(this, true)); targetSelector.addGoal(2, new NearestAttackableTargetGoal(this, typeid(Player), 0, true)); targetSelector.addGoal(2, new NearestAttackableTargetGoal(this, typeid(Villager), 0, false)); fireImmune = false; } void Husk::registerAttributes() { Zombie::registerAttributes(); getAttribute(SPAWN_REINFORCEMENTS_CHANCE)->setBaseValue(0); getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.5f); getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(3); } bool Husk::useNewAi() { return false; } void Husk::tick() { Zombie::tick(); } bool Husk::canSpawn() { return level->difficulty > Difficulty::PEACEFUL && level->isUnobstructed(bb) && level->getCubes(shared_from_this(), bb)->empty() && !level->containsAnyLiquid(bb); } shared_ptr Husk::findAttackTarget() { #ifndef _FINAL_BUILD #ifdef _DEBUG_MENUS_ENABLED if(app.GetMobsDontAttackEnabled()) { return shared_ptr(); } #endif #endif return Zombie::findAttackTarget(); } bool Husk::hurt(DamageSource *source, float dmg) { return Zombie::hurt(source, dmg); } int Husk::getAmbientSound() { return eSoundType_MOB_ZOMBIE_AMBIENT; } int Husk::getHurtSound() { return eSoundType_MOB_ZOMBIE_HURT; } int Husk::getDeathSound() { return eSoundType_MOB_ZOMBIE_DEATH; } void Husk::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) { int count = random->nextInt(2 + playerBonusLevel); for (int i = 0; i < count; i++) { spawnAtLocation(Item::rotten_flesh_Id, 2); } } bool Husk::mobInteract(shared_ptr player) { return false; } void Husk::dropRareDeathLoot(int rareLootLevel) { switch (random->nextInt(3)) { case 0: spawnAtLocation(Item::ironIngot_Id, 1); break; case 1: spawnAtLocation(Item::carrots_Id, 1); break; case 2: spawnAtLocation(Item::potato_Id, 1); break; } } int Husk::getDeathLoot() { return Item::rotten_flesh_Id; } MobGroupData *Husk::finalizeMobSpawn(MobGroupData *groupData, int extraData /*= 0*/) // 4J Added extraData param { Zombie::finalizeMobSpawn(groupData); setVillager(false); return groupData; } bool Husk::doHurtTarget(shared_ptr target) { if (Zombie::doHurtTarget(target)) { if ( target->instanceof(eTYPE_LIVINGENTITY) ) { dynamic_pointer_cast(target)->addEffect(new MobEffectInstance(MobEffect::hunger->id, 600, 0)); } return true; } return false; } void Husk::populateDefaultEquipmentSlots() { Monster::populateDefaultEquipmentSlots(); if (random->nextFloat() < (level->difficulty == Difficulty::HARD ? 0.05f : 0.01f)) { int rand = random->nextInt(3); if (rand == 0) { setEquippedSlot(SLOT_WEAPON, std::make_shared(Item::sword_iron)); } else { setEquippedSlot(SLOT_WEAPON, std::make_shared(Item::shovel_iron)); } } } void Husk::aiStep() { if (level->isDay() && !level->isClientSide) { float br = getBrightness(1); if (br > 0.5f && random->nextFloat() * 30 < (br - 0.4f) * 2 && level->canSeeSky(Mth::floor(x), static_cast(floor(y + 0.5)), Mth::floor(z))) { bool burn = false; if (burn) { setOnFire(8); } } } Monster::aiStep(); } int Husk::decreaseAirSupply(int currentSupply) { // infinite air supply return currentSupply; }