diff --git a/src/main/java/noppes/npcs/DataStats.java b/src/main/java/noppes/npcs/DataStats.java index 9c45576e7..0d085d823 100644 --- a/src/main/java/noppes/npcs/DataStats.java +++ b/src/main/java/noppes/npcs/DataStats.java @@ -53,6 +53,7 @@ public class DataStats { public boolean playBurstSound = true; // Internal Only public byte aimType = 0; public boolean projectilesKeepTerrain = false; + public boolean projectileInvincibility = true; public EnumCreatureAttribute creatureType = EnumCreatureAttribute.UNDEFINED; @@ -116,6 +117,7 @@ public class DataStats { compound.setBoolean("FiringSoundBegin", onSoundBegin); compound.setByte("AimType", aimType); compound.setBoolean("ProjectilesKeepTerrain", projectilesKeepTerrain); + compound.setBoolean("ProjectileInvincibility", projectileInvincibility); if (pTrail == EnumParticleType.Custom) compound.setTag("pCustom", pCustom.writeToNBT()); if (pEffect == EnumPotionType.Fire) @@ -185,6 +187,10 @@ public class DataStats { onSoundBegin = compound.getBoolean("FiringSoundBegin"); aimType = compound.getByte("AimType"); projectilesKeepTerrain = compound.getBoolean("ProjectilesKeepTerrain"); + if (compound.hasKey("ProjectileInvincibility")) + projectileInvincibility = compound.getBoolean("ProjectileInvincibility"); + else + projectileInvincibility = true; if (pTrail == EnumParticleType.Custom) pCustom = ScriptParticle.fromNBT(compound.getCompoundTag("pCustom")); if (pEffect == EnumPotionType.Fire) diff --git a/src/main/java/noppes/npcs/client/gui/SubGuiNpcRangeProperties.java b/src/main/java/noppes/npcs/client/gui/SubGuiNpcRangeProperties.java index 428e83016..cbd348eaa 100644 --- a/src/main/java/noppes/npcs/client/gui/SubGuiNpcRangeProperties.java +++ b/src/main/java/noppes/npcs/client/gui/SubGuiNpcRangeProperties.java @@ -72,6 +72,9 @@ public class SubGuiNpcRangeProperties extends SubGuiInterface implements ITextfi addButton(new GuiNpcButton(9, guiLeft + 100, y += 22, 70, 20, new String[]{"gui.no", "gui.yes", "stats.onShot"}, stats.aimType)); addLabel(new GuiNpcLabel(9, "stats.aimWhileShooting", guiLeft + 5, y + 5)); + addButton(new GuiNpcButton(11, guiLeft + 100, y += 22, 70, 20, new String[]{"stats.allowed", "stats.ignored"}, stats.projectileInvincibility ? 0 : 1)); + addLabel(new GuiNpcLabel(11, "stats.invincibility", guiLeft + 5, y + 5)); + addButton(new GuiNpcButton(66, guiLeft + 190, guiTop + 190, 60, 20, "gui.done")); } @@ -119,6 +122,8 @@ public class SubGuiNpcRangeProperties extends SubGuiInterface implements ITextfi close(); } else if (id == 9) { stats.aimType = (byte) ((GuiNpcButton) guibutton).getValue(); + } else if (id == 11) { + stats.projectileInvincibility = ((GuiNpcButton) guibutton).getValue() == 0; } } diff --git a/src/main/java/noppes/npcs/entity/EntityProjectile.java b/src/main/java/noppes/npcs/entity/EntityProjectile.java index 5391ff487..e25a66083 100644 --- a/src/main/java/noppes/npcs/entity/EntityProjectile.java +++ b/src/main/java/noppes/npcs/entity/EntityProjectile.java @@ -66,6 +66,7 @@ public class EntityProjectile extends EntityThrowable { public boolean canBePickedUp = false; public boolean destroyedOnEntityHit = true; + private boolean ignoreInvincibility = false; /** * Is the entity that throws this 'thing' (snowball, ender pearl, eye of ender or potion) @@ -464,13 +465,24 @@ public class EntityProjectile extends EntityThrowable { didDBCAttack = true; } } - if (movingobjectposition.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()), damage)) { + EntityLivingBase entityliving = movingobjectposition.entityHit instanceof EntityLivingBase ? (EntityLivingBase) movingobjectposition.entityHit : null; + int prevHurtResistantTime = -1; + if (ignoreInvincibility && entityliving != null) { + prevHurtResistantTime = entityliving.hurtResistantTime; + entityliving.hurtResistantTime = 0; + } + + boolean attacked = movingobjectposition.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()), damage); + + if (!attacked && ignoreInvincibility && entityliving != null) { + entityliving.hurtResistantTime = prevHurtResistantTime; + } + + if (attacked) { if (didDBCAttack) DBCAddon.instance.doDBCDamage(npc, this.damage, movingobjectposition.entityHit); - if (movingobjectposition.entityHit instanceof EntityLivingBase && (this.isArrow() || this.sticksToWalls())) { - EntityLivingBase entityliving = (EntityLivingBase) movingobjectposition.entityHit; - + if (entityliving != null && (this.isArrow() || this.sticksToWalls())) { if (!this.worldObj.isRemote) { entityliving.setArrowCountInEntity(entityliving.getArrowCountInEntity() + 1); } @@ -496,10 +508,10 @@ public class EntityProjectile extends EntityThrowable { } } - if (this.effect != EnumPotionType.None && movingobjectposition.entityHit instanceof EntityLivingBase) { + if (this.effect != EnumPotionType.None && entityliving != null) { if (this.effect != EnumPotionType.Fire) { int p = this.getPotionEffect(effect); - ((EntityLivingBase) movingobjectposition.entityHit).addPotionEffect(new PotionEffect(p, this.duration * 20, this.amplify)); + entityliving.addPotionEffect(new PotionEffect(p, this.duration * 20, this.amplify)); } else { movingobjectposition.entityHit.setFire(duration); } @@ -686,6 +698,7 @@ public class EntityProjectile extends EntityThrowable { par1NBTTagCompound.setByte("Spins", this.dataWatcher.getWatchableObjectByte(29)); par1NBTTagCompound.setByte("Sticks", this.dataWatcher.getWatchableObjectByte(30)); par1NBTTagCompound.setByte("trailCustom", this.dataWatcher.getWatchableObjectByte(31)); + par1NBTTagCompound.setBoolean("IgnoreInvincibility", ignoreInvincibility); } /** @@ -723,6 +736,9 @@ public class EntityProjectile extends EntityThrowable { byte trailCustom = par1NBTTagCompound.getByte("trailCustom"); this.dataWatcher.updateObject(31, Byte.valueOf(trailCustom)); } + if (par1NBTTagCompound.hasKey("IgnoreInvincibility")) { + this.ignoreInvincibility = par1NBTTagCompound.getBoolean("IgnoreInvincibility"); + } if (this.throwerName != null && this.throwerName.length() == 0) { this.throwerName = null; @@ -818,6 +834,7 @@ public class EntityProjectile extends EntityThrowable { setIs3D(stats.pRender3D); this.setRotating(stats.pSpin); this.setStickInWall(stats.pStick); + this.ignoreInvincibility = !stats.projectileInvincibility; } public void setParticleEffect(EnumParticleType type) { diff --git a/src/main/java/noppes/npcs/scripted/entity/ScriptNpc.java b/src/main/java/noppes/npcs/scripted/entity/ScriptNpc.java index 66a0c1c1b..53f26f5d9 100644 --- a/src/main/java/noppes/npcs/scripted/entity/ScriptNpc.java +++ b/src/main/java/noppes/npcs/scripted/entity/ScriptNpc.java @@ -342,6 +342,14 @@ public class ScriptNpc extends ScriptLiving imp return npc.stats.projectilesKeepTerrain; } + public void setProjectileInvincibility(boolean allowed) { + npc.stats.projectileInvincibility = allowed; + } + + public boolean getProjectileInvincibility() { + return npc.stats.projectileInvincibility; + } + /** * @param message The message the npc will say diff --git a/src/main/resources/assets/customnpcs/lang/en_US.lang b/src/main/resources/assets/customnpcs/lang/en_US.lang index 286f8446f..57dc34cdc 100644 --- a/src/main/resources/assets/customnpcs/lang/en_US.lang +++ b/src/main/resources/assets/customnpcs/lang/en_US.lang @@ -472,6 +472,9 @@ stats.regenhealth=Health Regen stats.combatregen=Combat Regen stats.naturallydespawns=Naturally Despawn stats.aimWhileShooting=Aim While Shooting +stats.invincibility=Invincibility +stats.allowed=ALLOWED +stats.ignored=IGNORED stats.potionImmune=PotionImmune stats.attackInvisible=Attack Invi stats.never=Never diff --git a/src/main/resources/assets/customnpcs/lang/ru_RU.lang b/src/main/resources/assets/customnpcs/lang/ru_RU.lang index 54d0c2cf4..0b286b3ae 100644 --- a/src/main/resources/assets/customnpcs/lang/ru_RU.lang +++ b/src/main/resources/assets/customnpcs/lang/ru_RU.lang @@ -271,6 +271,9 @@ stats.regenhealth=Реген. здоровья stats.combatregen=Реген. в бою stats.naturallydespawns=Естественное исчезновение stats.aimWhileShooting=Прицелив. при стрельбе +stats.invincibility=Invincibility +stats.allowed=ALLOWED +stats.ignored=IGNORED stats.potionImmune=Иммунитет к зельям stats.attackInvisible=Атаковать невидимых diff --git a/src/main/resources/assets/customnpcs/lang/zh_CN.lang b/src/main/resources/assets/customnpcs/lang/zh_CN.lang index e5d0b172a..7831cf590 100644 --- a/src/main/resources/assets/customnpcs/lang/zh_CN.lang +++ b/src/main/resources/assets/customnpcs/lang/zh_CN.lang @@ -395,6 +395,9 @@ stats.regenhealth=正常生命恢复 stats.combatregen=受攻击生命恢复 stats.naturallydespawns=自然消失 stats.aimWhileShooting=射击时瞄准 +stats.invincibility=无敌帧 +stats.allowed=允许 +stats.ignored=忽略 stats.potionImmune=免疫药水 stats.attackInvisible=攻击隐藏 stats.never=从不