the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 224 lines 6.7 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.effect.h" 3#include "net.minecraft.world.damagesource.h" 4#include "net.minecraft.world.entity.h" 5#include "net.minecraft.world.entity.ai.attributes.h" 6#include "net.minecraft.world.entity.ai.goal.h" 7#include "net.minecraft.world.entity.ai.goal.target.h" 8#include "net.minecraft.world.entity.monster.h" 9#include "net.minecraft.world.entity.projectile.h" 10#include "net.minecraft.world.item.h" 11#include "net.minecraft.world.item.alchemy.h" 12#include "net.minecraft.world.level.h" 13#include "net.minecraft.world.phys.h" 14#include "Witch.h" 15 16AttributeModifier *Witch::SPEED_MODIFIER_DRINKING = (new AttributeModifier(eModifierId_MOB_WITCH_DRINKSPEED, -0.25f, AttributeModifier::OPERATION_ADDITION))->setSerialize(false); 17 18const int Witch::DEATH_LOOT[Witch::DEATH_LOOT_COUNT] = { 19 Item::yellowDust_Id, Item::sugar_Id, Item::redStone_Id, Item::spiderEye_Id, Item::glassBottle_Id, Item::gunpowder_Id, Item::stick_Id, Item::stick_Id, 20}; 21 22Witch::Witch(Level *level) : Monster(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 defineSynchedData(); 27 registerAttributes(); 28 setHealth(getMaxHealth()); 29 30 usingTime = 0; 31 32 goalSelector.addGoal(1, new FloatGoal(this)); 33 goalSelector.addGoal(2, new RangedAttackGoal(this, this, 1.0, SharedConstants::TICKS_PER_SECOND * 3, 10)); 34 goalSelector.addGoal(2, new RandomStrollGoal(this, 1.0)); 35 goalSelector.addGoal(3, new LookAtPlayerGoal(this, typeid(Player), 8)); 36 goalSelector.addGoal(3, new RandomLookAroundGoal(this)); 37 38 targetSelector.addGoal(1, new HurtByTargetGoal(this, false)); 39 targetSelector.addGoal(2, new NearestAttackableTargetGoal(this, typeid(Player), 0, true)); 40} 41 42void Witch::defineSynchedData() 43{ 44 Monster::defineSynchedData(); 45 46 getEntityData()->define(DATA_USING_ITEM, (byte) 0); 47} 48 49int Witch::getAmbientSound() 50{ 51 return eSoundType_MOB_WITCH_IDLE; //"mob.witch.idle"; 52} 53 54int Witch::getHurtSound() 55{ 56 return eSoundType_MOB_WITCH_HURT; //"mob.witch.hurt"; 57} 58 59int Witch::getDeathSound() 60{ 61 return eSoundType_MOB_WITCH_DEATH; //"mob.witch.death"; 62} 63 64void Witch::setUsingItem(bool isUsing) 65{ 66 getEntityData()->set(DATA_USING_ITEM, isUsing ? (byte) 1 : (byte) 0); 67} 68 69bool Witch::isUsingItem() 70{ 71 return getEntityData()->getByte(DATA_USING_ITEM) == 1; 72} 73 74void Witch::registerAttributes() 75{ 76 Monster::registerAttributes(); 77 78 getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(26); 79 getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.25f); 80} 81 82bool Witch::useNewAi() 83{ 84 return true; 85} 86 87void Witch::aiStep() 88{ 89 if (!level->isClientSide) 90 { 91 if (isUsingItem()) 92 { 93 if (usingTime-- <= 0) 94 { 95 setUsingItem(false); 96 shared_ptr<ItemInstance> item = getCarriedItem(); 97 setEquippedSlot(SLOT_WEAPON, nullptr); 98 99 if (item != NULL && item->id == Item::potion_Id) 100 { 101 vector<MobEffectInstance *> *effects = Item::potion->getMobEffects(item); 102 if (effects != NULL) 103 { 104 for(AUTO_VAR(it, effects->begin()); it != effects->end(); ++it) 105 { 106 addEffect(new MobEffectInstance(*it)); 107 } 108 } 109 delete effects; 110 } 111 112 getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->removeModifier(SPEED_MODIFIER_DRINKING); 113 } 114 } 115 else 116 { 117 int potion = -1; 118 119 if (random->nextFloat() < 0.15f && isOnFire() && !hasEffect(MobEffect::fireResistance)) 120 { 121 potion = PotionBrewing::POTION_ID_FIRE_RESISTANCE; 122 } 123 else if (random->nextFloat() < 0.05f && getHealth() < getMaxHealth()) 124 { 125 potion = PotionBrewing::POTION_ID_HEAL; 126 } 127 else if (random->nextFloat() < 0.25f && getTarget() != NULL && !hasEffect(MobEffect::movementSpeed) && getTarget()->distanceToSqr(shared_from_this()) > 11 * 11) 128 { 129 potion = PotionBrewing::POTION_ID_SWIFTNESS; 130 } 131 else if (random->nextFloat() < 0.25f && getTarget() != NULL && !hasEffect(MobEffect::movementSpeed) && getTarget()->distanceToSqr(shared_from_this()) > 11 * 11) 132 { 133 potion = PotionBrewing::POTION_ID_SWIFTNESS; 134 } 135 136 if (potion > -1) 137 { 138 setEquippedSlot(SLOT_WEAPON, shared_ptr<ItemInstance>( new ItemInstance(Item::potion, 1, potion)) ); 139 usingTime = getCarriedItem()->getUseDuration(); 140 setUsingItem(true); 141 AttributeInstance *speed = getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED); 142 speed->removeModifier(SPEED_MODIFIER_DRINKING); 143 speed->addModifier(new AttributeModifier(*SPEED_MODIFIER_DRINKING)); 144 } 145 } 146 147 if (random->nextFloat() < 0.00075f) 148 { 149 level->broadcastEntityEvent(shared_from_this(), EntityEvent::WITCH_HAT_MAGIC); 150 } 151 } 152 153 Monster::aiStep(); 154} 155 156void Witch::handleEntityEvent(byte id) 157{ 158 if (id == EntityEvent::WITCH_HAT_MAGIC) 159 { 160 for (int i = 0; i < random->nextInt(35) + 10; i++) 161 { 162 level->addParticle(eParticleType_witchMagic, x + random->nextGaussian() * .13f, bb->y1 + 0.5f + random->nextGaussian() * .13f, z + random->nextGaussian() * .13f, 0, 0, 0); 163 } 164 } 165 else 166 { 167 Monster::handleEntityEvent(id); 168 } 169} 170 171float Witch::getDamageAfterMagicAbsorb(DamageSource *damageSource, float damage) 172{ 173 damage = Monster::getDamageAfterMagicAbsorb(damageSource, damage); 174 175 if (damageSource->getEntity() == shared_from_this()) damage = 0; 176 if (damageSource->isMagic()) damage *= 0.15; 177 178 return damage; 179} 180 181void Witch::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) 182{ 183 int passes = random->nextInt(3) + 1; 184 for (int pass = 0; pass < passes; pass++) 185 { 186 int count = random->nextInt(3); 187 int type = DEATH_LOOT[random->nextInt(DEATH_LOOT_COUNT)]; 188 if (playerBonusLevel > 0) count += random->nextInt(playerBonusLevel + 1); 189 190 for (int i = 0; i < count; i++) 191 { 192 spawnAtLocation(type, 1); 193 } 194 } 195} 196 197void Witch::performRangedAttack(shared_ptr<LivingEntity> target, float power) 198{ 199 if (isUsingItem()) return; 200 201 shared_ptr<ThrownPotion> potion = shared_ptr<ThrownPotion>( new ThrownPotion(level, dynamic_pointer_cast<LivingEntity>(shared_from_this()), PotionBrewing::POTION_ID_SPLASH_DAMAGE) ); 202 potion->xRot -= -20; 203 double xd = (target->x + target->xd) - x; 204 double yd = (target->y + target->getHeadHeight() - 1.1f) - y; 205 double zd = (target->z + target->zd) - z; 206 float dist = Mth::sqrt(xd * xd + zd * zd); 207 208 if (dist >= 8 && !target->hasEffect(MobEffect::movementSlowdown)) 209 { 210 potion->setPotionValue(PotionBrewing::POTION_ID_SPLASH_SLOWNESS); 211 } 212 else if (target->getHealth() >= 8 && !target->hasEffect(MobEffect::poison)) 213 { 214 potion->setPotionValue(PotionBrewing::POTION_ID_SPLASH_POISON); 215 } 216 else if (dist <= 3 && !target->hasEffect(MobEffect::weakness) && random->nextFloat() < 0.25f) 217 { 218 potion->setPotionValue(PotionBrewing::POTION_ID_SPLASH_WEAKNESS); 219 } 220 221 potion->shoot(xd, yd + dist * 0.2f, zd, 0.75f, 8); 222 223 level->addEntity(potion); 224}