RuneHive-Tarnish
Neural OSRS Enhancement Framework
Loading...
Searching...
No Matches
PlayerRangedStrategy.java
1package com.osroyale.game.world.entity.combat.strategy.player;
2
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;
27
28import java.util.Collections;
29import java.util.LinkedList;
30import java.util.List;
31import java.util.function.Consumer;
32import java.util.function.Predicate;
33
34public class PlayerRangedStrategy extends RangedStrategy<Player> {
35
36 private static final PlayerRangedStrategy INSTANCE = new PlayerRangedStrategy();
37
38 protected PlayerRangedStrategy() {
39 }
40
41 @Override
42 public boolean canAttack(Player attacker, Mob defender) {
43 Item weapon = attacker.equipment.get(Equipment.WEAPON_SLOT);
44
45 if (weapon == null) {
46 attacker.getCombat().reset();
47 return false;
48 }
49
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();
53 return false;
54 }
55
56 if (attacker.rangedDefinition == null) {
57 return false;
58 }
59
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)) {
64 return true;
65 }
66 attacker.send(new SendMessage("You can't use this ammunition with this weapon."));
67 } else if
68 (attacker.equipment.contains(bowsWithNoArrowsRequired)) {
69 return true;
70 } else {
71 attacker.send(new SendMessage("You need some ammunition to use this weapon!"));
72 }
73 attacker.getCombat().reset();
74 return false;
75 }
76
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);
83 }
84
85 @Override
86 public void start(Player attacker, Mob defender, Hit[] hits) {
87 if (attacker.isSpecialActivated()) {
88 attacker.getCombatSpecial().drain(attacker);
89 }
90
91 if (attacker.getCombat().getDefender() == defender) {
92 sendStuff(attacker, defender);
93
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);
101 }
102 if (!defender.isPlayer() || !PlayerRight.isIronman(attacker)) {
103 if (extra.isEmpty()) {
104 Collections.addAll(extra, hits);
105 addCombatExperience(attacker, extra.toArray(new Hit[0]));
106 } else {
107 addCombatExperience(attacker, hits);
108 }
109 }
110 } else if (!defender.isPlayer() || !PlayerRight.isIronman(attacker)) {
111 addCombatExperience(attacker, hits);
112 }
113 }
114 }
115
116 @Override
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);
122 }
123
124 Item weapon = attacker.equipment.get(Equipment.WEAPON_SLOT);
125 if(weapon != null) {
126 switch(weapon.getId()) {
127 case CrawsBow.CRAWS_CHARGED_ID -> {
128 attacker.crawsBowCharges--;
129 }
130 }
131 }
132 }
133
134 @Override
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);
139 }
140 }
141
142 @Override
143 public Animation getAttackAnimation(Player attacker, Mob defender) {
144 int animation = attacker.getCombat().getFightType().getAnimation();
145
146 if (attacker.equipment.hasShield()) {
147 Item weapon = attacker.equipment.getShield();
148 FightType fightType = attacker.getCombat().getFightType();
149 animation = weapon.getAttackAnimation(fightType).orElse(animation);
150 }
151
152 if (attacker.equipment.hasWeapon()) {
153 Item weapon = attacker.equipment.getWeapon();
154 FightType fightType = attacker.getCombat().getFightType();
155 animation = weapon.getAttackAnimation(fightType).orElse(animation);
156 }
157
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();
161 }
162
163 return new Animation(animation, UpdatePriority.HIGH);
164 }
165
166 @Override
167 public int getAttackDelay(Player attacker, Mob defender, FightType fightType) {
168 return attacker.getCombat().getFightType().getDelay();
169 }
170
171 @Override
172 public int getAttackDistance(Player attacker, FightType fightType) {
173 return fightType.getDistance();
174 }
175
176 @Override
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);
182 }
183 return hits;
184 }
185
186 @Override
187 public CombatType getCombatType() {
188 return CombatType.RANGED;
189 }
190
191 private void removeAmmunition(Player attacker, Mob defender, RangedWeaponType type) {
192 Item next = attacker.equipment.get(type.getSlot());
193 if (next == null) return;
194
195 if (attacker.rangedAmmo.isDroppable()) {
196 Item dropItem = new Item(next.getId());
197
198 boolean canBreak = !dropItem.getName().contains("arrow") || !attacker.prestige.hasPerk(PrestigePerk.ARROWHEAD);
199
200 if (!canBreak || RandomUtils.success(0.80)) {
201 if (Equipment.hasAssembler(attacker) /* AKA 100% */) {
202 return;
203 }
204
205 if (Equipment.hasAccumulator(attacker) && RandomUtils.success(0.90)) {
206 return;
207 }
208
209 if (Equipment.hasAttractor(attacker) && RandomUtils.success(0.80)) {
210 return;
211 }
212
213 Position dropPoisition = defender.getPosition();
214
215 if (Area.inKraken(attacker) || Area.inZulrah(attacker)) {
216 dropPoisition = attacker.getPosition();
217 }
218
219 GroundItem.create(attacker, dropItem, dropPoisition);
220 }
221 }
222 final int bowsWithNoArrowsRequired [] = {22550, 25865, 25867, 25884, 25886, 25890, 25892, 25894, 25896, 25888};
223 if (attacker.equipment.contains(bowsWithNoArrowsRequired)) {
224 return;
225 } else {
226 next.decrementAmount();
227 }
228
229
230 if (next.getAmount() == 0 && !attacker.equipment.contains(bowsWithNoArrowsRequired)) {
231 attacker.send(new SendMessage("That was the last of your ammunition!"));
232 next = null;
233 }
234
235 attacker.equipment.set(type.getSlot(), next, false);
236 attacker.equipment.refresh();
237 attacker.updateFlags.add(UpdateFlag.APPEARANCE);
238 }
239
240 public static PlayerRangedStrategy get() {
241 return INSTANCE;
242 }
243
244}