Made XP rates and ironman optional, locked behind new server config settings xp_rates and ironman

Removed the ironman_icons server config setting, locking it behind ironman instead
Removed the default_xp_rate server config setting and hardcoded the default xp rate to 1x
Changed a bunch of server config defaults for inauthentic features to disabled
Added enable_global_chat to the worldprops default config. Note the change from enable_globalchat to enable_global_chat
Removed the allow_slayer_rerolls worldprops config option
Large number of tutorial island improvements and authenticity enhancements
This commit is contained in:
Player Name 2025-11-25 13:12:56 +00:00 committed by Ryan
parent 66030f36d6
commit dfb53cfa03
37 changed files with 1526 additions and 1777 deletions

View file

@ -1,17 +1,22 @@
package content.global.skill.cooking
import core.api.amountInInventory
import content.region.misc.tutisland.handlers.TutorialStage
import core.api.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.interaction.QueueStrength
import core.game.node.entity.impl.Animator
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.game.node.scenery.Scenery
import core.game.world.update.flag.context.Animation
import org.rs09.consts.Items
import org.rs09.consts.Items.BREAD_DOUGH_2307
import org.rs09.consts.Items.RAW_BEAR_MEAT_2136
import org.rs09.consts.Items.RAW_BEEF_2132
import org.rs09.consts.Items.SEAWEED_401
import org.rs09.consts.Items.UNCOOKED_CAKE_1889
import org.rs09.consts.Sounds
/**
* @author Ceikry
@ -32,8 +37,36 @@ class CookingRewrite : InteractionListener {
}
override fun defineListeners() {
onUseWith(IntType.SCENERY,RAW_FOODS, *COOKING_OBJs){ player, used, with ->
if (!getAttribute(player, "/save:tutorial:complete", false)) {
// On tutorial island, we don't want to show the cook-x menu and we always want to burn our first shrimp
// This requirement of a simplified and predictable cooking system means that, for the second time, I have to reinvent the wheel of cooking
// (We only need to care about shrimp here, the tutorial island range is special and has its own separate listener)
queueScript(player, 0, QueueStrength.WEAK) { stage ->
if (stage == 0) {
val FIRE_ANIMATION = Animation(897, Animator.Priority.HIGH)
lock(player, FIRE_ANIMATION.duration)
lockInteractions(player, FIRE_ANIMATION.duration)
animate(player, FIRE_ANIMATION)
playAudio(player, Sounds.FRY_2577)
return@queueScript delayScript(player, FIRE_ANIMATION.duration)
}
val tutStage = getAttribute(player, "/save:tutorial:stage", 0)
if (tutStage < 15) {
replaceSlot(player, used.asItem().slot, Item(Items.BURNT_SHRIMP_7954), used.asItem())
setAttribute(player, "tutorial:stage", 15)
TutorialStage.load(player, 15)
} else {
replaceSlot(player, used.asItem().slot, Item(Items.SHRIMPS_315), used.asItem())
if (tutStage == 15) {
setAttribute(player, "tutorial:stage", 16)
TutorialStage.load(player, 16)
}
}
return@queueScript stopExecuting(player)
}
return@onUseWith true
}
val item = used.asItem()
val obj = with.asScenery()
val range = obj.name.toLowerCase().contains("range")
@ -66,7 +99,7 @@ class CookingRewrite : InteractionListener {
}
companion object {
val COOKING_OBJs = intArrayOf(24313,21302, 13528, 13529, 13533, 13531, 13536, 13539, 13542, 2728, 2729, 2730, 2731, 2732, 2859, 3038, 3039, 3769, 3775, 4265, 4266, 5249, 5499, 5631, 5632, 5981, 9682, 10433, 11404, 11405, 11406, 12102, 12796, 13337, 13881, 14169, 14919, 15156, 20000, 20001, 21620, 21792, 22713, 22714, 23046, 24283, 24284, 25155, 25156, 25465, 25730, 27297, 29139, 30017, 32099, 33500, 34495, 34546, 36973, 37597, 37629, 37726, 114, 4172, 5275, 8750, 16893, 22154, 34410, 34565, 114, 9085, 9086, 9087, 12269, 15398, 25440, 25441, 2724, 2725, 2726, 4618, 4650, 5165, 6093, 6094, 6095, 6096, 8712, 9374, 9439, 9440, 9441, 10824, 17640, 17641, 17642, 17643, 18039, 18170, 21795, 24285, 24329, 27251, 33498, 35449, 36815, 36816, 37426, 40110, 10377)
val COOKING_OBJs = intArrayOf(24313,21302, 13528, 13529, 13533, 13531, 13536, 13539, 13542, 2728, 2729, 2730, 2731, 2732, 2859, 3038, 3769, 3775, 4265, 4266, 5249, 5499, 5631, 5632, 5981, 9682, 10433, 11404, 11405, 11406, 12102, 12796, 13337, 13881, 14169, 14919, 15156, 20000, 20001, 21620, 21792, 22713, 22714, 23046, 24283, 24284, 25155, 25156, 25465, 25730, 27297, 29139, 30017, 32099, 33500, 34495, 34546, 36973, 37597, 37629, 37726, 114, 4172, 5275, 8750, 16893, 22154, 34410, 34565, 114, 9085, 9086, 9087, 12269, 15398, 25440, 25441, 2724, 2725, 2726, 4618, 4650, 5165, 6093, 6094, 6095, 6096, 8712, 9374, 9439, 9440, 9441, 10824, 17640, 17641, 17642, 17643, 18039, 18170, 21795, 24285, 24329, 27251, 33498, 35449, 36815, 36816, 37426, 40110, 10377)
@JvmStatic
fun cook(player: Player, `object`: Scenery?, initial: Int, product: Int, amount: Int) {

View file

@ -1,5 +1,6 @@
package content.global.skill.cooking
import content.region.misc.tutisland.handlers.TutorialStage
import core.api.*
import core.game.event.ResourceProducedEvent
import core.game.node.entity.skill.Skills
@ -24,7 +25,16 @@ class DoughMakingListener : InteractionListener {
FULL_WATER_CONTAINERS_TO_EMPTY_CONTAINERS.keys.toIntArray(),
Items.POT_OF_FLOUR_1933
) { player, waterContainer, flourContainer ->
openDialogue(player, DoughMakeDialogue(waterContainer.asItem(), flourContainer.asItem()))
if (getAttribute(player, "/save:tutorial:complete", false)) {
openDialogue(player, DoughMakeDialogue(waterContainer.asItem(), flourContainer.asItem()))
return@onUseWith true
}
// Continue the tutorial
replaceSlot(player, waterContainer.asItem().slot, Item(Items.BUCKET_1925), waterContainer.asItem())
replaceSlot(player, flourContainer.asItem().slot, Item(Items.EMPTY_POT_1931), flourContainer.asItem())
addItemOrDrop(player, Items.BREAD_DOUGH_2307)
setAttribute(player, "tutorial:stage", 20)
TutorialStage.load(player, 20)
return@onUseWith true
}
}
@ -73,7 +83,7 @@ class DoughMakingListener : InteractionListener {
sendMessage(
player!!,
"You mix the flower and the water to make some ${selectedDoughProduct.itemName.toLowerCase()}."
"You mix the flour and the water to make some ${selectedDoughProduct.itemName.toLowerCase()}."
)
}
} else {

View file

@ -42,11 +42,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
*/
private static final Item HOLY_SYMBOL = new Item(1718);
/**
* Represents the items to use.
*/
private static final Item[] ITEMS = new Item[]{new Item(9813), new Item(9814)};
/**
* Represents the coins item.
*/
@ -69,8 +64,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
private final int level = 2;
private int rerolls = 0;
/**
* Constructs a new {@code SlayerMasterDialogue} {@code Object}.
*/
@ -120,7 +113,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
@Override
public boolean handle(int interfaceId, int buttonId) {
rerolls = ServerStore.getInt(getStoreFile(), player.getUsername().toLowerCase(), 0);
if (isDiary) {
switch (stage) {
case 999:
@ -482,36 +474,19 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
stage = 999;
break;
}
if (!SlayerManager.getInstance(player).hasTask()) {
boolean hasTask = SlayerManager.getInstance(player).hasTask();
boolean reroll = hasTask && master == Master.TURAEL && !Master.hasSameTask(master, player);
if (!hasTask || reroll) {
SlayerManager.getInstance(player).generate(master);
if (SlayerManager.getInstance(player).getTask() == Tasks.JAD) {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to", "defeat the almighty TzTok-Jad.");
} else {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerUtils.pluralise(SlayerManager.getInstance(player).getTaskName()) + ".");
}
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerUtils.pluralise(SlayerManager.getInstance(player).getTaskName()) + ".");
stage = 844;
break;
}
if (Master.hasSameTask(master, player)) {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "You're still hunting something. But let me check something...");
stage = 847;
} else {
SlayerManager.getInstance(player).flags.setTaskStreak(0);
SlayerManager.getInstance(player).generate(master);
if (SlayerManager.getInstance(player).getTask() == Tasks.JAD) {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to", "defeat the almighty TzTok-Jad.");
} else {
interpreter.sendDialogues(master.getNpc(), getExpression(master), "Excellent, you're doing great. Your new task is to kill", "" + SlayerManager.getInstance(player).getAmount() + " " + SlayerUtils.pluralise(SlayerManager.getInstance(player).getTaskName()) + ".");
}
stage = 844;
}
interpreter.sendDialogues(master.getNpc(), getExpression(master), "You're still hunting something. Come back when you've","finished your task.");
stage = END_DIALOGUE;
break;
case 844:
if (GameWorld.getSettings().getAllow_slayer_reroll()) {
options("Got any tips for me?", "Okay, great!", "I'd like to re-roll that task.");
} else {
options("Got any tips for me?", "Okay, great!");
}
options("Got any tips for me?", "Okay, great!");
stage++;
break;
case 845:
@ -524,47 +499,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
player("Okay, great!");
stage = 999;
break;
case 3:
player("I'd like to re-roll this task.");
if(rerolls == 10){
stage++;
} else {
SlayerManager.getInstance(player).clear();
getStoreFile().put(player.getUsername().toLowerCase(), rerolls + 1);
stage = 701;
}
}
break;
case 846:
npcl(FacialExpression.NEUTRAL, "Actually, you're out of free rerolls. You can buy a reroll from my reward store, though.");
stage = END_DIALOGUE;
break;
case 847:
if(rerolls < 10){
npcl(FacialExpression.NEUTRAL, "You do have " + (10 - rerolls) + " rerolls left today, would you like to use one?");
stage++;
}
else {
npcl(FacialExpression.NEUTRAL, "And it also seems you're out of rerolls for today. That's unfortunate.");
stage = END_DIALOGUE;
}
break;
case 848:
options("Yes, please.", "No, thanks.");
stage++;
break;
case 849:
switch(buttonId){
case 1:
playerl(FacialExpression.FRIENDLY, "Yes, please.");
SlayerManager.getInstance(player).clear();
getStoreFile().put(player.getUsername().toLowerCase(), rerolls + 1);
stage = 701;
break;
case 2:
playerl(FacialExpression.NEUTRAL, "No, thanks.");
stage = END_DIALOGUE;
break;
}
break;
case 860:
@ -608,56 +542,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
}
stage = 999;
break;
case 906:
switch (buttonId) {
case 1:
player("May I buy a Quest Point cape?");
stage = 907;
break;
case 2:
interpreter.sendDialogues(master.getNpc(), FacialExpression.HALF_GUILTY, "'Ello, and what are you after, then?");
stage = 0;
break;
}
break;
case 907:
npc("You bet, " + player.getUsername() + "! Right when you give me 99000 coins.");
stage = 908;
break;
case 908:
options("Okay, here you go.", "No, thanks.");
stage = 909;
break;
case 909:
switch (buttonId) {
case 1:
player("Okay, here you go.");
stage = 910;
break;
case 2:
end();
break;
}
break;
case 910:
if (player.getInventory().freeSlots() < 2) {
player("I don't seem to have enough inventory space.");
stage = 999;
return true;
}
if (!player.getInventory().containsItem(COINS)) {
player("I don't seem to have enough coins with", "me at this time.");
stage = 999;
return true;
}
if (player.getInventory().remove(COINS) && player.getInventory().add(ITEMS)) {
npc("Have fun with it.");
stage = 999;
} else {
player("I don't seem to have enough coins with", "me at this time.");
stage = 999;
}
break;
}
return true;
}
@ -698,9 +582,4 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
public int[] getIds() {
return new int[]{70, 1598, 1596, 1597, 1599, 7780, 8275, 8273, 8274, 8649};
}
private JSONObject getStoreFile() {
return ServerStore.getArchive("daily-slayer-rerolls");
}
}

View file

@ -78,26 +78,6 @@ public final class FurnaceOptionPlugin extends OptionHandler {
player.getPacketDispatch().sendItemZoomOnInterface(2363, 150, 311, 12);
}
/**
* Method used to handle the tutorial island interaction.
* @param player the player.
*/
private final void handleTutorialIsland(final Player player) {
if (player.getInventory().containItems(438, 436)) {
player.animate(ANIMATION);
GameWorld.getPulser().submit(new Pulse(2, player) {
@Override
public boolean pulse() {
player.getInventory().remove(ITEMS);
player.getInventory().add(Bar.BRONZE.getProduct());
player.getSkills().addExperience(Skills.SMITHING, Bar.BRONZE.getExperience());
return true;
}
});
}
}
/**
* Represents the plugin used to handle the ore on the furance.
* @author 'Vexia

View file

@ -0,0 +1,15 @@
package content.region.misc.tutisland.dialogue
import content.region.misc.tutisland.handlers.sendStageDialog
import core.game.dialogue.ChatAnim
import core.game.dialogue.DialogueLabeller
/**
* Vannaka's angry dialogue when you try to enter his rat pen before you're supposed to
*/
class RatPenDialogue : DialogueLabeller() {
override fun addConversation() {
npc(ChatAnim.ANGRY, "Oi, get away from there!", "Don't enter my rat pen unless I say so!")
exec { player, _ -> sendStageDialog(player) }
}
}

View file

