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 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.IntType
import core.game.interaction.InteractionListener 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.entity.player.Player
import core.game.node.item.Item import core.game.node.item.Item
import core.game.node.scenery.Scenery import core.game.node.scenery.Scenery
import core.game.world.update.flag.context.Animation
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.Items.BREAD_DOUGH_2307 import org.rs09.consts.Items.BREAD_DOUGH_2307
import org.rs09.consts.Items.RAW_BEAR_MEAT_2136 import org.rs09.consts.Items.RAW_BEAR_MEAT_2136
import org.rs09.consts.Items.RAW_BEEF_2132 import org.rs09.consts.Items.RAW_BEEF_2132
import org.rs09.consts.Items.SEAWEED_401 import org.rs09.consts.Items.SEAWEED_401
import org.rs09.consts.Items.UNCOOKED_CAKE_1889 import org.rs09.consts.Items.UNCOOKED_CAKE_1889
import org.rs09.consts.Sounds
/** /**
* @author Ceikry * @author Ceikry
@ -32,8 +37,36 @@ class CookingRewrite : InteractionListener {
} }
override fun defineListeners() { override fun defineListeners() {
onUseWith(IntType.SCENERY,RAW_FOODS, *COOKING_OBJs){ player, used, with -> 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 item = used.asItem()
val obj = with.asScenery() val obj = with.asScenery()
val range = obj.name.toLowerCase().contains("range") val range = obj.name.toLowerCase().contains("range")
@ -66,7 +99,7 @@ class CookingRewrite : InteractionListener {
} }
companion object { 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 @JvmStatic
fun cook(player: Player, `object`: Scenery?, initial: Int, product: Int, amount: Int) { fun cook(player: Player, `object`: Scenery?, initial: Int, product: Int, amount: Int) {

View file

@ -1,5 +1,6 @@
package content.global.skill.cooking package content.global.skill.cooking
import content.region.misc.tutisland.handlers.TutorialStage
import core.api.* import core.api.*
import core.game.event.ResourceProducedEvent import core.game.event.ResourceProducedEvent
import core.game.node.entity.skill.Skills import core.game.node.entity.skill.Skills
@ -24,9 +25,18 @@ class DoughMakingListener : InteractionListener {
FULL_WATER_CONTAINERS_TO_EMPTY_CONTAINERS.keys.toIntArray(), FULL_WATER_CONTAINERS_TO_EMPTY_CONTAINERS.keys.toIntArray(),
Items.POT_OF_FLOUR_1933 Items.POT_OF_FLOUR_1933
) { player, waterContainer, flourContainer -> ) { player, waterContainer, flourContainer ->
if (getAttribute(player, "/save:tutorial:complete", false)) {
openDialogue(player, DoughMakeDialogue(waterContainer.asItem(), flourContainer.asItem())) openDialogue(player, DoughMakeDialogue(waterContainer.asItem(), flourContainer.asItem()))
return@onUseWith true 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
}
} }
private class DoughMakeDialogue(val waterContainer: Item, val flourContainer: Item) : DialogueFile() { private class DoughMakeDialogue(val waterContainer: Item, val flourContainer: Item) : DialogueFile() {
@ -73,7 +83,7 @@ class DoughMakingListener : InteractionListener {
sendMessage( sendMessage(
player!!, 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 { } else {

View file

@ -42,11 +42,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
*/ */
private static final Item HOLY_SYMBOL = new Item(1718); 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. * Represents the coins item.
*/ */
@ -69,8 +64,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
private final int level = 2; private final int level = 2;
private int rerolls = 0;
/** /**
* Constructs a new {@code SlayerMasterDialogue} {@code Object}. * Constructs a new {@code SlayerMasterDialogue} {@code Object}.
*/ */
@ -120,7 +113,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
@Override @Override
public boolean handle(int interfaceId, int buttonId) { public boolean handle(int interfaceId, int buttonId) {
rerolls = ServerStore.getInt(getStoreFile(), player.getUsername().toLowerCase(), 0);
if (isDiary) { if (isDiary) {
switch (stage) { switch (stage) {
case 999: case 999:
@ -482,36 +474,19 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
stage = 999; stage = 999;
break; 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); 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; stage = 844;
break; break;
} }
if (Master.hasSameTask(master, player)) { interpreter.sendDialogues(master.getNpc(), getExpression(master), "You're still hunting something. Come back when you've","finished your task.");
interpreter.sendDialogues(master.getNpc(), getExpression(master), "You're still hunting something. But let me check something..."); stage = END_DIALOGUE;
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;
}
break; break;
case 844: 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++; stage++;
break; break;
case 845: case 845:
@ -524,47 +499,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
player("Okay, great!"); player("Okay, great!");
stage = 999; stage = 999;
break; 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; break;
case 860: case 860:
@ -608,56 +542,6 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
} }
stage = 999; stage = 999;
break; 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; return true;
} }
@ -698,9 +582,4 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
public int[] getIds() { public int[] getIds() {
return new int[]{70, 1598, 1596, 1597, 1599, 7780, 8275, 8273, 8274, 8649}; 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); 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. * Represents the plugin used to handle the ore on the furance.
* @author 'Vexia * @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 core.plugin.Initializable
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage import content.region.misc.tutisland.handlers.TutorialStage
import core.game.component.Component.setUnclosable
/** /**
* Handles Skippy's skip tutorial dialogue * Handles Skippy's skip tutorial dialogue
* @author Ceikry * @author Ceikry, Player Name
*/ */
@Initializable @Initializable
class SkipTutorialDialogue(player: Player? = null) : DialoguePlugin(player) { 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 { 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 return true
} }
override fun handle(interfaceId: Int, buttonId: Int): Boolean { override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(stage){ 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 -> when(buttonId)
{ {
1 -> { 1 -> {

View file

@ -1,119 +1,108 @@
package content.region.misc.tutisland.dialogue package content.region.misc.tutisland.dialogue
import core.api.addItem import core.api.addItemOrDrop
import core.api.inInventory import core.api.inInventory
import core.api.setAttribute 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.Items
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage 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
/** class SurvivalExpertDialogue : InteractionListener {
* Handles the survival expert's dialogue override fun defineListeners() {
* @author Ceikry on(NPCs.SURVIVAL_EXPERT_943, IntType.NPC, "talk-to") { player, node ->
*/ DialogueLabeller.open(player, SurvivalExpertDialogueFile(), node as NPC)
@Initializable return@on true
class SurvivalExpertDialogue(player: Player? = null) : DialoguePlugin(player) { }
override fun newInstance(player: Player?): DialoguePlugin { }
return SurvivalExpertDialogue(player)
} }
override fun open(vararg args: Any?): Boolean { class SurvivalExpertDialogueFile : DialogueLabeller() {
npc = args[0] as NPC override fun addConversation() {
val tutStage = player?.getAttribute("tutorial:stage", 0) ?: 0 assignToIds(NPCs.SURVIVAL_EXPERT_943)
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( exec { player, _ ->
player, when (val stage = getAttribute(player, "/save:tutorial:stage", 0)) {
interpreter.sendDialogues( 4 -> loadLabel(player, "hello")
npc, 5, 6, 7, 8, 9, 10, 12, 13, 14 -> {
FacialExpression.FRIENDLY, if (!inInventory(player, Items.BRONZE_AXE_1351) && !inEquipment(player, Items.BRONZE_AXE_1351)) {
"Well done! Next we need to get some food in our", loadLabel(player, "spare axe")
"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)) if (!inInventory(player, Items.TINDERBOX_590)) {
{ loadLabel(player, "spare tinderbox")
player.dialogueInterpreter.sendItemMessage(Items.TINDERBOX_590, "The Survival Expert gives you a spare tinderbox.")
addItem(player, Items.TINDERBOX_590)
} }
return false 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")
} }
return true
} }
override fun handle(interfaceId: Int, buttonId: Int): Boolean { label("hello")
when(player?.getAttribute("tutorial:stage", 0)) 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, _ ->
4 -> when(stage) addItemOrDrop(player, Items.TINDERBOX_590)
{ addItemOrDrop(player, Items.BRONZE_AXE_1351)
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 -> { 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)
end() exec { player, _ ->
setAttribute(player, "tutorial:stage", 5) setAttribute(player, "tutorial:stage", 5)
TutorialStage.load(player, 5) TutorialStage.load(player, 5)
} }
} goto("nowhere")
11 -> when(stage){ label("fishing")
0 -> { 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)
Component.setUnclosable( exec { player, _ -> addItemOrDrop(player, Items.SMALL_FISHING_NET_303) }
player, item(Item(Items.SMALL_FISHING_NET_303), "The Survival Guide gives you a", "<col=08088A>net</col>!", unclosable = true)
interpreter.sendItemMessage(303, "The Survival Guide gives you a <col=08088A>net</col>!") exec { player, _ ->
)
addItem(player, Items.SMALL_FISHING_NET_303)
stage++
}
1 -> {
end()
setAttribute(player, "tutorial:stage", 12) setAttribute(player, "tutorial:stage", 12)
TutorialStage.load(player, 12) TutorialStage.load(player, 12)
} }
} goto("nowhere")
}
return true
}
override fun getIds(): IntArray { label("spare axe")
return intArrayOf(NPCs.SURVIVAL_EXPERT_943) 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 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.npc.NPC
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage 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
/** class CombatInstructorDialogue : InteractionListener {
* Handles the combat instructor's dialogue override fun defineListeners() {
* @author Ceikry on(NPCs.COMBAT_INSTRUCTOR_944, IntType.NPC, "talk-to") { player, node ->
*/ DialogueLabeller.open(player, CombatInstructorDialogueFile(), node as NPC)
@Initializable return@on true
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)
} }
} }
return true
} }
override fun handle(interfaceId: Int, buttonId: Int): Boolean { class CombatInstructorDialogueFile : DialogueLabeller() {
when(getAttribute(player, "tutorial:stage", 0)) fun lostWeapon(player: Player, id: Int): Boolean {
{ return !inInventory(player, id) && !inEquipment(player, id)
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++ } override fun addConversation() {
2 -> npcl(FacialExpression.FRIENDLY, "Let's get started by teaching you to wield a weapon.").also { stage++ } assignToIds(NPCs.COMBAT_INSTRUCTOR_944)
3 -> {
end() 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) setAttribute(player, "tutorial:stage", 45)
TutorialStage.load(player, 45) TutorialStage.load(player, 45)
} }
}
47 -> when(stage){ label("butter")
0 -> { 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.BRONZE_SWORD_1277)
addItemOrDrop(player, Items.WOODEN_SHIELD_1171) 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 -> { 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)
end() exec { player, _ ->
setAttribute(player, "tutorial:stage", 48) setAttribute(player, "tutorial:stage", 48)
TutorialStage.load(player, 48) TutorialStage.load(player, 48)
} }
} goto("nowhere")
53 -> when(stage){ label("lost sword")
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++ } exec { player, _ -> addItemOrDrop(player, Items.BRONZE_SWORD_1277) }
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++ } item(Item(Items.BRONZE_SWORD_1277), "The Combat Guide gives you a spare sword.", unclosable = true)
2 -> { exec { player, _ -> if (lostWeapon(player, Items.WOODEN_SHIELD_1171)) loadLabel(player, "lost shield") }
sendDoubleItemDialogue(player, Items.SHORTBOW_841, Items.BRONZE_ARROW_882, "The Combat Guide gives you some bronze arrows and a shortbow!") goto("nowhere")
if(!inInventory(player, Items.SHORTBOW_841) && !inEquipment(player, Items.SHORTBOW_841))
addItem(player, Items.SHORTBOW_841) label("lost shield")
if(!inInventory(player, Items.BRONZE_ARROW_882) && !inEquipment(player, Items.BRONZE_ARROW_882)) exec { player, _ -> addItemOrDrop(player, Items.WOODEN_SHIELD_1171) }
addItem(player, Items.BRONZE_ARROW_882, 30) item(Item(Items.WOODEN_SHIELD_1171), "The Combat Guide gives you a spare shield.", unclosable = true)
stage++ 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)
} }
3 -> { 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)
end() exec { player, _ ->
setAttribute(player, "tutorial:stage", 54) setAttribute(player, "tutorial:stage", 54)
TutorialStage.load(player, 54) TutorialStage.load(player, 54)
} }
} goto("nowhere")
}
return true
}
override fun getIds(): IntArray { label("lost bow")
return intArrayOf(NPCs.COMBAT_INSTRUCTOR_944) 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 core.plugin.Initializable
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage import content.region.misc.tutisland.handlers.TutorialStage
import core.game.component.Component.setUnclosable
import core.game.world.GameWorld.settings import core.game.world.GameWorld.settings
/** /**
* Handles the finance tutor's dialogue * Handles the finance tutor's dialogue
* @author Ceikry * @author Ceikry, Player Name
*/ */
@Initializable @Initializable
class TutorialFinanceAdvisorDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { 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 npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0)) when(getAttribute(player, "tutorial:stage", 0))
{ {
58 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Hello, who are you?") 58 -> setUnclosable(player, playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Hello, who are you?"))
59 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Move along, now.").also { return false } 59 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Move along, now."))
} }
return true return true
} }
@ -32,21 +33,22 @@ class TutorialFinanceAdvisorDialogue(player: Player? = null) : core.game.dialogu
override fun handle(interfaceId: Int, buttonId: Int): Boolean { override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(getAttribute(player, "tutorial:stage", 0)){ when(getAttribute(player, "tutorial:stage", 0)){
58 -> when(stage++){ 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.") 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 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "Okay. How can I make money then?") 1 -> setUnclosable(player, 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.") 2 -> setUnclosable(player, 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.") 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 -> 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.") 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 -> 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.") 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 -> 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.") 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 -> 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++ } 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 -> npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well, that about covers it. Move along now.") 8 -> setUnclosable(player, npcl(core.game.dialogue.FacialExpression.FRIENDLY, "Well, that about covers it. Move along now."))
9 -> { 9 -> {
end() end()
setAttribute(player, "tutorial:stage", 59) setAttribute(player, "tutorial:stage", 59)
TutorialStage.load(player, 59) TutorialStage.load(player, 59)
} }
} }
59 -> TutorialStage.load(player, 59)
} }
return true return true
} }
@ -54,5 +56,4 @@ class TutorialFinanceAdvisorDialogue(player: Player? = null) : core.game.dialogu
override fun getIds(): IntArray { override fun getIds(): IntArray {
return intArrayOf(NPCs.FINANCIAL_ADVISOR_947) return intArrayOf(NPCs.FINANCIAL_ADVISOR_947)
} }
} }

