1package com.osroyale.game.world.entity.combat.strategy.player;
3import com.osroyale.content.itemaction.impl.CrawsBow;
4import com.osroyale.content.prestige.PrestigePerk;
5import com.osroyale.game.Animation;
6import com.osroyale.game.UpdatePriority;
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.effect.impl.CombatPoisonEffect;
11import com.osroyale.game.world.entity.combat.hit.CombatHit;
12import com.osroyale.game.world.entity.combat.hit.Hit;
13import com.osroyale.game.world.entity.combat.ranged.RangedAmmunition;
14import com.osroyale.game.world.entity.combat.ranged.RangedWeaponType;
15import com.osroyale.game.world.entity.combat.strategy.basic.RangedStrategy;
16import com.osroyale.game.world.entity.mob.Mob;
17import com.osroyale.game.world.entity.mob.UpdateFlag;
18import com.osroyale.game.world.entity.mob.player.Player;
19import com.osroyale.game.world.entity.mob.player.PlayerRight;
20import com.osroyale.game.world.items.Item;
21import com.osroyale.game.world.items.containers.equipment.Equipment;
22import com.osroyale.game.world.items.ground.GroundItem;
23import com.osroyale.game.world.position.Area;
24import com.osroyale.game.world.position.Position;
25import com.osroyale.net.packet.out.SendMessage;
26import com.osroyale.util.RandomUtils;
28import java.util.Collections;
29import java.util.LinkedList;
31import java.util.function.Consumer;
32import java.util.function.Predicate;
36 private static final PlayerRangedStrategy INSTANCE =
new PlayerRangedStrategy();
38 protected PlayerRangedStrategy() {
42 public boolean canAttack(Player attacker, Mob defender) {
43 Item weapon = attacker.equipment.get(Equipment.WEAPON_SLOT);
46 attacker.getCombat().reset();
50 if(weapon.getId() == CrawsBow.CRAWS_CHARGED_ID && attacker.crawsBowCharges < 1) {
51 attacker.send(
new SendMessage(
"Your Craw's bow is out of charges!"));
52 attacker.getCombat().reset();
56 if (attacker.rangedDefinition ==
null) {
60 int bowsWithNoArrowsRequired [] = {22550, 25865, 25867, 25884, 25886, 25890, 25892, 25894, 25896, 25888};
61 Item ammo = attacker.equipment.get(attacker.rangedDefinition.getSlot());
62 if (ammo !=
null && attacker.rangedAmmo !=
null && ammo.getAmount() >= attacker.rangedAmmo.getRemoval()) {
63 if (attacker.rangedDefinition.isValid(attacker.rangedAmmo)) {
66 attacker.send(
new SendMessage(
"You can't use this ammunition with this weapon."));
68 (attacker.equipment.contains(bowsWithNoArrowsRequired)) {
71 attacker.send(
new SendMessage(
"You need some ammunition to use this weapon!"));
73 attacker.getCombat().reset();
77 protected void sendStuff(Player attacker, Mob defender) {
78 int id = attacker.equipment.get(attacker.rangedDefinition.getSlot()).getId();
79 Animation animation = attacker.rangedAmmo.getAnimation(
id).orElse(getAttackAnimation(attacker, defender));
80 attacker.animate(animation,
true);
81 attacker.rangedAmmo.getStart(
id).ifPresent(attacker::graphic);
82 attacker.rangedAmmo.sendProjectile(attacker, defender);
86 public void start(Player attacker, Mob defender, Hit[] hits) {
87 if (attacker.isSpecialActivated()) {
88 attacker.getCombatSpecial().drain(attacker);
91 if (attacker.getCombat().getDefender() == defender) {
92 sendStuff(attacker, defender);
94 int id = attacker.equipment.get(attacker.rangedDefinition.getSlot()).getId();
95 if (attacker.rangedAmmo.getEffect(
id).isPresent()) {
96 List<Hit> extra =
new LinkedList<>();
97 for (Hit hit : hits) {
98 Predicate<CombatImpact> filter = effect -> effect.canAffect(attacker, defender, hit);
99 Consumer<CombatImpact> execute = effect -> effect.impact(attacker, defender, hit, extra);
100 attacker.rangedAmmo.getEffect(
id).filter(filter).ifPresent(execute);
102 if (!defender.isPlayer() || !PlayerRight.isIronman(attacker)) {
103 if (extra.isEmpty()) {
104 Collections.addAll(extra, hits);
105 addCombatExperience(attacker, extra.toArray(
new Hit[0]));
107 addCombatExperience(attacker, hits);
110 }
else if (!defender.isPlayer() || !PlayerRight.isIronman(attacker)) {
111 addCombatExperience(attacker, hits);
117 public void attack(Player attacker, Mob defender, Hit hit) {
118 removeAmmunition(attacker, defender, attacker.rangedDefinition.getType());
119 if (hit.getDamage() > 1 && attacker.rangedDefinition !=
null) {
120 Item item = attacker.equipment.get(attacker.rangedDefinition.getSlot());
121 CombatPoisonEffect.getPoisonType(item).ifPresent(defender::poison);
124 Item weapon = attacker.equipment.get(Equipment.WEAPON_SLOT);
126 switch(weapon.getId()) {
127 case CrawsBow.CRAWS_CHARGED_ID -> {
128 attacker.crawsBowCharges--;
135 public void hit(Player attacker, Mob defender, Hit hit) {
136 if (attacker.rangedAmmo !=
null && attacker.rangedDefinition !=
null) {
137 int id = attacker.equipment.retrieve(attacker.rangedDefinition.getSlot()).map(Item::getId).orElse(-1);
138 attacker.rangedAmmo.getEnd(
id).ifPresent(defender::graphic);
143 public Animation getAttackAnimation(Player attacker, Mob defender) {
144 int animation = attacker.getCombat().getFightType().getAnimation();
146 if (attacker.equipment.hasShield()) {
147 Item weapon = attacker.equipment.getShield();
148 FightType fightType = attacker.getCombat().getFightType();
149 animation = weapon.getAttackAnimation(fightType).orElse(animation);
152 if (attacker.equipment.hasWeapon()) {
153 Item weapon = attacker.equipment.getWeapon();
154 FightType fightType = attacker.getCombat().getFightType();
155 animation = weapon.getAttackAnimation(fightType).orElse(animation);
158 if (attacker.overrides.hasOverride(Equipment.WEAPON_SLOT)) {
159 final var item = attacker.overrides.get(Equipment.WEAPON_SLOT);
160 animation = attacker.overrides.getFightType(item).getAnimation();
163 return new Animation(animation, UpdatePriority.HIGH);
167 public int getAttackDelay(Player attacker, Mob defender, FightType fightType) {
168 return attacker.getCombat().getFightType().getDelay();
172 public int getAttackDistance(Player attacker, FightType fightType) {
173 return fightType.getDistance();
177 public CombatHit[] getHits(Player attacker, Mob defender) {
178 RangedAmmunition ammo = attacker.rangedAmmo;
179 CombatHit[] hits =
new CombatHit[ammo.getRemoval()];
180 for (
int index = 0; index < hits.length; index++) {
181 hits[index] = nextRangedHit(attacker, defender);
187 public CombatType getCombatType() {
188 return CombatType.RANGED;
191 private void removeAmmunition(Player attacker, Mob defender, RangedWeaponType type) {
192 Item next = attacker.equipment.get(type.getSlot());
193 if (next ==
null)
return;
195 if (attacker.rangedAmmo.isDroppable()) {
196 Item dropItem =
new Item(next.getId());
198 boolean canBreak = !dropItem.getName().contains(
"arrow") || !attacker.prestige.hasPerk(PrestigePerk.ARROWHEAD);
200 if (!canBreak || RandomUtils.success(0.80)) {
201 if (Equipment.hasAssembler(attacker) ) {
205 if (Equipment.hasAccumulator(attacker) && RandomUtils.success(0.90)) {
209 if (Equipment.hasAttractor(attacker) && RandomUtils.success(0.80)) {
213 Position dropPoisition = defender.getPosition();
215 if (Area.inKraken(attacker) || Area.inZulrah(attacker)) {
216 dropPoisition = attacker.getPosition();
219 GroundItem.create(attacker, dropItem, dropPoisition);
222 final int bowsWithNoArrowsRequired [] = {22550, 25865, 25867, 25884, 25886, 25890, 25892, 25894, 25896, 25888};
223 if (attacker.equipment.contains(bowsWithNoArrowsRequired)) {
226 next.decrementAmount();
230 if (next.getAmount() == 0 && !attacker.equipment.contains(bowsWithNoArrowsRequired)) {
231 attacker.send(
new SendMessage(
"That was the last of your ammunition!"));
235 attacker.equipment.set(type.getSlot(), next,
false);
236 attacker.equipment.refresh();
237 attacker.updateFlags.add(UpdateFlag.APPEARANCE);
240 public static PlayerRangedStrategy
get() {