@ -9,10 +9,11 @@ import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage
import core.game.component.Component.setUnclosable
/**
* Handles Skippy's skip tutorial dialogue
* @author Ceikry
* @author Ceikry, Player Name
*/
@Initializable
class SkipTutorialDialogue(player: Player? = null) : DialoguePlugin(player) {
@ -21,13 +22,13 @@ class SkipTutorialDialogue(player: Player? = null) : DialoguePlugin(player) {
}
override fun open(vararg args: Any?): Boolean {
npcl(FacialExpression.FRIENDLY, "Hey, would you like to skip to the end? Choose wisely! This is the only time you get this choice.")
setUnclosable(player, npcl(FacialExpression.FRIENDLY, "Hey, would you like to skip to the end? Choose wisely! This is the only time you get this choice."))
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(stage){
0 -> options("Yes, I'd like to skip the tutorial.", "No thanks.").also { stage++ }
0 -> options("Yes, I'd like to skip the tutorial.", "No, thanks.").also { stage++ }
1 -> when(buttonId)
{
1 -> {

View file

@ -1,119 +1,108 @@
package content.region.misc.tutisland.dialogue
import core.api.addItem
import core.api.addItemOrDrop
import core.api.inInventory
import core.api.setAttribute
import core.game.component.Component
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.Items
import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage
import content.region.misc.tutisland.handlers.sendStageDialog
import core.api.getAttribute
import core.api.inEquipment
import core.game.dialogue.ChatAnim
import core.game.dialogue.DialogueLabeller
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.npc.NPC
import core.game.node.item.Item
/**
* Handles the survival expert's dialogue
* @author Ceikry
*/
@Initializable
class SurvivalExpertDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player?): DialoguePlugin {
return SurvivalExpertDialogue(player)
}
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
val tutStage = player?.getAttribute("tutorial:stage", 0) ?: 0
when(tutStage)
{
4 -> Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.FRIENDLY,
"Hello there, newcomer. My name is Brynna. My job is",
"to teach you a few survival tips and tricks. First off",
"we're going to start with the most basic survival skill of",
"all: making a fire."
)
)
11 -> Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.FRIENDLY,
"Well done! Next we need to get some food in our",
"bellies. We'll need something to cook. There are shrimp",
"in the pond there, so let's catch and cook some."
)
)
5, 14, 15 -> {
if(!inInventory(player, Items.BRONZE_AXE_1351))
{
player.dialogueInterpreter.sendItemMessage(Items.BRONZE_AXE_1351, "The Survival Expert gives you a spare bronze axe.")
addItem(player, Items.BRONZE_AXE_1351)
}
if(!inInventory(player, Items.TINDERBOX_590))
{
player.dialogueInterpreter.sendItemMessage(Items.TINDERBOX_590, "The Survival Expert gives you a spare tinderbox.")
addItem(player, Items.TINDERBOX_590)
}
return false
}
class SurvivalExpertDialogue : InteractionListener {
override fun defineListeners() {
on(NPCs.SURVIVAL_EXPERT_943, IntType.NPC, "talk-to") { player, node ->
DialogueLabeller.open(player, SurvivalExpertDialogueFile(), node as NPC)
return@on true
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(player?.getAttribute("tutorial:stage", 0))
{
4 -> when(stage)
{
0 -> {
Component.setUnclosable(
player,
interpreter.sendDoubleItemMessage(
Items.TINDERBOX_590,
Items.BRONZE_AXE_1351,
"The Survival Guide gives you a <col=08088A>tinderbox</col> and a <col=08088A>bronze axe</col>!"
)
)
addItem(player, Items.TINDERBOX_590)
addItem(player, Items.BRONZE_AXE_1351)
stage++
}
1 -> {
end()
setAttribute(player, "tutorial:stage", 5)
TutorialStage.load(player, 5)
}
}
11 -> when(stage){
0 -> {
Component.setUnclosable(
player,
interpreter.sendItemMessage(303, "The Survival Guide gives you a <col=08088A>net</col>!")
)
addItem(player, Items.SMALL_FISHING_NET_303)
stage++
}
1 -> {
end()
setAttribute(player, "tutorial:stage", 12)
TutorialStage.load(player, 12)
}
}
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.SURVIVAL_EXPERT_943)
}
}
class SurvivalExpertDialogueFile : DialogueLabeller() {
override fun addConversation() {
assignToIds(NPCs.SURVIVAL_EXPERT_943)
exec { player, _ ->
when (val stage = getAttribute(player, "/save:tutorial:stage", 0)) {
4 -> loadLabel(player, "hello")
5, 6, 7, 8, 9, 10, 12, 13, 14 -> {
if (!inInventory(player, Items.BRONZE_AXE_1351) && !inEquipment(player, Items.BRONZE_AXE_1351)) {
loadLabel(player, "spare axe")
}
if (!inInventory(player, Items.TINDERBOX_590)) {
loadLabel(player, "spare tinderbox")
}
if (stage >= 11 && !inInventory(player, Items.SMALL_FISHING_NET_303)) {
loadLabel(player, "spare net")
}
loadLabel(player, "nowhere")
}
11 -> loadLabel(player, "fishing")
else -> loadLabel(player, "nowhere")
}
}
label("hello")
npc(ChatAnim.FRIENDLY, "Hello there, newcomer. My name is Brynna. My job is to teach you a few survival tips and tricks. First off we're going to start with the most basic survival skill of all: making a fire.", unclosable = true)
exec { player, _ ->
addItemOrDrop(player, Items.TINDERBOX_590)
addItemOrDrop(player, Items.BRONZE_AXE_1351)
}
item(Item(Items.TINDERBOX_590), Item(Items.BRONZE_AXE_1351), "The Survival Guide gives you a <col=08088A>tinderbox</col> and a <col=08088A>bronze</col>", "<col=08088A>axe</col>!", unclosable = true)
exec { player, _ ->
setAttribute(player, "tutorial:stage", 5)
TutorialStage.load(player, 5)
}
goto("nowhere")
label("fishing")
npc(ChatAnim.FRIENDLY, "Well done! Next we need to get some food in our bellies. We'll need something to cook. There are shrimp in the pond there, so let's catch and cook some.", unclosable = true)
exec { player, _ -> addItemOrDrop(player, Items.SMALL_FISHING_NET_303) }
item(Item(Items.SMALL_FISHING_NET_303), "The Survival Guide gives you a", "<col=08088A>net</col>!", unclosable = true)
exec { player, _ ->
setAttribute(player, "tutorial:stage", 12)
TutorialStage.load(player, 12)
}
goto("nowhere")
label("spare axe")
exec { player, _ -> addItemOrDrop(player, Items.BRONZE_AXE_1351) }
item(Item(Items.BRONZE_AXE_1351), "The Survival Guide gives you a spare bronze axe.", unclosable = true)
exec { player, _ ->
if (!inInventory(player, Items.TINDERBOX_590)) {
loadLabel(player, "spare tinderbox")
}
val stage = getAttribute(player, "/save:tutorial:stage", 0)
if (stage >= 11 && !inInventory(player, Items.SMALL_FISHING_NET_303)) {
loadLabel(player, "spare net")
}
}
goto("nowhere") //closes the dialogue, letting the hook reopen the tutorial stage dialog as appropriate
label("spare tinderbox")
exec { player, _ -> addItemOrDrop(player, Items.TINDERBOX_590) }
item(Item(Items.TINDERBOX_590), "The Survival Guide gives you a spare tinderbox.", unclosable = true)
exec { player, _ ->
val stage = getAttribute(player, "/save:tutorial:stage", 0)
if (stage >= 11 && !inInventory(player, Items.SMALL_FISHING_NET_303)) {
loadLabel(player, "spare net")
}
}
goto("nowhere")
label("spare net")
exec { player, _ -> addItemOrDrop(player, Items.SMALL_FISHING_NET_303) }
item(Item(Items.SMALL_FISHING_NET_303), "The Survival Guide gives you a spare net.", unclosable = true)
goto("nowhere")
label("nowhere")
exec { player, _ -> sendStageDialog(player) }
}
}

View file

@ -1,95 +1,106 @@
package content.region.misc.tutisland.dialogue
import core.api.*
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.Items
import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage
import content.region.misc.tutisland.handlers.sendStageDialog
import core.api.*
import core.game.dialogue.ChatAnim
import core.game.dialogue.DialogueLabeller
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.player.Player
import core.game.node.item.Item
/**
* Handles the combat instructor's dialogue
* @author Ceikry
*/
@Initializable
class TutorialCombatInstructorDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player?): DialoguePlugin {
return TutorialCombatInstructorDialogue(player)
}
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0))
{
44 -> playerl(FacialExpression.FRIENDLY, "Hi! My name's ${player.username}.")
47 -> npcl(FacialExpression.FRIENDLY, "Very good, but that little butter knife isn't going to protect you much. Here, take these.")
53 -> playerl(FacialExpression.FRIENDLY, "I did it! I killed a giant rat!")
54 -> {
player.dialogueInterpreter.sendDoubleItemMessage(Items.SHORTBOW_841, Items.BRONZE_ARROW_882, "The Combat Guide gives you some bronze arrows and a shortbow!")
if(!inInventory(player, Items.SHORTBOW_841) && !inEquipment(player, Items.SHORTBOW_841))
addItemOrDrop(player, Items.SHORTBOW_841)
if(!inInventory(player, Items.BRONZE_ARROW_882) && !inEquipment(player, Items.BRONZE_ARROW_882))
addItemOrDrop(player, Items.BRONZE_ARROW_882, 30)
}
class CombatInstructorDialogue : InteractionListener {
override fun defineListeners() {
on(NPCs.COMBAT_INSTRUCTOR_944, IntType.NPC, "talk-to") { player, node ->
DialogueLabeller.open(player, CombatInstructorDialogueFile(), node as NPC)
return@on true
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(getAttribute(player, "tutorial:stage", 0))
{
44 -> when(stage){
0 -> npcl(FacialExpression.ANGRY, "Do I look like I care? To me you're just another newcomer who thinks they're ready to fight.").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "I'm Vannaka, the greatest swordsman alive.").also { stage++ }
2 -> npcl(FacialExpression.FRIENDLY, "Let's get started by teaching you to wield a weapon.").also { stage++ }
3 -> {
end()
setAttribute(player, "tutorial:stage", 45)
TutorialStage.load(player, 45)
}
}
47 -> when(stage){
0 -> {
addItemOrDrop(player, Items.BRONZE_SWORD_1277)
addItemOrDrop(player, Items.WOODEN_SHIELD_1171)
sendDoubleItemDialogue(player, Items.BRONZE_SWORD_1277, Items.WOODEN_SHIELD_1171, "The Combat Guide gives you a bronze sword and a wooden shield!")
stage++
}
1 -> {
end()
setAttribute(player, "tutorial:stage", 48)
TutorialStage.load(player, 48)
}
}
53 -> when(stage){
0 -> npcl(FacialExpression.FRIENDLY, "I saw, ${player.username}. You seem better at this than I thought. Now that you have grasped basic swordplay, let's move on.").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "Let's try some ranged attacking, with this you can kill foes from a distance. Also, foes unable to reach you are as good as dead. You'll be able to attack the rats, without entering the pit.").also { stage++ }
2 -> {
sendDoubleItemDialogue(player, Items.SHORTBOW_841, Items.BRONZE_ARROW_882, "The Combat Guide gives you some bronze arrows and a shortbow!")
if(!inInventory(player, Items.SHORTBOW_841) && !inEquipment(player, Items.SHORTBOW_841))
addItem(player, Items.SHORTBOW_841)
if(!inInventory(player, Items.BRONZE_ARROW_882) && !inEquipment(player, Items.BRONZE_ARROW_882))
addItem(player, Items.BRONZE_ARROW_882, 30)
stage++
}
3 -> {
end()
setAttribute(player, "tutorial:stage", 54)
TutorialStage.load(player, 54)
}
}
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.COMBAT_INSTRUCTOR_944)
}
}
class CombatInstructorDialogueFile : DialogueLabeller() {
fun lostWeapon(player: Player, id: Int): Boolean {
return !inInventory(player, id) && !inEquipment(player, id)
}
override fun addConversation() {
assignToIds(NPCs.COMBAT_INSTRUCTOR_944)
exec { player, _ ->
when (getAttribute(player, "tutorial:stage", 0)) {
44 -> loadLabel(player, "hello")
47 -> loadLabel(player, "butter")
48, 49, 50, 51, 52 -> loadLabel(player, if (lostWeapon(player, Items.BRONZE_SWORD_1277)) "lost sword" else if (lostWeapon(player, Items.WOODEN_SHIELD_1171)) "lost shield" else "nowhere")
53 -> loadLabel(player, "killed rat")
54 -> loadLabel(player, if (lostWeapon(player, Items.SHORTBOW_841)) "lost bow" else if (lostWeapon(player, Items.BRONZE_ARROW_882)) "lost arrows" else "nowhere")
else -> loadLabel(player, "nowhere")
}
}
label("hello")
player(ChatAnim.FRIENDLY, "Hi! My name's ${player?.username}.", unclosable = true)
npc(ChatAnim.ANGRY, "Do I look like I care? To me you're just another newcomer who thinks they're ready to fight.", unclosable = true)
npc(ChatAnim.FRIENDLY, "I'm Vannaka, the greatest swordsman alive.", unclosable = true)
npc(ChatAnim.FRIENDLY, "Let's get started by teaching you to wield a weapon.", unclosable = true)
exec { player, _ ->
setAttribute(player, "tutorial:stage", 45)
TutorialStage.load(player, 45)
}
label("butter")
npc(ChatAnim.FRIENDLY, "Very good, but that little butter knife isn't going to protect you much. Here, take these.", unclosable = true)
exec { player, _ ->
addItemOrDrop(player, Items.BRONZE_SWORD_1277)
addItemOrDrop(player, Items.WOODEN_SHIELD_1171)
}
item(Item(Items.BRONZE_SWORD_1277), Item(Items.WOODEN_SHIELD_1171), "The Combat Guide gives you a <col=08088A>bronze sword</col> and a", "<col=08088A>wooden shield</col>!", unclosable = true)
exec { player, _ ->
setAttribute(player, "tutorial:stage", 48)
TutorialStage.load(player, 48)
}
goto("nowhere")
label("lost sword")
exec { player, _ -> addItemOrDrop(player, Items.BRONZE_SWORD_1277) }
item(Item(Items.BRONZE_SWORD_1277), "The Combat Guide gives you a spare sword.", unclosable = true)
exec { player, _ -> if (lostWeapon(player, Items.WOODEN_SHIELD_1171)) loadLabel(player, "lost shield") }
goto("nowhere")
label("lost shield")
exec { player, _ -> addItemOrDrop(player, Items.WOODEN_SHIELD_1171) }
item(Item(Items.WOODEN_SHIELD_1171), "The Combat Guide gives you a spare shield.", unclosable = true)
goto("nowhere")
label("killed rat")
player(ChatAnim.FRIENDLY, "I did it! I killed a giant rat!", unclosable = true)
npc(ChatAnim.FRIENDLY, "I saw, ${player?.username}. You seem better at this than I thought. Now that you have grasped basic swordplay, let's move on.", unclosable = true)
npc(ChatAnim.FRIENDLY, "Let's try some ranged attacking, with this you can kill foes from a distance. Also, foes unable to reach you are as good as dead. You'll be able to attack the rats, without entering the pit.", unclosable = true)
exec { player, _ ->
addItemOrDrop(player, Items.SHORTBOW_841)
addItemOrDrop(player, Items.BRONZE_ARROW_882, 30)
}
item(Item(Items.SHORTBOW_841), Item(Items.BRONZE_ARROW_882), "The Combat Guide gives you some <col=08088A>bronze arrows</col> and", "a <col=08088A>shortbow</col>!", unclosable = true)
exec { player, _ ->
setAttribute(player, "tutorial:stage", 54)
TutorialStage.load(player, 54)
}
goto("nowhere")
label("lost bow")
exec { player, _ -> addItemOrDrop(player, Items.SHORTBOW_841) }
item(Item(Items.SHORTBOW_841), "The Combat Guide gives you a spare bow.", unclosable = true)
goto("nowhere")
label("lost arrows")
exec { player, _ -> addItemOrDrop(player, Items.BRONZE_ARROW_882, 10) }
item(Item(Items.BRONZE_ARROW_882), "You receive some spare arrows.", unclosable = true)
goto("nowhere")
label("nowhere")
exec { player, _ -> sendStageDialog(player) }
}
}

View file

