aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/VillagerGolem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.World/VillagerGolem.cpp')
-rw-r--r--Minecraft.World/VillagerGolem.cpp240
1 files changed, 240 insertions, 0 deletions
diff --git a/Minecraft.World/VillagerGolem.cpp b/Minecraft.World/VillagerGolem.cpp
new file mode 100644
index 00000000..a0f05472
--- /dev/null
+++ b/Minecraft.World/VillagerGolem.cpp
@@ -0,0 +1,240 @@
+#include "stdafx.h"
+#include "net.minecraft.world.entity.ai.control.h"
+#include "net.minecraft.world.entity.ai.goal.h"
+#include "net.minecraft.world.entity.ai.goal.target.h"
+#include "net.minecraft.world.entity.ai.navigation.h"
+#include "net.minecraft.world.entity.ai.village.h"
+#include "net.minecraft.world.entity.animal.h"
+#include "net.minecraft.world.entity.player.h"
+#include "net.minecraft.world.entity.monster.h"
+#include "net.minecraft.world.entity.h"
+#include "net.minecraft.world.damagesource.h"
+#include "net.minecraft.world.item.h"
+#include "net.minecraft.world.level.h"
+#include "net.minecraft.world.level.tile.h"
+#include "net.minecraft.world.phys.h"
+#include "..\Minecraft.Client\Textures.h"
+#include "SynchedEntityData.h"
+#include "VillagerGolem.h"
+#include "ParticleTypes.h"
+
+VillagerGolem::VillagerGolem(Level *level) : Golem(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();
+
+ villageUpdateInterval = 0;
+ village = weak_ptr<Village>();
+ attackAnimationTick = 0;
+ offerFlowerTick = 0;
+
+ this->textureIdx = TN_MOB_VILLAGER_GOLEM; // "/mob/villager_golem.png";
+ this->setSize(1.4f, 2.9f);
+
+ getNavigation()->setAvoidWater(true);
+
+ // 4J-JEV: These speed values are as they appear before 1.6.4 (1.5),
+ // as the movement speed system changes then. (Mob attributes added)
+ goalSelector.addGoal(1, new MeleeAttackGoal(this, 0.25f, true));
+ goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.22f, 32));
+ goalSelector.addGoal(3, new MoveThroughVillageGoal(this, 0.16f, true));
+ goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 0.16f));
+ goalSelector.addGoal(5, new OfferFlowerGoal(this));
+ goalSelector.addGoal(6, new RandomStrollGoal(this, 0.16f));
+ goalSelector.addGoal(7, new LookAtPlayerGoal(this, typeid(Player), 6));
+ goalSelector.addGoal(8, new RandomLookAroundGoal(this));
+
+ targetSelector.addGoal(1, new DefendVillageTargetGoal(this));
+ targetSelector.addGoal(2, new HurtByTargetGoal(this, false));
+ targetSelector.addGoal(3, new NearestAttackableTargetGoal(this, typeid(Monster), 16, 0, false, true));
+}
+
+void VillagerGolem::defineSynchedData()
+{
+ Golem::defineSynchedData();
+ entityData->define(DATA_FLAGS_ID, (byte) 0);
+}
+
+bool VillagerGolem::useNewAi()
+{
+ return true;
+}
+
+void VillagerGolem::serverAiMobStep()
+{
+ if (--villageUpdateInterval <= 0)
+ {
+ villageUpdateInterval = 70 + random->nextInt(50);
+ shared_ptr<Village> _village = level->villages->getClosestVillage(Mth::floor(x), Mth::floor(y), Mth::floor(z), Villages::MaxDoorDist);
+ village = _village;
+ if (_village == NULL) clearRestriction();
+ else
+ {
+ Pos *center = _village->getCenter();
+ restrictTo(center->x, center->y, center->z, (int)((float)_village->getRadius()) * 0.6f);
+ }
+ }
+
+ Golem::serverAiMobStep();
+}
+
+int VillagerGolem::getMaxHealth()
+{
+ return 100;
+}
+
+int VillagerGolem::decreaseAirSupply(int currentSupply)
+{
+ // infinite air supply
+ return currentSupply;
+}
+
+void VillagerGolem::aiStep()
+{
+ Golem::aiStep();
+
+ if (attackAnimationTick > 0) --attackAnimationTick;
+ if (offerFlowerTick > 0) --offerFlowerTick;
+
+ if (xd * xd + zd * zd > MoveControl::MIN_SPEED_SQR && random->nextInt(5) == 0)
+ {
+ int xt = Mth::floor(x);
+ int yt = Mth::floor(y - 0.2f - this->heightOffset);
+ int zt = Mth::floor(z);
+ int t = level->getTile(xt, yt, zt);
+ int d = level->getData(xt, yt, zt);
+ if (t > 0)
+ {
+ level->addParticle(PARTICLE_TILECRACK(t,d), x + (random->nextFloat() - 0.5) * bbWidth, bb->y0 + 0.1, z + (random->nextFloat() - 0.5) * bbWidth, 4 * (random->nextFloat() - 0.5), .5,
+ (random->nextFloat() - 0.5) * 4);
+ }
+ }
+}
+
+bool VillagerGolem::canAttackType(eINSTANCEOF targetType)
+{
+ if (isPlayerCreated() && (eTYPE_PLAYER & targetType) == eTYPE_PLAYER ) return false;
+ return Golem::canAttackType(targetType);
+}
+
+void VillagerGolem::addAdditonalSaveData(CompoundTag *tag)
+{
+ Golem::addAdditonalSaveData(tag);
+ tag->putBoolean(L"PlayerCreated", isPlayerCreated());
+}
+
+void VillagerGolem::readAdditionalSaveData(CompoundTag *tag)
+{
+ Golem::readAdditionalSaveData(tag);
+ setPlayerCreated(tag->getBoolean(L"PlayerCreated"));
+}
+
+bool VillagerGolem::doHurtTarget(shared_ptr<Entity> target)
+{
+ attackAnimationTick = 10;
+ level->broadcastEntityEvent(shared_from_this(), EntityEvent::START_ATTACKING);
+ bool hurt = target->hurt(DamageSource::mobAttack(dynamic_pointer_cast<Mob>(shared_from_this())), 7 + random->nextInt(15));
+ if (hurt) target->yd += 0.4f;
+ level->playSound(shared_from_this(), eSoundType_MOB_IRONGOLEM_THROW, 1, 1);
+ return hurt;
+}
+
+void VillagerGolem::handleEntityEvent(byte id)
+{
+ if (id == EntityEvent::START_ATTACKING)
+ {
+ attackAnimationTick = 10;
+ level->playSound(shared_from_this(), eSoundType_MOB_IRONGOLEM_THROW, 1, 1);
+ }
+ else if (id == EntityEvent::OFFER_FLOWER)
+ {
+ offerFlowerTick = OfferFlowerGoal::OFFER_TICKS;
+ }
+ else Golem::handleEntityEvent(id);
+}
+
+shared_ptr<Village> VillagerGolem::getVillage()
+{
+ return village.lock();
+}
+
+int VillagerGolem::getAttackAnimationTick()
+{
+ return attackAnimationTick;
+}
+
+void VillagerGolem::offerFlower(bool offer)
+{
+ offerFlowerTick = offer ? OfferFlowerGoal::OFFER_TICKS : 0;
+ level->broadcastEntityEvent(shared_from_this(), EntityEvent::OFFER_FLOWER);
+}
+
+int VillagerGolem::getAmbientSound()
+{
+ return -1;
+}
+
+int VillagerGolem::getHurtSound()
+{
+ return eSoundType_MOB_IRONGOLEM_HIT;
+}
+
+int VillagerGolem::getDeathSound()
+{
+ return eSoundType_MOB_IRONGOLEM_DEATH;
+}
+
+void VillagerGolem::playStepSound(int xt, int yt, int zt, int t)
+{
+ level->playSound(shared_from_this(), eSoundType_MOB_IRONGOLEM_WALK, 1, 1);
+}
+
+void VillagerGolem::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel)
+{
+ int roses = random->nextInt(3);
+ for (int i = 0; i < roses; i++)
+ {
+ spawnAtLocation(Tile::rose_Id, 1);
+ }
+ int iron = 3 + random->nextInt(3);
+ for (int i = 0; i < iron; i++)
+ {
+ spawnAtLocation(Item::ironIngot_Id, 1);
+ }
+}
+
+int VillagerGolem::getOfferFlowerTick()
+{
+ return offerFlowerTick;
+}
+
+bool VillagerGolem::isPlayerCreated()
+{
+ return (entityData->getByte(DATA_FLAGS_ID) & 0x01) != 0;
+}
+
+void VillagerGolem::setPlayerCreated(bool value)
+{
+ byte current = entityData->getByte(DATA_FLAGS_ID);
+ if (value)
+ {
+ entityData->set(DATA_FLAGS_ID, (byte) (current | 0x01));
+ }
+ else
+ {
+ entityData->set(DATA_FLAGS_ID, (byte) (current & ~0x01));
+ }
+}
+
+void VillagerGolem::die(DamageSource *source)
+{
+ if (!isPlayerCreated() && lastHurtByPlayer != NULL && village.lock() != NULL)
+ {
+ village.lock()->modifyStanding(lastHurtByPlayer->getName(), -5);
+ }
+ Golem::die(source);
+} \ No newline at end of file