Refactored the Player Safety Stronghold

This commit is contained in:
GregF 2024-04-17 07:45:55 +00:00 committed by Ryan
parent 6deadc6f90
commit 0dcdc84f79
17 changed files with 892 additions and 1099 deletions

View file

@ -72624,5 +72624,65 @@
"examine": "An intelligent-looking shop owner.", "examine": "An intelligent-looking shop owner.",
"name": "Obli", "name": "Obli",
"id": "516" "id": "516"
},
{
"examine": "A person sitting an exam.",
"melee_animation": "0",
"range_animation": "0",
"defence_animation": "0",
"magic_animation": "0",
"death_animation": "0",
"name": "Student",
"defence_level": "1",
"lifepoints": "10",
"strength_level": "1",
"id": "7151",
"range_level": "1",
"attack_level": "1"
},
{
"examine": "A person sitting an exam.",
"melee_animation": "0",
"range_animation": "0",
"defence_animation": "0",
"magic_animation": "0",
"death_animation": "0",
"name": "Student",
"defence_level": "1",
"lifepoints": "10",
"strength_level": "1",
"id": "7153",
"range_level": "1",
"attack_level": "1"
},
{
"examine": "A person sitting an exam.",
"melee_animation": "0",
"range_animation": "0",
"defence_animation": "0",
"magic_animation": "0",
"death_animation": "0",
"name": "Student",
"defence_level": "1",
"lifepoints": "10",
"strength_level": "1",
"id": "7154",
"range_level": "1",
"attack_level": "1"
},
{
"examine": "A person sitting an exam.",
"melee_animation": "0",
"range_animation": "0",
"defence_animation": "0",
"magic_animation": "0",
"death_animation": "0",
"name": "Student",
"defence_level": "1",
"lifepoints": "10",
"strength_level": "1",
"id": "7155",
"range_level": "1",
"attack_level": "1"
} }
] ]

View file

