mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-10 10:20:41 -07:00
Implemented Recruitment Drive quest
This commit is contained in:
parent
29fa9a5a21
commit
e25c7d7824
28 changed files with 2715 additions and 181 deletions
|
|
@ -627,6 +627,10 @@
|
|||
"item_id": "5523",
|
||||
"loc_data": "{1,2935,3282,1,90}-"
|
||||
},
|
||||
{
|
||||
"item_id": "5586",
|
||||
"loc_data": "{1,2473,4941,0,90}-"
|
||||
},
|
||||
{
|
||||
"item_id": "6291",
|
||||
"loc_data": "{1,2681,3111,0,30}-{1,2673,3112,0,30}-{1,2674,3094,0,30}-{1,2671,3089,0,30}-"
|
||||
|
|
|
|||
|
|
@ -50376,10 +50376,18 @@
|
|||
"id": "5584"
|
||||
},
|
||||
{
|
||||
"examine": "It's a metal spade without a handle.",
|
||||
"examine": "I hope the mould was accurate enough...",
|
||||
"durability": null,
|
||||
"name": "Bronze Key",
|
||||
"weight": "0.01",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5585"
|
||||
},
|
||||
{
|
||||
"examine": "It's a metal spade with a wooden handle.",
|
||||
"durability": null,
|
||||
"name": "Metal spade",
|
||||
"weight": "2.5",
|
||||
"weight": "1.814",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5586"
|
||||
},
|
||||
|
|
@ -50387,7 +50395,7 @@
|
|||
"examine": "It's a metal spade without a handle.",
|
||||
"durability": null,
|
||||
"name": "Metal spade",
|
||||
"weight": "2.5",
|
||||
"weight": "1.814",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5587"
|
||||
},
|
||||
|
|
@ -50399,101 +50407,101 @@
|
|||
"id": "5588"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "20",
|
||||
"examine": "A tin layered with some stuff from a vial.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.101",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5592"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "20",
|
||||
"examine": "It's full of a white lumpy mixture that seems to be hardening.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.101",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5593"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "20",
|
||||
"examine": "There is an impression of a key embedded in it.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.101",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5594"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "20",
|
||||
"examine": "There is an impression of a key, filled with tin ore.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.101",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5595"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "20",
|
||||
"examine": "There is an impression of a key, filled with copper ore.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.101",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5596"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "20",
|
||||
"examine": "There is an impression of a key, filled with tin and copper ore.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.101",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5597"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "20",
|
||||
"examine": "There is a bronze key surrounded by plaster in this tin.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.101",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5598"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "20",
|
||||
"examine": "There is a strange concoction filling this tin.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.101",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5599"
|
||||
},
|
||||
{
|
||||
"shop_price": "6",
|
||||
"examine": "This needs refining.",
|
||||
"grand_exchange_price": "42",
|
||||
"shop_price": "10",
|
||||
"examine": "I could probably pour something into this.",
|
||||
"grand_exchange_price": "0",
|
||||
"durability": null,
|
||||
"name": "Tin",
|
||||
"tradeable": "true",
|
||||
"weight": "2.25",
|
||||
"tradeable": "false",
|
||||
"weight": "0.1",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5600"
|
||||
},
|
||||
|
|
@ -50523,8 +50531,8 @@
|
|||
"grand_exchange_price": "41",
|
||||
"durability": null,
|
||||
"name": "Shears",
|
||||
"tradeable": "true",
|
||||
"weight": "0.1",
|
||||
"tradeable": "false",
|
||||
"weight": "0.113",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "5603"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23449,6 +23449,54 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "An observer for the Temple Knights.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Sir Spishyus",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "2282",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "An observer for the Temple Knights.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Lady Table",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "2283",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "An observer for the Temple Knights.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Sir Kuam Ferentse",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "2284",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A warrior blessed by Saradomin.",
|
||||
"melee_animation": "400",
|
||||
|
|
@ -23456,13 +23504,45 @@
|
|||
"defence_animation": "425",
|
||||
"death_animation": "836",
|
||||
"name": "Sir Leye",
|
||||
"defence_level": "1",
|
||||
"defence_level": "15",
|
||||
"safespot": null,
|
||||
"lifepoints": "21",
|
||||
"strength_level": "1",
|
||||
"strength_level": "18",
|
||||
"id": "2285",
|
||||
"aggressive": "true",
|
||||
"range_level": "1",
|
||||
"attack_level": "18"
|
||||
},
|
||||
{
|
||||
"examine": "An observer for the Temple Knights.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Sir Tinley",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "2286",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "An observer for the Temple Knights.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Sir Ren Itchood",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "2287",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
|
|
@ -23497,6 +23577,22 @@
|
|||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "Head of recruitment for the Temple Knights.",
|
||||
"melee_animation": "0",
|
||||
"range_animation": "0",
|
||||
"defence_animation": "0",
|
||||
"magic_animation": "0",
|
||||
"death_animation": "0",
|
||||
"name": "Sir Tiffy Cashien",
|
||||
"defence_level": "1",
|
||||
"safespot": null,
|
||||
"lifepoints": "10",
|
||||
"strength_level": "1",
|
||||
"id": "2290",
|
||||
"range_level": "1",
|
||||
"attack_level": "1"
|
||||
},
|
||||
{
|
||||
"examine": "A carpet merchant.",
|
||||
"melee_animation": "0",
|
||||
|
|
@ -71281,11 +71377,6 @@
|
|||
"name": "Sir Vyvin",
|
||||
"id": "605"
|
||||
},
|
||||
{
|
||||
"examine": "Head of recruitment for the Temple Knights.",
|
||||
"name": "Sir Tiffy Cashien",
|
||||
"id": "2290"
|
||||
},
|
||||
{
|
||||
"examine": "An armourer.",
|
||||
"name": "Wayne",
|
||||
|
|
|
|||
|
|
@ -5171,6 +5171,34 @@
|
|||
"npc_id": "2281",
|
||||
"loc_data": "{3187,3241,0,1,0}-{3177,3243,0,1,0}-{3246,3245,0,1,4}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "2282",
|
||||
"loc_data": "{2488,4973,0,0,6}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "2283",
|
||||
"loc_data": "{2458,4980,0,0,6}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "2284",
|
||||
"loc_data": "{2457,4966,0,0,6}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "2286",
|
||||
"loc_data": "{2476,4958,0,0,3}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "2287",
|
||||
"loc_data": "{2443,4956,0,0,4}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "2288",
|
||||
"loc_data": "{2469,4941,0,0,6}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "2289",
|
||||
"loc_data": "{2451,4939,0,0,6}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "2290",
|
||||
"loc_data": "{2997,3373,0,0,0}-"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import core.game.world.update.flag.context.Animation
|
|||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.Sounds
|
||||
import rs09.game.content.activity.castlewars.areas.CastleWarsWaitingArea
|
||||
import java.util.*
|
||||
|
||||
@Suppress("unused")
|
||||
class CastleWarsListeners : InteractionListener {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class TrollStronghold : Quest("Troll Stronghold",128, 127, 1, 317, 0, 1, 50) {
|
|||
if (stage >= 5) {
|
||||
line(player, "I have defeated the !!Troll Champion??", line++, true)
|
||||
} else if (stage >= 3) {
|
||||
line(player, "I have to defeat the !!Troll Champion??", line++)
|
||||
line(player, "I have accepted the !!Troll Champion's?? challenge.", line++)
|
||||
}
|
||||
if (stage in 5..7) {
|
||||
line++
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
package content.region.asgarnia.falador.dialogue;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the dialogue used for sir tiffy.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class SirTiffyCashienDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SirTiffyCashienDialogue} {@code Object}.
|
||||
*/
|
||||
public SirTiffyCashienDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SirTiffyCashienDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public SirTiffyCashienDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new SirTiffyCashienDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello.");
|
||||
stage = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "What ho, sirrag.", "Spiffing day for a walk in the park, what?");
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Spiffing?");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Absolutely, top-hole!", "Well, can't stay and chat all day, dontchaknow!", "Ta-ta for now!");
|
||||
stage = 10;
|
||||
break;
|
||||
case 3:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Erm...goodbye.");
|
||||
stage = 4;
|
||||
break;
|
||||
case 4:
|
||||
end();
|
||||
break;
|
||||
case 10:
|
||||
npc("Would you like to look at my wares?");
|
||||
stage++;
|
||||
break;
|
||||
case 11:
|
||||
player("Yes, please.");
|
||||
stage++;
|
||||
break;
|
||||
case 12:
|
||||
npc.openShop(player);
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 2290 };
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
package content.region.asgarnia.falador.dialogue
|
||||
|
||||
import content.region.asgarnia.falador.quest.recruitmentdrive.RecruitmentDrive
|
||||
import content.region.asgarnia.falador.quest.recruitmentdrive.SirTiffyCashienDialogueFile
|
||||
import core.ServerConstants
|
||||
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.game.world.map.Location
|
||||
import core.plugin.Initializable
|
||||
import core.tools.END_DIALOGUE
|
||||
import core.tools.START_DIALOGUE
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
@Initializable
|
||||
class SirTiffyCashienDialogue (player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
|
||||
// Completed Recruitment Drive & Start Wanted!! Quest
|
||||
if (isQuestComplete(player!!, RecruitmentDrive.questName)) {
|
||||
openDialogue(player, SirTiffyCashienAfterRecruitmentDriveQuestDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
|
||||
// Recruitment Drive Quest
|
||||
if (isQuestInProgress(player!!, RecruitmentDrive.questName, 1, 99)) {
|
||||
openDialogue(player, SirTiffyCashienDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
|
||||
// Fallback to default.
|
||||
when (stage) {
|
||||
START_DIALOGUE -> player("Hello.").also { stage++ }
|
||||
1 -> npc(FacialExpression.FRIENDLY, "What ho, ${if (player.isMale) "sirrah" else "milady"}.", "Spiffing day for a walk in the park, what?").also { stage++ }
|
||||
2 -> player(FacialExpression.THINKING, "Spiffing?").also { stage++ }
|
||||
3 -> npc(FacialExpression.FRIENDLY, "Absolutely, top-hole!", "Well, can't stay and chat all day, dontchaknow!", "Ta-ta for now!").also { stage++ }
|
||||
4 -> player(FacialExpression.THINKING, "Erm...goodbye.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
override fun newInstance(player: Player): DialoguePlugin {
|
||||
return SirTiffyCashienDialogue(player)
|
||||
}
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.SIR_TIFFY_CASHIEN_2290)
|
||||
}
|
||||
}
|
||||
|
||||
// Move this to Wanted!! Quest.
|
||||
class SirTiffyCashienAfterRecruitmentDriveQuestDialogueFile : DialogueBuilderFile() {
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate { _ -> true }
|
||||
.npc(FacialExpression.HAPPY, "What ho, @g[sirrah,milady].", "Jolly good show on the old training grounds thingy,", "what?")
|
||||
.options().let { optionBuilder ->
|
||||
optionBuilder.option_playerl("Do you have any jobs for me yet?")
|
||||
.npcl("Sorry dear @g[boy,gal] but we are still in the process of organising.")
|
||||
.npcl("I'm sure that we will have something for you soon, so please feel free to check back later.")
|
||||
// Started of Wanted! quest
|
||||
.end()
|
||||
optionBuilder.option("Can you explain the Gaze of Saradomin to me?")
|
||||
.playerl("I don't really understand this 'Gaze of Saradomin' thing... Do you think you could explain what it does for me?")
|
||||
.npcl("Certainly @g[sirrah,milady]! As you know, we Temple Knights are personally favoured by Saradomin himself.")
|
||||
.npcl("And when I say personally favoured, I don't mean that sometime off in the future he's going to buy us all a drink!")
|
||||
.npcl("He watches over each of us, and when we die he catches us as we fall, and ensures we arrive back at Falador castle safe and sound.")
|
||||
.npcl("We usually lose some equipment when he does so, but it's a small price to pay to be hale and hearty again, what?")
|
||||
.npcl("Some lucky fellows have a similar system going already, but when they die they spawn in that squalid little swamp village Lumbridge.")
|
||||
.playerl("Yeah, what kind of person would want to spawn there... Certainly not me, and I never have! Honest!")
|
||||
.npcl("Well, you should be glad that we offer you a step up then! Falador is clearly a far superior town to spend your time in!")
|
||||
.npcl("Was there something else you wanted to ask good old Tiffy, @g[sirrah,milady]?")
|
||||
.end()
|
||||
optionBuilder.option("Can I buy some armour?")
|
||||
.playerl("Can I buy some armour?")
|
||||
// Recruitment Drive -> Initiate level, Slug Menace -> Proselyte level
|
||||
.npcl("Of course dear @g[boy,gal]. I can sell you up to Initiate level items only I'm afraid.")
|
||||
.endWith { _, player ->
|
||||
openNpcShop(player, npc!!.id)
|
||||
}
|
||||
optionBuilder.option_playerl("Can I switch respawns please?")
|
||||
.npcl("I'm sorry dear @g[boy,gal], I'm afraid I can't switch your respawn point at the moment.")
|
||||
.end()
|
||||
// I have no idea how to do this properly.
|
||||
// optionBuilder.option("Can I switch respawns please?")
|
||||
// .branch { player -> if(player.properties.spawnLocation == Location(2997, 3375, 0)) { 1 } else { 0 } }
|
||||
// .let { branch ->
|
||||
// branch.onValue(1)
|
||||
// .npcl("Ah, so you'd like to respawn in Falador, the good old homestead! Are you sure?")
|
||||
// .endWith { _, player ->
|
||||
// player.properties.spawnLocation = Location(2997, 3375, 0)
|
||||
// }
|
||||
// branch.onValue(0)
|
||||
// .npcl("What? You're saying you want to respawn in Lumbridge? Are you sure?")
|
||||
// .endWith { _, player ->
|
||||
// player.properties.spawnLocation = ServerConstants.HOME_LOCATION
|
||||
// }
|
||||
// }
|
||||
optionBuilder.option("Goodbye.")
|
||||
.playerl("Well, see you around Tiffy.")
|
||||
.npcl(FacialExpression.HAPPY,"Ta-ta for now, old bean!")
|
||||
.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package content.region.asgarnia.falador.quest.blackknightsfortress;
|
||||
|
||||
import content.region.asgarnia.falador.quest.recruitmentdrive.SirAmikVarzeDialogueFile;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
|
|
@ -8,6 +9,8 @@ import core.game.node.entity.player.link.quest.Quest;
|
|||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
import static core.api.ContentAPIKt.openDialogue;
|
||||
|
||||
/**
|
||||
* Represents the sir amik varze dialogue.
|
||||
* @author Vexia
|
||||
|
|
@ -72,35 +75,7 @@ public class SirAmikVarzeDialogue extends DialoguePlugin {
|
|||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (quest.getStage(player)) {
|
||||
case 100:
|
||||
switch (stage) {
|
||||
case 0:
|
||||
interpreter.sendDialogues(npc, FacialExpression.FRIENDLY, "Hello, friend!");
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_ASKING, "Do you have any other quests for me to do?");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_THINKING, "Quests, eh?", "Well, I don't have anything on the go at the moment,", "but there is an organisation that is always looking for", "capable adventurers to assist them.");
|
||||
stage = 3;
|
||||
break;
|
||||
case 3:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HAPPY, "Your excellent work sorting out those Black Knights", "means I will happily write you a letter of", "recommendation.");
|
||||
stage = 4;
|
||||
break;
|
||||
case 4:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_ASKING, "Would you like me to put your name forwards to", "them?");
|
||||
stage = 5;
|
||||
break;
|
||||
case 5:
|
||||
interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "No thanks.");
|
||||
stage = 6;
|
||||
break;
|
||||
case 6:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
openDialogue(player, new SirAmikVarzeDialogueFile(), npc);
|
||||
break;
|
||||
case 30:
|
||||
switch (stage) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,248 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
import content.global.handlers.iface.BookInterface
|
||||
import content.global.handlers.iface.BookLine
|
||||
import content.global.handlers.iface.Page
|
||||
import content.global.handlers.iface.PageSet
|
||||
import core.api.setAttribute
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.player.Player
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Items
|
||||
|
||||
// https://www.youtube.com/watch?v=o-bAoxIYT-A 7:27
|
||||
@Initializable
|
||||
class AlchemicalNotes : InteractionListener {
|
||||
companion object {
|
||||
private val TITLE = "Alchemical Reactions Study"
|
||||
private val CONTENTS = arrayOf(
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Acetic acid and Cupric", 55),
|
||||
BookLine("Sulphate:", 56),
|
||||
BookLine("Endothermic.", 57),
|
||||
BookLine("The Cupric is in ", 58),
|
||||
BookLine("insufficient quantities to", 59),
|
||||
BookLine("cause any noticeable", 60),
|
||||
BookLine("reaction.", 61),
|
||||
),
|
||||
Page(
|
||||
BookLine("Acetic acid and Gypsum:", 66),
|
||||
BookLine("Endothermic.", 67),
|
||||
BookLine("Made a particularly bad", 68),
|
||||
BookLine("smell, but little else that", 69),
|
||||
BookLine("was productive.", 70),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Acetic acid and Sodium", 55),
|
||||
BookLine("Chloride:", 56),
|
||||
BookLine("Endothermic.", 57),
|
||||
BookLine("Very tasty when", 58),
|
||||
BookLine("combined with fried", 59),
|
||||
BookLine("potatoes at room", 60),
|
||||
BookLine("temperature.", 61),
|
||||
),
|
||||
Page(
|
||||
BookLine("Acetic acid and", 66),
|
||||
BookLine("Dihydrogen Monoxide:", 67),
|
||||
BookLine("Endothermic.", 68),
|
||||
BookLine("The Dihydrogen", 69),
|
||||
BookLine("Monoxide served only to", 70),
|
||||
BookLine("dilute the Acetic acid at", 71),
|
||||
BookLine("room temperature.", 72),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Acetic acid and Cupric", 55),
|
||||
BookLine("Ore Powder:", 56),
|
||||
BookLine("Endothermic.", 57),
|
||||
BookLine("The powdered form of", 58),
|
||||
BookLine("Cupric Ore allowed a", 59),
|
||||
BookLine("lower than usual melting", 60),
|
||||
BookLine("temperature, but the end", 61),
|
||||
BookLine("product was non-usable.", 62),
|
||||
),
|
||||
Page(
|
||||
BookLine("Acetic acid and Tin Ore", 66),
|
||||
BookLine("powder:", 67),
|
||||
BookLine("Endothermic.", 68),
|
||||
BookLine("Similar results to those", 69),
|
||||
BookLine("made using Cupric Ore.", 70),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Cupric Sulphate and", 55),
|
||||
BookLine("Dihyrdogen Monoxide:", 56),
|
||||
BookLine("Exothermic.", 57),
|
||||
BookLine("A blue compound was", 58),
|
||||
BookLine("produced, along with heat.", 59),
|
||||
),
|
||||
Page(
|
||||
BookLine("Cupric Sulphate and", 66),
|
||||
BookLine("Gypsum:", 67),
|
||||
BookLine("Endothermic.", 68),
|
||||
BookLine("At room temperature, no", 69),
|
||||
BookLine("useful product was", 70),
|
||||
BookLine("created.", 71),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Cupric Sulphate and", 55),
|
||||
BookLine("Sodium Chloride:", 56),
|
||||
BookLine("Endothermic.", 57),
|
||||
BookLine("A pungent odour was", 58),
|
||||
BookLine("released when combined.", 59),
|
||||
),
|
||||
Page(
|
||||
BookLine("Cupric Sulphate and", 66),
|
||||
BookLine("Cupric Ore powder:", 67),
|
||||
BookLine("Endothermic.", 68),
|
||||
BookLine("The Cupric did not react", 69),
|
||||
BookLine("with each other at room", 70),
|
||||
BookLine("temperature.", 71),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Cupric Sulphate and Tin", 55),
|
||||
BookLine("Ore powder:", 56),
|
||||
BookLine("Endothermic.", 57),
|
||||
BookLine("Similar results to those", 58),
|
||||
BookLine("shown with Cupric Ore,", 59),
|
||||
BookLine("despite the increased", 60),
|
||||
BookLine("solubility involved with", 61),
|
||||
BookLine("the powdered form.", 62),
|
||||
),
|
||||
Page(
|
||||
BookLine("Gypsum and Dihydrogen", 66),
|
||||
BookLine("Monoxide:", 67),
|
||||
BookLine("Exothermic.", 68),
|
||||
BookLine("A white liquid compound", 69),
|
||||
BookLine("was formed, that quickly", 70),
|
||||
BookLine("cooled at room", 71),
|
||||
BookLine("temperature to a white", 72),
|
||||
BookLine("heat resistant solid very", 73),
|
||||
BookLine("similar to plaster.", 74),
|
||||
BookLine("Heat was also produced,", 75),
|
||||
BookLine("although not in the same", 76),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("quantity as Cupric", 55),
|
||||
BookLine("Sulphate with Dihydrogen", 56),
|
||||
BookLine("Monoxide", 57),
|
||||
),
|
||||
Page(
|
||||
BookLine("Gypsum and Sodium", 66),
|
||||
BookLine("Chloride:", 67),
|
||||
BookLine("Endothermic.", 68),
|
||||
BookLine("The two did not seem to", 69),
|
||||
BookLine("noticably mix together at", 70),
|
||||
BookLine("room temperature.", 71),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Gypsum and Culpric Ore:", 55),
|
||||
BookLine("Endothermic.", 56),
|
||||
BookLine("The gypsum seems quite", 57),
|
||||
BookLine("resistant to most", 58),
|
||||
BookLine("compounds at normal", 59),
|
||||
BookLine("room temperature.", 60),
|
||||
),
|
||||
Page(
|
||||
BookLine("Gypsum and Tin Ore:", 66),
|
||||
BookLine("Endothermic.", 67),
|
||||
BookLine("Again, very similar results", 68),
|
||||
BookLine("as those shown with", 69),
|
||||
BookLine("Cupric Ore.", 70),
|
||||
)
|
||||
),
|
||||
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Sodium Chloride and", 55),
|
||||
BookLine("Dihydrogen Monoxide:", 56),
|
||||
BookLine("Endothermic.", 57),
|
||||
BookLine("At room temperature, the", 58),
|
||||
BookLine("Sodium Chloride dissolves", 59),
|
||||
BookLine("quite easily. Dissolution is", 60),
|
||||
BookLine("faster at higher", 61),
|
||||
BookLine("temperatures.", 62),
|
||||
),
|
||||
Page(
|
||||
BookLine("Sodium Chloride and", 66),
|
||||
BookLine("Cupric Ore:", 67),
|
||||
BookLine("Endothermic.", 68),
|
||||
BookLine("No visible combination at", 69),
|
||||
BookLine("room temperature.", 70),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Sodium Chloride and Tin", 55),
|
||||
BookLine("Ore:", 56),
|
||||
BookLine("Endothermic.", 57),
|
||||
BookLine("Another very similar ", 58),
|
||||
BookLine("result as with Cupric Ore.", 59),
|
||||
),
|
||||
Page(
|
||||
BookLine("Cupric Ore Powder and", 66),
|
||||
BookLine("Tin Ore Powder:", 67),
|
||||
BookLine("Endothermic.", 68),
|
||||
BookLine("When both ores are in", 69),
|
||||
BookLine("particulate form, a much", 70),
|
||||
BookLine("lower than usual bonding", 71),
|
||||
BookLine("temperature can be", 72),
|
||||
BookLine("obtained.", 73),
|
||||
BookLine("When combined at a", 74),
|
||||
BookLine("moderate heat, (my", 75),
|
||||
BookLine("laboratory heating", 76),
|
||||
)
|
||||
),
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("apparatus) I was able to", 55),
|
||||
BookLine("form liquid Bronze quite", 56),
|
||||
BookLine("easily, which cooled to", 57),
|
||||
BookLine("form a standard Bronze", 58),
|
||||
BookLine("Bar at a temperature far", 60),
|
||||
BookLine("lower than that required", 61),
|
||||
BookLine("to produce in mass at a", 62),
|
||||
BookLine("furnace.", 63),
|
||||
),
|
||||
Page(
|
||||
BookLine("Nitrous Monoxide:", 66),
|
||||
BookLine("Was not able to perform", 67),
|
||||
BookLine("an experimentation using", 68),
|
||||
BookLine("this substance, as the", 69),
|
||||
BookLine("gaseous form would", 70),
|
||||
BookLine("always escape when the", 71),
|
||||
BookLine("vial was opened.", 72),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun display(player:Player, pageNum: Int, buttonID: Int) : Boolean {
|
||||
BookInterface.pageSetup(player, BookInterface.FANCY_BOOK_3_49, TITLE, CONTENTS)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
override fun defineListeners() {
|
||||
on(Items.ALCHEMICAL_NOTES_5588, IntType.ITEM, "read") { player, _ ->
|
||||
setAttribute(player, "bookInterfaceCallback", ::display)
|
||||
setAttribute(player, "bookInterfaceCurrentPage", 0)
|
||||
display(player, 0, 0)
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
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.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
class LadyTableDialogue (player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
openDialogue(player, LadyTableDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
override fun newInstance(player: Player): DialoguePlugin {
|
||||
return LadyTableDialogue(player)
|
||||
}
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.LADY_TABLE_2283)
|
||||
}
|
||||
}
|
||||
|
||||
class LadyTableDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile(), InteractionListener {
|
||||
companion object {
|
||||
const val statueVarbit = 658
|
||||
const val attributeStatueStateNumber = "quest:recruitmentdrive-statuestatenumber"
|
||||
val statueArray = intArrayOf(0, 7308, 7307, 7306, 7305, 7304, 7303, 7312, 7313, 7314, 7311, 7310, 7309)
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
|
||||
on(statueArray, IntType.SCENERY, "touch") { player, node ->
|
||||
if( node.id == statueArray[getAttribute(player, attributeStatueStateNumber, 0)]) {
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) {
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1)
|
||||
sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, false, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.")
|
||||
return@on true
|
||||
}
|
||||
} else {
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) {
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
openDialogue(player, LadyTableDialogueFile(2), NPC(NPCs.LADY_TABLE_2283))
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1) {
|
||||
sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, false, "Please step through the portal to meet your next", "challenge.")
|
||||
}
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1) {
|
||||
openDialogue(player, LadyTableDialogueFile(2), NPC(NPCs.LADY_TABLE_2283))
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
}
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate { player -> dialogueNum == 1 }
|
||||
.endWith { _, player ->
|
||||
submitWorldPulse(object : Pulse() {
|
||||
var counter = 0
|
||||
override fun pulse(): Boolean {
|
||||
when (counter++) {
|
||||
0 -> {
|
||||
lock(player, 15)
|
||||
setAttribute(player, attributeStatueStateNumber, (1..12).random())
|
||||
setVarbit(player, statueVarbit, getAttribute(player, attributeStatueStateNumber, 0))
|
||||
sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true,"Welcome, @name.", "This room will test your observation skills.")
|
||||
}
|
||||
5 -> {
|
||||
sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true, "Study the statues closely.", "There is one missing statue in this room.")
|
||||
}
|
||||
10 -> {
|
||||
sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true, "We will also mix the order up a little, to make things", "interesting for you!")
|
||||
}
|
||||
15 -> {
|
||||
sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true,"You have 10 seconds to memorise the statues... starting", "NOW!")
|
||||
}
|
||||
20 -> {
|
||||
closeDialogue(player)
|
||||
}
|
||||
31 -> { // From 15 -> 16 * 600ms = 10 seconds
|
||||
openOverlay(player,Components.FADE_TO_BLACK_120)
|
||||
sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true,"We will now dim the lights and bring the missing statue", "back in.")
|
||||
}
|
||||
34 -> { // From 15 -> 16 * 600ms = 10 seconds
|
||||
setVarbit(player, statueVarbit, 0)
|
||||
openOverlay(player,Components.FADE_FROM_BLACK_170)
|
||||
sendNPCDialogueLines(player, NPCs.LADY_TABLE_2283, FacialExpression.NEUTRAL, true,"Please touch the statue you think has been added.")
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
b.onPredicate { player -> dialogueNum == 2 || (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1) }
|
||||
.betweenStage { _, player, _, _ ->
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
}
|
||||
.npc(FacialExpression.SAD, "No... I am very sorry.", "Apparently you are not up to the challenge.", "I will return you where you came from, better luck in the", "future.")
|
||||
.endWith { _, player ->
|
||||
removeAttribute(player, attributeStatueStateNumber)
|
||||
removeAttribute(player, RecruitmentDrive.attributeStagePassFailState)
|
||||
RecruitmentDriveListeners.FailTestCutscene(player).start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,512 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
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.global.action.DoorActionHandler
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.Location
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Scenery
|
||||
|
||||
@Initializable
|
||||
class MissCheeversDialogue (player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
openDialogue(player, MissCheeversDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
override fun newInstance(player: Player): DialoguePlugin {
|
||||
return MissCheeversDialogue(player)
|
||||
}
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.MISS_CHEEVERS_2288)
|
||||
}
|
||||
}
|
||||
|
||||
class MissCheeversDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() {
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate { _ -> dialogueNum == 0 }
|
||||
.playerl(FacialExpression.FRIENDLY,"Can you give me any help?")
|
||||
.npcl(FacialExpression.FRIENDLY,"No, I am sorry, but that is forbidden by our rules.")
|
||||
.npcl(FacialExpression.FRIENDLY,"If you are having a particularly tough time of it, I suggest you leave and come back later when you are in a more receptive frame of mind.")
|
||||
.npcl(FacialExpression.FRIENDLY,"Sometimes a break from concentration will yield fresh insight. Our aim is to test you, but not to the point of frustration!")
|
||||
.playerl(FacialExpression.FRIENDLY,"Okay, thanks!")
|
||||
.end()
|
||||
|
||||
|
||||
b.onPredicate { _ -> dialogueNum == 1 }
|
||||
.betweenStage { _, player, _, _ ->
|
||||
setVarbit(player, MissCheeversRoomListeners.doorVarbit, 0)
|
||||
removeAttribute(player, MissCheeversRoomListeners.attributebook)
|
||||
removeAttribute(player, MissCheeversRoomListeners.attributemagnet)
|
||||
removeAttribute(player, MissCheeversRoomListeners.attributeKnife)
|
||||
removeAttribute(player, MissCheeversRoomListeners.attributeShears)
|
||||
removeAttribute(player, MissCheeversRoomListeners.attributeTin)
|
||||
removeAttribute(player, MissCheeversRoomListeners.attributeChisel)
|
||||
removeAttribute(player, MissCheeversRoomListeners.attributeWire)
|
||||
|
||||
removeAttribute(player, MissCheeversRoomListeners.attribute3VialsOfLiquid)
|
||||
|
||||
MissCheeversRoomListeners.Companion.Vials.vialMap.map {
|
||||
removeAttribute(player, it.value.attribute)
|
||||
}
|
||||
|
||||
MissCheeversRoomListeners.Companion.DoorVials.doorVialsRequiredMap.map {
|
||||
removeAttribute(player, it.value.attribute)
|
||||
}
|
||||
}
|
||||
.npcl(FacialExpression.FRIENDLY,"Greetings, @name. Welcome to my challenge.")
|
||||
.npcl(FacialExpression.FRIENDLY,"All you need to do is leave from the opposite door to where you came in by.")
|
||||
.npcl(FacialExpression.FRIENDLY,"I will warn you that this is more complicated than it may at first appear.")
|
||||
.npcl(FacialExpression.FRIENDLY,"I should also warn you that there are limited supplies of the items in this room, so think carefully before using them, you may find yourself stuck and have to leave to start again!")
|
||||
.npcl(FacialExpression.FRIENDLY,"Best of luck!")
|
||||
.end()
|
||||
}
|
||||
}
|
||||
|
||||
class MissCheeversRoomListeners : InteractionListener {
|
||||
companion object {
|
||||
|
||||
const val doorVarbit = 686
|
||||
|
||||
const val attributebook = "quest:recruitmentdrive-book"
|
||||
const val attributemagnet = "quest:recruitmentdrive-magnet"
|
||||
const val attributeKnife = "quest:recruitmentdrive-knife"
|
||||
const val attributeShears = "quest:recruitmentdrive-shears"
|
||||
const val attributeTin = "quest:recruitmentdrive-tin"
|
||||
const val attributeChisel = "quest:recruitmentdrive-chisel"
|
||||
const val attributeWire = "quest:recruitmentdrive-wire"
|
||||
|
||||
const val attribute3VialsOfLiquid = "quest:recruitmentdrive-3vialsofliquid"
|
||||
|
||||
/** Enums to map canoes to related properties. */
|
||||
enum class Vials(val itemId: Int, val attribute: String) {
|
||||
CUPRIC_SULPHATE_5577(Items.CUPRIC_SULPHATE_5577, "quest:recruitmentdrive-cupricsulphate"),
|
||||
ACETIC_ACID_5578(Items.ACETIC_ACID_5578, "quest:recruitmentdrive-aceticacid"),
|
||||
GYPSUM_5579(Items.GYPSUM_5579, "quest:recruitmentdrive-gypsum"),
|
||||
SODIUM_CHLORIDE_5580(Items.SODIUM_CHLORIDE_5580, "quest:recruitmentdrive-sodiumchloride"),
|
||||
NITROUS_OXIDE_5581(Items.NITROUS_OXIDE_5581, "quest:recruitmentdrive-nitrousoxide"),
|
||||
VIAL_OF_LIQUID_5582(Items.VIAL_OF_LIQUID_5582, "quest:recruitmentdrive-vialofliquid"),
|
||||
TIN_ORE_POWDER_5583(Items.TIN_ORE_POWDER_5583, "quest:recruitmentdrive-tinorepowder"),
|
||||
CUPRIC_ORE_POWDER_5584(Items.CUPRIC_ORE_POWDER_5584, "quest:recruitmentdrive-cupricorepowder");
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val vialMap = Vials.values().associateBy { it.itemId }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Enums to map canoes to related properties. */
|
||||
enum class DoorVials(val itemId: Int, val attribute: String) {
|
||||
CUPRIC_SULPHATE_5577(Items.CUPRIC_SULPHATE_5577, "quest:recruitmentdrive-doorcupricsulphate"),
|
||||
ACETIC_ACID_5578(Items.ACETIC_ACID_5578, ""),
|
||||
SODIUM_CHLORIDE_5580(Items.SODIUM_CHLORIDE_5580, ""),
|
||||
VIAL_OF_LIQUID_5582(Items.VIAL_OF_LIQUID_5582, "quest:recruitmentdrive-doorvialofliquid");
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val doorVialsArray = DoorVials.values().map { it.itemId }.toIntArray()
|
||||
val doorVialsMap = DoorVials.values().associateBy { it.itemId }
|
||||
val doorVialsRequiredMap = DoorVials.values().associateBy { it.itemId }.filter { it.value.attribute != "" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun searchingHelper(player: Player, attributeCheck: String, item: Int, searchingDescription: String, objectDescription: String) {
|
||||
queueScript(player, 0, QueueStrength.WEAK) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
sendMessage(player, searchingDescription)
|
||||
return@queueScript delayScript(player, 2)
|
||||
}
|
||||
1 -> {
|
||||
if (attributeCheck != "" && !getAttribute(player, attributeCheck, false)) {
|
||||
setAttribute(player, attributeCheck, true)
|
||||
addItem(player, item)
|
||||
sendMessage(player, objectDescription)
|
||||
} else {
|
||||
sendMessage(player, "You don't find anything interesting.")
|
||||
}
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
|
||||
/** Obtainable Items */
|
||||
|
||||
on(Scenery.OLD_BOOKSHELF_7327, IntType.SCENERY, "search") { player, _ ->
|
||||
searchingHelper(player, attributemagnet, Items.MAGNET_5604, "You search the bookshelves...", "Hidden amongst the books you find a magnet.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.OLD_BOOKSHELF_7328, IntType.SCENERY, "search") { player, _ ->
|
||||
searchingHelper(player, attributebook, Items.ALCHEMICAL_NOTES_5588, "You search the bookshelves...", "You find a book that looks like it might be helpful.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.OLD_BOOKSHELF_7329, IntType.SCENERY, "search") { player, _ ->
|
||||
searchingHelper(player, attributeKnife, Items.KNIFE_5605, "You search the bookshelves...", "Hidden amongst the books you find a knife.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.OLD_BOOKSHELF_7330, IntType.SCENERY, "search") { player, _ ->
|
||||
searchingHelper(player, "", 0, "You search the bookshelves...", "")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.SHELVES_7333, IntType.SCENERY, "search") { player, _ ->
|
||||
val vialList = ArrayList<Int>()
|
||||
if (!getAttribute(player, Vials.vialMap[Items.ACETIC_ACID_5578]!!.attribute, false)) { vialList.add(Items.ACETIC_ACID_5578) }
|
||||
if (!getAttribute(player, Vials.vialMap[Items.VIAL_OF_LIQUID_5582]!!.attribute, false)) { vialList.add(Items.VIAL_OF_LIQUID_5582) }
|
||||
openDialogue(player, VialShelfDialogueFile(vialList.toIntArray()))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.SHELVES_7334, IntType.SCENERY, "search") { player, _ ->
|
||||
val vialList = ArrayList<Int>()
|
||||
if (!getAttribute(player, Vials.vialMap[Items.CUPRIC_SULPHATE_5577]!!.attribute, false)) { vialList.add(Items.CUPRIC_SULPHATE_5577) }
|
||||
openDialogue(player, VialShelfDialogueFile(vialList.toIntArray()))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.SHELVES_7335, IntType.SCENERY, "search") { player, _ ->
|
||||
val vialList = ArrayList<Int>()
|
||||
if (!getAttribute(player, Vials.vialMap[Items.GYPSUM_5579]!!.attribute, false)) { vialList.add(Items.GYPSUM_5579) }
|
||||
openDialogue(player, VialShelfDialogueFile(vialList.toIntArray()))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.SHELVES_7336, IntType.SCENERY, "search") { player, _ ->
|
||||
val vialList = ArrayList<Int>()
|
||||
if (!getAttribute(player, Vials.vialMap[Items.SODIUM_CHLORIDE_5580]!!.attribute, false)) { vialList.add(Items.SODIUM_CHLORIDE_5580) }
|
||||
openDialogue(player, VialShelfDialogueFile(vialList.toIntArray()))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.SHELVES_7337, IntType.SCENERY, "search") { player, _ ->
|
||||
val vialList = ArrayList<Int>()
|
||||
if (!getAttribute(player, Vials.vialMap[Items.NITROUS_OXIDE_5581]!!.attribute, false)) { vialList.add(Items.NITROUS_OXIDE_5581) }
|
||||
openDialogue(player, VialShelfDialogueFile(vialList.toIntArray()))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.SHELVES_7338, IntType.SCENERY, "search") { player, _ ->
|
||||
val vialList = ArrayList<Int>()
|
||||
if (!getAttribute(player, Vials.vialMap[Items.TIN_ORE_POWDER_5583]!!.attribute, false)) { vialList.add(Items.TIN_ORE_POWDER_5583) }
|
||||
openDialogue(player, VialShelfDialogueFile(vialList.toIntArray()))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.SHELVES_7339, IntType.SCENERY, "search") { player, _ ->
|
||||
val vialList = ArrayList<Int>()
|
||||
if (!getAttribute(player, Vials.vialMap[Items.CUPRIC_ORE_POWDER_5584]!!.attribute, false)) { vialList.add(Items.CUPRIC_ORE_POWDER_5584) }
|
||||
openDialogue(player, VialShelfDialogueFile(vialList.toIntArray()))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.SHELVES_7340, IntType.SCENERY, "search") { player, _ ->
|
||||
val vialList = ArrayList<Int>()
|
||||
val total = getAttribute(player, attribute3VialsOfLiquid, 3)
|
||||
for (i in 1..total) { vialList.add(Items.VIAL_OF_LIQUID_5582) }
|
||||
openDialogue(player, VialShelfDialogueFile(vialList.toIntArray(), attribute3VialsOfLiquid))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.CRATE_7347, IntType.SCENERY, "search") { player, node ->
|
||||
if (node.location == Location(2476, 4943)) {
|
||||
searchingHelper(player, attributeTin, Items.TIN_5600, "You search the crate...", "Inside the crate you find a tin.")
|
||||
} else {
|
||||
searchingHelper(player, "", 0, "You search the crate...", "")
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.CRATE_7348, IntType.SCENERY, "search") { player, node ->
|
||||
if (node.location == Location(2476, 4937)) {
|
||||
searchingHelper(player, attributeChisel, Items.CHISEL_5601, "You search the crate...", "Inside the crate you find a chisel.")
|
||||
} else {
|
||||
searchingHelper(player, "", 0, "You search the crate...", "")
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.CRATE_7349, IntType.SCENERY, "search") { player, node ->
|
||||
if (node.location == Location(2475, 4943)) {
|
||||
searchingHelper(player, attributeWire, Items.BRONZE_WIRE_5602, "You search the crate...", "Inside the crate you find some wire.")
|
||||
} else {
|
||||
searchingHelper(player, "", 0, "You search the crate...", "")
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.CLOSED_CHEST_7350, IntType.SCENERY, "open") { player, node ->
|
||||
replaceScenery(node as core.game.node.scenery.Scenery, Scenery.OPEN_CHEST_7351, 100)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.OPEN_CHEST_7351, IntType.SCENERY, "search") { player, _ ->
|
||||
searchingHelper(player, attributeShears, Items.SHEARS_5603, "You search the chest...", "Inside the chest you find some shears.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.OPEN_CHEST_7351, IntType.SCENERY, "close") { player, node ->
|
||||
replaceScenery(node as core.game.node.scenery.Scenery, Scenery.CLOSED_CHEST_7350, -1)
|
||||
return@on true
|
||||
}
|
||||
|
||||
/** Combining Items the correct way */
|
||||
|
||||
onUseWith(ITEM, Items.TIN_5600, Items.GYPSUM_5579) { player, used, with ->
|
||||
if(removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
sendMessage(player, "You empty the vial into the tin.")
|
||||
addItemOrDrop(player, Items.TIN_5592)
|
||||
addItemOrDrop(player, Items.VIAL_229)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.TIN_5592, Items.VIAL_OF_LIQUID_5582) { player, used, with ->
|
||||
if(removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
sendMessage(player, "You empty the vial into the tin.")
|
||||
sendMessage(player, "You notice the tin gets quite warm as you do this.")
|
||||
sendMessage(player, "A lumpy white mixture is made, that seems to be hardening.")
|
||||
addItemOrDrop(player, Items.TIN_5593)
|
||||
addItemOrDrop(player, Items.VIAL_229)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, Items.TIN_5593, Scenery.KEY_7346) { player, used, _ ->
|
||||
if(removeItem(player, used.id)) {
|
||||
sendMessage(player, "You make an impression of the key as the white mixture hardens.")
|
||||
addItemOrDrop(player, Items.TIN_5594)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.TIN_5594, Items.TIN_ORE_POWDER_5583) { player, used, with ->
|
||||
if(removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
sendMessage(player, "You pour the vial into the impression of the key.")
|
||||
addItemOrDrop(player, Items.TIN_5595)
|
||||
addItemOrDrop(player, Items.VIAL_229)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.TIN_5595, Items.CUPRIC_ORE_POWDER_5584) { player, used, with ->
|
||||
if(removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
sendMessage(player, "You pour the vial into the impression of the key.")
|
||||
addItemOrDrop(player, Items.TIN_5597)
|
||||
addItemOrDrop(player, Items.VIAL_229)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.TIN_5594, Items.CUPRIC_ORE_POWDER_5584) { player, used, with ->
|
||||
if(removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
sendMessage(player, "You pour the vial into the impression of the key.")
|
||||
addItemOrDrop(player, Items.TIN_5596)
|
||||
addItemOrDrop(player, Items.VIAL_229)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.TIN_5596, Items.TIN_ORE_POWDER_5583) { player, used, with ->
|
||||
if(removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
sendMessage(player, "You pour the vial into the impression of the key.")
|
||||
addItemOrDrop(player, Items.TIN_5597)
|
||||
addItemOrDrop(player, Items.VIAL_229)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, Items.TIN_5597, Scenery.BUNSEN_BURNER_7332) { player, used, _ ->
|
||||
if(removeItem(player, used.id)) {
|
||||
sendMessage(player, "You heat the two powdered ores together in the tin.")
|
||||
sendMessage(player, "You make a duplicate of the key in bronze.")
|
||||
addItemOrDrop(player, Items.TIN_5598)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.TIN_5598, Items.BRONZE_WIRE_5602, Items.CHISEL_5601, Items.KNIFE_5605) { player, used, with ->
|
||||
if(removeItem(player, used.id)) {
|
||||
sendMessage(player, "You prise the duplicate key out of the tin.")
|
||||
addItemOrDrop(player, Items.TIN_5594)
|
||||
addItemOrDrop(player, Items.BRONZE_KEY_5585)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, Items.METAL_SPADE_5586, Scenery.BUNSEN_BURNER_7332) { player, used, _ ->
|
||||
if(removeItem(player, used.id)) {
|
||||
sendMessage(player, "You burn the wooden handle away from the spade...")
|
||||
sendMessage(player, "...and are left with a metal spade with no handle.")
|
||||
addItemOrDrop(player, Items.ASHES_592)
|
||||
addItemOrDrop(player, Items.METAL_SPADE_5587)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
|
||||
on(Scenery.STONE_DOOR_7343, SCENERY, "study") { player, node ->
|
||||
sendDialogueLines(player, "There is a stone slab here obstructing the door.", "There is a small hole in the slab that looks like it might be for a handle.")
|
||||
sendMessage(player, "It's nearly a perfect fit!")
|
||||
return@on true
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, Items.METAL_SPADE_5587, Scenery.STONE_DOOR_7343) { player, used, _ ->
|
||||
if(removeItem(player, used.id)) {
|
||||
sendMessage(player, "You slide the spade into the hole in the stone...")
|
||||
sendMessage(player, "It's nearly a perfect fit!")
|
||||
setVarbit(player, doorVarbit, 1)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, DoorVials.doorVialsArray, Scenery.STONE_DOOR_7344) { player, used, _ ->
|
||||
if(removeItem(player, used.id)) {
|
||||
setAttribute(player, DoorVials.doorVialsMap[used.id]!!.attribute, true)
|
||||
sendMessage(player, "You pour the vial onto the flat part of the spade.")
|
||||
}
|
||||
if (DoorVials.doorVialsRequiredMap.all { getAttribute(player, it.value.attribute, false) }) {
|
||||
sendMessage(player, "Something caused a reaction when mixed!")
|
||||
sendMessage(player, "The spade gets hotter, and expands slightly.")
|
||||
setVarbit(player, doorVarbit, 2)
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
on(Scenery.STONE_DOOR_7344, SCENERY, "pull-spade") { player, node ->
|
||||
if (DoorVials.doorVialsRequiredMap.all { getAttribute(player, it.value.attribute, false) }) {
|
||||
sendMessage(player, "You pull on the spade...")
|
||||
sendMessage(player, "It works as a handle, and you swing the stone door open.")
|
||||
setVarbit(player, doorVarbit, 3)
|
||||
} else {
|
||||
sendMessage(player, "You pull on the spade...")
|
||||
sendMessage(player, "It comes loose, and slides out of the hole in the stone.")
|
||||
addItemOrDrop(player, Items.METAL_SPADE_5587)
|
||||
setVarbit(player, doorVarbit, 0)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.OPEN_DOOR_7345, SCENERY, "walk-through") { player, node ->
|
||||
if(player.location.x <= 2477) {
|
||||
player.walkingQueue.addPath(2477, 4940)
|
||||
player.walkingQueue.addPath(2478, 4940)
|
||||
} else {
|
||||
player.walkingQueue.addPath(2477, 4940)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class VialShelfDialogueFile(private val flaskIdsArray: IntArray, private val specialAttribute: String? = null) : DialogueBuilderFile() {
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate { _ -> true }.branch { _ -> flaskIdsArray.size }.let { branch ->
|
||||
|
||||
branch.onValue(3)
|
||||
// This is the only shelf with 3 vials of water.
|
||||
.line("There are three vials on this shelf.")
|
||||
.options("Take the vials?").let { optionBuilder ->
|
||||
optionBuilder.option("Take one vial.")
|
||||
.endWith { _, player ->
|
||||
addItemOrDrop(player, flaskIdsArray[0])
|
||||
if (specialAttribute != null) {
|
||||
setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 3) - 1)
|
||||
print(getAttribute(player, specialAttribute, 3))
|
||||
}
|
||||
}
|
||||
optionBuilder.option("Take two vials.")
|
||||
.endWith { _, player ->
|
||||
addItemOrDrop(player, flaskIdsArray[0])
|
||||
addItemOrDrop(player, flaskIdsArray[1])
|
||||
if (specialAttribute != null) {
|
||||
setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 3) - 2)
|
||||
}
|
||||
}
|
||||
optionBuilder.option("Take all three vials.")
|
||||
.endWith { _, player ->
|
||||
addItemOrDrop(player, flaskIdsArray[0])
|
||||
addItemOrDrop(player, flaskIdsArray[1])
|
||||
addItemOrDrop(player, flaskIdsArray[2])
|
||||
if (specialAttribute != null) {
|
||||
setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 3) - 3)
|
||||
}
|
||||
}
|
||||
optionBuilder.option("Don't take a vial.")
|
||||
.end()
|
||||
}
|
||||
branch.onValue(2)
|
||||
.line("There are two vials on this shelf.")
|
||||
.options("Take the vials?").let { optionBuilder ->
|
||||
optionBuilder.option("Take the first vial.")
|
||||
.endWith { _, player ->
|
||||
addItemOrDrop(player, flaskIdsArray[0])
|
||||
if (specialAttribute != null) {
|
||||
setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 2) - 1)
|
||||
} else {
|
||||
setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[0]]!!.attribute, true)
|
||||
}
|
||||
}
|
||||
optionBuilder.option("Take the second vial.")
|
||||
.endWith { _, player ->
|
||||
addItemOrDrop(player, flaskIdsArray[1])
|
||||
if (specialAttribute != null) {
|
||||
setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 2) - 1)
|
||||
} else {
|
||||
setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[1]]!!.attribute, true)
|
||||
}
|
||||
}
|
||||
optionBuilder.option("Take both vials.")
|
||||
.endWith { _, player ->
|
||||
addItemOrDrop(player, flaskIdsArray[0])
|
||||
addItemOrDrop(player, flaskIdsArray[1])
|
||||
if (specialAttribute != null) {
|
||||
setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 2) - 2)
|
||||
} else {
|
||||
setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[0]]!!.attribute, true)
|
||||
setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[1]]!!.attribute, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
branch.onValue(1)
|
||||
.line("There is a vial on this shelf.")
|
||||
.options("Take the vial?").let { optionBuilder ->
|
||||
optionBuilder.option("YES")
|
||||
.endWith { _, player ->
|
||||
addItemOrDrop(player, flaskIdsArray[0])
|
||||
if (specialAttribute != null) {
|
||||
setAttribute(player, specialAttribute, getAttribute(player, specialAttribute, 1) - 1)
|
||||
} else {
|
||||
setAttribute(player, MissCheeversRoomListeners.Companion.Vials.vialMap[flaskIdsArray[0]]!!.attribute, true)
|
||||
}
|
||||
}
|
||||
optionBuilder.option("NO")
|
||||
.end()
|
||||
}
|
||||
|
||||
branch.onValue(0)
|
||||
.line("There is nothing of interest on these shelves.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
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.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
@Initializable
|
||||
class MsHynnTerprettDialogue (player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
openDialogue(player, MsHynnTerprettDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
override fun newInstance(player: Player): DialoguePlugin {
|
||||
return MsHynnTerprettDialogue(player)
|
||||
}
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.MS_HYNN_TERPRETT_2289)
|
||||
}
|
||||
}
|
||||
|
||||
class MsHynnTerprettDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() {
|
||||
companion object {
|
||||
const val attributeRandomRiddle = "quest:recruitmentdrive-randomriddle"
|
||||
const val attributeRecentlyCorrect = "quest:recruitmentdrive-recentlycorrect"
|
||||
}
|
||||
|
||||
override fun create(b: DialogueBuilder) {
|
||||
|
||||
b.onPredicate { player -> true }.branch { player ->
|
||||
if (getAttribute(player, attributeRecentlyCorrect, false)) {
|
||||
return@branch 3
|
||||
} else if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1) {
|
||||
return@branch 2
|
||||
} else if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1) {
|
||||
return@branch 1
|
||||
} else {
|
||||
return@branch 0
|
||||
}
|
||||
}.let { branch ->
|
||||
/** Failed Branch */
|
||||
val failedStage = b.placeholder()
|
||||
failedStage.builder()
|
||||
.npc(FacialExpression.SAD, "No... I am very sorry.", "Apparently you are not up to the challenge.", "I will return you where you came from, better luck in the", "future.")
|
||||
.endWith { _, player ->
|
||||
removeAttribute(player, attributeRandomRiddle)
|
||||
removeAttribute(player, attributeRecentlyCorrect)
|
||||
removeAttribute(player, RecruitmentDrive.attributeStagePassFailState)
|
||||
RecruitmentDriveListeners.FailTestCutscene(player).start()
|
||||
}
|
||||
/** Passed Branch */
|
||||
val passedStage = b.placeholder()
|
||||
passedStage.builder()
|
||||
.betweenStage { _, player, _, _ ->
|
||||
removeAttribute(player, attributeRandomRiddle)
|
||||
removeAttribute(player, attributeRecentlyCorrect)
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) {
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1)
|
||||
}
|
||||
}
|
||||
.npc("Excellent work, @name.", "Please step through the portal to meet your next", "challenge.")
|
||||
.end()
|
||||
|
||||
branch.onValue(3) // Passed stage
|
||||
.goto(passedStage)
|
||||
branch.onValue(2) // Failed stage
|
||||
.goto(failedStage)
|
||||
branch.onValue(1) // Already passed stage
|
||||
.npc("You certainly have the wits to be a Temple Knight.", "Pass on through the portal to find your next challenge.")
|
||||
.end()
|
||||
branch.onValue(0)
|
||||
.betweenStage { _, player, _, _ ->
|
||||
if (getAttribute(player, attributeRandomRiddle, -1) !in 0..4) {
|
||||
setAttribute(player, attributeRandomRiddle, (0..4).random())
|
||||
}
|
||||
}
|
||||
.npc("Greetings, @name.", "I am here to test your wits with a simple riddle.")
|
||||
.branch { player -> getAttribute(player, attributeRandomRiddle, 0) }
|
||||
.let { branch ->
|
||||
branch.onValue(0)
|
||||
.npc(FacialExpression.THINKING, "Here is my riddle:", "I estimate there to be one million inhabitants in the world", "of @servername, creatures and people both.")
|
||||
.npc(FacialExpression.THINKING, "What number would you get if you multiply", "the number of fingers on everything's left hand, to the", "nearest million?")
|
||||
.manualStage { _, player, _, _ ->
|
||||
sendInputDialogue(player, false, "Enter the amount:") { value: Any ->
|
||||
if(value == "0") {
|
||||
setAttribute(player, attributeRecentlyCorrect, true)
|
||||
} else {
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
}
|
||||
openDialogue(player, MsHynnTerprettDialogueFile(), NPC(NPCs.MS_HYNN_TERPRETT_2289))
|
||||
return@sendInputDialogue
|
||||
}
|
||||
}
|
||||
.end()
|
||||
|
||||
branch.onValue(1)
|
||||
.npc(FacialExpression.THINKING, "Here is my riddle:", "Which of the following statements is true?")
|
||||
.options().let { optionBuilder ->
|
||||
optionBuilder.option("The number of false statements here is one.").goto(failedStage)
|
||||
optionBuilder.option("The number of false statements here is two.").goto(failedStage)
|
||||
optionBuilder.option("The number of false statements here is three.").goto(passedStage)
|
||||
optionBuilder.option("The number of false statements here is four.").goto(failedStage)
|
||||
}
|
||||
|
||||
branch.onValue(2)
|
||||
.npc(FacialExpression.THINKING, "Here is my riddle:", "I have both a husband and daughter.")
|
||||
.npc(FacialExpression.THINKING, "My husband is four times older than my daughter. ", "In twenty years time, he will be twice as old as my", "daughter.")
|
||||
.npc(FacialExpression.THINKING, "How old is my daughter now?")
|
||||
.manualStage { _, player, _, _ ->
|
||||
sendInputDialogue(player, true, "Enter the amount:") { value: Any ->
|
||||
if(value == 10) {
|
||||
setAttribute(player, attributeRecentlyCorrect, true)
|
||||
} else {
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
}
|
||||
openDialogue(player, MsHynnTerprettDialogueFile(), NPC(NPCs.MS_HYNN_TERPRETT_2289))
|
||||
return@sendInputDialogue
|
||||
}
|
||||
}
|
||||
.end()
|
||||
|
||||
branch.onValue(3)
|
||||
.npc(FacialExpression.THINKING, "Here is my riddle:", "Imagine that you have been captured by an enemy.", "You are to be killed, but in a moment of mercy, the", "enemy has allowed you to pick your own demise.")
|
||||
.npc(FacialExpression.THINKING, "Your first choice is to be drowned in a lake of acid.")
|
||||
.npc(FacialExpression.THINKING, "Your second choice is to be burned on a fire.")
|
||||
.npc(FacialExpression.THINKING, "Your third choice is to be thrown to a pack of wolves", "that have not been fed in over a month.")
|
||||
.npc(FacialExpression.THINKING, "Your final choice of fate is to be thrown from the walls", "of a castle, many hundreds of feet high.")
|
||||
.npc(FacialExpression.THINKING, "Which fate would you be wise to choose?")
|
||||
.options().let { optionBuilder ->
|
||||
optionBuilder.option("The lake of acid.").goto(failedStage)
|
||||
optionBuilder.option("The large fire.").goto(failedStage)
|
||||
optionBuilder.option("The wolves.").goto(passedStage)
|
||||
optionBuilder.option("The castle walls.").goto(failedStage)
|
||||
}
|
||||
|
||||
branch.onValue(4)
|
||||
.npc(FacialExpression.THINKING, "Here is my riddle:", "I dropped four identical stones, into four identical", "buckets, each containing an identical amount of water.")
|
||||
.npc(FacialExpression.THINKING, "The first bucket's water was at 32 degrees Fahrenheit,", "the second was at 33 degrees, the third at 34 and the", "fourth was at 35 degrees.")
|
||||
.npc(FacialExpression.THINKING, "Which bucket's stone dropped to the bottom of the bucket", "last?")
|
||||
.options().let { optionBuilder ->
|
||||
optionBuilder.option("Bucket A (32 degrees)").goto(passedStage)
|
||||
optionBuilder.option("Bucket B (33 degrees)").goto(failedStage)
|
||||
optionBuilder.option("Bucket C (34 degrees)").goto(failedStage)
|
||||
optionBuilder.option("Bucket D (35 degrees)").goto(failedStage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
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
|
||||
|
||||
/**
|
||||
* Recruitment Drive Quest
|
||||
*
|
||||
* https://www.youtube.com/watch?v=0yvFREeXNn0 - Quest start log only.
|
||||
* https://www.youtube.com/watch?v=lNlSiUvPL1o - Very good
|
||||
* https://www.youtube.com/watch?v=OGWpX1WqpKM 10:12 - Final congrats page.
|
||||
* https://www.youtube.com/watch?v=nu4OAswRcGg - Speaking to Tiffy after the quest (IMPORTANT!)
|
||||
* https://www.youtube.com/watch?v=srFMJa4nuX0 1:47 blur ass quest log again
|
||||
* https://www.youtube.com/watch?v=L7NdDTWa-1Q HAZEEL's CULT
|
||||
* 1 - Speak to Sir Amik Varze.
|
||||
* 2 - Sent to secret training ground.
|
||||
* 3 - Finish all stages.
|
||||
* 100 - Finish by talking to Tiffy.
|
||||
*/
|
||||
@Initializable
|
||||
class RecruitmentDrive : Quest("Recruitment Drive", 103, 102, 1, 496, 0, 1, 2) {
|
||||
companion object {
|
||||
const val questName = "Recruitment Drive"
|
||||
const val attributeOriginalGender = "/save:quest:recruitmentdrive-originalgender"
|
||||
|
||||
// Stage state: (0: reset), (1: passed), (-1: failed)
|
||||
const val attributeStagePassFailState = "/save:quest:recruitmentdrive-stagestate"
|
||||
const val attributeCurrentStage = "/save:quest:recruitmentdrive-currentstage"
|
||||
const val attributeStage1 = "/save:quest:recruitmentdrive-stage1"
|
||||
const val attributeStage2 = "/save:quest:recruitmentdrive-stage2"
|
||||
const val attributeStage3 = "/save:quest:recruitmentdrive-stage3"
|
||||
const val attributeStage4 = "/save:quest:recruitmentdrive-stage4"
|
||||
const val attributeStage5 = "/save:quest:recruitmentdrive-stage5"
|
||||
val attributeStageArray = arrayOf(attributeStage1, attributeStage2, attributeStage3, attributeStage4, attributeStage5)
|
||||
}
|
||||
|
||||
override fun drawJournal(player: Player, stage: Int) {
|
||||
super.drawJournal(player, stage)
|
||||
var line = 12
|
||||
var stage = getStage(player)
|
||||
|
||||
var started = getQuestStage(player, questName) > 0
|
||||
|
||||
if(!started){
|
||||
line(player, "I can start this quest by speaking to !!Sir Amik Varze??,", line++)
|
||||
line(player, "upstairs in !!Falador Castle,??", line++)
|
||||
if (isQuestComplete(player, "Druidic Ritual")) {
|
||||
line(player, "with the Druidic Ritual Quest completed,", line++, true)
|
||||
} else {
|
||||
line(player, "with the !!Druidic Ritual Quest?? completed,", line++)
|
||||
}
|
||||
if (isQuestComplete(player, "Black Knights' Fortress")) {
|
||||
line(player, "and since I have completed the Black Knights' Fortress", line++, true)
|
||||
line(player, "Quest.", line++, true)
|
||||
} else {
|
||||
line(player, "and after I have completed the !!Black Knights' Fortress??", line++)
|
||||
line(player, "Quest.", line++)
|
||||
}
|
||||
} else {
|
||||
line(player, "Sir Amik Varze told me that he had put my name forward as", line++, true)
|
||||
line(player, "a potential member of some mysterious organisation.", line++, true)
|
||||
|
||||
if (stage >= 2) {
|
||||
} else if (stage >= 1) {
|
||||
line(player, "I should head to !!Falador Park?? to meet my !!Contact?? so that I", line++, false)
|
||||
line(player, "can begin my !!testing for the job??", line++, false)
|
||||
}
|
||||
|
||||
if (stage >= 3) {
|
||||
line(player, "I went to Falador Park, and met a strange old man named", line++, true)
|
||||
line(player, "Tiffy.", line++, true)
|
||||
line(player, "He sent me to a secret training ground, where my wits", line++, true)
|
||||
line(player, "were thoroughly tested.", line++, true)
|
||||
line(player, "Luckily, I was too smart to fall for any of their little tricks,", line++, true)
|
||||
line(player, "and passed the test with flying colours.", line++, true)
|
||||
} else if (stage >= 2) {
|
||||
line(player, "I went to !!Falador Park??, and met a strange old man named", line++, false)
|
||||
line(player, "!!Tiffy??.", line++, false)
|
||||
line(player, "He sent me to a !!secret training ground??, where my wits", line++, false)
|
||||
line(player, "were thoroughly tested.", line++, false)
|
||||
}
|
||||
|
||||
if (stage >= 4) {
|
||||
line(player, "I am now an official member of the Temple Knights,", line++, true)
|
||||
line(player, "although I have to wait for the paperwork to go through", line++, true)
|
||||
line(player, "before I can commence working for them.", line++, true)
|
||||
} else if (stage >= 3) {
|
||||
line(player, "I should talk to !!Tiffy?? to become a Temple Knight.", line++, false)
|
||||
}
|
||||
if (stage >= 100) {
|
||||
line++
|
||||
line(player,"<col=FF0000>QUEST COMPLETE!</col>", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun reset(player: Player) {
|
||||
removeAttribute(player, attributeOriginalGender)
|
||||
removeAttribute(player, attributeStagePassFailState)
|
||||
removeAttribute(player, attributeCurrentStage)
|
||||
removeAttribute(player, attributeStage1)
|
||||
removeAttribute(player, attributeStage2)
|
||||
removeAttribute(player, attributeStage3)
|
||||
removeAttribute(player, attributeStage4)
|
||||
removeAttribute(player, attributeStage5)
|
||||
}
|
||||
|
||||
override fun finish(player: Player) {
|
||||
var ln = 10
|
||||
super.finish(player)
|
||||
player.packetDispatch.sendString("You have passed the Recruitment Drive!", 277, 4)
|
||||
player.packetDispatch.sendItemZoomOnInterface(Items.INITIATE_SALLET_5574, 230, 277, 5)
|
||||
|
||||
drawReward(player, "1 Quest Point", ln++)
|
||||
drawReward(player, "1000 Prayer, Herblore and", ln++)
|
||||
drawReward(player, "Agility XP", ln++)
|
||||
drawReward(player, "Gaze of Saradomin", ln++)
|
||||
drawReward(player, "Temple Knight's Initiate Helm", ln)
|
||||
|
||||
rewardXP(player, Skills.PRAYER, 1000.0)
|
||||
rewardXP(player, Skills.HERBLORE, 1000.0)
|
||||
rewardXP(player, Skills.AGILITY, 1000.0)
|
||||
addItem(player, Items.INITIATE_SALLET_5574)
|
||||
}
|
||||
|
||||
override fun newInstance(`object`: Any?): Quest {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,316 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau
|
||||
import core.ServerConstants
|
||||
import core.api.*
|
||||
import core.game.activity.Cutscene
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.global.action.DoorActionHandler
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.Entity
|
||||
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.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.ZoneRestriction
|
||||
import core.net.packet.PacketRepository
|
||||
import core.net.packet.context.MinimapStateContext
|
||||
import core.net.packet.out.MinimapState
|
||||
import org.rs09.consts.*
|
||||
|
||||
class RecruitmentDriveListeners : InteractionListener {
|
||||
companion object {
|
||||
|
||||
enum class Stages(val npc: Int, val startLocation: Location, val startWalkLocation: Location, val quitPortal: Int, val successDoor: Int) {
|
||||
SIR_SPISHYUS(NPCs.SIR_SPISHYUS_2282, Location(2490, 4972), Location(2489, 4972), Scenery.PORTAL_7272, Scenery.DOOR_7274),
|
||||
LADY_TABLE(NPCs.LADY_TABLE_2283, Location(2460, 4979), Location(2459, 4979), Scenery.PORTAL_7288, Scenery.DOOR_7302),
|
||||
SIR_KUAM_FERENTSE(NPCs.SIR_KUAM_FERENTSE_2284, Location(2455, 4964), Location(2456, 4964), Scenery.PORTAL_7315, Scenery.DOOR_7317),
|
||||
SIR_TINLEY(NPCs.SIR_TINLEY_2286, Location(2471, 4956), Location(2472, 4956), Scenery.PORTAL_7318, Scenery.DOOR_7320),
|
||||
SIR_REN_ITCHOOD(NPCs.SIR_REN_ITCHOOD_2287, Location(2439, 4956), Location(2440, 4956), Scenery.PORTAL_7321, Scenery.DOOR_7323),
|
||||
MISS_CHEEVERS(NPCs.MISS_CHEEVERS_2288, Location(2467, 4940), Location(2468, 4940), Scenery.PORTAL_7324, Scenery.DOOR_7326),
|
||||
MS_HYNN_TERPRETT(NPCs.MS_HYNN_TERPRETT_2289, Location(2451, 4935), Location(2451, 4936), Scenery.PORTAL_7352, Scenery.DOOR_7354);
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val indexMap = Stages.values().associateBy { it.ordinal }
|
||||
val indexArray = Stages.indexMap.keys.map { it }
|
||||
val quitPortalArray = Stages.indexMap.values.map { it.quitPortal }.toIntArray()
|
||||
val successDoorArray = Stages.indexMap.values.map { it.successDoor }.toIntArray()
|
||||
}
|
||||
}
|
||||
|
||||
fun shuffleStages(player: Player) {
|
||||
// Obtain an array to shuffle. Must be at least [5] long.
|
||||
val stagesArrayToShuffle = intArrayOf(0,1,2,3,4,5,6) // Stages.indexArray.toIntArray()
|
||||
stagesArrayToShuffle.shuffle()
|
||||
setAttribute(player, RecruitmentDrive.attributeStage1, stagesArrayToShuffle[0])
|
||||
setAttribute(player, RecruitmentDrive.attributeStage2, stagesArrayToShuffle[1])
|
||||
setAttribute(player, RecruitmentDrive.attributeStage3, stagesArrayToShuffle[2])
|
||||
setAttribute(player, RecruitmentDrive.attributeStage4, stagesArrayToShuffle[3])
|
||||
setAttribute(player, RecruitmentDrive.attributeStage5, stagesArrayToShuffle[4])
|
||||
setAttribute(player, RecruitmentDrive.attributeCurrentStage, 0)
|
||||
removeAttribute(player, RecruitmentDrive.attributeStagePassFailState)
|
||||
}
|
||||
|
||||
fun callStartingDialogues (player: Player, npc: Int) {
|
||||
when (npc) {
|
||||
NPCs.SIR_SPISHYUS_2282 -> openDialogue(player, SirSpishyusDialogueFile(1), NPC(npc))
|
||||
NPCs.LADY_TABLE_2283 -> openDialogue(player, LadyTableDialogueFile(1), NPC(npc))
|
||||
NPCs.SIR_KUAM_FERENTSE_2284 -> openDialogue(player, SirKuamFerentseDialogueFile(1), NPC(npc))
|
||||
NPCs.SIR_TINLEY_2286 -> openDialogue(player, SirTinleyDialogueFile(1), NPC(npc))
|
||||
NPCs.SIR_REN_ITCHOOD_2287 -> openDialogue(player, SirRenItchwoodDialogueFile(1), NPC(npc))
|
||||
NPCs.MISS_CHEEVERS_2288 -> openDialogue(player, MissCheeversDialogueFile(1), NPC(npc))
|
||||
NPCs.MS_HYNN_TERPRETT_2289 -> openDialogue(player, MsHynnTerprettDialogueFile(1), NPC(npc))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
|
||||
on(Stages.quitPortalArray, IntType.SCENERY, "use") { player, node ->
|
||||
FailTestCutscene(player).start()
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Stages.successDoorArray, IntType.SCENERY, "open") { player, node ->
|
||||
// This is specially for Miss Cheevers
|
||||
if (inInventory(player, Items.BRONZE_KEY_5585)) {
|
||||
sendMessage(player, "You use the duplicate key you made to unlock the door.")
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1)
|
||||
}
|
||||
// Success Door
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1) {
|
||||
removeAttribute(player, RecruitmentDrive.attributeStagePassFailState)
|
||||
setAttribute(player, RecruitmentDrive.attributeCurrentStage, getAttribute(player, RecruitmentDrive.attributeCurrentStage, 0) + 1)
|
||||
DoorActionHandler.handleAutowalkDoor(player, node as core.game.node.scenery.Scenery)
|
||||
val currentLevel = getAttribute(player, RecruitmentDrive.attributeCurrentStage, 0)
|
||||
if (currentLevel >= 5) {
|
||||
CompleteTestCutscene(player).start()
|
||||
return@on true
|
||||
}
|
||||
val currentStage = getAttribute(player, RecruitmentDrive.attributeStageArray[currentLevel], 0)
|
||||
val currentStageEnum = Stages.indexMap[currentStage]!!
|
||||
closeDialogue(player)
|
||||
|
||||
// This is specifically for Sir Spishyus to reset the fox, chicken, grain
|
||||
SirSpishyusRoomListeners.resetStage(player)
|
||||
|
||||
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
player.inventory.clear()
|
||||
player.equipment.clear()
|
||||
openOverlay(player, Components.FADE_TO_BLACK_120)
|
||||
return@queueScript delayScript(player, 6)
|
||||
}
|
||||
1 -> {
|
||||
teleport(player, currentStageEnum.startLocation)
|
||||
return@queueScript delayScript(player, 2)
|
||||
}
|
||||
2 -> {
|
||||
openOverlay(player, Components.FADE_FROM_BLACK_170)
|
||||
return@queueScript delayScript(player, 2)
|
||||
}
|
||||
3 -> {
|
||||
forceWalk(player, currentStageEnum.startWalkLocation, "dumb")
|
||||
return@queueScript delayScript(player, 2)
|
||||
}
|
||||
4 -> {
|
||||
callStartingDialogues(player, currentStageEnum.npc)
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(node.id == Scenery.DOOR_7323) {
|
||||
// This is specifically for SirRenItchwood
|
||||
openInterface(player, Components.RD_COMBOLOCK_285)
|
||||
} else {
|
||||
sendMessage(player, "You have not completed this room's puzzle yet.")
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
/** Starting Recruitment Drive test cutscene */
|
||||
class StartTestCutscene(player: Player) : Cutscene(player) {
|
||||
override fun setup() {
|
||||
loadRegion(9805)
|
||||
val currentStage = getAttribute(player, RecruitmentDrive.attributeStageArray[0], 0)
|
||||
setExit(Stages.indexMap[currentStage]!!.startLocation)
|
||||
}
|
||||
|
||||
override fun runStage(stage: Int) {
|
||||
when (stage) {
|
||||
0 -> {
|
||||
fadeToBlack()
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2))
|
||||
timedUpdate(6)
|
||||
}
|
||||
1 -> {
|
||||
dialogueLinesUpdate(NPCs.SIR_TIFFY_CASHIEN_2290, FacialExpression.HAPPY, "Here we go!", "Mind your head!")
|
||||
timedUpdate(3)
|
||||
}
|
||||
2 -> {
|
||||
dialogueLinesUpdate(NPCs.SIR_TIFFY_CASHIEN_2290, FacialExpression.HAPPY, "Oops. Ignore the smell!", "Nearly there!")
|
||||
timedUpdate(3)
|
||||
}
|
||||
3 -> {
|
||||
dialogueLinesUpdate(NPCs.SIR_TIFFY_CASHIEN_2290, FacialExpression.HAPPY, "And...", "Here we are!", "Best of luck!")
|
||||
timedUpdate(3)
|
||||
}
|
||||
4 -> {
|
||||
player.inventory.clear()
|
||||
player.equipment.clear()
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0))
|
||||
dialogueClose()
|
||||
endWithoutFade {
|
||||
val currentStage = getAttribute(player, RecruitmentDrive.attributeStageArray[0], 0)
|
||||
val firstStage = Stages.indexMap[currentStage]!!
|
||||
|
||||
// This is specifically for Sir Spishyus to reset the fox, chicken, grain
|
||||
SirSpishyusRoomListeners.resetStage(player)
|
||||
|
||||
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
fadeFromBlack()
|
||||
return@queueScript delayScript(player, 2)
|
||||
}
|
||||
1 -> {
|
||||
forceWalk(player, firstStage.startWalkLocation, "dumb")
|
||||
return@queueScript delayScript(player, 2)
|
||||
}
|
||||
2 -> {
|
||||
callStartingDialogues(player, firstStage.npc)
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Failed Recruitment Drive test cutscene */
|
||||
class FailTestCutscene(player: Player) : Cutscene(player) {
|
||||
override fun setup() {
|
||||
loadRegion(9805)
|
||||
setExit(Location(2997, 3374))
|
||||
}
|
||||
|
||||
override fun runStage(stage: Int) {
|
||||
when (stage) {
|
||||
0 -> {
|
||||
closeDialogue(player)
|
||||
fadeToBlack()
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2))
|
||||
timedUpdate(6)
|
||||
}
|
||||
1 -> {
|
||||
var clearBoss = getAttribute(player, SirKuamFerentseDialogueFile.attributeGeneratedSirLeye, NPC(0))
|
||||
if (clearBoss.id != 0) {
|
||||
clearBoss.clear()
|
||||
}
|
||||
player.inventory.clear()
|
||||
player.equipment.clear()
|
||||
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
fadeFromBlack()
|
||||
return@queueScript delayScript(player, 2)
|
||||
}
|
||||
1 -> {
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0))
|
||||
openDialogue(player, SirTiffyCashienFailedDialogueFile(), NPC(NPCs.SIR_TIFFY_CASHIEN_2290))
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
endWithoutFade {
|
||||
face(player, Location(2997, 3373))
|
||||
fadeFromBlack()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Complete Recruitment Drive test cutscene */
|
||||
class CompleteTestCutscene(player: Player) : Cutscene(player) {
|
||||
override fun setup() {
|
||||
loadRegion(9805)
|
||||
setExit(Location(2996, 3375))
|
||||
}
|
||||
|
||||
override fun runStage(stage: Int) {
|
||||
when (stage) {
|
||||
0 -> {
|
||||
if (getQuestStage(player, RecruitmentDrive.questName) == 2) {
|
||||
setQuestStage(player, RecruitmentDrive.questName, 3)
|
||||
}
|
||||
closeDialogue(player)
|
||||
fadeToBlack()
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2))
|
||||
timedUpdate(6)
|
||||
}
|
||||
1 -> {
|
||||
player.inventory.clear()
|
||||
player.equipment.clear()
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
fadeFromBlack()
|
||||
return@queueScript delayScript(player, 2)
|
||||
}
|
||||
1 -> {
|
||||
openDialogue(player, SirTiffyCashienDialogueFile(), NPC(NPCs.SIR_TIFFY_CASHIEN_2290))
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
endWithoutFade {
|
||||
face(player, Location(2997, 3373))
|
||||
fadeFromBlack()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LogoutRecruitmentDrive : MapArea {
|
||||
override fun defineAreaBorders(): Array<ZoneBorders> {
|
||||
return arrayOf(getRegionBorders(9805))
|
||||
}
|
||||
|
||||
override fun getRestrictions(): Array<ZoneRestriction> {
|
||||
return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS)
|
||||
}
|
||||
|
||||
override fun areaLeave(entity: Entity, logout: Boolean) {
|
||||
if (entity is Player) {
|
||||
// This is specifically for Sir Spishyus to reset the fox, chicken, grain
|
||||
SirSpishyusRoomListeners.resetStage(entity)
|
||||
// Clear inventory whenever you leave the recruitment drive area
|
||||
entity.inventory.clear()
|
||||
entity.equipment.clear()
|
||||
// Teleport you out if you log out. You should do this in one sitting.
|
||||
if (logout) {
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(entity, 0))
|
||||
teleport(entity, Location(2996, 3375))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
import core.api.*
|
||||
import core.game.dialogue.*
|
||||
|
||||
class SirAmikVarzeDialogueFile : DialogueBuilderFile() {
|
||||
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onQuestStages(RecruitmentDrive.questName, 0)
|
||||
.npcl(FacialExpression.FRIENDLY,"Hello, friend!")
|
||||
.playerl(FacialExpression.THINKING, "Do you have any other quests for me to do?")
|
||||
.branch { player -> if(isQuestComplete(player, "Black Knights' Fortress") && isQuestComplete(player, "Druidic Ritual")) { 1 } else { 0 } }
|
||||
.let{ branch ->
|
||||
// Failure branch
|
||||
branch.onValue(0)
|
||||
.npcl(FacialExpression.THINKING, "A quest? Alas I do not have any quests I can offer you at this time.")
|
||||
.end()
|
||||
return@let branch // Return DialogueBranchBuilder instead of DialogueBuilder to forward the success branch.
|
||||
}.onValue(1) // Success branch
|
||||
.npc("Quests, eh?", "Well, I don't have anything on the go at the moment,", "but there is an organisation that is always looking for", "capable adventurers to assist them.")
|
||||
.npc(FacialExpression.FRIENDLY,"Your excellent work sorting out those Black Knights", "means I will happily write you a letter of", "recommendation.")
|
||||
.npc("Would you like me to put your name forwards to", "them?")
|
||||
.options().let { optionBuilder ->
|
||||
optionBuilder.option ("Yes please")
|
||||
.playerl("Sure thing Sir Amik, sign me up!")
|
||||
.npc(FacialExpression.SUSPICIOUS,"Erm, well, this is a little embarrassing, I already HAVE", "put you forward as a potential member.")
|
||||
.npc("They are the Temple Knights, and you are to", "meet Sir Tiffy Cashien in Falador park for testing", "immediately.")
|
||||
.playerl("Okey dokey, I'll go do that then.")
|
||||
.endWith { _, player ->
|
||||
if(getQuestStage(player, RecruitmentDrive.questName) == 0) {
|
||||
setAttribute(player, RecruitmentDrive.attributeOriginalGender, player.isMale)
|
||||
setQuestStage(player, RecruitmentDrive.questName, 1)
|
||||
}
|
||||
}
|
||||
optionBuilder.option_playerl("No thanks")
|
||||
.end()
|
||||
optionBuilder.option("Tell me about this organization...")
|
||||
.npc(FacialExpression.SUSPICIOUS,"I cannot tell you much...", "They are called the Temple Knights, and are an", "organisation that was founded by Saradomin personally", "many centuries ago.")
|
||||
.npc("There are many rumours and fables about their works and", "actions, but official records of their presence are non-", "existent.")
|
||||
.npc("It is a secret organisation of extraordinary power and", "resourcefulness...")
|
||||
.npc("Let me put it this way:", "Should you decide to take them up on their generous", "offer to join, you will find yourself in an advantageous", "position that many in this world would envy, and that few")
|
||||
.npc("are called to occupy.")
|
||||
.playerl("Well, that wasn't quite as helpful as I thought it would be...but thanks anyway, I guess.")
|
||||
.end()
|
||||
}
|
||||
|
||||
b.onQuestStages(RecruitmentDrive.questName, 1,2,3,4)
|
||||
.npcl(FacialExpression.FRIENDLY,"Hello, friend!")
|
||||
.playerl(FacialExpression.THINKING, "Can I just skip the test to become a Temple Knight?")
|
||||
.npcl("No, I'm afraid not. I suggest you go meet Sir Tiffy in Falador Park, he will be expecting you.")
|
||||
.end()
|
||||
|
||||
// This should be after the Wanted Quest, but is the placeholder until that quest is implemented.
|
||||
b.onQuestStages(RecruitmentDrive.questName, 100)
|
||||
.npcl(FacialExpression.FRIENDLY,"Hello, friend!")
|
||||
.npcl(FacialExpression.FRIENDLY,"Well @name, now that you are a White Knight, I expect you should be out there hunting Black Knights for us!")
|
||||
.options().let { optionBuilder ->
|
||||
optionBuilder.option_playerl("Can you explain the White Knight honour system again?")
|
||||
.npcl("Sadly we are not as rich as we once were, and there are many White Knights who foolishly lose their combat equipment.")
|
||||
.npcl("We do not think it fair to make a profit from our brethren, so we will sell you equipment at cost, and rebuy it at the same cost, but we will only sell equipment to those we consider responsible enough to")
|
||||
.npcl("wield it correctly.")
|
||||
.npcl("By killing Black Knights, you will increase your reputation with us, by killing White Knights we will obviously think less of you.")
|
||||
.npcl("You can check your White Knight reputation level by looking at your quest journal for the Wanted! Quest, or Sir Vyvin will let you know what level you are at when you go to purchase equipment.")
|
||||
.npcl("Sir Vyvin can be found in Falador Castle, and he will sell you any equipment appropriate to your reputation level.")
|
||||
.npcl("Have fun, and go kill some Black Knights for me!")
|
||||
.playerl("Okay Amik, thanks for explaining!")
|
||||
.end()
|
||||
|
||||
optionBuilder.option("Okay, bye!")
|
||||
.playerl("Okay, 'bye then Amik!")
|
||||
.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
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.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.Location
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
@Initializable
|
||||
class SirKuamFerentseDialogue (player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
openDialogue(player, SirKuamFerentseDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
override fun newInstance(player: Player): DialoguePlugin {
|
||||
return SirKuamFerentseDialogue(player)
|
||||
}
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.SIR_KUAM_FERENTSE_2284)
|
||||
}
|
||||
}
|
||||
|
||||
class SirKuamFerentseDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() {
|
||||
companion object {
|
||||
const val attributeGeneratedSirLeye = "quest:recruitmentdrive-generatedsirleye"
|
||||
}
|
||||
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate { player -> getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1 }
|
||||
.npc(FacialExpression.FRIENDLY, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.")
|
||||
.end()
|
||||
|
||||
// You can't fail unless you quit the room.
|
||||
b.onPredicate { _ -> true }
|
||||
.npc("Ah, @name, you're finally here.", "Your task for this room is to defeat Sir Leye.", "He has been blessed by Saradomin to be undefeatable", "by any man, so it should be quite the challenge for you.")
|
||||
.npc("If you are having problems, remember", "A true warrior uses his wits as much as his brawn.", "Fight smarter, not harder.")
|
||||
.endWith { _, player ->
|
||||
var boss = getAttribute(player, attributeGeneratedSirLeye, NPC(0))
|
||||
if (boss.id != 0) {
|
||||
boss.clear()
|
||||
}
|
||||
boss = NPC(NPCs.SIR_LEYE_2285, player.location)
|
||||
setAttribute(player, attributeGeneratedSirLeye, boss)
|
||||
boss.isRespawn = false
|
||||
boss.isAggressive = false
|
||||
boss.isWalks = true
|
||||
boss.location = Location(2460, 4963)
|
||||
boss.init()
|
||||
registerHintIcon(player, boss)
|
||||
sendChat(boss, "No man may defeat me!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
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.entity.skill.Skills
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
class SirLeyeBehavior : NPCBehavior(NPCs.SIR_LEYE_2285) {
|
||||
var clearTime = 0
|
||||
|
||||
override fun tick(self: NPC): Boolean {
|
||||
// You have 400 ticks to kill Sir Leye
|
||||
if (clearTime++ > 400) {
|
||||
clearTime = 0
|
||||
poofClear(self)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) {
|
||||
val lifepoints = self.skills.lifepoints
|
||||
if (attacker is Player) {
|
||||
// If you are male, Sir Leye will recover to full health.
|
||||
if (attacker.isMale) {
|
||||
if (state.estimatedHit + Integer.max(state.secondaryHit, 0) > lifepoints - 1) {
|
||||
self.skills.lifepoints = self.getSkills().getStaticLevel(Skills.HITPOINTS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDeathFinished(self: NPC, killer: Entity) {
|
||||
if (killer is Player) {
|
||||
clearHintIcon(killer)
|
||||
setAttribute(killer, RecruitmentDrive.attributeStagePassFailState, 1)
|
||||
removeAttribute(killer, SirKuamFerentseDialogueFile.attributeGeneratedSirLeye)
|
||||
}
|
||||
}
|
||||
|
||||
// No xp from attacking this dude.
|
||||
override fun getXpMultiplier(self: NPC, attacker: Entity): Double {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
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.InterfaceListener
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.Location
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
@Initializable
|
||||
class SirRenItchwoodDialogue (player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
openDialogue(player, SirRenItchwoodDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
override fun newInstance(player: Player): DialoguePlugin {
|
||||
return SirRenItchwoodDialogue(player)
|
||||
}
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.SIR_REN_ITCHOOD_2287)
|
||||
}
|
||||
}
|
||||
|
||||
class SirRenItchwoodDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() {
|
||||
companion object {
|
||||
const val attributeClueNumber = "quest:recruitmentdrive-cluenumber"
|
||||
}
|
||||
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate { player -> dialogueNum in 0..1 && getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) != -1 }
|
||||
.betweenStage { _, player, _, _ ->
|
||||
if (getAttribute(player, attributeClueNumber, -1) !in 0..5) {
|
||||
setAttribute(player, attributeClueNumber, (0..5).random())
|
||||
}
|
||||
}
|
||||
.npc("Greetings friend, and welcome here,", "you'll find my puzzle not so clear.", "Hidden amongst my words, it's true,", "the password for the door as a clue.")
|
||||
.options().let { optionBuilder ->
|
||||
optionBuilder.option_playerl ("Can I have the clue for the door?")
|
||||
.branch { player -> getAttribute(player, attributeClueNumber, 0) }
|
||||
.let{ branch ->
|
||||
// Note: all the "I" in here are written in small case "i" (sic)
|
||||
branch.onValue(0)
|
||||
.npc("Better than me, you'll not find", "In rhyming and in puzzles.", "This clue so clear will tax your mind", "Entirely as it confuzzles!")
|
||||
.end()
|
||||
branch.onValue(1)
|
||||
.npc("Feel the aching of your mind", "In puzzlement, confused.", "See the clue hidden behind", "His words, as you perused.")
|
||||
.end()
|
||||
branch.onValue(2)
|
||||
.npc("Look closely at the words i speak;", "And study closely every part.", "See for yourself the word you seek", "Trapped for you if you're smart.")
|
||||
.end()
|
||||
branch.onValue(3)
|
||||
.npc("More than words, i have not for you", "Except the things i say today.", "Aware are you, this is a clue?", "Take note of what i say!")
|
||||
.end()
|
||||
branch.onValue(4)
|
||||
.npc("Rare it is that you will see", "A puzzle such as this!", "In many ways it tickles me", "Now, watching you hit and miss!")
|
||||
.end()
|
||||
branch.onValue(5)
|
||||
.npc("This riddle of mine may confuse,", "I am quite sure of that.", "Mayhap you should closely peruse", "Every word i have spat?")
|
||||
.end()
|
||||
}
|
||||
return@let optionBuilder.option("Can I have a different clue?")
|
||||
.player("I don't get that riddle...", "Can I have a different one?")
|
||||
.branch { player -> getAttribute(player, attributeClueNumber, 0) }
|
||||
.let{ branch ->
|
||||
branch.onValue(0)
|
||||
.npc("Before you hurry through that door", "Inspect the words i spoke.", "There is a simple hidden flaw", "Ere you think my rhyme a joke.")
|
||||
.end()
|
||||
branch.onValue(1)
|
||||
.npc("First my clue you did not see,", "I really wish you had.", "Such puzzling wordplay devilry", "Has left you kind of mad!")
|
||||
.end()
|
||||
branch.onValue(2)
|
||||
.npc("Last time my puzzle did not help", "Apparently, so you've bidden.", "Study my speech carefully, whelp", "To find the answer, hidden.")
|
||||
.end()
|
||||
branch.onValue(3)
|
||||
.npc("Many types have passed through here", "Even such as you amongst their sort.", "And in the end, the puzzles clear;", "The hidden word you saught.")
|
||||
.end()
|
||||
branch.onValue(4)
|
||||
.npc("Repetition, once again", "Against good sense it goes.", "In my words, the answers plain", "Now that you see rhyme flows.")
|
||||
.end()
|
||||
branch.onValue(5)
|
||||
.npc("Twice it is now, i have stated", "In a rhyme, what is the pass.", "Maybe my words obfuscated", "Entirely beyond your class.")
|
||||
.end()
|
||||
}
|
||||
/*
|
||||
// I'm too goddamned lazy to implement the final clue dialogue
|
||||
return@let optionBuilder.option("Can I have the final clue?")
|
||||
.branch { player -> getAttribute(player, attributeClueNumber, 0) }
|
||||
.let{ branch ->
|
||||
branch.onValue(0)
|
||||
.npc("Betrayed by words the answer is", "In that what i say is the key", "There is no more help after this", "Especially no more from me.")
|
||||
.end()
|
||||
branch.onValue(1)
|
||||
.npc("For the last time i will state", "In simple words, the clue.", "Such tricky words make you irate", "Having no idea what to do...")
|
||||
.end()
|
||||
branch.onValue(2)
|
||||
.npc("Lo! my final speech is now", "Attended to by you.", "Study my words, and find out how", "To understand my clue!")
|
||||
.end()
|
||||
branch.onValue(3)
|
||||
.npc("Many types have passed through here", "Even such as you amongst their sort.", "And in the end, the puzzles clear;", "The hidden word you saught.")
|
||||
.end()
|
||||
branch.onValue(4)
|
||||
.npc("Repetition, once again", "Against good sense it goes.", "In my words, the answers plain", "Now that you see rhyme flows.")
|
||||
.end()
|
||||
branch.onValue(5)
|
||||
.npc("Twice it is now, i have stated", "In a rhyme, what is the pass.", "Maybe my words obfuscated", "Entirely beyond your class.")
|
||||
.end()
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
b.onPredicate { player -> dialogueNum == 2 || getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1 }
|
||||
.betweenStage { _, player, _, _ ->
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
}
|
||||
.npc(FacialExpression.SAD, "It's sad to say,", "this test beat you.", "I'll send you to Tiffy,", "what to do?")
|
||||
.endWith { _, player ->
|
||||
removeAttribute(player, attributeClueNumber)
|
||||
removeAttribute(player, RecruitmentDrive.attributeStagePassFailState)
|
||||
RecruitmentDriveListeners.FailTestCutscene(player).start()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class DoorLockPuzzleInterfaceListener : InterfaceListener {
|
||||
|
||||
companion object {
|
||||
const val temp = Components.RD_COMBOLOCK_285
|
||||
const val attributeLock1 = "quest:recruitmentdrive-lock1"
|
||||
const val attributeLock2 = "quest:recruitmentdrive-lock2"
|
||||
const val attributeLock3 = "quest:recruitmentdrive-lock3"
|
||||
const val attributeLock4 = "quest:recruitmentdrive-lock4"
|
||||
val lockArray = arrayOf(attributeLock1, attributeLock2, attributeLock3, attributeLock4)
|
||||
val answers = arrayOf("BITE", "FISH", "LAST", "MEAT", "RAIN", "TIME")
|
||||
}
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
|
||||
onOpen(Components.RD_COMBOLOCK_285) { player, _ ->
|
||||
setAttribute(player, attributeLock1, 65)
|
||||
setAttribute(player, attributeLock2, 65)
|
||||
setAttribute(player, attributeLock3, 65)
|
||||
setAttribute(player, attributeLock4, 65)
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
onClose(Components.RD_COMBOLOCK_285) { player, _ ->
|
||||
removeAttribute(player, attributeLock1)
|
||||
removeAttribute(player, attributeLock2)
|
||||
removeAttribute(player, attributeLock3)
|
||||
removeAttribute(player, attributeLock4)
|
||||
return@onClose true
|
||||
}
|
||||
|
||||
on(Components.RD_COMBOLOCK_285) { player, component, opcode, buttonID, slot, itemID ->
|
||||
// Child IDs for respective locks:
|
||||
// 6 7 8 9
|
||||
// 10 < Lock1 > 11 12 < Lock2 > 13 14 < Lock3 > 15 16 < Lock4 > 17
|
||||
if (buttonID in 10..17) {
|
||||
val position = (buttonID - 10) / 2
|
||||
val backForth = (buttonID - 10) % 2
|
||||
var newValue = getAttribute(player, lockArray[position], 65) + (if (backForth == 0) { -1 } else { 1 })
|
||||
if (newValue < 65) { newValue = 90 } // If char number is under A(65), loop back to Z(90)
|
||||
if (newValue > 90) { newValue = 65 } // If char number is over Z(90), loop back to A(65)
|
||||
setAttribute(player, lockArray[position], newValue)
|
||||
setInterfaceText(player, newValue.toChar().toString(), Components.RD_COMBOLOCK_285, position + 6)
|
||||
}
|
||||
// Enter Button
|
||||
if (buttonID == 18) {
|
||||
val lock1 = getAttribute(player, attributeLock1, 65).toChar()
|
||||
val lock2 = getAttribute(player, attributeLock2, 65).toChar()
|
||||
val lock3 = getAttribute(player, attributeLock3, 65).toChar()
|
||||
val lock4 = getAttribute(player, attributeLock4, 65).toChar()
|
||||
val answer = arrayOf(lock1, lock2, lock3, lock4).joinToString("")
|
||||
closeInterface(player)
|
||||
if (answers[getAttribute(player, SirRenItchwoodDialogueFile.attributeClueNumber, 0)] == answer){
|
||||
removeAttribute(player, SirRenItchwoodDialogueFile.attributeClueNumber)
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) != -1) {
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1)
|
||||
}
|
||||
sendNPCDialogue(player, NPCs.SIR_REN_ITCHOOD_2287, "Your wit is sharp, your brains quite clear; You solved my puzzle with no fear. At puzzles I rank you quite the best, now enter the portal for your next test.")
|
||||
} else {
|
||||
removeAttribute(player, SirRenItchwoodDialogueFile.attributeClueNumber)
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) {
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
openDialogue(player, SirRenItchwoodDialogueFile(2), NPC(NPCs.SIR_REN_ITCHOOD_2287))
|
||||
}
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
import core.api.*
|
||||
import core.game.container.impl.EquipmentContainer
|
||||
import core.game.dialogue.DialogueBuilder
|
||||
import core.game.dialogue.DialogueBuilderFile
|
||||
import core.game.dialogue.DialoguePlugin
|
||||
import core.game.dialogue.FacialExpression
|
||||
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.zone.ZoneBorders
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Scenery
|
||||
|
||||
@Initializable
|
||||
class SirSpishyusDialogue (player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
openDialogue(player, SirSpishyusDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
override fun newInstance(player: Player): DialoguePlugin {
|
||||
return SirSpishyusDialogue(player)
|
||||
}
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.SIR_SPISHYUS_2282)
|
||||
}
|
||||
}
|
||||
|
||||
class SirSpishyusDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile() {
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate { player -> getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1 }
|
||||
.npc(FacialExpression.FRIENDLY, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.")
|
||||
.end()
|
||||
|
||||
b.onPredicate { player -> dialogueNum == 2 || getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1 }
|
||||
.betweenStage { _, player, _, _ ->
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
}
|
||||
.npc(FacialExpression.SAD, "No... I am very sorry.", "Apparently you are not up to the challenge.", "I will return you where you came from, better luck in the", "future.")
|
||||
.endWith { _, player ->
|
||||
removeAttribute(player, SirTinleyDialogueFile.attributeDoNotMove)
|
||||
removeAttribute(player, RecruitmentDrive.attributeStagePassFailState)
|
||||
RecruitmentDriveListeners.FailTestCutscene(player).start()
|
||||
}
|
||||
b.onPredicate { _ -> true }
|
||||
.npcl(FacialExpression.FRIENDLY, "Ah, welcome @name.")
|
||||
.playerl(FacialExpression.FRIENDLY, "Hello there." + " What am I supposed to be doing in this room?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Well, your task is to take this fox, this chicken and this bag of grain across that bridge there to the other side of the room.")
|
||||
.npcl(FacialExpression.FRIENDLY, "When you have done that, your task is complete.")
|
||||
.playerl(FacialExpression.FRIENDLY, "Is that it?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Well, it is not quite as simple as that may sound.")
|
||||
.npcl(FacialExpression.FRIENDLY, "Firstly, you may only carry one of the objects across the room at a time, for the bridge is old and fragile.")
|
||||
.npcl(FacialExpression.FRIENDLY, "Secondly, the fox wants to eat the chicken, and the chicken wants to eat the grain. Should you ever leave the fox unattended with the chicken, or the grain unattended with the chicken, then")
|
||||
.npcl(FacialExpression.FRIENDLY, "one of them will be eaten, and you will be unable to complete the test.")
|
||||
.playerl(FacialExpression.FRIENDLY, "Okay, I'll see what I can do.")
|
||||
.end()
|
||||
}
|
||||
}
|
||||
class SirSpishyusRoomListeners : InteractionListener {
|
||||
companion object {
|
||||
const val foxFromVarbit = 680
|
||||
const val foxToVarbit = 681
|
||||
const val chickenFromVarbit = 682
|
||||
const val chickenToVarbit = 683
|
||||
const val grainFromVarbit = 684
|
||||
const val grainToVarbit = 685
|
||||
|
||||
val fromZoneBorder = ZoneBorders(2479, 4967, 2490, 4977)
|
||||
val toZoneBorder = ZoneBorders(2471, 4967, 2478, 4977)
|
||||
|
||||
fun countEquipmentItems(player: Player): Int {
|
||||
var count = 0
|
||||
if(inEquipment(player, Items.GRAIN_5607)) { count++ }
|
||||
if(inEquipment(player, Items.FOX_5608)) { count++ }
|
||||
if(inEquipment(player, Items.CHICKEN_5609)) { count++ }
|
||||
return count
|
||||
}
|
||||
|
||||
fun checkFinished(player: Player) {
|
||||
if (getVarbit(player, foxToVarbit) == 1 && getVarbit(player, chickenToVarbit) == 1 && getVarbit(player, grainToVarbit) == 1) {
|
||||
sendMessage(player, "Congratulations! You have solved this room's puzzle!")
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkFail(player: Player): Boolean {
|
||||
return ((getVarbit(player, foxFromVarbit) == 0 && getVarbit(player, chickenFromVarbit) == 0 && getVarbit(player, grainFromVarbit) == 1) ||
|
||||
(getVarbit(player, foxFromVarbit) == 1 && getVarbit(player, chickenFromVarbit) == 0 && getVarbit(player, grainFromVarbit) == 0) ||
|
||||
(getVarbit(player, foxToVarbit) == 1 && getVarbit(player, chickenToVarbit) == 1 && getVarbit(player, grainToVarbit) == 0) ||
|
||||
(getVarbit(player, foxToVarbit) == 0 && getVarbit(player, chickenToVarbit) == 1 && getVarbit(player, grainToVarbit) == 1))
|
||||
}
|
||||
|
||||
fun resetStage(player: Player) {
|
||||
setVarbit(player, foxFromVarbit, 0)
|
||||
setVarbit(player, chickenFromVarbit, 0)
|
||||
setVarbit(player, grainFromVarbit, 0)
|
||||
setVarbit(player, foxToVarbit, 0)
|
||||
setVarbit(player, chickenToVarbit, 0)
|
||||
setVarbit(player, grainToVarbit, 0)
|
||||
removeItem(player, Items.GRAIN_5607, Container.EQUIPMENT)
|
||||
removeItem(player, Items.FOX_5608, Container.EQUIPMENT)
|
||||
removeItem(player, Items.CHICKEN_5609, Container.EQUIPMENT)
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(Scenery.PRECARIOUS_BRIDGE_7286, SCENERY, "cross") { player, node ->
|
||||
if (countEquipmentItems(player) > 1) {
|
||||
sendDialogue(player, "I really don't think I should be carrying more than 5Kg across that rickety bridge...")
|
||||
} else if (checkFail(player)) {
|
||||
openDialogue(player, SirTinleyDialogueFile(2), NPC(NPCs.SIR_SPISHYUS_2282)) // Fail
|
||||
} else {
|
||||
lock(player, 5)
|
||||
sendMessage(player, "You carefully walk across the rickety bridge...")
|
||||
player.walkingQueue.reset()
|
||||
player.walkingQueue.addPath(2476, 4972)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.PRECARIOUS_BRIDGE_7287, SCENERY, "cross") { player, node ->
|
||||
if (countEquipmentItems(player) > 1) {
|
||||
sendDialogue(player, "I really don't think I should be carrying more than 5Kg across that rickety bridge...")
|
||||
} else if (checkFail(player)) {
|
||||
openDialogue(player, SirTinleyDialogueFile(2), NPC(NPCs.SIR_SPISHYUS_2282)) // Fail
|
||||
} else {
|
||||
lock(player, 5)
|
||||
sendMessage(player, "You carefully walk across the rickety bridge...")
|
||||
player.walkingQueue.reset()
|
||||
player.walkingQueue.addPath(2484, 4972)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Scenery.GRAIN_7284, SCENERY, "pick-up") { player, _ ->
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) {
|
||||
if (fromZoneBorder.insideBorder(player)) {
|
||||
replaceSlot(player, EquipmentSlot.CAPE.ordinal, Item(Items.GRAIN_5607), null, Container.EQUIPMENT)
|
||||
setVarbit(player, grainFromVarbit, 1)
|
||||
}
|
||||
if (toZoneBorder.insideBorder(player)) {
|
||||
replaceSlot(player, EquipmentSlot.CAPE.ordinal, Item(Items.GRAIN_5607), null, Container.EQUIPMENT)
|
||||
setVarbit(player, grainToVarbit, 0)
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
onUnequip(Items.GRAIN_5607) { player, _ ->
|
||||
if (fromZoneBorder.insideBorder(player)) {
|
||||
removeItem(player, Items.GRAIN_5607, Container.EQUIPMENT)
|
||||
setVarbit(player, grainFromVarbit, 0)
|
||||
}
|
||||
if (toZoneBorder.insideBorder(player)) {
|
||||
removeItem(player, Items.GRAIN_5607, Container.EQUIPMENT)
|
||||
setVarbit(player, grainToVarbit, 1)
|
||||
checkFinished(player)
|
||||
}
|
||||
return@onUnequip true
|
||||
}
|
||||
|
||||
|
||||
on(Scenery.FOX_7277, SCENERY, "pick-up") { player, _ ->
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) {
|
||||
if (fromZoneBorder.insideBorder(player)) {
|
||||
replaceSlot(player, EquipmentSlot.WEAPON.ordinal, Item(Items.FOX_5608), null, Container.EQUIPMENT)
|
||||
setVarbit(player, foxFromVarbit, 1)
|
||||
}
|
||||
if (toZoneBorder.insideBorder(player)) {
|
||||
replaceSlot(player, EquipmentSlot.WEAPON.ordinal, Item(Items.FOX_5608), null, Container.EQUIPMENT)
|
||||
setVarbit(player, foxToVarbit, 0)
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
onUnequip(Items.FOX_5608) { player, _ ->
|
||||
if (fromZoneBorder.insideBorder(player)) {
|
||||
removeItem(player, Items.FOX_5608, Container.EQUIPMENT)
|
||||
setVarbit(player, foxFromVarbit, 0)
|
||||
}
|
||||
if (toZoneBorder.insideBorder(player)) {
|
||||
removeItem(player, Items.FOX_5608, Container.EQUIPMENT)
|
||||
setVarbit(player, foxToVarbit, 1)
|
||||
checkFinished(player)
|
||||
}
|
||||
return@onUnequip true
|
||||
}
|
||||
|
||||
|
||||
on(Scenery.CHICKEN_7281, SCENERY, "pick-up") { player, _ ->
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0) {
|
||||
if (fromZoneBorder.insideBorder(player)) {
|
||||
replaceSlot(player, EquipmentSlot.SHIELD.ordinal, Item(Items.CHICKEN_5609), null, Container.EQUIPMENT)
|
||||
setVarbit(player, chickenFromVarbit, 1)
|
||||
}
|
||||
if (toZoneBorder.insideBorder(player)) {
|
||||
replaceSlot(player, EquipmentSlot.SHIELD.ordinal, Item(Items.CHICKEN_5609), null, Container.EQUIPMENT)
|
||||
setVarbit(player, chickenToVarbit, 0)
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
onUnequip(Items.CHICKEN_5609) { player, _ ->
|
||||
if (fromZoneBorder.insideBorder(player)) {
|
||||
removeItem(player, Items.CHICKEN_5609, Container.EQUIPMENT)
|
||||
setVarbit(player, chickenFromVarbit, 0)
|
||||
}
|
||||
if (toZoneBorder.insideBorder(player)) {
|
||||
removeItem(player, Items.CHICKEN_5609, Container.EQUIPMENT)
|
||||
setVarbit(player, chickenToVarbit, 1)
|
||||
checkFinished(player)
|
||||
}
|
||||
return@onUnequip true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
import core.api.*
|
||||
import core.game.dialogue.DialogueBuilder
|
||||
import core.game.dialogue.DialogueBuilderFile
|
||||
import core.game.dialogue.FacialExpression
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class SirTiffyCashienDialogueFile : DialogueBuilderFile() {
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onQuestStages(RecruitmentDrive.questName, 1)
|
||||
.player(FacialExpression.FRIENDLY, "Sir Amik Varze sent me to meet you here for some", "sort of testing...")
|
||||
.npc(FacialExpression.FRIENDLY, "Ah, @name!", "Amik told me all about you, dontchaknow!", "Spliffing job you you did with the old Black Knights there,", "absolutely first class.")
|
||||
.playerl(FacialExpression.GUILTY, "...Thanks I think.")
|
||||
// .npcl(FacialExpression.FRIENDLY, "Well, not in those exact words, but you get my point, what?")
|
||||
.npc(FacialExpression.FRIENDLY, "Well, a top-notch filly like yourself is just the right sort", "we've been looking for for our organisation.")
|
||||
.npcl(FacialExpression.FRIENDLY, "So, are you ready to begin testing?")
|
||||
.let { path ->
|
||||
val originalPath = b.placeholder()
|
||||
path.goto(originalPath)
|
||||
return@let originalPath.builder().options().let { optionBuilder ->
|
||||
val continuePath = b.placeholder()
|
||||
optionBuilder.option("Testing..?")
|
||||
.playerl(FacialExpression.FRIENDLY, "Testing? What exactly do you mean by testing?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Jolly bad show! Varze was supposed to have informed you about all this before sending you here!")
|
||||
.npcl(FacialExpression.FRIENDLY, "Well, not your fault I suppose, what? Anywho, our organisation is looking for a certain specific type of person to join.")
|
||||
.playerl(FacialExpression.FRIENDLY, "So... You want me to go kill some monster or something for you?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Not at all, old bean. There's plenty of warriors around should we require dumb muscle.")
|
||||
.npcl(FacialExpression.FRIENDLY, "That's really not the kind of thing our organisation is after, what?")
|
||||
.playerl(FacialExpression.FRIENDLY, "So you want me to go and fetch you some kind of common item, and then take it for delivery somewhere on the other side of the country?")
|
||||
.playerl(FacialExpression.FRIENDLY, "Because I really hate doing that!")
|
||||
.npcl(FacialExpression.FRIENDLY, "Haw, haw, haw! What a dull thing to ask of someone, what?")
|
||||
.npcl(FacialExpression.FRIENDLY, "I know what you mean, though. I did my fair share of running errands when I was a young adventurer, myself!")
|
||||
.playerl(FacialExpression.FRIENDLY, "So what exactly will this test consist of?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Can't let just any old riff-raff in, what? The mindless thugs and bully boys are best left in the White Knights or the city guard. We look for the top-shelf brains to join us.")
|
||||
.playerl(FacialExpression.FRIENDLY, "So you want to test my brains? Will it hurt?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Haw, haw, haw! That's a good one!")
|
||||
.npcl(FacialExpression.FRIENDLY, "Not in the slightest.. Well, maybe a bit, but we all have to make sacrifices occasionally, what?")
|
||||
.playerl(FacialExpression.FRIENDLY, "What do you want me to do then?")
|
||||
.npcl(FacialExpression.FRIENDLY, "It's a test of wits, what? I'll take you to our secret training grounds, and you will have to pass through a series of five separate intelligence test to prove you're our sort of adventurer.")
|
||||
.npcl(FacialExpression.FRIENDLY, "Standard puzzle room rules will apply.")
|
||||
.playerl(FacialExpression.THINKING, "Erm... What are standard puzzle room rules exactly?")
|
||||
.npcl(FacialExpression.HAPPY, "Never done this sort of thing before, what?")
|
||||
.npc("The simple rules are:", "No items or equipment to be brought with you.", "Each room is a self-contained puzzle.", "You may quit at any time.")
|
||||
.npcl(FacialExpression.HAPPY, "Of course, if you quit a room, then all your progress up to that point will be cleared, and you'll have to start again from scratch.")
|
||||
.npc(FacialExpression.HAPPY, "Our organisation manages to filter all the top-notch", "adventurers this way.", "So, are you ready to go?")
|
||||
.goto(originalPath)
|
||||
optionBuilder.option("Organisation?")
|
||||
.playerl(FacialExpression.THINKING, "This organisation you keep mentioning.. Perhaps you could tell me a little about it?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Oh, that Amik! Jolly bad form. Did he not tell you anything that he was supposed to?")
|
||||
.playerl(FacialExpression.FRIENDLY, "No. He didn't really tell me anything except to come here and meet you.")
|
||||
.npcl(FacialExpression.FRIENDLY, "Well, now, old sport, let me give you the heads up and the low down, what?")
|
||||
.npcl(FacialExpression.FRIENDLY, "I represent the Temple Knights. We are the premier order of Knights in Asgarnia, if not the world. Saradomin himself personally founded our order centuries ago, and we answer only to him.")
|
||||
.npcl(FacialExpression.FRIENDLY, "Only the very best of the best are permitted to join, and the powers we command are formidable indeed.")
|
||||
.npcl(FacialExpression.FRIENDLY, "You might say that we are the front line of defence for the entire kingdom!")
|
||||
.playerl(FacialExpression.THINKING, "So what's the difference between you and the White Knights?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Well, in simple terms, we're better! Any fool with a sword can manage to get into the White Knights, which is mostly the reason they are so very, very incompetent, what?")
|
||||
.npcl(FacialExpression.FRIENDLY, "The Temple Knights, on the other hand, have to be smarter, stronger and better than all others. We are the elite. No man controls us, for our orders come directly from Saradomin himself!")
|
||||
.npcl(FacialExpression.FRIENDLY, "According to Sir Vey Lance, our head of operations, that is. He claims that everything he tells us to do is done with Saradomin's implicit permission.")
|
||||
.npcl(FacialExpression.FRIENDLY, "It's not every job where you have more authority than the king, though, is it?")
|
||||
.playerl(FacialExpression.THINKING, "Wait... You can order the King around?")
|
||||
.npcl(FacialExpression.FRIENDLY, "Well, not me personally. I'm only in the recruitment side of things, dontchaknow, but the higher ranking members of the organisation have almost absolute power over the kingdom.")
|
||||
.npcl(FacialExpression.FRIENDLY, "Plus a few others, so I hear...")
|
||||
.npcl(FacialExpression.FRIENDLY, "Anyway, this is why we keep our organisation shrouded in secrecy, and why we demand such rigorous testing for all potential recruits. Speaking of which, are you ready to begin your testing?")
|
||||
.goto(originalPath)
|
||||
optionBuilder.option("Yes, let's go!")
|
||||
.player(FacialExpression.FRIENDLY, "Yeah. this sounds right up my street.", "Let's go!")
|
||||
.branch { player -> if(player.inventory.isEmpty && player.equipment.isEmpty && !player.familiarManager.hasFamiliar()) { 1 } else { 0 } }
|
||||
.let { branch ->
|
||||
branch.onValue(0)
|
||||
.npcl(FacialExpression.NEUTRAL, "Well, bad luck, old @g[guy,gal]. You'll need to have a completely empty inventory and you can't be wearing any equipment before we can accurately test you.")
|
||||
.npcl(FacialExpression.HAPPY, "Don't want people cheating by smuggling stuff in, what? That includes things carried by familiars, too! Come and see me again after you've been to the old bank to drop your stuff off, what?")
|
||||
.end()
|
||||
return@let branch
|
||||
}
|
||||
.onValue(1)
|
||||
.npc(FacialExpression.HAPPY, "Jolly good show!", "Now the training grounds location is a secret, so...")
|
||||
.goto(continuePath)
|
||||
optionBuilder.option("No, I've changed my mind.")
|
||||
.player("No, I've changed my mind.")
|
||||
.end()
|
||||
|
||||
return@let continuePath.builder()
|
||||
}
|
||||
|
||||
}.endWith { _, player ->
|
||||
if (getQuestStage(player, RecruitmentDrive.questName) == 1) {
|
||||
setQuestStage(player, RecruitmentDrive.questName, 2)
|
||||
}
|
||||
RecruitmentDriveListeners.shuffleStages(player)
|
||||
RecruitmentDriveListeners.StartTestCutscene(player).start()
|
||||
}
|
||||
b.onQuestStages(RecruitmentDrive.questName, 2)
|
||||
.npc(FacialExpression.FRIENDLY, "Ah, what ho!", "Back for another go at the old testing, what?")
|
||||
.options().let { optionBuilder ->
|
||||
val continuePath = b.placeholder()
|
||||
optionBuilder.option("Yes, let's go!")
|
||||
.player(FacialExpression.FRIENDLY, "Yeah. this sounds right up my street.", "Let's go!")
|
||||
.branch { player -> if(player.inventory.isEmpty && player.equipment.isEmpty && !player.familiarManager.hasFamiliar()) { 1 } else { 0 } }
|
||||
.let { branch ->
|
||||
branch.onValue(0)
|
||||
.npcl(FacialExpression.NEUTRAL, "Well, bad luck, old @g[guy,gal]. You'll need to have a completely empty inventory and you can't be wearing any equipment before we can accurately test you.")
|
||||
.npcl(FacialExpression.HAPPY, "Don't want people cheating by smuggling stuff in, what? That includes things carried by familiars, too! Come and see me again after you've been to the old bank to drop your stuff off, what?")
|
||||
.end()
|
||||
return@let branch
|
||||
}
|
||||
.onValue(1)
|
||||
.npc(FacialExpression.FRIENDLY, "Jolly good show!", "Now the training grounds location is a secret, so...")
|
||||
.endWith { _, player ->
|
||||
RecruitmentDriveListeners.shuffleStages(player)
|
||||
RecruitmentDriveListeners.StartTestCutscene(player).start()
|
||||
}
|
||||
optionBuilder.option("No, I've changed my mind.")
|
||||
.player("No, I've changed my mind.")
|
||||
.end()
|
||||
return@let continuePath.builder()
|
||||
}
|
||||
b.onQuestStages(RecruitmentDrive.questName, 3)
|
||||
.npc(FacialExpression.HAPPY, "Oh, jolly well done!", "Your performance will need to be evaluated by Sir Vey", "personally, but I don't think it's going too far ahead of", "myself to welcome you to the team!")
|
||||
.endWith { _, player ->
|
||||
// Get a voucher and $3000 to change gender if you did do it during the quest.
|
||||
if (getAttribute(player, RecruitmentDrive.attributeOriginalGender, true) != player.isMale) {
|
||||
addItemOrDrop(player, Items.MAKEOVER_VOUCHER_5606)
|
||||
addItemOrDrop(player, Items.COINS_995, 3000)
|
||||
}
|
||||
removeAttribute(player, RecruitmentDrive.attributeOriginalGender)
|
||||
finishQuest(player, RecruitmentDrive.questName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SirTiffyCashienFailedDialogueFile : DialogueBuilderFile() {
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate { _ -> true }
|
||||
.npc(FacialExpression.SAD, "Oh, jolly bad luck, what?", "Not quite the brainbox you thought you were, eh?")
|
||||
.npc(FacialExpression.HAPPY, "Well, never mind!", "You have an open invitation to join our organization, so", "when you're feeling a little smarter, come back and talk", "to me again.")
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
package content.region.asgarnia.falador.quest.recruitmentdrive
|
||||
|
||||
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.Entity
|
||||
import core.game.node.entity.impl.Projectile
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Sounds
|
||||
|
||||
@Initializable
|
||||
class SirTinleyDialogue (player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
|
||||
openDialogue(player, SirTinleyDialogueFile(), npc)
|
||||
return true
|
||||
}
|
||||
override fun newInstance(player: Player): DialoguePlugin {
|
||||
return SirTinleyDialogue(player)
|
||||
}
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(NPCs.SIR_TINLEY_2286)
|
||||
}
|
||||
}
|
||||
|
||||
class SirTinleyDialogueFile(private val dialogueNum: Int = 0) : DialogueBuilderFile(), MapArea {
|
||||
companion object {
|
||||
const val attributeDoNotMove = "quest:recruitmentdrive-donotmove"
|
||||
}
|
||||
|
||||
override fun create(b: DialogueBuilder) {
|
||||
b.onPredicate {player -> dialogueNum == 0 && !getAttribute(player, attributeDoNotMove, false) && getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 0 }
|
||||
.npc("Ah, welcome @name.", "I have but one clue for you to pass this room's puzzle:", "'Patience'.")
|
||||
.endWith { _, player ->
|
||||
setAttribute(player, attributeDoNotMove, true)
|
||||
queueScript(player, 0, QueueStrength.NORMAL) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
return@queueScript delayScript(player, 15)
|
||||
}
|
||||
1 -> {
|
||||
if (getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) != -1) {
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, 1)
|
||||
setAttribute(player, attributeDoNotMove, false)
|
||||
npc(FacialExpression.FRIENDLY, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.")
|
||||
}
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.onPredicate {player -> dialogueNum == 0 && !getAttribute(player, attributeDoNotMove, false) && getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == 1 }
|
||||
.npc(FacialExpression.FRIENDLY, "Excellent work, @name.", "Please step through the portal to meet your next", "challenge.")
|
||||
.end()
|
||||
|
||||
// If you talk to him before time is up, you fail.
|
||||
b.onPredicate { player -> dialogueNum == 0 && getAttribute(player, attributeDoNotMove, false) || dialogueNum == 2 || getAttribute(player, RecruitmentDrive.attributeStagePassFailState, 0) == -1 }
|
||||
.betweenStage { _, player, _, _ ->
|
||||
setAttribute(player, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
}
|
||||
.npc(FacialExpression.SAD, "No... I am very sorry.", "Apparently you are not up to the challenge.", "I will return you where you came from, better luck in the", "future.")
|
||||
.endWith { _, player ->
|
||||
removeAttribute(player, attributeDoNotMove)
|
||||
removeAttribute(player, RecruitmentDrive.attributeStagePassFailState)
|
||||
RecruitmentDriveListeners.FailTestCutscene(player).start()
|
||||
}
|
||||
|
||||
b.onPredicate { _ -> dialogueNum == 1 }
|
||||
.npc("Ah, @name, you have arrived.", "Speak to me to begin your task.")
|
||||
.endWith { _, player ->
|
||||
setAttribute(player, attributeDoNotMove, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun defineAreaBorders(): Array<ZoneBorders> {
|
||||
return arrayOf(ZoneBorders(2474, 4959, 2478, 4957))
|
||||
}
|
||||
|
||||
override fun entityStep(entity: Entity, location: Location, lastLocation: Location) {
|
||||
if (entity is Player) {
|
||||
if(getAttribute(entity, attributeDoNotMove, false)) {
|
||||
setAttribute(entity, attributeDoNotMove, false)
|
||||
setAttribute(entity, RecruitmentDrive.attributeStagePassFailState, -1)
|
||||
openDialogue(entity, SirTinleyDialogueFile(2), NPC(NPCs.SIR_TINLEY_2286))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import core.plugin.Initializable;
|
|||
/**
|
||||
* Created for 2009Scape
|
||||
* User: Ethan Kyle Millard
|
||||
* https://www.youtube.com/watch?v=-RuHho3NbWg
|
||||
* Date: March 15, 2020
|
||||
* Time: 9:21 AM
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
package content.region.morytania.quest.creatureoffenkenstrain
|
||||
|
||||
import content.global.travel.canoe.CanoeListener
|
||||
import core.api.*
|
||||
import core.game.dialogue.FacialExpression
|
||||
import core.game.global.action.DoorActionHandler
|
||||
import core.game.global.action.PickupHandler
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.GroundItem
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.update.flag.context.Animation
|
||||
|
|
|
|||
|
|
@ -919,6 +919,14 @@ fun openDialogue(player: Player, dialogue: Any, vararg args: Any) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes any opened dialogue.
|
||||
*/
|
||||
fun closeDialogue(player: Player) {
|
||||
player.dialogueInterpreter.close()
|
||||
player.interfaceManager.closeChatbox()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an NPC with the given ID from the repository.
|
||||
* @param id the ID of the NPC to locate
|
||||
|
|
@ -1647,6 +1655,18 @@ fun sendNPCDialogue(player: Player, npc: Int, msg: String, expr: core.game.dialo
|
|||
player.dialogueInterpreter.sendDialogues(npc, expr, *splitLines(msg))
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a dialogue that uses the player's chathead.
|
||||
* @param player the player to send the dialogue to
|
||||
* @param npc the ID of the NPC to use for the chathead
|
||||
* @param expr the FacialExpression to use. An enum exists for these called FacialExpression.
|
||||
* @param msg the message to send.
|
||||
*/
|
||||
fun sendNPCDialogueLines(player: Player, npc: Int, expr: core.game.dialogue.FacialExpression, hideContinue: Boolean, vararg msgs: String) {
|
||||
val dialogueComponent = player.dialogueInterpreter.sendDialogues(npc, expr, *msgs)
|
||||
player.packetDispatch.sendInterfaceConfig(dialogueComponent.id, msgs.size + 4, hideContinue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an animation to a specific interface child
|
||||
* @param player the player to send the packet to
|
||||
|
|
|
|||
|
|
@ -121,6 +121,29 @@ abstract class Cutscene(val player: Player) {
|
|||
player.dialogueInterpreter.addAction { _,_ -> onContinue.invoke() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a dialogue to the player using the given NPC ID, which updates the cutscene stage by default when continued.
|
||||
* @param npcId the ID of the NPC to send a dialogue for
|
||||
* @param expression the FacialExpression the NPC should use
|
||||
* @param message the message to send
|
||||
* @param onContinue (optional) a method that runs when the dialogue is "continued." Increments the cutscene stage by default.
|
||||
*/
|
||||
fun dialogueLinesUpdate(npcId: Int, expression: core.game.dialogue.FacialExpression, vararg message: String, onContinue: () -> Unit = {incrementStage()})
|
||||
{
|
||||
logCutscene("Sending NPC dialogue lines update.")
|
||||
sendNPCDialogueLines(player, npcId, expression, true, *message)
|
||||
player.dialogueInterpreter.addAction { _,_ -> onContinue.invoke() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the dialogue to close.
|
||||
*/
|
||||
fun dialogueClose()
|
||||
{
|
||||
logCutscene("Sending dialogue close.")
|
||||
closeDialogue(player)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a non-NPC dialogue to the player, which updates the cutscene stage by default when continued
|
||||
* @param message the message to send
|
||||
|
|
@ -248,6 +271,51 @@ abstract class Cutscene(val player: Player) {
|
|||
AntiMacro.pause(player)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ends this cutscene, teleporting the player to the exit location, and then fading it back in and executing the endActions passed to this method.
|
||||
* @param endActions (optional) a method that executes when the cutscene fully completes
|
||||
*/
|
||||
fun endWithoutFade(endActions: (() -> Unit)? = null)
|
||||
{
|
||||
ended = true
|
||||
GameWorld.Pulser.submit(object : Pulse(){
|
||||
var tick: Int = 0
|
||||
override fun pulse(): Boolean {
|
||||
when(tick++)
|
||||
{
|
||||
0 -> player.properties.teleportLocation = exitLocation
|
||||
1 -> {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
player ?: return
|
||||
player.removeAttribute(ATTRIBUTE_CUTSCENE)
|
||||
player.removeAttribute(ATTRIBUTE_CUTSCENE_STAGE)
|
||||
player.properties.isSafeZone = false
|
||||
player.properties.safeRespawn = ServerConstants.HOME_LOCATION
|
||||
player.interfaceManager.restoreTabs()
|
||||
player.unlock()
|
||||
clearNPCs()
|
||||
player.unhook(CUTSCENE_DEATH_HOOK)
|
||||
player.logoutListeners.remove("cutscene")
|
||||
AntiMacro.unpause(player)
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0))
|
||||
try {
|
||||
endActions?.invoke()
|
||||
} catch (e: Exception) {
|
||||
log(this::class.java, Log.ERR, "There's some bad nasty code in ${this::class.java.simpleName} end actions!")
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends this cutscene, fading the screen to black, teleporting the player to the exit location, and then fading it back in and executing the endActions passed to this method.
|
||||
* @param fade (optional) should the cutscene fade to black?
|
||||
|
|
|
|||
|
|
@ -295,6 +295,14 @@ class DialogueBuilder(var target: DialogueBuilderFile, var clauseIndex: Int = -1
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The first if-statement to a dialogue. At minimum, you must have "b.onPredicate { _ -> true }"
|
||||
* PLEASE BE CAREFUL ABOUT HAVING COMPLEX PREDICATE.
|
||||
* If at any point during a dialogue that the predicate is not satisfied,
|
||||
* it will block further dialogue progression and any dialogue will suddenly disappear.
|
||||
* e.g. onPredicate(x==2) but during dialogue you set x=3, dialogue after it will disappear.
|
||||
* Think of this as a repeated filter at every dialogue step.
|
||||
*/
|
||||
fun onPredicate(predicate: (player: Player) -> Boolean): DialogueBuilder {
|
||||
target.data.add(DialogueClause(predicate, ArrayList()))
|
||||
clauseIndex = target.data.size - 1
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import core.game.node.entity.Entity;
|
|||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.ChildPositionContext;
|
||||
import core.net.packet.context.ContainerContext;
|
||||
|
|
@ -501,6 +502,7 @@ public final class DialogueInterpreter {
|
|||
static Pattern GENDERED_SUBSTITUTION = Pattern.compile("@g\\[([^,]*),([^\\]]*)\\]");
|
||||
public static String doSubstitutions(Player player, String msg) {
|
||||
msg = msg.replace("@name", player.getUsername());
|
||||
msg = msg.replace("@servername", GameWorld.getSettings().getName());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Matcher m = GENDERED_SUBSTITUTION.matcher(msg);
|
||||
int index = player.isMale() ? 1 : 2;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue