Damage modifier support for vanilla entities (throwables, shulker bullet and fangs)

This commit is contained in:
Electroblob77
2020-06-30 15:11:27 +01:00
parent 6a8951ab39
commit 148f527504
3 changed files with 51 additions and 2 deletions
@@ -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;
}
}
@@ -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);
}
}
@@ -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<T extends EntityThrowable> 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<World, EntityLivingBase, T> projectileFactory;
@@ -75,6 +88,7 @@ public class SpellThrowable<T extends EntityThrowable> 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<T extends EntityThrowable> 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);
}
}
}
}