@ -11389,11 +11389,11 @@
}, },
{ {
"npc_id": "7159", "npc_id": "7159",
"loc_data": "{3174,4238,2,1,6}-{3175,4243,2,1,6}-{3179,4236,2,1,4}-{3145,4272,1,1,3}-{3145,4276,1,1,3}-{3152,4271,1,1,6}-{3144,4264,1,1,4}-{3153,4266,1,1,1}-{3152,4261,1,1,4}-{3145,4259,1,1,6}-{3161,4259,1,1,0}-{3160,4265,1,1,0}-{3153,4246,1,1,3}-{3157,4248,1,1,6}-{3161,4247,1,1,4}-{3146,4247,1,1,6}-{3153,4233,1,1,4}-{3153,4240,1,1,6}-{3155,4238,1,1,5}-{3169,4267,3,1,3}-{3160,4265,3,1,6}-{3168,4250,3,1,4}-{3168,4244,3,1,6}-{3160,4239,3,1,1}-{3160,4228,3,1,3}-{3147,4225,3,1,3}-{3145,4242,3,1,5}-{3139,4249,3,1,6}-{3144,4253,3,1,3}-{3145,4266,3,1,0}-{3138,4266,3,1,3}-" "loc_data": "{3174,4238,2,1,6}-{3175,4243,2,1,6}-{3179,4236,2,1,4}-{3145,4272,1,1,3}-{3145,4276,1,1,3}-{3152,4271,1,1,6}-{3144,4264,1,1,4}-{3153,4266,1,1,1}-{3152,4261,1,1,4}-{3145,4259,1,1,6}-{3161,4259,1,1,0}-{3160,4265,1,1,0}-{3153,4246,1,1,3}-{3157,4248,1,1,6}-{3161,4247,1,1,4}-{3146,4247,1,1,6}-{3153,4233,1,1,4}-{3153,4240,1,1,6}-{3155,4238,1,1,5}-{3169,4267,3,1,3}-{3160,4265,3,1,6}-{3168,4250,3,1,4}-{3168,4244,3,1,6}-{3160,4239,3,1,1}-{3160,4228,3,1,3}-{3147,4225,3,1,3}-{3145,4242,3,1,5}-{3139,4249,3,1,6}-{3144,4253,3,1,3}-{3145,4266,3,1,0}-{3138,4266,3,1,3}-{3151,4272,3,1,0}-{3139,4272,3,1,0}-{3146,4231,3,1,0}-{3169,4270,3,1,0}-"
}, },
{ {
"npc_id": "7160", "npc_id": "7160",
"loc_data": "{3175,4254,2,1,7}-{3176,4247,2,1,5}-{3174,4269,2,1,1}-{3190,4253,2,1,3}-{3192,4247,2,1,3}-{3189,4235,2,1,0}-{3152,4269,0,1,4}-{3160,4278,0,1,1}-{3160,4262,0,1,3}-{3149,4250,0,1,0}-{3158,4250,0,1,5}-{3161,4236,0,1,6}-{3172,4250,0,1,2}-{3171,4269,3,1,1}-{3157,4277,3,1,3}-{3150,4278,3,1,3}-" "loc_data": "{3175,4254,2,1,7}-{3176,4247,2,1,5}-{3174,4269,2,1,1}-{3190,4253,2,1,3}-{3192,4247,2,1,3}-{3189,4235,2,1,0}-{3152,4269,0,1,4}-{3160,4278,0,1,1}-{3160,4262,0,1,3}-{3149,4250,0,1,0}-{3158,4250,0,1,5}-{3161,4236,0,1,6}-{3172,4250,0,1,2}-{3171,4269,3,1,1}-{3157,4277,3,1,3}-{3150,4278,3,1,3}-{3160,4271,1,1,0}-{3163,4274,1,1,0}-{3167,4277,1,1,0}-{3173,4277,1,1,0}-{3175,4275,1,1,0}-{3160,4269,0,1,0}-{3173,4264,0,1,0}-{3190,4237,2,1,0}-{3154,4279,3,1,0}-"
}, },
{ {
"npc_id": "7161", "npc_id": "7161",

View file

@ -0,0 +1,164 @@
package content.region.misthalin.barbvillage.stronghold.playersafety
import core.api.runTask
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.game.world.GameWorld.settings
import core.plugin.Initializable
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import org.rs09.consts.NPCs
@Initializable
class GuardDialogue(player: Player? = null) : DialoguePlugin(player) {
companion object{
const val DIALOGUE_COMPLETED = START_DIALOGUE
const val DIALOGUE_NOT_COMPLETED = 50
}
override fun open(vararg args: Any?): Boolean {
val hasRead = player.savedData.globalData.hasReadPlaques()
if (hasRead) {
npcl(FacialExpression.HALF_GUILTY, "Can I help you?").also { stage = DIALOGUE_COMPLETED }
}
else {
npcl(FacialExpression.FURIOUS, "Ahem! Can I help you?").also { stage = DIALOGUE_NOT_COMPLETED }
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
DIALOGUE_COMPLETED -> {
playerl(
FacialExpression.HALF_GUILTY, "Can I go upstairs?"
).also { stage++ }
}
DIALOGUE_COMPLETED + 1 -> {
npcl(
FacialExpression.FURIOUS,
"Yes, citizen. Before you do I am instructed to give " +
"you one final piece of information"
).also { stage++ }
}
DIALOGUE_COMPLETED + 2 -> {
playerl(FacialExpression.HALF_GUILTY, "Oh, okay then.").also { stage++ }
}
DIALOGUE_COMPLETED + 3 -> {
npcl(
FacialExpression.HALF_GUILTY,
"In your travels around " + settings!!.name + ", should you find a player who acts in a " +
"way that breaks on of our rules, you should report them."
).also { stage++ }
}
DIALOGUE_COMPLETED + 4 -> {
npcl(
FacialExpression.HALF_GUILTY,
"Reporting is very simple and easy to do. Simply click the Report Abuse button at " +
"the bottom of the screen and you will be shown the following screen:"
).also { stage++ }
}
DIALOGUE_COMPLETED + 5 -> {
player.interfaceManager.openComponent(700)
runTask(player, 5) {
if (player != null) {
player.interfaceManager.close()
}
return@runTask
}.also { stage++ }
}
DIALOGUE_COMPLETED + 6 -> {
npcl(
FacialExpression.HALF_GUILTY,
"Simply enter the player's name in the box and click the rule that the offender was breaking."
).also { stage++ }
}
DIALOGUE_COMPLETED + 7 -> {
playerl(FacialExpression.HALF_GUILTY, "Okay. Then what?").also { stage++ }
}
DIALOGUE_COMPLETED + 8 -> {
npcl(
FacialExpression.HALF_GUILTY,
"That's it! It really is that simple and it only takes a moment to do. " +
"Now you may enter the training centre. Good luck, citizen."
).also { stage++ }
}
DIALOGUE_COMPLETED + 9 -> {
playerl(FacialExpression.HALF_GUILTY, "Thanks!").also { stage = END_DIALOGUE }
}
DIALOGUE_NOT_COMPLETED -> {
playerl(
FacialExpression.HALF_GUILTY, "I'd like to go up to the training centre please."
).also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 1 -> {
npcl(FacialExpression.FURIOUS, "Sorry, citizen, you can't go up there.").also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 2 -> {
playerl(FacialExpression.OLD_SNEAKY, "Why not?").also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 3 -> {
npcl(
FacialExpression.ANNOYED,
"You must learn about player safety before entering the training centre."
).also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 4 -> {
playerl(FacialExpression.HALF_GUILTY, "Oh. How do I do that?").also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 5 -> {
npcl(
FacialExpression.HALF_GUILTY,
"Each of these gublinches have been caught breaking the rules of " + settings!!.name + ". " +
"You should read the plaques on each of their cells to learn what they did wrong."
).also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 6 -> {
playerl(
FacialExpression.HALF_GUILTY,
"Oh, right. I can enter the training centre once I have done that?"
).also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 7 -> {
npcl(
FacialExpression.HALF_GUILTY,
"Yes. Once you have have examined each of the plaques, come and speak to me " +
"and I will tell you about the Report Abuse function."
).also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 8 -> {
npcl(
FacialExpression.HALF_GUILTY,
"After that, I can let you into the training centre, upstairs."
).also { stage++ }
}
DIALOGUE_NOT_COMPLETED + 9 -> {
playerl(FacialExpression.HALF_GUILTY, "Okay, thanks for the help.").also { stage = END_DIALOGUE }
player.sendMessage("You need to read the jail plaques before the guard will allow you upstairs.")
}
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.GUARD_7142)
}
}

View file

@ -1,144 +0,0 @@
package content.region.misthalin.barbvillage.stronghold.playersafety;
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.tools.Log;
import core.tools.SystemLogger;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import static core.api.ContentAPIKt.log;
/**
* @author Tyler Telis
*/
public class GuardDialoguePlugin extends DialoguePlugin {
/**
* Constructs a new {@code GuardDialogue} instance.
* @param player The {@code Player} instance.
*/
public GuardDialoguePlugin(Player player) {
super(player);
}
/**
* Constructs a new {@code GuardDialoguePlugin} instance.
*/
public GuardDialoguePlugin() {
}
@Override
public DialoguePlugin newInstance(Player player) {
return new GuardDialoguePlugin(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
boolean read = player.getSavedData().getGlobalData().hasReadPlaques();
interpreter.sendDialogues(npc, read ? FacialExpression.HALF_GUILTY : FacialExpression.FURIOUS, read ? "Can I help you?" : "Ahem! Can I help you?");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
boolean read = player.getSavedData().getGlobalData().hasReadPlaques();
switch (stage) {
case -1:// END dialogue stage.
end();
break;
case 0:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, read ? "Can I go upstairs?" : "I'd like to go up to the training centre please.");
increment();
break;
case 1:
interpreter.sendDialogues(npc, FacialExpression.FURIOUS, !read ? "Sorry, citizen, you can't go up there." : "", "Yes, citizen. Before you do I am instructed to give", "you one final piece of information");
increment();
break;
case 2:
interpreter.sendDialogues(player, read ? FacialExpression.HALF_GUILTY : FacialExpression.OLD_SNEAKY, read ? "Oh, okay then." : "Why not?");
increment();
break;
case 3:
if (!read) {
npc("You must learn about player safety before<br>entering the training centre.");
} else {
npc("In your travels around " + GameWorld.getSettings().getName() + ", should you find a", "player who acts in a way that breaks on of our rules,", "you should report them.");
}
increment();
break;
case 4:
interpreter.sendDialogues(read ? npc : player, FacialExpression.HALF_GUILTY, !read ? "Oh. How do I do that?" : "Reporting is very simple and easy to do. Simply click", "the Report Abuse button at the bottom of the screen", "and you will be shown the following screen:");
stage = read ? 10 : stage + 1;
break;
case 5:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Each of these gublinches have been caught breaking the", "Rules of " + GameWorld.getSettings().getName() + ". You should read the plaques on", "each of their cells to learn what they did wrong.");
increment();
break;
case 6:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Oh, right. I can enter the training centre once I have", "done that?");
increment();
break;
case 7:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Yes. Once you have have examined each of the plaques,", "come and speak to me and I will tell you about the", "Report Abuse function.");
increment();
break;
case 8:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "After that, I can let you into the training centre,", "upstairs.");
increment();
break;
case 9:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Okay, thanks for the help.");
player.getPacketDispatch().sendMessage("You need to read the jail plaques before the guard will allow you upstairs.");
stage = -1;
break;
case 10:
if (read) {
player.getInterfaceManager().open(new Component(700));
GameWorld.getPulser().submit(new Pulse(5) {
@Override
public boolean pulse() {
if (player != null) {
player.getInterfaceManager().close();
}
return true;
}
});
stage = 12;
}
break;
case 12:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Simply enter the player's name in the box and click the", "rule that the offender was breaking.");
stage = 13;
break;
case 13:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Okay. Then what?");
stage = 14;
break;
case 14:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "That's it! It reall is that simple and it only takes a ", "moment to do. Now you may enter the training", "centre. Good luck, citizen.");
stage = 15;
break;
case 15:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Thanks!");
stage = -1;
break;
default:
log(this.getClass(), Log.ERR, "Unhandled dialogue stage=" + stage);
}
return false;
}
@Override
public int[] getIds() {
return new int[] { 7142 };
}
}

View file

@ -1,176 +0,0 @@
package content.region.misthalin.barbvillage.stronghold.playersafety;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JAIL_DOWN_STAIRS;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JAIL_ENTRANCE_ID_ENTER;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JAIL_ENTRANCE_LEAVE;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JAIL_ENTRANCE_LOCATION_ENTER;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JAIL_ENTRANCE_LOCATION_LEAVE;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JAIL_STAIRS_DOWN;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JAIL_STAIRS_UP;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JAIL_UP_STAIRS;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.TEST_PAPER_ITEM_ID;
import static content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.forId;
import core.cache.def.impl.ItemDefinition;
import core.cache.def.impl.SceneryDefinition;
import core.game.dialogue.DialogueAction;
import core.game.global.action.DoorActionHandler;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.emote.Emotes;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.node.scenery.SceneryBuilder;
import core.game.world.map.Location;
import core.plugin.Plugin;
import content.region.misthalin.barbvillage.stronghold.playersafety.StrongHoldOfPlayerSafetyPlugin.JailPlaques;
import static core.api.ContentAPIKt.*;
/**
* @author Tyler Telis
*/
public class PSOptionHandler extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
SceneryDefinition.forId(JAIL_ENTRANCE_ID_ENTER).getHandlers().put("option:use", this);
SceneryDefinition.forId(JAIL_ENTRANCE_LEAVE).getHandlers().put("option:leave", this);
SceneryDefinition.forId(JAIL_STAIRS_UP).getHandlers().put("option:climb-up", this);
SceneryDefinition.forId(JAIL_STAIRS_DOWN).getHandlers().put("option:climb-down", this);
SceneryDefinition.forId(29732).getHandlers().put("option:open", this);
SceneryDefinition.forId(29624).getHandlers().put("option:open", this);
SceneryDefinition.forId(29728).getHandlers().put("option:enter", this);
SceneryDefinition.forId(29735).getHandlers().put("option:pull-back", this);
SceneryDefinition.forId(29623).getHandlers().put("option:use", this);
SceneryDefinition.forId(29730).getHandlers().put("option:pull", this);
SceneryDefinition.forId(29731).getHandlers().put("option:pull", this);
SceneryDefinition.forId(29577).getHandlers().put("option:open", this);
SceneryDefinition.forId(29578).getHandlers().put("option:search", this);
ItemDefinition.forId(TEST_PAPER_ITEM_ID).getHandlers().put("option:take exam", this);
SceneryDefinition.forId(29729).getHandlers().put("option:climb", this);
for (JailPlaques plaque : JailPlaques.values()) {
SceneryDefinition.forId(plaque.getObjectId()).getHandlers().put("option:read-plaque on", this);
}
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
int config = getVarp(player, 1203);
boolean locked = config == (1 << 29) || config == (0 << 26);
switch (node.getId()) {
case 29577:// chest
SceneryBuilder.replace(node.asScenery(), node.asScenery().transform(29578), 60);
return true;
case 29578:
switch (option) {
case "search":
int stage = player.getSavedData().getGlobalData().getTestStage();
if (stage == 3) {
player.getEmoteManager().unlock(Emotes.SAFETY_FIRST);
player.getInventory().add(new Item(995, 10000), player);
player.getInventory().add(new Item(12629), player);
player.getDialogueInterpreter().sendItemMessage(12629, "You open the chest to find a large pile of gold, along with a pair of safety gloves. Also in the chest is the secret of the 'Safety First' emote.");
player.getSavedData().getGlobalData().setTestStage(4);
} else if (stage == 4) {
if (!player.hasItem(new Item(12629))) {
player.getInventory().add(new Item(12629), player);
player.getDialogueInterpreter().sendItemMessage(12629, "You find a pair of safety gloves.");
} else {
player.getDialogueInterpreter().sendDialogue("You already have a pair of safety gloves.");
}
}
return true;
}
return true;
case 29730:// lever
case 29731:// level down
if (!locked) {
player.sendMessage("You hear cogs and gears moving and the sound of heavy locks falling into place.");
config = (1 << 29);
} else {
player.sendMessage("You hear the cogs and gears moving and a distant unlocking sound.");
config += (1 << 26);
}
setVarp(player, 1203, config, true);
return true;
case 29624:
if (locked) {
player.sendMessage("The door seems to be locked by some kind of mechanism.");
} else {
if (player.getLocation().getZ() == 2) {
player.teleport(new Location(3177, 4266, 0));
} else {
player.teleport(new Location(3177, 4269, 2));
}
}
return true;
case 29729:
player.teleport(new Location(3078, 3463, 0));
return true;
case 29623:
player.teleport(new Location(3077, 4235, 0));
return true;
case 29735:
player.getDialogueInterpreter().sendDialogue("There appears to be a tunnel behind the poster.");
player.getDialogueInterpreter().addAction(new DialogueAction() {
@Override
public void handle(Player player, int buttonId) {
player.teleport(new Location(3140, 4230, 2));
}
});
return true;
case 29732:
if (!player.getSavedData().getGlobalData().hasReadPlaques()) {
player.sendMessage("This door is locked.");
} else {
DoorActionHandler.handleAutowalkDoor(player, node.asScenery());
}
return true;
case 29728:
if (player.getSavedData().getGlobalData().getTestStage() < 3) {
player.sendMessage("You need to complete the player safety test first.");
return true;
}
player.teleport(new Location(3158, 4280, 3));
return true;
}
if (node instanceof Scenery) {
Scenery object = (Scenery) node;
JailPlaques plaque = forId(object.getId());
if (plaque != null) {
plaque.read(player, object);
return true;
} else if (object.getId() == JAIL_ENTRANCE_ID_ENTER || object.getId() == JAIL_ENTRANCE_LEAVE) {
player.getProperties().setTeleportLocation(object.getId() == JAIL_ENTRANCE_ID_ENTER ? JAIL_ENTRANCE_LOCATION_ENTER : JAIL_ENTRANCE_LOCATION_LEAVE);
return true;
} else if (object.getId() == JAIL_STAIRS_UP || object.getId() == JAIL_STAIRS_DOWN) {
if (!player.getSavedData().getGlobalData().hasReadPlaques() && object.getId() != JAIL_STAIRS_DOWN) {
player.getPacketDispatch().sendMessage("You need to read the jail plaques before the guard will allow you upstairs.");
return true;
}
player.getProperties().setTeleportLocation(object.getId() == JAIL_STAIRS_UP ? JAIL_UP_STAIRS : JAIL_DOWN_STAIRS);
return true;
}
} else if (node instanceof Item) {
Item item = (Item) node;
if (player.getSavedData().getGlobalData().getTestStage() >= 2) {
player.sendMessage("You have already completed the test!");
return true;
}
if (item.getId() == TEST_PAPER_ITEM_ID) {
player.removeAttribute("s-stage");
player.getDialogueInterpreter().open("player_safety", node.getId());
return true;
}
}
return false;
}
}

View file

@ -1,269 +0,0 @@
package content.region.misthalin.barbvillage.stronghold.playersafety;
import core.game.component.Component;
import core.game.component.ComponentPlugin;
import core.game.dialogue.DialogueInterpreter;
import core.game.dialogue.DialoguePlugin;
import core.game.node.entity.player.Player;
import core.plugin.Plugin;
/**
* Handles the player safety test.
* @author Tyler Telis
* @author Vexia
*/
public class PlayerSafetyTest extends DialoguePlugin {
/**
* The check box button ids.
*/
public static int ANSWER_1 = 3, ANSWER_2 = 4, ANSWER_3 = 12;
/**
* Constructs a new {@Code PlayerSafetyTest} {@Code Object}
* @param player the player.
*/
public PlayerSafetyTest(Player player) {
super(player);
}
/**
* Constructs a new {@code PlayerSafetyTest} instance.
*/
public PlayerSafetyTest() {
}
@Override
public DialoguePlugin newInstance(Player player) {
return new PlayerSafetyTest(player);
}
@Override
public boolean open(Object... args) {
stage = player.getAttribute("s-stage", 0);
if (args.length >= 2) {
handleQuiz(Integer.parseInt(String.valueOf(args[1])));
} else {
stage = 0;
sendTest();
}
return true;
}
/**
* Sends the test.
*/
public void sendTest() {
Component component = getComponentForStage(stage);
component.setPlugin(new ComponentPlugin() {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
return this;
}
@Override
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
if (player == null) {
return false;
}
if (player.getDialogueInterpreter().getDialogue() == null) {
player.getDialogueInterpreter().open(DialogueInterpreter.getDialogueKey("player_safety"), "reopen", button);
}
if (player.getDialogueInterpreter().getDialogue() == null) {
return false;
}
return player.getDialogueInterpreter().getDialogue().handle(component.getId(), button);
}
});
player.getInterfaceManager().open(component);
}
@Override
public boolean handle(int interfaceId, int buttonId) {
return handleQuiz(buttonId);
}
private boolean handleQuiz(int buttonId) {
if (buttonId == 48 || buttonId == 39 || buttonId == 40) {
if (stage >= TestQuestions.values().length) {
player.getInterfaceManager().close();
player.getSavedData().getGlobalData().setTestStage(2);
player.sendMessage("Well done! You completed the exams.");
player.getDialogueInterpreter().sendDialogue("Congratulations! The test has been completed. Hand the paper in to", "Professor Henry for marking.");
return false;
} else {
sendTest();
}
return true;
}
if (stage == TestQuestions.values().length) {// Last question.
player.getDialogueInterpreter().getDialogue().end();
return true;
}
if (forStage(stage).answer(player, buttonId)) {
return true;
}
return true;
}
@Override
public boolean close() {
player.setAttribute("s-stage", stage);
return super.close();
}
/**
* A test question.
* @author Tyler Tellis
*/
public enum TestQuestions {
QUESTION_1(697, ANSWER_2) {
@Override
public void showAnswer(Player player, boolean correct, int interfaceId) {
player.getPacketDispatch().sendInterfaceConfig(interfaceId, 26, false);
player.getPacketDispatch().sendInterfaceConfig(interfaceId, correct ? 37 : 43, false);
}
},
QUESTION_2(699, ANSWER_2) {
@Override
public void showAnswer(Player player, boolean correct, int interfaceId) {
player.getPacketDispatch().sendInterfaceConfig(interfaceId, 20, false);
player.getPacketDispatch().sendInterfaceConfig(interfaceId, correct ? 31 : 34, false);
}
},
QUESTION_3(707, ANSWER_1) {
@Override
public void showAnswer(Player player, boolean correct, int interfaceId) {
player.getPacketDispatch().sendInterfaceConfig(interfaceId, 20, false);
player.getPacketDispatch().sendInterfaceConfig(interfaceId, correct ? 31 : 35, false);
}
},
QUESTION_4(710, 9) {
@Override
public void showAnswer(Player player, boolean correct, int interfaceId) {
player.getPacketDispatch().sendInterfaceConfig(interfaceId, 20, false);
player.getPacketDispatch().sendInterfaceConfig(interfaceId, correct ? 31 : 34, false);
}
},
QUESTION_5(704, 10) {
@Override
public void showAnswer(Player player, boolean correct, int interfaceId) {
player.getPacketDispatch().sendInterfaceConfig(interfaceId, 26, false);
player.getPacketDispatch().sendInterfaceConfig(interfaceId, correct ? 37 : 40, false);
}
},
QUESTION_6(694, 10) {
@Override
public void showAnswer(Player player, boolean correct, int interfaceId) {
player.getPacketDispatch().sendInterfaceConfig(interfaceId, 20, false);
player.getPacketDispatch().sendInterfaceConfig(interfaceId, correct ? 31 : 34, false);
}
},
QUESTION_8(696, 4) {
@Override
public void showAnswer(Player player, boolean correct, int interfaceId) {
player.getPacketDispatch().sendInterfaceConfig(interfaceId, 20, false);
player.getPacketDispatch().sendInterfaceConfig(interfaceId, correct ? 31 : 34, false);
}
};
/**
* The interface id.
*/
private int interfaceId;
/**
* The correct button id to click.
*/
private int correctButton;
/**
* Constructs a new {@Code TestQuestions} {@Code Object}
* @param interfaceId the interface.
* @param correctButton the button.
*/
private TestQuestions(int interfaceId, int correctButton) {
this.interfaceId = interfaceId;
this.correctButton = correctButton;
}
/**
* Answers a question.
* @param player the player.
* @param buttonId the button id.
* @return {@code True} if so.
*/
public boolean answer(Player player, int buttonId) {
boolean correct = buttonId == correctButton;
if (interfaceId == 710 && buttonId == 9) {
correct = true;
} else if (interfaceId == 704 && buttonId == 10) {
correct = true;
} else if (interfaceId == 696 && buttonId == 4) {
correct = true;
}
showAnswer(player, correct, interfaceId);
if (correct) {
player.getDialogueInterpreter().getDialogue().increment();
}
return player.getInterfaceManager().getComponent(interfaceId) != null;
}
/**
* Shows the answer.
* @param player the player.
* @param correct the correct.
* @param interfaceId the id.
*/
public abstract void showAnswer(Player player, boolean correct, int interfaceId);
/**
* Gets the value.
* @return the value.
*/
public int value() {
return ordinal();
}
/**
* Gets the inter id.
* @return the id.
*/
public int getInterfaceId() {
return interfaceId;
}
/**
* Gets the correct button.
* @return the button.
*/
public int getCorrectButton() {
return correctButton;
}
}
@Override
public int[] getIds() {
return new int[] { DialogueInterpreter.getDialogueKey("player_safety") };
}
/**
* Gets a new component for the stage.
* @param stage The stage;
* @return The {@code Component} instance.
*/
public static Component getComponentForStage(int stage) {
return new Component(forStage(stage).getInterfaceId());
}
/**
* Gets it for the stage.
* @param stage the stage.
* @return the question.
*/
public static TestQuestions forStage(int stage) {
return TestQuestions.values()[stage];
}
}

View file

@ -0,0 +1,102 @@
package content.region.misthalin.barbvillage.stronghold.playersafety
import core.api.*
import core.game.interaction.InterfaceListener
import core.game.node.entity.player.Player
import core.plugin.Initializable
// /**
// * Handles the player safety test.
// * Java version
// * @author Tyler Telis
// * @author Vexia
// * Kotlin
// * @author gregf36665
// */
@Initializable
class PlayerSafetyTest : InterfaceListener {
companion object {
private val testQuestions = listOf(
TestQuestion(697, 26, mapOf(4 to 37, 3 to 40, 5 to 43), 4),
TestQuestion(699, 20, mapOf(4 to 31, 3 to 34), 4),
TestQuestion(707, 20, mapOf(3 to 31, 4 to 35, 5 to 35), 3),
TestQuestion(710, 20, mapOf(9 to 31, 10 to 34), 9),
TestQuestion(704, 26, mapOf(10 to 37, 12 to 43, 11 to 40), 10),
// todo figure out why these 2 are not working
// TestQuestion(694, 20, mapOf(12 to 31, 13 to 34), 13),
// TestQuestion(708, 26, mapOf(12 to 31, 13 to 34), 12),
TestQuestion(696, 20, mapOf(4 to 31, 3 to 34, 5 to 34), 4)
)
private var testQuestionNumber = 0
}
/**
* Define a new Test Question
* interfaceId: the base ID for the test question
* baseChild: the ID of the Component child
* answers: A map of button press: child to display
* correctOption: The button number for the correct option
*/
class TestQuestion(val interfaceId: Int, val baseChild : Int, val answers : Map<Int, Int>, val correctOption: Int){
fun showAnswer(player: Player, button : Int){
setComponentVisibility(player, interfaceId, baseChild, false)
answers[button]?.let { setComponentVisibility(player, interfaceId, it, false) }
return
}
}
private fun checkAnswer(player: Player, button: Int){
val question = testQuestions[testQuestionNumber]
question.showAnswer(player, button)
if (button == question.correctOption){
testQuestionNumber += 1
}
}
private fun completedTest(player: Player) {
closeInterface(player)
player.savedData.globalData.testStage = 2
sendMessage(player,"Well done! You completed the exams.")
sendDialogue(player, "Congratulations! The test has been completed. " +
"Hand the paper in to Professor Henry for marking.")
}
fun update(player: Player){
// Close all open interfaces
closeInterface(player)
// Open the correct one now
testQuestions.forEachIndexed(){ index, testQuestion ->
if (index == testQuestionNumber){
openInterface(player, testQuestion.interfaceId)
}
}
}
override fun defineInterfaceListeners() {
onOpen(697) { _, _ ->
testQuestionNumber = 0 // Set the testQuestionNumber back to 0 on first launch
return@onOpen true
}
for (question in testQuestions){
on(question.interfaceId) { player, _, _, buttonID, _, _ ->
if (buttonID in 0..35) {
checkAnswer(player, buttonID)
}
else{
update(player)
if (testQuestionNumber == testQuestions.size) {
completedTest(player)
return@on true
}
}
return@on true
}
}
}
}

View file

@ -1,221 +0,0 @@
package content.region.misthalin.barbvillage.stronghold.playersafety;
import core.ServerConstants;
import core.api.Container;
import core.game.component.Component;
import core.game.node.entity.player.link.emote.Emotes;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import org.rs09.consts.Items;
import static core.api.ContentAPIKt.*;
/**
* @author Tyler Telis
*/
public class ProfessorHenryDialogue extends DialoguePlugin {
/**
* Constructs a new {@code ProfessorHenryDialogue} instance.
* @param player The {@code Player} instance.
*/
public ProfessorHenryDialogue(Player player) {
super(player);
}
/**
* Constructs a new {@code ProfessorHenryDialogue} instance.
*/
public ProfessorHenryDialogue() {
}
@Override
public DialoguePlugin newInstance(Player player) {
return new ProfessorHenryDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
stage = 0;
if (player.getSavedData().getGlobalData().getTestStage() == 2 && player.getInventory().contains(12626, 1)) {
player("Hello, Professor.");
stage = 900;
return true;
}
if (player.getSavedData().getGlobalData().getTestStage() >= 3) {
npc("Good job " + player.getUsername() + " you completed the test!");
stage = 800;
return true;
}
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "Hello.");
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 800:
end();
break;
case 900:
npc("Ah, " + player.getUsername() + ". How's the test going?");
stage++;
break;
case 901:
player("I think I've finished.");
stage++;
break;
case 902:
npc("Excellent! Let me just mark the paper for you then.");
stage++;
break;
case 903:
npc("Hmm. Uh-huh, yes I see. Good! Yes, that's right.");
stage++;
break;
case 904:
npc("Excellent! Allow me to reward you for your work. I", "have these two old lamps that you may find useful.");
stage++;
break;
case 905:
npc("Also, there is an old jail block connected to the cells", "below the training centre, which have been overrun with", "vicious creatures. If you search around the jail cells", "downstairs, you should find it easily enough.");
stage++;
break;
case 906:
npc("Now, your rewards.");
stage++;
break;
case 907:
if (player.getInventory().freeSlots() == 0) {
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "It seems your inventory is full.");
stage = -1;
return false;
}
if (removeItem(player, Items.TEST_PAPER_12626, Container.INVENTORY)) {
showReward(player);
end();
}
break;
case -1:
end();
break;
case 0:
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "Hello what?");
increment();
break;
case 1:
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "Uh...hello there?");
increment();
break;
case 2:
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "Hello, 'Professor'. Manners cost nothing, you know.", "When you're in my classroom, I ask that you use the", "proper address for my station.");
increment();
break;
case 3:
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "Your station?");
increment();
break;
case 4:
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "Yes. It means 'position', so to speak.");
increment();
break;
case 5:
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "Oh, okay.");
increment();
break;
case 6:
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "Now, what can I do for you, exactly?");
increment();
break;
case 7:
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "What is this place?");
increment();
break;
case 8:
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "This is the Misthalin Training Centre of Ezcelience. It", "is where bold adventurers, such as yourself, can come", "to learn of the dangers of the wide world and gain", "some valuable experience at the same time.");
increment();
break;
case 9:
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "What can I do here?");
increment();
break;
case 10:
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "Here you can take part in the Player Safety test: a set", "of valuable lessons to learn about staying safe in ", ServerConstants.SERVER_NAME + ".");
increment();
break;
case 11:
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "I can give you a test paper to take and, once", "completed, you can bring it back to me for marking.", "Would you like to take the test?", "It will not cost you anything");
increment();
break;
case 12:
interpreter.sendOptions("Select an Option", "Yes, please", "Not right now, thanks.");
increment();
break;
case 13:
if (buttonId == 1) {
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "Yes, please.");
increment();
} else if (buttonId == 2) {
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "Not right now, thanks.");
stage = -1;
}
break;
case 14:
if (player.getInventory().freeSlots() == 0) {
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "It seems your inventory is full.");
stage = -1;
return false;
} else if (player.getInventory().containItems(StrongHoldOfPlayerSafetyPlugin.TEST_PAPER_ITEM_ID)) {
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "You already have a test, please fill it out", "and return it to me.");
stage = -1;
return false;
}
player.getSavedData().getGlobalData().setTestStage(1);
player.getInventory().add(new Item(StrongHoldOfPlayerSafetyPlugin.TEST_PAPER_ITEM_ID));
sendNormalDialogue(npc, FacialExpression.HALF_GUILTY, "Right then. Here is the test paper. When you have", "completed all the questions, bring it back to me for", "marking.");
increment();
break;
case 15:
sendNormalDialogue(player, FacialExpression.HALF_GUILTY, "Okay, thanks.");
stage = -1;
break;
}
return false;
}
/**
* Shows the reward for the player.
* @param player the player.
*/
private void showReward(Player player) {
setVarp(player, 1203, 1 << 29, true);
player.getSavedData().getGlobalData().setTestStage(3);
player.getQuestRepository().syncronizeTab(player);
player.getInterfaceManager().open(new Component(277));
for (int i = 9; i < 18; i++) {
player.getPacketDispatch().sendString("", 277, i);
}
player.getPacketDispatch().sendString("You have completed the Player Safety test!", 277, 4);
player.getPacketDispatch().sendString("2 Experience lamps", 277, 9);
player.getPacketDispatch().sendString("Access to the Stronghold of", 277, 10);
player.getPacketDispatch().sendString("Player Safety Dungeon", 277, 11);
player.getPacketDispatch().sendString("The Safety First' emote", 277, 12);
player.getPacketDispatch().sendString(player.getQuestRepository().getPoints() + "", 277, 7);
player.getPacketDispatch().sendItemZoomOnInterface(12626, 240, 277, 5);
if (!player.hasItem(new Item(4447, 2))) {
player.getInventory().add(new Item(4447, 2), player);
}
player.getEmoteManager().unlock(Emotes.SAFETY_FIRST);
}
@Override
public int[] getIds() {
return new int[] { 7143 };
}
}

