mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-20 21:40:27 -07:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
bd930b037d
48 changed files with 1498 additions and 436 deletions
|
|
@ -346,13 +346,13 @@ public final class Class39 {
|
|||
} else if (Unsorted.incomingOpcode == 17) {
|
||||
var1 = BufferedDataStream.incomingBuffer.readUnsignedByte();
|
||||
var2 = Class65.currentChunkX + (var1 >> 4 & 7);
|
||||
var3 = currentChunkY - -(var1 & 7);
|
||||
var3 = currentChunkY + (var1 & 7);
|
||||
var4 = BufferedDataStream.incomingBuffer.readUnsignedShort();
|
||||
var5 = BufferedDataStream.incomingBuffer.readUnsignedByte();
|
||||
var6 = BufferedDataStream.incomingBuffer.readUnsignedShort();
|
||||
if (var2 >= 0 && var3 >= 0 && var2 < 104 && var3 < 104) {
|
||||
var2 = var2 * 128 - -64;
|
||||
var3 = var3 * 128 - -64;
|
||||
var2 = var2 * 128 + 64;
|
||||
var3 = var3 * 128 + 64;
|
||||
Class140_Sub2 var32 = new Class140_Sub2(var4, WorldListCountry.localPlane, var2, var3, -var5 + Class121.method1736(WorldListCountry.localPlane, 1, var2, var3), var6, Class44.anInt719);
|
||||
TextureOperation17.aLinkedList_3177.method1215(new Class3_Sub28_Sub2(var32));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.runite.client;
|
|||
|
||||
import org.rs09.Discord;
|
||||
import org.rs09.SlayerTracker;
|
||||
import org.rs09.SystemLogger;
|
||||
import org.rs09.XPGainDraw;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
|
|
|||
|
|
@ -530,5 +530,13 @@
|
|||
{
|
||||
"item_id": "4619",
|
||||
"loc_data": "{1,2713,4913,0,2}"
|
||||
},
|
||||
{
|
||||
"item_id": "2964",
|
||||
"loc_data": "{1,3437,3337,0,100}"
|
||||
},
|
||||
{
|
||||
"item_id": "2957",
|
||||
"loc_data": "{1,3443,9742,0,100}-{1,3443,9742,1,100}"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10595,28 +10595,31 @@
|
|||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "1052",
|
||||
"aggressive": "true",
|
||||
"aggressive": "false",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "Arrghhh... A Ghast.",
|
||||
"range_animation": "0",
|
||||
"attack_speed": "5",
|
||||
"melee_animation": "1087",
|
||||
"attack_speed": "4",
|
||||
"magic_level": "1",
|
||||
"respawn_delay": "60",
|
||||
"defence_animation": "0",
|
||||
"defence_animation": "1088",
|
||||
"weakness": "9",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "9467",
|
||||
"death_animation": "1089",
|
||||
"death_gfx": "265",
|
||||
"name": "Ghast",
|
||||
"defence_level": "25",
|
||||
"defence_level": "18",
|
||||
"safespot": null,
|
||||
"lifepoints": "71",
|
||||
"strength_level": "25",
|
||||
"lifepoints": "45",
|
||||
"strength_level": "22",
|
||||
"id": "1053",
|
||||
"aggressive": "true",
|
||||
"range_level": "1",
|
||||
"attack_level": "25"
|
||||
"attack_level": "22"
|
||||
},
|
||||
{
|
||||
"examine": "Ticket trader for the Brimhaven Agility Arena.",
|
||||
|
|
@ -16607,7 +16610,26 @@
|
|||
"attack_level": "32"
|
||||
},
|
||||
{
|
||||
"examine": "It's one leg short!",
|
||||
"examine": "He's one big leg short!",
|
||||
"melee_animation": "9471",
|
||||
"range_animation": "9471",
|
||||
"attack_speed": "4",
|
||||
"magic_level": "1",
|
||||
"defence_animation": "9473",
|
||||
"magic_animation": "9471",
|
||||
"death_animation": "9472",
|
||||
"name": "Turoth",
|
||||
"defence_level": "85",
|
||||
"safespot": null,
|
||||
"lifepoints": "78",
|
||||
"strength_level": "85",
|
||||
"id": "1622",
|
||||
"bonuses": "0,0,0,0,0,0,20,20,0,0,0,0,0,0,0",
|
||||
"range_level": "1",
|
||||
"attack_level": "55"
|
||||
},
|
||||
{
|
||||
"examine": "He's one big leg short!",
|
||||
"melee_animation": "9471",
|
||||
"range_animation": "9471",
|
||||
"attack_speed": "4",
|
||||
|
|
@ -16618,9 +16640,10 @@
|
|||
"name": "Turoth",
|
||||
"defence_level": "88",
|
||||
"safespot": null,
|
||||
"lifepoints": "27",
|
||||
"lifepoints": "81",
|
||||
"strength_level": "88",
|
||||
"id": "1623",
|
||||
"bonuses": "0,0,0,0,0,0,20,20,0,0,0,0,0,0,0",
|
||||
"range_level": "1",
|
||||
"attack_level": "58"
|
||||
},
|
||||
|
|
@ -16663,7 +16686,7 @@
|
|||
"attack_level": "105"
|
||||
},
|
||||
{
|
||||
"examine": "It's one leg short!",
|
||||
"examine": "She's one leg short!",
|
||||
"melee_animation": "9471",
|
||||
"range_animation": "9471",
|
||||
"attack_speed": "4",
|
||||
|
|
@ -16677,6 +16700,7 @@
|
|||
"lifepoints": "79",
|
||||
"strength_level": "86",
|
||||
"id": "1626",
|
||||
"bonuses": "0,0,0,0,0,0,20,20,0,0,0,0,0,0,0",
|
||||
"clue_level": "2",
|
||||
"range_level": "1",
|
||||
"attack_level": "56"
|
||||
|
|
@ -16696,12 +16720,13 @@
|
|||
"lifepoints": "77",
|
||||
"strength_level": "84",
|
||||
"id": "1627",
|
||||
"bonuses": "0,0,0,0,0,0,20,20,0,0,0,0,0,0,0",
|
||||
"clue_level": "2",
|
||||
"range_level": "1",
|
||||
"attack_level": "54"
|
||||
},
|
||||
{
|
||||
"examine": "It's one leg short!",
|
||||
"examine": "It's one small leg short!",
|
||||
"melee_animation": "9471",
|
||||
"range_animation": "9471",
|
||||
"attack_speed": "4",
|
||||
|
|
@ -16715,10 +16740,51 @@
|
|||
"lifepoints": "76",
|
||||
"strength_level": "83",
|
||||
"id": "1628",
|
||||
"bonuses": "0,0,0,0,0,0,20,20,0,0,0,0,0,0,0",
|
||||
"clue_level": "2",
|
||||
"range_level": "1",
|
||||
"attack_level": "53"
|
||||
},
|
||||
{
|
||||
"examine": "He's one big leg short!",
|
||||
"melee_animation": "9471",
|
||||
"range_animation": "9471",
|
||||
"attack_speed": "4",
|
||||
"magic_level": "1",
|
||||
"defence_animation": "9473",
|
||||
"magic_animation": "9471",
|
||||
"death_animation": "9472",
|
||||
"name": "Turoth",
|
||||
"defence_level": "87",
|
||||
"safespot": null,
|
||||
"lifepoints": "80",
|
||||
"strength_level": "87",
|
||||
"id": "1629",
|
||||
"bonuses": "0,0,0,0,0,0,20,20,0,0,0,0,0,0,0",
|
||||
"clue_level": "2",
|
||||
"range_level": "1",
|
||||
"attack_level": "57"
|
||||
},
|
||||
{
|
||||
"examine": "He's one big leg short!",
|
||||
"melee_animation": "9471",
|
||||
"range_animation": "9471",
|
||||
"attack_speed": "4",
|
||||
"magic_level": "1",
|
||||
"defence_animation": "9473",
|
||||
"magic_animation": "9471",
|
||||
"death_animation": "9472",
|
||||
"name": "Turoth",
|
||||
"defence_level": "87",
|
||||
"safespot": null,
|
||||
"lifepoints": "80",
|
||||
"strength_level": "87",
|
||||
"id": "1630",
|
||||
"bonuses": "0,0,0,0,0,0,20,20,0,0,0,0,0,0,0",
|
||||
"clue_level": "2",
|
||||
"range_level": "1",
|
||||
"attack_level": "57"
|
||||
},
|
||||
{
|
||||
"examine": "A rocky slug.",
|
||||
"slayer_task": "69",
|
||||
|
|
@ -68987,22 +69053,6 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "55"
|
||||
},
|
||||
{
|
||||
"examine": "The oldest man in Nardah.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghaslor the Elder",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "3029",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A water salesman from Pollnivneach.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -84828,43 +84878,6 @@
|
|||
"projectile": "100",
|
||||
"attack_level": "25"
|
||||
},
|
||||
{
|
||||
"examine": "Arrghhh... A Ghast.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"weakness": "9",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghast",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "1052",
|
||||
"aggressive": "true",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "Arrghhh... A Ghast.",
|
||||
"range_animation": "0",
|
||||
"attack_speed": "5",
|
||||
"respawn_delay": "60",
|
||||
"defence_animation": "0",
|
||||
"weakness": "9",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "9467",
|
||||
"name": "Ghast",
|
||||
"defence_level": "25",
|
||||
"safespot": null,
|
||||
"lifepoints": "71",
|
||||
"strength_level": "25",
|
||||
"id": "1053",
|
||||
"aggressive": "true",
|
||||
"range_level": "1",
|
||||
"attack_level": "25"
|
||||
},
|
||||
{
|
||||
"examine": "Ticket trader for the Brimhaven Agility Arena.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -102123,22 +102136,6 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "55"
|
||||
},
|
||||
{
|
||||
"examine": "The oldest man in Nardah.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghaslor the Elder",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "3029",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A water salesman from Pollnivneach.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -143402,22 +143399,6 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "55"
|
||||
},
|
||||
{
|
||||
"examine": "The oldest man in Nardah.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghaslor the Elder",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "3029",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A water salesman from Pollnivneach.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -159251,43 +159232,6 @@
|
|||
"projectile": "100",
|
||||
"attack_level": "25"
|
||||
},
|
||||
{
|
||||
"examine": "Arrghhh... A Ghast.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"weakness": "9",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghast",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "1052",
|
||||
"aggressive": "true",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "Arrghhh... A Ghast.",
|
||||
"range_animation": "0",
|
||||
"attack_speed": "5",
|
||||
"respawn_delay": "60",
|
||||
"defence_animation": "0",
|
||||
"weakness": "9",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "9467",
|
||||
"name": "Ghast",
|
||||
"defence_level": "25",
|
||||
"safespot": null,
|
||||
"lifepoints": "71",
|
||||
"strength_level": "25",
|
||||
"id": "1053",
|
||||
"aggressive": "true",
|
||||
"range_level": "1",
|
||||
"attack_level": "25"
|
||||
},
|
||||
{
|
||||
"examine": "Ticket trader for the Brimhaven Agility Arena.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -176546,22 +176490,6 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "55"
|
||||
},
|
||||
{
|
||||
"examine": "The oldest man in Nardah.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghaslor the Elder",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "3029",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A water salesman from Pollnivneach.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -217577,22 +217505,6 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "55"
|
||||
},
|
||||
{
|
||||
"examine": "The oldest man in Nardah.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghaslor the Elder",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "3029",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A water salesman from Pollnivneach.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -233418,43 +233330,6 @@
|
|||
"projectile": "100",
|
||||
"attack_level": "25"
|
||||
},
|
||||
{
|
||||
"examine": "Arrghhh... A Ghast.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"weakness": "9",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghast",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "1052",
|
||||
"aggressive": "true",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "Arrghhh... A Ghast.",
|
||||
"range_animation": "0",
|
||||
"attack_speed": "5",
|
||||
"respawn_delay": "60",
|
||||
"defence_animation": "0",
|
||||
"weakness": "9",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "9467",
|
||||
"name": "Ghast",
|
||||
"defence_level": "25",
|
||||
"safespot": null,
|
||||
"lifepoints": "71",
|
||||
"strength_level": "25",
|
||||
"id": "1053",
|
||||
"aggressive": "true",
|
||||
"range_level": "1",
|
||||
"attack_level": "25"
|
||||
},
|
||||
{
|
||||
"examine": "Ticket trader for the Brimhaven Agility Arena.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -250713,22 +250588,6 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "55"
|
||||
},
|
||||
{
|
||||
"examine": "The oldest man in Nardah.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghaslor the Elder",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "3029",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A water salesman from Pollnivneach.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -291992,22 +291851,6 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "55"
|
||||
},
|
||||
{
|
||||
"examine": "The oldest man in Nardah.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Ghaslor the Elder",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "3029",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A water salesman from Pollnivneach.",
|
||||
"melee_animation": "0",
|
||||
|
|
|
|||
|
|
@ -2484,7 +2484,7 @@
|
|||
"loc_data": "{3409,3489,0,1,4}-{3413,3485,0,1,4}-{3414,3491,1,1,6}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1047",
|
||||
"npc_id": "7690",
|
||||
"loc_data": "{3415,3489,2,0,0}"
|
||||
},
|
||||
{
|
||||
|
|
@ -2492,7 +2492,7 @@
|
|||
"loc_data": "{3437,3486,0,0,0}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1049",
|
||||
"npc_id": "7707",
|
||||
"loc_data": "{3440,9895,0,0,0}"
|
||||
},
|
||||
{
|
||||
|
|
@ -3547,29 +3547,29 @@
|
|||
"npc_id": "1621",
|
||||
"loc_data": "{2797,10035,0,1,6}-{2787,10032,0,1,3}-{2802,10031,0,1,3}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1623",
|
||||
"loc_data": "{2725,9999,0,1,6}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1624",
|
||||
"loc_data": "{3179,5522,0,1,6}-{3223,9393,0,1,5}-{3225,9401,0,1,0}-{3222,9375,0,1,6}-{3220,9380,0,1,6}-{3215,9364,0,1,3}-{3213,9361,0,1,1}-{3212,9355,0,1,2}-{3230,9367,0,1,3}-{3240,9350,0,1,5}-{3248,9348,0,1,4}-{3255,9350,0,1,4}-{3256,9392,0,1,4}-{3168,5513,0,1,3}-{3174,5514,0,1,6}-{3178,5517,0,1,4}-{3178,5528,0,1,1}-{3169,5516,0,1,3}-{3179,5524,0,1,4}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1626",
|
||||
"loc_data": "{3165,5537,0,1,3}-{3159,5538,0,1,4}-{3155,5539,0,1,3}-{3158,5537,0,1,4}"
|
||||
"loc_data": "{2723,10005,0,1,0}-{2726,9998,0,1,1}-{2723,10009,0,1,3}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1627",
|
||||
"loc_data": "{2724,10008,0,1,4}"
|
||||
"loc_data": "{2724,10008,0,1,4}-{2721,10005,0,1,1}-{2724,10005,0,1,3}-{2729,10004,0,1,3}-{2724,10012,0,1,4}-{2718,10009,0,1,1}-{2721,10001,0,1,7}-{2720,9996,0,1,7}-{2721,10006,0,1,3}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1628",
|
||||
"loc_data": "{2723,10004,0,1,4}-{2722,9999,0,1,1}-{2729,10002,0,1,1}"
|
||||
"loc_data": "{2723,10004,0,1,4}-{2722,9999,0,1,1}-{2729,10002,0,1,1}-{3155,5536,0,1,4}-{3156,5540,0,1,3}-{3157,5538,0,1,2}-{3166,5537,0,1,1}-{3165,5541,0,1,3}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1629",
|
||||
"loc_data": "{2723,10005,0,1,0}-{2726,9998,0,1,1}-{2723,10009,0,1,3}-{2727,9998,0,1,4}-{2727,10001,0,1,3}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1630",
|
||||
"loc_data": "{2721,10005,0,1,1}-{2724,10005,0,1,3}-{2729,10004,0,1,3}-{2724,10012,0,1,4}-{2718,10009,0,1,1}-{2721,10001,0,1,7}-{2720,9996,0,1,7}-{2721,10006,0,1,3}"
|
||||
"loc_data": "{3162,5538,0,1,2}-{3157,5538,0,1,4}-{3155,5537,0,1,1}-{3164,5538,0,1,2}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1631",
|
||||
|
|
@ -10734,5 +10734,13 @@
|
|||
{
|
||||
"npc_id": "1164",
|
||||
"loc_data": "{2780,3058,0,1,0}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1051",
|
||||
"loc_data": "{3440,9738,1,1,0}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1052",
|
||||
"loc_data": "{3420,3442,0,1,0}-{3429,3436,0,1,0}-{3439,3437,0,1,0}-{3448,3444,0,1,0}-{3458,3433,0,1,0}-{3459,3419,0,1,0}-{3449,3420,0,1,0}-{3441,3421,0,1,0}-{3427,3421,0,1,0}-{3414,3422,0,1,0}-{3411,3423,0,1,0}-{3415,3414,0,1,0}-{3410,3409,0,1,0}-{3422,3405,0,1,0}-{3431,3402,0,1,0}-{3444,3405,0,1,0}-{3453,3397,0,1,0}-{3467,3402,0,1,0}-{3473,3395,0,1,0}-{3470,3385,0,1,0}-{3463,3379,0,1,0}-{3451,3380,0,1,0}-{3445,3374,0,1,0}-{3438,3365,0,1,0}-{3429,3367,0,1,0}-{3417,3367,0,1,0}-{3413,3362,0,1,0}-{3417,3358,0,1,0}-{3426,3352,0,1,0}-{3435,3349,0,1,0}-{3442,3353,0,1,0}-{3448,3358,0,1,0}-{3457,3355,0,1,0}-{3461,3348,0,1,0}-{3457,3343,0,1,0}-{3471,3344,0,1,0}-{3426,3338,0,1,0}-{3423,3335,0,1,0}"
|
||||
}
|
||||
]
|
||||
|
|
@ -2131,5 +2131,14 @@
|
|||
"id": "240",
|
||||
"title": "Tiadeche's Karambwan Stall",
|
||||
"stock": "{3142,10}-{3157,10}"
|
||||
},
|
||||
{
|
||||
"npcs": "",
|
||||
"high_alch": "0",
|
||||
"currency": "995",
|
||||
"general_store": "false",
|
||||
"id": "241",
|
||||
"title": "Wishing Well",
|
||||
"stock": "{12204,10}-{12207,10}-{12210,0}-{12213,0}-{12216,0}-{12219,0}-{12222,0}-{12183,65000}-{12155,5000}"
|
||||
}
|
||||
]
|
||||
|
|
@ -2656,8 +2656,8 @@
|
|||
<offer>
|
||||
<id>379</id>
|
||||
<value>268</value>
|
||||
<uniqueTrades>0</uniqueTrades>
|
||||
<totalValue>0</totalValue>
|
||||
<uniqueTrades>173</uniqueTrades>
|
||||
<totalValue>57782</totalValue>
|
||||
<lastUpdate>0</lastUpdate>
|
||||
</offer>
|
||||
<offer>
|
||||
|
|
|
|||
|
|
@ -109,6 +109,10 @@ public abstract class Consumable implements Plugin<Object> {
|
|||
return effect.getHealthEffectValue(player);
|
||||
}
|
||||
|
||||
public ConsumableEffect getEffect() {
|
||||
return effect;
|
||||
}
|
||||
|
||||
public int[] getIds() {
|
||||
return ids;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,6 +381,6 @@ public final class DrezelDialogue extends DialoguePlugin {
|
|||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 1047 };
|
||||
return new int[] { 7690 };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
package core.game.content.dialogue;
|
||||
|
||||
import api.ContentAPI;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.quest.Quest;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.item.Item;
|
||||
import org.rs09.consts.NPCs;
|
||||
import rs09.game.content.quest.members.naturespirit.NSDrezelDialogue;
|
||||
import rs09.game.system.SystemLogger;
|
||||
|
||||
import static rs09.tools.DialogueConstKt.END_DIALOGUE;
|
||||
|
||||
/**
|
||||
* Represents the dialogue plugin used for the drezel monument.
|
||||
|
|
@ -44,7 +50,7 @@ public final class DrezelMonumentDialogue extends DialoguePlugin {
|
|||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
final Quest quest = player.getQuestRepository().getQuest("Priest in Peril");
|
||||
Quest quest = player.getQuestRepository().getQuest("Priest in Peril");
|
||||
if (quest.getStage(player) == 17) {
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Ah, " + player.getUsername() + ". I see you finally made it down here.", "Things are worse than I feared. I'm not sure if I will", "be able to repair the damage.");
|
||||
stage = 900;
|
||||
|
|
@ -64,9 +70,23 @@ public final class DrezelMonumentDialogue extends DialoguePlugin {
|
|||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "So can I pass through that barrier now?");
|
||||
stage = 400;
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
|
||||
/*else {
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Greetings again adventurer, How go your travels in", "Morytania? Is it as evil as I have heard?");
|
||||
stage = 420;
|
||||
}*/
|
||||
|
||||
quest = player.getQuestRepository().getQuest("Nature Spirit");
|
||||
|
||||
if(quest.getStage(player) <= 5){
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Greetings again adventurer, How go your travels in", "Morytania? Is it as evil as I have heard?");
|
||||
stage = 420;
|
||||
} else if (quest.getStage(player) < 100){
|
||||
ContentAPI.openDialogue(player, new NSDrezelDialogue(), npc);
|
||||
} else {
|
||||
npcl(FacialExpression.NEUTRAL, "I heard you finished your quest with Filliman! Great work!");
|
||||
stage = END_DIALOGUE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -108,16 +128,37 @@ public final class DrezelMonumentDialogue extends DialoguePlugin {
|
|||
end();
|
||||
break;
|
||||
case 420:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Well, I'm going to look around a bit more.");
|
||||
options("Well, I'm going to look around a bit more.", "Is there anything else interesting to do around here?");
|
||||
stage = 421;
|
||||
break;
|
||||
case 421:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well, that sounds like a good idea. Don't get into any", "trouble though!");
|
||||
stage = 422;
|
||||
switch(buttonId){
|
||||
case 1:
|
||||
playerl(FacialExpression.FRIENDLY, "Well, I'm going to look around a bit more.");
|
||||
stage++;
|
||||
break;
|
||||
case 2:
|
||||
playerl(FacialExpression.HALF_THINKING, "Is there anything else interesting to do around here?");
|
||||
stage = 425;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 422:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well, that sounds like a good idea. Don't get into any", "trouble though!");
|
||||
stage = 423;
|
||||
break;
|
||||
case 423:
|
||||
end();
|
||||
break;
|
||||
case 425:
|
||||
npcl(FacialExpression.HALF_THINKING, "Well, not a great deal... but there is something you can do for me if you're interested. Though it is quite dangerous.");
|
||||
stage++;
|
||||
break;
|
||||
case 426:
|
||||
end();
|
||||
player.getDialogueInterpreter().open(new NSDrezelDialogue(), npc);
|
||||
player.getDialogueInterpreter().handle(0,0);
|
||||
break;
|
||||
case 120:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I need " + player.getGameAttributes().getAttribute("priest-in-peril:rune", 50) + " more.");
|
||||
stage = 121;
|
||||
|
|
@ -239,6 +280,6 @@ public final class DrezelMonumentDialogue extends DialoguePlugin {
|
|||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 1049 };
|
||||
return new int[] { NPCs.DREZEL_7707 };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import core.plugin.Plugin;
|
|||
import rs09.plugin.PluginManager;
|
||||
import org.rs09.consts.Items;
|
||||
|
||||
import static rs09.tools.stringtools.StringToolsKt.colorize;
|
||||
import static rs09.tools.stringtools.GlobalsKt.colorize;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package core.game.interaction.item;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import api.ContentAPI;
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
|
|
@ -13,6 +14,9 @@ import core.plugin.Initializable;
|
|||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
import core.tools.StringUtils;
|
||||
import org.rs09.consts.Items;
|
||||
import rs09.game.content.global.WeightBasedTable;
|
||||
import rs09.game.content.global.WeightedItem;
|
||||
|
||||
/**
|
||||
* Represents the casket handling plugin.
|
||||
|
|
@ -25,7 +29,16 @@ public final class CasketPlugin extends OptionHandler {
|
|||
/**
|
||||
* Represents the casket rewards.
|
||||
*/
|
||||
private static final ChanceItem[] CASKET_REWARD = new ChanceItem[] { new ChanceItem(995, 8, 3000, 30), new ChanceItem(1623, 1, 30), new ChanceItem(1621, 1, 70), new ChanceItem(1619, 1, 70), new ChanceItem(1617, 1, 97), new ChanceItem(987, 1, 97), new ChanceItem(985, 1, 97), new ChanceItem(1454, 1, 30), new ChanceItem(1452, 1, 70), new ChanceItem(1462, 1, 97) };
|
||||
private WeightBasedTable table = WeightBasedTable.create(
|
||||
new WeightedItem(Items.COINS_995, 20, 640, 55, false),
|
||||
new WeightedItem(Items.UNCUT_SAPPHIRE_1623, 1, 1, 32, false),
|
||||
new WeightedItem(Items.UNCUT_EMERALD_1621, 1, 1, 16, false),
|
||||
new WeightedItem(Items.UNCUT_RUBY_1619, 1, 1, 9, false),
|
||||
new WeightedItem(Items.UNCUT_DIAMOND_1617, 1, 1, 2, false),
|
||||
new WeightedItem(Items.COSMIC_TALISMAN_1454, 1, 1, 8, false),
|
||||
new WeightedItem(Items.LOOP_HALF_OF_A_KEY_987, 1, 1, 1, false),
|
||||
new WeightedItem(Items.TOOTH_HALF_OF_A_KEY_985, 1, 1, 1, false)
|
||||
);
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
|
|
@ -35,10 +48,10 @@ public final class CasketPlugin extends OptionHandler {
|
|||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
final ChanceItem reward = getChanceItem(CASKET_REWARD);
|
||||
final Item reward = table.roll().get(0);
|
||||
player.getInventory().remove((Item) node);
|
||||
player.getDialogueInterpreter().sendItemMessage(reward, "You open the casket. Inside you find " + (reward.getAmount() > 1 ? "some" : (StringUtils.isPlusN(reward.getName()) ? "an" : "a")) + " " + reward.getName().toLowerCase() + ".");
|
||||
player.getInventory().add(reward.getAmount() == 1 ? reward : new Item(reward.getId(), RandomFunction.random(reward.getMinimumAmount(), reward.getMaximumAmount())));
|
||||
ContentAPI.addItemOrDrop(player, reward.getId(), reward.getAmount());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package core.game.interaction.item;
|
||||
|
||||
import api.ContentAPI;
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
|
|
@ -12,6 +13,7 @@ import core.game.world.map.RegionManager;
|
|||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
import rs09.game.content.quest.members.naturespirit.NSUtils;
|
||||
|
||||
/**
|
||||
* Handles the Silver Sickle (b) to collect Mort Myre Fungus.
|
||||
|
|
@ -29,45 +31,18 @@ public final class SilverSicklePlugin extends OptionHandler {
|
|||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
Region region = RegionManager.forId(player.getLocation().getRegionId());
|
||||
switch (option) {
|
||||
case "operate":
|
||||
case "cast bloom":
|
||||
if (player.getSkills().getPrayerPoints() < 1) {
|
||||
player.getPacketDispatch().sendMessage("You don't have enough prayer points to do this.");
|
||||
if(player.getQuestRepository().getQuest("Nature Spirit").getStage(player) >= 75) {
|
||||
player.getPacketDispatch().sendAnimation(9021);
|
||||
NSUtils.castBloom(player);
|
||||
} else {
|
||||
ContentAPI.sendDialogue(player, "You must complete Nature Spirit to use this.");
|
||||
}
|
||||
for (Scenery[] o : region.getPlanes()[0].getObjects()) {
|
||||
for (Scenery obj : o) {
|
||||
if (obj != null) {
|
||||
if (obj.getName().equalsIgnoreCase("Rotting log") && player.getSkills().getPrayerPoints() >= 1) {
|
||||
if (player.getLocation().withinDistance(obj.getLocation(), 2)) {
|
||||
handleVisuals(player, node);
|
||||
SceneryBuilder.add(new Scenery(3509, obj.getLocation(), obj.getRotation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RegionManager.getLock().unlock();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the draining of prayer points and physical graphics and
|
||||
* animation.
|
||||
*/
|
||||
public void handleVisuals(Player player, Node node) {
|
||||
player.getSkills().decrementPrayerPoints(RandomFunction.random(1, 3));
|
||||
player.getPacketDispatch().sendAnimation(9021);
|
||||
final Location[] AROUND_YOU = new Location[] { Location.create(player.getLocation().getX() - 1, player.getLocation().getY(), 0), Location.create(player.getLocation().getX() + 1, player.getLocation().getY(), 0), Location.create(player.getLocation().getX(), player.getLocation().getY() - 1, 0), Location.create(player.getLocation().getX(), player.getLocation().getY() + 1, 0), Location.create(player.getLocation().getX() + 1, player.getLocation().getY() + 1, 0), Location.create(player.getLocation().getX() - 1, player.getLocation().getY() + 1, 0), Location.create(player.getLocation().getX() + 1, player.getLocation().getY() - 1, 0), Location.create(player.getLocation().getX() - 1, player.getLocation().getY() - 1, 0), Location.create(player.getLocation().getX() + 1, player.getLocation().getY() + 1, 0), };
|
||||
for (Location location : AROUND_YOU) {
|
||||
// The graphic is meant to play on a 3x3 radius around you, but not
|
||||
// including the tile you are on.
|
||||
player.getPacketDispatch().sendGlobalPositionGraphic(263, location);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package core.game.interaction.item.withitem;
|
||||
|
||||
import api.ContentAPI;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
|
@ -7,6 +8,7 @@ import core.game.node.item.Item;
|
|||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import org.rs09.consts.Items;
|
||||
|
||||
/**
|
||||
* Handles weapon poisiong.
|
||||
|
|
@ -297,8 +299,8 @@ public class PoisonWeaponPlugin extends UseWithHandler {
|
|||
}
|
||||
int amt = Math.min(weaponItem.getAmount(), 5);
|
||||
player.getInventory().remove(new Item(weaponItem.getId(), amt));
|
||||
player.getInventory().add(new Item(229, 1));
|
||||
player.getInventory().add(new Item(product, amt));
|
||||
ContentAPI.addItemOrDrop(player, product, amt);
|
||||
ContentAPI.addItemOrDrop(player, Items.VIAL_229, 1);
|
||||
player.getPacketDispatch().sendMessage("You poison the " + weaponItem.getName().toLowerCase() + ".");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import core.game.node.object.Scenery;
|
|||
import core.game.world.map.Location;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import org.rs09.consts.NPCs;
|
||||
|
||||
/**
|
||||
* Represents the quest node plugin handler.
|
||||
|
|
@ -200,7 +201,7 @@ public class PriestInPerilOptionPlugin extends OptionHandler {
|
|||
}
|
||||
break;
|
||||
case "talk-through":
|
||||
player.getDialogueInterpreter().open(1047, NPC.create(1047, player.getLocation()));
|
||||
player.getDialogueInterpreter().open(NPCs.DREZEL_7690, NPC.create(NPCs.DREZEL_7690, player.getLocation()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -638,7 +638,6 @@ public abstract class Entity extends Node {
|
|||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the updateMasks.
|
||||
* @return The updateMasks.
|
||||
|
|
|
|||
|
|
@ -55,8 +55,9 @@ public final class DeathTask extends NodeTask {
|
|||
}
|
||||
}
|
||||
}
|
||||
e.getAnimator().forceAnimation(e.getProperties().getDeathAnimation());
|
||||
e.graphics(Animator.RESET_G);
|
||||
e.visualize(e.getProperties().getDeathAnimation(), e.getProperties().deathGfx);
|
||||
e.getAnimator().forceAnimation(e.getProperties().getDeathAnimation());
|
||||
e.commenceDeath(killer);
|
||||
e.getImpactHandler().setDisabledTicks(50);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import core.game.node.entity.player.Player;
|
|||
import core.game.node.item.Item;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import rs09.game.node.entity.combat.CombatPulse;
|
||||
import rs09.game.system.config.ItemConfigParser;
|
||||
import rs09.game.system.config.NPCConfigParser;
|
||||
|
|
@ -92,6 +93,8 @@ public final class Properties {
|
|||
*/
|
||||
private Animation deathAnimation = new Animation(9055, Animator.Priority.HIGH);
|
||||
|
||||
public Graphics deathGfx = new Graphics(-1);
|
||||
|
||||
/**
|
||||
* The range animation.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import core.game.world.map.RegionManager;
|
|||
import core.game.world.map.build.DynamicRegion;
|
||||
import core.game.world.map.path.Pathfinder;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.game.world.update.flag.npc.NPCFaceEntity;
|
||||
import core.game.world.update.flag.npc.NPCFaceLocation;
|
||||
import core.game.world.update.flag.npc.NPCForceChat;
|
||||
|
|
@ -305,6 +306,9 @@ public class NPC extends Entity {
|
|||
if (definition.getConfiguration("movement_radius") != null) {
|
||||
this.setWalkRadius(definition.getConfiguration("movement_radius"));
|
||||
}
|
||||
if(definition.getConfiguration("death_gfx") != null) {
|
||||
getProperties().deathGfx = new Graphics(definition.getConfiguration("death_gfx"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ import java.util.*;
|
|||
|
||||
import static rs09.game.node.entity.player.info.stats.StatAttributeKeysKt.STATS_BASE;
|
||||
import static rs09.game.node.entity.player.info.stats.StatAttributeKeysKt.STATS_DEATHS;
|
||||
import static rs09.tools.stringtools.StringToolsKt.colorize;
|
||||
import static rs09.tools.stringtools.GlobalsKt.colorize;
|
||||
|
||||
/**
|
||||
* Represents a player entity.
|
||||
|
|
@ -497,6 +497,9 @@ public class Player extends Entity {
|
|||
details.getSession().disconnect();
|
||||
getSession().setLastPing(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
//Decrements prayer points
|
||||
getPrayer().tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ public final class PacketDispatch {
|
|||
* @param location the location.
|
||||
*/
|
||||
public void sendPositionedGraphic(int id, int height, int delay, Location location) {
|
||||
PacketRepository.send(PositionedGraphic.class, new PositionedGraphicContext(player, new Graphics(id, height, delay), location));
|
||||
PacketRepository.send(PositionedGraphic.class, new PositionedGraphicContext(player, new Graphics(id, height, delay), location, 0, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -342,8 +342,7 @@ public final class PacketDispatch {
|
|||
* @param location the location.
|
||||
*/
|
||||
public void sendPositionedGraphics(Graphics graphics, Location location) {
|
||||
PacketRepository.send(PositionedGraphic.class, new PositionedGraphicContext(player, graphics, location));
|
||||
|
||||
PacketRepository.send(PositionedGraphic.class, new PositionedGraphicContext(player, graphics, location, 0, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
package core.game.node.entity.player.link.prayer;
|
||||
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.system.task.NodeTask;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.tools.RandomFunction;
|
||||
import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks;
|
||||
|
||||
/**
|
||||
* Represents an event used to drain prayer points.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public final class DrainTask extends NodeTask {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DrainTask} {@code Object}.
|
||||
*/
|
||||
public DrainTask() {
|
||||
super(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exec(Node node, Node... n) {
|
||||
Player player = node.asPlayer();
|
||||
if (player.getPrayer().getActive().isEmpty()) {
|
||||
getPulse().stop();
|
||||
return true;
|
||||
}
|
||||
player.getSkills().decrementPrayerPoints(getDrain(player.getPrayer()));
|
||||
|
||||
if (player.getPrayer().getActive().contains(PrayerType.PIETY)
|
||||
&& new ZoneBorders(2732, 3467, 2739, 3471, 0).insideBorder(player)) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 2, 3);
|
||||
}
|
||||
|
||||
return player.getSkills().getPrayerPoints() <= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(Node node, Node... n) {
|
||||
final Player player = node.asPlayer();
|
||||
if (player.getSkills().getPrayerPoints() <= 0) {
|
||||
player.getPrayer().reset();
|
||||
player.getAudioManager().send(2672);
|
||||
player.getPacketDispatch().sendMessage("You have run out of prayer points, you must recharge at an altar.");
|
||||
}
|
||||
super.stop(node, n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Node node, Node... n) {
|
||||
node.asPlayer().removeAttribute("prayer-message");
|
||||
super.start(node, n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFor(String s, Node node, Node... n) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to initialize this pulse.
|
||||
* @param player the player.
|
||||
*/
|
||||
public void init(final Player player) {
|
||||
if (getPulse() == null || !getPulse().isRunning()) {
|
||||
schedule(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to return that drain tick.
|
||||
* @param prayer the prayer manager.
|
||||
* @return the drain tick, converted to an integer.
|
||||
*/
|
||||
public double getDrain(final Prayer prayer) {
|
||||
double amountDrain = 0;
|
||||
for (PrayerType type : prayer.getActive()) {
|
||||
double drain = type.getDrain();
|
||||
double bonus = (1/30f) * prayer.getPlayer().getProperties().getBonuses()[12];
|
||||
drain = drain * (1 + bonus);
|
||||
drain = 0.6 / drain;
|
||||
amountDrain += drain;
|
||||
}
|
||||
if(SkillcapePerks.isActive(SkillcapePerks.DIVINE_FAVOR,prayer.getPlayer()) && RandomFunction.random(100) <= 10){
|
||||
amountDrain = 0;
|
||||
}
|
||||
return amountDrain;
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import core.game.world.map.Location;
|
|||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -28,16 +29,13 @@ public final class Prayer {
|
|||
*/
|
||||
private final List<PrayerType> active = new ArrayList<>(20);
|
||||
|
||||
/**
|
||||
* Represents the current draining task.
|
||||
*/
|
||||
private final DrainTask task = new DrainTask();
|
||||
|
||||
/**
|
||||
* Represents the player instance.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
private int prayerActiveTicks = 0;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Prayer} {@code Object}.
|
||||
*/
|
||||
|
|
@ -115,6 +113,30 @@ public final class Prayer {
|
|||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if(!getActive().isEmpty()) prayerActiveTicks ++;
|
||||
else prayerActiveTicks = 0;
|
||||
|
||||
if(prayerActiveTicks > 0 && prayerActiveTicks % 2 == 0){
|
||||
double amountDrain = 0;
|
||||
for(PrayerType type : getActive()){
|
||||
double drain = type.getDrain();
|
||||
double bonus = (1/30f) * getPlayer().getProperties().getBonuses()[12];
|
||||
drain = drain * (1 + bonus);
|
||||
drain = 0.6 / drain;
|
||||
amountDrain += drain;
|
||||
}
|
||||
if(SkillcapePerks.isActive(SkillcapePerks.DIVINE_FAVOR, getPlayer()) && RandomFunction.random(100) <= 10){
|
||||
amountDrain = 0;
|
||||
}
|
||||
|
||||
getPlayer().getSkills().decrementPrayerPoints(amountDrain);
|
||||
if(getPlayer().getSkills().getPrayerPoints() == 0){
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skill bonus for the given skill id.
|
||||
* @param skillId The skill id.
|
||||
|
|
@ -159,14 +181,6 @@ public final class Prayer {
|
|||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the task.
|
||||
* @return The task.
|
||||
*/
|
||||
public DrainTask getTask() {
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the active prayers.
|
||||
* @return The active.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package core.game.node.entity.player.link.prayer;
|
||||
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.SkillRestoration;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.audio.Audio;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -251,16 +253,16 @@ public enum PrayerType {
|
|||
if (on) {
|
||||
flag(player, this);
|
||||
player.getPrayer().getActive().add(this);
|
||||
player.getPrayer().getTask().init(player);
|
||||
iconify(player, getIcon(player, this));
|
||||
player.getAudioManager().send(getSound());
|
||||
|
||||
if (this == PrayerType.PIETY
|
||||
&& new ZoneBorders(2732, 3467, 2739, 3471, 0).insideBorder(player)) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 2, 3);
|
||||
}
|
||||
} else {
|
||||
player.getPrayer().getActive().remove(this);
|
||||
findNextIcon(player);
|
||||
if (player.getPrayer().getActive().isEmpty()) {
|
||||
player.getPrayer().getTask().stop(player);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import core.net.packet.PacketRepository;
|
|||
import core.net.packet.context.ContainerContext;
|
||||
import core.net.packet.out.ContainerPacket;
|
||||
|
||||
import static rs09.tools.stringtools.StringToolsKt.colorize;
|
||||
import static rs09.tools.stringtools.GlobalsKt.colorize;
|
||||
|
||||
/**
|
||||
* Represents the container during a trade session.
|
||||
|
|
|
|||
|
|
@ -87,9 +87,12 @@ public class BoneOfferPlugin extends UseWithHandler {
|
|||
return;
|
||||
}
|
||||
final Location start = player.getLocation();
|
||||
|
||||
Location gfxLoc = player.getLocation().transform(player.getDirection(), 1);
|
||||
|
||||
ContentAPI.submitIndividualPulse(player, new Pulse(1) {
|
||||
int counter = 0;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
counter++;
|
||||
|
|
@ -97,7 +100,7 @@ public class BoneOfferPlugin extends UseWithHandler {
|
|||
if (player.getInventory().remove(new Item(b.getItemId()))) {
|
||||
player.animate(ANIM);
|
||||
player.getAudioManager().send(new Audio(958));
|
||||
player.getPacketDispatch().sendPositionedGraphics(GFX, altar.getLocation());
|
||||
player.getPacketDispatch().sendPositionedGraphics(GFX, gfxLoc);
|
||||
player.sendMessage(getMessage(isLit(left), isLit(right)));
|
||||
player.getSkills().addExperience(Skills.PRAYER, b.getExperience() * getMod(altar, isLit(left), isLit(right)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package core.game.node.entity.skill.herblore;
|
||||
|
||||
import core.game.node.item.Item;
|
||||
import org.rs09.consts.Items;
|
||||
|
||||
/**
|
||||
* Represents a finished potion.
|
||||
|
|
@ -21,7 +22,7 @@ public enum FinishedPotion {
|
|||
SUPER_ANTIPOISON(UnfinishedPotion.IRIT, new Item(235), 48, 106.3, new Item(181)),
|
||||
FISHING_POTION(UnfinishedPotion.AVANTOE, new Item(231), 50, 112.5, new Item(151)),
|
||||
SUPER_ENERGY(UnfinishedPotion.AVANTOE, new Item(2970), 52, 117.5, new Item(3018)),
|
||||
HUNTING_POTION(UnfinishedPotion.AVANTOE, new Item(10109), 53, 120, new Item(10000)),
|
||||
HUNTING_POTION(UnfinishedPotion.AVANTOE, new Item(Items.KEBBIT_TEETH_DUST_10111), 53, 120, new Item(10000)),
|
||||
SUPER_STRENGTH(UnfinishedPotion.KWUARM, new Item(225), 55, 125, new Item(157)),
|
||||
WEAPON_POISON(UnfinishedPotion.KWUARM, new Item(241), 60, 137.5, new Item(187)),
|
||||
SUPER_RESTORE(UnfinishedPotion.SNAPDRAGON, new Item(223), 63, 142.5, new Item(3026)),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import core.game.world.map.path.Path;
|
|||
import core.game.world.map.path.Pathfinder;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Represents a location on the world map.
|
||||
* @author Emperor
|
||||
|
|
@ -250,6 +252,24 @@ public final class Location extends Node {
|
|||
return Math.sqrt(xdiff * xdiff + ydiff * ydiff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 8 tiles surrounding this location as an ArrayList<Location>
|
||||
*/
|
||||
public ArrayList<Location> getSurroundingTiles() {
|
||||
ArrayList<Location> locs = new ArrayList<>();
|
||||
|
||||
locs.add(transform(0,1,0)); //N
|
||||
locs.add(transform(1,1,0)); //NE
|
||||
locs.add(transform(1,0,0)); //E
|
||||
locs.add(transform(1,-1,0)); //SE
|
||||
locs.add(transform(0,-1,0)); //S
|
||||
locs.add(transform(-1,-1,0));//SW
|
||||
locs.add(transform(-1,0,0));//W
|
||||
locs.add(transform(-1,1,0));//NW
|
||||
|
||||
return locs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x position on the region chunk.
|
||||
* @return The x position on the region chunk.
|
||||
|
|
@ -339,7 +359,7 @@ public final class Location extends Node {
|
|||
* @return The local y-coordinate.
|
||||
*/
|
||||
public int getSceneY(Location loc) {
|
||||
return y - ((loc.getRegionY() - 6) * 8);
|
||||
return y - ((loc.getRegionY() - 6) << 3);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -89,8 +89,8 @@ object RegionManager {
|
|||
if (!region.isHasFlags) {
|
||||
return -1
|
||||
}
|
||||
x -= x shr 6 shl 6
|
||||
y -= y shr 6 shl 6
|
||||
x -= (x shr 6) shl 6
|
||||
y -= (y shr 6) shl 6
|
||||
return region.planes[z].flags.clippingFlags[x][y]
|
||||
}
|
||||
|
||||
|
|
@ -175,8 +175,8 @@ object RegionManager {
|
|||
if (!region.isHasFlags) {
|
||||
return
|
||||
}
|
||||
x -= x shr 6 shl 6
|
||||
y -= y shr 6 shl 6
|
||||
x -= (x shr 6) shl 6
|
||||
y -= (y shr 6) shl 6
|
||||
if (projectile) {
|
||||
region.planes[z].projectileFlags.flag(x, y, flag)
|
||||
} else {
|
||||
|
|
@ -201,8 +201,8 @@ object RegionManager {
|
|||
if (!region.isHasFlags) {
|
||||
return
|
||||
}
|
||||
x -= x shr 6 shl 6
|
||||
y -= y shr 6 shl 6
|
||||
x -= (x shr 6) shl 6
|
||||
y -= (y shr 6) shl 6
|
||||
if (projectile) {
|
||||
region.planes[z].projectileFlags.unflag(x, y, flag)
|
||||
} else {
|
||||
|
|
@ -226,8 +226,8 @@ object RegionManager {
|
|||
if (!region.isHasFlags) {
|
||||
return -1
|
||||
}
|
||||
x -= x shr 6 shl 6
|
||||
y -= y shr 6 shl 6
|
||||
x -= (x shr 6) shl 6
|
||||
y -= (y shr 6) shl 6
|
||||
return region.planes[z].projectileFlags.clippingFlags[x][y]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,16 +26,23 @@ public final class PositionedGraphicContext implements Context {
|
|||
*/
|
||||
private final Location location;
|
||||
|
||||
public int sceneX, sceneY;
|
||||
public int offsetX, offsetY;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PositionedGraphicContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param graphic The graphic to display on the given location.
|
||||
* @param location The location to display the graphic on.
|
||||
*/
|
||||
public PositionedGraphicContext(Player player, Graphics graphic, Location location) {
|
||||
public PositionedGraphicContext(Player player, Graphics graphic, Location location, int offsetX, int offsetY) {
|
||||
this.player = player;
|
||||
this.graphic = graphic;
|
||||
this.location = location;
|
||||
this.sceneX = location.getSceneX(player.getPlayerFlags().getLastSceneGraph());
|
||||
this.sceneY = location.getSceneY(player.getPlayerFlags().getLastSceneGraph());
|
||||
this.offsetX = offsetX;
|
||||
this.offsetY = offsetY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import core.cache.def.impl.VarbitDefinition;
|
|||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import org.rs09.consts.Items;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
|
@ -61,16 +62,27 @@ public final class ExaminePacket implements IncomingPacket {
|
|||
|
||||
/**
|
||||
* Gets the item examine.
|
||||
* @param id the id.
|
||||
* @return the name.
|
||||
* @param id the item id.
|
||||
* @return the item examine.
|
||||
*/
|
||||
public static String getItemExamine(int id) {
|
||||
if (id == 995) {
|
||||
|
||||
// Coins examine override
|
||||
if (id == Items.COINS_995) {
|
||||
return "Lovely money!";
|
||||
}
|
||||
|
||||
// Clue scroll examine override
|
||||
if (ItemDefinition.forId(id).getExamine().length() == 255) {
|
||||
return "A set of instructions to be followed.";
|
||||
}
|
||||
|
||||
// Noted item examine override
|
||||
if (!ItemDefinition.forId(id).isUnnoted()) {
|
||||
return "Swap this note at any bank for the equivalent item.";
|
||||
}
|
||||
|
||||
// Return the examine string for the given item ID
|
||||
return ItemDefinition.forId(id).getExamine();
|
||||
}
|
||||
}
|
||||
|
|
@ -338,7 +338,7 @@ public final class InteractionPacket implements IncomingPacket {
|
|||
player.debug("Handled by quest interaction manager.");
|
||||
return;
|
||||
}
|
||||
if(InteractionListeners.run(item.getId(), InteractionListener.Companion.getITEM(),option.getName(),player,item)){
|
||||
if(InteractionListeners.run(item.getId(), InteractionListener.Companion.getGROUNDITEM(), option.getName(),player,item)){
|
||||
return;
|
||||
}
|
||||
item.getInteraction().handle(player, option);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import core.game.world.update.flag.context.Graphics;
|
|||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.OutgoingPacket;
|
||||
import core.net.packet.context.PositionedGraphicContext;
|
||||
import rs09.game.system.SystemLogger;
|
||||
|
||||
/**
|
||||
* The positioned graphic outgoing packet.
|
||||
|
|
@ -16,8 +17,16 @@ public final class PositionedGraphic implements OutgoingPacket<PositionedGraphic
|
|||
public void send(PositionedGraphicContext context) {
|
||||
Location l = context.getLocation();
|
||||
Graphics g = context.getGraphic();
|
||||
IoBuffer buffer = UpdateAreaPosition.getBuffer(context.getPlayer(), l).put(17).put((l.getChunkOffsetX() << 4) | (l.getChunkOffsetY() & 0x7)).putShort(g.getId()).put(g.getHeight()).putShort(g.getDelay());
|
||||
buffer.cypherOpcode(context.getPlayer().getSession().getIsaacPair().getOutput());context.getPlayer().getSession().write(buffer);
|
||||
int offsetHash = (context.offsetX << 4) | context.offsetY;
|
||||
IoBuffer buffer = new IoBuffer()
|
||||
.put(26) //update current scene x and scene y client-side
|
||||
.putC(context.sceneX) //this has to be done for each graphic being sent
|
||||
.put(context.sceneY) //opcode 26 is the lastSceneX/lastSceneY update packet
|
||||
.put(17).put(offsetHash) //send the graphics
|
||||
.putShort(g.getId())
|
||||
.put(g.getHeight())
|
||||
.putShort(g.getDelay());
|
||||
context.getPlayer().getSession().write(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1090,6 +1090,29 @@ object ContentAPI {
|
|||
player.packetDispatch.sendItemOnInterface(item,amount,iface,child)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a dialogue box with a single item and some text
|
||||
* @param player the player to send it to
|
||||
* @param item the ID of the item to show
|
||||
* @param message the text to display
|
||||
*/
|
||||
@JvmStatic
|
||||
fun sendItemDialogue(player: Player, item: Int, message: String){
|
||||
player.dialogueInterpreter.sendItemMessage(item, *DialUtils.splitLines(message))
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a dialogue box with two items and some text
|
||||
* @param player the player to send it to
|
||||
* @param item1 the ID of the first item to show
|
||||
* @param item2 the ID of the second item to show
|
||||
* @param message the text to display
|
||||
*/
|
||||
@JvmStatic
|
||||
fun sendDoubleItemDialogue(player: Player, item1: Int, item2: Int, message: String){
|
||||
player.dialogueInterpreter.sendDoubleItemMessage(item1, item2, message)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an input dialogue to retrieve a specified value from the player
|
||||
* @param player the player to send the input dialogue to
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package rs09.game.content.quest.members.naturespirit
|
||||
|
||||
import api.ContentAPI
|
||||
import core.game.node.entity.npc.AbstractNPC
|
||||
import core.game.world.map.Location
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
@Initializable
|
||||
class FillimanTarlockNPC : AbstractNPC {
|
||||
var spawnedTicks = 0
|
||||
constructor() : super(NPCs.FILLIMAN_TARLOCK_1050, null, true) {}
|
||||
private constructor(id: Int, location: Location) : super(id, location) {}
|
||||
|
||||
override fun construct(id: Int, location: Location, vararg objects: Any?): AbstractNPC {
|
||||
return FillimanTarlockNPC(id, location)
|
||||
}
|
||||
|
||||
init {
|
||||
isNeverWalks = true
|
||||
isWalks = false
|
||||
}
|
||||
|
||||
override fun handleTickActions() {
|
||||
super.handleTickActions()
|
||||
if(spawnedTicks++ > 100) ContentAPI.poofClear(this)
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.FILLIMAN_TARLOCK_1050)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package rs09.game.content.quest.members.naturespirit
|
||||
|
||||
import api.ContentAPI
|
||||
import core.game.content.dialogue.FacialExpression
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import org.rs09.consts.Items
|
||||
import rs09.game.content.dialogue.DialogueFile
|
||||
import rs09.tools.END_DIALOGUE
|
||||
import rs09.tools.stringtools.colorize
|
||||
|
||||
class NSDrezelDialogue : DialogueFile() {
|
||||
var questStage = 0
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
questStage = player!!.questRepository.getStage("Nature Spirit")
|
||||
|
||||
if(questStage <= 5){
|
||||
when(stage){
|
||||
0 -> options("Sorry, not interested...", "Well, what is it, I may be able to help?").also { stage++ }
|
||||
1 -> when(buttonID){
|
||||
1 -> playerl(FacialExpression.NEUTRAL, "Sorry, not interested.").also { stage = END_DIALOGUE }
|
||||
2 -> playerl(FacialExpression.FRIENDLY, "Well, what is it, I may be able to help?").also { stage++ }
|
||||
}
|
||||
|
||||
2 -> npcl(FacialExpression.HALF_THINKING, "There's a man called Filliman who lives in Mort Myre, I wonder if you could look for him? The swamps of Mort Myre are dangerous though, they're infested with Ghasts!").also { stage++ }
|
||||
3 -> options("Who is this Filliman?", "Where's Mort Myre?", "What's a Ghast?", "Yes, I'll go and look for him.", "Sorry, I don't think I can help.").also { stage++ }
|
||||
4 -> when(buttonID){
|
||||
1 -> npcl(FacialExpression.NEUTRAL, "Filliman Tarlock is his full name and he's a Druid. He lives in Mort Myre much like a hermit, but there's many a traveller who he's helped.").also { stage-- }
|
||||
2 -> npcl(FacialExpression.NEUTRAL, "Mort Myre is a decayed and dangerous swamp to the south. It was once a beautiful forest but has since become filled with vile emanations from within Morytania.").also { stage = 6 }
|
||||
3 -> npcl(FacialExpression.NEUTRAL, "A Ghast is a poor soul who died in Mort Myre. They're undead of a special class, they're untouchable as far as I'm aware!").also { stage = 5 }
|
||||
4 -> playerl(FacialExpression.FRIENDLY, "Yes, I'll go and look for him.").also { stage = 10 }
|
||||
5 -> playerl(FacialExpression.NEUTRAL, "Sorry, I don't think I can help.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
5 -> npcl(FacialExpression.NEUTRAL, "Filliman knew how to tackle them, but I've not heard from him in a long time. Ghasts, when they attack, will devour any food you have. If you have no food, they'll draw their nourishment from you!").also { stage = 3 }
|
||||
6 -> npcl(FacialExpression.NEUTRAL, " We put a fence around it to stop unwary travellers going in. Anyone who dies in the swamp is forever cursed to haunt it as a Ghast. Ghasts attack travellers, turning food to rotten filth.").also { stage = 3 }
|
||||
|
||||
10 -> npcl(FacialExpression.NEUTRAL, "That's great, but it is very dangerous. Are you sure you want to do this?").also { stage++ }
|
||||
11 -> options("Yes, I'm sure.", "Sorry, I don't think I can help.").also { stage++ }
|
||||
12 -> when(buttonID){
|
||||
1 -> playerl(FacialExpression.FRIENDLY, "Yes, I'm sure.").also { stage = 20 }
|
||||
2 -> playerl(FacialExpression.NEUTRAL, "Sorry, I don't think I can help.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
20 -> npcl(FacialExpression.NEUTRAL, "That's great! Many Thanks! Now then, please be aware of the Ghasts, you cannot attack them, only Filliman knew how to take them on.").also { stage++ }
|
||||
21 -> npcl(FacialExpression.NEUTRAL, "Just run from them if you can. If you start to get lost, try to make your way back to the temple.").also { stage++ }
|
||||
22 -> {
|
||||
ContentAPI.sendDoubleItemDialogue(player!!, Items.MEAT_PIE_2327, Items.APPLE_PIE_2323, "The cleric hands you some food.")
|
||||
if(questStage == 0){
|
||||
repeat(3) { ContentAPI.addItemOrDrop(player!!, Items.MEAT_PIE_2327, 1) }
|
||||
repeat(3) { ContentAPI.addItemOrDrop(player!!, Items.APPLE_PIE_2323, 1) }
|
||||
player!!.questRepository.getQuest("Nature Spirit").setStage(player!!, 5)
|
||||
}
|
||||
stage++
|
||||
}
|
||||
23 -> npcl(FacialExpression.NEUTRAL, "Please take this food to Filliman, he'll probably appreciate a bit of cooked food. Now, he's never revealed where he lives in the swamps but I guess he'd be to the south, search for him won't you?").also { stage++ }
|
||||
24 -> playerl(FacialExpression.FRIENDLY, "I'll do my very best, don't worry, if he's in there and he's still alive I'll definitely find him.").also { stage = END_DIALOGUE; player!!.questRepository.getQuest("Nature Spirit").start(player!!) }
|
||||
}
|
||||
}
|
||||
|
||||
else if(questStage == 15) {
|
||||
when(stage){
|
||||
0 -> playerl(FacialExpression.HALF_GUILTY, "I've found Filliman and you should prepare for some sad news.").also { stage++ }
|
||||
1 -> npcl(FacialExpression.HALF_GUILTY, "You mean... he's dead?").also { stage++ }
|
||||
2 -> playerl(FacialExpression.NEUTRAL, "Well, er sort of. I got to his camp and I encountered a spirit of some kind. I don't think it was a Ghast, it tried to communicate with me, but made no sense, it was all 'ooooh' this and 'oooh' that.").also { stage++ }
|
||||
3 -> npcl(FacialExpression.NEUTRAL, "Hmmm, that's very interesting, I seem to remember Father Aereck in Lumbridge and his predecessor Father Urhney having a similar issue. Though this is probably not related to your problem.").also { stage++ }
|
||||
4 -> npcl(FacialExpression.NEUTRAL, " I will pray that it wasn't the spirit of my friend Filliman, but some lost soul who needs some help. Please do let me know how you get on with it.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
}
|
||||
|
||||
else if(questStage == 35){
|
||||
when(stage){
|
||||
0 -> playerl(FacialExpression.FRIENDLY, "Hello again! I'm helping Filliman, he plans to become a nature spirit. I have a spell to cast but first I need to be blessed. Can you bless me?").also { stage++ }
|
||||
1 -> npcl(FacialExpression.NEUTRAL, "But you haven't sneezed!").also { stage++ }
|
||||
2 -> playerl(FacialExpression.FRIENDLY, "You're so funny! But can you bless me?").also { stage++ }
|
||||
3 -> npcl(FacialExpression.NEUTRAL, "Very well my friend, prepare yourself for the blessings of Saradomin. Here we go!").also { stage++ }
|
||||
4 -> {
|
||||
end()
|
||||
player!!.lock();
|
||||
ContentAPI.submitIndividualPulse(player!!, BlessingPulse(npc!!, player!!))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if(questStage == 40){
|
||||
npcl(FacialExpression.NEUTRAL, "There you go my friend, you're now blessed. It's funny, now I look at you, there seems to be something of the faith about you. Anyway, good luck with your quest!").also { stage = END_DIALOGUE; player!!.questRepository.getQuest("Nature Spirit").setStage(player!!, 45) }
|
||||
}
|
||||
|
||||
else {
|
||||
when(stage){
|
||||
0 -> npcl(FacialExpression.NEUTRAL, "Hello, friend, how goes your quest with Filliman?").also { stage++ }
|
||||
1 -> playerl(FacialExpression.NEUTRAL, "Still working at it.").also { stage++ }
|
||||
2 -> npcl(FacialExpression.NEUTRAL, "Well enough! Do let me know when something develops!").also { stage = END_DIALOGUE }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class BlessingPulse(val drezel: NPC, val player: Player) : Pulse(){
|
||||
var ticks = 0
|
||||
|
||||
override fun pulse(): Boolean {
|
||||
when(ticks){
|
||||
0 -> ContentAPI.animate(drezel, 1162).also { ContentAPI.spawnProjectile(drezel, player, 268); ContentAPI.playAudio(player, Audio(2674)) }
|
||||
2 -> ContentAPI.visualize(player, Animation(645), Graphics(267, 100))
|
||||
4 -> ContentAPI.unlock(player).also { player.questRepository.getQuest("Nature Spirit").setStage(player, 40); return true }
|
||||
}
|
||||
ticks++
|
||||
return false
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
ContentAPI.openDialogue(player, NSDrezelDialogue(), drezel)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
package rs09.game.content.quest.members.naturespirit
|
||||
|
||||
import api.Container
|
||||
import api.ContentAPI
|
||||
import api.DialUtils
|
||||
import core.game.content.dialogue.FacialExpression
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.GroundItem
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import rs09.game.content.dialogue.DialogueFile
|
||||
import rs09.game.content.global.action.PickupHandler
|
||||
import rs09.game.interaction.InteractionListener
|
||||
import rs09.game.node.entity.npc.other.MortMyreGhastNPC
|
||||
import rs09.game.system.SystemLogger
|
||||
import rs09.game.system.config.ShopParser
|
||||
import rs09.tools.END_DIALOGUE
|
||||
|
||||
class NSListeners : InteractionListener() {
|
||||
|
||||
val GROTTO_TREE = 3517
|
||||
val GROTTO_ENTRANCE = 3516
|
||||
val GROTTO_ALTAR = 3520
|
||||
val NATURE_ALTAR = 3521
|
||||
val JOURNAL = Items.JOURNAL_2967
|
||||
val NATURE_STONE = 3527
|
||||
val FAITH_STONE = 3528
|
||||
val FREELY_GIVEN_STONE = 3529
|
||||
val WASHING_BOWL = Items.WASHING_BOWL_2964
|
||||
val MIRROR = Items.MIRROR_2966
|
||||
val SPELLCARD = Items.DRUIDIC_SPELL_2968
|
||||
val USED_SPELLCARD = Items.A_USED_SPELL_2969
|
||||
val FUNGUS = Items.MORT_MYRE_FUNGUS_2970
|
||||
val MIRROR_TAKEN = "/save:ns:mirror_taken"
|
||||
val GROTTO_SEARCHED = "/save:ns:grotto_searched"
|
||||
val WISHING_WELL = 28715
|
||||
val DRUID_POUCH = Items.DRUID_POUCH_2958
|
||||
val DRUID_POUCH_EMPTY = Items.DRUID_POUCH_2957
|
||||
val stones = intArrayOf(NATURE_STONE, FAITH_STONE, FREELY_GIVEN_STONE)
|
||||
val items = intArrayOf(USED_SPELLCARD, FUNGUS)
|
||||
|
||||
override fun defineListeners() {
|
||||
on(GROTTO_TREE, SCENERY, "look-at"){player, _ ->
|
||||
ContentAPI.sendMessage(player, "It looks like a tree on a large rock with roots trailing down to the ground.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(GROTTO_TREE, SCENERY, "search"){player, _ ->
|
||||
if(!ContentAPI.getAttribute(player, GROTTO_SEARCHED, false) || !(ContentAPI.inInventory(player, JOURNAL) || ContentAPI.inBank(player, JOURNAL))){
|
||||
ContentAPI.sendItemDialogue(player, JOURNAL, "You search the strange rock. You find a knot and inside of it you discover a small tome. The words on the front are a bit vague, but you can make out the words 'Tarlock' and 'journal'.")
|
||||
ContentAPI.addItemOrDrop(player, JOURNAL, 1)
|
||||
ContentAPI.setAttribute(player, GROTTO_SEARCHED, true)
|
||||
return@on true
|
||||
}
|
||||
return@on false
|
||||
}
|
||||
|
||||
on(GROTTO_ENTRANCE, SCENERY, "enter"){player, node ->
|
||||
val questStage = player.questRepository.getQuest("Nature Spirit").getStage(player)
|
||||
if(questStage < 55) {
|
||||
val npc = core.game.node.entity.npc.NPC.create(NPCs.FILLIMAN_TARLOCK_1050, Location.create(3440, 3336, 0))
|
||||
npc.init()
|
||||
} else if(questStage < 60) {
|
||||
player.teleport(Location.create(3442, 9734, 0))
|
||||
} else if (questStage >= 60){
|
||||
player.teleport(Location.create(3442, 9734, 1))
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(GROTTO_ALTAR, SCENERY,"search"){player, node ->
|
||||
val stage = player.questRepository.getStage("Nature Spirit")
|
||||
if(stage == 55){
|
||||
ContentAPI.openDialogue(player, FillimanCompletionDialogue(), NPC(NPCs.FILLIMAN_TARLOCK_1050))
|
||||
return@on true
|
||||
}
|
||||
|
||||
return@on false
|
||||
}
|
||||
|
||||
on(NATURE_STONE, SCENERY, "search"){player, _ ->
|
||||
ContentAPI.sendDialogue(player, "You search the stone and find that it has some sort of nature symbol scratched into it.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(FAITH_STONE, SCENERY, "search"){player, _ ->
|
||||
ContentAPI.sendDialogue(player, "You search the stone and find that it has some sort of faith symbol scratched into it.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(FREELY_GIVEN_STONE, SCENERY, "search"){player, _ ->
|
||||
ContentAPI.sendDialogue(player, "You search the stone and find it has some sort of spirit symbol scratched into it.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(WISHING_WELL, SCENERY, "make-wish"){player, node ->
|
||||
if(player.questRepository.isComplete("Nature Spirit") && player.questRepository.isComplete("Wolf Whistle"))
|
||||
ShopParser.openUid(player, 241)
|
||||
else
|
||||
ContentAPI.sendDialogue(player, "You can't do that yet.")
|
||||
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(JOURNAL, ITEM, "read"){player, _ ->
|
||||
player.dialogueInterpreter.open(NSJournalDialogue())
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(WASHING_BOWL, GROUNDITEM, "take"){player, node ->
|
||||
SystemLogger.logInfo("Running listener")
|
||||
GroundItemManager.create(Item(MIRROR), node.location, player)
|
||||
PickupHandler.take(player, node as GroundItem)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(MIRROR, GROUNDITEM, "take"){player, node ->
|
||||
if(ContentAPI.getAttribute(player, MIRROR_TAKEN, false) && (ContentAPI.inInventory(player, MIRROR) || ContentAPI.inBank(player, MIRROR))){
|
||||
ContentAPI.sendDialogue(player, "I don't need another one of these.")
|
||||
return@on true
|
||||
}
|
||||
ContentAPI.setAttribute(player, MIRROR_TAKEN, true)
|
||||
PickupHandler.take(player, node as GroundItem)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(SPELLCARD, ITEM, "cast"){player, node ->
|
||||
if(NSUtils.castBloom(player)){
|
||||
ContentAPI.removeItem(player, node.asItem(), Container.INVENTORY)
|
||||
ContentAPI.addItem(player, Items.A_USED_SPELL_2969)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(intArrayOf(DRUID_POUCH, DRUID_POUCH_EMPTY), ITEM, "fill"){player, node ->
|
||||
|
||||
if(player.questRepository.getStage("Nature Spirit") >= 75) {
|
||||
if (ContentAPI.amountInInventory(player, Items.MORT_MYRE_FUNGUS_2970) >= 3) {
|
||||
if (node.id != Items.DRUID_POUCH_2958) {
|
||||
ContentAPI.removeItem(player, node, Container.INVENTORY)
|
||||
}
|
||||
ContentAPI.removeItem(player, Item(Items.MORT_MYRE_FUNGUS_2970, 3), Container.INVENTORY)
|
||||
ContentAPI.addItem(player, Items.DRUID_POUCH_2958, 3)
|
||||
} else {
|
||||
ContentAPI.sendDialogue(player, "You need 3 fungus before you can do that.")
|
||||
}
|
||||
} else {
|
||||
ContentAPI.sendDialogue(player, "I don't know how to use that yet.")
|
||||
}
|
||||
|
||||
return@on true
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, Items.SILVER_SICKLE_2961, NATURE_ALTAR){player, used, with ->
|
||||
ContentAPI.sendItemDialogue(player, Items.SILVER_SICKLEB_2963, "You dump the sickle into the waters.")
|
||||
if(ContentAPI.removeItem(player, Items.SILVER_SICKLE_2961, Container.INVENTORY)){
|
||||
ContentAPI.addItem(player, Items.SILVER_SICKLEB_2963, 1)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(NPC, DRUID_POUCH, NPCs.GHAST_1052){player, used, with ->
|
||||
NSUtils.activatePouch(player, with as MortMyreGhastNPC)
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, items, *stones) { player, used, with ->
|
||||
when (used.id) {
|
||||
USED_SPELLCARD -> {
|
||||
if (with.id == FREELY_GIVEN_STONE) {
|
||||
if(ContentAPI.removeItem(player, used, Container.INVENTORY)){
|
||||
ContentAPI.sendNPCDialogue(player, NPCs.FILLIMAN_TARLOCK_1050, "Aha, yes, that seems right well done!")
|
||||
ContentAPI.sendMessage(player, "The stone seems to absorb the used spell scroll.")
|
||||
NSUtils.flagCardPlaced(player)
|
||||
}
|
||||
} else ContentAPI.sendMessage(player, "You try to put the item on the stone, but it just moves off.")
|
||||
}
|
||||
|
||||
FUNGUS -> {
|
||||
if (with.id == NATURE_STONE) {
|
||||
if(ContentAPI.removeItem(player, used, Container.INVENTORY)){
|
||||
ContentAPI.sendNPCDialogue(player, NPCs.FILLIMAN_TARLOCK_1050, "Aha, yes, that seems right well done!")
|
||||
ContentAPI.sendMessage(player, "The stone seems to absorb the used fungus.")
|
||||
NSUtils.flagFungusPlaced(player)
|
||||
}
|
||||
} else ContentAPI.sendMessage(player, "You try to put the item on the stone, but it just moves off.")
|
||||
}
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NSJournalDialogue : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
when(stage){
|
||||
0 -> dialogue(*DialUtils.splitLines("Most of the writing is pretty uninteresting, but something inside refers to a nature spirit. The requirements for which are,")).also { stage++ }
|
||||
1 -> dialogue(*DialUtils.splitLines("'Something from nature', 'something with faith' and 'something of the spirit-to-become freely given'. It's all pretty vague.")).also { stage = END_DIALOGUE }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FillimanCompletionDialogue : DialogueFile() {
|
||||
override fun handle(componentID: Int, buttonID: Int) {
|
||||
when(stage){
|
||||
0 -> npcl(FacialExpression.NEUTRAL, "Well, hello there again. I was just enjoying the grotto. Many thanks for your help, I couldn't have become a Spirit of nature without you.").also { stage++ }
|
||||
1 -> npcl(FacialExpression.NEUTRAL, "I must complete the transformation now. Just stand there and watch the show, apparently it's quite good!").also { stage++ }
|
||||
2 -> {
|
||||
end()
|
||||
ContentAPI.lock(player!!, 10)
|
||||
ContentAPI.submitWorldPulse(CompleteSpellPulse(player!!))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CompleteSpellPulse(val player: Player) : Pulse(2){
|
||||
var counter = 0
|
||||
val locations = arrayOf(Location.create(3444, 9740, 0), Location.create(3439, 9740, 0), Location.create(3439, 9737, 0), Location.create(3444, 9737, 0), Location.create(3444, 9735, 0), Location.create(3438, 9735, 0))
|
||||
val dest = Location.create(3441, 9738, 0)
|
||||
override fun pulse(): Boolean {
|
||||
when(counter++){
|
||||
0 -> repeat(6) { ContentAPI.spawnProjectile(locations[it], dest, 268, 0, 1000, 0, 40, 20) }
|
||||
1 -> player.questRepository.getQuest("Nature Spirit").setStage(player, 60)
|
||||
2 -> player.teleport(player.location.transform(0,0,1))
|
||||
3 -> ContentAPI.openDialogue(player, NPCs.NATURE_SPIRIT_1051, ContentAPI.findLocalNPC(player, NPCs.NATURE_SPIRIT_1051) as NPC).also { ContentAPI.unlock(player); return true }
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
package rs09.game.content.quest.members.naturespirit
|
||||
|
||||
import api.Container
|
||||
import api.ContentAPI
|
||||
import api.DialUtils
|
||||
import core.game.content.dialogue.DialoguePlugin
|
||||
import core.game.content.dialogue.FacialExpression
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.quest.Quest
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import rs09.tools.END_DIALOGUE
|
||||
|
||||
@Initializable
|
||||
class NSTarlockDialogue(player: Player? = null) : DialoguePlugin(player) {
|
||||
var questStage = 0
|
||||
|
||||
override fun newInstance(player: Player?): DialoguePlugin {
|
||||
return NSTarlockDialogue(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any?): Boolean {
|
||||
npc = args[0] as NPC
|
||||
val quest = player.questRepository.getQuest("Nature Spirit")
|
||||
questStage = quest.getStage(player)
|
||||
|
||||
if(questStage > 10 && !ContentAPI.inEquipment(player, Items.GHOSTSPEAK_AMULET_552)){
|
||||
npcl(FacialExpression.HALF_GUILTY, "OooOOOOOOoooOoOOoOOOo")
|
||||
setQuest(15)
|
||||
return false
|
||||
}
|
||||
|
||||
when(questStage){
|
||||
10, 15 -> sendDialogue("A shifting apparition appears in front of you.").also { stage = 1000 }
|
||||
20 -> npcl(FacialExpression.HALF_GUILTY, "Oh, hello there, do you still think I'm dead? It's hard to see how I could be dead when I'm still in the world. I can see everything quite clearly. And nothing of what you say reflects the truth.")
|
||||
25 -> npcl(FacialExpression.HALF_GUILTY, "Oh, hello... Sorry, you've caught me at a bad time, it's just that I've had a sign you see and I need to find my journal.").also { stage = 7 }
|
||||
30 -> npcl(FacialExpression.HALF_GUILTY, "Thanks for the journal, I've been reading it. It looks like I came to a violent and bitter end but that's not really important. I just have to figure out what I am going to do now?").also { stage = 14 }
|
||||
35 -> npcl(FacialExpression.NEUTRAL, "Hello there, have you been blessed yet?").also { stage = 60 }
|
||||
45 -> {
|
||||
if(ContentAPI.inInventory(player, Items.MORT_MYRE_FUNGUS_2970)){
|
||||
npcl(FacialExpression.NEUTRAL, "Did you manage to get something from nature?").also { stage = 80 }
|
||||
} else {
|
||||
playerl(
|
||||
FacialExpression.NEUTRAL,
|
||||
"Hello, I've been blessed but I don't know what to do now."
|
||||
).also { stage = 70 }
|
||||
}
|
||||
}
|
||||
50 -> npcl(FacialExpression.NEUTRAL, " Hello again! I don't suppose you've found out what the other components of the Nature spell are have you?").also { stage = 90 }
|
||||
else -> npcl(FacialExpression.NEUTRAL, ".......").also { stage = END_DIALOGUE }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
when(stage){
|
||||
0 -> if(ContentAPI.inInventory(player, Items.MIRROR_2966)){
|
||||
sendDialogue("You use the mirror on the spirit","of the dead Filliman Tarlock.").also { stage++ }
|
||||
} else {
|
||||
playerl(FacialExpression.NEUTRAL, "Yes, I do think you're dead and I'll prove it somehow.").also { stage = 1002 }
|
||||
}
|
||||
|
||||
1 -> playerl(FacialExpression.NEUTRAL, "Here take a look at this, perhaps you can see that you're utterly transparent now!").also { stage++ }
|
||||
2 -> sendDialogue("The spirit of Filliman reaches forwards and takes the mirror.").also { stage++ }
|
||||
3 -> npcl(FacialExpression.HALF_GUILTY, "Well, that is the most peculiar thing I've ever experienced. Strange how well it reflects the stagnant swamp behind me, but there is nothing of my own visage apparent.").also { stage++ }
|
||||
4 -> playerl(FacialExpression.NEUTRAL, "That's because you're dead! Dead as a door nail... Deader in fact... You bear a remarkable resemblance to wormbait! Err... No offence...").also { stage++ }
|
||||
5 -> npcl(FacialExpression.HALF_GUILTY, "I think you might be right my friend, though I still feel very much alive. It is strange how I still come to be here and yet I've not turned into a Ghast.").also { stage++ }
|
||||
6 -> npcl(FacialExpression.HALF_GUILTY, " It must be a sign... Yes a sign... I must try to find out what it means. Now, where did I put my journal?").also { stage++ }
|
||||
7 -> if(!ContentAPI.inInventory(player, Items.JOURNAL_2967)){
|
||||
playerl(FacialExpression.NEUTRAL, "Where did you put it?").also { stage++; setQuest(25) }
|
||||
} else sendDialogue("You give the journal to Filliman Tarlock").also { ContentAPI.removeItem(player, Items.JOURNAL_2967, Container.INVENTORY); stage = 10; setQuest(30) }
|
||||
|
||||
//no journal
|
||||
8 -> npcl(FacialExpression.HALF_GUILTY, "Well, if I knew that, I wouldn't still be looking for it. However, I do remember something about a knot? Perhaps I was meant to tie a knot or something?").also { stage = END_DIALOGUE }
|
||||
|
||||
//has journal
|
||||
10 -> playerl(FacialExpression.NEUTRAL, "Here, I found this, maybe you can use it?").also { stage++ }
|
||||
11 -> npcl(FacialExpression.FRIENDLY, "My journal! That should help to collect my thoughts.").also { stage++ }
|
||||
12 -> sendDialogue("~ The spirit starts leafing through the journal. ~", "~ He seems quite distant as he regards the pages. ~", "~ After some time the druid faces you again. ~").also {stage++}
|
||||
13 -> npcl(FacialExpression.HALF_GUILTY, "It's all coming back to me now. It looks like I came to a violent and bitter end but that's not important now. I just have to figure out what I am going to do now?").also { stage++ }
|
||||
14 -> options("Being dead, what options do you think you have?", "So, what's your plan?", "Well, good luck with that.", "How can I help?", "Ok thanks.").also { stage++ }
|
||||
15 -> when(buttonId){
|
||||
1 -> playerl(FacialExpression.NEUTRAL, "Being dead, what options do you think you have? I'm not trying to be rude or anything, but it's not like you have many options is it? I mean, it's either up or down for you isn't it?").also { stage = 20 }
|
||||
2 -> playerl(FacialExpression.NEUTRAL, "So, what's your plan?").also { stage = 30 }
|
||||
3 -> playerl(FacialExpression.NEUTRAL, "Well, good luck with that.").also { stage = 40 }
|
||||
4 -> playerl(FacialExpression.NEUTRAL, "How can I help?").also { stage = 50 }
|
||||
5 -> playerl(FacialExpression.NEUTRAL, "Ok thanks.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
//Being dead, what options
|
||||
20 -> npcl(FacialExpression.HALF_GUILTY, "Hmm, well you're a poetic one aren't you. Your material world logic stands you in good stead... If you're standing in the material world...").also { stage = 14 }
|
||||
|
||||
//what's your plan?
|
||||
30 -> npcl(FacialExpression.HALF_GUILTY, "In my former incarnation I was Filliman Tarlock, a great druid of some power. I spent many years in this place, which was once a forest and I would wish to protect it as a nature spirit.").also { stage = 14 }
|
||||
|
||||
//good luck with that
|
||||
40 -> npcl(FacialExpression.HALF_GUILTY, "Won't you help me to become a nature spirit? I could really use your help!").also { stage = 14 }
|
||||
|
||||
//How can I help?
|
||||
50 -> npcl(FacialExpression.HALF_GUILTY, "Will you help me to become a nature spirit? The directions for becoming one are a bit vague, I need three things but I know how to get one of them. Perhaps you can help collect the rest?").also { stage++ }
|
||||
51 -> playerl(FacialExpression.NEUTRAL, "I might be interested, what's involved?").also { stage++ }
|
||||
52 -> npcl(FacialExpression.HALF_GUILTY, "Well, the book says, that I need, and I quote:- 'Something with faith', 'something from nature' and the 'spirit-to-become' freely given'. Hmm, I know how to get something from nature.").also { stage++ }
|
||||
53 -> playerl(FacialExpression.NEUTRAL, "Well, that does seem a bit vague.").also { stage++ }
|
||||
54 -> npcl(FacialExpression.HALF_GUILTY, "Hmm, it does and I could understand if you didn't want to help. However, if you could perhaps at least get the item from nature, that would be a start. Perhaps we can figure out the rest as we go along.").also { stage++ }
|
||||
55 -> sendDialogue(*DialUtils.splitLines("The druid produces a small sheet of papyrus with some writing on it.")).also { ContentAPI.addItemOrDrop(player, Items.DRUIDIC_SPELL_2968); setQuest(35); stage++ }
|
||||
56 -> npcl(FacialExpression.NEUTRAL, "This spell needs to be cast in the swamp after you have been blessed. I'm afraid you'll need to go to the temple to the North and ask a member of the clergy to bless you.").also { stage++ }
|
||||
57 -> playerl(FacialExpression.NEUTRAL, "Blessed, what does that do?").also { stage++ }
|
||||
58 -> npcl(FacialExpression.NEUTRAL, "It is required if you're to cast this druid spell. Once you've cast the spell, you should find something from nature. Bring it back to me and then we'll try to figure out the other things we need.").also { stage = END_DIALOGUE }
|
||||
|
||||
//have you been blessed yet
|
||||
60 -> playerl(FacialExpression.NEUTRAL, "No, not yet.").also { stage++ }
|
||||
61 -> npcl(FacialExpression.NEUTRAL, "Well, hurry up!").also { stage++ }
|
||||
62 -> if(ContentAPI.inInventory(player, Items.DRUIDIC_SPELL_2968) || ContentAPI.inBank(player, Items.DRUIDIC_SPELL_2968)) end()
|
||||
else playerl(FacialExpression.NEUTRAL, "Could I have another bloom scroll please?").also { stage++ }
|
||||
63 -> npcl(FacialExpression.NEUTRAL, "Sure, but please look after this one.").also { stage++ }
|
||||
64 -> sendDialogue("The spirit of Filliman Tarlock gives you another bloom spell.").also { ContentAPI.addItemOrDrop(player, Items.DRUIDIC_SPELL_2968); stage = END_DIALOGUE }
|
||||
|
||||
//I've been blessed
|
||||
70 -> npcl(FacialExpression.NEUTRAL, "Well, you need to bring 'something from nature', 'something with faith' and 'something of the spirit-to- become freely given.'").also { stage++ }
|
||||
71 -> playerl(FacialExpression.NEUTRAL, "Yeah, but what does that mean?").also { stage++ }
|
||||
72 -> npcl(FacialExpression.NEUTRAL, "Hmm, it is a conundrum, however, if you use that spell I gave you, you should be able to get from nature. Once you have that, we may be puzzle the rest out.").also { stage++ }
|
||||
73 -> if(!ContentAPI.inInventory(player, Items.DRUIDIC_SPELL_2968) && !ContentAPI.inBank(player, Items.DRUIDIC_SPELL_2968)){
|
||||
playerl(FacialExpression.NEUTRAL, "Could I have another bloom scroll please?").also { stage++ }
|
||||
} else end()
|
||||
74 -> npcl(FacialExpression.NEUTRAL, "Sure, but please look after this one.").also { stage++ }
|
||||
75 -> sendDialogue("The spirit of Filliman Tarlock gives you","another bloom spell.").also { ContentAPI.addItem(player, Items.DRUIDIC_SPELL_2968); stage = END_DIALOGUE }
|
||||
|
||||
//has fungus
|
||||
80 -> sendDialogue("You show the fungus to Filliman.").also { stage++ }
|
||||
81 -> playerl(FacialExpression.NEUTRAL, "Yes, I have a fungus here that I picked.").also { stage++ }
|
||||
82 -> npcl(FacialExpression.NEUTRAL, "Wonderful, the mushroom represents 'something from nature'. Now we need to work out what the other components of the spell are!").also { stage = 90; setQuest(50) }
|
||||
|
||||
//pre-spell options
|
||||
90 -> options("What are the things that are needed?", "What should I do when I have those things?", "I think I've solved the puzzle!", "Could I have another bloom scroll please?", "Ok, thanks.").also { stage++ }
|
||||
91 -> when(buttonId){
|
||||
1 -> playerl(FacialExpression.NEUTRAL, "What are the things that are needed?").also { stage = 100 }
|
||||
2 -> playerl(FacialExpression.NEUTRAL, "What should I do when I have those things?").also { stage = 110 }
|
||||
3 -> playerl(FacialExpression.FRIENDLY, "I think I've solved the puzzle!").also { stage = 120 }
|
||||
4 -> playerl(FacialExpression.FRIENDLY, "Can I have another bloom scroll please?").also { stage = 130 }
|
||||
5 -> playerl(FacialExpression.NEUTRAL, "Ok, thanks.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
//What things are needed?
|
||||
100 -> npcl(FacialExpression.NEUTRAL, "The three things are: 'Something with faith', 'something from nature' and 'something of the spirit-to-become freely given'.").also { stage++ }
|
||||
101 -> playerl(FacialExpression.FRIENDLY, " Ok, and 'something from nature' is the mushroom from the bloom spell you gave me?").also { stage++ }
|
||||
102 -> npcl(FacialExpression.FRIENDLY, "Yes, that's correct, that seems right to me. The other things we need are 'something with faith' and 'something of the spirit-to-become freely given.").also { stage++ }
|
||||
103 -> playerl(FacialExpression.NEUTRAL, "Do you have any ideas what those things are?").also { stage++ }
|
||||
104 -> npcl(FacialExpression.HALF_GUILTY, "I'm sorry my friend, but I do not.").also { stage = 90 }
|
||||
|
||||
//What should I do when I have them?
|
||||
110 -> npcl(FacialExpression.NEUTRAL, "It says,.. 'to arrange upon three rocks around the spirit-to-become...'. Then I must cast a spell. As you can see, I've already placed the rocks.").also { stage++ }
|
||||
111 -> playerl(FacialExpression.NEUTRAL, "Can we just place the components on any rock?").also { stage++ }
|
||||
112 -> npcl(FacialExpression.NEUTRAL, "Well, the only thing the journal says is that 'something with faith stands south of the spirit-to-become', but I'm so confused now I don't really know what that means.").also { stage = 90 }
|
||||
|
||||
//I think I've solved the puzzle!
|
||||
120 -> npcl(FacialExpression.NEUTRAL, "Oh really.. Have you placed all the items on the stones? Ok, well, let's try!").also { stage++ }
|
||||
121 -> sendDialogue("~ The druid attempts to cast a spell. ~").also { stage++ }
|
||||
122 -> {
|
||||
ContentAPI.animate(npc, 812)
|
||||
if(NSUtils.hasPlacedCard(player) && NSUtils.hasPlacedFungus(player) && NSUtils.onStone(player)){
|
||||
end()
|
||||
player.lock()
|
||||
val locations = arrayOf(Location.create(3439, 3336, 0), Location.create(3441, 3336, 0), Location.create(3440, 3335, 0))
|
||||
repeat(3) {i -> ContentAPI.spawnProjectile(locations[i], Location.create(3440, 3336, 0), 268, 0, 35, 0, 100, 20) }
|
||||
ContentAPI.submitIndividualPulse(player, object : Pulse(4){
|
||||
override fun pulse(): Boolean {
|
||||
ContentAPI.sendNPCDialogue(player, npc.originalId, "Aha, everything seems to be in place! You can come through now into the grotto for the final section of my transformation.")
|
||||
setQuest(55)
|
||||
ContentAPI.unlock(player)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
ContentAPI.visualize(npc, -1, Graphics(266, 80))
|
||||
super.stop()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
npcl(FacialExpression.NEUTRAL, "Hmm, something still doesn't seem right. I think we need something more before we can continue.")
|
||||
}
|
||||
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
|
||||
130 -> if(ContentAPI.inInventory(player, Items.DRUIDIC_SPELL_2968) || ContentAPI.inBank(player, Items.DRUIDIC_SPELL_2968)){
|
||||
npcl(FacialExpression.NEUTRAL, "No, you've already got one!").also { stage = END_DIALOGUE }
|
||||
} else {
|
||||
npcl(FacialExpression.NEUTRAL, "Sure, but look after this one.")
|
||||
ContentAPI.addItem(player, Items.DRUIDIC_SPELL_2968)
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
|
||||
//Initial dialogue
|
||||
1000 -> playerl(FacialExpression.HALF_ASKING, "Hello?").also { stage++ }
|
||||
1001 -> if(ContentAPI.inEquipment(player, Items.GHOSTSPEAK_AMULET_552)){
|
||||
npcl(FacialExpression.EXTREMELY_SHOCKED, "Oh, I understand you! At last, someone who doesn't just mumble. I understand what you're saying!").also { stage++ }
|
||||
} else npcl(FacialExpression.HALF_GUILTY, "OooOOoOOoOOOOo.")
|
||||
|
||||
1002 -> options("I'm wearing an amulet of ghost speak!","How long have you been a ghost?", "What's it like being a ghost?", "Ok, thanks.").also { stage++ }
|
||||
1003 -> when(buttonId){
|
||||
1 -> playerl(FacialExpression.NEUTRAL, "I'm wearing an amulet of ghost speak!").also { stage = 1010; setQuest(20) }
|
||||
2 -> playerl(FacialExpression.NEUTRAL, "How long have you been a ghost?").also { stage = 1020; setQuest(20) }
|
||||
3 -> playerl(FacialExpression.NEUTRAL, "What's it like being a ghost?").also { stage = 1030; setQuest(20) }
|
||||
4 -> playerl(FacialExpression.NEUTRAL, "Ok, thanks.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
1010 -> npcl(FacialExpression.HALF_GUILTY, "Why you poor fellow, have you passed away and you want to send a message back to a loved one?").also { stage++ }
|
||||
1011 -> playerl(FacialExpression.HALF_THINKING, "Err.. Not exactly...").also { stage++ }
|
||||
1012 -> npcl(FacialExpression.HALF_GUILTY, "You have come to haunt my dreams until I pass on your message to a dearly loved one. I understand. Pray, tell me who would you like me to pass a message on to?").also { stage++ }
|
||||
1013 -> playerl(FacialExpression.NEUTRAL, "Ermm, you don't understand... It's just that...").also { stage++ }
|
||||
1014 -> npcl(FacialExpression.HALF_GUILTY, "Yes!").also { stage++ }
|
||||
1015 -> playerl(FacialExpression.NEUTRAL, "Well please don't be upset or anything... But you're the ghost!").also { stage++ }
|
||||
1016 -> npcl(FacialExpression.HALF_GUILTY, "Don't be silly now! That in no way reflects the truth!").also { stage = 1002 }
|
||||
|
||||
1020 -> npcl(FacialExpression.HALF_GUILTY, "What?! Don't be preposterous! I'm not a ghost! How could you say something like that?").also { stage++ }
|
||||
1021 -> playerl(FacialExpression.NEUTRAL, "But it's true, you're a ghost... well, at least that is to say, you're sort of not alive anymore.").also { stage++ }
|
||||
1022 -> npcl(FacialExpression.HALF_GUILTY, "Don't be silly, I can see you. I can see that tree. If I were dead, I wouldn't be able to see anything. What you say just doesn't reflect the truth. You'll have to try harder to put one over on me!").also { stage = 1002 }
|
||||
|
||||
1030 -> npcl(FacialExpression.HALF_GUILTY, "Oh, it's quite.... Oh... Trying to catch me out were you! Anyone can clearly see that I am not a ghost!").also { stage++ }
|
||||
1031 -> playerl(FacialExpression.NEUTRAL, "But you are a ghost, look at yourself! I can see straight through you! You're as dead as this swamp! Err... No offence or anything...").also { stage++ }
|
||||
1032 -> npcl(FacialExpression.HALF_GUILTY, "No I won't take offence because I'm not dead and I'm afraid you'll have to come up with some pretty conclusive proof before I believe it. What a strange dream this is.").also { stage = 1002 }
|
||||
|
||||
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.FILLIMAN_TARLOCK_1050)
|
||||
}
|
||||
|
||||
fun setQuest(stage: Int){
|
||||
player.questRepository.getQuest("Nature Spirit").setStage(player, stage)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
package rs09.game.content.quest.members.naturespirit
|
||||
|
||||
import api.Container
|
||||
import api.ContentAPI
|
||||
import core.game.node.Node
|
||||
import core.game.node.`object`.Scenery
|
||||
import core.game.node.`object`.SceneryBuilder
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.RegionManager.forId
|
||||
import core.game.world.map.RegionManager.lock
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import rs09.game.node.entity.npc.other.MortMyreGhastNPC
|
||||
|
||||
object NSUtils {
|
||||
fun flagFungusPlaced(player: Player) {
|
||||
ContentAPI.setAttribute(player, "/save:ns:fungus_placed", true)
|
||||
}
|
||||
|
||||
fun flagCardPlaced(player: Player){
|
||||
ContentAPI.setAttribute(player, "/save:ns:card_placed", true)
|
||||
}
|
||||
|
||||
fun hasPlacedFungus(player: Player): Boolean {
|
||||
return ContentAPI.getAttribute(player, "ns:fungus_placed", false)
|
||||
}
|
||||
|
||||
fun hasPlacedCard(player: Player): Boolean {
|
||||
return ContentAPI.getAttribute(player, "ns:card_placed", false)
|
||||
}
|
||||
|
||||
fun onStone(player: Player): Boolean {
|
||||
return player.location.equals(3440, 3335, 0)
|
||||
}
|
||||
|
||||
fun getGhastKC(player: Player): Int {
|
||||
return ContentAPI.getAttribute(player,"ns:ghasts_killed", 0) as Int
|
||||
}
|
||||
|
||||
fun incrementGhastKC(player: Player){
|
||||
ContentAPI.setAttribute(player, "/save:ns:ghasts_killed", getGhastKC(player) + 1)
|
||||
val msg = when(getGhastKC(player)) {
|
||||
1 -> "That's one down, two more to go."
|
||||
2 -> "Two down, only one more to go."
|
||||
3 -> "That's it! I've killed all 3 Ghasts!"
|
||||
else -> ""
|
||||
}
|
||||
|
||||
if(!msg.isEmpty()){
|
||||
ContentAPI.sendMessage(player, msg)
|
||||
}
|
||||
}
|
||||
|
||||
fun activatePouch(player: Player, attacker: MortMyreGhastNPC): Boolean {
|
||||
var shouldAddEmptyPouch = false
|
||||
val pouchAmt = ContentAPI.amountInInventory(player, Items.DRUID_POUCH_2958)
|
||||
if(pouchAmt == 1) shouldAddEmptyPouch = true
|
||||
if(pouchAmt > 0 && ContentAPI.removeItem(player, Items.DRUID_POUCH_2958, Container.INVENTORY)){
|
||||
if(shouldAddEmptyPouch){
|
||||
ContentAPI.addItem(player, Items.DRUID_POUCH_2957)
|
||||
}
|
||||
ContentAPI.spawnProjectile(player, attacker, 268)
|
||||
ContentAPI.submitWorldPulse(object : Pulse(){
|
||||
var ticks = 0
|
||||
override fun pulse(): Boolean {
|
||||
when(ticks++){
|
||||
2 -> ContentAPI.visualize(attacker, -1, Graphics(269, 125))
|
||||
3 -> attacker.transform(attacker.id + 1).also { attacker.attack(player); attacker.setAttribute("woke", ContentAPI.getWorldTicks()); return true }
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun cleanupAttributes(player: Player){
|
||||
player.removeAttribute("ns:fungus_placed")
|
||||
player.removeAttribute("ns:card_placed")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun castBloom(player: Player): Boolean{
|
||||
var success = false
|
||||
val region = forId(player.location.regionId)
|
||||
if (player.skills.prayerPoints < 1) {
|
||||
player.packetDispatch.sendMessage("You don't have enough prayer points to do this.")
|
||||
return false
|
||||
}
|
||||
handleVisuals(player)
|
||||
val locs = player.location.surroundingTiles
|
||||
for (o in locs) {
|
||||
val obj = RegionManager.getObject(o)
|
||||
if (obj != null) {
|
||||
if (obj.name.equals("Rotting log", ignoreCase = true) && player.skills.prayerPoints >= 1) {
|
||||
if (player.location.withinDistance(obj.location, 2)) {
|
||||
SceneryBuilder.replace(obj, obj.transform(3509))
|
||||
success = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return success
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the draining of prayer points and physical graphics and
|
||||
* animation.
|
||||
*/
|
||||
private fun handleVisuals(player: Player) {
|
||||
player.skills.decrementPrayerPoints(RandomFunction.random(1, 3).toDouble())
|
||||
val AROUND_YOU = player.location.surroundingTiles
|
||||
for (location in AROUND_YOU) {
|
||||
// The graphic is meant to play on a 3x3 radius around you, but not
|
||||
// including the tile you are on.
|
||||
player.packetDispatch.sendGlobalPositionGraphic(263, location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
package rs09.game.content.quest.members.naturespirit
|
||||
|
||||
import api.Container
|
||||
import api.ContentAPI
|
||||
import core.game.content.dialogue.DialoguePlugin
|
||||
import core.game.content.dialogue.FacialExpression
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import rs09.game.content.dialogue.DialogueFile
|
||||
import rs09.tools.END_DIALOGUE
|
||||
|
||||
@Initializable
|
||||
class NatureSpiritDialogue(player: Player? = null) : DialoguePlugin(player){
|
||||
|
||||
val questStage = player?.questRepository?.getStage("Nature Spirit") ?: 0
|
||||
override fun newInstance(player: Player?): DialoguePlugin {
|
||||
return NatureSpiritDialogue(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any?): Boolean {
|
||||
npc = args[0] as NPC
|
||||
|
||||
when(questStage){
|
||||
60 -> npcl(FacialExpression.NEUTRAL, "Hmm, good, the transformation is complete. Now, my friend, in return for your assistance, I will help you to kill the Ghasts. First bring to me a silver sickle so that I can bless it for you.").also { return true }
|
||||
65 -> npcl(FacialExpression.NEUTRAL, "Have you brought me a silver sickle?").also { stage = 100; return true }
|
||||
70 -> npcl(FacialExpression.NEUTRAL, "Now you can go forth and make the swamp bloom. Collect nature's bounty to fill a druids pouch. So armed will the Ghasts be bound to you until, you flee or they are defeated.").also { stage = 200 }
|
||||
75 -> npcl(FacialExpression.NEUTRAL, "Hello again, my friend. Have you defeated three ghasts as I asked you?").also { stage = 300 }
|
||||
else -> npcl(FacialExpression.FRIENDLY, "Welcome to my grotto, friend. Enjoy your visit.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(componentID: Int, buttonID: Int): Boolean {
|
||||
when(stage){
|
||||
0 -> playerl(FacialExpression.NEUTRAL,"A silver sickle? What's that?").also { stage++ }
|
||||
1 -> npcl(FacialExpression.NEUTRAL, "The sickle is the symbol and weapon of the Druid, you need to construct one of silver so that I can bless it, with its powers you will be able to defeat the Ghasts of Mort Myre.").also { stage++; setQuest(65) }
|
||||
2 -> options("Where would I get a silver sickle?", "What will you do to the silver sickle?", "How can a blessed sickle help me to defeat the Ghasts?", "Ok, thanks.").also { stage++ }
|
||||
3 -> when(buttonID){
|
||||
1 -> playerl(FacialExpression.NEUTRAL, "Where would I get a silver sickle?").also { stage = 10 }
|
||||
2 -> playerl(FacialExpression.NEUTRAL, "What will you do to the silver sickle?").also { stage = 20 }
|
||||
3 -> playerl(FacialExpression.NEUTRAL, "How can a blessed sickle help me to defeat the Ghasts?").also { stage = 30 }
|
||||
4 -> playerl(FacialExpression.NEUTRAL, "Ok, thanks.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
//where sickle
|
||||
10 -> npcl(FacialExpression.NEUTRAL, "You could make one yourself if you're artisan enough. I've heard of a distant sandy place where you can buy the mould that you require, it's similar in many respects to the creating of a holy symbol.").also { stage = 2 }
|
||||
|
||||
//What you gonna do to my sickle bro
|
||||
20 -> npcl(FacialExpression.NEUTRAL, "Why, I will give it my blessings so that the very swamp in which you stand will blossom and bloom!").also { stage = 2 } //pompous git
|
||||
|
||||
//bruh how does a silver sickle help me tho
|
||||
30 -> npcl(FacialExpression.NEUTRAL, "My blessings will entice nature to bloom in Mort Myre! And then with nature's harvest you can fill a druids pouch and release the Ghasts from their torment.").also { stage = 2 } //this dude kinda weird
|
||||
|
||||
//have you brought me a sickle yet bro
|
||||
100 -> if(ContentAPI.inInventory(player, Items.SILVER_SICKLE_2961)){
|
||||
playerl(FacialExpression.FRIENDLY, "Yes, here it is. What are you going to do with it?").also { stage = 110 }
|
||||
} else {
|
||||
playerl(FacialExpression.NEUTRAL, "No sorry, not yet!").also { stage++ }
|
||||
}
|
||||
101 -> npcl(FacialExpression.NEUTRAL, "Well, come to me when you have it.").also { stage = 2 }
|
||||
|
||||
/**
|
||||
* This dialogue drags on so much man this quest has been like 95% dialogue.
|
||||
* Nature Spirit dude also talks like an uppity self-righteous deity looking dude
|
||||
*/
|
||||
|
||||
//yeah bro I got it
|
||||
110 -> npcl(FacialExpression.NEUTRAL, "My friend, I will bless it for you and you will then be able to accomplish great things. Now then, I must cast the enchantment. You can bless a new sickle by dipping it in the holy water of the grotto.").also { stage++ }
|
||||
111 -> sendDialogue("- The Nature Spirit casts a spell on the player. -").also { stage++ }
|
||||
|
||||
/**
|
||||
* Here we go uoooh
|
||||
*/
|
||||
112 -> end().also { ContentAPI.lock(player, 10); ContentAPI.submitWorldPulse(SickleBlessPulse(player, npc)) }
|
||||
|
||||
//go kill some ghasts bro
|
||||
200 -> npcl(FacialExpression.NEUTRAL, "Go forth into Mort Myre and slay three Ghasts. You'll be releasing their souls from Mort Myre.").also { stage++ }
|
||||
201 -> ContentAPI.sendItemDialogue(player, Items.DRUID_POUCH_2957, "The nature spirit gives you an empty pouch.").also { stage++; setQuest(75) }
|
||||
202 -> npcl(FacialExpression.NEUTRAL, "You'll need this in order to collect together nature's bounty. It will bind the Ghast to you until you flee or it is defeated.").also { stage = END_DIALOGUE }
|
||||
|
||||
//Have you killed the ghasts yet bro
|
||||
300 -> if(NSUtils.getGhastKC(player) >= 3){
|
||||
playerl(FacialExpression.NEUTRAL, "Yes, I've killed all three and their spirits have been released!").also { stage = 350 }
|
||||
} else {
|
||||
playerl(FacialExpression.NEUTRAL, "Not yet.").also { stage++ }
|
||||
}
|
||||
|
||||
//nah bro
|
||||
301 -> npcl(FacialExpression.NEUTRAL, "Well, when you do, please come to me and I'll reward you!").also { stage++ }
|
||||
302 -> options("How do I get to attack the Ghasts?", "What's this pouch for?", "What can I do with this sickle?", "I've lost my sickle.", "Ok, thanks.").also { stage++ }
|
||||
303 -> when(buttonID){
|
||||
1 -> playerl(FacialExpression.NEUTRAL, "How do I get to attack the Ghasts?").also { stage = 310 }
|
||||
2 -> playerl(FacialExpression.NEUTRAL, "What's this pouch for?").also { stage = 320 }
|
||||
3 -> playerl(FacialExpression.NEUTRAL, "What can I do with this sickle?").also { stage = 330 }
|
||||
4 -> playerl(FacialExpression.NEUTRAL, "I've lost my sickle.").also { stage = 340 }
|
||||
5 -> playerl(FacialExpression.NEUTRAL, "Ok, thanks.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
//How do I attack duh ghosty bois
|
||||
310 -> npcl(FacialExpression.NEUTRAL, "Go forth and with the sickle make the swamp bloom. Collect natures bounty to fill a druids pouch. So armed will the Ghasts be bound to you until, you flee or they are defeated.").also { stage = 302 }
|
||||
|
||||
//What's dis funny pouch for?
|
||||
320 -> npcl(FacialExpression.NEUTRAL, "It is for collecting natures bounty, once it contains the blossomed items of the swamp, it will make the Ghasts appear and you can then attack them.").also { stage = 302 }
|
||||
|
||||
//What can I do wif da sickle m8
|
||||
330 -> npcl(FacialExpression.NEUTRAL, "You may use it wisely within the area of Mort Myre to affect natures balance and bring forth a bounty of natures harvest. Once collected into the druid pouch will the Ghast be apparent.").also { stage = 302 }
|
||||
|
||||
//oi I lost it bruv
|
||||
340 -> npcl(FacialExpression.NEUTRAL, "If you should lose the blessed sickle, simply bring another to my altar of nature and refresh it in the grotto waters.").also { stage = 302 }
|
||||
|
||||
//killed all dem buggers bruv
|
||||
350 -> npcl(FacialExpression.NEUTRAL, "Many thanks my friend, you have completed your quest!").also { stage++ }
|
||||
351 -> end().also { player.questRepository.getQuest("Nature Spirit").finish(player) }
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.NATURE_SPIRIT_1051)
|
||||
}
|
||||
|
||||
/**
|
||||
* Needs to spawn 4ish of those green projectiles and the player needs to lift up the sickle
|
||||
* then needs to open the dialogue back up with the quest stage at 70
|
||||
*/
|
||||
internal class SickleBlessPulse(val player: Player, val spirit: NPC) : Pulse() {
|
||||
var ticks = 0
|
||||
val locs: MutableList<Location> = player.location.surroundingTiles
|
||||
|
||||
override fun pulse(): Boolean {
|
||||
when(ticks++){
|
||||
0 -> ContentAPI.animate(spirit, 812)
|
||||
1 -> repeat(4) {
|
||||
val loc = locs.random()
|
||||
locs.remove(loc)
|
||||
|
||||
ContentAPI.spawnProjectile(loc, player.location, 268, 0, 400, 0, 125, 180)
|
||||
ContentAPI.animate(player, 9021)
|
||||
}
|
||||
4 -> {
|
||||
if(ContentAPI.removeItem(player, Items.SILVER_SICKLE_2961, Container.INVENTORY)){
|
||||
ContentAPI.addItem(player, Items.SILVER_SICKLEB_2963)
|
||||
ContentAPI.unlock(player)
|
||||
player.questRepository.getQuest("Nature Spirit").setStage(player, 70)
|
||||
ContentAPI.openDialogue(player, NPCs.NATURE_SPIRIT_1051, ContentAPI.findLocalNPC(player, NPCs.NATURE_SPIRIT_1051) as NPC)
|
||||
ContentAPI.sendMessage(player, "Your sickle has been blessed! You can bless a new sickle by dipping it into the grotto waters.")
|
||||
}
|
||||
}
|
||||
6 -> return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun setQuest(stage: Int){
|
||||
player!!.questRepository.getQuest("Nature Spirit").setStage(player!!, stage)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package rs09.game.content.quest.members.naturespirit
|
||||
|
||||
import api.ContentAPI
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.quest.Quest
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Items
|
||||
|
||||
@Initializable
|
||||
class NatureSpiritQuest : Quest("Nature Spirit", 95, 94, 2, 307, 0, 1, 110 ) {
|
||||
override fun newInstance(`object`: Any?): Quest {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun drawJournal(player: Player?, stage: Int) {
|
||||
super.drawJournal(player, stage)
|
||||
player ?: return
|
||||
var line = 11
|
||||
if(stage == 0){
|
||||
line(player, "I can start this quest by speaking to !!Drezel?? in the !!temple of Saradomin??.", line++)
|
||||
} else {
|
||||
if(stage >= 10){
|
||||
line(player, "After talking to Drezel in the temple of Saradomin I've",line++, true)
|
||||
line(player,"agreed to look for a Druid called Filliman Tarlock.", line++, true)
|
||||
}
|
||||
|
||||
if(stage == 10){
|
||||
line(player, "I need to look for !!Filliman Tarlock?? in the !!Swamps?? of Mort",line++)
|
||||
line(player, "Myre. I should be wary of !!Ghasts??.", line++)
|
||||
}
|
||||
|
||||
if(stage == 15){
|
||||
line(player, "I located a !!spirit?? in the swamp. I believe he's", line++, false)
|
||||
line(player, "!!Filliman Tarlock?? but I can't understand him.",line++, false)
|
||||
}
|
||||
|
||||
if(stage == 20){
|
||||
line(player, "I located !!Filliman Tarlock?? in the swamp. I believe he's",line++)
|
||||
line(player, "dead but he doesn't believe me. I need to convince him.", line++)
|
||||
}
|
||||
|
||||
if(stage >= 25){
|
||||
line(player, "I located Filliman Tarlock in the swamp and managed to",line++,true)
|
||||
line(player, "convince him that he is in fact a ghost. ", line++, true)
|
||||
}
|
||||
|
||||
if(stage == 25){
|
||||
line(player, "Filliman needs his !!journal?? to figure out what to do",line++)
|
||||
line(player, "next. He mentioned something about a !!knot??.", line++)
|
||||
}
|
||||
|
||||
if(stage >= 30){
|
||||
line(player, "I recovered Filliman's journal for him.", line++, true)
|
||||
}
|
||||
|
||||
if(stage == 30) {
|
||||
line(player, "I should speak to !!Filliman Tarlock?? to see what I can",line++)
|
||||
line(player, "do to help.", line++)
|
||||
}
|
||||
|
||||
if(stage >= 40){
|
||||
line(player, "I've gone and gotten blessed by Drezel.", line++, true)
|
||||
}
|
||||
|
||||
if(stage >= 35) {
|
||||
line(player, "I've agreed to help Filliman become a Nature Spirit.",line++, true)
|
||||
}
|
||||
|
||||
if(stage == 35){
|
||||
line(player, "The first thing Filliman needs me to do is go and get",line++)
|
||||
line(player, "blessed by !!Drezel?? in the temple of Saradomin.",line++)
|
||||
}
|
||||
|
||||
if (stage == 40){
|
||||
line(player, "I should return to !!Filliman?? to see what I need to do.", line++, false)
|
||||
}
|
||||
|
||||
if(stage in 45 until 55){
|
||||
line(player, "In order to help Filliman I need to find 3 things:", line++, false)
|
||||
line(player, "Something of !!Faith??.",line++, false)
|
||||
line(player, "Something of !!Nature??.", line++, stage >= 50)
|
||||
line(player, "Something of the !!spirit-to-be freely given??.", line++, false)
|
||||
}
|
||||
|
||||
if(stage == 50){
|
||||
line(player, "I know for a fact the fungus is !!something of Nature??.", line++, false)
|
||||
}
|
||||
|
||||
if(stage >= 55){
|
||||
line(player, "I've helped Filliman complete the spell.", line++, true)
|
||||
}
|
||||
|
||||
if(stage == 55){
|
||||
line(player, "Filliman has asked me to meet him back inside the !!grotto??.", line++, false)
|
||||
}
|
||||
|
||||
if(stage == 75){
|
||||
line(player, "I need to go and kill !!3 Ghasts?? for Filliman.", line++, false)
|
||||
}
|
||||
|
||||
if(stage >= 100){
|
||||
line(player,"!!QUEST COMPLETE!??",line++)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun finish(player: Player?) {
|
||||
super.finish(player)
|
||||
player ?: return
|
||||
var ln = 10
|
||||
player.packetDispatch.sendItemZoomOnInterface(Items.SILVER_SICKLEB_2963,230,277,5)
|
||||
drawReward(player, "2 Quest Points", ln++)
|
||||
drawReward(player, "3,000 Crafting XP",ln++)
|
||||
drawReward(player, "2,000 Hitpoints XP", ln++)
|
||||
drawReward(player, "2,000 Defence XP", ln++)
|
||||
ContentAPI.rewardXP(player, Skills.CRAFTING, 3000.0)
|
||||
ContentAPI.rewardXP(player, Skills.HITPOINTS, 2000.0)
|
||||
ContentAPI.rewardXP(player, Skills.DEFENCE, 2000.0)
|
||||
NSUtils.cleanupAttributes(player)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ abstract class InteractionListener : Listener{
|
|||
val ITEM = 0
|
||||
val SCENERY = 1
|
||||
val NPC = 2
|
||||
val GROUNDITEM = 3
|
||||
}
|
||||
fun on(id: Int, type: Int, vararg option: String,handler: (player: Player, node: Node) -> Boolean){
|
||||
InteractionListeners.add(id,type,option,handler)
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ object InteractionListeners {
|
|||
@JvmStatic
|
||||
fun run(id: Int, type: Int, option: String, player: Player, node: Node): Boolean{
|
||||
val flag = when(type){
|
||||
3 -> DestinationFlag.ITEM
|
||||
2 -> DestinationFlag.ENTITY
|
||||
1 -> DestinationFlag.OBJECT
|
||||
else -> DestinationFlag.OBJECT
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import rs09.game.interaction.InteractionListener
|
|||
class MorytaniaListeners : InteractionListener() {
|
||||
|
||||
val GROTTO_ENTRANCE = 3516
|
||||
val GROTTO_EXIT = 3526
|
||||
val GROTTO_EXIT = intArrayOf(3525, 3526)
|
||||
val GROTTO_BRIDGE = 3522
|
||||
val outside = Location.create(3439, 3337, 0)
|
||||
val inside = Location.create(3442, 9734, 1)
|
||||
|
|
@ -23,10 +23,10 @@ class MorytaniaListeners : InteractionListener() {
|
|||
private val JUMP_ANIM = Animation(1603)
|
||||
|
||||
override fun defineListeners() {
|
||||
on(GROTTO_ENTRANCE,SCENERY,"enter"){ player, node ->
|
||||
/* on(GROTTO_ENTRANCE,SCENERY,"enter"){ player, node ->
|
||||
player.teleport(inside)
|
||||
return@on true
|
||||
}
|
||||
}*/
|
||||
|
||||
on(GROTTO_EXIT,SCENERY,"exit"){ player, node ->
|
||||
player.teleport(outside)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,104 @@
|
|||
package rs09.game.node.entity.npc.other
|
||||
|
||||
import api.Container
|
||||
import api.ContentAPI
|
||||
import core.game.content.consumable.Consumables
|
||||
import core.game.content.consumable.Food
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.combat.ImpactHandler
|
||||
import core.game.node.entity.npc.AbstractNPC
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.plugin.Initializable
|
||||
import core.tools.RandomFunction
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import rs09.game.content.quest.members.naturespirit.NSUtils
|
||||
|
||||
@Initializable
|
||||
class MortMyreGhastNPC : AbstractNPC {
|
||||
//Constructor spaghetti because Arios I guess
|
||||
constructor() : super(NPCs.GHAST_1052, null, true) {}
|
||||
private constructor(id: Int, location: Location) : super(id, location) {}
|
||||
|
||||
override fun construct(id: Int, location: Location, vararg objects: Any?): AbstractNPC {
|
||||
isAggressive = id != ids[0]
|
||||
return MortMyreGhastNPC(id, location)
|
||||
}
|
||||
|
||||
override fun handleTickActions() {
|
||||
super.handleTickActions()
|
||||
if(id == ids[0] && RandomFunction.roll(35)){
|
||||
val players = RegionManager.getLocalPlayers(this, 5).filter { !it.inCombat() }
|
||||
if(players.isNotEmpty()){
|
||||
val player = players.random()
|
||||
ContentAPI.submitIndividualPulse(this, object : MovementPulse(this, player){
|
||||
override fun pulse(): Boolean {
|
||||
animate(Animation(1093))
|
||||
attemptLifeSiphon(player)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
val ticksTransformed = ContentAPI.getWorldTicks() - ContentAPI.getAttribute(this, "woke", 0)
|
||||
if(!inCombat() && ticksTransformed > 10){
|
||||
reTransform()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.GHAST_1052, NPCs.GHAST_1053)
|
||||
}
|
||||
|
||||
fun attemptLifeSiphon(player: Player){
|
||||
var hasFood = false
|
||||
|
||||
if(NSUtils.activatePouch(player, this)) return
|
||||
|
||||
GlobalScope.launch {
|
||||
for(i in player.inventory.toArray()){
|
||||
if(i == null) continue
|
||||
val consumable = Consumables.getConsumableById(i.id)
|
||||
if(consumable != null && consumable is Food) {
|
||||
hasFood = true
|
||||
ContentAPI.removeItem(player, i, Container.INVENTORY)
|
||||
ContentAPI.addItem(player, Items.ROTTEN_FOOD_2959)
|
||||
ContentAPI.sendMessage(player, "You feel something attacking your backpack, and smell a terrible stench.")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if(!hasFood && RandomFunction.roll(3)) {
|
||||
ContentAPI.sendMessage(player, "An attacking Ghast just misses you.")
|
||||
} else if(!hasFood){
|
||||
ContentAPI.impact(player, RandomFunction.random(3,6), ImpactHandler.HitsplatType.NORMAL)
|
||||
ContentAPI.sendMessage(player, "A supernatural force draws energy from you.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun commenceDeath(killer: Entity?) {
|
||||
super.commenceDeath(killer)
|
||||
}
|
||||
|
||||
override fun finalizeDeath(killer: Entity?) {
|
||||
super.finalizeDeath(killer)
|
||||
if(id == ids[1]) {
|
||||
reTransform()
|
||||
if(killer is Player){
|
||||
NSUtils.incrementGhastKC(killer)
|
||||
ContentAPI.rewardXP(killer, Skills.PRAYER, 30.0)
|
||||
removeAttribute("woke")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -170,6 +170,10 @@ class VisualCommand : CommandPlugin() {
|
|||
}
|
||||
return true
|
||||
}
|
||||
"teleallowed" -> {
|
||||
player!!.debug("Is tele allowed here? " + RegionManager.isTeleportPermitted(player!!.location))
|
||||
return true
|
||||
}
|
||||
"oib" -> player!!.interfaceManager.openInfoBars()
|
||||
"char" -> CharacterDesign.open(player)
|
||||
"savenpc" -> return true
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ NPCConfigParser {
|
|||
"prj_height",
|
||||
"end_height",
|
||||
"spell_id",
|
||||
"death_gfx",
|
||||
"magic_level" -> configs.put(it.key.toString(), if (it.value.toString().isEmpty()) Unit else it.value.toString().toInt())
|
||||
|
||||
//doubles
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue