Implemented Zogre Flesh Eaters quest

This commit is contained in:
Oven Bread
2025-02-16 07:09:36 +00:00
committed by Ryan
parent f1131b7d00
commit 9886049429
35 changed files with 2637 additions and 160 deletions
+4 -54
View File
@@ -3262,7 +3262,7 @@
}
],
"charm": [],
"ids": "73,74,75,419,420,421,422,423,424,1826,2714,2863,2866,2869,2878,3622,4392,4393,4394,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5375,5376,5377,5378,5379,5380,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,6099,6100,6131",
"ids": "73,74,75,419,420,421,422,423,424,2714,2863,2866,2869,2878,3622,4392,4393,4394,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5375,5376,5377,5378,5379,5380,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,6099,6100,6131",
"description": "",
"main": [
{
@@ -28545,60 +28545,10 @@
"maxAmount": "1"
}
],
"charm": [
{
"minAmount": "1",
"weight": "85.8093",
"id": "0",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "10.9113",
"id": "12158",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.6775",
"id": "12159",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.6019",
"id": "12160",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "0.0",
"id": "12163",
"maxAmount": "1"
}
],
"ids": "2044,2045,2046,2047,2048,2049,2051,2052,2053,2054,2055",
"charm": [],
"ids": "2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057",
"description": "",
"main": [
{
"minAmount": "1",
"weight": "1.0",
"id": "1",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "124.0",
"id": "0",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "3.0",
"id": "7848",
"maxAmount": "1"
}
]
"main": []
},
{
"default": [
+4
View File
@@ -627,6 +627,10 @@
"item_id": "4707",
"loc_data": "{1,3571,3312,0,40}-"
},
{
"item_id": "4838",
"loc_data": "{1,2593,3103,1,40}-"
},
{
"item_id": "5008",
"loc_data": "{1,3230,9609,0,44}-"
+33 -6
View File
@@ -19219,6 +19219,21 @@
"range_level": "1",
"attack_level": "1"
},
{
"examine": "A human zombie.",
"melee_animation": "5568",
"combat_audio": "931,923,922",
"defence_animation": "5567",
"death_animation": "5569",
"name": "Zombie",
"defence_level": "30",
"safespot": null,
"lifepoints": "50",
"strength_level": "30",
"id": "1826",
"range_level": "1",
"attack_level": "30"
},
{
"examine": "Flies like a rock.",
"melee_animation": "9454",
@@ -21498,16 +21513,28 @@
"attack_level": "1"
},
{
"examine": "A partially decomposing zombie ogre.",
"slayer_task": "64",
"combat_audio": "",
"melee_animation": "359",
"range_animation": "359",
"attack_speed": "6",
"magic_level": "1",
"respawn_delay": "60",
"defence_animation": "360",
"slayer_exp": "",
"weakness": "7",
"magic_animation": "359",
"death_animation": "361",
"name": "Slash Bash",
"defence_level": "1",
"defence_level": "60",
"safespot": null,
"lifepoints": "103",
"strength_level": "1",
"lifepoints": "100",
"strength_level": "120",
"id": "2060",
"aggressive": "true",
"range_level": "1",
"respawn_delay": "60",
"attack_level": "1"
"range_level": "100",
"attack_level": "100"
},
{
"examine": "I can see fish swimming in the water.",
+19 -3
View File
@@ -4717,15 +4717,27 @@
},
{
"npc_id": "2044",
"loc_data": "{2486,3048,0,1,3}-"
"loc_data": "{2486,3048,0,1,3}-{2484,9392,2,1,0}-{2465,9454,2,1,0}-{2471,9422,2,1,0}-{2448,9442,2,1,0}-"
},
{
"npc_id": "2045",
"loc_data": "{2482,3046,0,1,3}-"
"loc_data": "{2482,3046,0,1,3}-{2459,9394,2,1,0}-{2473,9430,2,1,0}-{2478,9442,2,1,0}-{2487,9455,2,1,0}-"
},
{
"npc_id": "2046",
"loc_data": "{2466,9389,2,1,0}-{2449,9429,0,1,0}-{2436,9452,2,1,0}-{2436,9465,2,1,0}-{2450,9460,2,1,0}-{2455,9440,2,1,0}-{2473,9439,2,1,0}-{2483,9408,2,1,0}-"
},
{
"npc_id": "2047",
"loc_data": "{2480,3046,0,1,3}-"
"loc_data": "{2480,3046,0,1,3}-{2477,9384,2,1,0}-{2449,9434,0,1,0}-{2437,9429,2,1,0}-{2440,9438,2,1,0}-{2458,9408,2,1,0}-"
},
{
"npc_id": "2048",
"loc_data": "{2485,9398,2,1,0}-{2455,9435,0,1,0}-{2457,9420,2,1,0}-{2462,9431,2,1,0}-{2482,9422,2,1,0}-"
},
{
"npc_id": "2049",
"loc_data": "{2452,9440,0,1,0}-"
},
{
"npc_id": "2050",
@@ -4755,6 +4767,10 @@
"npc_id": "2056",
"loc_data": "{2470,3040,0,0,0}-"
},
{
"npc_id": "2057",
"loc_data": "{2442,9436,2,1,0}-{2458,9413,2,1,0}-{2470,9435,2,1,0}-{2472,9460,2,1,0}-{2483,9413,2,1,0}-{2485,9447,2,1,0}-{2480,3046,0,1,0}-{2453,9393,2,1,0}-{2461,9403,2,1,0}-{2464,9380,2,1,0}-"
},
{
"npc_id": "2059",
"loc_data": "{2588,3088,0,1,3}-"
+9
View File
@@ -2186,5 +2186,14 @@
"id": "256",
"title": "Leon's Prototype Crossbow",
"stock": "{10156,2,100}"
},
{
"npcs": "2039",
"high_alch": "0",
"currency": "995",
"general_store": "false",
"id": "256",
"title": "Uglug's Stuffsies",
"stock": "{4844,100,10}-{10927,0,100}-{2862,100,100}-{1777,10,200}-{2876,0,500}-{2878,10,100}-{4850,0,100}-{946,5,100}-{4773,0,1000}-{4778,0,1000}-{4783,0,1000}-{4788,0,1500}-{4793,0,2000}-{4798,0,3000}-{4803,0,4000}-{4827,0,2000}"
}
]
@@ -132,6 +132,7 @@ public class Fletching {
YEW_LONGBOW((byte) 1,66,855,70, 75, new Animation(6688)),
MAGIC_SHORTBOW((byte) 1,72,861,80, 83.3, new Animation(6683)),
MAGIC_LONGBOW((byte) 1,70,859,85, 91.5, new Animation(6689)),
OGRE_COMP_BOW((byte) 1,4825,4827,30, 45, new Animation(-1)),
//crossbows
BRONZE_CBOW((byte) 2,9454,9174,9, 6, new Animation(6671)),
@@ -266,7 +267,7 @@ public class Fletching {
}
private enum Items{
STANDARD(1511,FletchingItems.ARROW_SHAFT, FletchingItems.SHORT_BOW, FletchingItems.LONG_BOW, FletchingItems.WOODEN_STOCK),
ACHEY(2862, FletchingItems.OGRE_ARROW_SHAFT),
ACHEY(2862, FletchingItems.OGRE_ARROW_SHAFT, FletchingItems.OGRE_COMP_BOW),
OAK(1521, FletchingItems.OAK_SHORTBOW, FletchingItems.OAK_LONGBOW, FletchingItems.OAK_STOCK),
WILLOW(1519, FletchingItems.WILLOW_SHORTBOW, FletchingItems.WILLOW_LONGBOW, FletchingItems.WILLOW_STOCK),
MAPLE(1517, FletchingItems.MAPLE_SHORTOW, FletchingItems.MAPLE_LONGBOW, FletchingItems.MAPLE_STOCK),
@@ -304,6 +305,7 @@ public class Fletching {
//Achey logs
OGRE_ARROW_SHAFT(2864, 6.4, 5, 4),
OGRE_COMP_BOW(4825, 45, 30, 1),
//Oak logs
OAK_SHORTBOW(54, 16.5, 20, 1),
@@ -1,12 +1,13 @@
package content.global.skill.fletching
import core.game.node.entity.skill.Skills
import content.global.skill.fletching.Fletching
import content.data.Quests
import content.global.skill.fletching.items.arrow.ArrowHeadPulse
import content.global.skill.fletching.items.arrow.HeadlessArrowPulse
import content.global.skill.fletching.items.arrow.HeadlessOgreArrowPulse
import content.global.skill.fletching.items.bow.StringPulse
import content.global.skill.fletching.items.crossbow.LimbPulse
import core.api.*
import core.game.node.entity.skill.Skills
import core.game.node.item.Item
import core.net.packet.PacketRepository
import core.net.packet.context.ChildPositionContext
@@ -34,7 +35,9 @@ class FletchingListeners : InteractionListener {
val MITH_GRAPPLE = Items.MITH_GRAPPLE_9418
val ROPE_GRAPPLE = Items.MITH_GRAPPLE_9419
val ARROW_SHAFT = Items.ARROW_SHAFT_52
val OGRE_ARROW_SHAFT = Items.OGRE_ARROW_SHAFT_2864
val FLETCHED_SHAFT = Items.HEADLESS_ARROW_53
val FLIGHTED_OGRE_ARROW = Items.FLIGHTED_OGRE_ARROW_2865
val UNFINISHED_ARROWS = Fletching.ArrowHeads.values().map(Fletching.ArrowHeads::unfinished).toIntArray()
val FEATHERS = intArrayOf(FEATHER_314,STRIPY_FEATHER_10087,RED_FEATHER_10088,BLUE_FEATHER_10089,YELLOW_FEATHER_10090,ORANGE_FEATHER_10091)
val UNSTRUNG_BOWS = Fletching.String.values().map(Fletching.String::unfinished).toIntArray()
@@ -44,6 +47,14 @@ class FletchingListeners : InteractionListener {
onUseWith(IntType.ITEM,STRINGS,*UNSTRUNG_BOWS){ player, string, bow ->
val enum = Fletching.stringMap[bow.id] ?: return@onUseWith false
if (bow.id == Items.UNSTRUNG_COMP_BOW_4825) {
// You shouldn't be able to string a bow
if (getQuestStage(player, Quests.ZOGRE_FLESH_EATERS) < 8) {
player.packetDispatch.sendMessage("You must have started Zogre Flesh Eaters and asked Grish to string this.")
return@onUseWith true
}
}
if(enum.string != string.id){
player.sendMessage("That's not the right kind of string for this.")
return@onUseWith true
@@ -78,6 +89,21 @@ class FletchingListeners : InteractionListener {
return@onUseWith true
}
onUseWith(IntType.ITEM,OGRE_ARROW_SHAFT,*FEATHERS){ player, shaft, feather ->
val handler: SkillDialogueHandler =
object : SkillDialogueHandler(player, SkillDialogue.MAKE_SET_ONE_OPTION, Item(FLIGHTED_OGRE_ARROW)) {
override fun create(amount: Int, index: Int) {
player.pulseManager.run(HeadlessOgreArrowPulse(player, shaft.asItem(), Item(feather.id, 4), amount))
}
override fun getAll(index: Int): Int {
return player.inventory.getAmount(FLIGHTED_OGRE_ARROW)
}
}
handler.open()
return@onUseWith true
}
onUseWith(IntType.ITEM,FLETCHED_SHAFT,*UNFINISHED_ARROWS){ player, shaft, unfinished ->
val head = Fletching.arrowHeadMap[unfinished.id] ?: return@onUseWith false
val handler: SkillDialogueHandler =
@@ -37,6 +37,11 @@ public final class FletchingPulse extends SkillPulse<Item> {
*/
private int amount = 0;
/**
* Represents the amount to arrows fletched (for ogre arrow shafts which is a random number from 2-6).
*/
private int finalAmount = 0;
/**
* Constructs a new {@code FletchingPulse.java} {@code Object}.
* @param player
@@ -63,6 +68,17 @@ public final class FletchingPulse extends SkillPulse<Item> {
return false;
}
}
if (fletch == Fletching.FletchingItems.OGRE_COMP_BOW) {
// Technically, this isn't supposed to show up till you've asked Grish.
if (player.getQuestRepository().getQuest(Quests.ZOGRE_FLESH_EATERS).getStage(player) < 8) {
player.getPacketDispatch().sendMessage("You must have started Zogre Flesh Eaters and asked Grish to make this.");
return false;
}
if (!player.getInventory().contains(2859, 1)) {
player.getPacketDispatch().sendMessage("You need to have Wolf Bones in order to make this.");
return false;
}
}
return true;
}
@@ -83,7 +99,16 @@ public final class FletchingPulse extends SkillPulse<Item> {
if (player.getInventory().remove(node)) {
final Item item = new Item(fletch.id,fletch.amount);
if ( fletch == Fletching.FletchingItems.OGRE_ARROW_SHAFT ) {
item.setAmount(RandomFunction.random(3,6));
// The amount of shafts given is random; between two and six will be made.
finalAmount = RandomFunction.random(2,6);
item.setAmount(finalAmount);
}
if ( fletch == Fletching.FletchingItems.OGRE_COMP_BOW ) {
if (!player.getInventory().contains(2859, 1)) {
return false;
} else {
player.getInventory().remove(new Item(2859));
}
}
player.getInventory().add(item);
player.getSkills().addExperience(Skills.FLETCHING, fletch.experience, true);
@@ -111,6 +136,8 @@ public final class FletchingPulse extends SkillPulse<Item> {
switch (fletch) {
case ARROW_SHAFT:
return "You carefully cut the wood into 15 arrow shafts.";
case OGRE_ARROW_SHAFT:
return "You carefully cut the wood into " + finalAmount + " arrow shafts.";
default:
return "You carefully cut the wood into " + (StringUtils.isPlusN(fletch.getItem().getName()) ? "an" : "a") + " " + fletch.getItem().getName().replace("(u)", "").trim() + ".";
}
@@ -0,0 +1,131 @@
package content.global.skill.fletching.items.arrow;
import core.game.node.entity.player.Player;
import core.game.node.entity.skill.SkillPulse;
import core.game.node.entity.skill.Skills;
import core.game.node.item.Item;
import org.rs09.consts.Items;
import static core.api.ContentAPIKt.hasSpaceFor;
import static core.api.ContentAPIKt.sendDialogue;
/**
* Represents the arrow pulse for creating unfinished ogre arrows.
* @author 'Vexia
*/
public final class HeadlessOgreArrowPulse extends SkillPulse<Item> {
/**
* Represents the headless ogre arrow item.
*/
private final Item HEADLESS_ARROW = new Item(Items.FLIGHTED_OGRE_ARROW_2865);
/**
* Represents the ogre arrow shaft item.
*/
private final Item ARROW_SHAFT = new Item(Items.OGRE_ARROW_SHAFT_2864);
/**
* Represents the feather items.
*/
private static final Item[] FEATHER = new Item[] {
new Item(Items.FEATHER_314, 4),
};
/**
* The feather being used.
*/
private Item feather;
/**
* Represents the amount to make.
*/
private int sets;
/**
* Constructs a new {@code ArrowPulse.java} {@code Object}.
* @param player the player.
* @param node the node.
*/
public HeadlessOgreArrowPulse(Player player, Item node, Item feather, int sets) {
super(player, node);
this.sets = sets;
this.feather = feather;
}
@Override
public boolean checkRequirements() {
if (!player.getInventory().containsItem(ARROW_SHAFT)) {
player.getDialogueInterpreter().sendDialogue("You don't have any arrow shafts.");
return false;
}
if (feather == null || !player.getInventory().containsItem(feather)) {
player.getDialogueInterpreter().sendDialogue("You don't have any feathers.");
return false;
}
if (!hasSpaceFor(player, HEADLESS_ARROW.asItem())) {
sendDialogue(player, "You do not have enough inventory space.");
return false;
}
return true;
}
@Override
public void animate() {
}
@Override
public boolean reward() {
int featherAmount = player.getInventory().getAmount(feather);
int shaftAmount = player.getInventory().getAmount(ARROW_SHAFT);
if (getDelay() == 1) {
super.setDelay(3);
}
if (featherAmount >= 24 && shaftAmount >= 6) {
feather.setAmount(24);
ARROW_SHAFT.setAmount(6);
player.getPacketDispatch().sendMessage("You attach 24 feathers to 6 ogre arrow shafts.");
} else {
int amount = Math.min(featherAmount / 4, shaftAmount);
feather.setAmount(amount*4);
ARROW_SHAFT.setAmount(amount);
player.getPacketDispatch().sendMessage(amount == 1
? "You attach a feathers to a shaft." : "You attach " + amount * 4 + " feathers to " + amount + " ogre arrow shafts.");
}
if (player.getInventory().remove(feather, ARROW_SHAFT)) {
HEADLESS_ARROW.setAmount(ARROW_SHAFT.getAmount());
player.getSkills().addExperience(Skills.FLETCHING, HEADLESS_ARROW.getAmount(), true);
player.getInventory().add(HEADLESS_ARROW);
}
HEADLESS_ARROW.setAmount(1);
feather.setAmount(1);
ARROW_SHAFT.setAmount(1);
if (!player.getInventory().containsItem(ARROW_SHAFT)) {
return true;
}
if (!player.getInventory().containsItem(feather)) {
return true;
}
sets--;
return sets <= 0;
}
@Override
public void message(int type) {
}
/**
* Gets the feather item.
* @return the item.
*/
private Item getFeather() {
int length = FEATHER.length;
for (int i = 0; i < length; i++) {
Item f = FEATHER[i];
if (player.getInventory().containsItem(f)) {
return f;
}
}
return null;
}
}
@@ -7,7 +7,7 @@ import core.game.node.item.Item;
* @author 'Vexia
*/
public enum Herbs {
GUAM(new Item(199), 2.5, 3, new Item(249)), MARRENTILL(new Item(201), 3.8, 5, new Item(251)), TARROMIN(new Item(203), 5, 11, new Item(253)), HARRALANDER(new Item(205), 6.3, 20, new Item(255)), RANARR(new Item(207), 7.5, 25, new Item(257)), TOADFLAX(new Item(3049), 8, 30, new Item(2998)), SPIRIT_WEED(new Item(12174), 7.8, 35, new Item(12172)), IRIT(new Item(209), 8.8, 40, new Item(259)), AVANTOE(new Item(211), 10, 48, new Item(261)), KWUARM(new Item(213), 11.3, 54, new Item(263)), SNAPDRAGON(new Item(3051), 11.8, 59, new Item(3000)), CADANTINE(new Item(215), 12.5, 65, new Item(265)), LANTADYME(new Item(2485), 13.1, 67, new Item(2481)), DWARF_WEED(new Item(217), 13.8, 70, new Item(267)), TORSTOL(new Item(219), 15, 75, new Item(269)), SNAKE_WEED(new Item(1525), 2.5, 3, new Item(1526)), ARDRIGAL(new Item(1527), 2.5, 3, new Item(1528)), SITO_FOIL(new Item(1529), 2.5, 3, new Item(1530)), VOLENCIA_MOSS(new Item(1531), 2.5, 3, new Item(1532)), ROGUES_PUSE(new Item(1533), 2.5, 3, new Item(1534));
GUAM(new Item(199), 2.5, 3, new Item(249)), MARRENTILL(new Item(201), 3.8, 5, new Item(251)), TARROMIN(new Item(203), 5, 11, new Item(253)), HARRALANDER(new Item(205), 6.3, 20, new Item(255)), RANARR(new Item(207), 7.5, 25, new Item(257)), TOADFLAX(new Item(3049), 8, 30, new Item(2998)), SPIRIT_WEED(new Item(12174), 7.8, 35, new Item(12172)), IRIT(new Item(209), 8.8, 40, new Item(259)), AVANTOE(new Item(211), 10, 48, new Item(261)), KWUARM(new Item(213), 11.3, 54, new Item(263)), SNAPDRAGON(new Item(3051), 11.8, 59, new Item(3000)), CADANTINE(new Item(215), 12.5, 65, new Item(265)), LANTADYME(new Item(2485), 13.1, 67, new Item(2481)), DWARF_WEED(new Item(217), 13.8, 70, new Item(267)), TORSTOL(new Item(219), 15, 75, new Item(269)), SNAKE_WEED(new Item(1525), 2.5, 3, new Item(1526)), ARDRIGAL(new Item(1527), 2.5, 3, new Item(1528)), SITO_FOIL(new Item(1529), 2.5, 3, new Item(1530)), VOLENCIA_MOSS(new Item(1531), 2.5, 3, new Item(1532)), ROGUES_PURSE(new Item(1533), 0, 8, new Item(1534));
/**
* Represents the herb item.
@@ -9,6 +9,7 @@ import core.game.node.item.Item;
public enum UnfinishedPotion {
GUAM(Herbs.GUAM.getProduct(), 3, new Item(91)),
MARRENTILL(Herbs.MARRENTILL.getProduct(), 5, new Item(93)),
ROGUES_PURSE(Herbs.ROGUES_PURSE.getProduct(), 5, new Item(4840)),
TARROMIN(Herbs.TARROMIN.getProduct(), 12, new Item(95)),
HARRALANDER(Herbs.HARRALANDER.getProduct(), 22, new Item(97)),
RANARR(Herbs.RANARR.getProduct(), 30, new Item(99)),
@@ -256,27 +256,6 @@ class ChompyBird : Quest(Quests.BIG_CHOMPY_BIRD_HUNTING, 35, 34, 2, Vars.VARP_QU
return@onUseWith true
}
onUseWith(IntType.ITEM, Items.OGRE_ARROW_SHAFT_2864, Items.FEATHER_314) { player, used, with ->
val shaftAmount = amountInInventory(player, used.id)
val featherAmount = amountInInventory(player, with.id)
var maxAmount = min(shaftAmount, featherAmount)
submitIndividualPulse(player, object : Pulse(3) {
override fun pulse() : Boolean {
val iterAmount = min(maxAmount, 6)
if (removeItem(player, Item(Items.OGRE_ARROW_SHAFT_2864, iterAmount)) && removeItem(player, Item(Items.FEATHER_314, iterAmount)))
{
addItem(player, Items.FLIGHTED_OGRE_ARROW_2865, iterAmount)
rewardXP(player, Skills.FLETCHING, 0.9 * iterAmount)
maxAmount -= iterAmount
}
return maxAmount == 0
}
})
return@onUseWith true
}
onUseWith(IntType.ITEM, Items.WOLF_BONES_2859, Items.CHISEL_1755) { player, used, with ->
val maxAmount = amountInInventory(player, used.id)
@@ -324,6 +303,7 @@ class ChompyBird : Quest(Quests.BIG_CHOMPY_BIRD_HUNTING, 35, 34, 2, Vars.VARP_QU
val amountThisIter = min(6, getMaxAmount())
if (removeItem(player, Item(used.id, amountThisIter)) && removeItem(player, Item(with.id, amountThisIter))) {
addItem(player, Items.OGRE_ARROW_2866, amountThisIter)
sendMessage(player, "You make $amountThisIter ogre arrows.")
rewardXP(player, Skills.FLETCHING, 6.0)
}
}
@@ -164,7 +164,7 @@ class ChompyBirdNPC : AbstractNPC, InteractionListener {
return@on true
}
on(Items.OGRE_BOW_2883, IntType.ITEM, "check kills") { player, _ ->
on(intArrayOf(Items.OGRE_BOW_2883, Items.COMP_OGRE_BOW_4827), IntType.ITEM, "check kills") { player, _ ->
val amount = player.getAttribute("chompy-kills", 0)
sendDialogue(player, "You have killed $amount chompy birds.")
return@on true
@@ -0,0 +1,62 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.FacialExpression
import org.rs09.consts.Items
class BartenderDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
b.onPredicate { _ -> dialogueNum == 1 }
.branch { player ->
return@branch if (getAttribute(player, ZogreFleshEaters.attributeAskedAboutTankard, false)) { 1 } else { 0 }
}.let { branch ->
branch.onValue(0)
.playerl("Hello there, I found this tankard in an ogre tomb cavern. It has the emblem of this Inn on it and I wondered if you knew anything about it?")
.npcl("Oh yes, this is Brentle's mug...I'm surprised he left it just lying around down some cave. He's quite protective of it.")
.playerl("Brentle you say? So you knew him then?")
.npcl("Yeah, this belongs to 'Brentle Vahn', he's quite a common customer, though I've not seen him in a while.")
.npcl(FacialExpression.THINKING, "He was talking to some shifty looking wizard the other day. I don't know his name, but I'd recognise him if I saw him.")
.playerl("Hmm, I'm sorry to tell you this, but Brentle Vahn is dead - I believe he was murdered.")
.npcl(FacialExpression.EXTREMELY_SHOCKED, "Noooo! I'm shocked...")
.npcl("...but not surprised. He was a good customer...but I knew he would sell his sword arm and do many a dark deed if paid enough.")
.npcl(FacialExpression.SAD, "If you need help bringing the culprit to justice, you let me know.")
.endWith { _, player ->
setAttribute(player, ZogreFleshEaters.attributeAskedAboutTankard, true)
}
branch.onValue(1)
.playerl("Hello again. Can you tell me what you know about this tankard again please?")
.npcl("Oh yes, Brentle's tankard. Yeah, you've shown me this already. It belonged to Brentle Vahn, he was quite a common customer, though I've not seen him in a while.")
.npcl("He was talking to some shifty looking wizard the other day. I don't know his name, but I'd recognise him if I saw him.")
.npcl(FacialExpression.SAD, "If you need help bringing the culprit to justice, you let me know.")
.end()
}
b.onPredicate { _ -> dialogueNum == 2 }
.iteml(Items.SITHIK_PORTRAIT_4814, "You show the portrait to the Inn keeper.")
.npcl("Yeah, that's the guy who was talking to Brentle Vahn the other day! Look at those eyes, never a more shifty looking pair will you ever see!")
.playerl("Hmm, you've just identified the man who I think sent Brentle Vahn to his death.")
.playerl("I'm trying to bring him to justice with the Wizards' Guild grand secretary. Do you think you could sign this portrait to say that he was talking to Brentle Vahn.")
.npcl("I can and I will!")
.betweenStage { df, player, _, _ ->
if (removeItem(player, Items.SITHIK_PORTRAIT_4814)) {
addItemOrDrop(player, Items.SIGNED_PORTRAIT_4816)
}
}
.iteml(Items.SIGNED_PORTRAIT_4816, "The Dragon Inn bartender signs the portrait.")
.playerl("Many thanks for your help, it's really very good of you.")
.npcl("Not at all, just doing my part.")
.end()
b.onPredicate { _ -> dialogueNum == 3 }
.iteml(Items.SITHIK_PORTRAIT_4815, "You show the sketch to the Inn keeper.")
.npcl("Who's that? I mean, I guess it's a picture of a person isn't it? Sorry...you've got me? And before you ask, you're not putting it up on my wall!")
.playerl("It's a portrait of Sithik Ints...don't you recognise him?")
.npcl("I'm sorry, I really am, but I just don't see it...can you make a better picture?")
.playerl("I'll try...")
.end()
}
}
@@ -0,0 +1,184 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import content.region.kandarin.quest.templeofikov.TempleOfIkov
import core.api.*
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
@Initializable
class GrishDialogue (player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player): DialoguePlugin {
return GrishDialogue(player)
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
openDialogue(player, GrishDialogueFile(), npc)
return false
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.GRISH_2038)
}
}
class GrishDialogueFile : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
b.onQuestStages(ZogreFleshEaters.questName, 0)
.playerl(FacialExpression.FRIENDLY, "Hello there, what's going on here?")
.npcl(FacialExpression.OLD_NORMAL, "Hey yous creature...wha's you's doing here? Yous be cleverer to be running so da sickies from da zogres don't dead ya.")
.let { builder ->
val returnJoin = b.placeholder()
returnJoin.builder()
.options()
.let { optionBuilder ->
optionBuilder.option_playerl("I'm just looking around thanks.")
.npcl(FacialExpression.OLD_NORMAL, "Yous creature won'ts see muchly in dis place...just da zogries coming wiv da sickies.")
.goto(returnJoin)
optionBuilder.option_playerl("What do you mean sickies?")
.npc(FacialExpression.OLD_NORMAL, "Da zogries comin wiv da sickies...yous get bashed by da", "zogries and get da sickies...den you gonna be like da", "zogries.")
.playerl(FacialExpression.FRIENDLY, "Sorry, I just don't understand...")
.betweenStage { df, player, _, _ ->
animate(npc!!, 2090)
setAttribute(player, ZogreFleshEaters.attributeAskedAboutSickies, true)
}
.npc(FacialExpression.OLD_NORMAL, "Da sickies is when yous creature goes like orange till", "green and then goes 'Urggghhhh!'", "<col=00000FF>~ Grish imitates falling down with only the white of his", "<col=00000FF>eyes visible. ~")
.goto(returnJoin);
optionBuilder.option_playerl("What are Zogres?")
.npcl(FacialExpression.OLD_NORMAL, "a Zogres are da bigun nasties wiv da sickies, deys old pals of Grish but deys jig in Jiggig when dey's full home is deep in da dirt, dey's is not da same dead'uns like was before.")
.goto(returnJoin);
optionBuilder.optionIf("Can I help in any way?") { player -> return@optionIf getAttribute(player, ZogreFleshEaters.attributeAskedAboutSickies, false) }
.playerl(FacialExpression.FRIENDLY, "Can I help in any way?")
.branch { player ->
return@branch if (ZogreFleshEaters.requirements(player)) { 1 } else { 0 }
}.let { branch ->
branch.onValue(0)
.npcl(FacialExpression.OLD_NORMAL, "Sorry, yous creatures, but yous is too green behind da ears for dis job Grish finks.")
.playerl(FacialExpression.ANGRY, "No, I'm not!")
.npcl(FacialExpression.OLD_ANGRY1, "Yes you are!")
.playerl(FacialExpression.ANGRY, "No, I'm not!")
.npcl(FacialExpression.OLD_ANGRY1, "Yes you are and that's final!")
.end()
branch.onValue(1)
.npcl(FacialExpression.OLD_NORMAL, "Yes creatures...yous does good fings for Grish and learn why Zogries at Jiggig and den get da Zogries back in da ground.")
.playerl("Oh, so you want me to find out why the Zogres have appeared and then find a way of burying them?")
.npcl(FacialExpression.OLD_NORMAL, "Is what Grish says! But dis is da biggy danger fing yous creatures...yous be geddin' sickies most surely...yous needs be ready..wiv da foodies un da glug-glugs.")
.playerl("Right, so you think there's a good chance that I can get ill from this, so I need to get some food and something to drink?")
.npcl(FacialExpression.OLD_NORMAL, "Yea creatures, yous just say what Grish says...not know own wordies creature?")
.options()
.let { optionBuilder ->
optionBuilder.option_playerl("Hmm, sorry, it sounds a bit too dangerous.")
.npcl(FacialExpression.OLD_NORMAL, "Yous creature is not a stoopid one...stays out of dere, like clever Grish. Yous can paint circles on chest and be da Shaman too!")
.playerl("Hmm, is it too late to reconsider?")
.end()
optionBuilder.option_playerl("Ok, I'll check things out then and report back.")
.npcl(FacialExpression.OLD_NORMAL, "Is yous creatures really, really sure yous wanna do dis creatures..we's got no glug-glugs for da sickies? We's knows nuffin for da going of da sickies?")
.options()
.let { optionBuilder2 ->
optionBuilder2.option_playerl("Yes, I'm really sure!")
.npcl(FacialExpression.OLD_NORMAL,"Dats da good fing yous creature...yous does Grish a good fing. But yous know dat yous get sickies and mebe get dead!")
.playerl("If that's your idea of a pep talk, I have to say that it leaves a lot to be desired.")
.npcl(FacialExpression.OLD_NORMAL,"Yous creatures is alus says funny stuff...speaks proper like Grish!")
.manualStage() { df, player, _, _ ->
sendDoubleItemDialogue(player, Items.COOKED_CHOMPY_2878, Items.SUPER_RESTORE3_3026, "Grish hands you some food and two potions.")
}
.npcl(FacialExpression.OLD_NORMAL,"Der's yous go creatures...da best me's do for yous...and be back wivout da sickies.")
.endWith { _, player ->
if(getQuestStage(player, ZogreFleshEaters.questName) == 0) {
// Trying to prevent players from spamming to get more super restores.
addItemOrDrop(player, Items.COOKED_CHOMPY_2878, 3)
addItemOrDrop(player, Items.SUPER_RESTORE3_3026, 2)
setQuestStage(player, ZogreFleshEaters.questName, 1)
}
}
optionBuilder2.option_playerl("Hmm, sorry, it sounds a bit too dangerous.")
.npcl(FacialExpression.OLD_NORMAL, "Yous creature is not a stoopid one...stays out of dere, like clever Grish. Yous can paint circles on chest and be da Shaman too!")
.end()
}
}
}
optionBuilder.option_playerl("Sorry, I have to go.")
.end()
}
}
b.onQuestStages(ZogreFleshEaters.questName, 1,2,3,4,5,6)
.npcl(FacialExpression.OLD_NORMAL, "Yous creature dun da fing yet? Da zogries going in da dirt full home?")
.playerl("Nope, I haven't figured out why the zogres are here yet.")
.end()
b.onQuestStages(ZogreFleshEaters.questName, 7)
.npcl(FacialExpression.OLD_NORMAL,"Yous creature dun da fing yet? Da zogries going in da ground?")
.playerl("I found who's responsible for the Zogres being here.")
.npcl(FacialExpression.OLD_NORMAL,"Where is da creature? Me's wants to squeeze him till he's a deadun...")
.playerl("The person responsible is a wizard named 'Sithik Ints' and he's going to be in serious trouble. He told me that the spell which raised the zogres from the ground will last forever.")
.playerl("I'm sorry to say, but you'll have to move the site of your ceremonial dancing somewhere else.")
.npcl(FacialExpression.OLD_NORMAL,"Dat is da bad fing creature...we's needs new Jiggig for da fallin' down jig.")
.playerl("Yes, that's right, you'll need to create a new ceremonial dance area.")
.npcl(FacialExpression.OLD_NORMAL,"Urghhh...not good fing creature, yous gotta get da ogrish old fings for da making new jiggig special. You's creature needs da key for getting in da low bury place.")
.betweenStage { df, player, _, _ ->
addItemOrDrop(player, Items.OGRE_GATE_KEY_4839)
}
.iteml(Items.OGRE_GATE_KEY_4839, "Grish gives you a crudely crafted key.")
.playerl("Oh, so you want me to go back in there and look for something for you?")
.npcl(FacialExpression.OLD_NORMAL,"Yeah creature, yous gotta get da ogrish old fings for da making new jiggig and proper in da special way.")
.endWith { _, player ->
if(getQuestStage(player, ZogreFleshEaters.questName) == 7) {
setQuestStage(player, ZogreFleshEaters.questName, 8)
}
}
b.onQuestStages(ZogreFleshEaters.questName, 8)
.npcl(FacialExpression.OLD_NORMAL, "Hey, you's creature got da old fings?")
.branch { player ->
return@branch if (inInventory(player, Items.OGRE_GATE_KEY_4839)) { 1 } else { 0 }
}.let { branch ->
branch.onValue(1)
.playerl("Nope, not yet.")
.npcl(FacialExpression.OLD_NORMAL, "Yous gets 'em quick tho, cos we'ze wonna do da new Jiggig place...")
.end()
branch.onValue(0)
.playerl("I lost the key you gave me.")
.betweenStage { df, player, _, _ ->
addItemOrDrop(player, Items.OGRE_GATE_KEY_4839)
}
.iteml(Items.OGRE_GATE_KEY_4839, "Grish gives you a crudely crafted key.")
.end()
}
b.onQuestStages(ZogreFleshEaters.questName, 9)
.branch { player ->
return@branch if (inInventory(player, Items.OGRE_ARTEFACT_4818)) { 1 } else { 0 }
}.let { branch ->
branch.onValue(0)
.npcl(FacialExpression.OLD_NORMAL, "Hey, you's creature got da old fings?")
.playerl("No sorry, I don't have them yet.")
.npcl(FacialExpression.OLD_NORMAL, "Yous creatures get dem for me soon doh, yes?")
.end() // There's all the default dialogue here, but I'm lazy again.
branch.onValue(1)
.npcl(FacialExpression.OLD_NORMAL, "Hey, you's creature got da old fings?")
.playerl("Yeah, I have them here!")
.npcl(FacialExpression.OLD_NORMAL, "Dat is da goodly fing yous creature, now's we's can make da new Jiggig place away from zogries! Yous been da big helpy fing yous creature, Grish wishin' yous good stuff for da next fings for creature.")
.npcl(FacialExpression.OLD_HAPPY, "<col=08088A>~ Grish seems very pleased about the return of the artefacts. ~")
.playerl("Thanks, that's very nice of you!")
.endWith { _, player ->
if (removeItem(player, Items.OGRE_ARTEFACT_4818)) {
if (getQuestStage(player, ZogreFleshEaters.questName) == 9) {
finishQuest(player, ZogreFleshEaters.questName)
}
}
}
}
b.onQuestStages(ZogreFleshEaters.questName, 100)
.playerl("How's everything going now?")
.npcl(FacialExpression.OLD_NORMAL,"All da zogries stayin' in da oldie Jiggig, we's gonna do da new Jiggig someways else. Yous creature da good- un for geddin' da oldie fings...")
// More default dialogue, but lazy.
.end()
}
}
@@ -0,0 +1,31 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.openDialogue
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
@Initializable
class GrugDialogue (player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player): DialoguePlugin {
return GrugDialogue(player)
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
openDialogue(player, GrugDialogueFile(), npc)
return false
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.GRUG_2041)
}
}
class GrugDialogueFile : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
b.onPredicate { _ -> true }
.npcl(FacialExpression.OLD_NORMAL, "Ukk...I's dun fer...me's don't feel legsies anymore!")
.end()
}
}
@@ -0,0 +1,27 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.dialogue.FacialExpression
import core.game.interaction.InteractionListener
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
class JiggigListeners : InteractionListener {
override fun defineListeners() {
on(Scenery.OGRE_COFFIN_6848, SCENERY, "open") { player, node ->
// https://youtu.be/HnRcW2iM8es
replaceScenery(node as core.game.node.scenery.Scenery, Scenery.OGRE_COFFIN_6890, 10)
return@on true
}
on(NPCs.UGLUG_NAR_2039, NPC, "trade") { player, node ->
if (getAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, false)) {
openNpcShop(player, NPCs.UGLUG_NAR_2039)
} else {
sendNPCDialogue(player, NPCs.UGLUG_NAR_2039, "Me's not got no glug-glugs to sell, yous bring me da sickies glug-glug den me's open da stufsies for ya.", FacialExpression.OLD_NORMAL)
}
return@on true
}
}
}
@@ -0,0 +1,73 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.interaction.QueueStrength
import core.game.node.entity.player.Player
import core.game.world.map.Location
import core.game.world.update.flag.context.Animation
import core.plugin.Initializable
import org.rs09.consts.NPCs
@Initializable
class OgreGuardDialogue (player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player): DialoguePlugin {
return OgreGuardDialogue(player)
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
openDialogue(player, OgreGuardDialogueFile(), npc)
return false
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.OGRE_GUARD_2042)
}
}
class OgreGuardDialogueFile : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
b.onQuestStages(ZogreFleshEaters.questName, 0)
.npcl(FacialExpression.OLD_NORMAL, "Yous needs ta stay away from dis place... yous get da sickies and mebe yous goes to dead if yous da unlucky fing.")
.playerl("Ok, thanks.")
.end()
b.onQuestStages(ZogreFleshEaters.questName, 1)
.npcl(FacialExpression.OLD_NORMAL, "Yous needs ta stay away from dis place... yous get da sickies and mebe yous goes to dead if yous da unlucky fing.")
.playerl(FacialExpression.FRIENDLY, "But Grish has asked me to look into this place and find out why all the undead ogres are here.")
.npcl(FacialExpression.OLD_NORMAL, "Ok, dat is da big, big scary, danger fing! You's sure you's wants to go in?")
.playerl(FacialExpression.FRIENDLY, "Yes, I'm sure.")
.npcl(FacialExpression.OLD_NORMAL, "Ok, I opens da stoppa's for yous creature.")
.endWith { _, player ->
lock(player, 4)
face(npc!!, Location(2456, 3049, 0))
// Lesson learnt here, endWith kills the npc object so tie the queueScript with the npc instead, not the player.
queueScript(npc!!, 2, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
animate(npc!!, 2102)
return@queueScript delayScript(npc!!, Animation(2102).duration)
}
1 -> {
if(getQuestStage(player, ZogreFleshEaters.questName) == 1) {
setQuestStage(player, ZogreFleshEaters.questName, 2)
}
setVarbit(player, ZogreFleshEaters.varbitGateBashed, 1)
unlock(player)
face(npc!!, player.location)
sendNPCDialogue(player, NPCs.OGRE_GUARD_2042, "Ok der' yous goes!", FacialExpression.OLD_NORMAL)
return@queueScript stopExecuting(npc!!)
}
else -> return@queueScript stopExecuting(npc!!)
}
}
}
b.onQuestStages(ZogreFleshEaters.questName, 2,3,4,5,6,7,8,9,10,100)
.npcl(FacialExpression.OLD_NORMAL, "Hey yous tryin' not to get da sickies else yous be da sick-un and mebe get to be a dead-un if yous be da unlucky fing.")
.playerl(FacialExpression.FRIENDLY, "Don't worry, I know how to take care of myself.")
.end()
}
}
@@ -0,0 +1,31 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
@Initializable
class PilgDialogue (player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player): DialoguePlugin {
return PilgDialogue(player)
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
openDialogue(player, PilgDialogueFile(), npc)
return false
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.PILG_2040)
}
}
class PilgDialogueFile : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
b.onPredicate { _ -> true }
.npcl(FacialExpression.OLD_NORMAL, "Dey got me in da belly, mees gutsies feel like had a dead dead dog dinner.")
.end()
}
}
@@ -0,0 +1,388 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.npc.NPC
import core.game.node.entity.skill.Skills
import core.game.node.item.Item
import core.tools.END_DIALOGUE
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
/** This NPC is a scenery. */
//@Initializable
//class SithikIntsDialogue (player: Player? = null) : DialoguePlugin(player) {
// override fun newInstance(player: Player): DialoguePlugin {
// return SithikIntsDialogue(player)
// }
// override fun handle(interfaceId: Int, buttonId: Int): Boolean {
// openDialogue(player, SithikIntsDialogueFile(), npc)
// return false
// }
// override fun getIds(): IntArray {
// return intArrayOf(NPCs.SITHIK_INTS_2061, NPCs.SITHIK_INTS_2062)
// }
//}
class SithikIntsDialogue : InteractionListener {
override fun defineListeners() {
on(Scenery.SITHIK_INTS_6888, SCENERY, "talk-to") { player, node ->
openDialogue(player, SithikIntsDialogueFile(), NPC(NPCs.SITHIK_INTS_2061))
return@on true
}
on(Scenery.SITHIK_INTS_6889, SCENERY, "talk-to") { player, node ->
openDialogue(player, SithikIntsOgreFormDialogueFile(), NPC(NPCs.SITHIK_INTS_2062))
return@on true
}
on(Scenery.DRAWERS_6875, SCENERY, "search") { player, node ->
if (getQuestStage(player, ZogreFleshEaters.questName) <= 2) {
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hey! What do you think you're doing?", FacialExpression.ANNOYED).also { stage++ }
1 -> sendPlayerDialogue(player, "Erk! I'd better not start rifling through peoples things without permission.").also { stage = END_DIALOGUE }
}
}
})
} else if (getQuestStage(player, ZogreFleshEaters.questName) in 3..4 &&
(!inInventory(player, Items.BOOK_OF_PORTRAITURE_4817) ||
!inInventory(player, Items.PAPYRUS_970) ||
!inInventory(player, Items.CHARCOAL_973)
)) {
if (hasSpaceFor(player, Item(Items.BOOK_OF_PORTRAITURE_4817, 3))) {
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> {
if (!inInventory(player, Items.PAPYRUS_970) && !inInventory(player, Items.CHARCOAL_973)) {
sendDoubleItemDialogue(player, Items.CHARCOAL_973, Items.PAPYRUS_970, "You find some charcoal and papyrus.")
addItemOrDrop(player, Items.PAPYRUS_970)
addItemOrDrop(player, Items.CHARCOAL_973)
stage++
} else if (!inInventory(player, Items.PAPYRUS_970)) {
sendItemDialogue(player, Items.PAPYRUS_970, "You find some papyrus.")
addItemOrDrop(player, Items.PAPYRUS_970)
stage++
} else if (!inInventory(player, Items.CHARCOAL_973)) {
sendItemDialogue(player, Items.CHARCOAL_973, "You find some charcoal.")
addItemOrDrop(player, Items.CHARCOAL_973)
stage++
} else {
sendItemDialogue(player, Items.BOOK_OF_PORTRAITURE_4817, "You also find a book on portraiture.")
addItemOrDrop(player, Items.BOOK_OF_PORTRAITURE_4817)
stage = END_DIALOGUE
}
}
1 -> {
sendItemDialogue(player, Items.BOOK_OF_PORTRAITURE_4817, "You also find a book on portraiture.")
addItemOrDrop(player, Items.BOOK_OF_PORTRAITURE_4817)
stage = END_DIALOGUE
}
}
}
})
} else {
sendDialogue(player, "You see some items in the drawer, but you need 3 free inventory spaces to take them.")
}
} else {
sendMessage(player, "You search but find nothing of significance.")
}
return@on true
}
on(Scenery.CUPBOARD_6876, SCENERY, "search") { player, node ->
if (getQuestStage(player, ZogreFleshEaters.questName) <= 2) {
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hey! What do you think you're doing?", FacialExpression.ANNOYED).also { stage++ }
1 -> sendPlayerDialogue(player, "Erk! I'd better not start rifling through peoples things without permission.").also { stage = END_DIALOGUE }
}
}
})
} else if (getQuestStage(player, ZogreFleshEaters.questName) in 3..4 && !inInventory(player, Items.NECROMANCY_BOOK_4837)) {
if (hasSpaceFor(player, Item(Items.NECROMANCY_BOOK_4837))) {
addItemOrDrop(player, Items.NECROMANCY_BOOK_4837)
sendItemDialogue(player, Items.NECROMANCY_BOOK_4837, "You find a book on Necromancy.")
setAttribute(player, ZogreFleshEaters.attributeFoundNecromanticBook, true)
} else {
sendDialogue(player, "You see an item in the cupboard, but you don't have space to put it in your inventory.")
}
} else {
sendMessage(player, "You search but find nothing of significance.")
}
return@on true
}
onUseWith(IntType.SCENERY, Items.NECROMANCY_BOOK_4837, Scenery.SITHIK_INTS_6888) { player, used, with ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendPlayerDialogue(player,"Aha! A necromantic book! What's this doing here then?").also { stage++ }
1 -> sendItemDialogue(player, Items.NECROMANCY_BOOK_4837, "You show the Necromantic book to Sithik.").also { stage++ }
2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Oh..I'm not quite sure actually...where did you find that then?").also { stage++ }
3 -> sendPlayerDialogue(player,"I found it in this cupboard! What do you have to say for yourself?").also { stage++ }
4 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Oh yes, that's right...I remember now. It's for my research, there's nothing really dangerous about it, unless it falls into the wrong hands. I'm sure it's pretty safe with me.").also { stage++ }
5 -> sendPlayerDialogue(player,"Hmmm, likely story!").also { stage = END_DIALOGUE }
}
}
})
return@onUseWith true
}
on(Scenery.WARDROBE_6877, SCENERY, "search") { player, node ->
if (getQuestStage(player, ZogreFleshEaters.questName) <= 2) {
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hey! What do you think you're doing?", FacialExpression.ANNOYED).also { stage++ }
1 -> sendPlayerDialogue(player, "Erk! I'd better not start rifling through peoples things without permission.").also { stage = END_DIALOGUE }
}
}
})
} else if (getQuestStage(player, ZogreFleshEaters.questName) in 3..4 && !inInventory(player, Items.BOOK_OF_HAM_4829)) {
if (hasSpaceFor(player, Item(Items.BOOK_OF_HAM_4829))) {
addItemOrDrop(player, Items.BOOK_OF_HAM_4829)
sendItemDialogue(player, Items.BOOK_OF_HAM_4829, "You find a book on Philosophy written by the 'Human's Against Monsters' leader, Johanhus Albrect.")
setAttribute(player, ZogreFleshEaters.attributeFoundHamBook, true)
} else {
sendDialogue(player, "You see an item in the wardrobe, but you don't have space to put it in your inventory.")
}
} else {
sendMessage(player, "You search but find nothing of significance.")
}
return@on true
}
onUseWith(IntType.SCENERY, Items.BOOK_OF_HAM_4829, Scenery.SITHIK_INTS_6888) { player, used, with ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendPlayerDialogue(player,"What's this then?").also { stage++ }
1 -> sendItemDialogue(player, Items.BOOK_OF_HAM_4829, "You show the HAM book to Sithik.").also { stage++ }
2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "What do you mean? It's a book by the respected HAM leader Johanhus Ulsbrecht, that man speaks for a lot of people who are unhappy with the current state of affairs.").also { stage++ }
3 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Can you honestly tell me that you've not had to fight for your life against the odd monster or two?").also { stage++ }
4 -> sendPlayerDialogue(player,"Hmm, that may be true, but I don't universally hate all monsters, whereas I have a sneaking suspicion that you do...and ogres in particular!").also { stage++ }
5 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hmm, that's an interesting theory, care to back it up with any facts?").also { stage = END_DIALOGUE }
}
}
})
return@onUseWith true
}
onUseWith(IntType.SCENERY, Items.PAPYRUS_970, Scenery.SITHIK_INTS_6888) { player, used, with ->
if(inInventory(player, Items.CHARCOAL_973)) {
if (removeItem(player, used)) {
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Oh lovely! You're making my portrait! Let me see it afterwards!", FacialExpression.FRIENDLY).also { stage++ }
1 -> sendDialogue(player, "You begin sketching the irritable Sithik.").also { animate(player, 909); stage++ }
2 -> {
val skill = Skills.CRAFTING
val level: Int = getDynLevel(player, skill) + getFamiliarBoost(player, skill)
val ratio = RandomFunction.getSkillSuccessChance(0.0, 80.0, level)
if (ratio > 0.5) {
// Passed
sendItemDialogue(player, Items.SITHIK_PORTRAIT_4814, "You get a portrait of Sithik.")
addItemOrDrop(player, Items.SITHIK_PORTRAIT_4814)
} else {
// Failed
sendItemDialogue(player, Items.SITHIK_PORTRAIT_4815, "You get a portrait of Sithik.")
addItemOrDrop(player, Items.SITHIK_PORTRAIT_4815)
}
setAttribute(player, ZogreFleshEaters.attributeMadePortrait, true)
stage = END_DIALOGUE
}
}
}
})
}
} else {
sendDialogue(player, "You have no charcoal with which to sketch this subject.")
}
return@onUseWith true
}
onUseWith(IntType.SCENERY, Items.BOOK_OF_PORTRAITURE_4817, Scenery.SITHIK_INTS_6888) { player, used, with ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendPlayerDialogue(player,"Oh, so explain this then?").also { stage++ }
1 -> sendItemDialogue(player, Items.BOOK_OF_PORTRAITURE_4817, "You show the book on portraiture to Sithik.").also { stage++ }
2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "It's my hobby...I'm interested in portraiture, but all art in general. It's fun, you should try it.").also { stage++ }
3 -> sendPlayerDialogue(player,"How do I do it...").also { stage++ }
4 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Well...you could start by reading the book!").also { stage = END_DIALOGUE }
}
}
})
return@onUseWith true
}
onUseWith(IntType.SCENERY, Items.SITHIK_PORTRAIT_4814, Scenery.SITHIK_INTS_6888) { player, used, with ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendPlayerDialogue(player, "Here you go, what do you think?").also { stage++ }
1 -> sendItemDialogue(player, Items.SITHIK_PORTRAIT_4814, "You show the sketch...").also { stage++ }
2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hmmm, well it's not the most flattering of portraits, but I like the 'honesty' of the work...well done.").also { stage = END_DIALOGUE }
}
}
})
return@onUseWith true
}
onUseWith(IntType.SCENERY, Items.SITHIK_PORTRAIT_4815, Scenery.SITHIK_INTS_6888) { player, used, with ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendPlayerDialogue(player, "Here you go, what do you think?").also { stage++ }
1 -> sendItemDialogue(player, Items.SITHIK_PORTRAIT_4815, "You show the sketch...").also { stage++ }
2 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hmmm, well it's an interesting interpretation, but not really classic realist representation is it? It's not my favourite, but I like the 'truth' of the work...well done.").also { stage = END_DIALOGUE }
}
}
})
return@onUseWith true
}
on(Items.CUP_OF_TEA_4838, ITEM, "take") { player, node ->
sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Hey! What do you think you're doing? Leave my tea alone!", FacialExpression.ANNOYED)
return@on true
}
onUseWith(IntType.SCENERY, Items.STRANGE_POTION_4836, Scenery.SITHIK_INTS_6888) { player, used, with ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendPlayerDialogue(player,"Here, try some of this potion, it'll make you feel better!").also { stage++ }
1 -> sendNPCDialogue(player, NPCs.SITHIK_INTS_2061, "Err, yuck...no way am I taking any potions or medication off you...I don't trust you!").also { stage = END_DIALOGUE }
}
}
})
return@onUseWith true
}
onUseWith(IntType.GROUNDITEM, Items.STRANGE_POTION_4836, Items.CUP_OF_TEA_4838) { player, _, with ->
if(getQuestStage(player, ZogreFleshEaters.questName) == 5) {
if (removeItem(player, Items.STRANGE_POTION_4836)) {
sendItemDialogue(player, Items.STRANGE_POTION_4836, "You pour some of the potion into the cup. Zavistic said it may take some time to have an effect.")
addItemOrDrop(player, Items.SAMPLE_BOTTLE_3377)
}
setQuestStage(player, ZogreFleshEaters.questName, 6)
}
return@onUseWith true
}
}
}
class SithikIntsDialogueFile : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
b.onQuestStages(ZogreFleshEaters.questName, 0, 1, 2)
.npcl(FacialExpression.ANNOYED, "Hey... who gave you permission to come in here! Get out, get out I say.")
.playerl("Alright, alright... keep your night cap on.")
.end()
b.onQuestStages(ZogreFleshEaters.questName, 3, 4, 5, 6)
.npcl(FacialExpression.ANNOYED, "Hey... who gave you permission to come in here! Get out, get out I say.")
.playerl("Zavistic Rarve said that I could come and talk to you and ask you a few questions.")
.betweenStage { df, player, _, _ ->
if (getQuestStage(player, ZogreFleshEaters.questName) == 3) {
setQuestStage(player, ZogreFleshEaters.questName, 4)
}
}
.npcl(FacialExpression.ANNOYED, "Oh, Zavistic...why...why would he send you to me?")
.let { builder ->
val returnJoin = b.placeholder()
returnJoin.builder()
.options()
.let { optionBuilder ->
optionBuilder.option_playerl("Do you know anything about the undead ogres at Jiggig?")
.npcl("Er...undead ogres...no, sorry, no idea what you're talking about there.")
.playerl("Hmm, is that right...")
.npcl("Well, yes, yes it is. If I knew something, I'd tell you.")
.npcl("Anyway, dead ogres you say? How strange? That must be a strange sight?")
.playerl("Very well, if you don't know anything about it, you won't mind if I look around then?")
.npcl("Well,err....well, actually yes I do mind...it's my place and I don't want strangers going through my things.")
.goto(returnJoin)
optionBuilder.option_playerl("What do you do?")
.npcl("I'm a scholarly student of the magical arts. When I was younger I used to be an adventurer, probably just like yourself. But I lost interest in the constant fighting, looting and gaining abilities.")
.npcl("Instead I decided to focus my attention and time to study the purer form of the lost arts.")
.playerl("The lost arts? What are they?")
.npcl("Ignorant people call them the 'dark arts'. I'm talking about Necromancy, the power to bring the dead back to life - the power of the gods! Surely the most awesome power known to man.")
.playerl("Hmm, well I guess I must be an ignorant person then, because bringing the dead back to life sounds very unnatural.")
.goto(returnJoin)
optionBuilder.option_playerl("Do you mind if I look around?")
.npcl("Well,err....well, actually yes I do mind...it's my place and I don't want strangers going through my things.")
.playerl("Well, I'm going to have a look around anyway, if you're not involved in this whole thing, you won't have anything to hide.")
.npcl("Why, if I was a few years younger I'd give you a good hiding!")
.playerl("I'm sure!")
.goto(returnJoin)
optionBuilder.option_playerl("Ok, thanks.")
.end()
}
builder.goto(returnJoin)
}
}
}
class SithikIntsOgreFormDialogueFile : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
b.onQuestStages(ZogreFleshEaters.questName, 7,8,9,100)
/*
There are some after first time dialogue, but who reads this...
.npcl("Arghhhh..what do you want now...you've turned me into a beast!")
.playerl("I've got some questions for you...and you'd better answer them well or else!")
.npcl("Ok, ok, I'll tell you anything, just turn me back into a human again!")
*/
.npcl(FacialExpression.OLD_DEFAULT, "Arghhhh..what's happened to me...you beast!")
.playerl("It's your own fault, you shouldn't have lied about your involvement with the undead Ogres at Jiggig. The potion will wear off once you've told the truth!")
.npcl(FacialExpression.OLD_DEFAULT, "Ok, ok, I admit it, I got Brentle Vahn to cast the spell to put an end to those awful Ogres...they're just disgusting creatures...")
.playerl("Ok, that's a start...now I want some answers.")
.let { builder ->
val returnJoin = b.placeholder()
returnJoin.builder()
.options()
.let { optionBuilder ->
optionBuilder.option("How do I remove the effects of the spell from the area?")
.playerl("How do I remove the effects of the spell from the area? The ogres want to get their ceremonial dance area back and can't do that with undead walking all over it.")
.npcl(FacialExpression.OLD_DEFAULT, "Unfortunately you can't. The spell is permanent, it will last forever, the only option you have is to move the ceremonial area.")
.playerl("You're an evil man and I'm going to make you pay for this...you can stay like that forever as far as I'm concerned.")
.npcl(FacialExpression.OLD_DEFAULT, "No...no, let me try to make amends...please I can help you. Just don't leave me like this.")
.goto(returnJoin)
optionBuilder.option_playerl("How do I get rid of the undead ogres?")
.npcl(FacialExpression.OLD_DEFAULT, "Ok, similar spells have been cast before and the only way to deal with the resulting creatures is to cordon off the area and not go in there again.")
.npcl(FacialExpression.OLD_DEFAULT, "The undead creatures usually manifest some sort of disease so it's best to attack them from a distance with a ranged weapon.")
.npcl(FacialExpression.OLD_DEFAULT, "Normal missiles like arrows and darts do very little damage to them because they're designed to destroy internal organs. This is a waste of time with undead creatures like undead ogres.")
.playerl("Yeah, clearly so what should we use?")
.npcl(FacialExpression.OLD_DEFAULT, "From my research it looks like a flat ended arrow was designed called a 'Brutal arrow'. This does large amounts of crushing damage to the creature. You can make them by using larger arrows.")
.npcl(FacialExpression.OLD_DEFAULT, "I think some Ogre hunters make them. But instead of adding an arrow tip, you hammer a large nail into the end of the shaft.")
.goto(returnJoin)
optionBuilder.option_playerl("How do I get rid of the disease?")
.npcl(FacialExpression.OLD_DEFAULT, "My research shows that two jungle based herbs can be used, one is found near river tributaries and looks like a vine, the other is found in caves and grows on the wall.")
.npcl(FacialExpression.OLD_DEFAULT, "It's quite well camouflaged so it's unlikely that you'll find it.")
.playerl("We'll see about that!")
.goto(returnJoin)
optionBuilder.option_playerl("Sorry, I have to go.")
.npcl(FacialExpression.OLD_DEFAULT, "But...you can't just leave me here like this!")
.end()
}
builder.goto(returnJoin)
}
}
}
@@ -0,0 +1,39 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.getOrStartTimer
import core.api.inEquipment
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.player.Player
import core.game.system.timer.impl.Disease
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class SkogreBehavior : NPCBehavior(*skogreIds) {
companion object {
private val skogreIds = intArrayOf(
NPCs.SKOGRE_2050,
NPCs.SKOGRE_2056,
NPCs.SKOGRE_2057,
)
}
override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) {
if (attacker is Player) {
if (inEquipment(attacker, Items.COMP_OGRE_BOW_4827)) {
return
}
state.estimatedHit = (state.estimatedHit * 0.25).toInt()
if (state.secondaryHit > 0) {
state.secondaryHit = (state.secondaryHit * 0.25).toInt()
}
}
}
override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) {
val disease = getOrStartTimer<Disease>(victim, 10)
disease.hitsLeft = 10
}
}
@@ -0,0 +1,92 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import content.global.handlers.item.equipment.special.DragonfireSwingHandler
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.combat.CombatStyle
import core.game.node.entity.combat.CombatSwingHandler
import core.game.node.entity.combat.MultiSwingHandler
import core.game.node.entity.combat.equipment.SwitchAttack
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.game.system.timer.impl.Disease
import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class SlashBashBehavior : NPCBehavior(NPCs.SLASH_BASH_2060) {
override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean {
if (attacker is Player) {
if (attacker == getAttribute<Player?>(self, "target", null)) {
return true
}
sendMessage(attacker, "It's not after you...")
}
return false
}
override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) {
if (victim is Player) {
val disease = getOrStartTimer<Disease>(victim, 25)
disease.hitsLeft = 25
}
}
override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) {
if (attacker is Player) {
if (inEquipment(attacker, Items.COMP_OGRE_BOW_4827)) {
return
}
state.estimatedHit = (state.estimatedHit * 0.25).toInt()
if (state.secondaryHit > 0) {
state.secondaryHit = (state.secondaryHit * 0.25).toInt()
}
}
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
if (killer is Player && getQuestStage(killer, ZogreFleshEaters.questName) == 8) {
drops.add(Item(Items.ZOGRE_BONES_4812, 2))
drops.add(Item(Items.OURG_BONES_4834, 3))
drops.add(Item(Items.OGRE_ARTEFACT_4818))
setQuestStage(killer, ZogreFleshEaters.questName, 9)
removeAttribute(killer, ZogreFleshEaters.attributeSlashBashInstance)
}
}
var clearTime = 0
override fun tick(self: NPC): Boolean {
val player: Player? = getAttribute<Player?>(self, "target", null)
// You have 500 ticks to kill this guy
if (clearTime++ > 500) {
poofClear(self)
clearTime = 0
if (player != null) {
removeAttribute(player, ZogreFleshEaters.attributeSlashBashInstance)
}
}
return true
}
/** MELEE Swing */
private val COMBAT_HANDLER = MultiSwingHandler(SwitchAttack(CombatStyle.MELEE.swingHandler, Animation(359)))
/** RANGE Swing (Projectile) */
private val COMBAT_HANDLER_FAR = MultiSwingHandler(SwitchAttack(CombatStyle.RANGE.swingHandler, Animation(359), Graphics(499)))
override fun getSwingHandlerOverride(self: NPC, original: CombatSwingHandler): CombatSwingHandler {
val victim = self.properties.combatPulse.getVictim() ?: return original
if (victim !is Player) return original
return if (victim.location.getDistance(self.location) >= 2)
COMBAT_HANDLER_FAR
else
COMBAT_HANDLER
}
}
@@ -0,0 +1,78 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
@Initializable
class UglugNarDialogue (player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player): DialoguePlugin {
return UglugNarDialogue(player)
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
openDialogue(player, UglugNarDialogueFile(), npc)
return false
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.UGLUG_NAR_2039)
}
}
class UglugNarDialogueFile : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
b.onQuestStages(ZogreFleshEaters.questName, 0)
.options()
.let { optionBuilder ->
optionBuilder.option_playerl("Hey, what's going on here?")
.npcl(FacialExpression.OLD_NORMAL, "Dem's dead ogre's come out of the ground...dey's makin' da rest of us into sick-ums ...and dead-uns.")
.playerl("That doesn't sound good!")
.npcl(FacialExpression.OLD_NORMAL, "Grish want's da person go down der - see what's what!")
.end()
optionBuilder.option_playerl("What are you selling?")
.npcl(FacialExpression.OLD_NORMAL, "Me's not got no glug-glugs to sell, yous bring me da sickies glug-glug den me's open da stufsies for ya.")
.end()
optionBuilder.option_playerl("Ok, thanks.")
.end()
}
b.onQuestStages(ZogreFleshEaters.questName, 1,2,3,4,5,6,7,8,9,10,100)
.options()
.let { optionBuilder ->
optionBuilder.option_playerl("Hello again.")
.branch { player ->
return@branch if (getAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, false)) { 1 } else { 0 }
}.let { branch ->
branch.onValue(1)
.npcl(FacialExpression.OLD_NORMAL, "Hey yous creature...yous did good fings gedin that glug-glugs for da sickies! All is ogries pepels are not gettin dead cos of you.")
.end()
branch.onValue(0)
.npcl(FacialExpression.OLD_NORMAL, "Hey yous creature...yous still here?")
.playerl("Yeah, I'm going to help Grish by figuring out what went on here.")
.npcl(FacialExpression.OLD_NORMAL, "If yous finds somefin for da sickies, yous brings to me...and I's give you bright pretties, den me make more for alls pepels.")
.playerl("Hmm, ok. I'll try to bear that in mind.")
.end()
}
optionBuilder.option_playerl("What are you selling?")
.branch { player ->
return@branch if (getAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, false)) { 1 } else { 0 }
}.let { branch ->
branch.onValue(1)
.npcl(FacialExpression.OLD_NORMAL, "Me's showin' you da stufsies for yous creatures!")
.endWith { _, player ->
openNpcShop(player, npc!!.id)
}
branch.onValue(0)
.npcl(FacialExpression.OLD_NORMAL, "Me's not got no glug-glugs to sell, yous bring me da sickies glug-glug den me's open da stufsies for ya.")
.end()
}
optionBuilder.option_playerl("Ok, thanks.")
.end()
}
}
}
@@ -0,0 +1,290 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.game.node.item.Item
import org.rs09.consts.Items
class ZavisticRarveDialogueFile : DialogueBuilderFile() {
companion object {
private fun hasEvidences(player: Player): Int {
var count = 0
if (inInventory(player, Items.NECROMANCY_BOOK_4837)) { count++ }
if (inInventory(player, Items.BOOK_OF_HAM_4829)) { count++ }
if (inInventory(player, Items.DRAGON_INN_TANKARD_4811)) { count++ }
if (inInventory(player, Items.SIGNED_PORTRAIT_4816)) { count++ }
return count
}
fun dialogueBlackPrismAndTornPage(builder: DialogueBuilder): DialogueBuilder {
return builder
.playerl("There's some undead ogre activity over at Jiggig, I've found some clues, I wondered if you'd have a look at them.")
.manualStage() { df, player, _, _ ->
sendDoubleItemDialogue(player, Items.BLACK_PRISM_4808, Items.TORN_PAGE_4809, "You show the prism and the necromantic half page to the aged wizard.")
}
.npcl("Hmmm, now this is interesting! Where did you get these from?")
.playerl("I got them from a nearby Ogre tomb, it's recently been infested with zombie ogres and I'm trying to work out what happened there.")
.npcl("This is very troubling @name, very troubling indeed. While it's permitted for learned members of our order to research the 'dark arts', it's absolutely forbidden to make use of such magic.")
.playerl("Do you have any leads on people that I might talk to regarding this?")
.npcl("Well a wizard by the name of 'Sithik Ints' was doing some research in this area. He may know something about it. He's lodged at that guest house to the North, though he's ill and isn't able to leave his room.")
.npcl("Why not go and talk to him, poke around a bit and see if anything comes up. Let me know how you get on. However, I doubt that 'Sithik' had anything to do with it.")
.npcl("Hmm, that black prism seems to have some magical protection. Once you've finished with this item, bring it back to me would you. I may have a reward for you.")
}
fun dialogueGoodPortrait(builder: DialogueBuilder): DialogueBuilder {
return builder
.playerl("Look, I made a portrait of Sithik.")
.iteml(Items.SITHIK_PORTRAIT_4814, "You show the portrait of Sithik to Zavistic.")
.npcl("Hmm, great...but I already know what he looks like!")
}
fun dialogueBadPortrait(builder: DialogueBuilder): DialogueBuilder {
return builder
.playerl("Look, I made a portrait of Sithik.")
.iteml(Items.SITHIK_PORTRAIT_4815, "You show the sketch...")
.npcl("Who the demonikin is that? Is it meant to be a portrait of Sithik, it doesn't look anything like him!")
}
// Too lazy to do this, but this gets mentioned whenever you've shown him one of the evidence (but not all).
fun dialogueSeenEvidenceBefore(builder: DialogueBuilder): DialogueBuilder {
return builder
.npcl("Yeah, you've shown me this before...if this is all the evidence you have?")
.playerl("Please just look at it again...")
.npcl("Ok, let me look then.")
}
}
override fun create(b: DialogueBuilder) {
b.onQuestStages(ZogreFleshEaters.questName, 2)
.let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.dialogueInitialTalk(it) }
.branch { player ->
return@branch if (inInventory(player, Items.BLACK_PRISM_4808) && inInventory(player, Items.TORN_PAGE_4809) ) {
3
} else if (inInventory(player, Items.BLACK_PRISM_4808) ) {
2
} else if (inInventory(player, Items.TORN_PAGE_4809) ) {
1
} else {
0
}
}.let { branch ->
branch.onValue(3)
.let{ dialogueBlackPrismAndTornPage(it) }
.endWith { _, player ->
if(getQuestStage(player, ZogreFleshEaters.questName) == 2) {
setQuestStage(player, ZogreFleshEaters.questName, 3)
}
}
branch.onValue(2)
.playerl("There's some undead ogre activity over at 'Jiggig', and the ogres have asked me to look into it. I think I've found a clue and I wonder if you could take a look at it for me?")
.iteml(Items.BLACK_PRISM_4808, "You show the black prism to the aged wizard.")
.npcl("Hmmm, well this is an uncommon spell component. On its own it's useless, but with certain necromantic spells it can be very powerful. Did you find anything else there?")
.branch { player ->
return@branch if (inInventory(player, Items.DRAGON_INN_TANKARD_4811)) { 1 } else { 0 }
}.let { branch2 ->
val returnJoin = b.placeholder()
branch2.onValue(0)
.goto(returnJoin)
branch2.onValue(1)
.iteml(Items.DRAGON_INN_TANKARD_4811, "You show the tankard to Zavistic.")
.playerl("Well, I found this...")
.npcl("Hmmm, no, that's not really associated with this to be honest. Did you find anything else there?")
.goto(returnJoin)
return@let returnJoin.builder()
}
.playerl("Not really.")
.npcl("I don't know what to say then, there isn't enough to go on with the clues you've shown me so far. I'd suggest going back to search a bit more, but you may just be wasting your time?")
.npcl("Hmm, but this prism does seem to have some magical protection. Once you've finished with this item, bring it back to me would you? I may have a reward for you!")
.playerl("Sure...I mean, I'll try if I remember.")
.end()
branch.onValue(1)
.playerl("There's some undead ogre activity over at Jiggig, I've found a clue that you may be able to help with.")
.iteml(Items.TORN_PAGE_4809, "You show the necromantic half page to the aged wizard.")
.npcl("Hmm, this is a half torn spell page, it requires another spell component to be effective. Did you find anything else there?")
.branch { player ->
return@branch if (inInventory(player, Items.DRAGON_INN_TANKARD_4811)) { 1 } else { 0 }
}.let { branch2 ->
val returnJoin = b.placeholder()
branch2.onValue(0)
.goto(returnJoin)
branch2.onValue(1)
.iteml(Items.DRAGON_INN_TANKARD_4811, "You show the tankard to Zavistic.")
.playerl("Well, I found this...")
.npcl("Hmmm, no, that's not really associated with this to be honest. Did you find anything else there?")
.goto(returnJoin)
return@let returnJoin.builder()
}
.playerl("Not really.")
.npcl("I don't know what to say then, there isn't enough to go on with the clues you've shown me so far. I'd suggest going back to search a bit more, but you may just be wasting your time?")
.end()
branch.onValue(0)
.let { builder ->
content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.defaultTalk(builder)
}
}
b.onQuestStages(ZogreFleshEaters.questName, 3,4)
.let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.dialogueInitialTalk(it) }
.let { builder ->
val returnJoin = b.placeholder()
builder.goto(returnJoin)
return@let returnJoin.builder().options()
.let { optionBuilder ->
val continuePath = b.placeholder()
optionBuilder.option("What did you say I should do?")
.playerl("What did you say I should do?")
.npcl("You should go and have a chat with Sithik Ints, he's in that house just to the north. He's a lodger and has a room upstairs. Just tell him that I sent you to see him. He should be fine once you've mentioned my name.")
.goto(returnJoin)
optionBuilder.option_playerl("Where is Sithik?")
.npcl("He's in that house just to the north, less than a few seconds walk away. He's a lodger and has a room upstairs...he's not very well though.")
.goto(returnJoin)
optionBuilder.optionIf("I have an item that I'd like you to look at.") { player -> return@optionIf hasEvidences(player) == 1 }
.goto(continuePath)
optionBuilder.optionIf("I have an item that I'd like you to look at.") { player -> return@optionIf hasEvidences(player) > 1 }
.goto(continuePath)
optionBuilder.option("I want to ask about the magic guild")
.let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.defaultTalk(it) }
optionBuilder.option_playerl("Sorry, I have to go.")
.end()
return@let continuePath.builder()
}
}
.branch { player ->
return@branch if (inInventory(player, Items.NECROMANCY_BOOK_4837) ) { 1 } else { 0 }
}.let { branch ->
val continuePath = b.placeholder()
branch.onValue(1)
.iteml(Items.NECROMANCY_BOOK_4837, "You show the Necromancy book to Zavistic.")
.playerl("I have this necromancy book as evidence that Sithik is involved with the undead ogres at Jiggig.")
.npcl("Ok, so he's researching necromancy...it doesn't mean anything in itself.")
.playerl("Yes, but if you look, you can see that there is a half torn page which matches the page I found at Jiggig.")
.npcl("Hmm, yes, but someone could have stolen that from him and then gone and cast it without his permission or to try and deliberately implicate him.")
.goto(continuePath)
branch.onValue(0)
.goto(continuePath)
return@let continuePath.builder()
}
.branch { player ->
return@branch if (inInventory(player, Items.BOOK_OF_HAM_4829) ) { 1 } else { 0 }
}.let { branch ->
val continuePath = b.placeholder()
branch.onValue(1)
.iteml(Items.BOOK_OF_HAM_4829, "You show the HAM book to Zavistic.")
.playerl("Look, this book proves that Sithik hates all monsters and most likely Ogres with a passion.")
.npcl("So what, hating monsters isn't a crime in itself...although I suppose that it does give a motive if Sithik was involved. On its own, it's not enough evidence though.")
.goto(continuePath)
branch.onValue(0)
.goto(continuePath)
return@let continuePath.builder()
}
.branch { player ->
return@branch if (inInventory(player, Items.DRAGON_INN_TANKARD_4811) ) { 1 } else { 0 }
}.let { branch ->
val continuePath = b.placeholder()
branch.onValue(1)
.iteml(Items.DRAGON_INN_TANKARD_4811, "You show the dragon Inn Tankard to Zavistic.")
.playerl("This is the tankard I found on the remains of Brentle Vahn!")
.npcl("That doesn't mean anything in itself, you could have gotten that from anywhere. Even from the Dragon Inn tavern! There isn't anything to link Brentle Vahn with Sithik Ints.")
.goto(continuePath)
branch.onValue(0)
.goto(continuePath)
return@let continuePath.builder()
}
.branch { player ->
return@branch if (inInventory(player, Items.SIGNED_PORTRAIT_4816) ) { 1 } else { 0 }
}.let { branch ->
val continuePath = b.placeholder()
branch.onValue(1)
.iteml(Items.SIGNED_PORTRAIT_4816, "You show the signed portrait of Sithik to Zavistic.")
.playerl("This is a portrait of Sithik, signed by the landlord of the Dragon Inn saying that he saw Sithik and Brentle Vahn together.")
.npcl("Hmmm, well that is interesting.")
.goto(continuePath)
branch.onValue(0)
.goto(continuePath)
return@let continuePath.builder()
}
.branch { player ->
return@branch if (hasEvidences(player) == 4) { 1 } else { 0 }
}.let { branch ->
branch.onValue(0)
.npcl("However, there isn't enough evidence for me to take the issue further at this point. If you find any further evidence bring it to me.")
.end()
return@let branch
}
.onValue(1)
.npcl("And I'm starting to think that Sithik may be involved. Here, take this potion and give some to Sithik. It'll bring on a change which should solicit some answers - tell him the effects won't revert until he's told the truth.")
.iteml(Items.STRANGE_POTION_4836 ,"Zavistic hands you a strange looking potion bottle and takes all the evidence you've accumulated so far.")
.endWith { _, player ->
if(getQuestStage(player, ZogreFleshEaters.questName) in 3..4) {
if (removeItem(player, Items.NECROMANCY_BOOK_4837) &&
removeItem(player, Items.BOOK_OF_HAM_4829) &&
removeItem(player, Items.DRAGON_INN_TANKARD_4811) &&
removeItem(player, Items.SIGNED_PORTRAIT_4816)) {
addItemOrDrop(player, Items.STRANGE_POTION_4836)
}
setQuestStage(player, ZogreFleshEaters.questName, 5)
}
}
b.onQuestStages(ZogreFleshEaters.questName, 5)
.let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.dialogueInitialTalk(it) }
.npcl("Have you used that potion yet?")
.branch { player ->
return@branch if (inInventory(player, Items.STRANGE_POTION_4836) ) { 1 } else { 0 }
}.let { branch ->
branch.onValue(1)
.playerl("No, not yet, what was I supposed to do again?")
.npcl("Try to use the potion on Sithik somehow, he should undergo an interesting transformation, though you'll probably want to leave the house in case there are any side effects. Then go back and question Sithik and tell")
.npcl("him the effects won't wear off until he tells the truth. In fact, that's not exactly true, but I'm sure it'll be an extra incentive to get him to be honest.")
.let { builder ->
content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.defaultTalk(builder)
}
branch.onValue(0)
.playerl("Well, actually, I've lost it, could I have another one please?")
.npcl("Sure, but don't lose it this time.")
.iteml(Items.STRANGE_POTION_4836 ,"Zavistic hands you a bottle of strange potion.")
.endWith { _, player ->
addItemOrDrop(player, Items.STRANGE_POTION_4836)
}
}
b.onQuestStages(ZogreFleshEaters.questName, 6,7,8,9)
.let { content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.dialogueInitialTalk(it) }
.npcl("Don't you worry about Sithik, he's not likely to be moving from his bed for a long time. When he eventually does get better, he's going to be sent before a disciplinary tribunal, then we'll sort out what's what.")
.playerl("Thanks for your help with all of this.")
.npcl("Ooohh, no thanks required. It's I who should be thanking you my friend...your investigative mind has shown how vigilant we really should be for this type of evil use of the magical arts.")
.let { builder ->
content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile.defaultTalk(builder)
}
}
}
/** Dialogues when you use stuff on him. */
class ZavisticRarveUseItemsDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() {
override fun create(b: DialogueBuilder) {
// SITHIK_PORTRAIT_4814
b.onPredicate { _ -> dialogueNum == 3 }
.let{ZavisticRarveDialogueFile.dialogueGoodPortrait(it)}
.end()
// SITHIK_PORTRAIT_4815
b.onPredicate { _ -> dialogueNum == 4 }
.let{ZavisticRarveDialogueFile.dialogueBadPortrait(it)}
.end()
// SIGNED_PORTRAIT_4816
b.onPredicate { _ -> dialogueNum == 5 }
// That would continue the conversation as above if you normally talk to him.
.end()
}
}
@@ -0,0 +1,47 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.getOrStartTimer
import core.api.inEquipment
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.player.Player
import core.game.system.timer.impl.Disease
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class ZogreBehavior : NPCBehavior(*zogreIds) {
companion object {
private val zogreIds = intArrayOf(
NPCs.ZOGRE_2044,
NPCs.ZOGRE_2045,
NPCs.ZOGRE_2046,
NPCs.ZOGRE_2047,
NPCs.ZOGRE_2048,
NPCs.ZOGRE_2049,
NPCs.ZOGRE_2051,
NPCs.ZOGRE_2052,
NPCs.ZOGRE_2053,
NPCs.ZOGRE_2054,
NPCs.ZOGRE_2055,
)
}
override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) {
if (attacker is Player) {
if (inEquipment(attacker, Items.COMP_OGRE_BOW_4827)) {
return
}
state.estimatedHit = (state.estimatedHit * 0.25).toInt()
if (state.secondaryHit > 0) {
state.secondaryHit = (state.secondaryHit * 0.25).toInt()
}
}
}
override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) {
val disease = getOrStartTimer<Disease>(victim, 10)
disease.hitsLeft = 10
}
}
@@ -0,0 +1,353 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import content.data.Quests
import core.api.*
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
/**
* Zogre Flesh Eaters Quest
*
* 1 - Talked to Grish
* 2 - Smashed Barricade
* 2 Cont' - Collected Stuff Underground
* A - Black Prism from Coffin
* B - Half Torn Page from Broken Lecturn
* C - Tankard from Backpack (Kill the Zombie which turns out to be Brentle Vahn)
* 3 - Talked to Zavistic Rarve with A & B only, points to where Sithik Ints is
* 4 - Talked to Sithik and challenged to incriminate him
* 4 Cont' - Collected Evidence
* A - Tankard from 2C after talking to Innkeeper
* B - Portrait of Sithik using papyrus and charcoal with questionable drawing skills
* C - Book of HAM philosophy from drawer
* D - Necromantic book
* 5 - Incriminate Sithik to Zavistic Rarve and given potion
* 6 - Turned Sithik into an Ogre with potion
* 7 - Talked to Grish
* 8 - Get Key from Grish
* 9 - Killed Slash Bash
* 100 - Returned to Grish with Ogre Artifact
*
* This quest journal is the worst; there's typos, and it is out of order.
*
* if (VARPBIT[487] > 12) return 2; if (VARPBIT[487 == 0) return 0; return 1; };
* define_varbit 487 455 0 4
*
*/
@Initializable
class ZogreFleshEaters : Quest(Quests.ZOGRE_FLESH_EATERS, 40, 39, 1, 455, 0, 1, 13) {
companion object {
val questName = Quests.ZOGRE_FLESH_EATERS
const val varbitGateBashed = 496
const val varbitOgreCoffin = 488
const val varbitSithikOgre = 495
const val attributeAskedAboutSickies = "quest:zogreflesheaters-askedaboutsickies"
// 2A
const val attributeSearchedCoffin = "/save:quest:zogreflesheaters-searchedcoffin"
const val attributeBrokeLockCoffin = "/save:quest:zogreflesheaters-brokelockcoffin"
const val attributeOpenedCoffin = "/save:quest:zogreflesheaters-openedcoffin" // You can fail apparently...
const val attributeFoundBlackPrism = "/save:quest:zogreflesheaters-foundblackprism"
// 2B
const val attributeFoundHalfTornPage = "/save:quest:zogreflesheaters-foundhalftornpage"
// 2C
const val attributeFoughtZombie = "/save:quest:zogreflesheaters-foughtzombie"
const val attributeFoundTankard = "/save:quest:zogreflesheaters-foundtankard"
// 4A
const val attributeAskedAboutTankard = "quest:zogreflesheaters-askedabouttankard"
// 4B
const val attributeMadePortrait = "/save:quest:zogreflesheaters-madeportrait"
// 4C
const val attributeFoundHamBook = "/save:quest:zogreflesheaters-foundhambook"
// 4D
const val attributeFoundNecromanticBook = "/save:quest:zogreflesheaters-foundnecromanticbook"
const val attributeSlashBashInstance = "/save:quest:zogreflesheaters-slashbashinstance"
// Open Uglug Nar Shop with Relicym balm
const val attributeOpenUglugNarShop = "/save:quest:zogreflesheaters-openuglugnarshop"
fun requirements(player: Player): Boolean {
return arrayOf(
hasLevelStat(player, Skills.RANGE, 30),
hasLevelStat(player, Skills.SMITHING, 4),
hasLevelStat(player, Skills.HERBLORE, 8),
isQuestComplete(player, Quests.JUNGLE_POTION),
isQuestComplete(player, Quests.BIG_CHOMPY_BIRD_HUNTING),
).all { it }
}
}
override fun drawJournal(player: Player, stage: Int) {
super.drawJournal(player, stage)
var line = 11
var stage = getStage(player)
var started = getQuestStage(player, questName) > 0
if (!started) {
line(player, "I can !!start?? this quest by talking to !!Grish?? at the Ogrish", line++, false)
line(player, "ceremonial dance place called !!Jiggig??.", line++, false)
line(player, "To start this !!quest?? I should complete these quests:-", line++, false)
line(player, "!!Jungle Potion.??", line++, isQuestComplete(player, Quests.JUNGLE_POTION))
line(player, "!!Big Chompy Bird Hunting.??", line++, isQuestComplete(player, Quests.BIG_CHOMPY_BIRD_HUNTING))
line(player, "It would help if I had the following skills levels:-", line++, false)
line(player, "!!Ranged level : 30??", line++, hasLevelStat(player, Skills.RANGE, 30))
line(player, "!!Fletching level : 30??", line++, hasLevelStat(player, Skills.FLETCHING, 30))
line(player, "!!Smithing level : 4??", line++, hasLevelStat(player, Skills.SMITHING, 4))
line(player, "!!Herblore level : 8??", line++, hasLevelStat(player, Skills.HERBLORE, 8))
line(player, "Must be able to defeat a !!level 111?? foe.", line++, false)
} else if (stage < 100) {
line(player, "I started this quest by talking to Grish, he asked me to", line++, true)
line(player, "check out the underground area where some Zombie ogres", line++, true)
line(player, "(Zogres) were coming from.", line++, true)
if (stage >= 2) {
line(player, "I have to find a way into the ceremonial dance area and", line++, true)
line(player, "then underground.", line++, true)
line(player, "I persuaded a guard to let me past, I only had to mention", line++, true)
line(player, "Grish's name and the guard smashed the barricade down. I", line++, true)
line(player, "can enter now.", line++, true)
} else if (stage >= 1) {
line(player, "I have to find a way into the ceremonial dance area and", line++, false)
line(player, "then underground.", line++, false)
}
if (stage >= 2) {
// Set 2A (Stays)
if (getAttribute(player, attributeFoundBlackPrism, false) || stage >= 3) {
line(player, "I have searched a coffin, it had a funny looking hole at the", line++, true)
line(player, "side.", line++, true)
line(player, "I have forced the lock on a coffin, maybe I can open it", line++, true)
line(player, "now?", line++, true)
line(player, "I've !!opened?? the !!coffin?? and retrieved a !!black prism??, this", line++, stage >= 3)
line(player, "may be useful.", line++, stage >= 3)
} else if (getAttribute(player, attributeOpenedCoffin, false)) {
line(player, "I have searched a coffin, it had a funny looking hole at the", line++, true)
line(player, "side.", line++, true)
line(player, "I have forced the lock on a coffin, maybe I can open it", line++, true)
line(player, "now?", line++, true)
line(player, "I've !!opened?? the !!coffin??, maybe there's something in it.", line++, false)
} else if (getAttribute(player, attributeBrokeLockCoffin, false)) {
line(player, "I have searched a coffin, it had a funny looking hole at the", line++, true)
line(player, "side.", line++, true)
line(player, "I have forced the lock on a !!coffin??, maybe I can open it", line++, false)
line(player, "now?", line++, false)
} else if (getAttribute(player, attributeSearchedCoffin, false)) {
line(player, "I have searched a coffin, it had a funny looking hole at the", line++, true)
line(player, "side.", line++, true)
}
}
if (stage >= 2) {
// Set 2B (Stays)
if (getAttribute(player, attributeFoundHalfTornPage, false) || stage >= 3) {
line(player, "I found a !!half torn page?? from a !!necromatic spellbook??,", line++, stage >= 3)
line(player, "maybe this is a !!clue???", line++, stage >= 3)
}
}
// 4 - This is the weirdest shit that is out of place. (Stays) This appears after talking to Sithik Int.
if (stage >= 4) {
line(player, "I have shown the prism and torn page to the grand", line++, true)
line(player, "secretary of the wizards guild.", line++, true)
}
// Set 2C (Does not stay)
if (stage in 2..4 && getAttribute(player, attributeFoundTankard, false)) {
line(player, "I killed a !!human zombie?? which dropped a !!backpack??. The", line++, stage >= 3)
line(player, "!!backpack?? had the name !!'B. Vahn'?? on it, inside the !!backpack??", line++, stage >= 3)
line(player, "I found a !!tankard??.", line++, stage >= 3)
} else if (stage in 2..4 && getAttribute(player, attributeFoughtZombie, false)) {
line(player, "I killed a !!human zombie?? which dropped a !!backpack??.", line++, stage >= 3)
}
// Stays until you find all the 3X stuff above.
if (stage in 2..4 && !(getAttribute(player, attributeFoundBlackPrism, false) &&
getAttribute(player, attributeFoundHalfTornPage, false) &&
getAttribute(player, attributeFoundTankard, false))) {
line(player, "I need to find out what happened here.", line++, false) // Cleared when the 3 sets above are done.
}
// Set 4A (Does not stay)
if (stage in 2..4 && getAttribute(player, attributeAskedAboutTankard, false)) {
line(player, "The 'Dragon Inn' !!Innkeeper?? says the tankard belongs to", line++, false)
line(player, "one of his locals called !!Brentle Vahn??. He was seen talking", line++, false)
line(player, "to a !!wizard?? the other day.", line++, false) // Cleared after handed in with the rest
}
// 3 Zavistic Rarve seen prism and page - lines disappears right after...
if (stage == 3) {
line(player, "I have shown the !!prism?? and the !!necromantic page?? to", line++, false)
line(player, "Zavistic Rarve. He's told me about a !!wizard?? named", line++, false)
line(player, "!!Sithik Ints?? who might have some information.", line++, false)
}
// 4 Spoken with Sithik
if (stage >= 4) {
line(player, "I've spoken to !!Sithik??, I need to see if he was !!involved??", line++, stage >= 5)
line(player, "with the !!Undead Ogres at 'Jiggig'?? in some way.", line++, stage >= 5)
}
// Only stays for 4
if (stage == 4) {
if (getAttribute(player, attributeMadePortrait, false)) {
line(player, "I've made a !!portrait?? of !!Sithik??...not sure what this will do?", line++, false)
}
if (getAttribute(player, attributeFoundHamBook, false)) {
line(player, "I've found a !!book?? on !!HAM philosophy??...what does this prove?", line++, false)
}
if (getAttribute(player, attributeFoundNecromanticBook, false)) {
line(player, "I've found a !!necromantic book??...what does this prove?", line++, false)
}
}
// 4 - Who the hell knows why this is here. (Stays) This appears after getting the potion.
if (stage >= 5) {
line(player, "I've talked to Zavistic Rarve regarding the prism and the", line++, true)
line(player, "torn page, he gave some information on a student called", line++, true)
line(player, "Sithik Ints, he may know more about what's happening", line++, true)
line(player, "here.", line++, true)
}
// Beyond this is legit
if (stage >= 5) {
line(player, "Zavistic has given me some sort of !!potion??, apparently I", line++, stage >= 6)
line(player, "need to give it to !!Sithik??.", line++, stage >= 6)
}
if (stage >= 7) {
line(player, "I came back into Sithik's room to find that he had been", line++, true)
line(player, "turned into an Ogre!", line++, true)
} else if (stage >= 6) {
line(player, "I have put some of the !!potion?? into !!Sithik's tea??, the !!potion??", line++, false)
line(player, "will take some time to act. Perhaps I should !!get out of??", line++, false)
line(player, "!!here?? in case there are any !!side effects???", line++, false)
}
if (stage >= 8) {
line(player, "Sithik has told me how to make 'brutal arrows', which", line++, true)
line(player, "should be more effective against Zogres.", line++, true)
line(player, "Sithik has given me some pointers on how I can make a", line++, true)
line(player, "cure disease potion, though I'm still not sure exactly which", line++, true)
line(player, "herbs I should use.", line++, true)
} else if (stage >= 7) {
line(player, "!!Sithik?? has told me that there is no way I can remove the", line++, false)
line(player, "effects of the !!necromantic curse spell?? from the !!Jiggig??", line++, false)
line(player, "area. I'll have to go back and let !!Grish?? know.", line++, false)
line(player, "!!Sithik?? has told me how to make !!'brutal arrows'??, which", line++, false)
line(player, "should be more !!effective?? against !!Zogres??.", line++, false)
line(player, "!!Sithik?? has given me some pointers on how I can make a", line++, false)
line(player, "!!cure disease potion??, though I'm still not sure exactly which", line++, false)
line(player, "!!herbs?? I should use.", line++, false)
}
if (stage >= 9) {
line(player, "I've told Grish to relocated the dance area, but he needs", line++, true)
line(player, "me to get something from the tomb to so that he can do", line++, true) // "tomb to so" is authentic [sic]
line(player, "this.", line++, true)
line(player, "I need to go back into the tomb and look for some 'old'", line++, true)
line(player, "items that Grish has asked for.", line++, true)
line(player, "I should return the !!artifact?? to !!Grish??.", line++, false)
} else if (stage >= 8) {
line(player, "I've told Grish to relocated the dance area, but he needs", line++, true)
line(player, "me to get something from the tomb to so that he can do", line++, true) // "tomb to so" is authentic [sic]
line(player, "this.", line++, true)
line(player, "I need to go back into the !!tomb?? and look for some !!'old'??", line++, false)
line(player, "!!items?? that !!Grish?? has asked for.", line++, false)
}
} else {
// The ending is COMPLETELY replaced from this entire shitshow of a quest log.
line(player, "I talked to Grish in the Jiggig area which is swarming with", line++, true)
line(player, "Zombie Ogres (Zogres) These disgusting creatures carry", line++, true)
line(player, "disease and are quite dangerous so the Ogres weren't", line++, true)
line(player, "too keen to try and sort them out.", line++, true)
line(player, "I talked to an ogre called Grish who asked me to look into", line++, true)
line(player, "the problem. After some searching around in a tomb, I", line++, true)
line(player, "found some clues which pointed me to the human", line++, true)
line(player, "habitation of Yannile.", line++, true)
line(player, "With the help of Zavistic Rarve, the grand secretary of", line++, true)
line(player, "the Wizards guild I was able to piece the clues together", line++, true)
line(player, "and discover that a Wizard named 'Sithik Ints' was", line++, true)
line(player, "responsible.", line++, true)
line(player, "Unfortunately I couldn't remove the curse from the area,", line++, true)
line(player, "however, I was able to return some important artefacts to", line++, true)
line(player, "Grish, who can now set up a new ceremonial dance area for", line++, true)
line(player, "the ogres of Gu' Tanoth.", line++, true)
line(player, "Sithik Ints also told me how to make Brutal arrows which are", line++, true)
line(player, "more effective against Zogres, and he also told me how to", line++, true)
line(player, "make a disease balm.", line++, true)
line++
line(player,"<col=FF0000>QUEST COMPLETE!</col>", line)
}
}
override fun reset(player: Player) {
setVarp(player, varbitGateBashed, 0, true)
removeAttribute(player, attributeAskedAboutSickies)
removeAttribute(player, attributeSearchedCoffin)
removeAttribute(player, attributeBrokeLockCoffin)
removeAttribute(player, attributeOpenedCoffin)
removeAttribute(player, attributeFoundBlackPrism)
removeAttribute(player, attributeFoundHalfTornPage)
removeAttribute(player, attributeFoughtZombie)
removeAttribute(player, attributeFoundTankard)
removeAttribute(player, attributeAskedAboutTankard)
removeAttribute(player, attributeMadePortrait)
removeAttribute(player, attributeFoundHamBook)
removeAttribute(player, attributeFoundNecromanticBook)
removeAttribute(player, attributeOpenUglugNarShop)
}
override fun finish(player: Player) {
var ln = 10
super.finish(player)
player.packetDispatch.sendString("You have completed Zogre Flesh Eaters!", 277, 4)
player.packetDispatch.sendItemZoomOnInterface(Items.OGRE_ARTEFACT_4818, 240, 277, 5)
drawReward(player,"1 Quest Point.", ln++)
drawReward(player,"Can now make Brutal Arrows", ln++)
drawReward(player,"and cure disease potions.", ln++)
drawReward(player,"2000 Ranged, Fletching and", ln++)
drawReward(player,"Herblore XP", ln++)
player.skills.addExperience(Skills.RANGE, 2000.0)
player.skills.addExperience(Skills.FLETCHING, 2000.0)
player.skills.addExperience(Skills.HERBLORE, 2000.0)
}
override fun setStage(player: Player, stage: Int) {
super.setStage(player, stage)
this.updateVarps(player)
}
override fun updateVarps(player: Player) {
if(getQuestStage(player, questName) >= 2) {
setVarbit(player, varbitGateBashed, 1, true)
} else {
setVarbit(player, varbitGateBashed, 0, true)
}
if(getQuestStage(player, questName) >= 7) {
setVarbit(player, varbitSithikOgre, 1, true)
} else {
setVarbit(player, varbitSithikOgre, 0, true)
}
}
override fun newInstance(`object`: Any?): Quest {
return this
}
}
@@ -0,0 +1,382 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.global.action.DoorActionHandler
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.game.world.map.Direction
import core.game.world.map.Location
import core.tools.END_DIALOGUE
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
class ZogreFleshEatersListeners : InteractionListener {
companion object {
@JvmStatic
fun ladderMakesSithikTurnIntoOgre(player: Player) {
if(getQuestStage(player, ZogreFleshEaters.questName) == 6) {
setQuestStage(player, ZogreFleshEaters.questName, 7)
setVarbit(player, ZogreFleshEaters.varbitSithikOgre, 1)
}
}
}
override fun defineListeners() {
// Stairs and doors
on(Scenery.STAIRS_6841, SCENERY, "climb-down") { player, node ->
sendMessage(player, "You climb down the steps.")
if (node.location == Location(2443, 9417, 2)) {
teleport(player, Location(2442, 9417, 0))
} else {
teleport(player, Location(2477, 9437, 2))
}
return@on true
}
on(Scenery.STAIRS_6842, SCENERY, "climb-up") { player, node ->
sendMessage(player, "You climb up the steps.")
if (node.location == Location(2443, 9417, 0)) {
teleport(player, Location(2447, 9417, 2))
} else {
teleport(player, Location(2485, 3045, 0))
}
return@on true
}
on(Scenery.OGRE_STONE_DOOR_6871, SCENERY, "open") { player, node ->
if (getQuestStage(player, ZogreFleshEaters.questName) >= 9) {
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
} else if (inInventory(player, Items.OGRE_GATE_KEY_4839)) {
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
sendMessage(player, "You use the Ogre Tomb Key to unlock the door.")
} else {
sendMessage(player, "The door is locked.")
}
return@on true
}
on(Scenery.OGRE_STONE_DOOR_6872, SCENERY, "open") { player, node ->
if (getQuestStage(player, ZogreFleshEaters.questName) >= 9) {
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
} else if (inInventory(player, Items.OGRE_GATE_KEY_4839)) {
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
sendMessage(player, "You use the Ogre Tomb Key to unlock the door.")
} else {
sendMessage(player, "The door is locked.")
}
return@on true
}
// Stage 2
on(Scenery.CRUSHED_BARRICADE_6881, SCENERY, "climb-over") { player, node ->
if (player.location.x < 2456) {
val distance = player.location.getDistance(Location(2457, 3049, 0)).toInt()
forceMove(player, player.location, Location(2457, 3049, 0), 0, distance * 15, null, 1236)
} else {
val distance = player.location.getDistance(Location(2455, 3049, 0)).toInt()
forceMove(player, player.location, Location(2455, 3049, 0), 0, distance * 15, null, 1236)
}
return@on true
}
on(Scenery.CRUSHED_BARRICADE_6882, SCENERY, "climb-over") { player, node ->
if (player.location.x < 2456) {
val distance = player.location.getDistance(Location(2457, 3048, 0)).toInt()
forceMove(player, player.location, Location(2457, 3048, 0), 0, distance * 15, null, 1236)
} else {
val distance = player.location.getDistance(Location(2455, 3048, 0)).toInt()
forceMove(player, player.location, Location(2455, 3048, 0), 0, distance * 15, null, 1236)
}
return@on true
}
// Stage 2A
on(Scenery.OGRE_COFFIN_6844, SCENERY, "search") { player, node ->
if (getVarbit(player, ZogreFleshEaters.varbitOgreCoffin) == 0) {
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendDialogueLines(player, "You search the coffin and find a small geometrically shaped hole in", "the side. It looks as if this hole was made with a considerable amount", "of force, maybe the thing which made the hole is still inside?").also { stage++ }
1 -> sendDialogueLines(player, "The lock looks quite crude, with some skill and a slender blade, you", "may be able to force it.").also { stage = END_DIALOGUE }
}
}
})
} else if (getVarbit(player, ZogreFleshEaters.varbitOgreCoffin) == 1) {
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendDialogueLines(player, "The lid looks heavy, but now that you've unlocked it, you may be", "able to lift it. You prepare yourself.").also { stage++ }
1 -> playerl("Urrrgggg.").also { sendChat(player, "Urrrgggg."); stage++ }
2 -> playerl("Aarrrgghhh!").also { sendChat(player, "Aarrrgghhh!"); stage++ }
// Supposed to have a failure state here.
3 -> playerl("Raarrrggggg! Yes!").also { sendChat(player, "Raarrrggggg! Yes!"); stage++ }
4 -> sendDialogueLines(player, "You eventually manage to lift the lid.").also {
setVarbit(player, ZogreFleshEaters.varbitOgreCoffin, 3, true)
stage = END_DIALOGUE
}
}
}
})
}
return@on true
}
onUseWith(IntType.SCENERY, Items.KNIFE_946, Scenery.OGRE_COFFIN_6844) { player, _, _ ->
sendItemDialogue(player, Items.KNIFE_946,
"With some skill you manage to slide the blade along the lock edge and click into place the teeth of the primitive mechanism.")
setVarbit(player, ZogreFleshEaters.varbitOgreCoffin, 1, true)
return@onUseWith true
}
on(Scenery.OGRE_COFFIN_6845, SCENERY, "search") { player, node ->
sendItemDialogue(player, Items.BLACK_PRISM_4808,
"You find a creepy looking black prism inside.")
addItemOrDrop(player, Items.BLACK_PRISM_4808)
return@on true
}
on(Items.BLACK_PRISM_4808, ITEM, "look-at") { player, node ->
sendItemDialogue(player, Items.BLACK_PRISM_4808,
"It looks like a smokey black gem of some sort...very creepy. Some magical force must have prevented it from being shattered when it hit the coffin.")
return@on true
}
// Stage 2B
on(Scenery.BROKEN_LECTURN_6846, SCENERY, "search") { player, node ->
sendMessage(player, "You search the broken down lecturn.")
if (inInventory(player, Items.TORN_PAGE_4809)) {
sendMessage(player, "You find nothing.")
} else {
sendItemDialogue(player, Items.TORN_PAGE_4809,
"You find a half torn page...it has spidery writing all over it.")
addItemOrDrop(player, Items.TORN_PAGE_4809)
}
return@on true
}
on(Items.TORN_PAGE_4809, ITEM, "read") { player, node ->
sendDialogue(player, "You don't manage to understand all of it as there is only a half page here. But it seems the spell was used to place a curse on an area and for all time raise the dead.")
return@on true
}
// Stage 2C
on(Scenery.SKELETON_6893, SCENERY, "search") { player, node ->
if (getQuestStage(player, ZogreFleshEaters.questName) >= 2){
if (getAttribute(player, ZogreFleshEaters.attributeFoughtZombie, false)) {
if (inInventory(player, Items.RUINED_BACKPACK_4810)) {
sendMessage(player, "You find nothing on the corpse.")
} else {
sendMessage(player, "You find another backpack.")
addItemOrDrop(player, Items.RUINED_BACKPACK_4810)
}
} else {
// Zombie time.
sendMessage(player, "Something screams into life right in front of you.")
val npc = NPC(NPCs.ZOMBIE_1826)
npc.isRespawn = false
npc.isWalks = false
npc.location = Location(2442, 9459, 2)
npc.direction = Direction.NORTH
npc.init()
npc.attack(player)
}
} else {
// At no point should this be reached since you need to start the quest anyway.
sendMessage(player, "You find nothing on the corpse.")
}
return@on true
}
on(Items.RUINED_BACKPACK_4810, ITEM, "open") { player, node ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> {
sendItemDialogue(player, Items.RUINED_BACKPACK_4810,
"Just before you open the backpack, you notice a small leather patch with the moniker: 'B.Vahn', on it.").also { stage++ }
sendItemZoomOnInterface(player, 241, 1, Items.RUINED_BACKPACK_4810, 230)
}
1 -> sendItemDialogue(player, Items.DRAGON_INN_TANKARD_4811,
"You find an interesting looking tankard.").also {
setAttribute(player, ZogreFleshEaters.attributeFoundTankard, true)
if(removeItem(player, node)) {
addItem(player, Items.ROTTEN_FOOD_2959)
addItem(player, Items.KNIFE_946)
addItem(player, Items.DRAGON_INN_TANKARD_4811)
}
stage++
}
2 -> sendDoubleItemDialogue(player, Items.KNIFE_946, Items.ROTTEN_FOOD_2959, "You find a knife and some rotten food, the backpack is ripped to shreds.").also {
sendMessage(player, "You find a knife and some rotten food.")
sendMessage(player, "You find an interesting looking tankard.")
stage = END_DIALOGUE
}
}
}
})
return@on true
}
on(Items.DRAGON_INN_TANKARD_4811, ITEM, "look-at") { player, node ->
sendItemDialogue(player, Items.DRAGON_INN_TANKARD_4811,
"A stout ceramic tankard with a Dragon Emblem on the side, the words, 'Ye Olde Dragon Inn' are inscribed in the bottom.")
return@on true
}
// Zavistic Bell, Stage 2,3,4,5,6 and on (Actually should be standalone.
on(Scenery.BELL_6847, SCENERY, "ring") { player, node ->
sendMessage(player, "You ring the bell.")
// TODO: Make Zavistic appear at the bell area.
openDialogue(player, content.region.kandarin.yanille.dialogue.ZavisticRarveDialogueFile(), NPC(NPCs.ZAVISTIC_RARVE_2059))
return@on true
}
// Stage 4A
onUseWith(IntType.NPC, Items.DRAGON_INN_TANKARD_4811, NPCs.BARTENDER_739) { player, used, with ->
openDialogue(player, BartenderDialogueFile(1), with as NPC)
return@onUseWith true
}
onUseWith(IntType.NPC, Items.SITHIK_PORTRAIT_4814, NPCs.BARTENDER_739) { player, used, with ->
// The good portrait
openDialogue(player, BartenderDialogueFile(2), with as NPC)
return@onUseWith true
}
onUseWith(IntType.NPC, Items.SITHIK_PORTRAIT_4815, NPCs.BARTENDER_739) { player, used, with ->
// The bad portrait
openDialogue(player, BartenderDialogueFile(3), with as NPC)
return@onUseWith true
}
on(Items.SIGNED_PORTRAIT_4816, ITEM, "look-at") { player, node ->
sendItemDialogue(player, Items.SIGNED_PORTRAIT_4816,
"You see an image of Sithik with a message underneath 'I, the bartender of the Dragon Inn, do swear that this is a true likeness of the wizzy who was talking to Brentle Vahn, my customer the other day.'")
return@on true
}
onUseWith(IntType.NPC, Items.SITHIK_PORTRAIT_4814, NPCs.ZAVISTIC_RARVE_2059) { player, used, with ->
// The good portrait
openDialogue(player, ZavisticRarveUseItemsDialogueFile(3), with as NPC)
return@onUseWith true
}
onUseWith(IntType.NPC, Items.SITHIK_PORTRAIT_4815, NPCs.ZAVISTIC_RARVE_2059) { player, used, with ->
// The bad portrait
openDialogue(player, ZavisticRarveUseItemsDialogueFile(4), with as NPC)
return@onUseWith true
}
// Stage 4B
on(Items.BOOK_OF_PORTRAITURE_4817, ITEM, "read") { player, node ->
sendDialogueLines(player,
"All interested artisans should really consider taking up the hobby of",
"portraiture. To do so, one uses a piece of papyrus on the intended",
"subject to initiate a likeness drawing activity.")
return@on true
}
// Stage 4C
on(Items.BOOK_OF_HAM_4829, ITEM, "read") { player, node ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> {
sendDialogue(player,
"You read this book for a while, it seems to be some sort of political "+
"manifesto about how the king doesn't do enough to safeguard the "+
"citizens of the realm from the monsters that still thrive within the "+
"borders. ").also { stage++ }
// This is the original, but it is too big for this to handle.
// sendDialogueLines(player,
// "You read this book for a while, it seems to be some sort of political",
// "manifesto about how the king doesn't do enough to safeguard the",
// "citizens of the realm from the monsters that still thrive within the",
// "borders. It sends out a rallying to all people who would want to",
// "stop monsters, to join the HAM movement.").also { stage++ }
}
1 -> sendDialogue(player, "It sends out a rallying to all people who would want to stop monsters, to join the HAM movement.").also { stage++ }
2 -> sendPlayerDialogue(player, "Hmm, Sithik must really hate monsters then, I wonder if he hates ogres in particular?").also {
stage = END_DIALOGUE
}
}
}
})
return@on true
}
// Stage 4D
on(Items.NECROMANCY_BOOK_4837, ITEM, "read") { player, node ->
sendDialogueLines(player,
"This book uses very strange language and some",
"incomprehensible symbols. It has a very dark and evil feeling to",
"it. As you're looking through the book, you notice that",
"one of the pages has been torn and half of it is missing.")
return@on true
}
onUseWith(IntType.ITEM, Items.NECROMANCY_BOOK_4837, Items.TORN_PAGE_4809) { player, _, _ ->
sendDoubleItemDialogue(player, Items.NECROMANCY_BOOK_4837, Items.TORN_PAGE_4809,
"The torn page matches exactly the part where a torn out page is missing from the book. You feel sure that this page came from this book.")
return@onUseWith true
}
// Uglug Nar Shop
onUseWith(IntType.NPC, intArrayOf(Items.RELICYMS_BALM1_4848, Items.RELICYMS_BALM2_4846, Items.RELICYMS_BALM3_4844, Items.RELICYMS_BALM4_4842), NPCs.UGLUG_NAR_2039) { player, used, with ->
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> sendItemDialogue(player, used.id,"You show the potion to Uglug Nar.").also { stage++ }
1 -> playerl("Hey, here you go! I brought you some of the potion which should cure the disease. You said that you would buy some from me.").also {
if (getAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, false)) {
stage = 2
} else {
stage = 3
}
}
2 -> sendNPCDialogue(player, NPCs.UGLUG_NAR_2039, "Yous creatures is da funny ones... yous already solds me's ones now..and us can now sell un to yous!", FacialExpression.OLD_NORMAL).also { stage = END_DIALOGUE }
3 -> sendNPCDialogue(player, NPCs.UGLUG_NAR_2039, "Yous creatures done da good fing...yous get many bright pretties for dis...!", FacialExpression.OLD_NORMAL).also { stage++ }
4 -> sendDoubleItemDialogue(player, Item(Items.COINS_995, 1000), used as Item, "You sell the potion and get 1000 coins in return.").also {
if (removeItem(player, used)) {
addItemOrDrop(player, Items.COINS_995, 1000)
setAttribute(player, ZogreFleshEaters.attributeOpenUglugNarShop, true)
}
stage = END_DIALOGUE
}
}
}
})
return@onUseWith true
}
// Stage 8 to 9
on(Scenery.STAND_6897, SCENERY, "search") { player, node ->
if (getQuestStage(player, ZogreFleshEaters.questName) == 8 &&
getAttribute<NPC?>(player, ZogreFleshEaters.attributeSlashBashInstance, null) == null
) {
// Zombie time.
sendMessage(player, "Something stirs behind you!")
val npc = NPC(NPCs.SLASH_BASH_2060)
setAttribute(player, ZogreFleshEaters.attributeSlashBashInstance, npc)
setAttribute(npc, "target", player)
npc.isRespawn = false
npc.isWalks = false
npc.location = Location(2478, 9446, 0)
npc.direction = Direction.EAST
npc.init()
npc.attack(player)
} else if (getQuestStage(player, ZogreFleshEaters.questName) > 8) {
if (inInventory(player, Items.OGRE_ARTEFACT_4818)) {
sendMessage(player, "You find nothing on the stand.")
} else {
sendMessage(player, "You find another artifact.")
addItemOrDrop(player, Items.OGRE_ARTEFACT_4818)
}
} else {
// At no point should this be reached since you need to start the quest anyway.
sendMessage(player, "You find nothing on the stand.")
}
return@on true
}
}
}
@@ -0,0 +1,109 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.skill.Skills
import core.game.node.item.Item
import org.rs09.consts.Items
import kotlin.math.min
public enum class BrutalArrows(val nailItem: Int, val level: Int, val product: Int, val exp: Double) {
BRONZE_BRUTAL(Items.BRONZE_NAILS_4819, 7, Items.BRONZE_BRUTAL_4773, 8.4),
IRON_BRUTAL(Items.IRON_NAILS_4820, 18, Items.IRON_BRUTAL_4778, 15.6),
STEEL_BRUTAL(Items.STEEL_NAILS_1539, 33, Items.STEEL_BRUTAL_4783, 30.6),
BLACK_BRUTAL(Items.BLACK_NAILS_4821, 38, Items.BLACK_BRUTAL_4788, 39.0),
MITHRIL_BRUTAL(Items.MITHRIL_NAILS_4822, 49, Items.MITHRIL_BRUTAL_4793, 45.0),
ADAMANT_BRUTAL(Items.ADAMANTITE_NAILS_4823, 62, Items.ADAMANT_BRUTAL_4798, 61.2),
RUNE_BRUTAL(Items.RUNE_NAILS_4824, 77, Items.RUNE_BRUTAL_4803, 75.0)
;
companion object {
@JvmField
val nailItemMap = values().associateBy { it.nailItem }
val nailItemArray = nailItemMap.values.map { it.nailItem }.toIntArray()
}
}
/**
* This handles potions and fletching related to zogre flesh eaters.
*
* Relicym's Balm is unique to zogre flesh eaters.
* Maybe move this to herblore when it can handle quest requirements better.
*/
class ZogrePotionAndFletchingListeners : InteractionListener {
override fun defineListeners() {
// ROGUES_PURSE_POTIONUNF_4840 is already in UnfinishedPotion.java
onUseWith(IntType.ITEM, Items.ROGUES_PURSE_POTIONUNF_4840, Items.CLEAN_SNAKE_WEED_1526) { player, used, with ->
if (!hasLevelStat(player, Skills.HERBLORE, 8)) {
sendMessage(player, "You need a herblore level of 8 to make this mix.")
return@onUseWith true
}
if (getQuestStage(player, ZogreFleshEaters.questName) < 7) {
sendMessage(player, "You need to have partially completed Zogre Flesh Eaters to make this mix.")
return@onUseWith true
}
if(removeItem(player, used) && removeItem(player, with)) {
sendMessage(player, "You add the snake weed to the rogues purse solution and make Relicyms Balm.")
addItem(player, Items.RELICYMS_BALM4_4842)
rewardXP(player, Skills.HERBLORE, 40.0)
}
return@onUseWith true
}
// FletchingListeners.kt
// ACHEY_TREE_LOGS_2862 -> UNSTRUNG_COMP_BOW_4825 -> COMP_OGRE_BOW_4827
// Requirement to wield comp ogre bow.
onEquip(Items.COMP_OGRE_BOW_4827) { player, _ ->
if (getQuestStage(player, ZogreFleshEaters.questName) >= 8){
return@onEquip true
}
sendMessage(player, "You need to complete part of Zogre Flesh Eaters to equip this.")
return@onEquip false
}
onUseWith(IntType.ITEM, BrutalArrows.nailItemArray, Items.FLIGHTED_OGRE_ARROW_2865) { player, used, with ->
fun getMaxAmount(_unused: Int = 0): Int {
val tips = amountInInventory(player, used.id)
val shafts = amountInInventory(player, with.id)
return min(tips, shafts)
}
fun process() {
val amountThisIter = min(6, getMaxAmount())
if (removeItem(player, Item(used.id, amountThisIter)) && removeItem(player, Item(with.id, amountThisIter))) {
addItem(player, BrutalArrows.nailItemMap[used.id]!!.product, amountThisIter)
sendMessage(player, "You make $amountThisIter brutal arrows.")
rewardXP(player, Skills.FLETCHING, BrutalArrows.nailItemMap[used.id]!!.exp)
}
}
if (getQuestStage(player, ZogreFleshEaters.questName) < 7) {
sendMessage(player, "You need to complete part of Zogre Flesh Eaters to make these.")
return@onUseWith true
}
if (getStatLevel(player, Skills.FLETCHING) < BrutalArrows.nailItemMap[used.id]!!.level) {
sendMessage(player, "You need a Fletching level of " + BrutalArrows.nailItemMap[used.id]!!.level + " to make these.")
return@onUseWith true
}
sendSkillDialogue(player) {
create { id, amount ->
runTask(
player,
delay = 2,
repeatTimes = min(amount, getMaxAmount() / 6 + 1),
task = ::process
)
}
calculateMaxAmount(::getMaxAmount)
withItems(Item(BrutalArrows.nailItemMap[used.id]!!.product, 5))
}
return@onUseWith true
}
}
}
@@ -0,0 +1,40 @@
package content.region.kandarin.feldip.quest.zogreflesheaters
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.game.system.timer.impl.Disease
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/** The zombie you have to fight when you click on the skeleton. */
class ZombieBrentleVahnBehavior : NPCBehavior(NPCs.ZOMBIE_1826) {
override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) {
val disease = getOrStartTimer<Disease>(victim, 10)
disease.hitsLeft = 10
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops backpack when killed.
if (killer is Player && getQuestStage(killer, ZogreFleshEaters.questName) in 2..4) {
drops.add(Item(Items.RUINED_BACKPACK_4810))
setAttribute(killer, ZogreFleshEaters.attributeFoughtZombie, true)
}
}
var clearTime = 0
override fun tick(self: NPC): Boolean {
// You have 400 ticks to kill this guy
if (clearTime++ > 400) {
clearTime = 0
poofClear(self)
}
return true
}
}
@@ -36,7 +36,6 @@ public final class WizardGuildPlugin extends OptionHandler {
SceneryDefinition.forId(2155).getHandlers().put("option:open", this);
SceneryDefinition.forId(1722).getHandlers().put("option:climb-up", this);
new WizardDistentorDialogue().init();
new ZavisticRarveDialogue().init();
new ProfessorImblewynDialogue().init();
new WizardFrumsconeDialogue().init();
new RobeStoreDialogue().init();
@@ -176,68 +175,6 @@ public final class WizardGuildPlugin extends OptionHandler {
}
/**
* Represents the dialogue used for zavistic rarve.
* @author 'Vexia
* @version 1.0
*/
public final class ZavisticRarveDialogue extends DialoguePlugin {
/**
* Constructs a new {@code ZavisticRarveDialogue} {@code Object}.
*/
public ZavisticRarveDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code ZavisticRarveDialogue} {@code Object}.
* @param player the player.
*/
public ZavisticRarveDialogue(final Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new ZavisticRarveDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
npc("What are you doing...Oh, it's you...sorry...didn't", "realise... what can I do for you?");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
player("Thanks for your help with all of this.");
stage = 1;
break;
case 1:
npc("Ooohh, no thanks required. It's I who should be", "thanking you my friend...your investigative mind has", "shown how vigilant we really should be for this type of", "evil use of the magical arts.");
stage = 2;
break;
case 2:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 2059 };
}
}
/**
* Represents the wizard distentor dialogue.
* @author 'Vexia
@@ -0,0 +1,120 @@
package content.region.kandarin.yanille.dialogue
import content.region.kandarin.feldip.quest.zogreflesheaters.ZogreFleshEaters
import core.api.*
import core.game.dialogue.DialogueBuilder
import core.game.dialogue.DialogueBuilderFile
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
@Initializable
class ZavisticRarveDialogue (player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player): DialoguePlugin {
return ZavisticRarveDialogue(player)
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
openDialogue(player, ZavisticRarveDialogueFile(), npc)
return false
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.ZAVISTIC_RARVE_2059)
}
}
class ZavisticRarveDialogueFile : DialogueBuilderFile() {
companion object {
fun dialogueInitialTalk(builder: DialogueBuilder) : DialogueBuilder {
return builder
.branch { player ->
return@branch if (getQuestStage(player, ZogreFleshEaters.questName) > 3 /* || hand in the sand quest */) {
1
} else {
0
}
}.let { branch2 ->
val returnJoin = builder.placeholder()
branch2.onValue(1)
.npcl("What are you doing...Oh, it's you...sorry...didn't realise...what can I do for you?")
// There is a fork here if you are doing hand in the sand.
.goto(returnJoin)
branch2.onValue(0)
.npcl("What are you doing bothering me? Don't you think some of us have work to do?")
.playerl("I thought you were here to help?")
.npcl("Well... I am, I suppose, anyway... we're very busy here, hurry up, what do you want?")
.goto(returnJoin)
return@let returnJoin.builder()
}
}
fun dialogueInitialTalkViaBell(builder: DialogueBuilder) : DialogueBuilder {
return builder
.branch { player ->
return@branch if (getQuestStage(player, ZogreFleshEaters.questName) > 3 /* || hand in the sand quest */) {
1
} else {
0
}
}.let { branch2 ->
val returnJoin = builder.placeholder()
branch2.onValue(1)
.npcl("What are you doing...Oh, it's you...sorry...didn't realise...what can I do for you?")
.goto(returnJoin)
branch2.onValue(0)
.npcl("What are you doing ringing that bell?! Don't you think some of us have work to do?")
.playerl("But I was told to ring the bell if I wanted some attention.")
.npcl("Well...anyway...we're very busy here, hurry up what do you want?")
.goto(returnJoin)
return@let returnJoin.builder()
}
}
fun defaultTalk(continueBuilder: DialogueBuilder) {
continueBuilder.let { builder ->
val returnJoin = builder.placeholder()
returnJoin.builder()
.options()
.let { optionBuilder ->
optionBuilder.option_playerl("What is there to do in the Wizards' Guild?")
.npcl("This is the finest wizards' establishment in the land.")
.npcl("We have magic portals to the other towers of wizardry around Gielinor.")
.npcl("We have a particularly wide collection of runes in our rune shop.")
.npcl("We sell some of the finest mage robes in the land and we have a training area full of zombies for you to practice your magic on.")
.goto(returnJoin)
optionBuilder.option_playerl("What are the requirements to get in the Wizards' Guild?")
.npcl("You need a magic level of 66, the high magic energy level is too dangerous for anyone below that level.")
.goto(returnJoin)
optionBuilder.option_playerl("What do you do in the Guild?")
.npcl("I'm the Grand Secretary for the Wizards' Guild, I have lots of correspondence to keep up with, as well as attending to the discipline of the more problematic guild members.")
.goto(returnJoin)
optionBuilder.option_playerl("Ok, thanks.")
.end()
}
builder.goto(returnJoin)
}
}
}
override fun create(b: DialogueBuilder) {
b.onPredicate { player -> isQuestComplete(player, ZogreFleshEaters.questName) }
.let { dialogueInitialTalk(it) }
.let { defaultTalk(it) }
// This is during the ZogreFleshEaters quest
b.onPredicate { player -> isQuestInProgress(player, ZogreFleshEaters.questName, 2, 99) }
.manualStage() { df, player, _, _ ->
openDialogue(player, content.region.kandarin.feldip.quest.zogreflesheaters.ZavisticRarveDialogueFile(), npc!!)
}
.end()
b.onPredicate { _ -> true }
.let { dialogueInitialTalk(it) }
.let { defaultTalk(it) }
}
}
@@ -115,7 +115,7 @@ public final class JunglePotion extends Quest {
});
}
},
PALM_TREE(2577, Herbs.ARDRIGAL, 20, "You are looking for Ardrigal. It is related to the palm", "and grows in its brothers shady profusion."), SITO_FOIL(2579, Herbs.SITO_FOIL, 30, "You are looking for Sito Foil, and it grows best where", "the ground has been blackened by the living flame."), VOLENCIA_MOSS(2581, Herbs.VOLENCIA_MOSS, 40, "You are looking for Volencia Moss. It clings to rocks", "for its existence. It is difficult to see, so you must", "search for it well."), ROGUES_PURSE(32106, Herbs.ROGUES_PUSE, 50, "It inhabits the darkness of the underground, and grows", "in the caverns to the north. A secret entrance to the", "caverns is set into the northern cliffs, be careful Bwana.") {
PALM_TREE(2577, Herbs.ARDRIGAL, 20, "You are looking for Ardrigal. It is related to the palm", "and grows in its brothers shady profusion."), SITO_FOIL(2579, Herbs.SITO_FOIL, 30, "You are looking for Sito Foil, and it grows best where", "the ground has been blackened by the living flame."), VOLENCIA_MOSS(2581, Herbs.VOLENCIA_MOSS, 40, "You are looking for Volencia Moss. It clings to rocks", "for its existence. It is difficult to see, so you must", "search for it well."), ROGUES_PURSE(32106, Herbs.ROGUES_PURSE, 50, "It inhabits the darkness of the underground, and grows", "in the caverns to the north. A secret entrance to the", "caverns is set into the northern cliffs, be careful Bwana.") {
@Override
public void search(final Player player, final Scenery object) {
final Animation animation = Animation.create(2097);
+5 -2
View File
@@ -1818,8 +1818,11 @@ fun sendItemDialogue(player: Player, item: Any, message: String) {
* @param item2 the ID of the second item to show
* @param message the text to display
*/
fun sendDoubleItemDialogue(player: Player, item1: Int, item2: Int, message: String) {
player.dialogueInterpreter.sendDoubleItemMessage(item1, item2, message)
fun sendDoubleItemDialogue(player: Player, item1: Any, item2: Any, message: String) {
when (item1) {
is Item -> player.dialogueInterpreter.sendDoubleItemMessage(item1, item2 as Item, message)
is Int -> player.dialogueInterpreter.sendDoubleItemMessage(item1, item2 as Int, message)
}
}
/**
@@ -3,6 +3,7 @@ package core.game.global.action;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.diary.DiaryType;
import core.game.world.map.Location;
import content.region.kandarin.feldip.quest.zogreflesheaters.ZogreFleshEatersListeners;
import java.util.Arrays;
import java.util.HashMap;
@@ -80,6 +81,13 @@ public enum SpecialLadders implements LadderAchievementCheck {
PATERDOMUS_TEMPLE_STAIRCASE_SOUTH_DOWN(new Location(3415, 3486,1), new Location(3414, 3486,0)),
PHASMATYS_BAR_DOWN(new Location(3681,3498,0), new Location(3682,9961,0)),
PHASMATYS_BAR_UP(new Location(3682,9962,0), new Location(3681,3497,0)),
YANNILE_HOUSE_DOWN(new Location(2597, 3107,1), new Location(2597, 3107,0)),
YANNILE_HOUSE_UP(new Location(2597, 3107,0), new Location(2597, 3107,1)) {
@Override
public void checkAchievement(Player player) {
ZogreFleshEatersListeners.ladderMakesSithikTurnIntoOgre(player);
}
},
SEERS_VILLAGE_SPINNING_HOUSE_ROOFTOP_UP(new Location(2715,3472,1), new Location(2714,3472,3)) {
@Override
public void checkAchievement(Player player) {
@@ -36,18 +36,28 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) {
/**
* Force animation + messages on all NPCs in a radius of 10 from the player.
* Add an optional 3rd argument if cycling through a range of animation ids.
*/
define("npcanim", Privilege.ADMIN, "::npcanim <lt>Animation ID<gt>") { player, args ->
define("npcanim", Privilege.ADMIN, "::npcanim <lt>Animation ID<gt> <lt>Optional: End Animation ID<gt>") { player, args ->
if (args.size < 2) {
reject(player, "Syntax error: ::npcanim <Animation ID>")
}
npcs = RegionManager.getLocalNpcs(player.location, 10)
for (n in npcs) {
n.sendChat(args.slice(1 until args.size).joinToString(" "))
n.lock(6)
n.faceTemporary(player, 6)
n.animator.animate(Animation(args[1].toInt()))
n.animate(Animation.create(-1), 6)
if (args.size == 2) {
n.sendChat(args.slice(1 until args.size).joinToString(" "))
n.animate(Animation(args[1].toInt()))
n.animate(Animation.create(-1), 6)
}
if (args.size == 3) {
var count = 0
for(animNum in args[1].toInt()..args[2].toInt()) {
count++
n.animate(Animation(animNum), count*6)
}
}
}
}