View file

@ -0,0 +1,144 @@
package content.region.misthalin.barbvillage.stronghold.playersafety
import core.ServerConstants
import core.api.*
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.dialogue.Topic
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.emote.Emotes
import core.plugin.Initializable
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import org.rs09.consts.Items
import org.rs09.consts.NPCs
@Initializable
class ProfessorHenryDialogue(player : Player? = null) : DialoguePlugin(player){
companion object{
const val HAND_IN_TEST = 10
const val MEETING = 100
const val GET_TEST = 200
const val iFace = 277
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage){
START_DIALOGUE -> {
if (player.savedData.globalData.testStage == 2 && inInventory(player, Items.TEST_PAPER_12626)){
// The player has the test and has completed it but need it marked
player("Hello, Professor.").also { stage = HAND_IN_TEST}
}
else if (player.savedData.globalData.testStage >= 3){
// The player has already had their test marked and taken
npcl(FacialExpression.HAPPY, "Good job ${player.name}, you completed the test!").also { stage = END_DIALOGUE }
return true
}
else{
player(FacialExpression.NEUTRAL, "Hello.").also { stage = MEETING }
}
}
MEETING -> npcl(FacialExpression.ANNOYED, "Hello what?").also { stage++ }
MEETING + 1 -> playerl(FacialExpression.HALF_GUILTY, "Uh...hello there?").also { stage++ }
MEETING + 2 -> npcl(FacialExpression.HALF_GUILTY, "Hello, 'Professor'. Manners cost nothing, you know. " +
"When you're in my classroom, I ask that you use the proper address for my station.").also { stage++ }
MEETING + 3 -> playerl(FacialExpression.HALF_GUILTY, "Your station?").also { stage++ }
MEETING + 4 -> npcl(FacialExpression.HALF_GUILTY, "Yes. It means 'position', so to speak.").also { stage++ }
MEETING + 5 -> playerl(FacialExpression.HALF_GUILTY, "Oh, okay.").also { stage++ }
MEETING + 6 -> npcl(FacialExpression.HALF_GUILTY, "Now, what can I do for you, exactly?").also { stage++ }
MEETING + 7 -> playerl(FacialExpression.HALF_GUILTY, "What is this place?").also { stage++ }
MEETING + 8 -> npcl(FacialExpression.HALF_GUILTY, "This is the Misthalin Training Centre of Excellence. " +
"It is where bold adventurers, such as yourself, can come to learn of the dangers of " +
"the wide world and gain some valuable experience at the same time.").also { stage++ }
MEETING + 9 -> playerl(FacialExpression.HALF_GUILTY, "What can I do here?").also { stage++ }
MEETING + 10 -> npcl(FacialExpression.HALF_GUILTY, "Here you can take part in the Player Safety test: " +
"a set of valuable lessons to learn about staying safe " +
"in ${ServerConstants.SERVER_NAME}.").also { stage++ }
MEETING + 11 -> npcl(FacialExpression.HALF_GUILTY, "I can give you a test paper to take and, once completed, " +
"you can bring it back to me for marking. Would you like to take the test? " +
"It will not cost you anything.").also { stage++ }
MEETING + 12 ->
showTopics(
Topic("Yes, please.", GET_TEST),
Topic("Not right now, thanks.", END_DIALOGUE)
)
GET_TEST -> {
if (player.inventory.isFull) {
npcl(FacialExpression.HALF_GUILTY, "It seems your inventory is full.").also { stage = END_DIALOGUE }
} else if (amountInInventory(player, Items.TEST_PAPER_12626) > 0) {
npcl(
FacialExpression.HALF_GUILTY,
"You already have a test, please fill it out and return it to me."
).also { stage = END_DIALOGUE }
} else {
player.savedData.globalData.testStage = 1
addItem(player, Items.TEST_PAPER_12626)
npcl( FacialExpression.HALF_GUILTY, "Right then. Here is the test paper. " +
"When you have completed all the questions, bring it back to me for marking."
).also { stage ++ }
}
}
GET_TEST + 1 -> playerl(FacialExpression.HALF_GUILTY, "Okay, thanks.").also { stage = END_DIALOGUE }
HAND_IN_TEST -> npcl(FacialExpression.HAPPY,
"Ah, ${player.name}. How's the test going?").also { stage ++ }
HAND_IN_TEST + 1 -> playerl(FacialExpression.NEUTRAL, "I think I've finished.").also { stage++ }
HAND_IN_TEST + 2 -> npcl(FacialExpression.HAPPY, "Excellent! Let me just mark the paper for you then.").also { stage++ }
HAND_IN_TEST + 3 -> npcl(FacialExpression.HAPPY, "Hmm. Uh-huh, yes I see. Good! Yes, that's right.").also{ stage++ }
HAND_IN_TEST + 4-> npcl(FacialExpression.HAPPY, "Excellent! Allow me to reward you for your work. " +
"I have these two old lamps that you may find useful.").also { stage++ }
// This needs to be npc for word wrap
HAND_IN_TEST + 5 -> npc("Also, there is an old jail block connected to the cells",
"below the training centre, which have been overrun with",
"vicious creatures. If you search around the jail cells",
"downstairs, you should find it easily enough.").also { stage++ }
HAND_IN_TEST + 6 -> npcl(FacialExpression.HAPPY, "Now, your rewards.").also { stage++ }
HAND_IN_TEST + 7 ->{
// Check for at least 1 slot
// Player will get 2 lamps but we will take the test from them
if (freeSlots(player) >= 1){
showReward().also { stage = END_DIALOGUE }
}
else {
npcl(FacialExpression.SAD, "You do not have space in your inventory for the rewards").also { stage = END_DIALOGUE }
}
}
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.PROFESSOR_HENRY_7143)
}
private fun showReward(){
// Show the poster tunnel
setVarp(player, 1203, 1 shl 29, true)
player.savedData.globalData.testStage = 3
removeItem(player, Items.TEST_PAPER_12626)
addItem(player, Items.ANTIQUE_LAMP_4447, 2)
player.emoteManager.unlock(Emotes.SAFETY_FIRST)
openInterface(player, iFace)
// Clear the other lines
for (i in 9.. 18){
player.packetDispatch.sendString("", iFace, i)
}
player.packetDispatch.sendString("You have completed the Player Safety test!", iFace, 4)
player.packetDispatch.sendString(player.getQuestRepository().points.toString() + "", iFace, 7)
player.packetDispatch.sendString("2 Experience lamps", iFace, 9)
player.packetDispatch.sendString("Access to the Stronghold of", iFace, 10)
player.packetDispatch.sendString("Player Safety Dungeon", iFace, 11)
player.packetDispatch.sendString("The Safety First' emote", iFace, 12)
sendItemZoomOnInterface(player, iFace, 5, Items.TEST_PAPER_12626)
}
}

