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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<EntityLivingBase> {
|
||||
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);
|
||||
|
||||
@@ -44,7 +44,7 @@ public class RenderDecay extends Render<EntityDecay> {
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<EntityPlayer> 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<EntityPlayer> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(1.0d, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
List<EntityLivingBase> 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;
|
||||
}
|
||||
|
||||
@@ -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<EntityLivingBase> 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<EntityLivingBase> 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(2.5d, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
List<EntityLivingBase> 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;
|
||||
}
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<EntityLivingBase>(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<EntityLivingBase>(caster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand for {@link WizardryUtilities#isValidTarget(Entity, Entity)}, with the owner of this construct as the
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<EntityLivingBase>(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<? extends EntityLivingBase> entityType){
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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(){
|
||||
|
||||
@@ -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<EntityLivingBase> getCasterReference(){ return casterReference; }
|
||||
@Override public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase> getCasterReference(){
|
||||
return casterReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase>(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<? extends EntityLivingBase> entityType){
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<EntityLivingBase> getCasterReference(){
|
||||
return casterReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase> getCasterReference(){ return casterReference; }
|
||||
@Override public void setCasterReference(WeakReference<EntityLivingBase> 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; }
|
||||
|
||||
}
|
||||
|
||||
@@ -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<EntityPhoenix> spellAttackAI = new EntityAIAttackSpell<EntityPhoenix>(this, AISpeed, 15f, 60, 140);
|
||||
private EntityAIAttackSpell<EntityPhoenix> spellAttackAI = new EntityAIAttackSpell<>(this, AISpeed, 15f, 60, 140);
|
||||
|
||||
private Spell continuousSpell;
|
||||
|
||||
private static final List<Spell> 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(){
|
||||
|
||||
@@ -35,12 +35,9 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
|
||||
|
||||
private static final List<Spell> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<EntityLivingBase> getCasterReference(){ return casterReference; }
|
||||
@Override public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase> getCasterReference(){
|
||||
return casterReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase>(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<? extends EntityLivingBase> entityType){
|
||||
|
||||
@@ -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<EntityLivingBase> getCasterReference(){ return casterReference; }
|
||||
@Override public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase> getCasterReference(){
|
||||
return casterReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase>(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<? extends EntityLivingBase> 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
|
||||
|
||||
@@ -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<EntityLivingBase> getCasterReference(){ return casterReference; }
|
||||
@Override public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase> getCasterReference(){
|
||||
return casterReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase>(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<? extends EntityLivingBase> entityType){
|
||||
|
||||
@@ -33,13 +33,11 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe
|
||||
|
||||
private static final List<Spell> 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<EntityLivingBase>(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<? extends EntityLivingBase> 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){
|
||||
|
||||
@@ -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<EntityLivingBase> getCasterReference(){ return casterReference; }
|
||||
@Override public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase> getCasterReference(){
|
||||
return casterReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCasterReference(WeakReference<EntityLivingBase> 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<EntityLivingBase>(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<? extends EntityLivingBase> 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
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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<EntityLivingBase>(caster);
|
||||
this.experienceValue = 0;
|
||||
this.lifetime = lifetime;
|
||||
}
|
||||
|
||||
// EntityZombie overrides (EntityZombie is a long class so there are lots of these)
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. <i>This is the correct method to use to set the owner of
|
||||
* this summoned creature.
|
||||
*/
|
||||
default void setCaster(@Nullable EntityLivingBase caster){
|
||||
setCasterReference(new WeakReference<EntityLivingBase>(caster));
|
||||
}
|
||||
|
||||
// Miscellaneous
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(){}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(){}
|
||||
|
||||
}
|
||||
@@ -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(){}
|
||||
|
||||
}
|
||||
@@ -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(){}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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<EntityLivingBase> shootingEntity;
|
||||
private WeakReference<EntityLivingBase> 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<EntityLivingBase>(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. <b>Use this
|
||||
* constructor for normal, player-cast spells.
|
||||
*/
|
||||
public EntityMagicArrow(World world, EntityLivingBase caster, float speed, float damageMultiplier){
|
||||
super(world);
|
||||
this.shootingEntity = new WeakReference<EntityLivingBase>(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<EntityLivingBase>(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>((EntityLivingBase)entity);
|
||||
this.caster = new WeakReference<EntityLivingBase>((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>(
|
||||
(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>(
|
||||
(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<EntityLivingBase>(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void entityInit() {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
protected void entityInit(){}
|
||||
}
|
||||
@@ -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(){ }
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
* <p>
|
||||
* 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<Entity> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)){
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<Entity> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Spell> 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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<EntityArrowRain> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<EntityLivingBase> secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange,
|
||||
List<EntityLivingBase> 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<EntityLivingBase> 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<EntityLivingBase> 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<EntityDecay> {
|
||||
|
||||
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<quantity; i++){
|
||||
BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, horizontalRange, verticalRange);
|
||||
if(pos == null) break;
|
||||
super.spawnConstruct(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, caster, modifiers);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@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)(int)target.getEntityBoundingBox().minY;
|
||||
int z = MathHelper.floor(target.posZ);
|
||||
|
||||
if(world.getBlockState(new BlockPos(x, y, z)).isNormalCube()) return false;
|
||||
|
||||
if(!world.isRemote){
|
||||
|
||||
world.spawnEntity(new EntityDecay(world, x + 0.5, y + 1, z + 0.5, caster));
|
||||
|
||||
for(int i = 0; i < 5; i++){
|
||||
BlockPos pos = WizardryUtilities.findNearbyFloorSpace(caster, 2, 6);
|
||||
if(pos == null) break;
|
||||
world.spawnEntity(new EntityDecay(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, caster));
|
||||
}
|
||||
}
|
||||
|
||||
caster.playSound(SoundEvents.ENTITY_WITHER_SHOOT, 1.0F, world.rand.nextFloat() * 0.2F + 1.0F);
|
||||
caster.swingArm(hand);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeCastByNPCs(){
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,71 +17,55 @@ import net.minecraft.world.World;
|
||||
public class Decoy extends Spell {
|
||||
|
||||
public Decoy(){
|
||||
super(Tier.ADVANCED, 40, Element.SORCERY, "decoy", SpellType.UTILITY, 200, EnumAction.BOW, false);
|
||||
super("decoy", Tier.ADVANCED, Element.SORCERY, SpellType.UTILITY, 40, 200, EnumAction.BOW, false);
|
||||
}
|
||||
|
||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
||||
|
||||
@Override
|
||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||
// Determines whether the caster moves left and the decoy moves right, or vice versa.
|
||||
// Uses the synchronised entity id to ensure it is consistent on client and server, but not always the same.
|
||||
double splitSpeed = caster.getEntityId() % 2 == 0 ? 0.3 : -0.3;
|
||||
|
||||
if(!world.isRemote){
|
||||
EntityDecoy decoy = new EntityDecoy(world, caster.posX, caster.posY, caster.posZ, caster, 600);
|
||||
decoy.setLocationAndAngles(caster.posX, caster.posY, caster.posZ, caster.rotationYaw, caster.rotationPitch);
|
||||
decoy.addVelocity(-caster.getLookVec().z * splitSpeed, 0, caster.getLookVec().x * splitSpeed);
|
||||
// Ignores the show names setting, since this would allow a player to easily detect a decoy
|
||||
decoy.setCustomNameTag(caster.getName());
|
||||
world.spawnEntity(decoy);
|
||||
|
||||
// Tricks any mobs that are targeting the caster into targeting the decoy instead.
|
||||
for(EntityLiving creature : WizardryUtilities.getEntitiesWithinRadius(16, caster.posX, caster.posY,
|
||||
caster.posZ, world, EntityLiving.class)){
|
||||
// More likely to trick mobs the higher the damage multiplier. Starts off at 50%.
|
||||
if(world.rand.nextInt((int)(6 * modifiers.get(SpellModifiers.DAMAGE))) < 3){
|
||||
if(creature.getAttackTarget() == caster) creature.setAttackTarget(decoy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
caster.addVelocity(caster.getLookVec().z * splitSpeed, 0, -caster.getLookVec().x * splitSpeed);
|
||||
|
||||
WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0F,
|
||||
0.4F / (world.rand.nextFloat() * 0.4F + 0.8F));
|
||||
spawnDecoy(world, caster, modifiers, splitSpeed);
|
||||
WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_CONJURATION, 1.0F, 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){
|
||||
|
||||
public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){
|
||||
// Determines whether the caster moves left and the decoy moves right, or vice versa.
|
||||
double splitSpeed = world.rand.nextBoolean() ? 0.3 : -0.3;
|
||||
|
||||
if(!world.isRemote){
|
||||
EntityDecoy decoy = new EntityDecoy(world, caster.posX, caster.posY, caster.posZ, caster, 600);
|
||||
decoy.setLocationAndAngles(caster.posX, caster.posY, caster.posZ, caster.rotationYaw, caster.rotationPitch);
|
||||
decoy.addVelocity(-caster.getLookVec().z * splitSpeed, 0, caster.getLookVec().x * splitSpeed);
|
||||
world.spawnEntity(decoy);
|
||||
|
||||
// Tricks any mobs that are targeting the caster into targeting the decoy instead.
|
||||
for(EntityLiving creature : WizardryUtilities.getEntitiesWithinRadius(16, caster.posX, caster.posY,
|
||||
caster.posZ, world, EntityLiving.class)){
|
||||
// More likely to trick mobs the higher the damage multiplier. Starts off at 50%.
|
||||
if(world.rand.nextInt((int)(6 * modifiers.get(SpellModifiers.DAMAGE))) < 3){
|
||||
if(creature.getAttackTarget() == caster) creature.setAttackTarget(decoy);
|
||||
}
|
||||
}
|
||||
}
|
||||
caster.addVelocity(caster.getLookVec().z * splitSpeed, 0, -caster.getLookVec().x * splitSpeed);
|
||||
|
||||
spawnDecoy(world, caster, modifiers, splitSpeed);
|
||||
caster.playSound(WizardrySounds.SPELL_CONJURATION, 1.0F, 0.4F / (world.rand.nextFloat() * 0.4F + 0.8F));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void spawnDecoy(World world, EntityLivingBase caster, SpellModifiers modifiers, double splitSpeed){
|
||||
|
||||
@Override
|
||||
public boolean canBeCastByNPCs(){
|
||||
return true;
|
||||
if(!world.isRemote){
|
||||
EntityDecoy decoy = new EntityDecoy(world);
|
||||
decoy.setCaster(caster);
|
||||
decoy.setLifetime(600);
|
||||
decoy.setLocationAndAngles(caster.posX, caster.posY, caster.posZ, caster.rotationYaw, caster.rotationPitch);
|
||||
decoy.addVelocity(-caster.getLookVec().z * splitSpeed, 0, caster.getLookVec().x * splitSpeed);
|
||||
// Ignores the show names setting, since this would allow a player to easily detect a decoy
|
||||
// Instead, a decoy player has its caster's name tag shown permanently and non-player decoys have nothing
|
||||
if(caster instanceof EntityPlayer) decoy.setCustomNameTag(caster.getName());
|
||||
world.spawnEntity(decoy);
|
||||
|
||||
// Tricks any mobs that are targeting the caster into targeting the decoy instead.
|
||||
for(EntityLiving creature : WizardryUtilities.getEntitiesWithinRadius(16, caster.posX, caster.posY,
|
||||
caster.posZ, world, EntityLiving.class)){
|
||||
// More likely to trick mobs the higher the damage multiplier. Starts off at 50%.
|
||||
if(world.rand.nextInt((int)(6 * modifiers.get(SpellModifiers.POTENCY))) < 3){
|
||||
if(creature.getAttackTarget() == caster) creature.setAttackTarget(decoy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
caster.addVelocity(caster.getLookVec().z * splitSpeed, 0, -caster.getLookVec().x * splitSpeed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,115 +10,59 @@ 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.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.SoundCategory;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class Detonate extends Spell {
|
||||
public class Detonate extends SpellRay {
|
||||
|
||||
private static final double BASE_RADIUS = 3;
|
||||
|
||||
public Detonate(){
|
||||
super(Tier.ADVANCED, 45, Element.FIRE, "detonate", SpellType.ATTACK, 50, EnumAction.NONE, false);
|
||||
super("detonate", Tier.ADVANCED, Element.FIRE, SpellType.ATTACK, 45, 50, false, 16, SoundEvents.ENTITY_GENERIC_EXPLODE);
|
||||
this.soundValues(4, 0.7f, 0.14f);
|
||||
this.ignoreEntities(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||
|
||||
RayTraceResult rayTrace = WizardryUtilities.rayTrace(16 * modifiers.get(WizardryItems.range_upgrade), world,
|
||||
caster, false);
|
||||
|
||||
if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){
|
||||
if(!world.isRemote){
|
||||
List<EntityLivingBase> 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<EntityLivingBase> 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<EntityLivingBase> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<EntityEarthquake> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user