ProjectAres/PGM/src/main/java/tc/oc/pgm/physics/KnockbackPlayerFacet.java

79 lines
2.9 KiB
Java

package tc.oc.pgm.physics;
import java.util.Optional;
import javax.inject.Inject;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerKnockbackEvent;
import org.bukkit.util.Vector;
import tc.oc.commons.bukkit.event.targeted.TargetedEventHandler;
import tc.oc.pgm.damage.DamageDisplayPlayerFacet;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.MatchPlayer;
import tc.oc.pgm.match.MatchPlayerFacet;
public class KnockbackPlayerFacet implements MatchPlayerFacet, Listener {
private final Optional<KnockbackSettings> knockback;
private final Match match;
private final Player victim;
@Inject KnockbackPlayerFacet(Optional<KnockbackSettings> knockback, Match match, Player victim) {
this.knockback = knockback;
this.match = match;
this.victim = victim;
}
@TargetedEventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onKnockback(PlayerKnockbackEvent event) {
if(knockback.isPresent() &&
victim.equals(event.getPlayer()) &&
event.getDamager() instanceof LivingEntity) {
event.setCancelled(true);
}
}
@TargetedEventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onMelee(EntityDamageByEntityEvent event) {
if(knockback.isPresent() &&
victim.equals(event.getEntity()) &&
event.getCause() == EntityDamageEvent.DamageCause.ENTITY_ATTACK &&
event.getDamager() instanceof LivingEntity &&
victim.getNoDamageTicks() <= 0) {
applyImpulses((LivingEntity) event.getDamager());
}
}
private void applyImpulses(LivingEntity attacker) {
final KnockbackSettings knockback = this.knockback.get();
final Vector normal = victim.getLocation().subtract(attacker.getLocation()).toVector();
if(normal.isZero()) return;
normal.normalize();
final Vector victimNormal = knockback.pitchedNormal(normal);
final Vector attackerNormal = normal.times(-1);
if(victimNormal.isZero() || attackerNormal.isZero()) return;
final boolean ground = attacker.isOnGround();
final double attackSpeed = Math.max(0, attacker.getPredictedVelocity().dot(normal));
final boolean sprint = ground && attackSpeed > knockback.sprintThreshold;
victim.applyImpulse(victimNormal.multiply(knockback.power(sprint)), true);
attacker.applyImpulse(attackerNormal.multiply(knockback.recoil(ground) * attackSpeed), true);
final MatchPlayer matchAttacker = match.getPlayer(attacker);
if(matchAttacker != null) {
matchAttacker.facet(DamageDisplayPlayerFacet.class).showKnockback(victim, sprint);
}
}
}