View file

@ -1,15 +0,0 @@
package content.region.misthalin.barbvillage.stronghold.playersafety;
import core.game.world.map.zone.MapZone;
public class SafetyMapZone extends MapZone {
public SafetyMapZone() {
super("strong hold of player safety", true);
}
@Override
public void configure() {
}
}

View file

@ -0,0 +1,333 @@
package content.region.misthalin.barbvillage.stronghold.playersafety
import core.api.*
import core.game.activity.Cutscene
import core.game.component.Component
import core.game.global.action.DoorActionHandler
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.interaction.InterfaceListener
import core.game.node.Node
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.emote.Emotes
import core.game.node.scenery.Scenery
import core.game.world.map.Location
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery as SceneryConst
@Suppress("unused")
class StrongHoldOfPlayerSafetyListener : InteractionListener{
companion object{
private val plaquesToIface = mapOf( // Door to interface
SceneryConst.JAIL_DOOR_29595 to 701,
SceneryConst.JAIL_DOOR_29596 to 703,
SceneryConst.JAIL_DOOR_29597 to 711,
SceneryConst.JAIL_DOOR_29598 to 695,
SceneryConst.JAIL_DOOR_29599 to 312,
SceneryConst.JAIL_DOOR_29600 to 706,
SceneryConst.JAIL_DOOR_29601 to 698,
)
private val creviceClimbedAttribute = "player_strong:crevice_climbed"
}
override fun defineListeners() {
// Test
on(Items.TEST_PAPER_12626, IntType.ITEM, "take exam") { player, _ ->
if (player.savedData.globalData.testStage == 2){
sendMessage(player, "You have already completed the test. Hand it in to Professor Henry for marking.")
}
else{
openInterface(player, 697)
}
return@on true
}
// Students
on(intArrayOf(NPCs.STUDENT_7151, NPCs.STUDENT_7152, NPCs.STUDENT_7153, NPCs.STUDENT_7154,
NPCs.STUDENT_7155, NPCs.STUDENT_7156, NPCs.STUDENT_7157), IntType.NPC, "Talk-to") { player, _ ->
sendMessage(player, "This student is trying to focus on their work.")
return@on true
}
// Jail teleports
on(SceneryConst.JAIL_ENTRANCE_29603, IntType.SCENERY, "use") { player, _->
teleport(player, Location.create(3082, 4229, 0))
return@on true
}
on(SceneryConst.JAIL_ENTRANCE_29602, IntType.SCENERY, "leave") { player, _ ->
teleport(player, Location.create(3074, 3456, 0))
return@on true
}
on(SceneryConst.STAIRS_29589, IntType.SCENERY, "climb-up") { player, _ ->
if (player.globalData.hasReadPlaques()){
teleport(player, Location.create(3083, 3452, 0))
}
else{
sendMessage(player, "You need to read the jail plaques before the guard will allow you upstairs")
}
return@on true
}
// Exam room
on(SceneryConst.DOOR_29732, IntType.SCENERY, "open") { player, node ->
if (player.globalData.testStage > 0){
// The player has talked to the prof
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
}
else{
sendMessage(player, "The door is locked")
}
return@on true
}
on(SceneryConst.STAIRS_29592, IntType.SCENERY, "climb-down") { player, _ ->
teleport(player, Location.create(3086, 4247, 0))
return@on true
}
// crevice (and rope)
on(SceneryConst.CREVICE_29728, IntType.SCENERY, "enter"){ player, _ ->
if (getAttribute(player, creviceClimbedAttribute, false)){
teleport(player, Location.create(3159, 4279, 3))
}
else{
// todo find what the crevice should say
sendMessage(player, "There's no way down")
}
return@on true
}
on(SceneryConst.ROPE_29729, IntType.SCENERY, "climb"){ player, _ ->
if (!getAttribute(player, creviceClimbedAttribute, false)){
setAttribute(player, creviceClimbedAttribute, true)
}
teleport(player, Location.create(3077, 3462, 0))
return@on true
}
// Plaques
on(intArrayOf(SceneryConst.JAIL_DOOR_29595, SceneryConst.JAIL_DOOR_29596, SceneryConst.JAIL_DOOR_29597,
SceneryConst.JAIL_DOOR_29598, SceneryConst.JAIL_DOOR_29599, SceneryConst.JAIL_DOOR_29600,
SceneryConst.JAIL_DOOR_29601) , IntType.SCENERY, "Read-plaque on") { player, node ->
read(player, node)
return@on true
}
// The dungeon
on(SceneryConst.POSTER_29586, IntType.SCENERY, "pull-back") { player, _ ->
sendDialogue(player, "There appears to be a tunnel behind this poster.")
teleport(player, Location.create(3140, 4230, 2))
return@on true
}
on(SceneryConst.TUNNEL_29623, IntType.SCENERY, "use") {player, _ ->
teleport(player, Location.create(3077, 4235, 0))
return@on true
}
on(SceneryConst.AN_OLD_LEVER_29730, IntType.SCENERY, "pull") {player, _ ->
sendMessage(player, "You hear the cogs and gears moving and a distant unlocking sound.")
setVarp(player, 1203, (1 shl 29) or (1 shl 26), true)
return@on true
}
on(SceneryConst.AN_OLD_LEVER_29731, IntType.SCENERY, "pull") {player, _ ->
sendMessage(player, "You hear cogs and gears moving and the sound of heavy locks falling into place.")
setVarp(player, 1203, 1 shl 29, true)
return@on true
}
// the same jail door is used in 4 different places
on(SceneryConst.JAIL_DOOR_29624, IntType.SCENERY, "open") { player, _ ->
if (getVarp(player, 1203) and (1 shl 26) == 0) {
// The door is locked
sendMessage(player, "The door seems to be locked by some kind of mechanism.")
return@on true
}
if (player.location.z == 2) {
// Floor 2 to hidden tunnel
teleport(player, Location.create(3177, 4266, 0))
}
else if (player.location.z == 1){
// Floor 1 to hidden tunnel
teleport(player, Location.create(3143, 4270, 0))
}
else {
// Leaving the hidden tunnel
if (player.location.x < 3150){
// Leaving by the west exit (to floor 1)
teleport(player, Location.create(3142, 4272, 1))
}
else{
// Must be exiting by the east exit (to floor 2)
teleport(player, Location.create(3177, 4269, 2))
}
}
return@on true
}
// the 4 stairs in the middle of the 1st/2nd floor
// NE
on(SceneryConst.STAIRS_29667, IntType.SCENERY, "climb-down") { player, _ ->
teleport(player, Location.create(3160, 4249, 1))
return@on true
}
on(SceneryConst.STAIRS_29668, IntType.SCENERY, "climb-up") { player, _ ->
teleport(player, Location.create(3158, 4250, 2))
return@on true
}
// SE
on(SceneryConst.STAIRS_29663, IntType.SCENERY, "climb-down") { player, _ ->
teleport(player, Location.create(3160, 4246, 1))
return@on true
}
on(SceneryConst.STAIRS_29664, IntType.SCENERY, "climb-up") { player, _ ->
teleport(player, Location.create(3158, 4245, 2))
return@on true
}
// SW
on(SceneryConst.STAIRS_29655, IntType.SCENERY, "climb-down") { player, _ ->
teleport(player, Location.create(3146, 4246, 1))
return@on true
}
on(SceneryConst.STAIRS_29656, IntType.SCENERY, "climb-up") { player, _ ->
teleport(player, Location.create(3149, 4244, 2))
return@on true
}
// NW
on(SceneryConst.STAIRS_29659, IntType.SCENERY, "climb-down") { player, _ ->
teleport(player, Location.create(3146, 4249, 1))
return@on true
}
on(SceneryConst.STAIRS_29660, IntType.SCENERY, "climb-up") { player, _ ->
teleport(player, Location.create(3148, 4250, 2))
return@on true
}
// rewards chest
on(SceneryConst.TREASURE_CHEST_29577, IntType.SCENERY, "open"){ player, _ ->
setVarbit(player, 4499, 1, true)
return@on true
}
on(SceneryConst.TREASURE_CHEST_29578, IntType.SCENERY, "search"){ player, _ ->
// Give the player rewards
if (player.globalData.testStage == 3){
// Check the player has enough slots
if ((freeSlots(player) == 0) or
((freeSlots(player) == 1) and !inInventory(player, Items.COINS_995))){
sendDialogue(player, "You do not have enough inventory space!")
}
else{
player.emoteManager.unlock(Emotes.SAFETY_FIRST)
addItem(player, Items.COINS_995, 1000)
addItem(player, Items.SAFETY_GLOVES_12629)
sendItemDialogue(player, Items.SAFETY_GLOVES_12629,
"You open the chest to find a large pile of gold, along with a pair of safety gloves. ")
player.globalData.testStage = 4
}
}
else {
// The player may have lost their gloves
if (hasAnItem(player, Items.SAFETY_GLOVES_12629).exists()){
sendDialogue(player, "The chest is empty")
}
else{
if (freeSlots(player) == 0){
sendDialogue(player, "You do not have enough inventory space!")
}
else {
addItem(player, Items.SAFETY_GLOVES_12629)
sendItemDialogue(
player, Items.SAFETY_GLOVES_12629,
"You open the chest to find a pair of safety gloves. "
)
}
}
}
return@on true
}
}
fun read(player: Player, plaque: Node){
if (plaque !is Scenery) return
player.interfaceManager.openChatbox(plaquesToIface[plaque.id]!!)
}
class PlaqueListener : InterfaceListener {
var scene : PlaqueCutscene? = null
override fun defineInterfaceListeners() {
for ((index, iface) in plaquesToIface.values.withIndex()){
onClose(iface){ player, _ ->
scene?.end(fade = false)
player.globalData.readPlaques[index] = true
return@onClose true
}
onOpen(iface) { player, component ->
scene = PlaqueCutscene(player, component)
scene?.start(hideMiniMap = false)
return@onOpen true
}
on(iface) { player, _, _, buttonID, _, _ ->
// If thumbs up is clicked
if (buttonID == 2){
scene?.incrementStage()
player.interfaceManager.closeChatbox()
}
return@on true
}
}
}
class PlaqueCutscene(player: Player, val component: Component): Cutscene(player) {
// Since the component does not know the door's location
// there needs to be some translation from player position
// to the door location. This is component -> rotation (dx, dy)
private val rotationMapping = mapOf(
701 to listOf(-1, 0),
703 to listOf(-1, 0),
711 to listOf(-1, 0),
695 to listOf(0, 1),
312 to listOf(1, 0),
706 to listOf(1, 0),
698 to listOf(1, 0),
)
override fun setup() {
setExit(player.location)
}
override fun runStage(stage: Int) {
when (stage){
0 -> {
// Go to head height
moveCamera(player.location.localX, player.location.localY, 245, speed = 50)
// Spin in the right direction
rotateCamera(player.location.localX + rotationMapping[component.id]!![0],
player.location.localY + rotationMapping[component.id]!![1],
245, speed = 50)
}
1 -> {
resetCamera()
}
}
}
}
}
}