@ -7,11 +7,12 @@ import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage
import core.game.component.Component.setUnclosable
import core.game.world.GameWorld.settings
/**
* Handles the finance tutor's dialogue
* @author Ceikry
* @author Ceikry, Player Name
*/
@Initializable
class TutorialFinanceAdvisorDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) {
@ -23,8 +24,8 @@ class TutorialFinanceAdvisorDialogue(player: Player? = null) : core.game.dialogu
npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0))
{
58 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Hello, who are you?")
59 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Move along, now.").also { return false }
58 -> setUnclosable(player, playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Hello, who are you?"))
59 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Move along, now."))
}
return true
}
@ -32,21 +33,22 @@ class TutorialFinanceAdvisorDialogue(player: Player? = null) : core.game.dialogu
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(getAttribute(player, "tutorial:stage", 0)){
58 -> when(stage++){
0 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "I'm the Financial Advisor. I'm here to tell people how to make money.")
1 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Okay. How can I make money then?")
2 -> npcl(core.game.dialogue.FacialExpression.HALF_THINKING, "How you can make money? Quite.")
3 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well there are three basic ways of making money here: combat, quests, and trading. I will talk you through each of them very quickly.")
4 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Let's start with combat as it is probably still fresh in your mind. Many enemies, both human and monster will drop items when they die.")
5 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Now, the next way to earn money quickly is by quests. Many people on " + settings!!.name + " have things they need doing, which they will reward you for.")
6 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "By getting a high level in skills such as Cooking, Mining, Smithing or Fishing, you can create or catch your own items and sell them for pure profit.")
7 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Lastly, we have jobs you can get from tutors in Lumbridge. These pay very handsomely early on!").also { stage++ }
8 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well, that about covers it. Move along now.")
0 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "I'm the Financial Advisor. I'm here to tell people how to make money."))
1 -> setUnclosable(player, playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Okay. How can I make money then?"))
2 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.HALF_THINKING, "How you can make money? Quite."))
3 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well there are three basic ways of making money here: combat, quests, and trading. I will talk you through each of them very quickly."))
4 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Let's start with combat as it is probably still fresh in your mind. Many enemies, both human and monster will drop items when they die."))
5 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Now, the next way to earn money quickly is by quests. Many people on " + settings!!.name + " have things they need doing, which they will reward you for."))
6 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "By getting a high level in skills such as Cooking, Mining, Smithing or Fishing, you can create or catch your own items and sell them for pure profit."))
7 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Lastly, we have jobs you can get from tutors in Lumbridge. These pay very handsomely early on!")).also { stage++ }
8 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well, that about covers it. Move along now."))
9 -> {
end()
setAttribute(player, "tutorial:stage", 59)
TutorialStage.load(player, 59)
}
}
59 -> TutorialStage.load(player, 59)
}
return true
}
@ -54,5 +56,4 @@ class TutorialFinanceAdvisorDialogue(player: Player? = null) : core.game.dialogu
override fun getIds(): IntArray {
return intArrayOf(NPCs.FINANCIAL_ADVISOR_947)
}
}

View file

