70 private static final int DEFAULT_DELAY = 10;
80 private static boolean started =
false;
81 public static final int MAX_HP = 3500;
82 public static int health = 0;
83 private static int startDelay = DEFAULT_DELAY;
84 private static int pyroSpeechDelay;
85 public static Region region;
91 public static final int BRUMA_KINDLING = 20696;
92 public static final int REJUV_POT_UNF = 20697;
93 public static final int REJUV_POT_4 = 20699;
94 public static final int REJUV_POT_3 = 20700;
95 public static final int REJUV_POT_2 = 20701;
96 public static final int REJUV_POT_1 = 20702;
97 public static final int BRUMA_HERB = 20698;
102 private static final String[] PYROMANCER_DEAD_TEXT = {
"My flame burns low.",
"Mummy!",
"I think I'm dying.",
"We are doomed.",
"Ugh, help me!"};
104 public static final int PYROMANCER = 7371;
105 public static final int INCAPACITATED_PYROMANCER = 7372;
106 private static final int FLAME = 7373;
111 private static final int SNOW_EFFECT_ID = 26690;
112 private static final int ACTIVE_STORM_ID = 29308;
113 private static final int INACTIVE_STORM_ID = 29309;
114 public static final int EMPTY_BRAZIER_ID = 29312;
115 public static final int BROKEN_BRAZIER_ID = 29313;
116 public static final int BURNING_BRAZIER_ID = 29314;
122 private static final List<Integer> GAME_ITEMS = Arrays.asList(
BRUMA_ROOT, BRUMA_KINDLING, BRUMA_HERB, REJUV_POT_UNF, REJUV_POT_4, REJUV_POT_3, REJUV_POT_2, REJUV_POT_1);
128 private static final List<Integer> WARM_CLOTHING = Arrays.asList(
130 1050, 12887, 12888, 12889, 12890, 12891, 12892, 12893, 12894, 12895, 12896, 13343, 13344,
132 23448, 13663, 13664, 13665, 13182,
134 19689, 19691, 19693, 19695, 19697,
154 20708, 20706, 20704, 20710,
156 11021, 11020, 11022, 11019,
158 20439, 20436, 20442, 20434,
172 6857, 6859, 6861, 6863, 9470, 21314,
182 13280, 13329, 21284, 21285, 13337, 20760, 21898, 24855, 21776, 21780, 21778, 13331, 13333, 13335,
188 1387, 1393, 3053, 11787, 11998, 1401, 3054, 11789, 12000, 13241, 13242, 13243, 13244, 21031, 21033, 12773, 20056, 20720,
198 new Brazier(
World.getRegions().
getRegion(
new Position(1620, 3997, 0)).getGameObject(29312,
new Position(1620, 3997, 0)),
new Npc(7371,
new Position(1619, 3996, 0), 0,
Direction.NORTH_EAST), 2, 2,
Direction.NORTH_EAST),
199 new Brazier(
World.getRegions().
getRegion(
new Position(1620, 4015, 0)).getGameObject(29312,
new Position(1620, 4015, 0)),
new Npc(7371,
new Position(1619, 4018, 0), 0,
Direction.SOUTH_EAST), 2, 0,
Direction.SOUTH_EAST),
200 new Brazier(
World.getRegions().
getRegion(
new Position(1638, 4015, 0)).getGameObject(29312,
new Position(1638, 4015, 0)),
new Npc(7371,
new Position(1641, 4018, 0), 0,
Direction.SOUTH_WEST), 0, 0,
Direction.SOUTH_WEST),
201 new Brazier(
World.getRegions().
getRegion(
new Position(1638, 3997, 0)).getGameObject(29312,
new Position(1638, 3997, 0)),
new Npc(7371,
new Position(1641, 3996, 0), 0,
Direction.NORTH_WEST), 0, 2,
Direction.NORTH_WEST)
204 public static boolean isActive() {
205 return startDelay <= 0;
208 public static void init() {
211 startDelay = DEFAULT_DELAY;
212 WINTERTODT =
new CustomGameObject(INACTIVE_STORM_ID,
new Position(1627, 4004, 0));
217 brazier.getPyromancer().register();
221 protected void execute() {
225 if(startDelay <= 0 && !started) start();
231 World.schedule(
new Task(2) {
233 protected void execute() {
234 if(!isActive())
return;
238 extinguishBraziers();
247 private static void start() {
248 WINTERTODT.transform(ACTIVE_STORM_ID);
252 brazier.getObject().unregister();
253 brazier.setObject(EMPTY_BRAZIER_ID);
254 brazier.getObject().register();
255 if (!brazier.isPyromancerAlive())
256 brazier.getPyromancer().transform(PYROMANCER);
264 private static void update() {
265 region.getPlayers(0).forEach(Wintertodt::send);
268 public static void send(Player player) {
269 player.send(
new SendString(
"Wintertodt's Energy: "+(health / (MAX_HP / 100))+
"%", 41553));
270 player.send(
new SendString(isActive() ?
"" :
"The Wintertodt returns in: " + ((startDelay * 600) / 1000) +
" secs", 41554));
271 player.send(
new SendString(
"<col="+(player.wintertodtPoints >= 500 ?
"FFFFFF" :
"FF0000")+
">Points\\n" + player.wintertodtPoints, 41556));
274 player.send(
new SendConfig(2224,
BRAZIERS[0].isPyromancerAlive() ? 0 : 1));
275 player.send(
new SendConfig(2222,
BRAZIERS[1].isPyromancerAlive() ? 0 : 1));
276 player.send(
new SendConfig(2223,
BRAZIERS[2].isPyromancerAlive() ? 0 : 1));
277 player.send(
new SendConfig(2225,
BRAZIERS[3].isPyromancerAlive() ? 0 : 1));
279 player.send(
new SendConfig(2228,
BRAZIERS[0].getBrazierState()));
280 player.send(
new SendConfig(2226,
BRAZIERS[1].getBrazierState()));
281 player.send(
new SendConfig(2227,
BRAZIERS[2].getBrazierState()));
282 player.send(
new SendConfig(2229,
BRAZIERS[3].getBrazierState()));
284 if (player.interfaceManager.
getWalkable() != 41550)
288 private static void applyColdDamage() {
289 region.getPlayers(0).forEach(player -> {
290 if(player.
getPosition().
getY() <= 3987 || Utility.random(25) != 0)
return;
293 player.message(
"The cold of the Wintertodt seeps into your bones.");
295 if(player.action.getCurrentAction() instanceof WintertodtAction)
296 player.action.getCurrentAction().cancel();
303 private static void extinguishBraziers() {
305 int roll = Utility.random(health + 1500) / 10;
306 if(brazier.getObject().getId() == BURNING_BRAZIER_ID && roll == 10) {
307 if(brazier.hasSnowStorm())
continue;
309 if(Utility.random(health < (MAX_HP / 2) ? 2 : 3) == 1)
310 breakBrazier(brazier);
314 brazier.getObject().unregister();
315 brazier.setObject(EMPTY_BRAZIER_ID);
316 brazier.getObject().register();
325 private static void breakBrazier(Brazier brazier) {
326 if(brazier.getObject().
getId() == BROKEN_BRAZIER_ID)
return;
328 List<GameObject> objects = Arrays.asList(
331 new CustomGameObject(SNOW_EFFECT_ID,
new Position(brazier.getObject().
getPosition().
getX() + 1, brazier.getObject().
getPosition().
getY() + 1, 0)),
332 new CustomGameObject(SNOW_EFFECT_ID,
new Position(brazier.getObject().
getPosition().
getX() + 2, brazier.getObject().
getPosition().
getY() + 1, 0)),
336 for(GameObject gameObject : objects)
337 gameObject.register();
339 brazier.setSnowStorm(
true);
341 World.schedule(
new Task(4) {
343 public void execute() {
345 for(GameObject gameObject : objects) {
346 gameObject.unregister();
347 region.getPlayers(0).forEach(players -> {
348 players.send(
new SendRemoveObject(
new CustomGameObject(gameObject.getId(), gameObject.getPosition())));
352 brazier.setSnowStorm(
false);
358 brazier.setObject(Wintertodt.BROKEN_BRAZIER_ID);
360 region.getPlayers(0).forEach(player -> {
362 player.message(
"The brazier is broken and shrapnel damages you.");
382 private static void doMagicAttack() {
390 List<GameObject> snowAttacks =
new ArrayList<>();
393 if(region.getObjects(
new Position(baseX + 1, baseY + 1, 0)).size() == 0)
395 if(region.getObjects(
new Position(baseX + 1, baseY - 1, 0)).size() == 0)
397 if(region.getObjects(
new Position(baseX - 1, baseY + 1, 0)).size() == 0)
399 if(region.getObjects(
new Position(baseX - 1, baseY - 1, 0)).size() == 0)
403 gameObject.register();
408 public void execute() {
410 gameObject.transform(index == 0 ? 29325 : 29324);
415 if(
Utility.goodDistance(baseX, baseY, players.getX(), player.
getY(), 1)) {
416 players.message(
"The freezing cold attack of the Wintertodt's magic hits you.");
424 World.schedule(
new Task(14) {
426 public void execute() {
427 for(GameObject gameObject : snowAttacks) {
428 gameObject.unregister();
429 region.getPlayers(0).forEach(players -> {
430 players.send(
new SendRemoveObject(
new CustomGameObject(gameObject.getId(), gameObject.getPosition())));
448 private static void attackPyromancers() {
449 List<Npc> pyros = Arrays.stream(
BRAZIERS).filter(Brazier::isPyromancerAlive).map(Brazier::getPyromancer).collect(Collectors.toList());
450 if (!pyros.isEmpty() &&
Utility.random(pyros.size() * 30) == pyros.size()) {
451 Npc pyro = pyros.get(
Utility.random(pyros.size()));
454 if(pyro.pyroSnowAttack) {
455 System.out.println(
"already a snow attack going for this pyro...");
459 pyro.pyroSnowAttack =
true;
465 public void execute() {
466 int damage = 6 +
Utility.random(4);
469 pyro.pyroHealth -= damage;
470 pyro.writeFakeDamage(
new Hit(damage));
473 pyro.transform(INCAPACITATED_PYROMANCER);
475 pyro.pyroSnowAttack =
false;
477 players.send(
new SendRemoveObject(
new CustomGameObject(snow.
getId(), snow.
getPosition())));
489 private static void pyromancerText() {
490 if(pyroSpeechDelay <= 0) {
493 if (!brazier.isPyromancerAlive())
494 brazier.getPyromancer().
speak(PYROMANCER_DEAD_TEXT[Utility.random(PYROMANCER_DEAD_TEXT.length - 1)]);
495 else if (brazier.getObject().
getId() == EMPTY_BRAZIER_ID)
496 brazier.getPyromancer().
speak(
"Light this brazier!");
497 else if (brazier.getObject().
getId() == BROKEN_BRAZIER_ID)
498 brazier.getPyromancer().
speak(
"Fix this brazier!");
499 else if (Utility.random(4) == 1)
500 brazier.getPyromancer().
speak(
"Yemalo shi cardito!");
502 if (brazier.isPyromancerAlive() && brazier.getObject().
getId() == BURNING_BRAZIER_ID && Utility.random(3) == 1)
503 brazier.getPyromancer().animate(4432);
511 private static void dealDamage() {
514 if (brazier.isPyromancerAlive() && brazier.getObject().
getId() == BURNING_BRAZIER_ID) {
527 health = Math.min(MAX_HP, health + 5);
537 flame.action.execute(
new FlameWalk(flame));
543 private static void death() {
545 startDelay = DEFAULT_DELAY;
547 WINTERTODT.transform(INACTIVE_STORM_ID);
550 brazier.getPyromancer().
speak(
"We can rest for a time.");
551 brazier.getPyromancer().transform(PYROMANCER);
552 brazier.getPyromancer().pyroSnowAttack =
false;
554 brazier.getPyromancer().animate(65535);
557 brazier.setObject(EMPTY_BRAZIER_ID);
561 region.
getPlayers(0).forEach(Wintertodt::award);
567 private static void award(
Player player) {
570 if (player.wintertodtPoints >= 500) {
571 CollectionLog.increaseCounter(player, CollectionLogData.WINTERTODT);
573 int crates = player.wintertodtPoints / 500;
575 player.message(
"You have gained " + crates +
" supply crates!");
577 player.message(
"You have gained a supply crate!");
578 player.inventory.
add(
new Item(20703, crates));
580 }
else player.message(
"You did not earn enough points to be worthy of a gift from the citizens of Kourend this time.");
582 player.wintertodtPoints = 0;
590 for (Item item : player.inventory.
getItems()) {
591 if (item !=
null && GAME_ITEMS.contains(item.getId())) {
592 player.inventory.set(slot,
null,
false);
610 int warmClothing = 0;
611 for(
int id : WARM_CLOTHING) {
612 if(player.equipment.contains(
id)) warmClothing++;
613 if(warmClothing >= 4)
break;
624 if (b.getObject().getId() == BURNING_BRAZIER_ID)
626 return Math.min(count, 3);
634 player.message(
"There's no need to do that at this time.");
640 if(axeData ==
null) {
641 player.message(
"You do not have an axe which you have the woodcutting level to use.");
646 player.message(
"You have no space for that.");
650 player.action.execute(
new ChopRoots(player));
658 player.message(
"There's no need to do that at this time.");
665 if(b.getObject().getId() == gameObject.
getId() && b.getObject().getPosition() == gameObject.
getPosition()) {
671 if(brazier ==
null) {
672 System.out.println(
"Brazier has not been found...");
677 player.action.execute(
new FeedBrazier(player, brazier));
685 player.message(
"There's no need to do that at this time.");
692 if(b.getObject().getId() == gameObject.
getId() && b.getObject().getPosition() == gameObject.
getPosition()) {
698 if(brazier ==
null) {
699 System.out.println(
"Brazier has not been found...");
703 if(!brazier.isPyromancerAlive()) {
704 player.message(
"Heal the Pyromancer before fixing the brazier.");
708 if(!player.inventory.
contains(2347)) {
709 player.message(
"You need a hammer to fix this brazier.");
713 player.animate(3676);
714 player.action.execute(
new FixBrazier(player, brazier));
722 player.message(
"There's no need to do that at this time.");
728 player.animate(1248);
737 player.message(
"There's no need to do that at this time.");
744 if(b.getObject().getId() == gameObject.
getId() && b.getObject().getPosition() == gameObject.
getPosition()) {
750 if(brazier ==
null) {
751 System.out.println(
"Brazier has not been found...");
755 if(!brazier.isPyromancerAlive()) {
756 player.message(
"Heal the Pyromancer before lighting the brazier.");
760 if(!player.inventory.
contains(590) && !player.equipment.contains(20720)) {
761 player.message(
"You need a tinderbox or Bruma Torch to light that brazier.");
766 player.action.execute(
new LightBrazier(player, brazier));
774 player.message(
"There's no need to do that at this time.");
780 int min =
Utility.min(herbs, pots);
785 player.action.execute(
new MixHerb(player, min));
793 player.message(
"There's no need to do that at this time.");
798 player.message(
"You have no space for that.");
802 player.animate(2282);
803 player.action.execute(
new PickHerb(player));
811 player.message(
"There's no need to do that at this time.");
818 if(b.getPyromancer().getPosition() == npc.
getPosition() && b.getPyromancer().id == npc.id) {
824 if(brazier ==
null) {
825 System.out.println(
"Brazier has not been found...");
829 Item itemUsed = player.inventory.
get(slot);
831 if(itemUsed.getId() != REJUV_POT_4 && itemUsed.getId() != REJUV_POT_3 && itemUsed.getId() != REJUV_POT_2 && itemUsed.getId() != REJUV_POT_1) {
832 System.out.println(
"not a rejuv potion");
836 Item newPot =
new Item(player.inventory.
getId(slot) + 1);
837 if(newPot.getId() > REJUV_POT_1) newPot =
null;
839 player.inventory.set(slot, newPot,
true);
841 brazier.getPyromancer().transform(PYROMANCER);
843 brazier.getPyromancer().pyroSnowAttack =
false;
852 int old = player.wintertodtPoints;
853 player.wintertodtPoints += amount;
854 if (old < 500 && player.wintertodtPoints >= 500) {
855 player.message(
"You have helped enough to earn a supply crate. Further work will go towards better rewards.");