View file

@ -1,211 +0,0 @@
package content.region.misthalin.barbvillage.stronghold.playersafety;
import core.game.component.CloseEvent;
import core.game.component.Component;
import core.game.component.ComponentPlugin;
import core.game.node.entity.player.Player;
import core.game.node.scenery.Scenery;
import core.game.world.map.Location;
import core.net.packet.PacketRepository;
import core.net.packet.context.CameraContext;
import core.net.packet.context.CameraContext.CameraType;
import core.net.packet.out.CameraViewPacket;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.ClassScanner;
/**
* @author Tyler Telis
*/
@Initializable
public class StrongHoldOfPlayerSafetyPlugin implements Plugin<Object> {
/**
* when u pull back the poster and the dialogue pops up
* you get teleported to this map tile: [3140, 4230, 2]
*/
/**
* The jail object ids.
*/
public static final int JAIL_ENTRANCE_ID_ENTER = 29603, JAIL_ENTRANCE_LEAVE = 29602, JAIL_STAIRS_UP = 29589, JAIL_STAIRS_DOWN = 29592;
/**
* The guard NPC id.
*/
public static final int GUARD_NPC_ID = 7142;
/**
* The test item id.
*/
public static final int TEST_PAPER_ITEM_ID = 12626;
/**
* The jail {@code Location}'s
*/
public static final Location JAIL_ENTRANCE_LOCATION_ENTER = Location.create(3082, 4229, 0), JAIL_ENTRANCE_LOCATION_LEAVE = Location.create(3074, 3456, 0), JAIL_UP_STAIRS = Location.create(3083, 3452, 0), JAIL_DOWN_STAIRS = Location.create(3086, 4247, 0);
@Override
public Plugin<Object> newInstance(Object object) throws Throwable {
ClassScanner.definePlugin(new PSOptionHandler());
ClassScanner.definePlugin(new GuardDialoguePlugin());
ClassScanner.definePlugin(new PlayerSafetyTest());
ClassScanner.definePlugin(new ProfessorHenryDialogue());
return this;
}
@Override
public Object fireEvent(String identifier, Object... object) {
return null;
}
public enum JailPlaques {
/**
* This sneaky gublinch wanted to set up a webcam conversation with a
* player! The player refused and sensibly used the Report Abuse button
* to enable us to catch him.
*/
PLAQUE_1(29599, 312),
/**
* This naughty gublinchette gave a player her email address. The wise
* player hit the Report Abuse button straight away, allowing us to
* catch her!
*/
PLAQUE_2(29598, 695),
/**
* This evil gublinch asked a younger player where she went to school.
* The player was smart enough to not tell the gublinch and report him
* instead.
*/
PLAQUE_3(29597, 711),
/**
* This vile gublinchette was asking a player for his home address. The
* clever player didn't give her their address, but used the Report
* Abuse button to report her instead.
*/
PLAQUE_4(29596, 703),
/**
* This sly gublinch wanted to meet one of his player friends in the
* real world. The player obviously refused and reported him straight
* away.
*/
PLAQUE_5(29600, 706),
/**
* This cheeky gublinch claimed to be a Jagex Moderator! He was reported
* straight away and dealt with.
*/
PLAQUE_6(29601, 698),
/**
* This wretched gublinch was asking a player for his telephone number.
* The player helped us catch him by refusing to give their information
* away and reporting the gublinch straight away!
*/
PLAQUE_7(29595, 701);
/**
* The object id & interface id.
*/
private int objectId, interfaceId;
/**
* Constructs a new {@code JailPlaques} instance.
* @param objectId The object id of the jail plague.
* @param interfaceId The interface id to send on the chat box.
*/
private JailPlaques(int objectId, int interfaceId) {
this.objectId = objectId;
this.interfaceId = interfaceId;
}
/**
* Gets the object id.
* @return objectId.
*/
public int getObjectId() {
return objectId;
}
/**
* Gets the interface id.
* @return interfaceId.
*/
public int getInterfaceId() {
return interfaceId;
}
/**
* Gets the value of the jail-plaque.
* @return The ordinal.
*/
public int value() {
return ordinal();
}
/**
* Sends the jail-plague interface.
* @param player The {@code Player} instance.
*/
public void read(Player player, Scenery object) {
int x = object.getLocation().getX();
int y = object.getLocation().getY();
int rotationX = x;
int rotationY = y;
Component component = new Component(interfaceId);
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.SET, x, y, 245, 1, 50));
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.ROTATION, rotationX, rotationY, 245, 1, 50));
player.getInterfaceManager().openChatbox(component);
component.setCloseEvent(new CloseEvent() {
@Override
public boolean close(Player player, Component c) {
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.RESET, 0, 0, 0, 1, 100));
if (!player.getSavedData().getGlobalData().getReadPlaques()[value()]) {
player.getSavedData().getGlobalData().getReadPlaques()[value()] = true;
}
return true;
}
});
component.setPlugin(new ComponentPlugin() {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
return this;
}
@Override
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
switch (button) {
case 2:
player.getInterfaceManager().closeChatbox();
player.getSavedData().getGlobalData().getReadPlaques()[value()] = true;
return true;
}
return false;
}
});
}
}
/**
* Find the {@link JailPlaques} instance for the object id.
* @param objectId The object id.
* @return The {@link JailPlaques} instance.
*/
public static JailPlaques forId(int objectId) {
for (JailPlaques plaque : JailPlaques.values()) {
if (plaque.getObjectId() == objectId) {
return plaque;
}
}
return null;
}
}

