diff --git a/Minecraft.World/Zombice.cpp b/Minecraft.World/Zombice.cpp new file mode 100644 index 00000000..3134fbc3 --- /dev/null +++ b/Minecraft.World/Zombice.cpp @@ -0,0 +1,185 @@ +#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 "Zombice.h" +#include "SharedConstants.h" +#include "..\Minecraft.Client\Textures.h" +#include "SoundTypes.h" + +void Zombice::_init() +{ + registerAttributes(); +} + +Zombice::Zombice(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 Zombice::registerAttributes() +{ + Zombie::registerAttributes(); + + getAttribute(SPAWN_REINFORCEMENTS_CHANCE)->setBaseValue(0); + getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.5f); + getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(3); +} + +bool Zombice::useNewAi() +{ + return false; +} + +void Zombice::tick() +{ + Zombie::tick(); +} + +bool Zombice::canSpawn() +{ + return level->difficulty > Difficulty::PEACEFUL && level->isUnobstructed(bb) && level->getCubes(shared_from_this(), bb)->empty() && !level->containsAnyLiquid(bb); +} + +shared_ptr Zombice::findAttackTarget() +{ +#ifndef _FINAL_BUILD +#ifdef _DEBUG_MENUS_ENABLED + if(app.GetMobsDontAttackEnabled()) + { + return shared_ptr(); + } +#endif +#endif + + return Zombie::findAttackTarget(); +} + +bool Zombice::hurt(DamageSource *source, float dmg) +{ + return Zombie::hurt(source, dmg); +} + +int Zombice::getAmbientSound() +{ + return eSoundType_MOB_ZOMBIE_AMBIENT; +} + +int Zombice::getHurtSound() +{ + return eSoundType_MOB_ZOMBIE_HURT; +} + +int Zombice::getDeathSound() +{ + return eSoundType_MOB_ZOMBIE_DEATH; +} + +void Zombice::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 Zombice::mobInteract(shared_ptr player) +{ + return false; +} + +void Zombice::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 Zombice::getDeathLoot() +{ + return Item::rotten_flesh_Id; +} + +MobGroupData *Zombice::finalizeMobSpawn(MobGroupData *groupData, int extraData /*= 0*/) // 4J Added extraData param +{ + Zombie::finalizeMobSpawn(groupData); + setVillager(false); + return groupData; +} + +bool Zombice::doHurtTarget(shared_ptr target) +{ + if (Zombie::doHurtTarget(target)) + { + if ( target->instanceof(eTYPE_LIVINGENTITY) ) + { + dynamic_pointer_cast(target)->addEffect(new MobEffectInstance(MobEffect::movementSlowdown->id, 300, 0)); + } + + return true; + } + return false; +} + +void Zombice::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::sword_stone)); + } + } +} + +void Zombice::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(); +} diff --git a/Minecraft.World/Zombice.h b/Minecraft.World/Zombice.h new file mode 100644 index 00000000..d6638bc2 --- /dev/null +++ b/Minecraft.World/Zombice.h @@ -0,0 +1,56 @@ +#pragma once +using namespace std; + +#include "Zombie.h" + +class DamageSource; + +class Zombice : public Zombie +{ +public: + eINSTANCEOF GetType() { return eTYPE_ZOMBICE; } + static Entity *create(Level *level) { return new Zombice(level); } + +private: + void _init(); + +public: + Zombice(Level *level); + +protected: + virtual void registerAttributes(); + virtual bool useNewAi(); + +public: + virtual void tick(); + virtual bool canSpawn(); + +protected: + virtual shared_ptr findAttackTarget(); + +public: + virtual bool hurt(DamageSource *source, float dmg); + virtual void aiStep(); + +private: + void alert(shared_ptr target); + +protected: + virtual int getAmbientSound(); + virtual int getHurtSound(); + virtual int getDeathSound(); + virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel); + virtual void populateDefaultEquipmentSlots(); + +public: + virtual bool mobInteract(shared_ptr player); + +protected: + virtual void dropRareDeathLoot(int rareLootLevel); + virtual int getDeathLoot(); + + +public: + virtual bool doHurtTarget(shared_ptr target); + virtual MobGroupData *finalizeMobSpawn(MobGroupData *groupData, int extraData = 0); +};