Initial commit

This commit is contained in:
Electroblob
2018-01-19 20:33:04 +00:00
commit da6b007a3a
945 changed files with 60616 additions and 0 deletions
@@ -0,0 +1,39 @@
package electroblob.wizardry.entity.construct;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class EntityArrowRain extends EntityMagicConstruct {
public EntityArrowRain(World par1World) {
super(par1World);
this.height = 3.0f;
this.width = 5.0f;
}
public EntityArrowRain(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.height = 3.0f;
this.width = 5.0f;
}
public void onUpdate(){
super.onUpdate();
if(!this.worldObj.isRemote){
EntityTippedArrow arrow = new EntityTippedArrow(worldObj, this.posX + rand.nextDouble()*6 - 3, this.posY + rand.nextDouble()*4 - 2, this.posZ + rand.nextDouble()*6 - 3);
arrow.motionX = Math.cos(Math.toRadians(this.rotationYaw + 90));
arrow.motionY = -0.6;
arrow.motionZ = Math.sin(Math.toRadians(this.rotationYaw + 90));
arrow.shootingEntity = this.getCaster();
arrow.setDamage(7.0d*damageMultiplier);
arrow.setPotionEffect(new ItemStack(Items.ARROW));
this.worldObj.spawnEntityInWorld(arrow);
}
}
}
@@ -0,0 +1,138 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.SoundEvents;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EntityBlackHole extends EntityMagicConstruct {
public int[] randomiser;
public int[] randomiser2;
public EntityBlackHole(World world){
super(world);
this.width = 6.0f;
this.height = 3.0f;
randomiser = new int[30];
for(int i=0; i<randomiser.length; i++){
randomiser[i] = this.rand.nextInt(10);
}
randomiser2 = new int[30];
for(int i=0; i<randomiser2.length; i++){
randomiser2[i] = this.rand.nextInt(10);
}
}
public EntityBlackHole(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.width = 6.0f;
this.height = 3.0f;
randomiser = new int[30];
for(int i=0; i<randomiser.length; i++){
randomiser[i] = this.rand.nextInt(10);
}
randomiser2 = new int[30];
for(int i=0; i<randomiser2.length; i++){
randomiser2[i] = this.rand.nextInt(10);
}
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbttagcompound) {
super.readEntityFromNBT(nbttagcompound);
randomiser = nbttagcompound.getIntArray("randomiser");
randomiser2 = nbttagcompound.getIntArray("randomiser2");
}
@Override
protected void writeEntityToNBT(NBTTagCompound nbttagcompound) {
super.writeEntityToNBT(nbttagcompound);
nbttagcompound.setIntArray("randomiser", randomiser);
nbttagcompound.setIntArray("randomiser2", randomiser2);
}
public void onUpdate(){
super.onUpdate();
//System.out.println("Client side: " + this.worldObj.isRemote + ", Caster: " + this.caster);
// Particle effect. Finishes 40 ticks before the end so the particles disappear at the same time.
if(this.ticksExisted + 40 < this.lifetime){
for (int i=0; i<5; i++){
//this.worldObj.spawnParticle(EnumParticleTypes.PORTAL, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height - 0.75D, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, (this.rand.nextDouble() - 0.5D) * 2.0D, -this.rand.nextDouble(), (this.rand.nextDouble() - 0.5D) * 2.0D);
this.worldObj.spawnParticle(EnumParticleTypes.PORTAL, this.posX, this.posY, this.posZ, (this.rand.nextDouble() - 0.5D) * 4.0D, (this.rand.nextDouble() - 0.5D) * 4.0D - 1, (this.rand.nextDouble() - 0.5D) * 4.0D);
}
}
if(this.lifetime - this.ticksExisted == 75){
this.playSound(SoundEvents.BLOCK_PORTAL_TRIGGER, 1.5f, 1.0f);
}else if(this.ticksExisted % 80 == 1 && this.ticksExisted + 80 < this.lifetime){
this.playSound(SoundEvents.BLOCK_PORTAL_AMBIENT, 1.5f, 1.0f);
}
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(6.0d, this.posX, this.posY, this.posZ, this.worldObj);
if(!this.worldObj.isRemote){
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
// Sucks the target in
if(this.posX > target.posX && target.motionX < 1){
target.motionX+=0.1;
}else if(this.posX < target.posX && target.motionX > -1){
target.motionX-=0.1;
}
if(this.posY > target.posY && target.motionY < 1){
target.motionY+=0.1;
}else if(this.posY < target.posY && target.motionY > -1){
target.motionY-=0.1;
}
if(this.posZ > target.posZ && target.motionZ < 1){
target.motionZ+=0.1;
}else if(this.posZ < target.posZ && target.motionZ > -1){
target.motionZ-=0.1;
}
// Player motion is handled on that player's client so needs packets
if(target instanceof EntityPlayerMP){
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
}
if(this.getDistanceToEntity(target) <= 2){
// Damages the target if it is close enough
if(this.getCaster() != null){
target.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.MAGIC), 2*damageMultiplier);
}else{
target.attackEntityFrom(DamageSource.magic, 2*damageMultiplier);
}
}
}
}
}
}
/**
* Checks using a Vec3dd to determine if this entity is within range of that vector to be rendered. Args: Vec3dD
*/
public boolean isInRangeToRenderVec3dD(Vec3d par1Vec3d)
{
return true;
}
}
@@ -0,0 +1,68 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
public class EntityBlizzard extends EntityMagicConstruct {
public EntityBlizzard(World par1World) {
super(par1World);
this.height = 1.0f;
this.width = 1.0f;
}
public EntityBlizzard(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.height = 1.0f;
this.width = 1.0f;
}
public void onUpdate(){
if(this.ticksExisted % 120 == 1){
this.playSound(WizardrySounds.SPELL_LOOP_WIND, 1.0f, 1.0f);
}
super.onUpdate();
if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(3.0d, this.posX, this.posY, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
if(this.getCaster() != null){
WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.FROST), 1*damageMultiplier);
}else{
WizardryUtilities.attackEntityWithoutKnockback(target, DamageSource.magic, 1*damageMultiplier);
}
}
// All entities are slowed, even the caster (except those immune to frost effects)
if(!MagicDamage.isEntityImmune(DamageType.FROST, target))
target.addPotionEffect(new PotionEffect(WizardryPotions.frost, 20, 0));
}
}else{
// For some reason this number of particles now causes the game to lag significantly, despite it being fine
// in 1.7.10. I thought particles were supposed to be LESS laggy now...
for(int i=1; i<6; i++){
float brightness = 0.5f + (rand.nextFloat()/2);
Wizardry.proxy.spawnParticle(WizardryParticleType.BLIZZARD, worldObj, this.posX, this.posY + rand.nextDouble()*3, this.posZ, 0, 0, 0, 100, brightness, brightness + 0.1f, 1.0f, false, rand.nextDouble() * 2.5d + 0.5d);
Wizardry.proxy.spawnParticle(WizardryParticleType.BLIZZARD, worldObj, this.posX, this.posY + rand.nextDouble()*3, this.posZ, 0, 0, 0, 100, 1.0f, 1.0f, 1.0f, false, rand.nextDouble() * 2.5d + 0.5d);
}
}
}
}
@@ -0,0 +1,123 @@
package electroblob.wizardry.entity.construct;
import java.lang.ref.WeakReference;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryUtilities;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.SoundEvents;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;
public class EntityBubble extends EntityMagicConstruct {
public boolean isDarkOrb;
private WeakReference<EntityLivingBase> rider;
public EntityBubble(World world){
super(world);
}
public EntityBubble(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, boolean isDarkOrb, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
//this.setSize(0.1f, 0.1f);
this.isDarkOrb = isDarkOrb;
}
@Override
public double getMountedYOffset()
{
return 0.1;
}
@Override
public boolean shouldRiderSit(){
return false;
}
public void onUpdate(){
super.onUpdate();
// Synchronises the rider field
if((this.rider == null || this.rider.get() == null) && WizardryUtilities.getRider(this) instanceof EntityLivingBase
&& !WizardryUtilities.getRider(this).isDead){
this.rider = new WeakReference<EntityLivingBase>((EntityLivingBase) WizardryUtilities.getRider(this));
}
// Prevents dismounting
if(WizardryUtilities.getRider(this) == null && this.rider != null && this.rider.get() != null && !this.rider.get().isDead){
this.rider.get().startRiding(this);
}
// Stops the bubble bursting instantly.
if(this.ticksExisted < 1 && !isDarkOrb) ((EntityLivingBase)WizardryUtilities.getRider(this)).hurtTime = 0;
this.moveEntity(0, 0.03, 0);
if(isDarkOrb){
if(WizardryUtilities.getRider(this) != null && this.ticksExisted % 30 == 0){
if(this.getCaster() != null){
WizardryUtilities.getRider(this).attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.MAGIC), 1*damageMultiplier);
}else{
WizardryUtilities.getRider(this).attackEntityFrom(DamageSource.magic, 1*damageMultiplier);
}
}
for(int i=0; i<5; i++){
this.worldObj.spawnParticle(EnumParticleTypes.PORTAL, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height + 0.5d, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, (this.rand.nextDouble() - 0.5D) * 2.0D, -this.rand.nextDouble(), (this.rand.nextDouble() - 0.5D) * 2.0D);
}
if(lifetime - this.ticksExisted == 75){
this.playSound(SoundEvents.BLOCK_PORTAL_TRIGGER, 1.5f, 1.0f);
}else if(this.ticksExisted % 100 == 1 && this.ticksExisted < 150){
this.playSound(SoundEvents.BLOCK_PORTAL_AMBIENT, 1.5f, 1.0f);
}
}
// Bubble bursts if the entity is hurt (see event handler) or killed, or if the bubble has existed for more than 10 seconds.
if(WizardryUtilities.getRider(this) == null && this.ticksExisted > 1){
if(!this.isDarkOrb) this.playSound(SoundEvents.ENTITY_ITEM_PICKUP, 1.5f, 1.0f);
this.setDead();
}
}
@Override
public void despawn(){
if(WizardryUtilities.getRider(this) != null){
((EntityLivingBase)WizardryUtilities.getRider(this)).dismountEntity(this);
}
if(!this.isDarkOrb) this.playSound(SoundEvents.ENTITY_ITEM_PICKUP, 1.5f, 1.0f);
super.despawn();
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbttagcompound) {
super.readEntityFromNBT(nbttagcompound);
isDarkOrb = nbttagcompound.getBoolean("isDarkOrb");
}
@Override
protected void writeEntityToNBT(NBTTagCompound nbttagcompound) {
super.writeEntityToNBT(nbttagcompound);
nbttagcompound.setBoolean("isDarkOrb", isDarkOrb);
}
@Override
public void writeSpawnData(ByteBuf data) {
super.writeSpawnData(data);
data.writeBoolean(this.isDarkOrb);
}
@Override
public void readSpawnData(ByteBuf data) {
super.readSpawnData(data);
this.isDarkOrb = data.readBoolean();
}
}
@@ -0,0 +1,78 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.SoundEvents;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EntityDecay extends EntityMagicConstruct {
public int textureIndex = 0;
public static final int LIFETIME = 400;
public EntityDecay(World par1World) {
super(par1World);
textureIndex = this.rand.nextInt(10);
this.height = 0.2f;
this.width = 2.0f;
}
public EntityDecay(World par1World, double x, double y, double z, EntityLivingBase caster) {
super(par1World, x, y, z, caster, LIFETIME, 1);
textureIndex = this.rand.nextInt(10);
this.height = 0.2f;
this.width = 2.0f;
}
@Override
public void onUpdate(){
super.onUpdate();
if(this.rand.nextInt(700) == 0 && this.ticksExisted+100 < LIFETIME) this.playSound(SoundEvents.BLOCK_LAVA_AMBIENT, 0.2F + rand.nextFloat() * 0.2F, 0.6F + rand.nextFloat() * 0.15F);
if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(1.0d, this.posX, this.posY, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(target != this.getCaster()){
// If this check wasn't here the potion would be reapplied every tick and hence the entity would be damaged each tick.
// In this case, we do want particles to be shown.
if(!target.isPotionActive(WizardryPotions.decay)) target.addPotionEffect(new PotionEffect(WizardryPotions.decay, LIFETIME, 0));
}
}
}else if(this.rand.nextInt(15) == 0){
double radius = rand.nextDouble()*0.8;
double angle = rand.nextDouble()*Math.PI*2;
float brightness = rand.nextFloat()*0.4f;
Wizardry.proxy.spawnParticle(WizardryParticleType.DARK_MAGIC, worldObj, this.posX + radius*Math.cos(angle), this.posY, this.posZ + radius*Math.sin(angle), 0, 0, 0, 0, brightness, 0, brightness+0.1f);
}
}
protected void entityInit(){}
@Override
protected void readEntityFromNBT(NBTTagCompound nbttagcompound) {
}
@Override
protected void writeEntityToNBT(NBTTagCompound nbttagcompound) {
}
/**
* Checks using a Vec3dd to determine if this entity is within range of that vector to be rendered. Args: Vec3dD
*/
public boolean isInRangeToRenderVec3dD(Vec3d par1Vec3d)
{
return true;
}
}
@@ -0,0 +1,107 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.MobEffects;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class EntityEarthquake extends EntityMagicConstruct {
public EntityEarthquake(World world){
super(world);
this.height = 1.0f;
this.width = 1.0f;
}
public EntityEarthquake(World world, double x, double y, double z, EntityLivingBase caster, int lifetime,
float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.height = 1.0f;
this.width = 1.0f;
}
public void onUpdate(){
super.onUpdate();
if(!worldObj.isRemote){
double speed = 0.4;
// The further the earthquake is going to spread, the finer the angle increments.
for(double angle=0; angle < 2*Math.PI; angle+=Math.PI/(lifetime*1.5)){
// Calculates coordinates for the block to be moved. The radius increases with time. The +1.5 is to leave
// blocks in the centre untouched.
int x = this.posX < 0 ? (int)(this.posX + ((this.ticksExisted*speed)+1.5)*Math.sin(angle) - 1) : (int)(this.posX + ((this.ticksExisted*speed)+1.5)*Math.sin(angle));
int y = (int)(this.posY - 0.5);
int z = this.posZ < 0 ? (int)(this.posZ + ((this.ticksExisted*speed)+1.5)*Math.cos(angle) - 1) : (int)(this.posZ + ((this.ticksExisted*speed)+1.5)*Math.cos(angle));
BlockPos pos = new BlockPos(x, y, z);
if(!WizardryUtilities.isBlockUnbreakable(worldObj, pos) && !worldObj.isAirBlock(pos) && worldObj.isBlockNormalCube(pos, false)
// Checks that the block above is not solid, since this causes the falling sand to vanish.
&& !worldObj.isBlockNormalCube(pos.up(), false)){
// Falling blocks do the setting block to air themselves.
EntityFallingBlock fallingblock = new EntityFallingBlock(worldObj, x+0.5, y+0.5, z+0.5, worldObj.getBlockState(new BlockPos(x, y, z)));
fallingblock.motionY = 0.3;
worldObj.spawnEntityInWorld(fallingblock);
}
}
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius((this.ticksExisted*speed)+1.5, this.posX, this.posY, this.posZ, worldObj);
// In this particular instance, the caster is completely unaffected because they will always be in the centre.
targets.remove(this.getCaster());
for(EntityLivingBase target : targets){
// Searches in a 1 wide ring.
if(this.getDistanceToEntity(target) > (this.ticksExisted*speed)+0.5 && target.posY < this.posY + 1 && target.posY > this.posY - 1){
// Knockback must be removed in this instance, or the target will fall into the floor.
double motionX = target.motionX;
double motionZ = target.motionZ;
if(this.isValidTarget(target)){
target.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), DamageType.BLAST), 10*this.damageMultiplier);
target.addPotionEffect(new PotionEffect(MobEffects.WEAKNESS, 400, 1));
}
// All targets are thrown, even those immune to the damage, so they don't fall into the ground.
target.motionX = motionX;
target.motionY = 0.8; // Throws target into the air.
target.motionZ = motionZ;
// Player motion is handled on that player's client so needs packets
if(target instanceof EntityPlayerMP){
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
}
}
}
// TODO: Uncomment once 2.1.0 is released
// }else{
//
// // Constant 15 blocks for now
// List<EntityPlayer> targets = WizardryUtilities.getEntitiesWithinRadius(15, this.posX, this.posY, this.posZ, worldObj, EntityPlayer.class);
//
// float magnitude = 6f * ((float)(this.lifetime - this.ticksExisted))/(float)this.lifetime;
//
// // Makes the screen shake
// for(EntityLivingBase target : targets){
// target.setAngles(0, this.ticksExisted % 4 < 2 ? magnitude : -magnitude);
// }
}
}
}
@@ -0,0 +1,67 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
public class EntityFireRing extends EntityMagicConstruct {
public EntityFireRing(World par1World) {
super(par1World);
this.height = 1.0f;
this.width = 5.0f;
}
public EntityFireRing(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.height = 1.0f;
this.width = 5.0f;
}
public void onUpdate(){
if(this.ticksExisted % 40 == 1){
this.playSound(SoundEvents.BLOCK_FIRE_AMBIENT, 4.0f, 0.7f);
}
super.onUpdate();
if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(2.5d, this.posX, this.posY, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
double velX = target.motionX;
double velY = target.motionY;
double velZ = target.motionZ;
if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)){
target.setFire(10);
if(this.getCaster() != null){
target.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.FIRE), 1*damageMultiplier);
}else{
target.attackEntityFrom(DamageSource.magic, 1*damageMultiplier);
}
}
// Removes knockback
target.motionX = velX;
target.motionY = velY;
target.motionZ = velZ;
}
}
}
}
}
@@ -0,0 +1,87 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;
public class EntityFireSigil extends EntityMagicConstruct {
public EntityFireSigil(World par1World) {
super(par1World);
this.height = 0.2f;
this.width = 2.0f;
}
public EntityFireSigil(World par1World, double x, double y, double z, EntityLivingBase caster, float damageMultiplier) {
super(par1World, x, y, z, caster, -1, damageMultiplier);
this.height = 0.2f;
this.width = 2.0f;
}
// Overrides the original to stop the entity moving when it intersects stuff. The default arrow does this to allow
// it to stick in blocks.
public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
{
this.setPosition(par1, par3, par5);
this.setRotation(par7, par8);
}
public void onUpdate(){
super.onUpdate();
if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(1.0d, this.posX, this.posY, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
double velX = target.motionX;
double velY = target.motionY;
double velZ = target.motionZ;
target.attackEntityFrom(this.getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), DamageType.FIRE) : DamageSource.magic, 6);
// Removes knockback
target.motionX = velX;
target.motionY = velY;
target.motionZ = velZ;
if(!MagicDamage.isEntityImmune(DamageType.FIRE, target)) target.setFire(10);
this.playSound(SoundEvents.ENTITY_BLAZE_SHOOT, 1, 1);
// The trap is destroyed once triggered.
this.setDead();
}
}
}else if(this.rand.nextInt(15) == 0){
double radius = 0.5 + rand.nextDouble()*0.3;
double angle = rand.nextDouble()*Math.PI*2;
worldObj.spawnParticle(EnumParticleTypes.FLAME, this.posX + radius*Math.cos(angle), this.posY + 0.1, this.posZ + radius*Math.sin(angle), 0, 0, 0);
}
}
@Override
protected void entityInit() {
}
/**
* Return whether this entity should be rendered as on fire.
*/
public boolean canRenderOnFire()
{
return false;
}
}
@@ -0,0 +1,91 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.World;
public class EntityForcefield extends EntityMagicConstruct {
public EntityForcefield(World world) {
super(world);
this.height = 6;
this.width = 6;
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 3, this.posY - 3, this.posZ - 3, this.posX + 3, this.posY + 3, this.posZ + 3));
}
public EntityForcefield(World world, double x, double y, double z, EntityLivingBase caster, int lifetime) {
// y-3 because it needs to be centred on the given position
// Damage multiplier is 1 because forcefields do no damage!
super(world, x, y-3, z, caster, lifetime, 1.0f);
this.height = 6;
this.width = 6;
this.setEntityBoundingBox(new AxisAlignedBB(this.posX - 3, this.posY - 3, this.posZ - 3, this.posX + 3, this.posY + 3, this.posZ + 3));
}
public boolean canBeCollidedWith()
{
return !this.isDead;
}
public AxisAlignedBB getCollisionBox(Entity par1Entity)
{
return par1Entity.getEntityBoundingBox();
}
public void onUpdate(){
super.onUpdate();
if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(3.5, this.posX, this.posY + 3, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
double multiplier = (3.5 - target.getDistance(this.posX, this.posY+3, this.posZ))*0.1;
target.addVelocity((target.posX - this.posX)*multiplier, (target.posY - (this.posY + 3))*multiplier, (target.posZ - this.posZ)*multiplier);
// Player motion is handled on that player's client so needs packets
if(target instanceof EntityPlayerMP){
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
}
}
}
}else{
for(int i=1; i<40; i++){
float brightness = 0.5f + (rand.nextFloat()*0.5f);
double radius = 3;
double yaw = rand.nextDouble()*Math.PI*2;
double pitch = (rand.nextDouble()-0.5)*Math.PI;
// Generates a spherical pattern of particles
Wizardry.proxy.spawnParticle(WizardryParticleType.BRIGHT_DUST, worldObj, this.posX + radius*Math.cos(yaw)*Math.cos(pitch), this.posY + 3 + radius*Math.sin(pitch), this.posZ + radius*Math.sin(yaw)*Math.cos(pitch), 0, 0, 0, 48 + this.rand.nextInt(12), brightness, brightness, 1.0f);
}
}
}
public boolean attackEntityFrom(DamageSource source, float par2){
if(source != null && source.getSourceOfDamage() != null){
// Now works for any source of damage.
source.getSourceOfDamage().playSound(WizardrySounds.SPELL_DEFLECTION, 0.3f, 1.3f);
}
super.attackEntityFrom(source, par2);
return false;
}
/**
* Return whether this entity should be rendered as on fire.
*/
public boolean canRenderOnFire()
{
return false;
}
}
@@ -0,0 +1,91 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
public class EntityFrostSigil extends EntityMagicConstruct {
public EntityFrostSigil(World par1World) {
super(par1World);
this.height = 0.2f;
this.width = 2.0f;
}
public EntityFrostSigil(World par1World, double x, double y, double z, EntityLivingBase caster, float damageMultiplier) {
super(par1World, x, y, z, caster, -1, damageMultiplier);
this.height = 0.2f;
this.width = 2.0f;
}
// Overrides the original to stop the entity moving when it intersects stuff. The default arrow does this to allow
// it to stick in blocks.
public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
{
this.setPosition(par1, par3, par5);
this.setRotation(par7, par8);
}
public void onUpdate(){
super.onUpdate();
if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(1.0d, this.posX, this.posY, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
double velX = target.motionX;
double velY = target.motionY;
double velZ = target.motionZ;
target.attackEntityFrom(this.getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, this.getCaster(), DamageType.FROST) : DamageSource.magic, 8);
// Removes knockback
target.motionX = velX;
target.motionY = velY;
target.motionZ = velZ;
if(!MagicDamage.isEntityImmune(DamageType.FROST, target))
target.addPotionEffect(new PotionEffect(WizardryPotions.frost, 200, 1));
this.playSound(WizardrySounds.SPELL_FREEZE, 1.0f, 1.0f);
// The trap is destroyed once triggered.
this.setDead();
}
}
}else if(this.rand.nextInt(15) == 0){
double radius = 0.5 + rand.nextDouble()*0.3;
double angle = rand.nextDouble()*Math.PI*2;
Wizardry.proxy.spawnParticle(WizardryParticleType.SNOW, worldObj, this.posX + radius*Math.cos(angle), this.posY + 0.1, this.posZ + radius*Math.sin(angle), 0, 0, 0, 40 + rand.nextInt(10));
}
}
@Override
protected void entityInit() {
}
/**
* Return whether this entity should be rendered as on fire.
*/
public boolean canRenderOnFire()
{
return false;
}
}
@@ -0,0 +1,37 @@
package electroblob.wizardry.entity.construct;
import electroblob.wizardry.entity.projectile.EntityIceShard;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.world.World;
public class EntityHailstorm extends EntityMagicConstruct {
public EntityHailstorm(World par1World) {
super(par1World);
this.height = 3.0f;
this.width = 5.0f;
}
public EntityHailstorm(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.height = 3.0f;
this.width = 5.0f;
}
public void onUpdate(){
super.onUpdate();
if(!this.worldObj.isRemote){
//System.out.println(this.rotationYaw);
EntityIceShard iceshard = new EntityIceShard(worldObj, this.posX + rand.nextDouble()*6 - 3, this.posY + rand.nextDouble()*4 - 2, this.posZ + rand.nextDouble()*6 - 3);
iceshard.motionX = Math.cos(Math.toRadians(this.rotationYaw + 90));
iceshard.motionY = -0.6;
iceshard.motionZ = Math.sin(Math.toRadians(this.rotationYaw + 90));
iceshard.setShootingEntity(this.getCaster());
iceshard.damageMultiplier = this.damageMultiplier;
this.worldObj.spawnEntityInWorld(iceshard);
}
}
}
@@ -0,0 +1,183 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.init.SoundEvents;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class EntityHammer extends EntityMagicConstruct {
/** How long the hammer has been falling for. */
public int fallTime;
public EntityHammer(World par1World){
super(par1World);
this.setSize(1.0f, 1.9F);
this.noClip = false;
}
public EntityHammer(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier){
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.setSize(1.0f, 1.9F);
this.motionX = 0.0D;
this.motionY = 0.0D;
this.motionZ = 0.0D;
this.noClip = false;
}
@Override
public boolean isBurning(){
return false;
}
@Override
public boolean canBeCollidedWith(){
return true;
}
@Override
public AxisAlignedBB getCollisionBoundingBox(){
return this.getEntityBoundingBox();
}
@Override
public void onUpdate(){
super.onUpdate();
if(this.ticksExisted % 20 == 1 && !this.onGround && worldObj.isRemote){
// Though this sound does repeat, it stops when it hits the ground.
Wizardry.proxy.playMovingSound(this, WizardrySounds.SPELL_LOOP_LIGHTNING, 3.0f, 1.0f, false);
}
if(this.worldObj.isRemote && this.ticksExisted % 3 == 0){
Wizardry.proxy.spawnParticle(WizardryParticleType.SPARK, worldObj, this.posX - 0.5d + rand.nextDouble(), this.posY + 2*rand.nextDouble(), this.posZ - 0.5d + rand.nextDouble(), 0, 0, 0, 3);
}
if(!this.worldObj.isRemote){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
++this.fallTime;
this.motionY -= 0.03999999910593033D;
this.moveEntity(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.9800000190734863D;
this.motionY *= 0.9800000190734863D;
this.motionZ *= 0.9800000190734863D;
if(this.onGround){
this.motionX *= 0.699999988079071D;
this.motionZ *= 0.699999988079071D;
this.motionY *= -0.5D;
if(this.ticksExisted % 40 == 0){
double seekerRange = 10.0d;
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, this.posX, this.posY+1, this.posZ, worldObj);
// For this spell there is no limit to the amount of secondary targets!
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
if(!worldObj.isRemote){
EntityArc arc = new EntityArc(worldObj);
arc.setEndpointCoords(this.posX, this.posY + this.height - 0.1, this.posZ,
target.posX, target.posY + target.height/2, target.posZ);
worldObj.spawnEntityInWorld(arc);
}else{
for(int j=0;j<8;j++){
Wizardry.proxy.spawnParticle(WizardryParticleType.SPARK, worldObj, target.posX + worldObj.rand.nextFloat() - 0.5, target.getEntityBoundingBox().minY + target.height/2 + worldObj.rand.nextFloat()*2 - 1, target.posZ + worldObj.rand.nextFloat() - 0.5, 0, 0, 0, 3);
worldObj.spawnParticle(EnumParticleTypes.SMOKE_LARGE, target.posX + rand.nextFloat(), target.getEntityBoundingBox().minY + target.height/2 + rand.nextFloat(), target.posZ + rand.nextFloat(), 0, 0, 0);
}
}
target.playSound(WizardrySounds.SPELL_SPARK, 1.0F, rand.nextFloat() * 0.4F + 1.5F);
if(this.getCaster() != null){
WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.SHOCK), 6*damageMultiplier);
WizardryUtilities.applyStandardKnockback(this, target);
}else{
target.attackEntityFrom(DamageSource.magic, 6*damageMultiplier);
}
}
}
}
}
}
}
@Override
public void despawn(){
this.playSound(SoundEvents.ENTITY_GENERIC_EXPLODE, 1.0F, 1.0f);
if(this.worldObj.isRemote){
this.worldObj.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
}
super.despawn();
}
@Override
public void fall(float distance, float damageMultiplier) {
if(worldObj.isRemote){
for(int i=0; i<40; i++){
double particleX = this.posX - 1.0d + 2*rand.nextDouble();
double particleZ = this.posZ - 1.0d + 2*rand.nextDouble();
// Roundabout way of getting a block instance for the block the hammer is standing on (if any).
IBlockState block = worldObj.getBlockState(new BlockPos(this.posX, this.posY-2, this.posZ));
if(block != null){
worldObj.spawnParticle(EnumParticleTypes.BLOCK_DUST, particleX, this.posY, particleZ,
particleX - this.posX, 0, particleZ - this.posZ, Block.getStateId(block));
}
}
}else{
// Just to check the hammer has actually fallen from the sky, rather than the block under it being broken.
if(this.fallDistance > 10){
EntityLightningBolt entitylightning = new EntityLightningBolt(worldObj, this.posX, this.posY, this.posZ, false);
worldObj.addWeatherEffect(entitylightning);
}
}
}
@Override
public void writeEntityToNBT(NBTTagCompound nbttagcompound)
{
super.writeEntityToNBT(nbttagcompound);
nbttagcompound.setByte("Time", (byte)this.fallTime);
}
@Override
public void readEntityFromNBT(NBTTagCompound nbttagcompound)
{
super.readEntityFromNBT(nbttagcompound);
this.fallTime = nbttagcompound.getByte("Time") & 255;
}
@Override
public boolean isInRangeToRenderDist(double distance) {
return true;
}
}
@@ -0,0 +1,85 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
public class EntityHealAura extends EntityMagicConstruct {
public EntityHealAura(World world) {
super(world);
this.height = 1.0f;
this.width = 5.0f;
}
public EntityHealAura(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.height = 1.0f;
this.width = 5.0f;
}
public void onUpdate(){
if(this.ticksExisted % 25 == 1){
this.playSound(WizardrySounds.SPELL_LOOP_SPARKLE, 0.1f, 1.0f);
}
super.onUpdate();
if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(2.5d, this.posX, this.posY, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
if(target.isEntityUndead()){
double velX = target.motionX;
double velY = target.motionY;
double velZ = target.motionZ;
if(this.getCaster() != null){
target.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.RADIANT), 1*damageMultiplier);
}else{
target.attackEntityFrom(DamageSource.magic, 1*damageMultiplier);
}
// Removes knockback
target.motionX = velX;
target.motionY = velY;
target.motionZ = velZ;
}
}else if(target.getHealth() < target.getMaxHealth() && this.ticksExisted % 5 == 0){
target.heal(1*damageMultiplier);
}
}
}else{
for(int i=1; i<3; i++){
float brightness = 0.5f + (rand.nextFloat()*0.5f);
double radius = rand.nextDouble()*2.0;
double angle = rand.nextDouble()*Math.PI*2;
Wizardry.proxy.spawnParticle(WizardryParticleType.SPARKLE, worldObj, this.posX + radius*Math.cos(angle), this.posY, this.posZ + radius*Math.sin(angle), 0, 0.05f, 0, 48 + this.rand.nextInt(12), 1.0f, 1.0f, brightness);
}
}
}
/**
* Return whether this entity should be rendered as on fire.
*/
public boolean canRenderOnFire()
{
return false;
}
}
@@ -0,0 +1,50 @@
package electroblob.wizardry.entity.construct;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.potion.PotionEffect;
import net.minecraft.world.World;
public class EntityIceSpike extends EntityMagicConstruct {
public EntityIceSpike(World world) {
super(world);
this.setSize(0.5f, 1.0f);
}
public EntityIceSpike(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier){
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.setSize(0.5f, 1.0f);
}
public void onUpdate(){
if(lifetime - this.ticksExisted < 15){
this.motionY = -0.01*(this.ticksExisted-(lifetime-15));
}else if(lifetime - this.ticksExisted < 25){
this.motionY = 0;
}else if(lifetime - this.ticksExisted < 28){
this.motionY = 0.25;
}
this.moveEntity(this.motionX, this.motionY, this.motionZ);
if(lifetime - this.ticksExisted == 30) this.playSound(WizardrySounds.SPELL_ICE, 1, 2);
if(!this.worldObj.isRemote){
for(Object entity : this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox())){
if(entity instanceof EntityLivingBase && this.isValidTarget((EntityLivingBase)entity)){
// Potion effect only gets added if the damage succeeded.
if(((EntityLivingBase)entity).attackEntityFrom(MagicDamage.causeDirectMagicDamage(this.getCaster(), DamageType.FROST), 5*this.damageMultiplier))
((EntityLivingBase)entity).addPotionEffect(new PotionEffect(WizardryPotions.frost, 100, 0));
}
}
}
super.onUpdate();
}
}
@@ -0,0 +1,26 @@
package electroblob.wizardry.entity.construct;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.world.World;
public class EntityLightningPulse extends EntityMagicConstruct {
public EntityLightningPulse(World world) {
super(world);
this.setSize(6, 0.2f);
}
public EntityLightningPulse(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.setSize(6, 0.2f);
}
/**
* Return whether this entity should be rendered as on fire.
*/
public boolean canRenderOnFire()
{
return false;
}
}
@@ -0,0 +1,125 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;
public class EntityLightningSigil extends EntityMagicConstruct {
public EntityLightningSigil(World par1World) {
super(par1World);
this.height = 0.2f;
this.width = 2.0f;
}
public EntityLightningSigil(World par1World, double x, double y, double z, EntityLivingBase caster, float damageMultiplier) {
super(par1World, x, y, z, caster, -1, damageMultiplier);
this.height = 0.2f;
this.width = 2.0f;
}
// Overrides the original to stop the entity moving when it intersects stuff. The default arrow does this to allow
// it to stick in blocks.
public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
{
this.setPosition(par1, par3, par5);
this.setRotation(par7, par8);
}
public void onUpdate(){
super.onUpdate();
if(this.ticksExisted > 600 && this.getCaster() == null && !this.worldObj.isRemote){
this.setDead();
}
//if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(1.0d, this.posX, this.posY, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
double velX = target.motionX;
double velY = target.motionY;
double velZ = target.motionZ;
// Only works if target is actually damaged to account for hurtResistantTime
if(target.attackEntityFrom(getCaster() != null ? MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.SHOCK) : DamageSource.magic, 6)){
// Removes knockback
target.motionX = velX;
target.motionY = velY;
target.motionZ = velZ;
this.playSound(WizardrySounds.SPELL_SPARK, 1.0f, 1.0f);
// Secondary chaining effect
double seekerRange = 5.0d;
List<EntityLivingBase> secondaryTargets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, target.posX, target.posY + target.height/2, target.posZ, worldObj);
for(int j=0;j<Math.min(secondaryTargets.size(), 3);j++){
EntityLivingBase secondaryTarget = secondaryTargets.get(j);
if(secondaryTarget != target && this.isValidTarget(secondaryTarget)){
if(!worldObj.isRemote){
EntityArc arc = new EntityArc(worldObj);
arc.setEndpointCoords(target.posX, target.posY + target.height/2, target.posZ,
secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height/2, secondaryTarget.posZ);
worldObj.spawnEntityInWorld(arc);
}else{
for(int k=0;k<8;k++){
Wizardry.proxy.spawnParticle(WizardryParticleType.SPARK, worldObj, secondaryTarget.posX + worldObj.rand.nextFloat() - 0.5, secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height/2 + worldObj.rand.nextFloat()*2 - 1, secondaryTarget.posZ + worldObj.rand.nextFloat() - 0.5, 0, 0, 0, 3);
worldObj.spawnParticle(EnumParticleTypes.SMOKE_LARGE, secondaryTarget.posX + worldObj.rand.nextFloat() - 0.5, secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height/2 + worldObj.rand.nextFloat()*2 - 1, secondaryTarget.posZ + worldObj.rand.nextFloat() - 0.5, 0, 0, 0);
}
}
secondaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F, worldObj.rand.nextFloat() * 0.4F + 1.5F);
secondaryTarget.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.SHOCK), 4);
}
}
// The trap is destroyed once triggered.
this.setDead();
}
}
}
//}
if(this.worldObj.isRemote && this.rand.nextInt(15) == 0){
double radius = 0.5 + rand.nextDouble()*0.3;
double angle = rand.nextDouble()*Math.PI*2;
Wizardry.proxy.spawnParticle(WizardryParticleType.SPARK, worldObj, this.posX + radius*Math.cos(angle), this.posY + 0.1, this.posZ + radius*Math.sin(angle), 0, 0, 0, 3);
}
}
@Override
protected void entityInit() {
}
/**
* Return whether this entity should be rendered as on fire.
*/
public boolean canRenderOnFire()
{
return false;
}
}
@@ -0,0 +1,153 @@
package electroblob.wizardry.entity.construct;
import java.lang.ref.WeakReference;
import java.util.UUID;
import electroblob.wizardry.util.WizardryUtilities;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
/**
* This class is for all inanimate magical constructs which are not projectiles. It was made from scratch
* to provide a unifying superclass for black hole, blizzard, tornado and a few others which all share some
* characteristics. The EntityPlayer instance of the caster, the lifetime and the damage multiplier are stored
* and synced here.
* <p>
* When extending this class, override both constructors. Generally speaking, subclasses of this class are areas
* of effect which deal damage or apply effects over time.
* @since Wizardry 1.0
*/
public abstract class EntityMagicConstruct extends Entity implements IEntityAdditionalSpawnData {
/** The entity that created this construct */
private WeakReference<EntityLivingBase> caster;
/** The UUID of the caster. Note that this is only for loading purposes; during normal updates
* the actual entity instance is stored (so that getEntityByUUID is not called constantly),
* so this will not always be synced (this is why it is private). */
private UUID casterUUID;
/** The time in ticks this magical construct lasts for; defaults to 600 (30 seconds). If this is -1 the construct
* doesn't despawn. */
public int lifetime = 600;
/** The damage multiplier for this construct, determined by the wand with which it was cast. */
public float damageMultiplier = 1.0f;
public EntityMagicConstruct(World par1World) {
super(par1World);
this.height = 1.0f;
this.width = 1.0f;
this.noClip = true;
}
public EntityMagicConstruct(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, float damageMultiplier) {
super(world);
this.height = 1.0f;
this.width = 1.0f;
this.setPosition(x, y, z);
this.caster = new WeakReference<EntityLivingBase>(caster);
this.noClip = true;
this.lifetime = lifetime;
this.damageMultiplier = damageMultiplier;
}
// Overrides the original to stop the entity moving when it intersects stuff. The default arrow does this to allow
// it to stick in blocks.
@Override
public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport)
{
this.setPosition(x, y, z);
this.setRotation(yaw, pitch);
}
public void onUpdate(){
if(this.getCaster() == null && this.casterUUID != null){
Entity entity = WizardryUtilities.getEntityByUUID(worldObj, casterUUID);
if(entity instanceof EntityLivingBase){
this.caster = new WeakReference<EntityLivingBase>((EntityLivingBase)entity);
}
}
if(this.ticksExisted > lifetime && lifetime != -1){
this.despawn();
}
super.onUpdate();
}
/**
* Defaults to just setDead() in EntityMagicConstruct, but is provided to allow subclasses to override this
* e.g. bubble uses it to dismount the entity inside it and play the 'pop' sound before calling super(). You
* should always call super() when overriding this method, in case it changes. There is no need, therefore, to
* call setDead() when overriding.
*/
public void despawn(){
this.setDead();
}
@Override
protected void entityInit() {
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbttagcompound){
casterUUID = nbttagcompound.getUniqueId("casterUUID");
lifetime = nbttagcompound.getInteger("lifetime");
damageMultiplier = nbttagcompound.getFloat("damageMultiplier");
}
@Override
protected void writeEntityToNBT(NBTTagCompound nbttagcompound){
if(this.getCaster() != null){
nbttagcompound.setUniqueId("casterUUID", this.getCaster().getUniqueID());
}
nbttagcompound.setInteger("lifetime", lifetime);
nbttagcompound.setFloat("damageMultiplier", damageMultiplier);
}
@Override
public void writeSpawnData(ByteBuf data){
data.writeInt(lifetime);
}
@Override
public void readSpawnData(ByteBuf data){
lifetime = data.readInt();
}
/**
* Returns the EntityLivingBase that created this construct, or null if it no longer exists. Cases where the
* entity may no longer exist are: entity died or was deleted, mob despawned, player logged out, entity teleported
* to another dimension, or this construct simply had no caster in the first place.
*/
public EntityLivingBase getCaster() {
return caster == null ? null : caster.get();
}
/**
* Shorthand for {@link WizardryUtilities#isValidTarget(Entity, Entity)}, with the owner of this construct as the
* attacker. Also allows subclasses to override it if they wish to do so.
*/
public boolean isValidTarget(Entity target){
return WizardryUtilities.isValidTarget(this.getCaster(), target);
}
@Override
public boolean canRenderOnFire()
{
return false;
}
@Override
public boolean isPushedByWater() {
return false;
}
}
@@ -0,0 +1,184 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryAchievements;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityPig;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class EntityTornado extends EntityMagicConstruct {
private double velX, velZ;
public EntityTornado(World world) {
super(world);
this.height = 8.0f;
this.width = 5.0f;
this.isImmuneToFire = false;
}
public EntityTornado(World world, double x, double y, double z, EntityLivingBase caster, int lifetime, double velX, double velZ, float damageMultiplier) {
super(world, x, y, z, caster, lifetime, damageMultiplier);
this.height = 8.0f;
this.width = 5.0f;
this.velX = velX;
this.velZ = velZ;
this.isImmuneToFire = false;
}
public void onUpdate(){
super.onUpdate();
if(this.ticksExisted % 120 == 1 && worldObj.isRemote){
// Repeat is false so that the sound fades out when the tornado does rather than stopping suddenly
Wizardry.proxy.playMovingSound(this, WizardrySounds.SPELL_LOOP_WIND, 1.0f, 1.0f, false);
}
this.moveEntity(velX, motionY, velZ);
BlockPos pos = new BlockPos(this);
int y = WizardryUtilities.getNearestFloorLevelC(worldObj, pos.up(3), 5);
pos = new BlockPos(pos.getX(), y, pos.getZ());
if(this.worldObj.getBlockState(pos).getMaterial() == Material.LAVA){
// Fire tornado!
this.setFire(5);
}
if(!this.worldObj.isRemote){
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(4.0d, this.posX, this.posY, this.posZ, this.worldObj);
for(EntityLivingBase target : targets){
if(this.isValidTarget(target)){
double velY = target.motionY;
double dx = this.posX-target.posX > 0? 0.5 - (this.posX-target.posX)/8 : -0.5 - (this.posX-target.posX)/8;
double dz = this.posZ-target.posZ > 0? 0.5 - (this.posZ-target.posZ)/8 : -0.5 - (this.posZ-target.posZ)/8;
if(this.isBurning()){
target.setFire(4);
}
if(this.getCaster() != null){
target.attackEntityFrom(MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.MAGIC), 1*damageMultiplier);
}else{
target.attackEntityFrom(DamageSource.magic, 1*damageMultiplier);
}
target.motionX = dx;
target.motionY = velY+0.2;
target.motionZ = dz;
// Player motion is handled on that player's client so needs packets
if(target instanceof EntityPlayerMP){
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
}
// The 'Not Again...' achievement
if(target instanceof EntityPig && WizardryUtilities.getRider(target) instanceof EntityPlayer){
((EntityPlayer)WizardryUtilities.getRider(target)).addStat(WizardryAchievements.pig_tornado);
}
}
}
}else{
for(int i=1; i<10; i++){
double yPos = rand.nextDouble()*8;
int blockX = (int)this.posX - 2 + this.rand.nextInt(4);
int blockZ = (int)this.posZ - 2 + this.rand.nextInt(4);
BlockPos pos1 = new BlockPos(blockX, this.posY+3, blockZ);
int blockY = WizardryUtilities.getNearestFloorLevelC(worldObj, pos1, 5) - 1;
pos1 = new BlockPos(pos1.getX(), blockY, pos1.getZ());
IBlockState block = this.worldObj.getBlockState(pos1);
// If the block it found was air or something it can't pick up, it makes a best guess based on the biome.
if(!canTornadoPickUpBitsOf(block)){
block = worldObj.getBiome(pos1).topBlock;
}
Wizardry.proxy.spawnTornadoParticle(worldObj, this.posX, this.posY + yPos, this.posZ, this.velX, this.velZ, yPos/3 + 0.5d, 100, block, pos1);
Wizardry.proxy.spawnTornadoParticle(worldObj, this.posX, this.posY + yPos, this.posZ, this.velX, this.velZ, yPos/3 + 0.5d, 100, block, pos1);
// Sometimes spawns leaf particles if the block is leaves
if(block.getMaterial() == Material.LEAVES && this.rand.nextInt(3) == 0){
double yPos1 = rand.nextDouble()*8;
Wizardry.proxy.spawnParticle(WizardryParticleType.LEAF, worldObj, this.posX + (rand.nextDouble()*2-1)*(yPos1/3 + 0.5d), this.posY + yPos1, this.posZ + (rand.nextDouble()*2-1)*(yPos1/3 + 0.5d), 0, -0.05, 0, 40 + rand.nextInt(10));
}
// Sometimes spawns snow particles if the block is snow
if(block.getMaterial() == Material.SNOW || block.getMaterial() == Material.CRAFTED_SNOW && this.rand.nextInt(3) == 0){
double yPos1 = rand.nextDouble()*8;
Wizardry.proxy.spawnParticle(WizardryParticleType.SNOW, worldObj, this.posX + (rand.nextDouble()*2-1)*(yPos1/3 + 0.5d), this.posY + yPos1, this.posZ + (rand.nextDouble()*2-1)*(yPos1/3 + 0.5d), 0, -0.02, 0, 40 + rand.nextInt(10));
}
}
}
}
private static boolean canTornadoPickUpBitsOf(IBlockState block){
Material material = block.getMaterial();
return material == Material.CRAFTED_SNOW
|| material == Material.GROUND
|| material == Material.GRASS
|| material == Material.LAVA
|| material == Material.SAND
|| material == Material.SNOW
|| material == Material.WATER
|| material == Material.PLANTS
|| material == Material.LEAVES
|| material == Material.VINE;
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbttagcompound) {
super.readEntityFromNBT(nbttagcompound);
velX = nbttagcompound.getDouble("velX");
velZ = nbttagcompound.getDouble("velZ");
}
@Override
protected void writeEntityToNBT(NBTTagCompound nbttagcompound) {
super.writeEntityToNBT(nbttagcompound);
nbttagcompound.setDouble("velX", velX);
nbttagcompound.setDouble("velZ", velZ);
}
@Override
public void writeSpawnData(ByteBuf data) {
super.writeSpawnData(data);
data.writeDouble(velX);
data.writeDouble(velZ);
}
@Override
public void readSpawnData(ByteBuf data) {
super.readSpawnData(data);
this.velX = data.readDouble();
this.velZ = data.readDouble();
}
}