View file

@ -1,30 +0,0 @@
package content.region.misthalin.barbvillage.stronghold.playersafety;
import core.cache.def.impl.NPCDefinition;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Handles interactions with exam center students, to address #106
* @author ceik
*/
@Initializable
public class Student extends OptionHandler {
public Plugin<Object> newInstance(Object arg) throws Throwable {
NPCDefinition.forId(7153).getHandlers().put("option:talk-to",this);
NPCDefinition.forId(7154).getHandlers().put("option:talk-to",this);
NPCDefinition.forId(7155).getHandlers().put("option:talk-to",this);
NPCDefinition.forId(7156).getHandlers().put("option:talk-to",this);
NPCDefinition.forId(7157).getHandlers().put("option:talk-to",this);
return this;
}
public final boolean handle(Player player, Node node, String options){
if(options.equals("talk-to")){
player.getPacketDispatch().sendMessage("This student is trying to focus on their work.");
}
return true;
}
}

View file

@ -1,18 +0,0 @@
package content.region.misthalin.edgeville.handlers
import core.api.sendDialogue
import core.api.teleport
import core.game.world.map.Location
import org.rs09.consts.Scenery
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
class PosterListener : InteractionListener {
override fun defineListeners() {
on(Scenery.POSTER_29586, IntType.SCENERY, "pull-back") { player, _ ->
sendDialogue(player, "There appears to be a tunnel behind this poster.")
teleport(player, Location.create(3140, 4230, 2))
return@on true
}
}
}

