1package com.osroyale.game.world.entity.combat.strategy.npc;
3import com.osroyale.game.Animation;
4import com.osroyale.game.Graphic;
5import com.osroyale.game.UpdatePriority;
6import com.osroyale.game.engine.GameEngine;
7import com.osroyale.game.world.entity.combat.CombatImpact;
8import com.osroyale.game.world.entity.combat.CombatType;
9import com.osroyale.game.world.entity.combat.attack.FightType;
10import com.osroyale.game.world.entity.combat.attack.FormulaFactory;
11import com.osroyale.game.world.entity.combat.effect.impl.CombatPoisonEffect;
12import com.osroyale.game.world.entity.combat.effect.impl.CombatVenomEffect;
13import com.osroyale.game.world.entity.combat.hit.CombatHit;
14import com.osroyale.game.world.entity.combat.hit.Hit;
15import com.osroyale.game.world.entity.combat.projectile.CombatProjectile;
16import com.osroyale.game.world.entity.combat.strategy.basic.RangedStrategy;
17import com.osroyale.game.world.entity.mob.Mob;
18import com.osroyale.game.world.entity.mob.npc.Npc;
19import com.osroyale.util.RandomUtils;
20import org.jire.tarnishps.WorldTask;
22import javax.annotation.Nullable;
23import java.util.Optional;
24import java.util.function.Consumer;
25import java.util.function.Predicate;
29 private final CombatProjectile combatProjectile;
31 public NpcRangedStrategy(CombatProjectile combatProjectile) {
32 this.combatProjectile = combatProjectile;
36 public CombatProjectile getCombatProjectile() {
37 return combatProjectile;
41 public void start(Npc attacker, Mob defender, Hit[] hits) {
42 sendAnimation(attacker, defender);
43 sendProjectile(attacker, defender,
null);
46 public void sendAnimation(Npc attacker, Mob defender) {
47 Animation animation = getAttackAnimation(attacker, defender);
48 if (animation.isReset()) {
49 Optional<Animation> projAnim = combatProjectile.getAnimation();
50 if (projAnim.isPresent()) animation = projAnim.get();
53 attacker.animate(animation,
true);
54 combatProjectile.getStart().ifPresent(attacker::graphic);
57 public int sendProjectile(Mob from, Mob to, @Nullable Runnable onProjectileLand) {
58 final int duration = combatProjectile.sendProjectile(from, to);
60 final Graphic endGraphic = getEndGraphic(combatProjectile,
false,
null, duration);
61 if (endGraphic !=
null) to.graphic(endGraphic);
63 if (onProjectileLand !=
null) {
64 final int delay = GameEngine.clientTicksToServerTicks(duration);
65 WorldTask.schedule(delay, onProjectileLand);
72 public void attack(Npc attacker, Mob defender, Hit
hit) {
73 Predicate<CombatImpact> filter = effect -> effect.canAffect(attacker, defender,
hit);
74 Consumer<CombatImpact> execute = effect -> effect.impact(attacker, defender,
hit,
null);
75 combatProjectile.getEffect().filter(filter).ifPresent(execute);
77 if (!attacker.definition.isPoisonous()) {
81 if (CombatVenomEffect.isVenomous(attacker) && RandomUtils.success(0.25)) {
84 CombatPoisonEffect.getPoisonType(attacker.id).ifPresent(defender::poison);
89 public CombatHit[] getHits(Npc attacker, Mob defender) {
90 int max = combatProjectile.getMaxHit();
92 max = FormulaFactory.getMaxHit(attacker, defender, getCombatType());
93 return new CombatHit[]{nextRangedHit(attacker, defender, max, combatProjectile)};
97 public int getAttackDelay(Npc attacker, Mob defender, FightType fightType) {
98 return attacker.definition.getAttackDelay();
102 public int getAttackDistance(Npc attacker, FightType fightType) {
107 public Animation getAttackAnimation(Npc attacker, Mob defender) {
108 return new Animation(attacker.definition.getAttackAnimation(), UpdatePriority.HIGH);
112 public boolean canAttack(Npc attacker, Mob defender) {
117 public CombatType getCombatType() {
118 return CombatType.RANGED;
void hit(T attacker, Mob defender, Hit hit)