@ -4,208 +4,226 @@ import content.global.handlers.iface.RulesAndInfo
import content.region.misc.tutisland.handlers.*
import core.ServerConstants
import core.api.*
import core.game.dialogue.ChatAnim
import core.game.dialogue.DialogueLabeller
import core.game.dialogue.DialogueOption
import core.game.interaction.InteractionListener
import core.game.interaction.QueueStrength
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.IronmanMode
import core.game.node.entity.player.link.TeleportManager
import core.game.node.item.Item
import core.game.world.GameWorld
import core.game.world.map.Location
import core.plugin.Initializable
import core.tools.END_DIALOGUE
import core.worker.ManagementEvents
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import proto.management.JoinClanRequest
/**
* Handles the magic tutor's dialogue
* @author Ceikry
*/
@Initializable
class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) {
private val STARTER_PACK = arrayOf(
Item(1351, 1),
Item(590, 1),
Item(303, 1),
Item(315, 1),
Item(1925, 1),
Item(1931, 1),
Item(2309, 1),
Item(1265, 1),
Item(1205, 1),
Item(1277, 1),
Item(1171, 1),
Item(841, 1),
Item(882, 25),
Item(556, 25),
Item(558, 15),
Item(555, 6),
Item(557, 4),
Item(559, 2)
)
private val STARTER_BANK = arrayOf(Item(995, 25))
override fun newInstance(player: Player?): core.game.dialogue.DialoguePlugin {
return TutorialMagicTutorDialogue(player)
class TutorialMagicTutorDialogue : InteractionListener {
override fun defineListeners() {
on(NPCs.MAGIC_INSTRUCTOR_946, NPC, "talk-to") { player, _ ->
val stage = getAttribute(player, "tutorial:stage", 0)
if (stage == 70 && inInventory(player, Items.AIR_RUNE_556) && inInventory(player, Items.MIND_RUNE_558)) {
// Player should be killing chickens instead, and could be. Instead of opening the dialogue and doing nothing (which will make you lose the tutorial island dialog), do nothing at all
return@on true
}
openDialogue(player, TutorialMagicTutorDialogueFile(), NPC(NPCs.MAGIC_INSTRUCTOR_946))
return@on true
}
}
}
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0))
{
67 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Hello.")
69 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Good. This is a list of your spells. Currently you can only cast one offensive spell called Wind Strike. Let's try it out on one of those chickens.")
70 -> if(!inInventory(player, Items.AIR_RUNE_556) && !inInventory(player, Items.MIND_RUNE_558))
{
player.dialogueInterpreter.sendDoubleItemMessage(Items.AIR_RUNE_556, Items.MIND_RUNE_558, "You receive some spare runes.")
class TutorialMagicTutorDialogueFile : DialogueLabeller() {
override fun addConversation() {
val STARTER_PACK = arrayOf(
Item(Items.BRONZE_AXE_1351),
Item(Items.TINDERBOX_590),
Item(Items.SMALL_FISHING_NET_303),
Item(Items.SHRIMPS_315),
Item(Items.BUCKET_1925),
Item(Items.EMPTY_POT_1931),
Item(Items.BREAD_2309),
Item(Items.BRONZE_PICKAXE_1265),
Item(Items.BRONZE_DAGGER_1205),
Item(Items.BRONZE_SWORD_1277),
Item(Items.WOODEN_SHIELD_1171),
Item(Items.SHORTBOW_841),
Item(Items.BRONZE_ARROW_882, 25),
Item(Items.AIR_RUNE_556, 25),
Item(Items.MIND_RUNE_558, 15),
Item(Items.WATER_RUNE_555, 6),
Item(Items.EARTH_RUNE_557, 4),
Item(Items.BODY_RUNE_559, 2)
)
val STARTER_BANK = arrayOf(Item(Items.COINS_995, 25))
exec { player, _ ->
when (getAttribute(player, "tutorial:stage", 0)) {
67 -> loadLabel(player, "hello")
69 -> loadLabel(player, "spelllist")
70 -> {
if (!inInventory(player, Items.AIR_RUNE_556, 1) || !inInventory(player, Items.MIND_RUNE_558, 1)) {
loadLabel(player, "givemorerunes")
} else {
goto("nowhere")
}
}
71 -> loadLabel(player, "finishedtutorial")
else -> goto("nowhere")
}
}
label("hello")
player(ChatAnim.FRIENDLY, "Hello.", unclosable = true)
npc(ChatAnim.FRIENDLY, "Good day, newcomer. My name is Terrova. I'm here to tell you about Magic. Let's start by opening your spell list.", unclosable = true)
exec { player, _ ->
setAttribute(player, "tutorial:stage", 68)
TutorialStage.load(player, 68)
}
label("spelllist")
npc(ChatAnim.FRIENDLY, "Good. This is a list of your spells. Currently you can only cast one offensive spell called Wind Strike. Let's try it out on one of those chickens.", unclosable = true)
exec { player, _ ->
setAttribute(player, "tutorial:stage", 70)
addItemOrDrop(player, Items.AIR_RUNE_556, 15)
addItemOrDrop(player, Items.MIND_RUNE_558, 15)
return false
}
71 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Alright, last thing. Are you interested in being an ironman or changing your experience rate?")
else -> return false
}
return true
}
item(Item(Items.AIR_RUNE_556), Item(Items.MIND_RUNE_558), "Terrova gives you 15 air runes and 15 mind runes!", unclosable = true)
exec { player, _ -> TutorialStage.load(player, 70) }
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(getAttribute(player, "tutorial:stage", 0))
{
67 -> when(stage++){
0 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Good day, newcomer. My name is Terrova. I'm here to tell you about Magic. Let's start by opening your spell list.")
1 -> {
end()
setAttribute(player, "tutorial:stage", 68)
TutorialStage.load(player, 68)
label("givemorerunes")
exec { player, _ ->
addItemOrDrop(player, Items.AIR_RUNE_556, 5)
addItemOrDrop(player, Items.MIND_RUNE_558, 5)
}
item(Item(Items.AIR_RUNE_556), Item(Items.MIND_RUNE_558), "You receive some spare runes.", unclosable = true)
exec { player, _ -> TutorialStage.load(player, 70) }
label("finishedtutorial")
exec { player, _ ->
if (ServerConstants.XP_RATES || ServerConstants.IRONMAN) {
loadLabel(player, "talk about inauthentic")
} else {
loadLabel(player, "leave")
}
}
69 -> when(stage++){
0 -> {
sendDoubleItemDialogue(player, Items.AIR_RUNE_556, Items.MIND_RUNE_558, "Terrova gives you 15 air runes and 15 mind runes!")
addItemOrDrop(player, Items.AIR_RUNE_556, 5)
addItemOrDrop(player, Items.MIND_RUNE_558, 5)
}
1 -> {
end()
setAttribute(player, "tutorial:stage", 70)
TutorialStage.load(player, 70)
}
label("talk about inauthentic")
npc(ChatAnim.FRIENDLY, "Alright, last thing. Are you interested in our inauthentic ${ServerConstants.SERVER_NAME} features?", unclosable = true)
goto("inauthentic")
label("inauthentic")
options(
DialogueOption("xprate","Change XP rate (current: ${player?.skills?.experienceMultiplier}x)", skipPlayer = true) { _, _ ->
return@DialogueOption ServerConstants.XP_RATES
},
DialogueOption("ironman","Set ironman mode (current: ${player?.ironmanManager?.mode?.name?.toLowerCase()})", skipPlayer = true) { _, _ ->
return@DialogueOption ServerConstants.IRONMAN
},
DialogueOption("leave","I'm ready now."),
unclosable = true)
label("xprate")
options(
DialogueOption("1.0x","1.0x (default)", skipPlayer = true),
DialogueOption("2.5x","2.5x", skipPlayer = true),
DialogueOption("5.0x","5.0x", skipPlayer = true),
title = "Change XP rate (current: ${player?.skills?.experienceMultiplier}x)",
unclosable = true
)
for (rate in doubleArrayOf(1.0, 2.5, 5.0)) {
label("${rate}x")
exec { player, _ -> player.skills.experienceMultiplier = rate }
manual(unclosable = true) { player, _ -> player.dialogueInterpreter.sendDialogue("You set your XP rate to: ${rate}x.") }
goto("inauthentic")
}
71 -> when(stage){
0 -> options("Set Ironman Mode (current: ${player.ironmanManager.mode.name})", "Change XP Rate (current: ${player.skills.experienceMultiplier}x)", "I'm ready now.").also { stage++ }
1 -> when(buttonId){
1 -> options("None","Standard","Ultimate","Nevermind.").also { stage = 10 }
2 -> options("1.0x","2.5x","5.0x").also { stage = 20 }
3 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well, you're all finished here now. I'll give you a reasonable number of starting items when you leave.").also { stage = 30 }
label("ironman")
options(
DialogueOption("NONE","None (default)", skipPlayer = true),
DialogueOption("STANDARD","Standard", skipPlayer = true),
DialogueOption("ULTIMATE","Ultimate (no bank)", skipPlayer = true),
title = "Change ironman mode (current: ${player?.ironmanManager?.mode?.name?.toLowerCase()}x)"
)
for (mode in arrayOf(IronmanMode.NONE, IronmanMode.STANDARD, IronmanMode.ULTIMATE)) {
label(mode.name)
exec { player, _ -> player.ironmanManager.mode = mode }
manual(unclosable = true){ player, _ -> return@manual player.dialogueInterpreter.sendDialogue("You set your ironman mode to: ${mode.name.toLowerCase()}.") }
exec { player, _ -> loadLabel(player, if (player.ironmanManager.mode == IronmanMode.NONE) "inauthentic" else "ironwarning") }
}
label("ironwarning")
manual(unclosable = true) { player, _ -> player.dialogueInterpreter.sendDialogue(*splitLines("WARNING: You have selected an ironman mode. This is an uncompromising mode that WILL completely restrict your ability to trade. This MAY leave you unable to complete certain content, including quests.")) }
goto("inauthentic")
label("leave")
npc(ChatAnim.FRIENDLY, "Well, you're all finished here now. I'll give you a reasonable number of starting items when you leave.", unclosable = true)
options(
DialogueOption("leave:yes","Yes, I'm ready.","I'm ready to go now, thank you.", ChatAnim.FRIENDLY),
DialogueOption("nowhere","No, not yet.","I'm not quite ready to go yet, thank you.", ChatAnim.FRIENDLY),
title = "Leave Tutorial Island?",
unclosable = true
)
label("leave:yes")
manual { player, _ ->
setAttribute(player, "/save:tutorial:complete", true)
setVarbit(player, 3756, 0)
setVarp(player, 281, 1000, true)
teleport(player, Location.create(3233, 3230), TeleportManager.TeleportType.NORMAL)
closeOverlay(player)
player.inventory.clear()
player.bank.clear()
player.equipment.clear()
player.interfaceManager.restoreTabs()
player.interfaceManager.setViewedTab(3)
player.inventory.add(*STARTER_PACK)
player.bank.add(*STARTER_BANK)
TutorialStage.removeHintIcon(player)
player.unhook(TutorialKillReceiver)
player.unhook(TutorialFireReceiver)
player.unhook(TutorialResourceReceiver)
player.unhook(TutorialUseWithReceiver)
player.unhook(TutorialInteractionReceiver)
player.unhook(TutorialButtonReceiver)
player.unhook(TutorialDialogPreserver)
if (GameWorld.settings!!.enable_default_clan) {
player.communication.currentClan = ServerConstants.SERVER_NAME.toLowerCase()
val clanJoin = JoinClanRequest.newBuilder()
clanJoin.clanName = ServerConstants.SERVER_NAME.toLowerCase()
clanJoin.username = player.name
ManagementEvents.publish(clanJoin.build())
}
10 -> {
stage = 0
if(buttonId < 5)
{
val mode = when (buttonId - 1)
{
0 -> IronmanMode.NONE
1 -> IronmanMode.STANDARD
2 -> IronmanMode.ULTIMATE
else -> IronmanMode.NONE
}
if (mode != IronmanMode.NONE) stage = 11
player.dialogueInterpreter.sendDialogue("You set your ironman mode to: ${mode.name}.")
player.ironmanManager.mode = mode
if (player.skills.experienceMultiplier == 10.0) player.skills.experienceMultiplier = 5.0
}
else
{
handle(interfaceId, 0)
}
}
11 -> player.dialogueInterpreter.sendPlainMessage(false, *splitLines("WARNING: You have selected an ironman mode. This is an uncompromising mode that WILL completely restrict your ability to trade. This MAY leave you unable to complete certain content, including quests.")).also { stage = 0 }
20 -> {
val rates = arrayOf(1.0,2.5,5.0)
val rate = rates[buttonId - 1]
if(rate == 10.0) {
player.dialogueInterpreter.sendDialogue("10.0x is no longer available!")
player.skills.experienceMultiplier = 5.0
stage = 0
return true
}
player.dialogueInterpreter.sendDialogue("You set your XP rate to: ${rate}x.")
player.skills.experienceMultiplier = rate
stage = 0
}
30 -> player.dialogueInterpreter.sendOptions("Leave Tutorial Island?", "Yes, I'm ready.", "No, not yet.").also { stage++ }
31 -> when(buttonId)
{
1 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "I'm ready to go now, thank you.").also { stage = 40 }
2 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "I'm not quite ready to go yet, thank you.").also { stage = END_DIALOGUE }
}
40 -> {
setAttribute(player, "/save:tutorial:complete", true)
setVarbit(player, 3756, 0)
setVarp(player, 281, 1000, true)
teleport(player, Location.create(3233, 3230), TeleportManager.TeleportType.NORMAL)
closeOverlay(player)
player.inventory.clear()
player.bank.clear()
player.equipment.clear()
player.interfaceManager.restoreTabs()
player.interfaceManager.setViewedTab(3)
player.inventory.add(*STARTER_PACK)
player.bank.add(*STARTER_BANK)
if(player.skills.experienceMultiplier == 10.0)
{
player.skills.experienceMultiplier = 5.0
}
//This overwrites the stuck dialogue after teleporting to Lumbridge for some reason
//Dialogue from 2007 or thereabouts
//Original is five lines, but if the same is done here it will break. Need to find another way of showing all this information.
interpreter.sendDialogue(
"Welcome to Lumbridge! To get more help, simply click on the",
"Lumbridge Guide or one of the Tutors - these can be found by looking",
"for the question mark icon on your mini-map. If you find you are lost",
"at any time, look for a signpost or use the Lumbridge Home Port Spell."
)
stage = 12
TutorialStage.removeHintIcon(player)
player.unhook(TutorialKillReceiver)
player.unhook(TutorialFireReceiver)
player.unhook(TutorialResourceReceiver)
player.unhook(TutorialUseWithReceiver)
player.unhook(TutorialInteractionReceiver)
player.unhook(TutorialButtonReceiver)
// This shows the actual dialog, which is what this manual stage is for.
// Dialog is from 2007 or thereabouts.
// Original is five lines, but if the same is done here it will break. Need to find another way of showing all this information.
player.dialogueInterpreter.sendDialogue(
"Welcome to Lumbridge! To get more help, simply click on the",
"Lumbridge Guide or one of the Tutors - these can be found by looking",
"for the question mark icon on your mini-map. If you find you are lost",
"at any time, look for a signpost or use the Lumbridge Home Port Spell."
)
if (ServerConstants.RULES_AND_INFO_ENABLED) {
RulesAndInfo.openFor(player)
if (GameWorld.settings!!.enable_default_clan) {
player.communication.currentClan = ServerConstants.SERVER_NAME.toLowerCase()
val clanJoin = JoinClanRequest.newBuilder()
clanJoin.clanName = ServerConstants.SERVER_NAME.toLowerCase()
clanJoin.username = player.name
ManagementEvents.publish(clanJoin.build())
// The teleport finishing will release the player, so we need to relock them here
queueScript(player, 4, QueueStrength.SOFT) { _ ->
player.lock()
return@queueScript stopExecuting(player)
}
}
12 -> {
player.setAttribute("close_c_", true)
end()
}
return@manual null
}
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.MAGIC_INSTRUCTOR_946)
label("nowhere")
exec { player, _ -> sendStageDialog(player) }
}
}

View file

@ -1,7 +1,7 @@
package content.region.misc.tutisland.dialogue
import core.api.*
import core.game.component.Component
import core.game.component.Component.setUnclosable
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
@ -25,32 +25,17 @@ class TutorialMasterChefDialogue(player: Player? = null) : DialoguePlugin(player
npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0))
{
18 -> Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.FRIENDLY,
"Ah! Welcome, newcomer. I am the Master Chef, Lev. It",
"is here I will teach you how to cook food truly fit for a",
"king."
)
)
19,20 -> {
if(!inInventory(player, Items.BREAD_DOUGH_2307))
{
if(!inInventory(player, Items.BUCKET_OF_WATER_1929))
{
sendItemDialogue(player, Items.BUCKET_OF_WATER_1929, "The Master Chef gives you another bucket of water.")
18 -> setUnclosable(player, interpreter.sendDialogues(npc, FacialExpression.FRIENDLY, "Ah! Welcome, newcomer. I am the Master Chef, Lev. It", "is here I will teach you how to cook food truly fit for a", "king."))
19, 20 -> {
if (!inInventory(player, Items.BREAD_DOUGH_2307)) {
if (!inInventory(player, Items.BUCKET_OF_WATER_1929)) {
setUnclosable(player, player.dialogueInterpreter.sendItemMessage(Items.BUCKET_OF_WATER_1929, "The Master Chef gives you another bucket of water."))
addItemOrDrop(player, Items.BUCKET_OF_WATER_1929)
TutorialStage.load(player, 19)
return false
}
if(!inInventory(player, Items.POT_OF_FLOUR_1933))
{
sendItemDialogue(player, Items.POT_OF_FLOUR_1933, "The Master Chef gives you another pot of flour.")
if (!inInventory(player, Items.POT_OF_FLOUR_1933)) {
setUnclosable(player, player.dialogueInterpreter.sendItemMessage(Items.POT_OF_FLOUR_1933, "The Master Chef gives you another pot of flour."))
addItemOrDrop(player, Items.POT_OF_FLOUR_1933)
TutorialStage.load(player, 19)
return false
}
}
@ -61,54 +46,21 @@ class TutorialMasterChefDialogue(player: Player? = null) : DialoguePlugin(player
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(getAttribute(player, "tutorial:stage", 0))
{
18 -> when(stage)
{
0 -> Component.setUnclosable(
player,
interpreter.sendDialogues(
player,
FacialExpression.HALF_GUILTY,
"I already know how to cook. Brynna taught me just",
"now."
)
).also { stage++ }
1 -> Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.LAUGH,
"Hahahahahaha! You call THAT cooking? Some shrimp",
"on an open log fire? Oh, no, no no. I am going to",
"teach you the fine art of cooking bread."
)
).also { stage++ }
2 -> Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.FRIENDLY,
"And no fine meal is complete without good music, so",
"we'll cover that while you're here too."
)
).also { stage++ }
when (getAttribute(player, "tutorial:stage", 0)) {
18 -> when(stage) {
0 -> setUnclosable(player, interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I already know how to cook. Brynna taught me just", "now.")).also { stage++ }
1 -> setUnclosable(player, interpreter.sendDialogues(npc, FacialExpression.LAUGH, "Hahahahahaha! You call THAT cooking? Some shrimp", "on an open log fire? Oh, no, no no. I am going to", "teach you the fine art of cooking bread.")).also { stage++ }
2 -> setUnclosable(player, interpreter.sendDialogues(npc, FacialExpression.FRIENDLY, "And no fine meal is complete without good music, so", "we'll cover that while you're here too.")).also { stage++ }
3 -> {
Component.setUnclosable(
player,
interpreter.sendDoubleItemMessage(
Items.BUCKET_OF_WATER_1929,
Items.POT_OF_FLOUR_1933,
"The Cooking Guide gives you a <col=08088A>bucket of water<col> and a <col=08088A>pot of flour</col>."
)
)
setUnclosable(player, interpreter.sendDoubleItemMessage(Items.BUCKET_OF_WATER_1929, Items.POT_OF_FLOUR_1933, "The Cooking Guide gives you a <col=08088A>bucket of water<col> and a","<col=08088A>pot of flour</col>."))
addItemOrDrop(player, Items.BUCKET_OF_WATER_1929)
addItemOrDrop(player, Items.POT_OF_FLOUR_1933)
stage++
setAttribute(player, "tutorial:stage", 19)
TutorialStage.load(player, 19)
}
4 -> {
end()
setAttribute(player, "tutorial:stage", 19)
TutorialStage.load(player, 19)
}
}

View file

@ -1,104 +1,95 @@
package content.region.misc.tutisland.dialogue
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.Items
import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage
import content.region.misc.tutisland.handlers.sendStageDialog
import core.api.*
import core.game.dialogue.ChatAnim
import core.game.dialogue.DialogueLabeller
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.player.Player
import core.game.node.item.Item
/**
* Handles the mining tutor's dialogue
* @author Ceikry
*/
@Initializable
class TutorialMiningInstructorDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player?): DialoguePlugin {
return TutorialMiningInstructorDialogue(player)
}
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0)) {
30 -> npcl(FacialExpression.FRIENDLY, "Hi there. You must be new around here. So what do I call you? 'Newcomer' seems so impersonal, and if we're going to be working together, I'd rather tell you by name.")
34 -> playerl(FacialExpression.FRIENDLY, "I prospected both types of rock! One set contains tin and the other has copper ore inside.")
35 -> {
if(!inInventory(player, Items.BRONZE_PICKAXE_1265)) {
addItemOrDrop(player, Items.BRONZE_PICKAXE_1265)
player.dialogueInterpreter.sendItemMessage(Items.BRONZE_PICKAXE_1265, "Dezzick gives you a bronze pickaxe!")
stage = 3
}
else {
TutorialStage.load(player, 35)
}
}
40 -> playerl(FacialExpression.ASKING, "How do I make a weapon out of this?")
41 -> {
if(!inInventory(player, Items.HAMMER_2347)) {
addItemOrDrop(player, Items.HAMMER_2347)
player.dialogueInterpreter.sendItemMessage(Items.HAMMER_2347, "Dezzick gives you a hammer!")
stage = 3
}
else
{
end()
TutorialStage.load(player, 41)
}
}
class MiningInstructorDialogue : InteractionListener {
override fun defineListeners() {
on(NPCs.MINING_INSTRUCTOR_948, IntType.NPC, "talk-to") { player, node ->
DialogueLabeller.open(player, MiningInstructorDialogueFile(), node as NPC)
return@on true
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(getAttribute(player, "tutorial:stage", 0)) {
30 -> when(stage) {
0 -> playerl(FacialExpression.FRIENDLY, "You can call me ${player.username}.").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "Ok then, ${player.username}. My name is Dezzick and I'm a miner by trade. Let's prospect some of these rocks.").also { stage++ }
2 -> {
end()
setAttribute(player, "tutorial:stage", 31)
TutorialStage.load(player, 31)
}
}
34,35 -> when(stage) {
0 -> npcl(FacialExpression.FRIENDLY, "Absolutely right, ${player.username}. These two ore types can be smelted together to make bronze.").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "So now you know what ore is in the rocks over there, why don't you have a go at mining some tin and copper? Here, you'll need this to start with.").also { stage++ }
2 -> {
addItem(player, Items.BRONZE_PICKAXE_1265)
player.dialogueInterpreter.sendItemMessage(Items.BRONZE_PICKAXE_1265, "Dezzick gives you a bronze pickaxe!")
stage++
}
3 -> {
end()
setAttribute(player, "tutorial:stage", 35)
TutorialStage.load(player, 35)
}
}
40,41 -> when(stage){
0 -> npcl(FacialExpression.FRIENDLY, "Okay, I'll show you how to make a dagger out of it. You'll be needing this..").also { stage++ }
1 -> {
addItem(player, Items.HAMMER_2347)
player.dialogueInterpreter.sendItemMessage(Items.HAMMER_2347, "Drezzick gives you a hammer!")
stage++
}
2 -> {
end()
setAttribute(player, "tutorial:stage", 41)
TutorialStage.load(player, 41)
}
}
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.MINING_INSTRUCTOR_948)
}
}
class MiningInstructorDialogueFile : DialogueLabeller() {
fun lostPickaxe(player: Player): Boolean {
return !inInventory(player, Items.BRONZE_PICKAXE_1265) && !inEquipment(player, Items.BRONZE_PICKAXE_1265)
}
override fun addConversation() {
assignToIds(NPCs.MINING_INSTRUCTOR_948)
exec { player, _ ->
when (getAttribute(player, "tutorial:stage", 0)) {
30 -> loadLabel(player, "hello")
34 -> loadLabel(player, "prospected")
35, 36, 37, 38, 39 -> loadLabel(player, if (lostPickaxe(player)) "lost pickaxe" else "nowhere")
40 -> loadLabel(player, "make wep")
41, 42, 43, 44, 45, 46 -> loadLabel(player, if (lostPickaxe(player)) "lost pickaxe" else if (!inInventory(player, Items.HAMMER_2347)) "lost hammer" else "nowhere")
else -> loadLabel(player, "nowhere")
}
}
label("hello")
npc(ChatAnim.FRIENDLY, "Hi there. You must be new around here. So what do I call you? 'Newcomer' seems so impersonal, and if we're going to be working together, I'd rather tell you by name.", unclosable = true)
player(ChatAnim.FRIENDLY, "You can call me ${player?.username}.", unclosable = true)
npc(ChatAnim.FRIENDLY, "Ok then, ${player?.username}. My name is Dezzick and I'm a miner by trade. Let's prospect some of these rocks.", unclosable = true)
exec { player, _ ->
setAttribute(player, "tutorial:stage", 31)
TutorialStage.load(player, 31)
}
label("prospected")
player(ChatAnim.FRIENDLY, "I prospected both types of rock! One set contains tin and the other has copper ore inside.", unclosable = true)
npc(ChatAnim.FRIENDLY, "Absolutely right, ${player?.username}. These two ore types can be smelted together to make bronze.", unclosable = true)
npc(ChatAnim.FRIENDLY, "So now you know what ore is in the rocks over there, why don't you have a go at mining some tin and copper? Here, you'll need this to start with.", unclosable = true)
exec { player, _ ->
addItem(player, Items.BRONZE_PICKAXE_1265)
setAttribute(player, "tutorial:stage", 35)
TutorialStage.load(player, 35)
}
item(Item(Items.BRONZE_PICKAXE_1265), "Dezzick gives you a bronze pickaxe!", unclosable = true)
goto("nowhere")
label("make wep")
player(ChatAnim.ASKING, "How do I make a weapon out of this?", unclosable = true)
npc(ChatAnim.FRIENDLY, "Okay, I'll show you how to make a dagger out of it. You'll be needing this.", unclosable = true)
exec { player, _ ->
addItem(player, Items.HAMMER_2347)
setAttribute(player, "tutorial:stage", 41)
TutorialStage.load(player, 41)
}
item(Item(Items.HAMMER_2347), "Dezzick gives you a hammer!", unclosable = true)
goto("nowhere")
label("lost pickaxe")
exec { player, _ -> addItem(player, Items.BRONZE_PICKAXE_1265) }
item(Item(Items.BRONZE_PICKAXE_1265), "Dezzick gives you a spare pickaxe.", unclosable = true)
exec { player, _ ->
val stage = getAttribute(player, "/save:tutorial:stage", 0)
if (stage >= 41 && !inInventory(player, Items.HAMMER_2347)) {
loadLabel(player, "lost hammer")
}
}
goto("nowhere")
label("lost hammer")
exec { player, _ -> addItem(player, Items.HAMMER_2347) }
item(Item(Items.HAMMER_2347), "Dezzick gives you a spare hammer.", unclosable = true)
goto("nowhere")
label("nowhere")
exec { player, _ -> sendStageDialog(player) }
}
}

View file

@ -9,6 +9,7 @@ import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage
import core.game.component.Component.setUnclosable
/**
* Handles the prayer guide's dialogue
@ -24,9 +25,9 @@ class TutorialPrayerDialogue(player: Player? = null) : DialoguePlugin(player) {
npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0))
{
60 -> npcl(FacialExpression.FRIENDLY, "Greetings! I'd just like to briefly go over two topics with you: Prayer, and Friend's.")
62 -> npcl(FacialExpression.FRIENDLY, "Prayers have all sorts of wonderful benefits! From boosting defence and damage, to protecting you from outside damage, to saving items on death!")
65 -> npcl(FacialExpression.FRIENDLY, "For your friend and ignore lists, it's quite simple really! Use your friend list to keep track of players who you like, and ignore those you don't!")
60 -> setUnclosable(player, npcl(FacialExpression.FRIENDLY, "Greetings! I'd just like to briefly go over two topics with you: Prayer, and Friend's."))
62 -> setUnclosable(player, npcl(FacialExpression.FRIENDLY, "Prayers have all sorts of wonderful benefits! From boosting defence and damage, to protecting you from outside damage, to saving items on death!"))
65 -> setUnclosable(player, npcl(FacialExpression.FRIENDLY, "For your friend and ignore lists, it's quite simple really! Use your friend list to keep track of players who you like, and ignore those you don't!"))
}
return true
}
@ -35,8 +36,8 @@ class TutorialPrayerDialogue(player: Player? = null) : DialoguePlugin(player) {
when(getAttribute(player, "tutorial:stage", 0))
{
60 -> when(stage++){
0 -> playerl(FacialExpression.FRIENDLY, "Alright, sounds fun!")
1 -> npcl(FacialExpression.FRIENDLY, "Right, so first thing: Prayer. Prayer is trained by offering bones to the gods, and can grant you many boons!")
0 -> setUnclosable(player, playerl(FacialExpression.FRIENDLY, "Alright, sounds fun!"))
1 -> setUnclosable(player, npcl(FacialExpression.FRIENDLY, "Right, so first thing: Prayer. Prayer is trained by offering bones to the gods, and can grant you many boons!"))
2 -> {
end()
setAttribute(player, "tutorial:stage", 61)
@ -45,8 +46,8 @@ class TutorialPrayerDialogue(player: Player? = null) : DialoguePlugin(player) {
}
62 -> when(stage++){
0 -> playerl(FacialExpression.AMAZED, "Very cool!")
1 -> npcl(FacialExpression.FRIENDLY, "Next up, let's talk about friends.")
0 -> setUnclosable(player, playerl(FacialExpression.AMAZED, "Very cool!"))
1 -> setUnclosable(player, npcl(FacialExpression.FRIENDLY, "Next up, let's talk about friends."))
2 -> {
end()
setAttribute(player, "tutorial:stage", 63)

View file

@ -12,6 +12,7 @@ import core.plugin.Initializable
import org.rs09.consts.Components
import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage
import core.game.component.Component.setUnclosable
/**
* Handles the quest guide's dialogue
@ -27,7 +28,7 @@ class TutorialQuestGuideDialogue(player: Player? = null) : DialoguePlugin(player
npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0))
{
27 -> Component.setUnclosable(
27 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -37,7 +38,7 @@ class TutorialQuestGuideDialogue(player: Player? = null) : DialoguePlugin(player
)
)
28 -> Component.setUnclosable(
28 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -57,7 +58,7 @@ class TutorialQuestGuideDialogue(player: Player? = null) : DialoguePlugin(player
when(getAttribute(player, "tutorial:stage", 0))
{
27 -> {
Component.setUnclosable(
setUnclosable(
player,
interpreter.sendPlaneMessageWithBlueTitle(
"Open the Quest Journal.",
@ -72,7 +73,7 @@ class TutorialQuestGuideDialogue(player: Player? = null) : DialoguePlugin(player
}
28 -> when(stage)
{
0 -> Component.setUnclosable(
0 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -83,7 +84,7 @@ class TutorialQuestGuideDialogue(player: Player? = null) : DialoguePlugin(player
"to begin."
)
).also { stage++ }
1 -> Component.setUnclosable(
1 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -93,7 +94,7 @@ class TutorialQuestGuideDialogue(player: Player? = null) : DialoguePlugin(player
"see marking my house."
)
).also { stage++ }
2 -> Component.setUnclosable(
2 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -118,5 +119,4 @@ class TutorialQuestGuideDialogue(player: Player? = null) : DialoguePlugin(player
override fun getIds(): IntArray {
return intArrayOf(NPCs.QUEST_GUIDE_949)
}
}

View file

@ -1,7 +1,6 @@
package content.region.misc.tutisland.dialogue
import core.api.setAttribute
import core.game.component.Component
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
@ -9,10 +8,12 @@ import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage
import core.game.component.Component.setUnclosable
/**
* Handles the RuneSccape guide's dialogue
* Handles the 2009scape guide's dialogue
* @author Ceikry
* @author Player Name
*/
@Initializable
class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
@ -23,26 +24,12 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
val tutStage = player?.getAttribute("tutorial:stage", 0) ?: 0
if(tutStage < 2) {
end()
player.dialogueInterpreter.sendDialogues(npc,FacialExpression.HALF_GUILTY,"Greetings! Please follow the onscreen, instructions!")
return false
} else {
Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.HALF_GUILTY,
"Greetings! Please follow the onscreen",
"instructions!"
)
)
}
if(tutStage == 2)
{
if (tutStage < 2) {
setUnclosable(player, player.dialogueInterpreter.sendDialogues(npc,FacialExpression.HALF_GUILTY,"Greetings! Please follow the onscreen instructions!"))
stage = 99
} else if (tutStage == 2) {
player.lock()
Component.setUnclosable(
setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -52,26 +39,17 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
)
)
stage = 0
return true
}
else
{
Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.HALF_GUILTY,
"Please follow the onscreen instructions!"
)
)
return false
} else {
setUnclosable(player, player.dialogueInterpreter.sendDialogues(npc,FacialExpression.HALF_GUILTY,"Please follow the onscreen instructions!"))
stage = 99
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(stage)
{
0 -> Component.setUnclosable(
0 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -81,7 +59,7 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
)
).also { stage++ }
1 -> Component.setUnclosable(
1 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -92,7 +70,7 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
)
).also { stage++ }
2 -> Component.setUnclosable(
2 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -104,7 +82,7 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
)
).also { stage++ }
3 -> Component.setUnclosable(
3 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -114,7 +92,7 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
)
).also { stage++ }
4 -> Component.setUnclosable(
4 -> setUnclosable(
player,
interpreter.sendDialogues(
npc,
@ -130,6 +108,11 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
setAttribute(player, "tutorial:stage", 3)
TutorialStage.load(player, 3)
}
99 -> {
end()
val tutStage = player?.getAttribute("tutorial:stage", 0) ?: 0
TutorialStage.load(player, tutStage)
}
}
return true
}

