Search in sources :

Example 6 with CombatDamageSource

use of jackiecrazy.wardance.api.CombatDamageSource in project WarDance by Jackiecrazy.

the class ShadowlessKick method kick.

private boolean kick(LivingEntity caster, SkillData stats) {
    LivingEntity target = GeneralUtils.raytraceLiving(caster, distance());
    if (target != null) {
        CombatData.getCap(target).consumePosture(caster, 2);
        if (caster instanceof PlayerEntity && caster.level instanceof ServerWorld) {
            double d0 = (double) (-MathHelper.sin(caster.yRot * ((float) Math.PI / 180F)));
            double d1 = (double) MathHelper.cos(caster.yRot * ((float) Math.PI / 180F));
            ((ServerWorld) caster.level).sendParticles(ParticleTypes.EXPLOSION, caster.getX() + d0, caster.getY(0.5D), caster.getZ() + d1, 0, d0, 0.0D, d1, 0.0D);
        }
        target.hurt(new CombatDamageSource("fallingBlock", caster).setDamageTyping(CombatDamageSource.TYPE.PHYSICAL).setProcSkillEffects(true).setProcNormalEffects(false).setProcAttackEffects(true).setKnockbackPercentage(0.7f), 1);
        if (target.getLastHurtByMob() == null)
            target.setLastHurtByMob(caster);
        stats.setArbitraryFloat(stats.getArbitraryFloat() + 1);
        if (stats.getArbitraryFloat() >= 6) {
            markUsed(caster);
            caster.level.playSound(null, caster.getX(), caster.getY(), caster.getZ(), SoundEvents.DRAGON_FIREBALL_EXPLODE, SoundCategory.PLAYERS, 0.5f + WarDance.rand.nextFloat() * 0.5f, 0.5f + WarDance.rand.nextFloat() * 0.5f);
            return false;
        }
        caster.level.playSound(null, caster.getX(), caster.getY(), caster.getZ(), SoundEvents.ZOMBIE_ATTACK_WOODEN_DOOR, SoundCategory.PLAYERS, 0.25f + WarDance.rand.nextFloat() * 0.5f, 0.5f + WarDance.rand.nextFloat() * 0.5f);
        return true;
    }
    return false;
}
Also used : LivingEntity(net.minecraft.entity.LivingEntity) ServerWorld(net.minecraft.world.server.ServerWorld) CombatDamageSource(jackiecrazy.wardance.api.CombatDamageSource) PlayerEntity(net.minecraft.entity.player.PlayerEntity)

Example 7 with CombatDamageSource

use of jackiecrazy.wardance.api.CombatDamageSource in project WarDance by Jackiecrazy.

the class CombatHandler method pain.

