the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 268 lines 7.2 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.entity.ai.attributes.h" 3#include "net.minecraft.world.entity.ai.control.h" 4#include "net.minecraft.world.entity.ai.goal.h" 5#include "net.minecraft.world.entity.ai.goal.target.h" 6#include "net.minecraft.world.entity.ai.navigation.h" 7#include "net.minecraft.world.entity.ai.village.h" 8#include "net.minecraft.world.entity.animal.h" 9#include "net.minecraft.world.entity.player.h" 10#include "net.minecraft.world.entity.monster.h" 11#include "net.minecraft.world.entity.h" 12#include "net.minecraft.world.damagesource.h" 13#include "net.minecraft.world.item.h" 14#include "net.minecraft.world.level.h" 15#include "net.minecraft.world.level.tile.h" 16#include "net.minecraft.world.phys.h" 17#include "..\Minecraft.Client\Textures.h" 18#include "SynchedEntityData.h" 19#include "VillagerGolem.h" 20#include "ParticleTypes.h" 21 22VillagerGolem::VillagerGolem(Level *level) : Golem(level) 23{ 24 // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that 25 // the derived version of the function is called 26 this->defineSynchedData(); 27 registerAttributes(); 28 setHealth(getMaxHealth()); 29 30 villageUpdateInterval = 0; 31 village = weak_ptr<Village>(); 32 attackAnimationTick = 0; 33 offerFlowerTick = 0; 34 35 setSize(1.4f, 2.9f); 36 37 getNavigation()->setAvoidWater(true); 38 39 goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0, true)); 40 goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9, 32)); 41 goalSelector.addGoal(3, new MoveThroughVillageGoal(this, 0.6, true)); 42 goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 1.0)); 43 goalSelector.addGoal(5, new OfferFlowerGoal(this)); 44 goalSelector.addGoal(6, new RandomStrollGoal(this, 0.6)); 45 goalSelector.addGoal(7, new LookAtPlayerGoal(this, typeid(Player), 6)); 46 goalSelector.addGoal(8, new RandomLookAroundGoal(this)); 47 48 targetSelector.addGoal(1, new DefendVillageTargetGoal(this)); 49 targetSelector.addGoal(2, new HurtByTargetGoal(this, false)); 50 targetSelector.addGoal(3, new NearestAttackableTargetGoal(this, typeid(Mob), 0, false, true, Enemy::ENEMY_SELECTOR)); 51} 52 53void VillagerGolem::defineSynchedData() 54{ 55 Golem::defineSynchedData(); 56 entityData->define(DATA_FLAGS_ID, (byte) 0); 57} 58 59bool VillagerGolem::useNewAi() 60{ 61 return true; 62} 63 64void VillagerGolem::serverAiMobStep() 65{ 66 if (--villageUpdateInterval <= 0) 67 { 68 villageUpdateInterval = 70 + random->nextInt(50); 69 shared_ptr<Village> _village = level->villages->getClosestVillage(Mth::floor(x), Mth::floor(y), Mth::floor(z), Villages::MaxDoorDist); 70 village = _village; 71 if (_village == NULL) clearRestriction(); 72 else 73 { 74 Pos *center = _village->getCenter(); 75 restrictTo(center->x, center->y, center->z, (int)((float)_village->getRadius()) * 0.6f); 76 } 77 } 78 79 Golem::serverAiMobStep(); 80} 81 82void VillagerGolem::registerAttributes() 83{ 84 Golem::registerAttributes(); 85 86 getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(100); 87 getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.25f); 88} 89 90int VillagerGolem::decreaseAirSupply(int currentSupply) 91{ 92 // infinite air supply 93 return currentSupply; 94} 95 96void VillagerGolem::doPush(shared_ptr<Entity> e) 97{ 98 if ( e->instanceof(eTYPE_ENEMY) ) 99 { 100 if (getRandom()->nextInt(20) == 0) 101 { 102 setTarget(dynamic_pointer_cast<LivingEntity>(e)); 103 } 104 } 105 Golem::doPush(e); 106} 107 108void VillagerGolem::aiStep() 109{ 110 Golem::aiStep(); 111 112 if (attackAnimationTick > 0) --attackAnimationTick; 113 if (offerFlowerTick > 0) --offerFlowerTick; 114 115 if (xd * xd + zd * zd > MoveControl::MIN_SPEED_SQR && random->nextInt(5) == 0) 116 { 117 int xt = Mth::floor(x); 118 int yt = Mth::floor(y - 0.2f - heightOffset); 119 int zt = Mth::floor(z); 120 int t = level->getTile(xt, yt, zt); 121 int d = level->getData(xt, yt, zt); 122 if (t > 0) 123 { 124 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, 125 (random->nextFloat() - 0.5) * 4); 126 } 127 } 128} 129 130bool VillagerGolem::canAttackType(eINSTANCEOF targetType) 131{ 132 if (isPlayerCreated() && (eTYPE_PLAYER & targetType) == eTYPE_PLAYER ) return false; 133 return Golem::canAttackType(targetType); 134} 135 136void VillagerGolem::addAdditonalSaveData(CompoundTag *tag) 137{ 138 Golem::addAdditonalSaveData(tag); 139 tag->putBoolean(L"PlayerCreated", isPlayerCreated()); 140} 141 142void VillagerGolem::readAdditionalSaveData(CompoundTag *tag) 143{ 144 Golem::readAdditionalSaveData(tag); 145 setPlayerCreated(tag->getBoolean(L"PlayerCreated")); 146} 147 148bool VillagerGolem::doHurtTarget(shared_ptr<Entity> target) 149{ 150 attackAnimationTick = 10; 151 level->broadcastEntityEvent(shared_from_this(), EntityEvent::START_ATTACKING); 152 bool hurt = target->hurt(DamageSource::mobAttack(dynamic_pointer_cast<Mob>(shared_from_this())), 7 + random->nextInt(15)); 153 if (hurt) target->yd += 0.4f; 154 playSound(eSoundType_MOB_IRONGOLEM_THROW, 1, 1); 155 return hurt; 156} 157 158void VillagerGolem::handleEntityEvent(byte id) 159{ 160 if (id == EntityEvent::START_ATTACKING) 161 { 162 attackAnimationTick = 10; 163 playSound(eSoundType_MOB_IRONGOLEM_THROW, 1, 1); 164 } 165 else if (id == EntityEvent::OFFER_FLOWER) 166 { 167 offerFlowerTick = OfferFlowerGoal::OFFER_TICKS; 168 } 169 else Golem::handleEntityEvent(id); 170} 171 172shared_ptr<Village> VillagerGolem::getVillage() 173{ 174 return village.lock(); 175} 176 177int VillagerGolem::getAttackAnimationTick() 178{ 179 return attackAnimationTick; 180} 181 182void VillagerGolem::offerFlower(bool offer) 183{ 184 offerFlowerTick = offer ? OfferFlowerGoal::OFFER_TICKS : 0; 185 level->broadcastEntityEvent(shared_from_this(), EntityEvent::OFFER_FLOWER); 186} 187 188int VillagerGolem::getAmbientSound() 189{ 190 return -1; 191} 192 193int VillagerGolem::getHurtSound() 194{ 195 return eSoundType_MOB_IRONGOLEM_HIT; 196} 197 198int VillagerGolem::getDeathSound() 199{ 200 return eSoundType_MOB_IRONGOLEM_DEATH; 201} 202 203void VillagerGolem::playStepSound(int xt, int yt, int zt, int t) 204{ 205 playSound(eSoundType_MOB_IRONGOLEM_WALK, 1, 1); 206} 207 208void VillagerGolem::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) 209{ 210 int roses = random->nextInt(3); 211 for (int i = 0; i < roses; i++) 212 { 213 spawnAtLocation(Tile::rose_Id, 1); 214 } 215 int iron = 3 + random->nextInt(3); 216 for (int i = 0; i < iron; i++) 217 { 218 spawnAtLocation(Item::ironIngot_Id, 1); 219 } 220} 221 222int VillagerGolem::getOfferFlowerTick() 223{ 224 return offerFlowerTick; 225} 226 227bool VillagerGolem::isPlayerCreated() 228{ 229 return (entityData->getByte(DATA_FLAGS_ID) & 0x01) != 0; 230} 231 232void VillagerGolem::setPlayerCreated(bool value) 233{ 234 byte current = entityData->getByte(DATA_FLAGS_ID); 235 if (value) 236 { 237 entityData->set(DATA_FLAGS_ID, (byte) (current | 0x01)); 238 } 239 else 240 { 241 entityData->set(DATA_FLAGS_ID, (byte) (current & ~0x01)); 242 } 243} 244 245void VillagerGolem::die(DamageSource *source) 246{ 247 if (!isPlayerCreated() && lastHurtByPlayer != NULL && village.lock() != NULL) 248 { 249 village.lock()->modifyStanding(lastHurtByPlayer->getName(), -5); 250 } 251 Golem::die(source); 252} 253 254bool VillagerGolem::hurt(DamageSource *source, float dmg) 255{ 256 // 4J: Protect owned golem from untrusted players 257 if (isPlayerCreated()) 258 { 259 shared_ptr<Entity> entity = source->getDirectEntity(); 260 if (entity != NULL && entity->instanceof(eTYPE_PLAYER)) 261 { 262 shared_ptr<Player> player = dynamic_pointer_cast<Player>(entity); 263 if (!player->isAllowedToAttackPlayers()) return false; 264 } 265 } 266 267 return Golem::hurt(source, dmg); 268}