View file

@ -0,0 +1,554 @@
package content.region.misc.tutisland.handlers
import core.api.getAttribute
import core.api.inInventory
import core.game.component.Component.setUnclosable
import core.game.event.DialogueCloseEvent
import core.game.event.EventHook
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.world.GameWorld.settings
import org.rs09.consts.Items
import kotlin.also
fun sendStageDialog(player: Player, stage: Int) {
val message = when (stage) {
0 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Getting started",
"To start the tutorial use your left mouse button to click on the",
"" + settings!!.name + " Guide in this room. He is indicated by a flashing",
"yellow arrow above his head. If you can't see him, use your",
"keyboard's arrow keys to rotate the view."
)
1 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"",
"",
"Game options",
"Please click on the flashing spanner icon found at the bottom",
"right of your screen. This will display your game options."
)
2 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"Game Options",
"In the interface, you can now see a variety of options such as",
"screen brightness, sound and music volume and whether you",
"want to accept aid from other player's or not. Don't worry",
"about these too much for now; they will become easier as you",
"explore the game. Talk to the " + settings!!.name + " Guide to continue."
)
3 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"Interacting with scenery",
"You can interact with many items of scenery by simply clicking",
"on them. Right clicking will also give more options. Feel free to",
"try it with the things in this room, then click on the door",
"indicated with the yellow arrow to go though to the next",
"instructor."
)
4 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Moving around",
"Follow the path to find the next instructor. Clicking on the",
"ground will walk you to that point. You can also navigate by",
"clicking on the minimap in the top-right corner of your screen.",
"Talk to Survival Expert by the pond to continue the tutorial."
)
5 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Viewing the items that you were given.",
"Click on the flashing backpack icon to the right-hand side of",
"the main window to view your inventory. Your inventory is a list",
"of everything you have in your backpack.",
""
)
6 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Cut down a tree",
"You can click on the backpack icon at any time to view the",
"items that you currently have in your inventory. You will see",
"that you now have an axe in your inventory. Use this to get",
"some logs by clicking on one of the trees in the area."
)
7 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Please wait.",
"",
"Your character is now attempting to cut down the tree. Sit back",
"for a moment while " + (if (player.appearance.isMale) "he" else "she") + " does all the hard work.",
""
)
8 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Making a fire",
"Well done! You managed to cut some logs from the tree! Next,",
"use the tinderbox in your inventory to light the logs.",
"First click on the tinderbox to 'use' it.",
"Then click on the logs in your inventory to light them."
)
9 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Please wait.",
"",
"Your character is now attempting to light the fire.",
"This should only take a few seconds.",
""
)
10 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"You gained some experience.",
"",
"Click on the flashing bar graph icon near the inventory button",
"to see your skill state.",
""
)
11 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Your skill stats",
"Here you will see how good your skills are. As you move your",
"mouse over any of the icons in this tab, the small yellow popup",
"box will show you the exact amount of experience you have",
"and how much is needed to get to the next level. Speak to the survival guide."
)
12 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Catch some shrimp",
"Click on the bubbling fishing spot, indicated by the flashing",
"arrow. Remember, you can check your inventory by clicking the",
"backpack icon.",
""
)
13 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Please wait.",
"",
"This should only take a few seconds.",
"As you gain Fishing experience you'll find that there are many",
"types of fish and many ways to catch them."
)
14 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Cooking your shrimp",
"Now you have caught some shrimp, let's cook it. First light a",
"fire: chop down a tree and then use the tinderbox on the logs.",
"If you've lost your axe or tinderbox Brynna will give you",
"another."
).also {
if (!inInventory(player, Items.RAW_SHRIMPS_317, 1)) {
setUnclosable(
player,
player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Cooking your shrimp",
"Now right click on the shrimp and select the use option. Next,",
"left click on the fire you just lit. If while doing this you look in",
"the top left of the screen, you will see the instruction that",
"you're giving your character."
)
)
}
}
15 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Burning your shrimp",
"You have just burnt your first shrimp. This is normal. As you",
"get more experience in Cooking you will burn stuff less often.",
"Let's try cooking without burning it this time. First catch some",
"more shrimp, then use them on a fire."
)
16 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Well done, you've just cooked your first " + settings!!.name + " meal.",
"If you'd like a recap on anything you've learnt so far, speak to",
"the Survival Expert. You can now move on to the next",
"instructor. Click on the gate shown and follow the path.",
"Remember, you can move the camera with the arrow keys."
)
17 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Find your next instructor",
"Follow the path until you get to the door with the yellow arrow",
"above it. Click on the door to open it. Notice the mini map in the",
"top right; this shows a top down view of the area around you.",
"This can also be used for navigation."
)
18 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Find your next instructor",
"Talk to the chef indicated. He will teach you the more advanced",
"aspects of Cooking such as combining ingredients. He will also",
"teach you about your Music Player.",
""
)
19 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Making dough",
"This is the base for many of the meals. To make dough we must",
"mix flour and water. First, right click the bucket of water and",
"select use, then left click on the pot of flour.",
""
)
20 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Cooking dough",
"Now you have made dough, you can cook it. To cook the dough,",
"use it with the range shown by the arrow. If you lose your",
"dough, talk to Lev - he will give you more ingredients.",
""
)
21 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"Cooking dough",
"Well done! Your first loaf of bread. As you gain experience in",
"Cooking, you will be able to make other things like pies, cakes",
"and even kebabs. Now you've got the hang of cooking, let's",
"move on. Click on the flashing icon in the bottom right to see",
"the flashing icon in the bottom right to see the Music Player."
)
22 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"The Music Player",
"From this interface you can control the music that is played.",
"As you explore the world and complete quests, more of the",
"tunes will become unlocked. Once you've examined this menu,",
"use the next door to continue. If you need a recap on anything",
"you've learnt so far, speak to the Master Chef."
)
23 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Emotes",
"",
"Now how about showing some feelings? You will see a flashing",
"icon in the shape of a person. Click on that to access your",
"emotes."
)
24 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Emotes",
"For those situations where words don't quite describe how you feel try",
"an emote. Go ahead try one out! You might notice that some of the",
"emotes are grey and cannot be used now. Don't worry! As you",
"progress further into the game you'll gain access to all sorts of things."
)
25 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Running",
"",
"It's only a short distance to the next guide.",
"Why not try running there? To do this, click on the run icon",
"next to the minimap."
)
26 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"Run to the next guide",
"Now that you have the run button turned on, follow the path",
"until you come to the end. You may notice that the number on",
"the button goes down. This is your run energy. If your run",
"energy reaches zero, you'll stop running. Click on the door to",
"pass through it."
)
27 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Talk with the Quest Guide.",
"",
"He will tell you all about quests.",
"",
""
)
28 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Your Quest Journal",
"",
"This is your Quest Journal, a list of all the quests in the game.",
"Talk to the Quest Guide again for an explanation.",
""
)
29 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"",
"Moving on",
"It's time to enter some caves. Click on the ladder to go down to",
"the next area.",
""
)
30 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Mining and Smithing",
"",
"Next let's get you a weapon, or more to the point, you can",
"make your first weapon yourself. Don't panic, the Mining",
"Instructor will help you. Talk to him and he'll tell you all about it."
)
31 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Prospecting",
"To prospect a mineable rock, just right click it and select the",
"'prospect rock' option. This will tell you the type of ore you can",
"mine from it. Try it now on one of the rocks indicated.",
""
)
32 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Please wait.",
"",
"Your character is now attempting to prospect the rock. This",
"should only take a few seconds.",
""
)
33 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"It's tin.",
"",
"So now you know there's tin in the grey rocks, try prospecting the",
"brown ones next.",
""
)
34 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"It's copper.",
"",
"Talk to the Mining Instructor to find out about these types of",
"ore and how you can mine them.",
"He'll even give you the required tools.",
)
35 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Mining",
"",
"It's quite simple really. All you need to do is right click on the",
"rock and select 'mine' You can only mine when you have a",
"pickaxe. So give it a try: first mine one tin ore.",
)
36 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Please wait.",
"",
"Your character is now attempting to mine the rock.",
"This should only take a few seconds.",
""
)
37 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Mining",
"",
"Now you have some tin ore you just need some copper ore,",
"then you'll have all you need to create a bronze bar. As you",
"did before right click on the copper rock and select 'mine'."
)
38 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Smelting",
"You should now have both some copper and tin ore. So let's",
"smelt them to make a bronze bar. To do this, right click on",
"either tin or copper ore and select use then left click on the",
"furnace. Try it now."
)
39, 40 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"You've made a bronze bar!",
"",
"Speak to the Mining Instructor and he'll show you how to make",
"it into a weapon.",
""
)
41 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Smithing a dagger",
"To smith you'll need a hammer - like the one you were given by",
"Dezzick - access to an anvil like the one with the arrow over it",
"and enough metal bars to make what you are trying to smith.",
"To start the process, use the bar on one of the anvils."
)
42 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Smithing a dagger.",
"Now you have the Smithing menu open, you will see a list of all",
"the things you can make. Only the dagger can be made at your",
"skill level; this is shown by the white text under it. You'll need",
"to select the dagger to continue."
)
43 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"You've finished in this area.",
"",
"So let's move on. Go through the gates shown by the arrow.",
"Remember, you may need to move the camera to see your",
"surroundings. Speak to the guide for a recap at any time.",
)
44 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Combat",
"",
"In this area you will find out about combat with swords and",
"bows. Speak to the guide and he will tell you all about it.",
""
)
45 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Wielding weapons",
"",
"You now have access to a new interface. Click on the flashing",
"icon of a man, the one to the right of your backpack icon.",
""
)
46 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"This is your worn inventory.",
"From here you can see what items you have equipped. Let's",
"get one of those slots filled, go back to your inventory and",
"right click your dagger, select wield from the menu.",
""
)
47 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"You're now holding your dagger.",
"Clothes, armour, weapons and many other items are equipped",
"like this. You can unequip items by clicking on the item in the",
"worn equipment. You can close this window by clicking on the",
"small 'x' in the top-right hand corner. Speak to the Combat",
"Instructor."
)
48 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"Unequipping items.",
"In your worn inventory panel, right click on the dagger and",
"select the remove option from the drop down list. After you've",
"unequipped the dagger, wield the sword and shield. As you",
"pass the mouse over an item you will see its name appear at",
"the top left of the screen."
)
49 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Combat interface.",
"",
"Click on the flashing crossed swords icon to see the combat",
"interface.",
""
)
50 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"This is your combat interface.",
"From this interface you can select the type of attack your",
"character will use. Different monsters have different",
"weaknesses. If you hover your mouse over the buttons, you",
"will see the type of XP you will receive when using each type of",
"attack. Now you have the tools needed for battle why not slay",
"some rats. Click on the gates indicated to continue."
)
51 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Attacking",
"To attack the rat, click it and select the attack option. You",
"will then walk over to it and start hitting it.",
"",
""
)
52 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Sit back and watch.",
"While you are fighting you will see a bar over your head. The",
"bar shows how much health you have left. Your opponent will",
"have one too. You will continue to attack the rat until it's dead",
"or you do something else."
)
53 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Well done, you've made your first kill!",
"",
"Pass through the gate and talk to the Combat Instructor; he",
"will give you your next task.",
""
)
54 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Rat ranging",
"Now you have a bow and some arrows. Before you can use",
"them you'll need to equip them. Once equipped with the",
"ranging gear try killing another rat. Remember: to attack, right",
"click on the monster and select attack."
)
55 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Moving on.",
"You have completed the tasks here. To move on, click on the",
"ladder shown. If you need to go over any of what you learnt",
"here, just talk to the Combat Instructor and he'll tell you what",
"he can."
)
56 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Banking.",
"Follow the path and you will come to the front of a building.",
"This is the 'Bank of " + settings!!.name + "' where you can store all your",
"most valued items. To open your bank box just right click on an",
"open booth indicated and select 'use'."
)
57 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"This is your bank box.",
"You can store stuff here for safekeeping. If you die, anything",
"in your bank will be saved. To deposit something, right click it",
"and select 'Deposit-1'. Once you've had a good look, close the",
"window and move on through the door indicated."
)
58 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Financial advice",
"",
"The guide here will tell you all about making cash. Just click on",
"him to hear what he's got to say.",
""
)
59 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"",
"",
"Continue through the next door.",
"",
""
)
60 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Prayer",
"Follow the path to the chapel and enter it.",
"Once inside talk to the monk. He'll tell you all about the Prayer",
"skill.",
""
)
61 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Your Prayer List",
"",
"Click on the flashing icon to open the Prayer List.",
"",
""
)
62 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"",
"Your Prayer List",
"",
"Talk with Brother Brace and he'll tell you all about prayers.",
""
)
63 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"",
"Friends list",
"You should now see another new icon. Click on the flashing",
"smiling face to open your Friend List.",
""
)
64 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"This is your Friends List.",
"",
"This will be explained by Brother Brace shortly, but first click",
"on the other flashing face in the interface.",
""
)
65 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"This is your Ignore List.",
"The two lists, Friends and Ignore - can be very helpful for",
"keeping track of when your friends are online or for blocking",
"messages from people you simply don't like. Speak with",
"Brother Brace and he will tell you more."
)
66 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"",
"Your final instructor!",
"You're almost finished on tutorial island. Pass through the",
"door to find the path leading to your final instructor.",
""
)
67 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Your final instructor!",
"Just follow the path to the Wizard's house, where you will be",
"shown how to cast spells. Just talk with the mage indicated to",
"find out more.",
""
)
68 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"Open up your final tab.",
"",
"Open up the Magic Spellbook tab by clicking on the flashing",
"icon next to the Prayer List tab you just learned about.",
""
)
69 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"",
"This is your spell list.",
"",
"Ask the mage about it.",
""
)
70 -> player.dialogueInterpreter.sendScrollMessageWithBlueTitle(
"Cast Wind Strike at a chicken.",
"Now you have the runes you should see the Wind Strike icon at the",
"top-left of your spellbook, second in from the left. Walk over",
"to the caged chickens, click the Wind Strike icon and then",
"select one of the chickens to cast it on. It may take several",
"tries."
)
71 -> player.dialogueInterpreter.sendPlaneMessageWithBlueTitle(
"You have almost completed the tutorial!",
"",
"All you need to do now is teleport to the mainland. Just speak",
"with Terrova and he'll tell you how to do that.",
""
)
else -> null
}
setUnclosable(player, message ?: return)
}
fun sendStageDialog(entity: Entity) {
val player = entity as Player
val stage = getAttribute(player, "tutorial:stage", 0)
sendStageDialog(player, stage)
}
// Because we don't have proper interface stacking, the above unclosable dialogs can still be closed, if a new dialog
// opens up over it and that dialog *is* closable. This is the case for npc dialogs and the smelting interface. Fake the
// authentic behavior by making sure we reopen our unclosable dialog when this happens.
object TutorialDialogPreserver : EventHook<DialogueCloseEvent> {
override fun process(entity: Entity, event: DialogueCloseEvent) {
sendStageDialog(entity)
}
}