@SubscribeEvent(priority = EventPriority.HIGHEST)
public static void pain(LivingHurtEvent e) {
    if (GeneralConfig.debug)
        WarDance.LOGGER.debug("damage from " + e.getSource() + " received with amount " + e.getAmount());
    LivingEntity uke = e.getEntityLiving();
    uke.removeEffect(WarEffects.DISTRACTION.get());
    uke.removeEffect(WarEffects.FEAR.get());
    uke.removeEffect(WarEffects.SLEEP.get());
    LivingEntity kek = null;
    DamageSource ds = e.getSource();
    if (uke.hasEffect(WarEffects.VULNERABLE.get()) && !CombatUtils.isPhysicalAttack(ds))
        e.setAmount(e.getAmount() + uke.getEffect(WarEffects.VULNERABLE.get()).getAmplifier() + 1);
    if (ds.getDirectEntity() instanceof LivingEntity) {
        kek = (LivingEntity) ds.getDirectEntity();
    }
    uke.getAttribute(Attributes.ARMOR).removeModifier(uuid);
    uke.getAttribute(Attributes.ARMOR).removeModifier(uuid2);
    if (ds instanceof CombatDamageSource) {
        float mult = -((CombatDamageSource) ds).getArmorReductionPercentage();
        if (mult != 0) {
            AttributeModifier armor = new AttributeModifier(uuid2, "temporary armor multiplier", mult, AttributeModifier.Operation.MULTIPLY_TOTAL);
            uke.getAttribute(Attributes.ARMOR).addTransientModifier(armor);
        }
    }
    ItemStack ukemain = uke.getMainHandItem();
    ItemStack ukeoff = uke.getOffhandItem();
    if (ukemain.getCapability(CombatManipulator.CAP).isPresent()) {
        ICombatItemCapability icic = ukemain.getCapability(CombatManipulator.CAP).resolve().get();
        e.setAmount(icic.onBeingHurt(e.getSource(), uke, ukemain, e.getAmount()));
    }
    if (ukeoff.getCapability(CombatManipulator.CAP).isPresent()) {
        ICombatItemCapability icic = ukeoff.getCapability(CombatManipulator.CAP).resolve().get();
        e.setAmount(icic.onBeingHurt(e.getSource(), uke, ukeoff, e.getAmount()));
    }
    ICombatCapability cap = CombatData.getCap(uke);
    cap.setSpiritGrace(ResourceConfig.spiritCD);
    cap.setAdrenalineCooldown(CombatConfig.adrenaline);
    SubtleBonusHandler.update = true;
    StealthUtils.Awareness awareness = StealthUtils.getAwareness(kek, uke);
    if (ds.getEntity() instanceof LivingEntity) {
        LivingEntity seme = ((LivingEntity) ds.getEntity());
        if (seme.getMainHandItem().getCapability(CombatManipulator.CAP).isPresent()) {
            ICombatItemCapability icic = seme.getMainHandItem().getCapability(CombatManipulator.CAP).resolve().get();
            e.setAmount(icic.hurtStart(e.getSource(), seme, uke, seme.getMainHandItem(), e.getAmount()) * icic.damageMultiplier(seme, uke, seme.getMainHandItem()));
            AttributeModifier armor = new AttributeModifier(uuid, "temporary armor removal", -icic.armorIgnoreAmount(e.getSource(), seme, uke, seme.getMainHandItem(), e.getAmount()), AttributeModifier.Operation.ADDITION);
            uke.getAttribute(Attributes.ARMOR).addTransientModifier(armor);
        }
        if (CombatUtils.isPhysicalAttack(e.getSource())) {
            if (awareness != StealthUtils.Awareness.ALERT) {
                e.setAmount((float) (e.getAmount() * CombatUtils.getDamageMultiplier(awareness, CombatUtils.getAttackingItemStack(ds))));
            }
            cap.setMightGrace(0);
        }
        double luckDiff = WarDance.rand.nextFloat() * (GeneralUtils.getAttributeValueSafe(seme, Attributes.LUCK)) - WarDance.rand.nextFloat() * (GeneralUtils.getAttributeValueSafe(uke, Attributes.LUCK));
        e.setAmount(e.getAmount() + (float) luckDiff * GeneralConfig.luck);
    }
    if (cap.getStaggerTime() > 0 && !cap.isFirstStaggerStrike()) {
        e.setAmount(e.getAmount() * CombatConfig.staggerDamage);
        // fatality!
        if (ds.getEntity() instanceof LivingEntity) {
            LivingEntity seme = ((LivingEntity) ds.getEntity());
            if (seme.level instanceof ServerWorld) {
                ((ServerWorld) seme.level).sendParticles(ParticleTypes.ANGRY_VILLAGER, uke.getX(), uke.getY(), uke.getZ(), 5, uke.getBbWidth(), uke.getBbHeight(), uke.getBbWidth(), 0.5f);
            }
            seme.level.playSound(null, uke.getX(), uke.getY(), uke.getZ(), SoundEvents.GENERIC_BIG_FALL, SoundCategory.PLAYERS, 0.25f + WarDance.rand.nextFloat() * 0.5f, 0.75f + WarDance.rand.nextFloat() * 0.5f);
        }
    } else {
        // unfatality!
        e.setAmount(e.getAmount() * CombatConfig.unStaggerDamage);
    }
}
Also used : LivingEntity(net.minecraft.entity.LivingEntity) ServerWorld(net.minecraft.world.server.ServerWorld) ICombatCapability(jackiecrazy.wardance.capability.resources.ICombatCapability) StealthUtils(jackiecrazy.wardance.utils.StealthUtils) CombatDamageSource(jackiecrazy.wardance.api.CombatDamageSource) ICombatItemCapability(jackiecrazy.wardance.capability.weaponry.ICombatItemCapability) CombatDamageSource(jackiecrazy.wardance.api.CombatDamageSource) AttributeModifier(net.minecraft.entity.ai.attributes.AttributeModifier) ItemStack(net.minecraft.item.ItemStack) SubscribeEvent(net.minecraftforge.eventbus.api.SubscribeEvent)