View file

@ -4,147 +4,172 @@ import content.global.handlers.iface.RulesAndInfo
import content.region.misc.tutisland.handlers.* import content.region.misc.tutisland.handlers.*
import core.ServerConstants import core.ServerConstants
import core.api.* 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.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.IronmanMode import core.game.node.entity.player.link.IronmanMode
import core.game.node.entity.player.link.TeleportManager import core.game.node.entity.player.link.TeleportManager
import core.game.node.item.Item import core.game.node.item.Item
import core.game.world.GameWorld import core.game.world.GameWorld
import core.game.world.map.Location import core.game.world.map.Location
import core.plugin.Initializable import core.plugin.Initializable
import core.tools.END_DIALOGUE
import core.worker.ManagementEvents import core.worker.ManagementEvents
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import proto.management.JoinClanRequest import proto.management.JoinClanRequest
/**
* Handles the magic tutor's dialogue
* @author Ceikry
*/
@Initializable @Initializable
class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { class TutorialMagicTutorDialogue : InteractionListener {
private val STARTER_PACK = arrayOf( override fun defineListeners() {
Item(1351, 1), on(NPCs.MAGIC_INSTRUCTOR_946, NPC, "talk-to") { player, _ ->
Item(590, 1), val stage = getAttribute(player, "tutorial:stage", 0)
Item(303, 1), if (stage == 70 && inInventory(player, Items.AIR_RUNE_556) && inInventory(player, Items.MIND_RUNE_558)) {
Item(315, 1), // 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
Item(1925, 1), return@on true
Item(1931, 1), }
Item(2309, 1), openDialogue(player, TutorialMagicTutorDialogueFile(), NPC(NPCs.MAGIC_INSTRUCTOR_946))
Item(1265, 1), return@on true
Item(1205, 1), }
Item(1277, 1), }
Item(1171, 1), }
Item(841, 1),
Item(882, 25), class TutorialMagicTutorDialogueFile : DialogueLabeller() {
Item(556, 25), override fun addConversation() {
Item(558, 15), val STARTER_PACK = arrayOf(
Item(555, 6), Item(Items.BRONZE_AXE_1351),
Item(557, 4), Item(Items.TINDERBOX_590),
Item(559, 2) 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)
) )
private val STARTER_BANK = arrayOf(Item(995, 25)) val STARTER_BANK = arrayOf(Item(Items.COINS_995, 25))
override fun newInstance(player: Player?): core.game.dialogue.DialoguePlugin { exec { player, _ ->
return TutorialMagicTutorDialogue(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")
}
} }
override fun open(vararg args: Any?): Boolean { label("hello")
npc = args[0] as NPC player(ChatAnim.FRIENDLY, "Hello.", unclosable = true)
when(getAttribute(player, "tutorial:stage", 0)) 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, _ ->
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.")
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
}
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) setAttribute(player, "tutorial:stage", 68)
TutorialStage.load(player, 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)
} }
69 -> when(stage++){ item(Item(Items.AIR_RUNE_556), Item(Items.MIND_RUNE_558), "Terrova gives you 15 air runes and 15 mind runes!", unclosable = true)
0 -> { exec { player, _ -> TutorialStage.load(player, 70) }
sendDoubleItemDialogue(player, Items.AIR_RUNE_556, Items.MIND_RUNE_558, "Terrova gives you 15 air runes and 15 mind runes!")
label("givemorerunes")
exec { player, _ ->
addItemOrDrop(player, Items.AIR_RUNE_556, 5) addItemOrDrop(player, Items.AIR_RUNE_556, 5)
addItemOrDrop(player, Items.MIND_RUNE_558, 5) addItemOrDrop(player, Items.MIND_RUNE_558, 5)
} }
1 -> { item(Item(Items.AIR_RUNE_556), Item(Items.MIND_RUNE_558), "You receive some spare runes.", unclosable = true)
end() exec { player, _ -> TutorialStage.load(player, 70) }
setAttribute(player, "tutorial:stage", 70)
TutorialStage.load(player, 70) label("finishedtutorial")
exec { player, _ ->
if (ServerConstants.XP_RATES || ServerConstants.IRONMAN) {
loadLabel(player, "talk about inauthentic")
} else {
loadLabel(player, "leave")
} }
} }
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 }
}
10 -> { label("talk about inauthentic")
stage = 0 npc(ChatAnim.FRIENDLY, "Alright, last thing. Are you interested in our inauthentic ${ServerConstants.SERVER_NAME} features?", unclosable = true)
if(buttonId < 5) goto("inauthentic")
{
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 -> { label("inauthentic")
val rates = arrayOf(1.0,2.5,5.0) options(
val rate = rates[buttonId - 1] DialogueOption("xprate","Change XP rate (current: ${player?.skills?.experienceMultiplier}x)", skipPlayer = true) { _, _ ->
if(rate == 10.0) { return@DialogueOption ServerConstants.XP_RATES
player.dialogueInterpreter.sendDialogue("10.0x is no longer available!") },
player.skills.experienceMultiplier = 5.0 DialogueOption("ironman","Set ironman mode (current: ${player?.ironmanManager?.mode?.name?.toLowerCase()})", skipPlayer = true) { _, _ ->
stage = 0 return@DialogueOption ServerConstants.IRONMAN
return true },
} DialogueOption("leave","I'm ready now."),
player.dialogueInterpreter.sendDialogue("You set your XP rate to: ${rate}x.") unclosable = true)
player.skills.experienceMultiplier = rate
stage = 0 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")
} }
30 -> player.dialogueInterpreter.sendOptions("Leave Tutorial Island?", "Yes, I'm ready.", "No, not yet.").also { stage++ } label("ironman")
31 -> when(buttonId) options(
{ DialogueOption("NONE","None (default)", skipPlayer = true),
1 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "I'm ready to go now, thank you.").also { stage = 40 } DialogueOption("STANDARD","Standard", skipPlayer = true),
2 -> playerl(core.game.dialogue.FacialExpression.FRIENDLY, "I'm not quite ready to go yet, thank you.").also { stage = END_DIALOGUE } 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") }
} }
40 -> { 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) setAttribute(player, "/save:tutorial:complete", true)
setVarbit(player, 3756, 0) setVarbit(player, 3756, 0)
setVarp(player, 281, 1000, true) setVarp(player, 281, 1000, true)
@ -159,30 +184,14 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di
player.inventory.add(*STARTER_PACK) player.inventory.add(*STARTER_PACK)
player.bank.add(*STARTER_BANK) 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) TutorialStage.removeHintIcon(player)
player.unhook(TutorialKillReceiver) player.unhook(TutorialKillReceiver)
player.unhook(TutorialFireReceiver) player.unhook(TutorialFireReceiver)
player.unhook(TutorialResourceReceiver) player.unhook(TutorialResourceReceiver)
player.unhook(TutorialUseWithReceiver) player.unhook(TutorialUseWithReceiver)
player.unhook(TutorialInteractionReceiver) player.unhook(TutorialInteractionReceiver)
player.unhook(TutorialButtonReceiver) player.unhook(TutorialButtonReceiver)
RulesAndInfo.openFor(player) player.unhook(TutorialDialogPreserver)
if (GameWorld.settings!!.enable_default_clan) { if (GameWorld.settings!!.enable_default_clan) {
player.communication.currentClan = ServerConstants.SERVER_NAME.toLowerCase() player.communication.currentClan = ServerConstants.SERVER_NAME.toLowerCase()
@ -193,19 +202,28 @@ class TutorialMagicTutorDialogue(player: Player? = null) : core.game.dialogue.Di
ManagementEvents.publish(clanJoin.build()) ManagementEvents.publish(clanJoin.build())
} }
// 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)
// 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)
}
}
return@manual null
} }
12 -> { label("nowhere")
player.setAttribute("close_c_", true) exec { player, _ -> sendStageDialog(player) }
end()
} }
} }
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.MAGIC_INSTRUCTOR_946)
}
}

