That's one heck of a commit you've got there...
I may have got a bit behind with version control. A lot behind, in fact. Maybe I'll go back and split this sometime - then again, I probably won't. But hey, at least it's here!
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
@@ -7,7 +10,6 @@ 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;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
@@ -24,16 +26,19 @@ public class EntityDarknessOrb extends EntityMagicProjectile {
|
||||
Entity target = rayTrace.entityHit;
|
||||
|
||||
if(target != null && !MagicDamage.isEntityImmune(DamageType.WITHER, target)){
|
||||
float damage = 8 * damageMultiplier;
|
||||
|
||||
float damage = Spells.darkness_orb.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
target.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.WITHER).setProjectile(),
|
||||
damage);
|
||||
|
||||
if(target instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.WITHER, target))
|
||||
((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.WITHER, 150, 1));
|
||||
((EntityLivingBase)target).addPotionEffect(new PotionEffect(MobEffects.WITHER,
|
||||
Spells.darkness_orb.getProperty(Spell.EFFECT_DURATION).intValue(),
|
||||
Spells.darkness_orb.getProperty(Spell.EFFECT_STRENGTH).intValue()));
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_WITHER_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
this.playSound(WizardrySounds.ENTITY_DARKNESS_ORB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
@@ -53,10 +58,6 @@ public class EntityDarknessOrb extends EntityMagicProjectile {
|
||||
ParticleBuilder.create(Type.DARK_MAGIC, this).clr(0.1f, 0.0f, 0.0f).spawn(world);
|
||||
}
|
||||
|
||||
if(this.ticksExisted > 150){
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
// Cancels out the slowdown effect in EntityThrowable
|
||||
this.motionX /= 0.99;
|
||||
this.motionY /= 0.99;
|
||||
@@ -67,4 +68,9 @@ public class EntityDarknessOrb extends EntityMagicProjectile {
|
||||
public boolean hasNoGravity(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return 60;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityDart extends EntityMagicArrow {
|
||||
@@ -15,7 +18,7 @@ public class EntityDart extends EntityMagicArrow {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override public double getDamage(){ return 4; }
|
||||
@Override public double getDamage(){ return Spells.dart.getProperty(Spell.DAMAGE).doubleValue(); }
|
||||
|
||||
@Override public boolean doGravity(){ return true; }
|
||||
|
||||
@@ -24,13 +27,14 @@ public class EntityDart extends EntityMagicArrow {
|
||||
@Override
|
||||
public void onEntityHit(EntityLivingBase entityHit){
|
||||
// Adds a weakness effect to the target.
|
||||
entityHit.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, 200, 1, false, false));
|
||||
this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
entityHit.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, Spells.dart.getProperty(Spell.EFFECT_DURATION).intValue(),
|
||||
Spells.dart.getProperty(Spell.EFFECT_STRENGTH).intValue(), false, false));
|
||||
this.playSound(WizardrySounds.ENTITY_DART_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockHit(){
|
||||
this.playSound(SoundEvents.ENTITY_ARROW_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
public void onBlockHit(RayTraceResult hit){
|
||||
this.playSound(WizardrySounds.ENTITY_DART_HIT_BLOCK, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,4 +55,8 @@ public class EntityDart extends EntityMagicArrow {
|
||||
@Override
|
||||
protected void entityInit(){}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.Disintegration;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityEmber extends EntityMagicProjectile {
|
||||
|
||||
private int extraLifetime;
|
||||
|
||||
public EntityEmber(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
public EntityEmber(World world, EntityLivingBase caster){
|
||||
super(world);
|
||||
this.thrower = caster;
|
||||
extraLifetime = rand.nextInt(30);
|
||||
this.setSize(0.1f, 0.1f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getCollisionBoundingBox(){
|
||||
return null;//this.getEntityBoundingBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return Spells.disintegration.getProperty(Disintegration.EMBER_LIFETIME).intValue() + extraLifetime;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult result){
|
||||
|
||||
if(result.entityHit != null){
|
||||
result.entityHit.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
|
||||
if(result.typeOfHit == RayTraceResult.Type.BLOCK){
|
||||
this.inGround = true;
|
||||
this.collided = true;
|
||||
if(result.sideHit.getAxis() == EnumFacing.Axis.X) motionX = 0;
|
||||
if(result.sideHit.getAxis() == EnumFacing.Axis.Y){
|
||||
motionY = 0;
|
||||
this.collidedVertically = true;
|
||||
}
|
||||
if(result.sideHit.getAxis() == EnumFacing.Axis.Z) motionZ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyEntityCollision(Entity entity){
|
||||
|
||||
super.applyEntityCollision(entity);
|
||||
|
||||
if(entity instanceof EntityLivingBase){
|
||||
entity.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(){
|
||||
|
||||
super.onUpdate();
|
||||
|
||||
if(this.collidedVertically){
|
||||
this.motionY += this.getGravityVelocity();
|
||||
this.motionX *= 0.5;
|
||||
this.motionZ *= 0.5;
|
||||
}
|
||||
|
||||
world.getEntitiesInAABBexcluding(thrower, this.getEntityBoundingBox(), e -> e instanceof EntityLivingBase)
|
||||
.forEach(e -> e.setFire(Spells.disintegration.getProperty(Spell.BURN_DURATION).intValue()));
|
||||
|
||||
// Copied from ParticleLava
|
||||
if(this.rand.nextFloat() > (float)this.ticksExisted / this.getLifetime()){
|
||||
this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, this.motionX, this.motionY, this.motionZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
@@ -16,19 +19,22 @@ public class EntityFirebolt extends EntityMagicProjectile {
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
float damage = 5 * damageMultiplier;
|
||||
|
||||
float damage = Spells.firebolt.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile(),
|
||||
damage);
|
||||
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit)) entityHit.setFire(5);
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit))
|
||||
entityHit.setFire(Spells.firebolt.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
|
||||
this.playSound(SoundEvents.BLOCK_LAVA_POP, 2, 0.8f + rand.nextFloat() * 0.3f);
|
||||
this.playSound(WizardrySounds.ENTITY_FIREBOLT_HIT, 2, 0.8f + rand.nextFloat() * 0.3f);
|
||||
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
@@ -47,16 +53,20 @@ public class EntityFirebolt extends EntityMagicProjectile {
|
||||
super.onUpdate();
|
||||
|
||||
if(world.isRemote){
|
||||
for(int i = 0; i < 4; i++){
|
||||
world.spawnParticle(EnumParticleTypes.FLAME, this.posX + rand.nextFloat() * 0.2 - 0.1,
|
||||
this.posY + this.height / 2 + rand.nextFloat() * 0.2 - 0.1,
|
||||
this.posZ + rand.nextFloat() * 0.2 - 0.1, 0, 0, 0);
|
||||
ParticleBuilder.create(ParticleBuilder.Type.MAGIC_FIRE, this).time(14).spawn(world);
|
||||
|
||||
if(this.ticksExisted > 1){ // Don't spawn particles behind where it started!
|
||||
double x = posX - motionX/2 + rand.nextFloat() * 0.2 - 0.1;
|
||||
double y = posY + this.height/2 - motionY/2 + rand.nextFloat() * 0.2 - 0.1;
|
||||
double z = posZ - motionZ/2 + rand.nextFloat() * 0.2 - 0.1;
|
||||
ParticleBuilder.create(ParticleBuilder.Type.MAGIC_FIRE).pos(x, y, z).time(14).spawn(world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(this.ticksExisted > 8){
|
||||
this.setDead();
|
||||
}
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
@@ -9,17 +10,23 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EntityFirebomb extends EntityBomb {
|
||||
|
||||
public EntityFirebomb(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
@@ -27,13 +34,14 @@ public class EntityFirebomb extends EntityBomb {
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the firebomb gets a direct hit
|
||||
float damage = 5 * damageMultiplier;
|
||||
float damage = Spells.firebomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile(),
|
||||
damage);
|
||||
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit)) entityHit.setFire(10);
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit))
|
||||
entityHit.setFire(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
|
||||
// Particle effect
|
||||
@@ -45,7 +53,7 @@ public class EntityFirebomb extends EntityBomb {
|
||||
for(int i = 0; i < 60 * blastMultiplier; i++){
|
||||
|
||||
ParticleBuilder.create(Type.MAGIC_FIRE, rand, posX, posY, posZ, 2*blastMultiplier, false)
|
||||
.time(15 + rand.nextInt(5)).scale(2 + rand.nextFloat()).spawn(world);
|
||||
.time(10 + rand.nextInt(4)).scale(2 + rand.nextFloat()).spawn(world);
|
||||
|
||||
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
|
||||
.clr(1.0f, 0.2f + rand.nextFloat() * 0.4f, 0.0f).spawn(world);
|
||||
@@ -56,10 +64,10 @@ public class EntityFirebomb extends EntityBomb {
|
||||
|
||||
if(!this.world.isRemote){
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
|
||||
this.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1);
|
||||
this.playSound(WizardrySounds.ENTITY_FIREBOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
|
||||
this.playSound(WizardrySounds.ENTITY_FIREBOMB_FIRE, 1, 1);
|
||||
|
||||
double range = 3.0d * blastMultiplier;
|
||||
double range = Spells.firebomb.getProperty(Spell.BLAST_RADIUS).floatValue() * blastMultiplier;
|
||||
|
||||
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(range, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
@@ -70,8 +78,8 @@ public class EntityFirebomb extends EntityBomb {
|
||||
// Splash damage does not count as projectile damage
|
||||
target.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE),
|
||||
4.0f * damageMultiplier);
|
||||
target.setFire(7);
|
||||
Spells.firebomb.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier);
|
||||
target.setFire(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +1,100 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.item.IManaStoringItem;
|
||||
import electroblob.wizardry.item.ISpellCastingItem;
|
||||
import electroblob.wizardry.item.ItemArtefact;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
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.EntityLivingBase;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class EntityForceArrow extends EntityMagicArrow {
|
||||
|
||||
/** The mana used to cast this force arrow, used for artefacts. */
|
||||
private int mana = 0;
|
||||
|
||||
/** Creates a new force arrow in the given world. */
|
||||
public EntityForceArrow(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
public void setMana(int mana){
|
||||
this.mana = mana;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityHit(EntityLivingBase entityHit){
|
||||
this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.0F, 1.0F);
|
||||
this.playSound(WizardrySounds.ENTITY_FORCE_ARROW_HIT, 1.0F, 1.0F);
|
||||
if(this.world.isRemote)
|
||||
ParticleBuilder.create(Type.FLASH).pos(posX, posY, posZ).scale(1.3f).clr(0.75f, 1, 0.85f).spawn(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickInGround(){
|
||||
returnManaToCaster();
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockHit(){
|
||||
this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.0F, 1.0F);
|
||||
public void onUpdate(){
|
||||
|
||||
if(getLifetime() >=0 && this.ticksExisted > getLifetime()){ // The last tick before it disappears
|
||||
returnManaToCaster();
|
||||
}
|
||||
|
||||
super.onUpdate();
|
||||
}
|
||||
|
||||
private void returnManaToCaster(){
|
||||
|
||||
if(mana > 0 && getCaster() instanceof EntityPlayer){
|
||||
|
||||
EntityPlayer player = (EntityPlayer)getCaster();
|
||||
|
||||
if(!player.capabilities.isCreativeMode && ItemArtefact.isArtefactActive(player, WizardryItems.ring_mana_return)){
|
||||
|
||||
for(ItemStack stack : WizardryUtilities.getPrioritisedHotbarAndOffhand(player)){
|
||||
if(stack.getItem() instanceof ISpellCastingItem && stack.getItem() instanceof IManaStoringItem
|
||||
&& Arrays.asList(((ISpellCastingItem)stack.getItem()).getSpells(stack)).contains(Spells.force_arrow)){
|
||||
((IManaStoringItem)stack.getItem()).rechargeMana(stack, mana);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockHit(RayTraceResult hit){
|
||||
this.playSound(WizardrySounds.ENTITY_FORCE_ARROW_HIT, 1.0F, 1.0F);
|
||||
if(this.world.isRemote){
|
||||
// Gets a position slightly away from the block hit so the particle doesn't get cut in half by the block face
|
||||
Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(0.15));
|
||||
ParticleBuilder.create(Type.FLASH).pos(vec).scale(1.3f).clr(0.75f, 1, 0.85f).spawn(world);
|
||||
vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET));
|
||||
ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0, 1, 0.5f).spawn(world);
|
||||
//vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET));
|
||||
//ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0, 1, 0.5f).spawn(world);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickInAir(){
|
||||
if(this.ticksExisted > 20){
|
||||
this.setDead();
|
||||
}
|
||||
public int getLifetime(){
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDamage(){
|
||||
return 7.0d;
|
||||
return Spells.force_arrow.getProperty(Spell.DAMAGE).floatValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,30 +1,37 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
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.EntityLivingBase;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EntityForceOrb extends EntityBomb {
|
||||
|
||||
public EntityForceOrb(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult par1RayTraceResult){
|
||||
|
||||
if(par1RayTraceResult.entityHit != null){
|
||||
// This is if the force orb gets a direct hit
|
||||
this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
this.playSound(WizardrySounds.ENTITY_FORCE_ORB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
}
|
||||
|
||||
// Particle effect
|
||||
@@ -41,10 +48,10 @@ public class EntityForceOrb extends EntityBomb {
|
||||
|
||||
// 2 gives a cool flanging effect!
|
||||
float pitch = this.rand.nextFloat() * 0.2F + 0.3F;
|
||||
this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.5F, pitch);
|
||||
this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.5F, pitch - 0.01f);
|
||||
this.playSound(WizardrySounds.ENTITY_FORCE_ORB_HIT_BLOCK, 1.5F, pitch);
|
||||
this.playSound(WizardrySounds.ENTITY_FORCE_ORB_HIT_BLOCK, 1.5F, pitch - 0.01f);
|
||||
|
||||
double blastRadius = 4.0d * blastMultiplier;
|
||||
double blastRadius = Spells.force_orb.getProperty(Spell.BLAST_RADIUS).floatValue() * blastMultiplier;
|
||||
|
||||
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(blastRadius, this.posX,
|
||||
this.posY, this.posZ, this.world);
|
||||
@@ -59,7 +66,7 @@ public class EntityForceOrb extends EntityBomb {
|
||||
double dz = this.posZ - target.posZ > 0 ? -0.5 - (this.posZ - target.posZ) / 8
|
||||
: 0.5 - (this.posZ - target.posZ) / 8;
|
||||
|
||||
float damage = 4 * damageMultiplier;
|
||||
float damage = Spells.force_orb.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
target.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.BLAST), damage);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
@@ -12,43 +12,55 @@ import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EntityIceCharge extends EntityBomb {
|
||||
|
||||
public static final String ICE_SHARDS = "ice_shards";
|
||||
|
||||
public EntityIceCharge(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult par1RayTraceResult){
|
||||
Entity entityHit = par1RayTraceResult.entityHit;
|
||||
public int getLifetime(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the ice charge gets a direct hit
|
||||
float damage = 4 * damageMultiplier;
|
||||
float damage = Spells.ice_charge.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FROST).setProjectile(),
|
||||
damage);
|
||||
|
||||
if(entityHit instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.FROST, entityHit))
|
||||
((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(WizardryPotions.frost, 120, 1));
|
||||
((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(WizardryPotions.frost,
|
||||
Spells.ice_charge.getProperty(Spell.DIRECT_EFFECT_DURATION).intValue(),
|
||||
Spells.ice_charge.getProperty(Spell.DIRECT_EFFECT_STRENGTH).intValue()));
|
||||
}
|
||||
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
|
||||
for(int i = 0; i < 30 * blastMultiplier; i++){
|
||||
|
||||
|
||||
ParticleBuilder.create(Type.ICE, rand, this.posX, this.posY, this.posZ, 2 * blastMultiplier, false)
|
||||
.time(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)
|
||||
.clr(brightness, brightness + 0.1f, 1.0f).spawn(world);
|
||||
@@ -57,10 +69,10 @@ public class EntityIceCharge extends EntityBomb {
|
||||
|
||||
if(!this.world.isRemote){
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.5f, rand.nextFloat() * 0.4f + 0.6f);
|
||||
this.playSound(WizardrySounds.SPELL_ICE, 1.2f, rand.nextFloat() * 0.4f + 1.2f);
|
||||
this.playSound(WizardrySounds.ENTITY_ICE_CHARGE_SMASH, 1.5f, rand.nextFloat() * 0.4f + 0.6f);
|
||||
this.playSound(WizardrySounds.ENTITY_ICE_CHARGE_ICE, 1.2f, rand.nextFloat() * 0.4f + 1.2f);
|
||||
|
||||
double radius = 3.0d * blastMultiplier;
|
||||
double radius = Spells.ice_charge.getProperty(Spell.EFFECT_RADIUS).floatValue() * blastMultiplier;
|
||||
|
||||
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(radius, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
@@ -69,7 +81,9 @@ public class EntityIceCharge extends EntityBomb {
|
||||
for(EntityLivingBase target : targets){
|
||||
if(target != entityHit && target != this.getThrower()){
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FROST, target))
|
||||
target.addPotionEffect(new PotionEffect(WizardryPotions.frost, 100, 0));
|
||||
target.addPotionEffect(new PotionEffect(WizardryPotions.frost,
|
||||
Spells.ice_charge.getProperty(Spell.SPLASH_EFFECT_DURATION).intValue(),
|
||||
Spells.ice_charge.getProperty(Spell.SPLASH_EFFECT_STRENGTH).intValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,35 +93,39 @@ public class EntityIceCharge extends EntityBomb {
|
||||
|
||||
BlockPos pos = new BlockPos(this.posX + i, this.posY, this.posZ + j);
|
||||
|
||||
int y = WizardryUtilities.getNearestFloorLevelB(world, pos, 7);
|
||||
Integer y = WizardryUtilities.getNearestSurface(world, pos, EnumFacing.UP, 7, true,
|
||||
WizardryUtilities.SurfaceCriteria.SOLID_LIQUID_TO_AIR);
|
||||
|
||||
pos = new BlockPos(pos.getX(), y, pos.getZ());
|
||||
if(y != null){
|
||||
|
||||
double dist = this.getDistance(pos.getX(), pos.getY(), pos.getZ());
|
||||
pos = new BlockPos(pos.getX(), y, pos.getZ());
|
||||
|
||||
// Randomised with weighting so that the nearer the block the more likely it is to be snowed.
|
||||
if(y != -1 && rand.nextInt((int)dist * 2 + 1) < 1 && dist < 2){
|
||||
if(world.getBlockState(pos.down()).getBlock() == Blocks.WATER){
|
||||
world.setBlockState(pos.down(), Blocks.ICE.getDefaultState());
|
||||
}else{
|
||||
// Don't need to check whether the block at pos can be replaced since getNearestFloorLevelB
|
||||
// only ever returns floors with air above them.
|
||||
world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState());
|
||||
double dist = this.getDistance(pos.getX(), pos.getY(), pos.getZ());
|
||||
|
||||
// Randomised with weighting so that the nearer the block the more likely it is to be snowed.
|
||||
if(rand.nextInt((int)dist * 2 + 1) < 1 && dist < 2){
|
||||
if(world.getBlockState(pos.down()).getBlock() == Blocks.WATER){
|
||||
world.setBlockState(pos.down(), Blocks.ICE.getDefaultState());
|
||||
}else{
|
||||
// Don't need to check whether the block at pos can be replaced since getNearestFloorLevelB
|
||||
// only ever returns floors with air above them.
|
||||
world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Releases shards
|
||||
for(int i = 0; i < 10; i++){
|
||||
for(int i = 0; i < Spells.ice_charge.getProperty(ICE_SHARDS).intValue(); i++){
|
||||
double dx = rand.nextDouble() - 0.5;
|
||||
double dy = rand.nextDouble() - 0.5;
|
||||
double dz = rand.nextDouble() - 0.5;
|
||||
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.motionX = dx * 1.5;
|
||||
iceshard.motionY = dy * 1.5;
|
||||
iceshard.motionZ = dz * 1.5;
|
||||
iceshard.setCaster(this.getThrower());
|
||||
iceshard.damageMultiplier = this.damageMultiplier;
|
||||
world.spawnEntity(iceshard);
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
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.EntityLivingBase;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityIceLance extends EntityMagicArrow {
|
||||
@@ -18,7 +21,9 @@ public class EntityIceLance extends EntityMagicArrow {
|
||||
this.setKnockbackStrength(1);
|
||||
}
|
||||
|
||||
@Override public double getDamage(){ return 10.0d; }
|
||||
@Override public double getDamage(){ return Spells.ice_lance.getProperty(Spell.DAMAGE).floatValue(); }
|
||||
|
||||
@Override public int getLifetime(){ return -1; }
|
||||
|
||||
@Override public DamageType getDamageType(){ return DamageType.FROST; }
|
||||
|
||||
@@ -35,13 +40,15 @@ public class EntityIceLance extends EntityMagicArrow {
|
||||
|
||||
// Adds a freeze effect to the target.
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FROST, entityHit))
|
||||
entityHit.addPotionEffect(new PotionEffect(WizardryPotions.frost, 300, 0));
|
||||
entityHit.addPotionEffect(new PotionEffect(WizardryPotions.frost,
|
||||
Spells.ice_lance.getProperty(Spell.EFFECT_DURATION).intValue(),
|
||||
Spells.ice_lance.getProperty(Spell.EFFECT_STRENGTH).intValue()));
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
this.playSound(WizardrySounds.ENTITY_ICE_LANCE_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockHit(){
|
||||
public void onBlockHit(RayTraceResult hit){
|
||||
// Adds a particle effect when the ice lance hits a block.
|
||||
if(this.world.isRemote){
|
||||
for(int j = 0; j < 10; j++){
|
||||
@@ -49,8 +56,8 @@ public class EntityIceLance extends EntityMagicArrow {
|
||||
.time(20 + rand.nextInt(10)).gravity(true).spawn(world);
|
||||
}
|
||||
}
|
||||
// Parameters for sound: sound event name, volume, pitch.
|
||||
this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.0F, rand.nextFloat() * 0.4F + 1.2F);
|
||||
|
||||
this.playSound(WizardrySounds.ENTITY_ICE_LANCE_SMASH, 1.0F, rand.nextFloat() * 0.4F + 1.2F);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
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.EntityLivingBase;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityIceShard extends EntityMagicArrow {
|
||||
@@ -17,7 +21,9 @@ public class EntityIceShard extends EntityMagicArrow {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override public double getDamage(){ return 6; }
|
||||
@Override public double getDamage(){ return Spells.ice_shard.getProperty(Spell.DAMAGE).floatValue(); }
|
||||
|
||||
@Override public int getLifetime(){ return -1; }
|
||||
|
||||
@Override public DamageType getDamageType(){ return DamageType.FROST; }
|
||||
|
||||
@@ -32,13 +38,16 @@ public class EntityIceShard extends EntityMagicArrow {
|
||||
|
||||
// Adds a freeze effect to the target.
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FROST, entityHit))
|
||||
entityHit.addPotionEffect(new PotionEffect(WizardryPotions.frost, 200, 0));
|
||||
entityHit.addPotionEffect(new PotionEffect(WizardryPotions.frost,
|
||||
Spells.ice_shard.getProperty(Spell.EFFECT_DURATION).intValue(),
|
||||
Spells.ice_shard.getProperty(Spell.EFFECT_STRENGTH).intValue()));
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
this.playSound(WizardrySounds.ENTITY_ICE_SHARD_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockHit(){
|
||||
public void onBlockHit(RayTraceResult hit){
|
||||
|
||||
// Adds a particle effect when the ice shard hits a block.
|
||||
if(this.world.isRemote){
|
||||
// Gets a position slightly away from the block hit so the particle doesn't get cut in half by the block face
|
||||
@@ -51,7 +60,7 @@ public class EntityIceShard extends EntityMagicArrow {
|
||||
}
|
||||
}
|
||||
// Parameters for sound: sound event name, volume, pitch.
|
||||
this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.0F, rand.nextFloat() * 0.4F + 1.2F);
|
||||
this.playSound(WizardrySounds.ENTITY_ICE_SHARD_SMASH, 1.0F, rand.nextFloat() * 0.4F + 1.2F);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityIceball extends EntityMagicProjectile {
|
||||
|
||||
public EntityIceball(World world){
|
||||
super(world);
|
||||
this.setSize(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
if(!world.isRemote){
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
|
||||
float damage = Spells.iceball.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FROST).setProjectile(),
|
||||
damage);
|
||||
|
||||
if(entityHit instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.FROST, entityHit)){
|
||||
((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(WizardryPotions.frost,
|
||||
Spells.iceball.getProperty(Spell.EFFECT_DURATION).intValue(),
|
||||
Spells.iceball.getProperty(Spell.EFFECT_STRENGTH).intValue()));
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
boolean flag = true;
|
||||
|
||||
if(this.getThrower() != null && this.getThrower() instanceof EntityLiving){
|
||||
flag = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this.getThrower());
|
||||
}
|
||||
|
||||
if(flag){
|
||||
|
||||
BlockPos pos = rayTrace.getBlockPos();
|
||||
|
||||
if(rayTrace.sideHit == EnumFacing.UP && !world.isRemote && world.isSideSolid(pos, EnumFacing.UP)
|
||||
&& WizardryUtilities.canBlockBeReplaced(world, pos.up())){
|
||||
world.setBlockState(pos.up(), Blocks.SNOW_LAYER.getDefaultState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.playSound(WizardrySounds.ENTITY_ICEBALL_HIT, 2, 0.8f + rand.nextFloat() * 0.3f);
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(){
|
||||
|
||||
super.onUpdate();
|
||||
|
||||
if(world.isRemote){
|
||||
|
||||
for(int i=0; i<5; i++){
|
||||
|
||||
double dx = (rand.nextDouble() - 0.5) * width;
|
||||
double dy = (rand.nextDouble() - 0.5) * height + this.height/2;
|
||||
double dz = (rand.nextDouble() - 0.5) * width;
|
||||
double v = 0.06;
|
||||
ParticleBuilder.create(ParticleBuilder.Type.SNOW)
|
||||
.pos(this.getPositionVector().add(dx - this.motionX/2, dy, dz - this.motionZ/2))
|
||||
.vel(-v * dx, -v * dy, -v * dz).scale(width*2).time(8 + rand.nextInt(4)).spawn(world);
|
||||
|
||||
if(ticksExisted > 1){
|
||||
dx = (rand.nextDouble() - 0.5) * width;
|
||||
dy = (rand.nextDouble() - 0.5) * height + this.height / 2;
|
||||
dz = (rand.nextDouble() - 0.5) * width;
|
||||
ParticleBuilder.create(ParticleBuilder.Type.SNOW)
|
||||
.pos(this.getPositionVector().add(dx - this.motionX, dy, dz - this.motionZ))
|
||||
.vel(-v * dx, -v * dy, -v * dz).scale(width*2).time(8 + rand.nextInt(4)).spawn(world);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNoGravity(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRenderOnFire(){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.entity.projectile.EntityLargeFireball;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
/**
|
||||
* It's like {@link EntityMagicFireball}, but bigger... the wizardry version of vanilla's
|
||||
* {@link net.minecraft.entity.projectile.EntityLargeFireball}
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class EntityLargeMagicFireball extends EntityMagicFireball {
|
||||
|
||||
public static final String EXPLOSION_POWER = "explosion_power";
|
||||
|
||||
/** The entity blast multiplier. This is now synced and saved centrally from {@link EntityBomb}. */
|
||||
public float blastMultiplier = 1.0f;
|
||||
|
||||
/** The explosion power of this fireball. If this is -1, the damage for the fireball
|
||||
* spell will be used instead; this is for when the fireball is not from a spell (i.e. a vanilla fireball replacement). */
|
||||
protected float explosionPower = -1;
|
||||
|
||||
public EntityLargeMagicFireball(World world){
|
||||
super(world);
|
||||
this.setSize(1, 1);
|
||||
}
|
||||
|
||||
public void setExplosionPower(float explosionPower){
|
||||
this.explosionPower = explosionPower;
|
||||
}
|
||||
|
||||
public float getExplosionPower(){
|
||||
return explosionPower == -1 ? Spells.greater_fireball.getProperty(EXPLOSION_POWER).floatValue() : explosionPower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDamage(){
|
||||
return damage == -1 ? Spells.greater_fireball.getProperty(Spell.DAMAGE).floatValue() : damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
if(!world.isRemote){
|
||||
boolean flag = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this.thrower);
|
||||
this.world.newExplosion(null, this.posX, this.posY, this.posZ, getExplosionPower() * blastMultiplier, flag, flag);
|
||||
}
|
||||
|
||||
super.onImpact(rayTrace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSpawnData(ByteBuf buffer){
|
||||
buffer.writeFloat(blastMultiplier);
|
||||
super.writeSpawnData(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readSpawnData(ByteBuf buffer){
|
||||
blastMultiplier = buffer.readFloat();
|
||||
super.readSpawnData(buffer);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onEntityJoinWorldEvent(EntityJoinWorldEvent event){
|
||||
// Replaces all vanilla large fireballs with wizardry ones
|
||||
if(Wizardry.settings.replaceVanillaFireballs && event.getEntity() instanceof EntityLargeFireball){
|
||||
|
||||
event.setCanceled(true);
|
||||
|
||||
EntityLargeMagicFireball fireball = new EntityLargeMagicFireball(event.getWorld());
|
||||
fireball.thrower = ((EntityLargeFireball)event.getEntity()).shootingEntity;
|
||||
fireball.setPosition(event.getEntity().posX, event.getEntity().posY, event.getEntity().posZ);
|
||||
fireball.setDamage(6);
|
||||
// Don't set the burn duration because vanilla large fireballs don't set mobs on fire directly
|
||||
fireball.setExplosionPower(((EntityLargeFireball)event.getEntity()).explosionPower);
|
||||
fireball.setLifetime(75);
|
||||
|
||||
fireball.motionX = ((EntityLargeFireball)event.getEntity()).accelerationX * ACCELERATION_CONVERSION_FACTOR;
|
||||
fireball.motionY = ((EntityLargeFireball)event.getEntity()).accelerationY * ACCELERATION_CONVERSION_FACTOR;
|
||||
fireball.motionZ = ((EntityLargeFireball)event.getEntity()).accelerationZ * ACCELERATION_CONVERSION_FACTOR;
|
||||
|
||||
event.getWorld().spawnEntity(fireball);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
@@ -14,7 +16,9 @@ public class EntityLightningArrow extends EntityMagicArrow {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override public double getDamage(){ return 7.0d; }
|
||||
@Override public double getDamage(){ return Spells.lightning_arrow.getProperty(Spell.DAMAGE).doubleValue(); }
|
||||
|
||||
@Override public int getLifetime(){ return 20; }
|
||||
|
||||
@Override public DamageType getDamageType(){ return DamageType.SHOCK; }
|
||||
|
||||
@@ -31,26 +35,22 @@ public class EntityLightningArrow extends EntityMagicArrow {
|
||||
}
|
||||
}
|
||||
|
||||
this.playSound(WizardrySounds.SPELL_SPARK, 1.0F, 1.0F);
|
||||
@Override
|
||||
public void onBlockHit(RayTraceResult hit){
|
||||
if(this.world.isRemote){
|
||||
Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET));
|
||||
ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0.4f, 0.8f, 1).scale(0.6f).spawn(world);
|
||||
}
|
||||
this.playSound(WizardrySounds.ENTITY_LIGHTNING_ARROW_HIT, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onBlockHit(RayTraceResult hit){
|
||||
// if(this.world.isRemote){
|
||||
// Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET));
|
||||
// ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0.4f, 0.8f, 1).scale(0.6f).spawn(world);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void tickInAir(){
|
||||
|
||||
if(this.ticksExisted > 20){
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
if(world.isRemote){
|
||||
ParticleBuilder.create(Type.SPARK).pos(posX, posY, posZ).spawn(world);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
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.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@@ -27,13 +25,12 @@ public class EntityLightningDisc extends EntityMagicProjectile {
|
||||
Entity entityHit = result.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
float damage = 12 * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK),
|
||||
damage);
|
||||
float damage = Spells.lightning_disc.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier;
|
||||
entityHit.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getThrower(),
|
||||
DamageType.SHOCK), damage);
|
||||
}
|
||||
|
||||
this.playSound(WizardrySounds.SPELL_SPARK, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
this.playSound(WizardrySounds.ENTITY_LIGHTNING_DISC_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
|
||||
if(result.typeOfHit == RayTraceResult.Type.BLOCK) this.setDead();
|
||||
}
|
||||
@@ -46,47 +43,27 @@ public class EntityLightningDisc extends EntityMagicProjectile {
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
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() * 2 - 1).spawn(world);
|
||||
}
|
||||
}
|
||||
|
||||
if(!this.collided && !world.isRemote){
|
||||
|
||||
double seekingRange = 5.0d;
|
||||
|
||||
List<EntityLivingBase> entities = WizardryUtilities.getEntitiesWithinRadius(seekingRange, this.posX,
|
||||
this.posY, this.posZ, this.world);
|
||||
Entity target = null;
|
||||
|
||||
for(Entity possibleTarget : entities){
|
||||
// Decides if current entity should be replaced.
|
||||
if(target == null || this.getDistance(target) > this.getDistance(possibleTarget)){
|
||||
// Decides if new entity is a valid target.
|
||||
if(WizardryUtilities.isValidTarget(this.getThrower(), possibleTarget)){
|
||||
target = possibleTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(target != null && Math.abs(this.motionX) < 1 && Math.abs(this.motionY) < 1
|
||||
&& Math.abs(this.motionZ) < 1){
|
||||
this.addVelocity((target.posX - this.posX) / 30, (target.posY + target.height / 2 - this.posY) / 30,
|
||||
(target.posZ - this.posZ) / 30);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.ticksExisted > 50){
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
// Cancels out the slowdown effect in EntityThrowable
|
||||
this.motionX /= 0.99;
|
||||
this.motionY /= 0.99;
|
||||
this.motionZ /= 0.99;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSeekingStrength(){
|
||||
return Spells.lightning_disc.getProperty(Spell.SEEKING_STRENGTH).floatValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNoGravity(){
|
||||
return true;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import electroblob.wizardry.item.ItemArtefact;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.util.AllyDesignationSystem;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.RayTracer;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.block.Block;
|
||||
@@ -23,22 +24,23 @@ import net.minecraft.network.play.server.SPacketChangeGameState;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
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.util.SoundCategory;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This class was copied from EntityArrow in the 1.7.10 update as part of the overhaul and major cleanup of the code for
|
||||
* the projectiles. It provides a unifying superclass for all <b>directed</b> projectiles (i.e. not spherical stuff like
|
||||
* snowballs), namely magic missile, ice shard, force arrow, lightning arrow and dart. All spherical projectiles should
|
||||
* extend {@link EntityMagicProjectile}.
|
||||
* <p>
|
||||
* <p></p>
|
||||
* This class handles saving of the damage multiplier and all shared logic. Methods are provided which are triggered at
|
||||
* useful points during the entity update cycle as well as a few getters for various properties. Override any of these
|
||||
* to change the behaviour (no need to call super for any of them).
|
||||
@@ -46,8 +48,12 @@ import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
* @since Wizardry 1.0
|
||||
* @author Electroblob
|
||||
*/
|
||||
// TODO: Might be a good idea to have this implement IEntityOwnable as well
|
||||
public abstract class EntityMagicArrow extends Entity implements IProjectile, IEntityAdditionalSpawnData {
|
||||
|
||||
public static final double LAUNCH_Y_OFFSET = 0.1;
|
||||
public static final int SEEKING_TIME = 15;
|
||||
|
||||
private int blockX = -1;
|
||||
private int blockY = -1;
|
||||
private int blockZ = -1;
|
||||
@@ -81,14 +87,14 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
|
||||
// Initialiser methods
|
||||
|
||||
/** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and
|
||||
/** Sets the shooter of the projectile to the given caster, positions the projectile 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.setLocationAndAngles(caster.posX, caster.getEntityBoundingBox().minY + (double)caster.getEyeHeight() - LAUNCH_Y_OFFSET,
|
||||
caster.posZ, caster.rotationYaw, caster.rotationPitch);
|
||||
|
||||
this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
|
||||
this.posY -= 0.10000000149011612D;
|
||||
@@ -106,7 +112,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
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
|
||||
/** Sets the shooter of the projectile to the given caster, positions the projectile 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. */
|
||||
@@ -114,7 +120,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
|
||||
this.setCaster(caster);
|
||||
|
||||
this.posY = caster.posY + (double)caster.getEyeHeight() - 0.1d;
|
||||
this.posY = caster.getEntityBoundingBox().minY + (double)caster.getEyeHeight() - LAUNCH_Y_OFFSET;
|
||||
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;
|
||||
@@ -141,6 +147,10 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
/** Subclasses must override this to set their own base damage. */
|
||||
public abstract double getDamage();
|
||||
|
||||
/** Returns the maximum flight time in ticks before this projectile disappears, or -1 if it can continue
|
||||
* indefinitely until it hits something. This should be constant. */
|
||||
public abstract int getLifetime();
|
||||
|
||||
/** Override this to specify the damage type dealt. Defaults to {@link DamageType#MAGIC}. */
|
||||
public DamageType getDamageType(){
|
||||
return DamageType.MAGIC;
|
||||
@@ -167,6 +177,16 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the seeking strength of this projectile, or the maximum distance from a target the projectile can be
|
||||
* heading for that will make it curve towards that target. By default, this is 2 if the caster is wearing a ring
|
||||
* of attraction, otherwise it is 0.
|
||||
*/
|
||||
public float getSeekingStrength(){
|
||||
return getCaster() instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)getCaster(),
|
||||
WizardryItems.ring_seeking) ? 2 : 0;
|
||||
}
|
||||
|
||||
// Setters and getters
|
||||
|
||||
/** Sets the amount of knockback the projectile applies when it hits a mob. */
|
||||
@@ -184,7 +204,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
}
|
||||
|
||||
public void setCaster(EntityLivingBase entity){
|
||||
caster = new WeakReference<EntityLivingBase>(entity);
|
||||
caster = new WeakReference<>(entity);
|
||||
}
|
||||
|
||||
// Methods triggered during the update cycle
|
||||
@@ -211,10 +231,15 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
|
||||
super.onUpdate();
|
||||
|
||||
// Projectile disappears after its lifetime (if it has one) has elapsed
|
||||
if(getLifetime() >=0 && this.ticksExisted > getLifetime()){
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
if(this.getCaster() == null && this.casterUUID != null){
|
||||
Entity entity = WizardryUtilities.getEntityByUUID(world, casterUUID);
|
||||
if(entity instanceof EntityLivingBase){
|
||||
this.caster = new WeakReference<EntityLivingBase>((EntityLivingBase)entity);
|
||||
this.caster = new WeakReference<>((EntityLivingBase)entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,8 +348,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
if(this.getCaster() == null){
|
||||
damagesource = DamageSource.causeThrownDamage(this, this);
|
||||
}else{
|
||||
damagesource = MagicDamage.causeIndirectMagicDamage(this,
|
||||
(EntityLivingBase)this.getCaster(), this.getDamageType()).setProjectile();
|
||||
damagesource = MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), this.getDamageType()).setProjectile();
|
||||
}
|
||||
|
||||
if(raytraceresult.entityHit.attackEntityFrom(damagesource,
|
||||
@@ -347,11 +371,9 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
}
|
||||
|
||||
// Thorns enchantment
|
||||
if(this.getCaster() != null
|
||||
&& this.getCaster() instanceof EntityLivingBase){
|
||||
if(this.getCaster() != null){
|
||||
EnchantmentHelper.applyThornEnchantments(entityHit, this.getCaster());
|
||||
EnchantmentHelper.applyArthropodEnchantments((EntityLivingBase)this.getCaster(),
|
||||
entityHit);
|
||||
EnchantmentHelper.applyArthropodEnchantments(this.getCaster(), entityHit);
|
||||
}
|
||||
|
||||
if(this.getCaster() != null && raytraceresult.entityHit != this.getCaster()
|
||||
@@ -401,6 +423,29 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
}
|
||||
}
|
||||
|
||||
// Seeking
|
||||
if(getSeekingStrength() > 0){
|
||||
|
||||
Vec3d velocity = new Vec3d(motionX, motionY, motionZ);
|
||||
|
||||
RayTraceResult hit = RayTracer.rayTrace(world, this.getPositionVector(),
|
||||
this.getPositionVector().add(velocity.scale(SEEKING_TIME)), getSeekingStrength(), false,
|
||||
true, false, EntityLivingBase.class, RayTracer.ignoreEntityFilter(null));
|
||||
|
||||
if(hit != null && hit.entityHit != null){
|
||||
|
||||
if(AllyDesignationSystem.isValidTarget(getCaster(), hit.entityHit)){
|
||||
|
||||
Vec3d direction = new Vec3d(hit.entityHit.posX, hit.entityHit.posY + hit.entityHit.height/2,
|
||||
hit.entityHit.posZ).subtract(this.getPositionVector()).normalize().scale(velocity.length());
|
||||
|
||||
motionX = motionX + 2 * (direction.x - motionX) / SEEKING_TIME;
|
||||
motionY = motionY + 2 * (direction.y - motionY) / SEEKING_TIME;
|
||||
motionZ = motionZ + 2 * (direction.z - motionZ) / SEEKING_TIME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.posX += this.motionX;
|
||||
this.posY += this.motionY;
|
||||
this.posZ += this.motionZ;
|
||||
@@ -510,8 +555,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
tag.setShort("zTile", (short)this.blockZ);
|
||||
tag.setShort("life", (short)this.ticksInGround);
|
||||
if(this.stuckInBlock != null){
|
||||
ResourceLocation resourcelocation = (ResourceLocation)Block.REGISTRY
|
||||
.getNameForObject(this.stuckInBlock.getBlock());
|
||||
ResourceLocation resourcelocation = Block.REGISTRY.getNameForObject(this.stuckInBlock.getBlock());
|
||||
tag.setString("inTile", resourcelocation == null ? "" : resourcelocation.toString());
|
||||
}
|
||||
tag.setByte("inData", (byte)this.inData);
|
||||
@@ -529,7 +573,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
this.blockY = tag.getShort("yTile");
|
||||
this.blockZ = tag.getShort("zTile");
|
||||
this.ticksInGround = tag.getShort("life");
|
||||
// Commented out for now because there's some funny stuff going on with blockstates and metadata.
|
||||
// Commented out for now because there's some funny stuff going on with blockstates and id.
|
||||
// this.stuckInBlock = Block.getBlockById(tag.getByte("inTile") & 255);
|
||||
this.inData = tag.getByte("inData") & 255;
|
||||
this.arrowShake = tag.getByte("shake") & 255;
|
||||
@@ -545,7 +589,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
|
||||
@Override
|
||||
public void readSpawnData(ByteBuf buffer){
|
||||
if(buffer.isReadable()) this.caster = new WeakReference<EntityLivingBase>(
|
||||
if(buffer.isReadable()) this.caster = new WeakReference<>(
|
||||
(EntityLivingBase)this.world.getEntityByID(buffer.readInt()));
|
||||
}
|
||||
|
||||
@@ -565,6 +609,11 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
|
||||
public float getShadowSize(){
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundCategory getSoundCategory(){
|
||||
return WizardrySounds.SPELLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void entityInit(){}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.projectile.EntitySmallFireball;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
/**
|
||||
* It's a fireball - but unlike vanilla fireballs, it actually looks like a fireball, and isn't completely useless for
|
||||
* attacking things (acceleration from stationary? Really, Mojang? No wonder I had so many blaze rods back in the day...)
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class EntityMagicFireball extends EntityMagicProjectile {
|
||||
|
||||
protected static final int ACCELERATION_CONVERSION_FACTOR = 10;
|
||||
|
||||
/** The damage dealt by this fireball. If this is -1, the damage for the fireball spell will be used instead;
|
||||
* this is for when the fireball is not from a spell (i.e. a vanilla fireball replacement). */
|
||||
protected float damage = -1;
|
||||
/** The number of seconds entities are set on fire by this fireball. If this is -1, the damage for the fireball
|
||||
* spell will be used instead; this is for when the fireball is not from a spell (i.e. a vanilla fireball replacement). */
|
||||
protected int burnDuration = -1;
|
||||
/** The lifetime of this fireball in ticks. This needs to be stored so that it can be changed for vanilla replacements,
|
||||
* or mobs that shoot fireballs would have severely reduced range! */
|
||||
protected int lifetime = 16;
|
||||
|
||||
public EntityMagicFireball(World world){
|
||||
super(world);
|
||||
this.setSize(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
public void setDamage(float damage){
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
public void setBurnDuration(int burnDuration){
|
||||
this.burnDuration = burnDuration;
|
||||
}
|
||||
|
||||
public float getDamage(){
|
||||
// I'm lazy, I'd rather not have an entire fireball spell class just to set two fields on the entity
|
||||
return damage == -1 ? Spells.fireball.getProperty(Spell.DAMAGE).floatValue() : damage;
|
||||
}
|
||||
|
||||
public int getBurnDuration(){
|
||||
return burnDuration == -1 ? Spells.fireball.getProperty(Spell.BURN_DURATION).intValue() : burnDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
if(!world.isRemote){
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
|
||||
float damage = getDamage() * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile(),
|
||||
damage);
|
||||
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit) && getBurnDuration() > 0)
|
||||
entityHit.setFire(getBurnDuration());
|
||||
|
||||
}else{
|
||||
|
||||
boolean flag = true;
|
||||
|
||||
if(this.getThrower() != null && this.getThrower() instanceof EntityLiving){
|
||||
flag = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, this.getThrower());
|
||||
}
|
||||
|
||||
if(flag){
|
||||
|
||||
BlockPos blockpos = rayTrace.getBlockPos().offset(rayTrace.sideHit);
|
||||
|
||||
if(this.world.isAirBlock(blockpos)){
|
||||
this.world.setBlockState(blockpos, Blocks.FIRE.getDefaultState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//this.playSound(WizardrySounds.ENTITY_MAGIC_FIREBALL_HIT, 2, 0.8f + rand.nextFloat() * 0.3f);
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(){
|
||||
|
||||
super.onUpdate();
|
||||
|
||||
if(world.isRemote){
|
||||
|
||||
for(int i=0; i<5; i++){
|
||||
|
||||
double dx = (rand.nextDouble() - 0.5) * width;
|
||||
double dy = (rand.nextDouble() - 0.5) * height + this.height/2 - 0.1; // -0.1 because flames aren't centred
|
||||
double dz = (rand.nextDouble() - 0.5) * width;
|
||||
double v = 0.06;
|
||||
ParticleBuilder.create(ParticleBuilder.Type.MAGIC_FIRE)
|
||||
.pos(this.getPositionVector().add(dx - this.motionX/2, dy, dz - this.motionZ/2))
|
||||
.vel(-v * dx, -v * dy, -v * dz).scale(width*2).time(10).spawn(world);
|
||||
|
||||
if(ticksExisted > 1){
|
||||
dx = (rand.nextDouble() - 0.5) * width;
|
||||
dy = (rand.nextDouble() - 0.5) * height + this.height / 2 - 0.1;
|
||||
dz = (rand.nextDouble() - 0.5) * width;
|
||||
ParticleBuilder.create(ParticleBuilder.Type.MAGIC_FIRE)
|
||||
.pos(this.getPositionVector().add(dx - this.motionX, dy, dz - this.motionZ))
|
||||
.vel(-v * dx, -v * dy, -v * dz).scale(width*2).time(10).spawn(world);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setLifetime(int lifetime){
|
||||
this.lifetime = lifetime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNoGravity(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRenderOnFire(){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSpawnData(ByteBuf buffer){
|
||||
buffer.writeInt(lifetime);
|
||||
super.writeSpawnData(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readSpawnData(ByteBuf buffer){
|
||||
lifetime = buffer.readInt();
|
||||
super.readSpawnData(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readEntityFromNBT(NBTTagCompound nbttagcompound){
|
||||
super.readEntityFromNBT(nbttagcompound);
|
||||
lifetime = nbttagcompound.getInteger("lifetime");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeEntityToNBT(NBTTagCompound nbttagcompound){
|
||||
super.writeEntityToNBT(nbttagcompound);
|
||||
nbttagcompound.setInteger("lifetime", lifetime);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onEntityJoinWorldEvent(EntityJoinWorldEvent event){
|
||||
// Replaces all vanilla fireballs with wizardry ones
|
||||
if(Wizardry.settings.replaceVanillaFireballs && event.getEntity() instanceof EntitySmallFireball){
|
||||
|
||||
event.setCanceled(true);
|
||||
|
||||
EntityMagicFireball fireball = new EntityMagicFireball(event.getWorld());
|
||||
fireball.thrower = ((EntitySmallFireball)event.getEntity()).shootingEntity;
|
||||
fireball.setPosition(event.getEntity().posX, event.getEntity().posY, event.getEntity().posZ);
|
||||
fireball.setDamage(5);
|
||||
fireball.setBurnDuration(5);
|
||||
fireball.setLifetime(40);
|
||||
|
||||
fireball.motionX = ((EntitySmallFireball)event.getEntity()).accelerationX * ACCELERATION_CONVERSION_FACTOR;
|
||||
fireball.motionY = ((EntitySmallFireball)event.getEntity()).accelerationY * ACCELERATION_CONVERSION_FACTOR;
|
||||
fireball.motionZ = ((EntitySmallFireball)event.getEntity()).accelerationZ * ACCELERATION_CONVERSION_FACTOR;
|
||||
|
||||
event.getWorld().spawnEntity(fireball);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,25 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityMagicMissile extends EntityMagicArrow {
|
||||
|
||||
/** The number of ticks the magic missile flies for before vanishing; effectively determines its range. */
|
||||
private static final int LIFETIME = 12;
|
||||
|
||||
/** Creates a new magic missile in the given world. */
|
||||
public EntityMagicMissile(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override public double getDamage(){ return 4; }
|
||||
@Override public double getDamage(){ return Spells.magic_missile.getProperty(Spell.DAMAGE).floatValue(); }
|
||||
|
||||
@Override public int getLifetime(){ return 12; }
|
||||
|
||||
@Override public boolean doGravity(){ return false; }
|
||||
|
||||
@@ -26,8 +27,8 @@ public class EntityMagicMissile extends EntityMagicArrow {
|
||||
|
||||
@Override
|
||||
public void onEntityHit(EntityLivingBase entityHit){
|
||||
this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
if(this.world.isRemote) spawnImpactParticles();
|
||||
this.playSound(WizardrySounds.ENTITY_MAGIC_MISSILE_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
if(this.world.isRemote) ParticleBuilder.create(Type.FLASH).pos(posX, posY, posZ).clr(1, 1, 0.65f).spawn(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,10 +43,6 @@ public class EntityMagicMissile extends EntityMagicArrow {
|
||||
@Override
|
||||
public void tickInAir(){
|
||||
|
||||
if(this.ticksExisted > LIFETIME){
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
if(this.world.isRemote){
|
||||
ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 0.03, true).clr(1, 1, 0.65f).fade(0.7f, 0, 1)
|
||||
.time(20 + rand.nextInt(10)).spawn(world);
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.item.ItemArtefact;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.util.AllyDesignationSystem;
|
||||
import electroblob.wizardry.util.RayTracer;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.projectile.EntityThrowable;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
|
||||
@@ -13,7 +22,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
* This class is a generic superclass for all <b>non-directed</b> projectiles, namely: darkness orb, firebolt, firebomb,
|
||||
* force orb, ice charge, lightning disc, poison bomb, spark, spark bomb and thunderbolt. Directed (arrow-like)
|
||||
* projectiles should instead extend {@link EntityMagicArrow}.
|
||||
* <p>
|
||||
* <p></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(), though due to a bug in vanilla it has to be synced by this class.
|
||||
@@ -24,6 +33,9 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
*/
|
||||
public abstract class EntityMagicProjectile extends EntityThrowable implements IEntityAdditionalSpawnData {
|
||||
|
||||
public static final double LAUNCH_Y_OFFSET = 0.1;
|
||||
public static final int SEEKING_TIME = 15;
|
||||
|
||||
public float damageMultiplier = 1.0f;
|
||||
|
||||
/** Creates a new projectile in the given world. */
|
||||
@@ -33,10 +45,10 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I
|
||||
|
||||
// Initialiser methods
|
||||
|
||||
/** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and
|
||||
/** Sets the shooter of the projectile to the given caster, positions the projectile 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.setPosition(caster.posX, caster.getEntityBoundingBox().minY + (double)caster.getEyeHeight() - LAUNCH_Y_OFFSET, 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;
|
||||
@@ -44,7 +56,7 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I
|
||||
this.ignoreEntity = caster;
|
||||
}
|
||||
|
||||
/** Sets the shooter of the projectile to the given caster, positions the projctile at the given caster's eyes and
|
||||
/** Sets the shooter of the projectile to the given caster, positions the projectile 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. */
|
||||
@@ -54,7 +66,7 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I
|
||||
// Mojang's 'fix' for the projectile-hitting-thrower bug actually made the problem worse, hence the following line.
|
||||
this.ignoreEntity = thrower;
|
||||
|
||||
this.posY = caster.posY + (double)caster.getEyeHeight() - 0.1d;
|
||||
this.posY = caster.getEntityBoundingBox().minY + (double)caster.getEyeHeight() - LAUNCH_Y_OFFSET;
|
||||
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;
|
||||
@@ -75,6 +87,54 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I
|
||||
}
|
||||
}
|
||||
|
||||
public void setCaster(EntityLivingBase caster){
|
||||
this.thrower = caster;
|
||||
this.ignoreEntity = caster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the seeking strength of this projectile, or the maximum distance from a target the projectile can be
|
||||
* heading for that will make it curve towards that target. By default, this is 2 if the caster is wearing a ring
|
||||
* of attraction, otherwise it is 0.
|
||||
*/
|
||||
public float getSeekingStrength(){
|
||||
return getThrower() instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)getThrower(),
|
||||
WizardryItems.ring_seeking) ? 2 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(){
|
||||
|
||||
super.onUpdate();
|
||||
|
||||
if(getLifetime() >=0 && this.ticksExisted > getLifetime()){
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
// Seeking
|
||||
if(getSeekingStrength() > 0){
|
||||
|
||||
Vec3d velocity = new Vec3d(motionX, motionY, motionZ);
|
||||
|
||||
RayTraceResult hit = RayTracer.rayTrace(world, this.getPositionVector(),
|
||||
this.getPositionVector().add(velocity.scale(SEEKING_TIME)), getSeekingStrength(), false,
|
||||
true, false, EntityLivingBase.class, RayTracer.ignoreEntityFilter(null));
|
||||
|
||||
if(hit != null && hit.entityHit != null){
|
||||
|
||||
if(AllyDesignationSystem.isValidTarget(getThrower(), hit.entityHit)){
|
||||
|
||||
Vec3d direction = new Vec3d(hit.entityHit.posX, hit.entityHit.posY + hit.entityHit.height/2,
|
||||
hit.entityHit.posZ).subtract(this.getPositionVector()).normalize().scale(velocity.length());
|
||||
|
||||
motionX = motionX + 2 * (direction.x - motionX) / SEEKING_TIME;
|
||||
motionY = motionY + 2 * (direction.y - motionY) / SEEKING_TIME;
|
||||
motionZ = motionZ + 2 * (direction.z - motionZ) / SEEKING_TIME;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readEntityFromNBT(NBTTagCompound nbttagcompound){
|
||||
super.readEntityFromNBT(nbttagcompound);
|
||||
@@ -88,20 +148,26 @@ 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){
|
||||
if(this.getThrower() != null) data.writeInt(this.getThrower().getEntityId());
|
||||
data.writeInt(this.getThrower() == null ? -1 : 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){
|
||||
if(data.isReadable()){
|
||||
Entity entity = this.world.getEntityByID(data.readInt());
|
||||
if(entity instanceof EntityLivingBase) this.thrower = (EntityLivingBase)entity;
|
||||
this.ignoreEntity = this.thrower;
|
||||
}
|
||||
int id = data.readInt();
|
||||
if(id == -1) return;
|
||||
Entity entity = this.world.getEntityByID(id);
|
||||
if(entity instanceof EntityLivingBase) this.thrower = (EntityLivingBase)entity;
|
||||
this.ignoreEntity = this.thrower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundCategory getSoundCategory(){
|
||||
return WizardrySounds.SPELLS;
|
||||
}
|
||||
|
||||
/** Returns the maximum flight time in ticks before this projectile disappears, or -1 if it can continue
|
||||
* indefinitely until it hits something. This should be constant. */
|
||||
public abstract int getLifetime();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
@@ -10,18 +11,24 @@ import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EntityPoisonBomb extends EntityBomb {
|
||||
|
||||
public EntityPoisonBomb(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
@@ -29,14 +36,16 @@ public class EntityPoisonBomb extends EntityBomb {
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the poison bomb gets a direct hit
|
||||
float damage = 5 * damageMultiplier;
|
||||
float damage = Spells.poison_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.POISON).setProjectile(),
|
||||
damage);
|
||||
|
||||
if(entityHit instanceof EntityLivingBase && !MagicDamage.isEntityImmune(DamageType.POISON, entityHit))
|
||||
((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(MobEffects.POISON, 120, 1));
|
||||
((EntityLivingBase)entityHit).addPotionEffect(new PotionEffect(MobEffects.POISON,
|
||||
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_DURATION).intValue(),
|
||||
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_STRENGTH).intValue()));
|
||||
}
|
||||
|
||||
// Particle effect
|
||||
@@ -48,7 +57,7 @@ public class EntityPoisonBomb extends EntityBomb {
|
||||
for(int i = 0; i < 60 * blastMultiplier; i++){
|
||||
|
||||
ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 2*blastMultiplier, false).time(35)
|
||||
.clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
|
||||
.scale(2).clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
|
||||
|
||||
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
|
||||
.clr(0.2f + rand.nextFloat() * 0.2f, 0.8f, 0.0f).spawn(world);
|
||||
@@ -60,10 +69,10 @@ public class EntityPoisonBomb extends EntityBomb {
|
||||
|
||||
if(!this.world.isRemote){
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
|
||||
this.playSound(SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.2F, 1.0f);
|
||||
this.playSound(WizardrySounds.ENTITY_POISON_BOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
|
||||
this.playSound(WizardrySounds.ENTITY_POISON_BOMB_POISON, 1.2F, 1.0f);
|
||||
|
||||
double range = 3.0d * blastMultiplier;
|
||||
double range = Spells.poison_bomb.getProperty(Spell.EFFECT_RADIUS).floatValue() * blastMultiplier;
|
||||
|
||||
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(range, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
@@ -73,8 +82,10 @@ public class EntityPoisonBomb extends EntityBomb {
|
||||
&& !MagicDamage.isEntityImmune(DamageType.POISON, target)){
|
||||
target.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.POISON),
|
||||
4.0f * damageMultiplier);
|
||||
target.addPotionEffect(new PotionEffect(MobEffects.POISON, 100, 1));
|
||||
Spells.poison_bomb.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier);
|
||||
target.addPotionEffect(new PotionEffect(MobEffects.POISON,
|
||||
Spells.poison_bomb.getProperty(Spell.SPLASH_EFFECT_DURATION).intValue(),
|
||||
Spells.poison_bomb.getProperty(Spell.SPLASH_EFFECT_STRENGTH).intValue()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
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.WizardryUtilities;
|
||||
@@ -10,18 +11,24 @@ import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EntitySmokeBomb extends EntityBomb {
|
||||
|
||||
public EntitySmokeBomb(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
@@ -47,25 +54,26 @@ public class EntitySmokeBomb extends EntityBomb {
|
||||
|
||||
if(!this.world.isRemote){
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_SPLASH_POTION_BREAK, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
|
||||
this.playSound(SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.2F, 1.0f);
|
||||
this.playSound(WizardrySounds.ENTITY_SMOKE_BOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
|
||||
this.playSound(WizardrySounds.ENTITY_SMOKE_BOMB_SMOKE, 1.2F, 1.0f);
|
||||
|
||||
double range = 3.0d * blastMultiplier;
|
||||
double range = Spells.smoke_bomb.getProperty(Spell.BLAST_RADIUS).floatValue() * blastMultiplier;
|
||||
|
||||
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(range, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
|
||||
int duration = Spells.smoke_bomb.getProperty(Spell.EFFECT_DURATION).intValue();
|
||||
|
||||
for(EntityLivingBase target : targets){
|
||||
if(target != this.getThrower()){
|
||||
// Gives the target blindness if it is a player, mind trick otherwise (since this has the desired
|
||||
// effect of preventing targeting)
|
||||
if(target instanceof EntityPlayer){
|
||||
target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 120, 0));
|
||||
target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, duration, 0));
|
||||
}else if(target instanceof EntityLiving){
|
||||
// New AI
|
||||
((EntityLiving)target).setAttackTarget(null);
|
||||
|
||||
target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, 120, 0));
|
||||
target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, duration, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
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.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@@ -26,13 +24,13 @@ public class EntitySpark extends EntityMagicProjectile {
|
||||
|
||||
if(entityHit != null){
|
||||
|
||||
float damage = 6 * damageMultiplier;
|
||||
entityHit.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK),
|
||||
damage);
|
||||
float damage = Spells.homing_spark.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier;
|
||||
entityHit.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getThrower(),
|
||||
DamageType.SHOCK), damage);
|
||||
|
||||
}
|
||||
|
||||
this.playSound(WizardrySounds.SPELL_SPARK, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
this.playSound(WizardrySounds.ENTITY_HOMING_SPARK_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
@@ -47,40 +45,16 @@ public class EntitySpark extends EntityMagicProjectile {
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
public void onUpdate(){
|
||||
|
||||
super.onUpdate();
|
||||
|
||||
if(!this.collided && !world.isRemote){
|
||||
|
||||
double seekingRange = 5.0d;
|
||||
|
||||
List<EntityLivingBase> entities = WizardryUtilities.getEntitiesWithinRadius(seekingRange, this.posX,
|
||||
this.posY, this.posZ, this.world);
|
||||
Entity target = null;
|
||||
|
||||
for(Entity possibleTarget : entities){
|
||||
// Decides if current entity should be replaced.
|
||||
if(target == null || this.getDistance(target) > this.getDistance(possibleTarget)){
|
||||
// Decides if new entity is a valid target.
|
||||
if(WizardryUtilities.isValidTarget(this.getThrower(), possibleTarget)){
|
||||
target = possibleTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(target != null && Math.abs(this.motionX) < 1 && Math.abs(this.motionY) < 1
|
||||
&& Math.abs(this.motionZ) < 1){
|
||||
this.addVelocity((target.posX - this.posX) / 30, (target.posY + target.height / 2 - this.posY) / 30,
|
||||
(target.posZ - this.posZ) / 30);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.ticksExisted > 100){
|
||||
this.setDead();
|
||||
}
|
||||
@Override
|
||||
public float getSeekingStrength(){
|
||||
return Spells.homing_spark.getProperty(Spell.SEEKING_STRENGTH).floatValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNoGravity(){
|
||||
return true;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
@@ -11,28 +11,36 @@ 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.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EntitySparkBomb extends EntityBomb {
|
||||
|
||||
public static final String SECONDARY_MAX_TARGETS = "secondary_max_targets";
|
||||
|
||||
public EntitySparkBomb(World world){
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST_FAR, 0.5f, 0.5f);
|
||||
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT_BLOCK, 0.5f, 0.5f);
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the spark bomb gets a direct hit
|
||||
float damage = 6 * damageMultiplier;
|
||||
float damage = Spells.spark_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_GENERIC_HURT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK).setProjectile(),
|
||||
@@ -45,19 +53,19 @@ public class EntitySparkBomb extends EntityBomb {
|
||||
ParticleBuilder.spawnShockParticles(world, posX, posY + height/2, posZ);
|
||||
}
|
||||
|
||||
double seekerRange = 5.0d * blastMultiplier;
|
||||
double seekerRange = Spells.spark_bomb.getProperty(Spell.EFFECT_RADIUS).doubleValue() * blastMultiplier;
|
||||
|
||||
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
|
||||
for(int i = 0; i < Math.min(targets.size(), 4); i++){
|
||||
for(int i = 0; i < Math.min(targets.size(), Spells.spark_bomb.getProperty(SECONDARY_MAX_TARGETS).intValue()); i++){
|
||||
|
||||
boolean flag = targets.get(i) != entityHit && targets.get(i) != this.getThrower()
|
||||
&& !(targets.get(i) instanceof EntityPlayer
|
||||
&& ((EntityPlayer)targets.get(i)).capabilities.isCreativeMode);
|
||||
&& ((EntityPlayer)targets.get(i)).isCreative());
|
||||
|
||||
// Detects (client side) if target is the thrower, to stop particles being spawned around them.
|
||||
//if(flag && world.isRemote && targets.get(i).getEntityId() == this.casterID) flag = false;
|
||||
//if(flag && world.isRemote && targets.get(i).getEntityId() == this.playerID) flag = false;
|
||||
|
||||
if(flag){
|
||||
|
||||
@@ -69,7 +77,7 @@ public class EntitySparkBomb extends EntityBomb {
|
||||
|
||||
target.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK),
|
||||
5.0f * damageMultiplier);
|
||||
Spells.spark_bomb.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier);
|
||||
|
||||
}else{
|
||||
ParticleBuilder.create(Type.LIGHTNING).pos(this.getPositionVector()).target(target).spawn(world);
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
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.init.SoundEvents;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class EntityThunderbolt extends EntityMagicProjectile {
|
||||
|
||||
public static final String KNOCKBACK_STRENGTH = "knockback_strength";
|
||||
|
||||
public EntityThunderbolt(World par1World){
|
||||
super(par1World);
|
||||
}
|
||||
@@ -27,17 +31,19 @@ public class EntityThunderbolt extends EntityMagicProjectile {
|
||||
|
||||
if(entityHit != null){
|
||||
|
||||
float damage = 3 * damageMultiplier;
|
||||
float damage = Spells.thunderbolt.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK).setProjectile(),
|
||||
damage);
|
||||
|
||||
float knockbackStrength = Spells.thunderbolt.getProperty(KNOCKBACK_STRENGTH).floatValue();
|
||||
|
||||
// Knockback
|
||||
entityHit.addVelocity(this.motionX * 0.2, this.motionY * 0.2, this.motionZ * 0.2);
|
||||
entityHit.addVelocity(this.motionX * knockbackStrength, this.motionY * knockbackStrength, this.motionZ * knockbackStrength);
|
||||
}
|
||||
|
||||
this.playSound(SoundEvents.ENTITY_FIREWORK_LARGE_BLAST, 1.4F, 0.5f + this.rand.nextFloat() * 0.1F);
|
||||
this.playSound(WizardrySounds.ENTITY_THUNDERBOLT_HIT, 1.4F, 0.5f + this.rand.nextFloat() * 0.1F);
|
||||
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
@@ -60,10 +66,11 @@ public class EntityThunderbolt extends EntityMagicProjectile {
|
||||
this.posZ + rand.nextFloat() * 0.2 - 0.1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.ticksExisted > 8){
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLifetime(){
|
||||
return 8;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user