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 builddir
logs logs
out/
Management-Server/target/* Management-Server/target/*
Management-Server/.gradle Management-Server/.gradle
Management-Server/build/ Management-Server/build/
@@ -11,6 +12,9 @@ Server/**/*.class
Server/build/ Server/build/
Server/.gradle/ Server/.gradle/
Server/data/eco/grand_exchange_db.emp 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 Server/ge_test.db
Management-Server/managementprops/ Management-Server/managementprops/
Server/worldprops/ Server/worldprops/
@@ -25,3 +29,4 @@ gradle
**/*.swp **/*.swp
**/*.swo **/*.swo
build/kotlin/sessions/ build/kotlin/sessions/
**/*.iml
@@ -91,7 +91,27 @@ public final class BankContainer extends Container {
return true; return true;
}); });
player.getInterfaceManager().removeTabs(0, 1, 2, 3, 4, 5, 6); 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) { public void setTabIndex(int tabIndex) {
this.tabIndex = 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; package core.game.content.zone.phasmatys;
import static api.ContentAPIKt.*; import static api.ContentAPIKt.*;
import core.game.content.global.Bones; import core.game.content.global.Bones;
import core.game.content.global.action.ClimbActionHandler; import core.game.content.global.action.ClimbActionHandler;
import core.game.interaction.Option; 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.game.world.update.flag.context.Animation;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.plugin.Plugin; import core.plugin.Plugin;
import org.rs09.consts.NPCs;
import rs09.plugin.ClassScanner; import rs09.plugin.ClassScanner;
/** /**
@@ -65,6 +67,13 @@ public final class PhasmatysZone extends MapZone implements Plugin<Object> {
player = e.asPlayer(); player = e.asPlayer();
if (target instanceof NPC) { if (target instanceof NPC) {
NPC npc = (NPC) target; 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)) { if ((npc.getName().toLowerCase().contains("ghost") || npc.getName().equalsIgnoreCase("velorina") || npc.getName().contains("husband")) && !hasAmulet(player)) {
player.getDialogueInterpreter().open("ghosty dialogue", target); player.getDialogueInterpreter().open("ghosty dialogue", target);
return true; return true;
@@ -76,13 +85,13 @@ public final class PhasmatysZone extends MapZone implements Plugin<Object> {
return true; return true;
case 5267: case 5267:
player.animate(Animation.create(536)); player.animate(Animation.create(536));
sendMessage(player, "The trapdoor opens..."); sendMessage(player, "The trapdoor opens...");
SceneryBuilder.replace((Scenery) target, ((Scenery) target).transform(5268)); SceneryBuilder.replace((Scenery) target, ((Scenery) target).transform(5268));
return true; return true;
case 5268: case 5268:
if (option.getName().equals("Close")) { if (option.getName().equals("Close")) {
player.animate(Animation.create(535)); player.animate(Animation.create(535));
sendMessage(player, "You close the trapdoor."); sendMessage(player, "You close the trapdoor.");
SceneryBuilder.replace((Scenery) target, ((Scenery) target).transform(5267)); SceneryBuilder.replace((Scenery) target, ((Scenery) target).transform(5267));
} else { } else {
sendMessage(player, "You climb down through the trapdoor..."); sendMessage(player, "You climb down through the trapdoor...");
@@ -94,11 +103,11 @@ public final class PhasmatysZone extends MapZone implements Plugin<Object> {
SceneryBuilder.replace(target.asScenery(), target.asScenery().transform(7435)); SceneryBuilder.replace(target.asScenery(), target.asScenery().transform(7435));
} }
break; break;
case 7435: // open trapdoor in bar case 7435: // open trapdoor in bar
if (option.getName().equalsIgnoreCase("close")) { if (option.getName().equalsIgnoreCase("close")) {
SceneryBuilder.replace(target.asScenery(), target.asScenery().transform(7434)); SceneryBuilder.replace(target.asScenery(), target.asScenery().transform(7434));
} }
break; break;
case 9308: case 9308:
if (player.getSkills().getStaticLevel(Skills.AGILITY) < 58) { if (player.getSkills().getStaticLevel(Skills.AGILITY) < 58) {
player.sendMessage("You need an agility level of at least 58 to climb down this wall."); player.sendMessage("You need an agility level of at least 58 to climb down this wall.");
@@ -255,9 +264,9 @@ public final class PhasmatysZone extends MapZone implements Plugin<Object> {
/** /**
* Checks if bones are in the hopper. * Checks if bones are in the hopper.
* *
* @param player the player. * @param player the player.
* @param inHopper in the hopper or in the bin. * @param inHopper in the hopper or in the bin.
* @param object the object. * @param object the object.
* @return {@code True} if so. * @return {@code True} if so.
*/ */
public static boolean hasBones(Player player, Scenery object, boolean inHopper) { public static boolean hasBones(Player player, Scenery object, boolean inHopper) {
@@ -1,44 +1,21 @@
package core.game.interaction.object; 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.DialoguePlugin;
import core.game.content.dialogue.FacialExpression; import core.game.content.dialogue.FacialExpression;
import core.game.interaction.OptionHandler; import core.game.interaction.OptionHandler;
import core.game.node.Node; import core.game.node.Node;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.npc.NPC; import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.IronmanMode; import core.game.node.entity.player.link.IronmanMode;
import core.game.node.entity.player.link.appearance.Gender; import core.game.node.entity.player.link.appearance.Gender;
import core.game.node.entity.player.link.diary.DiaryType; import core.game.node.entity.player.link.diary.DiaryType;
import core.game.node.item.Item; 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.Initializable;
import core.plugin.Plugin; 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.GrandExchangeOffer;
import rs09.game.ge.GrandExchangeRecords;
import rs09.game.world.GameWorld; import rs09.game.world.GameWorld;
import java.text.NumberFormat;
/** /**
* Represents the plugin used for anything related to banking. * Represents the plugin used for anything related to banking.
* *
@@ -50,78 +27,16 @@ public final class BankingPlugin extends OptionHandler {
@Override @Override
public Plugin<Object> newInstance(Object arg) throws Throwable { 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(); new BankerDialogue().init();
return this; return this;
} }
@Override @Override
public boolean handle(Player player, Node node, String option) { public boolean handle(Player player, Node node, String option) {
final Scenery object = (Scenery) node; player.sendChat(":crab: :crab: :crab: RETARDED PLUGIN IS GONE :crab: :crab: :crab:");
if (player.getIronmanManager().checkRestriction(IronmanMode.ULTIMATE)) {
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; 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. * Represents the dialogue plugin used for all bankers.
* *
@@ -317,7 +232,6 @@ public final class BankingPlugin extends OptionHandler {
case 2: case 2:
case 3: case 3:
player.getBankPinManager().openType(buttonId); player.getBankPinManager().openType(buttonId);
checkAchievements(player);
end(); end();
break; break;
case 4: case 4:
@@ -340,7 +254,6 @@ public final class BankingPlugin extends OptionHandler {
case 2: case 2:
case 3: case 3:
player.getBankPinManager().openType(buttonId); player.getBankPinManager().openType(buttonId);
checkAchievements(player);
end(); end();
break; break;
case 4: 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). * @param running The running flag (ctrl + click reward).
*/ */
public void reset(boolean running) { 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.clear();
walkingQueue.add(new Point(entity.getLocation().getX(), entity.getLocation().getY())); walkingQueue.add(new Point(loc.getX(), loc.getY()));
this.running = running; this.running = running;
} }
@@ -1,5 +1,7 @@
package core.game.node.entity.player.link; package core.game.node.entity.player.link;
import api.events.InterfaceCloseEvent;
import api.events.InterfaceOpenEvent;
import core.game.component.Component; import core.game.component.Component;
import core.game.component.InterfaceType; import core.game.component.InterfaceType;
import core.game.node.entity.combat.equipment.WeaponInterface; 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!"); SystemLogger.logErr("Set interface type to WINDOW_PANE for component " + windowsPane.getId() + ", definition requires updating!");
windowsPane.getDefinition().setType(InterfaceType.WINDOW_PANE); windowsPane.getDefinition().setType(InterfaceType.WINDOW_PANE);
} }
PacketRepository.send(WindowsPane.class, new WindowsPaneContext(player, windowsPane.getId(), overlap ? 1 : 0)); PacketRepository.send(WindowsPane.class, new WindowsPaneContext(player, windowsPane.getId(), overlap ? 1 : 0));
windowsPane.open(player); windowsPane.open(player);
if (opened != null)
player.dispatch(new InterfaceOpenEvent(opened));
return windowsPane; 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!"); SystemLogger.logErr("Set interface type to WINDOW_PANE for component " + windowsPane.getId() + ", definition requires updating!");
windowsPane.getDefinition().setType(InterfaceType.SINGLE_TAB); windowsPane.getDefinition().setType(InterfaceType.SINGLE_TAB);
} }
PacketRepository.send(WindowsPane.class, new WindowsPaneContext(player, windowsPane.getId(), type)); PacketRepository.send(WindowsPane.class, new WindowsPaneContext(player, windowsPane.getId(), type));
windowsPane.open(player); windowsPane.open(player);
if (opened != null)
player.dispatch(new InterfaceOpenEvent(opened));
} }
/** /**
@@ -161,7 +172,11 @@ public final class InterfaceManager {
return null; return null;
} }
component.open(player); 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.close(player)) {
if (opened != null && (!opened.getDefinition().isWalkable() || opened.getId() == 14)) { 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())); 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; opened = null;
} }
@@ -281,28 +281,6 @@ public final class FamiliarManager {
player.getInterfaceManager().setViewedTab(7); 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. * Makes the pet eat.
* @param foodId The food item id. * @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");
}
}
+290 -134
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.player.link.quest.QuestRepository
import core.game.node.entity.skill.Skills import core.game.node.entity.skill.Skills
import core.game.node.entity.skill.gather.SkillingTool 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.GroundItem
import core.game.node.item.GroundItemManager import core.game.node.item.GroundItemManager
import core.game.node.item.Item 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.chunk.AnimateObjectUpdateFlag
import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics import core.game.world.update.flag.context.Graphics
import org.rs09.consts.Items
import rs09.game.content.dialogue.DialogueFile import rs09.game.content.dialogue.DialogueFile
import rs09.game.content.dialogue.SkillDialogueHandler import rs09.game.content.dialogue.SkillDialogueHandler
import rs09.game.content.global.GlobalKillCounter 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. * @return the tool which meets the requirements or null if none.
*/ */
fun getTool(player: Player, pickaxe: Boolean): SkillingTool? { 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 * @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 * @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) 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 * @param id the ID of the item to check for
* @return the amount of the ID in the player's bank. * @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) 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 * @param id the ID of the item to check for
* @return the amount of the ID in the player's equipment. * @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) 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 * @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 * @return true if the player has an item corresponding to the given god, false otherwise
*/ */
fun hasGodItem(player: Player, god: God): Boolean fun hasGodItem(player: Player, god: God): Boolean {
{ god.validItems.forEach { if (amountInEquipment(player, it) > 0) return true }
god.validItems.forEach { if(amountInEquipment(player, it) > 0) return true }
return false 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") else -> throw IllegalStateException("Invalid value passed for item")
} }
return when(container){ return when (container) {
Container.INVENTORY -> player.inventory.remove(it) Container.INVENTORY -> player.inventory.remove(it)
Container.BANK -> player.bank.remove(it) Container.BANK -> player.bank.remove(it)
Container.EQUIPMENT -> player.equipment.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 * @return true if the item was successfully added
*/ */
fun addItem(player: Player, id: Int, amount: Int = 1, container: Container = Container.INVENTORY): Boolean { 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.INVENTORY -> player.inventory
Container.BANK -> player.bank Container.BANK -> player.bank
Container.EQUIPMENT -> player.equipment 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. * @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? { 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.INVENTORY -> player.inventory
Container.EQUIPMENT -> player.equipment Container.EQUIPMENT -> player.equipment
Container.BANK -> player.bank 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 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 * @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) 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. * Clears an NPC with the "poof" smoke graphics commonly seen with random event NPCs.
* @param npc the NPC object to initialize * @param npc the NPC object to initialize
*/ */
fun poofClear(npc: NPC){ fun poofClear(npc: NPC) {
submitWorldPulse(object : Pulse(){ submitWorldPulse(object : Pulse() {
var counter = 0 var counter = 0
override fun pulse(): Boolean { override fun pulse(): Boolean {
when(counter++){ when (counter++) {
2 -> { 2 -> {
npc.isInvisible = true; Graphics.send(Graphics(86), npc.location) 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. * @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) { fun replaceScenery(toReplace: Scenery, with: Int, for_ticks: Int, loc: Location? = null) {
val newLoc = when(loc){ val newLoc = when (loc) {
null -> toReplace.location null -> toReplace.location
else -> loc else -> loc
} }
if (for_ticks == -1) { if (for_ticks == -1) {
SceneryBuilder.replace(toReplace, toReplace.transform(with,toReplace.rotation,newLoc)) SceneryBuilder.replace(toReplace, toReplace.transform(with, toReplace.rotation, newLoc))
} else { } 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 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 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. * @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){ fun replaceScenery(toReplace: Scenery, with: Int, for_ticks: Int, rotation: Direction, loc: Location? = null) {
val newLoc = when(loc){ val newLoc = when (loc) {
null -> toReplace.location null -> toReplace.location
else -> loc else -> loc
} }
val rot = when(rotation){ val rot = when (rotation) {
Direction.NORTH_WEST -> 0 Direction.NORTH_WEST -> 0
Direction.NORTH -> 1 Direction.NORTH -> 1
Direction.NORTH_EAST -> 2 Direction.NORTH_EAST -> 2
@@ -367,9 +368,9 @@ fun replaceScenery(toReplace: Scenery, with: Int, for_ticks: Int, rotation: Dire
Direction.WEST -> 3 Direction.WEST -> 3
} }
if (for_ticks == -1) { if (for_ticks == -1) {
SceneryBuilder.replace(toReplace, toReplace.transform(with,rot, newLoc)) SceneryBuilder.replace(toReplace, toReplace.transform(with, rot, newLoc))
} else { } else {
SceneryBuilder.replace(toReplace, toReplace.transform(with,rot,newLoc), for_ticks) SceneryBuilder.replace(toReplace, toReplace.transform(with, rot, newLoc), for_ticks)
} }
toReplace.isActive = false 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 * Send an object animation independent of a player
*/ */
fun animateScenery(obj: Scenery, animationId: Int){ fun animateScenery(obj: Scenery, animationId: Int) {
val animation = Animation(animationId) val animation = Animation(animationId)
animation.setObject(obj) animation.setObject(obj)
getRegionChunk(obj.location).flag(AnimateObjectUpdateFlag(animation)) 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 speed the speed the projectile travels at
* @param angle the angle 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){ fun spawnProjectile(
Projectile.create(source, dest, projectile, startHeight, endHeight, delay, speed, angle, source.getDistance(dest).toInt()).send() 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 player the player to open the interface for
* @param id the ID of the interface to open * @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)) player.interfaceManager.openOverlay(Component(id))
} }
@@ -530,7 +550,7 @@ fun openOverlay(player: Player, id: Int){
* Closes any open overlays for the given player * Closes any open overlays for the given player
* @param player the player to close for * @param player the player to close for
*/ */
fun closeOverlay(player: Player){ fun closeOverlay(player: Player) {
player.interfaceManager.closeOverlay() 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) * @param forced whether or not to force the animation (usually not necessary)
*/ */
fun <T> animate(entity: Entity, anim: T, forced: Boolean = false) { fun <T> animate(entity: Entity, anim: T, forced: Boolean = false) {
val animation = when(anim){ val animation = when (anim) {
is Int -> Animation(anim) is Int -> Animation(anim)
is Animation -> anim is Animation -> anim
else -> throw IllegalStateException("Invalid value passed for 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 y the Y coordinate to use
* @param z the Z coordinate to use * @param z the Z coordinate to use
*/ */
fun getScenery(x: Int, y: Int, z: Int): Scenery?{ fun getScenery(x: Int, y: Int, z: Int): Scenery? {
return RegionManager.getObject(z,x,y) return RegionManager.getObject(z, x, y)
} }
/** /**
* Gets the spawned scenery from the world map using the given Location object. * Gets the spawned scenery from the world map using the given Location object.
* @param loc the Location object to use. * @param loc the Location object to use.
*/ */
fun getScenery(loc: Location): Scenery?{ fun getScenery(loc: Location): Scenery? {
return RegionManager.getObject(loc) return RegionManager.getObject(loc)
} }
@@ -667,7 +687,7 @@ fun findLocalNPC(entity: Entity, id: Int): NPC? {
* @param entity the entity to check around * @param entity the entity to check around
* @param ids the IDs of the NPCs to look for * @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() 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 ids the IDs of the NPCs to look for
* @param distance The maximum distance to the entity. * @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() 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 * @param regionId the ID of the region
* @return a [ZoneBorders] encapsulating the entire region indicated by the provided regionId * @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) return ZoneBorders.forRegion(regionId)
} }
@@ -742,9 +761,9 @@ fun unlock(entity: Entity) {
* @param transformTo the ID of the NPC to turn into * @param transformTo the ID of the NPC to turn into
* @param restoreTicks the number of ticks until the NPC returns to normal * @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) npc.transform(transformTo)
Pulser.submit(object : Pulse(restoreTicks){ Pulser.submit(object : Pulse(restoreTicks) {
override fun pulse(): Boolean { override fun pulse(): Boolean {
npc.reTransform() npc.reTransform()
return true 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 * Produces a Location object using the given x,y,z values
*/ */
fun location(x: Int, y: Int, z: Int): Location{ fun location(x: Int, y: Int, z: Int): Location {
return Location.create(x,y,z) return Location.create(x, y, z)
} }
/** /**
* Checks if the given entity is within the given ZoneBorders * 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) 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 * Checks if the given entity is within the given borders
*/ */
fun inBorders(entity: Entity, swX: Int, swY: Int, neX: Int, neY: Int): Boolean { 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 * 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) 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 offset the offset of the desired varbit inside the varp.
* @param value the value to set the varbit to * @param value the value to set the varbit to
*/ */
fun setVarbit(player: Player, varpIndex: Int, offset: Int, value: Int, save: Boolean = false){ fun setVarbit(player: Player, varpIndex: Int, offset: Int, value: Int, save: Boolean = false) {
player.varpManager.get(varpIndex).setVarbit(offset,value).send(player) player.varpManager.get(varpIndex).setVarbit(offset, value).send(player)
if(save) player.varpManager.flagSave(varpIndex) 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 player the player to clear for
* @param varpIndex the index of the varp to clear * @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() 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 * @param varpIndex the index of the varp to calculate the value of
* @return the value of the varp * @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() 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 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. * @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){ fun forceWalk(entity: Entity, dest: Location, type: String) {
if(type == "clip"){ if (type == "clip") {
ForceMovement(entity, dest, 10, 10).run() ForceMovement(entity, dest, 10, 10).run()
return return
} }
val pathfinder = when(type){ val pathfinder = when (type) {
"smart" -> Pathfinder.SMART "smart" -> Pathfinder.SMART
else -> Pathfinder.DUMB else -> Pathfinder.DUMB
} }
@@ -845,7 +864,7 @@ fun forceWalk(entity: Entity, dest: Location, type: String){
* Interrupts a given entity's walking queue * Interrupts a given entity's walking queue
* @param entity the entity to interrupt * @param entity the entity to interrupt
*/ */
fun stopWalk(entity: Entity){ fun stopWalk(entity: Entity) {
entity.walkingQueue.reset() entity.walkingQueue.reset()
} }
@@ -871,8 +890,8 @@ fun getChildren(scenery: Int): IntArray {
* @param node the node to adjust the charge of * @param node the node to adjust the charge of
* @param amount the amount to adjust by * @param amount the amount to adjust by
*/ */
fun adjustCharge(node: Node, amount: Int){ fun adjustCharge(node: Node, amount: Int) {
when(node){ when (node) {
is Item -> node.charge += amount is Item -> node.charge += amount
is Scenery -> node.charge += amount is Scenery -> node.charge += amount
else -> SystemLogger.logErr("Attempt to adjust the charge of invalid type: ${node.javaClass.simpleName}") 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 * @param node the node whose charge to check
* @return amount of charges the node has, or -1 if the node does not accept charges. * @return amount of charges the node has, or -1 if the node does not accept charges.
*/ */
fun getCharge(node: Node): Int{ fun getCharge(node: Node): Int {
when(node){ when (node) {
is Item -> return node.charge is Item -> return node.charge
is Scenery -> 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 node the node to set the charge for
* @param charge the amount to set the node's charge to (default is 1000) * @param charge the amount to set the node's charge to (default is 1000)
*/ */
fun setCharge(node: Node, charge: Int){ fun setCharge(node: Node, charge: Int) {
when(node){ when (node) {
is Item -> node.charge = charge is Item -> node.charge = charge
is Scenery -> node.charge = charge is Scenery -> node.charge = charge
else -> SystemLogger.logErr("Attempt to set the charge of invalid type: ${node.javaClass.simpleName}") 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 * @return the option the player used
*/ */
fun getUsedOption(player: Player): String { 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 anim the Animation object to use, can also be an ID.
* @param gfx the Graphics 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){ fun <A, G> visualize(entity: Entity, anim: A, gfx: G) {
val animation = when(anim){ val animation = when (anim) {
is Int -> Animation(anim) is Int -> Animation(anim)
is Animation -> anim is Animation -> anim
else -> throw IllegalStateException("Invalid parameter passed for animation.") else -> throw IllegalStateException("Invalid parameter passed for animation.")
} }
val graphics = when(gfx){ val graphics = when (gfx) {
is Int -> Graphics(gfx) is Int -> Graphics(gfx)
is Graphics -> gfx is Graphics -> gfx
else -> throw IllegalStateException("Invalid parameter passed for graphics.") 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. * Used to submit a pulse to the GameWorld's Pulser.
* @param pulse the Pulse object to submit * @param pulse the Pulse object to submit
*/ */
fun submitWorldPulse(pulse: Pulse){ fun submitWorldPulse(pulse: Pulse) {
GameWorld.Pulser.submit(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. * Teleports or "instantly moves" an entity to a given Location object.
* @param entity the entity to move * @param entity the entity to move
* @param loc the Location object to move them to * @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. * @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){ fun teleport(entity: Entity, loc: Location, type: TeleportManager.TeleportType = TeleportManager.TeleportType.INSTANT) {
if(type == TeleportManager.TeleportType.INSTANT) entity.properties.teleportLocation = loc if (type == TeleportManager.TeleportType.INSTANT) entity.properties.teleportLocation = loc
else entity.teleporter.send(loc,type) 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 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 * @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) 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 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 * @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) 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 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 * @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){ fun <T> removeAll(player: Player, item: T, container: Container) {
val it = when(item){ val it = when (item) {
is Item -> item.id is Item -> item.id
is Int -> item is Int -> item
else -> throw IllegalStateException("Invalid value passed as item") else -> throw IllegalStateException("Invalid value passed as item")
} }
when(container){ when (container) {
Container.EQUIPMENT -> player.equipment.remove(Item(it, amountInEquipment(player, it))) Container.EQUIPMENT -> player.equipment.remove(Item(it, amountInEquipment(player, it)))
Container.BANK -> player.bank.remove(Item(it, amountInBank(player, it))) Container.BANK -> player.bank.remove(Item(it, amountInBank(player, it)))
Container.INVENTORY -> player.inventory.remove(Item(it, amountInInventory(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 iface the ID of the interface to use
* @param child the index of the child to send the string to * @param child the index of the child to send the string to
*/ */
fun setInterfaceText(player: Player, string: String, iface: Int, child: Int){ fun setInterfaceText(player: Player, string: String, iface: Int, child: Int) {
player.packetDispatch.sendString(string,iface,child) player.packetDispatch.sendString(string, iface, child)
} }
/** /**
* Closes any open (non-chat) interfaces for the player * Closes any open (non-chat) interfaces for the player
* @param player the player to close the interface for * @param player the player to close the interface for
*/ */
fun closeInterface(player: Player){ fun closeInterface(player: Player) {
player.interfaceManager.close() player.interfaceManager.close()
} }
@@ -1038,7 +1075,7 @@ fun closeInterface(player: Player){
* Closes any opened tab interfaces for the player * Closes any opened tab interfaces for the player
* @param player the player to close the tab for * @param player the player to close the tab for
*/ */
fun closeTabInterface(player: Player){ fun closeTabInterface(player: Player) {
player.interfaceManager.closeSingleTab() player.interfaceManager.closeSingleTab()
} }
@@ -1048,7 +1085,7 @@ fun closeTabInterface(player: Player){
* @param msg the message to send. * @param msg the message to send.
* @param expr the FacialExpression to use. An enum exists for these called FacialExpression. Defaults to FacialExpression.FRIENDLY * @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)) 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 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 * @param child the index of the child on the interface to send the model to
*/ */
fun sendPlayerOnInterface(player: Player, iface: Int, child: Int){ fun sendPlayerOnInterface(player: Player, iface: Int, child: Int) {
player.packetDispatch.sendPlayerOnInterface(iface,child) player.packetDispatch.sendPlayerOnInterface(iface, child)
} }
/** /**
@@ -1069,7 +1106,7 @@ fun sendPlayerOnInterface(player: Player, iface: Int, child: Int){
* @param msg the message to send. * @param msg the message to send.
* @param expr the FacialExpression to use. An enum exists for these called FacialExpression. Defaults to FacialExpression.FRIENDLY * @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)) 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 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 * @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){ fun sendAnimationOnInterface(player: Player, anim: Int, iface: Int, child: Int) {
player.packetDispatch.sendAnimationInterface(anim,iface,child) 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 player the player to register the listener for
* @param handler the method to run when the listener is invoked (when the player logs out) * @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 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 player the player to remove the logout listner from
* @param key the key of the logout listener to remove. * @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) player.logoutListeners.remove(key)
} }
@@ -1110,8 +1147,8 @@ fun clearLogoutListener(player: Player, key: String){
* @param item the ID of the item to send * @param item the ID of the item to send
* @param amount the amount of the item to send - defaults to 1 * @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){ fun sendItemOnInterface(player: Player, iface: Int, child: Int, item: Int, amount: Int = 1) {
player.packetDispatch.sendItemOnInterface(item,amount,iface,child) 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 item the ID of the item to show
* @param message the text to display * @param message the text to display
*/ */
fun sendItemDialogue(player: Player, item: Int, message: String){ fun sendItemDialogue(player: Player, item: Any, message: String) {
player.dialogueInterpreter.sendItemMessage(item, *splitLines(message)) 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 item2 the ID of the second item to show
* @param message the text to display * @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) 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 prompt what to prompt the player
* @param handler the method that handles the value gained from the input dialogue * @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){ fun sendInputDialogue(player: Player, numeric: Boolean, prompt: String, handler: (value: Any) -> Unit) {
if(numeric) sendInputDialogue(player, InputType.NUMERIC, prompt, handler) if (numeric) sendInputDialogue(player, InputType.NUMERIC, prompt, handler)
else sendInputDialogue(player, InputType.STRING_SHORT, 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 prompt what to prompt the player
* @param handler the method that handles the value from the input dialogue * @param handler the method that handles the value from the input dialogue
*/ */
fun sendInputDialogue(player: Player, type: InputType, prompt: String, handler: (value: Any) -> Unit){ fun sendInputDialogue(player: Player, type: InputType, prompt: String, handler: (value: Any) -> Unit) {
when(type){ when (type) {
InputType.NUMERIC, InputType.STRING_SHORT -> player.dialogueInterpreter.sendInput(type != InputType.NUMERIC, prompt) 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.STRING_LONG -> player.dialogueInterpreter.sendLongInput(prompt)
InputType.MESSAGE -> player.dialogueInterpreter.sendMessageInput(prompt) InputType.MESSAGE -> player.dialogueInterpreter.sendMessageInput(prompt)
} }
player.setAttribute("runscript", handler) 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 entity the entity to make flee
* @param from the entity to flee from * @param from the entity to flee from
*/ */
fun flee(entity: Entity, from: Entity){ fun flee(entity: Entity, from: Entity) {
lock(entity, 5) lock(entity, 5)
face(entity, from, 5) face(entity, from, 5)
val diffX = entity.location.x - from.location.x val diffX = entity.location.x - from.location.x
val diffY = entity.location.y - from.location.y 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 entity the entity to submit the pulse to
* @param pulse the pulse to submit * @param pulse the pulse to submit
*/ */
fun submitIndividualPulse(entity: Entity, pulse: Pulse){ fun submitIndividualPulse(entity: Entity, pulse: Pulse) {
entity.pulseManager.run(pulse) entity.pulseManager.run(pulse)
} }
/** /**
* Similar to submitIndividualPulse, but for non-repeating tasks, with a cleaner syntax. * 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) { entity.pulseManager.run(object : Pulse(delay) {
override fun pulse(): Boolean { override fun pulse(): Boolean {
task.invoke() task.invoke()
@@ -1254,7 +1309,7 @@ fun finishQuest(player: Player, quest: String) {
* @param id the ID of the scenery to get the definition for. * @param id the ID of the scenery to get the definition for.
* @return the scenery definition * @return the scenery definition
*/ */
fun sceneryDefinition(id: Int): SceneryDefinition{ fun sceneryDefinition(id: Int): SceneryDefinition {
return SceneryDefinition.forId(id) return SceneryDefinition.forId(id)
} }
@@ -1263,7 +1318,7 @@ fun sceneryDefinition(id: Int): SceneryDefinition{
* @param zone the zone to register * @param zone the zone to register
* @param borders the ZoneBorders that compose the zone * @param borders the ZoneBorders that compose the zone
*/ */
fun registerMapZone(zone: MapZone, borders: ZoneBorders){ fun registerMapZone(zone: MapZone, borders: ZoneBorders) {
ZoneBuilder.configure(zone) ZoneBuilder.configure(zone)
zone.register(borders) zone.register(borders)
} }
@@ -1275,8 +1330,8 @@ fun registerMapZone(zone: MapZone, borders: ZoneBorders){
* @param child the child on the interface to animate. * @param child the child on the interface to animate.
* @param anim the ID of the animation to use. * @param anim the ID of the animation to use.
*/ */
fun animateInterface(player: Player, iface: Int, child: Int, anim: Int){ fun animateInterface(player: Player, iface: Int, child: Int, anim: Int) {
player.packetDispatch.sendAnimationInterface(anim,iface,child) 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 ladderLoc the location of the ladder/stairs object you want to climb.
* @param dest the destination for the climb. * @param dest the destination for the climb.
*/ */
fun addClimbDest(ladderLoc: Location, dest: Location){ fun addClimbDest(ladderLoc: Location, dest: Location) {
SpecialLadders.add(ladderLoc,dest) SpecialLadders.add(ladderLoc, dest)
} }
/** /**
* Sends a news announcement in game chat. * Sends a news announcement in game chat.
* @param message the message to announce * @param message the message to announce
*/ */
fun sendNews(message: String){ fun sendNews(message: String) {
Repository.sendNews(message, 12, "CC6600") 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 gfx the Graphics object, or the Integer ID of the graphics, to send. Either works.
* @param location the location to send it to * @param location the location to send it to
*/ */
fun <G> sendGraphics(gfx: G, location: Location){ fun <G> sendGraphics(gfx: G, location: Location) {
when(gfx){ when (gfx) {
is Int -> Graphics.send(Graphics(gfx),location) is Int -> Graphics.send(Graphics(gfx), location)
is Graphics -> Graphics.send(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 hasMastered = player.getSkills().masteredSkills > 0
val masteredSkills = ArrayList<String>() val masteredSkills = ArrayList<String>()
if(hasMastered){ if (hasMastered) {
for ((skillId, skillName) in Skills.SKILL_NAME.withIndex()) { 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. //phil you were looping every skill and performing a string comparison (another loop) for every one here.
//that's some real shit code bro. //that's some real shit code bro.
//you were also performing a dynamic level check rather than a static. //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) 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 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 ceik
* @author James Triantafylos * @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 val bank = player.bank
container.toArray().filterNotNull().forEach { item -> var dumpedCount = 0
if (!bank.hasSpaceFor(item)) {
player.packetDispatch.sendMessage("You have no more space in your bank.") run beginDepositing@{
return container.toArray().filterNotNull().forEach { item ->
} if (!bank.hasSpaceFor(item)) {
if (!bank.canAdd(item)) { sendMessage(player, "You have no more space in your bank.")
player.packetDispatch.sendMessage("A magical force prevents you from banking your " + item.name + ".") return@beginDepositing
return }
} else {
if (container is EquipmentContainer) { if (!bank.canAdd(item)) {
if(!InteractionListeners.run(item.id,player,item,false)) { sendMessage(player, "A magical force prevents you from banking the ${item.name}.")
player.packetDispatch.sendMessage("A magical force prevents you from removing that item.") return@forEach
return } else {
} if (container is EquipmentContainer) {
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(unnote(item))
dumpedCount++
} }
container.remove(item)
bank.add(if (item.definition.isUnnoted) item else Item(item.noteChange, item.amount))
} }
} }
container.update() container.update()
bank.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,14 +1544,13 @@ fun Player.getCutsceneStage(): Int {
return getAttribute(this, Cutscene.ATTRIBUTE_CUTSCENE_STAGE, 0) return getAttribute(this, Cutscene.ATTRIBUTE_CUTSCENE_STAGE, 0)
} }
fun getServerConfig() : Toml fun getServerConfig(): Toml {
{
return ServerConfigParser.tomlData ?: Toml() return ServerConfigParser.tomlData ?: Toml()
} }
fun getPathableRandomLocalCoordinate(target: Entity, radius: Int, center: Location, maxAttempts: Int = 3): Location { 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 neCorner = center.transform(radius, radius, center.z)
val borders = ZoneBorders(swCorner.x, swCorner.y, neCorner.x, neCorner.y, center.z) val borders = ZoneBorders(swCorner.x, swCorner.y, neCorner.x, neCorner.y, center.z)
var attempts = maxAttempts var attempts = maxAttempts
+1
View File
@@ -1,6 +1,7 @@
package api package api
enum class InputType { enum class InputType {
AMOUNT,
NUMERIC, NUMERIC,
STRING_SHORT, STRING_SHORT,
STRING_LONG, STRING_LONG,
+4 -1
View File
@@ -1,5 +1,6 @@
package api.events package api.events
import core.game.component.Component
import core.game.node.Node import core.game.node.Node
import core.game.node.entity.Entity import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
@@ -13,4 +14,6 @@ data class InteractionEvent(val target: Node, val option: String) : Event
data class ButtonClickedEvent(val iface: Int, val buttonId: Int) : Event data class ButtonClickedEvent(val iface: Int, val buttonId: Int) : Event
data class UsedWithEvent(val used: Int, val with: Int) : Event data class UsedWithEvent(val used: Int, val with: Int) : Event
data class SelfDeath(val killer: Entity) : Event data class SelfDeath(val killer: Entity) : Event
data class TickEvent(val worldTicks: Int) : 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 @JvmField
var BANK_SIZE: Int = 496 var BANK_SIZE: Int = 496
@JvmField
var BANK_BOOTH_QUICK_OPEN: Boolean = false
@JvmField @JvmField
var GE_AUTOSAVE_FREQUENCY = secondsToTicks(3600) //1 hour var GE_AUTOSAVE_FREQUENCY = secondsToTicks(3600) //1 hour
@@ -12,4 +12,6 @@ object Event {
@JvmStatic val UsedWith = UsedWithEvent::class.java @JvmStatic val UsedWith = UsedWithEvent::class.java
@JvmStatic val SelfDeath = SelfDeath::class.java @JvmStatic val SelfDeath = SelfDeath::class.java
@JvmStatic val Tick = TickEvent::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 var dialoguePlugin: DialoguePlugin? = null
abstract fun handle(componentID: Int, buttonID: Int) abstract fun handle(componentID: Int, buttonID: Int)
fun load(player: Player, npc: NPC?, interpreter: DialogueInterpreter): DialogueFile{ fun load(player: Player, npc: NPC?, interpreter: DialogueInterpreter): DialogueFile{
this.player = player this.player = player
this.npc = npc this.npc = npc
this.interpreter = interpreter this.interpreter = interpreter
return this return this
} }
@@ -1,25 +1,24 @@
package rs09.game.content.dialogue.region.lunarisle package rs09.game.content.dialogue.region.lunarisle
import api.hasSealOfPassage
import core.game.content.dialogue.DialoguePlugin import core.game.content.dialogue.DialoguePlugin
import core.game.content.dialogue.FacialExpression import core.game.content.dialogue.FacialExpression
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.plugin.Initializable import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import rs09.game.ge.GrandExchangeRecords import rs09.game.ge.GrandExchangeRecords
/** /**
* @author qmqz * @author qmqz
*/ */
@Initializable @Initializable
class SirsalBankerDialogue(player: Player? = null) : DialoguePlugin(player){ class SirsalBankerDialogue(player: Player? = null) : DialoguePlugin(player){
override fun open(vararg args: Any?): Boolean { override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC 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 } npc(FacialExpression.FRIENDLY, "Good day, how may I help you?").also { stage = 0 }
} else { } else {
player(FacialExpression.FRIENDLY, "Hi, I...").also { stage = 2 } 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 } 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 { 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 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.RandomEventManager
import rs09.game.content.ame.RandomEvents import rs09.game.content.ame.RandomEvents
import rs09.game.interaction.InteractionListener import rs09.game.interaction.InteractionListener
import rs09.game.system.SystemLogger
/** /**
* Handles the NPC talk-to option. * Handles the NPC talk-to option.
@@ -66,5 +65,7 @@ class NPCTalkListener : InteractionListener {
} }
return@setDest node.location 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.node.entity.skill.slayer.Tasks
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Components
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import org.rs09.consts.Scenery import org.rs09.consts.Scenery
import rs09.game.Event 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) { override fun login(player: Player) {
player.hook(Event.ResourceProduced, DiaryGatherHooks) player.hook(Event.ResourceProduced, DiaryGatherHooks)
player.hook(Event.Teleport, DiaryTeleportHooks) player.hook(Event.Teleport, DiaryTeleportHooks)
player.hook(Event.NPCKilled, DiaryCombatHooks) player.hook(Event.NPCKilled, DiaryCombatHooks)
player.hook(Event.FireLit, DiaryFireHooks) player.hook(Event.FireLit, DiaryFireHooks)
player.hook(Event.Interaction, DiaryInteractionEvents) player.hook(Event.Interaction, DiaryInteractionEvents)
player.hook(Event.InterfaceOpened, DiaryInterfaceOpenEvents)
player.hook(Event.InterfaceClosed, DiaryInterfaceCloseEvents)
} }
companion object { 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) { override fun process(entity: Entity, event: InteractionEvent) {
if(entity !is Player) return if (entity !is Player) return
val regionId = entity.viewport.region.id val regionId = entity.viewport.region.id
if(event.target is core.game.node.scenery.Scenery) if (event.target is core.game.node.scenery.Scenery)
when(event.target.id) when (event.target.id) {
{ 11729, 11727 -> if (regionId == 11828) finishTask(entity, DiaryType.FALADOR, 0, 3)
11729, 11727 -> if(regionId == 11828) finishTask(entity, DiaryType.FALADOR, 0, 3) 11889 -> if (regionId == 11572 && isEquipped(entity, Items.PROSELYTE_SALLET_9672) && isEquipped(
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) entity,
30941 -> if(regionId == 12184) finishTask(entity, DiaryType.FALADOR, 2, 6) Items.PROSELYTE_HAUBERK_9674
36771 -> if(regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 0, 0) ) && isEquipped(entity, Items.PROSELYTE_CUISSE_9676)
12537 -> if(regionId == 12337) finishTask(entity, DiaryType.LUMBRIDGE, 0, 11) ) finishTask(entity, DiaryType.FALADOR, 2, 0)
26934 -> if(regionId == 12342) finishTask(entity, DiaryType.VARROCK, 0, 10) 30941 -> if (regionId == 12184) finishTask(entity, DiaryType.FALADOR, 2, 6)
24350,24361 -> if(regionId == 12854) finishTask(entity, DiaryType.VARROCK, 0, 18) 36771 -> if (regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 0, 0)
in 115..122 -> if(event.option == "burst") finishTask(entity, DiaryType.FALADOR, 0, 12) 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) 16149 -> finishTask(entity, DiaryType.VARROCK, 0, 4)
//2112 -> if() //2112 -> if()
} }
} }
} }
private object DiaryFireHooks : EventHook<LitFireEvent> private object DiaryFireHooks : EventHook<LitFireEvent> {
{
val lumCastleBorders = ZoneBorders(3216, 3207, 3225, 3233, 0) val lumCastleBorders = ZoneBorders(3216, 3207, 3225, 3233, 0)
override fun process(entity: Entity, event: LitFireEvent) { override fun process(entity: Entity, event: LitFireEvent) {
if(entity !is Player) return if (entity !is Player) return
val region = entity.viewport.region.id val region = entity.viewport.region.id
when(region) when (region) {
{ 10806 -> if (event.logId == Items.MAGIC_LOGS_1513) finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 5)
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)
12593,12849 -> if(event.logId == Items.LOGS_1511) finishTask(entity, DiaryType.LUMBRIDGE, 1, 9)
else -> { else -> {
if(event.logId == Items.WILLOW_LOGS_1519 && lumCastleBorders.insideBorder(entity)) if (event.logId == Items.WILLOW_LOGS_1519 && lumCastleBorders.insideBorder(entity))
finishTask(entity, DiaryType.LUMBRIDGE,2 ,3) finishTask(entity, DiaryType.LUMBRIDGE, 2, 3)
} }
} }
} }
} }
private object DiaryGatherHooks : EventHook<ResourceProducedEvent> private object DiaryGatherHooks : EventHook<ResourceProducedEvent> {
{
override fun process(entity: Entity, event: ResourceProducedEvent) { override fun process(entity: Entity, event: ResourceProducedEvent) {
if(entity !is Player) return if (entity !is Player) return
val regionId = entity.viewport.region.id val regionId = entity.viewport.region.id
when(event.itemId) when (event.itemId) {
{
//Cut a log from a teak tree //Cut a log from a teak tree
Items.TEAK_LOGS_6333 -> finishTask(entity, DiaryType.KARAMJA, 1, 7) Items.TEAK_LOGS_6333 -> finishTask(entity, DiaryType.KARAMJA, 1, 7)
//Cut a log from a mahogany tree //Cut a log from a mahogany tree
Items.MAHOGANY_LOGS_6332 -> finishTask(entity, DiaryType.KARAMJA, 1, 8) Items.MAHOGANY_LOGS_6332 -> finishTask(entity, DiaryType.KARAMJA, 1, 8)
Items.LOGS_1511 -> { Items.LOGS_1511 -> {
//Cut down a dying tree in the Lumber Yard //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) finishTask(entity, DiaryType.VARROCK, 0, 6)
} }
Items.YEW_LOGS_1515 -> { Items.YEW_LOGS_1515 -> {
if(regionId == 10806) { if (regionId == 10806) {
setAttribute(entity, "/save:diary:seers:cut-yew", getAttribute(entity, "diary:seers:cut-yew", 0) + 1) setAttribute(
entity,
"/save:diary:seers:cut-yew",
getAttribute(entity, "diary:seers:cut-yew", 0) + 1
)
if (getAttribute(entity, "diary:seers:cut-yew", 0) >= 5) if (getAttribute(entity, "diary:seers:cut-yew", 0) >= 5)
finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 1) 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 -> { Items.IRON_ORE_440 -> {
if(regionId == 13108) finishTask(entity, DiaryType.VARROCK, 0, 2) if (regionId == 13108) finishTask(entity, DiaryType.VARROCK, 0, 2)
else if(regionId == 13107) finishTask(entity, DiaryType.LUMBRIDGE, 1, 0) 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) when (event.original) {
{ Items.RAW_RAT_MEAT_2134 -> if ((regionId == 12593 || regionId == 12849) && event.itemId == Items.COOKED_MEAT_2142) finishTask(
Items.RAW_RAT_MEAT_2134 -> if((regionId == 12593 || regionId == 12849) && event.itemId == Items.COOKED_MEAT_2142) finishTask(entity, DiaryType.LUMBRIDGE, 1, 10) 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) 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) 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) 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) 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) 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) finishTask(entity, DiaryType.LUMBRIDGE, 0, 7)
} }
} }
private object DiaryTeleportHooks : EventHook<TeleportEvent> private object DiaryTeleportHooks : EventHook<TeleportEvent> {
{
override fun process(entity: Entity, event: TeleportEvent) { override fun process(entity: Entity, event: TeleportEvent) {
TODO("Not yet implemented") 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 faladorDucks = intArrayOf(NPCs.DUCK_46, NPCs.DUCK_2693, NPCs.DUCK_6113)
val lumbridgeCows = intArrayOf(81, 397, 955, 1766, 1767, 3309) val lumbridgeCows = intArrayOf(81, 397, 955, 1766, 1767, 3309)
val elementalNPCs = intArrayOf(1019, 1020, 1021, 1022) val elementalNPCs = intArrayOf(1019, 1020, 1021, 1022)
val wyverns = Tasks.SKELETAL_WYVERN.npcs 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) val lumZombies = intArrayOf(NPCs.ZOMBIE_73, NPCs.ZOMBIE_74)
override fun process(entity: Entity, event: NPCKillEvent) { override fun process(entity: Entity, event: NPCKillEvent) {
if(entity !is Player) return if (entity !is Player) return
when(event.npc.id) when (event.npc.id) {
{
//FALADOR LEVEL 0 TASK 10 //FALADOR LEVEL 0 TASK 10
in faladorDucks -> { in faladorDucks -> {
if(entity.location.withinDistance(Location(2991, 3383, 0))) if (entity.location.withinDistance(Location(2991, 3383, 0)))
finishTask(entity, DiaryType.FALADOR, 0, 9) finishTask(entity, DiaryType.FALADOR, 0, 9)
} }
@@ -195,22 +262,21 @@ class DiaryEventHook : LoginListener
} }
NPCs.JOGRE_113 -> { NPCs.JOGRE_113 -> {
if(entity.viewport.region.id == 11412) if (entity.viewport.region.id == 11412)
finishTask(entity, DiaryType.KARAMJA, 0, 9) finishTask(entity, DiaryType.KARAMJA, 0, 9)
} }
in elementalNPCs -> { in elementalNPCs -> {
if(!entity.location.withinDistance(Location(2719,9889,0), 100)) if (!entity.location.withinDistance(Location(2719, 9889, 0), 100))
return return
when(event.npc.id) when (event.npc.id) {
{
1019 -> setAttribute(entity, "/save:diary:seers:elemental:fire", true) 1019 -> setAttribute(entity, "/save:diary:seers:elemental:fire", true)
1020 -> setAttribute(entity, "/save:diary:seers:elemental:earth", true) 1020 -> setAttribute(entity, "/save:diary:seers:elemental:earth", true)
1021 -> setAttribute(entity, "/save:diary:seers:elemental:air", true) 1021 -> setAttribute(entity, "/save:diary:seers:elemental:air", true)
1022 -> setAttribute(entity, "/save:diary:seers:elemental:water", true) 1022 -> setAttribute(entity, "/save:diary:seers:elemental:water", true)
} }
for (element in arrayOf("fire", "earth", "air", "water")) for (element in arrayOf("fire", "earth", "air", "water"))
if(!getAttribute(entity, "diary:seers:$element", false)) if (!getAttribute(entity, "diary:seers:$element", false))
return return
finishTask(entity, DiaryType.SEERS_VILLAGE, 1, 4) 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) NPCs.KET_ZEK_2743, NPCs.KET_ZEK_2744 -> finishTask(entity, DiaryType.KARAMJA, 2, 1)
in metalDragons -> { 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) finishTask(entity, DiaryType.KARAMJA, 2, 9)
} }
in wyverns -> finishTask(entity, DiaryType.FALADOR, 2, 8) in wyverns -> finishTask(entity, DiaryType.FALADOR, 2, 8)
in lumZombies -> { 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) finishTask(entity, DiaryType.LUMBRIDGE, 1, 18)
} }
NPCs.GIANT_RAT_86 -> { 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) 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_688 -> setAttribute(
NPCs.TOWER_ARCHER_689 -> setAttribute(entity, "/save:diary:seers:tower-archers", getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 1)) entity,
NPCs.TOWER_ARCHER_690 -> setAttribute(entity, "/save:diary:seers:tower-archers", getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 2)) "/save:diary:seers:tower-archers",
NPCs.TOWER_ARCHER_691 -> setAttribute(entity, "/save:diary:seers:tower-archers", getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 3)) 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) 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 -> define("spellbook"){player, args ->
if(args.size < 2){ if(args.size < 2){
reject(player,"Usage: ::spellbook [int]. 0 = MODERN, 1 = ANCIENTS, 2 = LUNARS") 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.RULES_AND_INFO_ENABLED = data.getBoolean("world.show_rules", true)
ServerConstants.BOTS_INFLUENCE_PRICE_INDEX = data.getBoolean("world.bots_influence_ge_price", 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.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", "") ServerConstants.DISCORD_GE_WEBHOOK = data.getString("server.discord_webhook", "")
} }