View file

@ -223,13 +223,19 @@ abstract class Cutscene(val player: Player) {
logCutscene("Added NPC $id at location LOCAL[$regionX,$regionY,$plane] GLOBAL[${npc.location.x},${npc.location.y},$plane]") logCutscene("Added NPC $id at location LOCAL[$regionX,$regionY,$plane] GLOBAL[${npc.location.x},${npc.location.y},$plane]")
} }
fun start() fun start(){
start(true)
}
fun start(hideMiniMap: Boolean)
{ {
logCutscene("Starting cutscene for ${player.username}.") logCutscene("Starting cutscene for ${player.username}.")
region = RegionManager.forId(player.location.regionId) region = RegionManager.forId(player.location.regionId)
base = RegionManager.forId(player.location.regionId).baseLocation base = RegionManager.forId(player.location.regionId).baseLocation
setup() setup()
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2)) if (hideMiniMap) {
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2))
}
runStage(player.getCutsceneStage()) runStage(player.getCutsceneStage())
setAttribute(player, ATTRIBUTE_CUTSCENE, this) setAttribute(player, ATTRIBUTE_CUTSCENE, this)
setAttribute(player, ATTRIBUTE_CUTSCENE_STAGE, 0) setAttribute(player, ATTRIBUTE_CUTSCENE_STAGE, 0)
@ -244,24 +250,26 @@ abstract class Cutscene(val player: Player) {
/** /**
* Ends this cutscene, fading the screen to black, teleporting the player to the exit location, and then fading it back in and executing the endActions passed to this method. * Ends this cutscene, fading the screen to black, teleporting the player to the exit location, and then fading it back in and executing the endActions passed to this method.
* @param fade (optional) should the cutscene fade to black?
* @param endActions (optional) a method that executes when the cutscene fully completes * @param endActions (optional) a method that executes when the cutscene fully completes
*/ */
fun end(endActions: (() -> Unit)? = null) fun end(fade: Boolean = true, endActions: (() -> Unit)? = null)
{ {
ended = true ended = true
fadeToBlack() if (fade) fadeToBlack()
GameWorld.Pulser.submit(object : Pulse(){ GameWorld.Pulser.submit(object : Pulse(){
var tick: Int = 0 var tick: Int = 0
override fun pulse(): Boolean { override fun pulse(): Boolean {
when(tick++) if (fade) {
{ when (tick++) {
8 -> player.properties.teleportLocation = exitLocation 8 -> player.properties.teleportLocation = exitLocation
9 -> fadeFromBlack() 9 -> fadeFromBlack()
16 -> { 16 -> return true
return true else -> return false
} }
} }
return false else player.properties.teleportLocation = exitLocation
return true
} }
override fun stop() { override fun stop() {

View file

@ -821,8 +821,8 @@ public final class GlobalData {
} }
/** /**
* Gets the read plagues. * Gets the read plaques.
* @return The plague * @return The plaques
*/ */
public boolean[] getReadPlaques() { public boolean[] getReadPlaques() {
return readPlaques; return readPlaques;

View file

@ -606,6 +606,72 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
sendDialogue(player, "Wrong pin. Try again.") sendDialogue(player, "Wrong pin. Try again.")
} }
} }
define("setplayerstrong", Privilege.ADMIN, "setplayerstrong <0-4>",
"Set the player progress through the Stronghold of Player Safety test."){player, args ->
/*
* 0 = Not started
* 1 = Received test
* 2 = Completed test, needs to be marked
* 3 = Test marked
* 4 = Dungeon cleared
*/
if(args.size < 2){
notify(player, "Player Stronghold progression currently: ${player.savedData.globalData.testStage}")
return@define
}
val stage = args[1].toIntOrNull() ?: (-1).also { reject(player, "Please enter a valid number") }
if (stage in 0 .. 4){
player.savedData.globalData.testStage = stage
notify(player, "Setting test stage to $stage")
if (stage in 0..2){
setVarp(player, 1203, 0, true)
notify(player, "The poster passage is now hidden")
}
else{
setVarp(player, 1203, 1 shl 29, true)
notify(player, "The poster passage is now usable")
}
if (stage == 4){
setVarbit(player, 4499, 1,true)
notify(player, "The loot has been taken already")
}
else {
setVarbit(player, 4499, 0, true)
notify(player, "The loot can be reacquired")
}
}
else{
reject(player, "Only stages 0-4 are valid")
}
}
define("setplaqueread", Privilege.ADMIN, "setplaqueread <true/false>",
"Set the plaques in the player safety stronghold to read or not read."){player, args ->
if (args.size == 1) {
notify(
player,
"Currently the plaques ${if (player.savedData.globalData.hasReadPlaques()) "have" else "have not"} been read"
)
return@define
}
when(args[1]) {
"true" -> setPlaqueReadStatus(player, true)
"false" -> setPlaqueReadStatus(player, false)
else -> reject(player, "Only true or false can be used")
}
notify(player, "Setting plaques read to: ${args[1]}")
}
}
fun setPlaqueReadStatus(player: Player, status: Boolean){
// For some reason the loop has to be this way to have read write access
for (i in 0 until player.savedData.globalData.readPlaques.size){
player.savedData.globalData.readPlaques[i] = status
}
} }
fun showGeBotsearch(player: Player, searchTerm: String) fun showGeBotsearch(player: Player, searchTerm: String)