View file

@ -7,13 +7,30 @@ import core.game.node.entity.player.Player
import content.global.skill.fishing.FishingSpot
import content.global.skill.gather.mining.MiningNode
import content.global.skill.gather.woodcutting.WoodcuttingNode
import core.api.animate
import core.api.delayScript
import core.api.forceWalk
import core.api.inInventory
import core.api.lock
import core.api.lockInteractions
import core.api.playAudio
import core.api.queueScript
import core.api.replaceSlot
import core.api.stopExecuting
import core.game.event.*
import core.game.interaction.QueueStrength
import core.game.node.entity.impl.Animator
import core.game.node.item.Item
import core.game.world.map.Location
import core.game.world.update.flag.context.Animation
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import org.rs09.consts.Sounds
/**
* Event receivers for tutorial island
* @author Ceikry
* @author Ceikry, Player Name
*/
object TutorialButtonReceiver : EventHook<ButtonClickEvent>
{
@ -77,7 +94,7 @@ object TutorialButtonReceiver : EventHook<ButtonClickEvent>
}
//Open equipment tab SD:548,42 HD:746,45
45 -> if((event.iface == 548 && event.buttonId == 42) || (event.iface == 746 && event.buttonId == 45)){
45, 46 -> if((event.iface == 548 && event.buttonId == 42) || (event.iface == 746 && event.buttonId == 45)){
setAttribute(entity, "tutorial:stage", 46)
TutorialStage.load(entity, 46)
}
@ -136,18 +153,6 @@ object TutorialInteractionReceiver : EventHook<InteractionEvent>
TutorialStage.load(entity, 13)
}
//Prospect rock - Tin
31 -> if(MiningNode.forId(event.target.id)?.identifier?.equals(2.toByte()) == true && event.option == "prospect"){
setAttribute(entity, "tutorial:stage", 32)
TutorialStage.load(entity, 32)
}
//Prospect rock- Copper
33 -> if(MiningNode.forId(event.target.id)?.identifier?.equals(1.toByte()) == true && event.option == "prospect"){
setAttribute(entity, "tutorial:stage", 34)
TutorialStage.load(entity, 34)
}
//Mine rock - Tin
35 -> if(MiningNode.forId(event.target.id)?.identifier?.equals(2.toByte()) == true && event.option == "mine"){
setAttribute(entity, "tutorial:stage", 36)
@ -211,30 +216,12 @@ object TutorialResourceReceiver : EventHook<ResourceProducedEvent>
TutorialStage.load(entity, 14)
}
//Cook a shrimp
14,15 -> if(event.itemId == Items.BURNT_SHRIMP_7954)
{
setAttribute(entity, "tutorial:stage", 15)
TutorialStage.load(entity, 15)
}
else if(event.itemId == Items.SHRIMPS_315)
{
setAttribute(entity, "tutorial:stage", 16)
TutorialStage.load(entity, 16)
}
//Make some bread dough
19 -> if(event.itemId == Items.BREAD_DOUGH_2307) {
setAttribute(entity, "tutorial:stage", 20)
TutorialStage.load(entity, 20)
}
//Bake some bread
20 -> if(event.itemId == Items.BREAD_2309 || event.itemId == Items.BURNT_BREAD_2311) {
setAttribute(entity, "tutorial:stage", 21)
TutorialStage.load(entity, 21)
}
//Mine some tin ore
36 -> if(event.itemId == Items.TIN_ORE_438){
setAttribute(entity, "tutorial:stage", 37)

View file

@ -1,51 +0,0 @@
package content.region.misc.tutisland.handlers
import core.api.*
import core.game.event.ResourceProducedEvent
import core.game.node.entity.skill.Skills
import content.global.skill.smithing.smelting.Bar
import core.game.system.task.Pulse
import core.game.world.update.flag.context.Animation
import org.rs09.consts.Items
import org.rs09.consts.Scenery
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
/**
* Listener for tutorial island furnace
* @author Byte
*/
class TutorialFurnaceListener : InteractionListener {
companion object {
private val ANIMATION = Animation(833)
private val ORES = intArrayOf(
Items.TIN_ORE_438,
Items.COPPER_ORE_436
)
}
override fun defineListeners() {
onUseWith(IntType.SCENERY, ORES, Scenery.FURNACE_3044) { player, _, _ ->
if (!inInventory(player, Items.TIN_ORE_438) || !inInventory(player, Items.COPPER_ORE_436)) {
return@onUseWith true
}
animate(player, ANIMATION)
submitIndividualPulse(player, object: Pulse(2) {
override fun pulse(): Boolean {
if (removeItem(player, Items.TIN_ORE_438) && removeItem(player, Items.COPPER_ORE_436)) {
addItem(player, Items.BRONZE_BAR_2349)
rewardXP(player, Skills.SMITHING, Bar.BRONZE.experience)
player.dispatch(ResourceProducedEvent(Items.BRONZE_BAR_2349, 1, player, Items.COPPER_ORE_436))
return true
}
return false
}
})
return@onUseWith true
}
}
}

View file

@ -1,13 +1,25 @@
package content.region.misc.tutisland.handlers
import content.global.skill.smithing.smelting.Bar
import content.region.misc.tutisland.dialogue.RatPenDialogue
import core.api.*
import core.game.event.ResourceProducedEvent
import core.game.node.scenery.Scenery
import core.game.system.task.Pulse
import core.game.world.map.Location
import org.rs09.consts.NPCs
import core.game.interaction.InteractionListener
import core.game.interaction.IntType
import core.game.interaction.QueueStrength
import core.game.node.entity.impl.Animator
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.node.item.Item
import core.game.world.repository.Repository
import core.game.world.update.flag.context.Animation
import org.rs09.consts.Items
import org.rs09.consts.Sounds
/**
* Handles tutorial-specific node interactions
@ -16,10 +28,13 @@ import core.game.world.repository.Repository
class TutorialListeners : InteractionListener {
val GUIDE_HOUSE_DOOR = 3014
val COOKS_DOOR = 3017
val RANGE = 3039
val COOKS_EXIT = 3018
val QUEST_ENTER = 3019
val QUEST_LADDER = 3029
val QUEST_EXIT_LADDER = 3028
val TIN_ROCK = 3043
val COPPER_ROCK = 3042
val COMBAT_EXIT = 3030
val BANK_EXIT = 3024
val FINANCE_EXIT = 3025
@ -27,6 +42,7 @@ class TutorialListeners : InteractionListener {
val FIRST_GATE = intArrayOf(3015,3016)
val COMBAT_GATES = intArrayOf(3020,3021)
val RAT_GATES = intArrayOf(3022, 3023)
val FURNACE = 3044
override fun defineListeners() {
on(GUIDE_HOUSE_DOOR, IntType.SCENERY, "open"){ player, door ->
@ -60,6 +76,36 @@ class TutorialListeners : InteractionListener {
return@on true
}
fun cookBread(player: Player, dough: Item): Boolean {
if (getAttribute(player, "tutorial:stage", 0) < 20) {
return true
}
// Need to reinvent the wheel of cooking. Yes, I do. On tutorial island, we don't want the default stuff like asking the player what dough they want to make.
queueScript(player, 0, QueueStrength.WEAK) { stage ->
if (stage == 0) {
val RANGE_ANIMATION = Animation(883, Animator.Priority.HIGH)
lock(player, RANGE_ANIMATION.duration)
lockInteractions(player, RANGE_ANIMATION.duration)
animate(player, RANGE_ANIMATION)
playAudio(player, Sounds.FRY_2577)
return@queueScript delayScript(player, RANGE_ANIMATION.duration)
} else {
replaceSlot(player, dough.slot, Item(Items.BREAD_2309), dough)
setAttribute(player, "tutorial:stage", 21)
TutorialStage.load(player, 21)
return@queueScript stopExecuting(player)
}
}
return true
}
on(RANGE, IntType.SCENERY, "use") { player, _ ->
val dough = player.inventory.get(Item(Items.BREAD_DOUGH_2307)) ?: return@on true
return@on cookBread(player, dough)
}
onUseWith(IntType.SCENERY, Items.BREAD_DOUGH_2307, RANGE) { player, dough, _ ->
return@onUseWith cookBread(player, dough as Item)
}
on(COOKS_EXIT, IntType.SCENERY, "open"){ player, door ->
if(getAttribute(player, "tutorial:stage", 0) != 22)
return@on true
@ -105,23 +151,41 @@ class TutorialListeners : InteractionListener {
return@on true
}
on(COMBAT_GATES, IntType.SCENERY, "open"){ player, gate ->
if(getAttribute(player, "tutorial:stage", 0) != 43)
on(TIN_ROCK, IntType.SCENERY, "prospect") { player, _ ->
if (getAttribute(player, "tutorial:stage", 0) != 31) {
return@on true
}
setAttribute(player, "tutorial:stage", 32)
TutorialStage.load(player, 32)
return@on true
}
on(COPPER_ROCK, IntType.SCENERY, "prospect") { player, _ ->
if (getAttribute(player, "tutorial:stage", 0) != 33) {
return@on true
}
setAttribute(player, "tutorial:stage", 34)
TutorialStage.load(player, 34)
return@on true
}
setAttribute(player, "tutorial:stage", 44)
TutorialStage.load(player, 44)
on(COMBAT_GATES, IntType.SCENERY, "open"){ player, gate ->
if (getAttribute(player, "tutorial:stage", 0) < 43) {
return@on true
}
if (getAttribute(player, "tutorial:stage", 0) == 43) {
setAttribute(player, "tutorial:stage", 44)
TutorialStage.load(player, 44)
}
core.game.global.action.DoorActionHandler.handleAutowalkDoor(player, gate as Scenery)
}
on(RAT_GATES, IntType.SCENERY, "open") { player, gate ->
val stage = getAttribute(player, "tutorial:stage", 0)
if(stage !in 50..53){
player.dialogueInterpreter.sendDialogues(NPCs.COMBAT_INSTRUCTOR_944, core.game.dialogue.FacialExpression.ANGRY, "Oi, get away from there!","Don't enter my rat pen unless I say so!")
if (stage !in 50..53) {
openDialogue(player, RatPenDialogue(), NPC(NPCs.COMBAT_INSTRUCTOR_944))
return@on true
}
if(stage == 50) {
if (stage == 50) {
setAttribute(player, "tutorial:stage", 51)
TutorialStage.load(player, 51)
}
@ -130,11 +194,14 @@ class TutorialListeners : InteractionListener {
}
on(COMBAT_EXIT, IntType.SCENERY, "climb-up") { player, ladder ->
if(getAttribute(player, "tutorial:stage", 0) != 55)
val stage = getAttribute(player, "tutorial:stage", 0)
if (stage < 55) {
return@on true
setAttribute(player, "tutorial:stage", 56)
TutorialStage.load(player, 56)
}
if (stage == 55) {
setAttribute(player, "tutorial:stage", 56)
TutorialStage.load(player, 56)
}
core.game.global.action.ClimbActionHandler.climbLadder(player, ladder.asScenery(), "climb-up")
}
@ -165,5 +232,28 @@ class TutorialListeners : InteractionListener {
core.game.global.action.DoorActionHandler.handleAutowalkDoor(player, door as Scenery)
}
fun smeltBronzeBar(player: Player): Boolean {
if (getAttribute(player, "tutorial:stage", 0) < 38) {
return true
}
if (!inInventory(player, Items.COPPER_ORE_436) || !inInventory(player, Items.TIN_ORE_438)) {
return true
}
animate(player, 833)
queueScript(player, 2, QueueStrength.WEAK) {
if (removeItem(player, Items.COPPER_ORE_436) && removeItem(player, Items.TIN_ORE_438)) {
addItem(player, Items.BRONZE_BAR_2349)
rewardXP(player, Skills.SMITHING, Bar.BRONZE.experience)
player.dispatch(ResourceProducedEvent(Items.BRONZE_BAR_2349, 1, player, Items.COPPER_ORE_436))
TutorialStage.load(player, 39)
}
return@queueScript stopExecuting(player)
}
return true
}
on(FURNACE, IntType.SCENERY, "use") { player, _ -> smeltBronzeBar(player) }
for (item in arrayOf(Items.COPPER_ORE_436, Items.TIN_ORE_438)) {
onUseWith(IntType.SCENERY, item, FURNACE) { player, _, _ -> smeltBronzeBar(player) }
}
}
}

View file

@ -161,7 +161,7 @@ class ServerConstants {
var LOG_CUTSCENE = true
@JvmField
var RULES_AND_INFO_ENABLED = true
var RULES_AND_INFO_ENABLED = false
@JvmField
var WATCHDOG_ENABLED = true
@ -292,13 +292,16 @@ class ServerConstants {
var DRAGON_AXE_USE_OSRS_SPEC = false
@JvmField
var ENABLE_GLOBALCHAT = false
var ENABLE_GLOBAL_CHAT = false
@JvmField
var MAX_PATHFIND_DISTANCE = 25
@JvmField
var IRONMAN_ICONS = false
var XP_RATES = false
@JvmField
var IRONMAN = false
@JvmField
var PLAYER_STOCK_CLEAR_INTERVAL = 1
@ -310,19 +313,19 @@ class ServerConstants {
var BOTSTOCK_LIMIT = 5000
@JvmField
var BETTER_AGILITY_PYRAMID_GP = true
var BETTER_AGILITY_PYRAMID_GP = false
@JvmField
var BETTER_DFS = true
var BETTER_DFS = false
@JvmField
var NEW_PLAYER_ANNOUNCEMENT = true
var NEW_PLAYER_ANNOUNCEMENT = false
@JvmField
var INAUTHENTIC_CANDLELIGHT_RANDOM = false
@JvmField
var HOLIDAY_EVENT_RANDOMS = true
var HOLIDAY_EVENT_RANDOMS = false
@JvmField
var FORCE_HALLOWEEN_EVENTS = false
@ -334,7 +337,7 @@ class ServerConstants {
var FORCE_EASTER_EVENTS = false
@JvmField
var RUNECRAFTING_FORMULA_REVISION = 581
var RUNECRAFTING_FORMULA_REVISION = 530
@JvmField
var ENHANCED_DEEP_WILDERNESS = false

View file

@ -1842,8 +1842,8 @@ fun sendItemDialogue(player: Player, item: Any, message: String) {
*/
fun sendDoubleItemDialogue(player: Player, item1: Any, item2: Any, message: String) {
when (item1) {
is Item -> player.dialogueInterpreter.sendDoubleItemMessage(item1, item2 as Item, *splitLines(message))
is Int -> player.dialogueInterpreter.sendDoubleItemMessage(item1, item2 as Int, *splitLines(message))
is Item -> player.dialogueInterpreter.sendDoubleItemMessage(item1, item2 as Item, *splitLines(message))
is Int -> player.dialogueInterpreter.sendDoubleItemMessage(item1, item2 as Int, *splitLines(message))
}
}

View file

@ -3,6 +3,7 @@ package core.api.utils
import content.global.skill.construction.HouseLocation
import content.minigame.blastfurnace.BFPlayerState
import content.minigame.blastfurnace.BlastFurnace
import core.ServerConstants
import core.api.isUsingSecondaryBankAccount
import core.api.teleport
import core.api.toggleBankAccount
@ -91,6 +92,9 @@ fun permadeath(target: Player) {
}
}
// Xp rate
target.skills.experienceMultiplier = 1.0
// Ironman data
target.ironmanManager.mode = IronmanMode.NONE

