249 lines
7.6 KiB
Java
249 lines
7.6 KiB
Java
package electroblob.wizardry.entity.projectile;
|
|
|
|
import electroblob.wizardry.Wizardry;
|
|
import electroblob.wizardry.registry.Spells;
|
|
import electroblob.wizardry.spell.Spell;
|
|
import electroblob.wizardry.util.BlockUtils;
|
|
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.EntityLivingBase;
|
|
import net.minecraft.entity.monster.EntityGhast;
|
|
import net.minecraft.entity.projectile.EntitySmallFireball;
|
|
import net.minecraft.init.Blocks;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.util.DamageSource;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.math.MathHelper;
|
|
import net.minecraft.util.math.RayTraceResult;
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraft.world.World;
|
|
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;
|
|
|
|
DamageSource source = getDamageSource(entityHit);
|
|
|
|
entityHit.attackEntityFrom(source, damage);
|
|
|
|
if(!MagicDamage.isEntityImmune(DamageType.FIRE, entityHit) && getBurnDuration() > 0)
|
|
entityHit.setFire(getBurnDuration());
|
|
|
|
}else{
|
|
|
|
BlockPos pos = rayTrace.getBlockPos().offset(rayTrace.sideHit);
|
|
|
|
// Remember that canPlaceBlock should ALWAYS be the last thing that gets checked, or it risks other mods
|
|
// thinking the block was placed even when a later condition prevents it, which may have side-effects
|
|
if(this.world.isAirBlock(pos) && BlockUtils.canPlaceBlock(thrower, world, pos)){
|
|
this.world.setBlockState(pos, Blocks.FIRE.getDefaultState());
|
|
}
|
|
}
|
|
|
|
//this.playSound(WizardrySounds.ENTITY_MAGIC_FIREBALL_HIT, 2, 0.8f + rand.nextFloat() * 0.3f);
|
|
|
|
this.setDead();
|
|
}
|
|
}
|
|
|
|
protected DamageSource getDamageSource(Entity entityHit){
|
|
return MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.FIRE).setProjectile();
|
|
}
|
|
|
|
@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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean canBeCollidedWith(){
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public float getCollisionBorderSize(){
|
|
return 1.0F;
|
|
}
|
|
|
|
@Override
|
|
public boolean attackEntityFrom(DamageSource source, float amount){
|
|
|
|
if(this.isEntityInvulnerable(source)){
|
|
return false;
|
|
|
|
}else{
|
|
|
|
this.markVelocityChanged();
|
|
|
|
if(source.getTrueSource() != null){
|
|
|
|
Vec3d vec3d = source.getTrueSource().getLookVec();
|
|
|
|
if(vec3d != null){
|
|
|
|
double speed = MathHelper.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
|
|
|
|
this.motionX = vec3d.x * speed;
|
|
this.motionY = vec3d.y * speed;
|
|
this.motionZ = vec3d.z * speed;
|
|
|
|
this.lifetime = 160;
|
|
|
|
}
|
|
|
|
if(source.getTrueSource() instanceof EntityLivingBase){
|
|
this.setCaster((EntityLivingBase)source.getTrueSource());
|
|
}
|
|
|
|
return true;
|
|
|
|
}else{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|