79 lines
2.9 KiB
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);
|
|
}
|
|
}
|
|
}
|