the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 359 lines 9.3 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.h" 3#include "net.minecraft.world.level.h" 4#include "net.minecraft.world.level.dimension.h" 5#include "net.minecraft.world.level.tile.entity.h" 6#include "net.minecraft.world.item.h" 7#include "net.minecraft.world.item.enchantment.h" 8#include "net.minecraft.world.effect.h" 9#include "net.minecraft.world.entity.h" 10#include "net.minecraft.world.entity.ai.attributes.h" 11#include "net.minecraft.world.entity.ai.goal.h" 12#include "net.minecraft.world.entity.ai.goal.target.h" 13#include "net.minecraft.world.entity.ai.navigation.h" 14#include "net.minecraft.world.entity.projectile.h" 15#include "net.minecraft.world.entity.item.h" 16#include "net.minecraft.world.entity.player.h" 17#include "net.minecraft.world.entity.monster.h" 18#include "net.minecraft.stats.h" 19#include "net.minecraft.world.damagesource.h" 20#include "SharedConstants.h" 21#include "Skeleton.h" 22#include "..\Minecraft.Client\Textures.h" 23#include "SoundTypes.h" 24 25Skeleton::Skeleton(Level *level) : Monster( level ) 26{ 27 // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that 28 // the derived version of the function is called 29 this->defineSynchedData(); 30 registerAttributes(); 31 setHealth(getMaxHealth()); 32 33 bowGoal = new RangedAttackGoal(this, this, 1.0, SharedConstants::TICKS_PER_SECOND * 1, SharedConstants::TICKS_PER_SECOND * 3, 15); 34 meleeGoal = new MeleeAttackGoal(this, eTYPE_PLAYER, 1.2, false); 35 36 goalSelector.addGoal(1, new FloatGoal(this)); 37 goalSelector.addGoal(2, new RestrictSunGoal(this)); 38 goalSelector.addGoal(3, new FleeSunGoal(this, 1.0)); 39 goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0)); 40 goalSelector.addGoal(6, new LookAtPlayerGoal(this, typeid(Player), 8)); 41 goalSelector.addGoal(6, new RandomLookAroundGoal(this)); 42 43 targetSelector.addGoal(1, new HurtByTargetGoal(this, false)); 44 targetSelector.addGoal(2, new NearestAttackableTargetGoal(this, typeid(Player), 0, true)); 45 46 if (level != NULL && !level->isClientSide) reassessWeaponGoal(); 47} 48 49Skeleton::~Skeleton() 50{ 51 delete bowGoal; 52 delete meleeGoal; 53} 54 55void Skeleton::registerAttributes() 56{ 57 Monster::registerAttributes(); 58 59 getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.25f); 60} 61 62void Skeleton::defineSynchedData() 63{ 64 Monster::defineSynchedData(); 65 66 entityData->define(DATA_TYPE_ID, (byte) TYPE_DEFAULT); 67} 68 69bool Skeleton::useNewAi() 70{ 71 return true; 72} 73 74int Skeleton::getAmbientSound() 75{ 76 return eSoundType_MOB_SKELETON_AMBIENT; 77} 78 79int Skeleton::getHurtSound() 80{ 81 return eSoundType_MOB_SKELETON_HURT; 82} 83 84int Skeleton::getDeathSound() 85{ 86 return eSoundType_MOB_SKELETON_DEATH; 87} 88 89void Skeleton::playStepSound(int xt, int yt, int zt, int t) 90{ 91 playSound(eSoundType_MOB_SKELETON_STEP, 0.15f, 1); 92} 93 94bool Skeleton::doHurtTarget(shared_ptr<Entity> target) 95{ 96 if (Monster::doHurtTarget(target)) 97 { 98 if ( (getSkeletonType() == TYPE_WITHER) && target->instanceof(eTYPE_LIVINGENTITY) ) 99 { 100 dynamic_pointer_cast<LivingEntity>(target)->addEffect(new MobEffectInstance(MobEffect::wither->id, SharedConstants::TICKS_PER_SECOND * 10)); 101 } 102 return true; 103 } 104 return false; 105} 106 107MobType Skeleton::getMobType() 108{ 109 return UNDEAD; 110} 111 112void Skeleton::aiStep() 113{ 114 if (level->isDay() && !level->isClientSide) 115 { 116 float br = getBrightness(1); 117 if (br > 0.5f && random->nextFloat() * 30 < (br - 0.4f) * 2 && level->canSeeSky(Mth::floor(x), (int)floor( y + 0.5 ), Mth::floor(z))) 118 { 119 bool burn = true; 120 121 shared_ptr<ItemInstance> helmet = getCarried(SLOT_HELM); 122 if (helmet != NULL) 123 { 124 if (helmet->isDamageableItem()) 125 { 126 helmet->setAuxValue(helmet->getDamageValue() + random->nextInt(2)); 127 if (helmet->getDamageValue() >= helmet->getMaxDamage()) 128 { 129 breakItem(helmet); 130 setEquippedSlot(SLOT_HELM, nullptr); 131 } 132 } 133 134 burn = false; 135 } 136 137 if (burn) 138 { 139 setOnFire(8); 140 } 141 } 142 } 143 if (level->isClientSide) 144 { 145 if (getSkeletonType() == TYPE_WITHER) 146 { 147 setSize(0.6f * 1.2f, 1.8f * 1.3f); 148 } 149 } 150 151 Monster::aiStep(); 152} 153 154void Skeleton::rideTick() 155{ 156 Monster::rideTick(); 157 158 if ( riding != NULL && riding->instanceof(eTYPE_PATHFINDER_MOB) ) 159 { 160 yBodyRot = dynamic_pointer_cast<PathfinderMob>(riding)->yBodyRot; 161 } 162 163} 164 165void Skeleton::die(DamageSource *source) 166{ 167 Monster::die(source); 168 169 if ( source->getDirectEntity() != NULL && source->getDirectEntity()->instanceof(eTYPE_ARROW) && source->getEntity() != NULL && source->getEntity()->instanceof(eTYPE_PLAYER) ) 170 { 171 shared_ptr<Player> player = dynamic_pointer_cast<Player>( source->getEntity() ); 172 173 double xd = player->x - x; 174 double zd = player->z - z; 175 if (xd * xd + zd * zd >= 50 * 50) 176 { 177 player->awardStat(GenericStats::snipeSkeleton(), GenericStats::param_snipeSkeleton()); 178 } 179 } 180} 181 182int Skeleton::getDeathLoot() 183{ 184 return Item::arrow->id; 185} 186 187void Skeleton::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) 188{ 189 if (getSkeletonType() == TYPE_WITHER) 190 { 191 // drop some arrows 192 int count = random->nextInt(3 + playerBonusLevel) - 1; 193 for (int i = 0; i < count; i++) 194 { 195 spawnAtLocation(Item::coal_Id, 1); 196 } 197 } 198 else 199 { 200 // drop some arrows 201 int count = random->nextInt(3 + playerBonusLevel); 202 for (int i = 0; i < count; i++) 203 { 204 spawnAtLocation(Item::arrow_Id, 1); 205 } 206 } 207 208 // and some bones 209 int count = random->nextInt(3 + playerBonusLevel); 210 for (int i = 0; i < count; i++) 211 { 212 spawnAtLocation(Item::bone->id, 1); 213 } 214} 215 216void Skeleton::dropRareDeathLoot(int rareLootLevel) 217{ 218 if (getSkeletonType() == TYPE_WITHER) 219 { 220 spawnAtLocation( shared_ptr<ItemInstance>( new ItemInstance(Item::skull_Id, 1, SkullTileEntity::TYPE_WITHER) ), 0); 221 } 222} 223 224void Skeleton::populateDefaultEquipmentSlots() 225{ 226 Monster::populateDefaultEquipmentSlots(); 227 228 setEquippedSlot(SLOT_WEAPON, shared_ptr<ItemInstance>( new ItemInstance(Item::bow))); 229} 230 231MobGroupData *Skeleton::finalizeMobSpawn(MobGroupData *groupData, int extraData /*= 0*/) // 4J Added extraData param 232{ 233 groupData = Monster::finalizeMobSpawn(groupData); 234 235 if ( dynamic_cast<HellDimension *>(level->dimension) != NULL && getRandom()->nextInt(5) > 0) 236 { 237 goalSelector.addGoal(4, meleeGoal, false); 238 239 setSkeletonType(TYPE_WITHER); 240 setEquippedSlot(SLOT_WEAPON, shared_ptr<ItemInstance>( new ItemInstance(Item::sword_stone))); 241 getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(4); 242 } 243 else 244 { 245 goalSelector.addGoal(4, bowGoal, false); 246 247 populateDefaultEquipmentSlots(); 248 populateDefaultEquipmentEnchantments(); 249 } 250 251 setCanPickUpLoot(random->nextFloat() < MAX_PICKUP_LOOT_CHANCE * level->getDifficulty(x, y, z)); 252 253 if (getCarried(SLOT_HELM) == NULL) 254 { 255 if (Calendar::GetMonth() + 1 == 10 && Calendar::GetDayOfMonth() == 31 && random->nextFloat() < 0.25f) 256 { 257 // Halloween! OooOOo! 25% of all skeletons/zombies can wear pumpkins on their heads. 258 setEquippedSlot(SLOT_HELM, shared_ptr<ItemInstance>( new ItemInstance(random->nextFloat() < 0.1f ? Tile::litPumpkin : Tile::pumpkin))); 259 dropChances[SLOT_HELM] = 0; 260 } 261 } 262 return groupData; 263} 264 265void Skeleton::reassessWeaponGoal() 266{ 267 goalSelector.removeGoal(meleeGoal); 268 goalSelector.removeGoal(bowGoal); 269 270 shared_ptr<ItemInstance> carried = getCarriedItem(); 271 272 if (carried != NULL && carried->id == Item::bow_Id) 273 { 274 goalSelector.addGoal(4, bowGoal, false); 275 } 276 else 277 { 278 goalSelector.addGoal(4, meleeGoal, false); 279 } 280} 281 282void Skeleton::performRangedAttack(shared_ptr<LivingEntity> target, float power) 283{ 284 shared_ptr<Arrow> arrow = shared_ptr<Arrow>( new Arrow(level, dynamic_pointer_cast<LivingEntity>(shared_from_this()), target, 1.60f, 14 - (level->difficulty * 4)) ); 285 int damageBonus = EnchantmentHelper::getEnchantmentLevel(Enchantment::arrowBonus->id, getCarriedItem()); 286 int knockbackBonus = EnchantmentHelper::getEnchantmentLevel(Enchantment::arrowKnockback->id, getCarriedItem()); 287 288 arrow->setBaseDamage(power * 2.0f + (random->nextGaussian() * 0.25f + (level->difficulty * 0.11f))); 289 290 if (damageBonus > 0) 291 { 292 arrow->setBaseDamage(arrow->getBaseDamage() + (double) damageBonus * .5 + .5); 293 } 294 if (knockbackBonus > 0) 295 { 296 arrow->setKnockback(knockbackBonus); 297 } 298 if (EnchantmentHelper::getEnchantmentLevel(Enchantment::arrowFire->id, getCarriedItem()) > 0 || getSkeletonType() == TYPE_WITHER) 299 { 300 arrow->setOnFire(100); 301 } 302 303 playSound(eSoundType_RANDOM_BOW, 1.0f, 1 / (getRandom()->nextFloat() * 0.4f + 0.8f)); 304 level->addEntity(arrow); 305} 306 307int Skeleton::getSkeletonType() 308{ 309 return (int) entityData->getByte(DATA_TYPE_ID); 310} 311 312void Skeleton::setSkeletonType(int type) 313{ 314 entityData->set(DATA_TYPE_ID, (byte) type); 315 316 fireImmune = type == TYPE_WITHER; 317 if (type == TYPE_WITHER) 318 { 319 setSize(0.6f * 1.2f, 1.8f * 1.3f); 320 } 321 else 322 { 323 setSize(0.6f, 1.8f); 324 } 325} 326 327void Skeleton::readAdditionalSaveData(CompoundTag *tag) 328{ 329 Monster::readAdditionalSaveData(tag); 330 331 if (tag->contains(L"SkeletonType")) 332 { 333 int value = tag->getByte(L"SkeletonType"); 334 setSkeletonType(value); 335 } 336 337 reassessWeaponGoal(); 338} 339 340void Skeleton::addAdditonalSaveData(CompoundTag *entityTag) 341{ 342 Monster::addAdditonalSaveData(entityTag); 343 entityTag->putByte(L"SkeletonType", (byte) getSkeletonType()); 344} 345 346void Skeleton::setEquippedSlot(int slot, shared_ptr<ItemInstance> item) 347{ 348 Monster::setEquippedSlot(slot, item); 349 350 if (!level->isClientSide && slot == SLOT_WEAPON) 351 { 352 reassessWeaponGoal(); 353 } 354} 355 356double Skeleton::getRidingHeight() 357{ 358 return Monster::getRidingHeight() - .5; 359}