View file

@ -1,9 +1,15 @@
package core.game.dialogue
import core.api.Event
import core.api.InputType
import core.api.face
import core.api.openDialogue
import core.api.splitLines
import core.game.component.Component
import core.game.component.Component.setUnclosable
import core.game.event.DialogueCloseEvent
import core.game.event.EventHook
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
@ -73,11 +79,14 @@ abstract class DialogueLabeller : DialogueFile() {
/** Implement this function instead of overriding handle. */
abstract fun addConversation()
/** Helper function to create an individual stage for each of the dialogue stages. */
private fun assignIndividualStage(callback: () -> Unit) {
/** Helper functions to create an individual stage for each of the dialogue stages. */
private fun assignIndividualStage(callback: () -> Component?, unclosable: Boolean) {
if (startingStage == null) { startingStage = 0 }
if (stage == dialogueCounter && jumpTo == null) { // Run this stage when the stage equals to the dialogueCounter of this dialogue
callback() // CALLBACK FUNCTION
val component = callback() // CALLBACK FUNCTION
if (unclosable && component != null) {
setUnclosable(player, component)
}
super.stage++ // Increment the stage to the next stage (only applies after a pass)
stageHit = true // Flag that the stage was hit, so that it doesn't close the dialogue
}
@ -131,13 +140,13 @@ abstract class DialogueLabeller : DialogueFile() {
}
/** Manual stage. For custom creation of an individual stage. Must call interpreter in some form. **/
fun manual(callback: (player: Player, npc: NPC) -> Unit) {
assignIndividualStage { callback(player!!, npc!!) }
fun manual(unclosable: Boolean = false, callback: (player: Player, npc: NPC) -> Component?) {
assignIndividualStage({ return@assignIndividualStage callback(player!!, npc!!) }, unclosable)
}
/** Dialogue player/playerl. Shows player chathead with text. **/
fun player(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) {
assignIndividualStage { interpreter!!.sendDialogues(player, chatAnim, *formatMessages(messages)) }
fun player(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String, unclosable: Boolean = false) {
assignIndividualStage({ return@assignIndividualStage interpreter!!.sendDialogues(player, chatAnim, *formatMessages(messages)) }, unclosable)
}
/** Dialogue player/playerl. Shows player chathead with text. **/
fun player(vararg messages: String) { player(ChatAnim.NEUTRAL, *messages) }
@ -147,16 +156,17 @@ abstract class DialogueLabeller : DialogueFile() {
fun playerl(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use player() instead.") }
/** Dialogue npc/npcl. Shows npc chathead with text. **/
fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) {
assignIndividualStage { interpreter!!.sendDialogues(npc, chatAnim, *formatMessages(messages)) }
fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String, unclosable: Boolean = false) {
val callback = callback@{ return@callback interpreter!!.sendDialogues(npc, chatAnim, *formatMessages(messages)) }
assignIndividualStage(callback, unclosable)
}
/** Dialogue npc/npcl. Shows npcId chathead with text. **/
fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, npcId: Int = npc!!.id, vararg messages: String) {
assignIndividualStage { interpreter!!.sendDialogues(NPC(npcId), chatAnim, *formatMessages(messages)) }
fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, npcId: Int = npc!!.id, vararg messages: String, unclosable: Boolean = false) {
assignIndividualStage({ return@assignIndividualStage interpreter!!.sendDialogues(NPC(npcId), chatAnim, *formatMessages(messages)) }, unclosable)
}
/** Dialogue npc/npcl. Shows npcId chathead with text. **/
fun npc(npcId: Int = npc!!.id, vararg messages: String) {
assignIndividualStage { interpreter!!.sendDialogues(NPC(npcId), ChatAnim.NEUTRAL, *formatMessages(messages)) }
fun npc(npcId: Int = npc!!.id, vararg messages: String, unclosable: Boolean = false) {
assignIndividualStage({ return@assignIndividualStage interpreter!!.sendDialogues(NPC(npcId), ChatAnim.NEUTRAL, *formatMessages(messages)) }, unclosable)
}
/** Dialogue npc/npcl. Shows npc chathead with text. **/
fun npc(vararg messages: String) { npc(ChatAnim.NEUTRAL, *messages) }
@ -166,40 +176,45 @@ abstract class DialogueLabeller : DialogueFile() {
fun npcl(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use npc() instead.") }
/** Dialogue item/iteml. Shows item with text. **/
fun item(item: Item, vararg messages: String, message: String = "") {
assignIndividualStage { interpreter!!.sendItemMessage(item, *formatMessages(messages, message)) }
fun item(item: Item, vararg messages: String, message: String = "", unclosable: Boolean = false) {
val callback = callback@{ return@callback interpreter!!.sendItemMessage(item, *formatMessages(messages, message)) }
assignIndividualStage(callback, unclosable)
}
@Deprecated("Use item() instead.", ReplaceWith("item(item, *messages)"))
fun iteml(item: Item, vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use item() instead.") }
/** Dialogue overloaded doubleItem/doubleIteml. Shows two items with text. **/
fun item(item: Item, item2: Item, vararg messages: String, message: String = "") {
assignIndividualStage { interpreter!!.sendDoubleItemMessage(item, item2, formatMessages(messages, message).joinToString(" ")) }
fun item(item: Item, item2: Item, vararg messages: String, message: String = "", unclosable: Boolean = false) {
assignIndividualStage({ return@assignIndividualStage interpreter!!.sendDoubleItemMessage(item, item2, *formatMessages(messages, message)) }, unclosable)
}
/** Dialogue line/linel. Simply shows text. **/
fun line(vararg messages: String) {
assignIndividualStage { interpreter!!.sendDialogue(*messages) }
fun line(vararg messages: String, unclosable: Boolean = false) {
val callback = callback@{ return@callback interpreter!!.sendDialogue(*messages) }
assignIndividualStage(callback, unclosable)
}
@Deprecated("Use line() instead.", ReplaceWith("line(*messages)"))
fun linel(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use line() instead.") }
/** Dialogue option. Shows the option dialogue with choices for the user to select. **/
fun options(vararg options: DialogueOption, title: String = "Select an Option") {
fun options(vararg options: DialogueOption, title: String = "Select an Option", unclosable: Boolean = false) {
// Filter out options that aren't shown.
val filteredOptions = options.filter{ if (it.optionIf != null) { it.optionIf.invoke(player!!, npc!!) } else { true } }
// Stage Part 1: Options List Dialogue
assignIndividualStage { interpreter!!.sendOptions(title, *filteredOptions.map{ it.option }.toTypedArray()) }
val callback = callback@{ return@callback interpreter!!.sendOptions(title, *filteredOptions.map{ it.option }.toTypedArray()) }
assignIndividualStage(callback, unclosable)
// Stage Part 2: Show spoken text.
var opt = if (buttonID != null && buttonID in 1..filteredOptions.size) { filteredOptions[buttonID!! - 1] } else { null }
assignIndividualStage {
val opt = if (buttonID != null && buttonID in 1..filteredOptions.size) { filteredOptions[buttonID!! - 1] } else { null }
assignIndividualStage({
var component: Component? = null
if (opt?.skipPlayer == true) {
jumpTo = stage + 1
} else {
interpreter!!.sendDialogues(player, opt?.expression ?: ChatAnim.NEUTRAL, *(splitLines(opt?.spokenText ?: " ")))
component = interpreter!!.sendDialogues(player, opt?.expression ?: ChatAnim.NEUTRAL, *(splitLines(opt?.spokenText ?: " ")))
}
optButton = buttonID // transfer the buttonID to a temp memory for the next stage
}
return@assignIndividualStage component
}, unclosable)
// Stage Part 3: Jump To goto
if (stage == dialogueCounter && optButton != null && optButton in 1..filteredOptions.size) {
jumpTo = labelStageMap[filteredOptions[optButton!! - 1].goto]
@ -211,7 +226,7 @@ abstract class DialogueLabeller : DialogueFile() {
/** Dialogue input. Shows the input dialogue with an input box for the user to type in. Read [optInput] for the value. **/
fun input(type: InputType, prompt: String = "Enter the amount") {
assignIndividualStage {
assignIndividualStage({
// These are similar to calling sendInputDialogue
when (type) {
InputType.AMOUNT -> interpreter!!.sendInput(true, prompt)
@ -230,14 +245,31 @@ abstract class DialogueLabeller : DialogueFile() {
interpreter!!.handle(player!!.interfaceManager.chatbox.id, 2)
}
player!!.setAttribute("input-type", type)
}
return@assignIndividualStage null
}, false)
}
/** Dialogue input. Shows the input dialogue with an input box for the user to type in. Read [optInput] in an [exec] function for the value. **/
fun input(numeric: Boolean, prompt: String = "Enter the amount") { input( if (numeric) { InputType.NUMERIC } else { InputType.STRING_SHORT }, prompt) }
/** Runs arbitrary code when the dialogue closes, once. **/
fun afterClose(callback: (player: Player) -> Unit) {
val hook = object : EventHook<DialogueCloseEvent> {
override fun process(entity: Entity, event: DialogueCloseEvent) {
val you = entity as Player
you.unhook(this)
callback(you)
}
}
player!!.hook(Event.DialogueClosed, hook)
}
/** Calls another dialogue file. Always use this to open another dialogue file instead of calling openDialogue() in exec{} due to interfaces clashing. **/
fun open(player: Player, dialogue: Any, vararg args: Any) {
assignIndividualStage { core.api.openDialogue(player, dialogue, *args) }
val callback = callback@{
core.api.openDialogue(player, dialogue, *args)
return@callback null
}
assignIndividualStage(callback, false)
}
/** WARNING: DIALOGUE LABELLER WILL BREAK IN CERTAIN FUNCTIONS. USE open() instead. */
@ -269,7 +301,10 @@ abstract class DialogueLabeller : DialogueFile() {
break
}
}
if (!stageHit) { end() } // If a dialogue stage is not hit, end the dialogues.
// If a dialogue stage is not hit, end the dialogue.
if (!stageHit) {
end()
}
}
}

View file

@ -276,8 +276,8 @@ public abstract class DialoguePlugin implements Plugin<Player> {
* Method used to send options.
* @param options the options.
*/
public void options(final String... options) {
interpreter.sendOptions("Select an Option", options);
public Component options(final String... options) {
return interpreter.sendOptions("Select an Option", options);
}
/**

View file

@ -25,11 +25,11 @@ public enum Rights {
if (c != Rights.REGULAR_PLAYER && c != null) {
return c.toInteger();
}
if (ServerConstants.IRONMAN_ICONS) {
if (player.getIronmanManager().isIronman()) {
return player.getIronmanManager().getMode().getIcon();
}
}
if (ServerConstants.IRONMAN) {
if (player.getIronmanManager().isIronman()) {
return player.getIronmanManager().getMode().getIcon();
}
}
return 0;
}

View file

@ -330,9 +330,6 @@ class PlayerSaveParser(val player: Player) {
player.skills.parse(skillData)
player.skills.experienceGained = saveFile!!["totalEXP"].toString().toDouble()
player.skills.experienceMultiplier = saveFile!!["exp_multiplier"].toString().toDouble()
if (GameWorld.settings?.default_xp_rate != 5.0) {
player.skills.experienceMultiplier = GameWorld.settings?.default_xp_rate!!
}
val divisor: Double
if(player.skills.experienceMultiplier >= 10 && !player.attributes.containsKey("permadeath")){ //exclude permadeath HCIMs from XP squish
divisor = player.skills.experienceMultiplier / 5.0

View file

@ -322,7 +322,6 @@ class PlayerSaver (val player: Player){
fun saveGlobalData(root: JSONObject){
val globalData = JSONObject()
globalData.put("tutorialStage",player.savedData.globalData.tutorialStage.toString())
globalData.put("homeTeleportDelay",player.savedData.globalData.homeTeleportDelay.toString())
globalData.put("lumbridgeRope",player.savedData.globalData.hasTiedLumbridgeRope())
globalData.put("apprentice",player.savedData.globalData.hasSpokenToApprentice())

View file

@ -10,12 +10,6 @@ import org.json.simple.JSONObject;
* @author 'Vexia
*/
public final class GlobalData {
/**
* Represents the tutorial stage.
*/
private int tutorialStage;
/**
* Represents the home teleport delay.
*/
@ -298,7 +292,6 @@ public final class GlobalData {
private boolean macroDisabled = false;
public void parse(JSONObject data){
tutorialStage = Integer.parseInt( data.get("tutorialStage").toString());
homeTeleportDelay = Long.parseLong(data.get("homeTeleportDelay").toString());
lumbridgeRope = (boolean) data.get("lumbridgeRope");
apprentice = (boolean) data.get("apprentice");
@ -467,22 +460,6 @@ public final class GlobalData {
playerTestStage = stage;
}
/**
* Gets the tutorialStage.
* @return The tutorialStage.
*/
public int getTutorialStage() {
return tutorialStage;
}
/**
* Sets the tutorialStage.
* @param tutorialStage The tutorialStage to set.
*/
public void setTutorialStage(int tutorialStage) {
this.tutorialStage = tutorialStage;
}
/**
* Gets the homeTeleportDelay.
* @return The homeTeleportDelay.

View file

@ -5,7 +5,7 @@ package core.game.node.entity.player.link;
* @author Vexia
*/
public enum IronmanMode {
// HARDCORE_DEAD has to be before Ultimate so that it does not adopt it's restrictions (on the basis of >= in IronmanManager.java?)
// HARDCORE_DEAD has to be before Ultimate so that it does not adopt its restrictions (on the basis of >= in IronmanManager.java)
NONE(-1), STANDARD(5), HARDCORE(6), ULTIMATE(7);
/**

View file

@ -135,7 +135,7 @@ public class TeleportManager {
/**
* Fires a random event.
* @param entity The entity teleporting.
* @param location The destination lcoation.
* @param location The destination location.
*/
public static void fireRandom(Entity entity, Location location) {
if (entity instanceof Player && entity.getTeleporter().getTeleportType() == 0) {

View file

@ -41,7 +41,7 @@ public final class Skills {
/**
* Represents the constant modifier of experience.
*/
public double experienceMultiplier = 5.0;
public double experienceMultiplier = 1.0;
/**
* The maximum experience multiplier.
@ -397,6 +397,7 @@ public final class Skills {
}
public void correct(double divisor){
// XP squish for legacy x20 accounts
for(int i = 0; i < staticLevels.length; i++){
experience[i] /= divisor;
staticLevels[i] = getStaticLevelByExperience(i);

View file

@ -76,8 +76,6 @@ object ServerConfigParser {
isQuickChat = false,
isLootshare = false,
msAddress = data.getString("server.msip"),
default_xp_rate = data.getDouble("world.default_xp_rate"),
allow_slayer_reroll = data.getBoolean("world.allow_slayer_reroll"),
enable_default_clan = data.getBoolean("world.enable_default_clan"),
enable_bots = data.getBoolean("world.enable_bots"),
autostock_ge = data.getBoolean("world.autostock_ge"),
@ -148,24 +146,25 @@ object ServerConfigParser {
ServerConstants.NOAUTH_DEFAULT_ADMIN = data.getBoolean("server.noauth_default_admin", false)
ServerConstants.DRAGON_AXE_USE_OSRS_SPEC = data.getBoolean("world.dragon_axe_use_osrs_spec", false)
ServerConstants.DISCORD_OPENRSC_HOOK = data.getString("integrations.openrsc_integration_webhook", "")
ServerConstants.ENABLE_GLOBALCHAT = data.getBoolean("world.enable_globalchat", true)
ServerConstants.ENABLE_GLOBAL_CHAT = data.getBoolean("world.enable_global_chat", false)
ServerConstants.MAX_PATHFIND_DISTANCE = data.getLong("server.max_pathfind_dist", 25L).toInt()
ServerConstants.IRONMAN_ICONS = data.getBoolean("world.ironman_icons", false)
ServerConstants.XP_RATES = data.getBoolean("world.xp_rates", false)
ServerConstants.IRONMAN = data.getBoolean("world.ironman", false)
ServerConstants.PLAYER_STOCK_CLEAR_INTERVAL = data.getLong("world.playerstock_clear_mins", 180L).toInt()
ServerConstants.PLAYER_STOCK_RECIRCULATE = data.getBoolean("world.playerstock_bot_offers", true)
ServerConstants.BOTSTOCK_LIMIT = data.getLong("world.botstock_limit", 5000L).toInt()
ServerConstants.BETTER_AGILITY_PYRAMID_GP = data.getBoolean("world.better_agility_pyramid_gp", true)
ServerConstants.BETTER_AGILITY_PYRAMID_GP = data.getBoolean("world.better_agility_pyramid_gp", false)
ServerConstants.GRAFANA_PATH = data.getPath("integrations.grafana_log_path")
ServerConstants.GRAFANA_LOGGING = data.getBoolean("integrations.grafana_logging", false)
ServerConstants.GRAFANA_TTL_DAYS = data.getLong("integrations.grafana_log_ttl_days", 7L).toInt()
ServerConstants.BETTER_DFS = data.getBoolean("world.better_dfs", true)
ServerConstants.NEW_PLAYER_ANNOUNCEMENT = data.getBoolean("world.new_player_announcement", true)
ServerConstants.BETTER_DFS = data.getBoolean("world.better_dfs", false)
ServerConstants.NEW_PLAYER_ANNOUNCEMENT = data.getBoolean("world.new_player_announcement", false)
ServerConstants.INAUTHENTIC_CANDLELIGHT_RANDOM = data.getBoolean("world.inauthentic_candlelight_random", false)
ServerConstants.HOLIDAY_EVENT_RANDOMS = data.getBoolean("world.holiday_event_randoms", true)
ServerConstants.HOLIDAY_EVENT_RANDOMS = data.getBoolean("world.holiday_event_randoms", false)
ServerConstants.FORCE_HALLOWEEN_EVENTS = data.getBoolean("world.force_halloween_randoms", false)
ServerConstants.FORCE_CHRISTMAS_EVENTS = data.getBoolean("world.force_christmas_randoms", false)
ServerConstants.FORCE_EASTER_EVENTS = data.getBoolean("world.force_easter_randoms", false)
ServerConstants.RUNECRAFTING_FORMULA_REVISION = data.getLong("world.runecrafting_formula_revision", 581).toInt()
ServerConstants.RUNECRAFTING_FORMULA_REVISION = data.getLong("world.runecrafting_formula_revision", 530).toInt()
ServerConstants.ENHANCED_DEEP_WILDERNESS = data.getBoolean("world.enhanced_deep_wilderness", false)
ServerConstants.WILDERNESS_EXCLUSIVE_LOOT = data.getBoolean("world.wilderness_exclusive_loot", false)
ServerConstants.SHOOTING_STAR_RING = data.getBoolean("world.shooting_star_ring", false)

View file

@ -69,8 +69,6 @@ class GameSettings
* The address of the Management server.
*/
var msAddress: String,
var default_xp_rate: Double,
var allow_slayer_reroll: Boolean,
var enable_default_clan: Boolean,
var enable_bots: Boolean,
var autostock_ge: Boolean,
@ -126,8 +124,6 @@ class GameSettings
val activity = data["activity"].toString()
val pvpWorld = data["pvpWorld"] as Boolean
val msip = data["msip"].toString()
val default_xp_rate = data["default_xp_rate"].toString().toDouble()
val allow_slayer_reroll = data["allow_slayer_reroll"] as Boolean
val enable_default_clan = data["enable_default_clan"] as Boolean
val enable_bots = data["enable_bots"] as Boolean
val autostock_ge = data["autostock_ge"] as Boolean
@ -157,8 +153,6 @@ class GameSettings
false,
false,
msip,
default_xp_rate,
allow_slayer_reroll,
enable_default_clan,
enable_bots,
autostock_ge,

View file

@ -208,7 +208,7 @@ object PacketProcessor {
if (pkt.player.details.isMuted)
pkt.player.sendMessage("You have been muted due to breaking a rule.")
else {
if (ServerConstants.ENABLE_GLOBALCHAT && pkt.message.startsWith("//")) {
if (ServerConstants.ENABLE_GLOBAL_CHAT && pkt.message.startsWith("//")) {
if (getAttribute(pkt.player, GlobalChat.ATTR_GLOBAL_MUTE, false))
return

View file

@ -27,8 +27,6 @@ members = true
#activity as displayed on the world list
activity = "2009Scape Classic."
pvp = false
default_xp_rate = 5.0
allow_slayer_reroll = false
#enables a default clan for players to join automatically. Should be an account with the same name as @name, with a clan set up already.
enable_default_clan = true
enable_bots = true
@ -49,6 +47,7 @@ max_adv_bots = 100
enable_doubling_money_scammers = true
wild_pvp_enabled = false
jad_practice_enabled = false
enable_global_chat = false
enable_castle_wars = false
personalized_shops = false

View file

@ -58,8 +58,6 @@ members = true
#activity as displayed on the world list
activity = "2009Scape Classic."
pvp = false
default_xp_rate = 5.0
allow_slayer_reroll = false
#enables a default clan for players to join automatically. Should be an account with the same name as @name, with a clan set up already.
enable_default_clan = true
enable_bots = true
@ -72,44 +70,61 @@ new_player_location = "2524,5002,0"
#the location of home teleport
home_location = "3222,3218,0"
autostock_ge = false
allow_token_purchase = true
skillcape_perks = true
allow_token_purchase = false
skillcape_perks = false
increased_door_time = false
enable_botting = false
max_adv_bots = 100
enable_doubling_money_scammers = true
wild_pvp_enabled = true
jad_practice_enabled = true
wild_pvp_enabled = false
jad_practice_enabled = false
enable_global_chat = false
#minimum HA value for announcements of bots selling on ge
ge_announcement_limit = 500
enable_castle_wars = false
personalized_shops = true
personalized_shops = false
bots_influence_ge_price = true
#verbose cutscene logging (for cutscenes in the new system)
verbose_cutscene = false
#show the rules the first time a player logs in
show_rules = true
show_rules = false
#the number of revenants active at a time
revenant_population = 30
#enable auto-buy/auto-sell on the GE.
i_want_to_cheat = false
#better agility pyramid gp reward (gp reward = 1000 + ((agility level / 99) * 9000))
better_agility_pyramid_gp = true
better_agility_pyramid_gp = false
#better dragonfire shield attack (30 second cooldown instead of 2 minutes)
better_dfs = true
better_dfs = false
#new player announcement
new_player_announcement = true
new_player_announcement = false
#enables inauthentic candlelight random event (adds an additional normal random event)
inauthentic_candlelight_random = true
inauthentic_candlelight_random = false
#enables holiday random events (no effect on normal random events)
holiday_event_randoms = true
holiday_event_randoms = false
#force holiday randoms (can only force one at a time)
force_halloween_randoms = false
force_christmas_randoms = false
#runecrafting formula revision (573 introduced probabilistic multiple runes, 581 extrapolated probabilistic runes past 99)
runecrafting_formula_revision = 581
#enable the enhanced deep wilderness, where the area past the members' fence applies a red skull that boosts brawler/pvp drop rates
enhanced_deep_wilderness = true
runecrafting_formula_revision = 530
#enables the enhanced deep wilderness, where the area past the members' fence applies a red skull that boosts brawler/pvp drop rates
enhanced_deep_wilderness = false
#enables wilderness-exclusive loot, i.e. brawling gloves and PvP gear, from revenants and the Chaos Elemental
wilderness_exclusive_loot = false
#enables the xp rates option on tutorial island
xp_rates = false
#enables the ironman option on tutorial island and the inauthentic game protocol addition to transmit chat icons for ironmen
ironman = false
#enables the custom-content ancient blueprint and ring of the star sprite
shooting_star_ring = false
#enables the inauthentic teleport option on the ring of wealth
ring_of_wealth_teleport = false
#enables second bank
second_bank = false
#enables inauthentic but non-dangerous commands for regular players
player_commands = false
#enables boosted rewards from fishing trawler consisting of key halves and pirate outfit pieces
boosted_trawler_rewards = false
[paths]
#path to the data folder, which contains the cache subfolder and such