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();
}
}
}
Aggregations