Search in sources :

Example 1 with ProjectileImpactMixin

use of jackiecrazy.wardance.mixin.ProjectileImpactMixin in project WarDance by Jackiecrazy.

the class CombatHandler method projectileParry.

@SubscribeEvent
public static void projectileParry(final ProjectileImpactEvent e) {
    Entity projectile = e.getEntity();
    // 0.01 per tick, up to 0.3 per shot from last attack
    if (projectile instanceof ProjectileEntity && ((ProjectileEntity) projectile).getOwner() instanceof LivingEntity) {
        final LivingEntity shooter = (LivingEntity) ((ProjectileEntity) projectile).getOwner();
        CombatData.getCap(shooter).addRangedMight(e.getRayTraceResult().getType() == RayTraceResult.Type.ENTITY);
    }
    if (e.getRayTraceResult().getType() == RayTraceResult.Type.ENTITY && e.getRayTraceResult() instanceof EntityRayTraceResult && ((EntityRayTraceResult) e.getRayTraceResult()).getEntity() instanceof LivingEntity) {
        LivingEntity uke = (LivingEntity) ((EntityRayTraceResult) e.getRayTraceResult()).getEntity();
        if (StealthUtils.getAwareness(null, uke) != StealthUtils.Awareness.ALERT) {
            return;
        }
        // dodged
        if (MovementUtils.hasInvFrames(uke))
            e.setCanceled(true);
        // defer to vanilla
        if (uke.isBlocking())
            return;
        // refuse to handle piercing arrows to prevent oddity
        if (e.getEntity() instanceof AbstractArrowEntity) {
            if (((AbstractArrowEntity) e.getEntity()).getPierceLevel() > 0)
                return;
        }
        float consume = CombatConfig.posturePerProjectile;
        ICombatCapability ukeCap = CombatData.getCap(uke);
        // 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 free = ukeCap.getBarrierCooldown() > 0;
        ItemStack defend = null;
        Hand h = null;
        float defMult = 0;
        if (CombatUtils.isShield(uke, uke.getOffhandItem()) && CombatUtils.canParry(uke, e.getEntity(), uke.getOffhandItem(), 0)) {
            defend = uke.getOffhandItem();
            defMult = CombatUtils.getPostureDef(null, uke, defend, 0);
            h = Hand.OFF_HAND;
        } else if (CombatUtils.isShield(uke, uke.getMainHandItem()) && CombatUtils.canParry(uke, e.getEntity(), uke.getMainHandItem(), 0)) {
            defend = uke.getMainHandItem();
            defMult = CombatUtils.getPostureDef(null, uke, defend, 0);
            h = Hand.MAIN_HAND;
        }
        StealthUtils.Awareness a = StealthUtils.Awareness.ALERT;
        if (projectile instanceof ProjectileEntity && ((ProjectileEntity) projectile).getOwner() instanceof LivingEntity) {
            // don't parry yourself
            if (((ProjectileEntity) projectile).getOwner() == uke)
                return;
            a = StealthUtils.getAwareness((LivingEntity) ((ProjectileEntity) projectile).getOwner(), uke);
        }
        boolean canParry = GeneralUtils.isFacingEntity(uke, projectile, 120);
        boolean force = false;
        if (a != StealthUtils.Awareness.UNAWARE && CombatUtils.parryMap.containsKey(GeneralUtils.getResourceLocationFromEntity(uke))) {
            CombatUtils.MobInfo stats = CombatUtils.parryMap.get(GeneralUtils.getResourceLocationFromEntity(uke));
            if (stats.shield && 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 (!canParry) {
                        h = 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;
                    force = true;
                }
            }
        }
        ProjectileParryEvent pe = new ProjectileParryEvent(uke, projectile, h, defend, defMult);
        if (failManualParry)
            pe.setResult(Event.Result.DENY);
        if (force)
            pe.setResult(Event.Result.ALLOW);
        MinecraftForge.EVENT_BUS.post(pe);
        if (pe.getResult() == Event.Result.ALLOW || (defend != null && canParry && pe.getResult() == Event.Result.DEFAULT && ukeCap.consumePosture(ukeCap.consumeBarrier(pe.getPostureConsumption()), 0.1f) == 0)) {
            e.setCanceled(true);
            // do not change shooter! It makes drowned tridents and skeleton arrows collectable, which is honestly silly
            uke.level.playSound(null, uke.getX(), uke.getY(), uke.getZ(), free ? SoundEvents.WOODEN_TRAPDOOR_OPEN : SoundEvents.WOODEN_TRAPDOOR_CLOSE, SoundCategory.PLAYERS, 0.75f + WarDance.rand.nextFloat() * 0.5f, (1 - (ukeCap.getPosture() / ukeCap.getMaxPosture())) + WarDance.rand.nextFloat() * 0.5f);
            if (pe.doesTrigger()) {
                if (uke.isEffectiveAi()) {
                    FearEntity dummy = new FearEntity(WarEntities.fear, uke.level);
                    dummy.teleportTo(projectile.getX(), projectile.getY(), projectile.getZ());
                    uke.level.addFreshEntity(dummy);
                    // I am not proud of this.
                    if (projectile instanceof ProjectileEntity) {
                        RayTraceResult rtr = new EntityRayTraceResult(dummy);
                        ((ProjectileImpactMixin) projectile).callOnHit(rtr);
                    }
                }
            } else if (pe.getReturnVec() != null) {
                projectile.setDeltaMovement(pe.getReturnVec().x, pe.getReturnVec().y, pe.getReturnVec().z);
                if (projectile instanceof ProjectileEntity) {
                    double power = pe.getReturnVec().x / pe.getReturnVec().normalize().x;
                    ((ProjectileEntity) projectile).shoot(pe.getReturnVec().x, pe.getReturnVec().y, pe.getReturnVec().z, (float) power, 0);
                }
            } else
                projectile.remove();
            CombatUtils.knockBack(uke, projectile, 0.01f, true, false);
            return;
        }
        // deflection
        if ((uke instanceof PlayerEntity || WarDance.rand.nextFloat() > CombatConfig.mobDeflectChance) && GeneralUtils.isFacingEntity(uke, projectile, 120 + 2 * (int) GeneralUtils.getAttributeValueSafe(uke, WarAttributes.DEFLECTION.get())) && !canParry && ukeCap.doConsumePosture(consume)) {
            e.setCanceled(true);
            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);
            if (pe.getReturnVec() != null) {
                projectile.setDeltaMovement(pe.getReturnVec().x, pe.getReturnVec().y, pe.getReturnVec().z);
                if (projectile instanceof ProjectileEntity) {
                    double power = pe.getReturnVec().x / pe.getReturnVec().normalize().x;
                    ((ProjectileEntity) projectile).shoot(pe.getReturnVec().x, pe.getReturnVec().y, pe.getReturnVec().z, (float) power, 0);
                }
            } else
                projectile.remove();
        }
    }
}
Also used : Entity(net.minecraft.entity.Entity) AbstractArrowEntity(net.minecraft.entity.projectile.AbstractArrowEntity) PlayerEntity(net.minecraft.entity.player.PlayerEntity) LivingEntity(net.minecraft.entity.LivingEntity) ProjectileEntity(net.minecraft.entity.projectile.ProjectileEntity) FearEntity(jackiecrazy.wardance.entity.FearEntity) ProjectileEntity(net.minecraft.entity.projectile.ProjectileEntity) StealthUtils(jackiecrazy.wardance.utils.StealthUtils) CombatUtils(jackiecrazy.wardance.utils.CombatUtils) EntityRayTraceResult(net.minecraft.util.math.EntityRayTraceResult) RayTraceResult(net.minecraft.util.math.RayTraceResult) EntityRayTraceResult(net.minecraft.util.math.EntityRayTraceResult) ProjectileImpactMixin(jackiecrazy.wardance.mixin.ProjectileImpactMixin) PlayerEntity(net.minecraft.entity.player.PlayerEntity) LivingEntity(net.minecraft.entity.LivingEntity) ICombatCapability(jackiecrazy.wardance.capability.resources.ICombatCapability) ItemStack(net.minecraft.item.ItemStack) FearEntity(jackiecrazy.wardance.entity.FearEntity) ProjectileParryEvent(jackiecrazy.wardance.event.ProjectileParryEvent) AbstractArrowEntity(net.minecraft.entity.projectile.AbstractArrowEntity) SubscribeEvent(net.minecraftforge.eventbus.api.SubscribeEvent)

Aggregations

ICombatCapability (jackiecrazy.wardance.capability.resources.ICombatCapability)1 FearEntity (jackiecrazy.wardance.entity.FearEntity)1 ProjectileParryEvent (jackiecrazy.wardance.event.ProjectileParryEvent)1 ProjectileImpactMixin (jackiecrazy.wardance.mixin.ProjectileImpactMixin)1 CombatUtils (jackiecrazy.wardance.utils.CombatUtils)1 StealthUtils (jackiecrazy.wardance.utils.StealthUtils)1 Entity (net.minecraft.entity.Entity)1 LivingEntity (net.minecraft.entity.LivingEntity)1 PlayerEntity (net.minecraft.entity.player.PlayerEntity)1 AbstractArrowEntity (net.minecraft.entity.projectile.AbstractArrowEntity)1 ProjectileEntity (net.minecraft.entity.projectile.ProjectileEntity)1 ItemStack (net.minecraft.item.ItemStack)1 EntityRayTraceResult (net.minecraft.util.math.EntityRayTraceResult)1 RayTraceResult (net.minecraft.util.math.RayTraceResult)1 SubscribeEvent (net.minecraftforge.eventbus.api.SubscribeEvent)1