Rewrote entire banking system (aside from dialogue), converted to listener system

This commit is contained in:
vddcore
2022-06-23 13:31:17 +00:00
committed by Ryan
parent 40dd58d610
commit b094fe5b0c
32 changed files with 1420 additions and 827 deletions
+5
View File
@@ -1,5 +1,6 @@
builddir
logs
out/
Management-Server/target/*
Management-Server/.gradle
Management-Server/build/
@@ -11,6 +12,9 @@ Server/**/*.class
Server/build/
Server/.gradle/
Server/data/eco/grand_exchange_db.emp
Server/data/eco/grandexchange.db
Server/data/serverstore/
Server/data/global_kill_stats.json
Server/ge_test.db
Management-Server/managementprops/
Server/worldprops/
@@ -25,3 +29,4 @@ gradle
**/*.swp
**/*.swo
build/kotlin/sessions/
**/*.iml
@@ -91,7 +91,27 @@ public final class BankContainer extends Container {
return true;
});
player.getInterfaceManager().removeTabs(0, 1, 2, 3, 4, 5, 6);
InterfaceContainer.generateItems(player, player.getInventory().toArray(), new String[]{"Examine", "Deposit-X", "Deposit-All", "Deposit-10", "Deposit-5", "Deposit-1"}, 11, 15, 5, 7);
refreshDepositBoxInterface();
}
/**
* Invalidates the visual state of deposit box interface
* forcing the client to re-draw the items
*/
public void refreshDepositBoxInterface()
{
InterfaceContainer.generateItems(
player,
player.getInventory().toArray(),
new String[] {
"Examine",
"Deposit-X",
"Deposit-All",
"Deposit-10",
"Deposit-5",
"Deposit-1"
}, 11, 15, 5, 7
);
}
/**
@@ -498,6 +518,13 @@ public final class BankContainer extends Container {
*/
public void setTabIndex(int tabIndex) {
this.tabIndex = tabIndex;
/*
* Kludge to update the interface
* after dumping all to prevent
* "invisible" items in slots.
*/
update(true);
}
/**
@@ -1,6 +1,7 @@
package core.game.content.zone.phasmatys;
import static api.ContentAPIKt.*;
import core.game.content.global.Bones;
import core.game.content.global.action.ClimbActionHandler;
import core.game.interaction.Option;
@@ -22,6 +23,7 @@ import core.game.world.map.zone.ZoneBuilder;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
import org.rs09.consts.NPCs;
import rs09.plugin.ClassScanner;
/**
@@ -65,6 +67,13 @@ public final class PhasmatysZone extends MapZone implements Plugin<Object> {
player = e.asPlayer();
if (target instanceof NPC) {
NPC npc = (NPC) target;
if (npc.getId() == NPCs.GHOST_BANKER_1702) {
// Kludge to prevent this module from overriding NPC
// handling until I rip this piece of Vexia shit out.
return false;
}
if ((npc.getName().toLowerCase().contains("ghost") || npc.getName().equalsIgnoreCase("velorina") || npc.getName().contains("husband")) && !hasAmulet(player)) {
player.getDialogueInterpreter().open("ghosty dialogue", target);
return true;
@@ -1,44 +1,21 @@
package core.game.interaction.object;
import static api.ContentAPIKt.*;
import api.IfaceSettingsBuilder;
import api.events.InteractionEvent;
import core.cache.def.impl.NPCDefinition;
import core.cache.def.impl.SceneryDefinition;
import core.game.component.CloseEvent;
import core.game.component.Component;
import core.game.component.ComponentDefinition;
import core.game.component.ComponentPlugin;
import core.game.container.access.InterfaceContainer;
import core.game.content.dialogue.DialogueAction;
import core.game.content.dialogue.DialoguePlugin;
import core.game.content.dialogue.FacialExpression;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.npc.AbstractNPC;
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.appearance.Gender;
import core.game.node.entity.player.link.diary.DiaryType;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.system.task.Pulse;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
import kotlin.Unit;
import rs09.game.content.dialogue.DepositAllDialogue;
import rs09.game.ge.GrandExchangeRecords;
import rs09.game.ge.GrandExchangeOffer;
import rs09.game.ge.GrandExchangeRecords;
import rs09.game.world.GameWorld;
import java.text.NumberFormat;
/**
* Represents the plugin used for anything related to banking.
*
@@ -50,77 +27,15 @@ public final class BankingPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
SceneryDefinition.setOptionHandler("use-quickly", this);
SceneryDefinition.setOptionHandler("use", this);
SceneryDefinition.setOptionHandler("bank", this);
SceneryDefinition.setOptionHandler("collect", this);
SceneryDefinition.setOptionHandler("deposit", this);
new BankingInterface().newInstance(arg);
new BankDepositInterface().newInstance(arg);
new BankNPCPlugin().newInstance(arg);
new BankNPC().newInstance(arg);
new BankerDialogue().init();
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final Scenery object = (Scenery) node;
if (player.getIronmanManager().checkRestriction(IronmanMode.ULTIMATE)) {
player.sendChat(":crab: :crab: :crab: RETARDED PLUGIN IS GONE :crab: :crab: :crab:");
return true;
}
if (object.getName().contains("Bank") || object.getName().contains("Deposit")) {
//TODO: REPLACE THIS ALL WITH A LISTENER. I DONT FEEL LIKE IT RIGHT NOW.
player.dispatch(new InteractionEvent(object, option));
switch (option) {
case "use":
// final Location l = object.getLocation();
// final Location p = player.getLocation();
// final NPC npc = Repository.findNPC(l.transform(l.getX() - p.getX(), l.getY() - p.getY(), 0));
// if (node.getId() == 4483) {
// player.getBank().open();
// return true;
// }
// if (npc != null && DialogueInterpreter.contains(npc.getId())) {
// npc.faceLocation(node.getLocation());
// player.getDialogueInterpreter().open(npc.getId(), npc.getId());
// } else {
// player.getDialogueInterpreter().open(494);
// }
// return true;
case "use-quickly":
case "bank":
player.getBankPinManager().openType(1);
checkAchievements(player);
return true;
case "collect":
GrandExchangeRecords.getInstance(player).openCollectionBox();
return true;
case "deposit":
openDepositBox(player);
return true;
}
}
return true;
}
/**
* Method used to open the deposit box.
*
* @param player the player.
*/
private void openDepositBox(final Player player) {
player.getInterfaceManager().open(new Component(11)).setCloseEvent(new CloseEvent() {
@Override
public boolean close(Player player, Component c) {
player.getInterfaceManager().openDefaultTabs();
return true;
}
});
//player.getInterfaceManager().closeDefaultTabs();
player.getInterfaceManager().removeTabs(0, 1, 2, 3, 4, 5, 6);
InterfaceContainer.generateItems(player, player.getInventory().toArray(), new String[]{"Examine", "Deposit-X", "Deposit-All", "Deposit-10", "Deposit-5", "Deposit-1",}, 11, 15, 5, 7);
}
/**
* Represents the dialogue plugin used for all bankers.
@@ -317,7 +232,6 @@ public final class BankingPlugin extends OptionHandler {
case 2:
case 3:
player.getBankPinManager().openType(buttonId);
checkAchievements(player);
end();
break;
case 4:
@@ -340,7 +254,6 @@ public final class BankingPlugin extends OptionHandler {
case 2:
case 3:
player.getBankPinManager().openType(buttonId);
checkAchievements(player);
end();
break;
case 4:
@@ -381,382 +294,4 @@ public final class BankingPlugin extends OptionHandler {
}
}
/**
* Represents the component plugin used to handle banking interfaces.
*
* @author Emperor
* @author 'Vexia
* @version 1.0
*/
public static final class BankingInterface extends ComponentPlugin {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ComponentDefinition.put(763, this);
ComponentDefinition.put(762, this);
ComponentDefinition.put(767, this);
return this;
}
@Override
public void open(Player player, Component component) {
super.open(player, component);
player.getBank().sendBankSpace();
int settings = new IfaceSettingsBuilder().enableAllOptions().enableSlotSwitch().setInterfaceEventsDepth(2).build();
player.getPacketDispatch().sendIfaceSettings(settings, 73, 762, 0, 496);
}
@Override
public boolean handle(final Player p, Component component, int opcode, int button, final int slot, int itemId) {
final Item item = component.getId() == 762 ? p.getBank().get(slot) : p.getInventory().get(slot);
switch (component.getId()) {
case 767:
switch (button) {
case 10:
p.getBank().open();
break;
}
break;
case 762:
switch (button) {
case 18:
p.getDialogueInterpreter().open(new DepositAllDialogue().getID());
return true;
case 23:
p.getDialogueInterpreter().sendOptions("Select an Option", "Check bank value", "Banking assistance", "Close");
p.getDialogueInterpreter().addAction(new DialogueAction() {
@Override
public void handle(Player player, int buttonId) {
switch (buttonId) {
case 2:
p.getDialogueInterpreter().sendItemMessage(new Item(995, 50000), "<br>Your bank is worth approximately <col=a52929>" + NumberFormat.getInstance().format(p.getBank().getWealth()) + "</col> coins.");
break;
case 3:
p.getBank().close();
p.getInterfaceManager().open(new Component(767));
break;
case 4:
p.getDialogueInterpreter().close();
break;
}
}
});
break;
case 14:
p.getBank().setInsertItems(!p.getBank().isInsertItems());
return true;
case 16:
p.getBank().setNoteItems(!p.getBank().isNoteItems());
return true;
case 73:
int amount = 0;
switch (opcode) {
case 155:
amount = 1;
break;
case 196:
amount = 5;
break;
case 124:
amount = 10;
break;
case 199:
amount = p.getBank().getLastAmountX();
break;
case 234:
sendInputDialogue(p, false, "Enter the amount:", (value) -> {
String s = value.toString();
s = s.replace("k","000");
s = s.replace("K","000");
s = s.replace("m","000000");
s = s.replace("M","000000");
int val = Integer.parseInt(s);
p.getBank().takeItem(slot, val);
p.getBank().updateLastAmountX(val);
return Unit.INSTANCE;
});
break;
case 9:
p.sendMessage(p.getBank().get(slot).getDefinition().getExamine());
break;
case 168:
amount = p.getBank().getAmount(item);
break;
case 166:
amount = p.getBank().getAmount(item) - 1;
break;
default:
return false;
}
if (amount > 0) {
final int withdraw = amount;
GameWorld.getPulser().submit(new Pulse(1, p) {
@Override
public boolean pulse() {
if (item == null) {
return true;
}
p.getBank().takeItem(slot, withdraw);
return true;
}
});
}
return true;
case 20://search
p.setAttribute("search", true);
break;
case 41:
case 39:
case 37:
case 35:
case 33:
case 31:
case 29:
case 27:
case 25:
if (p.getAttribute("search", false)) {
p.getBank().reopen();
}
int tabIndex = -((button - 41) / 2);
switch (opcode) {
case 155:
p.getBank().setTabIndex(tabIndex);
return true;
case 196:
p.getBank().collapseTab(tabIndex);
return true;
}
return false;
}
break;
case 763:// overlay.
switch (opcode) {
case 155:
p.getBank().addItem(slot, 1);
break;
case 196:
p.getBank().addItem(slot, 5);
break;
case 124:
p.getBank().addItem(slot, 10);
break;
case 199:
p.getBank().addItem(slot, p.getBank().getLastAmountX());
break;
case 234:
sendInputDialogue(p, false, "Enter the amount:", (value) -> {
String s = value.toString();
s = s.replace("k","000");
s = s.replace("K","000");
int val = Integer.parseInt(s);
p.getBank().addItem(slot, val);
p.getBank().updateLastAmountX(val);
return Unit.INSTANCE;
});
break;
case 168:
p.getBank().addItem(slot, p.getInventory().getAmount(item));
break;
}
break;
}
return true;
}
}
/**
* Represents the bank deposit interface handler.
*
* @author 'Vexia
* @version 1.0
*/
public static final class BankDepositInterface extends ComponentPlugin {
/**
* Represents the deposit animation.
*/
private static final Animation DEPOSIT_ANIMATION = new Animation(834);
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ComponentDefinition.put(11, this);
return this;
}
@Override
public boolean handle(final Player p, Component component, int opcode, int button, final int slot, int itemId) {
final Item item = p.getInventory().get(slot);
if (item == null && button != 15 && button != 13) {
return true;
}
switch (component.getId()) {
case 11:
p.animate(DEPOSIT_ANIMATION);
switch (opcode) {
case 155: // Deposit items
p.getBank().addItem(slot, 1);
break;
case 196:
p.getBank().addItem(slot, 5);
break;
case 124:
p.getBank().addItem(slot, 10);
break;
case 199:
p.getPulseManager().run(new Pulse(1, p) {
@Override
public boolean pulse() {
p.getBank().addItem(slot, p.getInventory().getAmount(item));
InterfaceContainer.generateItems(p, p.getInventory().toArray(), new String[]{"Examine", "Deposit-X", "Deposit-All", "Deposit-10", "Deposit-5", "Deposit-1",}, 11, 15, 5, 7);
return true;
}
});
return true;
case 234:
sendInputDialogue(p, false, "Enter the amount:", (value) -> {
String s = value.toString();
s = s.replace("k","000");
s = s.replace("K","000");
int val = Integer.parseInt(s);
p.getBank().addItem(slot, val);
InterfaceContainer.generateItems(p, p.getInventory().toArray(), new String[]{"Examine", "Deposit-X", "Deposit-All", "Deposit-10", "Deposit-5", "Deposit-1",}, 11, 15, 5, 7);
return Unit.INSTANCE;
});
break;
case 168:
p.sendMessage(item.getDefinition().getExamine());
break;
}
switch (button) {
case 13:
p.getFamiliarManager().dumpBob();
break;
}
break;
}
InterfaceContainer.generateItems(p, p.getInventory().toArray(), new String[]{"Examine", "Deposit-X", "Deposit-All", "Deposit-10", "Deposit-5", "Deposit-1",}, 11, 15, 5, 7);
return true;
}
}
/**
* Represents the plugin used to handle the banker npc.
*
* @author 'Vexia
* @author Emperor
* @version 1.01
*/
public static final class BankNPCPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
NPCDefinition.setOptionHandler("bank", this);
NPCDefinition.setOptionHandler("collect", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final NPC npc = ((NPC) node);
npc.faceLocation(node.getLocation());
if (option.equals("bank")) {
player.getBank().open();
checkAchievements(player);
} else {
GrandExchangeRecords.getInstance(player).openCollectionBox();
}
return true;
}
@Override
public Location getDestination(Node n, Node node) {
NPC npc = (NPC) node;
if (npc.getAttribute("facing_booth", false)) {
Direction dir = npc.getDirection();
return npc.getLocation().transform(dir.getStepX() << 1, dir.getStepY() << 1, 0);
}
if (npc.getId() == 6533) {
return Location.create(3167, 3489, 0);// ge bankers.
} else if (npc.getId() == 6534) {
return Location.create(3167, 3490, 0);// ge bankers.
} else if (npc.getId() == 6535) {
return Location.create(3162, 3489, 0);
} else if (npc.getId() == 6532) {
return Location.create(3162, 3489, 0);
} else if (npc.getId() == 4907) {
return npc.getLocation().transform(0, -2, 0);
}
return super.getDestination(npc, node);
}
}
/**
* Represents the abstract npc of a banker.
*
* @author 'Vexia
* @author Emperor
* @version 1.2
*/
public static final class BankNPC extends AbstractNPC {
/**
* Represents the ids of this class.
*/
private final int[] IDS = new int[]{4907, 44, 45, 166, 494, 495, 496, 497, 498, 499, 902, 1036, 1360, 1702, 2163, 2164, 2354, 2355, 2568, 2569, 2570, 2619, 3046, 3198, 3199, 4296, 4519, 5257, 5258, 5259, 5260, 5383, 5488, 5776, 5777, 5898, 5912, 5913, 6200, 6362, 6532, 6533, 6534, 6535, 6538, 7049, 7050, 7445, 7446, 7605};
/**
* Constructs a new {@code BankNPC} {@code Object}.
*/
public BankNPC() {
super(0, null);
}
@Override
public void init() {
super.init();
for (int i = 0; i < 4; i++) {
Direction dir = Direction.get(i);
Location loc = getLocation().transform(dir.getStepX(), dir.getStepY(), 0);
Scenery bank = RegionManager.getObject(loc);
if (bank != null && bank.getName().equals("Bank booth")) {
setDirection(dir);
setAttribute("facing_booth", true);
super.setWalks(false);
break;
}
}
}
/**
* Constructs a new {@code BankNPC} {@code Object}.
*
* @param id The NPC id.
* @param location The location.
*/
private BankNPC(int id, Location location) {
super(id, location);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new BankNPC(id, location);
}
@Override
public int[] getIds() {
return IDS;
}
}
private static void checkAchievements(Player player) {
// Access the bank in Draynor Village
if (player.getLocation().withinDistance(Location.create(3092, 3243, 0))) {
player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 1, 15);
}
}
}
@@ -375,8 +375,17 @@ public final class WalkingQueue {
* @param running The running flag (ctrl + click reward).
*/
public void reset(boolean running) {
Location loc = entity.getLocation();
if (loc == null) {
throw new IllegalStateException(
"The entity location provided was null."
+ "Are you sure anything down the stack trace isn't providing an NPC with a null location?"
);
}
walkingQueue.clear();
walkingQueue.add(new Point(entity.getLocation().getX(), entity.getLocation().getY()));
walkingQueue.add(new Point(loc.getX(), loc.getY()));
this.running = running;
}
@@ -1,5 +1,7 @@
package core.game.node.entity.player.link;
import api.events.InterfaceCloseEvent;
import api.events.InterfaceOpenEvent;
import core.game.component.Component;
import core.game.component.InterfaceType;
import core.game.node.entity.combat.equipment.WeaponInterface;
@@ -125,8 +127,13 @@ public final class InterfaceManager {
SystemLogger.logErr("Set interface type to WINDOW_PANE for component " + windowsPane.getId() + ", definition requires updating!");
windowsPane.getDefinition().setType(InterfaceType.WINDOW_PANE);
}
PacketRepository.send(WindowsPane.class, new WindowsPaneContext(player, windowsPane.getId(), overlap ? 1 : 0));
windowsPane.open(player);
if (opened != null)
player.dispatch(new InterfaceOpenEvent(opened));
return windowsPane;
}
@@ -136,8 +143,12 @@ public final class InterfaceManager {
SystemLogger.logErr("Set interface type to WINDOW_PANE for component " + windowsPane.getId() + ", definition requires updating!");
windowsPane.getDefinition().setType(InterfaceType.SINGLE_TAB);
}
PacketRepository.send(WindowsPane.class, new WindowsPaneContext(player, windowsPane.getId(), type));
windowsPane.open(player);
if (opened != null)
player.dispatch(new InterfaceOpenEvent(opened));
}
/**
@@ -161,7 +172,11 @@ public final class InterfaceManager {
return null;
}
component.open(player);
return opened = component;
opened = component;
player.dispatch(new InterfaceOpenEvent(opened));
return opened;
}
/**
@@ -191,6 +206,7 @@ public final class InterfaceManager {
if (opened != null && opened.close(player)) {
if (opened != null && (!opened.getDefinition().isWalkable() || opened.getId() == 14)) {
PacketRepository.send(CloseInterface.class, new InterfaceContext(player, opened.getDefinition().getWindowPaneId(isResizable()), opened.getDefinition().getChildId(isResizable()), opened.getId(), opened.getDefinition().isWalkable()));
player.dispatch(new InterfaceCloseEvent(opened));
}
opened = null;
}
@@ -281,28 +281,6 @@ public final class FamiliarManager {
player.getInterfaceManager().setViewedTab(7);
}
/**
* Dumps the bob.
*/
public void dumpBob() {
if (!hasFamiliar()) {
player.getPacketDispatch().sendMessage("You don't have a familiar.");
return;
}
Familiar familiar = getFamiliar();
if (!familiar.isBurdenBeast()) {
player.getPacketDispatch().sendMessage("Your familiar is not a beast of burden.");
return;
}
BurdenBeast beast = ((BurdenBeast) familiar);
if (!player.getBank().hasSpaceFor(beast.getContainer())) {
player.getPacketDispatch().sendMessage("There is not enough space left in your bank.");
return;
}
player.getBank().addAll(beast.getContainer());
beast.getContainer().clear();
}
/**
* Makes the pet eat.
* @param foodId The food item id.
@@ -1,47 +0,0 @@
package core.net.packet.in;
import static api.ContentAPIKt.*;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.RunScript;
import core.net.packet.IncomingPacket;
import core.net.packet.IoBuffer;
import core.tools.StringUtils;
import kotlin.jvm.functions.Function1;
/**
* Represents the incoming packet to handle a run script.
* @author 'Vexia
*/
public class RunScriptPacketHandler implements IncomingPacket {
@Override
public void decode(Player player, int opcode, IoBuffer buffer) {
final Function1 script = player.getAttribute("runscript", null);
if (script == null || player.getLocks().isInteractionLocked()) {
return;
}
Object value = "";
if (opcode == 244) {
value = StringUtils.longToString(buffer.getLong());
} else if (opcode == 23) {
value = buffer.getInt();
} else if (opcode == 65){
value = buffer.getString();//"longInput"
} else {
value = buffer.getInt();
}
if(value instanceof Integer)
{
if((int) value <= 0){
player.removeAttribute("runscript");
return;
}
}
try {
script.invoke(value);
} catch (NumberFormatException nfe){
sendDialogue(player, "That number's a bit large, don't you think?");
}
player.removeAttribute("runscript");
}
}
+281 -125
View File
@@ -22,6 +22,7 @@ import core.game.node.entity.player.link.emote.Emotes
import core.game.node.entity.player.link.quest.QuestRepository
import core.game.node.entity.skill.Skills
import core.game.node.entity.skill.gather.SkillingTool
import core.game.node.entity.skill.summoning.familiar.BurdenBeast
import core.game.node.item.GroundItem
import core.game.node.item.GroundItemManager
import core.game.node.item.Item
@@ -39,6 +40,7 @@ import core.game.world.map.zone.ZoneBuilder
import core.game.world.update.flag.chunk.AnimateObjectUpdateFlag
import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics
import org.rs09.consts.Items
import rs09.game.content.dialogue.DialogueFile
import rs09.game.content.dialogue.SkillDialogueHandler
import rs09.game.content.global.GlobalKillCounter
@@ -57,7 +59,7 @@ import rs09.game.world.repository.Repository
* @return the tool which meets the requirements or null if none.
*/
fun getTool(player: Player, pickaxe: Boolean): SkillingTool? {
return if(pickaxe) SkillingTool.getPickaxe(player) else SkillingTool.getHatchet(player)
return if (pickaxe) SkillingTool.getPickaxe(player) else SkillingTool.getHatchet(player)
}
/**
@@ -99,7 +101,7 @@ fun inInventory(player: Player, item: Int, amount: Int = 1): Boolean {
* @param id the ID of the item to check for the amount of
* @return the amount of the given ID in the player's inventory
*/
fun amountInInventory(player: Player, id: Int): Int{
fun amountInInventory(player: Player, id: Int): Int {
return player.inventory.getAmount(id)
}
@@ -109,7 +111,7 @@ fun amountInInventory(player: Player, id: Int): Int{
* @param id the ID of the item to check for
* @return the amount of the ID in the player's bank.
*/
fun amountInBank(player: Player, id: Int): Int{
fun amountInBank(player: Player, id: Int): Int {
return player.bank.getAmount(id)
}
@@ -119,7 +121,7 @@ fun amountInBank(player: Player, id: Int): Int{
* @param id the ID of the item to check for
* @return the amount of the ID in the player's equipment.
*/
fun amountInEquipment(player: Player, id: Int): Int{
fun amountInEquipment(player: Player, id: Int): Int {
return player.equipment.getAmount(id)
}
@@ -153,9 +155,8 @@ fun hasAnItem(player: Player, vararg ids: Int): ContainerisedItem {
* @param god the God whose equipment we are checking for
* @return true if the player has an item corresponding to the given god, false otherwise
*/
fun hasGodItem(player: Player, god: God): Boolean
{
god.validItems.forEach { if(amountInEquipment(player, it) > 0) return true }
fun hasGodItem(player: Player, god: God): Boolean {
god.validItems.forEach { if (amountInEquipment(player, it) > 0) return true }
return false
}
@@ -173,7 +174,7 @@ fun <T> removeItem(player: Player, item: T, container: Container = Container.INV
else -> throw IllegalStateException("Invalid value passed for item")
}
return when(container){
return when (container) {
Container.INVENTORY -> player.inventory.remove(it)
Container.BANK -> player.bank.remove(it)
Container.EQUIPMENT -> player.equipment.remove(it)
@@ -189,7 +190,7 @@ fun <T> removeItem(player: Player, item: T, container: Container = Container.INV
* @return true if the item was successfully added
*/
fun addItem(player: Player, id: Int, amount: Int = 1, container: Container = Container.INVENTORY): Boolean {
val cont = when(container){
val cont = when (container) {
Container.INVENTORY -> player.inventory
Container.BANK -> player.bank
Container.EQUIPMENT -> player.equipment
@@ -207,7 +208,7 @@ fun addItem(player: Player, id: Int, amount: Int = 1, container: Container = Con
* @return the item that was previously in the slot, or null if none.
*/
fun replaceSlot(player: Player, slot: Int, item: Item, container: Container = Container.INVENTORY): Item? {
val cont = when(container) {
val cont = when (container) {
Container.INVENTORY -> player.inventory
Container.EQUIPMENT -> player.equipment
Container.BANK -> player.bank
@@ -222,20 +223,20 @@ fun replaceSlot(player: Player, slot: Int, item: Item, container: Container = Co
* @param id the ID of the item to add to the player's inventory
* @param amount the amount of the ID to add to the player's inventory, defaults to 1
*/
fun addItemOrDrop(player: Player, id: Int, amount: Int = 1){
fun addItemOrDrop(player: Player, id: Int, amount: Int = 1) {
val item = Item(id, amount)
if(!player.inventory.add(item)) GroundItemManager.create(item,player)
if (!player.inventory.add(item)) GroundItemManager.create(item, player)
}
/**
* Clears an NPC with the "poof" smoke graphics commonly seen with random event NPCs.
* @param npc the NPC object to initialize
*/
fun poofClear(npc: NPC){
submitWorldPulse(object : Pulse(){
fun poofClear(npc: NPC) {
submitWorldPulse(object : Pulse() {
var counter = 0
override fun pulse(): Boolean {
when(counter++){
when (counter++) {
2 -> {
npc.isInvisible = true; Graphics.send(Graphics(86), npc.location)
}
@@ -331,14 +332,14 @@ fun rewardXP(player: Player, skill: Int, amount: Double) {
* @param loc the location to move the new object to if necessary. Defaults to null.
*/
fun replaceScenery(toReplace: Scenery, with: Int, for_ticks: Int, loc: Location? = null) {
val newLoc = when(loc){
val newLoc = when (loc) {
null -> toReplace.location
else -> loc
}
if (for_ticks == -1) {
SceneryBuilder.replace(toReplace, toReplace.transform(with,toReplace.rotation,newLoc))
SceneryBuilder.replace(toReplace, toReplace.transform(with, toReplace.rotation, newLoc))
} else {
SceneryBuilder.replace(toReplace, toReplace.transform(with,toReplace.rotation, newLoc), for_ticks)
SceneryBuilder.replace(toReplace, toReplace.transform(with, toReplace.rotation, newLoc), for_ticks)
}
toReplace.isActive = false
}
@@ -351,12 +352,12 @@ fun replaceScenery(toReplace: Scenery, with: Int, for_ticks: Int, loc: Location?
* @Param rotation the Direction of the rotation it should use. Direction.NORTH, Direction.SOUTH, etc
* @param loc the location to move the new object to if necessary. Defaults to null.
*/
fun replaceScenery(toReplace: Scenery, with: Int, for_ticks: Int, rotation: Direction, loc: Location? = null){
val newLoc = when(loc){
fun replaceScenery(toReplace: Scenery, with: Int, for_ticks: Int, rotation: Direction, loc: Location? = null) {
val newLoc = when (loc) {
null -> toReplace.location
else -> loc
}
val rot = when(rotation){
val rot = when (rotation) {
Direction.NORTH_WEST -> 0
Direction.NORTH -> 1
Direction.NORTH_EAST -> 2
@@ -367,9 +368,9 @@ fun replaceScenery(toReplace: Scenery, with: Int, for_ticks: Int, rotation: Dire
Direction.WEST -> 3
}
if (for_ticks == -1) {
SceneryBuilder.replace(toReplace, toReplace.transform(with,rot, newLoc))
SceneryBuilder.replace(toReplace, toReplace.transform(with, rot, newLoc))
} else {
SceneryBuilder.replace(toReplace, toReplace.transform(with,rot,newLoc), for_ticks)
SceneryBuilder.replace(toReplace, toReplace.transform(with, rot, newLoc), for_ticks)
}
toReplace.isActive = false
}
@@ -453,7 +454,7 @@ fun animateScenery(player: Player, obj: Scenery, animationId: Int, global: Boole
/**
* Send an object animation independent of a player
*/
fun animateScenery(obj: Scenery, animationId: Int){
fun animateScenery(obj: Scenery, animationId: Int) {
val animation = Animation(animationId)
animation.setObject(obj)
getRegionChunk(obj.location).flag(AnimateObjectUpdateFlag(animation))
@@ -484,8 +485,27 @@ fun spawnProjectile(source: Entity, dest: Entity, projectileId: Int) {
* @param speed the speed the projectile travels at
* @param angle the angle the projectile travels at
*/
fun spawnProjectile(source: Location, dest: Location, projectile: Int, startHeight: Int, endHeight: Int, delay: Int, speed: Int, angle: Int){
Projectile.create(source, dest, projectile, startHeight, endHeight, delay, speed, angle, source.getDistance(dest).toInt()).send()
fun spawnProjectile(
source: Location,
dest: Location,
projectile: Int,
startHeight: Int,
endHeight: Int,
delay: Int,
speed: Int,
angle: Int
) {
Projectile.create(
source,
dest,
projectile,
startHeight,
endHeight,
delay,
speed,
angle,
source.getDistance(dest).toInt()
).send()
}
/**
@@ -522,7 +542,7 @@ fun openInterface(player: Player, id: Int) {
* @param player the player to open the interface for
* @param id the ID of the interface to open
*/
fun openOverlay(player: Player, id: Int){
fun openOverlay(player: Player, id: Int) {
player.interfaceManager.openOverlay(Component(id))
}
@@ -530,7 +550,7 @@ fun openOverlay(player: Player, id: Int){
* Closes any open overlays for the given player
* @param player the player to close for
*/
fun closeOverlay(player: Player){
fun closeOverlay(player: Player) {
player.interfaceManager.closeOverlay()
}
@@ -576,7 +596,7 @@ fun sendDialogue(player: Player, message: String) {
* @param forced whether or not to force the animation (usually not necessary)
*/
fun <T> animate(entity: Entity, anim: T, forced: Boolean = false) {
val animation = when(anim){
val animation = when (anim) {
is Int -> Animation(anim)
is Animation -> anim
else -> throw IllegalStateException("Invalid value passed for anim")
@@ -630,15 +650,15 @@ fun findNPC(id: Int): NPC? {
* @param y the Y coordinate to use
* @param z the Z coordinate to use
*/
fun getScenery(x: Int, y: Int, z: Int): Scenery?{
return RegionManager.getObject(z,x,y)
fun getScenery(x: Int, y: Int, z: Int): Scenery? {
return RegionManager.getObject(z, x, y)
}
/**
* Gets the spawned scenery from the world map using the given Location object.
* @param loc the Location object to use.
*/
fun getScenery(loc: Location): Scenery?{
fun getScenery(loc: Location): Scenery? {
return RegionManager.getObject(loc)
}
@@ -667,7 +687,7 @@ fun findLocalNPC(entity: Entity, id: Int): NPC? {
* @param entity the entity to check around
* @param ids the IDs of the NPCs to look for
*/
fun findLocalNPCs(entity: Entity, ids: IntArray): List<NPC>{
fun findLocalNPCs(entity: Entity, ids: IntArray): List<NPC> {
return RegionManager.getLocalNpcs(entity).filter { it.id in ids }.toList()
}
@@ -677,7 +697,7 @@ fun findLocalNPCs(entity: Entity, ids: IntArray): List<NPC>{
* @param ids the IDs of the NPCs to look for
* @param distance The maximum distance to the entity.
*/
fun findLocalNPCs(entity: Entity, ids: IntArray, distance: Int): List<NPC>{
fun findLocalNPCs(entity: Entity, ids: IntArray, distance: Int): List<NPC> {
return RegionManager.getLocalNpcs(entity, distance).filter { it.id in ids }.toList()
}
@@ -685,8 +705,7 @@ fun findLocalNPCs(entity: Entity, ids: IntArray, distance: Int): List<NPC>{
* @param regionId the ID of the region
* @return a [ZoneBorders] encapsulating the entire region indicated by the provided regionId
*/
fun getRegionBorders(regionId: Int) : ZoneBorders
{
fun getRegionBorders(regionId: Int): ZoneBorders {
return ZoneBorders.forRegion(regionId)
}
@@ -742,9 +761,9 @@ fun unlock(entity: Entity) {
* @param transformTo the ID of the NPC to turn into
* @param restoreTicks the number of ticks until the NPC returns to normal
*/
fun transformNpc(npc: NPC, transformTo: Int, restoreTicks: Int){
fun transformNpc(npc: NPC, transformTo: Int, restoreTicks: Int) {
npc.transform(transformTo)
Pulser.submit(object : Pulse(restoreTicks){
Pulser.submit(object : Pulse(restoreTicks) {
override fun pulse(): Boolean {
npc.reTransform()
return true
@@ -755,14 +774,14 @@ fun transformNpc(npc: NPC, transformTo: Int, restoreTicks: Int){
/**
* Produces a Location object using the given x,y,z values
*/
fun location(x: Int, y: Int, z: Int): Location{
return Location.create(x,y,z)
fun location(x: Int, y: Int, z: Int): Location {
return Location.create(x, y, z)
}
/**
* Checks if the given entity is within the given ZoneBorders
*/
fun inBorders(entity: Entity, borders: ZoneBorders): Boolean{
fun inBorders(entity: Entity, borders: ZoneBorders): Boolean {
return borders.insideBorder(entity)
}
@@ -770,13 +789,13 @@ fun inBorders(entity: Entity, borders: ZoneBorders): Boolean{
* Checks if the given entity is within the given borders
*/
fun inBorders(entity: Entity, swX: Int, swY: Int, neX: Int, neY: Int): Boolean {
return ZoneBorders(swX,swY,neX,neY).insideBorder(entity)
return ZoneBorders(swX, swY, neX, neY).insideBorder(entity)
}
/**
* AHeals the given entity for the given number of hitpoints
*/
fun heal(entity: Entity, amount: Int){
fun heal(entity: Entity, amount: Int) {
entity.skills.heal(amount)
}
@@ -787,9 +806,9 @@ fun heal(entity: Entity, amount: Int){
* @param offset the offset of the desired varbit inside the varp.
* @param value the value to set the varbit to
*/
fun setVarbit(player: Player, varpIndex: Int, offset: Int, value: Int, save: Boolean = false){
player.varpManager.get(varpIndex).setVarbit(offset,value).send(player)
if(save) player.varpManager.flagSave(varpIndex)
fun setVarbit(player: Player, varpIndex: Int, offset: Int, value: Int, save: Boolean = false) {
player.varpManager.get(varpIndex).setVarbit(offset, value).send(player)
if (save) player.varpManager.flagSave(varpIndex)
}
/**
@@ -797,7 +816,7 @@ fun setVarbit(player: Player, varpIndex: Int, offset: Int, value: Int, save: Boo
* @param player the player to clear for
* @param varpIndex the index of the varp to clear
*/
fun clearVarp(player: Player, varpIndex: Int){
fun clearVarp(player: Player, varpIndex: Int) {
player.varpManager.get(varpIndex).clear()
}
@@ -807,7 +826,7 @@ fun clearVarp(player: Player, varpIndex: Int){
* @param varpIndex the index of the varp to calculate the value of
* @return the value of the varp
*/
fun getVarpValue(player: Player, varpIndex: Int): Int{
fun getVarpValue(player: Player, varpIndex: Int): Int {
return player.varpManager.get(varpIndex).getValue()
}
@@ -828,12 +847,12 @@ fun getVarbitValue(player: Player, varpIndex: Int, offset: Int): Int {
* @param dest the Location object to walk to
* @param type the type of pathfinder to use. "smart" for the SMART pathfinder, "clip" for the noclip pathfinder, anything else for DUMB.
*/
fun forceWalk(entity: Entity, dest: Location, type: String){
if(type == "clip"){
fun forceWalk(entity: Entity, dest: Location, type: String) {
if (type == "clip") {
ForceMovement(entity, dest, 10, 10).run()
return
}
val pathfinder = when(type){
val pathfinder = when (type) {
"smart" -> Pathfinder.SMART
else -> Pathfinder.DUMB
}
@@ -845,7 +864,7 @@ fun forceWalk(entity: Entity, dest: Location, type: String){
* Interrupts a given entity's walking queue
* @param entity the entity to interrupt
*/
fun stopWalk(entity: Entity){
fun stopWalk(entity: Entity) {
entity.walkingQueue.reset()
}
@@ -871,8 +890,8 @@ fun getChildren(scenery: Int): IntArray {
* @param node the node to adjust the charge of
* @param amount the amount to adjust by
*/
fun adjustCharge(node: Node, amount: Int){
when(node){
fun adjustCharge(node: Node, amount: Int) {
when (node) {
is Item -> node.charge += amount
is Scenery -> node.charge += amount
else -> SystemLogger.logErr("Attempt to adjust the charge of invalid type: ${node.javaClass.simpleName}")
@@ -884,11 +903,12 @@ fun adjustCharge(node: Node, amount: Int){
* @param node the node whose charge to check
* @return amount of charges the node has, or -1 if the node does not accept charges.
*/
fun getCharge(node: Node): Int{
when(node){
fun getCharge(node: Node): Int {
when (node) {
is Item -> return node.charge
is Scenery -> return node.charge
else -> SystemLogger.logErr("Attempt to get charge of invalid type: ${node.javaClass.simpleName}").also { return -1 }
else -> SystemLogger.logErr("Attempt to get charge of invalid type: ${node.javaClass.simpleName}")
.also { return -1 }
}
}
@@ -897,8 +917,8 @@ fun getCharge(node: Node): Int{
* @param node the node to set the charge for
* @param charge the amount to set the node's charge to (default is 1000)
*/
fun setCharge(node: Node, charge: Int){
when(node){
fun setCharge(node: Node, charge: Int) {
when (node) {
is Item -> node.charge = charge
is Scenery -> node.charge = charge
else -> SystemLogger.logErr("Attempt to set the charge of invalid type: ${node.javaClass.simpleName}")
@@ -911,7 +931,7 @@ fun setCharge(node: Node, charge: Int){
* @return the option the player used
*/
fun getUsedOption(player: Player): String {
return player.getAttribute("interact:option","INVALID")
return player.getAttribute("interact:option", "INVALID")
}
/**
@@ -920,39 +940,56 @@ fun getUsedOption(player: Player): String {
* @param anim the Animation object to use, can also be an ID.
* @param gfx the Graphics object to use, can also be an ID.
*/
fun <A,G> visualize(entity: Entity, anim: A, gfx: G){
val animation = when(anim){
fun <A, G> visualize(entity: Entity, anim: A, gfx: G) {
val animation = when (anim) {
is Int -> Animation(anim)
is Animation -> anim
else -> throw IllegalStateException("Invalid parameter passed for animation.")
}
val graphics = when(gfx){
val graphics = when (gfx) {
is Int -> Graphics(gfx)
is Graphics -> gfx
else -> throw IllegalStateException("Invalid parameter passed for graphics.")
}
entity.visualize(animation,graphics)
entity.visualize(animation, graphics)
}
/**
* Used to submit a pulse to the GameWorld's Pulser.
* @param pulse the Pulse object to submit
*/
fun submitWorldPulse(pulse: Pulse){
fun submitWorldPulse(pulse: Pulse) {
GameWorld.Pulser.submit(pulse)
}
/**
* Used to submit a pulse to the GameWorld's Pulser, albeit with a cleaner syntax.
* @param task an anonymous function that will be run in the Pulse
* @return the newly submitted Pulse
*/
fun runWorldTask(task: () -> Unit): Pulse {
val pulse = object : Pulse() {
override fun pulse(): Boolean {
task.invoke()
return true
}
}
submitWorldPulse(pulse)
return pulse
}
/**
* Teleports or "instantly moves" an entity to a given Location object.
* @param entity the entity to move
* @param loc the Location object to move them to
* @param type the teleport type to use (defaults to instant). An enum exists as TeleportManager.TeleportType.
*/
fun teleport(entity: Entity, loc: Location, type: TeleportManager.TeleportType = TeleportManager.TeleportType.INSTANT){
if(type == TeleportManager.TeleportType.INSTANT) entity.properties.teleportLocation = loc
else entity.teleporter.send(loc,type)
fun teleport(entity: Entity, loc: Location, type: TeleportManager.TeleportType = TeleportManager.TeleportType.INSTANT) {
if (type == TeleportManager.TeleportType.INSTANT) entity.properties.teleportLocation = loc
else entity.teleporter.send(loc, type)
}
/**
@@ -961,7 +998,7 @@ fun teleport(entity: Entity, loc: Location, type: TeleportManager.TeleportType =
* @param skill the Skill to set. A Skills enum exists that can be used. Ex: Skills.STRENGTH
* @param level the level to set the skill to
*/
fun setTempLevel(entity: Entity, skill: Int, level: Int){
fun setTempLevel(entity: Entity, skill: Int, level: Int) {
entity.skills.setLevel(skill, level)
}
@@ -991,7 +1028,7 @@ fun getDynLevel(entity: Entity, skill: Int): Int {
* @param skill the Skill to adjust. A Skills enum exists that can be used. Ex: Skills.STRENGTH
* @param amount the amount to adjust the skill by. Ex-Buff: 5, Ex-Debuff: -5
*/
fun adjustLevel(entity: Entity, skill: Int, amount: Int){
fun adjustLevel(entity: Entity, skill: Int, amount: Int) {
entity.skills.setLevel(skill, entity.skills.getStaticLevel(skill) + amount)
}
@@ -1001,14 +1038,14 @@ fun adjustLevel(entity: Entity, skill: Int, amount: Int){
* @param item the item to remove. Can be an Item object or an ID.
* @param container the Container to remove the item from. An enum exists for this called Container. Ex: Container.BANK
*/
fun <T> removeAll(player: Player, item: T, container: Container){
val it = when(item){
fun <T> removeAll(player: Player, item: T, container: Container) {
val it = when (item) {
is Item -> item.id
is Int -> item
else -> throw IllegalStateException("Invalid value passed as item")
}
when(container){
when (container) {
Container.EQUIPMENT -> player.equipment.remove(Item(it, amountInEquipment(player, it)))
Container.BANK -> player.bank.remove(Item(it, amountInBank(player, it)))
Container.INVENTORY -> player.inventory.remove(Item(it, amountInInventory(player, it)))
@@ -1022,15 +1059,15 @@ fun <T> removeAll(player: Player, item: T, container: Container){
* @param iface the ID of the interface to use
* @param child the index of the child to send the string to
*/
fun setInterfaceText(player: Player, string: String, iface: Int, child: Int){
player.packetDispatch.sendString(string,iface,child)
fun setInterfaceText(player: Player, string: String, iface: Int, child: Int) {
player.packetDispatch.sendString(string, iface, child)
}
/**
* Closes any open (non-chat) interfaces for the player
* @param player the player to close the interface for
*/
fun closeInterface(player: Player){
fun closeInterface(player: Player) {
player.interfaceManager.close()
}
@@ -1038,7 +1075,7 @@ fun closeInterface(player: Player){
* Closes any opened tab interfaces for the player
* @param player the player to close the tab for
*/
fun closeTabInterface(player: Player){
fun closeTabInterface(player: Player) {
player.interfaceManager.closeSingleTab()
}
@@ -1048,7 +1085,7 @@ fun closeTabInterface(player: Player){
* @param msg the message to send.
* @param expr the FacialExpression to use. An enum exists for these called FacialExpression. Defaults to FacialExpression.FRIENDLY
*/
fun sendPlayerDialogue(player: Player, msg: String, expr: FacialExpression = FacialExpression.FRIENDLY){
fun sendPlayerDialogue(player: Player, msg: String, expr: FacialExpression = FacialExpression.FRIENDLY) {
player.dialogueInterpreter.sendDialogues(player, expr, *splitLines(msg))
}
@@ -1058,8 +1095,8 @@ fun sendPlayerDialogue(player: Player, msg: String, expr: FacialExpression = Fac
* @param iface the ID of the interface to send it to
* @param child the index of the child on the interface to send the model to
*/
fun sendPlayerOnInterface(player: Player, iface: Int, child: Int){
player.packetDispatch.sendPlayerOnInterface(iface,child)
fun sendPlayerOnInterface(player: Player, iface: Int, child: Int) {
player.packetDispatch.sendPlayerOnInterface(iface, child)
}
/**
@@ -1069,7 +1106,7 @@ fun sendPlayerOnInterface(player: Player, iface: Int, child: Int){
* @param msg the message to send.
* @param expr the FacialExpression to use. An enum exists for these called FacialExpression. Defaults to FacialExpression.FRIENDLY
*/
fun sendNPCDialogue(player: Player, npc: Int, msg: String, expr: FacialExpression = FacialExpression.FRIENDLY){
fun sendNPCDialogue(player: Player, npc: Int, msg: String, expr: FacialExpression = FacialExpression.FRIENDLY) {
player.dialogueInterpreter.sendDialogues(npc, expr, *splitLines(msg))
}
@@ -1080,8 +1117,8 @@ fun sendNPCDialogue(player: Player, npc: Int, msg: String, expr: FacialExpressio
* @param iface the ID of the interface to send the animation to
* @param child the index of the child on the interface to send the model to
*/
fun sendAnimationOnInterface(player: Player, anim: Int, iface: Int, child: Int){
player.packetDispatch.sendAnimationInterface(anim,iface,child)
fun sendAnimationOnInterface(player: Player, anim: Int, iface: Int, child: Int) {
player.packetDispatch.sendAnimationInterface(anim, iface, child)
}
/**
@@ -1089,7 +1126,7 @@ fun sendAnimationOnInterface(player: Player, anim: Int, iface: Int, child: Int){
* @param player the player to register the listener for
* @param handler the method to run when the listener is invoked (when the player logs out)
*/
fun registerLogoutListener(player: Player, key: String, handler: (p: Player) -> Unit){
fun registerLogoutListener(player: Player, key: String, handler: (p: Player) -> Unit) {
player.logoutListeners[key] = handler
}
@@ -1098,7 +1135,7 @@ fun registerLogoutListener(player: Player, key: String, handler: (p: Player) ->
* @param player the player to remove the logout listner from
* @param key the key of the logout listener to remove.
*/
fun clearLogoutListener(player: Player, key: String){
fun clearLogoutListener(player: Player, key: String) {
player.logoutListeners.remove(key)
}
@@ -1110,8 +1147,8 @@ fun clearLogoutListener(player: Player, key: String){
* @param item the ID of the item to send
* @param amount the amount of the item to send - defaults to 1
*/
fun sendItemOnInterface(player: Player, iface: Int, child: Int, item: Int, amount: Int = 1){
player.packetDispatch.sendItemOnInterface(item,amount,iface,child)
fun sendItemOnInterface(player: Player, iface: Int, child: Int, item: Int, amount: Int = 1) {
player.packetDispatch.sendItemOnInterface(item, amount, iface, child)
}
/**
@@ -1120,8 +1157,16 @@ fun sendItemOnInterface(player: Player, iface: Int, child: Int, item: Int, amoun
* @param item the ID of the item to show
* @param message the text to display
*/
fun sendItemDialogue(player: Player, item: Int, message: String){
player.dialogueInterpreter.sendItemMessage(item, *splitLines(message))
fun sendItemDialogue(player: Player, item: Any, message: String) {
val dialogueItem = when (item) {
is Item -> item
is Int -> Item(item)
else -> {
throw java.lang.IllegalArgumentException("Expected an Item or an Int, got ${item::class.java.simpleName}.")
}
}
player.dialogueInterpreter.sendItemMessage(dialogueItem, *splitLines(message))
}
/**
@@ -1131,7 +1176,7 @@ fun sendItemDialogue(player: Player, item: Int, message: String){
* @param item2 the ID of the second item to show
* @param message the text to display
*/
fun sendDoubleItemDialogue(player: Player, item1: Int, item2: Int, message: String){
fun sendDoubleItemDialogue(player: Player, item1: Int, item2: Int, message: String) {
player.dialogueInterpreter.sendDoubleItemMessage(item1, item2, message)
}
@@ -1142,8 +1187,8 @@ fun sendDoubleItemDialogue(player: Player, item1: Int, item2: Int, message: Stri
* @param prompt what to prompt the player
* @param handler the method that handles the value gained from the input dialogue
*/
fun sendInputDialogue(player: Player, numeric: Boolean, prompt: String, handler: (value: Any) -> Unit){
if(numeric) sendInputDialogue(player, InputType.NUMERIC, prompt, handler)
fun sendInputDialogue(player: Player, numeric: Boolean, prompt: String, handler: (value: Any) -> Unit) {
if (numeric) sendInputDialogue(player, InputType.NUMERIC, prompt, handler)
else sendInputDialogue(player, InputType.STRING_SHORT, prompt, handler)
}
@@ -1154,12 +1199,22 @@ fun sendInputDialogue(player: Player, numeric: Boolean, prompt: String, handler:
* @param prompt what to prompt the player
* @param handler the method that handles the value from the input dialogue
*/
fun sendInputDialogue(player: Player, type: InputType, prompt: String, handler: (value: Any) -> Unit){
when(type){
InputType.NUMERIC, InputType.STRING_SHORT -> player.dialogueInterpreter.sendInput(type != InputType.NUMERIC, prompt)
fun sendInputDialogue(player: Player, type: InputType, prompt: String, handler: (value: Any) -> Unit) {
when (type) {
InputType.AMOUNT -> {
player.setAttribute("parseamount", true)
player.dialogueInterpreter.sendInput(true, prompt)
}
InputType.NUMERIC, InputType.STRING_SHORT -> player.dialogueInterpreter.sendInput(
type != InputType.NUMERIC,
prompt
)
InputType.STRING_LONG -> player.dialogueInterpreter.sendLongInput(prompt)
InputType.MESSAGE -> player.dialogueInterpreter.sendMessageInput(prompt)
}
player.setAttribute("runscript", handler)
}
@@ -1168,14 +1223,14 @@ fun sendInputDialogue(player: Player, type: InputType, prompt: String, handler:
* @param entity the entity to make flee
* @param from the entity to flee from
*/
fun flee(entity: Entity, from: Entity){
fun flee(entity: Entity, from: Entity) {
lock(entity, 5)
face(entity, from, 5)
val diffX = entity.location.x - from.location.x
val diffY = entity.location.y - from.location.y
forceWalk(entity, entity.location.transform(diffX,diffY,0), "DUMB")
forceWalk(entity, entity.location.transform(diffX, diffY, 0), "DUMB")
}
/**
@@ -1183,14 +1238,14 @@ fun flee(entity: Entity, from: Entity){
* @param entity the entity to submit the pulse to
* @param pulse the pulse to submit
*/
fun submitIndividualPulse(entity: Entity, pulse: Pulse){
fun submitIndividualPulse(entity: Entity, pulse: Pulse) {
entity.pulseManager.run(pulse)
}
/**
* Similar to submitIndividualPulse, but for non-repeating tasks, with a cleaner syntax.
*/
fun runTask(entity: Entity, delay: Int = 0, task: () -> Unit){
fun runTask(entity: Entity, delay: Int = 0, task: () -> Unit) {
entity.pulseManager.run(object : Pulse(delay) {
override fun pulse(): Boolean {
task.invoke()
@@ -1254,7 +1309,7 @@ fun finishQuest(player: Player, quest: String) {
* @param id the ID of the scenery to get the definition for.
* @return the scenery definition
*/
fun sceneryDefinition(id: Int): SceneryDefinition{
fun sceneryDefinition(id: Int): SceneryDefinition {
return SceneryDefinition.forId(id)
}
@@ -1263,7 +1318,7 @@ fun sceneryDefinition(id: Int): SceneryDefinition{
* @param zone the zone to register
* @param borders the ZoneBorders that compose the zone
*/
fun registerMapZone(zone: MapZone, borders: ZoneBorders){
fun registerMapZone(zone: MapZone, borders: ZoneBorders) {
ZoneBuilder.configure(zone)
zone.register(borders)
}
@@ -1275,8 +1330,8 @@ fun registerMapZone(zone: MapZone, borders: ZoneBorders){
* @param child the child on the interface to animate.
* @param anim the ID of the animation to use.
*/
fun animateInterface(player: Player, iface: Int, child: Int, anim: Int){
player.packetDispatch.sendAnimationInterface(anim,iface,child)
fun animateInterface(player: Player, iface: Int, child: Int, anim: Int) {
player.packetDispatch.sendAnimationInterface(anim, iface, child)
}
/**
@@ -1284,15 +1339,15 @@ fun animateInterface(player: Player, iface: Int, child: Int, anim: Int){
* @param ladderLoc the location of the ladder/stairs object you want to climb.
* @param dest the destination for the climb.
*/
fun addClimbDest(ladderLoc: Location, dest: Location){
SpecialLadders.add(ladderLoc,dest)
fun addClimbDest(ladderLoc: Location, dest: Location) {
SpecialLadders.add(ladderLoc, dest)
}
/**
* Sends a news announcement in game chat.
* @param message the message to announce
*/
fun sendNews(message: String){
fun sendNews(message: String) {
Repository.sendNews(message, 12, "CC6600")
}
@@ -1301,9 +1356,9 @@ fun sendNews(message: String){
* @param gfx the Graphics object, or the Integer ID of the graphics, to send. Either works.
* @param location the location to send it to
*/
fun <G> sendGraphics(gfx: G, location: Location){
when(gfx){
is Int -> Graphics.send(Graphics(gfx),location)
fun <G> sendGraphics(gfx: G, location: Location) {
when (gfx) {
is Int -> Graphics.send(Graphics(gfx), location)
is Graphics -> Graphics.send(gfx, location)
}
}
@@ -1325,12 +1380,12 @@ fun getMasteredSkillNames(player: Player): List<String> {
val hasMastered = player.getSkills().masteredSkills > 0
val masteredSkills = ArrayList<String>()
if(hasMastered){
if (hasMastered) {
for ((skillId, skillName) in Skills.SKILL_NAME.withIndex()) {
//phil you were looping every skill and performing a string comparison (another loop) for every one here.
//that's some real shit code bro.
//you were also performing a dynamic level check rather than a static.
if(hasLevelStat(player, skillId, 99)){
if (hasLevelStat(player, skillId, 99)) {
masteredSkills.add(skillName)
}
}
@@ -1339,35 +1394,137 @@ fun getMasteredSkillNames(player: Player): List<String> {
}
/**
* Dumps the given player's given container into that player's bank.
* Empties the provided container into the player's bank.
* @param player the player
* @param container the player's container to dump.
* @param container the container to be emptied.
* @return The amount of items which were successfully transferred to the bank.
*
* @author ceik
* @author James Triantafylos
* @author vddCore
*/
fun dumpContainer(player: Player, container: core.game.container.Container) {
fun dumpContainer(player: Player, container: core.game.container.Container): Int {
val bank = player.bank
var dumpedCount = 0
run beginDepositing@{
container.toArray().filterNotNull().forEach { item ->
if (!bank.hasSpaceFor(item)) {
player.packetDispatch.sendMessage("You have no more space in your bank.")
return
sendMessage(player, "You have no more space in your bank.")
return@beginDepositing
}
if (!bank.canAdd(item)) {
player.packetDispatch.sendMessage("A magical force prevents you from banking your " + item.name + ".")
return
sendMessage(player, "A magical force prevents you from banking the ${item.name}.")
return@forEach
} else {
if (container is EquipmentContainer) {
if(!InteractionListeners.run(item.id,player,item,false)) {
player.packetDispatch.sendMessage("A magical force prevents you from removing that item.")
return
if (!InteractionListeners.run(item.id, player, item, false)) {
sendMessage(player, "A magical force prevents you from removing your ${item.name}.")
return@forEach
}
}
container.remove(item)
bank.add(if (item.definition.isUnnoted) item else Item(item.noteChange, item.amount))
bank.add(unnote(item))
dumpedCount++
}
}
}
container.update()
bank.update()
return dumpedCount
}
/**
* Attempts to empty the player's Beast of Burden's inventory
* into the player's bank.
*
* @param player The player whose Beast of Burden's inventory to empty.
*
* @author vddCore
*/
fun dumpBeastOfBurden(player: Player) {
val famMan = player.familiarManager
if (!famMan.hasFamiliar()) {
sendMessage(player, "You don't have a familiar.")
return
}
if (famMan.familiar !is BurdenBeast) {
sendMessage(player, "Your familiar is not a Beast of Burden.")
return
}
val beast: BurdenBeast = (famMan.familiar as BurdenBeast)
if (beast.container.isEmpty) {
sendMessage(player, "Your familiar's inventory is empty.")
return
}
val itemCount = beast.container.itemCount()
val dumpedCount = dumpContainer(player, beast.container)
when {
dumpedCount == itemCount -> sendMessage(player, "Your familiar's inventory was deposited into your bank.")
dumpedCount > 0 -> {
val remainPhrase = when {
(itemCount - dumpedCount == 1) -> "item remains"
else -> "items remain"
}
sendMessage(player, "${itemCount - dumpedCount} $remainPhrase in your familiar's inventory.")
}
}
}
/**
* Converts an item into its noted representation.
*
* @param item The item to convert.
* @return Noted form of the item or the item itself if it's already, or cannot be, noted.
*
* @author vddCore
*/
fun note(item: Item): Item {
if (!item.definition.isUnnoted)
return item
if (item.definition.noteId < 0)
return item
return Item(item.definition.noteId, item.amount, item.charge)
}
/**
* Converts a noted item into its unnoted representation.
*
* @param item The item to convert.
* @return Unnoted form of the item, or the item itself if it's already unnoted.
*
* @author vddCore
*/
fun unnote(item: Item): Item {
if (item.definition.isUnnoted)
return item
return Item(item.noteChange, item.amount, item.charge)
}
/**
* Checks if the player has the Seal of Passage equipped or if it's present in the inventory.
*
* @param player The player to inspect for item's presence.
* @return True if Seal of Passage present, false otherwise.
*/
fun hasSealOfPassage(player: Player): Boolean {
return isEquipped(player, Items.SEAL_OF_PASSAGE_9083)
|| inInventory(player, Items.SEAL_OF_PASSAGE_9083)
}
/**
@@ -1387,13 +1544,12 @@ fun Player.getCutsceneStage(): Int {
return getAttribute(this, Cutscene.ATTRIBUTE_CUTSCENE_STAGE, 0)
}
fun getServerConfig() : Toml
{
fun getServerConfig(): Toml {
return ServerConfigParser.tomlData ?: Toml()
}
fun getPathableRandomLocalCoordinate(target: Entity, radius: Int, center: Location, maxAttempts: Int = 3): Location {
val swCorner = center.transform(-radius,-radius, center.z)
val swCorner = center.transform(-radius, -radius, center.z)
val neCorner = center.transform(radius, radius, center.z)
val borders = ZoneBorders(swCorner.x, swCorner.y, neCorner.x, neCorner.y, center.z)
+1
View File
@@ -1,6 +1,7 @@
package api
enum class InputType {
AMOUNT,
NUMERIC,
STRING_SHORT,
STRING_LONG,
@@ -1,5 +1,6 @@
package api.events
import core.game.component.Component
import core.game.node.Node
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
@@ -14,3 +15,5 @@ data class ButtonClickedEvent(val iface: Int, val buttonId: Int) : Event
data class UsedWithEvent(val used: Int, val with: Int) : Event
data class SelfDeath(val killer: Entity) : Event
data class TickEvent(val worldTicks: Int) : Event
data class InterfaceOpenEvent(val component: Component) : Event
data class InterfaceCloseEvent(val component: Component) : Event
@@ -0,0 +1,56 @@
package core.net.packet.`in`
import api.sendDialogue
import core.game.node.entity.player.Player
import core.net.packet.IncomingPacket
import core.net.packet.IoBuffer
import core.tools.StringUtils
/**
* Handles an incoming script execution request packet.
*
* @author vddCore
*/
class RunScriptPacketHandler : IncomingPacket {
private fun processInput(player: Player, value: Any, script: ((Any) -> Boolean)) {
if (value is Int && value <= 0) return
var input = value
if (player.getAttribute("parseamount", false)) {
input = value.toString().lowercase()
if (!input.matches(Regex("^(\\d+)(k+|m+)?$"))) {
sendDialogue(player, "That doesn't look right. Please try again.")
return
}
input = input.replace("k", "000").replace("m", "000000")
}
try {
script(input)
} catch (_: NumberFormatException) {
sendDialogue(player, "That number's a bit large, don't you think?")
}
}
override fun decode(player: Player, opcode: Int, buffer: IoBuffer) {
val script: ((Any) -> Boolean)? = player.getAttribute("runscript", null)
if (script == null || player.locks.isInteractionLocked)
return
val value: Any = when(opcode) {
244 -> StringUtils.longToString(buffer.long)
65 -> buffer.string
else -> buffer.int // Handles OpCode 23 and other cases.
}
processInput(player, value, script)
player.removeAttribute("parseamount")
player.removeAttribute("runscript")
}
}
@@ -110,6 +110,9 @@ class ServerConstants {
@JvmField
var BANK_SIZE: Int = 496
@JvmField
var BANK_BOOTH_QUICK_OPEN: Boolean = false
@JvmField
var GE_AUTOSAVE_FREQUENCY = secondsToTicks(3600) //1 hour
@@ -12,4 +12,6 @@ object Event {
@JvmStatic val UsedWith = UsedWithEvent::class.java
@JvmStatic val SelfDeath = SelfDeath::class.java
@JvmStatic val Tick = TickEvent::class.java
@JvmStatic val InterfaceOpened = InterfaceOpenEvent::class.java
@JvmStatic val InterfaceClosed = InterfaceCloseEvent::class.java
}
@@ -0,0 +1,57 @@
package rs09.game.content.dialogue
import api.*
import core.game.content.dialogue.DialoguePlugin
import core.game.node.entity.player.Player
import core.plugin.Initializable
import rs09.tools.START_DIALOGUE
/**
* Represents the dialogue shown when the user presses
* "Deposit Beast of Burden" button on the Bank Interface.
*
* @author vddCore
*/
class BankDepositDialogue : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
START_DIALOGUE -> options(
"Deposit Inventory",
"Deposit Worn Equipment",
"Deposit Beast of Burden",
"Cancel"
).also { stage++ }
1 -> when (buttonID) {
1 -> player?.let {
end()
if (it.inventory.isEmpty) {
sendMessage(it, "You have nothing in your inventory that you can deposit.")
} else {
dumpContainer(it, it.inventory)
}
}
2 -> player?.let {
end()
if (it.equipment.isEmpty) {
sendMessage(it, "You have no equipment that you can deposit.")
} else {
dumpContainer(it, it.equipment)
}
}
3 -> player?.let {
end()
dumpBeastOfBurden(it)
}
4 -> end()
}
}
}
}
@@ -0,0 +1,57 @@
package rs09.game.content.dialogue
import api.*
import core.game.content.dialogue.DialogueInterpreter
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.item.Item
import org.rs09.consts.Components
import org.rs09.consts.Items
import rs09.tools.START_DIALOGUE
/**
* Represents the dialogue shown when the user presses
* the "?" button on the Bank Interface.
*
* @author vddCore
*/
class BankHelpDialogue : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
START_DIALOGUE -> options(
"Check Bank Value",
"Banking Assistance",
"Close"
).also { stage++ }
1 -> when (buttonID) {
1 -> player?.let {
end()
val wealth = it.bank.wealth
if (wealth > 0) {
val word = if (wealth != 1) "coins" else "coin"
sendItemDialogue(
it,
Item(Items.COINS_995, wealth),
"<br>Your bank is worth <col=a52929>${wealth}</col> ${word}."
)
} else {
sendDialogue(it, "You have no valuables in your bank.")
}
}
2 -> player?.let {
end()
it.bank.close()
openInterface(it, Components.BANK_V2_HELP_767)
}
3 -> end()
}
}
}
}
@@ -1,55 +0,0 @@
package rs09.game.content.dialogue
import api.*
import core.game.content.dialogue.DialoguePlugin
import core.game.node.entity.player.Player
import core.plugin.Initializable
@Initializable
/**
* Represents the dialogue plugin used to handle the deposit all/deposit inventory/etc button
* @author Splinter
* @author James Triantafylos
*/
class DepositAllDialogue(player: Player? = null) : DialoguePlugin(player) {
val ID = 628371
override fun newInstance(player: Player?): DialoguePlugin {
return DepositAllDialogue(player)
}
override fun open(vararg args: Any?): Boolean {
options("Deposit Inventory", "Deposit Equipment", "Deposit Beast of Burden", "Cancel")
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (buttonId) {
1 -> {
if (player.inventory.isEmpty) {
player.packetDispatch.sendMessage("You have nothing in your inventory to deposit.")
} else {
dumpContainer(player, player.inventory)
}
}
2 -> {
if (player.equipment.isEmpty) {
player.packetDispatch.sendMessage("You have no equipment to deposit.")
} else {
dumpContainer(player, player.equipment)
}
}
3 -> {
player.familiarManager.dumpBob()
}
4 -> {
}
}
end()
return true
}
override fun getIds(): IntArray {
return intArrayOf(ID)
}
}
@@ -18,10 +18,12 @@ abstract class DialogueFile {
var dialoguePlugin: DialoguePlugin? = null
abstract fun handle(componentID: Int, buttonID: Int)
fun load(player: Player, npc: NPC?, interpreter: DialogueInterpreter): DialogueFile{
this.player = player
this.npc = npc
this.interpreter = interpreter
return this
}
@@ -1,25 +1,24 @@
package rs09.game.content.dialogue.region.lunarisle
import api.hasSealOfPassage
import core.game.content.dialogue.DialoguePlugin
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import rs09.game.ge.GrandExchangeRecords
/**
* @author qmqz
*/
@Initializable
class SirsalBankerDialogue(player: Player? = null) : DialoguePlugin(player){
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
if (player.inventory.contains(Items.SEAL_OF_PASSAGE_9083, 1) || player.equipment.contains(Items.SEAL_OF_PASSAGE_9083, 1)) {
if (hasSealOfPassage(player)) {
npc(FacialExpression.FRIENDLY, "Good day, how may I help you?").also { stage = 0 }
} else {
player(FacialExpression.FRIENDLY, "Hi, I...").also { stage = 2 }
@@ -239,7 +239,7 @@ class PeerTheSeerDialogue(player: Player? = null) : DialoguePlugin(player) {
3 -> playerl(FacialExpression.HAPPY,"Nothing really, I just stopped by to say hello").also { stage = 160 }
}
202 -> npcl(FacialExpression.HAPPY,"Of course, ${player.getAttribute("fremennikname","dingle")}. I am always happy to aid those who have earned the right to wear Fremennik sea boots.").also {
BankingPlugin.BankDepositInterface()
player.bank.openDepositBox()
stage = 1000
}
@@ -0,0 +1,69 @@
package rs09.game.interaction.inter
import api.*
import api.sendMessage
import core.game.component.Component
import core.game.node.entity.player.Player
import core.game.node.entity.skill.summoning.familiar.FamiliarManager
import org.rs09.consts.Animations
import org.rs09.consts.Components
import rs09.game.interaction.InterfaceListener
import rs09.game.interaction.util.BankUtils
private const val BUTTON_DEPOSIT_BOB = 13
private const val MENU_ELEMENT = 11
private const val OP_AMOUNT_ONE = 155
private const val OP_AMOUNT_FIVE = 196
private const val OP_AMOUNT_TEN = 124
private const val OP_AMOUNT_ALL = 199
private const val OP_AMOUNT_X = 234
private const val OP_EXAMINE = 168
/**
* Allows the user to interact with the
* Bank Deposit Box interface
*
* @author vddCore
*/
class BankDepositBoxInterface : InterfaceListener {
private fun handleDepositBoxMenu(player: Player, component: Component, opcode: Int, buttonID: Int, slot: Int, itemID: Int): Boolean {
val item = player.inventory.get(slot)
?: return true
if (opcode == OP_EXAMINE) {
sendMessage(player, item.definition.examine)
return true
}
runWorldTask {
when (opcode) {
OP_AMOUNT_ONE -> player.bank.addItem(slot, 1)
OP_AMOUNT_FIVE -> player.bank.addItem(slot, 5)
OP_AMOUNT_TEN -> player.bank.addItem(slot, 10)
OP_AMOUNT_X -> BankUtils.transferX(
player,
slot,
false,
// Needs to have a callback here because the depositing moment is independent from the world task.
player.bank::refreshDepositBoxInterface
)
OP_AMOUNT_ALL -> player.bank.addItem(slot, player.inventory.getAmount(item))
else -> player.debug("Unknown deposit box menu opcode $opcode")
}
player.bank.refreshDepositBoxInterface()
animate(player, Animations.HUMAN_BANK_DEPOSIT_BOX_834)
}
return true
}
override fun defineInterfaceListeners() {
on(Components.BANK_DEPOSIT_BOX_11, ::handleDepositBoxMenu)
on(Components.BANK_DEPOSIT_BOX_11, BUTTON_DEPOSIT_BOB) { player, _, _, _, _, _ ->
dumpBeastOfBurden(player); true
}
}
}
@@ -0,0 +1,163 @@
package rs09.game.interaction.inter
import api.*
import core.game.component.Component
import core.game.node.entity.player.Player
import org.rs09.consts.Components
import org.rs09.consts.Items
import rs09.ServerConstants
import rs09.game.content.dialogue.BankHelpDialogue
import rs09.game.content.dialogue.BankDepositDialogue
import rs09.game.interaction.InterfaceListener
import rs09.game.interaction.util.BankUtils
private const val MAIN_BUTTON_CLOSE = 10
private const val MAIN_BUTTON_INSERT_MODE = 14
private const val MAIN_BUTTON_NOTE_MODE = 16
private const val MAIN_BUTTON_BOB_DEPOSIT = 18
private const val MAIN_BUTTON_SEARCH_BANK = 20
private const val MAIN_BUTTON_HELP = 23
private const val MENU_ELEMENT = 73
private const val OP_AMOUNT_ONE = 155
private const val OP_AMOUNT_FIVE = 196
private const val OP_AMOUNT_TEN = 124
private const val OP_AMOUNT_LAST_X = 199
private const val OP_AMOUNT_X = 234
private const val OP_AMOUNT_ALL = 168
private const val OP_AMOUNT_ALL_BUT_ONE = 166
private const val OP_EXAMINE = 9
private const val BANK_TAB_1 = 41
private const val BANK_TAB_2 = 39
private const val BANK_TAB_3 = 37
private const val BANK_TAB_4 = 35
private const val BANK_TAB_5 = 33
private const val BANK_TAB_6 = 31
private const val BANK_TAB_7 = 29
private const val BANK_TAB_8 = 27
private const val BANK_TAB_9 = 25
private val BANK_TABS = intArrayOf(
BANK_TAB_1, BANK_TAB_2, BANK_TAB_3,
BANK_TAB_4, BANK_TAB_5, BANK_TAB_6,
BANK_TAB_7, BANK_TAB_8, BANK_TAB_9
)
private const val OP_SET_TAB = 155
private const val OP_COLLAPSE_TAB = 196
/**
* Allows the user to interact with the Bank Interface.
*
* @author vddCore
*/
class BankInterface : InterfaceListener {
private fun onBankInterfaceOpen(player: Player, component: Component): Boolean {
player.bank.sendBankSpace();
val settings = IfaceSettingsBuilder()
.enableAllOptions()
.enableSlotSwitch()
.setInterfaceEventsDepth(2)
.build()
player.packetDispatch.sendIfaceSettings(
settings,
73,
Components.BANK_V2_MAIN_762,
0,
ServerConstants.BANK_SIZE
)
return false
}
private fun handleTabInteraction(player: Player, component: Component, opcode: Int, buttonID: Int, slot: Int, itemID: Int): Boolean {
if (getAttribute(player, "search", false)) {
player.bank.reopen()
}
val clickedTabIndex = -((buttonID - 41) / 2)
when (opcode) {
OP_SET_TAB -> {
if (player.bank.tabIndex != clickedTabIndex) {
player.bank.tabIndex = clickedTabIndex
}
}
OP_COLLAPSE_TAB -> {
player.bank.collapseTab(clickedTabIndex)
}
}
return true
}
private fun handleBankMenu(player: Player, component: Component, opcode: Int, buttonID: Int, slot: Int, itemID: Int): Boolean {
val item = player.bank.get(slot)
?: return true
when (opcode) {
OP_AMOUNT_ONE -> runWorldTask { player.bank.takeItem(slot, 1) }
OP_AMOUNT_FIVE -> runWorldTask { player.bank.takeItem(slot, 5) }
OP_AMOUNT_TEN -> runWorldTask { player.bank.takeItem(slot, 10) }
OP_AMOUNT_LAST_X -> runWorldTask { player.bank.takeItem(slot, player.bank.lastAmountX) }
OP_AMOUNT_X -> runWorldTask { BankUtils.transferX(player, slot, true) }
OP_AMOUNT_ALL -> runWorldTask { player.bank.takeItem(slot, player.bank.getAmount(item)) }
OP_AMOUNT_ALL_BUT_ONE -> runWorldTask { player.bank.takeItem(slot, player.bank.getAmount(item) - 1) }
OP_EXAMINE -> sendMessage(player, item.definition.examine)
else -> player.debug("Unknown bank menu opcode $opcode")
}
return true
}
private fun handleInventoryMenu(player: Player, component: Component, opcode: Int, buttonID: Int, slot: Int, itemID: Int): Boolean {
val item = player.inventory.get(slot)
?: return true
when (opcode) {
OP_AMOUNT_ONE -> player.bank.addItem(slot, 1)
OP_AMOUNT_FIVE -> player.bank.addItem(slot, 5)
OP_AMOUNT_TEN -> player.bank.addItem(slot, 10)
OP_AMOUNT_LAST_X -> player.bank.addItem(slot, player.bank.lastAmountX)
OP_AMOUNT_X -> BankUtils.transferX(player, slot, false)
OP_AMOUNT_ALL -> player.bank.addItem(slot, player.inventory.getAmount(item))
OP_EXAMINE -> sendMessage(player, item.definition.examine)
else -> player.debug("Unknown inventory menu opcode $opcode")
}
return true
}
override fun defineInterfaceListeners() {
onOpen(Components.BANK_V2_MAIN_762, ::onBankInterfaceOpen)
on(Components.BANK_V2_MAIN_762) { player, component, opcode, buttonID, slot, itemID ->
when (buttonID) {
MAIN_BUTTON_HELP -> openDialogue(player, BankHelpDialogue())
MAIN_BUTTON_BOB_DEPOSIT -> openDialogue(player, BankDepositDialogue())
MAIN_BUTTON_INSERT_MODE -> player.bank.isInsertItems = !player.bank.isInsertItems
MAIN_BUTTON_NOTE_MODE -> player.bank.isNoteItems = !player.bank.isNoteItems
MAIN_BUTTON_SEARCH_BANK -> setAttribute(player, "search", true)
MENU_ELEMENT -> handleBankMenu(player, component, opcode, buttonID, slot, itemID)
in BANK_TABS -> handleTabInteraction(player, component, opcode, buttonID, slot, itemID)
}
return@on true
}
on(Components.BANK_V2_HELP_767) { player, component, opcode, buttonID, slot, itemID ->
when (buttonID) {
MAIN_BUTTON_CLOSE -> player.bank.open()
}
return@on true
}
on(Components.BANK_V2_SIDE_763, ::handleInventoryMenu)
}
}
@@ -0,0 +1,109 @@
package rs09.game.interaction.npc
import api.getScenery
import api.location
import api.openDialogue
import core.game.node.Node
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.world.map.Direction
import core.game.world.map.Location
import core.game.world.map.path.Pathfinder
import org.rs09.consts.NPCs
import rs09.game.content.dialogue.region.lunarisle.SirsalBankerDialogue
import rs09.game.ge.GrandExchangeRecords
import rs09.game.interaction.InteractionListener
import rs09.game.interaction.`object`.BankBoothHandler
import rs09.game.node.entity.npc.other.BankerNPC
import rs09.game.system.SystemLogger
/**
* Allows the user to interact with banker NPC options.
*
* @author vddCore
*/
class BankerNPCListener : InteractionListener {
companion object {
val BANKER_NPCS = intArrayOf(
NPCs.BANKER_44, NPCs.BANKER_45, NPCs.BANKER_494, NPCs.BANKER_495, NPCs.BANKER_496, NPCs.BANKER_497,
NPCs.BANKER_498, NPCs.BANKER_499, NPCs.BANKER_1036, NPCs.BANKER_1360, NPCs.BANKER_2163, NPCs.BANKER_2164,
NPCs.BANKER_2354, NPCs.BANKER_2355, NPCs.BANKER_2568, NPCs.BANKER_2569, NPCs.BANKER_2570, NPCs.BANKER_3198,
NPCs.BANKER_3199, NPCs.BANKER_5258, NPCs.BANKER_5259, NPCs.BANKER_5260, NPCs.BANKER_5261, NPCs.BANKER_5776,
NPCs.BANKER_5777, NPCs.BANKER_5912, NPCs.BANKER_5913, NPCs.BANKER_6200, NPCs.BANKER_6532, NPCs.BANKER_6533,
NPCs.BANKER_6534, NPCs.BANKER_6535, NPCs.BANKER_6538, NPCs.BANKER_7445, NPCs.BANKER_7446, NPCs.BANKER_7605,
NPCs.BANK_TUTOR_4907,
NPCs.GHOST_BANKER_1702, NPCs.GNOME_BANKER_166, NPCs.NARDAH_BANKER_3046,
NPCs.OGRESS_BANKER_7049, NPCs.OGRESS_BANKER_7050, NPCs.SIRSAL_BANKER_4519,
NPCs.FADLI_958, NPCs.ARNOLD_LYDSPOR_3824, NPCs.MAGNUS_GRAM_5488
)
fun provideDestinationOverride(entity: Entity, node: Node): Location {
val npc = node as NPC
return when(npc.id) {
/* Ogress bankers are 2x2 with their spawn being offset to south-western tile. */
NPCs.OGRESS_BANKER_7049,
NPCs.OGRESS_BANKER_7050 -> npc.location.transform(3, 1, 0)
/* Magnus has no bank booth nearby so we need to handle that edge case here. */
NPCs.MAGNUS_GRAM_5488 -> npc.location.transform(Direction.NORTH, 2)
else -> {
if (npc is BankerNPC) {
npc.findAdjacentBankBoothLocation()?.let {
return it.second
}
}
val path = Pathfinder.find(entity, node)
if (path.isSuccessful) {
val pt = path.points.last
return Location(pt.x, pt.y)
}
return npc.location
}
}
}
}
override fun defineListeners() {
on(BANKER_NPCS, NPC, "bank") { player, node ->
val npc = node as NPC
if (BankerNPC.checkLunarIsleRestriction(player, node)) {
openDialogue(player, npc.id, npc)
return@on true
}
npc.faceLocation(null)
player.bank.open(); true
}
on(BANKER_NPCS, NPC, "collect") { player, node ->
val npc = node as NPC
if (BankerNPC.checkLunarIsleRestriction(player, node)) {
openDialogue(player, npc.id, npc)
return@on true
}
npc.faceLocation(null)
GrandExchangeRecords.getInstance(player).openCollectionBox(); true
}
on(BANKER_NPCS, NPC, "talk-to") { player, node ->
val npc = node as NPC
openDialogue(player, npc.id, npc); true
}
}
override fun defineDestinationOverrides() {
setDest(NPC, BANKER_NPCS, "bank", "collect", "talk-to", handler = ::provideDestinationOverride)
}
}
@@ -7,7 +7,6 @@ import rs09.game.content.activity.gnomecooking.*
import rs09.game.content.ame.RandomEventManager
import rs09.game.content.ame.RandomEvents
import rs09.game.interaction.InteractionListener
import rs09.game.system.SystemLogger
/**
* Handles the NPC talk-to option.
@@ -66,5 +65,7 @@ class NPCTalkListener : InteractionListener {
}
return@setDest node.location
}
setDest(NPC, BankerNPCListener.BANKER_NPCS, "talk-to", handler = BankerNPCListener::provideDestinationOverride)
}
}
@@ -0,0 +1,135 @@
package rs09.game.interaction.`object`
import api.openDialogue
import core.game.content.dialogue.DialogueInterpreter
import core.game.node.Node
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.world.map.Direction
import core.game.world.map.Location
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.ServerConstants
import rs09.game.ge.GrandExchangeRecords
import rs09.game.interaction.InteractionListener
import rs09.game.node.entity.npc.other.BankerNPC
import rs09.game.world.repository.Repository
/**
* Allows the user to interact with bank booths.
*
* @author vddCore
*/
class BankBoothHandler : InteractionListener {
companion object {
val BANK_BOOTHS = intArrayOf(
Scenery.BANK_BOOTH_2213, Scenery.BANK_BOOTH_2214, Scenery.BANK_BOOTH_3045, Scenery.BANK_BOOTH_5276,
Scenery.BANK_BOOTH_6084, Scenery.BANK_BOOTH_10517, Scenery.BANK_BOOTH_11338, Scenery.BANK_BOOTH_11402,
Scenery.BANK_BOOTH_11758, Scenery.BANK_BOOTH_12798, Scenery.BANK_BOOTH_12799, Scenery.BANK_BOOTH_12800,
Scenery.BANK_BOOTH_12801, Scenery.BANK_BOOTH_14367, Scenery.BANK_BOOTH_14368, Scenery.BANK_BOOTH_16700,
Scenery.BANK_BOOTH_18491, Scenery.BANK_BOOTH_19230, Scenery.BANK_BOOTH_20325, Scenery.BANK_BOOTH_20326,
Scenery.BANK_BOOTH_20327, Scenery.BANK_BOOTH_20328, Scenery.BANK_BOOTH_22819, Scenery.BANK_BOOTH_24914,
Scenery.BANK_BOOTH_25808, Scenery.BANK_BOOTH_26972, Scenery.BANK_BOOTH_29085, Scenery.BANK_BOOTH_30015,
Scenery.BANK_BOOTH_30016, Scenery.BANK_BOOTH_34205, Scenery.BANK_BOOTH_34752, Scenery.BANK_BOOTH_35647,
Scenery.BANK_BOOTH_35648, Scenery.BANK_BOOTH_36262, Scenery.BANK_BOOTH_36786, Scenery.BANK_BOOTH_37474
)
}
/**
* Searches an area in the order described
* by each number with X being the location
* of node being interacted with.
*
* [1]
* [4][X][2]
* [3]
*/
private fun locateAdjacentBankerLinear(node: Node): NPC? {
for (dir in arrayOf(Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST)) {
Repository.findNPC(node.location.transform(dir))?.let { return it }
}
return null
}
/**
* If size is 1 then the following method
* searches a square area in the following
* order with X being the location of node
* that was interacted with.
*
* ->[ ]
* [ X ]
* [ ]->
*
*/
private fun locateAdjacentBankerSquare(node: Node, size: Int = 1): NPC? {
for (y in (node.location.y - size)..(node.location.y + size)) {
for (x in (node.location.x - size)..(node.location.x + size)) {
Repository.findNPC(Location(x, y))?.let { return it }
}
}
return null
}
private fun tryInvokeBankerDialogue(player: Player, node: Node) {
/**
* First, we look for regular bankers that neatly stand in front of the bank booth.
* If that fails, we expand the search to a larger area.
*/
(locateAdjacentBankerLinear(node) ?: locateAdjacentBankerSquare(node, 2))?.let {
if (DialogueInterpreter.contains(it.id)) {
it.faceLocation(node.location)
openDialogue(player, it.id, NPC(it.id, it.location))
} else {
player.dialogueInterpreter.open(NPCs.BANKER_494)
}
}
}
private fun quickBankBoothUse(player: Player, node: Node): Boolean {
if (player.ironmanManager.checkRestriction(IronmanMode.ULTIMATE)) {
return true
}
if (BankerNPC.checkLunarIsleRestriction(player, node)) {
tryInvokeBankerDialogue(player, node)
return true
}
player.bank.open()
return true
}
private fun regularBankBoothUse(player: Player, node: Node): Boolean {
if (player.ironmanManager.checkRestriction(IronmanMode.ULTIMATE)) {
return true
}
if (ServerConstants.BANK_BOOTH_QUICK_OPEN) {
return quickBankBoothUse(player, node)
}
tryInvokeBankerDialogue(player, node)
return true
}
private fun collectBankBoothUse(player: Player, node: Node): Boolean {
if (BankerNPC.checkLunarIsleRestriction(player, node)) {
tryInvokeBankerDialogue(player, node)
return true
}
GrandExchangeRecords.getInstance(player).openCollectionBox()
return true
}
override fun defineListeners() {
on(BANK_BOOTHS, SCENERY, "use-quickly", "bank", handler = ::quickBankBoothUse)
on(BANK_BOOTHS, SCENERY, "use", handler = ::regularBankBoothUse)
on(BANK_BOOTHS, SCENERY, "collect", handler = ::collectBankBoothUse)
}
}
@@ -0,0 +1,39 @@
package rs09.game.interaction.`object`
import core.game.node.Node
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.IronmanMode
import org.rs09.consts.Scenery
import rs09.game.interaction.InteractionListener
private val BANK_CHESTS = intArrayOf(
Scenery.BANK_CHEST_3194,
Scenery.BANK_CHEST_4483,
Scenery.BANK_CHEST_10562,
Scenery.BANK_CHEST_14382,
Scenery.BANK_CHEST_16695,
Scenery.BANK_CHEST_16696,
Scenery.BANK_CHEST_21301,
Scenery.BANK_CHEST_27662,
Scenery.BANK_CHEST_27663
)
/**
* Allows the user to interact with Bank Chests.
*
* @author vddCore
*/
class BankChestHandler : InteractionListener {
private fun useBankChest(player: Player, node: Node): Boolean {
if (player.ironmanManager.checkRestriction(IronmanMode.ULTIMATE)) {
return true
}
player.bank.open()
return true
}
override fun defineListeners() {
on(BANK_CHESTS, SCENERY, "bank", "use", handler = ::useBankChest)
}
}
@@ -0,0 +1,60 @@
package rs09.game.interaction.`object`
import core.game.component.CloseEvent
import core.game.component.Component
import core.game.container.access.InterfaceContainer
import core.game.node.Node
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.IronmanMode
import org.rs09.consts.Components
import org.rs09.consts.Scenery
import rs09.game.interaction.InteractionListener
private val BANK_DEPOSIT_BOXES = intArrayOf(
Scenery.BANK_DEPOSIT_BOX_9398,
Scenery.BANK_DEPOSIT_BOX_20228,
Scenery.BANK_DEPOSIT_BOX_25937,
Scenery.BANK_DEPOSIT_BOX_26969,
Scenery.BANK_DEPOSIT_BOX_34755,
Scenery.BANK_DEPOSIT_BOX_36788,
Scenery.BANK_DEPOSIT_BOX_39830
)
/**
* Allows the user to interact with bank deposit boxes.
*
* @author vddCore
*/
class BankDepositBoxHandler : InteractionListener {
private fun openDepositBox(player: Player, node: Node) : Boolean {
if (player.ironmanManager.checkRestriction(IronmanMode.ULTIMATE)) {
return true
}
player.interfaceManager.open(Component(Components.BANK_DEPOSIT_BOX_11)).closeEvent = CloseEvent { p, _ ->
p.interfaceManager.openDefaultTabs()
return@CloseEvent true
}
player.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6)
InterfaceContainer.generateItems(
player,
player.inventory.toArray(),
arrayOf(
"Examine",
"Deposit-X",
"Deposit-All",
"Deposit-10",
"Deposit-5",
"Deposit-1"
), 11, 15, 5, 7
)
return true
}
override fun defineListeners() {
on(BANK_DEPOSIT_BOXES, SCENERY, "deposit", handler = ::openDepositBox)
}
}
@@ -0,0 +1,23 @@
package rs09.game.interaction.util
import api.InputType
import api.sendInputDialogue
import api.sendMessage
import core.game.node.entity.player.Player
object BankUtils {
fun transferX(player: Player, slot: Int, withdraw: Boolean, after: (() -> Unit)? = null) {
sendInputDialogue(player, InputType.AMOUNT, "Enter the amount:") { value ->
val number = Integer.parseInt(value.toString())
if (withdraw) {
player.bank.takeItem(slot, number)
} else {
player.bank.addItem(slot, number)
}
player.bank.updateLastAmountX(number)
after?.let { it() }
}
}
}
@@ -0,0 +1,77 @@
package rs09.game.node.entity.npc.other
import api.getScenery
import api.hasSealOfPassage
import core.game.content.dialogue.DialogueInterpreter
import core.game.node.Node
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.world.map.Direction
import core.game.world.map.Location
import core.plugin.Initializable
import rs09.game.interaction.npc.BankerNPCListener
import rs09.game.interaction.`object`.BankBoothHandler
private const val LUNAR_ISLE_BANK_REGION = 8253
@Initializable
class BankerNPC : AbstractNPC {
companion object {
/**
* This is poorly named, but performs a few checks to see if the player
* is trying to access the bank on the Lunar Isle and returns a boolean
* controlling whether or not to pass the quick bank or collection use.
*
* TODO
* The location of this method is shit too. Find a better place for it?
*/
fun checkLunarIsleRestriction(player: Player, node: Node): Boolean {
if (node.location.regionId != LUNAR_ISLE_BANK_REGION)
return false
if (!hasSealOfPassage(player)) {
return true
}
return false
}
}
//Constructor spaghetti because Arios I guess
constructor() : super(0, null)
private constructor(id: Int, location: Location) : super(id, location)
override fun construct(id: Int, location: Location, vararg objects: Any?): AbstractNPC {
return BankerNPC(id, location)
}
fun findAdjacentBankBoothLocation(): Pair<Direction, Location>? {
for (side in arrayOf(Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.EAST)) {
val boothLocation = location.transform(side)
val sceneryObject = getScenery(boothLocation)
if (sceneryObject != null && sceneryObject.id in BankBoothHandler.BANK_BOOTHS) {
return Pair(side, boothLocation.transform(side, 1))
}
}
return null
}
override fun init() {
super.init()
findAdjacentBankBoothLocation()?.let {
val (boothDirection, _) = it
direction = boothDirection
isWalks = false
setAttribute("facing_booth", true)
}
}
override fun getIds(): IntArray = BankerNPCListener.BANKER_NPCS
}
@@ -8,19 +8,24 @@ import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.entity.skill.slayer.Tasks
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Components
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.game.Event
import rs09.game.system.command.Privilege
class DiaryEventHook : LoginListener
{
private const val TASK_DRAYNOR_BANK = 15
class DiaryEventHook : LoginListener, Commands {
override fun login(player: Player) {
player.hook(Event.ResourceProduced, DiaryGatherHooks)
player.hook(Event.Teleport, DiaryTeleportHooks)
player.hook(Event.NPCKilled, DiaryCombatHooks)
player.hook(Event.FireLit, DiaryFireHooks)
player.hook(Event.Interaction, DiaryInteractionEvents)
player.hook(Event.InterfaceOpened, DiaryInterfaceOpenEvents)
player.hook(Event.InterfaceClosed, DiaryInterfaceCloseEvents)
}
companion object {
@@ -29,161 +34,223 @@ class DiaryEventHook : LoginListener
}
}
private object DiaryInteractionEvents : EventHook<InteractionEvent>
{
private object DiaryInterfaceCloseEvents : EventHook<InterfaceCloseEvent> {
override fun process(entity: Entity, event: InterfaceCloseEvent) {
// TODO("Not yet implemented")
}
}
private object DiaryInterfaceOpenEvents : EventHook<InterfaceOpenEvent> {
override fun process(entity: Entity, event: InterfaceOpenEvent) {
if (entity !is Player)
return
when (entity.viewport.region.id) {
12338 -> if (event.component.id == Components.BANK_V2_MAIN_762) {
finishTask(
entity,
DiaryType.LUMBRIDGE,
1,
TASK_DRAYNOR_BANK
)
}
}
}
}
private object DiaryInteractionEvents : EventHook<InteractionEvent> {
override fun process(entity: Entity, event: InteractionEvent) {
if(entity !is Player) return
if (entity !is Player) return
val regionId = entity.viewport.region.id
if(event.target is core.game.node.scenery.Scenery)
when(event.target.id)
{
11729, 11727 -> if(regionId == 11828) finishTask(entity, DiaryType.FALADOR, 0, 3)
11889 -> if(regionId == 11572 && isEquipped(entity, Items.PROSELYTE_SALLET_9672) && isEquipped(entity, Items.PROSELYTE_HAUBERK_9674) && isEquipped(entity, Items.PROSELYTE_CUISSE_9676)) finishTask(entity, DiaryType.FALADOR, 2, 0)
30941 -> if(regionId == 12184) finishTask(entity, DiaryType.FALADOR, 2, 6)
36771 -> if(regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 0, 0)
12537 -> if(regionId == 12337) finishTask(entity, DiaryType.LUMBRIDGE, 0, 11)
26934 -> if(regionId == 12342) finishTask(entity, DiaryType.VARROCK, 0, 10)
24350,24361 -> if(regionId == 12854) finishTask(entity, DiaryType.VARROCK, 0, 18)
in 115..122 -> if(event.option == "burst") finishTask(entity, DiaryType.FALADOR, 0, 12)
if (event.target is core.game.node.scenery.Scenery)
when (event.target.id) {
11729, 11727 -> if (regionId == 11828) finishTask(entity, DiaryType.FALADOR, 0, 3)
11889 -> if (regionId == 11572 && isEquipped(entity, Items.PROSELYTE_SALLET_9672) && isEquipped(
entity,
Items.PROSELYTE_HAUBERK_9674
) && isEquipped(entity, Items.PROSELYTE_CUISSE_9676)
) finishTask(entity, DiaryType.FALADOR, 2, 0)
30941 -> if (regionId == 12184) finishTask(entity, DiaryType.FALADOR, 2, 6)
36771 -> if (regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 0, 0)
12537 -> if (regionId == 12337) finishTask(entity, DiaryType.LUMBRIDGE, 0, 11)
26934 -> if (regionId == 12342) finishTask(entity, DiaryType.VARROCK, 0, 10)
24350, 24361 -> if (regionId == 12854) finishTask(entity, DiaryType.VARROCK, 0, 18)
in 115..122 -> if (event.option == "burst") finishTask(entity, DiaryType.FALADOR, 0, 12)
16149 -> finishTask(entity, DiaryType.VARROCK, 0, 4)
//2112 -> if()
}
}
}
private object DiaryFireHooks : EventHook<LitFireEvent>
{
private object DiaryFireHooks : EventHook<LitFireEvent> {
val lumCastleBorders = ZoneBorders(3216, 3207, 3225, 3233, 0)
override fun process(entity: Entity, event: LitFireEvent) {
if(entity !is Player) return
if (entity !is Player) return
val region = entity.viewport.region.id
when(region)
{
10806 -> if(event.logId == Items.MAGIC_LOGS_1513) finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 5)
12593,12849 -> if(event.logId == Items.LOGS_1511) finishTask(entity, DiaryType.LUMBRIDGE, 1, 9)
when (region) {
10806 -> if (event.logId == Items.MAGIC_LOGS_1513) finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 5)
12593, 12849 -> if (event.logId == Items.LOGS_1511) finishTask(entity, DiaryType.LUMBRIDGE, 1, 9)
else -> {
if(event.logId == Items.WILLOW_LOGS_1519 && lumCastleBorders.insideBorder(entity))
finishTask(entity, DiaryType.LUMBRIDGE,2 ,3)
if (event.logId == Items.WILLOW_LOGS_1519 && lumCastleBorders.insideBorder(entity))
finishTask(entity, DiaryType.LUMBRIDGE, 2, 3)
}
}
}
}
private object DiaryGatherHooks : EventHook<ResourceProducedEvent>
{
private object DiaryGatherHooks : EventHook<ResourceProducedEvent> {
override fun process(entity: Entity, event: ResourceProducedEvent) {
if(entity !is Player) return
if (entity !is Player) return
val regionId = entity.viewport.region.id
when(event.itemId)
{
when (event.itemId) {
//Cut a log from a teak tree
Items.TEAK_LOGS_6333 -> finishTask(entity, DiaryType.KARAMJA, 1, 7)
//Cut a log from a mahogany tree
Items.MAHOGANY_LOGS_6332 -> finishTask(entity, DiaryType.KARAMJA, 1, 8)
Items.LOGS_1511 -> {
//Cut down a dying tree in the Lumber Yard
if(event.source.id == Scenery.DYING_TREE_24168 && regionId == 13110)
if (event.source.id == Scenery.DYING_TREE_24168 && regionId == 13110)
finishTask(entity, DiaryType.VARROCK, 0, 6)
}
Items.YEW_LOGS_1515 -> {
if(regionId == 10806) {
setAttribute(entity, "/save:diary:seers:cut-yew", getAttribute(entity, "diary:seers:cut-yew", 0) + 1)
if (regionId == 10806) {
setAttribute(
entity,
"/save:diary:seers:cut-yew",
getAttribute(entity, "diary:seers:cut-yew", 0) + 1
)
if (getAttribute(entity, "diary:seers:cut-yew", 0) >= 5)
finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 1)
}
}
Items.WILLOW_LOGS_1519 -> if(regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 2, 6)
Items.WILLOW_LOGS_1519 -> if (regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 2, 6)
Items.RAW_MACKEREL_353 -> if(regionId == 11317) finishTask(entity, DiaryType.SEERS_VILLAGE, 0, 11)
Items.RAW_MACKEREL_353 -> if (regionId == 11317) finishTask(entity, DiaryType.SEERS_VILLAGE, 0, 11)
Items.RAW_BASS_363 -> if(regionId == 11317 && !getAttribute(entity, "diary:seers:bass-caught", false)) entity.setAttribute("/save:diary:seers:bass-caught", true)
Items.RAW_BASS_363 -> if (regionId == 11317 && !getAttribute(
entity,
"diary:seers:bass-caught",
false
)
) entity.setAttribute("/save:diary:seers:bass-caught", true)
Items.RAW_SHARK_383 -> if(regionId == 11317) setAttribute(entity, "/save:diary:seers:shark-caught", getAttribute(entity, "diary:seers:shark-caught", 0) + 1)
Items.RAW_SHARK_383 -> if (regionId == 11317) setAttribute(
entity,
"/save:diary:seers:shark-caught",
getAttribute(entity, "diary:seers:shark-caught", 0) + 1
)
Items.RAW_SHRIMPS_2514, Items.RAW_SHRIMPS_317 -> if(regionId == 12849) finishTask(entity, DiaryType.LUMBRIDGE, 0, 13)
Items.RAW_SHRIMPS_2514, Items.RAW_SHRIMPS_317 -> if (regionId == 12849) finishTask(
entity,
DiaryType.LUMBRIDGE,
0,
13
)
Items.RAW_PIKE_349 -> if(regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 1, 4)
Items.RAW_PIKE_349 -> if (regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 1, 4)
Items.RAW_SALMON_331 -> if(regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 2, 9)
Items.RAW_SALMON_331 -> if (regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 2, 9)
Items.RAW_TROUT_335 -> if(regionId == 12341) finishTask(entity, DiaryType.VARROCK, 0, 16)
Items.RAW_TROUT_335 -> if (regionId == 12341) finishTask(entity, DiaryType.VARROCK, 0, 16)
Items.IRON_ORE_440 -> {
if(regionId == 13108) finishTask(entity, DiaryType.VARROCK, 0, 2)
else if(regionId == 13107) finishTask(entity, DiaryType.LUMBRIDGE, 1, 0)
if (regionId == 13108) finishTask(entity, DiaryType.VARROCK, 0, 2)
else if (regionId == 13107) finishTask(entity, DiaryType.LUMBRIDGE, 1, 0)
}
Items.LIMESTONE_3211 -> if(regionId == 13366) finishTask(entity, DiaryType.VARROCK, 0, 15)
Items.LIMESTONE_3211 -> if (regionId == 13366) finishTask(entity, DiaryType.VARROCK, 0, 15)
Items.GOLD_ORE_444 -> if(regionId == 10802) finishTask(entity, DiaryType.KARAMJA, 0, 2)
Items.GOLD_ORE_444 -> if (regionId == 10802) finishTask(entity, DiaryType.KARAMJA, 0, 2)
Items.UNCUT_RED_TOPAZ_1629 -> if(regionId == 11310 || regionId == 11410) finishTask(entity, DiaryType.KARAMJA, 1, 18)
Items.UNCUT_RED_TOPAZ_1629 -> if (regionId == 11310 || regionId == 11410) finishTask(
entity,
DiaryType.KARAMJA,
1,
18
)
Items.SOFT_CLAY_1761 -> if(regionId == 12596) finishTask(entity, DiaryType.LUMBRIDGE, 0, 5)
Items.SOFT_CLAY_1761 -> if (regionId == 12596) finishTask(entity, DiaryType.LUMBRIDGE, 0, 5)
Items.COPPER_ORE_436 -> if(regionId == 12849) finishTask(entity, DiaryType.LUMBRIDGE, 0, 12)
Items.COPPER_ORE_436 -> if (regionId == 12849) finishTask(entity, DiaryType.LUMBRIDGE, 0, 12)
Items.SILVER_ORE_442 -> if(regionId == 13107) finishTask(entity, DiaryType.LUMBRIDGE, 2, 10)
Items.SILVER_ORE_442 -> if (regionId == 13107) finishTask(entity, DiaryType.LUMBRIDGE, 2, 10)
Items.COAL_453 -> if(regionId == 12593) finishTask(entity, DiaryType.LUMBRIDGE, 2, 11)
Items.COAL_453 -> if (regionId == 12593) finishTask(entity, DiaryType.LUMBRIDGE, 2, 11)
Items.BASS_365 -> if(regionId == 11317 && getAttribute(entity, "diary:seers:bass-caught", false)) finishTask(entity, DiaryType.SEERS_VILLAGE, 1, 11)
Items.BASS_365 -> if (regionId == 11317 && getAttribute(
entity,
"diary:seers:bass-caught",
false
)
) finishTask(entity, DiaryType.SEERS_VILLAGE, 1, 11)
Items.SHARK_385 -> if(regionId == 11317 && getAttribute(entity, "diary:seers:shark-cooked", false) && isEquipped(entity, Items.COOKING_GAUNTLETS_775)) entity.incrementAttribute("/save:diary:seers:shark-cooked")
Items.SHARK_385 -> if (regionId == 11317 && getAttribute(
entity,
"diary:seers:shark-cooked",
false
) && isEquipped(entity, Items.COOKING_GAUNTLETS_775)
) entity.incrementAttribute("/save:diary:seers:shark-cooked")
Items.LOBSTER_379 -> if(event.source.id == Scenery.COOKING_RANGE_114) finishTask(entity, DiaryType.LUMBRIDGE, 2, 4)
Items.LOBSTER_379 -> if (event.source.id == Scenery.COOKING_RANGE_114) finishTask(
entity,
DiaryType.LUMBRIDGE,
2,
4
)
}
when(event.original)
{
Items.RAW_RAT_MEAT_2134 -> if((regionId == 12593 || regionId == 12849) && event.itemId == Items.COOKED_MEAT_2142) finishTask(entity, DiaryType.LUMBRIDGE, 1, 10)
when (event.original) {
Items.RAW_RAT_MEAT_2134 -> if ((regionId == 12593 || regionId == 12849) && event.itemId == Items.COOKED_MEAT_2142) finishTask(
entity,
DiaryType.LUMBRIDGE,
1,
10
)
}
if(getAttribute(entity, "diary:seers:shark-caught", 0) >= 5)
if (getAttribute(entity, "diary:seers:shark-caught", 0) >= 5)
finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 7)
if(getAttribute(entity, "diary:seers:shark-cooked", 0) >= 5)
if (getAttribute(entity, "diary:seers:shark-cooked", 0) >= 5)
finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 8)
if((regionId == 12593 || regionId == 12849) && event.source.name.startsWith("dead", true))
if ((regionId == 12593 || regionId == 12849) && event.source.name.startsWith("dead", true))
finishTask(entity, DiaryType.LUMBRIDGE, 1, 8)
if(event.source.id == NPCs.FISHING_SPOT_333 && entity.zoneMonitor.isInZone("karamja"))
if (event.source.id == NPCs.FISHING_SPOT_333 && entity.zoneMonitor.isInZone("karamja"))
finishTask(entity, DiaryType.KARAMJA, 0, 6)
if(event.source.id == Scenery.YEW_TREE_8513 && regionId == 11828)
if (event.source.id == Scenery.YEW_TREE_8513 && regionId == 11828)
finishTask(entity, DiaryType.FALADOR, 2, 3)
if(event.source.id == Scenery.COOKING_RANGE_114 && regionId == 12850)
if (event.source.id == Scenery.COOKING_RANGE_114 && regionId == 12850)
finishTask(entity, DiaryType.LUMBRIDGE, 0, 7)
}
}
private object DiaryTeleportHooks : EventHook<TeleportEvent>
{
private object DiaryTeleportHooks : EventHook<TeleportEvent> {
override fun process(entity: Entity, event: TeleportEvent) {
TODO("Not yet implemented")
}
}
private object DiaryCombatHooks : EventHook<NPCKillEvent>
{
private object DiaryCombatHooks : EventHook<NPCKillEvent> {
val faladorDucks = intArrayOf(NPCs.DUCK_46, NPCs.DUCK_2693, NPCs.DUCK_6113)
val lumbridgeCows = intArrayOf(81, 397, 955, 1766, 1767, 3309)
val elementalNPCs = intArrayOf(1019, 1020, 1021, 1022)
val wyverns = Tasks.SKELETAL_WYVERN.npcs
val metalDragons = intArrayOf(NPCs.BRONZE_DRAGON_1590, NPCs.IRON_DRAGON_1591, NPCs.STEEL_DRAGON_1592, NPCs.STEEL_DRAGON_3590)
val metalDragons =
intArrayOf(NPCs.BRONZE_DRAGON_1590, NPCs.IRON_DRAGON_1591, NPCs.STEEL_DRAGON_1592, NPCs.STEEL_DRAGON_3590)
val lumZombies = intArrayOf(NPCs.ZOMBIE_73, NPCs.ZOMBIE_74)
override fun process(entity: Entity, event: NPCKillEvent) {
if(entity !is Player) return
when(event.npc.id)
{
if (entity !is Player) return
when (event.npc.id) {
//FALADOR LEVEL 0 TASK 10
in faladorDucks -> {
if(entity.location.withinDistance(Location(2991, 3383, 0)))
if (entity.location.withinDistance(Location(2991, 3383, 0)))
finishTask(entity, DiaryType.FALADOR, 0, 9)
}
@@ -195,22 +262,21 @@ class DiaryEventHook : LoginListener
}
NPCs.JOGRE_113 -> {
if(entity.viewport.region.id == 11412)
if (entity.viewport.region.id == 11412)
finishTask(entity, DiaryType.KARAMJA, 0, 9)
}
in elementalNPCs -> {
if(!entity.location.withinDistance(Location(2719,9889,0), 100))
if (!entity.location.withinDistance(Location(2719, 9889, 0), 100))
return
when(event.npc.id)
{
when (event.npc.id) {
1019 -> setAttribute(entity, "/save:diary:seers:elemental:fire", true)
1020 -> setAttribute(entity, "/save:diary:seers:elemental:earth", true)
1021 -> setAttribute(entity, "/save:diary:seers:elemental:air", true)
1022 -> setAttribute(entity, "/save:diary:seers:elemental:water", true)
}
for (element in arrayOf("fire", "earth", "air", "water"))
if(!getAttribute(entity, "diary:seers:$element", false))
if (!getAttribute(entity, "diary:seers:$element", false))
return
finishTask(entity, DiaryType.SEERS_VILLAGE, 1, 4)
}
@@ -218,31 +284,64 @@ class DiaryEventHook : LoginListener
NPCs.KET_ZEK_2743, NPCs.KET_ZEK_2744 -> finishTask(entity, DiaryType.KARAMJA, 2, 1)
in metalDragons -> {
if(entity.viewport.region.id == 10899 || entity.viewport.region.id == 10900)
if (entity.viewport.region.id == 10899 || entity.viewport.region.id == 10900)
finishTask(entity, DiaryType.KARAMJA, 2, 9)
}
in wyverns -> finishTask(entity, DiaryType.FALADOR, 2, 8)
in lumZombies -> {
if(entity.viewport.region.id == 12438 || entity.viewport.region.id == 12439)
if (entity.viewport.region.id == 12438 || entity.viewport.region.id == 12439)
finishTask(entity, DiaryType.LUMBRIDGE, 1, 18)
}
NPCs.GIANT_RAT_86 -> {
if(entity.viewport.region.id == 12593 || entity.viewport.region.id == 12849)
if (entity.viewport.region.id == 12593 || entity.viewport.region.id == 12849)
finishTask(entity, DiaryType.LUMBRIDGE, 1, 7)
}
NPCs.TOWER_ARCHER_688 -> setAttribute(entity, "/save:diary:seers:tower-archers", getAttribute(entity, "diary:seers:tower-archers", 0) or 1)
NPCs.TOWER_ARCHER_689 -> setAttribute(entity, "/save:diary:seers:tower-archers", getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 1))
NPCs.TOWER_ARCHER_690 -> setAttribute(entity, "/save:diary:seers:tower-archers", getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 2))
NPCs.TOWER_ARCHER_691 -> setAttribute(entity, "/save:diary:seers:tower-archers", getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 3))
NPCs.TOWER_ARCHER_688 -> setAttribute(
entity,
"/save:diary:seers:tower-archers",
getAttribute(entity, "diary:seers:tower-archers", 0) or 1
)
NPCs.TOWER_ARCHER_689 -> setAttribute(
entity,
"/save:diary:seers:tower-archers",
getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 1)
)
NPCs.TOWER_ARCHER_690 -> setAttribute(
entity,
"/save:diary:seers:tower-archers",
getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 2)
)
NPCs.TOWER_ARCHER_691 -> setAttribute(
entity,
"/save:diary:seers:tower-archers",
getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 3)
)
}
if(getAttribute(entity,"diary:seers:tower-archers", 0) == 0xF)
if (getAttribute(entity, "diary:seers:tower-archers", 0) == 0xF)
finishTask(entity, DiaryType.SEERS_VILLAGE, 1, 6)
}
}
override fun defineCommands() {
define("cleardiary", Privilege.ADMIN) { player, _ ->
// I know this sucks but it's only for debugging.
// Please don't slap me, daddy.
//
for (type in DiaryType.values()) {
val diary = player.achievementDiaryManager.getDiary(type)
for (level in 0 until diary.levelStarted.size) {
for (task in 0 until diary.taskCompleted[level].size) {
diary.resetTask(player, level, task)
}
}
}
sendMessage(player, "All achievement diaries cleared successfully.")
}
}
}
@@ -38,6 +38,10 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
}
}
define("region") {player, args ->
sendMessage(player, "Region ID: ${player.viewport.region.regionId}")
}
define("spellbook"){player, args ->
if(args.size < 2){
reject(player,"Usage: ::spellbook [int]. 0 = MODERN, 1 = ANCIENTS, 2 = LUNARS")
@@ -116,6 +116,7 @@ object ServerConfigParser {
ServerConstants.RULES_AND_INFO_ENABLED = data.getBoolean("world.show_rules", true)
ServerConstants.BOTS_INFLUENCE_PRICE_INDEX = data.getBoolean("world.bots_influence_ge_price", true)
ServerConstants.REVENANT_POPULATION = data.getLong("world.revenant_population", 30L).toInt()
ServerConstants.BANK_BOOTH_QUICK_OPEN = data.getBoolean("world.bank_booth_quick_open", false)
ServerConstants.DISCORD_GE_WEBHOOK = data.getString("server.discord_webhook", "")
}