View file

@ -1,7 +1,7 @@
package content.region.misc.tutisland.dialogue package content.region.misc.tutisland.dialogue
import core.api.* import core.api.*
import core.game.component.Component import core.game.component.Component.setUnclosable
import core.game.dialogue.DialoguePlugin import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression import core.game.dialogue.FacialExpression
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
@ -25,32 +25,17 @@ class TutorialMasterChefDialogue(player: Player? = null) : DialoguePlugin(player
npc = args[0] as NPC npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0)) when(getAttribute(player, "tutorial:stage", 0))
{ {
18 -> Component.setUnclosable( 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."))
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 -> { 19, 20 -> {
if(!inInventory(player, Items.BREAD_DOUGH_2307)) if (!inInventory(player, Items.BREAD_DOUGH_2307)) {
{ if (!inInventory(player, Items.BUCKET_OF_WATER_1929)) {
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."))
{
sendItemDialogue(player, Items.BUCKET_OF_WATER_1929, "The Master Chef gives you another bucket of water.")
addItemOrDrop(player, Items.BUCKET_OF_WATER_1929) addItemOrDrop(player, Items.BUCKET_OF_WATER_1929)
TutorialStage.load(player, 19)
return false return false
} }
if(!inInventory(player, Items.POT_OF_FLOUR_1933)) 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."))
sendItemDialogue(player, Items.POT_OF_FLOUR_1933, "The Master Chef gives you another pot of flour.")
addItemOrDrop(player, Items.POT_OF_FLOUR_1933) addItemOrDrop(player, Items.POT_OF_FLOUR_1933)
TutorialStage.load(player, 19)
return false return false
} }
} }
@ -61,54 +46,21 @@ class TutorialMasterChefDialogue(player: Player? = null) : DialoguePlugin(player
} }
override fun handle(interfaceId: Int, buttonId: Int): Boolean { override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(getAttribute(player, "tutorial:stage", 0)) when (getAttribute(player, "tutorial:stage", 0)) {
{ 18 -> when(stage) {
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++ }
0 -> Component.setUnclosable( 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++ }
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++ }
3 -> { 3 -> {
Component.setUnclosable( 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>."))
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.BUCKET_OF_WATER_1929)
addItemOrDrop(player, Items.POT_OF_FLOUR_1933) addItemOrDrop(player, Items.POT_OF_FLOUR_1933)
stage++ stage++
setAttribute(player, "tutorial:stage", 19)
TutorialStage.load(player, 19)
} }
4 -> { 4 -> {
end() end()
setAttribute(player, "tutorial:stage", 19)
TutorialStage.load(player, 19) TutorialStage.load(player, 19)
} }
} }

View file

@ -1,104 +1,95 @@
package content.region.misc.tutisland.dialogue 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.npc.NPC
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage import content.region.misc.tutisland.handlers.TutorialStage
import content.region.misc.tutisland.handlers.sendStageDialog
import core.api.* 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
/** class MiningInstructorDialogue : InteractionListener {
* Handles the mining tutor's dialogue override fun defineListeners() {
* @author Ceikry on(NPCs.MINING_INSTRUCTOR_948, IntType.NPC, "talk-to") { player, node ->
*/ DialogueLabeller.open(player, MiningInstructorDialogueFile(), node as NPC)
@Initializable return@on true
class TutorialMiningInstructorDialogue(player: Player? = null) : DialoguePlugin(player) { }
override fun newInstance(player: Player?): DialoguePlugin { }
return TutorialMiningInstructorDialogue(player)
} }
override fun open(vararg args: Any?): Boolean { class MiningInstructorDialogueFile : DialogueLabeller() {
npc = args[0] as NPC 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)) { 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.") 30 -> loadLabel(player, "hello")
34 -> playerl(FacialExpression.FRIENDLY, "I prospected both types of rock! One set contains tin and the other has copper ore inside.") 34 -> loadLabel(player, "prospected")
35 -> { 35, 36, 37, 38, 39 -> loadLabel(player, if (lostPickaxe(player)) "lost pickaxe" else "nowhere")
if(!inInventory(player, Items.BRONZE_PICKAXE_1265)) { 40 -> loadLabel(player, "make wep")
addItemOrDrop(player, Items.BRONZE_PICKAXE_1265) 41, 42, 43, 44, 45, 46 -> loadLabel(player, if (lostPickaxe(player)) "lost pickaxe" else if (!inInventory(player, Items.HAMMER_2347)) "lost hammer" else "nowhere")
player.dialogueInterpreter.sendItemMessage(Items.BRONZE_PICKAXE_1265, "Dezzick gives you a bronze pickaxe!") else -> loadLabel(player, "nowhere")
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)
}
} }
} }
return true 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)
override fun handle(interfaceId: Int, buttonId: Int): Boolean { 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)
when(getAttribute(player, "tutorial:stage", 0)) { exec { player, _ ->
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) setAttribute(player, "tutorial:stage", 31)
TutorialStage.load(player, 31) TutorialStage.load(player, 31)
} }
}
34,35 -> when(stage) { label("prospected")
0 -> npcl(FacialExpression.FRIENDLY, "Absolutely right, ${player.username}. These two ore types can be smelted together to make bronze.").also { stage++ } player(ChatAnim.FRIENDLY, "I prospected both types of rock! One set contains tin and the other has copper ore inside.", unclosable = true)
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++ } npc(ChatAnim.FRIENDLY, "Absolutely right, ${player?.username}. These two ore types can be smelted together to make bronze.", unclosable = true)
2 -> { 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) 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) setAttribute(player, "tutorial:stage", 35)
TutorialStage.load(player, 35) TutorialStage.load(player, 35)
} }
} item(Item(Items.BRONZE_PICKAXE_1265), "Dezzick gives you a bronze pickaxe!", unclosable = true)
goto("nowhere")
40,41 -> when(stage){ label("make wep")
0 -> npcl(FacialExpression.FRIENDLY, "Okay, I'll show you how to make a dagger out of it. You'll be needing this..").also { stage++ } player(ChatAnim.ASKING, "How do I make a weapon out of this?", unclosable = true)
1 -> { 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) addItem(player, Items.HAMMER_2347)
player.dialogueInterpreter.sendItemMessage(Items.HAMMER_2347, "Drezzick gives you a hammer!")
stage++
}
2 -> {
end()
setAttribute(player, "tutorial:stage", 41) setAttribute(player, "tutorial:stage", 41)
TutorialStage.load(player, 41) TutorialStage.load(player, 41)
} }
} item(Item(Items.HAMMER_2347), "Dezzick gives you a hammer!", unclosable = true)
} goto("nowhere")
return true 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")
override fun getIds(): IntArray { label("lost hammer")
return intArrayOf(NPCs.MINING_INSTRUCTOR_948) 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 core.plugin.Initializable
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage import content.region.misc.tutisland.handlers.TutorialStage
import core.game.component.Component.setUnclosable
/** /**
* Handles the prayer guide's dialogue * Handles the prayer guide's dialogue
@ -24,9 +25,9 @@ class TutorialPrayerDialogue(player: Player? = null) : DialoguePlugin(player) {
npc = args[0] as NPC npc = args[0] as NPC
when(getAttribute(player, "tutorial:stage", 0)) 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.") 60 -> setUnclosable(player, 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!") 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 -> 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!") 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 return true
} }
@ -35,8 +36,8 @@ class TutorialPrayerDialogue(player: Player? = null) : DialoguePlugin(player) {
when(getAttribute(player, "tutorial:stage", 0)) when(getAttribute(player, "tutorial:stage", 0))
{ {
60 -> when(stage++){ 60 -> when(stage++){
0 -> playerl(FacialExpression.FRIENDLY, "Alright, sounds fun!") 0 -> setUnclosable(player, 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!") 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 -> { 2 -> {
end() end()
setAttribute(player, "tutorial:stage", 61) setAttribute(player, "tutorial:stage", 61)
@ -45,8 +46,8 @@ class TutorialPrayerDialogue(player: Player? = null) : DialoguePlugin(player) {
} }
62 -> when(stage++){ 62 -> when(stage++){
0 -> playerl(FacialExpression.AMAZED, "Very cool!") 0 -> setUnclosable(player, playerl(FacialExpression.AMAZED, "Very cool!"))
1 -> npcl(FacialExpression.FRIENDLY, "Next up, let's talk about friends.") 1 -> setUnclosable(player, npcl(FacialExpression.FRIENDLY, "Next up, let's talk about friends."))
2 -> { 2 -> {
end() end()
setAttribute(player, "tutorial:stage", 63) setAttribute(player, "tutorial:stage", 63)

View file

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

View file

@ -1,7 +1,6 @@
package content.region.misc.tutisland.dialogue package content.region.misc.tutisland.dialogue
import core.api.setAttribute import core.api.setAttribute
import core.game.component.Component
import core.game.dialogue.DialoguePlugin import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression import core.game.dialogue.FacialExpression
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
@ -9,10 +8,12 @@ import core.game.node.entity.player.Player
import core.plugin.Initializable import core.plugin.Initializable
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import content.region.misc.tutisland.handlers.TutorialStage 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 Ceikry
* @author Player Name
*/ */
@Initializable @Initializable
class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) { class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
@ -24,25 +25,11 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
npc = args[0] as NPC npc = args[0] as NPC
val tutStage = player?.getAttribute("tutorial:stage", 0) ?: 0 val tutStage = player?.getAttribute("tutorial:stage", 0) ?: 0
if (tutStage < 2) { if (tutStage < 2) {
end() setUnclosable(player, player.dialogueInterpreter.sendDialogues(npc,FacialExpression.HALF_GUILTY,"Greetings! Please follow the onscreen instructions!"))
player.dialogueInterpreter.sendDialogues(npc,FacialExpression.HALF_GUILTY,"Greetings! Please follow the onscreen, instructions!") stage = 99
return false } else if (tutStage == 2) {
} else {
Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.HALF_GUILTY,
"Greetings! Please follow the onscreen",
"instructions!"
)
)
}
if(tutStage == 2)
{
player.lock() player.lock()
Component.setUnclosable( setUnclosable(
player, player,
interpreter.sendDialogues( interpreter.sendDialogues(
npc, npc,
@ -52,26 +39,17 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
) )
) )
stage = 0 stage = 0
} else {
setUnclosable(player, player.dialogueInterpreter.sendDialogues(npc,FacialExpression.HALF_GUILTY,"Please follow the onscreen instructions!"))
stage = 99
}
return true return true
} }
else
{
Component.setUnclosable(
player,
interpreter.sendDialogues(
npc,
FacialExpression.HALF_GUILTY,
"Please follow the onscreen instructions!"
)
)
return false
}
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean { override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(stage) when(stage)
{ {
0 -> Component.setUnclosable( 0 -> setUnclosable(
player, player,
interpreter.sendDialogues( interpreter.sendDialogues(
npc, npc,
@ -81,7 +59,7 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
) )
).also { stage++ } ).also { stage++ }
1 -> Component.setUnclosable( 1 -> setUnclosable(
player, player,
interpreter.sendDialogues( interpreter.sendDialogues(
npc, npc,
@ -92,7 +70,7 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
) )
).also { stage++ } ).also { stage++ }
2 -> Component.setUnclosable( 2 -> setUnclosable(
player, player,
interpreter.sendDialogues( interpreter.sendDialogues(
npc, npc,
@ -104,7 +82,7 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
) )
).also { stage++ } ).also { stage++ }
3 -> Component.setUnclosable( 3 -> setUnclosable(
player, player,
interpreter.sendDialogues( interpreter.sendDialogues(
npc, npc,
@ -114,7 +92,7 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
) )
).also { stage++ } ).also { stage++ }
4 -> Component.setUnclosable( 4 -> setUnclosable(
player, player,
interpreter.sendDialogues( interpreter.sendDialogues(
npc, npc,
@ -130,6 +108,11 @@ class TutorialRSGuideDialogue(player: Player? = null) : DialoguePlugin(player) {
setAttribute(player, "tutorial:stage", 3) setAttribute(player, "tutorial:stage", 3)
TutorialStage.load(player, 3) TutorialStage.load(player, 3)
} }
99 -> {
end()
val tutStage = player?.getAttribute("tutorial:stage", 0) ?: 0
TutorialStage.load(player, tutStage)
}
} }
return true 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.fishing.FishingSpot
import content.global.skill.gather.mining.MiningNode import content.global.skill.gather.mining.MiningNode
import content.global.skill.gather.woodcutting.WoodcuttingNode 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.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.Items
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import org.rs09.consts.Sounds
/** /**
* Event receivers for tutorial island * Event receivers for tutorial island
* @author Ceikry * @author Ceikry, Player Name
*/ */
object TutorialButtonReceiver : EventHook<ButtonClickEvent> object TutorialButtonReceiver : EventHook<ButtonClickEvent>
{ {
@ -77,7 +94,7 @@ object TutorialButtonReceiver : EventHook<ButtonClickEvent>
} }
//Open equipment tab SD:548,42 HD:746,45 //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) setAttribute(entity, "tutorial:stage", 46)
TutorialStage.load(entity, 46) TutorialStage.load(entity, 46)
} }
@ -136,18 +153,6 @@ object TutorialInteractionReceiver : EventHook<InteractionEvent>
TutorialStage.load(entity, 13) 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 //Mine rock - Tin
35 -> if(MiningNode.forId(event.target.id)?.identifier?.equals(2.toByte()) == true && event.option == "mine"){ 35 -> if(MiningNode.forId(event.target.id)?.identifier?.equals(2.toByte()) == true && event.option == "mine"){
setAttribute(entity, "tutorial:stage", 36) setAttribute(entity, "tutorial:stage", 36)
@ -211,30 +216,12 @@ object TutorialResourceReceiver : EventHook<ResourceProducedEvent>
TutorialStage.load(entity, 14) 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 //Make some bread dough
19 -> if(event.itemId == Items.BREAD_DOUGH_2307) { 19 -> if(event.itemId == Items.BREAD_DOUGH_2307) {
setAttribute(entity, "tutorial:stage", 20) setAttribute(entity, "tutorial:stage", 20)
TutorialStage.load(entity, 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 //Mine some tin ore
36 -> if(event.itemId == Items.TIN_ORE_438){ 36 -> if(event.itemId == Items.TIN_ORE_438){
setAttribute(entity, "tutorial:stage", 37) 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 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.api.*
import core.game.event.ResourceProducedEvent
import core.game.node.scenery.Scenery import core.game.node.scenery.Scenery
import core.game.system.task.Pulse import core.game.system.task.Pulse
import core.game.world.map.Location import core.game.world.map.Location
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import core.game.interaction.InteractionListener import core.game.interaction.InteractionListener
import core.game.interaction.IntType 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.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 * Handles tutorial-specific node interactions
@ -16,10 +28,13 @@ import core.game.world.repository.Repository
class TutorialListeners : InteractionListener { class TutorialListeners : InteractionListener {
val GUIDE_HOUSE_DOOR = 3014 val GUIDE_HOUSE_DOOR = 3014
val COOKS_DOOR = 3017 val COOKS_DOOR = 3017
val RANGE = 3039
val COOKS_EXIT = 3018 val COOKS_EXIT = 3018
val QUEST_ENTER = 3019 val QUEST_ENTER = 3019
val QUEST_LADDER = 3029 val QUEST_LADDER = 3029
val QUEST_EXIT_LADDER = 3028 val QUEST_EXIT_LADDER = 3028
val TIN_ROCK = 3043
val COPPER_ROCK = 3042
val COMBAT_EXIT = 3030 val COMBAT_EXIT = 3030
val BANK_EXIT = 3024 val BANK_EXIT = 3024
val FINANCE_EXIT = 3025 val FINANCE_EXIT = 3025
@ -27,6 +42,7 @@ class TutorialListeners : InteractionListener {
val FIRST_GATE = intArrayOf(3015,3016) val FIRST_GATE = intArrayOf(3015,3016)
val COMBAT_GATES = intArrayOf(3020,3021) val COMBAT_GATES = intArrayOf(3020,3021)
val RAT_GATES = intArrayOf(3022, 3023) val RAT_GATES = intArrayOf(3022, 3023)
val FURNACE = 3044
override fun defineListeners() { override fun defineListeners() {
on(GUIDE_HOUSE_DOOR, IntType.SCENERY, "open"){ player, door -> on(GUIDE_HOUSE_DOOR, IntType.SCENERY, "open"){ player, door ->
@ -60,6 +76,36 @@ class TutorialListeners : InteractionListener {
return@on true 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 -> on(COOKS_EXIT, IntType.SCENERY, "open"){ player, door ->
if(getAttribute(player, "tutorial:stage", 0) != 22) if(getAttribute(player, "tutorial:stage", 0) != 22)
return@on true return@on true
@ -105,22 +151,40 @@ class TutorialListeners : InteractionListener {
return@on true return@on true
} }
on(COMBAT_GATES, IntType.SCENERY, "open"){ player, gate -> on(TIN_ROCK, IntType.SCENERY, "prospect") { player, _ ->
if(getAttribute(player, "tutorial:stage", 0) != 43) if (getAttribute(player, "tutorial:stage", 0) != 31) {
return@on true 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
}
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) setAttribute(player, "tutorial:stage", 44)
TutorialStage.load(player, 44) TutorialStage.load(player, 44)
}
core.game.global.action.DoorActionHandler.handleAutowalkDoor(player, gate as Scenery) core.game.global.action.DoorActionHandler.handleAutowalkDoor(player, gate as Scenery)
} }
on(RAT_GATES, IntType.SCENERY, "open") { player, gate -> on(RAT_GATES, IntType.SCENERY, "open") { player, gate ->
val stage = getAttribute(player, "tutorial:stage", 0) val stage = getAttribute(player, "tutorial:stage", 0)
if (stage !in 50..53) { 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!") openDialogue(player, RatPenDialogue(), NPC(NPCs.COMBAT_INSTRUCTOR_944))
return@on true return@on true
} }
if (stage == 50) { if (stage == 50) {
setAttribute(player, "tutorial:stage", 51) setAttribute(player, "tutorial:stage", 51)
TutorialStage.load(player, 51) TutorialStage.load(player, 51)
@ -130,11 +194,14 @@ class TutorialListeners : InteractionListener {
} }
on(COMBAT_EXIT, IntType.SCENERY, "climb-up") { player, ladder -> 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 return@on true
}
if (stage == 55) {
setAttribute(player, "tutorial:stage", 56) setAttribute(player, "tutorial:stage", 56)
TutorialStage.load(player, 56) TutorialStage.load(player, 56)
}
core.game.global.action.ClimbActionHandler.climbLadder(player, ladder.asScenery(), "climb-up") 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) 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 var LOG_CUTSCENE = true
@JvmField @JvmField
var RULES_AND_INFO_ENABLED = true var RULES_AND_INFO_ENABLED = false
@JvmField @JvmField
var WATCHDOG_ENABLED = true var WATCHDOG_ENABLED = true
@ -292,13 +292,16 @@ class ServerConstants {
var DRAGON_AXE_USE_OSRS_SPEC = false var DRAGON_AXE_USE_OSRS_SPEC = false
@JvmField @JvmField
var ENABLE_GLOBALCHAT = false var ENABLE_GLOBAL_CHAT = false
@JvmField @JvmField
var MAX_PATHFIND_DISTANCE = 25 var MAX_PATHFIND_DISTANCE = 25
@JvmField @JvmField
var IRONMAN_ICONS = false var XP_RATES = false
@JvmField
var IRONMAN = false
@JvmField @JvmField
var PLAYER_STOCK_CLEAR_INTERVAL = 1 var PLAYER_STOCK_CLEAR_INTERVAL = 1
@ -310,19 +313,19 @@ class ServerConstants {
var BOTSTOCK_LIMIT = 5000 var BOTSTOCK_LIMIT = 5000
@JvmField @JvmField
var BETTER_AGILITY_PYRAMID_GP = true var BETTER_AGILITY_PYRAMID_GP = false
@JvmField @JvmField
var BETTER_DFS = true var BETTER_DFS = false
@JvmField @JvmField
var NEW_PLAYER_ANNOUNCEMENT = true var NEW_PLAYER_ANNOUNCEMENT = false
@JvmField @JvmField
var INAUTHENTIC_CANDLELIGHT_RANDOM = false var INAUTHENTIC_CANDLELIGHT_RANDOM = false
@JvmField @JvmField
var HOLIDAY_EVENT_RANDOMS = true var HOLIDAY_EVENT_RANDOMS = false
@JvmField @JvmField
var FORCE_HALLOWEEN_EVENTS = false var FORCE_HALLOWEEN_EVENTS = false
@ -334,7 +337,7 @@ class ServerConstants {
var FORCE_EASTER_EVENTS = false var FORCE_EASTER_EVENTS = false
@JvmField @JvmField
var RUNECRAFTING_FORMULA_REVISION = 581 var RUNECRAFTING_FORMULA_REVISION = 530
@JvmField @JvmField
var ENHANCED_DEEP_WILDERNESS = false var ENHANCED_DEEP_WILDERNESS = false

View file

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

View file

@ -1,9 +1,15 @@
package core.game.dialogue package core.game.dialogue
import core.api.Event
import core.api.InputType import core.api.InputType
import core.api.face import core.api.face
import core.api.openDialogue import core.api.openDialogue
import core.api.splitLines 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.npc.NPC
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.item.Item import core.game.node.item.Item
@ -73,11 +79,14 @@ abstract class DialogueLabeller : DialogueFile() {
/** Implement this function instead of overriding handle. */ /** Implement this function instead of overriding handle. */
abstract fun addConversation() abstract fun addConversation()
/** Helper function to create an individual stage for each of the dialogue stages. */ /** Helper functions to create an individual stage for each of the dialogue stages. */
private fun assignIndividualStage(callback: () -> Unit) { private fun assignIndividualStage(callback: () -> Component?, unclosable: Boolean) {
if (startingStage == null) { startingStage = 0 } if (startingStage == null) { startingStage = 0 }
if (stage == dialogueCounter && jumpTo == null) { // Run this stage when the stage equals to the dialogueCounter of this dialogue 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) 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 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. **/ /** Manual stage. For custom creation of an individual stage. Must call interpreter in some form. **/
fun manual(callback: (player: Player, npc: NPC) -> Unit) { fun manual(unclosable: Boolean = false, callback: (player: Player, npc: NPC) -> Component?) {
assignIndividualStage { callback(player!!, npc!!) } assignIndividualStage({ return@assignIndividualStage callback(player!!, npc!!) }, unclosable)
} }
/** Dialogue player/playerl. Shows player chathead with text. **/ /** Dialogue player/playerl. Shows player chathead with text. **/
fun player(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) { fun player(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String, unclosable: Boolean = false) {
assignIndividualStage { interpreter!!.sendDialogues(player, chatAnim, *formatMessages(messages)) } assignIndividualStage({ return@assignIndividualStage interpreter!!.sendDialogues(player, chatAnim, *formatMessages(messages)) }, unclosable)
} }
/** Dialogue player/playerl. Shows player chathead with text. **/ /** Dialogue player/playerl. Shows player chathead with text. **/
fun player(vararg messages: String) { player(ChatAnim.NEUTRAL, *messages) } 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.") } fun playerl(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use player() instead.") }
/** Dialogue npc/npcl. Shows npc chathead with text. **/ /** Dialogue npc/npcl. Shows npc chathead with text. **/
fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String) { fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, vararg messages: String, unclosable: Boolean = false) {
assignIndividualStage { interpreter!!.sendDialogues(npc, chatAnim, *formatMessages(messages)) } val callback = callback@{ return@callback interpreter!!.sendDialogues(npc, chatAnim, *formatMessages(messages)) }
assignIndividualStage(callback, unclosable)
} }
/** Dialogue npc/npcl. Shows npcId chathead with text. **/ /** Dialogue npc/npcl. Shows npcId chathead with text. **/
fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, npcId: Int = npc!!.id, vararg messages: String) { fun npc(chatAnim: ChatAnim = ChatAnim.NEUTRAL, npcId: Int = npc!!.id, vararg messages: String, unclosable: Boolean = false) {
assignIndividualStage { interpreter!!.sendDialogues(NPC(npcId), chatAnim, *formatMessages(messages)) } assignIndividualStage({ return@assignIndividualStage interpreter!!.sendDialogues(NPC(npcId), chatAnim, *formatMessages(messages)) }, unclosable)
} }
/** Dialogue npc/npcl. Shows npcId chathead with text. **/ /** Dialogue npc/npcl. Shows npcId chathead with text. **/
fun npc(npcId: Int = npc!!.id, vararg messages: String) { fun npc(npcId: Int = npc!!.id, vararg messages: String, unclosable: Boolean = false) {
assignIndividualStage { interpreter!!.sendDialogues(NPC(npcId), ChatAnim.NEUTRAL, *formatMessages(messages)) } assignIndividualStage({ return@assignIndividualStage interpreter!!.sendDialogues(NPC(npcId), ChatAnim.NEUTRAL, *formatMessages(messages)) }, unclosable)
} }
/** Dialogue npc/npcl. Shows npc chathead with text. **/ /** Dialogue npc/npcl. Shows npc chathead with text. **/
fun npc(vararg messages: String) { npc(ChatAnim.NEUTRAL, *messages) } 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.") } fun npcl(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use npc() instead.") }
/** Dialogue item/iteml. Shows item with text. **/ /** Dialogue item/iteml. Shows item with text. **/
fun item(item: Item, vararg messages: String, message: String = "") { fun item(item: Item, vararg messages: String, message: String = "", unclosable: Boolean = false) {
assignIndividualStage { interpreter!!.sendItemMessage(item, *formatMessages(messages, message)) } val callback = callback@{ return@callback interpreter!!.sendItemMessage(item, *formatMessages(messages, message)) }
assignIndividualStage(callback, unclosable)
} }
@Deprecated("Use item() instead.", ReplaceWith("item(item, *messages)")) @Deprecated("Use item() instead.", ReplaceWith("item(item, *messages)"))
fun iteml(item: Item, vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use item() instead.") } fun iteml(item: Item, vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use item() instead.") }
/** Dialogue overloaded doubleItem/doubleIteml. Shows two items with text. **/ /** Dialogue overloaded doubleItem/doubleIteml. Shows two items with text. **/
fun item(item: Item, item2: Item, vararg messages: String, message: String = "") { fun item(item: Item, item2: Item, vararg messages: String, message: String = "", unclosable: Boolean = false) {
assignIndividualStage { interpreter!!.sendDoubleItemMessage(item, item2, formatMessages(messages, message).joinToString(" ")) } assignIndividualStage({ return@assignIndividualStage interpreter!!.sendDoubleItemMessage(item, item2, *formatMessages(messages, message)) }, unclosable)
} }
/** Dialogue line/linel. Simply shows text. **/ /** Dialogue line/linel. Simply shows text. **/
fun line(vararg messages: String) { fun line(vararg messages: String, unclosable: Boolean = false) {
assignIndividualStage { interpreter!!.sendDialogue(*messages) } val callback = callback@{ return@callback interpreter!!.sendDialogue(*messages) }
assignIndividualStage(callback, unclosable)
} }
@Deprecated("Use line() instead.", ReplaceWith("line(*messages)")) @Deprecated("Use line() instead.", ReplaceWith("line(*messages)"))
fun linel(vararg messages: String) { throw Exception("Deprecated DialogueLabel: Use line() instead.") } 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. **/ /** 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. // Filter out options that aren't shown.
val filteredOptions = options.filter{ if (it.optionIf != null) { it.optionIf.invoke(player!!, npc!!) } else { true } } val filteredOptions = options.filter{ if (it.optionIf != null) { it.optionIf.invoke(player!!, npc!!) } else { true } }
// Stage Part 1: Options List Dialogue // 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. // Stage Part 2: Show spoken text.
var opt = if (buttonID != null && buttonID in 1..filteredOptions.size) { filteredOptions[buttonID!! - 1] } else { null } val opt = if (buttonID != null && buttonID in 1..filteredOptions.size) { filteredOptions[buttonID!! - 1] } else { null }
assignIndividualStage { assignIndividualStage({
var component: Component? = null
if (opt?.skipPlayer == true) { if (opt?.skipPlayer == true) {
jumpTo = stage + 1 jumpTo = stage + 1
} else { } 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 optButton = buttonID // transfer the buttonID to a temp memory for the next stage
} return@assignIndividualStage component
}, unclosable)
// Stage Part 3: Jump To goto // Stage Part 3: Jump To goto
if (stage == dialogueCounter && optButton != null && optButton in 1..filteredOptions.size) { if (stage == dialogueCounter && optButton != null && optButton in 1..filteredOptions.size) {
jumpTo = labelStageMap[filteredOptions[optButton!! - 1].goto] 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. **/ /** 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") { fun input(type: InputType, prompt: String = "Enter the amount") {
assignIndividualStage { assignIndividualStage({
// These are similar to calling sendInputDialogue // These are similar to calling sendInputDialogue
when (type) { when (type) {
InputType.AMOUNT -> interpreter!!.sendInput(true, prompt) InputType.AMOUNT -> interpreter!!.sendInput(true, prompt)
@ -230,14 +245,31 @@ abstract class DialogueLabeller : DialogueFile() {
interpreter!!.handle(player!!.interfaceManager.chatbox.id, 2) interpreter!!.handle(player!!.interfaceManager.chatbox.id, 2)
} }
player!!.setAttribute("input-type", type) 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. **/ /** 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) } 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. **/ /** 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) { 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. */ /** WARNING: DIALOGUE LABELLER WILL BREAK IN CERTAIN FUNCTIONS. USE open() instead. */
@ -269,7 +301,10 @@ abstract class DialogueLabeller : DialogueFile() {
break 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. * Method used to send options.
* @param options the options. * @param options the options.
*/ */
public void options(final String... options) { public Component options(final String... options) {
interpreter.sendOptions("Select an Option", options); return interpreter.sendOptions("Select an Option", options);
} }
/** /**

View file

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

View file

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

View file

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

View file

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

View file

@ -5,7 +5,7 @@ package core.game.node.entity.player.link;
* @author Vexia * @author Vexia
*/ */
public enum IronmanMode { 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); NONE(-1), STANDARD(5), HARDCORE(6), ULTIMATE(7);
/** /**

View file

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

View file

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

View file

@ -76,8 +76,6 @@ object ServerConfigParser {
isQuickChat = false, isQuickChat = false,
isLootshare = false, isLootshare = false,
msAddress = data.getString("server.msip"), 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_default_clan = data.getBoolean("world.enable_default_clan"),
enable_bots = data.getBoolean("world.enable_bots"), enable_bots = data.getBoolean("world.enable_bots"),
autostock_ge = data.getBoolean("world.autostock_ge"), 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.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.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.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.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_CLEAR_INTERVAL = data.getLong("world.playerstock_clear_mins", 180L).toInt()
ServerConstants.PLAYER_STOCK_RECIRCULATE = data.getBoolean("world.playerstock_bot_offers", true) ServerConstants.PLAYER_STOCK_RECIRCULATE = data.getBoolean("world.playerstock_bot_offers", true)
ServerConstants.BOTSTOCK_LIMIT = data.getLong("world.botstock_limit", 5000L).toInt() 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_PATH = data.getPath("integrations.grafana_log_path")
ServerConstants.GRAFANA_LOGGING = data.getBoolean("integrations.grafana_logging", false) ServerConstants.GRAFANA_LOGGING = data.getBoolean("integrations.grafana_logging", false)
ServerConstants.GRAFANA_TTL_DAYS = data.getLong("integrations.grafana_log_ttl_days", 7L).toInt() ServerConstants.GRAFANA_TTL_DAYS = data.getLong("integrations.grafana_log_ttl_days", 7L).toInt()
ServerConstants.BETTER_DFS = data.getBoolean("world.better_dfs", true) ServerConstants.BETTER_DFS = data.getBoolean("world.better_dfs", false)
ServerConstants.NEW_PLAYER_ANNOUNCEMENT = data.getBoolean("world.new_player_announcement", true) ServerConstants.NEW_PLAYER_ANNOUNCEMENT = data.getBoolean("world.new_player_announcement", false)
ServerConstants.INAUTHENTIC_CANDLELIGHT_RANDOM = data.getBoolean("world.inauthentic_candlelight_random", 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_HALLOWEEN_EVENTS = data.getBoolean("world.force_halloween_randoms", false)
ServerConstants.FORCE_CHRISTMAS_EVENTS = data.getBoolean("world.force_christmas_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.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.ENHANCED_DEEP_WILDERNESS = data.getBoolean("world.enhanced_deep_wilderness", false)
ServerConstants.WILDERNESS_EXCLUSIVE_LOOT = data.getBoolean("world.wilderness_exclusive_loot", false) ServerConstants.WILDERNESS_EXCLUSIVE_LOOT = data.getBoolean("world.wilderness_exclusive_loot", false)
ServerConstants.SHOOTING_STAR_RING = data.getBoolean("world.shooting_star_ring", 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. * The address of the Management server.
*/ */
var msAddress: String, var msAddress: String,
var default_xp_rate: Double,
var allow_slayer_reroll: Boolean,
var enable_default_clan: Boolean, var enable_default_clan: Boolean,
var enable_bots: Boolean, var enable_bots: Boolean,
var autostock_ge: Boolean, var autostock_ge: Boolean,
@ -126,8 +124,6 @@ class GameSettings
val activity = data["activity"].toString() val activity = data["activity"].toString()
val pvpWorld = data["pvpWorld"] as Boolean val pvpWorld = data["pvpWorld"] as Boolean
val msip = data["msip"].toString() 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_default_clan = data["enable_default_clan"] as Boolean
val enable_bots = data["enable_bots"] as Boolean val enable_bots = data["enable_bots"] as Boolean
val autostock_ge = data["autostock_ge"] as Boolean val autostock_ge = data["autostock_ge"] as Boolean
@ -157,8 +153,6 @@ class GameSettings
false, false,
false, false,
msip, msip,
default_xp_rate,
allow_slayer_reroll,
enable_default_clan, enable_default_clan,
enable_bots, enable_bots,
autostock_ge, autostock_ge,

View file

@ -208,7 +208,7 @@ object PacketProcessor {
if (pkt.player.details.isMuted) if (pkt.player.details.isMuted)
pkt.player.sendMessage("You have been muted due to breaking a rule.") pkt.player.sendMessage("You have been muted due to breaking a rule.")
else { 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)) if (getAttribute(pkt.player, GlobalChat.ATTR_GLOBAL_MUTE, false))
return return

View file

@ -27,8 +27,6 @@ members = true
#activity as displayed on the world list #activity as displayed on the world list
activity = "2009Scape Classic." activity = "2009Scape Classic."
pvp = false 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. #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_default_clan = true
enable_bots = true enable_bots = true
@ -49,6 +47,7 @@ max_adv_bots = 100
enable_doubling_money_scammers = true enable_doubling_money_scammers = true
wild_pvp_enabled = false wild_pvp_enabled = false
jad_practice_enabled = false jad_practice_enabled = false
enable_global_chat = false
enable_castle_wars = false enable_castle_wars = false
personalized_shops = false personalized_shops = false

View file

@ -58,8 +58,6 @@ members = true
#activity as displayed on the world list #activity as displayed on the world list
activity = "2009Scape Classic." activity = "2009Scape Classic."
pvp = false 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. #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_default_clan = true
enable_bots = true enable_bots = true
@ -72,44 +70,61 @@ new_player_location = "2524,5002,0"
#the location of home teleport #the location of home teleport
home_location = "3222,3218,0" home_location = "3222,3218,0"
autostock_ge = false autostock_ge = false
allow_token_purchase = true allow_token_purchase = false
skillcape_perks = true skillcape_perks = false
increased_door_time = false increased_door_time = false
enable_botting = false enable_botting = false
max_adv_bots = 100 max_adv_bots = 100
enable_doubling_money_scammers = true enable_doubling_money_scammers = true
wild_pvp_enabled = true wild_pvp_enabled = false
jad_practice_enabled = true jad_practice_enabled = false
enable_global_chat = false
#minimum HA value for announcements of bots selling on ge #minimum HA value for announcements of bots selling on ge
ge_announcement_limit = 500 ge_announcement_limit = 500
enable_castle_wars = false enable_castle_wars = false
personalized_shops = true personalized_shops = false
bots_influence_ge_price = true bots_influence_ge_price = true
#verbose cutscene logging (for cutscenes in the new system) #verbose cutscene logging (for cutscenes in the new system)
verbose_cutscene = false verbose_cutscene = false
#show the rules the first time a player logs in #show the rules the first time a player logs in
show_rules = true show_rules = false
#the number of revenants active at a time #the number of revenants active at a time
revenant_population = 30 revenant_population = 30
#enable auto-buy/auto-sell on the GE. #enable auto-buy/auto-sell on the GE.
i_want_to_cheat = false i_want_to_cheat = false
#better agility pyramid gp reward (gp reward = 1000 + ((agility level / 99) * 9000)) #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 dragonfire shield attack (30 second cooldown instead of 2 minutes)
better_dfs = true better_dfs = false
#new player announcement #new player announcement
new_player_announcement = true new_player_announcement = false
#enables inauthentic candlelight random event (adds an additional normal random event) #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) #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 holiday randoms (can only force one at a time)
force_halloween_randoms = false force_halloween_randoms = false
force_christmas_randoms = false force_christmas_randoms = false
#runecrafting formula revision (573 introduced probabilistic multiple runes, 581 extrapolated probabilistic runes past 99) #runecrafting formula revision (573 introduced probabilistic multiple runes, 581 extrapolated probabilistic runes past 99)
runecrafting_formula_revision = 581 runecrafting_formula_revision = 530
#enable the enhanced deep wilderness, where the area past the members' fence applies a red skull that boosts brawler/pvp drop rates #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 = true 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] [paths]
#path to the data folder, which contains the cache subfolder and such #path to the data folder, which contains the cache subfolder and such