162 lines
6.2 KiB
Java
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;
|
|
}
|
|
|
|
}
|