Files
Wizardry/src/main/java/electroblob/wizardry/spell/GreaterTelekinesis.java
T

162 lines
6.2 KiB
Java

package electroblob.wizardry.spell;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.entity.EntityLevitatingBlock;
import electroblob.wizardry.item.ItemArtefact;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.EnumAction;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.World;
public class GreaterTelekinesis extends SpellRay {
public static final String HOLD_RANGE = "hold_range";
public static final String THROW_VELOCITY = "throw_velocity";
/** Makes things a bit smoother-looking / 'realistic'. */
private static final float UNDERSHOOT = 0.2f;
public GreaterTelekinesis(){
super("greater_telekinesis", true, EnumAction.NONE);
this.aimAssist(0.4f);
this.particleSpacing(1);
this.particleJitter(0.05);
this.particleVelocity(0.3);
addProperties(HOLD_RANGE, THROW_VELOCITY, DAMAGE);
this.soundValues(0.8f, 1, 0.2f);
}
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
@Override
protected SoundEvent[] createSounds(){
return this.createContinuousSpellSounds();
}
@Override
protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){
this.playSoundLoop(world, entity, ticksInUse);
}
@Override
protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){
this.playSoundLoop(world, x, y, z, ticksInUse, duration);
}
@Override
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
// Can't be cast by dispensers so we know caster isn't null, but just in case...
if(caster != null && (target instanceof EntityLivingBase || target instanceof EntityLevitatingBlock || target instanceof EntityTNTPrimed)){
if(target instanceof EntityPlayer && ((caster instanceof EntityPlayer && !Wizardry.settings.playersMoveEachOther)
|| ItemArtefact.isArtefactActive((EntityPlayer)target, WizardryItems.amulet_anchoring))){
if(!world.isRemote && caster instanceof EntityPlayer) ((EntityPlayer)caster).sendStatusMessage(
new TextComponentTranslation("spell.resist", target.getName(), this.getNameForTranslationFormatted()), true);
return false;
}
if(target instanceof EntityLevitatingBlock){
((EntityLevitatingBlock)target).suspend();
((EntityLevitatingBlock)target).setCaster(caster); // Yep, you can steal other players' blocks in mid-air!
}
Vec3d targetPos = target.getPositionVector().add(0, target.height/2, 0);
if(caster.isSneaking()){
Vec3d look = caster.getLookVec().scale(getProperty(THROW_VELOCITY).floatValue() * modifiers.get(WizardryItems.range_upgrade));
target.addVelocity(look.x, look.y, look.z);
if(caster instanceof EntityPlayer) caster.swingArm(caster.getActiveHand());
}else{
WizardryUtilities.undoGravity(target);
// The following code extrapolates the entity's current velocity to determine whether it will pass the
// target position in the next tick, and adds or subtracts velocity accordingly.
Vec3d vec = origin.add(caster.getLookVec().scale(getProperty(HOLD_RANGE).floatValue()));
Vec3d velocity = vec.subtract(targetPos).subtract(target.motionX, target.motionY, target.motionZ)
.scale(1 - UNDERSHOOT);
target.addVelocity(velocity.x, velocity.y, velocity.z);
}
// Player motion is handled on that player's client so needs packets
if(target instanceof EntityPlayerMP){
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
}
if(world.isRemote){
ParticleBuilder.create(Type.BEAM).entity(caster).clr(0.2f, 0.6f + 0.3f * world.rand.nextFloat(), 1)
.pos(origin.subtract(caster.getPositionVector())).target(target).time(0)
.scale(MathHelper.sin(ticksInUse * 0.3f) * 0.1f + 0.9f).spawn(world);
if(ticksInUse % 18 == 1) ParticleBuilder.create(Type.FLASH).entity(target).pos(0, target.height/2, 0)
.scale(2.5f).time(30).clr(0.2f, 0.8f, 1).fade(1f, 1f, 1f).spawn(world);
ParticleBuilder.create(Type.SPARKLE, target).vel(0, 0.05, 0).time(15).scale(0.6f).clr(0.2f, 0.6f, 1)
.fade(1f, 1f, 1f).spawn(world);
}
return true;
}
return false;
}
@Override
protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
if(WizardryUtilities.canDamageBlocks(caster, world) && !WizardryUtilities.isBlockUnbreakable(world, pos)
&& world.getBlockState(pos).getMaterial().isSolid()
&& (world.getTileEntity(pos) == null || !world.getTileEntity(pos).getTileData().hasUniqueId(ArcaneLock.NBT_KEY))){
if(!world.isRemote){
EntityLevitatingBlock block = new EntityLevitatingBlock(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
world.getBlockState(pos));
block.fallTime = 1;
block.damageMultiplier = modifiers.get(SpellModifiers.POTENCY);
block.setCaster(caster);
world.spawnEntity(block);
world.setBlockToAir(pos);
}
return true;
}
return false;
}
@Override
protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){
return false;
}
}