RuneHive-Tarnish
Neural OSRS Enhancement Framework
Loading...
Searching...
No Matches
Vorkath.java
1package com.osroyale.game.world.entity.combat.strategy.npc.boss;
2
3import com.osroyale.game.Animation;
4import com.osroyale.game.Graphic;
5import com.osroyale.game.Projectile;
6import com.osroyale.game.UpdatePriority;
7import com.osroyale.game.task.TickableTask;
8import com.osroyale.game.world.World;
9import com.osroyale.game.world.entity.combat.Combat;
10import com.osroyale.game.world.entity.combat.CombatType;
11import com.osroyale.game.world.entity.combat.CombatUtil;
12import com.osroyale.game.world.entity.combat.attack.FightType;
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.hit.Hitsplat;
16import com.osroyale.game.world.entity.combat.projectile.CombatProjectile;
17import com.osroyale.game.world.entity.combat.strategy.CombatStrategy;
18import com.osroyale.game.world.entity.combat.strategy.npc.MultiStrategy;
19import com.osroyale.game.world.entity.combat.strategy.npc.NpcMagicStrategy;
20import com.osroyale.game.world.entity.combat.strategy.npc.NpcMeleeStrategy;
21import com.osroyale.game.world.entity.combat.strategy.npc.NpcRangedStrategy;
22import com.osroyale.game.world.entity.combat.strategy.npc.impl.DragonfireStrategy;
23import com.osroyale.game.world.entity.mob.Mob;
24import com.osroyale.game.world.entity.mob.data.LockType;
25import com.osroyale.game.world.entity.mob.npc.Npc;
26import com.osroyale.game.world.object.CustomGameObject;
27import com.osroyale.game.world.pathfinding.TraversalMap;
28import com.osroyale.game.world.position.Area;
29import com.osroyale.game.world.position.Position;
30import com.osroyale.net.packet.out.SendWidget;
31import com.osroyale.util.RandomUtils;
32import com.osroyale.util.Utility;
33
34import java.util.Collections;
35import java.util.Deque;
36import java.util.LinkedList;
37import java.util.List;
38
39import static com.osroyale.game.world.entity.combat.CombatUtil.createStrategyArray;
40
81
82public class Vorkath extends MultiStrategy {
83 private static final NpcMeleeStrategy MELEE = NpcMeleeStrategy.get();
84 private static final MagicAttack MAGIC = new MagicAttack();
85 private static final RangedAttack RANGED = new RangedAttack();
86 private static final FireballAttack FIREBALL = new FireballAttack();
87
88 private static final DragonfireStrategy DRAGONFIRE = new DragonfireAttack();
89 private static final DragonfireStrategy PINK_DRAGONFIRE = new PinkDragonfireAttack();
90 private static final DragonfireStrategy VENOM_DRAGONFIRE = new VenomDragonfireAttack();
91
92 private static final VenomSpecial VENOM_SPECIAL = new VenomSpecial();
93 private static final FrozenSpecial FROZEN_SPECIAL = new FrozenSpecial();
94
95 private static final CombatStrategy<Npc>[] FULL_STRATEGIES = createStrategyArray(MELEE, DRAGONFIRE, MAGIC, FIREBALL, RANGED, VENOM_DRAGONFIRE, PINK_DRAGONFIRE);
96 private static final CombatStrategy<Npc>[] NON_MELEE = createStrategyArray(FIREBALL, DRAGONFIRE, MAGIC, RANGED, VENOM_DRAGONFIRE, PINK_DRAGONFIRE);
97 private final CombatStrategy<Npc>[] SPECIALS = createStrategyArray(VENOM_SPECIAL, FROZEN_SPECIAL);
98
99 private final Deque<CombatStrategy<Npc>> strategyQueue = new LinkedList<>();
100 private int specialIndex;
101
102 public Vorkath() {
103 currentStrategy = MELEE;
104 }
105
106 @Override
107 public void init(Npc attacker, Mob defender) {
108 if (strategyQueue.isEmpty()) {
109 for (int index = 0; index < 6; index++) {
110 strategyQueue.add(RandomUtils.random(FULL_STRATEGIES));
111 }
112 strategyQueue.add(SPECIALS[specialIndex++ % SPECIALS.length]);
113 }
114 currentStrategy = strategyQueue.poll();
115 }
116
117 @Override
118 public boolean canAttack(Npc attacker, Mob defender) {
119 if (currentStrategy == MELEE && !MELEE.canAttack(attacker, defender)) {
120 currentStrategy = RandomUtils.random(NON_MELEE);
121 }
122 return currentStrategy.canAttack(attacker, defender);
123 }
124
125 @Override
126 public boolean withinDistance(Npc attacker, Mob defender) {
127 if (currentStrategy == MELEE && !MELEE.withinDistance(attacker, defender)) {
128 currentStrategy = RandomUtils.random(NON_MELEE);
129 }
130 return currentStrategy.canAttack(attacker, defender);
131 }
132
133 private static class VenomSpecial extends NpcMagicStrategy {
134 VenomSpecial() {
135 super(CombatProjectile.getDefinition("EMPTY"));
136 }
137
138 @Override
139 public int getAttackDelay(Npc attacker, Mob defender, FightType fightType) {
140 return 30;
141 }
142
143 @Override
144 public void start(Npc attacker, Mob defender, Hit[] hits) {
145 World.schedule(2, () -> {
146 attacker.animate(new Animation(7957, UpdatePriority.HIGH));
147 List<Position> boundaries = TraversalMap.getTraversableTiles(attacker.getPosition().transform(-7, -7), 30, 30);
148 Collections.shuffle(boundaries);
149
150 World.schedule(1, () -> {
151
152 Projectile projectile = new Projectile(1483, 10, 85, 20, 0);
153 projectile.send(attacker, defender.getPosition());
154 World.schedule(AcidTask(defender, defender.getPosition().copy()));
155
156
157 for (int index = 0; index < 40; index++) {
158 Position position = boundaries.get(index);
159 projectile.send(attacker, position);
160 World.schedule(AcidTask(defender, position));
161 }
162
163 final Projectile projectile2 = new Projectile(1482, 15, 95, 15, 15);
164
165 World.schedule(dragonFireTickableTask(attacker, defender, projectile2));
166 });
167 });
168 }
169
170 private TickableTask dragonFireTickableTask(Mob attacker, Mob defender, Projectile projectile) {
171 return new TickableTask(false, 1) {
172
173 private boolean possible() {
174 return attacker != null
175 && !attacker.isDead()
176 && !defender.isDead()
177 && !defender.inTeleport
178 && !defender.locking.locked()
179 && Area.inVorkath(defender);
180 }
181
182 @Override
183 protected void onCancel(boolean logout) {
184 super.onCancel(logout);
185
186 if (!logout && attacker != null) {
187 final Combat<? extends Mob> combat = attacker.getCombat();
188 if (combat != null) {
189 combat.clearDamageQueue();
190 }
191 }
192 }
193
194 @Override
195 protected void tick() {
196 if (!possible()) {
197 cancel();
198 return;
199 }
200
201 if (tick > 27) {
202 cancel();
203 return;
204 }
205
206 if (tick < 3) {
207 return;
208 }
209
210 Position position = defender.getPosition().copy();
211 projectile.send(attacker, position);
212
213 World.schedule(3, () -> {
214 if (!possible()) {
215 final Combat<? extends Mob> combat = defender.getCombat();
216 if (combat != null) {
217 combat.clearDamageQueue();
218 }
219 return;
220 }
221
222 World.sendGraphic(new Graphic(131, UpdatePriority.HIGH), position, attacker.instance);
223
224 if (defender.getPosition().equals(position)) {
225 defender.damage(new Hit(Utility.random(30)));
226 }
227 });
228 }
229 };
230 }
231
232 private TickableTask AcidTask(Mob defender, Position position) {
233 return new TickableTask(false, 2) {
234 private CustomGameObject object;
235
236 @Override
237 protected void tick() {
238 if (tick == 1) {
239 object = new CustomGameObject(32000, defender.instance, position);
240 object.register();
241 } else if (tick == 13) {
242 object.unregister();
243 cancel();
244 return;
245 }
246
247 if (defender.getPosition().equals(position) && Area.inVorkath(defender)) {
248 defender.writeDamage(new Hit(Utility.random(1, 10)));
249 }
250 }
251 };
252 }
253
254 @Override
255 public CombatHit[] getHits(Npc attacker, Mob defender) {
256 CombatHit combatHit = nextMagicHit(attacker, defender, 0);
257 combatHit.setAccurate(true);
258 combatHit.setDamage(-1);
259 return new CombatHit[]{combatHit};
260 }
261 }
262
263 private static class RangedAttack extends NpcRangedStrategy {
264
265 RangedAttack() {
266 super(CombatProjectile.getDefinition("Vorkath Ranged"));
267 }
268
269 @Override
270 public Animation getAttackAnimation(Npc attacker, Mob defender) {
271 return new Animation(7952, UpdatePriority.HIGH);
272 }
273
274 @Override
275 public CombatHit[] getHits(Npc attacker, Mob defender) {
276 return new CombatHit[]{nextRangedHit(attacker, defender, 32)};
277 }
278 }
279
280 private static class MagicAttack extends NpcMagicStrategy {
281
282 MagicAttack() {
283 super(CombatProjectile.getDefinition("Vorkath Magic"));
284 }
285
286 @Override
287 public Animation getAttackAnimation(Npc attacker, Mob defender) {
288 return new Animation(7952, UpdatePriority.HIGH);
289 }
290
291 @Override
292 public CombatHit[] getHits(Npc attacker, Mob defender) {
293 return new CombatHit[]{nextRangedHit(attacker, defender, 32)};
294 }
295 }
296
297 private static class FrozenSpecial extends NpcMagicStrategy {
298 private final Projectile PROJECTILE = new Projectile(1470, 5, 85, 30, 30, 40);
299
300 FrozenSpecial() {
301 super(CombatProjectile.getDefinition("Vorkath Frozen Special"));
302 }
303
304 @Override
305 public Animation getAttackAnimation(Npc attacker, Mob defender) {
306 return new Animation(7952, UpdatePriority.HIGH);
307 }
308
309 @Override
310 public void hit(Npc attacker, Mob defender, Hit hit) {
311 defender.graphic(new Graphic(369));
312 defender.locking.lock(LockType.FREEZE);
313
314 attacker.blockInteract = true;
315 attacker.resetFace();
316 attacker.face(new Position(2277, 4057));
317 attacker.animate(new Animation(7960, UpdatePriority.HIGH));
318 PROJECTILE.send(attacker, new Position(2277, 4057));
319
320 World.schedule(4, () -> {
321 attacker.blockInteract = false;
322 Npc zombie = new Npc(8063, defender.instance, new Position(2277, 4057)) {
323 @Override
324 public void appendDeath() {
325 super.appendDeath();
326 defender.locking.unlock();
327 defender.getPlayer().send(new SendWidget(SendWidget.WidgetType.FROZEN, 0));
328 }
329 };
330 zombie.instance = defender.instance;
331 zombie.register();
332 zombie.walkTo(defender, () -> {
333 World.sendGraphic(new Graphic(1460, true), zombie.getPosition(), defender.instance);
334 defender.damage(new Hit(60 * zombie.getCurrentHealth() / zombie.getMaximumHealth()));
335 defender.locking.unlock();
336 defender.getPlayer().send(new SendWidget(SendWidget.WidgetType.FROZEN, 0));
337 zombie.unregister();
338 });
339 });
340 }
341
342 @Override
343 public int getAttackDelay(Npc attacker, Mob defender, FightType fightType) {
344 return 15;
345 }
346
347 @Override
348 public CombatHit[] getHits(Npc attacker, Mob defender) {
349 CombatHit combatHit = nextMagicHit(attacker, defender, -1);
350 combatHit.setAccurate(false);
351 return new CombatHit[]{combatHit};
352 }
353 }
354
355 private static class DragonfireAttack extends DragonfireStrategy {
356 DragonfireAttack() {
357 super(CombatProjectile.getDefinition("Metalic dragonfire"));
358 }
359
360 @Override
361 public Animation getAttackAnimation(Npc attacker, Mob defender) {
362 return new Animation(7952, UpdatePriority.HIGH);
363 }
364
365 @Override
366 public int getAttackDistance(Npc attacker, FightType fightType) {
367 return 10;
368 }
369
370 @Override
371 public CombatHit[] getHits(Npc attacker, Mob defender) {
372 return new CombatHit[]{CombatUtil.generateDragonfire(attacker, defender, 85, true)};
373 }
374 }
375
376 private static class VenomDragonfireAttack extends DragonfireStrategy {
377 VenomDragonfireAttack() {
378 super(CombatProjectile.getDefinition("Vorkath Venom Dragonfire"));
379 }
380
381 @Override
382 public Animation getAttackAnimation(Npc attacker, Mob defender) {
383 return new Animation(7952, UpdatePriority.HIGH);
384 }
385
386 @Override
387 public int getAttackDistance(Npc attacker, FightType fightType) {
388 return 10;
389 }
390
391 @Override
392 public void hit(Npc attacker, Mob defender, Hit hit) {
393 super.hit(attacker, defender, hit);
394 if (hit.isAccurate()) {
395 defender.venom();
396 }
397 }
398
399 @Override
400 public CombatHit[] getHits(Npc attacker, Mob defender) {
401 CombatHit combatHit = CombatUtil.generateDragonfire(attacker, defender, 75, true);
402 combatHit.setHitsplat(Hitsplat.VENOM);
403 return new CombatHit[]{combatHit};
404 }
405 }
406
407 private static class PinkDragonfireAttack extends DragonfireStrategy {
408 PinkDragonfireAttack() {
409 super(CombatProjectile.getDefinition("Vorkath Pink Dragonfire"));
410 }
411
412 @Override
413 public Animation getAttackAnimation(Npc attacker, Mob defender) {
414 return new Animation(7952, UpdatePriority.HIGH);
415 }
416
417 @Override
418 public void hitsplat(Npc attacker, Mob defender, Hit hit) {
419 super.hitsplat(attacker, defender, hit);
420
421 if (defender.isPlayer()) {
422 defender.prayer.reset();
423 }
424 }
425
426 @Override
427 public int getAttackDistance(Npc attacker, FightType fightType) {
428 return 10;
429 }
430
431 @Override
432 public CombatHit[] getHits(Npc attacker, Mob defender) {
433 return new CombatHit[]{CombatUtil.generateDragonfire(attacker, defender, 80, true)};
434 }
435 }
436
437 private static class FireballAttack extends DragonfireStrategy {
438 private final Projectile PROJECTILE = new Projectile(1481, 5, 105, 30, 30, 40);
439 private final Graphic GRAPHIC = new Graphic(1466, true);
440 private Position position;
441
442 FireballAttack() {
443 super(CombatProjectile.getDefinition("EMPTY"));
444 }
445
446 @Override
447 public Animation getAttackAnimation(Npc attacker, Mob defender) {
448 return new Animation(7960, UpdatePriority.HIGH);
449 }
450
451 @Override
452 public void start(Npc attacker, Mob defender, Hit[] hits) {
453 super.start(attacker, defender, hits);
454 position = defender.getPosition().copy();
455 }
456
457 @Override
458 public void attack(Npc attacker, Mob defender, Hit hit) {
459 PROJECTILE.send(attacker, position);
460 }
461
462 @Override
463 public void hit(Npc attacker, Mob defender, Hit hit) {
464 super.hitsplat(attacker, defender, hit);
465 World.sendGraphic(GRAPHIC, position, defender.instance);
466 hit.setAccurate(false);
467 if (defender.getPosition().equals(position)) {
468 hit.setAs(CombatUtil.generateDragonfire(attacker, defender, 150, true));
469 hit.setAccurate(true);
470 } else if (Utility.withinOctal(defender.getPosition(), defender.width(), defender.length(), position, 1, 1, 1)) {
471 hit.setAs(CombatUtil.generateDragonfire(attacker, defender, 150, true));
472 hit.modifyDamage(damage -> damage / 2);
473 hit.setAccurate(true);
474 }
475 }
476
477 @Override
478 public int getAttackDistance(Npc attacker, FightType fightType) {
479 return 10;
480 }
481
482 @Override
483 public CombatHit[] getHits(Npc attacker, Mob defender) {
484 return new CombatHit[]{nextMagicHit(attacker, defender, -1, CombatUtil.getHitDelay(attacker, defender, CombatType.MAGIC) + 1, 1)};
485 }
486 }
487
488}
static void sendGraphic(Graphic graphic, Position position, int instance)
Definition World.java:305
static void schedule(Task task)
Definition World.java:284
static int getHitDelay(final Mob attacker, final Mob defender, final CombatType type)
void face(GameObject object)
Definition Mob.java:326
abstract Combat<? extends Mob > getCombat()
static List< Position > getTraversableTiles(Position southWest, int width, int length)
Position transform(int diffX, int diffY, int diffZ)