/**
Copyright (C) <2017> <coolAlias>
This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such,
you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package zeldaswordskills.entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.util.DamageSource;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import zeldaswordskills.api.damage.DamageUtils.DamageSourceBaseIndirect;
import zeldaswordskills.api.damage.EnumDamageType;
/**
*
* Custom lightning bolt spawned by Ether Medallion targets a single entity only
*
*/
public class EntityEtherLightning extends EntityLightningBolt
{
/** Copies of EntityLightningBolt's private fields */
private int lightningState, boltLivingTime;
/** Entity responsible for spawning the lightning bolt */
protected final EntityLivingBase thrower;
/** Entity targeted by the lightning bolt; set to null after first strike */
protected EntityLivingBase target;
public EntityEtherLightning(World world, EntityLivingBase thrower, EntityLivingBase target, double posX, double posY, double posZ) {
super(world, posX, posY, posZ);
this.thrower = thrower;
this.target = target;
this.setLocationAndAngles(posX, posY, posZ, 0.0F, 0.0F);
this.lightningState = 2;
this.boltVertex = this.rand.nextLong();
this.boltLivingTime = this.rand.nextInt(3) + 1;
if (!world.isRemote && world.getGameRules().getBoolean("doFireTick") && (world.getDifficulty() == EnumDifficulty.NORMAL || world.getDifficulty() == EnumDifficulty.HARD) && world.isAreaLoaded(new BlockPos(this), 10)) {
extinguishFire(world);
}
}
@Override
public void onUpdate() {
super.onEntityUpdate(); // bypass super.onUpdate
if (lightningState == 2) {
worldObj.playSoundEffect(posX, posY, posZ, "ambient.weather.thunder", 10000.0F, 0.8F + rand.nextFloat() * 0.2F);
worldObj.playSoundEffect(posX, posY, posZ, "random.explode", 2.0F, 0.5F + rand.nextFloat() * 0.2F);
}
--lightningState;
if (lightningState < 0) {
if (boltLivingTime == 0) {
setDead();
} else if (lightningState < -rand.nextInt(10)) {
--boltLivingTime;
lightningState = 1;
boltVertex = rand.nextLong();
}
}
if (lightningState >= 0) {
if (worldObj.isRemote) {
worldObj.setLastLightningBolt(2);
} else if (target != null) {
int strength = (worldObj.isRaining() ? 20 : 0) + (worldObj.isThundering() ? 30 : 0);
// 15 to 35 damage, or 1/3 that for entities on the ground
float damage = 15.0F + rand.nextInt(11) + (strength * 0.2F);
// TODO many ground-based targets are not on the ground... should
// max damage be restricted to actual registered flying entities only?
if (target.onGround) {
damage /= 3.0F;
}
int time = 600 + (strength > 0 || !target.onGround ? rand.nextInt(10) + rand.nextInt(Math.max(1, strength)) + 10 : 0);
DamageSource source = new DamageSourceBaseIndirect(DamageSource.lightningBolt.damageType, this, this.thrower, true, EnumDamageType.SHOCK).setMagicDamage().setDamageBypassesArmor();
if (time > 0) {
((DamageSourceBaseIndirect) source).setStunDamage(time, 1, true);
}
target.attackEntityFrom(source, damage);
if (!net.minecraftforge.event.ForgeEventFactory.onEntityStruckByLightning(target, this)) {
target.onStruckByLightning(this);
}
target = null; // prevent processing again, since lightning can apparently strike 2-3 times per entity
}
}
}
/**
* Hack to put out any fires caused by EntityLightningBolt constructor
*/
private void extinguishFire(World world) {
BlockPos centerPos = new BlockPos(this);
for (int i = -1; i < 2; ++i) {
for (int j = -1; j < 2; ++j) {
for (int k = -1; k < 2; ++k) {
BlockPos pos = centerPos.add(i, j, k);
if (world.getBlockState(pos).getBlock() == Blocks.fire) {
world.setBlockToAir(pos);
}
}
}
}
}
}