diff --git a/src/main/java/electroblob/wizardry/spell/Fangs.java b/src/main/java/electroblob/wizardry/spell/Fangs.java index 362d3894..c7367e62 100644 --- a/src/main/java/electroblob/wizardry/spell/Fangs.java +++ b/src/main/java/electroblob/wizardry/spell/Fangs.java @@ -88,7 +88,9 @@ public class Fangs extends Spell { Integer y = BlockUtils.getNearestFloor(world, new BlockPos(vec), 5); if(y != null){ - world.spawnEntity(new EntityEvokerFangs(world, vec.x, y, vec.z, yaw, i, caster)); // null is fine here + EntityEvokerFangs fangs = new EntityEvokerFangs(world, vec.x, y, vec.z, yaw, i, caster); // null is fine here + fangs.getEntityData().setFloat(SpellThrowable.DAMAGE_MODIFIER_NBT_KEY, modifiers.get(SpellModifiers.POTENCY)); + world.spawnEntity(fangs); flag = true; } } diff --git a/src/main/java/electroblob/wizardry/spell/ShulkerBullet.java b/src/main/java/electroblob/wizardry/spell/ShulkerBullet.java index 1eb275c0..d2c57b88 100644 --- a/src/main/java/electroblob/wizardry/spell/ShulkerBullet.java +++ b/src/main/java/electroblob/wizardry/spell/ShulkerBullet.java @@ -78,7 +78,7 @@ public class ShulkerBullet extends Spell { if(caster != null){ world.spawnEntity(new EntityShulkerBullet(world, caster, target, direction.getAxis())); }else{ - // Can't use the normal constructor because doesn't accept null for the owner + // Can't use the normal constructor because it doesn't accept null for the owner EntityShulkerBullet bullet = new EntityShulkerBullet(world); bullet.setLocationAndAngles(x, y, z, bullet.rotationYaw, bullet.rotationPitch); @@ -94,6 +94,8 @@ public class ShulkerBullet extends Spell { NBTExtras.storeTagSafely(nbt, "Target", targetTag); bullet.readFromNBT(nbt); // LOL I just modified private fields without reflection + bullet.getEntityData().setFloat(SpellThrowable.DAMAGE_MODIFIER_NBT_KEY, modifiers.get(SpellModifiers.POTENCY)); + world.spawnEntity(bullet); } } diff --git a/src/main/java/electroblob/wizardry/spell/SpellThrowable.java b/src/main/java/electroblob/wizardry/spell/SpellThrowable.java index 7f3b0338..06201ddd 100644 --- a/src/main/java/electroblob/wizardry/spell/SpellThrowable.java +++ b/src/main/java/electroblob/wizardry/spell/SpellThrowable.java @@ -2,8 +2,11 @@ package electroblob.wizardry.spell; import electroblob.wizardry.Wizardry; import electroblob.wizardry.entity.living.ISpellCaster; +import electroblob.wizardry.integration.DamageSafetyChecker; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.util.EntityUtils; +import electroblob.wizardry.util.MagicDamage; +import electroblob.wizardry.util.MagicDamage.DamageType; import electroblob.wizardry.util.SpellModifiers; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; @@ -12,9 +15,13 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.projectile.EntityThrowable; import net.minecraft.item.EnumAction; import net.minecraft.tileentity.TileEntityDispenser; +import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; +import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.util.function.BiFunction; @@ -39,8 +46,14 @@ import java.util.function.BiFunction; * @since Wizardry 4.2.8 */ // TODO: Use events to make these projectiles seek targets when the caster is wearing a ring of attraction (is this possible?) +@EventBusSubscriber public class SpellThrowable extends Spell { + /** NBT key for storing a damage modifier in an external entity (i.e. from vanilla or another mod). Entities with a + * float value stored under this key will have their damage dealt multiplied by that value. This is not just for + * projectiles; it will work for any entity that uses a damage source with itself as the immediate source. */ + public static final String DAMAGE_MODIFIER_NBT_KEY = Wizardry.MODID + "DamageModifier"; + private static final float LAUNCH_Y_OFFSET = 0.1f; protected final BiFunction projectileFactory; @@ -75,6 +88,7 @@ public class SpellThrowable extends Spell { float velocity = calculateVelocity(modifiers, caster.getEyeHeight() - LAUNCH_Y_OFFSET); T projectile = projectileFactory.apply(world, caster); projectile.shoot(caster, caster.rotationPitch, caster.rotationYaw, 0.0f, velocity, 1.0f); + projectile.getEntityData().setFloat(DAMAGE_MODIFIER_NBT_KEY, modifiers.get(SpellModifiers.POTENCY)); addProjectileExtras(projectile, caster, modifiers); world.spawnEntity(projectile); } @@ -139,4 +153,35 @@ public class SpellThrowable extends Spell { */ protected void addProjectileExtras(T projectile, EntityLivingBase caster, SpellModifiers modifiers){} + @SubscribeEvent + public static void onLivingAttackEvent(LivingAttackEvent event){ + + // TODO: Annoyingly, wither skulls apply 'direct' damage from their shooter so they won't be recognised here + if(!(event.getSource() instanceof MagicDamage)){ // Prevent infinite looping + + float damageModifier = event.getSource().getImmediateSource().getEntityData().getFloat(DAMAGE_MODIFIER_NBT_KEY); + + // Really, we just want to increase the damage without modifying the source, but that would cause an + // infinite loop so we need some way of identifying it - the easiest way is to use MagicDamage, which fits + // quite nicely since we can only get here if the entity was from a spell anyway + if(damageModifier > 0){ + + Entity projectile = event.getSource().getImmediateSource(); + Entity shooter = event.getSource().getTrueSource(); + + DamageSource newSource = shooter == projectile + ? MagicDamage.causeDirectMagicDamage(projectile, DamageType.MAGIC) + : MagicDamage.causeIndirectMagicDamage(projectile, shooter, DamageType.MAGIC); + + // Copy over any relevant 'attributes' the original DamageSource might have had. + if(event.getSource().isExplosion()) newSource.setExplosion(); + if(event.getSource().isFireDamage()) newSource.setFireDamage(); + if(event.getSource().isProjectile()) newSource.setProjectile(); + + DamageSafetyChecker.attackEntitySafely(event.getEntity(), newSource, + event.getAmount() * damageModifier, event.getSource(), true); + } + } + } + } \ No newline at end of file