Example 8 with CombatDamageSource

use of jackiecrazy.wardance.api.CombatDamageSource in project WarDance by Jackiecrazy.

the class ShieldBash method performEffect.

protected void performEffect(LivingEntity caster, LivingEntity target) {
    final ICombatCapability cap = CombatData.getCap(caster);
    SkillUtils.auxAttack(caster, target, new CombatDamageSource("player", caster).setProcNormalEffects(false).setProcAttackEffects(true).setProcSkillEffects(true).setAttackingHand(Hand.OFF_HAND).setDamageTyping(CombatDamageSource.TYPE.PHYSICAL).setDamageDealer(caster.getMainHandItem()), 0, cap.consumeBarrier(cap.getBarrier()));
    cap.setBarrierCooldown(cap.getBarrierCooldown() / 2);
}
Also used : ICombatCapability(jackiecrazy.wardance.capability.resources.ICombatCapability) CombatDamageSource(jackiecrazy.wardance.api.CombatDamageSource)

Example 9 with CombatDamageSource

use of jackiecrazy.wardance.api.CombatDamageSource in project WarDance by Jackiecrazy.

the class CombatHandler method parry.

// because compat with BHT...
@SubscribeEvent(priority = EventPriority.LOWEST)
public static void parry(final LivingAttackEvent e) {
    if (!e.getEntityLiving().level.isClientSide && e.getSource() != null && CombatUtils.isPhysicalAttack(e.getSource())) {
        LivingEntity uke = e.getEntityLiving();
        if (MovementUtils.hasInvFrames(uke)) {
            e.setCanceled(true);
        }
        ICombatCapability ukeCap = CombatData.getCap(uke);
        ItemStack attack = CombatUtils.getAttackingItemStack(e.getSource());
        if (CombatUtils.isMeleeAttack(e.getSource()) && e.getSource().getEntity() instanceof LivingEntity && attack != null && e.getAmount() > 0) {
            LivingEntity seme = (LivingEntity) e.getSource().getEntity();
            if (StealthConfig.inv)
                seme.removeEffect(Effects.INVISIBILITY);
            ICombatCapability semeCap = CombatData.getCap(seme);
            Hand attackingHand = semeCap.isOffhandAttack() ? Hand.OFF_HAND : Hand.MAIN_HAND;
            // hand bound or staggered, no attack
            if (semeCap.getStaggerTime() > 0 || semeCap.getHandBind(attackingHand) > 0) {
                e.setCanceled(true);
                return;
            }
            boolean sweeping = false;
            // capability handler
            seme.getMainHandItem().getCapability(CombatManipulator.CAP).ifPresent((i) -> i.attackStart(e.getSource(), seme, uke, seme.getMainHandItem(), e.getAmount()));
            // add stats if it's the first attack this tick and cooldown is sufficient
            if (semeCap.getSweepTick() != seme.tickCount) {
                // first hit of a potential sweep attack
                semeCap.addRank(0.1f);
                float might = CombatUtils.getAttackMight(seme, uke);
                semeCap.addMight(might);
                semeCap.setSweepTick(seme.tickCount);
            } else {
                // hitting twice in a sweep attack, disqualified from parry refund
                sweeping = true;
            }
            // blocking, reset posture cooldown without resetting combo cooldown, bypass parry
            if (uke.isBlocking()) {
                ukeCap.consumePosture(0);
                return;
            }
            // manual parry toggle
            // why does everyone want this feature...
            boolean failManualParry = CombatConfig.sneakParry > 0 && (ukeCap.getParryingTick() > uke.tickCount || ukeCap.getParryingTick() < uke.tickCount - CombatConfig.sneakParry);
            failManualParry |= CombatConfig.sneakParry < 0 && ukeCap.getParryingTick() == -1;
            failManualParry &= uke instanceof PlayerEntity;
            boolean canParry = GeneralUtils.isFacingEntity(uke, seme, 120);
            boolean useDeflect = (uke instanceof PlayerEntity || WarDance.rand.nextFloat() < CombatConfig.mobDeflectChance) && GeneralUtils.isFacingEntity(uke, seme, 120 + 2 * (int) GeneralUtils.getAttributeValueSafe(uke, WarAttributes.DEFLECTION.get())) && !GeneralUtils.isFacingEntity(uke, seme, 120) && !canParry;
            // staggered, no parry
            if (ukeCap.getStaggerTime() > 0) {
                downingHit = false;
                return;
            }
            // parry code start, grab attack multiplier
            float atkMult = CombatUtils.getPostureAtk(seme, seme, attackingHand, e.getAmount(), attack);
            // store atkMult at this stage for event
            float original = atkMult;
            downingHit = true;
            // stabby bonus
            StealthUtils.Awareness awareness = StealthUtils.getAwareness(seme, uke);
            atkMult *= CombatUtils.getDamageMultiplier(awareness, attack);
            // crit bonus
            if (e.getSource() instanceof CombatDamageSource && ((CombatDamageSource) e.getSource()).isCrit())
                atkMult *= ((CombatDamageSource) e.getSource()).getCritDamage();
            // grab defending stack
            ItemStack defend = null;
            Hand parryHand = null;
            if (canParry) {
                float posMod = 1337;
                boolean isShield = false;
                if (CombatUtils.canParry(uke, seme, uke.getOffhandItem(), atkMult)) {
                    defend = uke.getOffhandItem();
                    posMod = CombatUtils.getPostureDef(seme, uke, uke.getOffhandItem(), e.getAmount());
                    isShield = CombatUtils.isShield(uke, uke.getOffhandItem());
                    parryHand = Hand.OFF_HAND;
                }
                if (!isShield && CombatUtils.canParry(uke, seme, uke.getMainHandItem(), atkMult) && CombatUtils.getPostureDef(seme, uke, uke.getMainHandItem(), e.getAmount()) < posMod) {
                    defend = uke.getMainHandItem();
                    parryHand = Hand.MAIN_HAND;
                }
            }
            float defMult = CombatUtils.getPostureDef(seme, uke, defend, e.getAmount());
            // special mob parry overrides
            if (atkMult >= 0 && awareness != StealthUtils.Awareness.UNAWARE && CombatUtils.parryMap.containsKey(GeneralUtils.getResourceLocationFromEntity(uke))) {
                CombatUtils.MobInfo stats = CombatUtils.parryMap.get(GeneralUtils.getResourceLocationFromEntity(uke));
                if (WarDance.rand.nextFloat() < stats.chance) {
                    if (stats.mult < 0) {
                        // cannot parry
                        defend = null;
                        canParry = false;
                        defMult = (float) -stats.mult;
                    } else if (stats.omnidirectional || canParry) {
                        if (defMult > stats.mult) {
                            if (!canParry) {
                                parryHand = CombatUtils.getCooledAttackStrength(uke, Hand.MAIN_HAND, 0.5f) > CombatUtils.getCooledAttackStrength(uke, Hand.OFF_HAND, 0.5f) ? Hand.MAIN_HAND : Hand.OFF_HAND;
                            }
                            defend = ItemStack.EMPTY;
                            defMult = (float) Math.min(stats.mult, defMult);
                            canParry = true;
                        }
                    }
                }
            }
            // accounting for negative posture damage, used to mark an item as ignoring parries
            float finalPostureConsumption = Math.abs(atkMult * defMult);
            // updating this quickly, it's basically the above without crit and stab multipliers, which were necessary for calculating canParry so they couldn't be eliminated cleanly...
            float originalPostureConsumption = Math.abs(original * defMult);
            ParryEvent pe = new ParryEvent(uke, seme, ((canParry && defend != null) || useDeflect), attackingHand, attack, parryHand, defend, finalPostureConsumption, originalPostureConsumption, e.getAmount());
            if (failManualParry)
                pe.setResult(Event.Result.DENY);
            MinecraftForge.EVENT_BUS.post(pe);
            if (pe.isCanceled()) {
                e.setCanceled(true);
                return;
            }
            if (ukeCap.getStaggerTime() == 0) {
                // overflow posture
                float consumption = pe.getPostureConsumption();
                /*
                    barrier reduction if appropriate
                    this is so ugly oh my god
                     */
                if (pe.canParry() && !useDeflect && CombatUtils.isShield(uke, defend)) {
                    consumption -= ukeCap.consumeBarrier(consumption);
                }
                /*
                    end ugliness
                     */
                float knockback = ukeCap.consumePosture(seme, consumption);
                // no parries if stabby
                if (StealthConfig.ignore && awareness == StealthUtils.Awareness.UNAWARE)
                    return;
                if (pe.canParry()) {
                    e.setCanceled(true);
                    downingHit = false;
                    ukeCap.addRank(0);
                    if (useDeflect) {
                        // deflect
                        uke.level.playSound(null, uke.getX(), uke.getY(), uke.getZ(), SoundEvents.IRON_TRAPDOOR_OPEN, SoundCategory.PLAYERS, 0.75f + WarDance.rand.nextFloat() * 0.5f, (1 - (ukeCap.getPosture() / ukeCap.getMaxPosture())) + WarDance.rand.nextFloat() * 0.5f);
                        return;
                    }
                    // shield disabling
                    boolean disshield = false;
                    parryHand = uke.getOffhandItem() == defend ? Hand.OFF_HAND : Hand.MAIN_HAND;
                    // barrier has already been handled. Subsequent binding and cooldown are handled by the capability.
                    if (CombatUtils.isShield(uke, defend)) {
                        Tuple<Integer, Float> stat = CombatUtils.getShieldStats(defend);
                        if (attack.canDisableShield(defend, uke, seme)) {
                            // shield is disabled
                            if (uke instanceof PlayerEntity) {
                                ((PlayerEntity) uke).getCooldowns().addCooldown(defend.getItem(), stat.getA());
                            } else
                                ukeCap.setHandBind(parryHand, stat.getA());
                            disshield = true;
                        }
                    }
                    // knockback based on posture consumed
                    // this will return negative if the defmult is greater, and positive if the atkmult is greater. Larger abs val=larger difference
                    double kb = Math.sqrt(atkMult) - 0.18 - (1 / Math.max(defMult, 0.1));
                    // sigmoid curve again!
                    // this is the knockback to be applied to the defender
                    kb = 1d / (1d + Math.exp(-kb));
                    CombatUtils.knockBack(uke, seme, Math.min(uke instanceof PlayerEntity ? 1.6f : 1.3f, 0.2f + (pe.getPostureConsumption() + knockback) * (float) kb * (uke instanceof PlayerEntity ? 6 : 4) / ukeCap.getMaxPosture()), true, false);
                    kb = 1 - kb;
                    CombatUtils.knockBack(seme, uke, Math.min(uke instanceof PlayerEntity ? 1.6f : 1.3f, 0.1f + pe.getPostureConsumption() * (float) kb * (seme instanceof PlayerEntity ? 3 : 2) / semeCap.getMaxPosture()), true, false);
                    uke.level.playSound(null, uke.getX(), uke.getY(), uke.getZ(), disshield ? SoundEvents.SHIELD_BLOCK : SoundEvents.ANVIL_PLACE, SoundCategory.PLAYERS, 0.25f + WarDance.rand.nextFloat() * 0.5f, (1 - (ukeCap.getPosture() / ukeCap.getMaxPosture())) + WarDance.rand.nextFloat() * 0.5f);
                    // reset cooldown
                    if (defMult != 0) {
                        // shield time
                        // (posture consumption+1)*5 ticks of cooldown
                        int ticks = (int) ((consumption + 1) * 5);
                        // attack cooldown ticks
                        float cd = CombatUtils.getCooldownPeriod(uke, parryHand);
                        if (// if attack speed is lower, refund partial cooldown
                        cd > ticks)
                            CombatUtils.setHandCooldownDirect(uke, parryHand, ticks, true);
                        else
                            // otherwise bind hand
                            ukeCap.setHandBind(parryHand, (ticks - (int) cd));
                    }
                    if (sweeping) {
                        CombatUtils.setHandCooldown(seme, attackingHand, 0, true);
                    } else
                        CombatUtils.setHandCooldown(seme, attackingHand, (float) (1 - kb), true);
                    // sword on sword is 1.4, sword on shield is 1.12
                    if (defend != null) {
                        ItemStack finalDefend = defend;
                        defend.getCapability(CombatManipulator.CAP).ifPresent((i) -> i.onParry(seme, uke, finalDefend, e.getAmount()));
                        Hand other = uke.getMainHandItem() == defend ? Hand.OFF_HAND : Hand.MAIN_HAND;
                        ItemStack finalDefend1 = uke.getItemInHand(other);
                        finalDefend1.getCapability(CombatManipulator.CAP).ifPresent((i) -> i.onOtherHandParry(seme, uke, finalDefend1, e.getAmount()));
                    }
                }
            }
            if (!(seme instanceof PlayerEntity)) {
                semeCap.setHandBind(attackingHand, CombatUtils.getCooldownPeriod(seme, attackingHand) + 7);
            }
        }
        // shatter, at the rock bottom of the attack event, saving your protected butt.
        if (!uke.isBlocking() && !e.isCanceled()) {
            if (CombatUtils.isPhysicalAttack(e.getSource()) && StealthUtils.getAwareness(e.getSource().getDirectEntity() instanceof LivingEntity ? (LivingEntity) e.getSource().getDirectEntity() : null, uke) != StealthUtils.Awareness.UNAWARE) {
                if (CombatData.getCap(uke).consumeShatter(e.getAmount())) {
                    e.setCanceled(true);
                    uke.level.playSound(null, uke.getX(), uke.getY(), uke.getZ(), SoundEvents.GLASS_BREAK, SoundCategory.PLAYERS, 0.25f + WarDance.rand.nextFloat() * 0.5f, 0.75f + WarDance.rand.nextFloat() * 0.5f);
                }
            // otherwise the rest of the damage goes through and is handled later down the line anyway
            }
        }
    }
}
Also used : StealthUtils(jackiecrazy.wardance.utils.StealthUtils) CombatUtils(jackiecrazy.wardance.utils.CombatUtils) PlayerEntity(net.minecraft.entity.player.PlayerEntity) LivingEntity(net.minecraft.entity.LivingEntity) ICombatCapability(jackiecrazy.wardance.capability.resources.ICombatCapability) CombatDamageSource(jackiecrazy.wardance.api.CombatDamageSource) ParryEvent(jackiecrazy.wardance.event.ParryEvent) ProjectileParryEvent(jackiecrazy.wardance.event.ProjectileParryEvent) ItemStack(net.minecraft.item.ItemStack) SubscribeEvent(net.minecraftforge.eventbus.api.SubscribeEvent)

