From 29261082f1d4ccdb21563f4a0685a2305006136b Mon Sep 17 00:00:00 2001 From: Electroblob <35599699+Electroblob77@users.noreply.github.com> Date: Wed, 20 Jun 2018 22:25:54 +0100 Subject: [PATCH] Spell hierarchisation and refactoring, plus miscellaneous renaming and minor refactoring - Adds new generic spell superclasses which aim to group spells such that duplicate code is eliminated, and functions standardised, as much as possible. - Removes numerous spell classes which are no longer required as a result of this change, and replaces them with instances of the relevant generic spell classes. - Changes the remaining spell classes to fit with the new system, mostly by having them extend the generic spell classes. - Completes the transfer of particle spawning to the ParticleBuilder system. --- .../wizardry/block/BlockStatue.java | 88 ++++- .../client/WizardryClientEventHandler.java | 2 +- .../wizardry/client/renderer/LayerStone.java | 4 +- .../wizardry/client/renderer/RenderDecay.java | 2 +- .../entity/construct/EntityArrowRain.java | 12 +- .../entity/construct/EntityBlackHole.java | 27 +- .../entity/construct/EntityBlizzard.java | 11 +- .../entity/construct/EntityBubble.java | 7 - .../entity/construct/EntityDecay.java | 39 +-- .../entity/construct/EntityEarthquake.java | 31 +- .../entity/construct/EntityFireRing.java | 11 +- .../entity/construct/EntityFireSigil.java | 30 +- .../entity/construct/EntityForcefield.java | 37 +- .../entity/construct/EntityFrostSigil.java | 40 +-- .../entity/construct/EntityHailstorm.java | 19 +- .../entity/construct/EntityHammer.java | 11 +- .../entity/construct/EntityHealAura.java | 15 +- .../entity/construct/EntityIceSpike.java | 7 +- .../construct/EntityLightningPulse.java | 12 +- .../construct/EntityLightningSigil.java | 33 +- .../construct/EntityMagicConstruct.java | 24 +- .../entity/construct/EntityTornado.java | 10 +- .../entity/living/EntityBlazeMinion.java | 49 +-- .../wizardry/entity/living/EntityDecoy.java | 8 +- .../entity/living/EntityEvilWizard.java | 12 + .../entity/living/EntityIceGiant.java | 125 ++----- .../entity/living/EntityIceWraith.java | 21 +- .../entity/living/EntityLightningWraith.java | 31 +- .../entity/living/EntityMagicSlime.java | 81 +---- .../wizardry/entity/living/EntityPhoenix.java | 10 +- .../entity/living/EntityShadowWraith.java | 14 +- .../entity/living/EntitySilverfishMinion.java | 95 +---- .../entity/living/EntitySkeletonMinion.java | 96 +---- .../entity/living/EntitySpiderMinion.java | 89 +---- .../entity/living/EntityStormElemental.java | 6 +- .../entity/living/EntitySummonedCreature.java | 57 +-- .../living/EntityWitherSkeletonMinion.java | 103 ++---- .../wizardry/entity/living/EntityWizard.java | 14 +- .../entity/living/EntityZombieMinion.java | 19 +- .../wizardry/entity/living/ISpellCaster.java | 11 + .../entity/living/ISummonedCreature.java | 8 + .../entity/projectile/EntityBomb.java | 18 +- .../entity/projectile/EntityDarknessOrb.java | 34 +- .../entity/projectile/EntityDart.java | 55 +-- .../entity/projectile/EntityFirebolt.java | 28 +- .../entity/projectile/EntityFirebomb.java | 21 +- .../entity/projectile/EntityForceArrow.java | 29 +- .../entity/projectile/EntityForceOrb.java | 46 +-- .../entity/projectile/EntityIceCharge.java | 28 +- .../entity/projectile/EntityIceLance.java | 82 +---- .../entity/projectile/EntityIceShard.java | 69 +--- .../projectile/EntityLightningArrow.java | 55 +-- .../projectile/EntityLightningDisc.java | 27 +- .../entity/projectile/EntityMagicArrow.java | 329 ++++++++---------- .../entity/projectile/EntityMagicMissile.java | 48 +-- .../projectile/EntityMagicProjectile.java | 107 +++--- .../entity/projectile/EntityPoisonBomb.java | 24 +- .../entity/projectile/EntitySmokeBomb.java | 19 +- .../entity/projectile/EntitySpark.java | 44 +-- .../entity/projectile/EntitySparkBomb.java | 48 +-- .../entity/projectile/EntityThunderbolt.java | 40 +-- .../wizardry/item/ItemFirebomb.java | 5 +- .../wizardry/item/ItemPoisonBomb.java | 5 +- .../wizardry/item/ItemSmokeBomb.java | 5 +- .../electroblob/wizardry/item/ItemWand.java | 4 +- .../wizardry/item/ItemWizardArmour.java | 4 +- .../wizardry/potion/PotionDecay.java | 9 +- .../electroblob/wizardry/registry/Spells.java | 143 +++++--- .../electroblob/wizardry/spell/Agility.java | 51 --- .../java/electroblob/wizardry/spell/Arc.java | 93 ++--- .../wizardry/spell/ArcaneJammer.java | 93 ++--- .../electroblob/wizardry/spell/ArrowRain.java | 64 ++-- .../electroblob/wizardry/spell/Banish.java | 139 ++------ .../electroblob/wizardry/spell/BlackHole.java | 70 ---- .../electroblob/wizardry/spell/Blink.java | 6 +- .../electroblob/wizardry/spell/Blizzard.java | 81 ----- .../electroblob/wizardry/spell/Bubble.java | 125 +++---- .../wizardry/spell/ChainLightning.java | 207 ++++------- .../wizardry/spell/Clairvoyance.java | 18 +- .../electroblob/wizardry/spell/Cobwebs.java | 130 ++----- .../wizardry/spell/ConjureArmour.java | 38 +- .../wizardry/spell/ConjureBow.java | 60 ---- .../wizardry/spell/ConjurePickaxe.java | 50 --- .../wizardry/spell/ConjureSword.java | 49 --- .../wizardry/spell/CureEffects.java | 63 +--- .../wizardry/spell/CurseOfSoulbinding.java | 76 ++-- .../wizardry/spell/DarknessOrb.java | 68 ---- .../wizardry/spell/Darkvision.java | 45 --- .../java/electroblob/wizardry/spell/Dart.java | 67 ---- .../electroblob/wizardry/spell/Decay.java | 97 ++---- .../electroblob/wizardry/spell/Decoy.java | 80 ++--- .../electroblob/wizardry/spell/Detonate.java | 128 ++----- .../wizardry/spell/Diamondflesh.java | 53 --- .../wizardry/spell/Earthquake.java | 66 ++-- .../wizardry/spell/Entrapment.java | 116 ++---- .../wizardry/spell/FireResistance.java | 78 ----- .../electroblob/wizardry/spell/FireSigil.java | 51 --- .../electroblob/wizardry/spell/Fireball.java | 2 +- .../electroblob/wizardry/spell/Firebolt.java | 69 ---- .../electroblob/wizardry/spell/Firebomb.java | 70 ---- .../electroblob/wizardry/spell/Fireskin.java | 70 ---- .../electroblob/wizardry/spell/Firestorm.java | 125 ++++--- .../electroblob/wizardry/spell/FlameRay.java | 135 +++---- .../wizardry/spell/FlamingAxe.java | 42 +-- .../wizardry/spell/FlamingWeapon.java | 22 +- .../electroblob/wizardry/spell/Flight.java | 25 +- .../wizardry/spell/FontOfMana.java | 20 +- .../wizardry/spell/FontOfVitality.java | 57 --- .../wizardry/spell/ForceArrow.java | 69 ---- .../electroblob/wizardry/spell/ForceOrb.java | 70 ---- .../wizardry/spell/Forcefield.java | 73 ---- .../wizardry/spell/ForestsCurse.java | 88 ++--- .../electroblob/wizardry/spell/Freeze.java | 193 +++------- .../wizardry/spell/FreezingWeapon.java | 24 +- .../electroblob/wizardry/spell/FrostAxe.java | 45 +-- .../electroblob/wizardry/spell/FrostRay.java | 182 ++++------ .../wizardry/spell/FrostSigil.java | 51 --- .../electroblob/wizardry/spell/Glide.java | 23 +- .../wizardry/spell/GreaterFireball.java | 2 +- .../wizardry/spell/GreaterHeal.java | 60 +--- .../electroblob/wizardry/spell/GroupHeal.java | 38 +- .../wizardry/spell/GrowthAura.java | 2 +- .../electroblob/wizardry/spell/Hailstorm.java | 60 ++-- .../java/electroblob/wizardry/spell/Heal.java | 63 +--- .../electroblob/wizardry/spell/HealAlly.java | 68 ++-- .../wizardry/spell/HealingAura.java | 68 ---- .../wizardry/spell/HomingSpark.java | 65 ---- .../electroblob/wizardry/spell/IceAge.java | 2 +- .../electroblob/wizardry/spell/IceCharge.java | 70 ---- .../electroblob/wizardry/spell/IceLance.java | 67 ---- .../electroblob/wizardry/spell/IceShard.java | 67 ---- .../electroblob/wizardry/spell/IceShroud.java | 71 ---- .../electroblob/wizardry/spell/IceSpikes.java | 117 ++----- .../electroblob/wizardry/spell/IceStatue.java | 138 ++------ .../electroblob/wizardry/spell/Ignite.java | 163 ++------- .../wizardry/spell/ImbueWeapon.java | 28 +- .../wizardry/spell/Intimidate.java | 23 +- .../wizardry/spell/InvigoratingPresence.java | 28 +- .../wizardry/spell/Invisibility.java | 78 ----- .../wizardry/spell/InvokeWeather.java | 22 +- .../electroblob/wizardry/spell/Ironflesh.java | 79 ----- .../java/electroblob/wizardry/spell/Leap.java | 4 +- .../wizardry/spell/Levitation.java | 18 +- .../electroblob/wizardry/spell/LifeDrain.java | 137 +++----- .../electroblob/wizardry/spell/Light.java | 4 +- .../wizardry/spell/LightningArrow.java | 69 ---- .../wizardry/spell/LightningBolt.java | 78 ++--- .../wizardry/spell/LightningDisc.java | 69 ---- .../wizardry/spell/LightningHammer.java | 53 +-- .../wizardry/spell/LightningPulse.java | 28 +- .../wizardry/spell/LightningRay.java | 175 ++++------ .../wizardry/spell/LightningSigil.java | 53 --- .../wizardry/spell/LightningWeb.java | 296 +++++++--------- .../wizardry/spell/MagicMissile.java | 71 ---- .../wizardry/spell/Metamorphosis.java | 86 +++-- .../electroblob/wizardry/spell/Meteor.java | 53 ++- .../wizardry/spell/MindControl.java | 113 ++---- .../electroblob/wizardry/spell/MindTrick.java | 88 ++--- .../java/electroblob/wizardry/spell/None.java | 4 +- .../electroblob/wizardry/spell/Oakflesh.java | 79 ----- .../electroblob/wizardry/spell/Petrify.java | 136 ++------ .../electroblob/wizardry/spell/PhaseStep.java | 6 +- .../wizardry/spell/PlagueOfDarkness.java | 36 +- .../wizardry/spell/PocketFurnace.java | 4 +- .../wizardry/spell/PocketWorkbench.java | 2 +- .../electroblob/wizardry/spell/Poison.java | 143 +++----- .../wizardry/spell/PoisonBomb.java | 70 ---- .../wizardry/spell/ReplenishHunger.java | 36 +- .../wizardry/spell/RingOfFire.java | 74 ---- .../wizardry/spell/ShadowWard.java | 4 +- .../electroblob/wizardry/spell/Shield.java | 2 +- .../electroblob/wizardry/spell/Shockwave.java | 32 +- .../wizardry/spell/SilverfishSwarm.java | 49 --- .../wizardry/spell/SixthSense.java | 2 +- .../electroblob/wizardry/spell/Slime.java | 119 +++---- .../electroblob/wizardry/spell/SmokeBomb.java | 70 ---- .../electroblob/wizardry/spell/Snare.java | 94 +++-- .../electroblob/wizardry/spell/Snowball.java | 2 +- .../electroblob/wizardry/spell/SparkBomb.java | 70 ---- .../wizardry/spell/SpectralPathway.java | 2 +- .../electroblob/wizardry/spell/Spell.java | 75 ++-- .../wizardry/spell/SpellAreaEffect.java | 140 ++++++++ .../wizardry/spell/SpellArrow.java | 135 +++++++ .../electroblob/wizardry/spell/SpellBuff.java | 153 ++++++++ .../wizardry/spell/SpellConjuration.java | 120 +++++++ .../wizardry/spell/SpellConstruct.java | 185 ++++++++++ .../wizardry/spell/SpellConstructRanged.java | 133 +++++++ .../wizardry/spell/SpellMinion.java | 165 +++++++++ .../wizardry/spell/SpellProjectile.java | 135 +++++++ .../electroblob/wizardry/spell/SpellRay.java | 320 +++++++++++++++++ .../wizardry/spell/SpiderSwarm.java | 76 ---- .../wizardry/spell/StaticAura.java | 71 ---- .../wizardry/spell/SummonBlaze.java | 71 ---- .../wizardry/spell/SummonIceGiant.java | 53 --- .../wizardry/spell/SummonIceWraith.java | 70 ---- .../wizardry/spell/SummonIronGolem.java | 27 +- .../wizardry/spell/SummonLightningWraith.java | 70 ---- .../wizardry/spell/SummonPhoenix.java | 46 --- .../wizardry/spell/SummonShadowWraith.java | 37 +- .../wizardry/spell/SummonSkeleton.java | 63 +--- .../wizardry/spell/SummonSkeletonLegion.java | 76 +--- .../wizardry/spell/SummonSnowGolem.java | 27 +- .../wizardry/spell/SummonSpiritHorse.java | 2 +- .../wizardry/spell/SummonSpiritWolf.java | 2 +- .../wizardry/spell/SummonStormElemental.java | 45 --- .../wizardry/spell/SummonWitherSkeleton.java | 76 ---- .../wizardry/spell/SummonZombie.java | 67 ---- .../wizardry/spell/Telekinesis.java | 127 +++---- .../wizardry/spell/Thunderbolt.java | 68 ---- .../wizardry/spell/Thunderstorm.java | 53 ++- .../electroblob/wizardry/spell/Tornado.java | 62 +--- .../wizardry/spell/Transience.java | 2 +- .../wizardry/spell/Transportation.java | 2 +- .../wizardry/spell/VanishingBox.java | 7 +- .../wizardry/spell/WallOfFrost.java | 140 +++++--- .../wizardry/spell/WaterBreathing.java | 44 --- .../electroblob/wizardry/spell/Whirlwind.java | 78 +---- .../electroblob/wizardry/spell/Wither.java | 115 ++---- .../wizardry/spell/WitherSkull.java | 2 +- .../wizardry/util/ParticleBuilder.java | 18 + .../wizardry/util/SpellModifiers.java | 4 +- .../wizardry/util/WizardryUtilities.java | 92 ++--- 222 files changed, 4412 insertions(+), 9016 deletions(-) delete mode 100644 src/main/java/electroblob/wizardry/spell/Agility.java delete mode 100644 src/main/java/electroblob/wizardry/spell/BlackHole.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Blizzard.java delete mode 100644 src/main/java/electroblob/wizardry/spell/ConjureBow.java delete mode 100644 src/main/java/electroblob/wizardry/spell/ConjurePickaxe.java delete mode 100644 src/main/java/electroblob/wizardry/spell/ConjureSword.java delete mode 100644 src/main/java/electroblob/wizardry/spell/DarknessOrb.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Darkvision.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Dart.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Diamondflesh.java delete mode 100644 src/main/java/electroblob/wizardry/spell/FireResistance.java delete mode 100644 src/main/java/electroblob/wizardry/spell/FireSigil.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Firebolt.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Firebomb.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Fireskin.java delete mode 100644 src/main/java/electroblob/wizardry/spell/FontOfVitality.java delete mode 100644 src/main/java/electroblob/wizardry/spell/ForceArrow.java delete mode 100644 src/main/java/electroblob/wizardry/spell/ForceOrb.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Forcefield.java delete mode 100644 src/main/java/electroblob/wizardry/spell/FrostSigil.java delete mode 100644 src/main/java/electroblob/wizardry/spell/HealingAura.java delete mode 100644 src/main/java/electroblob/wizardry/spell/HomingSpark.java delete mode 100644 src/main/java/electroblob/wizardry/spell/IceCharge.java delete mode 100644 src/main/java/electroblob/wizardry/spell/IceLance.java delete mode 100644 src/main/java/electroblob/wizardry/spell/IceShard.java delete mode 100644 src/main/java/electroblob/wizardry/spell/IceShroud.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Invisibility.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Ironflesh.java delete mode 100644 src/main/java/electroblob/wizardry/spell/LightningArrow.java delete mode 100644 src/main/java/electroblob/wizardry/spell/LightningDisc.java delete mode 100644 src/main/java/electroblob/wizardry/spell/LightningSigil.java delete mode 100644 src/main/java/electroblob/wizardry/spell/MagicMissile.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Oakflesh.java delete mode 100644 src/main/java/electroblob/wizardry/spell/PoisonBomb.java delete mode 100644 src/main/java/electroblob/wizardry/spell/RingOfFire.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SilverfishSwarm.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SmokeBomb.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SparkBomb.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellAreaEffect.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellArrow.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellBuff.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellConjuration.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellConstruct.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellConstructRanged.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellMinion.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellProjectile.java create mode 100644 src/main/java/electroblob/wizardry/spell/SpellRay.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SpiderSwarm.java delete mode 100644 src/main/java/electroblob/wizardry/spell/StaticAura.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SummonBlaze.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SummonIceGiant.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SummonIceWraith.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SummonLightningWraith.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SummonPhoenix.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SummonStormElemental.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SummonWitherSkeleton.java delete mode 100644 src/main/java/electroblob/wizardry/spell/SummonZombie.java delete mode 100644 src/main/java/electroblob/wizardry/spell/Thunderbolt.java delete mode 100644 src/main/java/electroblob/wizardry/spell/WaterBreathing.java diff --git a/src/main/java/electroblob/wizardry/block/BlockStatue.java b/src/main/java/electroblob/wizardry/block/BlockStatue.java index d4c3d891..d52295b8 100644 --- a/src/main/java/electroblob/wizardry/block/BlockStatue.java +++ b/src/main/java/electroblob/wizardry/block/BlockStatue.java @@ -2,13 +2,14 @@ package electroblob.wizardry.block; import java.util.Random; -import electroblob.wizardry.spell.Petrify; import electroblob.wizardry.tileentity.TileEntityStatue; +import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLiving; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumBlockRenderType; @@ -23,6 +24,9 @@ import net.minecraftforge.fml.relauncher.SideOnly; public class BlockStatue extends BlockContainer { private boolean isIce; + + /** The NBT tag name for storing the petrified flag (used for rendering) in the target's tag compound. */ + public static final String NBT_KEY = "petrified"; public BlockStatue(Material material){ super(material); @@ -146,7 +150,7 @@ public class BlockStatue extends BlockContainer { // This is only when position == 1 because world.destroyBlock calls this function for the other blocks. if(tileentity != null && tileentity.position == 1 && tileentity.creature != null){ - tileentity.creature.getEntityData().removeTag(Petrify.NBT_KEY); + tileentity.creature.getEntityData().removeTag(BlockStatue.NBT_KEY); tileentity.creature.isDead = false; world.spawnEntity(tileentity.creature); } @@ -166,4 +170,84 @@ public class BlockStatue extends BlockContainer { return this.isIce && block == this ? false : super.shouldSideBeRendered(blockState, blockAccess, pos, side); } + + /** + * Turns the given entity into a statue. The type of statue depends on the block instance this method was invoked on. + * @param entity The entity to turn into a statue. + * @param duration The time for which the entity should remain a statue. For petrified creatures, this is the minimum + * time it can stay as a statue. + * @return True if the entity was successfully turned into a statue, false if not (i.e. something was in the way). + */ + // Making this an instance method means it works equally well for both types of statue + public boolean convertToStatue(EntityLiving entity, int duration){ + + if(entity.deathTime > 0) return false; + + BlockPos pos = new BlockPos(entity); + World world = entity.world; + + entity.hurtTime = 0; // Stops the entity looking red while frozen and the resulting z-fighting + entity.extinguish(); + + // Short mobs such as spiders and pigs + if((entity.height < 1.2 || entity.isChild()) && WizardryUtilities.canBlockBeReplaced(world, pos)){ + + world.setBlockState(pos, this.getDefaultState()); + if(world.getTileEntity(pos) instanceof TileEntityStatue){ + ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(entity, 1, 1); + ((TileEntityStatue)world.getTileEntity(pos)).setLifetime(duration); + } + + if(!this.isIce) entity.getEntityData().setBoolean(NBT_KEY, true); + entity.setDead(); + return true; + } + // Normal sized mobs like zombies and skeletons + else if(entity.height < 2.5 && WizardryUtilities.canBlockBeReplaced(world, pos) + && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ + + world.setBlockState(pos, this.getDefaultState()); + if(world.getTileEntity(pos) instanceof TileEntityStatue){ + ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(entity, 1, 2); + ((TileEntityStatue)world.getTileEntity(pos)).setLifetime(duration); + } + + world.setBlockState(pos.up(), this.getDefaultState()); + if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ + ((TileEntityStatue)world.getTileEntity(pos.up())).setCreatureAndPart(entity, 2, 2); + } + + if(!this.isIce) entity.getEntityData().setBoolean(NBT_KEY, true); + entity.setDead(); + return true; + } + // Tall mobs like endermen + else if(WizardryUtilities.canBlockBeReplaced(world, pos) + && WizardryUtilities.canBlockBeReplaced(world, pos.up()) + && WizardryUtilities.canBlockBeReplaced(world, pos.up(2))){ + + world.setBlockState(pos, this.getDefaultState()); + if(world.getTileEntity(pos) instanceof TileEntityStatue){ + ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(entity, 1, 3); + ((TileEntityStatue)world.getTileEntity(pos)).setLifetime(duration); + } + + world.setBlockState(pos.up(), this.getDefaultState()); + if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ + ((TileEntityStatue)world.getTileEntity(pos.up())).setCreatureAndPart(entity, 2, 3); + } + + world.setBlockState(pos.up(2), this.getDefaultState()); + if(world.getTileEntity(pos.up(2)) instanceof TileEntityStatue){ + ((TileEntityStatue)world.getTileEntity(pos.up(2))).setCreatureAndPart(entity, 3, 3); + } + + if(!this.isIce) entity.getEntityData().setBoolean(NBT_KEY, true); + entity.setDead(); + return true; + } + + return false; + } + } diff --git a/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java b/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java index 04ff6202..e9ea54fb 100644 --- a/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java +++ b/src/main/java/electroblob/wizardry/client/WizardryClientEventHandler.java @@ -208,7 +208,7 @@ public final class WizardryClientEventHandler { Minecraft mc = Minecraft.getMinecraft(); WizardData properties = WizardData.get(mc.player); - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(mc.world, mc.player, 16); + RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(mc.world, mc.player, 16, false); RenderManager renderManager = event.getRenderer().getRenderManager(); ItemStack wand = mc.player.getHeldItemMainhand(); diff --git a/src/main/java/electroblob/wizardry/client/renderer/LayerStone.java b/src/main/java/electroblob/wizardry/client/renderer/LayerStone.java index 3630e58a..7978e26e 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/LayerStone.java +++ b/src/main/java/electroblob/wizardry/client/renderer/LayerStone.java @@ -4,8 +4,8 @@ import java.util.Map.Entry; import org.lwjgl.opengl.GL11; +import electroblob.wizardry.block.BlockStatue; import electroblob.wizardry.client.ClientProxy; -import electroblob.wizardry.spell.Petrify; import net.minecraft.client.Minecraft; import net.minecraft.client.model.ModelBase; import net.minecraft.client.model.ModelBiped; @@ -60,7 +60,7 @@ public class LayerStone implements LayerRenderer { public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale){ - if(entity.getEntityData().getBoolean(Petrify.NBT_KEY)){ + if(entity.getEntityData().getBoolean(BlockStatue.NBT_KEY)){ GlStateManager.enableLighting(); int i = this.getBlockBrightnessForEntity(entity, partialTicks); diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderDecay.java b/src/main/java/electroblob/wizardry/client/renderer/RenderDecay.java index 272b8527..b631a5a7 100644 --- a/src/main/java/electroblob/wizardry/client/renderer/RenderDecay.java +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderDecay.java @@ -44,7 +44,7 @@ public class RenderDecay extends Render { GlStateManager.rotate(-90, 1, 0, 0); - float scale = 2 * Math.min(1, (float)(EntityDecay.LIFETIME - entity.ticksExisted) / 50f); + float scale = 2 * Math.min(1, (float)(entity.lifetime - entity.ticksExisted) / 50f); GlStateManager.scale(scale, scale, scale); diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityArrowRain.java b/src/main/java/electroblob/wizardry/entity/construct/EntityArrowRain.java index 1ad7632d..b2ecca42 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityArrowRain.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityArrowRain.java @@ -1,6 +1,5 @@ package electroblob.wizardry.entity.construct; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.projectile.EntityTippedArrow; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; @@ -8,15 +7,8 @@ import net.minecraft.world.World; public class EntityArrowRain extends EntityMagicConstruct { - public EntityArrowRain(World par1World){ - super(par1World); - this.height = 3.0f; - this.width = 5.0f; - } - - public EntityArrowRain(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); + public EntityArrowRain(World world){ + super(world); this.height = 3.0f; this.width = 5.0f; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityBlackHole.java b/src/main/java/electroblob/wizardry/entity/construct/EntityBlackHole.java index b7d77fb8..68fc1ae6 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityBlackHole.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityBlackHole.java @@ -12,8 +12,9 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.SPacketEntityVelocity; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; public class EntityBlackHole extends EntityMagicConstruct { @@ -34,21 +35,6 @@ public class EntityBlackHole extends EntityMagicConstruct { } } - public EntityBlackHole(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); - this.width = 6.0f; - this.height = 3.0f; - randomiser = new int[30]; - for(int i = 0; i < randomiser.length; i++){ - randomiser[i] = this.rand.nextInt(10); - } - randomiser2 = new int[30]; - for(int i = 0; i < randomiser2.length; i++){ - randomiser2[i] = this.rand.nextInt(10); - } - } - @Override protected void readEntityFromNBT(NBTTagCompound nbttagcompound){ super.readEntityFromNBT(nbttagcompound); @@ -135,11 +121,10 @@ public class EntityBlackHole extends EntityMagicConstruct { } } } - - /** - * Checks using a Vec3dd to determine if this entity is within range of that vector to be rendered. Args: Vec3dD - */ - public boolean isInRangeToRenderVec3dD(Vec3d par1Vec3d){ + + @Override + @SideOnly(Side.CLIENT) + public boolean isInRangeToRenderDist(double distance){ return true; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java b/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java index 358eb4a6..c45abe77 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java @@ -16,15 +16,8 @@ import net.minecraft.world.World; public class EntityBlizzard extends EntityMagicConstruct { - public EntityBlizzard(World par1World){ - super(par1World); - this.height = 1.0f; - this.width = 1.0f; - } - - public EntityBlizzard(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); + public EntityBlizzard(World world){ + super(world); this.height = 1.0f; this.width = 1.0f; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityBubble.java b/src/main/java/electroblob/wizardry/entity/construct/EntityBubble.java index a864526b..58c3e0e5 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityBubble.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityBubble.java @@ -28,13 +28,6 @@ public class EntityBubble extends EntityMagicConstruct { super(world); } - public EntityBubble(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - boolean isDarkOrb, float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); - // this.setSize(0.1f, 0.1f); - this.isDarkOrb = isDarkOrb; - } - @Override public double getMountedYOffset(){ return 0.1; diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java b/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java index 19b150d6..6c40f523 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java @@ -10,23 +10,14 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class EntityDecay extends EntityMagicConstruct { public int textureIndex = 0; - public static final int LIFETIME = 400; - public EntityDecay(World par1World){ - super(par1World); - textureIndex = this.rand.nextInt(10); - this.height = 0.2f; - this.width = 2.0f; - } - - public EntityDecay(World par1World, double x, double y, double z, EntityLivingBase caster){ - super(par1World, x, y, z, caster, LIFETIME, 1); + public EntityDecay(World world){ + super(world); textureIndex = this.rand.nextInt(10); this.height = 0.2f; this.width = 2.0f; @@ -37,7 +28,7 @@ public class EntityDecay extends EntityMagicConstruct { super.onUpdate(); - if(this.rand.nextInt(700) == 0 && this.ticksExisted + 100 < LIFETIME) + if(this.rand.nextInt(700) == 0 && this.ticksExisted + 100 < lifetime) this.playSound(SoundEvents.BLOCK_LAVA_AMBIENT, 0.2F + rand.nextFloat() * 0.2F, 0.6F + rand.nextFloat() * 0.15F); @@ -50,7 +41,7 @@ public class EntityDecay extends EntityMagicConstruct { // damaged each tick. // In this case, we do want particles to be shown. if(!target.isPotionActive(WizardryPotions.decay)) - target.addPotionEffect(new PotionEffect(WizardryPotions.decay, LIFETIME, 0)); + target.addPotionEffect(new PotionEffect(WizardryPotions.decay, lifetime, 0)); } } @@ -67,23 +58,15 @@ public class EntityDecay extends EntityMagicConstruct { } } - protected void entityInit(){ - } + @Override protected void entityInit(){} + + @Override protected void readEntityFromNBT(NBTTagCompound nbttagcompound){} + + @Override protected void writeEntityToNBT(NBTTagCompound nbttagcompound){} @Override - protected void readEntityFromNBT(NBTTagCompound nbttagcompound){ - - } - - @Override - protected void writeEntityToNBT(NBTTagCompound nbttagcompound){ - - } - - /** - * Checks using a Vec3dd to determine if this entity is within range of that vector to be rendered. Args: Vec3dD - */ - public boolean isInRangeToRenderVec3dD(Vec3d par1Vec3d){ + public boolean isInRangeToRenderDist(double distance){ return true; } + } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityEarthquake.java b/src/main/java/electroblob/wizardry/entity/construct/EntityEarthquake.java index abc8d982..4a26e83f 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityEarthquake.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityEarthquake.java @@ -7,6 +7,7 @@ import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityFallingBlock; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.MobEffects; import net.minecraft.network.play.server.SPacketEntityVelocity; @@ -22,13 +23,6 @@ public class EntityEarthquake extends EntityMagicConstruct { this.width = 1.0f; } - public EntityEarthquake(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); - this.height = 1.0f; - this.width = 1.0f; - } - public void onUpdate(){ super.onUpdate(); @@ -99,19 +93,16 @@ public class EntityEarthquake extends EntityMagicConstruct { } } } - // TODO: Uncomment once 2.1.0 is released - // }else{ - // - // // Constant 15 blocks for now - // List targets = WizardryUtilities.getEntitiesWithinRadius(15, this.posX, this.posY, - // this.posZ, world, EntityPlayer.class); - // - // float magnitude = 6f * ((float)(this.lifetime - this.ticksExisted))/(float)this.lifetime; - // - // // Makes the screen shake - // for(EntityLivingBase target : targets){ - // target.setAngles(0, this.ticksExisted % 4 < 2 ? magnitude : -magnitude); - // } + }else{ + // Constant 15 blocks for now + List targets = WizardryUtilities.getEntitiesWithinRadius(15, posX, posY, posZ, world, EntityPlayer.class); + + float magnitude = 6f * ((float)(this.lifetime - this.ticksExisted))/(float)this.lifetime; + + // Makes the screen shake + for(EntityPlayer target : targets){ + target.rotationPitch = this.ticksExisted % 2 == 0 ? magnitude : -magnitude; + } } } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityFireRing.java b/src/main/java/electroblob/wizardry/entity/construct/EntityFireRing.java index 97ed7876..5037b3bf 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityFireRing.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityFireRing.java @@ -12,15 +12,8 @@ import net.minecraft.world.World; public class EntityFireRing extends EntityMagicConstruct { - public EntityFireRing(World par1World){ - super(par1World); - this.height = 1.0f; - this.width = 5.0f; - } - - public EntityFireRing(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); + public EntityFireRing(World world){ + super(world); this.height = 1.0f; this.width = 5.0f; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityFireSigil.java b/src/main/java/electroblob/wizardry/entity/construct/EntityFireSigil.java index ecf45f74..bb6b7e34 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityFireSigil.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityFireSigil.java @@ -13,34 +13,20 @@ import net.minecraft.world.World; public class EntityFireSigil extends EntityMagicConstruct { - public EntityFireSigil(World par1World){ - super(par1World); + public EntityFireSigil(World world){ + super(world); this.height = 0.2f; this.width = 2.0f; } - public EntityFireSigil(World par1World, double x, double y, double z, EntityLivingBase caster, - float damageMultiplier){ - super(par1World, x, y, z, caster, -1, damageMultiplier); - this.height = 0.2f; - this.width = 2.0f; - } - - // Overrides the original to stop the entity moving when it intersects stuff. The default arrow does this to allow - // it to stick in blocks. - public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9){ - this.setPosition(par1, par3, par5); - this.setRotation(par7, par8); - } - + @Override public void onUpdate(){ super.onUpdate(); if(!this.world.isRemote){ - List targets = WizardryUtilities.getEntitiesWithinRadius(1.0d, this.posX, this.posY, - this.posZ, this.world); + List targets = WizardryUtilities.getEntitiesWithinRadius(width/2, posX, posY, posZ, world); for(EntityLivingBase target : targets){ @@ -76,13 +62,9 @@ public class EntityFireSigil extends EntityMagicConstruct { } @Override - protected void entityInit(){ + protected void entityInit(){} - } - - /** - * Return whether this entity should be rendered as on fire. - */ + @Override public boolean canRenderOnFire(){ return false; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java b/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java index 8717ccaa..1a77659d 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java @@ -20,40 +20,34 @@ public class EntityForcefield extends EntityMagicConstruct { super(world); this.height = 6; this.width = 6; - this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 3, this.posY - 3, this.posZ - 3, this.posX + 3, - this.posY + 3, this.posZ + 3)); - } - - public EntityForcefield(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ // y-3 because it needs to be centred on the given position - // Damage multiplier is 1 because forcefields do no damage! - super(world, x, y - 3, z, caster, lifetime, 1.0f); - this.height = 6; - this.width = 6; - this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 3, this.posY - 3, this.posZ - 3, this.posX + 3, - this.posY + 3, this.posZ + 3)); + this.setEntityBoundingBox(new AxisAlignedBB(posX - 3, posY - 3, posZ - 3, posX + 3, posY + 3, posZ + 3)); } + @Override public boolean canBeCollidedWith(){ return !this.isDead; } - public AxisAlignedBB getCollisionBox(Entity par1Entity){ - return par1Entity.getEntityBoundingBox(); + @Override + public AxisAlignedBB getCollisionBox(Entity entity){ + return entity.getEntityBoundingBox(); } + @Override public void onUpdate(){ super.onUpdate(); if(!this.world.isRemote){ - List targets = WizardryUtilities.getEntitiesWithinRadius(3.5, this.posX, this.posY + 3, - this.posZ, this.world); + // TESTME: This used to say posY+3, but I'm pretty sure that's wrong because of how the bounding box was set... + List targets = WizardryUtilities.getEntitiesWithinRadius(3.5, posX, posY, posZ, world); + for(EntityLivingBase target : targets){ if(this.isValidTarget(target)){ - double multiplier = (3.5 - target.getDistance(this.posX, this.posY + 3, this.posZ)) * 0.1; + double multiplier = (3.5 - target.getDistance(this.posX, this.posY, this.posZ)) * 0.1; target.addVelocity((target.posX - this.posX) * multiplier, - (target.posY - (this.posY + 3)) * multiplier, (target.posZ - this.posZ) * multiplier); + (target.posY - this.posY) * multiplier, (target.posZ - this.posZ) * multiplier); // Player motion is handled on that player's client so needs packets if(target instanceof EntityPlayerMP){ ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); @@ -78,19 +72,18 @@ public class EntityForcefield extends EntityMagicConstruct { } } - public boolean attackEntityFrom(DamageSource source, float par2){ + @Override + public boolean attackEntityFrom(DamageSource source, float damage){ if(source != null && source.getImmediateSource() != null){ // Now works for any source of damage. source.getImmediateSource().playSound(WizardrySounds.SPELL_DEFLECTION, 0.3f, 1.3f); } - super.attackEntityFrom(source, par2); + super.attackEntityFrom(source, damage); return false; } - /** - * Return whether this entity should be rendered as on fire. - */ + @Override public boolean canRenderOnFire(){ return false; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityFrostSigil.java b/src/main/java/electroblob/wizardry/entity/construct/EntityFrostSigil.java index cb29f67e..1632335b 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityFrostSigil.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityFrostSigil.java @@ -16,26 +16,13 @@ import net.minecraft.world.World; public class EntityFrostSigil extends EntityMagicConstruct { - public EntityFrostSigil(World par1World){ - super(par1World); + public EntityFrostSigil(World world){ + super(world); this.height = 0.2f; this.width = 2.0f; } - public EntityFrostSigil(World par1World, double x, double y, double z, EntityLivingBase caster, - float damageMultiplier){ - super(par1World, x, y, z, caster, -1, damageMultiplier); - this.height = 0.2f; - this.width = 2.0f; - } - - // Overrides the original to stop the entity moving when it intersects stuff. The default arrow does this to allow - // it to stick in blocks. - public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9){ - this.setPosition(par1, par3, par5); - this.setRotation(par7, par8); - } - + @Override public void onUpdate(){ super.onUpdate(); @@ -48,20 +35,11 @@ public class EntityFrostSigil extends EntityMagicConstruct { for(EntityLivingBase target : targets){ if(this.isValidTarget(target)){ - - double velX = target.motionX; - double velY = target.motionY; - double velZ = target.motionZ; - - target.attackEntityFrom(this.getCaster() != null + + WizardryUtilities.attackEntityWithoutKnockback(target, this.getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), DamageType.FROST) : DamageSource.MAGIC, 8); - // Removes knockback - target.motionX = velX; - target.motionY = velY; - target.motionZ = velZ; - if(!MagicDamage.isEntityImmune(DamageType.FROST, target)) target.addPotionEffect(new PotionEffect(WizardryPotions.frost, 200, 1)); @@ -82,13 +60,9 @@ public class EntityFrostSigil extends EntityMagicConstruct { } @Override - protected void entityInit(){ + protected void entityInit(){} - } - - /** - * Return whether this entity should be rendered as on fire. - */ + @Override public boolean canRenderOnFire(){ return false; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityHailstorm.java b/src/main/java/electroblob/wizardry/entity/construct/EntityHailstorm.java index 5bb73e18..6a2baaab 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityHailstorm.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityHailstorm.java @@ -1,20 +1,12 @@ package electroblob.wizardry.entity.construct; import electroblob.wizardry.entity.projectile.EntityIceShard; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.world.World; public class EntityHailstorm extends EntityMagicConstruct { - public EntityHailstorm(World par1World){ - super(par1World); - this.height = 3.0f; - this.width = 5.0f; - } - - public EntityHailstorm(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); + public EntityHailstorm(World world){ + super(world); this.height = 3.0f; this.width = 5.0f; } @@ -25,12 +17,13 @@ public class EntityHailstorm extends EntityMagicConstruct { if(!this.world.isRemote){ // System.out.println(this.rotationYaw); - EntityIceShard iceshard = new EntityIceShard(world, this.posX + rand.nextDouble() * 6 - 3, - this.posY + rand.nextDouble() * 4 - 2, this.posZ + rand.nextDouble() * 6 - 3); + EntityIceShard iceshard = new EntityIceShard(world); + iceshard.setPosition(this.posX + rand.nextDouble() * 6 - 3, this.posY + rand.nextDouble() * 4 - 2, + this.posZ + rand.nextDouble() * 6 - 3); iceshard.motionX = Math.cos(Math.toRadians(this.rotationYaw + 90)); iceshard.motionY = -0.6; iceshard.motionZ = Math.sin(Math.toRadians(this.rotationYaw + 90)); - iceshard.setShootingEntity(this.getCaster()); + iceshard.setCaster(this.getCaster()); iceshard.damageMultiplier = this.damageMultiplier; this.world.spawnEntity(iceshard); } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java b/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java index a66fb43c..6f174d91 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java @@ -28,15 +28,8 @@ public class EntityHammer extends EntityMagicConstruct { /** How long the hammer has been falling for. */ public int fallTime; - public EntityHammer(World par1World){ - super(par1World); - this.setSize(1.0f, 1.9F); - this.noClip = false; - } - - public EntityHammer(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); + public EntityHammer(World world){ + super(world); this.setSize(1.0f, 1.9F); this.motionX = 0.0D; this.motionY = 0.0D; diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java b/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java index 8ca40faa..32e893f7 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java @@ -20,13 +20,7 @@ public class EntityHealAura extends EntityMagicConstruct { this.width = 5.0f; } - public EntityHealAura(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); - this.height = 1.0f; - this.width = 5.0f; - } - + @Override public void onUpdate(){ if(this.ticksExisted % 25 == 1){ @@ -37,8 +31,7 @@ public class EntityHealAura extends EntityMagicConstruct { if(!this.world.isRemote){ - List targets = WizardryUtilities.getEntitiesWithinRadius(2.5d, this.posX, this.posY, - this.posZ, this.world); + List targets = WizardryUtilities.getEntitiesWithinRadius(2.5, posX, posY, posZ, world); for(EntityLivingBase target : targets){ @@ -83,9 +76,7 @@ public class EntityHealAura extends EntityMagicConstruct { } } - /** - * Return whether this entity should be rendered as on fire. - */ + @Override public boolean canRenderOnFire(){ return false; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityIceSpike.java b/src/main/java/electroblob/wizardry/entity/construct/EntityIceSpike.java index d415480e..86817bb4 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityIceSpike.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityIceSpike.java @@ -16,12 +16,7 @@ public class EntityIceSpike extends EntityMagicConstruct { this.setSize(0.5f, 1.0f); } - public EntityIceSpike(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); - this.setSize(0.5f, 1.0f); - } - + @Override public void onUpdate(){ if(lifetime - this.ticksExisted < 15){ diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningPulse.java b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningPulse.java index edab4346..b2d46ab5 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningPulse.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningPulse.java @@ -1,8 +1,8 @@ package electroblob.wizardry.entity.construct; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.world.World; +@Deprecated // This needs changing into a particle public class EntityLightningPulse extends EntityMagicConstruct { public EntityLightningPulse(World world){ @@ -10,15 +10,7 @@ public class EntityLightningPulse extends EntityMagicConstruct { this.setSize(6, 0.2f); } - public EntityLightningPulse(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); - this.setSize(6, 0.2f); - } - - /** - * Return whether this entity should be rendered as on fire. - */ + @Override public boolean canRenderOnFire(){ return false; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java index 0c2bb112..62dcea76 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java @@ -16,26 +16,13 @@ import net.minecraft.world.World; public class EntityLightningSigil extends EntityMagicConstruct { - public EntityLightningSigil(World par1World){ - super(par1World); + public EntityLightningSigil(World world){ + super(world); this.height = 0.2f; this.width = 2.0f; } - public EntityLightningSigil(World par1World, double x, double y, double z, EntityLivingBase caster, - float damageMultiplier){ - super(par1World, x, y, z, caster, -1, damageMultiplier); - this.height = 0.2f; - this.width = 2.0f; - } - - // Overrides the original to stop the entity moving when it intersects stuff. The default arrow does this to allow - // it to stick in blocks. - public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9){ - this.setPosition(par1, par3, par5); - this.setRotation(par7, par8); - } - + @Override public void onUpdate(){ super.onUpdate(); @@ -56,10 +43,8 @@ public class EntityLightningSigil extends EntityMagicConstruct { double velZ = target.motionZ; // Only works if target is actually damaged to account for hurtResistantTime - if(target.attackEntityFrom( - getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.SHOCK) - : DamageSource.MAGIC, - 6)){ + if(target.attackEntityFrom(getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, getCaster(), + DamageType.SHOCK) : DamageSource.MAGIC, 6)){ // Removes knockback target.motionX = velX; @@ -125,13 +110,9 @@ public class EntityLightningSigil extends EntityMagicConstruct { } @Override - protected void entityInit(){ + protected void entityInit(){} - } - - /** - * Return whether this entity should be rendered as on fire. - */ + @Override public boolean canRenderOnFire(){ return false; } diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityMagicConstruct.java b/src/main/java/electroblob/wizardry/entity/construct/EntityMagicConstruct.java index 36e93b46..8951c743 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityMagicConstruct.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityMagicConstruct.java @@ -10,6 +10,8 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; /** * This class is for all inanimate magical constructs which are not projectiles. It was made from scratch to provide a @@ -42,30 +44,18 @@ public abstract class EntityMagicConstruct extends Entity implements IEntityAddi /** The damage multiplier for this construct, determined by the wand with which it was cast. */ public float damageMultiplier = 1.0f; - public EntityMagicConstruct(World par1World){ - super(par1World); - this.height = 1.0f; - this.width = 1.0f; - this.noClip = true; - } - - public EntityMagicConstruct(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, - float damageMultiplier){ + public EntityMagicConstruct(World world){ super(world); this.height = 1.0f; this.width = 1.0f; - this.setPosition(x, y, z); - this.caster = new WeakReference(caster); this.noClip = true; - this.lifetime = lifetime; - this.damageMultiplier = damageMultiplier; } // Overrides the original to stop the entity moving when it intersects stuff. The default arrow does this to allow // it to stick in blocks. @Override - public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, - int posRotationIncrements, boolean teleport){ + @SideOnly(Side.CLIENT) + public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport){ this.setPosition(x, y, z); this.setRotation(yaw, pitch); } @@ -136,6 +126,10 @@ public abstract class EntityMagicConstruct extends Entity implements IEntityAddi public EntityLivingBase getCaster(){ return caster == null ? null : caster.get(); } + + public void setCaster(EntityLivingBase caster){ + this.caster = new WeakReference(caster); + } /** * Shorthand for {@link WizardryUtilities#isValidTarget(Entity, Entity)}, with the owner of this construct as the diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java b/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java index 908ac574..f53c2b54 100644 --- a/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java +++ b/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java @@ -34,17 +34,13 @@ public class EntityTornado extends EntityMagicConstruct { this.width = 5.0f; this.isImmuneToFire = false; } - - public EntityTornado(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, double velX, - double velZ, float damageMultiplier){ - super(world, x, y, z, caster, lifetime, damageMultiplier); - this.height = 8.0f; - this.width = 5.0f; + + public void setHorizontalVelocity(double velX, double velZ){ this.velX = velX; this.velZ = velZ; - this.isImmuneToFire = false; } + @Override public void onUpdate(){ super.onUpdate(); diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityBlazeMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityBlazeMinion.java index c609375c..2bab8ebd 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityBlazeMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityBlazeMinion.java @@ -56,29 +56,12 @@ public class EntityBlazeMinion extends EntityBlaze implements ISummonedCreature this.casterUUID = uuid; } - /** - * Default shell constructor, only used by client. Lifetime defaults arbitrarily to 600, but this doesn't matter - * because the client side entity immediately gets the lifetime value copied over to it by this class anyway. When - * extending this class, you must override this constructor or Minecraft won't like it, but there's no need to do - * anything inside it other than call super(). - */ + /** Creates a new blaze minion in the given world. */ public EntityBlazeMinion(World world){ super(world); this.experienceValue = 0; } - /** - * Set lifetime to -1 to allow this creature to last forever. This constructor should be overridden when extending - * this class (be sure to call super()) so that AI and other things can be added. - */ - public EntityBlazeMinion(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world); - this.setPosition(x, y, z); - this.casterReference = new WeakReference(caster); - this.experienceValue = 0; - this.lifetime = lifetime; - } - // EntityBlaze overrides // This particular override is pretty standard: let the superclass handle basic AI like swimming, but replace its @@ -154,31 +137,13 @@ public class EntityBlazeMinion extends EntityBlaze implements ISummonedCreature // Recommended overrides - @Override - protected int getExperiencePoints(EntityPlayer player){ - return 0; - } - - @Override - protected boolean canDropLoot(){ - return false; - } - - @Override - protected Item getDropItem(){ - return null; - } - - @Override - protected ResourceLocation getLootTable(){ - return null; - } - + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } // This vanilla method has nothing to do with the custom despawn() method. - @Override - protected boolean canDespawn(){ - return false; - } + @Override protected boolean canDespawn(){ return false; } @Override public boolean canAttackClass(Class entityType){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java b/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java index 5ec8aa58..38665937 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java @@ -18,12 +18,14 @@ import net.minecraft.world.World; public class EntityDecoy extends EntitySummonedCreature { + /** Creates a new decoy in the given world. */ public EntityDecoy(World world){ super(world); } - - public EntityDecoy(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world, x, y, z, caster, lifetime); + + @Override + public void setCaster(EntityLivingBase caster){ + super.setCaster(caster); this.setAlwaysRenderNameTag(caster instanceof EntityPlayer); } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java index ad9119b3..44dc43b0 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java @@ -49,6 +49,7 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; @@ -178,6 +179,17 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity public Spell getContinuousSpell(){ return this.continuousSpell; } + + @Override + public int getAimingError(EnumDifficulty difficulty){ + // Being more intelligent than skeletons, wizards are a little more accurate. + switch(difficulty){ + case EASY: return 7; + case NORMAL: return 4; + case HARD: return 1; + default: return 7; // Peaceful counts as easy + } + } @Override public void onLivingUpdate(){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java b/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java index ebc34fdb..93e25d2b 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java @@ -37,61 +37,20 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature private UUID casterUUID; // Setter + getter implementations - @Override - public int getLifetime(){ - return lifetime; - } + @Override public int getLifetime(){ return lifetime; } + @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } + @Override public WeakReference getCasterReference(){ return casterReference; } + @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } + @Override public UUID getCasterUUID(){ return casterUUID; } + @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } - @Override - public void setLifetime(int lifetime){ - this.lifetime = lifetime; - } - - @Override - public WeakReference getCasterReference(){ - return casterReference; - } - - @Override - public void setCasterReference(WeakReference reference){ - casterReference = reference; - } - - @Override - public UUID getCasterUUID(){ - return casterUUID; - } - - @Override - public void setCasterUUID(UUID uuid){ - this.casterUUID = uuid; - } - - /** - * Default shell constructor, only used by client. Lifetime defaults arbitrarily to 600, but this doesn't matter - * because the client side entity immediately gets the lifetime value copied over to it by this class anyway. When - * extending this class, you must override this constructor or Minecraft won't like it, but there's no need to do - * anything inside it other than call super(). - */ + /** Creates a new ice giant in the given world. */ public EntityIceGiant(World world){ super(world); this.setSize(1.4F, 2.9F); this.experienceValue = 0; } - /** - * Set lifetime to -1 to allow this creature to last forever. This constructor should be overridden when extending - * this class (be sure to call super()) so that AI and other things can be added. - */ - public EntityIceGiant(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world); - this.setSize(1.4F, 2.9F); - this.setPosition(x, y, z); - this.casterReference = new WeakReference(caster); - this.experienceValue = 0; - this.lifetime = lifetime; - } - @Override protected void initEntityAI(){ this.getNavigator().getNodeProcessor().setCanSwim(false); @@ -108,19 +67,9 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature // EntityIronGolem overrides - @Override - protected void updateAITasks(){ - } // Disables home-checking - - @Override - public Village getVillage(){ - return null; - } - - @Override - public int getHoldRoseTick(){ - return 0; - } + @Override protected void updateAITasks(){} // Disables home-checking + @Override public Village getVillage(){ return null; } + @Override public int getHoldRoseTick(){ return 0; } // Implementations @@ -137,20 +86,21 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature @Override public void onSpawn(){ + this.spawnParticleEffect(); } @Override public void onDespawn(){ this.playSound(WizardrySounds.SPELL_FREEZE, 1.0f, 1.0f); + this.spawnParticleEffect(); + } + + private void spawnParticleEffect(){ if(this.world.isRemote){ for(int i = 0; i < 30; i++){ float brightness = 0.5f + (rand.nextFloat() / 2); - ParticleBuilder.create(Type.SPARKLE) - .pos(this.posX - 1 + rand.nextDouble() * 2, this.posY + rand.nextDouble() * 3, this.posZ - 1 + rand.nextDouble() * 2) - .vel(0, -0.02, 0) - .lifetime(12 + rand.nextInt(8)) - .colour(brightness, brightness + 0.1f, 1.0f) - .spawn(world); + ParticleBuilder.create(Type.SPARKLE, this).vel(0, -0.02, 0).lifetime(12 + rand.nextInt(8)) + .colour(brightness, brightness + 0.1f, 1.0f).spawn(world); } } } @@ -161,9 +111,7 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature super.onLivingUpdate(); if(this.world.isRemote){ - ParticleBuilder.create(Type.SNOW) - .pos(this.posX - 1 + rand.nextDouble() * 2, this.posY + rand.nextDouble() * 3, this.posZ - 1 + rand.nextDouble() * 2) - .spawn(world); + ParticleBuilder.create(Type.SNOW, this).spawn(world); } } @@ -207,36 +155,13 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature // Recommended overrides - @Override - protected int getExperiencePoints(EntityPlayer player){ - return 0; - } - - @Override - protected boolean canDropLoot(){ - return false; - } - - @Override - protected Item getDropItem(){ - return null; - } - - @Override - protected ResourceLocation getLootTable(){ - return null; - } - - @Override - public boolean canPickUpLoot(){ - return false; - } - - // This vanilla method has nothing to do with the custom onDespawn() method. - @Override - protected boolean canDespawn(){ - return false; - } + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. + @Override protected boolean canDespawn(){ return false; } @Override public boolean canAttackClass(Class entityType){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java index e9ad7d34..3f2c07e1 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java @@ -25,12 +25,9 @@ public class EntityIceWraith extends EntityBlazeMinion { /** The version from EntityLivingBase is only used in onLivingUpdate, so it can safely be copied. */ private int jumpTicks; + /** Creates a new ice wraith in the given world. */ public EntityIceWraith(World world){ super(world); - } - - public EntityIceWraith(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world, x, y, z, caster, lifetime); this.isImmuneToFire = false; } @@ -204,32 +201,24 @@ public class EntityIceWraith extends EntityBlazeMinion { this.setMutexBits(3); } - /** - * Returns whether the EntityAIBase should begin execution. - */ + @Override public boolean shouldExecute(){ EntityLivingBase entitylivingbase = this.blaze.getAttackTarget(); return entitylivingbase != null && entitylivingbase.isEntityAlive(); } - /** - * Execute a one shot task or start executing a continuous task - */ + @Override public void startExecuting(){ this.attackStep = 0; } - /** - * Resets the task - */ + @Override public void resetTask(){ // This might be called setOnFire, but what it really controls is whether the wraith is in attack mode. this.blaze.setOnFire(false); } - /** - * Updates the task - */ + @Override public void updateTask(){ --this.attackTime; EntityLivingBase entitylivingbase = this.blaze.getAttackTarget(); diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java index 3c90a171..fb5364e8 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java @@ -21,10 +21,6 @@ public class EntityLightningWraith extends EntityBlazeMinion { public EntityLightningWraith(World world){ super(world); - } - - public EntityLightningWraith(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world, x, y, z, caster, lifetime); this.isImmuneToFire = false; } @@ -44,12 +40,8 @@ public class EntityLightningWraith extends EntityBlazeMinion { if(this.world.isRemote){ for(int i = 0; i < 15; i++){ float brightness = 0.3f + (rand.nextFloat() / 2); - ParticleBuilder.create(Type.SPARKLE) - .pos(this.posX - 0.5d + rand.nextDouble(), this.posY + this.height / 2 - 0.5d + rand.nextDouble(), this.posZ - 0.5d + rand.nextDouble()) - .vel(0, 0.05, 0) - .lifetime(20 + rand.nextInt(10)) - .colour(brightness, brightness + 0.2f, 1.0f) - .spawn(world); + ParticleBuilder.create(Type.SPARKLE, this).vel(0, 0.05, 0).lifetime(20 + rand.nextInt(10)) + .colour(brightness, brightness + 0.2f, 1.0f).spawn(world); } } } @@ -98,32 +90,24 @@ public class EntityLightningWraith extends EntityBlazeMinion { this.setMutexBits(3); } - /** - * Returns whether the EntityAIBase should begin execution. - */ + @Override public boolean shouldExecute(){ EntityLivingBase entitylivingbase = this.blaze.getAttackTarget(); return entitylivingbase != null && entitylivingbase.isEntityAlive(); } - /** - * Execute a one shot task or start executing a continuous task - */ + @Override public void startExecuting(){ this.attackStep = 0; } - /** - * Resets the task - */ + @Override public void resetTask(){ // This might be called setOnFire, but what it really controls is whether the wraith is in attack mode. this.blaze.setOnFire(false); } - /** - * Updates the task - */ + @Override public void updateTask(){ --this.attackTime; EntityLivingBase entitylivingbase = this.blaze.getAttackTarget(); @@ -154,8 +138,7 @@ public class EntityLightningWraith extends EntityBlazeMinion { if(this.attackStep > 1){ // Proof, if it were at all needed, of the elegance and versatility of the spell system. - Spells.arc.cast(this.blaze.world, this.blaze, EnumHand.MAIN_HAND, 0, entitylivingbase, - new SpellModifiers()); + Spells.arc.cast(this.blaze.world, this.blaze, EnumHand.MAIN_HAND, 0, entitylivingbase, new SpellModifiers()); // TODO: Decide if an event should be fired here. I'm guessing no. } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityMagicSlime.java b/src/main/java/electroblob/wizardry/entity/living/EntityMagicSlime.java index 3257701b..1c9da3ce 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityMagicSlime.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityMagicSlime.java @@ -31,35 +31,12 @@ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature { private UUID casterUUID; // Setter + getter implementations - @Override - public int getLifetime(){ - return lifetime; - } - - @Override - public void setLifetime(int lifetime){ - this.lifetime = lifetime; - } - - @Override - public WeakReference getCasterReference(){ - return casterReference; - } - - @Override - public void setCasterReference(WeakReference reference){ - casterReference = reference; - } - - @Override - public UUID getCasterUUID(){ - return casterUUID; - } - - @Override - public void setCasterUUID(UUID uuid){ - this.casterUUID = uuid; - } + @Override public int getLifetime(){ return lifetime; } + @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } + @Override public WeakReference getCasterReference(){ return casterReference; } + @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } + @Override public UUID getCasterUUID(){ return casterUUID; } + @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } public EntityMagicSlime(World world){ super(world); @@ -88,13 +65,8 @@ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature { // EntitySlime overrides - @Override - protected void initEntityAI(){ - } // Has no AI! - - @Override - protected void dealDamage(EntityLivingBase entity){ - } // Handles damage itself + @Override protected void initEntityAI(){} // Has no AI! + @Override protected void dealDamage(EntityLivingBase entity){} // Handles damage itself @Override public void setDead(){ @@ -197,35 +169,12 @@ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature { // Recommended overrides - @Override - protected int getExperiencePoints(EntityPlayer player){ - return 0; - } - - @Override - protected boolean canDropLoot(){ - return false; - } - - @Override - protected Item getDropItem(){ - return null; - } - - @Override - protected ResourceLocation getLootTable(){ - return null; - } - - @Override - public boolean canPickUpLoot(){ - return false; - } - - // This vanilla method has nothing to do with the custom onDespawn() method. - @Override - protected boolean canDespawn(){ - return false; - } + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. + @Override protected boolean canDespawn(){ return false; } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java b/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java index 54325cd5..73170416 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityPhoenix.java @@ -27,18 +27,15 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste private double AISpeed = 0.5; // Can attack for 7 seconds, then must cool down for 3. - private EntityAIAttackSpell spellAttackAI = new EntityAIAttackSpell(this, AISpeed, 15f, 60, 140); + private EntityAIAttackSpell spellAttackAI = new EntityAIAttackSpell<>(this, AISpeed, 15f, 60, 140); private Spell continuousSpell; private static final List attack = Collections.singletonList(Spells.flame_ray); + /** Creates a new phoenix in the given world. */ public EntityPhoenix(World world){ super(world); - } - - public EntityPhoenix(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world, x, y, z, caster, lifetime); this.isImmuneToFire = true; this.height = 2.0f; // For some reason this can't be in initEntityAI @@ -185,8 +182,7 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste } @Override - public void fall(float distance, float damageMultiplier){ - } // Immune to fall damage + public void fall(float distance, float damageMultiplier){} // Immune to fall damage @Override public boolean isBurning(){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java index 835fab80..b182af36 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java @@ -35,12 +35,9 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell private static final List attack = Collections.singletonList(Spells.darkness_orb); + /** Creates a new shadow wraith in the gievn world. */ public EntityShadowWraith(World world){ super(world); - } - - public EntityShadowWraith(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world, x, y, z, caster, lifetime); // For some reason this can't be in initEntityAI this.tasks.addTask(0, this.spellAttackAI); } @@ -128,13 +125,8 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell if(this.world.isRemote){ for(int i = 0; i < 15; i++){ float brightness = rand.nextFloat() * 0.4f; - ParticleBuilder.create(Type.SPARKLE) - .pos(this.posX - 0.5d + rand.nextDouble(), this.posY + this.height / 2 - 0.5d + rand.nextDouble(), - this.posZ - 0.5d + rand.nextDouble()) - .vel(0, 0.05, 0) - .lifetime(20 + rand.nextInt(10)) - .colour(brightness, 0.0f, brightness) - .spawn(world); + ParticleBuilder.create(Type.SPARKLE, this).vel(0, 0.05, 0).lifetime(20 + rand.nextInt(10)) + .colour(brightness, 0.0f, brightness).spawn(world); } } } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java index a1a79b4d..b2a2c8fa 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java @@ -30,59 +30,19 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone private UUID casterUUID; // Setter + getter implementations - @Override - public int getLifetime(){ - return lifetime; - } + @Override public int getLifetime(){ return lifetime; } + @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } + @Override public WeakReference getCasterReference(){ return casterReference; } + @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } + @Override public UUID getCasterUUID(){ return casterUUID; } + @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } - @Override - public void setLifetime(int lifetime){ - this.lifetime = lifetime; - } - - @Override - public WeakReference getCasterReference(){ - return casterReference; - } - - @Override - public void setCasterReference(WeakReference reference){ - casterReference = reference; - } - - @Override - public UUID getCasterUUID(){ - return casterUUID; - } - - @Override - public void setCasterUUID(UUID uuid){ - this.casterUUID = uuid; - } - - /** - * Default shell constructor, only used by client. Lifetime defaults arbitrarily to 600, but this doesn't matter - * because the client side entity immediately gets the lifetime value copied over to it by this class anyway. When - * extending this class, you must override this constructor or Minecraft won't like it, but there's no need to do - * anything inside it other than call super(). - */ + /** Creates a new silverfish minion in the given world. */ public EntitySilverfishMinion(World world){ super(world); this.experienceValue = 0; } - /** - * Set lifetime to -1 to allow this creature to last forever. This constructor should be overridden when extending - * this class (be sure to call super()) so that AI and other things can be added. - */ - public EntitySilverfishMinion(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world); - this.setPosition(x, y, z); - this.casterReference = new WeakReference(caster); - this.experienceValue = 0; - this.lifetime = lifetime; - } - // EntitySilverfish overrides @Override protected void initEntityAI(){ @@ -144,8 +104,10 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone int alliesToSummon = rand.nextInt(4) + 1; for(int i = 0; i < alliesToSummon; i++){ - EntitySilverfishMinion silverfish = new EntitySilverfishMinion(this.world, victim.posX, victim.posY, - victim.posZ, this.getCaster(), this.lifetime); + EntitySilverfishMinion silverfish = new EntitySilverfishMinion(this.world); + silverfish.setPosition(victim.posX, victim.posY, victim.posZ); + silverfish.setCaster(this.getCaster()); + silverfish.setLifetime(this.getLifetime()); this.world.spawnEntity(silverfish); } } @@ -177,36 +139,13 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone // Recommended overrides - @Override - protected int getExperiencePoints(EntityPlayer player){ - return 0; - } - - @Override - protected boolean canDropLoot(){ - return false; - } - - @Override - protected Item getDropItem(){ - return null; - } - - @Override - protected ResourceLocation getLootTable(){ - return null; - } - - @Override - public boolean canPickUpLoot(){ - return false; - } - + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } // This vanilla method has nothing to do with the custom despawn() method. - @Override - protected boolean canDespawn(){ - return false; - } + @Override protected boolean canDespawn(){ return false; } @Override public boolean canAttackClass(Class entityType){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySkeletonMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntitySkeletonMinion.java index 167d34f1..c1801d76 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySkeletonMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySkeletonMinion.java @@ -7,6 +7,7 @@ import java.util.UUID; import javax.annotation.Nullable; import electroblob.wizardry.Wizardry; +import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IEntityLivingData; import net.minecraft.entity.SharedMonsterAttributes; @@ -19,6 +20,7 @@ import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.Item; +import net.minecraft.item.ItemBow; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumHand; @@ -37,59 +39,19 @@ public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCre private UUID casterUUID; // Setter + getter implementations - @Override - public int getLifetime(){ - return lifetime; - } + @Override public int getLifetime(){ return lifetime; } + @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } + @Override public WeakReference getCasterReference(){ return casterReference; } + @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } + @Override public UUID getCasterUUID(){ return casterUUID; } + @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } - @Override - public void setLifetime(int lifetime){ - this.lifetime = lifetime; - } - - @Override - public WeakReference getCasterReference(){ - return casterReference; - } - - @Override - public void setCasterReference(WeakReference reference){ - casterReference = reference; - } - - @Override - public UUID getCasterUUID(){ - return casterUUID; - } - - @Override - public void setCasterUUID(UUID uuid){ - this.casterUUID = uuid; - } - - /** - * Default shell constructor, only used by client. Lifetime defaults arbitrarily to 600, but this doesn't matter - * because the client side entity immediately gets the lifetime value copied over to it by this class anyway. When - * extending this class, you must override this constructor or Minecraft won't like it, but there's no need to do - * anything inside it other than call super(). - */ + /** Creates a new skeleton minion in the given world. */ public EntitySkeletonMinion(World world){ super(world); this.experienceValue = 0; } - /** - * Set lifetime to -1 to allow this creature to last forever. This constructor should be overridden when extending - * this class (be sure to call super()) so that AI and other things can be added. - */ - public EntitySkeletonMinion(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world); - this.setPosition(x, y, z); - this.casterReference = new WeakReference(caster); - this.experienceValue = 0; - this.lifetime = lifetime; - } - // EntitySkeleton overrides // This particular override is pretty standard: let the superclass handle basic AI like swimming, but replace its @@ -120,7 +82,7 @@ public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCre this.setLeftHanded(true); }else{ this.setLeftHanded(false); - } + } // Halloween pumpkin heads! Why not? if(this.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty()){ @@ -194,40 +156,18 @@ public class EntitySkeletonMinion extends EntitySkeleton implements ISummonedCre // Recommended overrides - @Override - protected int getExperiencePoints(EntityPlayer player){ - return 0; - } - - @Override - protected boolean canDropLoot(){ - return false; - } - - @Override - protected Item getDropItem(){ - return null; - } - - @Override - protected ResourceLocation getLootTable(){ - return null; - } - - @Override - public boolean canPickUpLoot(){ - return false; - } - + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } // This vanilla method has nothing to do with the custom despawn() method. - @Override - protected boolean canDespawn(){ - return false; - } + @Override protected boolean canDespawn(){ return false; } @Override public boolean canAttackClass(Class entityType){ - return true; + // Returns true unless the given entity type is a flying entity and this skeleton does not have a bow. + return !EntityFlying.class.isAssignableFrom(entityType) || this.getHeldItemMainhand().getItem() instanceof ItemBow; } @Override diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java index 4a979455..23b7824b 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java @@ -35,59 +35,19 @@ public class EntitySpiderMinion extends EntityCaveSpider implements ISummonedCre private UUID casterUUID; // Setter + getter implementations - @Override - public int getLifetime(){ - return lifetime; - } + @Override public int getLifetime(){ return lifetime; } + @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } + @Override public WeakReference getCasterReference(){ return casterReference; } + @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } + @Override public UUID getCasterUUID(){ return casterUUID; } + @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } - @Override - public void setLifetime(int lifetime){ - this.lifetime = lifetime; - } - - @Override - public WeakReference getCasterReference(){ - return casterReference; - } - - @Override - public void setCasterReference(WeakReference reference){ - casterReference = reference; - } - - @Override - public UUID getCasterUUID(){ - return casterUUID; - } - - @Override - public void setCasterUUID(UUID uuid){ - this.casterUUID = uuid; - } - - /** - * Default shell constructor, only used by client. Lifetime defaults arbitrarily to 600, but this doesn't matter - * because the client side entity immediately gets the lifetime value copied over to it by this class anyway. When - * extending this class, you must override this constructor or Minecraft won't like it, but there's no need to do - * anything inside it other than call super(). - */ + /** Creates a new spider minion in the given world. */ public EntitySpiderMinion(World world){ super(world); this.experienceValue = 0; } - /** - * Set lifetime to -1 to allow this creature to last forever. This constructor should be overridden when extending - * this class (be sure to call super()) so that AI and other things can be added. - */ - public EntitySpiderMinion(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world); - this.setPosition(x, y, z); - this.casterReference = new WeakReference(caster); - this.experienceValue = 0; - this.lifetime = lifetime; - } - // EntitySpider overrides // This particular override is pretty standard: let the superclass handle basic AI like swimming, but replace its @@ -198,36 +158,13 @@ public class EntitySpiderMinion extends EntityCaveSpider implements ISummonedCre // Recommended overrides - @Override - protected int getExperiencePoints(EntityPlayer player){ - return 0; - } - - @Override - protected boolean canDropLoot(){ - return false; - } - - @Override - protected Item getDropItem(){ - return null; - } - - @Override - protected ResourceLocation getLootTable(){ - return null; - } - - @Override - public boolean canPickUpLoot(){ - return false; - } - + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } // This vanilla method has nothing to do with the custom despawn() method. - @Override - protected boolean canDespawn(){ - return false; - } + @Override protected boolean canDespawn(){ return false; } @Override public boolean canAttackClass(Class entityType){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java b/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java index f86586c5..602a6941 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java @@ -33,13 +33,11 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe private static final List attack = Collections.singletonList(Spells.lightning_disc); + /** Creates a new storm elemental in the given world. */ public EntityStormElemental(World world){ super(world); - } - - public EntityStormElemental(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world, x, y, z, caster, lifetime); // For some reason this can't be in initEntityAI + // TESTME: May need to be inside a !world.isRemote check. this.tasks.addTask(0, this.spellAttackAI); } diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySummonedCreature.java b/src/main/java/electroblob/wizardry/entity/living/EntitySummonedCreature.java index 64d2e46b..2ef50929 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntitySummonedCreature.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntitySummonedCreature.java @@ -64,29 +64,12 @@ public abstract class EntitySummonedCreature extends EntityCreature implements I this.casterUUID = uuid; } - /** - * Default shell constructor, only used by client. Lifetime defaults arbitrarily to 600, but this doesn't matter - * because the client side entity immediately gets the lifetime value copied over to it by this class anyway. When - * extending this class, you must override this constructor or Minecraft won't like it, but there's no need to do - * anything inside it other than call super(). - */ + /** Creates a new summoned creature in the given world. */ public EntitySummonedCreature(World world){ super(world); this.experienceValue = 0; } - /** - * Set lifetime to -1 to allow this creature to last forever. This constructor should be overridden when extending - * this class (be sure to call super()) so that AI and other things can be added. - */ - public EntitySummonedCreature(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world); - this.setPosition(x, y, z); - this.casterReference = new WeakReference(caster); - this.experienceValue = 0; - this.lifetime = lifetime; - } - // Implementations @Override @@ -134,36 +117,13 @@ public abstract class EntitySummonedCreature extends EntityCreature implements I // Recommended overrides - @Override - protected int getExperiencePoints(EntityPlayer player){ - return 0; - } - - @Override - protected boolean canDropLoot(){ - return false; - } - - @Override - protected Item getDropItem(){ - return null; - } - - @Override - protected ResourceLocation getLootTable(){ - return null; - } - - @Override - public boolean canPickUpLoot(){ - return false; - } - - // This vanilla method has nothing to do with the custom onDespawn() method. - @Override - protected boolean canDespawn(){ - return false; - } + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } + // This vanilla method has nothing to do with the custom despawn() method. + @Override protected boolean canDespawn(){ return false; } @Override public boolean canAttackClass(Class entityType){ @@ -171,7 +131,6 @@ public abstract class EntitySummonedCreature extends EntityCreature implements I return !EntityFlying.class.isAssignableFrom(entityType) || this.hasRangedAttack(); } - // TODO: Backport the following two methods to 1.7.10. @Override public ITextComponent getDisplayName(){ if(getCaster() != null){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityWitherSkeletonMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityWitherSkeletonMinion.java index dee3d51e..8606978b 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityWitherSkeletonMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityWitherSkeletonMinion.java @@ -7,6 +7,7 @@ import java.util.UUID; import javax.annotation.Nullable; import electroblob.wizardry.Wizardry; +import net.minecraft.entity.EntityFlying; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IEntityLivingData; import net.minecraft.entity.SharedMonsterAttributes; @@ -20,6 +21,7 @@ import net.minecraft.init.Items; import net.minecraft.init.MobEffects; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.Item; +import net.minecraft.item.ItemBow; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; @@ -39,59 +41,19 @@ public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements private UUID casterUUID; // Setter + getter implementations - @Override - public int getLifetime(){ - return lifetime; - } + @Override public int getLifetime(){ return lifetime; } + @Override public void setLifetime(int lifetime){ this.lifetime = lifetime; } + @Override public WeakReference getCasterReference(){ return casterReference; } + @Override public void setCasterReference(WeakReference reference){ casterReference = reference; } + @Override public UUID getCasterUUID(){ return casterUUID; } + @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } - @Override - public void setLifetime(int lifetime){ - this.lifetime = lifetime; - } - - @Override - public WeakReference getCasterReference(){ - return casterReference; - } - - @Override - public void setCasterReference(WeakReference reference){ - casterReference = reference; - } - - @Override - public UUID getCasterUUID(){ - return casterUUID; - } - - @Override - public void setCasterUUID(UUID uuid){ - this.casterUUID = uuid; - } - - /** - * Default shell constructor, only used by client. Lifetime defaults arbitrarily to 600, but this doesn't matter - * because the client side entity immediately gets the lifetime value copied over to it by this class anyway. When - * extending this class, you must override this constructor or Minecraft won't like it, but there's no need to do - * anything inside it other than call super(). - */ + /** Creates a new wither skeleton minion in the given world. */ public EntityWitherSkeletonMinion(World world){ super(world); this.experienceValue = 0; } - /** - * Set lifetime to -1 to allow this creature to last forever. This constructor should be overridden when extending - * this class (be sure to call super()) so that AI and other things can be added. - */ - public EntityWitherSkeletonMinion(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world); - this.setPosition(x, y, z); - this.casterReference = new WeakReference(caster); - this.experienceValue = 0; - this.lifetime = lifetime; - } - // EntitySkeleton overrides // This particular override is pretty standard: let the superclass handle basic AI like swimming, but replace its @@ -105,13 +67,13 @@ public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements 0, false, true, this.getTargetSelector())); } - // Shouldn't have randomised armour, but does still need a bow! + // Shouldn't have randomised armour, but does still need a sword! @Override protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty){ - this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); + this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.STONE_SWORD)); + this.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); } - // Where the skeleton minion is summoned does not affect its type. @Override public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata){ // Can't call super, so the code from the next level up (EntityLiving) had to be copied as well. @@ -123,6 +85,9 @@ public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements }else{ this.setLeftHanded(false); } + + this.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.STONE_SWORD)); + this.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); // Halloween pumpkin heads! Why not? if(this.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty()){ @@ -201,40 +166,18 @@ public class EntityWitherSkeletonMinion extends EntityWitherSkeleton implements // Recommended overrides - @Override - protected int getExperiencePoints(EntityPlayer player){ - return 0; - } - - @Override - protected boolean canDropLoot(){ - return false; - } - - @Override - protected Item getDropItem(){ - return null; - } - - @Override - protected ResourceLocation getLootTable(){ - return null; - } - - @Override - public boolean canPickUpLoot(){ - return false; - } - + @Override protected int getExperiencePoints(EntityPlayer player){ return 0; } + @Override protected boolean canDropLoot(){ return false; } + @Override protected Item getDropItem(){ return null; } + @Override protected ResourceLocation getLootTable(){ return null; } + @Override public boolean canPickUpLoot(){ return false; } // This vanilla method has nothing to do with the custom despawn() method. - @Override - protected boolean canDespawn(){ - return false; - } + @Override protected boolean canDespawn(){ return false; } @Override public boolean canAttackClass(Class entityType){ - return true; + // Returns true unless the given entity type is a flying entity and this skeleton does not have a bow. + return !EntityFlying.class.isAssignableFrom(entityType) || this.getHeldItemMainhand().getItem() instanceof ItemBow; } @Override diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java index ccdec06d..339e6f41 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java @@ -23,10 +23,10 @@ import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WandHelper; import electroblob.wizardry.util.WildcardTradeList; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import io.netty.buffer.ByteBuf; import net.minecraft.entity.Entity; @@ -70,6 +70,7 @@ import net.minecraft.util.text.ITextComponent; import net.minecraft.village.MerchantRecipe; import net.minecraft.village.MerchantRecipeList; import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.common.util.FakePlayer; @@ -216,6 +217,17 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp public Spell getContinuousSpell(){ return this.continuousSpell; } + + @Override + public int getAimingError(EnumDifficulty difficulty){ + // Being more intelligent than skeletons, wizards are a little more accurate. + switch(difficulty){ + case EASY: return 7; + case NORMAL: return 4; + case HARD: return 1; + default: return 7; // Peaceful counts as easy + } + } @Override public void setCustomer(EntityPlayer player){ diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityZombieMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntityZombieMinion.java index 7a7b10d8..3613d614 100644 --- a/src/main/java/electroblob/wizardry/entity/living/EntityZombieMinion.java +++ b/src/main/java/electroblob/wizardry/entity/living/EntityZombieMinion.java @@ -36,29 +36,12 @@ public class EntityZombieMinion extends EntityZombie implements ISummonedCreatur @Override public UUID getCasterUUID(){ return casterUUID; } @Override public void setCasterUUID(UUID uuid){ this.casterUUID = uuid; } - /** - * Default shell constructor, only used by client. Lifetime defaults arbitrarily to 600, but this doesn't matter - * because the client side entity immediately gets the lifetime value copied over to it by this class anyway. When - * extending this class, you must override this constructor or Minecraft won't like it, but there's no need to do - * anything inside it other than call super(). - */ + /** Creates a new zombie minion in the given world. */ public EntityZombieMinion(World world){ super(world); this.experienceValue = 0; } - /** - * Set lifetime to -1 to allow this creature to last forever. This constructor should be overridden when extending - * this class (be sure to call super()) so that AI and other things can be added. - */ - public EntityZombieMinion(World world, double x, double y, double z, EntityLivingBase caster, int lifetime){ - super(world); - this.setPosition(x, y, z); - this.casterReference = new WeakReference(caster); - this.experienceValue = 0; - this.lifetime = lifetime; - } - // EntityZombie overrides (EntityZombie is a long class so there are lots of these) @Override diff --git a/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java b/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java index a43c0153..86eda769 100644 --- a/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java +++ b/src/main/java/electroblob/wizardry/entity/living/ISpellCaster.java @@ -7,6 +7,8 @@ import javax.annotation.Nonnull; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.world.EnumDifficulty; /** * Interface for entities that can cast spells. Mainly intended for use by wizard-type entities, but can be implemented @@ -65,4 +67,13 @@ public interface ISpellCaster { * to NBT is up to you. If the implementing class does not deal with continuous spells, leave this method blank. */ public void setContinuousSpell(Spell spell); + + /** + * Returns the aiming arror for the given difficulty, used in projectile spells. Defaults to the values used by + * skeletons, which are: Easy - 10, Normal - 6, Hard - 2, Peaceful - 10 (rarely used). + */ + // This is what default methods are actually intended for! + public default int getAimingError(EnumDifficulty difficulty) { + return WizardryUtilities.getDefaultAimingError(difficulty); + } } diff --git a/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java b/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java index 4219b6bf..1b6a0069 100644 --- a/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java +++ b/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java @@ -130,6 +130,14 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData { default EntityLivingBase getCaster(){ return getCasterReference() == null ? null : getCasterReference().get(); } + + /** + * Sets the EntityLivingBase that summoned this creature. This is the correct method to use to set the owner of + * this summoned creature. + */ + default void setCaster(@Nullable EntityLivingBase caster){ + setCasterReference(new WeakReference(caster)); + } // Miscellaneous diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityBomb.java index 11cb8562..6f4af21a 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityBomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityBomb.java @@ -1,7 +1,6 @@ package electroblob.wizardry.entity.projectile; import io.netty.buffer.ByteBuf; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; @@ -21,29 +20,16 @@ public abstract class EntityBomb extends EntityMagicProjectile { super(world); } - public EntityBomb(World world, EntityLivingBase thrower){ - super(world, thrower); - } - - public EntityBomb(World world, EntityLivingBase thrower, float damageMultiplier, float blastMultiplier){ - super(world, thrower, damageMultiplier); - this.blastMultiplier = blastMultiplier; - } - - public EntityBomb(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); - } - @Override public void writeSpawnData(ByteBuf buffer){ - super.writeSpawnData(buffer); buffer.writeFloat(blastMultiplier); + super.writeSpawnData(buffer); } @Override public void readSpawnData(ByteBuf buffer){ - super.readSpawnData(buffer); blastMultiplier = buffer.readFloat(); + super.readSpawnData(buffer); } @Override diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java index 6fb6f290..43e81c5e 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java @@ -14,30 +14,14 @@ import net.minecraft.world.World; public class EntityDarknessOrb extends EntityMagicProjectile { - public EntityDarknessOrb(World par1World){ - super(par1World); - } - - public EntityDarknessOrb(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntityDarknessOrb(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier); - } - - public EntityDarknessOrb(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); + public EntityDarknessOrb(World world){ + super(world); } @Override - protected float getSpeed(){ - return 0.5F; - } - - @Override - protected void onImpact(RayTraceResult RayTraceResult){ - Entity target = RayTraceResult.entityHit; + protected void onImpact(RayTraceResult rayTrace){ + + Entity target = rayTrace.entityHit; if(target != null && !MagicDamage.isEntityImmune(DamageType.WITHER, target)){ float damage = 8 * damageMultiplier; @@ -79,10 +63,8 @@ public class EntityDarknessOrb extends EntityMagicProjectile { this.motionZ /= 0.99; } - /** - * Gets the amount of gravity to apply to the thrown entity with each tick. - */ - protected float getGravityVelocity(){ - return 0.0F; + @Override + public boolean hasNoGravity(){ + return true; } } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java index 7208a8f0..02eafdb6 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java @@ -1,9 +1,7 @@ package electroblob.wizardry.entity.projectile; -import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.MobEffects; import net.minecraft.init.SoundEvents; @@ -11,36 +9,17 @@ import net.minecraft.potion.PotionEffect; import net.minecraft.world.World; public class EntityDart extends EntityMagicArrow { - /** Basic shell constructor. Should only be used by the client. */ + + /** Creates a new dart in the given world. */ public EntityDart(World world){ super(world); } - /** - * Creates a projectile at position xyz in world, with no motion. Do not create a projectile with this constructor - * and then call setVelocity() as that method is, bizarrely, client-side only. - */ - public EntityDart(World world, double x, double y, double z){ - super(world, x, y, z); - } + @Override public double getDamage(){ return 4.0d; } - /** - * Creates a projectile at the position of the caster, pointing at the given target. The trajectory seems to be - * altered slightly by a random amount determined by the last parameter. For reference, skeletons set this to 10 on - * easy, 6 on normal and 2 on hard difficulty. - */ - public EntityDart(World world, EntityLivingBase caster, Entity target, float speed, float aimingError, - float damageMultiplier){ - super(world, caster, target, speed, aimingError, damageMultiplier); - } + @Override public boolean doGravity(){ return true; } - /** - * Creates a projectile pointing in the direction the caster is looking, with the given speed. USE THIS CONSTRUCTOR - * FOR NORMAL SPELLS. - */ - public EntityDart(World world, EntityLivingBase caster, float speed, float damageMultiplier){ - super(world, caster, speed, damageMultiplier); - } + @Override public boolean doDeceleration(){ return true; } @Override public void onEntityHit(EntityLivingBase entityHit){ @@ -70,28 +49,6 @@ public class EntityDart extends EntityMagicArrow { } @Override - public double getDamage(){ - return 4.0d; - } - - @Override - public DamageType getDamageType(){ - return DamageType.MAGIC; - } - - @Override - public boolean doGravity(){ - return true; - } - - @Override - public boolean doDeceleration(){ - return true; - } - - @Override - protected void entityInit(){ - - } + protected void entityInit(){} } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebolt.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebolt.java index 268a15c2..d0bfcf28 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebolt.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebolt.java @@ -3,27 +3,15 @@ package electroblob.wizardry.entity.projectile; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; public class EntityFirebolt extends EntityMagicProjectile { - public EntityFirebolt(World par1World){ - super(par1World); - } - - public EntityFirebolt(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntityFirebolt(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier); - } - - public EntityFirebolt(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); + + public EntityFirebolt(World world){ + super(world); } @Override @@ -72,17 +60,11 @@ public class EntityFirebolt extends EntityMagicProjectile { } } - /** - * Gets the amount of gravity to apply to the thrown entity with each tick. - */ @Override - protected float getGravityVelocity(){ - return 0.0F; + public boolean hasNoGravity(){ + return true; } - /** - * Return whether this entity should be rendered as on fire. - */ @Override public boolean canRenderOnFire(){ return false; diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java index b181ab2b..d6e207c5 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java @@ -16,27 +16,14 @@ import net.minecraft.world.World; public class EntityFirebomb extends EntityBomb { - public EntityFirebomb(World par1World){ - super(par1World); - } - - public EntityFirebomb(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntityFirebomb(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier, - float blastMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier, blastMultiplier); - } - - public EntityFirebomb(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); + public EntityFirebomb(World world){ + super(world); } @Override - protected void onImpact(RayTraceResult par1RayTraceResult){ + protected void onImpact(RayTraceResult rayTrace){ - Entity entityHit = par1RayTraceResult.entityHit; + Entity entityHit = rayTrace.entityHit; if(entityHit != null){ // This is if the firebomb gets a direct hit diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java index c1b6f1be..89738294 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java @@ -1,44 +1,17 @@ package electroblob.wizardry.entity.projectile; import electroblob.wizardry.util.MagicDamage.DamageType; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; import net.minecraft.world.World; public class EntityForceArrow extends EntityMagicArrow { - /** Basic shell constructor. Should only be used by the client. */ + /** Creates a new force arrow in the given world. */ public EntityForceArrow(World world){ super(world); } - /** - * Creates a projectile at position xyz in world, with no motion. Do not create a projectile with this constructor - * and then call setVelocity() as that method is, bizarrely, client-side only. - */ - public EntityForceArrow(World world, double x, double y, double z){ - super(world, x, y, z); - } - - /** - * Creates a projectile at the position of the caster, pointing at the given target. The trajectory seems to be - * altered slightly by a random amount determined by the last parameter. For reference, skeletons set this to 10 on - * easy, 6 on normal and 2 on hard difficulty. - */ - public EntityForceArrow(World world, EntityLivingBase caster, Entity target, float speed, float aimingError, - float damageMultiplier){ - super(world, caster, target, speed, aimingError, damageMultiplier); - } - - /** - * Creates a projectile pointing in the direction the caster is looking, with the given speed. USE THIS CONSTRUCTOR - * FOR NORMAL SPELLS. - */ - public EntityForceArrow(World world, EntityLivingBase caster, float speed, float damageMultiplier){ - super(world, caster, speed, damageMultiplier); - } - @Override public void onEntityHit(EntityLivingBase entityHit){ this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.0F, 1.0F); diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java index d7edcb12..5c554aa2 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java @@ -9,40 +9,17 @@ import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -public class EntityForceOrb extends EntityMagicProjectile { - - /** - * The entity blast multiplier. In this particular case, it doesn't need syncing, so this class doesn't extend - * EntityBlastProjectile. - */ - public float blastMultiplier; - - public EntityForceOrb(World par1World){ - super(par1World); +public class EntityForceOrb extends EntityBomb { + + public EntityForceOrb(World world){ + super(world); } - public EntityForceOrb(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntityForceOrb(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier, - float blastMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier); - this.blastMultiplier = blastMultiplier; - } - - public EntityForceOrb(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); - } - - /** - * Called when this EntityThrowable hits a block or entity. - */ + @Override protected void onImpact(RayTraceResult par1RayTraceResult){ if(par1RayTraceResult.entityHit != null){ @@ -96,16 +73,5 @@ public class EntityForceOrb extends EntityMagicProjectile { this.setDead(); } } - - @Override - public void readEntityFromNBT(NBTTagCompound nbttagcompound){ - super.readEntityFromNBT(nbttagcompound); - blastMultiplier = nbttagcompound.getFloat("blastMultiplier"); - } - - @Override - public void writeEntityToNBT(NBTTagCompound nbttagcompound){ - super.writeEntityToNBT(nbttagcompound); - nbttagcompound.setFloat("blastMultiplier", blastMultiplier); - } + } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java index a6768266..25282d28 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java @@ -21,26 +21,11 @@ import net.minecraft.world.World; public class EntityIceCharge extends EntityBomb { - public EntityIceCharge(World par1World){ - super(par1World); + public EntityIceCharge(World world){ + super(world); } - public EntityIceCharge(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntityIceCharge(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier, - float blastMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier, blastMultiplier); - } - - public EntityIceCharge(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); - } - - /** - * Called when this EntityThrowable hits a block or entity. - */ + @Override protected void onImpact(RayTraceResult par1RayTraceResult){ Entity entityHit = par1RayTraceResult.entityHit; @@ -62,7 +47,7 @@ public class EntityIceCharge extends EntityBomb { for(int i = 0; i < 30 * blastMultiplier; i++){ ParticleBuilder.create(Type.ICE, rand, this.posX, this.posY, this.posZ, 2 * blastMultiplier, false) - .lifetime(35).spawn(world); + .lifetime(35).gravity(true).spawn(world); float brightness = 0.4f + rand.nextFloat() * 0.5f; ParticleBuilder.create(Type.DARK_MAGIC, rand, this.posX, this.posY, this.posZ, 2 * blastMultiplier, false) @@ -118,11 +103,12 @@ public class EntityIceCharge extends EntityBomb { double dx = rand.nextDouble() - 0.5; double dy = rand.nextDouble() - 0.5; double dz = rand.nextDouble() - 0.5; - EntityIceShard iceshard = new EntityIceShard(world, this.posX + dx, this.posY + dy, this.posZ + dz); + EntityIceShard iceshard = new EntityIceShard(world); + iceshard.setPosition(this.posX + dx, this.posY + dy, this.posZ + dz); iceshard.motionX = dx; iceshard.motionY = dy; iceshard.motionZ = dz; - iceshard.setShootingEntity(this.getThrower()); + iceshard.setCaster(this.getThrower()); iceshard.damageMultiplier = this.damageMultiplier; world.spawnEntity(iceshard); } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java index f8cb6ee3..2a6094c0 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java @@ -5,7 +5,6 @@ import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; @@ -13,40 +12,23 @@ import net.minecraft.world.World; public class EntityIceLance extends EntityMagicArrow { - /** Basic shell constructor. Should only be used by the client. */ + /** Creates a new ice lance in the given world. */ public EntityIceLance(World world){ super(world); this.setKnockbackStrength(1); } - /** - * Creates a projectile at position xyz in world, with no motion. Do not create a projectile with this constructor - * and then call setVelocity() as that method is, bizarrely, client-side only. - */ - public EntityIceLance(World world, double x, double y, double z){ - super(world, x, y, z); - this.setKnockbackStrength(1); - } + @Override public double getDamage(){ return 10.0d; } - /** - * Creates a projectile at the position of the caster, pointing at the given target. The trajectory seems to be - * altered slightly by a random amount determined by the last parameter. For reference, skeletons set this to 10 on - * easy, 6 on normal and 2 on hard difficulty. - */ - public EntityIceLance(World world, EntityLivingBase caster, Entity target, float speed, float aimingError, - float damageMultiplier){ - super(world, caster, target, speed, aimingError, damageMultiplier); - this.setKnockbackStrength(1); - } + @Override public DamageType getDamageType(){ return DamageType.FROST; } - /** - * Creates a projectile pointing in the direction the caster is looking, with the given speed. USE THIS CONSTRUCTOR - * FOR NORMAL SPELLS. - */ - public EntityIceLance(World world, EntityLivingBase caster, float speed, float damageMultiplier){ - super(world, caster, speed, damageMultiplier); - this.setKnockbackStrength(1); - } + @Override public boolean doGravity(){ return true; } + + @Override public boolean doDeceleration(){ return true; } + + @Override public boolean doOverpenetration(){ return true; } + + @Override public boolean canRenderOnFire(){ return false; } @Override public void onEntityHit(EntityLivingBase entityHit){ @@ -58,11 +40,6 @@ public class EntityIceLance extends EntityMagicArrow { this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); } - @Override - public void tickInAir(){ - - } - @Override public void onBlockHit(){ // Adds a particle effect when the ice lance hits a block. @@ -78,43 +55,6 @@ public class EntityIceLance extends EntityMagicArrow { } @Override - public void tickInGround(){ - this.setDead(); - } - - @Override - public double getDamage(){ - return 10.0d; - } - - @Override - public DamageType getDamageType(){ - return DamageType.FROST; - } - - @Override - public boolean doGravity(){ - return true; - } - - @Override - public boolean doDeceleration(){ - return true; - } - - @Override - public boolean doOverpenetration(){ - return true; - } - - @Override - protected void entityInit(){ - - } - - @Override - public boolean canRenderOnFire(){ - return false; - } + protected void entityInit(){} } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java index 19e72bb6..483d1c55 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java @@ -5,7 +5,6 @@ import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; import net.minecraft.potion.PotionEffect; @@ -13,36 +12,20 @@ import net.minecraft.world.World; public class EntityIceShard extends EntityMagicArrow { - /** Basic shell constructor. Should only be used by the client. */ + /** Creates a new ice shard in the given world. */ public EntityIceShard(World world){ super(world); } - /** - * Creates a projectile at position xyz in world, with no motion. Do not create a projectile with this constructor - * and then call setVelocity() as that method is, bizarrely, client-side only. - */ - public EntityIceShard(World world, double x, double y, double z){ - super(world, x, y, z); - } + @Override public double getDamage(){ return 6.0d; } - /** - * Creates a projectile at the position of the caster, pointing at the given target. The trajectory seems to be - * altered slightly by a random amount determined by the last parameter. For reference, skeletons set this to 10 on - * easy, 6 on normal and 2 on hard difficulty. - */ - public EntityIceShard(World world, EntityLivingBase caster, Entity target, float speed, float aimingError, - float damageMultiplier){ - super(world, caster, target, speed, aimingError, damageMultiplier); - } + @Override public DamageType getDamageType(){ return DamageType.FROST; } - /** - * Creates a projectile pointing in the direction the caster is looking, with the given speed. USE THIS CONSTRUCTOR - * FOR NORMAL SPELLS. - */ - public EntityIceShard(World world, EntityLivingBase caster, float speed, float damageMultiplier){ - super(world, caster, speed, damageMultiplier); - } + @Override public boolean doGravity(){ return true; } + + @Override public boolean doDeceleration(){ return true; } + + @Override public boolean canRenderOnFire(){ return false; } @Override public void onEntityHit(EntityLivingBase entityHit){ @@ -54,18 +37,13 @@ public class EntityIceShard extends EntityMagicArrow { this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F)); } - @Override - public void tickInAir(){ - - } - @Override public void onBlockHit(){ // Adds a particle effect when the ice shard hits a block. if(this.world.isRemote){ for(int j = 0; j < 10; j++){ ParticleBuilder.create(Type.ICE, this.rand, this.posX, this.posY, this.posZ, 0.5, true) - .lifetime(20 + rand.nextInt(10)).spawn(world); + .lifetime(20 + rand.nextInt(10)).gravity(true).spawn(world); } } // Parameters for sound: sound event name, volume, pitch. @@ -74,33 +52,6 @@ public class EntityIceShard extends EntityMagicArrow { } @Override - public double getDamage(){ - return 6.0d; - } - - @Override - public DamageType getDamageType(){ - return DamageType.FROST; - } - - @Override - public boolean doGravity(){ - return true; - } - - @Override - public boolean doDeceleration(){ - return true; - } - - @Override - protected void entityInit(){ - - } - - @Override - public boolean canRenderOnFire(){ - return false; - } + protected void entityInit(){} } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java index 4da5d2d0..8e5d38dc 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java @@ -4,42 +4,23 @@ import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.world.World; public class EntityLightningArrow extends EntityMagicArrow { - /** Basic shell constructor. Should only be used by the client. */ + /** Creates a new lightning arrow in the given world. */ public EntityLightningArrow(World world){ super(world); } - /** - * Creates a projectile at position xyz in world, with no motion. Do not create a projectile with this constructor - * and then call setVelocity() as that method is, bizarrely, client-side only. - */ - public EntityLightningArrow(World world, double x, double y, double z){ - super(world, x, y, z); - } + @Override public double getDamage(){ return 7.0d; } - /** - * Creates a projectile at the position of the caster, pointing at the given target. The trajectory seems to be - * altered slightly by a random amount determined by the last parameter. For reference, skeletons set this to 10 on - * easy, 6 on normal and 2 on hard difficulty. - */ - public EntityLightningArrow(World world, EntityLivingBase caster, Entity target, float speed, float aimingError, - float damageMultiplier){ - super(world, caster, target, speed, aimingError, damageMultiplier); - } + @Override public DamageType getDamageType(){ return DamageType.SHOCK; } - /** - * Creates a projectile pointing in the direction the caster is looking, with the given speed. USE THIS CONSTRUCTOR - * FOR NORMAL SPELLS. - */ - public EntityLightningArrow(World world, EntityLivingBase caster, float speed, float damageMultiplier){ - super(world, caster, speed, damageMultiplier); - } + @Override public boolean doGravity(){ return false; } + + @Override public boolean doDeceleration(){ return false; } @Override public void onEntityHit(EntityLivingBase entityHit){ @@ -67,28 +48,6 @@ public class EntityLightningArrow extends EntityMagicArrow { } @Override - public double getDamage(){ - return 7.0d; - } - - @Override - public DamageType getDamageType(){ - return DamageType.SHOCK; - } - - @Override - public boolean doGravity(){ - return false; - } - - @Override - public boolean doDeceleration(){ - return false; - } - - @Override - protected void entityInit(){ - - } + protected void entityInit(){} } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningDisc.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningDisc.java index 988fd2ba..afa24ff8 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningDisc.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningDisc.java @@ -15,29 +15,12 @@ import net.minecraft.world.World; public class EntityLightningDisc extends EntityMagicProjectile { - public EntityLightningDisc(World par1World){ - super(par1World); - } - - public EntityLightningDisc(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntityLightningDisc(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier); - } - - public EntityLightningDisc(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); + public EntityLightningDisc(World world){ + super(world); this.width = 2.0f; this.height = 0.5f; } - @Override - protected float getSpeed(){ - return 1.2f; - } - @Override protected void onImpact(RayTraceResult result){ @@ -65,7 +48,7 @@ public class EntityLightningDisc extends EntityMagicProjectile { for(int i = 0; i < 8; i++){ // TODO: Why are the x and z parameters different? ParticleBuilder.create(Type.SPARK).pos(this.posX + rand.nextFloat() * 2 - 1, - this.posY, this.posZ + rand.nextFloat() - 0.5).spawn(world); + this.posY, this.posZ + rand.nextFloat() * 2 - 1).spawn(world); } } @@ -105,8 +88,8 @@ public class EntityLightningDisc extends EntityMagicProjectile { } @Override - protected float getGravityVelocity(){ - return 0.0F; + public boolean hasNoGravity(){ + return true; } @Override diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java index cbcc6208..64091a91 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java @@ -59,7 +59,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE /** Seems to be some sort of timer for animating an arrow. */ public int arrowShake; /** The owner of this arrow. */ - private WeakReference shootingEntity; + private WeakReference caster; /** * The UUID of the caster. Note that this is only for loading purposes; during normal updates the actual entity * instance is stored (so that getEntityByUUID is not called constantly), so this will not always be synced (this is @@ -70,87 +70,74 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE int ticksInAir; /** The amount of knockback an arrow applies when it hits a mob. */ private int knockbackStrength; - /** - * The damage multiplier for the arrow. Normally this isn't set directly, since it can be done via the constructor. - * An exception is where other entities need to pass in their multipliers, e.g. ice charge. - */ + /** The damage multiplier for the projectile. */ public float damageMultiplier = 1.0f; - /** Basic shell constructor. Should only be used by the client. */ + /** Creates a new projectile in the given world. */ public EntityMagicArrow(World world){ super(world); this.setSize(0.5F, 0.5F); } - - /** - * Creates a projectile at position xyz in world, with no motion. Do not create a projectile with this constructor - * and then call setVelocity() as that method is, bizarrely, client-side only. - */ - public EntityMagicArrow(World world, double x, double y, double z){ - super(world); - this.setSize(0.5F, 0.5F); - this.setPosition(x, y, z); - // yOffset was set to 0 here, but that has been replaced by getYOffset(), which returns 0 in Entity anyway. - } - - /** - * Creates a projectile at the position of the caster, pointing at the given target. The trajectory seems to be - * altered slightly by a random amount determined by the aimingError parameter. For reference, skeletons set this to - * 10 on easy, 6 on normal and 2 on hard difficulty. - */ - public EntityMagicArrow(World world, EntityLivingBase caster, Entity target, float speed, float aimingError, - float damageMultiplier){ - super(world); - this.shootingEntity = new WeakReference(caster); - this.damageMultiplier = damageMultiplier; - - this.posY = caster.posY + (double)caster.getEyeHeight() - 0.10000000149011612D; - double d0 = target.posX - caster.posX; - double d1 = this.doGravity() ? target.getEntityBoundingBox().minY + (double)(target.height / 3.0F) - this.posY - : target.getEntityBoundingBox().minY + (double)(target.height / 2.0F) - this.posY; - double d2 = target.posZ - caster.posZ; - double d3 = (double)MathHelper.sqrt(d0 * d0 + d2 * d2); - - if(d3 >= 1.0E-7D){ - float f2 = (float)(Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F; - float f3 = (float)(-(Math.atan2(d1, d3) * 180.0D / Math.PI)); - double d4 = d0 / d3; - double d5 = d2 / d3; - this.setLocationAndAngles(caster.posX + d4, this.posY, caster.posZ + d5, f2, f3); - // yOffset was set to 0 here, but that has been replaced by getYOffset(), which returns 0 in Entity anyway. - - // f4 depends on the horizontal distance between the two entities and accounts for bullet drop, - // but of course if gravity is ignored this should be 0. - float bulletDropCompensation = this.doGravity() ? (float)d3 * 0.2F : 0; - this.shoot(d0, d1 + (double)bulletDropCompensation, d2, speed, aimingError); - } - } - - /** - * Creates a projectile pointing in the direction the caster is looking, with the given speed. Use this - * constructor for normal, player-cast spells. - */ - public EntityMagicArrow(World world, EntityLivingBase caster, float speed, float damageMultiplier){ - super(world); - this.shootingEntity = new WeakReference(caster); - this.damageMultiplier = damageMultiplier; - - this.setSize(0.5F, 0.5F); + + // Initialiser methods + + /** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and + * aims it in the direction they are looking with the given speed. */ + public void aim(EntityLivingBase caster, float speed){ + + this.setCaster(caster); + this.setLocationAndAngles(caster.posX, caster.posY + (double)caster.getEyeHeight(), caster.posZ, caster.rotationYaw, caster.rotationPitch); + this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F); this.posY -= 0.10000000149011612D; this.posZ -= (double)(MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F); + this.setPosition(this.posX, this.posY, this.posZ); + // yOffset was set to 0 here, but that has been replaced by getYOffset(), which returns 0 in Entity anyway. this.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI)); + this.motionY = (double)(-MathHelper.sin(this.rotationPitch / 180.0F * (float)Math.PI)); this.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI)); - this.motionY = (double)(-MathHelper.sin(this.rotationPitch / 180.0F * (float)Math.PI)); + this.shoot(this.motionX, this.motionY, this.motionZ, speed * 1.5F, 1.0F); } + /** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and + * aims it at the given target with the given speed. The trajectory will be altered slightly by a random amount + * determined by the aimingError parameter. For reference, skeletons set this to 10 on easy, 6 on normal and 2 on hard + * difficulty. */ + public void aim(EntityLivingBase caster, Entity target, float speed, float aimingError){ + + this.setCaster(caster); + + this.posY = caster.posY + (double)caster.getEyeHeight() - 0.1d; + double dx = target.posX - caster.posX; + double dy = this.doGravity() ? target.getEntityBoundingBox().minY + (double)(target.height / 3.0f) - this.posY + : target.getEntityBoundingBox().minY + (double)(target.height / 2.0f) - this.posY; + double dz = target.posZ - caster.posZ; + double horizontalDistance = (double)MathHelper.sqrt(dx * dx + dz * dz); + + if(horizontalDistance >= 1.0E-7D){ + float yaw = (float)(Math.atan2(dz, dx) * 180.0d / Math.PI) - 90.0f; + float pitch = (float)(-(Math.atan2(dy, horizontalDistance) * 180.0d / Math.PI)); + double dxNormalised = dx / horizontalDistance; + double dzNormalised = dz / horizontalDistance; + this.setLocationAndAngles(caster.posX + dxNormalised, this.posY, caster.posZ + dzNormalised, yaw, pitch); + // yOffset was set to 0 here, but that has been replaced by getYOffset(), which returns 0 in Entity anyway. + + // Depends on the horizontal distance between the two entities and accounts for bullet drop, + // but of course if gravity is ignored this should be 0 since there is no bullet drop. + float bulletDropCompensation = this.doGravity() ? (float)horizontalDistance * 0.2f : 0; + this.shoot(dx, dy + (double)bulletDropCompensation, dz, speed, aimingError); + } + } + + // Property getters (to be overridden by subclasses) + /** Subclasses must override this to set their own base damage. */ public abstract double getDamage(); @@ -180,86 +167,52 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE return false; } + // Setters and getters + + /** Sets the amount of knockback the projectile applies when it hits a mob. */ + public void setKnockbackStrength(int knockback){ + this.knockbackStrength = knockback; + } + /** - * Similar to setArrowHeading, it's point the throwable entity to a x, y, z direction. + * Returns the EntityLivingBase that created this construct, or null if it no longer exists. Cases where the entity + * may no longer exist are: entity died or was deleted, mob despawned, player logged out, entity teleported to + * another dimension, or this construct simply had no caster in the first place. */ - @Override - public void shoot(double x, double y, double z, float speed, float randomness){ - float f2 = MathHelper.sqrt(x * x + y * y + z * z); - x /= (double)f2; - y /= (double)f2; - z /= (double)f2; - x += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D - * (double)randomness; - y += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D - * (double)randomness; - z += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D - * (double)randomness; - x *= (double)speed; - y *= (double)speed; - z *= (double)speed; - this.motionX = x; - this.motionY = y; - this.motionZ = z; - float f3 = MathHelper.sqrt(x * x + z * z); - this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(x, z) * 180.0D / Math.PI); - this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(y, (double)f3) * 180.0D / Math.PI); - this.ticksInGround = 0; + public EntityLivingBase getCaster(){ + return caster == null ? null : caster.get(); } - // There was an override for setPositionAndRotationDirect here, but it was exactly the same as the superclass - // method (in Entity), so it was removed since it was redundant. - - /** - * Sets the velocity to the args. Args: x, y, z. THIS IS CLIENT SIDE ONLY! DO NOT USE IN COMMON OR SERVER CODE! - */ - @Override - @SideOnly(Side.CLIENT) - public void setVelocity(double p_70016_1_, double p_70016_3_, double p_70016_5_){ - this.motionX = p_70016_1_; - this.motionY = p_70016_3_; - this.motionZ = p_70016_5_; - - if(this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F){ - float f = MathHelper.sqrt(p_70016_1_ * p_70016_1_ + p_70016_5_ * p_70016_5_); - this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(p_70016_1_, p_70016_5_) * 180.0D / Math.PI); - this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(p_70016_3_, (double)f) * 180.0D / Math.PI); - this.prevRotationPitch = this.rotationPitch; - this.prevRotationYaw = this.rotationYaw; - this.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch); - this.ticksInGround = 0; - } + public void setCaster(EntityLivingBase entity){ + caster = new WeakReference(entity); } + + // Methods triggered during the update cycle - /** - * Called each tick when the projectile is in a block. Defaults to setDead(), but can be overridden to change the - * behaviour. - */ - public void tickInGround(){ + /** Called each tick when the projectile is in a block. Defaults to setDead(), but can be overridden to change the + * behaviour. */ + protected void tickInGround(){ this.setDead(); } /** Called each tick when the projectile is in the air. Override to add particles and such like. */ - public void tickInAir(){ - } + protected void tickInAir(){} /** Called when the projectile hits an entity. Override to add potion effects and such like. */ - public void onEntityHit(EntityLivingBase entityHit){ - } + protected void onEntityHit(EntityLivingBase entityHit){} /** Called when the projectile hits a block. Override to add sound effects and such like. */ - public void onBlockHit(){ - } + protected void onBlockHit(){} @Override public void onUpdate(){ super.onUpdate(); - if(this.getShootingEntity() == null && this.casterUUID != null){ + if(this.getCaster() == null && this.casterUUID != null){ Entity entity = WizardryUtilities.getEntityByUUID(world, casterUUID); if(entity instanceof EntityLivingBase){ - this.shootingEntity = new WeakReference((EntityLivingBase)entity); + this.caster = new WeakReference((EntityLivingBase)entity); } } @@ -320,7 +273,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE for(i = 0; i < list.size(); ++i){ Entity entity1 = (Entity)list.get(i); - if(entity1.canBeCollidedWith() && (entity1 != this.getShootingEntity() || this.ticksInAir >= 5)){ + if(entity1.canBeCollidedWith() && (entity1 != this.getCaster() || this.ticksInAir >= 5)){ f1 = 0.3F; AxisAlignedBB axisalignedbb1 = entity1.getEntityBoundingBox().grow((double)f1, (double)f1, (double)f1); @@ -347,8 +300,8 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE && raytraceresult.entityHit instanceof EntityPlayer){ EntityPlayer entityplayer = (EntityPlayer)raytraceresult.entityHit; - if(entityplayer.capabilities.disableDamage || this.getShootingEntity() instanceof EntityPlayer - && !((EntityPlayer)this.getShootingEntity()).canAttackPlayer(entityplayer)){ + if(entityplayer.capabilities.disableDamage || this.getCaster() instanceof EntityPlayer + && !((EntityPlayer)this.getCaster()).canAttackPlayer(entityplayer)){ raytraceresult = null; } } @@ -359,11 +312,11 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE if(raytraceresult.entityHit != null){ DamageSource damagesource = null; - if(this.getShootingEntity() == null){ + if(this.getCaster() == null){ damagesource = DamageSource.causeThrownDamage(this, this); }else{ damagesource = MagicDamage.causeIndirectMagicDamage(this, - (EntityLivingBase)this.getShootingEntity(), this.getDamageType()).setProjectile(); + (EntityLivingBase)this.getCaster(), this.getDamageType()).setProjectile(); } if(raytraceresult.entityHit.attackEntityFrom(damagesource, @@ -386,17 +339,17 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE } // Thorns enchantment - if(this.getShootingEntity() != null - && this.getShootingEntity() instanceof EntityLivingBase){ - EnchantmentHelper.applyThornEnchantments(entityHit, this.getShootingEntity()); - EnchantmentHelper.applyArthropodEnchantments((EntityLivingBase)this.getShootingEntity(), + if(this.getCaster() != null + && this.getCaster() instanceof EntityLivingBase){ + EnchantmentHelper.applyThornEnchantments(entityHit, this.getCaster()); + EnchantmentHelper.applyArthropodEnchantments((EntityLivingBase)this.getCaster(), entityHit); } - if(this.getShootingEntity() != null && raytraceresult.entityHit != this.getShootingEntity() + if(this.getCaster() != null && raytraceresult.entityHit != this.getCaster() && raytraceresult.entityHit instanceof EntityPlayer - && this.getShootingEntity() instanceof EntityPlayerMP){ - ((EntityPlayerMP)this.getShootingEntity()).connection + && this.getCaster() instanceof EntityPlayerMP){ + ((EntityPlayerMP)this.getCaster()).connection .sendPacket(new SPacketChangeGameState(6, 0.0F)); } } @@ -497,6 +450,51 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE } } + @Override + public void shoot(double x, double y, double z, float speed, float randomness){ + float f2 = MathHelper.sqrt(x * x + y * y + z * z); + x /= (double)f2; + y /= (double)f2; + z /= (double)f2; + x += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)randomness; + y += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)randomness; + z += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)randomness; + x *= (double)speed; + y *= (double)speed; + z *= (double)speed; + this.motionX = x; + this.motionY = y; + this.motionZ = z; + float f3 = MathHelper.sqrt(x * x + z * z); + this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(x, z) * 180.0D / Math.PI); + this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(y, (double)f3) * 180.0D / Math.PI); + this.ticksInGround = 0; + } + + // There was an override for setPositionAndRotationDirect here, but it was exactly the same as the superclass + // method (in Entity), so it was removed since it was redundant. + + /** Sets the velocity to the args. Args: x, y, z. THIS IS CLIENT SIDE ONLY! DO NOT USE IN COMMON OR SERVER CODE! */ + @Override + @SideOnly(Side.CLIENT) + public void setVelocity(double p_70016_1_, double p_70016_3_, double p_70016_5_){ + this.motionX = p_70016_1_; + this.motionY = p_70016_3_; + this.motionZ = p_70016_5_; + + if(this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F){ + float f = MathHelper.sqrt(p_70016_1_ * p_70016_1_ + p_70016_5_ * p_70016_5_); + this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(p_70016_1_, p_70016_5_) * 180.0D / Math.PI); + this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(p_70016_3_, (double)f) * 180.0D / Math.PI); + this.prevRotationPitch = this.rotationPitch; + this.prevRotationYaw = this.rotationYaw; + this.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch); + this.ticksInGround = 0; + } + } + + // Data reading and writing + @Override public void writeEntityToNBT(NBTTagCompound tag){ tag.setShort("xTile", (short)this.blockX); @@ -512,8 +510,8 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE tag.setByte("shake", (byte)this.arrowShake); tag.setByte("inGround", (byte)(this.inGround ? 1 : 0)); tag.setFloat("damageMultiplier", this.damageMultiplier); - if(this.getShootingEntity() != null){ - tag.setUniqueId("casterUUID", this.getShootingEntity().getUniqueID()); + if(this.getCaster() != null){ + tag.setUniqueId("casterUUID", this.getCaster().getUniqueID()); } } @@ -531,58 +529,35 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE this.damageMultiplier = tag.getFloat("damageMultiplier"); casterUUID = tag.getUniqueId("casterUUID"); } + + @Override + public void writeSpawnData(ByteBuf buffer){ + if(this.getCaster() != null) buffer.writeInt(this.getCaster().getEntityId()); + } - /** - * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to - * prevent them from trampling crops - */ + @Override + public void readSpawnData(ByteBuf buffer){ + if(buffer.isReadable()) this.caster = new WeakReference( + (EntityLivingBase)this.world.getEntityByID(buffer.readInt())); + } + + // Miscellaneous overrides + + @Override protected boolean canTriggerWalking(){ return false; } + + @Override + public boolean canBeAttackedWithItem(){ + return false; + } @SideOnly(Side.CLIENT) public float getShadowSize(){ return 0.0F; } - /** - * Sets the amount of knockback the arrow applies when it hits a mob. - */ - public void setKnockbackStrength(int p_70240_1_){ - this.knockbackStrength = p_70240_1_; - } - - /** - * If returns false, the item will not inflict any damage against entities. - */ - public boolean canAttackWithItem(){ - return false; - } - - public void writeSpawnData(ByteBuf buffer){ - if(this.getShootingEntity() != null) buffer.writeInt(this.getShootingEntity().getEntityId()); - } - - public void readSpawnData(ByteBuf buffer){ - if(buffer.isReadable()) this.shootingEntity = new WeakReference( - (EntityLivingBase)this.world.getEntityByID(buffer.readInt())); - } - - /** - * Returns the EntityLivingBase that created this construct, or null if it no longer exists. Cases where the entity - * may no longer exist are: entity died or was deleted, mob despawned, player logged out, entity teleported to - * another dimension, or this construct simply had no caster in the first place. - */ - public EntityLivingBase getShootingEntity(){ - return shootingEntity == null ? null : shootingEntity.get(); - } - - public void setShootingEntity(EntityLivingBase entity){ - shootingEntity = new WeakReference(entity); - } - @Override - protected void entityInit() { - // TODO Auto-generated method stub - } + protected void entityInit(){} } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java index 76ddbda4..e2ccd32b 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java @@ -2,43 +2,22 @@ package electroblob.wizardry.entity.projectile; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; import net.minecraft.world.World; public class EntityMagicMissile extends EntityMagicArrow { - /** Basic shell constructor. Should only be used by the client. */ + /** Creates a new magic missile in the given world. */ public EntityMagicMissile(World world){ super(world); } - /** - * Creates a projectile at position xyz in world, with no motion. Do not create a projectile with this constructor - * and then call setVelocity() as that method is, bizarrely, client-side only. - */ - public EntityMagicMissile(World world, double x, double y, double z){ - super(world, x, y, z); - } + @Override public double getDamage(){ return 4.0d; } - /** - * Creates a projectile at the position of the caster, pointing at the given target. The trajectory seems to be - * altered slightly by a random amount determined by the last parameter. For reference, skeletons set this to 10 on - * easy, 6 on normal and 2 on hard difficulty. - */ - public EntityMagicMissile(World world, EntityLivingBase caster, Entity target, float speed, float aimingError, - float damageMultiplier){ - super(world, caster, target, speed, aimingError, damageMultiplier); - } + @Override public boolean doGravity(){ return false; } - /** - * Creates a projectile pointing in the direction the caster is looking, with the given speed. USE THIS CONSTRUCTOR - * FOR NORMAL SPELLS. - */ - public EntityMagicMissile(World world, EntityLivingBase caster, float speed, float damageMultiplier){ - super(world, caster, speed, damageMultiplier); - } + @Override public boolean doDeceleration(){ return false; } @Override public void onEntityHit(EntityLivingBase entityHit){ @@ -70,23 +49,6 @@ public class EntityMagicMissile extends EntityMagicArrow { } @Override - public double getDamage(){ - return 4.0d; - } - - @Override - public boolean doGravity(){ - return false; - } - - @Override - public boolean doDeceleration(){ - return false; - } - - @Override - protected void entityInit(){ - - } + protected void entityInit(){ } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicProjectile.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicProjectile.java index 3aad3978..0045eb34 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicProjectile.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicProjectile.java @@ -5,6 +5,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.projectile.EntityThrowable; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; @@ -15,10 +16,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; *

* This class purely handles saving of the damage multiplier; EntityThrowable is pretty well suited to my purposes as it * is. Range is done via the velocity when the constructor is called. Caster is already handled by - * EntityThrowable.getThrower(). - * - * Note that this class does not implement {@link IEntityAdditionalSpawnData}; subclasses that need to transfer extra - * data to the client should implement that interface themselves. See {@link EntityBomb} for an example. + * EntityThrowable.getThrower(), though due to a bug in vanilla it has to be synced by this class. * * @since Wizardry 1.0 * @author Electroblob @@ -28,70 +26,52 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I public float damageMultiplier = 1.0f; + /** Creates a new projectile in the given world. */ public EntityMagicProjectile(World world){ super(world); } - public EntityMagicProjectile(World world, EntityLivingBase thrower){ - super(world, thrower); + // Initialiser methods + + /** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and + * aims it in the direction they are looking with the given speed. */ + public void aim(EntityLivingBase caster, float speed){ + this.setPosition(caster.posX, caster.posY + (double)caster.getEyeHeight() - 0.1d, caster.posZ); + // This is the standard set of parameters for this method, used by snowballs and ender pearls amongst others. + this.shoot(caster, caster.rotationPitch, caster.rotationYaw, 0.0f, speed, 1.0f); + this.thrower = caster; + // Mojang's 'fix' for the projectile-hitting-thrower bug actually made the problem worse, hence the following line. + this.ignoreEntity = caster; } - public EntityMagicProjectile(World world, EntityLivingBase thrower, float damageMultiplier){ - super(world, thrower); - // This is the standard set of parameters for this method, used by snowballs and ender pearls amongst others. - this.shoot(thrower, thrower.rotationPitch, thrower.rotationYaw, 0.0f, this.getSpeed(), 1.0f); - this.damageMultiplier = damageMultiplier; + /** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and + * aims it at the given target with the given speed. The trajectory will be altered slightly by a random amount + * determined by the aimingError parameter. For reference, skeletons set this to 10 on easy, 6 on normal and 2 on hard + * difficulty. */ + public void aim(EntityLivingBase caster, Entity target, float speed, float aimingError){ + + this.thrower = caster; // Mojang's 'fix' for the projectile-hitting-thrower bug actually made the problem worse, hence the following line. this.ignoreEntity = thrower; - } - public EntityMagicProjectile(World world, double x, double y, double z){ - super(world, x, y, z); - } + this.posY = caster.posY + (double)caster.getEyeHeight() - 0.1d; + double dx = target.posX - caster.posX; + double dy = !this.hasNoGravity() ? target.getEntityBoundingBox().minY + (double)(target.height / 3.0f) - this.posY + : target.getEntityBoundingBox().minY + (double)(target.height / 2.0f) - this.posY; + double dz = target.posZ - caster.posZ; + double horizontalDistance = (double)MathHelper.sqrt(dx * dx + dz * dz); - /** This got removed at some point since 1.7.10, but I liked it so I thought I'd add it back in again. */ - protected float getSpeed(){ - return 1.5f; - } + if(horizontalDistance >= 1.0E-7D){ + + double dxNormalised = dx / horizontalDistance; + double dzNormalised = dz / horizontalDistance; + this.setPosition(caster.posX + dxNormalised, this.posY, caster.posZ + dzNormalised); - /** Sets this projectile's velocity as a normalised vector towards the target. */ - public void directTowards(Entity target, float velocity){ - - double dx = target.posX - this.posX; - double dy = target.getEntityBoundingBox().minY + (double)(target.height / 2.0F) - - (this.posY + (double)(this.height / 2.0F)); - double dz = target.posZ - this.posZ; - - this.motionX = dx / this.getDistance(target) * velocity; - this.motionY = dy / this.getDistance(target) * velocity; - this.motionZ = dz / this.getDistance(target) * velocity; - } - - @Override - public void onUpdate(){ - // This fixes the client-side projectile-hitting-thrower bug. Comparing with 1.10.2, this was caused by a change - // to the line EntityThrowable:215, where a thrower != null check was added. Since the thrower field is not synced, - // this fails and the ignoreEntity field is never set, causing the projectile to hit its thrower client-side. - // The 'proper' way to fix this is to use IEntityAdditionalSpawnData to sync the thrower field, but I don't really - // want to waste packets like that, so, since things worked just fine in 1.10.2 without the thrower != null check, - // it makes sense to just duplicate that block of code and remove the offending check. - // The only side-effect (and probably why the change was made to vanilla) is that if this entity is summoned - // inside a mob using commands, it wouldn't hit that mob. This is so minor that it's not worth sending a packet - // for, though it may become more noticeable if spells firing from blocks are added. - // TODO: Investigate whether this is still necessary in 1.12 -// if(this.world.isRemote){ -// -// List list = this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox().expand(this.motionX, this.motionY, this.motionZ).grow(1.0D)); -// -// for(Entity entity : list){ // Why does vanilla still not use a for-each loop? -// if(entity.canBeCollidedWith() && this.ticksExisted < 2 && this.ignoreEntity == null){ -// this.ignoreEntity = entity; -// } -// } -// // Pretty sure EntityThrowable handles the rest. -// } - - super.onUpdate(); + // Depends on the horizontal distance between the two entities and accounts for bullet drop, + // but of course if gravity is ignored this should be 0 since there is no bullet drop. + float bulletDropCompensation = !this.hasNoGravity() ? (float)horizontalDistance * 0.2f : 0; + this.shoot(dx, dy + (double)bulletDropCompensation, dz, speed, aimingError); + } } @Override @@ -107,15 +87,20 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I } @Override + // For now, we're only writing when the thrower exists, so subclasses MUST CALL SUPER LAST. + // TODO: Figure out whether there's a default value we can write that is never used as an entity id (0? -1? +/-MAX_VALUE?) public void writeSpawnData(ByteBuf data){ - data.writeInt(this.getThrower().getEntityId()); + if(this.getThrower() != null) data.writeInt(this.getThrower().getEntityId()); } @Override + // For now, we're only writing when the thrower exists, so subclasses MUST CALL SUPER LAST. public void readSpawnData(ByteBuf data){ - Entity entity = this.world.getEntityByID(data.readInt()); - if(entity instanceof EntityLivingBase) this.thrower = (EntityLivingBase)entity; - this.ignoreEntity = this.thrower; + if(data.isReadable()){ + Entity entity = this.world.getEntityByID(data.readInt()); + if(entity instanceof EntityLivingBase) this.thrower = (EntityLivingBase)entity; + this.ignoreEntity = this.thrower; + } } } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java index 94f739f8..c2ae3d54 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java @@ -18,26 +18,14 @@ import net.minecraft.world.World; public class EntityPoisonBomb extends EntityBomb { - public EntityPoisonBomb(World par1World){ - super(par1World); + public EntityPoisonBomb(World world){ + super(world); } - - public EntityPoisonBomb(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntityPoisonBomb(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier, - float blastMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier, blastMultiplier); - } - - public EntityPoisonBomb(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); - } - + @Override - protected void onImpact(RayTraceResult par1RayTraceResult){ - Entity entityHit = par1RayTraceResult.entityHit; + protected void onImpact(RayTraceResult rayTrace){ + + Entity entityHit = rayTrace.entityHit; if(entityHit != null){ // This is if the poison bomb gets a direct hit diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java index 5d6a432d..61dcf727 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java @@ -18,25 +18,12 @@ import net.minecraft.world.World; public class EntitySmokeBomb extends EntityBomb { - public EntitySmokeBomb(World par1World){ - super(par1World); - } - - public EntitySmokeBomb(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntitySmokeBomb(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier, - float blastMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier, blastMultiplier); - } - - public EntitySmokeBomb(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); + public EntitySmokeBomb(World world){ + super(world); } @Override - protected void onImpact(RayTraceResult par1RayTraceResult){ + protected void onImpact(RayTraceResult rayTrace){ // Particle effect if(world.isRemote){ diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntitySpark.java b/src/main/java/electroblob/wizardry/entity/projectile/EntitySpark.java index 8415bbee..f4aed2bc 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntitySpark.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntitySpark.java @@ -15,32 +15,14 @@ import net.minecraft.world.World; public class EntitySpark extends EntityMagicProjectile { - public EntitySpark(World par1World){ - super(par1World); + public EntitySpark(World world){ + super(world); } - public EntitySpark(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntitySpark(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier); - } - - public EntitySpark(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); - } - - /** This is the speed */ - protected float getSpeed(){ - return 0.5F; - } - - /** - * Called when this EntityThrowable hits a block or entity. - */ - protected void onImpact(RayTraceResult par1RayTraceResult){ - Entity entityHit = par1RayTraceResult.entityHit; + @Override + protected void onImpact(RayTraceResult rayTrace){ + + Entity entityHit = rayTrace.entityHit; if(entityHit != null){ @@ -98,17 +80,13 @@ public class EntitySpark extends EntityMagicProjectile { this.setDead(); } } - - /** - * Gets the amount of gravity to apply to the thrown entity with each tick. - */ - protected float getGravityVelocity(){ - return 0.0F; + + @Override + public boolean hasNoGravity(){ + return true; } - /** - * Return whether this entity should be rendered as on fire. - */ + @Override public boolean canRenderOnFire(){ return false; } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java index 29421463..6b8a92b1 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java @@ -7,42 +7,26 @@ import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; public class EntitySparkBomb extends EntityBomb { - public EntitySparkBomb(World par1World){ - super(par1World); + public EntitySparkBomb(World world){ + super(world); } - public EntitySparkBomb(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } - - public EntitySparkBomb(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier, - float blastMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier, blastMultiplier); - } - - public EntitySparkBomb(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); - } - - /** - * Called when this EntityThrowable hits a block or entity. - */ - protected void onImpact(RayTraceResult par1RayTraceResult){ + @Override + protected void onImpact(RayTraceResult rayTrace){ + this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST_FAR, 0.5f, 0.5f); - Entity entityHit = par1RayTraceResult.entityHit; + Entity entityHit = rayTrace.entityHit; if(entityHit != null){ // This is if the spark bomb gets a direct hit @@ -58,15 +42,7 @@ public class EntitySparkBomb extends EntityBomb { // Particle effect if(world.isRemote){ - for(int i = 0; i < 8; i++){ - double x = this.posX + rand.nextDouble() - 0.5; - double y = this.posY + this.height / 2 + rand.nextDouble() - 0.5; - double z = this.posZ + rand.nextDouble() - 0.5; - ParticleBuilder.create(Type.SPARK).pos(x, y, z).spawn(world); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, this.posX + rand.nextFloat() - 0.5, - this.posY + this.height / 2 + rand.nextFloat() - 0.5, this.posZ + rand.nextFloat() - 0.5, 0, 0, - 0); - } + ParticleBuilder.spawnShockParticles(world, posX, posY + height/2, posZ); } double seekerRange = 5.0d * blastMultiplier; @@ -102,15 +78,7 @@ public class EntitySparkBomb extends EntityBomb { }else{ // Particle effect - for(int j = 0; j < 8; j++){ - double x = target.posX + rand.nextFloat() - 0.5; - double y = target.getEntityBoundingBox().minY + target.height * rand.nextFloat(); - double z = target.posZ + rand.nextFloat() - 0.5; - ParticleBuilder.create(Type.SPARK).pos(x, y, z).spawn(world); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, target.posX + rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height * rand.nextFloat(), - target.posZ + rand.nextFloat() - 0.5, 0, 0, 0); - } + ParticleBuilder.spawnShockParticles(world, target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ); } } } diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityThunderbolt.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityThunderbolt.java index d38bcfce..7508b150 100644 --- a/src/main/java/electroblob/wizardry/entity/projectile/EntityThunderbolt.java +++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityThunderbolt.java @@ -5,7 +5,6 @@ import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.RayTraceResult; @@ -17,26 +16,11 @@ public class EntityThunderbolt extends EntityMagicProjectile { super(par1World); } - public EntityThunderbolt(World par1World, EntityLivingBase par2EntityLivingBase){ - super(par1World, par2EntityLivingBase); - } + @Override public boolean hasNoGravity(){ return true; } - public EntityThunderbolt(World par1World, EntityLivingBase par2EntityLivingBase, float damageMultiplier){ - super(par1World, par2EntityLivingBase, damageMultiplier); - } - - public EntityThunderbolt(World par1World, double par2, double par4, double par6){ - super(par1World, par2, par4, par6); - } - - /** This is the speed */ - protected float getSpeed(){ - return 2.5F; - } - - /** - * Called when this EntityThrowable hits a block or entity. - */ + @Override public boolean canRenderOnFire(){ return false; } + + @Override protected void onImpact(RayTraceResult par1RayTraceResult){ Entity entityHit = par1RayTraceResult.entityHit; @@ -63,6 +47,7 @@ public class EntityThunderbolt extends EntityMagicProjectile { this.setDead(); } + @Override public void onUpdate(){ super.onUpdate(); @@ -80,18 +65,5 @@ public class EntityThunderbolt extends EntityMagicProjectile { this.setDead(); } } - - /** - * Gets the amount of gravity to apply to the thrown entity with each tick. - */ - protected float getGravityVelocity(){ - return 0.0F; - } - - /** - * Return whether this entity should be rendered as on fire. - */ - public boolean canRenderOnFire(){ - return false; - } + } diff --git a/src/main/java/electroblob/wizardry/item/ItemFirebomb.java b/src/main/java/electroblob/wizardry/item/ItemFirebomb.java index 27cb433c..1a3a6097 100644 --- a/src/main/java/electroblob/wizardry/item/ItemFirebomb.java +++ b/src/main/java/electroblob/wizardry/item/ItemFirebomb.java @@ -30,9 +30,8 @@ public class ItemFirebomb extends Item { player.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); if(!world.isRemote){ - EntityFirebomb firebomb = new EntityFirebomb(world, player); - // This is the standard set of parameters for this method, used by snowballs and ender pearls. - firebomb.shoot(player, player.rotationPitch, player.rotationYaw, 0.0f, 1.5f, 1.0f); + EntityFirebomb firebomb = new EntityFirebomb(world); + firebomb.aim(player, 1.5f); world.spawnEntity(firebomb); } diff --git a/src/main/java/electroblob/wizardry/item/ItemPoisonBomb.java b/src/main/java/electroblob/wizardry/item/ItemPoisonBomb.java index 3613e0e7..76a9f12a 100644 --- a/src/main/java/electroblob/wizardry/item/ItemPoisonBomb.java +++ b/src/main/java/electroblob/wizardry/item/ItemPoisonBomb.java @@ -30,9 +30,8 @@ public class ItemPoisonBomb extends Item { player.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); if(!world.isRemote){ - EntityPoisonBomb poisonbomb = new EntityPoisonBomb(world, player); - // This is the standard set of parameters for this method, used by snowballs and ender pearls. - poisonbomb.shoot(player, player.rotationPitch, player.rotationYaw, 0.0f, 1.5f, 1.0f); + EntityPoisonBomb poisonbomb = new EntityPoisonBomb(world); + poisonbomb.aim(player, 1.5f); world.spawnEntity(poisonbomb); } diff --git a/src/main/java/electroblob/wizardry/item/ItemSmokeBomb.java b/src/main/java/electroblob/wizardry/item/ItemSmokeBomb.java index 023fe59f..880a84c4 100644 --- a/src/main/java/electroblob/wizardry/item/ItemSmokeBomb.java +++ b/src/main/java/electroblob/wizardry/item/ItemSmokeBomb.java @@ -30,9 +30,8 @@ public class ItemSmokeBomb extends Item { player.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F)); if(!world.isRemote){ - EntitySmokeBomb smokebomb = new EntitySmokeBomb(world, player); - // This is the standard set of parameters for this method, used by snowballs and ender pearls. - smokebomb.shoot(player, player.rotationPitch, player.rotationYaw, 0.0f, 1.5f, 1.0f); + EntitySmokeBomb smokebomb = new EntitySmokeBomb(world); + smokebomb.aim(player, 1.5f); world.spawnEntity(smokebomb); } diff --git a/src/main/java/electroblob/wizardry/item/ItemWand.java b/src/main/java/electroblob/wizardry/item/ItemWand.java index 0d146a49..522d819d 100644 --- a/src/main/java/electroblob/wizardry/item/ItemWand.java +++ b/src/main/java/electroblob/wizardry/item/ItemWand.java @@ -375,7 +375,7 @@ public class ItemWand extends Item { // normal mob on full 20 health, but wither 2 for the same duration only deals about 6 hearts of damage in // total. if(this.element == spell.element){ - modifiers.set(SpellModifiers.DAMAGE, 1.0f + (this.tier.level + 1) * Constants.DAMAGE_INCREASE_PER_TIER, + modifiers.set(SpellModifiers.POTENCY, 1.0f + (this.tier.level + 1) * Constants.DAMAGE_INCREASE_PER_TIER, true); } @@ -401,7 +401,7 @@ public class ItemWand extends Item { private boolean selectMinionTarget(EntityPlayer player, World world){ - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, player, 16); + RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, player, 16, false); if(rayTrace != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ diff --git a/src/main/java/electroblob/wizardry/item/ItemWizardArmour.java b/src/main/java/electroblob/wizardry/item/ItemWizardArmour.java index 63484b97..bb356ec8 100644 --- a/src/main/java/electroblob/wizardry/item/ItemWizardArmour.java +++ b/src/main/java/electroblob/wizardry/item/ItemWizardArmour.java @@ -7,11 +7,11 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockStatue; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.constants.Element; import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryTabs; -import electroblob.wizardry.spell.Petrify; import net.minecraft.client.model.ModelBiped; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.Entity; @@ -142,7 +142,7 @@ public class ItemWizardArmour extends ItemArmor { // fix, considering how long I spent trying to do this before - a bit of lateral thinking was all it took. // Do note however that a texture pack could override this. if(entity instanceof EntityLivingBase && ((EntityLivingBase)entity).isInvisible() - && !entity.getEntityData().getBoolean(Petrify.NBT_KEY)) + && !entity.getEntityData().getBoolean(BlockStatue.NBT_KEY)) return "ebwizardry:textures/armour/invisible_armour.png"; if(slot == EntityEquipmentSlot.LEGS) diff --git a/src/main/java/electroblob/wizardry/potion/PotionDecay.java b/src/main/java/electroblob/wizardry/potion/PotionDecay.java index c16cb8db..db22ee7e 100644 --- a/src/main/java/electroblob/wizardry/potion/PotionDecay.java +++ b/src/main/java/electroblob/wizardry/potion/PotionDecay.java @@ -68,8 +68,8 @@ public class PotionDecay extends Potion { EntityLivingBase target = event.getEntityLiving(); - if(target.isPotionActive(WizardryPotions.decay) && target.ticksExisted % Constants.DECAY_SPREAD_INTERVAL == 0 - && target.onGround){ + if(!target.world.isRemote && target.isPotionActive(WizardryPotions.decay) && target.onGround + && target.ticksExisted % Constants.DECAY_SPREAD_INTERVAL == 0){ List entities = target.world.getEntitiesWithinAABBExcludingEntity(target, target.getEntityBoundingBox()); @@ -80,7 +80,10 @@ public class PotionDecay extends Potion { // The victim spreading the decay is the 'caster' here, so that it can actually wear off, otherwise it // just gets infected with its own decay and the effect lasts forever. - target.world.spawnEntity(new EntityDecay(target.world, target.posX, target.posY, target.posZ, target)); + EntityDecay decay = new EntityDecay(target.world); + decay.setCaster(target); + decay.setPosition(target.posX, target.posY, target.posZ); + target.world.spawnEntity(decay); } } diff --git a/src/main/java/electroblob/wizardry/registry/Spells.java b/src/main/java/electroblob/wizardry/registry/Spells.java index b573df79..7fcc7da8 100644 --- a/src/main/java/electroblob/wizardry/registry/Spells.java +++ b/src/main/java/electroblob/wizardry/registry/Spells.java @@ -1,7 +1,49 @@ package electroblob.wizardry.registry; +import org.apache.commons.lang3.tuple.Triple; + import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.entity.construct.EntityBlackHole; +import electroblob.wizardry.entity.construct.EntityBlizzard; +import electroblob.wizardry.entity.construct.EntityFireRing; +import electroblob.wizardry.entity.construct.EntityFireSigil; +import electroblob.wizardry.entity.construct.EntityForcefield; +import electroblob.wizardry.entity.construct.EntityFrostSigil; +import electroblob.wizardry.entity.construct.EntityHealAura; +import electroblob.wizardry.entity.construct.EntityLightningSigil; +import electroblob.wizardry.entity.living.EntityBlazeMinion; +import electroblob.wizardry.entity.living.EntityIceGiant; +import electroblob.wizardry.entity.living.EntityIceWraith; +import electroblob.wizardry.entity.living.EntityLightningWraith; +import electroblob.wizardry.entity.living.EntityPhoenix; +import electroblob.wizardry.entity.living.EntitySilverfishMinion; +import electroblob.wizardry.entity.living.EntitySpiderMinion; +import electroblob.wizardry.entity.living.EntityStormElemental; +import electroblob.wizardry.entity.living.EntityWitherSkeletonMinion; +import electroblob.wizardry.entity.living.EntityZombieMinion; +import electroblob.wizardry.entity.projectile.EntityDart; +import electroblob.wizardry.entity.projectile.EntityFirebolt; +import electroblob.wizardry.entity.projectile.EntityFirebomb; +import electroblob.wizardry.entity.projectile.EntityForceArrow; +import electroblob.wizardry.entity.projectile.EntityForceOrb; +import electroblob.wizardry.entity.projectile.EntityIceCharge; +import electroblob.wizardry.entity.projectile.EntityIceLance; +import electroblob.wizardry.entity.projectile.EntityIceShard; +import electroblob.wizardry.entity.projectile.EntityLightningArrow; +import electroblob.wizardry.entity.projectile.EntityLightningDisc; +import electroblob.wizardry.entity.projectile.EntityMagicMissile; +import electroblob.wizardry.entity.projectile.EntityPoisonBomb; +import electroblob.wizardry.entity.projectile.EntitySmokeBomb; +import electroblob.wizardry.entity.projectile.EntitySpark; +import electroblob.wizardry.entity.projectile.EntitySparkBomb; +import electroblob.wizardry.entity.projectile.EntityThunderbolt; import electroblob.wizardry.spell.*; +import net.minecraft.init.MobEffects; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.EnumAction; import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; @@ -198,36 +240,35 @@ public final class Spells { IForgeRegistry registry = event.getRegistry(); - // event.getRegistry should always equal Spell.registry. registry.register(new None()); - registry.register(new MagicMissile()); + registry.register(new SpellArrow("magic_missile", Tier.BASIC, Element.MAGIC, 5, 10, EntityMagicMissile::new, 2, WizardrySounds.SPELL_MAGIC).soundValues(1, 1.4f, 0.4f)); registry.register(new Ignite()); registry.register(new Freeze()); registry.register(new Snowball()); registry.register(new Arc()); - registry.register(new Thunderbolt()); - registry.register(new SummonZombie()); + registry.register(new SpellProjectile("thunderbolt", Tier.BASIC, Element.LIGHTNING, 10, 15, EntityThunderbolt::new, 2.5f, WizardrySounds.SPELL_ICE).soundValues(0.8f, 0.9f, 0.2f)); + registry.register(new SpellMinion<>("summon_zombie", Tier.BASIC, Element.NECROMANCY, 10, 40, EntityZombieMinion::new, 600, WizardrySounds.SPELL_SUMMONING).soundValues(7, 0.6f, 0)); registry.register(new Snare()); - registry.register(new Dart()); + registry.register(new SpellArrow("dart", Tier.BASIC, Element.EARTH, 5, 10, EntityDart::new, 2, SoundEvents.ENTITY_ARROW_SHOOT).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new Light()); registry.register(new Telekinesis()); registry.register(new Heal()); registry.register(new Fireball()); registry.register(new FlameRay()); - registry.register(new Firebomb()); - registry.register(new FireSigil()); - registry.register(new Firebolt()); + registry.register(new SpellProjectile("firebomb", Tier.APPRENTICE, Element.FIRE, 15, 25, EntityFirebomb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellConstructRanged<>("fire_sigil", Tier.APPRENTICE, Element.FIRE, SpellType.CONSTRUCT, 10, 20, EntityFireSigil::new, -1, 10, SoundEvents.ITEM_FLINTANDSTEEL_USE).floor(true)); + registry.register(new SpellProjectile("firebolt", Tier.APPRENTICE, Element.FIRE, 10, 10, EntityFirebolt::new, 2.5f, SoundEvents.ENTITY_BLAZE_SHOOT)); registry.register(new FrostRay()); registry.register(new SummonSnowGolem()); - registry.register(new IceShard()); + registry.register(new SpellArrow("ice_shard", Tier.APPRENTICE, Element.ICE, 10, 10, EntityIceShard::new, 2, WizardrySounds.SPELL_ICE).soundValues(1, 1.6f, 0.4f)); registry.register(new IceStatue()); - registry.register(new FrostSigil()); + registry.register(new SpellConstructRanged<>("frost_sigil", Tier.APPRENTICE, Element.ICE, SpellType.CONSTRUCT, 10, 20, EntityFrostSigil::new, -1, 10, WizardrySounds.SPELL_ICE).floor(true)); registry.register(new LightningRay()); - registry.register(new SparkBomb()); - registry.register(new HomingSpark()); - registry.register(new LightningSigil()); - registry.register(new LightningArrow()); + registry.register(new SpellProjectile("spark_bomb", Tier.APPRENTICE, Element.LIGHTNING, 15, 25, EntitySparkBomb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); + registry.register(new SpellProjectile("homing_spark", Tier.APPRENTICE, Element.LIGHTNING, 10, 20, EntitySpark::new, 0.5f, WizardrySounds.SPELL_CONJURATION).soundValues(1.0f, 0.4f, 0.2f)); + registry.register(new SpellConstructRanged<>("lightning_sigil", Tier.APPRENTICE, Element.LIGHTNING, SpellType.CONSTRUCT, 10, 20, EntityLightningSigil::new, -1, 10, WizardrySounds.SPELL_CONJURATION).floor(true)); + registry.register(new SpellArrow("lightning_arrow", Tier.APPRENTICE, Element.LIGHTNING, 15, 20, EntityLightningArrow::new, 2, WizardrySounds.SPELL_LIGHTNING).soundValues(1, 1.45f, 0.3f)); registry.register(new LifeDrain()); registry.register(new SummonSkeleton()); registry.register(new Metamorphosis()); @@ -236,69 +277,69 @@ public final class Spells { registry.register(new GrowthAura()); registry.register(new Bubble()); registry.register(new Whirlwind()); - registry.register(new PoisonBomb()); + registry.register(new SpellProjectile("poison_bomb", Tier.APPRENTICE, Element.EARTH, 15, 25, EntityPoisonBomb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new SummonSpiritWolf()); registry.register(new Blink()); - registry.register(new Agility()); - registry.register(new ConjureSword()); - registry.register(new ConjurePickaxe()); - registry.register(new ConjureBow()); - registry.register(new ForceArrow()); + registry.register(new SpellBuff("agility", Tier.APPRENTICE, Element.SORCERY, SpellType.BUFF, 20, 40, WizardrySounds.SPELL_HEAL, 0.4f, 1.0f, 0.8f, Triple.of(MobEffects.SPEED, 600, 1), Triple.of(MobEffects.JUMP_BOOST, 600, 1)).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellConjuration("conjure_sword", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 25, 50, WizardryItems.spectral_sword, WizardrySounds.SPELL_CONJURATION)); + registry.register(new SpellConjuration("conjure_pickaxe", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 25, 50, WizardryItems.spectral_pickaxe, WizardrySounds.SPELL_CONJURATION)); + registry.register(new SpellConjuration("conjure_bow", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 40, 50, WizardryItems.spectral_bow, WizardrySounds.SPELL_CONJURATION)); + registry.register(new SpellArrow("force_arrow", Tier.APPRENTICE, Element.SORCERY, 15, 20, EntityForceArrow::new, 1, WizardrySounds.SPELL_FORCE).soundValues(1, 1.3f, 0.2f)); registry.register(new Shield()); registry.register(new ReplenishHunger()); registry.register(new CureEffects()); registry.register(new HealAlly()); - registry.register(new SummonBlaze()); - registry.register(new RingOfFire()); + registry.register(new SpellMinion<>("summon_blaze", Tier.ADVANCED, Element.FIRE, 40, 200, EntityBlazeMinion::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.2f)); + registry.register(new SpellConstruct<>("ring_of_fire", Tier.ADVANCED, Element.FIRE, SpellType.CONSTRUCT, 30, 100, EnumAction.BOW, EntityFireRing::new, 600, SoundEvents.ENTITY_BLAZE_SHOOT)); registry.register(new Detonate()); - registry.register(new FireResistance()); - registry.register(new Fireskin()); + registry.register(new SpellBuff("fire_resistance", Tier.ADVANCED, Element.FIRE, SpellType.DEFENCE, 20, 80, WizardrySounds.SPELL_HEAL, 1, 0.5f, 0, Triple.of(MobEffects.FIRE_RESISTANCE, 600, 0)).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("fireskin", Tier.ADVANCED, Element.FIRE, SpellType.DEFENCE, 40, 250, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 0.5f, 0, Triple.of(WizardryPotions.fireskin, 600, 0))); registry.register(new FlamingAxe()); - registry.register(new Blizzard()); - registry.register(new SummonIceWraith()); - registry.register(new IceShroud()); - registry.register(new IceCharge()); + registry.register(new SpellConstructRanged<>("blizzard", Tier.ADVANCED, Element.ICE, SpellType.CONSTRUCT, 40, 100, EntityBlizzard::new, 600, 20, WizardrySounds.SPELL_ICE)); + registry.register(new SpellMinion<>("summon_ice_wraith", Tier.ADVANCED, Element.ICE, 40, 200, EntityIceWraith::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.2f)); + registry.register(new SpellBuff("ice_shroud", Tier.ADVANCED, Element.ICE, SpellType.DEFENCE, 40, 250, WizardrySounds.SPELL_ICE, 0.3f, 0.5f, 1, Triple.of(WizardryPotions.ice_shroud, 600, 0)).soundValues(1, 1.6f, 0.4f)); + registry.register(new SpellProjectile("ice_charge", Tier.ADVANCED, Element.ICE, 20, 30, EntityIceCharge::new, 1.5f, WizardrySounds.SPELL_ICE).soundValues(1, 1.6f, 0.4f)); registry.register(new FrostAxe()); registry.register(new InvokeWeather()); registry.register(new ChainLightning()); registry.register(new LightningBolt()); - registry.register(new SummonLightningWraith()); - registry.register(new StaticAura()); - registry.register(new LightningDisc()); + registry.register(new SpellMinion<>("summon_lightning_wraith", Tier.ADVANCED, Element.LIGHTNING, 40, 200, EntityLightningWraith::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.2f)); + registry.register(new SpellBuff("static_aura", Tier.ADVANCED, Element.LIGHTNING, SpellType.DEFENCE, 40, 250, WizardrySounds.SPELL_SPARK, 0, 0.5f, 0.7f, Triple.of(WizardryPotions.static_aura, 600, 0)).soundValues(1, 1.6f, 0.4f)); + registry.register(new SpellProjectile("lightning_disc", Tier.ADVANCED, Element.LIGHTNING, 25, 60, EntityLightningDisc::new, 1.2f, WizardrySounds.SPELL_LIGHTNING).soundValues(1, 0.95f, 0.3f)); registry.register(new MindControl()); - registry.register(new SummonWitherSkeleton()); + registry.register(new SpellMinion<>("summon_wither_skeleton", Tier.ADVANCED, Element.NECROMANCY, 35, 150, EntityWitherSkeletonMinion::new, 600, WizardrySounds.SPELL_SUMMONING).soundValues(7, 0.6f, 0)); registry.register(new Entrapment()); registry.register(new WitherSkull()); - registry.register(new DarknessOrb()); + registry.register(new SpellProjectile("darkness_orb", Tier.ADVANCED, Element.NECROMANCY, 20, 20, EntityThunderbolt::new, 0.5f, SoundEvents.ENTITY_WITHER_SHOOT).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new ShadowWard()); registry.register(new Decay()); - registry.register(new WaterBreathing()); + registry.register(new SpellBuff("water_breathing", Tier.ADVANCED, Element.EARTH, SpellType.BUFF, 30, 250, WizardrySounds.SPELL_HEAL, 0.3f, 0.3f, 1, Triple.of(MobEffects.WATER_BREATHING, 1200, 0)){ @Override public boolean canBeCastByNPCs(){ return false; } }.soundValues(0.7f, 1.2f, 0.4f)); registry.register(new Tornado()); registry.register(new Glide()); registry.register(new SummonSpiritHorse()); - registry.register(new SpiderSwarm()); + registry.register(new SpellMinion<>("spider_swarm", Tier.ADVANCED, Element.EARTH, 45, 200, EntitySpiderMinion::new, 600, SoundEvents.BLOCK_FIRE_EXTINGUISH).soundValues(1, 1.1f, 0.1f).quantity(5).range(3)); registry.register(new Slime()); registry.register(new Petrify()); - registry.register(new Invisibility()); + registry.register(new SpellBuff("invisibility", Tier.ADVANCED, Element.SORCERY, SpellType.BUFF, 35, 200, WizardrySounds.SPELL_HEAL, 0.7f, 1, 1, Triple.of(MobEffects.INVISIBILITY, 600, 0)).soundValues(0.7f, 1.2f, 0.4f)); registry.register(new Levitation()); - registry.register(new ForceOrb()); + registry.register(new SpellProjectile("force_orb", Tier.ADVANCED, Element.SORCERY, 20, 20, EntityForceOrb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new Transportation()); registry.register(new SpectralPathway()); registry.register(new PhaseStep()); registry.register(new VanishingBox()); registry.register(new GreaterHeal()); - registry.register(new HealingAura()); - registry.register(new Forcefield()); - registry.register(new Ironflesh()); + registry.register(new SpellConstruct<>("healing_aura", Tier.ADVANCED, Element.HEALING, SpellType.CONSTRUCT, 35, 150, EnumAction.BOW, EntityHealAura::new, 600, null)); + registry.register(new SpellConstruct<>("forcefield", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 45, 200, EnumAction.BOW, EntityForcefield::new, 600, WizardrySounds.SPELL_CONJURATION_LARGE)); + registry.register(new SpellBuff("ironflesh", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 30, 100, WizardrySounds.SPELL_HEAL, 0.4f, 0.5f, 0.6f, Triple.of(MobEffects.RESISTANCE, 600, 2)).soundValues(0.7f, 1.2f, 0.4f)); registry.register(new Transience()); registry.register(new Meteor()); registry.register(new Firestorm()); - registry.register(new SummonPhoenix()); + registry.register(new SpellMinion<>("summon_phoenix", Tier.MASTER, Element.FIRE, 150, 400, EntityPhoenix::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.1f)); registry.register(new IceAge()); registry.register(new WallOfFrost()); - registry.register(new SummonIceGiant()); + registry.register(new SpellMinion<>("summon_ice_giant", Tier.MASTER, Element.ICE, 100, 400, EntityIceGiant::new, 600, WizardrySounds.SPELL_ICE).soundValues(1, 0.15f, 0.1f)); registry.register(new Thunderstorm()); registry.register(new LightningHammer()); registry.register(new PlagueOfDarkness()); @@ -306,17 +347,17 @@ public final class Spells { registry.register(new SummonShadowWraith()); registry.register(new ForestsCurse()); registry.register(new Flight()); - registry.register(new SilverfishSwarm()); - registry.register(new BlackHole()); + registry.register(new SpellMinion<>("silverfish_swarm", Tier.MASTER, Element.EARTH, 80, 300, EntitySilverfishMinion::new, 600, SoundEvents.BLOCK_FIRE_EXTINGUISH).soundValues(1, 1.1f, 0.1f).quantity(20).range(3)); + registry.register(new SpellConstructRanged<>("black_hole", Tier.MASTER, Element.SORCERY, SpellType.CONSTRUCT, 150, 400, EntityBlackHole::new, 600, 10, SoundEvents.ENTITY_WITHER_SPAWN).soundValues(2, 0.7f, 0)); registry.register(new Shockwave()); registry.register(new SummonIronGolem()); registry.register(new ArrowRain()); - registry.register(new Diamondflesh()); - registry.register(new FontOfVitality()); + registry.register(new SpellBuff("diamondflesh", Tier.MASTER, Element.HEALING, SpellType.DEFENCE, 100, 300, WizardrySounds.SPELL_HEAL, 0.1f, 0.7f, 1, Triple.of(MobEffects.RESISTANCE, 600, 5)).soundValues(0.7f, 1.2f, 0.4f)); + registry.register(new SpellBuff("font_of_vitality", Tier.MASTER, Element.HEALING, SpellType.DEFENCE, 75, 300, WizardrySounds.SPELL_HEAL, 1, 0.8f, 0.3f, Triple.of(MobEffects.ABSORPTION, 1200, 1), Triple.of(MobEffects.REGENERATION, 300, 1)).soundValues(0.7f, 1.2f, 0.4f)); // Wizardry 1.1 spells - registry.register(new SmokeBomb()); + registry.register(new SpellProjectile("smoke_bomb", Tier.BASIC, Element.FIRE, 10, 20, EntitySmokeBomb::new, 1.5f, SoundEvents.ENTITY_SNOWBALL_THROW).soundValues(0.5f, 0.4f, 0.2f)); registry.register(new MindTrick()); registry.register(new Leap()); @@ -324,16 +365,16 @@ public final class Spells { registry.register(new Intimidate()); registry.register(new Banish()); registry.register(new SixthSense()); - registry.register(new Darkvision()); + registry.register(new SpellBuff("darkvision", Tier.APPRENTICE, Element.EARTH, SpellType.BUFF, 20, 40, WizardrySounds.SPELL_HEAL, 0, 0.4f, 0.7f, Triple.of(MobEffects.NIGHT_VISION, 900, 0)){ @Override public boolean canBeCastByNPCs(){ return false; } }.soundValues(0.7f, 1.2f, 0.4f)); registry.register(new Clairvoyance()); registry.register(new PocketWorkbench()); registry.register(new ImbueWeapon()); registry.register(new InvigoratingPresence()); - registry.register(new Oakflesh()); + registry.register(new SpellBuff("oakflesh", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 20, 50, WizardrySounds.SPELL_HEAL, 0.6f, 0.5f, 0.4f, Triple.of(MobEffects.RESISTANCE, 600, 1)).soundValues(0.7f, 1.2f, 0.4f)); registry.register(new GreaterFireball()); registry.register(new FlamingWeapon()); - registry.register(new IceLance()); + registry.register(new SpellArrow("ice_lance", Tier.ADVANCED, Element.ICE, 20, 20, EntityIceLance::new, 2, WizardrySounds.SPELL_ICE).soundValues(1, 1, 0.4f)); registry.register(new FreezingWeapon()); registry.register(new IceSpikes()); registry.register(new LightningPulse()); @@ -346,7 +387,7 @@ public final class Spells { registry.register(new Hailstorm()); registry.register(new LightningWeb()); - registry.register(new SummonStormElemental()); + registry.register(new SpellMinion<>("summon_storm_elemental", Tier.MASTER, Element.LIGHTNING, 100, 400, EntityStormElemental::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT).soundValues(1, 1.1f, 0.1f)); registry.register(new Earthquake()); registry.register(new FontOfMana()); } diff --git a/src/main/java/electroblob/wizardry/spell/Agility.java b/src/main/java/electroblob/wizardry/spell/Agility.java deleted file mode 100644 index dd760919..00000000 --- a/src/main/java/electroblob/wizardry/spell/Agility.java +++ /dev/null @@ -1,51 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.ParticleBuilder; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Agility extends Spell { - - public Agility(){ - super(Tier.APPRENTICE, 20, Element.SORCERY, "agility", SpellType.UTILITY, 40, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - // 1.10 allows the particles to be completely hidden. - caster.addPotionEffect(new PotionEffect(MobEffects.SPEED, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); - caster.addPotionEffect(new PotionEffect(MobEffects.JUMP_BOOST, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - ParticleBuilder.create(Type.SPARKLE).pos(x1, y1, z1).vel(0, 0.1F, 0) - .lifetime(48 + world.rand.nextInt(12)).colour(0.4f, 1.0f, 0.8f).spawn(world); - } - Wizardry.proxy.spawnEntityParticle(world, caster, 15, 0.4f, 1.0f, 0.8f); - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Arc.java b/src/main/java/electroblob/wizardry/spell/Arc.java index 56335ed2..296b3355 100644 --- a/src/main/java/electroblob/wizardry/spell/Arc.java +++ b/src/main/java/electroblob/wizardry/spell/Arc.java @@ -1,119 +1,68 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.EntityArc; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -// This spell was the 'guinea pig' for damage types, so to speak, so there's a bit of commentary on them here that may -// be useful for future reference. -public class Arc extends Spell { +public class Arc extends SpellRay { + + private static final float BASE_DAMAGE = 3; public Arc(){ - super(Tier.BASIC, 5, Element.LIGHTNING, "arc", SpellType.ATTACK, 15, EnumAction.NONE, false); + super("arc", Tier.BASIC, Element.LIGHTNING, SpellType.ATTACK, 5, 15, false, 8, null); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 8 * modifiers.get(WizardryItems.range_upgrade), 4.0f); - - if(rayTrace != null && rayTrace.entityHit != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - Entity target = rayTrace.entityHit; - + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + if(!world.isRemote){ EntityArc arc = new EntityArc(world); - arc.setEndpointCoords(caster.posX, caster.posY + 1, caster.posZ, target.posX, - target.posY + target.height / 2, target.posZ); + arc.setEndpointCoords(caster.posX, caster.posY + 1, caster.posZ, target.posX, target.posY + target.height / 2, target.posZ); world.spawnEntity(arc); }else{ - for(int i = 0; i < 8; i++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0); - } + ParticleBuilder.spawnShockParticles(world, target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ); } - + // This is a lot neater than it was, thanks to the damage type system. if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted())); }else{ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); + BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); } - - caster.swingArm(hand); + + // TODO: Does this mean that players hit by the spell hear no sound? target.playSound(WizardrySounds.SPELL_SPARK, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); return true; } - + return false; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityArc arc = new EntityArc(world); - arc.setEndpointCoords(caster.posX, caster.posY + 1, caster.posZ, target.posX, - target.posY + target.height / 2, target.posZ); - world.spawnEntity(arc); - }else{ - for(int i = 0; i < 8; i++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0); - } - } - - // What's great about the damage type system is that, because I don't need to know if the creature resisted - // the damage here, I can simply call this without having to check for immunities at all. - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); - - caster.swingArm(hand); - target.playSound(WizardrySounds.SPELL_SPARK, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); - return true; - } - + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean canBeCastByNPCs(){ - return true; + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; } } diff --git a/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java b/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java index 6316b0f1..650e1966 100644 --- a/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java +++ b/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -10,105 +9,65 @@ import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber -public class ArcaneJammer extends Spell { +public class ArcaneJammer extends SpellRay { public ArcaneJammer(){ - super(Tier.ADVANCED, 30, Element.HEALING, "arcane_jammer", SpellType.ATTACK, 50, EnumAction.NONE, false); + super("arcane_jammer", Tier.ADVANCED, Element.HEALING, SpellType.ATTACK, 30, 50, false, 10, WizardrySounds.SPELL_DEFLECTION); + this.soundValues(0.7f, 1, 0.4f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - EntityLivingBase entity = (EntityLivingBase)rayTrace.entityHit; - if(entity instanceof EntityWizard) WizardryAdvancementTriggers.jam_wizard.triggerFor(caster); - + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + if(target instanceof EntityWizard && caster instanceof EntityPlayer) + WizardryAdvancementTriggers.jam_wizard.triggerFor((EntityPlayer)caster); + if(!world.isRemote){ - entity.addPotionEffect(new PotionEffect(WizardryPotions.arcane_jammer, + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.arcane_jammer, (int)(300 * modifiers.get(WizardryItems.duration_upgrade)), 0)); } } - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 0.9f, 0.3f, 0.7f); - } - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_DEFLECTION, 0.7F, - world.rand.nextFloat() * 0.4F + 0.8F); + return true; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - if(!world.isRemote){ - target.addPotionEffect(new PotionEffect(WizardryPotions.arcane_jammer, - (int)(300 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - } - - if(world.isRemote){ - - double dx = (target.posX - caster.posX) / caster.getDistance(target); - double dy = (target.posY - caster.posY) / caster.getDistance(target); - double dz = (target.posZ - caster.posZ) / caster.getDistance(target); - - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - - double x1 = caster.posX + dx * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + dy * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + dz * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 0.9f, 0.3f, 0.7f); - } - } - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_DEFLECTION, 0.7F, world.rand.nextFloat() * 0.4F + 0.8F); - } - + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean canBeCastByNPCs(){ + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(0.9f, 0.3f, 0.7f) + .spawn(world); + } @SubscribeEvent public static void onSpellCastPreEvent(SpellCastEvent.Pre event){ // Arcane jammer prevents spell casting. - if(event.getEntityLiving().isPotionActive(WizardryPotions.arcane_jammer)) event.setCanceled(true); + if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.arcane_jammer)) event.setCanceled(true); } } diff --git a/src/main/java/electroblob/wizardry/spell/ArrowRain.java b/src/main/java/electroblob/wizardry/spell/ArrowRain.java index b767a523..796641fd 100644 --- a/src/main/java/electroblob/wizardry/spell/ArrowRain.java +++ b/src/main/java/electroblob/wizardry/spell/ArrowRain.java @@ -4,58 +4,38 @@ import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityArrowRain; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.world.World; -public class ArrowRain extends Spell { +public class ArrowRain extends SpellConstructRanged { public ArrowRain(){ - super(Tier.MASTER, 75, Element.SORCERY, "arrow_rain", SpellType.ATTACK, 300, EnumAction.NONE, false); + super("arrow_rain", Tier.MASTER, Element.SORCERY, SpellType.ATTACK, 75, 300, EntityArrowRain::new, 120, 20, WizardrySounds.SPELL_SUMMONING); + this.floor(true); } - + @Override - public boolean doesSpellRequirePacket(){ - return false; + protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + + // Moves the entity back towards the caster a bit, so the area of effect is better centred on the position. + // 3 is the distance to move the entity back towards the caster. + double dx = caster.posX - x; + double dz = caster.posZ - z; + double distRatio = 3 / Math.sqrt(dx * dx + dz * dz); + x += dx * distRatio; + z += dz * distRatio; + // Moves the entity up 5 blocks so that it is above mobs' heads. + y += 5; + + return super.spawnConstruct(world, x, y, z, caster, modifiers); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(20 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - if(!world.isRemote){ - double x = rayTrace.hitVec.x; - double y = rayTrace.hitVec.y; - double z = rayTrace.hitVec.z; - // Moves the entity back towards the caster a bit, so the area of effect is better centred on the - // position. - // 3.0d is the distance to move the entity back towards the caster. - double dx = caster.posX - x; - double dz = caster.posZ - z; - double distRatio = 3.0d / Math.sqrt(dx * dx + dz * dz); - x += dx * distRatio; - z += dz * distRatio; - - EntityArrowRain arrowrain = new EntityArrowRain(world, x, y + 5, z, caster, - (int)(120 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - arrowrain.rotationYaw = caster.rotationYawHead; - world.spawnEntity(arrowrain); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 1.0F, 1.0F); - return true; - } - return false; + protected void addConstructExtras(EntityArrowRain construct, EntityLivingBase caster, SpellModifiers modifiers){ + // Makes the arrows shoot in the direction the caster was looking when they cast the spell. + construct.rotationYaw = caster.rotationYawHead; } } diff --git a/src/main/java/electroblob/wizardry/spell/Banish.java b/src/main/java/electroblob/wizardry/spell/Banish.java index 01b01c73..efec3bcf 100644 --- a/src/main/java/electroblob/wizardry/spell/Banish.java +++ b/src/main/java/electroblob/wizardry/spell/Banish.java @@ -1,58 +1,48 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class Banish extends Spell { +public class Banish extends SpellRay { public Banish(){ - super(Tier.APPRENTICE, 15, Element.NECROMANCY, "banish", SpellType.ATTACK, 40, EnumAction.NONE, false); + super("banish", Tier.APPRENTICE, Element.NECROMANCY, SpellType.ATTACK, 15, 40, false, 10, SoundEvents.ENTITY_ENDERMEN_TELEPORT); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(target instanceof EntityLivingBase){ - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - // Left as EntityLivingBase, since it's reasonable to teleport armour stands around. - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && rayTrace.entityHit instanceof EntityLivingBase){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; + EntityLivingBase entity = (EntityLivingBase)target; double radius = (8 + world.rand.nextDouble() * 8) * modifiers.get(WizardryItems.range_upgrade); double angle = world.rand.nextDouble() * Math.PI * 2; - int x = MathHelper.floor(target.posX + Math.sin(angle) * radius); - int z = MathHelper.floor(target.posZ - Math.cos(angle) * radius); + int x = MathHelper.floor(entity.posX + Math.sin(angle) * radius); + int z = MathHelper.floor(entity.posZ - Math.cos(angle) * radius); int y = WizardryUtilities.getNearestFloorLevel(world, new BlockPos(x, (int)caster.getEntityBoundingBox().minY, z), (int)radius); if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double dx1 = target.posX; - double dy1 = target.getEntityBoundingBox().minY + target.height * world.rand.nextFloat(); - double dz1 = target.posZ; + for(int i=0; i<10; i++){ + double dx1 = entity.posX; + double dy1 = entity.getEntityBoundingBox().minY + entity.height * world.rand.nextFloat(); + double dz1 = entity.posZ; world.spawnParticle(EnumParticleTypes.PORTAL, dx1, dy1, dz1, world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5); } @@ -60,7 +50,7 @@ public class Banish extends Spell { if(y > -1){ - // This means stuff like snow layers is ignored, meaning when on snow-covered ground the caster does + // This means stuff like snow layers is ignored, meaning when on snow-covered ground the target does // not teleport 1 block above the ground. if(!world.getBlockState(new BlockPos(x, y, z)).getMaterial().blocksMovement()){ y--; @@ -72,101 +62,30 @@ public class Banish extends Spell { } if(!world.isRemote){ - target.setPositionAndUpdate(x + 0.5, y + 1, z + 0.5); + entity.setPositionAndUpdate(x + 0.5, y + 1, z + 0.5); } - target.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); + entity.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); } } - - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - world.spawnParticle(EnumParticleTypes.PORTAL, x1, y1 - 0.5, z1, 0.0d, 0.0d, 0.0d); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0, - 0.2f, 0.0f, 0.2f); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); - caster.swingArm(hand); + return true; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - double radius = (8 + world.rand.nextDouble() * 8) * modifiers.get(WizardryItems.range_upgrade); - double angle = world.rand.nextDouble() * Math.PI * 2; - - int x = MathHelper.floor(target.posX + Math.sin(angle) * radius); - int z = MathHelper.floor(target.posZ - Math.cos(angle) * radius); - int y = WizardryUtilities.getNearestFloorLevel(world, - new BlockPos(x, (int)caster.getEntityBoundingBox().minY, z), (int)radius); - - if(world.isRemote){ - - double dx = (target.posX - caster.posX) / caster.getDistance(target); - double dy = (target.posY - caster.posY) / caster.getDistance(target); - double dz = (target.posZ - caster.posZ) / caster.getDistance(target); - - for(int i = 1; i < 25; i += 2){ - - double x1 = caster.posX + dx * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + dy * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + dz * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - world.spawnParticle(EnumParticleTypes.PORTAL, x1, y1 - 0.5, z1, 0.0d, 0.0d, 0.0d); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 0, 0.2f, 0.0f, 0.2f); - } - - for(int i = 0; i < 10; i++){ - double dx1 = target.posX; - double dy1 = target.getEntityBoundingBox().minY + target.height * world.rand.nextFloat(); - double dz1 = target.posZ; - world.spawnParticle(EnumParticleTypes.PORTAL, dx1, dy1, dz1, world.rand.nextDouble() - 0.5, - world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5); - } - } - - if(y > -1){ - - // This means stuff like snow layers is ignored, meaning when on snow-covered ground the caster does - // not teleport 1 block above the ground. - if(!world.getBlockState(new BlockPos(x, y, z)).getMaterial().blocksMovement()){ - y--; - } - - if(world.getBlockState(new BlockPos(x, y + 1, z)).getMaterial().blocksMovement() - || world.getBlockState(new BlockPos(x, y + 2, z)).getMaterial().blocksMovement()){ - return false; - } - - if(!world.isRemote){ - target.setPositionAndUpdate(x + 0.5, y + 1, z + 0.5); - } - - target.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); - } - } - - caster.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0F, 1.0f); - caster.swingArm(hand); - return true; + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; } @Override - public boolean canBeCastByNPCs(){ + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + world.spawnParticle(EnumParticleTypes.PORTAL, x, y - 0.5, z, 0, 0, 0); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.2f, 0, 0.2f).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/BlackHole.java b/src/main/java/electroblob/wizardry/spell/BlackHole.java deleted file mode 100644 index f8c15034..00000000 --- a/src/main/java/electroblob/wizardry/spell/BlackHole.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityBlackHole; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.world.World; - -public class BlackHole extends Spell { - - public BlackHole(){ - super(Tier.MASTER, 150, Element.SORCERY, "black_hole", SpellType.ATTACK, 400, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(10 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - // This demonstrates beautifully the elegance of BlockPos. In 1.7.10 this required a 50-line long switch - // statement and a flag variable; now it only needs a few lines. - BlockPos pos = new BlockPos(rayTrace.hitVec).offset(rayTrace.sideHit); - - if(world.isAirBlock(pos)){ - - if(!world.isRemote){ - world.spawnEntity(new EntityBlackHole(world, pos.getX() + 0.5, pos.getY() - 1 + 0.5, - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE))); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 2.0f, 0.7f); - return true; - } - - }else{ - int x = (int)(Math.floor(caster.posX) + caster.getLookVec().x * 8); - int y = (int)(Math.floor(caster.posY) + caster.eyeHeight + caster.getLookVec().y * 8); - int z = (int)(Math.floor(caster.posZ) + caster.getLookVec().z * 8); - if(!world.isRemote){ - world.spawnEntity(new EntityBlackHole(world, x, y, z, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE))); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 2.0f, 0.7f); - return true; - } - return false; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Blink.java b/src/main/java/electroblob/wizardry/spell/Blink.java index 85fee81c..1668f32b 100644 --- a/src/main/java/electroblob/wizardry/spell/Blink.java +++ b/src/main/java/electroblob/wizardry/spell/Blink.java @@ -22,14 +22,14 @@ import net.minecraft.world.World; public class Blink extends Spell { public Blink(){ - super(Tier.APPRENTICE, 15, Element.SORCERY, "blink", SpellType.UTILITY, 25, EnumAction.NONE, false); + super("blink", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 15, 25, EnumAction.NONE, false); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - RayTraceResult rayTrace = WizardryUtilities.rayTrace(25 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); + RayTraceResult rayTrace = WizardryUtilities.standardBlockRayTrace(world, caster, + 25 * modifiers.get(WizardryItems.range_upgrade), false); // It's worth noting that on the client side, the cast() method only gets called if the server side // cast method succeeded, so you need not check any conditions for spawning particles. diff --git a/src/main/java/electroblob/wizardry/spell/Blizzard.java b/src/main/java/electroblob/wizardry/spell/Blizzard.java deleted file mode 100644 index 38a1b4b8..00000000 --- a/src/main/java/electroblob/wizardry/spell/Blizzard.java +++ /dev/null @@ -1,81 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityBlizzard; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.world.World; - -public class Blizzard extends Spell { - - public Blizzard(){ - super(Tier.ADVANCED, 40, Element.ICE, "blizzard", SpellType.ATTACK, 100, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(20 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - if(!world.isRemote){ - double x = rayTrace.hitVec.x; - double y = rayTrace.hitVec.y; - double z = rayTrace.hitVec.z; - EntityBlizzard blizzard = new EntityBlizzard(world, x, y + 0.5, z, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(blizzard); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - return true; - } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - double x = target.posX; - double y = target.posY; - double z = target.posZ; - EntityBlizzard blizzard = new EntityBlizzard(world, x, y + 0.5, z, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(blizzard); - } - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Bubble.java b/src/main/java/electroblob/wizardry/spell/Bubble.java index 7a9c5ff2..34b1698f 100644 --- a/src/main/java/electroblob/wizardry/spell/Bubble.java +++ b/src/main/java/electroblob/wizardry/spell/Bubble.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -9,115 +8,81 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class Bubble extends Spell { +public class Bubble extends SpellRay { public Bubble(){ - super(Tier.APPRENTICE, 15, Element.EARTH, "bubble", SpellType.ATTACK, 20, EnumAction.NONE, false); + super("bubble", Tier.APPRENTICE, Element.EARTH, SpellType.ATTACK, 15, 20, false, 10, WizardrySounds.SPELL_ICE); + this.soundValues(0.5f, 1.1f, 0.2f); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + // This spell uses more than one sound, so this is required... + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_GENERIC_SWIM, 1, 1 + 0.2f * world.rand.nextFloat()); + return flag; + } - Vec3d look = caster.getLookVec(); + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag) caster.playSound(SoundEvents.ENTITY_GENERIC_SWIM, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); + return flag; + } - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - EntityLivingBase entity = (EntityLivingBase)rayTrace.entityHit; + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + if(!world.isRemote){ - entity.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), - 1.0f * modifiers.get(SpellModifiers.DAMAGE)); - // Deprecated in favour of entity riding method - // entity.addPotionEffect(new PotionEffect(Wizardry.bubblePotion, 200, 0)); - EntityBubble entitybubble = new EntityBubble(world, entity.posX, entity.posY, entity.posZ, caster, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), false, - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(entitybubble); - entity.startRiding(entitybubble); + // Deals a small amount damage so the target counts as being hit by the caster + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), 1); + + EntityBubble bubble = new EntityBubble(world); + bubble.setPosition(target.posX, target.posY, target.posZ); + bubble.setCaster(caster); + bubble.lifetime = ((int)(200 * modifiers.get(WizardryItems.duration_upgrade))); + bubble.isDarkOrb = false; + bubble.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + + world.spawnEntity(bubble); + target.startRiding(bubble); } } - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - world.spawnParticle(EnumParticleTypes.WATER_SPLASH, x1, y1, z1, 0.0d, 0.0d, 0.0d); - Wizardry.proxy.spawnParticle(Type.MAGIC_BUBBLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0); - } - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_GENERIC_SWIM, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.5F, - world.rand.nextFloat() * 0.2F + 1.0F); + return true; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), - 1.0f * modifiers.get(SpellModifiers.DAMAGE)); - // Deprecated in favour of entity riding method - // entity.addPotionEffect(new PotionEffect(Wizardry.bubblePotion, 200, 0)); - EntityBubble entitybubble = new EntityBubble(world, target.posX, target.posY, target.posZ, caster, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), false, - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(entitybubble); - target.startRiding(entitybubble); - - } - if(world.isRemote){ - - double dx = (target.posX - caster.posX) / caster.getDistance(target); - double dy = (target.posY - caster.posY) / caster.getDistance(target); - double dz = (target.posZ - caster.posZ) / caster.getDistance(target); - - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - - double x1 = caster.posX + dx * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + dy * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + dz * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - world.spawnParticle(EnumParticleTypes.WATER_SPLASH, x1, y1, z1, 0.0d, 0.0d, 0.0d); - Wizardry.proxy.spawnParticle(Type.MAGIC_BUBBLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 0); - } - } - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_GENERIC_SWIM, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); - caster.playSound(WizardrySounds.SPELL_ICE, 0.5F, world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean canBeCastByNPCs(){ + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + world.spawnParticle(EnumParticleTypes.WATER_SPLASH, x, y, z, 0, 0, 0); + ParticleBuilder.create(Type.MAGIC_BUBBLE).pos(x, y, z).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/ChainLightning.java b/src/main/java/electroblob/wizardry/spell/ChainLightning.java index 78422b25..ca23af59 100644 --- a/src/main/java/electroblob/wizardry/spell/ChainLightning.java +++ b/src/main/java/electroblob/wizardry/spell/ChainLightning.java @@ -2,181 +2,116 @@ package electroblob.wizardry.spell; import java.util.List; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.EntityArc; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.item.EntityArmorStand; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class ChainLightning extends Spell { +public class ChainLightning extends SpellRay { + + private static final float PRIMARY_DAMAGE = 10; + private static final float SECONDARY_DAMAGE = 8; + private static final float TERTIARY_DAMAGE = 6; + + private static final double PRIMARY_RANGE = 10; + private static final double SECONDARY_RANGE = 5; + private static final double TERTIARY_RANGE = 5; + + private static final int SECONDARY_MAX_TARGETS = 5; + private static final int TERTIARY_MAX_TARGETS = 2; // This is per secondary target, giving 10 in total public ChainLightning(){ - super(Tier.ADVANCED, 25, Element.LIGHTNING, "chain_lightning", SpellType.ATTACK, 50, EnumAction.NONE, false); + super("chain_lightning", Tier.ADVANCED, Element.LIGHTNING, SpellType.ATTACK, 25, 50, false, PRIMARY_RANGE, null); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - // First shot has range 10 (this is the only range affected by upgrades) and does 5 hearts of damage. - // Chains to up to 5 secondary targets within a range of 5 of the primary target, and then to up to 2 - // tertiary targets per secondary target within a range of 5 of that. Secondary targets are dealt 4 hearts - // of damage; tertiary targets are dealt 3 hearts of damage. - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade), 8.0f); + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ // Anything can be attacked with the initial arc, because the player has control over where it goes. If they // hit a minion or an ally, it's their problem! - if(rayTrace != null && rayTrace.entityHit != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ + if(WizardryUtilities.isLiving(target)){ - Entity target = rayTrace.entityHit; - - if(!world.isRemote){ - EntityArc arc = new EntityArc(world); - arc.setEndpointCoords(caster.posX, caster.posY + caster.height / 2, caster.posZ, target.posX, - target.posY + target.height / 2, target.posZ); - world.spawnEntity(arc); - }else{ - for(int i = 0; i < 8; i++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0); - } - } - - target.playSound(WizardrySounds.SPELL_SPARK, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); - - if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ - if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), - this.getNameForTranslationFormatted())); - }else{ - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 10.0f * modifiers.get(SpellModifiers.DAMAGE)); - } + electrocute(world, caster, caster, target, PRIMARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); // Secondary chaining effect - double seekerRange = 5.0d; - - List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, + List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(SECONDARY_RANGE, target.posX, target.posY + target.height / 2, target.posZ, world); - - secondaryTargets.removeIf(e -> e instanceof EntityArmorStand); - for(int i = 0; i < Math.min(secondaryTargets.size(), 5); i++){ + secondaryTargets.remove(target); + secondaryTargets.removeIf(e -> !WizardryUtilities.isLiving(e)); + secondaryTargets.removeIf(e -> !WizardryUtilities.isValidTarget(caster, e)); + if(secondaryTargets.size() > SECONDARY_MAX_TARGETS) secondaryTargets = secondaryTargets.subList(0, SECONDARY_MAX_TARGETS); - EntityLivingBase secondaryTarget = secondaryTargets.get(i); + for(EntityLivingBase secondaryTarget : secondaryTargets){ - if(secondaryTarget != target && WizardryUtilities.isValidTarget(caster, secondaryTarget)){ + electrocute(world, caster, target, secondaryTarget, + SECONDARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); - if(!world.isRemote){ - EntityArc arc = new EntityArc(world); - arc.setEndpointCoords(target.posX, target.posY + target.height / 2, target.posZ, - secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2, - secondaryTarget.posZ); - world.spawnEntity(arc); - }else{ - for(int j = 0; j < 8; j++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - secondaryTarget.posX + world.rand.nextFloat() - 0.5, - secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - secondaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, - secondaryTarget.posX + world.rand.nextFloat() - 0.5, - secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - secondaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0); - } - } + // Tertiary chaining effect - secondaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); + List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius(TERTIARY_RANGE, + secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2, + secondaryTarget.posZ, world); - if(MagicDamage.isEntityImmune(DamageType.SHOCK, secondaryTarget)){ - if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", - secondaryTarget.getName(), this.getNameForTranslationFormatted())); - }else{ - secondaryTarget.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 8.0f * modifiers.get(SpellModifiers.DAMAGE)); - } + tertiaryTargets.remove(target); + tertiaryTargets.removeAll(secondaryTargets); + tertiaryTargets.removeIf(e -> !WizardryUtilities.isLiving(e)); + tertiaryTargets.removeIf(e -> !WizardryUtilities.isValidTarget(caster, e)); + if(tertiaryTargets.size() > TERTIARY_MAX_TARGETS) tertiaryTargets = tertiaryTargets.subList(0, TERTIARY_MAX_TARGETS); - // Tertiary chaining effect - - List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, - secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2, - secondaryTarget.posZ, world); - - tertiaryTargets.removeIf(e -> e instanceof EntityArmorStand); - - for(int j = 0; j < Math.min(tertiaryTargets.size(), 2); j++){ - - EntityLivingBase tertiaryTarget = (EntityLivingBase)tertiaryTargets.get(j); - - if(tertiaryTarget != target && !secondaryTargets.contains(tertiaryTarget) - && WizardryUtilities.isValidTarget(caster, tertiaryTarget)){ - - if(!world.isRemote){ - EntityArc arc = new EntityArc(world); - arc.setEndpointCoords(secondaryTarget.posX, - secondaryTarget.posY + secondaryTarget.height / 2, secondaryTarget.posZ, - tertiaryTarget.posX, tertiaryTarget.posY + tertiaryTarget.height / 2, - tertiaryTarget.posZ); - world.spawnEntity(arc); - }else{ - for(int k = 0; k < 8; k++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - tertiaryTarget.posX + world.rand.nextFloat() - 0.5, - tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - tertiaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, - tertiaryTarget.posX + world.rand.nextFloat() - 0.5, - tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - tertiaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0); - } - } - - tertiaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F, - world.rand.nextFloat() * 0.4F + 1.5F); - - if(MagicDamage.isEntityImmune(DamageType.SHOCK, tertiaryTarget)){ - if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", - tertiaryTarget.getName(), this.getNameForTranslationFormatted())); - }else{ - tertiaryTarget.attackEntityFrom( - MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 6.0f * modifiers.get(SpellModifiers.DAMAGE)); - } - } - } + for(EntityLivingBase tertiaryTarget : tertiaryTargets){ + electrocute(world, caster, secondaryTarget, tertiaryTarget, + TERTIARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); } } - caster.swingArm(hand); return true; } + return false; } + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + private void electrocute(World world, Entity caster, Entity origin, Entity target, float damage){ + + if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ + if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), + this.getNameForTranslationFormatted())); + }else{ + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), damage); + } + + if(!world.isRemote){ + EntityArc arc = new EntityArc(world); + arc.setEndpointCoords(caster.posX, caster.getEntityBoundingBox().minY + caster.height / 2, caster.posZ, + target.posX, target.getEntityBoundingBox().minY + target.height / 2, target.posZ); + world.spawnEntity(arc); + }else{ + ParticleBuilder.spawnShockParticles(world, target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ); + } + + target.playSound(WizardrySounds.SPELL_SPARK, 1, 1.5f + 0.4f * world.rand.nextFloat()); + } + } diff --git a/src/main/java/electroblob/wizardry/spell/Clairvoyance.java b/src/main/java/electroblob/wizardry/spell/Clairvoyance.java index 5f648b1c..6f74e00a 100644 --- a/src/main/java/electroblob/wizardry/spell/Clairvoyance.java +++ b/src/main/java/electroblob/wizardry/spell/Clairvoyance.java @@ -1,7 +1,6 @@ package electroblob.wizardry.spell; import electroblob.wizardry.WizardData; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -11,9 +10,10 @@ import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WandHelper; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryPathFinder; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.SharedMonsterAttributes; @@ -40,7 +40,7 @@ public class Clairvoyance extends Spell { public static final int PARTICLE_MOVEMENT_INTERVAL = 45; public Clairvoyance(){ - super(Tier.APPRENTICE, 20, Element.SORCERY, "clairvoyance", SpellType.UTILITY, 100, EnumAction.BOW, false); + super("clairvoyance", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 20, 100, EnumAction.BOW, false); } @Override @@ -123,9 +123,11 @@ public class Clairvoyance extends Spell { nextPoint = path.getCurrentPathLength() - path.getCurrentPathIndex() <= 2 ? path.getFinalPathPoint() : path.getPathPointFromIndex(path.getCurrentPathIndex() + 2); - Wizardry.proxy.spawnParticle(Type.PATH, world, point.x + 0.5, point.y + 0.5, point.z + 0.5, - (nextPoint.x - point.x) / (float)PARTICLE_MOVEMENT_INTERVAL, (nextPoint.y - point.y) / (float)PARTICLE_MOVEMENT_INTERVAL, - (nextPoint.z - point.z) / (float)PARTICLE_MOVEMENT_INTERVAL, (int)(1800 * durationMultiplier), 0, 1, 0.3f); + ParticleBuilder.create(Type.PATH).pos(point.x + 0.5, point.y + 0.5, point.z + 0.5).vel( + (nextPoint.x - point.x) / (float)PARTICLE_MOVEMENT_INTERVAL, + (nextPoint.y - point.y) / (float)PARTICLE_MOVEMENT_INTERVAL, + (nextPoint.z - point.z) / (float)PARTICLE_MOVEMENT_INTERVAL) + .lifetime((int)(1800 * durationMultiplier)).colour(0, 1, 0.3f).spawn(world); path.incrementPathIndex(); path.incrementPathIndex(); @@ -133,8 +135,8 @@ public class Clairvoyance extends Spell { point = path.getFinalPathPoint(); - Wizardry.proxy.spawnParticle(Type.PATH, world, point.x + 0.5, point.y + 0.5, point.z + 0.5, 0, 0, 0, - (int)(1800 * durationMultiplier), 1, 1, 1); + ParticleBuilder.create(Type.PATH).pos(point.x + 0.5, point.y + 0.5, point.z + 0.5) + .lifetime((int)(1800 * durationMultiplier)).colour(1, 1, 1).spawn(world); } @SubscribeEvent diff --git a/src/main/java/electroblob/wizardry/spell/Cobwebs.java b/src/main/java/electroblob/wizardry/spell/Cobwebs.java index 460576ee..1e78ac2d 100644 --- a/src/main/java/electroblob/wizardry/spell/Cobwebs.java +++ b/src/main/java/electroblob/wizardry/spell/Cobwebs.java @@ -7,133 +7,69 @@ import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.tileentity.TileEntityTimer; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -public class Cobwebs extends Spell { +public class Cobwebs extends SpellRay { - private static final int baseDuration = 400; + private static final int BASE_DURATION = 400; public Cobwebs(){ - super(Tier.ADVANCED, 30, Element.EARTH, "cobwebs", SpellType.ATTACK, 70, EnumAction.NONE, false); + super("cobwebs", Tier.ADVANCED, Element.EARTH, SpellType.ATTACK, 30, 70, false, 12, SoundEvents.BLOCK_LAVA_EXTINGUISH); + this.ignoreEntities(true); } + @Override public boolean doesSpellRequirePacket(){ return false; } + @Override - public boolean doesSpellRequirePacket(){ + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + boolean flag = false; + + pos = pos.offset(side); - RayTraceResult rayTrace = WizardryUtilities.rayTrace(12 * modifiers.get(WizardryItems.range_upgrade), world, - caster, true); + if(world.isAirBlock(pos)){ + if(!world.isRemote){ + world.setBlockState(pos, WizardryBlocks.vanishing_cobweb.getDefaultState()); + if(world.getTileEntity(pos) instanceof TileEntityTimer){ + ((TileEntityTimer)world.getTileEntity(pos)) + .setLifetime((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); + } + } + flag = true; + } - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ + for(EnumFacing facing : EnumFacing.values()){ - boolean flag = false; + BlockPos pos1 = pos.offset(facing); - BlockPos pos = rayTrace.getBlockPos().offset(rayTrace.sideHit); - - if(world.isAirBlock(pos)){ + if(world.isAirBlock(pos1)){ if(!world.isRemote){ - world.setBlockState(pos, WizardryBlocks.vanishing_cobweb.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityTimer){ - ((TileEntityTimer)world.getTileEntity(pos)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); + world.setBlockState(pos1, WizardryBlocks.vanishing_cobweb.getDefaultState()); + if(world.getTileEntity(pos1) instanceof TileEntityTimer){ + ((TileEntityTimer)world.getTileEntity(pos1)) + .setLifetime((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); } } flag = true; } - - for(EnumFacing side : EnumFacing.values()){ - - BlockPos pos1 = pos.offset(side); - - if(world.isAirBlock(pos1)){ - if(!world.isRemote){ - world.setBlockState(pos1, WizardryBlocks.vanishing_cobweb.getDefaultState()); - if(world.getTileEntity(pos1) instanceof TileEntityTimer){ - ((TileEntityTimer)world.getTileEntity(pos1)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - } - flag = true; - } - } - - if(flag){ - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_LAVA_EXTINGUISH, 1.0f, 1.0f); - return true; - } } - return false; + + return flag; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - int x = MathHelper.floor(target.posX); - int y = (int)target.getEntityBoundingBox().minY; - int z = MathHelper.floor(target.posZ); - - boolean flag = false; - - BlockPos pos = new BlockPos(x, y, z); - - if(world.isAirBlock(pos)){ - if(!world.isRemote){ - world.setBlockState(pos, WizardryBlocks.vanishing_cobweb.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityTimer){ - ((TileEntityTimer)world.getTileEntity(pos)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - } - flag = true; - } - - for(EnumFacing side : EnumFacing.values()){ - - BlockPos pos1 = pos.offset(side); - - if(world.isAirBlock(pos1)){ - if(!world.isRemote){ - world.setBlockState(pos1, WizardryBlocks.vanishing_cobweb.getDefaultState()); - if(world.getTileEntity(pos1) instanceof TileEntityTimer){ - ((TileEntityTimer)world.getTileEntity(pos1)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - } - flag = true; - } - } - - if(flag){ - caster.swingArm(hand); - caster.playSound(SoundEvents.BLOCK_LAVA_EXTINGUISH, 1.0f, 1.0f); - return true; - } - } + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } - @Override - public boolean canBeCastByNPCs(){ - return true; - } - } diff --git a/src/main/java/electroblob/wizardry/spell/ConjureArmour.java b/src/main/java/electroblob/wizardry/spell/ConjureArmour.java index 7a9f14a1..9ae9ce91 100644 --- a/src/main/java/electroblob/wizardry/spell/ConjureArmour.java +++ b/src/main/java/electroblob/wizardry/spell/ConjureArmour.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -8,31 +7,25 @@ import electroblob.wizardry.item.IConjuredItem; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; -import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; -public class ConjureArmour extends Spell { +public class ConjureArmour extends SpellConjuration { public ConjureArmour(){ - super(Tier.ADVANCED, 45, Element.HEALING, "conjure_armour", SpellType.DEFENCE, 50, EnumAction.BOW, false); + super("conjure_armour", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 45, 50, null, WizardrySounds.SPELL_CONJURATION); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - + protected boolean conjureItem(EntityPlayer caster, SpellModifiers modifiers){ + ItemStack armour; boolean flag = false; - // A blank "ench" tag is set to trick the renderer into showing the enchantment effect on the actual armour model. - - // Used this rather than getArmorInventoryList because I need to access the slot itself. + // Used this rather than getArmorInventoryList because I need to access the slot itself for(EntityEquipmentSlot slot : WizardryUtilities.ARMOUR_SLOTS){ if(caster.getItemStackFromSlot(slot).isEmpty() && @@ -40,28 +33,13 @@ public class ConjureArmour extends Spell { armour = new ItemStack(WizardryItems.SPECTRAL_ARMOUR_MAP.get(slot)); IConjuredItem.setDurationMultiplier(armour, modifiers.get(WizardryItems.duration_upgrade)); + // Sets a blank "ench" tag to trick the renderer into showing the enchantment effect on the armour model armour.getTagCompound().setTag("ench", new NBTTagList()); caster.setItemStackToSlot(slot, armour); flag = true; } } - - if(flag){ - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.7f, 0.9f, 1.0f); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); - } - + return flag; } diff --git a/src/main/java/electroblob/wizardry/spell/ConjureBow.java b/src/main/java/electroblob/wizardry/spell/ConjureBow.java deleted file mode 100644 index 488327bd..00000000 --- a/src/main/java/electroblob/wizardry/spell/ConjureBow.java +++ /dev/null @@ -1,60 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.item.IConjuredItem; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class ConjureBow extends Spell { - - public ConjureBow(){ - super(Tier.APPRENTICE, 40, Element.SORCERY, "conjure_bow", SpellType.UTILITY, 50, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - ItemStack bow = new ItemStack(WizardryItems.spectral_bow); - - IConjuredItem.setDurationMultiplier(bow, modifiers.get(WizardryItems.duration_upgrade)); - - if(!WizardryUtilities.doesPlayerHaveItem(caster, WizardryItems.spectral_bow) - && conjureItemInInventory(caster, bow)){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - if(world.isRemote){ - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.7f, 0.9f, 1.0f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); - return true; - } - return false; - } - - // TODO: When spells get superclassed, this method needs to be in the conjuration superclass. - /** Adds the given item to the given player's inventory, placing it in the main hand if the main hand is empty. */ - public static boolean conjureItemInInventory(EntityPlayer caster, ItemStack item){ - if(caster.getHeldItemMainhand().isEmpty()){ - caster.setHeldItem(EnumHand.MAIN_HAND, item); - return true; - }else{ - return caster.inventory.addItemStackToInventory(item); - } - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/ConjurePickaxe.java b/src/main/java/electroblob/wizardry/spell/ConjurePickaxe.java deleted file mode 100644 index 9e51ef3a..00000000 --- a/src/main/java/electroblob/wizardry/spell/ConjurePickaxe.java +++ /dev/null @@ -1,50 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.item.IConjuredItem; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class ConjurePickaxe extends Spell { - - public ConjurePickaxe(){ - super(Tier.APPRENTICE, 25, Element.SORCERY, "conjure_pickaxe", SpellType.UTILITY, 50, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - ItemStack pickaxe = new ItemStack(WizardryItems.spectral_pickaxe); - - IConjuredItem.setDurationMultiplier(pickaxe, modifiers.get(WizardryItems.duration_upgrade)); - - if(!WizardryUtilities.doesPlayerHaveItem(caster, WizardryItems.spectral_pickaxe) - && ConjureBow.conjureItemInInventory(caster, pickaxe)){ - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.7f, 0.9f, 1.0f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); - return true; - } - return false; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/ConjureSword.java b/src/main/java/electroblob/wizardry/spell/ConjureSword.java deleted file mode 100644 index a9876cfa..00000000 --- a/src/main/java/electroblob/wizardry/spell/ConjureSword.java +++ /dev/null @@ -1,49 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.item.IConjuredItem; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class ConjureSword extends Spell { - - public ConjureSword(){ - super(Tier.APPRENTICE, 25, Element.SORCERY, "conjure_sword", SpellType.UTILITY, 50, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - ItemStack sword = new ItemStack(WizardryItems.spectral_sword); - - IConjuredItem.setDurationMultiplier(sword, modifiers.get(WizardryItems.duration_upgrade)); - - if(!WizardryUtilities.doesPlayerHaveItem(caster, WizardryItems.spectral_sword) - && ConjureBow.conjureItemInInventory(caster, sword)){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - if(world.isRemote){ - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.7f, 0.9f, 1.0f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); - return true; - } - return false; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/CureEffects.java b/src/main/java/electroblob/wizardry/spell/CureEffects.java index 6597a7a6..d0f4a372 100644 --- a/src/main/java/electroblob/wizardry/spell/CureEffects.java +++ b/src/main/java/electroblob/wizardry/spell/CureEffects.java @@ -1,77 +1,28 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; -public class CureEffects extends Spell { +public class CureEffects extends SpellBuff { public CureEffects(){ - super(Tier.APPRENTICE, 25, Element.HEALING, "cure_effects", SpellType.DEFENCE, 40, EnumAction.BOW, false); + super("cure_effects", Tier.APPRENTICE, Element.HEALING, SpellType.DEFENCE, 25, 40, WizardrySounds.SPELL_HEAL, 0.8f, 0.8f, 1); + this.soundValues(0.7f, 1.2f, 0.4f); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.6f, 0.6f, 1.0f); - } - } - + protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ + if(!caster.getActivePotionEffects().isEmpty()){ caster.clearActivePotions(); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); return true; } - // Fixes the sound not playing in first person. - if(world.isRemote) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - + return false; } - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!caster.getActivePotionEffects().isEmpty()){ - caster.clearActivePotions(); - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)caster.posY + caster.getEyeHeight() - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.6f, 0.6f, 1.0f); - } - } - caster.playSound(WizardrySounds.SPELL_HEAL, 0.7F, world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - } diff --git a/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java b/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java index 8baa67aa..4936395a 100644 --- a/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java +++ b/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java @@ -1,71 +1,63 @@ package electroblob.wizardry.spell; import electroblob.wizardry.WizardData; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.IElementalDamage; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber -public class CurseOfSoulbinding extends Spell { +public class CurseOfSoulbinding extends SpellRay { public CurseOfSoulbinding(){ - super(Tier.ADVANCED, 35, Element.NECROMANCY, "curse_of_soulbinding", SpellType.ATTACK, 100, EnumAction.NONE, - false); + super("curse_of_soulbinding", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 35, 100, false, 10, SoundEvents.ENTITY_WITHER_SPAWN); + this.soundValues(1, 1.1f, 0.2f); + } + + @Override public boolean canBeCastByNPCs() { return false; } + + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target) && caster instanceof EntityPlayer + && WizardData.get((EntityPlayer)caster) != null){ + // Return false if soulbinding failed (e.g. if the target is already soulbound) + if(!WizardData.get((EntityPlayer)caster).soulbind((EntityLivingBase)target)) return false; + } + + return true; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY - && WizardryUtilities.isLiving(rayTrace.entityHit) && WizardData.get(caster) != null){ - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - if(!WizardData.get(caster).soulbind(target)) return false; - } - - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - // world.spawnParticle("mobSpell", x1, y1, z1, -1*look.xCoord, -1*look.yCoord, -1*look.zCoord); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0, - 0.4f, 0.0f, 0.0f); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0, - 0.1f, 0.0f, 0.0f); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 1.0f, 0.8f, 1.0f); - } - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.4f, 0, 0).spawn(world); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0, 0).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(1, 0.8f, 1).spawn(world); + } @SubscribeEvent public static void onLivingHurtEvent(LivingHurtEvent event){ diff --git a/src/main/java/electroblob/wizardry/spell/DarknessOrb.java b/src/main/java/electroblob/wizardry/spell/DarknessOrb.java deleted file mode 100644 index df098a99..00000000 --- a/src/main/java/electroblob/wizardry/spell/DarknessOrb.java +++ /dev/null @@ -1,68 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityDarknessOrb; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class DarknessOrb extends Spell { - - public DarknessOrb(){ - super(Tier.ADVANCED, 20, Element.NECROMANCY, "darkness_orb", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityDarknessOrb darknessorb = new EntityDarknessOrb(world, caster, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(darknessorb); - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - caster.swingArm(hand); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityDarknessOrb darknessorb = new EntityDarknessOrb(world, caster, - modifiers.get(SpellModifiers.DAMAGE)); - darknessorb.directTowards(target, 0.5f); - world.spawnEntity(darknessorb); - } - - caster.playSound(SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - caster.swingArm(hand); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Darkvision.java b/src/main/java/electroblob/wizardry/spell/Darkvision.java deleted file mode 100644 index 40b829e8..00000000 --- a/src/main/java/electroblob/wizardry/spell/Darkvision.java +++ /dev/null @@ -1,45 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Darkvision extends Spell { - - public Darkvision(){ - super(Tier.APPRENTICE, 20, Element.EARTH, "darkvision", SpellType.UTILITY, 40, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - caster.addPotionEffect(new PotionEffect(MobEffects.NIGHT_VISION, - (int)(900 * modifiers.get(WizardryItems.duration_upgrade)), 0, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.0f, 0.4f, 0.7f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Dart.java b/src/main/java/electroblob/wizardry/spell/Dart.java deleted file mode 100644 index fd74e549..00000000 --- a/src/main/java/electroblob/wizardry/spell/Dart.java +++ /dev/null @@ -1,67 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityDart; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Dart extends Spell { - - public Dart(){ - super(Tier.BASIC, 5, Element.EARTH, "dart", SpellType.ATTACK, 10, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityDart dart = new EntityDart(world, caster, 2 * modifiers.get(WizardryItems.range_upgrade), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(dart); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ARROW_SHOOT, 0.5F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityDart dart = new EntityDart(world, caster, target, 2 * modifiers.get(WizardryItems.range_upgrade), - 2, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(dart); - } - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_ARROW_SHOOT, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Decay.java b/src/main/java/electroblob/wizardry/spell/Decay.java index eca8d586..598a09c6 100644 --- a/src/main/java/electroblob/wizardry/spell/Decay.java +++ b/src/main/java/electroblob/wizardry/spell/Decay.java @@ -7,94 +7,39 @@ import electroblob.wizardry.entity.construct.EntityDecay; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -public class Decay extends Spell { +public class Decay extends SpellConstructRanged { + + private static final int BASE_SPAWN_COUNT = 5; public Decay(){ - super(Tier.ADVANCED, 50, Element.NECROMANCY, "decay", SpellType.ATTACK, 200, EnumAction.NONE, false); + super("decay", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 50, 200, EntityDecay::new, 400, 12, SoundEvents.ENTITY_WITHER_SHOOT); + this.soundValues(1, 1.1f, 0.1f); + this.floor(true); + this.overlap(true); } @Override - public boolean doesSpellRequirePacket(){ - return false; - } + protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + + if(world.getBlockState(new BlockPos(x, y, z)).isNormalCube()) return false; + + super.spawnConstruct(world, x, y, z, caster, modifiers); + + int quantity = (int)(BASE_SPAWN_COUNT * modifiers.get(WizardryItems.blast_upgrade)); + int horizontalRange = (int)(2 * modifiers.get(WizardryItems.blast_upgrade)); + int verticalRange = (int)(6 * modifiers.get(WizardryItems.blast_upgrade)); - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(12 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = rayTrace.getBlockPos(); - - if(world.getBlockState(pos.up()).isNormalCube()) return false; - - if(!world.isRemote){ - - world.spawnEntity(new EntityDecay(world, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, caster)); - - for(int i = 0; i < 5; i++){ - BlockPos pos1 = WizardryUtilities.findNearbyFloorSpace(caster, 2, 6); - if(pos1 == null) break; - world.spawnEntity( - new EntityDecay(world, pos1.getX() + 0.5, pos1.getY(), pos1.getZ() + 0.5, caster)); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - caster.swingArm(hand); - return true; + for(int i=0; i targets = WizardryUtilities.getEntitiesWithinRadius( - 3.0d * modifiers.get(WizardryItems.blast_upgrade), (rayTrace.hitVec.x + 0.5), - (rayTrace.hitVec.y + 0.5), (rayTrace.hitVec.z + 0.5), world); - for(int i = 0; i < targets.size(); i++){ - targets.get(i).attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.BLAST), - // Damage decreases with distance but cannot be less than 0, naturally. - Math.max(12.0f - (float)((EntityLivingBase)targets.get(i)).getDistance( - (rayTrace.hitVec.x + 0.5), (rayTrace.hitVec.y + 0.5), - (rayTrace.hitVec.z + 0.5)) * 4, 0) * modifiers.get(SpellModifiers.DAMAGE)); - - } - } - if(world.isRemote){ - double dx = (rayTrace.hitVec.x + 0.5) - caster.posX; - double dy = (rayTrace.hitVec.y + 0.5) - WizardryUtilities.getPlayerEyesPos(caster); - double dz = (rayTrace.hitVec.z + 0.5) - caster.posZ; - world.spawnParticle(EnumParticleTypes.EXPLOSION_HUGE, (rayTrace.hitVec.x + 0.5), - (rayTrace.hitVec.y + 0.5), (rayTrace.hitVec.z + 0.5), 0, 0, 0); - for(int i = 1; i < 5; i++){ - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - } - } - world.playSound(caster, (rayTrace.hitVec.x + 0.5), (rayTrace.hitVec.y + 0.5), - (rayTrace.hitVec.z + 0.5), SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 4.0F, - (1.0F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.2F) * 0.7F); - caster.swingArm(hand); - return true; - } + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - if(!world.isRemote){ - List targets = WizardryUtilities.getEntitiesWithinRadius(3.0d, target.posX, - target.posY, target.posZ, world); - for(int i = 0; i < targets.size(); i++){ - targets.get(i).attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.BLAST), - // Damage decreases with distance but cannot be less than 0, naturally. - Math.max(12.0f - (float)((EntityLivingBase)targets.get(i)).getDistance(target.posX, - target.posY, target.posZ) * 4, 0) * modifiers.get(SpellModifiers.DAMAGE)); - - } + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(!world.isRemote){ + + List targets = WizardryUtilities.getEntitiesWithinRadius( + BASE_RADIUS * modifiers.get(WizardryItems.blast_upgrade), pos.getX(), pos.getY(), pos.getZ(), world); + + for(EntityLivingBase target : targets){ + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.BLAST), + // Damage decreases with distance but cannot be less than 0, naturally. + Math.max(12.0f - (float)target.getDistance(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5) + * 4, 0) * modifiers.get(SpellModifiers.POTENCY)); } - if(world.isRemote){ - double dx = target.posX - caster.posX; - double dy = target.posY - (caster.posY + caster.getEyeHeight()); - double dz = target.posZ - caster.posZ; - world.spawnParticle(EnumParticleTypes.EXPLOSION_HUGE, target.posX, target.posY, target.posZ, 0, 0, 0); - for(int i = 1; i < 5; i++){ - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - caster.posY + caster.getEyeHeight() + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - caster.posY + caster.getEyeHeight() + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - } - } - // Player is null here because the sound was not caused by a player. - world.playSound(null, target.posX, target.posY, target.posZ, SoundEvents.ENTITY_GENERIC_EXPLODE, - SoundCategory.BLOCKS, 4.0F, - (1.0F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.2F) * 0.7F); - caster.swingArm(hand); - return true; + + }else{ + world.spawnParticle(EnumParticleTypes.EXPLOSION_HUGE, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 0, 0, 0); } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ + return true; } + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + world.spawnParticle(EnumParticleTypes.FLAME, x, y, z, 0, 0, 0); + } + } diff --git a/src/main/java/electroblob/wizardry/spell/Diamondflesh.java b/src/main/java/electroblob/wizardry/spell/Diamondflesh.java deleted file mode 100644 index 848f4a68..00000000 --- a/src/main/java/electroblob/wizardry/spell/Diamondflesh.java +++ /dev/null @@ -1,53 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Diamondflesh extends Spell { - - public Diamondflesh(){ - super(Tier.MASTER, 100, Element.HEALING, "diamondflesh", SpellType.DEFENCE, 300, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - caster.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 4, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.0f, 0.5f, 1.0f); - - x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.6f, 0.7f, 0.9f); - - } - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Earthquake.java b/src/main/java/electroblob/wizardry/spell/Earthquake.java index b712f6ac..344b3d52 100644 --- a/src/main/java/electroblob/wizardry/spell/Earthquake.java +++ b/src/main/java/electroblob/wizardry/spell/Earthquake.java @@ -1,4 +1,4 @@ -package electroblob.wizardry.spell; + package electroblob.wizardry.spell; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; @@ -10,54 +10,54 @@ import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; import net.minecraft.world.World; -public class Earthquake extends Spell { +public class Earthquake extends SpellConstruct { public Earthquake(){ - super(Tier.MASTER, 75, Element.EARTH, "earthquake", SpellType.ATTACK, 250, EnumAction.NONE, false); + super("earthquake", Tier.MASTER, Element.EARTH, SpellType.ATTACK, 75, 250, EnumAction.NONE, EntityEarthquake::new, -1, WizardrySounds.SPELL_EARTHQUAKE); + this.soundValues(2, 1, 0); + this.overlap(true); + this.floor(true); } - + + // This one spawns particles + @Override public boolean doesSpellRequirePacket(){ return true; } + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + protected void addConstructExtras(EntityEarthquake construct, EntityLivingBase caster, SpellModifiers modifiers){ + construct.lifetime = (int)(20 * modifiers.get(WizardryItems.blast_upgrade)); + } + + @Override + protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + + // TODO: Couldn't this be moved to EntityEarthquake? + if(world.isRemote){ - if(caster.onGround){ + world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, caster.posX, + caster.getEntityBoundingBox().minY + 0.1, caster.posZ, 0, 0, 0); - if(!world.isRemote){ - world.spawnEntity(new EntityEarthquake(world, caster.posX, caster.getEntityBoundingBox().minY, - caster.posZ, caster, (int)(20 * modifiers.get(WizardryItems.blast_upgrade)), - modifiers.get(SpellModifiers.DAMAGE))); - }else{ + double particleX, particleZ; - world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, caster.posX, - caster.getEntityBoundingBox().minY + 0.1, caster.posZ, 0, 0, 0); + for(int i=0; i<40; i++){ - double particleX, particleZ; + particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); + particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - for(int i = 0; i < 40; i++){ - - particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); - particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - - IBlockState block = WizardryUtilities.getBlockEntityIsStandingOn(caster); - if(block != null){ - world.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, caster.getEntityBoundingBox().minY, - particleZ, particleX - caster.posX, 0, particleZ - caster.posZ, - Block.getStateId(block)); - } + IBlockState block = WizardryUtilities.getBlockEntityIsStandingOn(caster); + if(block != null){ + world.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, caster.getEntityBoundingBox().minY, + particleZ, particleX - caster.posX, 0, particleZ - caster.posZ, + Block.getStateId(block)); } } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_EARTHQUAKE, 2, 1); - caster.swingArm(hand); - - return true; } - return false; + + return super.spawnConstruct(world, x, y, z, caster, modifiers); } } diff --git a/src/main/java/electroblob/wizardry/spell/Entrapment.java b/src/main/java/electroblob/wizardry/spell/Entrapment.java index db7503a0..2b7f8c30 100644 --- a/src/main/java/electroblob/wizardry/spell/Entrapment.java +++ b/src/main/java/electroblob/wizardry/spell/Entrapment.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -8,112 +7,63 @@ import electroblob.wizardry.entity.construct.EntityBubble; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class Entrapment extends Spell { +public class Entrapment extends SpellRay { public Entrapment(){ - super(Tier.ADVANCED, 35, Element.NECROMANCY, "entrapment", SpellType.ATTACK, 75, EnumAction.NONE, false); + super("entrapment", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 35, 75, false, 10, SoundEvents.ENTITY_WITHER_SHOOT); + this.soundValues(1, 0.85f, 0.3f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - EntityLivingBase entity = (EntityLivingBase)rayTrace.entityHit; + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + if(!world.isRemote){ - entity.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), - 1.0f * modifiers.get(SpellModifiers.DAMAGE)); - - EntityBubble entitybubble = new EntityBubble(world, entity.posX, entity.posY, entity.posZ, caster, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), true, - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(entitybubble); - entity.startRiding(entitybubble); + // Deals a small amount damage so the target counts as being hit by the caster + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), 1); + + EntityBubble bubble = new EntityBubble(world); + bubble.setPosition(target.posX, target.posY, target.posZ); + bubble.setCaster(caster); + bubble.lifetime = ((int)(200 * modifiers.get(WizardryItems.duration_upgrade))); + bubble.isDarkOrb = true; + bubble.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + + world.spawnEntity(bubble); + target.startRiding(bubble); } } - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - world.spawnParticle(EnumParticleTypes.PORTAL, x1, y1 - 0.5, z1, 0.0d, 0.0d, 0.0d); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0, - 0.1f, 0.0f, 0.0f); - } - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, - world.rand.nextFloat() * 0.3F + 0.7F); + return true; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), - 1.0f * modifiers.get(SpellModifiers.DAMAGE)); - // Deprecated in favour of entity riding method - // entity.addPotionEffect(new PotionEffect(Wizardry.bubblePotion, 200, 0)); - EntityBubble entitybubble = new EntityBubble(world, target.posX, target.posY, target.posZ, caster, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), true, - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(entitybubble); - target.startRiding(entitybubble); - - } - if(world.isRemote){ - - double dx = (target.posX - caster.posX) / caster.getDistance(target); - double dy = (target.posY - caster.posY) / caster.getDistance(target); - double dz = (target.posZ - caster.posZ) / caster.getDistance(target); - - for(int i = 1; i < 25; i += 2){ - - double x1 = caster.posX + dx * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + dy * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + dz * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - world.spawnParticle(EnumParticleTypes.PORTAL, x1, y1 - 0.5, z1, 0.0d, 0.0d, 0.0d); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 0, 0.1f, 0.0f, 0.0f); - } - } - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, world.rand.nextFloat() * 0.3F + 0.7F); - return true; - } - + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean canBeCastByNPCs(){ + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + world.spawnParticle(EnumParticleTypes.PORTAL, x, y - 0.5, z, 0, 0, 0); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0, 0).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/FireResistance.java b/src/main/java/electroblob/wizardry/spell/FireResistance.java deleted file mode 100644 index 42596b3b..00000000 --- a/src/main/java/electroblob/wizardry/spell/FireResistance.java +++ /dev/null @@ -1,78 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class FireResistance extends Spell { - - public FireResistance(){ - super(Tier.ADVANCED, 20, Element.FIRE, "fire_resistance", SpellType.DEFENCE, 80, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - caster.addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 0.5f, 0.0f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - // Like witches, wizards who have this spell will only cast it if they are on fire. - if(caster.isBurning() && !caster.isPotionActive(MobEffects.FIRE_RESISTANCE)){ - - caster.addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)caster.posY + caster.getEyeHeight() - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 0.5f, 0.0f); - } - } - caster.playSound(WizardrySounds.SPELL_HEAL, 0.7F, world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/FireSigil.java b/src/main/java/electroblob/wizardry/spell/FireSigil.java deleted file mode 100644 index 7d4d0b0f..00000000 --- a/src/main/java/electroblob/wizardry/spell/FireSigil.java +++ /dev/null @@ -1,51 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityFireSigil; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.world.World; - -public class FireSigil extends Spell { - - public FireSigil(){ - super(Tier.APPRENTICE, 10, Element.FIRE, "fire_sigil", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(10 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK && rayTrace.sideHit == EnumFacing.UP){ - if(!world.isRemote){ - double x = rayTrace.hitVec.x; - double y = rayTrace.hitVec.y; - double z = rayTrace.hitVec.z; - EntityFireSigil firesigil = new EntityFireSigil(world, x, y, z, caster, - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(firesigil); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ITEM_FLINTANDSTEEL_USE, 1.0F, 1.0F); - return true; - } - return false; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Fireball.java b/src/main/java/electroblob/wizardry/spell/Fireball.java index 83e680b2..08ecb170 100644 --- a/src/main/java/electroblob/wizardry/spell/Fireball.java +++ b/src/main/java/electroblob/wizardry/spell/Fireball.java @@ -18,7 +18,7 @@ import net.minecraft.world.World; public class Fireball extends Spell { public Fireball(){ - super(Tier.APPRENTICE, 10, Element.FIRE, "fireball", SpellType.ATTACK, 15, EnumAction.NONE, false); + super("fireball", Tier.APPRENTICE, Element.FIRE, SpellType.ATTACK, 10, 15, EnumAction.NONE, false); // Does 2.5 hearts of damage and 5 seconds of fire, for reference. } diff --git a/src/main/java/electroblob/wizardry/spell/Firebolt.java b/src/main/java/electroblob/wizardry/spell/Firebolt.java deleted file mode 100644 index f81804b1..00000000 --- a/src/main/java/electroblob/wizardry/spell/Firebolt.java +++ /dev/null @@ -1,69 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityFirebolt; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Firebolt extends Spell { - - public Firebolt(){ - super(Tier.APPRENTICE, 10, Element.FIRE, "firebolt", SpellType.ATTACK, 10, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityFirebolt firebolt = new EntityFirebolt(world, caster, modifiers.get(SpellModifiers.DAMAGE)); - firebolt.motionX *= 2.5; - firebolt.motionY *= 2.5; - firebolt.motionZ *= 2.5; - world.spawnEntity(firebolt); - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - caster.swingArm(hand); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityFirebolt firebolt = new EntityFirebolt(world, caster, modifiers.get(SpellModifiers.DAMAGE)); - firebolt.directTowards(target, 2.5f); - world.spawnEntity(firebolt); - } - - caster.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - caster.swingArm(hand); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Firebomb.java b/src/main/java/electroblob/wizardry/spell/Firebomb.java deleted file mode 100644 index 6a95a583..00000000 --- a/src/main/java/electroblob/wizardry/spell/Firebomb.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityFirebomb; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Firebomb extends Spell { - - public Firebomb(){ - super(Tier.APPRENTICE, 15, Element.FIRE, "firebomb", SpellType.ATTACK, 25, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityFirebomb firebomb = new EntityFirebomb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - world.spawnEntity(firebomb); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityFirebomb firebomb = new EntityFirebomb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - firebomb.directTowards(target, 1.5f); - world.spawnEntity(firebomb); - } - - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Fireskin.java b/src/main/java/electroblob/wizardry/spell/Fireskin.java deleted file mode 100644 index 20f4497f..00000000 --- a/src/main/java/electroblob/wizardry/spell/Fireskin.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Fireskin extends Spell { - - public Fireskin(){ - super(Tier.ADVANCED, 40, Element.FIRE, "fireskin", SpellType.DEFENCE, 250, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - // Cannot be cast when it has already been cast - if(!caster.isPotionActive(WizardryPotions.fireskin)){ - if(!world.isRemote){ - caster.addPotionEffect(new PotionEffect(WizardryPotions.fireskin, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - return true; - } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - // Cannot be cast when it has already been cast - if(!caster.isPotionActive(WizardryPotions.fireskin)){ - if(!world.isRemote){ - caster.addPotionEffect(new PotionEffect(WizardryPotions.fireskin, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - } - caster.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - return true; - } - return false; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Firestorm.java b/src/main/java/electroblob/wizardry/spell/Firestorm.java index baf1d219..55bdd341 100644 --- a/src/main/java/electroblob/wizardry/spell/Firestorm.java +++ b/src/main/java/electroblob/wizardry/spell/Firestorm.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -8,83 +7,103 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class Firestorm extends Spell { +public class Firestorm extends SpellRay { + + private static final float BASE_DAMAGE = 6; + /** The base duration for which entities are set on fire by this spell. */ + private static final int BASE_DURATION = 10; public Firestorm(){ - super(Tier.MASTER, 15, Element.FIRE, "firestorm", SpellType.ATTACK, 0, EnumAction.NONE, true); + super("firestorm", Tier.MASTER, Element.FIRE, SpellType.ATTACK, 15, 0, true, 10, null); + this.particleVelocity(1); + this.particleDither(0.3); + this.particleSpacing(0.25); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + // Temporary solution until I implement a better continuous sound system + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag){ + if(ticksInUse % 16 == 0){ + if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_FIRE, 0.5f, 1.0f); + } + } + return flag; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag){ + if(ticksInUse % 16 == 0){ + if(ticksInUse == 0) caster.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); + caster.playSound(WizardrySounds.SPELL_LOOP_FIRE, 0.5f, 1.0f); + } + } + return flag; + } - Vec3d look = caster.getLookVec(); + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + // Fire can damage armour stands + if(target instanceof EntityLivingBase){ - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - // Fire can damage armour stands. - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && rayTrace.entityHit instanceof EntityLivingBase){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - - if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)){ - target.setFire(10); - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), - 6.0f * modifiers.get(SpellModifiers.DAMAGE)); - }else{ + if(MagicDamage.isEntityImmune(DamageType.FIRE, target)){ if(!world.isRemote && ticksInUse == 1) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted())); + }else{ + target.setFire((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); + WizardryUtilities.attackEntityWithoutKnockback(target, + MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), + BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); } - - }else if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = rayTrace.getBlockPos().offset(rayTrace.sideHit); - - if(world.isAirBlock(pos)){ - if(!world.isRemote){ - world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - } - } + + return true; } + + return false; + } - if(world.isRemote){ - for(int i = 0; i < 40; i++){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() * 0.6f - 0.3f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() * 0.4f - 0.2f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() * 0.6f - 0.3f; - Wizardry.proxy.spawnParticle(Type.MAGIC_FIRE, world, x1, y1, z1, - look.x * modifiers.get(WizardryItems.range_upgrade), - look.y * modifiers.get(WizardryItems.range_upgrade), - look.z * modifiers.get(WizardryItems.range_upgrade), 0, 3 + world.rand.nextFloat(), 0, 0); - Wizardry.proxy.spawnParticle(Type.MAGIC_FIRE, world, x1, y1, z1, - look.x * modifiers.get(WizardryItems.range_upgrade), - look.y * modifiers.get(WizardryItems.range_upgrade), - look.z * modifiers.get(WizardryItems.range_upgrade), 0, 3 + world.rand.nextFloat(), 0, 0); - } - } - if(ticksInUse % 16 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_FIRE, 0.5F, 1.0f); + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + pos = pos.offset(side); + + if(world.isAirBlock(pos)){ + if(!world.isRemote) world.setBlockState(pos, Blocks.FIRE.getDefaultState()); + return true; } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).scale(3 + world.rand.nextFloat()).spawn(world); + ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).scale(3 + world.rand.nextFloat()).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/FlameRay.java b/src/main/java/electroblob/wizardry/spell/FlameRay.java index c6d6d47c..71e686fd 100644 --- a/src/main/java/electroblob/wizardry/spell/FlameRay.java +++ b/src/main/java/electroblob/wizardry/spell/FlameRay.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -8,106 +7,71 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class FlameRay extends Spell { +public class FlameRay extends SpellRay { + + private static final float BASE_DAMAGE = 3; + /** The base duration for which entities are set on fire by this spell. */ + private static final int BASE_DURATION = 10; public FlameRay(){ - super(Tier.APPRENTICE, 5, Element.FIRE, "flame_ray", SpellType.ATTACK, 0, EnumAction.NONE, true); + super("flame_ray", Tier.APPRENTICE, Element.FIRE, SpellType.ATTACK, 5, 0, true, 10, null); + this.particleVelocity(1); + this.particleSpacing(0.5); } - + @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - // Fire can damage armour stands - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && rayTrace.entityHit instanceof EntityLivingBase){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - - if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)){ - target.setFire(10); - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); - }else{ - if(!world.isRemote && ticksInUse == 1) caster.sendMessage(new TextComponentTranslation("spell.resist", - target.getName(), this.getNameForTranslationFormatted())); + // TODO: Temporary solution until I implement a better continuous sound system + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag){ + if(ticksInUse % 16 == 0){ + if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_FIRE, 0.5f, 1.0f); } } - if(world.isRemote){ - for(int i = 0; i < 20; i++){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.MAGIC_FIRE, world, x1, y1, z1, - look.x * modifiers.get(WizardryItems.range_upgrade), - look.y * modifiers.get(WizardryItems.range_upgrade), - look.z * modifiers.get(WizardryItems.range_upgrade), 0); - Wizardry.proxy.spawnParticle(Type.MAGIC_FIRE, world, x1, y1, z1, - look.x * modifiers.get(WizardryItems.range_upgrade), - look.y * modifiers.get(WizardryItems.range_upgrade), - look.z * modifiers.get(WizardryItems.range_upgrade), 0); - } - } - if(ticksInUse % 16 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_FIRE, 0.5F, 1.0f); - } - return true; + return flag; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - Vec3d vec = new Vec3d(target.posX - caster.posX, target.posY - caster.posY, target.posZ - caster.posZ).normalize(); - - target.setFire(10); - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); - - if(world.isRemote){ - for(int i = 0; i < 20; i++){ - double x1 = caster.posX + vec.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + vec.y * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + vec.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.MAGIC_FIRE, world, x1, y1, z1, - vec.x * modifiers.get(WizardryItems.range_upgrade), - vec.y * modifiers.get(WizardryItems.range_upgrade), - vec.z * modifiers.get(WizardryItems.range_upgrade), 0); - Wizardry.proxy.spawnParticle(Type.MAGIC_FIRE, world, x1, y1, z1, - vec.x * modifiers.get(WizardryItems.range_upgrade), - vec.y * modifiers.get(WizardryItems.range_upgrade), - vec.z * modifiers.get(WizardryItems.range_upgrade), 0); - } - } - + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag){ if(ticksInUse % 16 == 0){ if(ticksInUse == 0) caster.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - caster.playSound(WizardrySounds.SPELL_LOOP_FIRE, 0.5F, 1.0f); + caster.playSound(WizardrySounds.SPELL_LOOP_FIRE, 0.5f, 1.0f); + } + } + return flag; + } + + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + // Fire can damage armour stands + if(target instanceof EntityLivingBase){ + + if(MagicDamage.isEntityImmune(DamageType.FIRE, target)){ + if(!world.isRemote && ticksInUse == 1) caster.sendMessage(new TextComponentTranslation("spell.resist", + target.getName(), this.getNameForTranslationFormatted())); + }else { + target.setFire((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); + WizardryUtilities.attackEntityWithoutKnockback(target, + MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE), + BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); } return true; @@ -117,8 +81,19 @@ public class FlameRay extends Spell { } @Override - public boolean canBeCastByNPCs(){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).spawn(world); + ParticleBuilder.create(Type.MAGIC_FIRE).pos(x, y, z).vel(vx, vy, vz).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/FlamingAxe.java b/src/main/java/electroblob/wizardry/spell/FlamingAxe.java index b320de52..33498792 100644 --- a/src/main/java/electroblob/wizardry/spell/FlamingAxe.java +++ b/src/main/java/electroblob/wizardry/spell/FlamingAxe.java @@ -3,48 +3,28 @@ package electroblob.wizardry.spell; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.item.IConjuredItem; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; import net.minecraft.world.World; -public class FlamingAxe extends Spell { +public class FlamingAxe extends SpellConjuration { public FlamingAxe(){ - super(Tier.ADVANCED, 45, Element.FIRE, "flaming_axe", SpellType.UTILITY, 50, EnumAction.BOW, false); + super("flaming_axe", Tier.ADVANCED, Element.FIRE, SpellType.UTILITY, 45, 50, WizardryItems.flaming_axe, SoundEvents.ENTITY_BLAZE_SHOOT); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - ItemStack flamingaxe = new ItemStack(WizardryItems.flaming_axe); - - IConjuredItem.setDurationMultiplier(flamingaxe, modifiers.get(WizardryItems.duration_upgrade)); - - if(!WizardryUtilities.doesPlayerHaveItem(caster, WizardryItems.flaming_axe) - && ConjureBow.conjureItemInInventory(caster, flamingaxe)){ - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - world.spawnParticle(EnumParticleTypes.FLAME, x1, y1, z1, 0, 0, 0); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - return true; + protected void spawnParticles(World world, EntityLivingBase caster, SpellModifiers modifiers){ + + for(int i=0; i<10; i++){ + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + world.spawnParticle(EnumParticleTypes.FLAME, x, y, z, 0, 0, 0); } - return false; } } diff --git a/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java b/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java index b70f491a..f157a8c2 100644 --- a/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java +++ b/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java @@ -1,7 +1,6 @@ package electroblob.wizardry.spell; import electroblob.wizardry.WizardData; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; @@ -9,8 +8,9 @@ import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryEnchantments; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.EntityPlayer; @@ -24,7 +24,7 @@ import net.minecraft.world.World; public class FlamingWeapon extends Spell { public FlamingWeapon(){ - super(Tier.ADVANCED, 35, Element.FIRE, "flaming_weapon", SpellType.UTILITY, 70, EnumAction.BOW, false); + super("flaming_weapon", Tier.ADVANCED, Element.FIRE, SpellType.UTILITY, 35, 70, EnumAction.BOW, false); } @Override @@ -41,21 +41,19 @@ public class FlamingWeapon extends Spell { // The enchantment level as determined by the damage multiplier. The + 0.5f is so that // weird float processing doesn't incorrectly round it down. stack.addEnchantment(WizardryEnchantments.flaming_weapon, - modifiers.get(SpellModifiers.DAMAGE) == 1.0f ? 1 - : (int)((modifiers.get(SpellModifiers.DAMAGE) - 1.0f) + modifiers.get(SpellModifiers.POTENCY) == 1.0f ? 1 + : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) / Constants.DAMAGE_INCREASE_PER_TIER + 0.5f)); WizardData.get(caster).setImbuementDuration(WizardryEnchantments.flaming_weapon, (int)(900 * modifiers.get(WizardryItems.duration_upgrade))); if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.9f, 0.7f, 1.0f); + for(int i=0; i<10; i++){ + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.9f, 0.7f, 1).spawn(world); } } diff --git a/src/main/java/electroblob/wizardry/spell/Flight.java b/src/main/java/electroblob/wizardry/spell/Flight.java index 97db2f9c..70183b00 100644 --- a/src/main/java/electroblob/wizardry/spell/Flight.java +++ b/src/main/java/electroblob/wizardry/spell/Flight.java @@ -1,11 +1,11 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; @@ -16,7 +16,7 @@ import net.minecraft.world.World; public class Flight extends Spell { public Flight(){ - super(Tier.MASTER, 10, Element.EARTH, "flight", SpellType.UTILITY, 0, EnumAction.NONE, true); + super("flight", Tier.MASTER, Element.EARTH, SpellType.UTILITY, 10, 0, EnumAction.NONE, true); } @Override @@ -36,19 +36,22 @@ public class Flight extends Spell { } caster.fallDistance = 0.0f; } + if(world.isRemote){ - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX - 1 + world.rand.nextDouble() * 2, - WizardryUtilities.getPlayerEyesPos(caster) - 0.5f + world.rand.nextDouble(), - caster.posZ - 1 + world.rand.nextDouble() * 2, 0, -0.1F, 0, 15, 0.8f, 1.0f, 0.5f); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX - 1 + world.rand.nextDouble() * 2, - WizardryUtilities.getPlayerEyesPos(caster) - 0.5f + world.rand.nextDouble(), - caster.posZ - 1 + world.rand.nextDouble() * 2, 0, -0.1F, 0, 15, 1.0f, 1.0f, 1.0f); + double x = caster.posX - 1 + world.rand.nextDouble() * 2; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ - 1 + world.rand.nextDouble() * 2; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).lifetime(15).colour(0.8f, 1, 0.5f).spawn(world); + x = caster.posX - 1 + world.rand.nextDouble() * 2; + y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + z = caster.posZ - 1 + world.rand.nextDouble() * 2; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).lifetime(15).colour(1, 1, 1).spawn(world); } + if(ticksInUse % 24 == 0){ WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERDRAGON_FLAP, 0.5F, 1.0f); } + return true; } diff --git a/src/main/java/electroblob/wizardry/spell/FontOfMana.java b/src/main/java/electroblob/wizardry/spell/FontOfMana.java index 3915ae6d..df6f46af 100644 --- a/src/main/java/electroblob/wizardry/spell/FontOfMana.java +++ b/src/main/java/electroblob/wizardry/spell/FontOfMana.java @@ -2,15 +2,15 @@ package electroblob.wizardry.spell; import java.util.List; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; @@ -21,7 +21,7 @@ import net.minecraft.world.World; public class FontOfMana extends Spell { public FontOfMana(){ - super(Tier.MASTER, 100, Element.HEALING, "font_of_mana", SpellType.UTILITY, 250, EnumAction.BOW, false); + super("font_of_mana", Tier.MASTER, Element.HEALING, SpellType.UTILITY, 100, 250, EnumAction.BOW, false); } @Override @@ -37,19 +37,23 @@ public class FontOfMana extends Spell { // calculating this. target.addPotionEffect(new PotionEffect(WizardryPotions.font_of_mana, (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE) > 1 ? 1 : 0)); + modifiers.get(SpellModifiers.POTENCY) > 1 ? 1 : 0)); } } if(world.isRemote){ for(int i = 0; i < 100 * modifiers.get(WizardryItems.blast_upgrade); i++){ + double radius = (1 + world.rand.nextDouble() * 4) * modifiers.get(WizardryItems.blast_upgrade); double angle = world.rand.nextDouble() * Math.PI * 2; float hue = world.rand.nextFloat() * 0.4f; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX + radius * Math.cos(angle), caster.getEntityBoundingBox().minY, - caster.posZ + radius * Math.sin(angle), 0, 0.03, 0, 50, 1, 1 - hue, 0.6f + hue); - + + double x = caster.posX + radius * Math.cos(angle); + double y = caster.getEntityBoundingBox().minY; + double z = caster.posZ + radius * Math.sin(angle); + + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).lifetime(50) + .colour(1, 1 - hue, 0.6f + hue).spawn(world); } } diff --git a/src/main/java/electroblob/wizardry/spell/FontOfVitality.java b/src/main/java/electroblob/wizardry/spell/FontOfVitality.java deleted file mode 100644 index 88f4cec7..00000000 --- a/src/main/java/electroblob/wizardry/spell/FontOfVitality.java +++ /dev/null @@ -1,57 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class FontOfVitality extends Spell { - - public FontOfVitality(){ - super(Tier.MASTER, 75, Element.HEALING, "font_of_vitality", SpellType.DEFENCE, 300, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - caster.addPotionEffect(new PotionEffect(MobEffects.ABSORPTION, - (int)(1200 * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); - caster.addPotionEffect(new PotionEffect(MobEffects.REGENERATION, - (int)(300 * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 0.6f, 0.7f); - - x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 0.8f, 0.3f); - - } - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/ForceArrow.java b/src/main/java/electroblob/wizardry/spell/ForceArrow.java deleted file mode 100644 index f052b43f..00000000 --- a/src/main/java/electroblob/wizardry/spell/ForceArrow.java +++ /dev/null @@ -1,69 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityForceArrow; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class ForceArrow extends Spell { - - public ForceArrow(){ - super(Tier.APPRENTICE, 15, Element.SORCERY, "force_arrow", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityForceArrow forceArrow = new EntityForceArrow(world, caster, - 1 * modifiers.get(WizardryItems.range_upgrade), modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(forceArrow); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_FORCE, 1.0f, - 1.2f + world.rand.nextFloat() * 0.2f); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityForceArrow forceArrow = new EntityForceArrow(world, caster, target, - 1 * modifiers.get(WizardryItems.range_upgrade), 2, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(forceArrow); - } - - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_FORCE, 1.0f, 1.2f + world.rand.nextFloat() * 0.2f); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/ForceOrb.java b/src/main/java/electroblob/wizardry/spell/ForceOrb.java deleted file mode 100644 index 5db4e5fa..00000000 --- a/src/main/java/electroblob/wizardry/spell/ForceOrb.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityForceOrb; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class ForceOrb extends Spell { - - public ForceOrb(){ - super(Tier.ADVANCED, 20, Element.SORCERY, "force_orb", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityForceOrb forceOrb = new EntityForceOrb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - world.spawnEntity(forceOrb); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityForceOrb forceOrb = new EntityForceOrb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - forceOrb.directTowards(target, 1.5f); - world.spawnEntity(forceOrb); - } - - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Forcefield.java b/src/main/java/electroblob/wizardry/spell/Forcefield.java deleted file mode 100644 index eea373b9..00000000 --- a/src/main/java/electroblob/wizardry/spell/Forcefield.java +++ /dev/null @@ -1,73 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityForcefield; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Forcefield extends Spell { - - public Forcefield(){ - super(Tier.ADVANCED, 45, Element.HEALING, "forcefield", SpellType.DEFENCE, 200, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(caster.onGround){ - if(!world.isRemote){ - EntityForcefield forcefield = new EntityForcefield(world, caster.posX, caster.posY, caster.posZ, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(forcefield); - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION_LARGE, 1.0f, 1.0f); - return true; - } - - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - // Wizards can no longer cast forcefield when they are inside one - if(caster.onGround - && world.getEntitiesWithinAABB(EntityForcefield.class, caster.getEntityBoundingBox()).isEmpty()){ - if(!world.isRemote){ - EntityForcefield forcefield = new EntityForcefield(world, caster.posX, caster.posY, caster.posZ, - caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(forcefield); - } - caster.playSound(WizardrySounds.SPELL_CONJURATION_LARGE, 1.0f, 1.0f); - return true; - } - - return false; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/ForestsCurse.java b/src/main/java/electroblob/wizardry/spell/ForestsCurse.java index 44b7a30e..e08bd145 100644 --- a/src/main/java/electroblob/wizardry/spell/ForestsCurse.java +++ b/src/main/java/electroblob/wizardry/spell/ForestsCurse.java @@ -1,76 +1,62 @@ package electroblob.wizardry.spell; -import java.util.List; - -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; import net.minecraft.world.World; -public class ForestsCurse extends Spell { +public class ForestsCurse extends SpellAreaEffect { + + private static final int BASE_DAMAGE = 4; + private static final int BASE_DURATION = 140; public ForestsCurse(){ - super(Tier.MASTER, 75, Element.EARTH, "forests_curse", SpellType.ATTACK, 200, EnumAction.BOW, false); + super("forests_curse", Tier.MASTER, Element.EARTH, SpellType.ATTACK, 75, 200, EnumAction.BOW, 5, SoundEvents.ENTITY_WITHER_SPAWN); + this.soundValues(1, 1.1f, 0.2f); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - List targets = WizardryUtilities.getEntitiesWithinRadius( - 5.0d * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); - - for(EntityLivingBase target : targets){ - if(WizardryUtilities.isValidTarget(caster, target) - && !MagicDamage.isEntityImmune(DamageType.POISON, target)){ - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON), - 4.0f * modifiers.get(SpellModifiers.DAMAGE)); - target.addPotionEffect(new PotionEffect(MobEffects.POISON, - (int)(140 * modifiers.get(WizardryItems.duration_upgrade)), 2)); - target.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, - (int)(140 * modifiers.get(WizardryItems.duration_upgrade)), 2)); - target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, - (int)(140 * modifiers.get(WizardryItems.duration_upgrade)), 2)); - } + protected void affectEntity(World world, EntityLivingBase caster, EntityLivingBase target, SpellModifiers modifiers){ + + if(!MagicDamage.isEntityImmune(DamageType.POISON, target) && WizardryUtilities.isLiving(target)){ + + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON), + BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + + int duration = (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)); + + target.addPotionEffect(new PotionEffect(MobEffects.POISON, duration, 2)); + target.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, duration, 2)); + target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, duration, 2)); } - - if(world.isRemote){ - for(int i = 0; i < 50 * modifiers.get(WizardryItems.blast_upgrade); i++){ - double radius = (1 + world.rand.nextDouble() * 4) * modifiers.get(WizardryItems.blast_upgrade); - double angle = world.rand.nextDouble() * Math.PI * 2; - float brightness = world.rand.nextFloat() / 4; - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, - caster.posX + radius * Math.cos(angle), WizardryUtilities.getPlayerEyesPos(caster) + 0.5, - caster.posZ + radius * Math.sin(angle), 0, -0.2, 0, 0, 0.05f + brightness, 0.2f + brightness, - 0.0f); - brightness = world.rand.nextFloat() / 4; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX + radius * Math.cos(angle), WizardryUtilities.getPlayerEyesPos(caster) + 0.5, - caster.posZ + radius * Math.sin(angle), 0, -0.05, 0, 50, 0.1f + brightness, 0.2f + brightness, - 0.0f); - Wizardry.proxy.spawnParticle(Type.LEAF, world, caster.posX + radius * Math.cos(angle), - WizardryUtilities.getPlayerEyesPos(caster) + 0.5, caster.posZ + radius * Math.sin(angle), 0, - -0.01, 0, 40 + world.rand.nextInt(12)); - - } - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z){ + + y += 2; // Moves the particles up to the caster's head level + + float brightness = world.rand.nextFloat() / 4; + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).vel(0, -0.2, 0) + .colour(0.05f + brightness, 0.2f + brightness, 0).spawn(world); + + brightness = world.rand.nextFloat() / 4; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.05, 0).lifetime(50) + .colour(0.1f + brightness, 0.2f + brightness, 0).spawn(world); + + ParticleBuilder.create(Type.LEAF).pos(x, y, z).vel(0, -0.01, 0).lifetime(40 + world.rand.nextInt(12)).spawn(world); } } diff --git a/src/main/java/electroblob/wizardry/spell/Freeze.java b/src/main/java/electroblob/wizardry/spell/Freeze.java index 2f9a2790..48f19bb0 100644 --- a/src/main/java/electroblob/wizardry/spell/Freeze.java +++ b/src/main/java/electroblob/wizardry/spell/Freeze.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -10,189 +9,87 @@ import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.monster.EntityMagmaCube; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; -import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class Freeze extends Spell { +public class Freeze extends SpellRay { + + /** The base duration of the frostbite effect appled by this spell. */ + private static final int BASE_DURATION = 200; + /** The base damage dealt to entities vulnerable to frost. */ + private static final float BASE_DAMAGE = 3; public Freeze(){ - super(Tier.BASIC, 5, Element.ICE, "freeze", SpellType.ATTACK, 10, EnumAction.NONE, false); + super("freeze", Tier.BASIC, Element.ICE, SpellType.ATTACK, 5, 10, false, 10, WizardrySounds.SPELL_ICE); + this.soundValues(1, 1.4f, 0.4f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ - // Entity ray trace is done first because block ray trace passes through entities; if it was the other - // way round, entities would only be hit when there were no blocks in range behind them. - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - - if(target instanceof EntityBlaze || target instanceof EntityMagmaCube - || target instanceof EntityBlazeMinion){ + if(target instanceof EntityBlaze || target instanceof EntityMagmaCube || target instanceof EntityBlazeMinion){ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.FROST), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); + BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); } if(MagicDamage.isEntityImmune(DamageType.FROST, target)){ if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted())); }else{ - target.addPotionEffect(new PotionEffect(WizardryPotions.frost, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), 1)); + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.frost, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 1)); } - if(target.isBurning()){ - target.extinguish(); - } - - if(world.isRemote){ - double dx = target.posX - caster.posX; - double dy = (target.getEntityBoundingBox().minY + target.height / 2) - - WizardryUtilities.getPlayerEyesPos(caster); - double dz = target.posZ - caster.posZ; - for(int i = 1; i < 5; i++){ - float brightness = 0.5f + (world.rand.nextFloat() / 2); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), brightness, brightness + 0.1f, 1.0f); - Wizardry.proxy.spawnParticle(Type.SNOW, world, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, -0.02, 0, - 40 + world.rand.nextInt(10)); - } - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.4F + 1.2F); + if(target.isBurning()) target.extinguish(); + return true; - - }else{ - rayTrace = WizardryUtilities.rayTrace(10 * modifiers.get(WizardryItems.range_upgrade), world, caster, true); - // Gets block the player is looking at and sets to ice or covers with snow as necessary - // Note how the block is set on the server side only (kinda obvious really) but the particles are - // spawned on the client side only. - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = rayTrace.getBlockPos(); - - if(world.getBlockState(pos).getBlock() == Blocks.WATER && !world.isRemote){ - world.setBlockState(pos, Blocks.ICE.getDefaultState()); - }else if(world.getBlockState(pos).getBlock() == Blocks.LAVA && !world.isRemote){ - world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState()); - }else if(world.getBlockState(pos).getBlock() == Blocks.FLOWING_LAVA && !world.isRemote){ - world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); - }else if(rayTrace.sideHit == EnumFacing.UP && !world.isRemote && world.isSideSolid(pos, EnumFacing.UP) - && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ - world.setBlockState(pos.up(), Blocks.SNOW_LAYER.getDefaultState()); - } - - if(world.isRemote){ - - double dx = pos.getX() + 0.5 - caster.posX; - double dy = pos.getY() + 0.5 - WizardryUtilities.getPlayerEyesPos(caster); - double dz = pos.getZ() + 0.5 - caster.posZ; - - for(int i = 1; i < 5; i++){ - float brightness = 0.5f + (world.rand.nextFloat() / 2); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) - + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0.0d, 0.0d, 0.0d, - 20 + world.rand.nextInt(8), brightness, brightness + 0.1f, 1.0f); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) - + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0, - 20 + world.rand.nextInt(8), 1.0f, 1.0f, 1.0f); - } - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.4F + 1.2F); - return true; - } } - return false; + + return false; // If the spell hit a non-living entity } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(target instanceof EntityBlaze || target instanceof EntityMagmaCube - || target instanceof EntityBlazeMinion){ - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.FROST), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); - } - - if(!world.isRemote && !MagicDamage.isEntityImmune(DamageType.FROST, target)){ - target.addPotionEffect(new PotionEffect(WizardryPotions.frost, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), 1)); - } - - if(target.isBurning()){ - target.extinguish(); - } - - if(world.isRemote){ - double dx = target.posX - caster.posX; - double dy = (target.getEntityBoundingBox().minY + target.height / 2) - - (caster.posY + caster.getEyeHeight()); - double dz = target.posZ - caster.posZ; - for(int i = 1; i < 5; i++){ - float brightness = 0.5f + (world.rand.nextFloat() / 2); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - caster.posY + caster.getEyeHeight() + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), brightness, brightness + 0.1f, 1.0f); - Wizardry.proxy.spawnParticle(Type.SNOW, world, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - caster.posY + caster.getEyeHeight() + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, -0.02, 0, - 40 + world.rand.nextInt(10)); - } - } - - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, world.rand.nextFloat() * 0.4F + 1.2F); - return true; + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(world.getBlockState(pos).getBlock() == Blocks.WATER && !world.isRemote){ + world.setBlockState(pos, Blocks.ICE.getDefaultState()); + }else if(world.getBlockState(pos).getBlock() == Blocks.LAVA && !world.isRemote){ + world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState()); + }else if(world.getBlockState(pos).getBlock() == Blocks.FLOWING_LAVA && !world.isRemote){ + world.setBlockState(pos, Blocks.COBBLESTONE.getDefaultState()); + }else if(side == EnumFacing.UP && !world.isRemote && world.isSideSolid(pos, EnumFacing.UP) + && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ + world.setBlockState(pos.up(), Blocks.SNOW_LAYER.getDefaultState()); } - - return false; + + return true; // Always succeeds if it hits a block } @Override - public boolean canBeCastByNPCs(){ - return true; + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + float brightness = 0.5f + (world.rand.nextFloat() / 2); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)) + .colour(brightness, brightness + 0.1f, 1).spawn(world); + ParticleBuilder.create(Type.SNOW).pos(x, y, z).spawn(world); } } diff --git a/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java b/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java index 765d8df6..e2792eb9 100644 --- a/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java +++ b/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java @@ -1,7 +1,6 @@ package electroblob.wizardry.spell; import electroblob.wizardry.WizardData; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; @@ -9,8 +8,9 @@ import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryEnchantments; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.EntityPlayer; @@ -30,7 +30,7 @@ public class FreezingWeapon extends Spell { public static final String FREEZING_ARROW_NBT_KEY = "frostLevel"; public FreezingWeapon(){ - super(Tier.ADVANCED, 35, Element.ICE, "freezing_weapon", SpellType.UTILITY, 70, EnumAction.BOW, false); + super("freezing_weapon", Tier.ADVANCED, Element.ICE, SpellType.UTILITY, 35, 70, EnumAction.BOW, false); } @Override @@ -47,25 +47,23 @@ public class FreezingWeapon extends Spell { // The enchantment level as determined by the damage multiplier. The + 0.5f is so that // weird float processing doesn't incorrectly round it down. stack.addEnchantment(WizardryEnchantments.freezing_weapon, - modifiers.get(SpellModifiers.DAMAGE) == 1.0f ? 1 - : (int)((modifiers.get(SpellModifiers.DAMAGE) - 1.0f) + modifiers.get(SpellModifiers.POTENCY) == 1.0f ? 1 + : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) / Constants.DAMAGE_INCREASE_PER_TIER + 0.5f)); WizardData.get(caster).setImbuementDuration(WizardryEnchantments.freezing_weapon, (int)(900 * modifiers.get(WizardryItems.duration_upgrade))); if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.9f, 0.7f, 1.0f); + for(int i=0; i<10; i++){ + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.9f, 0.7f, 1).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/FrostAxe.java b/src/main/java/electroblob/wizardry/spell/FrostAxe.java index 0daffc81..e9b15a57 100644 --- a/src/main/java/electroblob/wizardry/spell/FrostAxe.java +++ b/src/main/java/electroblob/wizardry/spell/FrostAxe.java @@ -1,52 +1,31 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.item.IConjuredItem; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.world.World; -public class FrostAxe extends Spell { +public class FrostAxe extends SpellConjuration { public FrostAxe(){ - super(Tier.ADVANCED, 45, Element.ICE, "frost_axe", SpellType.UTILITY, 50, EnumAction.BOW, false); + super("frost_axe", Tier.ADVANCED, Element.ICE, SpellType.UTILITY, 45, 50, WizardryItems.frost_axe, WizardrySounds.SPELL_ICE); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - ItemStack frostaxe = new ItemStack(WizardryItems.frost_axe); - - IConjuredItem.setDurationMultiplier(frostaxe, modifiers.get(WizardryItems.duration_upgrade)); - - if(!WizardryUtilities.doesPlayerHaveItem(caster, WizardryItems.frost_axe) - && ConjureBow.conjureItemInInventory(caster, frostaxe)){ - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SNOW, world, x1, y1, z1, 0, -0.02d, 0, - 40 + world.rand.nextInt(10)); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0f, 1.0f); - return true; + protected void spawnParticles(World world, EntityLivingBase caster, SpellModifiers modifiers){ + + for(int i=0; i<10; i++){ + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SNOW).pos(x, y, z).spawn(world); } - return false; } } diff --git a/src/main/java/electroblob/wizardry/spell/FrostRay.java b/src/main/java/electroblob/wizardry/spell/FrostRay.java index 4f560b6e..1a360880 100644 --- a/src/main/java/electroblob/wizardry/spell/FrostRay.java +++ b/src/main/java/electroblob/wizardry/spell/FrostRay.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -9,154 +8,105 @@ import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.monster.EntityBlaze; import net.minecraft.entity.monster.EntityMagmaCube; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class FrostRay extends Spell { +public class FrostRay extends SpellRay { + + private static final float BASE_DAMAGE = 3; + /** The base duration of the forstbite effect applied by this spell. */ + private static final int BASE_DURATION = 200; public FrostRay(){ - super(Tier.APPRENTICE, 5, Element.ICE, "frost_ray", SpellType.ATTACK, 0, EnumAction.NONE, true); + super("frost_ray", Tier.APPRENTICE, Element.ICE, SpellType.ATTACK, 5, 0, true, 10, null); + this.particleVelocity(1); + this.particleSpacing(0.5); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + // TODO: Temporary solution until I implement a better continuous sound system + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag){ + if(ticksInUse % 12 == 0){ + if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.5f, 1); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_ICE, 0.5f, 1); + } + } + return flag; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - - if(target.isBurning()){ - target.extinguish(); + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag){ + if(ticksInUse % 12 == 0){ + if(ticksInUse == 0) caster.playSound(WizardrySounds.SPELL_ICE, 0.5f, 1); + caster.playSound(WizardrySounds.SPELL_LOOP_ICE, 0.5f, 1); } + } + return flag; + } + + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + if(target.isBurning()) target.extinguish(); if(MagicDamage.isEntityImmune(DamageType.FROST, target)){ if(!world.isRemote && ticksInUse == 1) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted())); }else{ - // For frost ray the entity can move slightly, unlike freeze. - target.addPotionEffect(new PotionEffect(WizardryPotions.frost, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), 0)); + // For frost ray the entity can move slightly, unlike freeze + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.frost, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); - float baseDamage = target instanceof EntityBlaze || target instanceof EntityMagmaCube ? 6.0f : 3.0f; - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.FROST), - baseDamage * modifiers.get(SpellModifiers.DAMAGE)); + float damage = BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY); + if(target instanceof EntityBlaze || target instanceof EntityMagmaCube) damage *= 2; + + WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeDirectMagicDamage(caster, + DamageType.FROST), damage); } - } - - if(world.isRemote){ - for(int i = 0; i < 20; i++){ - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, - look.x * modifiers.get(WizardryItems.range_upgrade), - look.y * modifiers.get(WizardryItems.range_upgrade), - look.z * modifiers.get(WizardryItems.range_upgrade), 8 + world.rand.nextInt(12), 0.4f, - 0.6f, 1.0f); - - x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, - look.x * modifiers.get(WizardryItems.range_upgrade), - look.y * modifiers.get(WizardryItems.range_upgrade), - look.z * modifiers.get(WizardryItems.range_upgrade), 8 + world.rand.nextInt(12), 1.0f, - 1.0f, 1.0f); - } - } - - if(ticksInUse % 12 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.5F, 1.0f); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_ICE, 0.5F, 1.0f); - } - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - Vec3d vec = new Vec3d(target.posX - caster.posX, target.posY - caster.posY, target.posZ - caster.posZ) - .normalize(); - - if(target.isBurning()){ - target.extinguish(); - } - - if(!MagicDamage.isEntityImmune(DamageType.FROST, target)){ - // For frost ray the entity can move slightly, unlike freeze. - target.addPotionEffect(new PotionEffect(WizardryPotions.frost, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - - float baseDamage = target instanceof EntityBlaze || target instanceof EntityMagmaCube ? 6.0f : 3.0f; - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.FROST), - baseDamage * modifiers.get(SpellModifiers.DAMAGE)); - - } - - if(world.isRemote){ - for(int i = 0; i < 20; i++){ - double x1 = caster.posX + vec.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + vec.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + vec.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, - vec.x * modifiers.get(WizardryItems.range_upgrade), - vec.y * modifiers.get(WizardryItems.range_upgrade), - vec.z * modifiers.get(WizardryItems.range_upgrade), 8 + world.rand.nextInt(12), 0.4f, - 0.6f, 1.0f); - - x1 = caster.posX + vec.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - y1 = caster.posY + caster.getEyeHeight() - 0.4f + vec.y * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - z1 = caster.posZ + vec.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, - vec.x * modifiers.get(WizardryItems.range_upgrade), - vec.y * modifiers.get(WizardryItems.range_upgrade), - vec.z * modifiers.get(WizardryItems.range_upgrade), 8 + world.rand.nextInt(12), 1.0f, - 1.0f, 1.0f); - } - } - - if(ticksInUse % 12 == 0){ - if(ticksInUse == 0) caster.playSound(WizardrySounds.SPELL_ICE, 0.5F, 1.0f); - caster.playSound(WizardrySounds.SPELL_LOOP_ICE, 0.5F, 1.0f); - } - + return true; } - + return false; } @Override - public boolean canBeCastByNPCs(){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + float brightness = world.rand.nextFloat(); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(12)) + .colour(0.4f + 0.6f * brightness, 0.6f + 0.4f*brightness, 1).spawn(world); + ParticleBuilder.create(Type.SNOW).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(12)).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/FrostSigil.java b/src/main/java/electroblob/wizardry/spell/FrostSigil.java deleted file mode 100644 index 5e2ec592..00000000 --- a/src/main/java/electroblob/wizardry/spell/FrostSigil.java +++ /dev/null @@ -1,51 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityFrostSigil; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.world.World; - -public class FrostSigil extends Spell { - - public FrostSigil(){ - super(Tier.APPRENTICE, 10, Element.ICE, "frost_sigil", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(10 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK && rayTrace.sideHit == EnumFacing.UP){ - if(!world.isRemote){ - double x = rayTrace.hitVec.x; - double y = rayTrace.hitVec.y; - double z = rayTrace.hitVec.z; - EntityFrostSigil frostsigil = new EntityFrostSigil(world, x, y, z, caster, - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(frostsigil); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - return true; - } - return false; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Glide.java b/src/main/java/electroblob/wizardry/spell/Glide.java index 9878e3ac..0db03cca 100644 --- a/src/main/java/electroblob/wizardry/spell/Glide.java +++ b/src/main/java/electroblob/wizardry/spell/Glide.java @@ -1,11 +1,11 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; @@ -16,7 +16,7 @@ import net.minecraft.world.World; public class Glide extends Spell { public Glide(){ - super(Tier.ADVANCED, 5, Element.EARTH, "glide", SpellType.UTILITY, 0, EnumAction.NONE, true); + super("glide", Tier.ADVANCED, Element.EARTH, SpellType.UTILITY, 5, 0, EnumAction.NONE, true); } @Override @@ -32,19 +32,20 @@ public class Glide extends Spell { } if(world.isRemote){ - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX - 0.25d + world.rand.nextDouble() / 2, - WizardryUtilities.getPlayerEyesPos(caster) - 1.5f + world.rand.nextDouble(), - caster.posZ - 0.25d + world.rand.nextDouble() / 2, 0, -0.1F, 0, 15, 1.0f, 1.0f, 1.0f); - Wizardry.proxy.spawnParticle(Type.LEAF, world, - caster.posX - 0.25d + world.rand.nextDouble() / 2, - WizardryUtilities.getPlayerEyesPos(caster) - 1.5f + world.rand.nextDouble(), - caster.posZ - 0.25d + world.rand.nextDouble() / 2, 0, -0.03, 0, 20); + double x = caster.posX - 0.25 + world.rand.nextDouble() / 2; + double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble(); + double z = caster.posZ - 0.25 + world.rand.nextDouble() / 2; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).lifetime(15).colour(1, 1, 1).spawn(world); + x = caster.posX - 0.25 + world.rand.nextDouble() / 2; + y = caster.getEntityBoundingBox().minY + world.rand.nextDouble(); + z = caster.posZ - 0.25 + world.rand.nextDouble() / 2; + ParticleBuilder.create(Type.LEAF).pos(x, y, z).lifetime(20).spawn(world); } if(ticksInUse % 24 == 0){ WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ITEM_ELYTRA_FLYING, 0.5F, 1.0f); } + return true; } diff --git a/src/main/java/electroblob/wizardry/spell/GreaterFireball.java b/src/main/java/electroblob/wizardry/spell/GreaterFireball.java index d1d83f98..84db6989 100644 --- a/src/main/java/electroblob/wizardry/spell/GreaterFireball.java +++ b/src/main/java/electroblob/wizardry/spell/GreaterFireball.java @@ -18,7 +18,7 @@ import net.minecraft.world.World; public class GreaterFireball extends Spell { public GreaterFireball(){ - super(Tier.ADVANCED, 20, Element.FIRE, "greater_fireball", SpellType.ATTACK, 30, EnumAction.NONE, false); + super("greater_fireball", Tier.ADVANCED, Element.FIRE, SpellType.ATTACK, 20, 30, EnumAction.NONE, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/GreaterHeal.java b/src/main/java/electroblob/wizardry/spell/GreaterHeal.java index 1173dc11..52452809 100644 --- a/src/main/java/electroblob/wizardry/spell/GreaterHeal.java +++ b/src/main/java/electroblob/wizardry/spell/GreaterHeal.java @@ -1,68 +1,28 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; -public class GreaterHeal extends Spell { +public class GreaterHeal extends SpellBuff { public GreaterHeal(){ - super(Tier.ADVANCED, 15, Element.HEALING, "greater_heal", SpellType.DEFENCE, 40, EnumAction.BOW, false); + super("greater_heal", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 15, 40, WizardrySounds.SPELL_HEAL, 1, 1, 0.3f); + this.soundValues(0.7f, 1.2f, 0.4f); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(caster.shouldHeal()){ - caster.heal((int)(8 * modifiers.get(SpellModifiers.DAMAGE))); - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double dx = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double dy = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double dz = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, dx, dy, dz, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 1.0f, 0.3f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); + protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ + + if(caster.getHealth() < caster.getMaxHealth() && caster.getHealth() > 0){ + caster.heal(8 * modifiers.get(SpellModifiers.POTENCY)); return true; } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(caster.getHealth() < caster.getMaxHealth()){ - caster.heal((int)(8 * modifiers.get(SpellModifiers.DAMAGE))); - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double dx = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double dy = (double)((float)caster.posY + caster.getEyeHeight() - 0.5F + world.rand.nextFloat()); - double dz = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, dx, dy, dz, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 1.0f, 0.3f); - } - } - caster.playSound(WizardrySounds.SPELL_HEAL, 0.7F, world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - return false; + + return false; } } diff --git a/src/main/java/electroblob/wizardry/spell/GroupHeal.java b/src/main/java/electroblob/wizardry/spell/GroupHeal.java index fe25fbff..58030155 100644 --- a/src/main/java/electroblob/wizardry/spell/GroupHeal.java +++ b/src/main/java/electroblob/wizardry/spell/GroupHeal.java @@ -9,8 +9,9 @@ import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.ISummonedCreature; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -21,7 +22,7 @@ import net.minecraft.world.World; public class GroupHeal extends Spell { public GroupHeal(){ - super(Tier.ADVANCED, 35, Element.HEALING, "group_heal", SpellType.DEFENCE, 150, EnumAction.BOW, false); + super("group_heal", Tier.ADVANCED, Element.HEALING, SpellType.DEFENCE, 35, 150, EnumAction.BOW, false); } @Override @@ -40,17 +41,18 @@ public class GroupHeal extends Spell { if(((EntityPlayer)target).shouldHeal()){ - target.heal((int)(6 * modifiers.get(SpellModifiers.DAMAGE))); + target.heal(6 * modifiers.get(SpellModifiers.POTENCY)); if(world.isRemote){ + for(int i = 0; i < 10; i++){ - double d0 = (double)((float)target.posX + world.rand.nextFloat() * 2 - 1.0F); - double d1 = (double)((float)WizardryUtilities.getPlayerEyesPos((EntityPlayer)target) - - 0.5F + world.rand.nextFloat()); - double d2 = (double)((float)target.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, d0, d1, d2, 0, 0.1F, - 0, 48 + world.rand.nextInt(12), 1.0f, 1.0f, 0.3f); + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(1, 1, 0.3f).spawn(world); } + + Wizardry.proxy.spawnEntityParticle(world, caster, 15, 1, 1, 0.3f); } WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, @@ -59,7 +61,7 @@ public class GroupHeal extends Spell { } } - // Now also works on summoned creatures + // Now also works on summoned creatures }else if(target instanceof ISummonedCreature){ EntityLivingBase summoner = ((ISummonedCreature)target).getCaster(); @@ -67,19 +69,19 @@ public class GroupHeal extends Spell { if(summoner == caster || (summoner instanceof EntityPlayer && WizardryUtilities.isPlayerAlly(caster, (EntityPlayer)summoner))){ - if(target.getHealth() < target.getMaxHealth()){ + if(target.getHealth() < target.getMaxHealth() && target.getHealth() > 0){ - target.heal((int)(6 * modifiers.get(SpellModifiers.DAMAGE))); + target.heal(6 * modifiers.get(SpellModifiers.POTENCY)); if(world.isRemote){ for(int i = 0; i < 10; i++){ - double d0 = (double)((float)target.posX + world.rand.nextFloat() * 2 - 1.0F); - double d1 = (double)((float)WizardryUtilities.getPlayerEyesPos((EntityPlayer)target) - - 0.5F + world.rand.nextFloat()); - double d2 = (double)((float)target.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, d0, d1, d2, 0, 0.1F, - 0, 48 + world.rand.nextInt(12), 1.0f, 1.0f, 0.3f); + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(1, 1, 0.3f).spawn(world); } + + Wizardry.proxy.spawnEntityParticle(world, caster, 15, 1, 1, 0.3f); } WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, diff --git a/src/main/java/electroblob/wizardry/spell/GrowthAura.java b/src/main/java/electroblob/wizardry/spell/GrowthAura.java index 390c6603..c873ba80 100644 --- a/src/main/java/electroblob/wizardry/spell/GrowthAura.java +++ b/src/main/java/electroblob/wizardry/spell/GrowthAura.java @@ -18,7 +18,7 @@ import net.minecraft.world.World; public class GrowthAura extends Spell { public GrowthAura(){ - super(Tier.APPRENTICE, 20, Element.EARTH, "growth_aura", SpellType.UTILITY, 50, EnumAction.NONE, false); + super("growth_aura", Tier.APPRENTICE, Element.EARTH, SpellType.UTILITY, 20, 50, EnumAction.NONE, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/Hailstorm.java b/src/main/java/electroblob/wizardry/spell/Hailstorm.java index 481848ca..b054517e 100644 --- a/src/main/java/electroblob/wizardry/spell/Hailstorm.java +++ b/src/main/java/electroblob/wizardry/spell/Hailstorm.java @@ -4,58 +4,38 @@ import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityHailstorm; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.world.World; -public class Hailstorm extends Spell { +public class Hailstorm extends SpellConstructRanged { public Hailstorm(){ - super(Tier.MASTER, 75, Element.ICE, "hailstorm", SpellType.ATTACK, 300, EnumAction.NONE, false); + super("hailstorm", Tier.MASTER, Element.ICE, SpellType.ATTACK, 75, 300, EntityHailstorm::new, 120, 20, WizardrySounds.SPELL_ICE); + this.floor(true); } @Override - public boolean doesSpellRequirePacket(){ - return false; + protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + + // Moves the entity back towards the caster a bit, so the area of effect is better centred on the position. + // 3 is the distance to move the entity back towards the caster. + double dx = caster.posX - x; + double dz = caster.posZ - z; + double distRatio = 3 / Math.sqrt(dx * dx + dz * dz); + x += dx * distRatio; + z += dz * distRatio; + // Moves the entity up 5 blocks so that it is above mobs' heads. + y += 5; + + return super.spawnConstruct(world, x, y, z, caster, modifiers); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(20 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - if(!world.isRemote){ - double x = rayTrace.hitVec.x; - double y = rayTrace.hitVec.y; - double z = rayTrace.hitVec.z; - // Moves the entity back towards the caster a bit, so the area of effect is better centred on the - // position. - // 3.0d is the distance to move the entity back towards the caster. - double dx = caster.posX - x; - double dz = caster.posZ - z; - double distRatio = 3.0d / Math.sqrt(dx * dx + dz * dz); - x += dx * distRatio; - z += dz * distRatio; - - EntityHailstorm hailstorm = new EntityHailstorm(world, x, y + 5, z, caster, - (int)(120 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - hailstorm.rotationYaw = caster.rotationYawHead; - world.spawnEntity(hailstorm); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - return true; - } - return false; + protected void addConstructExtras(EntityHailstorm construct, EntityLivingBase caster, SpellModifiers modifiers){ + // Makes the arrows shoot in the direction the caster was looking when they cast the spell. + construct.rotationYaw = caster.rotationYawHead; } } diff --git a/src/main/java/electroblob/wizardry/spell/Heal.java b/src/main/java/electroblob/wizardry/spell/Heal.java index 3b9977f4..46055d50 100644 --- a/src/main/java/electroblob/wizardry/spell/Heal.java +++ b/src/main/java/electroblob/wizardry/spell/Heal.java @@ -1,72 +1,27 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; -public class Heal extends Spell { +public class Heal extends SpellBuff { public Heal(){ - super(Tier.BASIC, 5, Element.HEALING, "heal", SpellType.DEFENCE, 20, EnumAction.BOW, false); + super("heal", Tier.BASIC, Element.HEALING, SpellType.DEFENCE, 5, 20, WizardrySounds.SPELL_HEAL, 1, 1, 0.3f); + this.soundValues(0.7f, 1.2f, 0.4f); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(caster.shouldHeal()){ - - caster.heal((int)(4 * modifiers.get(SpellModifiers.DAMAGE))); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double d0 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - // Apparently the client side spawns the particles 1 block higher than it should... hence the -0.5F. - double d1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double d2 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, d0, d1, d2, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 1.0f, 0.3f); - } - Wizardry.proxy.spawnEntityParticle(world, caster, 15, 1.0f, 1.0f, 0.3f); - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); + protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ + + if(caster.getHealth() < caster.getMaxHealth() && caster.getHealth() > 0){ + caster.heal(4 * modifiers.get(SpellModifiers.POTENCY)); return true; } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(caster.getHealth() < caster.getMaxHealth()){ - caster.heal((int)(4 * modifiers.get(SpellModifiers.DAMAGE))); - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double dx = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double dy = (double)((float)caster.posY + caster.getEyeHeight() - 0.5F + world.rand.nextFloat()); - double dz = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, dx, dy, dz, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 1.0f, 0.3f); - } - } - caster.playSound(WizardrySounds.SPELL_HEAL, 0.7F, world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - + return false; } diff --git a/src/main/java/electroblob/wizardry/spell/HealAlly.java b/src/main/java/electroblob/wizardry/spell/HealAlly.java index d8f3edc4..f6ccdb65 100644 --- a/src/main/java/electroblob/wizardry/spell/HealAlly.java +++ b/src/main/java/electroblob/wizardry/spell/HealAlly.java @@ -4,53 +4,63 @@ import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class HealAlly extends Spell { +public class HealAlly extends SpellRay { public HealAlly(){ - super(Tier.APPRENTICE, 10, Element.HEALING, "heal_ally", SpellType.DEFENCE, 20, EnumAction.NONE, false); + super("heal_ally", Tier.APPRENTICE, Element.HEALING, SpellType.DEFENCE, 10, 20, false, 10, WizardrySounds.SPELL_HEAL); + this.soundValues(0.7f, 1.2f, 0.4f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade), 8.0f); - - if(rayTrace != null && rayTrace.entityHit != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - if(target.getHealth() < target.getMaxHealth()){ - target.heal((int)(5 * modifiers.get(SpellModifiers.DAMAGE))); + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + EntityLivingBase entity = (EntityLivingBase)target; + + if(entity.getHealth() < entity.getMaxHealth() && entity.getHealth() > 0){ + + entity.heal((int)(5 * modifiers.get(SpellModifiers.POTENCY))); if(world.isRemote){ + + float r = 1; float g = 1; float b = 0.3f; + for(int i = 0; i < 10; i++){ - double d0 = (double)((float)target.posX + world.rand.nextFloat() * 2 - 1.0F); - // Apparently the client side spawns the particles 1 block higher than it should... hence the - - // 0.5F. - double d1 = (double)((float)target.getEntityBoundingBox().minY + target.height - 0.5f - + world.rand.nextFloat()); - double d2 = (double)((float)target.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, d0, d1, d2, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 1.0f, 0.3f); + double x1 = (double)((float)entity.posX + world.rand.nextFloat() * 2 - 1.0f); + double y1 = (double)((float)entity.getEntityBoundingBox().minY + entity.getEyeHeight() - 0.5f + world.rand.nextFloat()); + double z1 = (double)((float)entity.posZ + world.rand.nextFloat() * 2 - 1.0f); + ParticleBuilder.create(Type.SPARKLE).pos(x1, y1, z1).vel(0, 0.1F, 0).colour(r, g, b).spawn(world); } + + Wizardry.proxy.spawnEntityParticle(world, entity, 15, r, g, b); } - - caster.swingArm(hand); - target.playSound(WizardrySounds.SPELL_HEAL, 0.7F, world.rand.nextFloat() * 0.4F + 1.0F); - return true; } + + return true; } + + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/HealingAura.java b/src/main/java/electroblob/wizardry/spell/HealingAura.java deleted file mode 100644 index d3a9844e..00000000 --- a/src/main/java/electroblob/wizardry/spell/HealingAura.java +++ /dev/null @@ -1,68 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityHealAura; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class HealingAura extends Spell { - - public HealingAura(){ - super(Tier.ADVANCED, 35, Element.HEALING, "healing_aura", SpellType.DEFENCE, 150, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(caster.onGround){ - if(!world.isRemote){ - EntityHealAura healaura = new EntityHealAura(world, caster.posX, caster.posY, caster.posZ, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(healaura); - } - return true; - } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - if(caster.onGround - && world.getEntitiesWithinAABB(EntityHealAura.class, caster.getEntityBoundingBox()).isEmpty()){ - if(!world.isRemote){ - EntityHealAura healaura = new EntityHealAura(world, caster.posX, caster.posY, caster.posZ, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(healaura); - } - return true; - } - return false; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/HomingSpark.java b/src/main/java/electroblob/wizardry/spell/HomingSpark.java deleted file mode 100644 index 074658e2..00000000 --- a/src/main/java/electroblob/wizardry/spell/HomingSpark.java +++ /dev/null @@ -1,65 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntitySpark; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class HomingSpark extends Spell { - - public HomingSpark(){ - super(Tier.APPRENTICE, 10, Element.LIGHTNING, "homing_spark", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntitySpark spark = new EntitySpark(world, caster, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(spark); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - } - caster.swingArm(hand); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntitySpark spark = new EntitySpark(world, caster, modifiers.get(SpellModifiers.DAMAGE)); - spark.directTowards(target, 0.5f); - world.spawnEntity(spark); - caster.playSound(WizardrySounds.SPELL_CONJURATION, 1.0F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - } - caster.swingArm(hand); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/IceAge.java b/src/main/java/electroblob/wizardry/spell/IceAge.java index 6c72c2b9..1f21e3cc 100644 --- a/src/main/java/electroblob/wizardry/spell/IceAge.java +++ b/src/main/java/electroblob/wizardry/spell/IceAge.java @@ -28,7 +28,7 @@ public class IceAge extends Spell { private static final int baseDuration = 1200; public IceAge(){ - super(Tier.MASTER, 70, Element.ICE, "ice_age", SpellType.ATTACK, 250, EnumAction.BOW, false); + super("ice_age", Tier.MASTER, Element.ICE, SpellType.ATTACK, 70, 250, EnumAction.BOW, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/IceCharge.java b/src/main/java/electroblob/wizardry/spell/IceCharge.java deleted file mode 100644 index 231d78b7..00000000 --- a/src/main/java/electroblob/wizardry/spell/IceCharge.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityIceCharge; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class IceCharge extends Spell { - - public IceCharge(){ - super(Tier.ADVANCED, 20, Element.ICE, "ice_charge", SpellType.ATTACK, 30, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityIceCharge icecharge = new EntityIceCharge(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - world.spawnEntity(icecharge); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.4F + 1.4F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityIceCharge icecharge = new EntityIceCharge(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - icecharge.directTowards(target, 1.5f); - world.spawnEntity(icecharge); - } - - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, world.rand.nextFloat() * 0.4F + 1.4F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/IceLance.java b/src/main/java/electroblob/wizardry/spell/IceLance.java deleted file mode 100644 index 88c36745..00000000 --- a/src/main/java/electroblob/wizardry/spell/IceLance.java +++ /dev/null @@ -1,67 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityIceLance; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class IceLance extends Spell { - - public IceLance(){ - super(Tier.ADVANCED, 20, Element.ICE, "ice_lance", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityIceLance iceLance = new EntityIceLance(world, caster, 2 * modifiers.get(WizardryItems.range_upgrade), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(iceLance); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.4F + 0.8F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityIceLance iceLance = new EntityIceLance(world, caster, target, - 2 * modifiers.get(WizardryItems.range_upgrade), 4, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(iceLance); - } - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/IceShard.java b/src/main/java/electroblob/wizardry/spell/IceShard.java deleted file mode 100644 index 79c4f1b7..00000000 --- a/src/main/java/electroblob/wizardry/spell/IceShard.java +++ /dev/null @@ -1,67 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityIceShard; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class IceShard extends Spell { - - public IceShard(){ - super(Tier.APPRENTICE, 10, Element.ICE, "ice_shard", SpellType.ATTACK, 10, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityIceShard iceShard = new EntityIceShard(world, caster, 2 * modifiers.get(WizardryItems.range_upgrade), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(iceShard); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.4F + 1.4F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityIceShard iceShard = new EntityIceShard(world, caster, target, - 2 * modifiers.get(WizardryItems.range_upgrade), 4, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(iceShard); - } - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, world.rand.nextFloat() * 0.4F + 1.4F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/IceShroud.java b/src/main/java/electroblob/wizardry/spell/IceShroud.java deleted file mode 100644 index 88a933d9..00000000 --- a/src/main/java/electroblob/wizardry/spell/IceShroud.java +++ /dev/null @@ -1,71 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class IceShroud extends Spell { - - public IceShroud(){ - super(Tier.ADVANCED, 40, Element.ICE, "ice_shroud", SpellType.DEFENCE, 250, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - // Cannot be cast when it has already been cast - if(!caster.isPotionActive(WizardryPotions.ice_shroud)){ - if(!world.isRemote){ - caster.addPotionEffect(new PotionEffect(WizardryPotions.ice_shroud, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.4F + 1.4F); - return true; - } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - // Cannot be cast when it has already been cast - if(!caster.isPotionActive(WizardryPotions.ice_shroud)){ - if(!world.isRemote){ - caster.addPotionEffect(new PotionEffect(WizardryPotions.ice_shroud, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - } - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, world.rand.nextFloat() * 0.4F + 1.4F); - return true; - } - return false; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/IceSpikes.java b/src/main/java/electroblob/wizardry/spell/IceSpikes.java index c00590b2..7a07adc7 100644 --- a/src/main/java/electroblob/wizardry/spell/IceSpikes.java +++ b/src/main/java/electroblob/wizardry/spell/IceSpikes.java @@ -8,107 +8,52 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -public class IceSpikes extends Spell { +public class IceSpikes extends SpellConstructRanged { + + private static final int BASE_SPAWN_COUNT = 17; // Was 18, reduced to 17 to account for the extra one in the middle. public IceSpikes(){ - super(Tier.ADVANCED, 30, Element.ICE, "ice_spikes", SpellType.ATTACK, 75, EnumAction.NONE, false); + // Base duration is set to -1 so that the superclass doesn't waste time retrieving the duration multiplier + super("ice_spikes", Tier.ADVANCED, Element.ICE, SpellType.ATTACK, 30, 75, EntityIceSpike::new, -1, 20, WizardrySounds.SPELL_ICE); } - + @Override - public boolean doesSpellRequirePacket(){ - return false; - } + protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + + if(world.getBlockState(new BlockPos(x, y, z)).isNormalCube()) return false; + + // Now always spawns a spike exactly at the position aimed at + super.spawnConstruct(world, x, y-1, z, caster, modifiers); + + int quantity = (int)(BASE_SPAWN_COUNT * modifiers.get(WizardryItems.blast_upgrade)); - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + for(int i=0; i -1){ - EntityIceSpike icespike = new EntityIceSpike(world, x1, y1, z1, caster, - 30 + world.rand.nextInt(15), modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(icespike); - } - } + if(y1 > -1){ + super.spawnConstruct(world, x1, y1, z1, caster, modifiers); } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - return true; } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - - double x = target.posX; - double y = target.posY; - double z = target.posZ; - - for(int i = 0; i < (int)(18 * modifiers.get(WizardryItems.blast_upgrade)); i++){ - - float angle = (float)(world.rand.nextFloat() * Math.PI * 2); - double radius = 0.5 + world.rand.nextDouble() * 2 * modifiers.get(WizardryItems.blast_upgrade); - - double x1 = x + radius * MathHelper.sin(angle); - double z1 = z + radius * MathHelper.cos(angle); - double y1 = WizardryUtilities.getNearestFloorLevel(world, - new BlockPos(MathHelper.floor(x1), (int)y, MathHelper.floor(z1)), 2) - 1; - - if(y1 > -1){ - EntityIceSpike icespike = new EntityIceSpike(world, x1, y1, z1, caster, - 30 + world.rand.nextInt(15), modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(icespike); - } - } - } - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ + return true; } + + @Override + protected void addConstructExtras(EntityIceSpike construct, EntityLivingBase caster, SpellModifiers modifiers){ + // In this particular case, lifetime is implemented as a delay instead so is treated differently. + construct.lifetime = 30 + construct.world.rand.nextInt(15); + } } diff --git a/src/main/java/electroblob/wizardry/spell/IceStatue.java b/src/main/java/electroblob/wizardry/spell/IceStatue.java index c32cfc6d..2132ef16 100644 --- a/src/main/java/electroblob/wizardry/spell/IceStatue.java +++ b/src/main/java/electroblob/wizardry/spell/IceStatue.java @@ -1,131 +1,63 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockStatue; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.tileentity.TileEntityStatue; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.monster.EntityBlaze; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class IceStatue extends Spell { +public class IceStatue extends SpellRay { - private static final int baseDuration = 400; + private static final int BASE_DURATION = 400; public IceStatue(){ - super(Tier.APPRENTICE, 15, Element.ICE, "ice_statue", SpellType.ATTACK, 40, EnumAction.NONE, false); + super("ice_statue", Tier.APPRENTICE, Element.ICE, SpellType.ATTACK, 15, 40, false, 10, WizardrySounds.SPELL_ICE); + this.soundValues(1, 1.4f, 0.4f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY - && rayTrace.entityHit instanceof EntityLiving && !world.isRemote){ - - EntityLiving target = (EntityLiving)rayTrace.entityHit; - - BlockPos pos = new BlockPos(target); - - if(target.isBurning()){ - target.extinguish(); - } - - // Stops the entity looking red while frozen and the resulting z-fighting - target.hurtTime = 0; - - if(target instanceof EntityBlaze) WizardryAdvancementTriggers.freeze_blaze.triggerFor(caster); - - // Short mobs such as spiders and pigs - if((target.height < 1.2 || target.isChild()) && WizardryUtilities.canBlockBeReplaced(world, pos)){ - world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(target, 1, 1); - ((TileEntityStatue)world.getTileEntity(pos)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - target.setDead(); - target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); - } - // Normal sized mobs like zombies and skeletons - else if(target.height < 2.5 && WizardryUtilities.canBlockBeReplaced(world, pos) - && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ - world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(target, 1, 2); - ((TileEntityStatue)world.getTileEntity(pos)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - - world.setBlockState(pos.up(), WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up())).setCreatureAndPart(target, 2, 2); - } - target.setDead(); - target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); - } - // Tall mobs like endermen and iron golems - else if(WizardryUtilities.canBlockBeReplaced(world, pos) - && WizardryUtilities.canBlockBeReplaced(world, pos.up()) - && WizardryUtilities.canBlockBeReplaced(world, pos.up(2))){ - world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(target, 1, 3); - ((TileEntityStatue)world.getTileEntity(pos)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - - world.setBlockState(pos.up(), WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up())).setCreatureAndPart(target, 2, 3); - } - - world.setBlockState(pos.up(2), WizardryBlocks.ice_statue.getDefaultState()); - if(world.getTileEntity(pos.up(2)) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up(2))).setCreatureAndPart(target, 3, 3); - } - target.setDead(); + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(target instanceof EntityLiving && !world.isRemote){ + // Unchecked cast is fine because the block is a static final field + if(((BlockStatue)WizardryBlocks.ice_statue).convertToStatue((EntityLiving)target, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)))){ + target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); + return true; } } - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - float brightness = 0.5f + (world.rand.nextFloat() / 2); + + return false; + } - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), brightness, brightness + 0.1f, 1.0f); - Wizardry.proxy.spawnParticle(Type.SNOW, world, x1, y1, z1, 0.0d, -0.02d, 0.0d, - 20 + world.rand.nextInt(10)); - - } - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.4F + 1.2F); + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + float brightness = 0.5f + world.rand.nextFloat() * 0.5f; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)) + .colour(brightness, brightness + 0.1f, 1.0f).spawn(world); + ParticleBuilder.create(Type.SNOW).pos(x, y, z).lifetime(20 + world.rand.nextInt(10)).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/Ignite.java b/src/main/java/electroblob/wizardry/spell/Ignite.java index bb5f8705..145607f3 100644 --- a/src/main/java/electroblob/wizardry/spell/Ignite.java +++ b/src/main/java/electroblob/wizardry/spell/Ignite.java @@ -7,168 +7,69 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class Ignite extends Spell { +public class Ignite extends SpellRay { + /** The base duration for which entities are set on fire by this spell. */ + private static final int BASE_DURATION = 10; + public Ignite(){ - super(Tier.BASIC, 5, Element.FIRE, "ignite", SpellType.ATTACK, 10, EnumAction.NONE, false); + super("ignite", Tier.BASIC, Element.FIRE, SpellType.ATTACK, 5, 10, false, 10, SoundEvents.ITEM_FLINTANDSTEEL_USE); + this.soundValues(1, 1, 0.4f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - // Entity ray trace is done first because block ray trace passes through entities; if it was the other - // way round, entities would only be hit when there were no blocks in range behind them. - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - // Fire can damage armour stands - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && rayTrace.entityHit instanceof EntityLivingBase){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + // Fire can damage armour stands, so this includes them + if(target instanceof EntityLivingBase) { + if(MagicDamage.isEntityImmune(DamageType.FIRE, target)){ if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted())); }else{ - target.setFire((int)(10 * modifiers.get(WizardryItems.duration_upgrade))); + target.setFire((int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); } - - if(world.isRemote){ - double dx = target.posX - caster.posX; - double dy = (target.getEntityBoundingBox().minY + target.height / 2) - - WizardryUtilities.getPlayerEyesPos(caster); - double dz = target.posZ - caster.posZ; - // i starts at 1 so that particles are not spawned in the player's head. - for(int i = 1; i < 5; i++){ - // WizardryUtilities.spawnParticleAndNotify(world, EnumParticleTypes.FLAME, caster.posX + (i*(dx/5)) - // + world.rand.nextFloat()/5, caster.posY + (i*(dy/5)) + world.rand.nextFloat()/5, caster.posZ + - // (i*(dz/5)) + world.rand.nextFloat()/5, 0, 0, 0, 0, 0, 0, 0); - // WizardryUtilities.spawnParticleAndNotify(world, EnumParticleTypes.FLAME, caster.posX + (i*(dx/5)) - // + world.rand.nextFloat()/5, caster.posY + (i*(dy/5)) + world.rand.nextFloat()/5, caster.posZ + - // (i*(dz/5)) + world.rand.nextFloat()/5, 0, 0, 0, 0, 0, 0, 0); - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - } - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ITEM_FLINTANDSTEEL_USE, 1.0F, - world.rand.nextFloat() * 0.4F + 0.8F); - + return true; - - }else{ - - rayTrace = WizardryUtilities.rayTrace(10 * modifiers.get(WizardryItems.range_upgrade), world, caster, - false); - - // Gets block the player is looking at and sets the appropriate surrounding air block to fire. - // Note how the block is set on the server side only (kinda obvious really) but the particles are - // spawned on the client side only. - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = rayTrace.getBlockPos().offset(rayTrace.sideHit); - - if(world.isAirBlock(pos)){ - if(!world.isRemote){ - world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - } - - if(world.isRemote){ - - double dx = pos.getX() + 0.5 - caster.posX; - double dy = pos.getY() + 0.5 - WizardryUtilities.getPlayerEyesPos(caster); - double dz = pos.getZ() + 0.5 - caster.posZ; - - for(int i = 1; i < 5; i++){ - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) - + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) - + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - } - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ITEM_FLINTANDSTEEL_USE, 1.0F, - world.rand.nextFloat() * 0.4F + 0.8F); - return true; - } - } } + return false; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)) - target.setFire((int)(10 * modifiers.get(WizardryItems.duration_upgrade))); - - if(world.isRemote){ - double dx = target.posX - caster.posX; - double dy = (target.getEntityBoundingBox().minY + target.height / 2) - - (caster.posY + caster.getEyeHeight()); - double dz = target.posZ - caster.posZ; - // i starts at 1 so that particles are not spawned in the player's head. - for(int i = 1; i < 5; i++){ - // WizardryUtilities.spawnParticleAndNotify(world, EnumParticleTypes.FLAME, caster.posX + (i*(dx/5)) - // + world.rand.nextFloat()/5, caster.posY + (i*(dy/5)) + world.rand.nextFloat()/5, caster.posZ + - // (i*(dz/5)) + world.rand.nextFloat()/5, 0, 0, 0, 0, 0, 0, 0); - // WizardryUtilities.spawnParticleAndNotify(world, EnumParticleTypes.FLAME, caster.posX + (i*(dx/5)) - // + world.rand.nextFloat()/5, caster.posY + (i*(dy/5)) + world.rand.nextFloat()/5, caster.posZ + - // (i*(dz/5)) + world.rand.nextFloat()/5, 0, 0, 0, 0, 0, 0, 0); - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - caster.posY + caster.getEyeHeight() + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - world.spawnParticle(EnumParticleTypes.FLAME, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - caster.posY + caster.getEyeHeight() + (i * (dy / 5)) + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, 0, 0); - } + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + pos = pos.offset(side); + + if(world.isAirBlock(pos)){ + + if(!world.isRemote){ + world.setBlockState(pos, Blocks.FIRE.getDefaultState()); } - - caster.swingArm(hand); - caster.playSound(SoundEvents.ITEM_FLINTANDSTEEL_USE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); - + return true; } - + return false; } @Override - public boolean canBeCastByNPCs(){ - return true; + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + world.spawnParticle(EnumParticleTypes.FLAME, x, y, z, 0, 0, 0); } } diff --git a/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java b/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java index 66f7ea82..caf3f92e 100644 --- a/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java +++ b/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java @@ -1,7 +1,6 @@ package electroblob.wizardry.spell; import electroblob.wizardry.WizardData; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; @@ -9,8 +8,9 @@ import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryEnchantments; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.EntityPlayer; @@ -24,7 +24,7 @@ import net.minecraft.world.World; public class ImbueWeapon extends Spell { public ImbueWeapon(){ - super(Tier.APPRENTICE, 20, Element.SORCERY, "imbue_weapon", SpellType.UTILITY, 50, EnumAction.BOW, false); + super("imbue_weapon", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 20, 50, EnumAction.BOW, false); } @Override @@ -40,9 +40,9 @@ public class ImbueWeapon extends Spell { && WizardData.get(caster).getImbuementDuration(WizardryEnchantments.magic_sword) <= 0){ // The enchantment level as determined by the damage multiplier. The + 0.5f is so that // weird float processing doesn't incorrectly round it down. - stack.addEnchantment(WizardryEnchantments.magic_sword, modifiers.get(SpellModifiers.DAMAGE) == 1.0f + stack.addEnchantment(WizardryEnchantments.magic_sword, modifiers.get(SpellModifiers.POTENCY) == 1.0f ? 1 - : (int)((modifiers.get(SpellModifiers.DAMAGE) - 1.0f) / Constants.DAMAGE_INCREASE_PER_TIER + : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) / Constants.DAMAGE_INCREASE_PER_TIER + 0.5f)); WizardData.get(caster).setImbuementDuration(WizardryEnchantments.magic_sword, (int)(900 * modifiers.get(WizardryItems.duration_upgrade))); @@ -52,9 +52,9 @@ public class ImbueWeapon extends Spell { && WizardData.get(caster).getImbuementDuration(WizardryEnchantments.magic_bow) <= 0){ // The enchantment level as determined by the damage multiplier. The + 0.5f is so that // weird float processing doesn't incorrectly round it down. - stack.addEnchantment(WizardryEnchantments.magic_bow, modifiers.get(SpellModifiers.DAMAGE) == 1.0f + stack.addEnchantment(WizardryEnchantments.magic_bow, modifiers.get(SpellModifiers.POTENCY) == 1.0f ? 1 - : (int)((modifiers.get(SpellModifiers.DAMAGE) - 1.0f) / Constants.DAMAGE_INCREASE_PER_TIER + : (int)((modifiers.get(SpellModifiers.POTENCY) - 1.0f) / Constants.DAMAGE_INCREASE_PER_TIER + 0.5f)); WizardData.get(caster).setImbuementDuration(WizardryEnchantments.magic_bow, (int)(900 * modifiers.get(WizardryItems.duration_upgrade))); @@ -64,17 +64,15 @@ public class ImbueWeapon extends Spell { } if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.9f, 0.7f, 1.0f); + for(int i=0; i<10; i++){ + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.9f, 0.7f, 1).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0f, 1.0f); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1); return true; } } diff --git a/src/main/java/electroblob/wizardry/spell/Intimidate.java b/src/main/java/electroblob/wizardry/spell/Intimidate.java index 5cbabdff..2d8f6aa4 100644 --- a/src/main/java/electroblob/wizardry/spell/Intimidate.java +++ b/src/main/java/electroblob/wizardry/spell/Intimidate.java @@ -2,14 +2,14 @@ package electroblob.wizardry.spell; import java.util.List; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityCreature; @@ -34,9 +34,12 @@ public class Intimidate extends Spell { /** The NBT tag name for storing the feared entity's UUID in the target's tag compound. */ public static final String NBT_KEY = "fearedEntity"; + + private static final double BASE_RANGE = 8; + private static final int BASE_DURATION = 600; public Intimidate(){ - super(Tier.APPRENTICE, 20, Element.NECROMANCY, "intimidate", SpellType.ATTACK, 100, EnumAction.BOW, false); + super("intimidate", Tier.APPRENTICE, Element.NECROMANCY, SpellType.ATTACK, 20, 100, EnumAction.BOW, false); } @Override @@ -45,8 +48,8 @@ public class Intimidate extends Spell { if(!world.isRemote){ List entities = WizardryUtilities.getEntitiesWithinRadius( - 8 * modifiers.get(WizardryItems.range_upgrade), caster.posX, caster.posY, caster.posZ, world, - EntityCreature.class); + BASE_RANGE * modifiers.get(WizardryItems.range_upgrade), caster.posX, caster.posY, caster.posZ, + world, EntityCreature.class); for(EntityCreature target : entities){ @@ -56,16 +59,16 @@ public class Intimidate extends Spell { if(entityNBT != null) entityNBT.setUniqueId(NBT_KEY, caster.getUniqueID()); ((EntityLiving)target).addPotionEffect(new PotionEffect(WizardryPotions.fear, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); } }else{ for(int i = 0; i < 30; i++){ - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, - caster.posX - 1 + world.rand.nextDouble() * 2, - caster.getEntityBoundingBox().minY + 1.5 + world.rand.nextDouble() * 0.5, - caster.posZ - 1 + world.rand.nextDouble() * 2, 0, 0, 0, 0, 0.9f, 0.1f, 0.0f); + double x = caster.posX - 1 + world.rand.nextDouble() * 2; + double y = caster.getEntityBoundingBox().minY + 1.5 + world.rand.nextDouble() * 0.5; + double z = caster.posZ - 1 + world.rand.nextDouble() * 2; + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.9f, 0.1f, 0).spawn(world); } } WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERDRAGON_GROWL, 1.0f, 1.0f); diff --git a/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java b/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java index a8ede484..859a5a90 100644 --- a/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java +++ b/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java @@ -2,14 +2,14 @@ package electroblob.wizardry.spell; import java.util.List; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; @@ -19,40 +19,46 @@ import net.minecraft.util.EnumHand; import net.minecraft.world.World; public class InvigoratingPresence extends Spell { + + private static final double BASE_RANGE = 5; + private static final int BASE_DURATION = 900; public InvigoratingPresence(){ - super(Tier.APPRENTICE, 30, Element.HEALING, "invigorating_presence", SpellType.UTILITY, 60, EnumAction.BOW, - false); + super("invigorating_presence", Tier.APPRENTICE, Element.HEALING, SpellType.UTILITY, 30, 60, EnumAction.BOW, false); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ List targets = WizardryUtilities.getEntitiesWithinRadius( - 5 * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world, + BASE_RANGE * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world, EntityPlayer.class); for(EntityPlayer target : targets){ if(WizardryUtilities.isPlayerAlly(caster, target) || target == caster){ // Strength 2 for 45 seconds. target.addPotionEffect(new PotionEffect(MobEffects.STRENGTH, - (int)(900 * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); } } if(world.isRemote){ + for(int i = 0; i < 50 * modifiers.get(WizardryItems.blast_upgrade); i++){ + double radius = (1 + world.rand.nextDouble() * 4) * modifiers.get(WizardryItems.blast_upgrade); double angle = world.rand.nextDouble() * Math.PI * 2; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX + radius * Math.cos(angle), caster.getEntityBoundingBox().minY, - caster.posZ + radius * Math.sin(angle), 0, 0.03, 0, 50, 1, 0.2f, 0.2f); + + double x = caster.posX + radius * Math.cos(angle); + double y = caster.getEntityBoundingBox().minY; + double z = caster.posZ + radius * Math.sin(angle); + + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).lifetime(50).colour(1, 0.2f, 0.2f).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1 + 0.2f * world.rand.nextFloat()); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/Invisibility.java b/src/main/java/electroblob/wizardry/spell/Invisibility.java deleted file mode 100644 index 0fe1caba..00000000 --- a/src/main/java/electroblob/wizardry/spell/Invisibility.java +++ /dev/null @@ -1,78 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Invisibility extends Spell { - - public Invisibility(){ - super(Tier.ADVANCED, 35, Element.SORCERY, "invisibility", SpellType.UTILITY, 200, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - caster.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.7f, 1.0f, 1.0f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!caster.isPotionActive(MobEffects.INVISIBILITY)){ - - caster.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)caster.posY + caster.getEyeHeight() - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.7f, 1.0f, 1.0f); - } - } - caster.playSound(WizardrySounds.SPELL_HEAL, 0.7F, world.rand.nextFloat() * 0.4F + 1.0F); - return true; - - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/InvokeWeather.java b/src/main/java/electroblob/wizardry/spell/InvokeWeather.java index 9046e787..e2773b79 100644 --- a/src/main/java/electroblob/wizardry/spell/InvokeWeather.java +++ b/src/main/java/electroblob/wizardry/spell/InvokeWeather.java @@ -2,12 +2,12 @@ package electroblob.wizardry.spell; import java.util.Random; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; @@ -19,7 +19,7 @@ import net.minecraft.world.World; public class InvokeWeather extends Spell { public InvokeWeather(){ - super(Tier.ADVANCED, 30, Element.LIGHTNING, "invoke_weather", SpellType.UTILITY, 100, EnumAction.BOW, false); + super("invoke_weather", Tier.ADVANCED, Element.LIGHTNING, SpellType.UTILITY, 30, 100, EnumAction.BOW, false); } @Override @@ -28,8 +28,9 @@ public class InvokeWeather extends Spell { if(caster.dimension == 0){ if(!world.isRemote){ - // TODO: Backport these changes. + int standardWeatherTime = (300 + (new Random()).nextInt(600)) * 20; + if(world.isRaining()){ caster.sendMessage(new TextComponentTranslation("spell." + this.getUnlocalisedName() + ".sun")); world.getWorldInfo().setCleanWeatherTime(standardWeatherTime); @@ -50,18 +51,17 @@ public class InvokeWeather extends Spell { if(world.isRemote){ for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.5f, 0.7f, 1.0f); + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.5f, 0.7f, 1).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_LIGHTNING_THUNDER, 0.5F, 1.0f); + WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_LIGHTNING_THUNDER, 0.5f, 1.0f); return true; } + return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Ironflesh.java b/src/main/java/electroblob/wizardry/spell/Ironflesh.java deleted file mode 100644 index 7828b4d0..00000000 --- a/src/main/java/electroblob/wizardry/spell/Ironflesh.java +++ /dev/null @@ -1,79 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Ironflesh extends Spell { - - public Ironflesh(){ - super(Tier.ADVANCED, 30, Element.HEALING, "ironflesh", SpellType.DEFENCE, 100, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - caster.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 2, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.4f, 0.5f, 0.6f); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!caster.isPotionActive(MobEffects.RESISTANCE)){ - - caster.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 2, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)caster.posY + caster.getEyeHeight() - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.4f, 0.5f, 0.6f); - } - } - - caster.playSound(WizardrySounds.SPELL_HEAL, 0.7F, world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Leap.java b/src/main/java/electroblob/wizardry/spell/Leap.java index dc426c65..2bb1263b 100644 --- a/src/main/java/electroblob/wizardry/spell/Leap.java +++ b/src/main/java/electroblob/wizardry/spell/Leap.java @@ -15,7 +15,7 @@ import net.minecraft.world.World; public class Leap extends Spell { public Leap(){ - super(Tier.BASIC, 10, Element.EARTH, "leap", SpellType.UTILITY, 20, EnumAction.NONE, false); + super("leap", Tier.BASIC, Element.EARTH, SpellType.UTILITY, 10, 20, EnumAction.NONE, false); } @Override @@ -23,7 +23,7 @@ public class Leap extends Spell { if(caster.onGround){ - caster.motionY = 0.65 * modifiers.get(SpellModifiers.DAMAGE); + caster.motionY = 0.65 * modifiers.get(SpellModifiers.POTENCY); caster.addVelocity(caster.getLookVec().x * 0.3, 0, caster.getLookVec().z * 0.3); if(world.isRemote){ diff --git a/src/main/java/electroblob/wizardry/spell/Levitation.java b/src/main/java/electroblob/wizardry/spell/Levitation.java index 1879e9bc..34779ce6 100644 --- a/src/main/java/electroblob/wizardry/spell/Levitation.java +++ b/src/main/java/electroblob/wizardry/spell/Levitation.java @@ -5,9 +5,9 @@ import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; @@ -16,7 +16,7 @@ import net.minecraft.world.World; public class Levitation extends Spell { public Levitation(){ - super(Tier.ADVANCED, 10, Element.SORCERY, "levitation", SpellType.UTILITY, 0, EnumAction.BOW, true); + super("levitation", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 10, 0, EnumAction.BOW, true); } @Override @@ -24,16 +24,16 @@ public class Levitation extends Spell { caster.fallDistance = 0; - caster.motionY = caster.motionY < 0.5d ? caster.motionY + 0.1d : caster.motionY; + caster.motionY = caster.motionY < 0.5 ? caster.motionY + 0.1 : caster.motionY; if(world.isRemote){ - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX - 0.25d + world.rand.nextDouble() / 2, - WizardryUtilities.getPlayerEyesPos(caster) - 1.5f, - caster.posZ - 0.25d + world.rand.nextDouble() / 2, 0, -0.1F, 0, 15, 0.5f, 1.0f, 0.7f); + double x = caster.posX - 0.25 + world.rand.nextDouble() * 0.5; + double y = caster.getEntityBoundingBox().minY; + double z = caster.posZ - 0.25 + world.rand.nextDouble() * 0.5; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).lifetime(15).colour(0.5f, 1, 0.7f).spawn(world); } if(ticksInUse % 24 == 0 && world.isRemote){ - Wizardry.proxy.playMovingSound(caster, WizardrySounds.SPELL_LOOP_SPARKLE, 0.5F, 1.0f, false); + Wizardry.proxy.playMovingSound(caster, WizardrySounds.SPELL_LOOP_SPARKLE, 0.5f, 1, false); } return true; } diff --git a/src/main/java/electroblob/wizardry/spell/LifeDrain.java b/src/main/java/electroblob/wizardry/spell/LifeDrain.java index 77d314bb..364b5890 100644 --- a/src/main/java/electroblob/wizardry/spell/LifeDrain.java +++ b/src/main/java/electroblob/wizardry/spell/LifeDrain.java @@ -1,110 +1,76 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class LifeDrain extends Spell { +public class LifeDrain extends SpellRay { + + private static final float BASE_DAMAGE = 2; + /** The fraction of the damage dealt that is transferred to the caster as healing. */ + private static final float HEAL_FACTOR = 0.35f; public LifeDrain(){ - super(Tier.APPRENTICE, 10, Element.NECROMANCY, "life_drain", SpellType.ATTACK, 0, EnumAction.NONE, true); + super("life_drain", Tier.APPRENTICE, Element.NECROMANCY, SpellType.ATTACK, 10, 0, true, 10, null); + this.particleVelocity(-0.5); + this.particleSpacing(0.4); } - + @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - - if(ticksInUse % 12 == 0){ - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), - 2.0f * modifiers.get(SpellModifiers.DAMAGE)); - caster.heal(1); + // TODO: Temporary solution until I implement a better continuous sound system + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag){ + if(ticksInUse % 18 == 0){ + if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 1, 0.6f); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_CRACKLE, 2, 1); } } - if(world.isRemote){ - for(int i = 5; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - // world.spawnParticle("mobSpell", x1, y1, z1, -1*look.xCoord, -1*look.yCoord, -1*look.zCoord); - if(i % 5 == 0){ - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 0, 0.1f, 0.0f, 0.0f); - } - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, -0.05 * look.x * i, - -0.05 * look.y * i, -0.05 * look.z * i, 8 + world.rand.nextInt(6), 0.5f, 0.0f, 0.0f); - } - } - if(ticksInUse % 18 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 1.0F, 0.6f); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_CRACKLE, 2.0F, 1.0f); - } - return true; + return flag; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - Vec3d vec = new Vec3d(target.posX - caster.posX, target.posY - caster.posY, target.posZ - caster.posZ).normalize(); - - if(ticksInUse % 12 == 0){ - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.MAGIC), - 2.0f * modifiers.get(SpellModifiers.DAMAGE)); - caster.heal(1); - } - - if(world.isRemote){ - for(int i = 5; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - double x1 = caster.posX + vec.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + vec.y * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + vec.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - // world.spawnParticle("mobSpell", x1, y1, z1, -1*look.xCoord, -1*look.yCoord, -1*look.zCoord); - if(i % 5 == 0){ - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 0, 0.1f, 0.0f, 0.0f); - } - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, -0.05 * vec.x * i, - -0.05 * vec.y * i, -0.05 * vec.z * i, 8 + world.rand.nextInt(6), 0.5f, 0.0f, 0.0f); - } - } - + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag){ if(ticksInUse % 18 == 0){ - if(ticksInUse == 0) caster.playSound(WizardrySounds.SPELL_SUMMONING, 1.0F, 0.6f); - caster.playSound(WizardrySounds.SPELL_LOOP_CRACKLE, 2.0F, 1.0f); + if(ticksInUse == 0) caster.playSound(WizardrySounds.SPELL_SUMMONING, 1, 0.6f); + caster.playSound(WizardrySounds.SPELL_LOOP_CRACKLE, 2, 1); } + } + return flag; + } + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + if(ticksInUse % 12 == 0){ + + float damage = BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY); + + WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeDirectMagicDamage(caster, + DamageType.MAGIC), damage); + + caster.heal(damage * HEAL_FACTOR); + } + return true; } @@ -112,8 +78,21 @@ public class LifeDrain extends Spell { } @Override - public boolean canBeCastByNPCs(){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + if(world.rand.nextInt(5) == 0) ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0, 0).spawn(world); + // This used to multiply the velocity by the distance from the caster + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(6)) + .colour(0.5f, 0, 0).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/Light.java b/src/main/java/electroblob/wizardry/spell/Light.java index 453c2865..b97cf15b 100644 --- a/src/main/java/electroblob/wizardry/spell/Light.java +++ b/src/main/java/electroblob/wizardry/spell/Light.java @@ -19,7 +19,7 @@ import net.minecraft.world.World; public class Light extends Spell { public Light(){ - super(Tier.BASIC, 5, Element.SORCERY, "light", SpellType.UTILITY, 15, EnumAction.NONE, false); + super("light", Tier.BASIC, Element.SORCERY, SpellType.UTILITY, 5, 15, EnumAction.NONE, false); } @Override @@ -30,7 +30,7 @@ public class Light extends Spell { @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - RayTraceResult rayTrace = WizardryUtilities.rayTrace(4, world, caster, false); + RayTraceResult rayTrace = WizardryUtilities.standardBlockRayTrace(world, caster, 4, false); if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ diff --git a/src/main/java/electroblob/wizardry/spell/LightningArrow.java b/src/main/java/electroblob/wizardry/spell/LightningArrow.java deleted file mode 100644 index 0940bc3b..00000000 --- a/src/main/java/electroblob/wizardry/spell/LightningArrow.java +++ /dev/null @@ -1,69 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityLightningArrow; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class LightningArrow extends Spell { - - public LightningArrow(){ - super(Tier.APPRENTICE, 15, Element.LIGHTNING, "lightning_arrow", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityLightningArrow lightningArrow = new EntityLightningArrow(world, caster, - 2 * modifiers.get(WizardryItems.range_upgrade), modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(lightningArrow); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1.0F, - world.rand.nextFloat() * 0.3F + 1.3F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityLightningArrow lightningArrow = new EntityLightningArrow(world, caster, target, - 2 * modifiers.get(WizardryItems.range_upgrade), 4, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(lightningArrow); - } - - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_LIGHTNING, 1.0F, world.rand.nextFloat() * 0.3F + 1.3F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/LightningBolt.java b/src/main/java/electroblob/wizardry/spell/LightningBolt.java index 85567859..49c854d3 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningBolt.java +++ b/src/main/java/electroblob/wizardry/spell/LightningBolt.java @@ -6,100 +6,66 @@ import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.effect.EntityLightningBolt; import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.passive.EntityPig; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; import net.minecraftforge.event.entity.EntityStruckByLightningEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber -public class LightningBolt extends Spell { +public class LightningBolt extends SpellRay { /** The NBT key used to store the UUID of the player that summoned the lightning bolt. Used for achievements. */ public static final String NBT_KEY = "summoningPlayer"; public LightningBolt(){ - super(Tier.ADVANCED, 40, Element.LIGHTNING, "lightning_bolt", SpellType.ATTACK, 80, EnumAction.NONE, false); + super("lightning_bolt", Tier.ADVANCED, Element.LIGHTNING, SpellType.ATTACK, 40, 80, false, 200, null); + this.ignoreEntities(true); } + @Override public boolean doesSpellRequirePacket(){ return false; } + @Override - public boolean doesSpellRequirePacket(){ + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(world.canBlockSeeSky(pos.up())){ - RayTraceResult rayTrace = WizardryUtilities.rayTrace(200, world, caster, false); + if(!world.isRemote){ + EntityLightningBolt entitylightning = new EntityLightningBolt(world, pos.getX(), pos.getY(), + pos.getZ(), false); + world.addWeatherEffect(entitylightning); - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = rayTrace.getBlockPos(); - - // Not sure why it is up 1 but it has to be for canBlockSeeSky to work properly. - // TODO: Remove this requirement? - if(world.canBlockSeeSky(pos.up())){ - - if(!world.isRemote){ - EntityLightningBolt entitylightning = new EntityLightningBolt(world, pos.getX(), pos.getY(), - pos.getZ(), false); - world.addWeatherEffect(entitylightning); - - // Code for eventhandler recognition; for achievements and such like. Left in for future use. + // Code for eventhandler recognition for achievements + if(caster instanceof EntityPlayer){ NBTTagCompound entityNBT = entitylightning.getEntityData(); entityNBT.setUniqueId(NBT_KEY, caster.getUniqueID()); } - - caster.swingArm(hand); - return true; } - } + return true; + } + return false; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - int x = (int)target.posX; - int y = (int)target.posY; - int z = (int)target.posZ; - - // Not sure why it is up 1 but it has to be for canBlockSeeSky to work properly. - // TODO: Remove this requirement? - if(world.canBlockSeeSky(new BlockPos(x, y, z))){ - - if(!world.isRemote){ - EntityLightningBolt entitylightning = new EntityLightningBolt(world, x, y, z, false); - world.addWeatherEffect(entitylightning); - } - - caster.swingArm(hand); - return true; - } - } - + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } - @Override - public boolean canBeCastByNPCs(){ - return true; - } - @SubscribeEvent public static void onEntityStruckByLightningEvent(EntityStruckByLightningEvent event){ @@ -116,6 +82,6 @@ public class LightningBolt extends Spell { WizardryAdvancementTriggers.frankenstein.triggerFor(player); } } - } + } diff --git a/src/main/java/electroblob/wizardry/spell/LightningDisc.java b/src/main/java/electroblob/wizardry/spell/LightningDisc.java deleted file mode 100644 index ef01f4f3..00000000 --- a/src/main/java/electroblob/wizardry/spell/LightningDisc.java +++ /dev/null @@ -1,69 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityLightningDisc; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class LightningDisc extends Spell { - - public LightningDisc(){ - super(Tier.ADVANCED, 25, Element.LIGHTNING, "lightning_disc", SpellType.ATTACK, 60, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityLightningDisc lightningdisc = new EntityLightningDisc(world, caster, - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(lightningdisc); - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1.0F, - world.rand.nextFloat() * 0.3F + 0.8F); - caster.swingArm(hand); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityLightningDisc lightningdisc = new EntityLightningDisc(world, caster, - modifiers.get(SpellModifiers.DAMAGE)); - lightningdisc.directTowards(target, 1.2f); - world.spawnEntity(lightningdisc); - } - - caster.playSound(WizardrySounds.SPELL_LIGHTNING, 1.0F, world.rand.nextFloat() * 0.3F + 0.8F); - caster.swingArm(hand); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/LightningHammer.java b/src/main/java/electroblob/wizardry/spell/LightningHammer.java index 6bf29e29..e31c283e 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningHammer.java +++ b/src/main/java/electroblob/wizardry/spell/LightningHammer.java @@ -4,60 +4,31 @@ import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityHammer; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -public class LightningHammer extends Spell { +public class LightningHammer extends SpellConstructRanged { public LightningHammer(){ - super(Tier.MASTER, 100, Element.LIGHTNING, "lightning_hammer", SpellType.ATTACK, 300, EnumAction.BOW, false); + super("lightning_hammer", Tier.MASTER, Element.LIGHTNING, SpellType.ATTACK, 100, 300, EntityHammer::new, 600, 40, WizardrySounds.SPELL_SUMMONING); + this.soundValues(3, 1, 0); + this.floor(true); + this.overlap(true); } @Override - public boolean doesSpellRequirePacket(){ - return false; + protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + // TESTME: Does this need to be one block higher? + if(!world.canBlockSeeSky(new BlockPos(x, y, z))) return false; + return super.spawnConstruct(world, x, y + 50, z, caster, modifiers); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(40 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = rayTrace.getBlockPos(); - - // Not sure why it is +1 but it has to be to work properly. - if(world.canBlockSeeSky(pos.up())){ - - if(!world.isRemote){ - - EntityHammer hammer = new EntityHammer(world, pos.getX() + 0.5, pos.getY() + 50, pos.getZ() + 0.5, - caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - - hammer.motionX = 0; - hammer.motionY = -2; - hammer.motionZ = 0; - - world.spawnEntity(hammer); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 3.0f, 1.0f); - return true; - } - } - return false; + protected void addConstructExtras(EntityHammer construct, EntityLivingBase caster, SpellModifiers modifiers){ + construct.motionY = -2; } } diff --git a/src/main/java/electroblob/wizardry/spell/LightningPulse.java b/src/main/java/electroblob/wizardry/spell/LightningPulse.java index 85fb7b49..acd809d4 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningPulse.java +++ b/src/main/java/electroblob/wizardry/spell/LightningPulse.java @@ -22,15 +22,20 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; public class LightningPulse extends Spell { + + private static final double BASE_RADIUS = 3; + private static final float BASE_DAMAGE = 8; public LightningPulse(){ - super(Tier.ADVANCED, 25, Element.LIGHTNING, "lightning_pulse", SpellType.ATTACK, 75, EnumAction.NONE, false); + super("lightning_pulse", Tier.ADVANCED, Element.LIGHTNING, SpellType.ATTACK, 25, 75, EnumAction.NONE, false); } @Override public boolean doesSpellRequirePacket(){ return false; } + + // TODO: NPC casting support @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ @@ -38,13 +43,13 @@ public class LightningPulse extends Spell { if(caster.onGround){ List targets = WizardryUtilities.getEntitiesWithinRadius( - 3.0d * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + BASE_RADIUS * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); for(EntityLivingBase target : targets){ if(WizardryUtilities.isValidTarget(caster, target)){ - // Damage is 4 hearts no matter where the target is. + // Base damage is 4 hearts no matter where the target is. target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 8 * modifiers.get(SpellModifiers.DAMAGE)); + BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); if(!world.isRemote){ @@ -66,15 +71,20 @@ public class LightningPulse extends Spell { } } } + if(!world.isRemote){ - EntityLightningPulse lightningpulse = new EntityLightningPulse(world, caster.posX, - caster.getEntityBoundingBox().minY, caster.posZ, caster, 7, - modifiers.get(SpellModifiers.DAMAGE)); + // Surely neither of the commented lines would have done anything? + EntityLightningPulse lightningpulse = new EntityLightningPulse(world); + lightningpulse.setPosition(caster.posX, caster.getEntityBoundingBox().minY, caster.posZ); + //lightningpulse.setCaster(caster); + lightningpulse.lifetime = 7; + //lightningpulse.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); world.spawnEntity(lightningpulse); } + caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1.0f, 1.0f); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SHOCKWAVE, 2.0f, 1.0f); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1, 1); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SHOCKWAVE, 2, 1); return true; } return false; diff --git a/src/main/java/electroblob/wizardry/spell/LightningRay.java b/src/main/java/electroblob/wizardry/spell/LightningRay.java index 0d7236b2..c2eb74a6 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningRay.java +++ b/src/main/java/electroblob/wizardry/spell/LightningRay.java @@ -1,158 +1,123 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.EntityArc; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class LightningRay extends Spell { +public class LightningRay extends SpellRay { + + private static final float BASE_DAMAGE = 3; public LightningRay(){ - super(Tier.APPRENTICE, 5, Element.LIGHTNING, "lightning_ray", SpellType.ATTACK, 0, EnumAction.NONE, true); + super("lightning_ray", Tier.APPRENTICE, Element.LIGHTNING, SpellType.ATTACK, 5, 0, true, 10, null); } - + @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade), 2.0f); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - Entity target = rayTrace.entityHit; - if(!world.isRemote){ - // This statement means the arc only spawns every other tick. - if(ticksInUse % 2 == 0){ - - EntityArc arc = new EntityArc(world); - // The look vec stuff performs a translation on the start point to line it up with the wand. - // EDIT: removed due to 1st/3rd person render differences. - arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ, target.posX, - target.posY + target.height / 2, target.posZ); - - arc.lifetime = 1; - - world.spawnEntity(arc); - } - - if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ - if(!world.isRemote && ticksInUse == 1) - caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), - this.getNameForTranslationFormatted())); - }else{ - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); - } - - }else{ - for(int i = 0; i < 5; i++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - } - } - + // TODO: Temporary solution until I implement a better continuous sound system + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag){ if(ticksInUse == 1){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1.0F, 1.0f); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1, 1); }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_LIGHTNING, 1.0F, 1.0f); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_LIGHTNING, 1, 1); } - - return true; - - }else{ - if(!world.isRemote){ - // This statement means the arc only spawns every other tick. - if(ticksInUse % 2 == 0){ - - EntityArc arc = new EntityArc(world); - - arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ, - caster.posX + caster.getLookVec().x * 8, - caster.posY + caster.eyeHeight + caster.getLookVec().y * 8, - caster.posZ + caster.getLookVec().z * 8); - - arc.lifetime = 1; - - world.spawnEntity(arc); - } - } - - if(ticksInUse == 1){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1.0F, 1.0f); - }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_LIGHTNING, 1.0F, 1.0f); - } - - return true; } + return flag; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag){ + if(ticksInUse == 1){ + caster.playSound(WizardrySounds.SPELL_LIGHTNING, 1, 1); + }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ + caster.playSound(WizardrySounds.SPELL_LOOP_LIGHTNING, 1, 1); + } + } + return flag; + } - if(target != null){ + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ + if(!world.isRemote && ticksInUse == 1) + caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), + this.getNameForTranslationFormatted())); + }else{ + WizardryUtilities.attackEntityWithoutKnockback(target, + MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), + BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); + } + if(!world.isRemote){ - // This statement means the arc only spawns every other tick. + if(ticksInUse % 2 == 0){ EntityArc arc = new EntityArc(world); - // The look vec stuff performs a translation on the start point to line it up with the wand. - // EDIT: removed due to 1st/3rd person render differences. arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ, target.posX, target.posY + target.height / 2, target.posZ); - arc.lifetime = 1; - world.spawnEntity(arc); } - WizardryUtilities.attackEntityWithoutKnockback(target, - MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); - }else{ - for(int i = 0; i < 5; i++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); + // Particle effect + for(int i=0; i<5; i++){ + ParticleBuilder.create(Type.SPARK, target); } } - - if(ticksInUse == 1){ - caster.playSound(WizardrySounds.SPELL_LIGHTNING, 1.0F, 1.0f); - }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - caster.playSound(WizardrySounds.SPELL_LOOP_LIGHTNING, 1.0F, 1.0f); - } - - return true; } - + return false; } @Override - public boolean canBeCastByNPCs(){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + // This is a nice example of when onMiss is used for more than just returning a boolean + if(!world.isRemote){ + + if(ticksInUse % 2 == 0){ + + double freeRange = 0.8 * baseRange; // The arc does not reach full range when it has a free end + + EntityArc arc = new EntityArc(world); + arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ, + caster.posX + caster.getLookVec().x * freeRange, + caster.posY + caster.getEyeHeight() + caster.getLookVec().y * freeRange, + caster.posZ + caster.getLookVec().z * freeRange); + arc.lifetime = 1; + world.spawnEntity(arc); + + } + } + return true; } diff --git a/src/main/java/electroblob/wizardry/spell/LightningSigil.java b/src/main/java/electroblob/wizardry/spell/LightningSigil.java deleted file mode 100644 index 14044079..00000000 --- a/src/main/java/electroblob/wizardry/spell/LightningSigil.java +++ /dev/null @@ -1,53 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityLightningSigil; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.world.World; - -public class LightningSigil extends Spell { - - public LightningSigil(){ - super(Tier.APPRENTICE, 10, Element.LIGHTNING, "lightning_sigil", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(10 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK && rayTrace.sideHit == EnumFacing.UP){ - - if(!world.isRemote){ - double x = rayTrace.hitVec.x; - double y = rayTrace.hitVec.y; - double z = rayTrace.hitVec.z; - EntityLightningSigil lightningsigil = new EntityLightningSigil(world, x, y, z, caster, - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(lightningsigil); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0F, 0.3F); - return true; - } - return false; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/LightningWeb.java b/src/main/java/electroblob/wizardry/spell/LightningWeb.java index 7bc5519b..548bec0e 100644 --- a/src/main/java/electroblob/wizardry/spell/LightningWeb.java +++ b/src/main/java/electroblob/wizardry/spell/LightningWeb.java @@ -2,219 +2,169 @@ package electroblob.wizardry.spell; import java.util.List; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.EntityArc; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class LightningWeb extends Spell { +public class LightningWeb extends SpellRay { + + private static final float PRIMARY_DAMAGE = 5; + private static final float SECONDARY_DAMAGE = 4; + private static final float TERTIARY_DAMAGE = 3; + + private static final double PRIMARY_RANGE = 10; + private static final double SECONDARY_RANGE = 5; + private static final double TERTIARY_RANGE = 5; + + private static final int SECONDARY_MAX_TARGETS = 5; + private static final int TERTIARY_MAX_TARGETS = 2; // This is per secondary target, giving 10 in total public LightningWeb(){ - super(Tier.MASTER, 15, Element.LIGHTNING, "lightning_web", SpellType.ATTACK, 0, EnumAction.NONE, true); + super("lightning_web", Tier.MASTER, Element.LIGHTNING, SpellType.ATTACK, 15, 0, true, PRIMARY_RANGE, null); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + // TODO: Temporary solution until I implement a better continuous sound system + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag){ + if(ticksInUse == 1){ + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1, 1); + }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_LIGHTNING, 1, 1); + } + } + return flag; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade), 2.0f); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - Entity target = rayTrace.entityHit; - - if(!world.isRemote){ - - // This statement means the arc only spawns every other tick. - if(ticksInUse % 2 == 0){ - EntityArc arc = new EntityArc(world); - // The look vec stuff performs a translation on the start point to line it up with the wand. - // EDIT: removed due to 1st/3rd person render differences. - arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ, target.posX, - target.posY + target.height / 2, target.posZ); - arc.lifetime = 1; - world.spawnEntity(arc); - } - - if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ - if(!world.isRemote && ticksInUse == 1) - caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), - this.getNameForTranslationFormatted())); - }else{ - // This motion stuff removes knockback, which is desirable for continuous spells. - double motionX = target.motionX; - double motionY = target.motionY; - double motionZ = target.motionZ; - - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 5.0f * modifiers.get(SpellModifiers.DAMAGE)); - - target.motionX = motionX; - target.motionY = motionY; - target.motionZ = motionZ; - } - }else{ - for(int i = 0; i < 5; i++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - target.posX + world.rand.nextFloat() - 0.5, - target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1, - target.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - } + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag){ + if(ticksInUse == 1){ + caster.playSound(WizardrySounds.SPELL_LIGHTNING, 1, 1); + }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ + caster.playSound(WizardrySounds.SPELL_LOOP_LIGHTNING, 1, 1); } - + } + return flag; + } + + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + electrocute(world, caster, caster, target, PRIMARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY), ticksInUse); + // Secondary chaining effect - double seekerRange = 5.0d; - List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, + List secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(SECONDARY_RANGE, target.posX, target.posY + target.height / 2, target.posZ, world); - // This is a MUCH better way of filtering the secondary targets! + secondaryTargets.remove(target); - if(secondaryTargets.size() > 5) secondaryTargets = secondaryTargets.subList(0, 5); + secondaryTargets.removeIf(e -> !WizardryUtilities.isLiving(e)); + secondaryTargets.removeIf(e -> !WizardryUtilities.isValidTarget(caster, e)); + if(secondaryTargets.size() > SECONDARY_MAX_TARGETS) secondaryTargets = secondaryTargets.subList(0, SECONDARY_MAX_TARGETS); for(EntityLivingBase secondaryTarget : secondaryTargets){ - if(WizardryUtilities.isValidTarget(caster, secondaryTarget)){ + electrocute(world, caster, target, secondaryTarget, + SECONDARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY), ticksInUse); - if(!world.isRemote){ - // This statement means the arc only spawns every other tick. - if(ticksInUse % 2 == 0){ - EntityArc arc = new EntityArc(world); - arc.setEndpointCoords(target.posX, target.posY + 1.2, target.posZ, secondaryTarget.posX, - secondaryTarget.posY + secondaryTarget.height / 2, secondaryTarget.posZ); - arc.lifetime = 1; - world.spawnEntity(arc); - } + // Tertiary chaining effect - if(MagicDamage.isEntityImmune(DamageType.SHOCK, secondaryTarget)){ - if(!world.isRemote && ticksInUse == 1) - caster.sendMessage(new TextComponentTranslation("spell.resist", - secondaryTarget.getName(), this.getNameForTranslationFormatted())); - }else{ - // This motion stuff removes knockback, which is desirable for continuous spells. - double motionX = secondaryTarget.motionX; - double motionY = secondaryTarget.motionY; - double motionZ = secondaryTarget.motionZ; + List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius(TERTIARY_RANGE, + secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2, + secondaryTarget.posZ, world); + + tertiaryTargets.remove(target); + tertiaryTargets.removeAll(secondaryTargets); + tertiaryTargets.removeIf(e -> !WizardryUtilities.isLiving(e)); + tertiaryTargets.removeIf(e -> !WizardryUtilities.isValidTarget(caster, e)); + if(tertiaryTargets.size() > TERTIARY_MAX_TARGETS) tertiaryTargets = tertiaryTargets.subList(0, TERTIARY_MAX_TARGETS); - secondaryTarget.attackEntityFrom( - MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 4.0f * modifiers.get(SpellModifiers.DAMAGE)); - - secondaryTarget.motionX = motionX; - secondaryTarget.motionY = motionY; - secondaryTarget.motionZ = motionZ; - } - }else{ - for(int i = 0; i < 5; i++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - secondaryTarget.posX + world.rand.nextFloat() - 0.5, - secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - secondaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - } - } - - // Tertiary chaining effect - - List tertiaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, - secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2, - secondaryTarget.posZ, world); - tertiaryTargets.remove(target); - tertiaryTargets.removeAll(secondaryTargets); - if(tertiaryTargets.size() > 2) tertiaryTargets = tertiaryTargets.subList(0, 2); - - for(EntityLivingBase tertiaryTarget : tertiaryTargets){ - - if(WizardryUtilities.isValidTarget(caster, tertiaryTarget)){ - - if(!world.isRemote){ - // This statement means the arc only spawns every other tick. - if(ticksInUse % 2 == 0){ - EntityArc arc = new EntityArc(world); - arc.setEndpointCoords(secondaryTarget.posX, secondaryTarget.posY + 1.2, - secondaryTarget.posZ, tertiaryTarget.posX, - tertiaryTarget.posY + tertiaryTarget.height / 2, tertiaryTarget.posZ); - arc.lifetime = 1; - world.spawnEntity(arc); - } - - if(MagicDamage.isEntityImmune(DamageType.SHOCK, tertiaryTarget)){ - if(!world.isRemote && ticksInUse == 1) - caster.sendMessage(new TextComponentTranslation("spell.resist", - tertiaryTarget.getName(), this.getNameForTranslationFormatted())); - }else{ - // This motion stuff removes knockback, which is desirable for continuous spells. - double motionX = tertiaryTarget.motionX; - double motionY = tertiaryTarget.motionY; - double motionZ = tertiaryTarget.motionZ; - - tertiaryTarget.attackEntityFrom( - MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 3.0f * modifiers.get(SpellModifiers.DAMAGE)); - - tertiaryTarget.motionX = motionX; - tertiaryTarget.motionY = motionY; - tertiaryTarget.motionZ = motionZ; - } - }else{ - for(int i = 0; i < 5; i++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - tertiaryTarget.posX + world.rand.nextFloat() - 0.5, - tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - tertiaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - } - } - } - } + for(EntityLivingBase tertiaryTarget : tertiaryTargets){ + electrocute(world, caster, secondaryTarget, tertiaryTarget, + TERTIARY_DAMAGE * modifiers.get(SpellModifiers.POTENCY), ticksInUse); } } + } + + return false; + } - if(ticksInUse == 1){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1.0F, 1.0f); - }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_LIGHTNING, 1.0F, 1.0f); + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + // This is a nice example of when onMiss is used for more than just returning a boolean + if(!world.isRemote){ + + if(ticksInUse % 2 == 0){ + + double freeRange = 0.8 * baseRange; // The arc does not reach full range when it has a free end + + EntityArc arc = new EntityArc(world); + arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ, + caster.posX + caster.getLookVec().x * freeRange, + caster.posY + caster.getEyeHeight() + caster.getLookVec().y * freeRange, + caster.posZ + caster.getLookVec().z * freeRange); + arc.lifetime = 1; + world.spawnEntity(arc); + } + } + + return true; + } + + private void electrocute(World world, Entity caster, Entity origin, Entity target, float damage, int ticksInUse){ - return true; - + if(MagicDamage.isEntityImmune(DamageType.SHOCK, target)){ + if(!world.isRemote && ticksInUse == 1) + caster.sendMessage(new TextComponentTranslation("spell.resist", + target.getName(), this.getNameForTranslationFormatted())); }else{ - if(!world.isRemote){ - // This statement means the arc only spawns every other tick. - if(ticksInUse % 2 == 0){ - EntityArc arc = new EntityArc(world); - arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ, - caster.posX + caster.getLookVec().x * 8, - caster.posY + caster.eyeHeight + caster.getLookVec().y * 8, - caster.posZ + caster.getLookVec().z * 8); - arc.lifetime = 1; - // arc.setOffset(entityplayer.getLookVec().zCoord * 0.5, entityplayer.getLookVec().xCoord * 0.5); - world.spawnEntity(arc); - } + WizardryUtilities.attackEntityWithoutKnockback(target, + MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), damage); + } + + if(!world.isRemote){ + // Arc entity spawning + if(ticksInUse % 2 == 0){ + EntityArc arc = new EntityArc(world); + arc.setEndpointCoords(origin.posX, origin.posY + 1.2, origin.posZ, target.posX, + target.posY + target.height / 2, target.posZ); + arc.lifetime = 1; + world.spawnEntity(arc); } - - if(ticksInUse == 1){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LIGHTNING, 1.0F, 1.0f); - }else if(ticksInUse > 0 && ticksInUse % 20 == 0){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_LIGHTNING, 1.0F, 1.0f); + + }else{ + // Particle effect + for(int i=0; i<5; i++){ + ParticleBuilder.create(Type.SPARK, target); } - - return true; } } diff --git a/src/main/java/electroblob/wizardry/spell/MagicMissile.java b/src/main/java/electroblob/wizardry/spell/MagicMissile.java deleted file mode 100644 index 1b42bc93..00000000 --- a/src/main/java/electroblob/wizardry/spell/MagicMissile.java +++ /dev/null @@ -1,71 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityMagicMissile; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class MagicMissile extends Spell { - - public MagicMissile(){ - super(Tier.BASIC, 5, Element.MAGIC, "magic_missile", SpellType.ATTACK, 10, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityMagicMissile magicMissile = new EntityMagicMissile(world, caster, - 2 * modifiers.get(WizardryItems.range_upgrade), modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(magicMissile); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_MAGIC, 1.0F, - world.rand.nextFloat() * 0.4F + 1.2F); - - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityMagicMissile magicMissile = new EntityMagicMissile(world, caster, target, - 2 * modifiers.get(WizardryItems.range_upgrade), 4, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(magicMissile); - } - - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_MAGIC, 1.0F, world.rand.nextFloat() * 0.4F + 1.2F); - - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Metamorphosis.java b/src/main/java/electroblob/wizardry/spell/Metamorphosis.java index 5489e28d..56ec9107 100644 --- a/src/main/java/electroblob/wizardry/spell/Metamorphosis.java +++ b/src/main/java/electroblob/wizardry/spell/Metamorphosis.java @@ -9,10 +9,10 @@ import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntitySkeletonMinion; import electroblob.wizardry.entity.living.EntityWitherSkeletonMinion; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -31,21 +31,16 @@ import net.minecraft.entity.passive.EntityChicken; import net.minecraft.entity.passive.EntityCow; import net.minecraft.entity.passive.EntityMooshroom; import net.minecraft.entity.passive.EntityPig; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class Metamorphosis extends Spell { +public class Metamorphosis extends SpellRay { public static final BiMap, Class> TRANSFORMATIONS = HashBiMap.create(); - public Metamorphosis(){ - super(Tier.APPRENTICE, 15, Element.NECROMANCY, "metamorphosis", SpellType.UTILITY, 30, EnumAction.NONE, false); - + static { addTransformation(EntityPig.class, EntityPigZombie.class); addTransformation(EntityCow.class, EntityMooshroom.class); addTransformation(EntityChicken.class, EntityBat.class); @@ -66,25 +61,26 @@ public class Metamorphosis extends Spell { previousEntity = entity; } } + + public Metamorphosis(){ + super("metamorphosis", Tier.APPRENTICE, Element.NECROMANCY, SpellType.UTILITY, 15, 30, false, 10, WizardrySounds.SPELL_DEFLECTION); + this.soundValues(0.5f, 0.8f, 0); + } + + @Override public boolean canBeCastByNPCs() { return false; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.entityHit != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - Entity entityHit = rayTrace.entityHit; - double xPos = entityHit.posX; - double yPos = entityHit.posY; - double zPos = entityHit.posZ; + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + double xPos = target.posX; + double yPos = target.posY; + double zPos = target.posZ; // Sneaking allows the entities to be cycled through in the other direction. Class newEntityClass = caster.isSneaking() ? - TRANSFORMATIONS.inverse().get(entityHit.getClass()) : TRANSFORMATIONS.get(entityHit.getClass()); + TRANSFORMATIONS.inverse().get(target.getClass()) : TRANSFORMATIONS.get(target.getClass()); if(newEntityClass == null) return false; @@ -93,7 +89,8 @@ public class Metamorphosis extends Spell { try { newEntity = newEntityClass.getConstructor(World.class).newInstance(world); } catch (Exception e){ - Wizardry.logger.error("Error while attempting to transform entity " + entityHit.getClass() + " to entity " + newEntityClass); + Wizardry.logger.error("Error while attempting to transform entity " + target.getClass() + " to entity " + + newEntityClass); e.printStackTrace(); } @@ -101,39 +98,34 @@ public class Metamorphosis extends Spell { if(!world.isRemote){ // Transfers attributes from the old entity to the new one. - newEntity.setHealth(((EntityLivingBase)entityHit).getHealth()); + newEntity.setHealth(((EntityLivingBase)target).getHealth()); NBTTagCompound tag = new NBTTagCompound(); - entityHit.writeToNBT(tag); + target.writeToNBT(tag); // Remove the UUID because keeping it the same causes the entity to disappear WizardryUtilities.removeUniqueId(tag, "UUID"); newEntity.readFromNBT(tag); - entityHit.setDead(); + target.setDead(); newEntity.setPosition(xPos, yPos, zPos); world.spawnEntity(newEntity); }else{ - - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - // world.spawnParticle("mobSpell", x1, y1, z1, -1*look.xCoord, -1*look.yCoord, -1*look.zCoord); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 0.2f, 0.0f, 0.1f); - } - for(int i = 0; i < 5; i++){ - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, xPos, yPos, zPos, 0.0d, - 0.0d, 0.0d, 0, 0.1f, 0.0f, 0.0f); + for(int i=0; i<5; i++){ + ParticleBuilder.create(Type.DARK_MAGIC).pos(xPos, yPos, zPos).colour(0.1f, 0, 0).spawn(world); } } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_DEFLECTION, 0.5F, 0.8f); - return true; } + + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/Meteor.java b/src/main/java/electroblob/wizardry/spell/Meteor.java index 073d9ba6..e309762e 100644 --- a/src/main/java/electroblob/wizardry/spell/Meteor.java +++ b/src/main/java/electroblob/wizardry/spell/Meteor.java @@ -7,49 +7,46 @@ import electroblob.wizardry.entity.EntityMeteor; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -public class Meteor extends Spell { +public class Meteor extends SpellRay { public Meteor(){ - super(Tier.MASTER, 100, Element.FIRE, "meteor", SpellType.ATTACK, 200, EnumAction.NONE, false); + super("meteor", Tier.MASTER, Element.FIRE, SpellType.ATTACK, 100, 200, false, 40, WizardrySounds.SPELL_SUMMONING); + this.soundValues(3, 1, 0); + this.ignoreEntities(true); } + @Override public boolean doesSpellRequirePacket(){ return false; } + @Override - public boolean doesSpellRequirePacket(){ + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(world.canBlockSeeSky(pos.up())){ - RayTraceResult rayTrace = WizardryUtilities.rayTrace(40 * modifiers.get(WizardryItems.range_upgrade), world, - caster, false); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = rayTrace.getBlockPos(); - - // Not sure why it is +1 but it has to be to work properly. - if(world.canBlockSeeSky(pos.up())){ - - if(!world.isRemote){ - EntityMeteor meteor = new EntityMeteor(world, pos.getX(), pos.getY() + 50, pos.getZ(), - modifiers.get(WizardryItems.blast_upgrade)); - world.spawnEntity(meteor); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 3.0f, 1.0f); - return true; + if(!world.isRemote){ + EntityMeteor meteor = new EntityMeteor(world, pos.getX(), pos.getY() + 50, pos.getZ(), + modifiers.get(WizardryItems.blast_upgrade)); + world.spawnEntity(meteor); } + + return true; } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } diff --git a/src/main/java/electroblob/wizardry/spell/MindControl.java b/src/main/java/electroblob/wizardry/spell/MindControl.java index bcf46dc8..96c4cccd 100644 --- a/src/main/java/electroblob/wizardry/spell/MindControl.java +++ b/src/main/java/electroblob/wizardry/spell/MindControl.java @@ -11,8 +11,9 @@ import electroblob.wizardry.entity.living.EntityEvilWizard; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityList; @@ -21,12 +22,10 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.INpc; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.item.EntityArmorStand; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; @@ -35,115 +34,73 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber -public class MindControl extends Spell { +public class MindControl extends SpellRay { - /** - * The NBT tag name for storing the controlling entity's UUID in the target's tag compound. Defined here in case it - * changes. - */ + /** The NBT tag name for storing the controlling entity's UUID in the target's tag compound. */ public static final String NBT_KEY = "controllingEntity"; + + private static final int BASE_DURATION = 600; public MindControl(){ - super(Tier.ADVANCED, 40, Element.NECROMANCY, "mind_control", SpellType.ATTACK, 150, EnumAction.NONE, false); + super("mind_control", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 40, 150, false, 8, WizardrySounds.SPELL_SUMMONING); } - + @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 8 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.entityHit != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + if(!world.isRemote){ + if(!canControl(target)){ // Adds a message saying that the player/boss entity/wizard resisted mind control caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted())); - + }else if(target instanceof EntityLiving){ - + if(!MindControl.findMindControlTarget((EntityLiving)target, caster, world)){ // If no valid target was found, this just acts like mind trick. ((EntityLiving)target).setAttackTarget(null); } - + NBTTagCompound entityNBT = target.getEntityData(); if(entityNBT != null) entityNBT.setUniqueId(NBT_KEY, caster.getUniqueID()); - + ((EntityLiving)target).addPotionEffect(new PotionEffect(WizardryPotions.mind_control, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); } + }else{ - for(int i = 0; i < 10; i++){ - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, - target.posX - 0.25 + world.rand.nextDouble() * 0.5, - target.getEntityBoundingBox().minY + target.getEyeHeight() - 0.25 - + world.rand.nextDouble() * 0.5, - target.posZ - 0.25 + world.rand.nextDouble() * 0.5, 0, 0, 0, 0, 0.8f, 0.2f, 1.0f); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, - target.posX - 0.25 + world.rand.nextDouble() * 0.5, - target.getEntityBoundingBox().minY + target.getEyeHeight() - 0.25 - + world.rand.nextDouble() * 0.5, - target.posZ - 0.25 + world.rand.nextDouble() * 0.5, 0, 0, 0, 0, 0.2f, 0.04f, 0.25f); + + for(int i=0; i<10; i++){ + ParticleBuilder.create(Type.DARK_MAGIC, world.rand, target.posX, + target.getEntityBoundingBox().minY + target.getEyeHeight(), target.posZ, 0.25, false) + .colour(0.8f, 0.2f, 1.0f).spawn(world); + ParticleBuilder.create(Type.DARK_MAGIC, world.rand, target.posX, + target.getEntityBoundingBox().minY + target.getEyeHeight(), target.posZ, 0.25, false) + .colour(0.2f, 0.04f, 0.25f).spawn(world); } } - target.playSound(WizardrySounds.SPELL_SUMMONING, 1.0f, 1.0f); - caster.swingArm(hand); + return true; } + return false; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - if(!world.isRemote){ - if(canControl(target)){ - - if(!MindControl.findMindControlTarget((EntityLiving)target, caster, world)){ - // If no valid target was found, this just acts like mind trick. - ((EntityLiving)target).setAttackTarget(null); - } - - NBTTagCompound entityNBT = target.getEntityData(); - if(entityNBT != null) entityNBT.setUniqueId(NBT_KEY, caster.getUniqueID()); - - ((EntityLiving)target).addPotionEffect(new PotionEffect(WizardryPotions.mind_control, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - } - }else{ - for(int i = 0; i < 10; i++){ - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, - target.posX - 0.25 + world.rand.nextDouble() * 0.5, - target.getEntityBoundingBox().minY + target.getEyeHeight() - 0.25 - + world.rand.nextDouble() * 0.5, - target.posZ - 0.25 + world.rand.nextDouble() * 0.5, 0, 0, 0, 0, 0.8f, 0.2f, 1.0f); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, - target.posX - 0.25 + world.rand.nextDouble() * 0.5, - target.getEntityBoundingBox().minY + target.getEyeHeight() - 0.25 - + world.rand.nextDouble() * 0.5, - target.posZ - 0.25 + world.rand.nextDouble() * 0.5, 0, 0, 0, 0, 0.2f, 0.04f, 0.25f); - } - } - target.playSound(WizardrySounds.SPELL_SUMMONING, 1.0f, 1.0f); - caster.swingArm(hand); - return true; - } + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean canBeCastByNPCs(){ - return true; + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; } /** Returns true if the given entity can be mind controlled (i.e. is not a player, npc, evil wizard or boss). */ - public static boolean canControl(EntityLivingBase target){ + public static boolean canControl(Entity target){ return target instanceof EntityLiving && target.isNonBoss() && !(target instanceof INpc) && !(target instanceof EntityEvilWizard) && !Arrays.asList(Wizardry.settings.mindControlTargetsBlacklist) .contains(EntityList.getKey(target.getClass())); diff --git a/src/main/java/electroblob/wizardry/spell/MindTrick.java b/src/main/java/electroblob/wizardry/spell/MindTrick.java index 9f4f0dab..0bf6b2fa 100644 --- a/src/main/java/electroblob/wizardry/spell/MindTrick.java +++ b/src/main/java/electroblob/wizardry/spell/MindTrick.java @@ -1,23 +1,23 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardryPotions; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; @@ -25,90 +25,56 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @Mod.EventBusSubscriber -public class MindTrick extends Spell { +public class MindTrick extends SpellRay { + + private static final int BASE_DURATION = 300; public MindTrick(){ - super(Tier.BASIC, 10, Element.NECROMANCY, "mind_trick", SpellType.ATTACK, 40, EnumAction.NONE, false); + super("mind_trick", Tier.BASIC, Element.NECROMANCY, SpellType.ATTACK, 10, 40, false, 8, WizardrySounds.SPELL_DEFLECTION); + this.soundValues(0.7f, 1, 0.4f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 8 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.entityHit != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ if(!world.isRemote){ if(target instanceof EntityPlayer){ - target.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, - (int)(300 * modifiers.get(WizardryItems.duration_upgrade)), 0)); + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.NAUSEA, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); }else if(target instanceof EntityLiving){ ((EntityLiving)target).setAttackTarget(null); - target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, - (int)(300 * modifiers.get(WizardryItems.duration_upgrade)), 0)); + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 0)); } + }else{ - for(int i = 0; i < 10; i++){ - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, - target.posX - 0.25 + world.rand.nextDouble() * 0.5, - target.getEntityBoundingBox().minY + target.getEyeHeight() - 0.25 - + world.rand.nextDouble() * 0.5, - target.posZ - 0.25 + world.rand.nextDouble() * 0.5, 0, 0, 0, 0, 0.8f, 0.2f, 1.0f); + for(int i=0; i<10; i++){ + ParticleBuilder.create(Type.DARK_MAGIC, world.rand, target.posX, + target.getEntityBoundingBox().minY + target.getEyeHeight(), target.posZ, 0.25, false) + .colour(0.8f, 0.2f, 1.0f).spawn(world); } } - - target.playSound(WizardrySounds.SPELL_DEFLECTION, 0.7F, world.rand.nextFloat() * 0.4F + 0.8F); - caster.swingArm(hand); + return true; } + return false; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - if(!world.isRemote){ - if(target instanceof EntityPlayer){ - - target.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, - (int)(300 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - - }else if(target instanceof EntityLiving){ - - ((EntityLiving)target).setAttackTarget(null); - target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, - (int)(300 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - - } - }else{ - for(int i = 0; i < 10; i++){ - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, - target.posX - 0.25 + world.rand.nextDouble() * 0.5, - target.getEntityBoundingBox().minY + target.getEyeHeight() - 0.25 - + world.rand.nextDouble() * 0.5, - target.posZ - 0.25 + world.rand.nextDouble() * 0.5, 0, 0, 0, 0, 0.8f, 0.2f, 1.0f); - } - } - - target.playSound(WizardrySounds.SPELL_DEFLECTION, 0.7F, world.rand.nextFloat() * 0.4F + 0.8F); - caster.swingArm(hand); - return true; - } + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean canBeCastByNPCs(){ - return true; + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; } @SubscribeEvent diff --git a/src/main/java/electroblob/wizardry/spell/None.java b/src/main/java/electroblob/wizardry/spell/None.java index 23d16860..95e82045 100644 --- a/src/main/java/electroblob/wizardry/spell/None.java +++ b/src/main/java/electroblob/wizardry/spell/None.java @@ -12,12 +12,12 @@ import net.minecraft.world.World; /** * This class represents a blank spell used to fill empty slots on wands. It is unobtainable in-game, except via * commands, and does nothing when the player attempts to cast it. Its instance can be referenced directly using - * {@link electroblob.wizardry.registry.Spells#none WizardryRegistry.none} + * {@link electroblob.wizardry.registry.Spells#none Spells.none} */ public class None extends Spell { public None(){ - super(Tier.BASIC, 0, Element.MAGIC, "none", SpellType.UTILITY, 0, EnumAction.NONE, false); + super("none", Tier.BASIC, Element.MAGIC, SpellType.UTILITY, 0, 0, EnumAction.NONE, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/Oakflesh.java b/src/main/java/electroblob/wizardry/spell/Oakflesh.java deleted file mode 100644 index 21488735..00000000 --- a/src/main/java/electroblob/wizardry/spell/Oakflesh.java +++ /dev/null @@ -1,79 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Oakflesh extends Spell { - - public Oakflesh(){ - super(Tier.APPRENTICE, 20, Element.HEALING, "oakflesh", SpellType.DEFENCE, 50, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - caster.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.6f, 0.5f, 0.4f); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!caster.isPotionActive(MobEffects.RESISTANCE)){ - - caster.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 1, false, false)); - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)caster.posY + caster.getEyeHeight() - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.6f, 0.5f, 0.4f); - } - } - - caster.playSound(WizardrySounds.SPELL_HEAL, 0.7F, world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Petrify.java b/src/main/java/electroblob/wizardry/spell/Petrify.java index 7b1f1a6a..bdbaba16 100644 --- a/src/main/java/electroblob/wizardry/spell/Petrify.java +++ b/src/main/java/electroblob/wizardry/spell/Petrify.java @@ -1,126 +1,60 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockStatue; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.tileentity.TileEntityStatue; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.SpellModifiers; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class Petrify extends Spell { +public class Petrify extends SpellRay { - private static final int baseDuration = 900; - - /** - * The NBT tag name for storing the petrified flag in the target's tag compound. Defined here in case it changes. - */ - public static final String NBT_KEY = "petrified"; + private static final int BASE_DURATION = 900; public Petrify(){ - super(Tier.ADVANCED, 40, Element.SORCERY, "petrify", SpellType.ATTACK, 100, EnumAction.NONE, false); + super("petrify", Tier.ADVANCED, Element.SORCERY, SpellType.ATTACK, 40, 100, false, 10, SoundEvents.ENTITY_WITHER_SPAWN); + this.soundValues(1, 1.1f, 0.2f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY - && rayTrace.entityHit instanceof EntityLiving && !world.isRemote){ - - EntityLiving target = (EntityLiving)rayTrace.entityHit; - - if(target.deathTime > 0) return false; - - BlockPos pos = new BlockPos(target); - - target.extinguish(); - - // Short mobs such as spiders and pigs - if((target.height < 1.2 || target.isChild()) && WizardryUtilities.canBlockBeReplaced(world, pos)){ - world.setBlockState(pos, WizardryBlocks.petrified_stone.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(target, 1, 1); - ((TileEntityStatue)world.getTileEntity(pos)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - target.getEntityData().setBoolean(NBT_KEY, true); - target.setDead(); - } - // Normal sized mobs like zombies and skeletons - else if(target.height < 2.5 && WizardryUtilities.canBlockBeReplaced(world, pos) - && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ - world.setBlockState(pos, WizardryBlocks.petrified_stone.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(target, 1, 2); - ((TileEntityStatue)world.getTileEntity(pos)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - - world.setBlockState(pos.up(), WizardryBlocks.petrified_stone.getDefaultState()); - if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up())).setCreatureAndPart(target, 2, 2); - } - target.getEntityData().setBoolean(NBT_KEY, true); - target.setDead(); - } - // Tall mobs like endermen - else if(WizardryUtilities.canBlockBeReplaced(world, pos) - && WizardryUtilities.canBlockBeReplaced(world, pos.up()) - && WizardryUtilities.canBlockBeReplaced(world, pos.up(2))){ - world.setBlockState(pos, WizardryBlocks.petrified_stone.getDefaultState()); - if(world.getTileEntity(pos) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos)).setCreatureAndPart(target, 1, 3); - ((TileEntityStatue)world.getTileEntity(pos)) - .setLifetime((int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade))); - } - - world.setBlockState(pos.up(), WizardryBlocks.petrified_stone.getDefaultState()); - if(world.getTileEntity(pos.up()) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up())).setCreatureAndPart(target, 2, 3); - } - - world.setBlockState(pos.up(2), WizardryBlocks.petrified_stone.getDefaultState()); - if(world.getTileEntity(pos.up(2)) instanceof TileEntityStatue){ - ((TileEntityStatue)world.getTileEntity(pos.up(2))).setCreatureAndPart(target, 3, 3); - } - target.getEntityData().setBoolean(NBT_KEY, true); - target.setDead(); + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(target instanceof EntityLiving && !world.isRemote){ + // Unchecked cast is fine because the block is a static final field + if(((BlockStatue)WizardryBlocks.petrified_stone).convertToStatue((EntityLiving)target, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)))){ + + return true; } } - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - // world.spawnParticle("mobSpell", x1, y1, z1, -1*look.xCoord, -1*look.yCoord, -1*look.zCoord); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0, - 0.1f, 0.1f, 0.1f); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 0.2f, 0.2f, 0.2f); - } - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); + + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(0.2f, 0.2f, 0.2f).spawn(world); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0.1f, 0.1f).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/PhaseStep.java b/src/main/java/electroblob/wizardry/spell/PhaseStep.java index c7f21d7b..2a7ad268 100644 --- a/src/main/java/electroblob/wizardry/spell/PhaseStep.java +++ b/src/main/java/electroblob/wizardry/spell/PhaseStep.java @@ -20,7 +20,7 @@ import net.minecraft.world.World; public class PhaseStep extends Spell { public PhaseStep(){ - super(Tier.ADVANCED, 35, Element.SORCERY, "phase_step", SpellType.UTILITY, 40, EnumAction.NONE, false); + super("phase_step", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 35, 40, EnumAction.NONE, false); } @Override @@ -28,7 +28,7 @@ public class PhaseStep extends Spell { // Phase step does not gain range from range multiplier, instead it increases the thickness // of the wall you can teleport through. - RayTraceResult rayTrace = WizardryUtilities.rayTrace(5, world, caster, false); + RayTraceResult rayTrace = WizardryUtilities.standardBlockRayTrace(world, caster, 5, false); if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ @@ -71,7 +71,7 @@ public class PhaseStep extends Spell { if(world.isRemote){ for(int i = 0; i < 10; i++){ double dx1 = caster.posX; - double dy1 = WizardryUtilities.getPlayerEyesPos(caster) - 1.5 + 2 * world.rand.nextFloat(); + double dy1 = caster.getEntityBoundingBox().minY + 2 * world.rand.nextFloat(); double dz1 = caster.posZ; world.spawnParticle(EnumParticleTypes.PORTAL, dx1, dy1, dz1, world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5); diff --git a/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java b/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java index 03d4ba9e..f9f87a10 100644 --- a/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java +++ b/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java @@ -2,15 +2,15 @@ package electroblob.wizardry.spell; import java.util.List; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; @@ -25,42 +25,48 @@ import net.minecraft.util.EnumParticleTypes; import net.minecraft.world.World; public class PlagueOfDarkness extends Spell { + + private static final double BASE_RADIUS = 5; + private static final float BASE_DAMAGE = 8; + private static final int BASE_DURATION = 140; public PlagueOfDarkness(){ - super(Tier.MASTER, 75, Element.NECROMANCY, "plague_of_darkness", SpellType.ATTACK, 200, EnumAction.BOW, false); + super("plague_of_darkness", Tier.MASTER, Element.NECROMANCY, SpellType.ATTACK, 75, 200, EnumAction.BOW, false); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ List targets = WizardryUtilities.getEntitiesWithinRadius( - 5.0d * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + BASE_RADIUS * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); for(EntityLivingBase target : targets){ if(WizardryUtilities.isValidTarget(caster, target) && !MagicDamage.isEntityImmune(DamageType.WITHER, target)){ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.WITHER), - 8.0f * modifiers.get(SpellModifiers.DAMAGE)); + BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY)); target.addPotionEffect(new PotionEffect(MobEffects.WITHER, - (int)(140 * modifiers.get(WizardryItems.duration_upgrade)), 2)); + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 2)); } } if(world.isRemote){ + double particleX, particleZ; + for(int i = 0; i < 40 * modifiers.get(WizardryItems.blast_upgrade); i++){ + particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, particleX, - WizardryUtilities.getPlayerEyesPos(caster) - 1.5, particleZ, particleX - caster.posX, 0, - particleZ - caster.posZ, 0, 0.1f, 0.0f, 0.0f); + ParticleBuilder.create(Type.DARK_MAGIC).pos(particleX, caster.getEntityBoundingBox().minY, particleZ) + .vel(particleX - caster.posX, 0, particleZ - caster.posZ).colour(0.1f, 0, 0).spawn(world); + particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, particleX, - WizardryUtilities.getPlayerEyesPos(caster) - 1.5, particleZ, particleX - caster.posX, 0, - particleZ - caster.posZ, 30, 0.1f, 0.0f, 0.05f); + ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ) + .vel(particleX - caster.posX, 0, particleZ - caster.posZ).lifetime(30).colour(0.1f, 0, 0.05f).spawn(world); + particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - IBlockState block = WizardryUtilities.getBlockEntityIsStandingOn(caster); if(block != null){ @@ -69,9 +75,9 @@ public class PlagueOfDarkness extends Spell { } } } + caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_DEATH, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); + WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_DEATH, 1, 1 + 0.2f * world.rand.nextFloat()); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/PocketFurnace.java b/src/main/java/electroblob/wizardry/spell/PocketFurnace.java index 78bc3342..dbcb7312 100644 --- a/src/main/java/electroblob/wizardry/spell/PocketFurnace.java +++ b/src/main/java/electroblob/wizardry/spell/PocketFurnace.java @@ -17,7 +17,7 @@ import net.minecraft.world.World; public class PocketFurnace extends Spell { public PocketFurnace(){ - super(Tier.APPRENTICE, 30, Element.FIRE, "pocket_furnace", SpellType.UTILITY, 40, EnumAction.BOW, false); + super("pocket_furnace", Tier.APPRENTICE, Element.FIRE, SpellType.UTILITY, 30, 40, EnumAction.BOW, false); } @Override @@ -60,7 +60,7 @@ public class PocketFurnace extends Spell { if(world.isRemote){ for(int i = 0; i < 10; i++){ double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); + double y1 = (double)((float)caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5F + world.rand.nextFloat()); double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); world.spawnParticle(EnumParticleTypes.FLAME, x1, y1, z1, 0, 0.01F, 0); } diff --git a/src/main/java/electroblob/wizardry/spell/PocketWorkbench.java b/src/main/java/electroblob/wizardry/spell/PocketWorkbench.java index 9f047445..fc5e9e6a 100644 --- a/src/main/java/electroblob/wizardry/spell/PocketWorkbench.java +++ b/src/main/java/electroblob/wizardry/spell/PocketWorkbench.java @@ -16,7 +16,7 @@ import net.minecraft.world.World; public class PocketWorkbench extends Spell { public PocketWorkbench(){ - super(Tier.APPRENTICE, 30, Element.SORCERY, "pocket_workbench", SpellType.UTILITY, 40, EnumAction.BOW, false); + super("pocket_workbench", Tier.APPRENTICE, Element.SORCERY, SpellType.UTILITY, 30, 40, EnumAction.BOW, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/Poison.java b/src/main/java/electroblob/wizardry/spell/Poison.java index 8fd97d21..0a81900e 100644 --- a/src/main/java/electroblob/wizardry/spell/Poison.java +++ b/src/main/java/electroblob/wizardry/spell/Poison.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -8,110 +7,26 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class Poison extends Spell { +public class Poison extends SpellRay { + + private static final int BASE_DURATION = 200; public Poison(){ - super(Tier.APPRENTICE, 10, Element.EARTH, "poison", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; - // Has no effect on undead or spiders. - if(MagicDamage.isEntityImmune(DamageType.POISON, target)){ - if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), - this.getNameForTranslationFormatted())); - }else{ - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON), - 1.0f * modifiers.get(SpellModifiers.DAMAGE)); - target.addPotionEffect(new PotionEffect(MobEffects.POISON, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), 1)); - } - } - - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - // world.spawnParticle("mobSpell", x1, y1, z1, -1*look.xCoord, -1*look.yCoord, -1*look.zCoord); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0, - 0.3f, 0.7f, 0.0f); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 0.1f, 0.4f, 0.0f); - } - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - // Has no effect on undead or spiders. - if(!MagicDamage.isEntityImmune(DamageType.POISON, target) && !world.isRemote){ - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON), - 1.0f * modifiers.get(SpellModifiers.DAMAGE)); - target.addPotionEffect(new PotionEffect(MobEffects.POISON, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), 1)); - } - - if(world.isRemote){ - - double dx = (target.posX - caster.posX) / caster.getDistance(target); - double dy = (target.posY - caster.posY) / caster.getDistance(target); - double dz = (target.posZ - caster.posZ) / caster.getDistance(target); - - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - - double x1 = caster.posX + dx * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + dy * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + dz * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 0, 0.3f, 0.7f, 0.0f); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 0.1f, 0.4f, 0.0f); - } - } - - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - return false; + super("poison", Tier.APPRENTICE, Element.EARTH, SpellType.ATTACK, 10, 20, false, 10, WizardrySounds.SPELL_ICE); + this.soundValues(1, 1.1f, 0.2f); } @Override @@ -119,4 +34,42 @@ public class Poison extends Spell { return true; } + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ + + // Has no effect on undead or spiders. + if(MagicDamage.isEntityImmune(DamageType.POISON, target)){ + if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), + this.getNameForTranslationFormatted())); + }else{ + target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.POISON), + 1 * modifiers.get(SpellModifiers.POTENCY)); + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.POISON, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 1)); + } + + return true; + } + + return false; + } + + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.3f, 0.7f, 0).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(0.1f, 0.4f, 0).spawn(world); + } + } diff --git a/src/main/java/electroblob/wizardry/spell/PoisonBomb.java b/src/main/java/electroblob/wizardry/spell/PoisonBomb.java deleted file mode 100644 index d4e51911..00000000 --- a/src/main/java/electroblob/wizardry/spell/PoisonBomb.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityPoisonBomb; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class PoisonBomb extends Spell { - - public PoisonBomb(){ - super(Tier.APPRENTICE, 15, Element.EARTH, "poison_bomb", SpellType.ATTACK, 25, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityPoisonBomb poisonbomb = new EntityPoisonBomb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - world.spawnEntity(poisonbomb); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityPoisonBomb poisonbomb = new EntityPoisonBomb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - poisonbomb.directTowards(target, 1.5f); - world.spawnEntity(poisonbomb); - } - - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/ReplenishHunger.java b/src/main/java/electroblob/wizardry/spell/ReplenishHunger.java index 0af5b579..d5aa5028 100644 --- a/src/main/java/electroblob/wizardry/spell/ReplenishHunger.java +++ b/src/main/java/electroblob/wizardry/spell/ReplenishHunger.java @@ -1,45 +1,39 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; import net.minecraft.world.World; -public class ReplenishHunger extends Spell { +public class ReplenishHunger extends SpellBuff { public ReplenishHunger(){ - super(Tier.APPRENTICE, 10, Element.HEALING, "replenish_hunger", SpellType.UTILITY, 30, EnumAction.BOW, false); + super("replenish_hunger", Tier.APPRENTICE, Element.HEALING, SpellType.BUFF, 10, 30, WizardrySounds.SPELL_HEAL, 1, 0.7f, 0.3f); + this.soundValues(0.7f, 1.2f, 0.4f); } - + + @Override public boolean canBeCastByNPCs(){ return false; } + + @Override + protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ + return true; // In this case the best solution is to remove the functionality of this method and override cast. + } + @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ if(caster.getFoodStats().needFood()){ - int foodAmount = (int)(6 * modifiers.get(SpellModifiers.DAMAGE)); + int foodAmount = (int)(4 * modifiers.get(SpellModifiers.POTENCY)); // Fixed issue #6: Changed to addStats, since setFoodLevel is client-side only caster.getFoodStats().addStats(foodAmount, foodAmount * 0.1f); - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F - + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 1.0f, 0.7f, 0.3f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; + return super.cast(world, caster, hand, ticksInUse, modifiers); } + return false; } diff --git a/src/main/java/electroblob/wizardry/spell/RingOfFire.java b/src/main/java/electroblob/wizardry/spell/RingOfFire.java deleted file mode 100644 index 1d95f216..00000000 --- a/src/main/java/electroblob/wizardry/spell/RingOfFire.java +++ /dev/null @@ -1,74 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.construct.EntityFireRing; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class RingOfFire extends Spell { - - public RingOfFire(){ - super(Tier.ADVANCED, 30, Element.FIRE, "ring_of_fire", SpellType.ATTACK, 100, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(caster.onGround){ - if(!world.isRemote){ - EntityFireRing firering = new EntityFireRing(world, caster.posX, caster.posY, caster.posZ, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(firering); - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - return true; - } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - if(caster.onGround - && world.getEntitiesWithinAABB(EntityFireRing.class, caster.getEntityBoundingBox()).isEmpty()){ - if(!world.isRemote){ - EntityFireRing firering = new EntityFireRing(world, caster.posX, caster.posY, caster.posZ, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), - modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(firering); - } - - caster.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1); - return true; - } - return false; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/ShadowWard.java b/src/main/java/electroblob/wizardry/spell/ShadowWard.java index 594da63e..6c1db4c4 100644 --- a/src/main/java/electroblob/wizardry/spell/ShadowWard.java +++ b/src/main/java/electroblob/wizardry/spell/ShadowWard.java @@ -27,7 +27,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class ShadowWard extends Spell { public ShadowWard(){ - super(Tier.ADVANCED, 10, Element.NECROMANCY, "shadow_ward", SpellType.DEFENCE, 0, EnumAction.BLOCK, true); + super("shadow_ward", Tier.ADVANCED, Element.NECROMANCY, SpellType.DEFENCE, 10, 0, EnumAction.BLOCK, true); } @Override @@ -37,7 +37,7 @@ public class ShadowWard extends Spell { double dx = -1 + 2 * world.rand.nextFloat(); double dy = -1 + world.rand.nextFloat(); double dz = -1 + 2 * world.rand.nextFloat(); - world.spawnParticle(EnumParticleTypes.PORTAL, caster.posX, WizardryUtilities.getPlayerEyesPos(caster), caster.posZ, dx, dy, dz); + world.spawnParticle(EnumParticleTypes.PORTAL, caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight(), caster.posZ, dx, dy, dz); } if(ticksInUse % 50 == 0){ diff --git a/src/main/java/electroblob/wizardry/spell/Shield.java b/src/main/java/electroblob/wizardry/spell/Shield.java index 0b974fff..dac072c6 100644 --- a/src/main/java/electroblob/wizardry/spell/Shield.java +++ b/src/main/java/electroblob/wizardry/spell/Shield.java @@ -18,7 +18,7 @@ import net.minecraft.world.World; public class Shield extends Spell { public Shield(){ - super(Tier.APPRENTICE, 5, Element.HEALING, "shield", SpellType.DEFENCE, 0, EnumAction.BLOCK, true); + super("shield", Tier.APPRENTICE, Element.HEALING, SpellType.DEFENCE, 5, 0, EnumAction.BLOCK, true); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/Shockwave.java b/src/main/java/electroblob/wizardry/spell/Shockwave.java index e1a63679..52bf90a8 100644 --- a/src/main/java/electroblob/wizardry/spell/Shockwave.java +++ b/src/main/java/electroblob/wizardry/spell/Shockwave.java @@ -2,7 +2,6 @@ package electroblob.wizardry.spell; import java.util.List; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -10,8 +9,9 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; @@ -26,22 +26,25 @@ import net.minecraft.world.World; public class Shockwave extends Spell { + private static final double BASE_RADIUS = 5; + private static final float BASE_DAMAGE = 8; + public Shockwave(){ - super(Tier.MASTER, 65, Element.SORCERY, "shockwave", SpellType.ATTACK, 150, EnumAction.BOW, false); + super("shockwave", Tier.MASTER, Element.SORCERY, SpellType.ATTACK, 65, 150, EnumAction.BOW, false); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ List targets = WizardryUtilities.getEntitiesWithinRadius( - 5.0d * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + BASE_RADIUS * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); for(EntityLivingBase target : targets){ if(WizardryUtilities.isValidTarget(caster, target)){ // Damage increases closer to player up to a maximum of 4 hearts (at 1 block distance). - float damage = Math.min(8.0f / target.getDistance(caster), 8.0f); + float damage = Math.min(BASE_DAMAGE / target.getDistance(caster), BASE_DAMAGE); target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.BLAST), - damage * modifiers.get(SpellModifiers.DAMAGE)); + damage * modifiers.get(SpellModifiers.POTENCY)); if(!world.isRemote){ @@ -65,23 +68,25 @@ public class Shockwave extends Spell { } } } + if(world.isRemote){ double particleX, particleZ; + for(int i = 0; i < 40; i++){ + particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, particleX, - WizardryUtilities.getPlayerEyesPos(caster) - 1.5, particleZ, particleX - caster.posX, 0, - particleZ - caster.posZ, 30, 0.8f, 0.8f, 1.0f); + ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ) + .vel(particleX - caster.posX, 0, particleZ - caster.posZ).lifetime(30).colour(0.8f, 0.8f, 1).spawn(world); + particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, particleX, - WizardryUtilities.getPlayerEyesPos(caster) - 1.5, particleZ, particleX - caster.posX, 0, - particleZ - caster.posZ, 30, 0.9f, 0.9f, 0.9f); + ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ) + .vel(particleX - caster.posX, 0, particleZ - caster.posZ).lifetime(30).colour(0.9f, 0.9f, 0.9f).spawn(world); + particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble(); particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble(); - IBlockState block = WizardryUtilities.getBlockEntityIsStandingOn(caster); if(block != null){ @@ -94,6 +99,7 @@ public class Shockwave extends Spell { caster.getEntityBoundingBox().minY + 0.1, caster.posZ, 0, 0, 0); } + caster.swingArm(hand); WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SHOCKWAVE, 1.0f, 0.7f); WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SHOCKWAVE, 2.0f, 0.3f); diff --git a/src/main/java/electroblob/wizardry/spell/SilverfishSwarm.java b/src/main/java/electroblob/wizardry/spell/SilverfishSwarm.java deleted file mode 100644 index d626418e..00000000 --- a/src/main/java/electroblob/wizardry/spell/SilverfishSwarm.java +++ /dev/null @@ -1,49 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntitySilverfishMinion; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SilverfishSwarm extends Spell { - - public SilverfishSwarm(){ - super(Tier.MASTER, 80, Element.EARTH, "silverfish_swarm", SpellType.MINION, 300, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - for(int i = 0; i < 20; i++){ - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 3, 6); - // The spell instantly fails if no space was found (see javadoc for the above method). - if(pos == null) return false; - - EntitySilverfishMinion silverfish = new EntitySilverfishMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(silverfish); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - // Can't possibly get this far if nothing was spawned. - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SixthSense.java b/src/main/java/electroblob/wizardry/spell/SixthSense.java index b33ac6c9..a7d731bf 100644 --- a/src/main/java/electroblob/wizardry/spell/SixthSense.java +++ b/src/main/java/electroblob/wizardry/spell/SixthSense.java @@ -18,7 +18,7 @@ import net.minecraft.world.World; public class SixthSense extends Spell { public SixthSense(){ - super(Tier.APPRENTICE, 20, Element.EARTH, "sixth_sense", SpellType.UTILITY, 100, EnumAction.BOW, false); + super("sixth_sense", Tier.APPRENTICE, Element.EARTH, SpellType.BUFF, 20, 100, EnumAction.BOW, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/Slime.java b/src/main/java/electroblob/wizardry/spell/Slime.java index b1569eab..4b04b83d 100644 --- a/src/main/java/electroblob/wizardry/spell/Slime.java +++ b/src/main/java/electroblob/wizardry/spell/Slime.java @@ -1,6 +1,5 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -8,119 +7,87 @@ import electroblob.wizardry.entity.living.EntityMagicSlime; import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.monster.EntitySkeleton; import net.minecraft.entity.monster.EntitySlime; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class Slime extends Spell { +public class Slime extends SpellRay { + + private static final int BASE_DURATION = 200; public Slime(){ - super(Tier.ADVANCED, 20, Element.EARTH, "slime", SpellType.ATTACK, 50, EnumAction.NONE, false); + super("slime", Tier.ADVANCED, Element.EARTH, SpellType.ATTACK, 20, 50, false, 8, WizardrySounds.SPELL_ICE); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + // This spell uses more than one sound, so this is required... + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag) WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SLIME_ATTACK, 1.0F, 0.5F); + return flag; + } - Vec3d look = caster.getLookVec(); + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag) caster.playSound(SoundEvents.ENTITY_SLIME_ATTACK, 1.0F, 0.5F); + return flag; + } - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 8 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.entityHit != null && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target) && !(target instanceof EntityMagicSlime)){ if(target instanceof EntitySlime){ if(!world.isRemote) caster.sendMessage(new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted())); - }else if(!(target instanceof EntityMagicSlime)){ + }else{ - if(target instanceof EntitySkeleton) WizardryAdvancementTriggers.slime_skeleton.triggerFor(caster); + if(target instanceof EntitySkeleton && caster instanceof EntityPlayer) + WizardryAdvancementTriggers.slime_skeleton.triggerFor((EntityPlayer)caster); if(!world.isRemote){ - EntityMagicSlime slime = new EntityMagicSlime(world, caster, target, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade))); + EntityMagicSlime slime = new EntityMagicSlime(world, caster, (EntityLivingBase)target, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade))); world.spawnEntity(slime); } } - } - - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - world.spawnParticle(EnumParticleTypes.SLIME, x1, y1, z1, 0.0d, 0.0d, 0.0d); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0, - 0.2f, 0.8f, 0.1f); - } - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SLIME_ATTACK, 1.0F, 0.5F); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null && !(target instanceof EntitySlime) && !(target instanceof EntityMagicSlime)){ - - if(!world.isRemote){ - EntityMagicSlime slime = new EntityMagicSlime(world, caster, target, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(slime); - } - - if(world.isRemote){ - - double dx = (target.posX - caster.posX) / caster.getDistance(target); - double dy = (target.posY - caster.posY) / caster.getDistance(target); - double dz = (target.posZ - caster.posZ) / caster.getDistance(target); - - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - - double x1 = caster.posX + dx * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + dy * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + dz * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - world.spawnParticle(EnumParticleTypes.SLIME, x1, y1, z1, 0.0d, 0.0d, 0.0d); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 0, 0.2f, 0.8f, 0.1f); - } - } - - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_SLIME_ATTACK, 1.0F, 0.5F); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, 1.0F); + return true; - } - + return false; } @Override - public boolean canBeCastByNPCs(){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + world.spawnParticle(EnumParticleTypes.SLIME, x, y, z, 0, 0, 0); + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.2f, 0.8f, 0.1f).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/SmokeBomb.java b/src/main/java/electroblob/wizardry/spell/SmokeBomb.java deleted file mode 100644 index c10a4b5b..00000000 --- a/src/main/java/electroblob/wizardry/spell/SmokeBomb.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntitySmokeBomb; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class SmokeBomb extends Spell { - - public SmokeBomb(){ - super(Tier.BASIC, 10, Element.FIRE, "smoke_bomb", SpellType.ATTACK, 20, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntitySmokeBomb smokebomb = new EntitySmokeBomb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - world.spawnEntity(smokebomb); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntitySmokeBomb smokebomb = new EntitySmokeBomb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - smokebomb.directTowards(target, 1.5f); - world.spawnEntity(smokebomb); - } - - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Snare.java b/src/main/java/electroblob/wizardry/spell/Snare.java index 64fb6f55..d7e64753 100644 --- a/src/main/java/electroblob/wizardry/spell/Snare.java +++ b/src/main/java/electroblob/wizardry/spell/Snare.java @@ -1,78 +1,62 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryBlocks; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.tileentity.TileEntityPlayerSave; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -public class Snare extends Spell { +public class Snare extends SpellRay { public Snare(){ - super(Tier.BASIC, 10, Element.EARTH, "snare", SpellType.ATTACK, 10, EnumAction.NONE, false); + super("snare", Tier.BASIC, Element.EARTH, SpellType.ATTACK, 10, 10, false, 10, SoundEvents.BLOCK_GRASS_PLACE); + this.soundValues(1, 1.4f, 0.4f); + this.ignoreEntities(true); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(10 * modifiers.get(WizardryItems.range_upgrade), world, - caster, true); - - // Gets block the player is looking at and places snare - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - BlockPos pos = rayTrace.getBlockPos(); - - if(rayTrace.sideHit == EnumFacing.UP && world.isSideSolid(pos, EnumFacing.UP) - && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ - - if(!world.isRemote){ - world.setBlockState(pos.up(), WizardryBlocks.snare.getDefaultState()); - ((TileEntityPlayerSave)world.getTileEntity(pos.up())).setCaster(caster); - } - - double dx = pos.getX() + 0.5 - caster.posX; - double dy = pos.getY() + 1.5 - (caster.posY + caster.height / 2); - double dz = pos.getZ() + 0.5 - caster.posZ; - - if(world.isRemote){ - for(int i = 1; i < 5; i++){ - float brightness = world.rand.nextFloat() / 4; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) - + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0.0d, 0.0d, 0.0d, - 20 + world.rand.nextInt(8), brightness, brightness + 0.1f, 0.0f); - Wizardry.proxy.spawnParticle(Type.LEAF, world, - caster.posX + (i * (dx / 5)) + world.rand.nextFloat() / 5, - WizardryUtilities.getPlayerEyesPos(caster) + (i * (dy / 5)) - + world.rand.nextFloat() / 5, - caster.posZ + (i * (dz / 5)) + world.rand.nextFloat() / 5, 0, -0.01, 0, - 40 + world.rand.nextInt(10)); - } - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_GRASS_PLACE, 1.0F, - world.rand.nextFloat() * 0.4F + 1.2F); - return true; - } - } + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(side == EnumFacing.UP && world.isSideSolid(pos, EnumFacing.UP) + && WizardryUtilities.canBlockBeReplaced(world, pos.up())){ + + if(!world.isRemote){ + world.setBlockState(pos.up(), WizardryBlocks.snare.getDefaultState()); + ((TileEntityPlayerSave)world.getTileEntity(pos.up())).setCaster(caster); + } + + return true; + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + float brightness = world.rand.nextFloat() * 0.25f; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(20 + world.rand.nextInt(8)) + .colour(brightness, brightness + 0.1f, 0).spawn(world); + ParticleBuilder.create(Type.LEAF).pos(x, y, z).vel(0, -0.01, 0).lifetime(40 + world.rand.nextInt(10)).spawn(world); + } + } diff --git a/src/main/java/electroblob/wizardry/spell/Snowball.java b/src/main/java/electroblob/wizardry/spell/Snowball.java index 0f7f71e5..1e4e901a 100644 --- a/src/main/java/electroblob/wizardry/spell/Snowball.java +++ b/src/main/java/electroblob/wizardry/spell/Snowball.java @@ -15,7 +15,7 @@ import net.minecraft.world.World; public class Snowball extends Spell { public Snowball(){ - super(Tier.BASIC, 1, Element.ICE, "snowball", SpellType.ATTACK, 1, EnumAction.NONE, false); + super("snowball", Tier.BASIC, Element.ICE, SpellType.ATTACK, 1, 1, EnumAction.NONE, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/SparkBomb.java b/src/main/java/electroblob/wizardry/spell/SparkBomb.java deleted file mode 100644 index b8adbdb5..00000000 --- a/src/main/java/electroblob/wizardry/spell/SparkBomb.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntitySparkBomb; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class SparkBomb extends Spell { - - public SparkBomb(){ - super(Tier.APPRENTICE, 15, Element.LIGHTNING, "spark_bomb", SpellType.ATTACK, 25, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntitySparkBomb sparkBomb = new EntitySparkBomb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - world.spawnEntity(sparkBomb); - } - - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, - 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntitySparkBomb sparkBomb = new EntitySparkBomb(world, caster, modifiers.get(SpellModifiers.DAMAGE), - modifiers.get(WizardryItems.blast_upgrade)); - sparkBomb.directTowards(target, 1.5f); - world.spawnEntity(sparkBomb); - } - - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 0.5F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F)); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SpectralPathway.java b/src/main/java/electroblob/wizardry/spell/SpectralPathway.java index db2b3c59..5591448b 100644 --- a/src/main/java/electroblob/wizardry/spell/SpectralPathway.java +++ b/src/main/java/electroblob/wizardry/spell/SpectralPathway.java @@ -21,7 +21,7 @@ import net.minecraft.world.World; public class SpectralPathway extends Spell { public SpectralPathway(){ - super(Tier.ADVANCED, 40, Element.SORCERY, "spectral_pathway", SpellType.UTILITY, 300, EnumAction.BOW, false); + super("spectral_pathway", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 40, 300, EnumAction.BOW, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/Spell.java b/src/main/java/electroblob/wizardry/spell/Spell.java index f15e49dd..b7b1a930 100644 --- a/src/main/java/electroblob/wizardry/spell/Spell.java +++ b/src/main/java/electroblob/wizardry/spell/Spell.java @@ -79,16 +79,18 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C /** Forge registry-based replacement for the internal spells list. */ public static IForgeRegistry registry; - /** The tier this spell belongs to. */ - public final Tier tier; - /** Mana cost of the spell. If it is a continuous spell the cost is per second. */ - public final int cost; - /** The element this spell belongs to. */ - public final Element element; + /** Mod ID of the mod that added this spell; defaults to {@link Wizardry#MODID} if not specified. */ + private final String modID; /** The unlocalised name of the spell. */ private final String unlocalisedName; + /** The tier this spell belongs to. */ + public final Tier tier; + /** The element this spell belongs to. */ + public final Element element; /** The type of spell this is classified as. */ public final SpellType type; + /** Mana cost of the spell. If it is a continuous spell the cost is per second. */ + public final int cost; /** Cooldown for the spell in ticks */ public final int cooldown; /** The action the player does when this spell is cast. */ @@ -98,66 +100,64 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C /** ResourceLocation of the spell icon. */ private final ResourceLocation icon; - /** Mod ID of the mod that added this spell; defaults to {@link Wizardry#MODID} if not specified. */ - private final String modID; /** * False if the spell has been disabled in the config file, true otherwise. This is now encapsulated to stop it * being fiddled with. */ - private boolean isEnabled = true; + private boolean enabled = true; /** * This constructor should be called from any subclasses, either feeding in the constants directly or through their * own constructor from wherever the spell is registered. This is the constructor for wizardry's own spells; spells * added by other mods should use - * {@link Spell#Spell(Tier, int, Element, String, SpellType, int, EnumAction, boolean, String)}. - * - * @param tier The tier this spell belongs to. - * @param cost The amount of mana used to cast the spell. If this is a continuous spell, it represents mana cost per - * second and should be a multiple of 5. - * @param element The element this spell belongs to. + * {@link Spell#Spell(String, String, Tier, Element, SpellType, int, int, EnumAction, boolean)}. * @param name The registry name of the spell. This will also be the name of the icon file. The spell's * unlocalised name will be a resource location with the format [modid]:[name]. + * @param tier The tier this spell belongs to. + * @param element The element this spell belongs to. + * @param type The type of spell this is classified as. + * @param cost The amount of mana used to cast the spell. If this is a continuous spell, it represents mana cost per + * second and should be a multiple of 5. * @param cooldown The cooldown time for this spell in ticks. * @param action The vanilla usage action to be displayed when casting this spell. * @param isContinuous Whether this spell is continuous, meaning you cast it for a length of time by holding the * right mouse button. */ - public Spell(Tier tier, int cost, Element element, String name, SpellType type, int cooldown, EnumAction action, + public Spell(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, boolean isContinuous){ - this(tier, cost, element, name, type, cooldown, action, isContinuous, Wizardry.MODID); + this(Wizardry.MODID, name, tier, element, type, cost, cooldown, action, isContinuous); } /** * This constructor should be called from any subclasses, either feeding in the constants directly or through their * own constructor from wherever the spell is registered. - * - * @param tier The tier this spell belongs to. - * @param cost The amount of mana used to cast the spell. If this is a continuous spell, it represents mana cost per - * second and should be a multiple of 5. - * @param element The element this spell belongs to. + * @param modID The mod id of the mod that added this spell. This allows wizardry to use the correct file path for + * the spell icon, and also more generally to distinguish between original and addon spells. * @param name The registry name of the spell, excluding the mod id. This will also be the name of the icon * file. The spell's unlocalised name will be a resource location with the format [modid]:[name]. + * @param tier The tier this spell belongs to. + * @param element The element this spell belongs to. + * @param type The type of spell this is classified as. + * @param cost The amount of mana used to cast the spell. If this is a continuous spell, it represents mana cost per + * second and should be a multiple of 5. * @param cooldown The cooldown time for this spell in ticks. * @param action The vanilla usage action to be displayed when casting this spell (see {@link}EnumAction) * @param isContinuous Whether this spell is continuous, meaning you cast it for a length of time by holding the * right mouse button. - * @param modID The mod id of the mod that added this spell. This allows wizardry to use the correct file path for - * the spell icon, and also more generally to distinguish between original and addon spells. */ - public Spell(Tier tier, int cost, Element element, String name, SpellType type, int cooldown, EnumAction action, - boolean isContinuous, String modID){ - this.tier = tier; - this.cost = cost; - this.element = element; - this.type = type; - this.cooldown = cooldown; - this.action = action; - this.isContinuous = isContinuous; + public Spell(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, + EnumAction action, boolean isContinuous){ this.modID = modID; this.setRegistryName(modID, name); this.unlocalisedName = this.getRegistryName().toString(); + this.tier = tier; + this.element = element; + this.type = type; + this.cost = cost; + this.cooldown = cooldown; + this.action = action; + this.isContinuous = isContinuous; this.icon = new ResourceLocation(this.modID, "textures/spells/" + name + ".png"); } @@ -187,8 +187,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C * {@code new SpellModifiers()}. * @return True if the spell succeeded and mana should be used up, false if not. */ - public abstract boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, - SpellModifiers modifiers); + public abstract boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers); /** * Casts the spell, but with an EntityLiving as the caster. Each subclass can optionally override this method and @@ -337,12 +336,12 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C /** Returns whether the spell is enabled in the config. */ public final boolean isEnabled(){ - return isEnabled; + return enabled; } /** Sets whether the spell is enabled or not. */ public final void setEnabled(boolean isEnabled){ - this.isEnabled = isEnabled; + this.enabled = isEnabled; } // Spells are sorted according to tier and element. Where several spells have the same tier and element, @@ -472,5 +471,5 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C return spell.isEnabled() && (this.tier == null || spell.tier == this.tier) && (this.element == null || spell.element == this.element); } - }; + } } diff --git a/src/main/java/electroblob/wizardry/spell/SpellAreaEffect.java b/src/main/java/electroblob/wizardry/spell/SpellAreaEffect.java new file mode 100644 index 00000000..3194da2d --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SpellAreaEffect.java @@ -0,0 +1,140 @@ +package electroblob.wizardry.spell; + +import java.util.List; + +import javax.annotation.Nullable; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +public abstract class SpellAreaEffect extends Spell { + + // TODO: This class doesn't really work as it is right now, it needs rethinking. The aim is to try and have all the + // different casting methods call a single (abstract) positional method to do the actual AoE. + + /** The base radius of this spell's area of effect. */ + protected final double baseRadius; + /** The sound that gets played when this spell is cast. */ + @Nullable + protected final SoundEvent sound; + + /** The average number of particles to spawn per block in this spell's area of effect. */ + protected float particleDensity = 0.65f; + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + + public SpellAreaEffect(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, double baseRadius, SoundEvent sound){ + this(Wizardry.MODID, name, tier, element, type, cost, cooldown, action, baseRadius, sound); + } + + public SpellAreaEffect(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, double baseRadius, SoundEvent sound){ + super(modID, name, tier, element, type, cost, cooldown, action, false); + this.baseRadius = baseRadius; + this.sound = sound; + } + + /** + * Sets the sound parameters for this spell. + * @param volume + * @param pitch + * @param pitchVariation + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellAreaEffect soundValues(float volume, float pitch, float pitchVariation) { + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; + } + + /** + * Sets the number of particles to spawn per block for this spell. + * @param particleDensity The average number of particles to spawn per block in this spell's area of effect. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellAreaEffect particleDensity(float particleDensity) { + this.particleDensity = particleDensity; + return this; + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + List targets = WizardryUtilities.getEntitiesWithinRadius( + baseRadius * modifiers.get(WizardryItems.blast_upgrade), caster.posX, caster.posY, caster.posZ, world); + + targets.removeIf(target -> !WizardryUtilities.isValidTarget(caster, target)); + + for(EntityLivingBase target : targets){ + affectEntity(world, caster, target, modifiers); + } + + if(world.isRemote){ + spawnParticleEffect(world, caster, modifiers); + } + + if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + + } + + /** + * Called to do something to each entity within the spell's area of effect. + * @param world The world in which the spell was cast. + * @param caster The entity that cast the spell. + * @param target The entity to do something to. + * @param modifiers The modifiers the spell was cast with. + */ + protected abstract void affectEntity(World world, EntityLivingBase caster, EntityLivingBase target, SpellModifiers modifiers); + + /** + * Called to spawn the spell's particle effect. By default, this generates a set of random points within the spell's + * area of effect and calls {@link SpellAreaEffect#spawnParticle(World, double, double, double)} at each to spawn + * the individual particles. Only called client-side. Override to add a custom particle effect. + * @param world + * @param caster + * @param modifiers + */ + protected void spawnParticleEffect(World world, EntityLivingBase caster, SpellModifiers modifiers){ + + double maxRadius = baseRadius * modifiers.get(WizardryItems.blast_upgrade); + int particleCount = (int)Math.round(particleDensity * Math.PI * maxRadius * maxRadius); + + for(int i=0; i + * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} + *

+ * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + * + * @author Electroblob + * @since Wizardry 4.2 + */ +public class SpellArrow extends Spell { + + // The general contract for these spell subtypes is that any required parameters are set via the constructor and are + // final, whereas any non-critical parameters are set via chainable setters with sensible defaults if not. For example, + // the actual sound to play is required, but it makes sense for its volume and pitch to default to 1 if unspecified. + + /** A factory that creates projectile entities. */ + protected final Function arrowFactory; + /** The base range (projectile speed) of this spell. */ + protected final float baseRange; + /** The sound that gets played when this spell is cast, or null if the spell plays no sound. */ + @Nullable + protected final SoundEvent sound; + + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + + public SpellArrow(String name, Tier tier, Element element, int cost, int cooldown, Function arrowFactory, float baseRange, SoundEvent sound) { + this(Wizardry.MODID, name, tier, element, cost, cooldown, arrowFactory, baseRange, sound); + } + + public SpellArrow(String modID, String name, Tier tier, Element element, int cost, int cooldown, Function arrowFactory, float baseRange, SoundEvent sound){ + super(modID, name, tier, element, SpellType.PROJECTILE, cost, cooldown, EnumAction.NONE, false); + this.arrowFactory = arrowFactory; + this.baseRange = baseRange; + this.sound = sound; + } + + /** + * Sets the sound parameters for this spell. + * @param volume + * @param pitch + * @param pitchVariation + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellArrow soundValues(float volume, float pitch, float pitchVariation) { + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; + } + + @Override public boolean doesSpellRequirePacket(){ return false; } + + @Override public boolean canBeCastByNPCs(){ return true; } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + if(!world.isRemote){ + // Creates a projectile from the supplied factory + EntityMagicArrow projectile = arrowFactory.apply(world); + // Sets the necessary parameters + projectile.aim(caster, baseRange * modifiers.get(WizardryItems.range_upgrade)); + projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + // Spawns the projectile in the world + world.spawnEntity(projectile); + } + + caster.swingArm(hand); + + if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + + if(target != null){ + + if(!world.isRemote){ + // Creates a projectile from the supplied factory + EntityMagicArrow projectile = arrowFactory.apply(world); + // Sets the necessary parameters + int aimingError = caster instanceof ISpellCaster ? ((ISpellCaster)caster).getAimingError(world.getDifficulty()) + : WizardryUtilities.getDefaultAimingError(world.getDifficulty()); + projectile.aim(caster, target, baseRange * modifiers.get(WizardryItems.range_upgrade), aimingError); + projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + // Spawns the projectile in the world + world.spawnEntity(projectile); + } + + caster.swingArm(hand); + + if(sound != null) caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + + return true; + } + + return false; + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/SpellBuff.java b/src/main/java/electroblob/wizardry/spell/SpellBuff.java new file mode 100644 index 00000000..0c91c08f --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SpellBuff.java @@ -0,0 +1,153 @@ +package electroblob.wizardry.spell; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.tuple.Triple; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; +import net.minecraft.world.World; + +/** + * Generic superclass for all spells which buff their caster. + * This allows all the relevant code to be centralised, since these spells all work in the same way. Usually, a simple + * instantiation of this class is sufficient to create a buff spell; if something extra needs to be done, such as + * applying a non-potion buff, then methods can be overridden (perhaps using an anonymous class) to add the required + * functionality. + *

+ * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} + *

+ * By default, this type of spell requires a packet to be sent. {@link Spell#doesSpellRequirePacket()} + * + * @author Electroblob + * @since Wizardry 4.2 + */ +public class SpellBuff extends Spell { + + /** An array of triples representing the parameters of the status effects that this spell applies to its caster. + * These are of the form [effect, base duration, base amplifier]. */ + protected final Triple[] effects; + /** A set of all the different potions (status effects) that this spell applies to its caster. */ + protected final Set potionSet; + /** The sound that gets played when this spell is cast. */ + protected final SoundEvent sound; + /** The RGB colour values of the particles spawned when this spell is cast. */ + protected final float r, g, b; + + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + /** The number of sparkle particles spawned when this spell is cast. Defualts to 10. */ + protected float particleCount = 10; + + @SafeVarargs + public SpellBuff(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, SoundEvent sound, float r, float g, float b, Triple... effects){ + this(Wizardry.MODID, name, tier, element, type, cost, cooldown, sound, r, g, b, effects); + } + + @SafeVarargs + public SpellBuff(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, SoundEvent sound, float r, float g, float b, Triple... effects){ + super(modID, name, tier, element, type, cost, cooldown, EnumAction.BOW, false); + this.sound = sound; + this.effects = effects; + this.r = r; + this.g = g; + this.b = b; + // Pretty sure this is better than iterating over (or streaming) all the elements each time the spell is cast. + this.potionSet = Arrays.stream(effects).map(Triple::getLeft).collect(Collectors.toSet()); + } + + /** + * Sets the sound parameters for this spell. + * @param volume + * @param pitch + * @param pitchVariation + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellBuff soundValues(float volume, float pitch, float pitchVariation) { + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; + } + + /** + * Sets the number of sparkle particles spawned when this spell is cast. + * @param particleCount The number of particles. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellBuff particleCount(int particleCount){ + this.particleCount = particleCount; + return this; + } + + @Override public boolean canBeCastByNPCs(){ return true; } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + if(!this.applyEffects(caster, modifiers)) return false; + if(world.isRemote) this.spawnParticles(world, caster, modifiers); + WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + // Wizards can only cast a buff spell if they don't already have its effects. + if(caster.getActivePotionMap().keySet().containsAll(potionSet)) return false; + if(!this.applyEffects(caster, modifiers)) return false; + if(world.isRemote) this.spawnParticles(world, caster, modifiers); + caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + /** Actually applies the status effects to the caster. By default, this iterates through the array of effects and + * applies each in turn, multiplying the duration and amplifier by the appropriate modifiers. Particles are always + * hidden and isAmbient is always set to false. Override to do something special, like apply a non-potion buff. + * Returns a boolean to allow subclasses to cause the spell to fail if for some reason the effect cannot be applied + * (for example, {@link Heal} fails if the caster is on full health). */ + protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){ + // TODO: Find a good way (if any) of implementing potency modifiers + for(Triple effect : effects){ + caster.addPotionEffect(new PotionEffect(effect.getLeft(), (int)(effect.getMiddle() + * modifiers.get(WizardryItems.duration_upgrade)), effect.getRight(), false, false)); + } + + return true; + } + + /** Spawns buff particles around the caster. Override to add a custom particle effect. Only called client-side. */ + protected void spawnParticles(World world, EntityLivingBase caster, SpellModifiers modifiers){ + + for(int i = 0; i < particleCount; i++){ + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(r, g, b).spawn(world); + } + + Wizardry.proxy.spawnEntityParticle(world, caster, 15, r, g, b); + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/SpellConjuration.java b/src/main/java/electroblob/wizardry/spell/SpellConjuration.java new file mode 100644 index 00000000..9dd9d068 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SpellConjuration.java @@ -0,0 +1,120 @@ +package electroblob.wizardry.spell; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.item.IConjuredItem; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; +import net.minecraft.world.World; + +/** + * Generic superclass for all spells which conjure an item for a certain duration. + * This allows all the relevant code to be centralised, since these spells all work in the same way. Usually, a simple + * instantiation of this class is sufficient to create a conjuration spell; if something extra needs to be done, such as + * a custom particle effect or conjuring the item in a specific slot, then methods can be overridden (perhaps using an + * anonymous class) to add the required functionality. + *

+ * By default, this type of spell cannot be cast by NPCs. {@link Spell#canBeCastByNPCs()} + *

+ * By default, this type of spell requires a packet to be sent. {@link Spell#doesSpellRequirePacket()} + * + * @author Electroblob + * @since Wizardry 4.2 + * @see IConjuredItem + */ +public class SpellConjuration extends Spell { + + /** The item that is conjured by this spell. Should implement {@link IConjuredItem}. */ + protected final Item item; + /** The sound that gets played when this spell is cast. */ + protected final SoundEvent sound; + + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + + public SpellConjuration(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, Item item, SoundEvent sound){ + this(Wizardry.MODID, name, tier, element, type, cost, cooldown, item, sound); + } + + public SpellConjuration(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, Item item, SoundEvent sound){ + super(modID, name, tier, element, type, cost, cooldown, EnumAction.BOW, false); + this.item = item; + this.sound = sound; + } + + /** + * Sets the sound parameters for this spell. + * @param volume + * @param pitch + * @param pitchVariation + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellConjuration soundValues(float volume, float pitch, float pitchVariation) { + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + if(conjureItem(caster, modifiers)){ + + if(world.isRemote) spawnParticles(world, caster, modifiers); + + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1, 1); + return true; + } + + return false; + } + + /** Spawns sparkle particles around the caster. Override to add a custom particle effect. Only called client-side. */ + protected void spawnParticles(World world, EntityLivingBase caster, SpellModifiers modifiers){ + + for(int i=0; i<10; i++){ + double x = caster.posX + world.rand.nextDouble() * 2 - 1; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble(); + double z = caster.posZ + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.7f, 0.9f, 1).spawn(world); + } + } + + /** Adds this spell's item to the given player's inventory, placing it in the main hand if the main hand is empty. + * Returns true if the item was successfully added to the player's inventory, false if there as no space or if the + * player already had the item. Override to add special conjuring behaviour. */ + protected boolean conjureItem(EntityPlayer caster, SpellModifiers modifiers){ + + ItemStack stack = new ItemStack(item); + + IConjuredItem.setDurationMultiplier(stack, modifiers.get(WizardryItems.duration_upgrade)); + + if(WizardryUtilities.doesPlayerHaveItem(caster, item)) return false; + + if(caster.getHeldItemMainhand().isEmpty()){ + caster.setHeldItem(EnumHand.MAIN_HAND, stack); + return true; + }else{ + return caster.inventory.addItemStackToInventory(stack); + } + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/SpellConstruct.java b/src/main/java/electroblob/wizardry/spell/SpellConstruct.java new file mode 100644 index 00000000..bd3b4ad5 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SpellConstruct.java @@ -0,0 +1,185 @@ +package electroblob.wizardry.spell; + +import java.util.function.Function; + +import javax.annotation.Nullable; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.entity.construct.EntityMagicConstruct; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; +import net.minecraft.world.World; + +/** + * Generic superclass for all spells which conjure constructs (i.e. instances of {@link EntityMagicConstruct}). + * This allows all the relevant code to be centralised, since these spells all work in a similar way. Usually, a simple + * instantiation of this class is sufficient to create a construct spell; if something extra needs to be done, such as + * particle spawning, then methods can be overridden (perhaps using an anonymous class) to add the required functionality. + * It is encouraged, however, to put extra functionality in the construct entity class instead whenever possible. + *

+ * This class spawns the construct entity at the caster's feet, like ring of fire and healing aura. Use + * {@link SpellConstructRanged} (which extends this class) for spells that spawn constructs at an aimed-at position. + *

+ * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} + *

+ * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + * + * @author Electroblob + * @since Wizardry 4.2 + * @see SpellConstructRanged + */ +public class SpellConstruct extends Spell { + + /** A factory that creates projectile entities. */ + protected final Function constructFactory; + /** The base lifetime of the construct created by this spell, or -1 if the construct does not despawn. */ + protected final int baseDuration; + /** The sound that gets played when this spell is cast, or null if the spell plays no sound. */ + @Nullable + protected final SoundEvent sound; + + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + /** Whether the construct must be spawned on the ground. Defaults to false. */ + protected boolean requiresFloor = false; + /** Whether constructs spawned by this spell may overlap. Defaults to false. */ + protected boolean allowOverlap = false; + + public SpellConstruct(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, Function constructFactory, int baseDuration, SoundEvent sound){ + this(Wizardry.MODID, name, tier, element, type, cost, cooldown, action, constructFactory, baseDuration, sound); + } + + public SpellConstruct(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, EnumAction action, Function constructFactory, int baseDuration, SoundEvent sound){ + super(modID, name, tier, element, type, cost, cooldown, action, false); + this.constructFactory = constructFactory; + this.baseDuration = baseDuration; + this.sound = sound; + } + + /** + * Sets the sound parameters for this spell. + * @param volume The volume of the sound, relative to 1. + * @param pitch The pitch of the sound, relative to 1. + * @param pitchVariation The pitch variation. The pitch will be set to a random value within this range either side + * of the set pitch value. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellConstruct soundValues(float volume, float pitch, float pitchVariation) { + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; + } + + @Override public boolean doesSpellRequirePacket(){ return false; } + + @Override public boolean canBeCastByNPCs(){ return true; } + + /** + * Sets whether the construct must be spawned on the ground. + * @param requiresFloor True to require that the construct be spawned on the ground, false to allow it in mid-air. + * Defaults to false. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellConstruct floor(boolean requiresFloor){ + this.requiresFloor = requiresFloor; + return this; + } + + /** + * Sets whether constructs spawned by this spell may overlap. + * @param allowOverlap True to allow overlapping, false to prevent it. Defaults to false. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellConstruct overlap(boolean allowOverlap){ + this.allowOverlap = allowOverlap; + return this; + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + if(caster.onGround || !requiresFloor){ + if(!spawnConstruct(world, caster.posX, caster.posY, caster.posZ, caster, modifiers)) return false; + if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + return false; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + + if(target != null){ + if(caster.onGround || !requiresFloor){ + if(!spawnConstruct(world, caster.posX, caster.posY, caster.posZ, caster, modifiers)) return false; + if(sound != null) caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + } + + return false; + } + + /** + * Actually spawns the construct. By default, spawns the construct at the position of the caster and always returns + * true. Returning false will cause the spell to fail. + * @param world The world to spawn the construct in. + * @param x The x coordinate to spawn the construct at. + * @param y The y coordinate to spawn the construct at. + * @param z The z coordinate to spawn the construct at. + * @param caster The EntityLivingBase that cast this spell. + * @param modifiers The modifiers with which the spell was cast. + * @return false to cause the spell to fail, true to continue with casting. + */ + protected boolean spawnConstruct(World world, double x, double y, double z, EntityLivingBase caster, SpellModifiers modifiers){ + + if(!world.isRemote){ + // Creates a new constuct using the supplied factory + T construct = constructFactory.apply(world); + // Sets the position of the construct (and initialises its bounding box) + construct.setPosition(x, y, z); + // Prevents overlapping of multiple constructs of the same type. Since we have an instance here this is + // very simple. The trade-off is that we have to create the entity before the spell fails, but unless + // world.spawnEntity(...) is called, its scope is limited to this method so it should be fine. + if(!allowOverlap && !world.getEntitiesWithinAABB(construct.getClass(), caster.getEntityBoundingBox()).isEmpty()) return false; + // Sets the various parameters + construct.setCaster(caster); + construct.lifetime = baseDuration == -1 ? -1 : (int)(baseDuration * modifiers.get(WizardryItems.duration_upgrade)); + construct.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + addConstructExtras(construct, caster, modifiers); + // Spawns the construct in the world + world.spawnEntity(construct); + } + + return true; + } + + /** + * Called just before each construct is spawned. Does nothing by default, but is provided to allow subclasses to call + * extra methods on the spawned entity. This method is only called server-side so cannot be used to spawn particles + * directly. + * @param construct The entity being spawned. + * @param caster The caster of this spell. + * @param modifiers The modifiers this spell was cast with. + */ + // This is the reason this class is generic: it allows subclasses to do whatever they want to their specific entity, + // without needing to cast to it. + protected void addConstructExtras(T construct, EntityLivingBase caster, SpellModifiers modifiers){} + +} diff --git a/src/main/java/electroblob/wizardry/spell/SpellConstructRanged.java b/src/main/java/electroblob/wizardry/spell/SpellConstructRanged.java new file mode 100644 index 00000000..cac214de --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SpellConstructRanged.java @@ -0,0 +1,133 @@ +package electroblob.wizardry.spell; + +import java.util.function.Function; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.entity.construct.EntityMagicConstruct; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +/** + * Generic superclass for all spells which conjure constructs (i.e. instances of {@link EntityMagicConstruct}) at an + * aimed-at position (players and dispensers) or target (non-player spell casters). + * This allows all the relevant code to be centralised, since these spells all work in a similar way. Usually, a simple + * instantiation of this class is sufficient to create a construct spell; if something extra needs to be done, such as + * particle spawning, then methods can be overridden (perhaps using an anonymous class) to add the required functionality. + * It is encouraged, however, to put extra functionality in the construct entity class instead whenever possible. + *

+ * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} + *

+ * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + * + * @author Electroblob + * @since Wizardry 4.2 + * @see SpellConstruct + */ +public class SpellConstructRanged extends SpellConstruct { + + /** The base range of this spell. */ + protected final double baseRange; + + public SpellConstructRanged(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, + Function constructFactory, int baseDuration, double baseRange, SoundEvent sound){ + this(Wizardry.MODID, name, tier, element, type, cost, cooldown, constructFactory, baseDuration, baseRange, sound); + } + + public SpellConstructRanged(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, + Function constructFactory, int baseDuration, double baseRange, SoundEvent sound){ + super(modID, name, tier, element, type, cost, cooldown, EnumAction.NONE, constructFactory, baseDuration, sound); + this.baseRange = baseRange; + } + + @Override public boolean doesSpellRequirePacket(){ return false; } + + @Override public boolean canBeCastByNPCs(){ return true; } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + double range = baseRange * modifiers.get(WizardryItems.range_upgrade); + RayTraceResult rayTrace = WizardryUtilities.standardBlockRayTrace(world, caster, range, false); + + if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK && (rayTrace.sideHit == EnumFacing.UP || + !requiresFloor)){ + + if(!world.isRemote){ + + double x = rayTrace.hitVec.x; + double y = rayTrace.hitVec.y; + double z = rayTrace.hitVec.z; + + if(!spawnConstruct(world, x, y, z, caster, modifiers)) return false; + } + + }else if(!requiresFloor){ + + if(!world.isRemote){ + + Vec3d look = caster.getLookVec(); + + double x = caster.posX + look.x * range; + double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() + look.y * range; + double z = caster.posZ + look.z * range; + + if(!spawnConstruct(world, x, y, z, caster, modifiers)) return false; + } + + }else{ + return false; + } + + caster.swingArm(hand); + if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, + SpellModifiers modifiers){ + + double range = baseRange * modifiers.get(WizardryItems.range_upgrade); + + if(target != null && caster.getDistance(target) <= range){ + + if(!world.isRemote){ + + double x = target.posX; + double y = target.posY; + double z = target.posZ; + + // If the target is not on the ground but the construct must be placed on the floor, searches for the + // floor under the caster and returns false if it does not find one within 3 blocks. + if(!target.onGround && requiresFloor){ + y = WizardryUtilities.getNearestFloorLevel(world, new BlockPos(x, y, z), 3); + if(y < 0) return false; + } + + if(!spawnConstruct(world, x, y, z, caster, modifiers)) return false; + } + + caster.swingArm(hand); + if(sound != null) caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + return false; + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/SpellMinion.java b/src/main/java/electroblob/wizardry/spell/SpellMinion.java new file mode 100644 index 00000000..d7971d27 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SpellMinion.java @@ -0,0 +1,165 @@ +package electroblob.wizardry.spell; + +import java.util.function.Function; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.entity.living.ISummonedCreature; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** + * Generic superclass for all spells which summon minions (i.e. instances of {@link ISummonedCreature}). + * This allows all the relevant code to be centralised, since these spells all work in the same way. Usually, a simple + * instantiation of this class is sufficient to create a projectile spell; if something extra needs to be done, such as + * particle spawning, then methods can be overridden (perhaps using an anonymous class) to add the required functionality. + * It is encouraged, however, to put extra functionality in the summoned creature class instead whenever possible. + *

+ * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} + *

+ * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + * + * @author Electroblob + * @since Wizardry 4.2 + */ +// Adding a type parameter to this class seems to work very nicely! +public class SpellMinion extends Spell { + + /** A factory that creates summoned creature entities. */ + protected final Function minionFactory; + /** The base lifetime of the summoned creature. */ + protected final int baseDuration; + /** The sound that gets played when this spell is cast. */ + protected final SoundEvent sound; + + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + /** The number of minions to summon. Defaults to 1. */ + protected int quantity = 1; + /** The maximum number of blocks from the caster in a single direction that the minions can spawn, defaults to 2. */ + protected int range = 2; + + public SpellMinion(String name, Tier tier, Element element, int cost, int cooldown, Function minionFactory, int baseDuration, SoundEvent sound){ + this(Wizardry.MODID, name, tier, element, cost, cooldown, minionFactory, baseDuration, sound); + } + + public SpellMinion(String modID, String name, Tier tier, Element element, int cost, int cooldown, Function minionFactory, int baseDuration, SoundEvent sound){ + super(modID, name, tier, element, SpellType.MINION, cost, cooldown, EnumAction.BOW, false); + this.minionFactory = minionFactory; + this.baseDuration = baseDuration; + this.sound = sound; + } + + /** + * Sets the sound parameters for this spell. + * @param volume + * @param pitch + * @param pitchVariation + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellMinion soundValues(float volume, float pitch, float pitchVariation) { + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; + } + + /** + * Sets the number of minions this spell will summon. + * @param quantity The number of minions to summon. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellMinion quantity(int quantity){ + this.quantity = quantity; + return this; + } + + /** + * Sets the range within which minions can spawn. + * @param range The maximum number of blocks from the caster that minions can be spawned. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellMinion range(int range){ + this.range = range; + return this; + } + + @Override public boolean doesSpellRequirePacket(){ return false; } + + @Override public boolean canBeCastByNPCs(){ return true; } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + if(!this.spawnMinions(world, caster, modifiers)) return false; + WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, + SpellModifiers modifiers){ + + if(!this.spawnMinions(world, caster, modifiers)) return false; + caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + /** Actually spawns the minions. By default, this spawns the number of minions specified by + * {@link SpellMinion#quantity} within a number of blocks of the caster specified by {@link SpellMinion#range}, + * returning false if there is no space to spawn the minions. Returning false from this method causes the spell to + * fail. Override to do something special, like spawning mnions in a specific position. + * @see SpellMinion#addMinionExtras(Entity, EntityLivingBase, SpellModifiers, int) */ + // Protected since someone might want to extend this class and change the behaviour of this method. + protected boolean spawnMinions(World world, EntityLivingBase caster, SpellModifiers modifiers){ + + if(!world.isRemote){ + for(int i=0; i + * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} + *

+ * By default, this type of spell does not require a packet to be sent. {@link Spell#doesSpellRequirePacket()} + * + * @author Electroblob + * @since Wizardry 4.2 + */ +public class SpellProjectile extends Spell { + + // The general contract for these spell subtypes is that any required parameters are set via the constructor and are + // final, whereas any non-critical parameters are set via chainable setters with sensible defaults if not. For example, + // the actual sound to play is required, but it makes sense for its volume and pitch to default to 1 if unspecified. + + /** A factory that creates projectile entities. */ + protected final Function projectileFactory; + /** The base range (projectile speed) of this spell. */ + protected final float baseRange; + /** The sound that gets played when this spell is cast. */ + protected final SoundEvent sound; + + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + + public SpellProjectile(String name, Tier tier, Element element, int cost, int cooldown, Function projectileFactory, float baseRange, SoundEvent sound) { + this(Wizardry.MODID, name, tier, element, cost, cooldown, projectileFactory, baseRange, sound); + } + + public SpellProjectile(String modID, String name, Tier tier, Element element, int cost, int cooldown, Function projectileFactory, float baseRange, SoundEvent sound){ + super(modID, name, tier, element, SpellType.PROJECTILE, cost, cooldown, EnumAction.NONE, false); + this.projectileFactory = projectileFactory; + this.baseRange = baseRange; + this.sound = sound; + } + + /** + * Sets the sound parameters for this spell. + * @param volume + * @param pitch + * @param pitchVariation + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellProjectile soundValues(float volume, float pitch, float pitchVariation) { + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; + } + + @Override public boolean doesSpellRequirePacket(){ return false; } + + @Override public boolean canBeCastByNPCs(){ return true; } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + if(!world.isRemote){ + // Creates a projectile from the supplied factory + EntityMagicProjectile projectile = projectileFactory.apply(world); + // Sets the necessary parameters + projectile.aim(caster, baseRange * modifiers.get(WizardryItems.range_upgrade)); + projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + if(projectile instanceof EntityBomb) ((EntityBomb)projectile).blastMultiplier = modifiers.get(WizardryItems.blast_upgrade); + // Spawns the projectile in the world + world.spawnEntity(projectile); + } + + caster.swingArm(hand); + + WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + + if(target != null){ + + if(!world.isRemote){ + // Creates a projectile from the supplied factory + EntityMagicProjectile projectile = projectileFactory.apply(world); + // Sets the necessary parameters + int aimingError = caster instanceof ISpellCaster ? ((ISpellCaster)caster).getAimingError(world.getDifficulty()) + : WizardryUtilities.getDefaultAimingError(world.getDifficulty()); + projectile.aim(caster, target, baseRange * modifiers.get(WizardryItems.range_upgrade), aimingError); + projectile.damageMultiplier = modifiers.get(SpellModifiers.POTENCY); + if(projectile instanceof EntityBomb) ((EntityBomb)projectile).blastMultiplier = modifiers.get(WizardryItems.blast_upgrade); + // Spawns the projectile in the world + world.spawnEntity(projectile); + } + + caster.swingArm(hand); + + caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + + return true; + } + + return false; + } + +} diff --git a/src/main/java/electroblob/wizardry/spell/SpellRay.java b/src/main/java/electroblob/wizardry/spell/SpellRay.java new file mode 100644 index 00000000..79b2f310 --- /dev/null +++ b/src/main/java/electroblob/wizardry/spell/SpellRay.java @@ -0,0 +1,320 @@ +package electroblob.wizardry.spell; + +import javax.annotation.Nullable; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.constants.SpellType; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +/** + * Generic superclass for all spells which use a raytrace to do something and (optionally) spawn particles along that + * trajectory. This is for both continuous ('stream') spells and non-continuous ('bolt') spells This allows all the + * relevant code to be centralised. This class differs from most other spell superclasses in that it is abstract and as + * such must be subclassed to define what the spell actually does. This is because ray-like spells do a wider variety of + * different things, so it does not make sense to define more specific functions in this class since they would be + * redundant in the majority of cases. + *

+ * By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()} + *

+ * By default, this type of spell requires a packet to be sent. {@link Spell#doesSpellRequirePacket()} + * + * @author Electroblob + * @since Wizardry 4.2 + * @see SpellStream + */ +public abstract class SpellRay extends Spell { + + // TODO: Implement the 'aim assist' (borderSize) effect for rayTracing + + /** The distance below the caster's eyes that the bolt particles start from. */ + private static final double Y_OFFSET = 0.4; + + /** The base range of this spell. */ + protected final double baseRange; + /** The sound that gets played when this spell is cast. */ + @Nullable + protected final SoundEvent sound; + + /** The volume of the sound played when this spell is cast. Defaults to 1. */ + protected float volume = 1; + /** The pitch of the sound played when this spell is cast. Defaults to 1. */ + protected float pitch = 1; + /** The pitch variation of the sound played when this spell is cast. Defaults to 0. */ + protected float pitchVariation = 0; + /** The distance between spawned particles. Defaults to 0.85. */ + // 0.85 was chosen to keep it similar to the most common method used previously, which gave an effective spacing of + // 10/12 = 0.8333 when the spell did not hit anything. + protected double particleSpacing = 0.85; + /** The maximum dither (random position offset) for spawned particles. Defaults to 0.1. */ + protected double particleDither = 0.1; + /** The velocity of spawned particles in the direction the caster is aiming, can be negative. Defaults to 0. */ + protected double particleVelocity = 0; + /** Whether entities are ignored when raytracing. Defaults to false. */ + protected boolean ignoreEntities = false; + /** Whether liquids count as blocks when raytracing. Defaults to false. */ + protected boolean hitLiquids = false; + + public SpellRay(String name, Tier tier, Element element, SpellType type, int cost, int cooldown, boolean isContinuous, double baseRange, SoundEvent sound){ + this(Wizardry.MODID, name, tier, element, type, cost, cooldown, isContinuous, baseRange, sound); + } + + public SpellRay(String modID, String name, Tier tier, Element element, SpellType type, int cost, int cooldown, boolean isContinuous, double baseRange, SoundEvent sound){ + super(modID, name, tier, element, type, cost, cooldown, EnumAction.NONE, isContinuous); + this.baseRange = baseRange; + this.sound = sound; + } + + /** + * Sets the sound parameters for this spell. + * @param volume + * @param pitch + * @param pitchVariation + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellRay soundValues(float volume, float pitch, float pitchVariation) { + this.volume = volume; + this.pitch = pitch; + this.pitchVariation = pitchVariation; + return this; + } + + /** + * Sets the distance between spawned particles. + * @param particleSpacing The distance between particles in the ray effect. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellRay particleSpacing(double particleSpacing){ + this.particleSpacing = particleSpacing; + return this; + } + + /** + * Sets the maximum dither (random position offset) for spawned particles. + * @param particleDither The maximum dither for particles in the ray effect. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellRay particleDither(double particleDither){ + this.particleDither = particleDither; + return this; + } + + /** + * Sets the velocity of spawned particles. + * @param particleVelocity The velocity of spawned particles in the direction the caster is aiming, can be negative. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellRay particleVelocity(double particleVelocity){ + this.particleVelocity = particleVelocity; + return this; + } + + /** + * Sets whether entities are ignored when raytracing. + * @param ignoreEntities Whether to ignore entities when raytracing. If this is true, the spell will pass through + * entities as if they weren't there. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellRay ignoreEntities(boolean ignoreEntities){ + this.ignoreEntities = ignoreEntities; + return this; + } + + /** + * Sets whether liquids count as blocks when raytracing. + * @param hitLiquids Whether to hit liquids when raytracing. If this is false, the spell will pass through + * liquids as if they weren't there. + * @return The spell instance, allowing this method to be chained onto the constructor. + */ + public SpellRay hitLiquids(boolean hitLiquids){ + this.hitLiquids = hitLiquids; + return this; + } + + @Override public boolean canBeCastByNPCs(){ return true; } + + // Finally everything in here is standardised and written in a form that's actually readable - it was long overdue! + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + + Vec3d look = caster.getLookVec(); + Vec3d origin = new Vec3d(caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight() - Y_OFFSET, + caster.posZ); + + double range = baseRange * modifiers.get(WizardryItems.range_upgrade); + + // The first method will hit the first block it touches, passing through entities as if they weren't there. + // The second method will hit the first thing it touches, whether that's a block or an entity. + // Note that when it hits a block, the exact position hit is returned in hitVec, whereas when it hits an + // entity, it just returns the entity's position in hitVec. + RayTraceResult rayTrace = ignoreEntities + ? WizardryUtilities.standardBlockRayTrace(world, caster, range, hitLiquids) + : WizardryUtilities.standardEntityRayTrace(world, caster, range, hitLiquids); + + boolean flag = false; + + if(rayTrace != null){ + // Doesn't matter which way round these are, they're mutually exclusive + if(rayTrace.typeOfHit == RayTraceResult.Type.ENTITY){ + + Entity target = rayTrace.entityHit; + // Do whatever the spell does when it hits an entity + flag = onEntityHit(world, target, caster, ticksInUse, modifiers); + // If the spell succeeded, clip the particles to the correct distance so they don't go through the entity + if(flag){ + // The most pragmatic solution is to use the target's centre point for reasons explained earlier + double dx = origin.x - target.posX; + double dy = origin.y - (target.getEntityBoundingBox().minY + target.height/2); + double dz = origin.z - target.posZ; + range = MathHelper.sqrt(dx*dx + dy*dy + dz*dz); + } + + }else if(rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ + // Do whatever the spell does when it hits an block + flag = onBlockHit(world, rayTrace.getBlockPos(), rayTrace.sideHit, caster, ticksInUse, modifiers); + // If the spell succeeded, clip the particles to the correct distance so they don't go through the block + if(flag) range = origin.distanceTo(rayTrace.hitVec); + } + } + + // If flag is false, either the spell missed or the relevant entity/block hit method returned false + if(!flag && !onMiss(world, caster, ticksInUse, modifiers)) return false; + + // Particle spawning + if(world.isRemote){ + spawnParticleRay(world, origin, look, range); + } + + if(!isContinuous) caster.swingArm(hand); // Bit of a dirty fix but I don't think it'll be a problem! + if(sound != null) WizardryUtilities.playSoundAtPlayer(caster, sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + // IDEA: Add in an aiming error and trigger onMiss accordingly + Vec3d origin = new Vec3d(caster.posX, caster.getEntityBoundingBox().minY + caster.getEyeHeight() - Y_OFFSET, caster.posZ); + Vec3d direction = null; + + boolean flag = false; + + if(target != null){ + + if(!ignoreEntities && onEntityHit(world, target, caster, ticksInUse, modifiers)){ + + direction = new Vec3d(target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ) + .subtract(origin); + flag = true; + + }else{ // Will run if the spell does not do anything special on entity hit. + + int x = MathHelper.floor(target.posX); + int y = (int)target.getEntityBoundingBox().minY - 1; // -1 because we need the block under the target + int z = MathHelper.floor(target.posZ); + BlockPos pos = new BlockPos(x, y, z); + + // This works as if the NPC had actually aimed at the floor beneath the target, so it needs to check + // that the block is not air and (optionally) not a liquid. + if(!world.isAirBlock(pos) && (!world.getBlockState(pos).getMaterial().isLiquid() || hitLiquids) + && onBlockHit(world, pos, EnumFacing.UP, caster, ticksInUse, modifiers)){ + + direction = new Vec3d(x + 0.5, y + 1, z + 0.5).subtract(origin); + flag = true; + } + } + } + + // Wizards don't miss... yet + if(!flag) return false; + + // Particle spawning (direction should never be null at this point but no harm in checking) + if(world.isRemote && direction != null){ + spawnParticleRay(world, origin, direction.normalize(), direction.lengthVector()); + } + + if(!isContinuous) caster.swingArm(hand); // Bit of a dirty fix but I don't think it'll be a problem! + if(sound != null) caster.playSound(sound, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f)); + return true; + } + + // Private helper method, no-one will need to override it since it's pretty much the whole point of this class. + private void spawnParticleRay(World world, Vec3d origin, Vec3d direction, double distance){ + + Vec3d velocity = direction.scale(particleVelocity); + + for(double d = particleSpacing; d <= distance; d += particleSpacing){ + double x = origin.x + d*direction.x + particleDither * (world.rand.nextDouble()*2 - 1); + double y = origin.y + d*direction.y + particleDither * (world.rand.nextDouble()*2 - 1); + double z = origin.z + d*direction.z + particleDither * (world.rand.nextDouble()*2 - 1); + spawnParticle(world, x, y, z, velocity.x, velocity.y, velocity.z); + } + } + + /** + * Called when the spell hits an entity. Will never be called if ignoreEntities is true. + * @param world The world the entity is in. + * @param target The entity that was hit. + * @param caster The caster of this spell, or null if this spell was cast from a dispenser. + * @param ticksInUse The number of ticks the spell has already been cast for (used only for continuous spells). + * @param modifiers The modifiers this spell was cast with. + * @return True to continue with spell casting and spawn particles, false to trigger a miss (N.B. you will need to + * return false from {@link SpellRay#onMiss(World, EntityLivingBase, int, SpellModifiers)} if a miss should not consume + * mana). + */ + protected abstract boolean onEntityHit(World world, Entity target, @Nullable EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers); + + /** + * Called when the spell hits a block. + * @param world The world the block is in. + * @param pos The BlockPos of the block that was hit. + * @param side The side of the block that was hit. + * @param caster The caster of this spell, or null if this spell was cast from a dispenser. + * @param ticksInUse The number of ticks the spell has already been cast for (used only for continuous spells). + * @param modifiers The modifiers this spell was cast with. + * @return True to continue with spell casting and spawn particles, false to trigger a miss (N.B. you will need to + * return false from {@link SpellRay#onMiss(World, EntityLivingBase, int, SpellModifiers)} if a miss should not consume + * mana). + */ + protected abstract boolean onBlockHit(World world, BlockPos pos, EnumFacing side, @Nullable EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers); + + /** + * Called when the spell does not hit anything or when the spell hits something it has no effect on. Most of the time + * this will just return true or false, but some spells may, for example, display a chat readout. + * @param world The world the spell is in. + * @param caster The caster of this spell, or null if this spell was cast from a dispenser. + * @param ticksInUse The number of ticks the spell has already been cast for (used only for continuous spells). + * @param modifiers The modifiers this spell was cast with. + * @return True to continue with spell casting and spawn particles, false to cause the spell to fail. + */ + protected abstract boolean onMiss(World world, @Nullable EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers); + + /** + * Called at each point along the spell trajectory to spawn one or more particles at that point. Only called + * client-side. Does nothing by default. + * @param world The world in which to spawn the particle. + * @param x The x-coordinate to spawn the particle at, with dither already applied. + * @param y The y-coordinate to spawn the particle at, with dither already applied. + * @param z The z-coordinate to spawn the particle at, with dither already applied. + * @param vx The x velocity to spawn the particle with. Usually this is only non-zero for continuous spells. + * @param vy The y velocity to spawn the particle with. Usually this is only non-zero for continuous spells. + * @param vz The z velocity to spawn the particle with. Usually this is only non-zero for continuous spells. + */ + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){} + +} diff --git a/src/main/java/electroblob/wizardry/spell/SpiderSwarm.java b/src/main/java/electroblob/wizardry/spell/SpiderSwarm.java deleted file mode 100644 index fbb9d926..00000000 --- a/src/main/java/electroblob/wizardry/spell/SpiderSwarm.java +++ /dev/null @@ -1,76 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntitySpiderMinion; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SpiderSwarm extends Spell { - - public SpiderSwarm(){ - super(Tier.ADVANCED, 45, Element.EARTH, "spider_swarm", SpellType.MINION, 200, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - for(int i = 0; i < 5; i++){ - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 3, 6); - // The spell instantly fails if no space was found (see javadoc for the above method). - if(pos == null) return false; - - EntitySpiderMinion spider = new EntitySpiderMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(spider); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - // Can't possibly get this far if nothing was spawned. - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!world.isRemote){ - for(int i = 0; i < 5; i++){ - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 3, 6); - // The spell instantly fails if no space was found (see javadoc for the above method). - if(pos == null) return false; - - EntitySpiderMinion spider = new EntitySpiderMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(spider); - } - } - - caster.playSound(SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); - // Can't possibly get this far if nothing was spawned. - return true; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } -} diff --git a/src/main/java/electroblob/wizardry/spell/StaticAura.java b/src/main/java/electroblob/wizardry/spell/StaticAura.java deleted file mode 100644 index b04cc612..00000000 --- a/src/main/java/electroblob/wizardry/spell/StaticAura.java +++ /dev/null @@ -1,71 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardryPotions; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class StaticAura extends Spell { - - public StaticAura(){ - super(Tier.ADVANCED, 40, Element.LIGHTNING, "static_aura", SpellType.DEFENCE, 250, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - // Cannot be cast when it has already been cast - if(!caster.isPotionActive(WizardryPotions.static_aura)){ - if(!world.isRemote){ - caster.addPotionEffect(new PotionEffect(WizardryPotions.static_aura, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SPARK, 1.0F, - world.rand.nextFloat() * 0.4F + 1.4F); - return true; - } - return false; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - // Cannot be cast when it has already been cast - if(!caster.isPotionActive(WizardryPotions.static_aura)){ - if(!world.isRemote){ - caster.addPotionEffect(new PotionEffect(WizardryPotions.static_aura, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade)), 0)); - } - caster.playSound(WizardrySounds.SPELL_SPARK, 1.0F, world.rand.nextFloat() * 0.4F + 1.4F); - return true; - } - return false; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SummonBlaze.java b/src/main/java/electroblob/wizardry/spell/SummonBlaze.java deleted file mode 100644 index 9a67355b..00000000 --- a/src/main/java/electroblob/wizardry/spell/SummonBlaze.java +++ /dev/null @@ -1,71 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityBlazeMinion; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SummonBlaze extends Spell { - - public SummonBlaze(){ - super(Tier.ADVANCED, 40, Element.FIRE, "summon_blaze", SpellType.MINION, 200, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityBlazeMinion blaze = new EntityBlazeMinion(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, - caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(blaze); - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityBlazeMinion blaze = new EntityBlazeMinion(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, - caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(blaze); - } - - caster.playSound(SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SummonIceGiant.java b/src/main/java/electroblob/wizardry/spell/SummonIceGiant.java deleted file mode 100644 index 87d30b8d..00000000 --- a/src/main/java/electroblob/wizardry/spell/SummonIceGiant.java +++ /dev/null @@ -1,53 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityIceGiant; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SummonIceGiant extends Spell { - - public SummonIceGiant(){ - super(Tier.MASTER, 100, Element.ICE, "summon_ice_giant", SpellType.MINION, 400, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - if(!world.isRemote){ - - EntityIceGiant icegiant = new EntityIceGiant(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(icegiant); - } - - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)pos.getX() + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)pos.getY() + 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)pos.getZ() + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0, 0, - 48 + world.rand.nextInt(12), 0.6f, 0.6f, 1.0f); - } - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, - world.rand.nextFloat() * 0.1F + 0.2F); - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SummonIceWraith.java b/src/main/java/electroblob/wizardry/spell/SummonIceWraith.java deleted file mode 100644 index 83571178..00000000 --- a/src/main/java/electroblob/wizardry/spell/SummonIceWraith.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityIceWraith; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SummonIceWraith extends Spell { - - public SummonIceWraith(){ - super(Tier.ADVANCED, 40, Element.ICE, "summon_ice_wraith", SpellType.MINION, 200, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityIceWraith iceWraith = new EntityIceWraith(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, - caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(iceWraith); - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityIceWraith iceWraith = new EntityIceWraith(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, - caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(iceWraith); - } - caster.playSound(SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java b/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java index fa2a0759..1fee0dab 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java +++ b/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java @@ -1,11 +1,11 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.entity.player.EntityPlayer; @@ -18,7 +18,7 @@ import net.minecraft.world.World; public class SummonIronGolem extends Spell { public SummonIronGolem(){ - super(Tier.MASTER, 175, Element.SORCERY, "summon_iron_golem", SpellType.MINION, 400, EnumAction.BOW, false); + super("summon_iron_golem", Tier.MASTER, Element.SORCERY, SpellType.MINION, 175, 400, EnumAction.BOW, false); } @Override @@ -28,23 +28,22 @@ public class SummonIronGolem extends Spell { if(pos == null) return false; if(!world.isRemote){ + EntityIronGolem golem = new EntityIronGolem(world); golem.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); world.spawnEntity(golem); - } - - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)pos.getX() + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)pos.getY() + 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)pos.getZ() + world.rand.nextFloat() * 2 - 1.0F); - if(world.isRemote){ - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0, 0, - 48 + world.rand.nextInt(12), 0.6f, 0.6f, 1.0f); + + }else{ + + for(int i=0; i<10; i++){ + double x = pos.getX() + world.rand.nextDouble() * 2 - 1; + double y = pos.getY() + 0.5 + world.rand.nextDouble(); + double z = pos.getZ() + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).colour(0.6f, 0.6f, 1).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); + WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 1, 1 + 0.2f * world.rand.nextFloat()); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/SummonLightningWraith.java b/src/main/java/electroblob/wizardry/spell/SummonLightningWraith.java deleted file mode 100644 index 0baff375..00000000 --- a/src/main/java/electroblob/wizardry/spell/SummonLightningWraith.java +++ /dev/null @@ -1,70 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityLightningWraith; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SummonLightningWraith extends Spell { - - public SummonLightningWraith(){ - super(Tier.ADVANCED, 40, Element.LIGHTNING, "summon_lightning_wraith", SpellType.MINION, 200, EnumAction.BOW, - false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityLightningWraith lightningWraith = new EntityLightningWraith(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(lightningWraith); - } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityLightningWraith lightningWraith = new EntityLightningWraith(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(lightningWraith); - } - caster.playSound(SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SummonPhoenix.java b/src/main/java/electroblob/wizardry/spell/SummonPhoenix.java deleted file mode 100644 index c74b39d9..00000000 --- a/src/main/java/electroblob/wizardry/spell/SummonPhoenix.java +++ /dev/null @@ -1,46 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityPhoenix; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SummonPhoenix extends Spell { - - public SummonPhoenix(){ - super(Tier.MASTER, 150, Element.FIRE, "summon_phoenix", SpellType.MINION, 400, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityPhoenix phoenix = new EntityPhoenix(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, caster, - (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(phoenix); - } - - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SummonShadowWraith.java b/src/main/java/electroblob/wizardry/spell/SummonShadowWraith.java index 6f00f8f2..8dac0d1c 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonShadowWraith.java +++ b/src/main/java/electroblob/wizardry/spell/SummonShadowWraith.java @@ -1,48 +1,17 @@ package electroblob.wizardry.spell; import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntityShadowWraith; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -public class SummonShadowWraith extends Spell { +public class SummonShadowWraith extends SpellMinion { public SummonShadowWraith(){ - super(Tier.MASTER, 100, Element.NECROMANCY, "summon_shadow_wraith", SpellType.MINION, 400, EnumAction.BOW, - false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityShadowWraith shadowWraith = new EntityShadowWraith(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(shadowWraith); - } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; + super("summon_shadow_wraith", Tier.MASTER, Element.NECROMANCY, 100, 400, EntityShadowWraith::new, 600, SoundEvents.ENTITY_WITHER_AMBIENT); + this.soundValues(1, 1.1f, 0.1f); } @SideOnly(Side.CLIENT) diff --git a/src/main/java/electroblob/wizardry/spell/SummonSkeleton.java b/src/main/java/electroblob/wizardry/spell/SummonSkeleton.java index 68bcbcf1..4bec5e60 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSkeleton.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSkeleton.java @@ -1,75 +1,26 @@ package electroblob.wizardry.spell; import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntitySkeletonMinion; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.inventory.EntityEquipmentSlot; -import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -public class SummonSkeleton extends Spell { +public class SummonSkeleton extends SpellMinion { public SummonSkeleton(){ - super(Tier.APPRENTICE, 15, Element.NECROMANCY, "summon_skeleton", SpellType.MINION, 50, EnumAction.BOW, false); + super("summon_skeleton", Tier.APPRENTICE, Element.NECROMANCY, 15, 50, EntitySkeletonMinion::new, 600, WizardrySounds.SPELL_SUMMONING); + this.soundValues(7, 0.6f, 0); } - + @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntitySkeletonMinion skeleton = new EntitySkeletonMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - skeleton.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); - skeleton.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); - world.spawnEntity(skeleton); - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 7.0f, 0.6f); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntitySkeletonMinion skeleton = new EntitySkeletonMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - skeleton.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); - skeleton.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); - world.spawnEntity(skeleton); - } - caster.playSound(WizardrySounds.SPELL_SUMMONING, 7.0f, 0.6f); - return true; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; + protected void addMinionExtras(EntitySkeletonMinion minion, EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){ + minion.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); + minion.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); } } diff --git a/src/main/java/electroblob/wizardry/spell/SummonSkeletonLegion.java b/src/main/java/electroblob/wizardry/spell/SummonSkeletonLegion.java index 02defe38..f7fb9c4c 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSkeletonLegion.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSkeletonLegion.java @@ -1,78 +1,40 @@ package electroblob.wizardry.spell; import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.living.EntitySkeletonMinion; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Items; import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; -import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -public class SummonSkeletonLegion extends Spell { +public class SummonSkeletonLegion extends SpellMinion { public SummonSkeletonLegion(){ - super(Tier.MASTER, 100, Element.NECROMANCY, "summon_skeleton_legion", SpellType.MINION, 400, EnumAction.BOW, - false); + super("summon_skeleton_legion", Tier.MASTER, Element.NECROMANCY, 100, 400, EntitySkeletonMinion::new, 1200, SoundEvents.ENTITY_WITHER_SPAWN); + this.soundValues(1, 1.1f, 0.1f); + this.quantity(3); + this.range(3); } - + @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ + protected void addMinionExtras(EntitySkeletonMinion minion, EntityLivingBase caster, SpellModifiers modifiers, int alreadySpawned){ + + if(alreadySpawned % 2 == 0){ // Archers - for(int i = 0; i < 3; i++){ - // This is all so much neater now thanks to this method. - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 3, 6); - // The spell instantly fails if no space was found (see javadoc for the above method). - if(pos == null) return false; - - EntitySkeletonMinion skeleton = new EntitySkeletonMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(1200 * modifiers.get(WizardryItems.duration_upgrade))); - skeleton.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); - skeleton.setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(Items.CHAINMAIL_HELMET)); - skeleton.setItemStackToSlot(EntityEquipmentSlot.CHEST, new ItemStack(Items.CHAINMAIL_CHESTPLATE)); - skeleton.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); - skeleton.setDropChance(EntityEquipmentSlot.HEAD, 0.0f); - skeleton.setDropChance(EntityEquipmentSlot.CHEST, 0.0f); - world.spawnEntity(skeleton); - } + minion.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); + }else{ // Swordsmen - for(int i = 0; i < 3; i++){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 3, 6); - // The spell instantly fails if no space was found (see javadoc for the above method). - if(pos == null) return false; - - EntitySkeletonMinion skeleton = new EntitySkeletonMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(1200 * modifiers.get(WizardryItems.duration_upgrade))); - skeleton.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD)); - skeleton.setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(Items.CHAINMAIL_HELMET)); - skeleton.setItemStackToSlot(EntityEquipmentSlot.CHEST, new ItemStack(Items.CHAINMAIL_CHESTPLATE)); - skeleton.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); - skeleton.setDropChance(EntityEquipmentSlot.HEAD, 0.0f); - skeleton.setDropChance(EntityEquipmentSlot.CHEST, 0.0f); - world.spawnEntity(skeleton); - } + minion.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD)); } - - // Can't possibly get this far if nothing was spawned. - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_SPAWN, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; + + minion.setItemStackToSlot(EntityEquipmentSlot.HEAD, new ItemStack(Items.CHAINMAIL_HELMET)); + minion.setItemStackToSlot(EntityEquipmentSlot.CHEST, new ItemStack(Items.CHAINMAIL_CHESTPLATE)); + minion.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); + minion.setDropChance(EntityEquipmentSlot.HEAD, 0.0f); + minion.setDropChance(EntityEquipmentSlot.CHEST, 0.0f); } } diff --git a/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java b/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java index d50da8c1..e168d3b8 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java @@ -1,12 +1,12 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.entity.monster.EntitySnowman; import net.minecraft.entity.player.EntityPlayer; @@ -18,7 +18,7 @@ import net.minecraft.world.World; public class SummonSnowGolem extends Spell { public SummonSnowGolem(){ - super(Tier.APPRENTICE, 15, Element.ICE, "summon_snow_golem", SpellType.MINION, 20, EnumAction.BOW, false); + super("summon_snow_golem", Tier.APPRENTICE, Element.ICE, SpellType.MINION, 15, 20, EnumAction.BOW, false); } @Override @@ -28,21 +28,22 @@ public class SummonSnowGolem extends Spell { if(pos == null) return false; if(!world.isRemote){ + EntitySnowman snowman = new EntitySnowman(world); snowman.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5); world.spawnEntity(snowman); - } - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)pos.getX() + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)pos.getY() + 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)pos.getZ() + world.rand.nextFloat() * 2 - 1.0F); - if(world.isRemote){ - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.6f, 0.6f, 1.0f); + + }else{ + + for(int i=0; i<10; i++){ + double x = pos.getX() + world.rand.nextDouble() * 2 - 1; + double y = pos.getY() + 0.5 + world.rand.nextDouble(); + double z = pos.getZ() + world.rand.nextDouble() * 2 - 1; + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.6f, 0.6f, 1).spawn(world); } } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); + + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7f, 1 + 0.4f * world.rand.nextFloat()); return true; } diff --git a/src/main/java/electroblob/wizardry/spell/SummonSpiritHorse.java b/src/main/java/electroblob/wizardry/spell/SummonSpiritHorse.java index 359e2b45..a256d880 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSpiritHorse.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSpiritHorse.java @@ -17,7 +17,7 @@ import net.minecraft.world.World; public class SummonSpiritHorse extends Spell { public SummonSpiritHorse(){ - super(Tier.ADVANCED, 50, Element.EARTH, "summon_spirit_horse", SpellType.MINION, 150, EnumAction.BOW, false); + super("summon_spirit_horse", Tier.ADVANCED, Element.EARTH, SpellType.MINION, 50, 150, EnumAction.BOW, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/SummonSpiritWolf.java b/src/main/java/electroblob/wizardry/spell/SummonSpiritWolf.java index 4d0ce4c3..f3896c7f 100644 --- a/src/main/java/electroblob/wizardry/spell/SummonSpiritWolf.java +++ b/src/main/java/electroblob/wizardry/spell/SummonSpiritWolf.java @@ -17,7 +17,7 @@ import net.minecraft.world.World; public class SummonSpiritWolf extends Spell { public SummonSpiritWolf(){ - super(Tier.APPRENTICE, 25, Element.EARTH, "summon_spirit_wolf", SpellType.MINION, 100, EnumAction.BOW, false); + super("summon_spirit_wolf", Tier.APPRENTICE, Element.EARTH, SpellType.MINION, 25, 100, EnumAction.BOW, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/SummonStormElemental.java b/src/main/java/electroblob/wizardry/spell/SummonStormElemental.java deleted file mode 100644 index ed41e623..00000000 --- a/src/main/java/electroblob/wizardry/spell/SummonStormElemental.java +++ /dev/null @@ -1,45 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityStormElemental; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SummonStormElemental extends Spell { - - public SummonStormElemental(){ - super(Tier.MASTER, 100, Element.LIGHTNING, "summon_storm_elemental", SpellType.MINION, 400, EnumAction.BOW, - false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityStormElemental stormElemental = new EntityStormElemental(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(stormElemental); - } - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_AMBIENT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } -} diff --git a/src/main/java/electroblob/wizardry/spell/SummonWitherSkeleton.java b/src/main/java/electroblob/wizardry/spell/SummonWitherSkeleton.java deleted file mode 100644 index 58372589..00000000 --- a/src/main/java/electroblob/wizardry/spell/SummonWitherSkeleton.java +++ /dev/null @@ -1,76 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityWitherSkeletonMinion; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Items; -import net.minecraft.inventory.EntityEquipmentSlot; -import net.minecraft.item.EnumAction; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SummonWitherSkeleton extends Spell { - - public SummonWitherSkeleton(){ - super(Tier.ADVANCED, 35, Element.NECROMANCY, "summon_wither_skeleton", SpellType.MINION, 150, EnumAction.BOW, - false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityWitherSkeletonMinion skeleton = new EntityWitherSkeletonMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - skeleton.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.STONE_SWORD)); - skeleton.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); - world.spawnEntity(skeleton); - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 7.0f, 0.6f); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityWitherSkeletonMinion skeleton = new EntityWitherSkeletonMinion(world, pos.getX() + 0.5, pos.getY(), - pos.getZ() + 0.5, caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - skeleton.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.STONE_SWORD)); - skeleton.setDropChance(EntityEquipmentSlot.MAINHAND, 0.0f); - world.spawnEntity(skeleton); - } - caster.playSound(WizardrySounds.SPELL_SUMMONING, 7.0f, 0.6f); - return true; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/SummonZombie.java b/src/main/java/electroblob/wizardry/spell/SummonZombie.java deleted file mode 100644 index 8e8e684f..00000000 --- a/src/main/java/electroblob/wizardry/spell/SummonZombie.java +++ /dev/null @@ -1,67 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.living.EntityZombieMinion; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class SummonZombie extends Spell { - - public SummonZombie(){ - super(Tier.BASIC, 10, Element.NECROMANCY, "summon_zombie", SpellType.MINION, 40, EnumAction.BOW, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - EntityZombieMinion zombie = new EntityZombieMinion(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, - caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(zombie); - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_SUMMONING, 7.0f, 0.6f); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(!world.isRemote){ - - BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 4); - if(pos == null) return false; - - EntityZombieMinion zombie = new EntityZombieMinion(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, - caster, (int)(600 * modifiers.get(WizardryItems.duration_upgrade))); - world.spawnEntity(zombie); - } - caster.playSound(WizardrySounds.SPELL_SUMMONING, 7.0f, 0.6f); - return true; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Telekinesis.java b/src/main/java/electroblob/wizardry/spell/Telekinesis.java index 40b7f34b..13dbe35c 100644 --- a/src/main/java/electroblob/wizardry/spell/Telekinesis.java +++ b/src/main/java/electroblob/wizardry/spell/Telekinesis.java @@ -4,115 +4,80 @@ import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -public class Telekinesis extends Spell { +public class Telekinesis extends SpellRay { public Telekinesis(){ - super(Tier.BASIC, 5, Element.SORCERY, "telekinesis", SpellType.UTILITY, 5, EnumAction.NONE, false); + super("telekinesis", Tier.BASIC, Element.SORCERY, SpellType.UTILITY, 5, 5, false, 8, WizardrySounds.SPELL_CONJURATION); } + @Override public boolean doesSpellRequirePacket(){ return false; } + @Override - public boolean doesSpellRequirePacket(){ - return false; - } + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(target instanceof EntityItem){ - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + target.motionX = (caster.posX - target.posX) / 6; + target.motionY = (caster.posY + caster.getEyeHeight() - target.posY) / 6; + target.motionZ = (caster.posZ - target.posZ) / 6; + return true; - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 8 * modifiers.get(WizardryItems.range_upgrade), 3.0f); - - if(rayTrace != null && rayTrace.entityHit != null){ - - if(rayTrace.entityHit instanceof EntityItem){ - - Entity entityHit = rayTrace.entityHit; - entityHit.motionX = (caster.posX - entityHit.posX) / 6; - entityHit.motionY = (caster.posY + caster.eyeHeight - entityHit.posY) / 6; - entityHit.motionZ = (caster.posZ - entityHit.posZ) / 6; - entityHit.playSound(WizardrySounds.SPELL_CONJURATION, 1.0F, 1.0f); - caster.swingArm(hand); - return true; - - }else if(rayTrace.entityHit instanceof EntityPlayer && Wizardry.settings.telekineticDisarmament){ - - EntityPlayer target = (EntityPlayer)rayTrace.entityHit; - - if(!target.getHeldItemMainhand().isEmpty()){ - - if(!world.isRemote){ - EntityItem item = target.entityDropItem(target.getHeldItemMainhand(), 0.0f); - // Makes the item move towards the caster - item.motionX = (caster.posX - target.posX) / 20; - item.motionZ = (caster.posZ - target.posZ) / 20; - } - - target.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY); - - target.playSound(WizardrySounds.SPELL_CONJURATION, 1.0F, 1.0f); - caster.swingArm(hand); - return true; - } - } - } - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){ - - IBlockState blockstate = world.getBlockState(new BlockPos(rayTrace.getBlockPos())); - - if(blockstate.getBlock().onBlockActivated(world, rayTrace.getBlockPos(), blockstate, caster, hand, - rayTrace.sideHit, 0, 0, 0)){ - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0F, 1.0f); - caster.swingArm(hand); - return true; - } - } - return false; - } - - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target instanceof EntityPlayer && !target.getHeldItemMainhand().isEmpty()){ + }else if(target instanceof EntityPlayer && (Wizardry.settings.telekineticDisarmament || !(caster instanceof EntityPlayer))){ + EntityPlayer player = (EntityPlayer)target; + // IDEA: Disarm the offhand if the mainhand is empty or otherwise harmless? - if(!world.isRemote){ - EntityItem item = target.entityDropItem(target.getHeldItemMainhand(), 0.0f); - // Makes the item move towards the caster - item.motionX = (caster.posX - target.posX) / 20; - item.motionZ = (caster.posZ - target.posZ) / 20; + if(!player.getHeldItemMainhand().isEmpty()){ + + if(!world.isRemote){ + EntityItem item = player.entityDropItem(player.getHeldItemMainhand(), 0); + // Makes the item move towards the caster + item.motionX = (caster.posX - player.posX) / 20; + item.motionZ = (caster.posZ - player.posZ) / 20; + } + + player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY); + + return true; } - - target.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY); - - target.playSound(WizardrySounds.SPELL_CONJURATION, 1.0F, 1.0f); - caster.swingArm(hand); - return true; } - + return false; } @Override - public boolean canBeCastByNPCs(){ - return true; + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(caster instanceof EntityPlayer){ + + IBlockState blockstate = world.getBlockState(pos); + + if(blockstate.getBlock().onBlockActivated(world, pos, blockstate, (EntityPlayer)caster, EnumHand.MAIN_HAND, + side, 0, 0, 0)){ + return true; + } + } + + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; } } diff --git a/src/main/java/electroblob/wizardry/spell/Thunderbolt.java b/src/main/java/electroblob/wizardry/spell/Thunderbolt.java deleted file mode 100644 index ecdf0762..00000000 --- a/src/main/java/electroblob/wizardry/spell/Thunderbolt.java +++ /dev/null @@ -1,68 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.entity.projectile.EntityThunderbolt; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class Thunderbolt extends Spell { - - public Thunderbolt(){ - super(Tier.BASIC, 10, Element.LIGHTNING, "thunderbolt", SpellType.ATTACK, 15, EnumAction.NONE, false); - } - - @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - EntityThunderbolt thunderbolt = new EntityThunderbolt(world, caster, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(thunderbolt); - } - - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.8F, - world.rand.nextFloat() * 0.2F + 0.8F); - caster.swingArm(hand); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - EntityThunderbolt thunderbolt = new EntityThunderbolt(world, caster, - modifiers.get(SpellModifiers.DAMAGE)); - thunderbolt.directTowards(target, 2.5f); - world.spawnEntity(thunderbolt); - } - - caster.playSound(WizardrySounds.SPELL_ICE, 0.8F, world.rand.nextFloat() * 0.2F + 0.8F); - caster.swingArm(hand); - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Thunderstorm.java b/src/main/java/electroblob/wizardry/spell/Thunderstorm.java index cb533a50..a96d65ea 100644 --- a/src/main/java/electroblob/wizardry/spell/Thunderstorm.java +++ b/src/main/java/electroblob/wizardry/spell/Thunderstorm.java @@ -2,7 +2,6 @@ package electroblob.wizardry.spell; import java.util.List; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; @@ -11,27 +10,37 @@ import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.effect.EntityLightningBolt; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; import net.minecraft.util.EnumHand; -import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class Thunderstorm extends Spell { public Thunderstorm(){ - super(Tier.MASTER, 100, Element.LIGHTNING, "thunderstorm", SpellType.ATTACK, 250, EnumAction.BOW, false); + super("thunderstorm", Tier.MASTER, Element.LIGHTNING, SpellType.ATTACK, 100, 250, EnumAction.BOW, false); } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - + return doCasting(world, caster, modifiers); + } + + @Override + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + return doCasting(world, caster, modifiers); + } + + // This spell is exactly the same for players and NPCs. + private boolean doCasting(World world, EntityLivingBase caster, SpellModifiers modifiers){ + if(world.canBlockSeeSky(new BlockPos(caster))){ for(int r = 0; r < 10; r++){ @@ -69,25 +78,16 @@ public class Thunderstorm extends Spell { secondaryTarget.posY + secondaryTarget.height / 2, secondaryTarget.posZ); world.spawnEntity(arc); }else{ - for(int j = 0; j < 8; j++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - secondaryTarget.posX + world.rand.nextFloat() - 0.5, - secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - secondaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, - secondaryTarget.posX + world.rand.nextFloat() - 0.5, - secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - secondaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0); - } + ParticleBuilder.spawnShockParticles(world, secondaryTarget.posX, + secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2, + secondaryTarget.posZ); } secondaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F, world.rand.nextFloat() * 0.4F + 1.5F); secondaryTarget.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 10.0f * modifiers.get(SpellModifiers.DAMAGE)); + 10.0f * modifiers.get(SpellModifiers.POTENCY)); // Tertiary chaining effect @@ -110,18 +110,9 @@ public class Thunderstorm extends Spell { tertiaryTarget.posZ); world.spawnEntity(arc); }else{ - for(int k = 0; k < 8; k++){ - Wizardry.proxy.spawnParticle(Type.SPARK, world, - tertiaryTarget.posX + world.rand.nextFloat() - 0.5, - tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - tertiaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0, 3); - world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, - tertiaryTarget.posX + world.rand.nextFloat() - 0.5, - tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2 - + world.rand.nextFloat() * 2 - 1, - tertiaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0); - } + ParticleBuilder.spawnShockParticles(world, tertiaryTarget.posX, + tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2, + tertiaryTarget.posZ); } tertiaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F, @@ -129,7 +120,7 @@ public class Thunderstorm extends Spell { tertiaryTarget.attackEntityFrom( MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), - 8.0f * modifiers.get(SpellModifiers.DAMAGE)); + 8.0f * modifiers.get(SpellModifiers.POTENCY)); } } } diff --git a/src/main/java/electroblob/wizardry/spell/Tornado.java b/src/main/java/electroblob/wizardry/spell/Tornado.java index bae3d7ee..166b071e 100644 --- a/src/main/java/electroblob/wizardry/spell/Tornado.java +++ b/src/main/java/electroblob/wizardry/spell/Tornado.java @@ -4,74 +4,20 @@ import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.entity.construct.EntityTornado; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumAction; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; -public class Tornado extends Spell { +public class Tornado extends SpellConstruct { public Tornado(){ - super(Tier.ADVANCED, 35, Element.EARTH, "tornado", SpellType.ATTACK, 80, EnumAction.NONE, false); + super("tornado", Tier.ADVANCED, Element.EARTH, SpellType.ATTACK, 35, 80, EnumAction.NONE, EntityTornado::new, 200, WizardrySounds.SPELL_ICE); } @Override - public boolean doesSpellRequirePacket(){ - return false; - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - if(!world.isRemote){ - double x = caster.posX + caster.getLookVec().x; - double y = caster.posY; - double z = caster.posZ + caster.getLookVec().z; - - EntityTornado tornado = new EntityTornado(world, x, y, z, caster, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), caster.getLookVec().x / 3, - caster.getLookVec().z / 3, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(tornado); - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - double x = caster.posX + caster.getLookVec().x; - double y = caster.posY; - double z = caster.posZ + caster.getLookVec().z; - - EntityTornado tornado = new EntityTornado(world, x, y, z, caster, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), caster.getLookVec().x / 3, - caster.getLookVec().z / 3, modifiers.get(SpellModifiers.DAMAGE)); - world.spawnEntity(tornado); - } - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 1.0F, 1.0F); - - return true; - } - - return false; - } - - @Override - public boolean canBeCastByNPCs(){ - return true; + protected void addConstructExtras(EntityTornado construct, EntityLivingBase caster, SpellModifiers modifiers){ + construct.setHorizontalVelocity(caster.getLookVec().x / 3, caster.getLookVec().z / 3); } } diff --git a/src/main/java/electroblob/wizardry/spell/Transience.java b/src/main/java/electroblob/wizardry/spell/Transience.java index faee9216..07bcc516 100644 --- a/src/main/java/electroblob/wizardry/spell/Transience.java +++ b/src/main/java/electroblob/wizardry/spell/Transience.java @@ -24,7 +24,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class Transience extends Spell { public Transience(){ - super(Tier.ADVANCED, 50, Element.HEALING, "transience", SpellType.DEFENCE, 100, EnumAction.BOW, false); + super("transience", Tier.ADVANCED, Element.HEALING, SpellType.BUFF, 50, 100, EnumAction.BOW, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/Transportation.java b/src/main/java/electroblob/wizardry/spell/Transportation.java index 51b8cedd..2e91f4dd 100644 --- a/src/main/java/electroblob/wizardry/spell/Transportation.java +++ b/src/main/java/electroblob/wizardry/spell/Transportation.java @@ -19,7 +19,7 @@ import net.minecraft.world.World; public class Transportation extends Spell { public Transportation(){ - super(Tier.ADVANCED, 100, Element.SORCERY, "transportation", SpellType.UTILITY, 100, EnumAction.BOW, false); + super("transportation", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 100, 100, EnumAction.BOW, false); } @Override diff --git a/src/main/java/electroblob/wizardry/spell/VanishingBox.java b/src/main/java/electroblob/wizardry/spell/VanishingBox.java index 76bf97ee..24ea13df 100644 --- a/src/main/java/electroblob/wizardry/spell/VanishingBox.java +++ b/src/main/java/electroblob/wizardry/spell/VanishingBox.java @@ -15,13 +15,10 @@ import net.minecraft.world.World; public class VanishingBox extends Spell { public VanishingBox(){ - super(Tier.ADVANCED, 45, Element.SORCERY, "vanishing_box", SpellType.UTILITY, 70, EnumAction.BOW, false); + super("vanishing_box", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 45, 70, EnumAction.BOW, false); } - @Override - public boolean doesSpellRequirePacket(){ - return false; - } + @Override public boolean doesSpellRequirePacket(){ return false; } @Override public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ diff --git a/src/main/java/electroblob/wizardry/spell/WallOfFrost.java b/src/main/java/electroblob/wizardry/spell/WallOfFrost.java index 98907300..37a55b55 100644 --- a/src/main/java/electroblob/wizardry/spell/WallOfFrost.java +++ b/src/main/java/electroblob/wizardry/spell/WallOfFrost.java @@ -1,103 +1,137 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockStatue; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryBlocks; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.tileentity.TileEntityStatue; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WizardryUtilities; +import electroblob.wizardry.util.ParticleBuilder.Type; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.EnumAction; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -public class WallOfFrost extends Spell { +public class WallOfFrost extends SpellRay { + private static final int BASE_DURATION = 600; + public WallOfFrost(){ - super(Tier.MASTER, 15, Element.ICE, "wall_of_frost", SpellType.UTILITY, 0, EnumAction.NONE, true); + super("wall_of_frost", Tier.MASTER, Element.ICE, SpellType.UTILITY, 15, 0, true, 10, null); + this.particleVelocity(1); + this.particleSpacing(0.5); + } + + @Override + public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + // TODO: Temporary solution until I implement a better continuous sound system + boolean flag = super.cast(world, caster, hand, ticksInUse, modifiers); + if(flag){ + if(ticksInUse % 12 == 0){ + if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.5f, 1); + WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_ICE, 0.5f, 1); + } + } + return flag; } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ + public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){ + boolean flag = super.cast(world, caster, hand, ticksInUse, target, modifiers); + if(flag){ + if(ticksInUse % 12 == 0){ + if(ticksInUse == 0) caster.playSound(WizardrySounds.SPELL_ICE, 0.5f, 1); + caster.playSound(WizardrySounds.SPELL_LOOP_ICE, 0.5f, 1); + } + } + return flag; + } - // IDEA: Use frosted ice instead of ice statue + @Override + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + // Wall of frost now freezes entities solid too! + if(target instanceof EntityLiving && !world.isRemote){ + // Unchecked cast is fine because the block is a static final field + if(((BlockStatue)WizardryBlocks.ice_statue).convertToStatue((EntityLiving)target, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)))){ + + target.playSound(WizardrySounds.SPELL_FREEZE, 1.0F, world.rand.nextFloat() * 0.4F + 0.8F); + return true; + } + } + + return false; + } - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.rayTrace(10 * modifiers.get(WizardryItems.range_upgrade), world, - caster, true); - - if(rayTrace != null && !world.isRemote){ - - BlockPos pos = rayTrace.getBlockPos(); + @Override + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + // IDEA: Use frosted ice instead of ice statue blocks + + if(!world.isRemote){ // Stops the ice being placed floating above snow and grass. Directions other than up included for // completeness. if(WizardryUtilities.canBlockBeReplaced(world, pos)){ // Moves the blockpos back into the block - pos = pos.offset(rayTrace.sideHit.getOpposite()); + pos = pos.offset(side.getOpposite()); } if(caster.getDistance(pos.getX(), pos.getY(), pos.getZ()) > 2 && world.getBlockState(pos).getBlock() != WizardryBlocks.ice_statue){ - pos = pos.offset(rayTrace.sideHit); + pos = pos.offset(side); + + int duration = (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)); if(WizardryUtilities.canBlockBeReplaced(world, pos)){ + world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); + + if(world.getTileEntity(pos) instanceof TileEntityStatue){ + ((TileEntityStatue)world.getTileEntity(pos)).setLifetime(duration); + } } // Builds a 2 block high wall if it hits the ground - if(rayTrace.sideHit == EnumFacing.UP){ - pos = pos.offset(rayTrace.sideHit); + if(side == EnumFacing.UP){ + pos = pos.offset(side); if(WizardryUtilities.canBlockBeReplaced(world, pos)){ + world.setBlockState(pos, WizardryBlocks.ice_statue.getDefaultState()); + + if(world.getTileEntity(pos) instanceof TileEntityStatue){ + ((TileEntityStatue)world.getTileEntity(pos)).setLifetime(duration); + } } } } } - - for(int i = 0; i < 20; i++){ - - if(world.isRemote){ - - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, - look.x * modifiers.get(WizardryItems.range_upgrade), - look.y * modifiers.get(WizardryItems.range_upgrade), - look.z * modifiers.get(WizardryItems.range_upgrade), 8 + world.rand.nextInt(12), 0.4f, - 0.6f, 1.0f); - - x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, - look.x * modifiers.get(WizardryItems.range_upgrade), - look.y * modifiers.get(WizardryItems.range_upgrade), - look.z * modifiers.get(WizardryItems.range_upgrade), 8 + world.rand.nextInt(12), 1.0f, - 1.0f, 1.0f); - } - } - - if(ticksInUse % 12 == 0){ - if(ticksInUse == 0) WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.5F, 1.0f); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_LOOP_ICE, 0.5F, 1.0f); - } - + return true; } + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return true; + } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + float brightness = world.rand.nextFloat(); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(12)) + .colour(0.4f + 0.6f * brightness, 0.6f + 0.4f*brightness, 1).spawn(world); + ParticleBuilder.create(Type.SNOW).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(12)).spawn(world); + } + } diff --git a/src/main/java/electroblob/wizardry/spell/WaterBreathing.java b/src/main/java/electroblob/wizardry/spell/WaterBreathing.java deleted file mode 100644 index 4b2462eb..00000000 --- a/src/main/java/electroblob/wizardry/spell/WaterBreathing.java +++ /dev/null @@ -1,44 +0,0 @@ -package electroblob.wizardry.spell; - -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.constants.Element; -import electroblob.wizardry.constants.SpellType; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; -import electroblob.wizardry.registry.WizardrySounds; -import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.ParticleBuilder.Type; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.MobEffects; -import net.minecraft.item.EnumAction; -import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.world.World; - -public class WaterBreathing extends Spell { - - public WaterBreathing(){ - super(Tier.ADVANCED, 30, Element.EARTH, "water_breathing", SpellType.UTILITY, 250, EnumAction.BOW, false); - } - - @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - caster.addPotionEffect(new PotionEffect(MobEffects.WATER_BREATHING, - (int)(1200 * modifiers.get(WizardryItems.duration_upgrade)), 0, false, false)); - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x1 = (double)((float)caster.posX + world.rand.nextFloat() * 2 - 1.0F); - double y1 = (double)((float)WizardryUtilities.getPlayerEyesPos(caster) - 0.5F + world.rand.nextFloat()); - double z1 = (double)((float)caster.posZ + world.rand.nextFloat() * 2 - 1.0F); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0, 0.1F, 0, - 48 + world.rand.nextInt(12), 0.3f, 0.3f, 1.0f); - } - } - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F, - world.rand.nextFloat() * 0.4F + 1.0F); - return true; - } - -} diff --git a/src/main/java/electroblob/wizardry/spell/Whirlwind.java b/src/main/java/electroblob/wizardry/spell/Whirlwind.java index 526b8dbb..c3ff793e 100644 --- a/src/main/java/electroblob/wizardry/spell/Whirlwind.java +++ b/src/main/java/electroblob/wizardry/spell/Whirlwind.java @@ -3,36 +3,29 @@ package electroblob.wizardry.spell; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.util.SpellModifiers; -import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.EnumAction; import net.minecraft.network.play.server.SPacketEntityVelocity; -import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class Whirlwind extends Spell { +public class Whirlwind extends SpellRay { public Whirlwind(){ - super(Tier.APPRENTICE, 10, Element.EARTH, "whirlwind", SpellType.DEFENCE, 15, EnumAction.NONE, false); + super("whirlwind", Tier.APPRENTICE, Element.EARTH, SpellType.DEFENCE, 10, 15, false, 10, WizardrySounds.SPELL_ICE); + this.soundValues(0.8f, 0.7f, 0.2f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + // Left as EntityLivingBase because why not be able to move armour stands around? - if(rayTrace != null && rayTrace.entityHit instanceof EntityLivingBase){ - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; + if(target instanceof EntityLivingBase){ if(!world.isRemote){ @@ -48,66 +41,31 @@ public class Whirlwind extends Spell { if(world.isRemote){ for(int i = 0; i < 10; i++){ - double x2 = (double)(caster.posX + world.rand.nextFloat() - 0.5F + double x = (double)(caster.posX + world.rand.nextFloat() - 0.5F + caster.getLookVec().x * caster.getDistance(target) * 0.5); - double y2 = (double)(WizardryUtilities.getPlayerEyesPos(caster) + world.rand.nextFloat() - 0.5F + double y = (double)(caster.getEntityBoundingBox().minY + caster.getEyeHeight() + world.rand.nextFloat() - 0.5F + caster.getLookVec().y * caster.getDistance(target) * 0.5); - double z2 = (double)(caster.posZ + world.rand.nextFloat() - 0.5F + double z = (double)(caster.posZ + world.rand.nextFloat() - 0.5F + caster.getLookVec().z * caster.getDistance(target) * 0.5); - world.spawnParticle(EnumParticleTypes.CLOUD, x2, y2, z2, caster.getLookVec().x, + world.spawnParticle(EnumParticleTypes.CLOUD, x, y, z, caster.getLookVec().x, caster.getLookVec().y, caster.getLookVec().z); - // Minecraft.getMinecraft().effectRenderer.addEffect(new EntitySparkleFX(world, x2, y2, z2, - // entityplayer.getLookVec().xCoord, entityplayer.getLookVec().yCoord, - // entityplayer.getLookVec().zCoord, null, 1.0f, 1.0f, 0.8f, 10)); } } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_ICE, 0.8F, - world.rand.nextFloat() * 0.2F + 0.6F); + return true; } + return false; } @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - - if(!world.isRemote){ - target.motionX = caster.getLookVec().x * 2; - target.motionY = caster.getLookVec().y * 2 + 1; - target.motionZ = caster.getLookVec().z * 2; - - // Player motion is handled on that player's client so needs packets - if(target instanceof EntityPlayerMP){ - ((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target)); - } - } - if(world.isRemote){ - for(int i = 0; i < 10; i++){ - double x2 = (double)(caster.posX + world.rand.nextFloat() - 0.5F - + caster.getLookVec().x * caster.getDistance(target) * 0.5); - double y2 = (double)(caster.posY + caster.getEyeHeight() + world.rand.nextFloat() - 0.5F - + caster.getLookVec().y * caster.getDistance(target) * 0.5); - double z2 = (double)(caster.posZ + world.rand.nextFloat() - 0.5F - + caster.getLookVec().z * caster.getDistance(target) * 0.5); - world.spawnParticle(EnumParticleTypes.CLOUD, x2, y2, z2, caster.getLookVec().x, - caster.getLookVec().y, caster.getLookVec().z); - } - } - caster.swingArm(hand); - caster.playSound(WizardrySounds.SPELL_ICE, 0.8F, world.rand.nextFloat() * 0.2F + 0.6F); - return true; - } - + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return false; } @Override - public boolean canBeCastByNPCs(){ - return true; + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; } } diff --git a/src/main/java/electroblob/wizardry/spell/Wither.java b/src/main/java/electroblob/wizardry/spell/Wither.java index 9234756d..bd356785 100644 --- a/src/main/java/electroblob/wizardry/spell/Wither.java +++ b/src/main/java/electroblob/wizardry/spell/Wither.java @@ -1,45 +1,38 @@ package electroblob.wizardry.spell; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.SpellType; import electroblob.wizardry.constants.Tier; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.MagicDamage; import electroblob.wizardry.util.MagicDamage.DamageType; -import electroblob.wizardry.util.SpellModifiers; +import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; +import electroblob.wizardry.util.SpellModifiers; import electroblob.wizardry.util.WizardryUtilities; -import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; import net.minecraft.init.SoundEvents; -import net.minecraft.item.EnumAction; import net.minecraft.potion.PotionEffect; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; -public class Wither extends Spell { +public class Wither extends SpellRay { + + private static final int BASE_DURATION = 200; public Wither(){ - super(Tier.APPRENTICE, 10, Element.NECROMANCY, "wither", SpellType.ATTACK, 20, EnumAction.NONE, false); + super("wither", Tier.APPRENTICE, Element.NECROMANCY, SpellType.ATTACK, 10, 20, false, 10, SoundEvents.ENTITY_WITHER_HURT); + this.soundValues(1, 1.1f, 0.2f); } @Override - public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){ - - Vec3d look = caster.getLookVec(); - - RayTraceResult rayTrace = WizardryUtilities.standardEntityRayTrace(world, caster, - 10 * modifiers.get(WizardryItems.range_upgrade)); - - if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){ - - EntityLivingBase target = (EntityLivingBase)rayTrace.entityHit; + protected boolean onEntityHit(World world, Entity target, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + + if(WizardryUtilities.isLiving(target)){ // Has no effect on withers or wither skeletons. if(MagicDamage.isEntityImmune(DamageType.WITHER, target)){ @@ -47,79 +40,31 @@ public class Wither extends Spell { this.getNameForTranslationFormatted())); }else{ target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.WITHER), - 1.0f * modifiers.get(SpellModifiers.DAMAGE)); - target.addPotionEffect(new PotionEffect(MobEffects.WITHER, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), 1)); + 1.0f * modifiers.get(SpellModifiers.POTENCY)); + ((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.WITHER, + (int)(BASE_DURATION * modifiers.get(WizardryItems.duration_upgrade)), 1)); } - } - if(world.isRemote){ - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - // I figured it out! when on client side, entityplayer.posY is at the eyes, not the feet! - // This is a test for lining up the ray with the wand tip. Not sure if I like it or not. - /* Vec3d origin = Wizardry.proxy.getWandTipPosition(caster); double x1 = origin.xCoord + look.xCoord*i/2 - * + world.rand.nextFloat()/5 - 0.1f; double y1 = origin.yCoord + look.yCoord*i/2 + - * world.rand.nextFloat()/5 - 0.1f; double z1 = origin.zCoord + look.zCoord*i/2 + - * world.rand.nextFloat()/5 - 0.1f; */ - double x1 = caster.posX + look.x * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = WizardryUtilities.getPlayerEyesPos(caster) - 0.4f + look.y * i / 2 - + world.rand.nextFloat() / 5 - 0.1f; - double z1 = caster.posZ + look.z * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - // world.spawnParticle("mobSpell", x1, y1, z1, -1*look.xCoord, -1*look.yCoord, -1*look.zCoord); - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, 0, - 0.1f, 0.0f, 0.0f); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 0.1f, 0.0f, 0.05f); - } - } - caster.swingArm(hand); - WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_WITHER_HURT, 1.0F, - world.rand.nextFloat() * 0.2F + 1.0F); - return true; - } - - @Override - public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, - SpellModifiers modifiers){ - - if(target != null){ - // Has no effect on withers or wither skeletons. - if(!MagicDamage.isEntityImmune(DamageType.WITHER, target) && !world.isRemote){ - target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.WITHER), - 1.0f * modifiers.get(SpellModifiers.DAMAGE)); - target.addPotionEffect(new PotionEffect(MobEffects.WITHER, - (int)(200 * modifiers.get(WizardryItems.duration_upgrade)), 1)); - } - - if(world.isRemote){ - - double dx = (target.posX - caster.posX) / caster.getDistance(target); - double dy = (target.posY - caster.posY) / caster.getDistance(target); - double dz = (target.posZ - caster.posZ) / caster.getDistance(target); - - for(int i = 1; i < (int)(25 * modifiers.get(WizardryItems.range_upgrade)); i += 2){ - - double x1 = caster.posX + dx * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - double y1 = caster.posY + caster.getEyeHeight() - 0.4f + dy * i / 2 + world.rand.nextFloat() / 5 - - 0.1f; - double z1 = caster.posZ + dz * i / 2 + world.rand.nextFloat() / 5 - 0.1f; - - Wizardry.proxy.spawnParticle(Type.DARK_MAGIC, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 0, 0.1f, 0.0f, 0.0f); - Wizardry.proxy.spawnParticle(Type.SPARKLE, world, x1, y1, z1, 0.0d, 0.0d, 0.0d, - 12 + world.rand.nextInt(8), 0.1f, 0.0f, 0.05f); - } - } - caster.swingArm(hand); - caster.playSound(SoundEvents.ENTITY_WITHER_HURT, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F); + return true; } - + return false; } @Override - public boolean canBeCastByNPCs(){ + protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ + return false; + } + + @Override + protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){ return true; } + + @Override + protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){ + ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0, 0).spawn(world); + ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(0.1f, 0, 0.05f).spawn(world); + } } diff --git a/src/main/java/electroblob/wizardry/spell/WitherSkull.java b/src/main/java/electroblob/wizardry/spell/WitherSkull.java index b6bd4549..85a8b363 100644 --- a/src/main/java/electroblob/wizardry/spell/WitherSkull.java +++ b/src/main/java/electroblob/wizardry/spell/WitherSkull.java @@ -18,7 +18,7 @@ import net.minecraft.world.World; public class WitherSkull extends Spell { public WitherSkull(){ - super(Tier.ADVANCED, 20, Element.NECROMANCY, "wither_skull", SpellType.ATTACK, 30, EnumAction.NONE, false); + super("wither_skull", Tier.ADVANCED, Element.NECROMANCY, SpellType.ATTACK, 20, 30, EnumAction.NONE, false); } @Override diff --git a/src/main/java/electroblob/wizardry/util/ParticleBuilder.java b/src/main/java/electroblob/wizardry/util/ParticleBuilder.java index c09fe325..0b7e7c10 100644 --- a/src/main/java/electroblob/wizardry/util/ParticleBuilder.java +++ b/src/main/java/electroblob/wizardry/util/ParticleBuilder.java @@ -4,6 +4,7 @@ import java.util.Random; import electroblob.wizardry.Wizardry; import net.minecraft.entity.Entity; +import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; @@ -375,4 +376,21 @@ public final class ParticleBuilder { entity = null; } + // Methods for spawning specific effects (similar to the FX playing methods with the ids in RenderGlobal) + + /** Spawns spark and large smoke particles (8 of each) within a 1x1x1 volume centred on the given position. */ + public static void spawnShockParticles(World world, double x, double y, double z) { + double px, py, pz; + for(int i=0; i<8; i++){ + px = x + world.rand.nextDouble() - 0.5; + py = y + world.rand.nextDouble() - 0.5; + pz = z + world.rand.nextDouble() - 0.5; + ParticleBuilder.create(Type.SPARK).pos(px, py, pz).spawn(world); + px = x + world.rand.nextDouble() - 0.5; + py = y + world.rand.nextDouble() - 0.5; + pz = z + world.rand.nextDouble() - 0.5; + world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, px, py, pz, 0, 0, 0); + } + } + } diff --git a/src/main/java/electroblob/wizardry/util/SpellModifiers.java b/src/main/java/electroblob/wizardry/util/SpellModifiers.java index bbb7c08c..59155a29 100644 --- a/src/main/java/electroblob/wizardry/util/SpellModifiers.java +++ b/src/main/java/electroblob/wizardry/util/SpellModifiers.java @@ -40,8 +40,8 @@ import net.minecraftforge.fml.common.network.ByteBufUtils; // fly. public final class SpellModifiers { - /** Constant string identifier for the damage modifier. All the other modifiers in Wizardry have items. */ - public static final String DAMAGE = "damage"; + /** Constant string identifier for the potency modifier. All the other modifiers in Wizardry have items. */ + public static final String POTENCY = "potency"; private Map multiplierMap; private Map syncedMultiplierMap; diff --git a/src/main/java/electroblob/wizardry/util/WizardryUtilities.java b/src/main/java/electroblob/wizardry/util/WizardryUtilities.java index 1e15ef13..6fc8622d 100644 --- a/src/main/java/electroblob/wizardry/util/WizardryUtilities.java +++ b/src/main/java/electroblob/wizardry/util/WizardryUtilities.java @@ -53,6 +53,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.ReflectionHelper; import net.minecraftforge.fml.relauncher.Side; @@ -238,15 +239,15 @@ public final class WizardryUtilities { } /** - * Gets a random position on the ground near the player within the specified horizontal and vertical ranges. Used to - * find a position to spawn entities in summoning spells. + * Gets a random position on the ground near the given entity within the specified horizontal and vertical ranges. + * Used to find a position to spawn entities in summoning spells. * - * @param entity The entity around which to search + * @param entity The entity around which to search. * @param horizontalRange The maximum number of blocks on the x or z axis the returned position can be from the * given entity. The number of operations performed by this method is proportional to the square of this * parameter, so for performance reasons it is recommended that it does not exceed around 10. * @param verticalRange The maximum number of blocks on the y axis the returned position can be from the given - * entity + * entity. * @return A BlockPos with the coordinates of the block directly above the ground at the position found, or null if * none were found within range. Importantly, since this method checks all possible positions within * range (i.e. randomness only occurs when deciding between the possible positions), if it returns null once @@ -257,8 +258,31 @@ public final class WizardryUtilities { public static BlockPos findNearbyFloorSpace(Entity entity, int horizontalRange, int verticalRange){ World world = entity.world; - List possibleLocations = new ArrayList(); BlockPos origin = new BlockPos(entity); + return findNearbyFloorSpace(world, origin, horizontalRange, verticalRange); + } + + /** + * Gets a random position on the ground near the given BlockPos within the specified horizontal and vertical ranges. + * Used to find a position to spawn entities in summoning spells. + * + * @param world The world in which to search. + * @param origin The BlockPos around which to search. + * @param horizontalRange The maximum number of blocks on the x or z axis the returned position can be from the + * given position. The number of operations performed by this method is proportional to the square of this + * parameter, so for performance reasons it is recommended that it does not exceed around 10. + * @param verticalRange The maximum number of blocks on the y axis the returned position can be from the given + * position. + * @return A BlockPos with the coordinates of the block directly above the ground at the position found, or null if + * none were found within range. Importantly, since this method checks all possible positions within + * range (i.e. randomness only occurs when deciding between the possible positions), if it returns null once + * then it will always return null given the same circumstances and parameters. What this means is that you + * can (and should) immediately stop trying to cast a summoning spell if this returns null. + */ + @Nullable + public static BlockPos findNearbyFloorSpace(World world, BlockPos origin, int horizontalRange, int verticalRange){ + + List possibleLocations = new ArrayList(); for(int x = -horizontalRange; x <= horizontalRange; x++){ for(int z = -horizontalRange; z <= horizontalRange; z++){ @@ -272,7 +296,6 @@ public final class WizardryUtilities { }else{ return possibleLocations.get(world.rand.nextInt(possibleLocations.size())); } - } /** @@ -424,23 +447,6 @@ public final class WizardryUtilities { target.knockBack(null, 0.4f, dx, dz); } - // Just what benefit does having posY be the eye position on the first person client actually give? - - /** - * Gets the y coordinate of the given player's eyes. This is to cover an inconsistency between the value of - * EntityPlayer.posY on the first person client and everywhere else; in first person (i.e. when - * Minecraft.getMinecraft().player == player) player.posY is the eye position, but everywhere else it is the feet - * position. This is intended for use when spawning particles, since this is the only situation where the - * discrepancy is likely to matter. - *

- * As of Wizardry 1.2, this is just a shorthand for: - *

- *

player.getEntityBoundingBox().minY + player.getEyeHeight()
- */ - public static double getPlayerEyesPos(EntityPlayer player){ - return player.getEntityBoundingBox().minY + player.getEyeHeight(); - } - /** * Returns a list of the itemstacks in the given player's hotbar. Defined here for convenience and to centralise the * (unfortunately unavoidable) use of hardcoded numbers to reference the inventory slots. The returned list is a @@ -509,6 +515,17 @@ public final class WizardryUtilities { public static boolean isPlayerOp(EntityPlayer player, MinecraftServer server){ return server.getPlayerList().getOppedPlayers().getEntry(player.getGameProfile()) != null; } + + /** Returns the default aiming arror used by skeletons for the given difficulty. For reference, these are: Easy - 10, + * Normal - 6, Hard - 2, Peaceful - 10 (rarely used). */ + public static int getDefaultAimingError(EnumDifficulty difficulty){ + switch(difficulty){ + case EASY: return 10; + case NORMAL: return 6; + case HARD: return 2; + default: return 10; // Peaceful counts as easy; the only time this is used is when a player attacks a (good) wizard. + } + } /** * Returns true if the given entity is an EntityLivingBase and not an armour stand; makes the code a bit neater. @@ -539,7 +556,7 @@ public final class WizardryUtilities { * Does a block ray trace (NOT entities) from an entity's eyes (i.e. properly...) */ @Nullable - public static RayTraceResult rayTrace(double range, World world, EntityLivingBase entity, boolean hitLiquids){ + public static RayTraceResult standardBlockRayTrace(World world, EntityLivingBase entity, double range, boolean hitLiquids){ Vec3d start = new Vec3d(entity.posX, entity.getEntityBoundingBox().minY + entity.getEyeHeight(), entity.posZ); Vec3d look = entity.getLookVec(); @@ -557,16 +574,8 @@ public final class WizardryUtilities { * @return */ @Nullable - public static RayTraceResult standardEntityRayTrace(World world, EntityLivingBase entity, double range){ - double dx = entity.getLookVec().x * range; - double dy = entity.getLookVec().y * range; - double dz = entity.getLookVec().z * range; - HashSet hashset = new HashSet(1); - hashset.add(entity); - return WizardryUtilities.tracePath(world, (float)entity.posX, - (float)(entity.getEntityBoundingBox().minY + entity.getEyeHeight()), (float)entity.posZ, - (float)(entity.posX + dx), (float)(entity.posY + entity.getEyeHeight() + dy), (float)(entity.posZ + dz), - 1.0f, hashset, false); + public static RayTraceResult standardEntityRayTrace(World world, EntityLivingBase entity, double range, boolean hitLiquids){ + return standardEntityRayTrace(world, entity, range, 1, hitLiquids); } /** @@ -580,8 +589,7 @@ public final class WizardryUtilities { * @return */ @Nullable - public static RayTraceResult standardEntityRayTrace(World world, EntityLivingBase entity, double range, - float borderSize){ + public static RayTraceResult standardEntityRayTrace(World world, EntityLivingBase entity, double range, float borderSize, boolean hitLiquids){ double dx = entity.getLookVec().x * range; double dy = entity.getLookVec().y * range; double dz = entity.getLookVec().z * range; @@ -590,12 +598,11 @@ public final class WizardryUtilities { return WizardryUtilities.tracePath(world, (float)entity.posX, (float)(entity.getEntityBoundingBox().minY + entity.getEyeHeight()), (float)entity.posZ, (float)(entity.posX + dx), (float)(entity.posY + entity.getEyeHeight() + dy), (float)(entity.posZ + dz), - borderSize, hashset, false); + borderSize, hashset, false, hitLiquids); } /** - * Method for ray tracing entities (the useless default method doesn't work, despite EnumHitType having an ENTITY - * field...) You can also use this for seeking. + * Method for ray tracing entities. You can also use this for seeking. * * @param world * @param x startX @@ -611,7 +618,7 @@ public final class WizardryUtilities { */ @Nullable public static RayTraceResult tracePath(World world, float x, float y, float z, float tx, float ty, float tz, - float borderSize, HashSet excluded, boolean collideablesOnly){ + float borderSize, HashSet excluded, boolean collideablesOnly, boolean hitLiquids){ Vec3d startVec = new Vec3d(x, y, z); // Vec3d lookVec = new Vec3d(tx-x, ty-y, tz-z); @@ -622,10 +629,9 @@ public final class WizardryUtilities { float maxX = x > tx ? x : tx; float maxY = y > ty ? y : ty; float maxZ = z > tz ? z : tz; - AxisAlignedBB bb = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).grow(borderSize, borderSize, - borderSize); + AxisAlignedBB bb = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).grow(borderSize, borderSize, borderSize); List allEntities = world.getEntitiesWithinAABBExcludingEntity(null, bb); - RayTraceResult blockHit = world.rayTraceBlocks(startVec, endVec); + RayTraceResult blockHit = world.rayTraceBlocks(startVec, endVec, hitLiquids); startVec = new Vec3d(x, y, z); endVec = new Vec3d(tx, ty, tz); float maxDistance = (float)endVec.distanceTo(startVec);