Example 10 with CombatDamageSource

use of jackiecrazy.wardance.api.CombatDamageSource in project WarDance by Jackiecrazy.

the class CombatHandler method otherKnockbackHooks.

@SubscribeEvent
public static void otherKnockbackHooks(DamageKnockbackEvent e) {
    if (e.getDamageSource() instanceof CombatDamageSource) {
        CombatDamageSource cds = (CombatDamageSource) e.getDamageSource();
        e.setStrength(e.getStrength() * cds.getKnockbackPercentage());
    }
}
Also used : CombatDamageSource(jackiecrazy.wardance.api.CombatDamageSource) SubscribeEvent(net.minecraftforge.eventbus.api.SubscribeEvent)

Aggregations

CombatDamageSource (jackiecrazy.wardance.api.CombatDamageSource)11 LivingEntity (net.minecraft.entity.LivingEntity)8 SubscribeEvent (net.minecraftforge.eventbus.api.SubscribeEvent)5 ICombatCapability (jackiecrazy.wardance.capability.resources.ICombatCapability)3 PlayerEntity (net.minecraft.entity.player.PlayerEntity)3 ServerWorld (net.minecraft.world.server.ServerWorld)3 StealthUtils (jackiecrazy.wardance.utils.StealthUtils)2 ItemStack (net.minecraft.item.ItemStack)2 ISkillCapability (jackiecrazy.wardance.capability.skill.ISkillCapability)1 ICombatItemCapability (jackiecrazy.wardance.capability.weaponry.ICombatItemCapability)1 ParryEvent (jackiecrazy.wardance.event.ParryEvent)1 ProjectileParryEvent (jackiecrazy.wardance.event.ProjectileParryEvent)1 SkillData (jackiecrazy.wardance.skill.SkillData)1 CombatUtils (jackiecrazy.wardance.utils.CombatUtils)1 Entity (net.minecraft.entity.Entity)1 AttributeModifier (net.minecraft.entity.ai.attributes.AttributeModifier)1 LightningBoltEntity (net.minecraft.entity.effect.LightningBoltEntity)1 DamageSource (net.minecraft.util.DamageSource)1 Redirect (org.spongepowered.asm.mixin.injection.Redirect)1