Part 1 of achievement diary rewrite, the following diaries have been partially or totally rewritten

Lumbridge Beginner
Lumbridge Easy
Lumbridge Medium
Falador Easy
Falador Hard
Fremennik Easy
Fremennik Medium
Karamja Easy
Karamja Medium
Karamja Hard
Seers' Village Easy
Seers' Village Medium
Varrock Easy
Varrock Medium
This commit is contained in:
vddcore 2022-07-09 08:57:21 +00:00 committed by Ryan
parent 374d6ec478
commit 0a531d5926
65 changed files with 3271 additions and 1690 deletions

View file

@ -184,7 +184,6 @@ public final class GnomeCopterActivity extends ActivityPlugin {
player.getInterfaceManager().restoreTabs();
usedLandingPads[pad] = false;
player.removeAttribute("gc:flying");
player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 2, 1);
return true;
}
return false;

View file

@ -1,5 +1,6 @@
package core.game.content.activity.tzhaar;
import api.events.NPCKillEvent;
import core.game.content.activity.ActivityPlugin;
import core.game.content.global.BossKillCounter;
import core.game.interaction.Option;
@ -257,6 +258,10 @@ public final class TzhaarFightCavesPlugin extends ActivityPlugin {
} else {
leave((Player) e, e.getAttribute("fc_wave", 0));
}
/* Kludge to fix this plugin overriding the base NPC death finalization
* resulting in not dispatching the proper NPC kill event. */
killer.dispatch(new NPCKillEvent(e.asNpc()));
return true;
}

View file

@ -1,5 +1,8 @@
package core.game.content.dialogue;
import api.events.DialogueCloseEvent;
import api.events.DialogueOpenEvent;
import api.events.DialogueOptionSelectionEvent;
import core.cache.def.impl.ItemDefinition;
import core.cache.def.impl.NPCDefinition;
import core.game.component.Component;
@ -116,6 +119,11 @@ public final class DialogueInterpreter {
dialogue = null;
return false;
}
if (dialogue != null) {
player.dispatch(new DialogueOpenEvent(dialogue));
}
return true;
}
@ -154,11 +162,28 @@ public final class DialogueInterpreter {
activeTopics.clear();
return;
}
if(file != null){
player.getDialogueInterpreter().getDialogue().file.handle(componentId,buttonId - 1);
return;
player.dispatch(
new DialogueOptionSelectionEvent(
file,
file.getStage(),
buttonId - 1
)
);
file.handle(componentId,buttonId - 1);
} else {
player.dispatch(
new DialogueOptionSelectionEvent(
dialogue,
dialogue.stage,
buttonId - 1
)
);
dialogue.handle(componentId, buttonId - 1);//here
}
player.getDialogueInterpreter().getDialogue().handle(componentId, buttonId - 1);//here
}
/**
@ -176,6 +201,7 @@ public final class DialogueInterpreter {
DialoguePlugin d = dialogue;
dialogue = null;
d.close();
player.dispatch(new DialogueCloseEvent(d));
}
}
activeTopics.clear();

View file

@ -1,211 +0,0 @@
package core.game.content.dialogue;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.diary.DiaryType;
import core.plugin.Initializable;
import core.game.node.item.Item;
/**
* Represents the kaylee dialogue plugin.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class KayleeDialogue extends DialoguePlugin {
/**
* Represents the coins item.
*/
private static final Item COINS = new Item(995, 3);
/**
* Represents the ale item.
*/
private static final Item ASGARNIAN_ALE = new Item(1905, 1);
/**
* Represents the wizards mind bomb.
*/
private static final Item MIND_BOMB = new Item(1907, 1);
/**
* Represents the dwarven stout item.
*/
private static final Item DWARVEN_STOUT = new Item(1913, 1);
/**
* Constructs a new {@code KayleeDialogue} {@code Object}.
*/
public KayleeDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code KayleeDialogue} {@code Object}.
* @param player the player.
*/
public KayleeDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new KayleeDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hi! What can I get you?");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
if (player.getInventory().contains(1919, 1)) {
interpreter.sendOptions("What would you like to say?", "What ales are you serving?", "I've got this beer glass...");
stage = 1;
} else {
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What ales are you serving?");
stage = 20;
}
break;
case 1:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What ales are you serving?");
stage = 20;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I've got these beer glasses....");
stage = 200;
break;
}
break;
case 20:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well, we've got Asgarnian Ale, Wizard's Mind Bomb", "and Dwarven Stout, all for only 3 coins.");
stage = 21;
break;
case 21:
interpreter.sendOptions("What would you like to say?", "One Asgarnian Ale, please.", "I'll try the Mind Bomb.", "Can I have A Dwarven Stout?", "I don't feel like any of those.");
stage = 22;
break;
case 22:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "One Asgarnian Ale, please.");
stage = 100;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'll try the Mind Bomb.");
stage = 120;
break;
case 3:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Can I have a Dwarven Stout?");
stage = 130;
break;
case 4:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I don't feel like any of those.");
stage = 444;
break;
}
break;
case 100:
if (!player.getInventory().containsItem(COINS)) {
end();
player.getPacketDispatch().sendMessage("You need 3 gold coins to buy ale.");
return true;
}
if (player.getInventory().remove(COINS)) {
player.getInventory().add(ASGARNIAN_ALE);
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Thanks, " + npc.getName() + ".");
player.getPacketDispatch().sendMessage("You buy a Asgarnian Ale.");
stage = 101;
} else {
end();
player.getPacketDispatch().sendMessage("You need 3 gold coins to buy ale.");
}
break;
case 101:
end();
player.getAchievementDiaryManager().finishTask(player,DiaryType.FALADOR, 0, 1);
break;
case 120:
if (player.getInventory().remove(COINS)) {
player.getInventory().add(MIND_BOMB);
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Thanks, " + npc.getName() + ".");
player.getPacketDispatch().sendMessage("You buy a Wizard's Mind Bomb.");
stage = 101;
} else {
end();
player.getPacketDispatch().sendMessage("You need 3 gold coins to buy ale.");
}
break;
case 130:
if (player.getInventory().remove(COINS)) {
player.getInventory().add(DWARVEN_STOUT);
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Thanks, " + npc.getName() + ".");
player.getPacketDispatch().sendMessage("You buy a Dwarven Stout.");
stage = 101;
} else {
end();
player.getPacketDispatch().sendMessage("You need 3 gold coins to buy ale.");
}
break;
case 200:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Ooh, we'll buy those off you if", "you're interested. 2gp per glass.");
stage = 201;
break;
case 201:
interpreter.sendOptions("What would you like to say?", "Okay, sure.", "No thanks, I like empty beer glasses.");
stage = 202;
break;
case 202:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Okay, sure.");
stage = 190;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "No thanks, I like empty beer glasses.");
stage = 400;
break;
}
break;
case 190:
if (player.getInventory().contains(1919, 1)) {
player.getInventory().add(new Item(995, 2 * player.getInventory().getAmount(new Item(1919))));
player.getInventory().remove(new Item(1919, player.getInventory().getAmount(new Item(1919))));
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "There you go.");
stage = 191;
} else
end();
stage = 191;
break;
case 191:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Thanks!");
stage = 192;
break;
case 192:
end();
break;
case 444:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 3217, 736 };
}
}

View file

@ -1,6 +1,6 @@
package core.game.interaction;
import api.events.UsedWithEvent;
import api.events.UseWithEvent;
import core.cache.def.impl.SceneryDefinition;
import core.game.node.Node;
import core.game.node.entity.npc.NPC;
@ -144,7 +144,7 @@ public abstract class UseWithHandler implements Plugin<Object> {
event.getPlayer().getPulseManager().run(new Pulse(1, event.getPlayer(), event.getUsed(), event.getUsedWith()) {
@Override
public boolean pulse() {
event.getPlayer().dispatch(new UsedWithEvent(event.getUsed().getId(), event.getUsedWith().getId()));
event.getPlayer().dispatch(new UseWithEvent(event.getUsed().getId(), event.getUsedWith().getId()));
boolean handled = false;
if (event.getPlayer() != null) {
event.getPlayer().getInterfaceManager().close();
@ -170,7 +170,7 @@ public abstract class UseWithHandler implements Plugin<Object> {
event.getPlayer().getPulseManager().run(new MovementPulse(event.getPlayer(), event.getUsedWith(), handler.get(0)) {
@Override
public boolean pulse() {
event.getPlayer().dispatch(new UsedWithEvent(event.getUsed().getId(), event.getUsedWith().getId()));
event.getPlayer().dispatch(new UseWithEvent(event.getUsed().getId(), event.getUsedWith().getId()));
event.getPlayer().faceLocation(FaceLocationFlag.getFaceLocation(event.getPlayer(), event.getUsedWith()));
boolean handled = false;
Item used = (Item) event.getUsed();

View file

@ -1,5 +1,6 @@
package core.game.interaction.inter;
import api.events.SpellCastEvent;
import core.game.component.Component;
import core.game.component.ComponentDefinition;
import core.game.component.ComponentPlugin;
@ -34,7 +35,20 @@ public final class MagicBookInterface extends ComponentPlugin {
if (GameWorld.getTicks() < player.getAttribute("magic:delay", -1)) {
return true;
}
SpellBook spellBook = component.getId() == 192
? SpellBook.MODERN
: component.getId() == 193
? SpellBook.ANCIENT
: SpellBook.LUNAR;
SpellListeners.run(button, SpellListener.NONE, SpellUtils.getBookFromInterface(component.getId()),player,null);
return MagicSpell.castSpell(player, component.getId() == 192 ? SpellBook.MODERN : component.getId() == 193 ? SpellBook.ANCIENT : SpellBook.LUNAR, button, player);
boolean result = MagicSpell.castSpell(player, spellBook, button, player);
if (result) {
player.dispatch(new SpellCastEvent(spellBook, button));
}
return result;
}
}

View file

@ -1,8 +1,6 @@
package core.game.node.entity;
import api.events.Event;
import api.events.EventHook;
import api.events.TickEvent;
import api.events.*;
import core.game.content.holiday.HolidayEvent;
import core.game.interaction.DestinationFlag;
import core.game.node.Node;
@ -776,6 +774,7 @@ public abstract class Entity extends Node {
*/
public void setAttribute(String key, Object value) {
attributes.setAttribute(key, value);
dispatch(new AttributeSetEvent(this, key, value));
}
/**
@ -819,6 +818,7 @@ public abstract class Entity extends Node {
*/
public void removeAttribute(String string) {
attributes.removeAttribute(string);
dispatch(new AttributeRemoveEvent(this, string));
}
/**

View file

@ -1,6 +1,6 @@
package core.game.node.entity.combat;
import api.events.SelfDeath;
import api.events.SelfDeathEvent;
import core.game.container.Container;
import core.game.container.ContainerType;
import core.game.node.Node;
@ -85,7 +85,7 @@ public final class DeathTask extends NodeTask {
e.getImpactHandler().getImpactLog().clear();// check if this needs to be
// before finalize
e.getImpactHandler().setDisabledTicks(4);
e.dispatch(new SelfDeath(killer));
e.dispatch(new SelfDeathEvent(killer));
}
@Override

View file

@ -1,5 +1,6 @@
package core.game.node.entity.skill;
import api.events.DynamicSkillLevelChangeEvent;
import core.game.interaction.item.brawling_gloves.BrawlingGloves;
import core.game.interaction.item.brawling_gloves.BrawlingGlovesManager;
import core.game.node.entity.Entity;
@ -604,9 +605,13 @@ public final class Skills {
} else if (slot == PRAYER) {
prayerPoints = level;
}
int previousLevel = dynamicLevels[slot];
dynamicLevels[slot] = level;
if (entity instanceof Player) {
PacketRepository.send(SkillLevel.class, new SkillContext((Player) entity, slot));
entity.dispatch(new DynamicSkillLevelChangeEvent(slot, previousLevel, level));
}
}

View file

@ -1,138 +0,0 @@
package core.game.node.entity.skill.crafting;
/**
* Represents a silver product.
* @author 'Vexia
*/
public enum SilverProduct {
UNBLESSED(16, 1599, 1714, 16, 50, 1716),
UNHOLY(23, 1594, 1720, 17, 50, 1724),
SICKLE(30, 2976, 2961, 18, 50, -1),
TIARA(44, 5523, 5525, 23, 52.5, -1),
DEMONIC_SIGIL(59, 6747, 6748, 20, 50, -1),
SILVTHRIL_CHAIN(73, 13153, 13154, 1, 100, -1),
LIGHTNING_ROD(37, 4200, 4201, 20, 50, -1),
SILVTHRIL_ROD(52, 7649, 7637, 99, 1, -1),
SILVER_BOLTS(66, 9434, 9382, 21, 50, -1);
/**
* The button id.
*/
private final int button;
/**
* The product item.
*/
private final int product;
/**
* The item needed.
*/
private final int needed;
/**
* The level needed.
*/
private final int level;
/**
* The exp gained.
*/
private final double exp;
/**
* The strung id.
*/
private final int strung;
/**
* Constructs a new {@code SilverDefinitions.java} {@Code Object}
* @param button
* @param product
* @param level
* @param exp
*/
SilverProduct(int button, int needed, int product, int level, double exp, int strung) {
this.button = button;
this.needed = needed;
this.product = product;
this.level = level;
this.exp = exp;
this.strung = strung;
}
/**
* returns the value.
* @param id
* @return
*/
public static SilverProduct forId(int id) {
for (SilverProduct silver : SilverProduct.values()) {
if (silver.button == id) {
return silver;
}
}
return null;
}
/**
* Gets the button.
* @return The button.
*/
public int getButton() {
return button;
}
/**
* Gets the product.
* @return The product.
*/
public int getProduct() {
return product;
}
/**
* Gets the needed.
* @return The needed.
*/
public int getNeeded() {
return needed;
}
/**
* Gets the level.
* @return The level.
*/
public int getLevel() {
return level;
}
/**
* Gets the exp.
* @return The exp.
*/
public double getExp() {
return exp;
}
/**
* Gets the strung.
* @return The strung.
*/
public int getStrung() {
return strung;
}
/**
* returns the value.
* @param id
* @return
*/
public static SilverProduct forProductId(int id) {
for (SilverProduct silver : SilverProduct.values()) {
if (silver.getProduct() == id) {
return silver;
}
}
return null;
}
}

View file

@ -1,49 +0,0 @@
package core.game.node.entity.skill.crafting;
import core.game.interaction.NodeUsageEvent;
import core.game.interaction.UseWithHandler;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Represents the plugin used to string jewelry.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class SilverStringingPlugin extends UseWithHandler {
/**
* Constructs a new {@code SilverStringingPlugin} {@code Object}.
*/
public SilverStringingPlugin() {
super(1714, 1720);
}
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
SilverProduct silver = null;
if (event.getUsedItem().getId() != 1759) {
silver = SilverProduct.forProductId(event.getUsedItem().getId());
} else if (((Item) event.getUsedWith()).getId() != 1759) {
silver = SilverProduct.forProductId((((Item) event.getUsedWith()).getId()));
}
if (silver == null) {
return true;
}
player.getInventory().remove(new Item(silver.getProduct(), 1));
player.getInventory().remove(new Item(1759, 1));
player.getInventory().add(new Item(silver.getStrung(), 1));
return true;
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
addHandler(1759, ITEM_TYPE, this);
return null;
}
}

View file

@ -1,5 +1,6 @@
package core.game.node.entity.skill.summoning;
import api.events.SummoningPointsRechargeEvent;
import core.cache.def.impl.SceneryDefinition;
import core.plugin.Initializable;
import core.game.node.entity.skill.Skills;
@ -32,6 +33,7 @@ public final class ObeliskOptionPlugin extends OptionHandler {
player.visualize(Animation.create(8502), Graphics.create(1308));
player.getAudioManager().send(4214);
player.getSkills().setLevel(Skills.SUMMONING, player.getSkills().getStaticLevel(Skills.SUMMONING));
player.dispatch(new SummoningPointsRechargeEvent(node));
player.getPacketDispatch().sendMessage("You renew your summoning points.");
return true;
}

View file

@ -1,8 +1,7 @@
package core.game.world.map.zone.impl;
import api.LoginListener;
import api.events.EventHook;
import api.events.UsedWithEvent;
import api.events.UseWithEvent;
import core.game.component.Component;
import core.game.content.global.LightSource;
import core.game.interaction.Option;
@ -29,7 +28,7 @@ import static api.ContentAPIKt.runTask;
* Handles a dark area.
* @author Emperor
*/
public final class DarkZone extends MapZone implements EventHook<UsedWithEvent>{
public final class DarkZone extends MapZone implements EventHook<UseWithEvent>{
/**
* The darkness overlay.
@ -200,7 +199,7 @@ public final class DarkZone extends MapZone implements EventHook<UsedWithEvent>{
}
@Override
public void process(@NotNull Entity entity, @NotNull UsedWithEvent event) {
public void process(@NotNull Entity entity, @NotNull UseWithEvent event) {
boolean isTinderbox = getItemName(event.getUsed()).equals("Tinderbox") || getItemName(event.getWith()).equals("Tinderbox");
if (isTinderbox && entity instanceof Player) runTask(entity, 2, () -> {

View file

@ -1,6 +1,6 @@
package core.net.packet.in;
import api.events.ButtonClickedEvent;
import api.events.ButtonClickEvent;
import core.game.component.Component;
import core.game.component.ComponentPlugin;
import core.game.container.Container;
@ -62,7 +62,7 @@ public class ActionButtonPacket implements IncomingPacket {
}
int cOpcode = buffer.opcode();
ComponentPlugin plugin = c.getPlugin();
player.dispatch(new ButtonClickedEvent(c.getId(), buttonId));
player.dispatch(new ButtonClickEvent(c.getId(), buttonId));
if (plugin != null) {
player.debug("Component plugin = " + plugin.getClass().getSimpleName());
plugin.handle(player, c, cOpcode, buttonId, slot, itemId);

View file

@ -1,6 +1,6 @@
import api.*
import api.events.EventHook
import api.events.SelfDeath
import api.events.SelfDeathEvent
import core.game.component.Component
import core.game.content.dialogue.FacialExpression
import core.game.interaction.MovementPulse
@ -362,9 +362,9 @@ abstract class Cutscene(val player: Player) {
companion object {
const val ATTRIBUTE_CUTSCENE = "cutscene"
const val ATTRIBUTE_CUTSCENE_STAGE = "cutscene:stage"
object CUTSCENE_DEATH_HOOK : EventHook<SelfDeath>
object CUTSCENE_DEATH_HOOK : EventHook<SelfDeathEvent>
{
override fun process(entity: Entity, event: SelfDeath) {
override fun process(entity: Entity, event: SelfDeathEvent) {
if(entity !is Player) return
entity.getCutscene()?.end() ?: entity.unhook(this)
}

View file

@ -135,6 +135,15 @@ fun isEquipped(player: Player, id: Int): Boolean {
return amountInEquipment(player, id) > 0
}
/**
* Check that a set of items is equipped by the given player
*/
fun areEquipped(player: Player, vararg ids: Int): Boolean {
return ids.all { id ->
amountInEquipment(player, id) > 0
}
}
data class ContainerisedItem(val container: core.game.container.Container?, val itemId: Int)
/**

View file

@ -1,22 +1,44 @@
package api.events
import core.game.component.Component
import core.game.content.dialogue.DialoguePlugin
import core.game.node.Node
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.link.SpellBookManager.SpellBook
import core.game.node.entity.player.link.TeleportManager.TeleportType
import core.game.node.item.Item
import core.game.world.map.Location
import rs09.game.content.jobs.JobType
import rs09.game.interaction.inter.FairyRing
import rs09.game.node.entity.skill.magic.TeleportMethod
data class ResourceProducedEvent(val itemId: Int, val amount: Int, val source: Node, val original: Int = -1) : Event
data class NPCKillEvent(val npc: NPC) : Event
data class TeleportEvent(val type: TeleportType, val source: Int = -1, val location: Location) : Event
data class TeleportEvent(val type: TeleportType, val method: TeleportMethod, val source: Any, val location: Location) : Event
data class LitFireEvent(val logId: Int) : Event
data class InteractionEvent(val target: Node, val option: String) : Event
data class ButtonClickedEvent(val iface: Int, val buttonId: Int) : Event
data class UsedWithEvent(val used: Int, val with: Int) : Event
data class SelfDeath(val killer: Entity) : Event
data class ButtonClickEvent(val iface: Int, val buttonId: Int) : Event
data class DialogueOpenEvent(val dialogue: DialoguePlugin) : Event
data class DialogueOptionSelectionEvent(val dialogue: Any, val currentStage: Int, val optionId: Int) : Event
data class DialogueCloseEvent(val dialogue: DialoguePlugin) : Event
data class UseWithEvent(val used: Int, val with: Int) : Event
data class SelfDeathEvent(val killer: Entity) : Event
data class TickEvent(val worldTicks: Int) : Event
data class PickUpEvent(val itemId: Int) : Event
data class InterfaceOpenEvent(val component: Component) : Event
data class InterfaceCloseEvent(val component: Component) : Event
data class VarbitUpdateEvent(val offset: Int, val value: Int) : Event
data class AttributeSetEvent(val entity: Entity, val attribute: String, val value: Any) : Event
data class AttributeRemoveEvent(val entity: Entity, val attribute: String) : Event
data class SpellCastEvent(val spellBook: SpellBook, val spellId: Int) : Event
data class ItemAlchemizationEvent(val itemId: Int, val isHigh: Boolean) : Event
data class ItemEquipEvent(val itemId: Int, val slotId: Int) : Event
data class ItemUnequipEvent(val itemId: Int, val slotId: Int) : Event
data class ItemShopPurchaseEvent(val itemId: Int, val amount: Int, val currency: Item) : Event
data class ItemShopSellEvent(val itemId: Int, val amount: Int, val currency: Item) : Event
data class JobAssignmentEvent(val jobType: JobType, val employerNpc: NPC) : Event
data class FairyRingDialEvent(val fairyRing: FairyRing) : Event
data class VarbitUpdateEvent(val offset: Int, val value: Int) : Event
data class DynamicSkillLevelChangeEvent(val skillId: Int, val oldValue: Int, val newValue: Int): Event
data class SummoningPointsRechargeEvent(val obelisk: Node) : Event
data class PrayerPointsRechargeEvent(val altar: Node) : Event

View file

@ -5,15 +5,31 @@ import api.events.*
object Event {
@JvmStatic val ResourceProduced = ResourceProducedEvent::class.java
@JvmStatic val NPCKilled = NPCKillEvent::class.java
@JvmStatic val Teleport = TeleportEvent::class.java
@JvmStatic val Teleported = TeleportEvent::class.java
@JvmStatic val FireLit = LitFireEvent::class.java
@JvmStatic val Interaction = InteractionEvent::class.java
@JvmStatic val ButtonClicked = ButtonClickedEvent::class.java
@JvmStatic val UsedWith = UsedWithEvent::class.java
@JvmStatic val SelfDeath = SelfDeath::class.java
@JvmStatic val Interacted = InteractionEvent::class.java
@JvmStatic val ButtonClicked = ButtonClickEvent::class.java
@JvmStatic val DialogueOpened = DialogueOpenEvent::class.java
@JvmStatic val DialogueOptionSelected = DialogueOptionSelectionEvent::class.java
@JvmStatic val DialogueClosed = DialogueCloseEvent::class.java
@JvmStatic val UsedWith = UseWithEvent::class.java
@JvmStatic val SelfDeath = SelfDeathEvent::class.java
@JvmStatic val Tick = TickEvent::class.java
@JvmStatic val PickedUp = PickUpEvent::class.java
@JvmStatic val InterfaceOpened = InterfaceOpenEvent::class.java
@JvmStatic val InterfaceClosed = InterfaceCloseEvent::class.java
@JvmStatic val AttributeSet = AttributeSetEvent::class.java
@JvmStatic val AttributeRemoved = AttributeRemoveEvent::class.java
@JvmStatic val SpellCast = SpellCastEvent::class.java
@JvmStatic val ItemAlchemized = ItemAlchemizationEvent::class.java
@JvmStatic val ItemEquipped = ItemEquipEvent::class.java
@JvmStatic val ItemUnequipped = ItemUnequipEvent::class.java
@JvmStatic val ItemPurchased = ItemShopPurchaseEvent::class.java
@JvmStatic val ItemSold = ItemShopSellEvent::class.java
@JvmStatic val JobAssigned = JobAssignmentEvent::class.java
@JvmStatic val FairyRingDialed = FairyRingDialEvent::class.java
@JvmStatic val VarbitUpdated = VarbitUpdateEvent::class.java
@JvmStatic val DynamicSkillLevelChanged = DynamicSkillLevelChangeEvent::class.java
@JvmStatic val SummoningPointsRecharged = SummoningPointsRechargeEvent::class.java
@JvmStatic val PrayerPointsRecharged = PrayerPointsRechargeEvent::class.java
}

View file

@ -23,7 +23,6 @@ class CaptainCainDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun open(vararg args: Any?): Boolean {
npcl(FacialExpression.FRIENDLY, "Hello, there, adventurer. Say, you wouldn't happen to be interested in purchasing a Fighter Torso would you?")
player.achievementDiaryManager.finishTask(player,DiaryType.FREMENNIK,0,3)
stage = 0
return true
}

View file

@ -0,0 +1,157 @@
package rs09.game.content.dialogue.region.falador
import api.*
import core.game.content.dialogue.DialoguePlugin
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import rs09.game.content.dialogue.IfTopic
import rs09.game.content.dialogue.Topic
import rs09.tools.END_DIALOGUE
import rs09.tools.START_DIALOGUE
/**
* Handles dialogue for Kaylee and Emily
* of the Rising Sun Inn
*
* @author vddCore
*/
@Initializable
class RisingSunInnBartenderDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun newInstance(player: Player): DialoguePlugin
= RisingSunInnBartenderDialogue(player)
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
npcl(
FacialExpression.HAPPY,
"Hi! What can I get you?"
)
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
START_DIALOGUE -> if (hasAnyBeerGlasses()) {
showTopics(
Topic(FacialExpression.HALF_ASKING, "What ales are you serving?", 10),
Topic(FacialExpression.HALF_GUILTY, "I've got some beer glasses...", 20)
)
} else {
playerl(FacialExpression.HALF_ASKING, "What ales are you serving?")
.also { stage = 10 }
}
10 -> npcl(
FacialExpression.HALF_GUILTY,
"Well, we've got Asgarnian Ale, Wizard's Mind Bomb and Dwarven Stout. "
+ "Each for only 3 coins."
).also { stage++ }
11 -> showTopics(
Topic(FacialExpression.HAPPY, "One Asgarnian Ale, please.", 12),
Topic(FacialExpression.HAPPY, "I'll try the Mind Bomb.", 13),
Topic(FacialExpression.HALF_ASKING, "Can I have a Dwarven Stout?", 14),
Topic(FacialExpression.NEUTRAL, "I don't feel like any of those.", END_DIALOGUE)
)
12 -> if (ensureHasMoney()) {
purchaseBrew(Items.ASGARNIAN_ALE_1905)
}
13 -> if (ensureHasMoney()) {
purchaseBrew(Items.WIZARDS_MIND_BOMB_1907)
}
14 -> if (ensureHasMoney()) {
purchaseBrew(Items.DWARVEN_STOUT_1913)
}
20 -> {
npcl(
FacialExpression.HALF_GUILTY,
"Oh, we will buy those from you if you're interested. We offer 2 coins for each glass."
).also { stage ++ }
}
21 -> showTopics(
Topic(FacialExpression.HAPPY, "Yes, please!", 22),
Topic(FacialExpression.NEUTRAL, "No thanks, I like my empty beer glasses.", END_DIALOGUE)
)
22 -> {
trySellAllBeerGlasses()
npcl(
FacialExpression.FRIENDLY,
"There you go!"
).also { stage = END_DIALOGUE }
}
30 -> {
playerl(FacialExpression.FRIENDLY, "Thanks, ${npc.name}.")
.also { stage = END_DIALOGUE }
}
}
return true
}
override fun getIds(): IntArray = intArrayOf(
NPCs.EMILY_736,
NPCs.KAYLEE_3217
)
private fun ensureHasMoney(): Boolean {
if (!inInventory(player, Items.COINS_995, 3)) {
npcl(FacialExpression.ANGRY, "No freeloaders!")
.also {
sendMessage(player, "You don't have enough money to buy that.")
stage = END_DIALOGUE
}
return false
}
return true
}
private fun purchaseBrew(brewId: Int) {
if (removeItem(player, Item(Items.COINS_995, 3))) {
addItemOrDrop(player, brewId)
sendItemDialogue(
player,
Item(brewId),
"You hand 3 coins over to ${npc.name}. She gives you ${when (brewId) {
Items.WIZARDS_MIND_BOMB_1907 -> "a Wizard's Mind Bomb"
Items.DWARVEN_STOUT_1913 -> "a Dwarven Stout"
Items.ASGARNIAN_ALE_1905 -> "an Asgarnian Ale"
else -> "a broken fucking dialogue"
}}."
).also { stage = 30 }
}
}
private fun hasAnyBeerGlasses()
= inInventory(player, Items.BEER_GLASS_1919)
|| inInventory(player, Items.BEER_GLASS_1920)
private fun trySellAllBeerGlasses() {
val regularGlassAmount = amountInInventory(player, Items.BEER_GLASS_1919)
val notedGlassAmount = amountInInventory(player, Items.BEER_GLASS_1920)
if (removeItem(player, Item(Items.BEER_GLASS_1919, regularGlassAmount))) {
addItem(player, Items.COINS_995, regularGlassAmount * 2)
}
if (removeItem(player, Item(Items.BEER_GLASS_1920, notedGlassAmount))) {
addItem(player, Items.COINS_995, notedGlassAmount * 2)
}
}
}

View file

@ -33,8 +33,7 @@ class DukeHoracioDialogue(player: Player? = null) : DialoguePlugin(player) {
if (!sendChoices()) {
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Greetings. Welcome to my castle.")
}
// Speak to the Duke of Lumbridge
player.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 0, 2)
return true
}

View file

@ -6,12 +6,14 @@ import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.plugin.Initializable
import org.rs09.consts.NPCs
import rs09.game.content.dialogue.Topic
import rs09.tools.END_DIALOGUE
import rs09.tools.START_DIALOGUE
/**
* Represents the dialogue plugin used for Otto
* @author Splinter
* @version 1.0
* @author vddCore
*/
@Initializable
class OttoGodblessedDialogue(player: Player? = null) : DialoguePlugin(player) {
@ -22,40 +24,69 @@ class OttoGodblessedDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
npc("Good day, you seem a hearty warrior. Maybe even", "some barbarian blood in that body of yours?")
stage = -1
return true
}
override fun init() {
super.init()
npcl(
FacialExpression.HAPPY,
"Good day, you seem a hearty warrior. "
+ "Maybe even some barbarian blood in that body of yours?"
)
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
-1 -> options("Ask about barbarian training", "Nevermind.").also { stage++ }
0 -> when(buttonId){
1 -> player("Is there anything you can teach me?").also { stage = 20 }
2 -> stage++
START_DIALOGUE -> showTopics(
Topic(FacialExpression.ASKING, "Is there anything you can teach me?", 1),
Topic(FacialExpression.NEUTRAL, "Nevermind.", END_DIALOGUE)
)
1 -> npcl(
FacialExpression.FRIENDLY,
"I can teach you how to fish."
).also { stage++ }
2 -> playerl(
FacialExpression.HALF_ROLLING_EYES,
"Oh, that's pretty underwhelming. But uhhh, okay!"
).also { stage++ }
3 -> npcl(
FacialExpression.FRIENDLY,
"Alright, so here's what you gotta do: you need to grab a pole and some bait, and then... "
+ "Fling it into the water!"
).also { stage++ }
4 -> playerl(
FacialExpression.HALF_ASKING,
"The whole... Pole?"
).also { stage++ }
5 -> npcl(
FacialExpression.ANNOYED,
"No, not the whole pole!"
).also { stage++ }
6 -> npcl(
FacialExpression.ANNOYED,
"Look. Just... Grab the pole from under my bed and go click on that fishing spot."
).also { stage++ }
7 -> playerl(
FacialExpression.STRUGGLE,
"...click?"
).also { stage++ }
8 -> npcl(
FacialExpression.FURIOUS,
"JUST GO DO IT!"
).also {
stage = END_DIALOGUE;
player.setAttribute("/save:barbtraining:fishing", true)
}
1 -> stage = END_DIALOGUE
20 -> npc("I can teach you how to fish.").also { stage++ }
21 -> player("Oh, that's pretty underwhelming. But uhhh, okay!").also { stage++ }
22 -> npc("Alright so here's what you gotta do:","You need to grab a pole and some bait, and then","fling it into the water!").also { stage++ }
23 -> player("The whole pole?").also { stage++ }
24 -> npc(FacialExpression.ANGRY, "No, not the whole pole!").also { stage++ }
25 -> npc("Look, just... grab the pole under my bed","and go click on that fishing spot.").also { stage++ }
26 -> player(FacialExpression.ASKING,"...click?").also { stage++ }
27 -> npc(FacialExpression.FURIOUS, "JUST GO DO IT!").also { stage++; player.setAttribute("/save:barbtraining:fishing",true) }
28 -> end().also { player.achievementDiaryManager.finishTask(player, DiaryType.FREMENNIK,0,4) }
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(2725)
}
override fun getIds(): IntArray = intArrayOf(NPCs.OTTO_GODBLESSED_2725)
}

View file

@ -4,14 +4,15 @@ import core.game.content.dialogue.DialoguePlugin
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.plugin.Initializable
import org.rs09.consts.NPCs
import rs09.game.content.dialogue.Topic
import rs09.tools.END_DIALOGUE
import rs09.tools.START_DIALOGUE
/**
* Represents the dialogue plugin used for the Hunting Expert in the Rellekkan Hunter area
* @author Crash
* @version 1.0
* @author vddcore
*/
@Initializable
class HuntingExpertRellekkaDialogue(player: Player? = null) : DialoguePlugin(player) {
@ -22,40 +23,67 @@ class HuntingExpertRellekkaDialogue(player: Player? = null) : DialoguePlugin(pla
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
npc("Good day, you seem to have a keen eye. Maybe even", "some hunter's blood in that body of yours?")
stage = -1
return true
}
override fun init() {
super.init()
npcl(
FacialExpression.HAPPY,
"Good day, you seem to have a keen eye. "
+ "Maybe even some hunter's blood in that body of yours?"
)
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
-1 -> options("Ask about polar hunting", "Nevermind.").also { stage++ }
0 -> when(buttonId){
1 -> player("Is there anything you can teach me?").also { stage = 20 }
2 -> stage++
}
START_DIALOGUE -> showTopics(
Topic(FacialExpression.ASKING, "Is there anything you can teach me?", 1),
Topic(FacialExpression.NEUTRAL, "Nevermind.", END_DIALOGUE)
)
1 -> stage = END_DIALOGUE
1 -> npcl(
FacialExpression.FRIENDLY,
"I can teach you how to hunt."
).also { stage++ }
2 -> playerl(
FacialExpression.THINKING,
"What kind of creatures can I hunt?"
).also { stage++ }
20 -> npc("I can teach you how to hunt.").also { stage++ }
21 -> player("What kind of creatures can I hunt?").also { stage++ }
22 -> npc("Many creatures in many ways.","You need to make some traps","and catch birds!").also { stage++ }
23 -> player("Birds?").also { stage++ }
24 -> npc(FacialExpression.ANGRY, "Yes, birds! Like these ones here!").also { stage++ }
25 -> npc("Look, just... get some Hunting gear","and go set up some traps.").also { stage++ }
26 -> player(FacialExpression.ASKING,"Is that it?").also { stage++ }
27 -> npc(FacialExpression.FURIOUS, "JUST GO DO IT!").also { stage++ }
28 -> end().also { player.achievementDiaryManager.finishTask(player, DiaryType.FREMENNIK,0,6) }
3 -> npcl(
FacialExpression.FRIENDLY,
"Many creatures in many ways. You need to make some traps "
+ "and catch birds!"
).also { stage++ }
4 -> playerl(
FacialExpression.HALF_ASKING,
"Birds?"
).also { stage++ }
5 -> npcl(
FacialExpression.ANNOYED,
"Yes, birds! Like the ones here!"
).also { stage++ }
6 -> npcl(
FacialExpression.ANNOYED,
"Look. Just... Get some hunting gear and go set up some traps."
).also { stage++ }
7 -> playerl(
FacialExpression.HALF_ROLLING_EYES,
"Is that it?"
).also { stage++ }
8 -> npcl(
FacialExpression.FURIOUS,
"JUST GO DO IT!"
).also { stage = END_DIALOGUE }
}
return true
}
override fun getIds(): IntArray {
return intArrayOf(5112)
}
override fun getIds(): IntArray
= intArrayOf(NPCs.HUNTING_EXPERT_5112)
}

View file

@ -1,158 +0,0 @@
package rs09.game.content.dialogue.region.sorcererstower
import core.game.component.Component
import core.game.content.dialogue.DialoguePlugin
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.item.Item
import core.plugin.Initializable
import org.rs09.consts.Items
/**
* Thormac
* Involved in Scorpion Catcher
* @author afaroutdude
*/
@Initializable
class ThormacDialogue(player: Player? = null) : DialoguePlugin(player) {
val scorpionCageEmpty = Item(Items.SCORPION_CAGE_456)
val scorpionCageFull = Item(Items.SCORPION_CAGE_463)
val scorpionCages: IntArray = intArrayOf(
Items.SCORPION_CAGE_456,
Items.SCORPION_CAGE_457,
Items.SCORPION_CAGE_458,
Items.SCORPION_CAGE_459,
Items.SCORPION_CAGE_460,
Items.SCORPION_CAGE_461,
Items.SCORPION_CAGE_462,
Items.SCORPION_CAGE_463
)
val COMPONENT = Component(332)
override fun open(vararg args: Any?): Boolean {
val scorpionStage = try {
player?.questRepository?.getStage("Scorpion Catcher") ?: 100
} catch (e: Exception) {
100
}
when (scorpionStage) {
0 -> {
npc("Hello I am Thormac the Sorcerer, I don't suppose you could be of assistance to me?");stage = 0
}
10, 20, 30, 40, 50, 60, 70, 80, 90 -> {
npc("How goes your quest?");stage = 70
}
100 -> {
npc("Thank you for rescuing my scorpions.");stage = 100
}
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
999 -> {end()}
// initial convo
0 -> {options("What do you need assistance with?", "I'm a little busy.");stage++}
1 -> when(buttonId){
1 -> {player ("What do you need assistance with?");stage=2}
2 -> {player ("I'm a little busy.");stage=50}
}
2 -> {npc ("I've lost my pet scorpions. They're lesser Kharid scorpions, a very rare breed. I left their cage door open, now I don't know where they've gone. There's three of them, and they're quick little beasties. They're all over 2009scape.")}
3 -> {options ("So how would I go about catching them then?", "What's in it for me?", "I'm not interested then.");stage++}
4 -> when(buttonId){
1 -> {player("So how would I go about catching them then?");stage++}
2 -> {player("What's in it for me?");stage=20}}
3 -> {player ("I'm not interested then.");stage=51}
5 -> {npc("Well I have a scorpion cage here which you can use to catch them in.");stage++}
6 -> {
sendDialogue("Thormac gives you a cage.")
player.inventory.add(scorpionCageEmpty)
stage++
}
7 -> {npc ("If you go up to the village of Seers, to the North of here, one of them will be able to tell you where the scorpions are now.");stage++}
8 -> {options ("What's in it for me?", "Ok, I will do it then.");stage++}
9 -> when(buttonId){
1 -> {player("What's in it for me?");stage=20}
2 -> {
player("Ok, I will do it then.")
// start quest here
stage = 999
}
}
20 -> {npc ("Well I suppose I can aid you with my skills as a staff sorcerer. Most battlestaffs around here are a bit puny. I can beef them up for you a bit. If you go up to the village of Seers, to the North of here, one of them will be able to tell you where the scorpions are now.");stage++}
21 -> {options("So how would I go about catching them then?","Ok, I will do it then.");stage++}
22 -> when(buttonId) {
1 -> {player("So how would I go about catching them then?");stage=5}
2 -> {
player("Ok, I wil do it then.")
// start quest here
stage = 999
}
}
50 -> {npc ("Come back if you have some spare time.");stage=999} // invention
51 -> {npc ("Come back if you change your mind.");stage=999} // invention
// after that
70 -> {
if (!player.inventory.containsAtLeastOneItem(scorpionCages)
&& !player.bank.containsAtLeastOneItem(scorpionCages)) {
player("I've lost my cage.")
stage = 71
} else if (!player.inventory.containsAtLeastOneItem(scorpionCageFull.id)) {
player("I've not caught all the scorpions yet.")
stage = 72
} else {
player("I have retrieved all your scorpions.")
stage = 73
}
}
71 -> {
// if lost or destroyed cage
npc("Ok, here's another cage. You're almost as bad at losing things as me.")
player.inventory.add(scorpionCageEmpty)
stage=999
}
72 -> {npc("Well remember to go speak to the Seers, North of here, if you need any help.");stage=999}
73 -> {
npc("Aha, my little scorpions home at last!")
// complete quest here
stage=999
}
// post-quest
100 -> {
if (!player.inventory.contains(84,1)) {
options("That's okay.", "You said you'd enchant my battlestaff for me.")
} else {
options("That's okay.", "You said you'd enchant my battlestaff for me.", "Could you enchant my Armadyl battlestaff?")
}
stage++
}
101 -> when (buttonId) {
1 -> {player("That's okay.");stage=999}
2 -> {player ("You said you'd enchant my battlestaff for me.");stage=110}
3 -> {player ("Could you enchant my Armadyl battlestaff?");stage=150}
}
110 -> {npc("Yes, although it'll cost you 40,000 coins for the","materials. What kind of staff did you want enchanting?");stage++}
111 -> {
end()
player.interfaceManager.open(COMPONENT)
player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 1, 1)
}
}
return true;
}
override fun newInstance(player: Player?): DialoguePlugin {
return ThormacDialogue(player)
}
override fun getIds(): IntArray {
return intArrayOf(389)
}
}

View file

@ -1,97 +1,215 @@
package rs09.game.content.dialogue.region.varrock
import api.inInventory
import api.removeItem
import api.sendInputDialogue
import api.sendItemDialogue
import core.game.content.dialogue.DialoguePlugin
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.item.Item
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import rs09.game.content.dialogue.Topic
import rs09.tools.END_DIALOGUE
import rs09.tools.START_DIALOGUE
/**
* Elsie
* @author afaroutdude
* @author Regenleif
*/
@Initializable
class ElsieDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun open(vararg args: Any?): Boolean {
when (player.inventory.containsAtLeastOneItem(Items.CUP_OF_TEA_712)) {
true -> npc("Ooh - that looks like a lovely cup of tea, dearie.", "Is it for me?").also { stage = 100 }
false -> npc("Hello dearie! What can old Elsie do for you?").also { stage = 10 }
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
999 -> end()
10 -> interpreter.sendOptions("What would you like to say?", "What are you making?", "Can you tell me a story?", "Can you tell me how to get rich?").also { stage++ }
11 ->
when (buttonId) {
1 -> player("What are you making?").also { stage = 21 }
2 -> player("Can you tell me a story?").also { stage = 31 }
3 -> player("Can you tell me how to get rich?").also { stage = 41 }
}
21 -> npc("I'm knitting a new stole for Father Lawrence", "downstairs. He could do with something to keep his", "neck warm, standing in that draughty old church", "all day.").also { stage++ }
22 -> interpreter.sendOptions("What would you like to say?", "Can you tell me a story?", "Can you tell me how to get rich?").also { stage++ }
23 ->
when (buttonId) {
1 -> player("Can you tell me a story?").also { stage = 31 }
2 -> player("Can you tell me how to get rich?").also { stage = 41 }
}
31 -> npc("Maybe I could tell you a story if you'd fetch me", "a nice cup of tea.").also { stage++ }
32 -> player("I'll think about it.").also { stage = 999 }
41 -> npc("Well, dearie, I'm probably not the best person to", "ask about money, but I think the best thing would", "be for you to get a good trade. If you've got a trade", "you can earn your way, that's what my old father told me.").also { stage++ }
42 -> npc("Saradomin rest his soul. I hear people try to get", "rich by fighting in the Wilderness north of here or", "the Duel Arena in the south, but that's no way for honest", "folks to earn a living! So get yourself a good trade, and").also { stage++ }
43 -> npc("keep working at it. There's always folks wanting", "to buy ore and food around here.").also { stage++ }
44 -> player("Thanks, old woman.").also { stage++ }
45 -> interpreter.sendOptions("What would you like to say?", "What are you making?", "Can you tell me a story?").also { stage++ }
46 ->
when (buttonId) {
1 -> player("What are you making?").also { stage = 21 }
2 -> player("Can you tell me a story?").also { stage = 31 }
}
100 -> interpreter.sendOptions("What would you like to say?", "Yes, you can have it.", "No, keep your hands off my tea.").also { stage++ }
101 ->
when (buttonId) {
1 -> player("Yes, you can have it.").also { stage = 103 }
2 -> player("No, keep your hands off my tea.").also { stage = 120 }
}
103 -> npc("Ahh, there's nothing like a nice cuppa tea. I know what,", "I'll tell you a story to thank you for the lovely tea...").also {
player.inventory.remove(Item(Items.CUP_OF_TEA_712))
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 0, 14)
stage++
}
104 -> npc("A long time ago, when I was a little girl, there was a", "handsome young man living in Varrock. I saw him here", "in the church quite often. Everyone said he was going", "to become a priest, and we girls were so sad about that.").also { stage++ }
105 -> npc("But young Dissy - that was the young man's nickname", "- he was a wild young thing. One night he gathered", "some lads together, and after the evening prayer-", "meeting they all put on masks and sneaked down to the").also { stage++ }
106 -> npc("evil temple in the south of the city, the evil one. The", "next day, there was quite a hubbub. The guards told us", "that someone had painted 'Saradomin pwns' on the wall", "of the Zamorakian temple!").also { stage++ }
107 -> npc("Now, we'd always been taught to keep well away from", "that dreadful place, but it really did us all good to see", "someone wasn't afraid of the scum who live at that end", "of town. Old Father Packett was furious, but Dissy just").also { stage++ }
108 -> npc("laughed it off.").also { stage++ }
109 -> npc("Dissy left town after that, saying he wanted to see the", "world. It was such a shame, he had the most handsome", "shoulders...").also { stage++ }
110 -> npc("A young man came here looking for stories about Dissy", "- of course, that's not his proper name, but his friends", "called him Dissy - and I told him that one. He said", "Dissy had become a really famous man and there was").also { stage++ }
111 -> npc("going to be a book about him. Well, that's all good, but I", "do wish Dissy had just come back to Varrock. I did", "miss him so much... well, until I met my Freddie and", "we got married, but that's another story.").also { stage++ }
112 -> player("Thank you. I'll leave you to", "your knitting now.").also { stage = 999 }
120 -> npc("Aww. Maybe another time.", "Anyway, what can old Elsie do for you?").also { stage++ }
121 -> interpreter.sendOptions("What would you like to say?", "What are you making?", "Can you tell me a story?", "Can you tell me how to get rich?").also { stage++ }
122 ->
when (buttonId) {
1 -> player("What are you making?").also { stage = 21 }
2 -> player("Can you tell me a story?").also { stage = 123 }
3 -> player("Can you tell me how to get rich?").also { stage = 41 }
}
123 -> npc("Well, maybe I could tell a story if you'd give", "me that lovely cup of tea you've got there.").also { stage = 100 }
}
return true;
}
override fun newInstance(player: Player?): DialoguePlugin {
return ElsieDialogue(player)
}
override fun getIds(): IntArray {
return intArrayOf(5915)
override fun open(vararg args: Any?): Boolean {
npc = args[0] as NPC
if (hasTea()) {
npcl(
FacialExpression.FRIENDLY,
"Ooh - that looks like a lovely cup of tea, dearie. Is it for me?"
).also { stage = 10 }
} else {
npcl(
FacialExpression.FRIENDLY,
"Hello dearie! What can old Elsie do for you?"
)
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
START_DIALOGUE -> showTopics(
Topic(FacialExpression.ASKING, "What are you making?", 1),
Topic(FacialExpression.ASKING, "Can you tell me a story?", 3),
Topic(FacialExpression.ASKING, "Can you tell me how to get rich?", 5),
Topic(FacialExpression.NEUTRAL, "I've got to go.", END_DIALOGUE)
)
1 -> npcl(
FacialExpression.FRIENDLY,
"I'm knitting a new stole for Father Lawrence downstairs."
).also { stage++ }
2 -> npcl(
FacialExpression.FRIENDLY,
"He could do with something to keep his neck warm, standing in "
+ "that draughty old church all day."
).also { stage = START_DIALOGUE }
3 -> {
if (hasTea()) {
npcl(
FacialExpression.HALF_THINKING,
"Perhaps... Can I have that lovely cup of tea you have over there?"
).also { stage = 10 }
} else {
npcl(
FacialExpression.NEUTRAL,
"Maybe I could tell you a story if you'd fetch me a nice cup of tea."
).also { stage++ }
}
}
4 -> playerl(
FacialExpression.ROLLING_EYES,
"I'll think about it."
).also { stage = START_DIALOGUE }
5 -> npcl(
FacialExpression.NEUTRAL,
"Well, dearie, I am probably not the best person to ask about money, but I think the best thing "
+ "would be for you to get a good trade."
).also { stage++ }
6 -> npcl(
FacialExpression.HALF_WORRIED,
"If you've got a good trade you can earn your way. That's what my old father would tell me."
).also { stage++ }
7 -> npcl(
FacialExpression.HALF_WORRIED,
"Saradomin rest his soul. I hear people try to get rich by fighting in the Wilderness north of here "
+ "or the Duel Arena in the south... But that's no way for honest folk to earn a living!"
).also { stage++ }
8 -> npcl(
FacialExpression.HALF_WORRIED,
"So get yourself a good trade, and keep working at it. There's always folks wanting to buy ore and food around here."
).also { stage++ }
9 -> playerl(
FacialExpression.ROLLING_EYES,
"Thanks, old woman."
).also { stage = START_DIALOGUE }
10 -> showTopics(
Topic(FacialExpression.HAPPY, "Yes, you can have it.", 12),
Topic(FacialExpression.ANNOYED, "No, keep your hands off my tea.", 11)
)
11 -> npcl(
FacialExpression.SAD,
"Aww. Maybe another time, then... Anyway, what can old Elsie do for you?"
).also { stage = START_DIALOGUE }
12 -> sendItemDialogue(player, Items.CUP_OF_TEA_712, "Elsie takes a sip from the cup of tea.")
.also { stage++; removeItem(player, Items.CUP_OF_TEA_712) }
13 -> npcl(
FacialExpression.HAPPY,
"Ahh, there's nothing like a nice cuppa tea. You know what, I'll tell you a story as a thank-you for that lovely tea..."
).also { stage++ }
14 -> npcl(
FacialExpression.NEUTRAL,
"A long time ago, when I was a little girl, there was a handsome young man living in Varrock..."
).also { stage++ }
15 -> npcl(
FacialExpression.HALF_GUILTY,
"I saw him here in the church quite often. Everyone said he was going to become a priest and "
+ "we girls were so sad about that..."
).also { stage++ }
16 -> npcl(
FacialExpression.NEUTRAL,
"But young Dissy - that was the young man's nickname - he was a wild young thing."
).also { stage++ }
17 -> npcl(
FacialExpression.NEUTRAL,
"One night he gathered some lads together, and after the evening prayer-meeting "
+ "they all put their masks on..."
).also { stage++ }
18 -> npcl(
FacialExpression.NEUTRAL,
"Then, they snuck down to the temple in the south of the city - the evil one. "
+ "The next day, there was quite a hubbub..."
).also { stage++ }
19 -> npcl(
FacialExpression.LAUGH,
"The guards told us that someone had painted 'Saradomin pwns' on the wall of Zamorakian temple!"
).also { stage++ }
20 -> npcl(
FacialExpression.HALF_THINKING,
"Now, we'd always been taught to keep well away from that dreadful place..."
).also { stage++ }
21 -> npcl(
FacialExpression.FRIENDLY,
"But it really did us all good to see someone wasn't afraid of the scum who live at that end of town."
).also { stage++ }
22 -> npcl(
FacialExpression.NEUTRAL,
"Old Father Packett was furious, but Dissy just laughed it off. "
+ "Dissy left town after that, saying he wanted to see the world."
).also { stage++ }
23 -> npcl(
FacialExpression.HALF_GUILTY,
"It was such a shame, he had the most handsome... Shoulders..."
).also { stage++ }
24 -> npcl(
FacialExpression.HAPPY,
"One day, a young man came here looking for stories about Dissy - of course, "
+ "that's not his proper name, but his friends called him Dissy - and I told "
+ "him that one. "
).also { stage++ }
25 -> npcl(
FacialExpression.HALF_WORRIED,
"He said Dissy had become a really famous man and there was going to be a book about him. "
+ "That's good and all, but I do wish Dissy had just come back to Varrock. I did miss him so much... "
).also { stage++ }
26 -> npcl(
FacialExpression.HAPPY,
"Well, until I met my Freddie and we got married. But that's another story."
).also { stage++ }
27 -> playerl(
FacialExpression.FRIENDLY,
"Thank you. I'll leave you to your knitting now."
).also { stage = END_DIALOGUE }
}
return true
}
override fun getIds(): IntArray = intArrayOf(NPCs.ELSIE_5915)
private fun hasTea(): Boolean {
return inInventory(player, Items.CUP_OF_TEA_712)
}
}

View file

@ -7,6 +7,7 @@ import core.game.node.entity.player.link.diary.DiaryType
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import org.rs09.consts.Components
@Initializable
class ThessaliaDialogue(player: Player? = null): DialoguePlugin(player) {
@ -15,13 +16,12 @@ class ThessaliaDialogue(player: Player? = null): DialoguePlugin(player) {
//The trade argument is handled elsewhere
if (args.size == 3) { //Right-Click 'Change-Clothes' Option
if (player.equipment.isEmpty) {
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 0, 0)
if (player.isMale) {
end()
player.interfaceManager.open(Component(591))
player.interfaceManager.open(Component(Components.THESSALIA_CLOTHES_MALE_591))
} else {
end()
player.interfaceManager.open(Component(594))
player.interfaceManager.open(Component(Components.THESSALIA_CLOTHES_FEMALE_594))
}
} else { //Has some armour equipped
interpreter.sendDialogues(548, FacialExpression.WORRIED, "You can't try them on while wearing armour. Take", "it off and speak to me again.")
@ -110,13 +110,12 @@ class ThessaliaDialogue(player: Player? = null): DialoguePlugin(player) {
stage = 52
}
31 -> if (player.equipment.isEmpty) {
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 0, 0)
if (player.isMale) {
end()
player.interfaceManager.open(Component(591))
player.interfaceManager.open(Component(Components.THESSALIA_CLOTHES_MALE_591))
} else {
end()
player.interfaceManager.open(Component(594))
player.interfaceManager.open(Component(Components.THESSALIA_CLOTHES_FEMALE_594))
}
}
49 -> {

View file

@ -12,6 +12,7 @@ import core.game.world.map.Location
import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics
import org.rs09.consts.Items
import rs09.game.node.entity.skill.magic.TeleportMethod
import rs09.game.node.entity.skill.slayer.SlayerManager.Companion.getInstance
import rs09.game.world.GameWorld.Pulser
import java.util.*
@ -108,8 +109,8 @@ enum class EnchantedJewellery(
arrayOf(
Location.create(2899, 3563, 0),
Location.create(2520, 3571, 0),
Location.create(3266, 3686, 0),
Location.create(3179, 3685, 0),
Location.create(3266, 3686, 0),
Location.create(2885, 4372, 2)
),
true,
@ -235,7 +236,7 @@ enum class EnchantedJewellery(
replaceJewellery(player, item, nextJewellery, isEquipped)
}
unlock(player)
player.dispatch(TeleportEvent(TeleportManager.TeleportType.NORMAL, 1,location))
player.dispatch(TeleportEvent(TeleportManager.TeleportType.NORMAL, TeleportMethod.JEWELRY, item, location))
return true
}
}

View file

@ -1,16 +1,15 @@
package rs09.game.content.global.action
import api.events.ItemEquipEvent
import api.events.ItemUnequipEvent
import core.game.container.impl.EquipmentContainer
import core.game.interaction.item.brawling_gloves.BrawlingGlovesManager
import core.game.node.Node
import core.game.node.entity.combat.equipment.WeaponInterface
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.audio.Audio
import core.game.node.entity.player.link.diary.DiaryType
import rs09.game.node.entity.skill.slayer.SlayerEquipmentFlags
import core.game.world.map.zone.ZoneBorders
import core.plugin.Plugin
import org.rs09.consts.Items
import rs09.game.interaction.InteractionListener
import rs09.game.interaction.InteractionListeners
import rs09.game.system.config.ItemConfigParser
@ -23,31 +22,27 @@ import rs09.game.system.config.ItemConfigParser
class EquipHandler : InteractionListener {
override fun defineListeners() {
on(ITEM,"equip","wield","wear"){player,node ->
handleEquip(player,node)
on(ITEM, "equip", "wield", "wear") { player, node ->
handleEquip(player, node)
return@on true
}
}
fun handleEquip(player: Player,node: Node){
fun handleEquip(player: Player, node: Node) {
val item = node.asItem()
if(item == null || player.inventory[item.slot] != item || item.name.toLowerCase().contains("goblin mail")){
if (item == null || player.inventory[item.slot] != item || item.name.toLowerCase().contains("goblin mail")) {
return
}
val equipStateListener = item.definition.getConfiguration<Plugin<Any>>("equipment", null)
if(equipStateListener != null){
val bool = equipStateListener.fireEvent("equip",player,item)
if(bool != true){
if (equipStateListener != null) {
val bool = equipStateListener.fireEvent("equip", player, item)
if (bool != true) {
return
}
}
if(!InteractionListeners.run(node.id,player,node,true)){
if (!InteractionListeners.run(node.id, player, node, true)) {
return
}
@ -65,12 +60,10 @@ class EquipHandler : InteractionListener {
player.debug("Registering gloves... ID: " + item.id)
BrawlingGlovesManager.getInstance(player).registerGlove(item.id)
}
if (item.id == Items.BLACK_CHAINBODY_1107 && player.getAttribute("diary:falador:black-chain-bought", false)
&& ZoneBorders(2969, 3310, 2975, 3314, 0).insideBorder(player)
) {
player.achievementDiaryManager.finishTask(player, DiaryType.FALADOR, 0, 2)
}
player.dialogueInterpreter.close()
/* TODO: Send different equip sound based on what is being equip.*/
player.audioManager.send(item.definition.getConfiguration(ItemConfigParser.EQUIP_AUDIO, 2244))
if (player.properties.autocastSpell != null) {
player.properties.autocastSpell = null
@ -79,9 +72,11 @@ class EquipHandler : InteractionListener {
wif.openAutocastSelect()
}
if(SlayerEquipmentFlags.isSlayerEq(item.id)){
if (SlayerEquipmentFlags.isSlayerEq(item.id)) {
SlayerEquipmentFlags.updateFlags(player)
}
player.dispatch(ItemEquipEvent(item.id, item.slot))
}
}
@ -119,16 +114,19 @@ class EquipHandler : InteractionListener {
return
}
}
if(!InteractionListeners.run(itemId,player,item,false)) {
if (!InteractionListeners.run(itemId, player, item, false)) {
return
}
if (player.equipment.remove(item)) {
/* TODO: Send different unequip sound based on what is being unequipped.*/
player.audioManager.send(Audio(2238, 10, 1))
player.dialogueInterpreter.close()
player.inventory.add(item)
player.dispatch(ItemUnequipEvent(itemId, slot))
}
if(SlayerEquipmentFlags.isSlayerEq(item.id)){
if (SlayerEquipmentFlags.isSlayerEq(item.id)) {
SlayerEquipmentFlags.updateFlags(player)
}
}

View file

@ -1,6 +1,8 @@
package rs09.game.content.global.shops
import api.*
import api.events.ItemShopPurchaseEvent
import api.events.ItemShopSellEvent
import core.game.component.Component
import core.game.container.Container
import core.game.container.ContainerEvent
@ -319,6 +321,7 @@ class Shop(val title: String, val stock: Array<ShopItem>, val general: Boolean =
sendMessage(player, "You don't have enough ${cost.name.toLowerCase()} to buy that many.")
}
player.dispatch(ItemShopPurchaseEvent(item.id, item.amount, cost))
return TransactionStatus.Success()
}
@ -387,6 +390,8 @@ class Shop(val title: String, val stock: Array<ShopItem>, val general: Boolean =
needsUpdate[ServerConstants.SERVER_NAME.hashCode()] = true
}
}
player.dispatch(ItemShopSellEvent(item.id, item.amount, profit))
return TransactionStatus.Success()
}

View file

@ -1,8 +1,10 @@
package rs09.game.content.global.travel
import api.events.TeleportEvent
import core.game.node.entity.impl.Projectile
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.item.Item
import core.game.system.task.Pulse
@ -11,6 +13,7 @@ import core.game.world.map.Location
import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics
import core.tools.RandomFunction
import rs09.game.node.entity.skill.magic.TeleportMethod
/**
* Represents a utilitity class for rune essence teleporting.
@ -20,7 +23,15 @@ object EssenceTeleport {
/**
* Array of all the possible `Location` locations.
*/
val LOCATIONS = arrayOf(Location.create(2911, 4832, 0), Location.create(2913, 4837, 0), Location.create(2930, 4850, 0), Location.create(2894, 4811, 0), Location.create(2896, 4845, 0), Location.create(2922, 4820, 0), Location.create(2931, 4813, 0))
val LOCATIONS = arrayOf(
Location.create(2911, 4832, 0),
Location.create(2913, 4837, 0),
Location.create(2930, 4850, 0),
Location.create(2894, 4811, 0),
Location.create(2896, 4845, 0),
Location.create(2922, 4820, 0),
Location.create(2931, 4813, 0)
)
/**
* Represents the animation to use.
@ -65,16 +76,20 @@ object EssenceTeleport {
}
}
player.savedData.globalData.essenceTeleporter = npc.id
val loc: Location =Location.create(2922, 4820, 0)
val loc = LOCATIONS[RandomFunction.random(0, LOCATIONS.size)]
player.properties.teleportLocation = loc
if (npc.id == 553) {
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 0, 1)
}
if (npc.id == 300) {
player.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 1, 14)
}
player.dispatch(
TeleportEvent(
TeleportManager.TeleportType.TELE_OTHER,
TeleportMethod.NPC,
npc,
loc
)
)
}
3 -> {
player.graphics(Graphics(110))
player.unlock()

View file

@ -1,55 +1,83 @@
package rs09.game.content.jobs
import GatheringJobs
import SlayingJob
import api.*
import rs09.game.content.jobs.impl.GatheringJobs
import rs09.game.content.jobs.impl.SlayingJobs
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.game.node.item.Item
import org.rs09.consts.Items
import rs09.game.content.dialogue.DialogueFile
import rs09.game.content.dialogue.Topic
import rs09.tools.END_DIALOGUE
import rs09.tools.START_DIALOGUE
class CancelJobDialogueFile : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when(stage){
0 -> options("Check Job Progress","Cancel Job").also { stage++ }
1 -> when(buttonID){
1 -> player("How am I doing on my job?").also { stage++ }
2 -> player("I'd like to cancel my job.").also { stage = 10 }
}
2 -> {
val amt = player!!.getAttribute("jobs:original_amount",0)
val type = player!!.getAttribute("jobs:type",0)
val jobId = player!!.getAttribute("jobs:id",0)
val needed = player!!.getAttribute("jobs:amount",0)
if(type == 0){
player!!.dialogueInterpreter.sendItemMessage(GatheringJobs.values()[jobId].itemId,"You still need to gather ${needed} more.")
} else {
player!!.dialogueInterpreter.sendDialogue("You still need to kill $needed more ${NPC(SlayingJob.values()[jobId].ids[0]).name.toLowerCase()}.")
when (stage) {
START_DIALOGUE -> showTopics(
Topic(FacialExpression.HALF_ASKING, "How am I doing on my job?", 1),
Topic(FacialExpression.HALF_GUILTY, "I'd like to cancel my job.", 10)
)
1 -> {
val jobType = JobType.values()[getAttribute(player!!, "jobs:type", 0)]
val jobId = getAttribute(player!!, "jobs:id", 0)
val needed = getAttribute(player!!, "jobs:amount", 0)
when (jobType) {
JobType.GATHERING -> {
sendItemDialogue(
player!!,
Item(GatheringJobs.values()[jobId].itemId),
"You still need to gather $needed more."
)
}
JobType.SLAYING -> {
sendDialogue(
player!!,
"You still need to kill $needed more ${NPC(SlayingJobs.values()[jobId].ids[0]).name.lowercase()}"
)
}
}
stage = END_DIALOGUE
}
10 -> npc("It will cost 500 coins.").also { stage++ }
11 -> options("Yes, please.","No, thanks.").also { stage++ }
12 -> when(buttonID){
1 -> player("Yes, please.").also{ stage = 20 }
2 -> player("No, thanks.").also { stage = 30 }
}
20 -> npc("Alright then, hand over the money.").also { stage++ }
21 -> if(player!!.inventory.contains(995,500)){
10 -> npc("It will cost 500 coins.")
.also { stage++ }
11 -> showTopics(
Topic(FacialExpression.HAPPY, "Yes, please.", 20),
Topic(FacialExpression.NEUTRAL, "No, thanks.", 30)
)
20 -> npc("Alright then, hand over the money.")
.also { stage++ }
21 -> if (inInventory(player!!, Items.COINS_995, 500)) {
player("Here you go.")
player!!.inventory.remove(Item(995,500))
player!!.removeAttribute("jobs:id")
player!!.removeAttribute("jobs:amount")
player!!.removeAttribute("jobs:original_amount")
player!!.removeAttribute("jobs:type")
removeItem(player!!, Item(Items.COINS_995, 500))
removeAttribute(player!!, "jobs:id")
removeAttribute(player!!, "jobs:amount")
removeAttribute(player!!, "jobs:original_amount")
removeAttribute(player!!, "jobs:type")
stage = END_DIALOGUE
} else {
player("Oh, I don't seem to have the money...")
stage++
player(
FacialExpression.HALF_WORRIED,
"Oh, I don't seem to have the money..."
).also { stage++ }
}
22 -> npc("Ah, that sucks! Get to work.").also { stage = END_DIALOGUE }
30 -> npc("Alright then, get to work!").also { stage = END_DIALOGUE }
22 -> npc("Ah, that sucks! Get to work.")
.also { stage = END_DIALOGUE }
30 -> npc("Alright then, get to work!")
.also { stage = END_DIALOGUE }
}
}
}

View file

@ -1,82 +1,111 @@
package rs09.game.content.jobs
import GatheringJobs
import SlayingJob
import api.*
import rs09.game.content.jobs.impl.GatheringJobs
import rs09.game.content.jobs.impl.SlayingJobs
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.item.GroundItemManager
import core.game.node.item.Item
import org.json.simple.JSONObject
import org.rs09.consts.Items
import rs09.ServerStore
import rs09.ServerStore.Companion.getInt
import rs09.game.system.SystemLogger
import java.util.concurrent.TimeUnit
object JobManager {
@JvmStatic
fun updateJobRemaining(player: Player, amount: Int = 0) {
val cur = player.getAttribute("jobs:amount",0)
val cur = getAttribute(player, "jobs:amount", 0)
val new = cur - amount
val jobType = player.getAttribute("jobs:type",0)
val jobId = player.getAttribute("jobs:id",0)
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
val jobId = getAttribute(player, "jobs:id", 0)
var gJob: GatheringJobs? = null
var sJob: SlayingJob? = null
when (jobType) {
JobType.GATHERING -> { }
if(jobType == 0){
gJob = GatheringJobs.values()[jobId]
} else {
sJob = SlayingJob.values()[jobId]
JobType.SLAYING -> {
val job = SlayingJobs.values()[jobId]
if (new % 5 == 0 && new > 0) {
sendMessage(
player,
"You have $new ${NPC(job.ids[0]).name.lowercase()} left to go."
)
} else if (new == 0) {
sendMessage(
player,
"<col=00AA00>You have completed your job.</col>"
)
}
}
}
if(new % 5 == 0 && sJob != null && new > 0){
player.sendMessage("You have $new ${NPC(sJob.ids[0]).name.toLowerCase()} left to go.")
}
if(new == 0 && sJob != null){
player.sendMessage("You have completed your job.")
}
player.setAttribute("jobs:amount",new)
setAttribute(player, "jobs:amount", new)
}
@JvmStatic
fun rewardPlayer(player: Player, npc: NPC){
val amt = player.getAttribute("jobs:original_amount",0)
val type = player.getAttribute("jobs:type",0)
val jobId = player.getAttribute("jobs:id",0)
if(type == 0){
val it = Item(GatheringJobs.values()[jobId].itemId)
var amount = player.inventory.getAmount(it)
val needed = player.getAttribute("jobs:amount",0)
if(amount == 0){
player.dialogueInterpreter.open(CancelJobDialogueFile(),npc)
SystemLogger.logAlert("Opening CancelJob")
return
}
if(amount < needed){
player.dialogueInterpreter.sendItemMessage(GatheringJobs.values()[jobId].itemId,"You still need to gather ${needed - amount} more.")
player.inventory.remove(Item(it.id,amount))
player.setAttribute("jobs:amount",needed - amount)
return
}
if(amount > needed) amount = needed
player.inventory.remove(Item(it.id,amount))
} else {
val needed = player.getAttribute("jobs:amount",0)
if(needed > 0){
player.dialogueInterpreter.sendDialogue("You still need to kill $needed more ${NPC(SlayingJob.values()[jobId].ids[0]).name.toLowerCase()}.")
return
}
player.dialogueInterpreter.sendDialogue("Excellent work, thank you! Here's your reward.")
}
if(!player.inventory.add(Item(995,250 * amt))){
GroundItemManager.create(Item(995,250 * amt),player.centerLocation,player)
}
player.removeAttribute("jobs:id")
player.removeAttribute("jobs:amount")
player.removeAttribute("jobs:original_amount")
player.removeAttribute("jobs:type")
fun rewardPlayer(player: Player, npc: NPC) {
val amt = getAttribute(player, "jobs:original_amount", 0)
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
val jobId = getAttribute(player, "jobs:id", 0)
getStoreFile()[player.username.toLowerCase()] = getStoreFile().getInt(player.username.toLowerCase()) + 1
when (jobType) {
JobType.GATHERING -> {
val it = Item(GatheringJobs.values()[jobId].itemId)
var amount = amountInInventory(player, it.id)
val needed = getAttribute(player, "jobs:amount", 0)
if (amount == 0) {
openDialogue(player, CancelJobDialogueFile(), npc)
return
}
if (amount < needed) {
sendItemDialogue(
player,
GatheringJobs.values()[jobId].itemId,
"You still need to gather ${needed - amount} more."
)
removeItem(player, Item(it.id, amount))
setAttribute(player, "jobs:amount", needed - amount)
return
}
if (amount > needed) {
amount = needed
}
removeItem(player, Item(it.id, amount))
}
JobType.SLAYING -> {
val needed = getAttribute(player, "jobs:amount", 0)
if (needed > 0) {
sendDialogue(
player,
"You still need to kill $needed more ${NPC(SlayingJobs.values()[jobId].ids[0]).name.lowercase()}."
)
return
}
sendDialogue(
player,
"Excellent work, thank you! Here's your reward."
)
}
}
addItemOrDrop(player, Items.COINS_995, 250 * amt)
removeAttribute(player, "jobs:id")
removeAttribute(player, "jobs:amount")
removeAttribute(player, "jobs:original_amount")
removeAttribute(player, "jobs:type")
getStoreFile()[player.username.lowercase()] = getStoreFile().getInt(player.username.lowercase()) + 1
}
fun getStoreFile(): JSONObject {

View file

@ -0,0 +1,6 @@
package rs09.game.content.jobs
enum class JobType {
GATHERING,
SLAYING
}

View file

@ -1,153 +1,222 @@
package rs09.game.content.jobs
import GatheringJobs
import SlayingJob
import rs09.game.content.jobs.impl.GatheringJobs
import rs09.game.content.jobs.impl.SlayingJobs
import api.*
import api.events.EventHook
import api.events.JobAssignmentEvent
import api.events.NPCKillEvent
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.item.Item
import org.json.simple.JSONObject
import org.rs09.consts.Items
import rs09.ServerStore
import org.rs09.consts.NPCs
import rs09.ServerStore.Companion.getInt
import rs09.game.Event
import rs09.game.interaction.InteractionListener
import rs09.game.system.SystemLogger
import java.util.*
import java.util.concurrent.TimeUnit
/**
* Handles the work-for actions for the NPCs
* @author Ceikry
* @author vddCore
*/
class WorkForInteractionListener : InteractionListener, LoginListener {
val possibleWeaponLooks = arrayListOf(
Items.BRONZE_SCIMITAR_1321,
Items.STEEL_SCIMITAR_1325,
Items.RUNE_SCIMITAR_1333,
Items.BRONZE_MACE_1422,
Items.MITHRIL_WARHAMMER_1343
)
companion object {
private val WEAPON_ICONS = arrayListOf(
Items.BRONZE_SCIMITAR_1321,
Items.STEEL_SCIMITAR_1325,
Items.RUNE_SCIMITAR_1333,
Items.BRONZE_MACE_1422,
Items.MITHRIL_WARHAMMER_1343
)
val gatheringMap = mapOf<Int,List<GatheringJobs>>(
0 to listOf(GatheringJobs.AIR_RUNE,GatheringJobs.COWHIDES,GatheringJobs.WATER_RUNE),
922 to listOf(GatheringJobs.ASHES,GatheringJobs.AIR_RUNE,GatheringJobs.WATER_RUNE),
3807 to listOf(GatheringJobs.COWHIDES),
4899 to listOf(GatheringJobs.CAKE,GatheringJobs.ANCHOVY_PIZZA,GatheringJobs.COOKED_SALMON,GatheringJobs.COOKED_TROUT,GatheringJobs.MEAT_PIE,GatheringJobs.MEAT_PIZZA,GatheringJobs.PLAIN_PIZZA),
4901 to listOf(GatheringJobs.RAW_SALMON,GatheringJobs.RAW_SHRIMP,GatheringJobs.RAW_TROUT),
4902 to listOf(GatheringJobs.COPPER_ORE,GatheringJobs.TIN_ORE,GatheringJobs.COAL,GatheringJobs.IRON_ORE,GatheringJobs.SILVER_ORE,GatheringJobs.GOLD_ORE),
4903 to listOf(GatheringJobs.SILVER_ORE),
4904 to listOf(GatheringJobs.BRONZE_BAR,GatheringJobs.IRON_BAR,GatheringJobs.STEEL_BAR),
4906 to listOf(GatheringJobs.LOG,GatheringJobs.OAK,GatheringJobs.WILLOW)
)
private val EMPLOYERS_AND_JOBS = mapOf(
NPCs.HANS_0 to listOf(
GatheringJobs.AIR_RUNE,
GatheringJobs.COWHIDES,
GatheringJobs.WATER_RUNE
),
val typeMap = mapOf(
0 to 0,
705 to 1,
922 to 0,
1861 to 1,
3807 to 0,
4899 to 0,
4901 to 0,
4902 to 0,
4903 to 0,
4904 to 0,
4906 to 0,
4707 to 1
)
NPCs.AGGIE_922 to listOf(
GatheringJobs.ASHES,
GatheringJobs.AIR_RUNE,
GatheringJobs.WATER_RUNE
),
NPCs.GILLIE_GROATS_3807 to listOf(
GatheringJobs.COWHIDES
),
NPCs.COOKING_TUTOR_4899 to listOf(
GatheringJobs.CAKE,
GatheringJobs.ANCHOVY_PIZZA,
GatheringJobs.COOKED_SALMON,
GatheringJobs.COOKED_TROUT,
GatheringJobs.MEAT_PIE,
GatheringJobs.MEAT_PIZZA,
GatheringJobs.PLAIN_PIZZA
),
NPCs.FISHING_TUTOR_4901 to listOf(
GatheringJobs.RAW_SALMON,
GatheringJobs.RAW_SHRIMP,
GatheringJobs.RAW_TROUT
),
NPCs.MINING_TUTOR_4902 to listOf(
GatheringJobs.COPPER_ORE,
GatheringJobs.TIN_ORE,
GatheringJobs.COAL,
GatheringJobs.IRON_ORE,
GatheringJobs.SILVER_ORE,
GatheringJobs.GOLD_ORE
),
NPCs.PRAYER_TUTOR_4903 to listOf(
GatheringJobs.SILVER_ORE
),
NPCs.SMELTING_TUTOR_4904 to listOf(
GatheringJobs.BRONZE_BAR,
GatheringJobs.IRON_BAR,
GatheringJobs.STEEL_BAR
),
NPCs.WOODCUTTING_TUTOR_4906 to listOf(
GatheringJobs.LOG,
GatheringJobs.OAK,
GatheringJobs.WILLOW
)
)
private val EMPLOYER_JOB_TYPES = mapOf(
NPCs.HANS_0 to JobType.GATHERING,
NPCs.MELEE_TUTOR_705 to JobType.SLAYING,
NPCs.AGGIE_922 to JobType.GATHERING,
NPCs.RANGED_TUTOR_1861 to JobType.SLAYING,
NPCs.GILLIE_GROATS_3807 to JobType.GATHERING,
NPCs.MAGIC_TUTOR_4707 to JobType.SLAYING,
NPCs.COOKING_TUTOR_4899 to JobType.GATHERING,
NPCs.FISHING_TUTOR_4901 to JobType.GATHERING,
NPCs.MINING_TUTOR_4902 to JobType.GATHERING,
NPCs.PRAYER_TUTOR_4903 to JobType.GATHERING,
NPCs.SMELTING_TUTOR_4904 to JobType.GATHERING,
NPCs.WOODCUTTING_TUTOR_4906 to JobType.GATHERING
)
private val EMPLOYER_IDS = EMPLOYER_JOB_TYPES.keys.toIntArray()
}
val IDs = typeMap.keys.toIntArray()
override fun login(player: Player) {
if(getAttribute(player, "jobs:type", -1) == 1 && getAttribute(player, "jobs:amount", -1) > 0)
val remaining = getAttribute(player, "jobs:amount", -1)
val jobType = JobType.values()[getAttribute(player, "jobs:type", 0)]
if (jobType == JobType.SLAYING && remaining > 0) {
player.hook(Event.NPCKilled, JobKillHook)
}
}
override fun defineListeners() {
on(IDs,NPC,"work-for"){ player,node ->
var amount = 0
var jobId = 0
if(JobManager.getStoreFile().getInt(player.username.toLowerCase()) == 3){
sendNPCDialogue(player, node.id,"You've hit your limit for the day. Come back tomorrow!")
on(EMPLOYER_IDS, NPC, "work-for") { player, node ->
if (JobManager.getStoreFile().getInt(player.username.lowercase()) == 3) {
sendNPCDialogue(player, node.id, "You've hit your limit for the day. Come back tomorrow!")
return@on true
}
if(player.getAttribute("jobs:id",-1) != -1){
JobManager.rewardPlayer(player,node.asNpc())
if (getAttribute(player, "jobs:id", -1) != -1) {
JobManager.rewardPlayer(player, node.asNpc())
return@on true
}
val type = typeMap[node.id] ?: return@on false
jobId = if(type == 0) {
val job = gatheringMap[node.id]?.filter { checkRequirement(player, it) }?.randomOrNull()
var amount: Int
val jobType = EMPLOYER_JOB_TYPES[node.id] ?: return@on false
val jobId = when (jobType) {
JobType.GATHERING -> {
val job = EMPLOYERS_AND_JOBS[node.id]?.filter { checkRequirement(player, it) }?.randomOrNull()
if (job == null) {
sendNPCDialogue(
player,
node.id,
"I'm sorry, I don't currently have any jobs that you're qualified for.",
FacialExpression.HALF_THINKING
)
return@on true
if (job == null) {
sendNPCDialogue(
player,
node.id,
"I'm sorry, I don't currently have any jobs that you're qualified for.",
FacialExpression.HALF_THINKING
)
return@on true
}
amount = job.getAmount()
job.ordinal
}
amount = job.getAmount()
job.ordinal
} else {
SlayingJob.values().random().ordinal.also { amount = SlayingJob.values()[it].getAmount() }
JobType.SLAYING -> {
SlayingJobs.values().random().ordinal.also {
amount = SlayingJobs.values()[it].getAmount()
}
}
}
when(type){
0 -> {
when (jobType) {
JobType.GATHERING -> {
val job = GatheringJobs.values()[jobId]
player.dialogueInterpreter.sendItemMessage(job.itemId,"You are assigned to gather $amount ${Item(job.itemId).name.toLowerCase()}")
// Have the Fishing Tutor send you on an errand
if (node.id == 4901) player.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 0, 14);
sendItemDialogue(
player,
job.itemId,
"You are assigned to gather $amount ${Item(job.itemId).name.lowercase()}"
)
}
1 -> {
val job = SlayingJob.values()[jobId]
player.dialogueInterpreter.sendItemMessage(possibleWeaponLooks.random(),"You are assigned to kill $amount ${NPC(job.ids[0]).name.toLowerCase()}")
JobType.SLAYING -> {
val job = SlayingJobs.values()[jobId]
sendItemDialogue(
player,
WEAPON_ICONS.random(),
"You are assigned to kill $amount ${NPC(job.ids[0]).name.lowercase()}"
)
player.unhook(JobKillHook) //try to unhook just in case they already had it hooked, unlikely but possible.
player.hook(Event.NPCKilled, JobKillHook)
}
}
player.setAttribute("/save:jobs:id",jobId)
player.setAttribute("/save:jobs:amount",amount)
player.setAttribute("/save:jobs:original_amount",amount)
player.setAttribute("/save:jobs:type",type)
setAttribute(player, "/save:jobs:id", jobId)
setAttribute(player, "/save:jobs:amount", amount)
setAttribute(player, "/save:jobs:original_amount", amount)
setAttribute(player, "/save:jobs:type", jobType.ordinal)
player.dispatch(JobAssignmentEvent(jobType, node.asNpc()))
return@on true
}
}
fun checkRequirement(player: Player, jobs: GatheringJobs?): Boolean{
private fun checkRequirement(player: Player, jobs: GatheringJobs?): Boolean {
jobs ?: return true
if(player.skills.getLevel(jobs.skill) < jobs.lvlReq){
if (getStatLevel(player, jobs.skill) < jobs.lvlReq) {
return false
}
return true
}
private object JobKillHook : EventHook<NPCKillEvent>
{
private object JobKillHook : EventHook<NPCKillEvent> {
override fun process(entity: Entity, event: NPCKillEvent) {
if(entity !is Player) return
if (entity !is Player) return
if (entity.isArtificial) return
val job = getAttribute(entity, "jobs:id", -1)
if (job !in 0 until SlayingJob.values().size) return
val ids = SlayingJob.values()[job].ids
if(event.npc.id in ids){
if (job !in 0 until SlayingJobs.values().size) {
return
}
val ids = SlayingJobs.values()[job].ids
if (event.npc.id in ids) {
JobManager.updateJobRemaining(entity, 1)
}
}

View file

@ -1,3 +1,5 @@
package rs09.game.content.jobs.impl
import core.game.node.entity.skill.Skills
import core.tools.RandomFunction

View file

@ -1,6 +1,8 @@
package rs09.game.content.jobs.impl
import core.tools.RandomFunction
enum class SlayingJob(val lower: Int, val upper: Int, vararg val ids: Int) {
enum class SlayingJobs(val lower: Int, val upper: Int, vararg val ids: Int) {
CHICKEN(25,26,41,1017),
COW(25,25,397,1766,81,1767),
GIANT_SPIDER(22,25,59,60),

View file

@ -51,8 +51,6 @@ class DukeHoracioDSDialogue(val questStage: Int) : DialogueFile() {
GroundItemManager.create(DragonSlayer.SHIELD, player)
}
interpreter!!.sendItemMessage(DragonSlayer.SHIELD, "The Duke hands you a heavy orange shield.")
// Obtain an Anti-dragonbreath shield from Duke Horacio
player!!.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 2, 5)
stage = END_DIALOGUE
}
}
@ -80,8 +78,6 @@ class DukeHoracioDSDialogue(val questStage: Int) : DialogueFile() {
GroundItemManager.create(DragonSlayer.SHIELD, player)
}
interpreter!!.sendItemMessage(DragonSlayer.SHIELD, "The Duke hands you the shield.")
// Obtain an Anti-dragonbreath shield from Duke Horacio
player!!.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 2, 5)
stage = END_DIALOGUE
}
}

View file

@ -15,9 +15,9 @@ import org.rs09.consts.NPCs
* Event receivers for tutorial island
* @author Ceikry
*/
object TutorialButtonReceiver : EventHook<ButtonClickedEvent>
object TutorialButtonReceiver : EventHook<ButtonClickEvent>
{
override fun process(entity: Entity, event: ButtonClickedEvent) {
override fun process(entity: Entity, event: ButtonClickEvent) {
if(entity !is Player) return
when(getAttribute(entity, "tutorial:stage", 0))
@ -277,9 +277,9 @@ object TutorialFireReceiver : EventHook<LitFireEvent>
}
}
object TutorialUseWithReceiver : EventHook<UsedWithEvent>
object TutorialUseWithReceiver : EventHook<UseWithEvent>
{
override fun process(entity: Entity, event: UsedWithEvent) {
override fun process(entity: Entity, event: UseWithEvent) {
if(entity !is Player) return

View file

@ -29,7 +29,7 @@ object TutorialStage {
if(login)
{
player.hook(Event.ButtonClicked, TutorialButtonReceiver)
player.hook(Event.Interaction, TutorialInteractionReceiver)
player.hook(Event.Interacted, TutorialInteractionReceiver)
player.hook(Event.ResourceProduced, TutorialResourceReceiver)
player.hook(Event.UsedWith, TutorialUseWithReceiver)
player.hook(Event.FireLit, TutorialFireReceiver)

View file

@ -1,52 +0,0 @@
package rs09.game.node.entity.player.diary.seers
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.plugin.Initializable
import core.game.world.map.zone.MapZone
import core.game.node.entity.player.link.diary.DiaryType
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import core.game.world.map.zone.ZoneBuilder
import core.plugin.Plugin
@Initializable
class WindsweptTreeZone : MapZone("windswept-tree", true), Plugin<Any?> {
override fun newInstance(arg: Any?): WindsweptTreeZone {
ZoneBuilder.configure(this)
return this
}
override fun configure() {
super.register(ZoneBorders(2746, 3733, 2746, 3735))
super.register(ZoneBorders(2570, 3732, 2570, 3736))
}
override fun enter(e: Entity?): Boolean {
return super.enter(e)
}
override fun fireEvent(identifier: String?, vararg args: Any?): Any {
return Unit
}
override fun locationUpdate(e: Entity?, last: Location?) {
if (e is Player && !e.isArtificial) {
val player = e.asPlayer()
if (!player.achievementDiaryManager.hasCompletedTask(DiaryType.FREMENNIK, 0, 2)) {
player.achievementDiaryManager.finishTask(player, DiaryType.FREMENNIK, 0, 2)
println("Fremennik Easy Diary Task 2 Completed!")
} else {
player.achievementDiaryManager.finishTask(player, DiaryType.FREMENNIK, 0, 2)
}
}
}
}
// override fun leave(e: Entity?, logout: Boolean) {
// if (e is Player) {
// super.leave(e, logout)
//}
//}}

View file

@ -1,7 +1,7 @@
package rs09.game.interaction
import api.events.InteractionEvent
import api.events.UsedWithEvent
import api.events.UseWithEvent
import core.game.interaction.DestinationFlag
import core.game.interaction.MovementPulse
import core.game.interaction.Option
@ -9,7 +9,6 @@ import core.game.node.Node
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.world.map.Location
import rs09.game.system.SystemLogger
object InteractionListeners {
private val listeners = HashMap<String,(Player, Node) -> Boolean>(1000)
@ -189,16 +188,16 @@ object InteractionListeners {
return true
}
player.faceLocation(with.location)
if(flipped) player.dispatch(UsedWithEvent(with.id, used.id))
else player.dispatch(UsedWithEvent(used.id, with.id))
if(flipped) player.dispatch(UseWithEvent(with.id, used.id))
else player.dispatch(UseWithEvent(used.id, with.id))
if(flipped) method.invoke(player,with,used)
else method.invoke(player,used,with)
return true
}
})
} else {
if(flipped) player.dispatch(UsedWithEvent(with.id, used.id))
else player.dispatch(UsedWithEvent(used.id, with.id))
if(flipped) player.dispatch(UseWithEvent(with.id, used.id))
else player.dispatch(UseWithEvent(used.id, with.id))
if(flipped) method.invoke(player,with,used)
else method.invoke(player,used,with)
}

View file

@ -1,6 +1,7 @@
package rs09.game.interaction.inter
import api.*
import api.events.FairyRingDialEvent
import core.game.component.Component
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.player.Player
@ -138,22 +139,11 @@ class FairyRingInterface : InterfaceListener{
}
}
closeInterface(player)
if(ring == FairyRing.ALS && !player.achievementDiaryManager.hasCompletedTask(DiaryType.SEERS_VILLAGE,2,4)){
player.achievementDiaryManager.finishTask(player,DiaryType.SEERS_VILLAGE,2,4)
ring.let {
player.dispatch(FairyRingDialEvent(it!!))
teleport(player, tile!!, TeleportManager.TeleportType.FAIRY_RING)
}
else if(ring == FairyRing.DKS && !player.achievementDiaryManager.hasCompletedTask(DiaryType.FREMENNIK,1,7)){
player.achievementDiaryManager.finishTask(player,DiaryType.FREMENNIK,1,7)
teleport(player, tile!!, TeleportManager.TeleportType.FAIRY_RING)
}
else if(ring == FairyRing.AIQ && !player.achievementDiaryManager.hasCompletedTask(DiaryType.FALADOR,2,4)){
player.achievementDiaryManager.finishTask(player,DiaryType.FALADOR,2,4)
teleport(player, tile!!, TeleportManager.TeleportType.FAIRY_RING)
}
else if(ring == FairyRing.DKR && !player.achievementDiaryManager.hasCompletedTask(DiaryType.VARROCK,1,19)){
player.achievementDiaryManager.finishTask(player,DiaryType.VARROCK,1,19)
teleport(player, tile!!, TeleportManager.TeleportType.FAIRY_RING)
}else teleport(player, tile!!, TeleportManager.TeleportType.FAIRY_RING)
}
}

View file

@ -1,100 +0,0 @@
package rs09.game.interaction.inter
import api.*
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.entity.skill.Skills
import core.game.node.entity.skill.crafting.SilverProduct
import core.game.system.task.Pulse
import org.rs09.consts.Components
import org.rs09.consts.Items
import rs09.game.interaction.InteractionListener
import rs09.game.interaction.InterfaceListener
class SilverInterface : InterfaceListener {
val IFACE = Components.CRAFTING_SILVER_CASTING_438
val ANIM = getAnimation(899)
override fun defineInterfaceListeners() {
onOpen(IFACE){player, _ ->
sendItemOnInterface(player, IFACE, 17, 1718)
sendItemOnInterface(player, IFACE, 24, 1724)
sendItemOnInterface(player, IFACE, 31, 2961)
sendItemOnInterface(player, IFACE, 38, 4201)
sendItemOnInterface(player, IFACE, 45, 5525)
sendItemOnInterface(player, IFACE, 53, 7637)
sendItemOnInterface(player, IFACE, 60, 6748)
sendItemOnInterface(player, IFACE, 67, 9382)
sendItemOnInterface(player, IFACE, 74, 13154)
return@onOpen true
}
on(IFACE){player, _, opcode, buttonID, _, _ ->
val product = SilverProduct.forId(buttonID) ?: return@on true
if(!inInventory(player, product.needed)){
sendMessage(player, "You need a ${itemDefinition(product.needed).name.toLowerCase()} to make this item.")
return@on true
}
if(product == SilverProduct.SILVTHRIL_ROD || product == SilverProduct.SILVTHRIL_CHAIN){
sendMessage(player, "You can't do that yet.")
return@on true
}
if(!hasLevelDyn(player, Skills.CRAFTING, product.level)){
sendMessage(player, "You need a Crafting level of ${product.level} to make this.")
return@on true
}
val amt = when(opcode){
155 -> 1
196 -> 5
124 -> amountInInventory(player, Items.SILVER_BAR_2355)
199 -> -1 //Make X
else -> return@on true
}
if(amt == -1) sendInputDialogue(player, true, "Enter the amount:"){value ->
make(player,product,value as Int)
} else make(player, product, amt)
return@on true
}
}
fun make(player: Player, product: SilverProduct, amount: Int){
var amt = amount
closeInterface(player)
submitIndividualPulse(player, object : Pulse(){
override fun pulse(): Boolean {
if(amt < 1) return true
if(!inInventory(player, product.needed) || !inInventory(player, Items.SILVER_BAR_2355)) return true;
animate(player, ANIM)
if(removeItem(player, Items.SILVER_BAR_2355, api.Container.INVENTORY)){
addItem(player, product.product, if(product == SilverProduct.SILVER_BOLTS) 10 else 1)
rewardXP(player, Skills.CRAFTING, product.exp)
if(product == SilverProduct.UNBLESSED && player.location.withinDistance(location(3226,3254,0))){
player.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 2, 8)
}
delay = 3
} else return true
amt--
return false
}
})
}
}
class SilverBarUseWith : InteractionListener {
val FURNACES = intArrayOf(2966, 3044, 3294, 4304, 6189, 11009, 11010, 11666, 12100, 12809, 18497, 18525, 18526, 21879, 22721, 26814, 28433, 28434, 30021, 30510, 36956, 37651)
override fun defineListeners() {
onUseWith(SCENERY, Items.SILVER_BAR_2355, *FURNACES){ player, _, _ ->
openInterface(player, Components.CRAFTING_SILVER_CASTING_438)
return@onUseWith true
}
}
}

View file

@ -170,7 +170,7 @@ class ThessaliaInterface : ComponentPlugin(){
override fun handle(player: Player?, component: Component?, opcode: Int, button: Int, slot: Int, itemId: Int): Boolean {
player ?: return false
when(button){
181,180 -> pay(player)
181,180,297 -> pay(player)
else -> when(component?.id){
THESSALIA_MALE_COMPONENT -> {
when(button){

View file

@ -4,21 +4,80 @@ import api.removeItem
import api.sendChat
import api.sendMessage
import core.game.content.global.Bones
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.item.Item
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import rs09.game.interaction.InteractionListener
class BonesOnStrayDog : InteractionListener {
override fun defineListeners() {
val bones = Bones.array
val dogs = intArrayOf(NPCs.STRAY_DOG_4766, NPCs.STRAY_DOG_4767, NPCs.STRAY_DOG_5917, NPCs.STRAY_DOG_5918)
onUseWith(NPC, bones, *dogs){player, used, with ->
if(removeItem(player, used.asItem())){
sendMessage(player, "You feed your dog bones.")
sendChat(with.asNpc(), "Woof")
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 0, 8)
val dogs = intArrayOf(
NPCs.STRAY_DOG_4766,
NPCs.STRAY_DOG_4767,
NPCs.STRAY_DOG_5917,
NPCs.STRAY_DOG_5918
)
onUseWith(NPC, bones, *dogs) { player, used, with ->
used as Item; with as NPC
var woof = "Woof"
if (removeItem(player, used)) {
sendMessage(
player,
"You feed the ${with.definition.name.lowercase()} your ${used.definition.name.lowercase()}."
)
when (used.id) {
Items.BURNT_BONES_528 -> {
sendMessage(
player,
"The dog looks at you, disappointed, but takes the bones anyway."
)
woof = "Woof..."
}
Items.FAYRG_BONES_4830,
Items.RAURG_BONES_4832,
Items.OURG_BONES_4834 -> {
sendMessage(
player,
"The dog looks at you, confused, but takes the bones anyway."
)
woof = "Woof..?"
}
Items.BABYDRAGON_BONES_534,
Items.BIG_BONES_532 -> {
sendMessage(
player,
"The dog seems to be very happy."
)
woof = "Woof!"
}
Items.WYVERN_BONES_6812,
Items.DRAGON_BONES_536 -> {
sendMessage(
player,
"The dog seems to be extremely overjoyed."
)
woof = "WOOF!"
}
}
sendChat(with, woof)
}
return@onUseWith true
}
}

View file

@ -1,43 +1,51 @@
package rs09.game.interaction.item.withnpc
import api.sendNPCDialogue
import api.sendPlayerDialogue
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.item.Item
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import rs09.game.content.dialogue.DialogueFile
import rs09.game.interaction.InteractionListener
import rs09.tools.END_DIALOGUE
class PoisonChaliceOnKingArthur : InteractionListener {
override fun defineListeners() {
onUseWith(NPC, Items.POISON_CHALICE_197, NPCs.KING_ARTHUR_251){player, used, with ->
player.dialogueInterpreter.open(PoisonChaliceOnKingArthurDialogue(),with)
onUseWith(NPC, Items.POISON_CHALICE_197, NPCs.KING_ARTHUR_251) { player, _, with ->
player.dialogueInterpreter.open(PoisonChaliceOnKingArthurDialogue(), with)
return@onUseWith true
}
}
}
class PoisonChaliceOnKingArthurDialogue : DialogueFile(){
var init = true
class PoisonChaliceOnKingArthurDialogue : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
if (init) stage = 0 ; init = false
when (stage) {
0 -> npcl(
FacialExpression.SAD,
"You have chosen poorly."
).also { stage++ }
when(stage){
0 -> sendNPCDialogue(player!!,this.npc!!.id,"You have chosen poorly",FacialExpression.SAD).also { stage++ }
1 -> sendPlayerDialogue(player!!,"Excuse me?",FacialExpression.ANNOYED).also { stage++ }
2 -> sendNPCDialogue(player!!,this.npc!!.id,"Sorry, I meant to say 'thank you'. Most refreshing.").also { stage++ }
3 -> sendPlayerDialogue(player!!,"Are you sure that stuff is safe to drink?",FacialExpression.DISGUSTED_HEAD_SHAKE).also { stage++ }
4 -> sendNPCDialogue(player!!,this.npc!!.id,"Oh yes, Stankers' creations may be dangerous for those with weak constitutions, but, personally. I find them rather invigorating.").also { stage++ }
5 ->{ if (!player!!.achievementDiaryManager.hasCompletedTask(DiaryType.SEERS_VILLAGE,0,3)){
player!!.achievementDiaryManager.finishTask(player!!,DiaryType.SEERS_VILLAGE,0,3)
player!!.inventory.remove(Item(197,1))
end()
}else {
player!!.inventory.remove(Item(197,1))
end()
}
1 -> playerl(
FacialExpression.ANNOYED,
"Excuse me?"
).also { stage++ }
2 -> npcl(
FacialExpression.FRIENDLY,
"Sorry, I meant to say 'thank you'. Most refreshing."
).also { stage++ }
3 -> playerl(
FacialExpression.DISGUSTED_HEAD_SHAKE,
"Are you sure that stuff is safe to drink?"
).also { stage++ }
4 -> npcl(
FacialExpression.HAPPY,
"Oh yes, Stankers' creations may be dangerous for those with weak constitutions, but, personally. I find them rather invigorating."
).also {
player!!.inventory.remove(Item(197, 1))
stage = END_DIALOGUE
}
}
}

View file

@ -0,0 +1,75 @@
package rs09.game.interaction.item.withobject
import api.*
import core.game.node.item.Item
import org.rs09.consts.Items
import org.rs09.consts.Scenery
import rs09.game.interaction.InteractionListener
/**
* Handles coal truck interactions
* @author ceik
* @author vddCore
*/
class CoalTruckListener : InteractionListener {
companion object {
private const val ATTRIBUTE_COAL_TRUCK_INVENTORY = "coal-truck-inventory"
}
override fun defineListeners() {
on(Scenery.COAL_TRUCK_2114, SCENERY, "remove-coal") { player, node ->
var coalInTruck = getAttribute(player, ATTRIBUTE_COAL_TRUCK_INVENTORY, 0)
if (coalInTruck == 0) {
sendDialogue(player, "The coal truck is empty.")
return@on true
}
var toRemove = freeSlots(player)
if (toRemove > coalInTruck) {
toRemove = coalInTruck
}
if (addItem(player, Items.COAL_453, toRemove)) {
coalInTruck -= toRemove
setAttribute(player, "/save:$ATTRIBUTE_COAL_TRUCK_INVENTORY", coalInTruck)
}
return@on true
}
on(Scenery.COAL_TRUCK_2114, SCENERY, "investigate") { player, _ ->
val coalInTruck = getAttribute(player, ATTRIBUTE_COAL_TRUCK_INVENTORY, 0)
sendDialogue(
player,
"There is currently $coalInTruck coal in the truck. "
+ "The truck has space for " + (120 - coalInTruck) + " more coal."
)
return@on true
}
onUseWith(SCENERY, Items.COAL_453, Scenery.COAL_TRUCK_2114) { player, _, _ ->
var coalInTruck = getAttribute(player, ATTRIBUTE_COAL_TRUCK_INVENTORY, 0)
var coalInInventory = amountInInventory(player, Items.COAL_453)
if (coalInInventory + coalInTruck >= 120) {
coalInInventory = 120 - coalInTruck
sendMessage(player, "You have filled up the coal truck.")
}
if (removeItem(player, Item(Items.COAL_453, coalInInventory))) {
coalInTruck += coalInInventory
setAttribute(
player,
"/save:$ATTRIBUTE_COAL_TRUCK_INVENTORY",
coalInTruck
)
}
return@onUseWith true
}
}
}

View file

@ -1,80 +0,0 @@
package rs09.game.interaction.item.withobject
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.item.Item
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
import rs09.game.interaction.InteractionListener
import java.util.*
/**
* Handles coal truck interactions
* @author ceik
*/
class CoalTruckInteractionListeners : InteractionListener {
val SEERS_VILLAGE_COAL_TRUCK_2114 = 2114
val seersVillageTrucks = ZoneBorders(2690,3502,2699,3508)
val COAL_TRUCK_2114 = 2114
val COAL = Items.COAL_453
override fun defineListeners() {
on(SEERS_VILLAGE_COAL_TRUCK_2114, SCENERY, "remove-coal") { player, node ->
var coalInTruck = player.getAttribute("coal-truck-inventory", 0)
var freeSpace = player.inventory.freeSlots()
val toAdd: MutableList<Item> = ArrayList()
if (coalInTruck == 0) {
player.dialogueInterpreter.sendDialogue("The coal truck is empty.")
return@on true
}
var toRemove = player.inventory.freeSlots()
if(toRemove > coalInTruck) toRemove = coalInTruck
player.inventory.add(Item(Items.COAL_453,toRemove))
coalInTruck -= toRemove
player.setAttribute("/save:coal-truck-inventory", coalInTruck)
if (!player.achievementDiaryManager.hasCompletedTask(DiaryType.SEERS_VILLAGE, 1, 2)
&& seersVillageTrucks.insideBorder(player)
&& player.getAttribute("diary:seers:coal-truck-full", false)) {
player.removeAttribute("diary:seers:coal-truck-full")
player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 1, 2)
}
return@on true
}
on(SEERS_VILLAGE_COAL_TRUCK_2114, SCENERY, "investigate") { player, node ->
var coalInTruck = player.getAttribute("coal-truck-inventory", 0)
player.dialogueInterpreter.sendDialogue("There is currently $coalInTruck coal in the truck.", "The truck has space for " + (120 - coalInTruck) + " more coal.")
return@on true
}
onUseWith(SCENERY,COAL,COAL_TRUCK_2114){ player, _, _ ->
var coalInTruck = player.getAttribute("coal-truck-inventory", 0)
var coalInInventory = player.inventory.getAmount(Items.COAL_453)
if(coalInInventory + coalInTruck >= 120){
coalInInventory = 120 - coalInTruck
player.packetDispatch.sendMessage("You have filled up the coal truck.")
//handle coal truck task for seer's village
if (!player.achievementDiaryManager.getDiary(DiaryType.SEERS_VILLAGE).isComplete(1, 2)
&& player.viewport.region.id == 10294) { // region 10294 is at coal truck mine, region 10806 is in seers village
player.setAttribute("/save:diary:seers:coal-truck-full", true)
}
}
player.inventory.remove(Item(Items.COAL_453,coalInInventory))
coalInTruck += coalInInventory
player.setAttribute("/save:coal-truck-inventory",coalInTruck)
return@onUseWith true
}
}
}

View file

@ -4,25 +4,25 @@ import api.*
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.entity.player.link.emote.Emotes
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.game.interaction.InteractionListener
/**
* Handles taunting of the demon in the wizard's tower
* @author afaroutdude / Ceikry
* @author Ceikry
* @author vddCore
*/
private const val BARS = 37668
class DemonTauntHandler : InteractionListener{
class DemonTauntHandler : InteractionListener {
override fun defineListeners() {
on(BARS,SCENERY,"taunt-through"){ player, _ ->
sendMessage(player, "You taunt the demon, making it growl.")
on(Scenery.RAILING_37668, SCENERY, "taunt-through") { player, _ ->
val demon = findLocalNPC(player, NPCs.LESSER_DEMON_82) ?: return@on true
sendMessage(player, "You taunt the demon, making it growl.")
sendChat(demon, "Graaagh!")
face(demon, player, 3)
emote(player, Emotes.RASPBERRY)
player.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 1, 13)
return@on true
}
}
}

View file

@ -21,7 +21,7 @@ class CanoeInterfaceListeners : InterfaceListener {
val SHAPE_INTERFACE = Components.CANOE_52
val DESTINATION_INTERFACE = Components.CANOE_STATIONS_MAP_53
val EDGEVILLE_REGION = 12342
private val boatChilds = intArrayOf(47, 48, 3, 6, 49)
private val locationChilds = intArrayOf(50, 47, 44, 36)
@ -51,9 +51,6 @@ class CanoeInterfaceListeners : InterfaceListener {
player.pulseManager.run(object : Pulse(3) {
override fun pulse(): Boolean {
if (RandomFunction.random(if (canoe == Canoe.WAKA) 8 else 6) == 1) {
if (player.location.regionId == EDGEVILLE_REGION && canoe == Canoe.WAKA) {
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 2, 10)
}
player.varpManager.setVarbit(varbit,CanoeUtils.getCraftValue(canoe,false))
player.skills.addExperience(Skills.WOODCUTTING, canoe.experience)
player.unlock()

View file

@ -0,0 +1,22 @@
package rs09.game.node.entity.player.link.diary
import api.inBorders
import core.game.node.entity.player.Player
import core.game.world.map.zone.ZoneBorders
class AreaDiaryTask(
val zoneBorders: ZoneBorders,
val diaryLevel: DiaryLevel,
val taskId: Int,
private val condition: ((player: Player) -> Boolean)? = null
) {
fun whenSatisfied(player: Player, then: () -> Unit) {
var result = inBorders(player, zoneBorders)
condition?.let {
result = it(player)
}
if (result) then()
}
}

View file

@ -1,437 +0,0 @@
package rs09.game.node.entity.player.link.diary
import api.*
import api.events.*
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.entity.skill.slayer.Tasks
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Components
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.game.Event
import rs09.game.system.command.Privilege
private const val TASK_DRAYNOR_BANK = 15
private const val TASK_LUMBRIDGE_GENERAL_STORE = 18
class DiaryEventHook : LoginListener {
override fun login(player: Player) {
player.hook(Event.ResourceProduced, DiaryGatherHooks)
player.hook(Event.Teleport, DiaryTeleportHooks)
player.hook(Event.NPCKilled, DiaryCombatHooks)
player.hook(Event.FireLit, DiaryFireHooks)
player.hook(Event.Interaction, DiaryInteractionEvents)
player.hook(Event.InterfaceOpened, DiaryInterfaceOpenEvents)
player.hook(Event.InterfaceClosed, DiaryInterfaceCloseEvents)
player.hook(Event.PickedUp, DiaryPickupEvents)
}
companion object {
private fun finishTask(entity: Player, diary: DiaryType, index: Int, task: Int) {
entity.achievementDiaryManager.finishTask(entity, diary, index, task)
}
private fun taskCompleted(entity: Player, diary: DiaryType,index: Int,task: Int): Boolean {
return entity.achievementDiaryManager.hasCompletedTask(diary,index,task)
}
}
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
)
}
12850 -> if (event.component.id == Components.SHOP_TEMPLATE_620) {
finishTask(
entity,
DiaryType.LUMBRIDGE,
0,
TASK_LUMBRIDGE_GENERAL_STORE
)
}
}
}
}
private object DiaryInteractionEvents : EventHook<InteractionEvent> {
override fun process(entity: Entity, event: InteractionEvent) {
if (entity !is Player) return
val regionId = entity.viewport.region.id
if (event.target is core.game.node.scenery.Scenery)
when (event.target.id) {
11729, 11727 -> if (regionId == 11828) finishTask(entity, DiaryType.FALADOR, 0, 3)
11889 -> if (regionId == 11572 && isEquipped(entity, Items.PROSELYTE_SALLET_9672) && isEquipped(
entity,
Items.PROSELYTE_HAUBERK_9674
) && isEquipped(entity, Items.PROSELYTE_CUISSE_9676)
) finishTask(entity, DiaryType.FALADOR, 2, 0)
30941 -> if (regionId == 12184) finishTask(entity, DiaryType.FALADOR, 2, 6)
36771 -> if (regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 0, 0)
12537 -> if (regionId == 12337) finishTask(entity, DiaryType.LUMBRIDGE, 0, 11)
26934 -> if (regionId == 12342) finishTask(entity, DiaryType.VARROCK, 0, 10)
24350, 24361 -> if (regionId == 12854) finishTask(entity, DiaryType.VARROCK, 0, 18)
in 115..122 -> if (event.option == "burst") finishTask(entity, DiaryType.FALADOR, 0, 12)
16149 -> finishTask(entity, DiaryType.VARROCK, 0, 4)
29944 -> if(regionId == 10552 && event.option == "renew-points") finishTask(entity, DiaryType.FREMENNIK,0,8)
//18137 -> if(regionId == 10810 && event.option == "examine") finishTask(entity, DiaryType.FREMENNIK,0,2)
//2112 -> if()
}
}
}
private object DiaryFireHooks : EventHook<LitFireEvent> {
val lumCastleBorders = ZoneBorders(3216, 3207, 3225, 3233, 0)
override fun process(entity: Entity, event: LitFireEvent) {
if (entity !is Player) return
val region = entity.viewport.region.id
when (region) {
10806 -> if (event.logId == Items.MAGIC_LOGS_1513) finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 5)
12593, 12849 -> if (event.logId == Items.LOGS_1511) finishTask(entity, DiaryType.LUMBRIDGE, 1, 9)
else -> {
if (event.logId == Items.WILLOW_LOGS_1519 && lumCastleBorders.insideBorder(entity))
finishTask(entity, DiaryType.LUMBRIDGE, 2, 3)
}
}
}
}
private object DiaryPickupEvents : EventHook<PickUpEvent>
{
override fun process(entity: Entity, event: PickUpEvent) {
if(entity !is Player) return
val regionId = entity.viewport.region.id
val Karamja = intArrayOf(10801,10802,11053,11054,11055,11056,11057,11058,11309,
11310,11311,11312,11313,11314,11565,11566,11567,11568,11569,11821,11822,11823)
when(event.itemId){
Items.SEAWEED_401 -> {
if(regionId == 10810 && !taskCompleted(entity,DiaryType.FREMENNIK,0,5)){
when(entity.getAttribute("RellekaSeaweed",0)){
0 -> entity.setAttribute("/save:RellekaSeaweed",1)
1 -> entity.incrementAttribute("RellekaSeaweed")
2 -> {
finishTask(entity, DiaryType.FREMENNIK,0,5)
entity.removeAttribute("RellekkaSeaweed")
}
}
}
if(regionId in Karamja && !taskCompleted(entity,DiaryType.KARAMJA, 0, 7)){
when(entity.getAttribute("KaramjaSeaweed", 0)){
0 -> entity.setAttribute("/save:KaramjaSeaweed",1)
in 1..3 -> entity.incrementAttribute("KaramjaSeaweed")
4 -> {
finishTask(entity,DiaryType.KARAMJA,0,7)
entity.removeAttribute("KaramjaSeaweed")
}
}
}
}
Items.PALM_LEAF_2339 -> {
if(regionId in Karamja && !taskCompleted(entity,DiaryType.KARAMJA,2,7)){
when(entity.getAttribute("KaramjaPalms",0)){
0 -> entity.setAttribute("/save:KaramjaPalms",1)
in 1..3 -> entity.incrementAttribute("KaramjaPalms")
4 -> {
finishTask(entity,DiaryType.KARAMJA,2,7)
entity.removeAttribute("KaramjaPalms")
}
}
}
}
}
}
}
private object DiaryGatherHooks : EventHook<ResourceProducedEvent> {
override fun process(entity: Entity, event: ResourceProducedEvent) {
if (entity !is Player) return
val regionId = entity.viewport.region.id
val RellekkaFishingSpots = intArrayOf(NPCs.FISHING_SPOT_324, NPCs.FISHING_SPOT_334, NPCs.FISHING_SPOT_322, NPCs.FISHING_SPOT_309)
when(event.itemId)
{
//Cut a log from a teak tree
Items.TEAK_LOGS_6333 -> finishTask(entity, DiaryType.KARAMJA, 1, 7)
//Cut a log from a mahogany tree
Items.MAHOGANY_LOGS_6332 -> finishTask(entity, DiaryType.KARAMJA, 1, 8)
Items.LOGS_1511 -> {
//Cut down a dying tree in the Lumber Yard
if (event.source.id == Scenery.DYING_TREE_24168 && regionId == 13110)
finishTask(entity, DiaryType.VARROCK, 0, 6)
}
Items.YEW_LOGS_1515 -> {
if (regionId == 10806) {
setAttribute(
entity,
"/save:diary:seers:cut-yew",
getAttribute(entity, "diary:seers:cut-yew", 0) + 1
)
if (getAttribute(entity, "diary:seers:cut-yew", 0) >= 5)
finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 1)
}
}
Items.WILLOW_LOGS_1519 -> if (regionId == 12850) finishTask(entity, DiaryType.LUMBRIDGE, 2, 6)
Items.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_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_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_TROUT_335 -> if (regionId == 12341) finishTask(entity, DiaryType.VARROCK, 0, 16)
Items.IRON_ORE_440 -> {
if (regionId == 13108) finishTask(entity, DiaryType.VARROCK, 0, 2)
else if (regionId == 13107) finishTask(entity, DiaryType.LUMBRIDGE, 1, 0)
}
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.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.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.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.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
)
}
when (event.original) {
Items.RAW_RAT_MEAT_2134 -> if ((regionId == 12593 || regionId == 12849) && event.itemId == Items.COOKED_MEAT_2142) finishTask(
entity,
DiaryType.LUMBRIDGE,
1,
10
)
}
if (getAttribute(entity, "diary:seers:shark-caught", 0) >= 5)
finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 7)
if (getAttribute(entity, "diary:seers:shark-cooked", 0) >= 5)
finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 8)
if ((regionId == 12593 || regionId == 12849) && event.source.name.startsWith("dead", true))
finishTask(entity, DiaryType.LUMBRIDGE, 1, 8)
if (event.source.id == NPCs.FISHING_SPOT_333 && entity.zoneMonitor.isInZone("karamja"))
finishTask(entity, DiaryType.KARAMJA, 0, 6)
if (event.source.id == Scenery.YEW_TREE_8513 && regionId == 11828)
finishTask(entity, DiaryType.FALADOR, 2, 3)
if (event.source.id == Scenery.COOKING_RANGE_114 && regionId == 12850)
finishTask(entity, DiaryType.LUMBRIDGE, 0, 7)
if(event.source.id == NPCs.FISHING_SPOT_324 && regionId == 10553)
finishTask(entity, DiaryType.FREMENNIK, 0, 7)
//Fish off of any of Rellekka's piers
//in RellekkaFishingSpots -> {
// if(entity.viewport.region.id == 10553)
//finishTask(entity, DiaryType.FREMENNIK, 0, 7)
//}
}
}
private object DiaryTeleportHooks : EventHook<TeleportEvent> {
val rangingGuild = Location(2657, 3439, 0)
override fun process(entity: Entity, event: TeleportEvent) {
if(entity !is Player) return
when(event.source){
1 -> if (event.location.withinDistance(rangingGuild)) {
finishTask(entity, DiaryType.SEERS_VILLAGE, 2, 0)
}
}
}
}
private object DiaryCombatHooks : EventHook<NPCKillEvent> {
val faladorDucks = intArrayOf(NPCs.DUCK_46, NPCs.DUCK_2693, NPCs.DUCK_6113)
val lumbridgeCows = intArrayOf(81, 397, 955, 1766, 1767, 3309)
val elementalNPCs = intArrayOf(1019, 1020, 1021, 1022)
val wyverns = Tasks.SKELETAL_WYVERN.npcs
val metalDragons =
intArrayOf(NPCs.BRONZE_DRAGON_1590, NPCs.IRON_DRAGON_1591, NPCs.STEEL_DRAGON_1592, NPCs.STEEL_DRAGON_3590)
val lumZombies = intArrayOf(NPCs.ZOMBIE_73, NPCs.ZOMBIE_74)
val fremCrabs = intArrayOf(NPCs.ROCK_CRAB_1265,NPCs.ROCK_CRAB_1267,NPCs.GIANT_ROCK_CRAB_2452,NPCs.GIANT_ROCK_CRAB_2885)
val fremCrawlers = intArrayOf(NPCs.CAVE_CRAWLER_1600,NPCs.CAVE_CRAWLER_1601,NPCs.CAVE_CRAWLER_1602,NPCs.CAVE_CRAWLER_1603,NPCs.CAVE_CRAWLER_7787,NPCs.CAVE_CRAWLER_7812)
override fun process(entity: Entity, event: NPCKillEvent) {
if (entity !is Player) return
when (event.npc.id) {
//FALADOR LEVEL 0 TASK 10
in faladorDucks -> {
if (entity.location.withinDistance(Location(2991, 3383, 0)))
finishTask(entity, DiaryType.FALADOR, 0, 9)
}
in lumbridgeCows -> {
// Obtain a cow-hide from a cow in the field north-east of Lumbridge
if (entity.viewport.region.id == 12850 || entity.viewport.region.id == 12851) {
finishTask(entity, DiaryType.LUMBRIDGE, 1, 1)
}
}
in fremCrawlers ->{
if(entity.viewport.region.id == 11164){
finishTask(entity,DiaryType.FREMENNIK,0,0)
}
}
in fremCrabs -> {
if (entity.viewport.region.id == 10810 || entity.viewport.region.id == 10042) {
when(entity.getAttribute("FremCrabs",0)){
0 -> entity.setAttribute("/save:FremCrabs",1)
in 1..3 -> entity.incrementAttribute("FremCrabs")
4 -> finishTask(entity,DiaryType.FREMENNIK, 0, 1)
}
}
}
NPCs.BLACK_UNICORN_133 -> {
if (entity.viewport.region.id in 10808..10809){
finishTask(entity,DiaryType.FREMENNIK,0,9)
}
}
NPCs.JOGRE_113 -> {
if (entity.viewport.region.id == 11412)
finishTask(entity, DiaryType.KARAMJA, 0, 9)
}
in elementalNPCs -> {
if (!entity.location.withinDistance(Location(2719, 9889, 0), 100))
return
when (event.npc.id) {
1019 -> setAttribute(entity, "/save:diary:seers:elemental:fire", true)
1020 -> setAttribute(entity, "/save:diary:seers:elemental:earth", true)
1021 -> setAttribute(entity, "/save:diary:seers:elemental:air", true)
1022 -> setAttribute(entity, "/save:diary:seers:elemental:water", true)
}
for (element in arrayOf("fire", "earth", "air", "water"))
if (!getAttribute(entity, "diary:seers:$element", false))
return
finishTask(entity, DiaryType.SEERS_VILLAGE, 1, 4)
}
NPCs.KET_ZEK_2743, NPCs.KET_ZEK_2744 -> finishTask(entity, DiaryType.KARAMJA, 2, 1)
in metalDragons -> {
if (entity.viewport.region.id == 10899 || entity.viewport.region.id == 10900)
finishTask(entity, DiaryType.KARAMJA, 2, 9)
}
in wyverns -> finishTask(entity, DiaryType.FALADOR, 2, 8)
in lumZombies -> {
if (entity.viewport.region.id == 12438 || entity.viewport.region.id == 12439)
finishTask(entity, DiaryType.LUMBRIDGE, 1, 18)
}
NPCs.GIANT_RAT_86 -> {
if (entity.viewport.region.id == 12593 || entity.viewport.region.id == 12849)
finishTask(entity, DiaryType.LUMBRIDGE, 1, 7)
}
NPCs.TOWER_ARCHER_688 -> setAttribute(
entity,
"/save:diary:seers:tower-archers",
getAttribute(entity, "diary:seers:tower-archers", 0) or 1
)
NPCs.TOWER_ARCHER_689 -> setAttribute(
entity,
"/save:diary:seers:tower-archers",
getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 1)
)
NPCs.TOWER_ARCHER_690 -> setAttribute(
entity,
"/save:diary:seers:tower-archers",
getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 2)
)
NPCs.TOWER_ARCHER_691 -> setAttribute(
entity,
"/save:diary:seers:tower-archers",
getAttribute(entity, "diary:seers:tower-archers", 0) or (1 shl 3)
)
}
if (getAttribute(entity, "diary:seers:tower-archers", 0) == 0xF)
finishTask(entity, DiaryType.SEERS_VILLAGE, 1, 6)
}
}
}

View file

@ -0,0 +1,230 @@
package rs09.game.node.entity.player.link.diary
import api.*
import api.events.*
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.world.map.zone.ZoneBorders
import rs09.game.Event
abstract class DiaryEventHookBase(private val diaryType: DiaryType) : MapArea, LoginListener {
protected companion object {
private fun <T> forEligibleEntityDo(entity: Entity, event: T, handler: (Player, T) -> Unit) {
if (entity !is Player) return
if (entity.isArtificial) return
handler(entity, event)
}
}
class EventHandler<T : api.events.Event>(
private val owner: DiaryEventHookBase,
private val handler: (Player, T) -> Unit
) : EventHook<T> {
override fun process(entity: Entity, event: T) {
forEligibleEntityDo(entity, event, handler)
}
}
open val areaTasks get() = arrayOf<AreaDiaryTask>()
final override fun defineAreaBorders(): Array<ZoneBorders>
= areaTasks.map { task -> task.zoneBorders }.toTypedArray()
final override fun areaEnter(entity: Entity) {
if (entity !is Player) return
if (entity.isArtificial) return
onAreaVisited(entity)
}
final override fun areaLeave(entity: Entity, logout: Boolean) {
if (entity !is Player) return
if (entity.isArtificial) return
onAreaLeft(entity)
}
final override fun login(player: Player) {
player.hook(Event.ResourceProduced, EventHandler(this, ::onResourceProduced))
player.hook(Event.NPCKilled, EventHandler(this, ::onNpcKilled))
player.hook(Event.Teleported, EventHandler(this, ::onTeleported))
player.hook(Event.FireLit, EventHandler(this, ::onFireLit))
player.hook(Event.Interacted, EventHandler(this, ::onInteracted))
player.hook(Event.ButtonClicked, EventHandler(this, ::onButtonClicked))
player.hook(Event.DialogueOpened, EventHandler(this, ::onDialogueOpened))
player.hook(Event.DialogueOptionSelected, EventHandler(this, ::onDialogueOptionSelected))
player.hook(Event.DialogueClosed, EventHandler(this, ::onDialogueClosed))
player.hook(Event.UsedWith, EventHandler(this, ::onUsedWith))
player.hook(Event.PickedUp, EventHandler(this, ::onPickedUp))
player.hook(Event.InterfaceOpened, EventHandler(this, ::onInterfaceOpened))
player.hook(Event.AttributeSet, EventHandler(this, ::onAttributeSet))
player.hook(Event.AttributeRemoved, EventHandler(this, ::onAttributeRemoved))
player.hook(Event.SpellCast, EventHandler(this, ::onSpellCast))
player.hook(Event.ItemAlchemized, EventHandler(this, ::onItemAlchemized))
player.hook(Event.ItemEquipped, EventHandler(this, ::onItemEquipped))
player.hook(Event.ItemUnequipped, EventHandler(this, ::onItemUnequipped))
player.hook(Event.ItemPurchased, EventHandler(this, ::onItemPurchasedFromShop))
player.hook(Event.ItemSold, EventHandler(this, ::onItemSoldToShop))
player.hook(Event.JobAssigned, EventHandler(this, ::onJobAssigned))
player.hook(Event.FairyRingDialed, EventHandler(this, ::onFairyRingDialed))
player.hook(Event.SummoningPointsRecharged, EventHandler(this, ::onSummoningPointsRecharged))
player.hook(Event.PrayerPointsRecharged, EventHandler(this, ::onPrayerPointsRecharged))
}
protected fun fulfillTaskRequirement(player: Player, level: DiaryLevel, task: Int, attribute: String) {
if (getAttribute(player, attribute, false)) return
player.achievementDiaryManager.updateTask(
player,
diaryType,
findIndexFor(level),
task,
false
)
setAttribute(player, "/save:$attribute", true)
}
protected fun whenTaskRequirementFulfilled(player: Player, attribute: String, then: () -> Unit) {
if (getAttribute(player, attribute, false)) {
then()
removeAttribute(player, attribute)
}
}
protected fun progressIncrementalTask(
player: Player,
level: DiaryLevel,
task: Int,
attribute: String,
maxProgress: Int
) {
if (isTaskCompleted(player, level, task)) return
val newValue = getAttribute(player, attribute, 0) + 1
setAttribute(
player,
"/save:${attribute}",
newValue
)
if (newValue < maxProgress) {
player.achievementDiaryManager.updateTask(
player,
diaryType,
findIndexFor(level),
task,
false
)
} else {
finishTask(player, level, task)
removeAttribute(player, attribute)
}
}
protected fun progressFlaggedTask(
player: Player,
level: DiaryLevel,
task: Int,
attribute: String,
bit: Int,
targetValue: Int
) {
if (isTaskCompleted(player, level, task)) {
return
}
val oldValue = getAttribute(player, attribute, 0)
val newValue = oldValue or bit
if (newValue != targetValue) {
if ((oldValue and bit) != 0) return
setAttribute(
player,
"/save:${attribute}",
newValue
)
player.achievementDiaryManager.updateTask(
player,
diaryType,
findIndexFor(level),
task,
false
)
} else {
finishTask(player, level, task)
removeAttribute(player, attribute)
}
}
protected fun finishTask(player: Player, level: DiaryLevel, task: Int) {
player.achievementDiaryManager.finishTask(
player,
diaryType,
findIndexFor(level),
task
)
}
private fun isTaskCompleted(player: Player, level: DiaryLevel, task: Int): Boolean {
return player.achievementDiaryManager.hasCompletedTask(
diaryType,
findIndexFor(level),
task
)
}
private fun findIndexFor(level: DiaryLevel): Int {
val levelName = level.name.lowercase().replaceFirstChar { c -> c.uppercase() }
val levelIndex = diaryType.levelNames.indexOf(levelName)
if (levelIndex < 0) {
throw IllegalArgumentException("'$levelName' was not found in diary '$diaryType'.")
}
return levelIndex
}
protected open fun onAreaVisited(player: Player) {
areaTasks.forEach {
it.whenSatisfied(player) {
finishTask(
player,
it.diaryLevel,
it.taskId
)
}
}
}
protected open fun onAreaLeft(player: Player) {}
protected open fun onResourceProduced(player: Player, event: ResourceProducedEvent) {}
protected open fun onNpcKilled(player: Player, event: NPCKillEvent) {}
protected open fun onTeleported(player: Player, event: TeleportEvent) {}
protected open fun onFireLit(player: Player, event: LitFireEvent) {}
protected open fun onInteracted(player: Player, event: InteractionEvent) {}
protected open fun onButtonClicked(player: Player, event: ButtonClickEvent) {}
protected open fun onDialogueOpened(player: Player, event: DialogueOpenEvent) {}
protected open fun onDialogueClosed(player: Player, event: DialogueCloseEvent) {}
protected open fun onDialogueOptionSelected(player: Player, event: DialogueOptionSelectionEvent) {}
protected open fun onUsedWith(player: Player, event: UseWithEvent) {}
protected open fun onPickedUp(player: Player, event: PickUpEvent) {}
protected open fun onInterfaceOpened(player: Player, event: InterfaceOpenEvent) {}
protected open fun onAttributeSet(player: Player, event: AttributeSetEvent) {}
protected open fun onAttributeRemoved(player: Player, event: AttributeRemoveEvent) {}
protected open fun onSpellCast(player: Player, event: SpellCastEvent) {}
protected open fun onItemAlchemized(player: Player, event: ItemAlchemizationEvent) {}
protected open fun onItemEquipped(player: Player, event: ItemEquipEvent) {}
protected open fun onItemUnequipped(player: Player, event: ItemUnequipEvent) {}
protected open fun onItemPurchasedFromShop(player: Player, event: ItemShopPurchaseEvent) {}
protected open fun onItemSoldToShop(player: Player, event: ItemShopSellEvent) {}
protected open fun onJobAssigned(player: Player, event: JobAssignmentEvent) {}
protected open fun onFairyRingDialed(player: Player, event: FairyRingDialEvent) {}
protected open fun onSummoningPointsRecharged(player: Player, event: SummoningPointsRechargeEvent) {}
protected open fun onPrayerPointsRecharged(player: Player, event: PrayerPointsRechargeEvent) {}
}

View file

@ -0,0 +1,236 @@
package rs09.game.node.entity.player.link.diary.events
import api.areEquipped
import api.events.*
import api.inBorders
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.game.content.dialogue.region.falador.RisingSunInnBartenderDialogue
import rs09.game.interaction.inter.FairyRing
import rs09.game.node.entity.player.link.diary.AreaDiaryTask
import rs09.game.node.entity.player.link.diary.DiaryEventHookBase
import rs09.game.node.entity.player.link.diary.DiaryLevel
class FaladorAchievementDiary : DiaryEventHookBase(DiaryType.FALADOR) {
companion object {
private const val ATTRIBUTE_BLACK_CHAINBODY_PURCHASED = "diary:falador:black-chain-bought"
private val MINING_GUILD_AREA = ZoneBorders(3016, 9731, 3055, 9756)
private val DARK_WIZARDS_TOWER_ROOF_AREA = ZoneBorders(2904, 3331, 2911, 3338, 2)
private val WHITE_KNIGHTS_CASTLE_ROOF_AREA = ZoneBorders(2955, 3333, 2996, 3354, 3)
private val PARK_TREE_PATCH_AREA = ZoneBorders(3002, 3371, 3006, 3375)
private val PARK_POND_AREA = ZoneBorders(2987, 3381, 2994, 3386)
private val WAYNES_CHAINS_AREA = ZoneBorders(2969, 3310, 2975, 3314)
private val SARAHS_FARMING_SHOP_AREA = ZoneBorders(3021, 3285, 3040, 3296)
private val PROSELYTE_FULL_ARMOR_MALE = intArrayOf(
Items.PROSELYTE_SALLET_9672,
Items.PROSELYTE_HAUBERK_9674,
Items.PROSELYTE_CUISSE_9676
)
private val PROSELYTE_FULL_ARMOR_FEMALE = intArrayOf(
Items.PROSELYTE_SALLET_9672,
Items.PROSELYTE_HAUBERK_9674,
Items.PROSELYTE_TASSET_9678
)
private val PARTY_BALLOONS = intArrayOf(
Scenery.PARTY_BALLOON_115, Scenery.PARTY_BALLOON_116, Scenery.PARTY_BALLOON_117,
Scenery.PARTY_BALLOON_118, Scenery.PARTY_BALLOON_119, Scenery.PARTY_BALLOON_120,
Scenery.PARTY_BALLOON_121, Scenery.PARTY_BALLOON_122
)
private val PARK_DUCKS = intArrayOf(
NPCs.DUCK_46, NPCs.DUCK_2693
)
private val SKELETAL_WYVERNS = intArrayOf(
NPCs.SKELETAL_WYVERN_3068, NPCs.SKELETAL_WYVERN_3069,
NPCs.SKELETAL_WYVERN_3070, NPCs.SKELETAL_WYVERN_3071
)
object EasyTasks {
const val PORT_SARIM_SARAH_BUY_FARMING_AMULET = 0
const val RISING_SUN_BUY_A_STATBOOST = 1
const val WAYNE_BUY_AND_WEAR_BLACK_CHAINBODY = 2
const val WHITE_KNIGHTS_CASTLE_CLIMB_TO_TOP = 3
const val SIR_RENITEE_FAMILY_CREST_DISCOVER = 4
const val PARK_ENTER_MOLE_LAIR = 5
const val FEED_RIDGELEY_AT_HAIRDRESSERS = 6
const val FILL_BUCKET_FROM_NORTHERN_PUMP = 7
const val HEAL_ELEMENTAL_WIZARD_WITH_SPELL = 8
const val PARK_KILL_A_DUCK = 9
const val SOUTHERN_ROAD_KILL_HIGHWAYMAN = 10
const val MAKE_AIR_TIARA = 11
const val POP_PARTY_BALLOON = 12
const val PORT_SARIM_RECHARGE_PRAYER_POINTS = 13
const val TAKE_BOAT_TO_ENTRANA = 14
}
object MediumTasks {
const val PORT_SARIM_CRAFT_FRUIT_BASKET = 0
const val CRAWL_UNDER_SOUTHERN_WALL = 1
const val GRAPPLE_AND_JUMP_OFF_NORTHERN_WALL = 2
const val INCREASE_WHITE_KNIGHT_REPUTATION = 3
const val ICE_DUNGEON_KILL_ICE_GIANT = 4
const val CHEMISTS_LIGHT_BULLSEYE_LANTERN = 5
const val PICKPOCKET_GUARD = 6
const val PORT_SARIM_NORTHERN_PATCH_PLACE_SCARECROW = 7
const val SALUTE_SIR_TIFFY_CASHIEN_IN_INITIATE_ARMOR = 8
const val SMITH_BLURITE_CROSSBOW_LIMBS_ON_THURGOS_ANVIL = 9
const val PORT_SARIM_CHAROS_TRAVEL_TO_MUSA_POINT = 10
const val PORT_SARIM_VISIT_RAT_PITS = 11
}
object HardTasks {
const val DARK_WIZARDS_TOWER_ASCEND_IN_FULL_PROSELYTE_ARMOR = 0
const val CHANGE_FAMILY_CREST_TO_SARADOMIN = 1
const val CRAFT_196_AIR_RUNES_AT_ONCE = 2
const val CUT_DOWN_GROWN_YEW_OR_MAGIC_TREE = 3
const val DIAL_FAIRY_RING_MUDSKIPPER_POINT = 4
const val PORT_SARIM_BETTY_DYE_CAPE_PINK = 5
const val ENTER_MINING_GUILD = 6
const val MUDSKIPPER_POINT_KILL_MOGRE = 7
const val ICE_DUNGEON_KILL_SKELETAL_WYVERN = 8
const val PORT_SARIM_FISH_STORE_SUMMON_IBIS = 9
}
}
override val areaTasks
get() = arrayOf(
AreaDiaryTask(
WHITE_KNIGHTS_CASTLE_ROOF_AREA,
DiaryLevel.EASY,
EasyTasks.WHITE_KNIGHTS_CASTLE_CLIMB_TO_TOP
),
AreaDiaryTask(
MINING_GUILD_AREA,
DiaryLevel.HARD,
HardTasks.ENTER_MINING_GUILD
),
AreaDiaryTask(
DARK_WIZARDS_TOWER_ROOF_AREA,
DiaryLevel.HARD,
HardTasks.DARK_WIZARDS_TOWER_ASCEND_IN_FULL_PROSELYTE_ARMOR,
) { player ->
areEquipped(player, *PROSELYTE_FULL_ARMOR_MALE)
|| areEquipped(player, *PROSELYTE_FULL_ARMOR_FEMALE)
}
)
override fun onInteracted(player: Player, event: InteractionEvent) {
when (player.viewport.region.id) {
12084 -> {
if (event.option == "burst" && event.target.id in PARTY_BALLOONS) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.POP_PARTY_BALLOON
)
}
}
}
}
override fun onDialogueOptionSelected(player: Player, event: DialogueOptionSelectionEvent) {
when (event.dialogue) {
is RisingSunInnBartenderDialogue -> {
if (event.currentStage in 12..14) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.RISING_SUN_BUY_A_STATBOOST
)
}
}
}
}
override fun onResourceProduced(player: Player, event: ResourceProducedEvent) {
when (player.viewport.region.id) {
11828 -> when (event.itemId) {
Items.YEW_LOGS_1515, Items.MAGIC_LOGS_1513 -> {
if (inBorders(player, PARK_TREE_PATCH_AREA)) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.CUT_DOWN_GROWN_YEW_OR_MAGIC_TREE
)
}
}
}
}
}
override fun onNpcKilled(player: Player, event: NPCKillEvent) {
when (player.viewport.region.id) {
11828 -> if (event.npc.id in PARK_DUCKS && inBorders(event.npc, PARK_POND_AREA)) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.PARK_KILL_A_DUCK
)
}
12181 -> if (event.npc.id in SKELETAL_WYVERNS) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.ICE_DUNGEON_KILL_SKELETAL_WYVERN
)
}
}
}
override fun onItemPurchasedFromShop(player: Player, event: ItemShopPurchaseEvent) {
when {
inBorders(player, WAYNES_CHAINS_AREA) && (event.itemId == Items.BLACK_CHAINBODY_1107) -> {
fulfillTaskRequirement(
player,
DiaryLevel.EASY,
EasyTasks.WAYNE_BUY_AND_WEAR_BLACK_CHAINBODY,
ATTRIBUTE_BLACK_CHAINBODY_PURCHASED
)
}
inBorders(player, SARAHS_FARMING_SHOP_AREA) && (event.itemId == Items.AMULET_OF_FARMING8_12622) -> {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.PORT_SARIM_SARAH_BUY_FARMING_AMULET
)
}
}
}
override fun onItemEquipped(player: Player, event: ItemEquipEvent) {
when {
inBorders(player, WAYNES_CHAINS_AREA) && (event.itemId == Items.BLACK_CHAINBODY_1107) -> {
whenTaskRequirementFulfilled(player, ATTRIBUTE_BLACK_CHAINBODY_PURCHASED) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.WAYNE_BUY_AND_WEAR_BLACK_CHAINBODY
)
}
}
}
}
override fun onFairyRingDialed(player: Player, event: FairyRingDialEvent) {
if (event.fairyRing == FairyRing.AIQ) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.DIAL_FAIRY_RING_MUDSKIPPER_POINT
)
}
}
}

View file

@ -0,0 +1,201 @@
package rs09.game.node.entity.player.link.diary.events
import api.events.*
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.game.content.dialogue.region.barbarianassault.CaptainCainDialogue
import rs09.game.content.dialogue.region.rellekka.HuntingExpertRellekkaDialogue
import rs09.game.interaction.inter.FairyRing
import rs09.game.node.entity.player.link.diary.AreaDiaryTask
import rs09.game.node.entity.player.link.diary.DiaryEventHookBase
import rs09.game.node.entity.player.link.diary.DiaryLevel
class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) {
companion object {
private const val ATTRIBUTE_SEAWEED_PICKED = "diary:fremennik:seaweed-picked"
private const val ATTRIBUTE_ROCK_CRAB_KILLCOUNT = "diary:fremennik:rock-crabs-killed"
private const val ATTRIBUTE_BARBARIAN_FISHING_TRAINING = "barbtraining:fishing"
private const val ATTRIBUTE_BARBARIAN_HUNTING_TRAINING = "barbtraining:hunting"
private val WINDSWEPT_TREE_AREA = ZoneBorders(2743, 3718, 2750, 3737)
private val FISHING_SPOTS = arrayOf(
NPCs.FISHING_SPOT_309, NPCs.FISHING_SPOT_334,
NPCs.FISHING_SPOT_324, NPCs.FISHING_SPOT_322
)
private val ROCK_CRABS = arrayOf(
NPCs.ROCK_CRAB_1265, NPCs.ROCK_CRAB_1267
)
private val CAVE_CRAWLERS = arrayOf(
NPCs.CAVE_CRAWLER_1600, NPCs.CAVE_CRAWLER_1601,
NPCs.CAVE_CRAWLER_1602, NPCs.CAVE_CRAWLER_1603
)
object EasyTasks {
const val SLAYER_CAVE_KILL_CAVE_CRAWLER = 0
const val KILL_5_ROCK_CRABS = 1
const val MAINLAND_FIND_HIGHEST_TREE = 2
const val BARBARIAN_ASSAULT_VIEW_REWARDS = 3
const val OTTO_GODBLESSED_LEARN_BARBARIAN_FISHING = 4
const val PICK_3_SEAWEED = 5
const val FIND_HUNTING_EXPERT = 6
const val PIER_CATCH_FISH = 7
const val GATE_OBELISK_RECHARGE_POINTS = 8
const val KILL_ADULT_BLACK_UNICORN = 9
}
object MediumTasks {
const val LEARN_HISTORY_FROM_CHIEFTAIN_BRUNDT = 0
const val TOWER_GUARDS_WATCH_SHOUTING_MATCH = 1
const val INTERACT_WITH_PET_ROCK = 2
const val MAKE_3_VIALS = 3
const val CHARM_FOSSEGRIMEN_RAW_BASS = 4
const val KILL_ICE_TROLL_WHILE_WEARING_YAK_ARMOR = 5
const val MAKE_CHEESE_WITH_CHURN = 6
const val DIAL_FAIRY_RING_MOUNTAINTOP = 7
const val BROWSE_BOOT_COLORS_YRSA = 8
const val HUNT_SABRE_TOOTHED_KYATT = 9
const val STEAL_FISH_FROM_STALL = 10
}
object HardTasks {
const val KILL_3_DAGANNOTHS = 0
const val FREMENNIK_HONORIFIC_ARMOR = 1
const val COMPLETE_BARBARIAN_OUTPOST_AGILITY_COURSE = 2
const val LUNAR_ISLE_MINE_PURE_ESSENCE = 3
const val MAKE_BARBARIAN_PYRE_SHIP_ARCTIC_PINE = 4
const val CATCH_TUNE_WITHOUT_HARPOON = 5
const val BAKE_PIE_WITH_MAGIC = 6
const val KILL_MITHRIL_DRAGON = 7
const val GET_MAHOGANY_FROM_ETCETERIA = 8
}
}
override val areaTasks get() = arrayOf(
AreaDiaryTask(
WINDSWEPT_TREE_AREA,
DiaryLevel.EASY,
EasyTasks.MAINLAND_FIND_HIGHEST_TREE
)
)
override fun onAttributeSet(player: Player, event: AttributeSetEvent) {
when (event.attribute) {
"/save:${ATTRIBUTE_BARBARIAN_FISHING_TRAINING}" -> {
if (event.value !is Boolean) return
if (event.value) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.OTTO_GODBLESSED_LEARN_BARBARIAN_FISHING
)
}
}
}
}
override fun onDialogueOpened(player: Player, event: DialogueOpenEvent) {
when (event.dialogue) {
is CaptainCainDialogue -> {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.BARBARIAN_ASSAULT_VIEW_REWARDS
)
}
is HuntingExpertRellekkaDialogue -> {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.FIND_HUNTING_EXPERT
)
}
}
}
override fun onResourceProduced(player: Player, event: ResourceProducedEvent) {
when (player.viewport.region.id) {
10553 -> if (event.source.id in FISHING_SPOTS) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.PIER_CATCH_FISH
)
}
}
}
override fun onNpcKilled(player: Player, event: NPCKillEvent) {
when (player.viewport.region.id) {
10042, 10554 -> if (event.npc.id in ROCK_CRABS) {
progressIncrementalTask(
player,
DiaryLevel.EASY,
EasyTasks.KILL_5_ROCK_CRABS,
ATTRIBUTE_ROCK_CRAB_KILLCOUNT,
5
)
}
11164 -> if (event.npc.id in CAVE_CRAWLERS) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.SLAYER_CAVE_KILL_CAVE_CRAWLER
)
}
10808, 10809 -> if (event.npc.id == NPCs.BLACK_UNICORN_133) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.KILL_ADULT_BLACK_UNICORN
)
}
}
}
override fun onPickedUp(player: Player, event: PickUpEvent) {
when (player.viewport.region.id) {
10810 -> if (event.itemId == Items.SEAWEED_401) {
progressIncrementalTask(
player,
DiaryLevel.EASY,
EasyTasks.PICK_3_SEAWEED,
ATTRIBUTE_SEAWEED_PICKED,
3
)
}
}
}
override fun onFairyRingDialed(player: Player, event: FairyRingDialEvent) {
if (event.fairyRing == FairyRing.DKS) {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.DIAL_FAIRY_RING_MOUNTAINTOP
)
}
}
override fun onSummoningPointsRecharged(player: Player, event: SummoningPointsRechargeEvent) {
when (player.viewport.region.id) {
10552 -> if (event.obelisk.id == Scenery.SMALL_OBELISK_29944) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.GATE_OBELISK_RECHARGE_POINTS
)
}
}
}
}

View file

@ -0,0 +1,192 @@
package rs09.game.node.entity.player.link.diary.events
import api.events.NPCKillEvent
import api.events.PickUpEvent
import api.events.ResourceProducedEvent
import api.inBorders
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import rs09.game.node.entity.player.link.diary.DiaryEventHookBase
import rs09.game.node.entity.player.link.diary.DiaryLevel
class KaramjaAchievementDiary : DiaryEventHookBase(DiaryType.KARAMJA) {
companion object {
private const val ATTRIBUTE_SEAWEED_PICKED = "diary:karamja:seaweed-picked"
private const val ATTRIBUTE_PALM_LEAF_PICKED = "diary:karamja:palm-leaf-picked"
private val MAIN_ISLAND_AREA = ZoneBorders(2749, 2886, 2972, 3132)
private val BANANA_FISHING_SPOT_AREA = ZoneBorders(2923, 3173, 2928, 3182)
private val TAI_BWO_WANNAI_WOODCUTTING_AREA = ZoneBorders(2817, 3076, 2829, 3090)
private val KET_ZEKS = arrayOf(
NPCs.KET_ZEK_2743,
NPCs.KET_ZEK_2744
)
private val METAL_DRAGONS = arrayOf(
NPCs.BRONZE_DRAGON_1590,
NPCs.IRON_DRAGON_1591,
NPCs.STEEL_DRAGON_1592
)
object EasyTasks {
const val PICK_5_BANANAS = 0
const val TRAVEL_TO_MOSS_GIANTS_VIA_ROPESWING = 1
const val BRIMHAVEN_MINE_GOLD = 2
const val MUSA_POINT_CHARTER_SHIP_TO_PORT_SARIM = 3
const val BRIMHAVEN_CHARTER_SHIP_TO_ARDOUGNE = 4
const val CAIRN_ISLE_VISIT = 5
const val USE_FISHING_SPOTS_BANANA_PLANTATION = 6
const val PICK_5_SEAWEED = 7
const val ATTEMPT_TZHAAR_FIGHT_PITS_OR_FIGHT_CAVE = 8
const val POTHOLE_DUNGEON_KILL_JOGRE = 9
}
object MediumTasks {
const val BRIMHAVEN_CLAIM_AGILITY_ARENA_TICKET = 0
const val FIND_HIDDEN_WALL_BELOW_VOLCANO = 1
const val CRANDOR_ISLAND_VISIT = 2
const val USE_VIGROY_HAJEDY_CARTS = 3
const val TAI_BWO_WANNAI_EARN_FULL_FAVOR = 4
const val COOK_SPIDER_ON_STICK = 5
const val CAIRN_ISLE_CHARTER_LADY_OF_THE_WAVES = 6
const val CUT_TEAK_TREE = 7
const val CUT_MAHOGANY_TREE = 8
const val CATCH_KARAMBWAN = 9
const val EXCHANGE_GEMS_TUBER_TRADING_STICKS_FOR_MACHETE = 10
const val GNOME_GLIDE_TO_KARAMJA = 11
const val BRIMHAVEN_GROW_HEALTHY_FRUIT_TREE = 12
const val TRAP_HORNED_GRAAHK = 13
const val BRIMHAVEN_DUNGEON_CHOP_VINES = 14
const val BRIMHAVEN_DUNGEON_CROSS_LAVA_STEPPING_STONES = 15
const val CHARTER_SHIP_EAST = 16
const val MINE_RED_TOPAZ = 17
}
object HardTasks {
const val FIGHT_PITS_BECOME_CHAMPION = 0
const val FIGHT_CAVE_KILL_KET_ZEK = 1
const val EAT_OOMLIE_WRAP = 2
const val CRAFT_NATURE_RUNES = 3
const val COOK_KARAMBWAN_PROPERLY = 4
const val KHARAZI_JUNGLE_KILL_DEATHWING = 5
const val VOLCANO_USE_CROSSBOW_SHORTCUT_SOUTH = 6
const val PICK_5_PALM_LEAVES = 7
const val DURADEL_LAPALOK_GET_SLAYER_TASK = 8
const val BRIMHAVEN_DUNGEON_KILL_METAL_DRAGON = 9
}
}
override fun onResourceProduced(player: Player, event: ResourceProducedEvent) {
when (player.viewport.region.id) {
11310, 11410 -> if (event.itemId == Items.UNCUT_RED_TOPAZ_1629) {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.MINE_RED_TOPAZ
)
}
10802 -> if (event.itemId == Items.GOLD_ORE_444) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.BRIMHAVEN_MINE_GOLD
)
}
}
when {
inBorders(player, BANANA_FISHING_SPOT_AREA) -> {
when (event.source.id) {
NPCs.FISHING_SPOT_323,
NPCs.FISHING_SPOT_333 -> {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.USE_FISHING_SPOTS_BANANA_PLANTATION
)
}
}
}
inBorders(player, TAI_BWO_WANNAI_WOODCUTTING_AREA) -> {
when (event.itemId) {
Items.MAHOGANY_LOGS_6332 -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CUT_MAHOGANY_TREE
)
}
Items.TEAK_LOGS_6333 -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CUT_TEAK_TREE
)
}
}
}
}
}
override fun onNpcKilled(player: Player, event: NPCKillEvent) {
when (player.viewport.region.id) {
10899, 10900 -> if (event.npc.id in METAL_DRAGONS) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.BRIMHAVEN_DUNGEON_KILL_METAL_DRAGON
)
}
11412 -> if (event.npc.id == NPCs.JOGRE_113) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.POTHOLE_DUNGEON_KILL_JOGRE
)
}
/* Ket-Zek only appears in an instanced Fight Cave area. */
else -> if (event.npc.id in KET_ZEKS) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.FIGHT_CAVE_KILL_KET_ZEK
)
}
}
}
override fun onPickedUp(player: Player, event: PickUpEvent) {
when {
inBorders(player, MAIN_ISLAND_AREA) -> {
if (event.itemId == Items.SEAWEED_401) {
progressIncrementalTask(
player,
DiaryLevel.EASY,
EasyTasks.PICK_5_SEAWEED,
ATTRIBUTE_SEAWEED_PICKED,
5
)
}
if (event.itemId == Items.PALM_LEAF_2339) {
progressIncrementalTask(
player,
DiaryLevel.HARD,
HardTasks.PICK_5_PALM_LEAVES,
ATTRIBUTE_PALM_LEAF_PICKED,
5
)
}
}
}
}
}

View file

@ -0,0 +1,417 @@
package rs09.game.node.entity.player.link.diary.events
import api.events.*
import api.inBorders
import api.questStage
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Components
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.game.content.dialogue.region.lumbridge.DukeHoracioDialogue
import rs09.game.content.jobs.JobType
import rs09.game.content.quest.free.dragonslayer.DukeHoracioDSDialogue
import rs09.game.node.entity.player.link.diary.AreaDiaryTask
import rs09.game.node.entity.player.link.diary.DiaryEventHookBase
import rs09.game.node.entity.player.link.diary.DiaryLevel
import rs09.game.node.entity.skill.magic.TeleportMethod
import rs09.game.node.entity.skill.magic.spellconsts.Modern
class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) {
companion object {
private val DEAD_TREES = arrayOf(
Scenery.DEAD_TREE_1282,
Scenery.DEAD_TREE_1286,
Scenery.DEAD_TREE_1365
)
private val ZOMBIES = arrayOf(
NPCs.ZOMBIE_73,
NPCs.ZOMBIE_74
)
private val CASTLE_ROOF_AREA = ZoneBorders(3207, 3215, 3210, 3222, 3)
private val CASTLE_COURTYARD_AREA = ZoneBorders(3226, 3229, 3217, 3208)
private val COW_PEN_AREA_1 = ZoneBorders(3253, 3255, 3265, 3297)
private val COW_PEN_AREA_2 = ZoneBorders(3245, 3278, 3253, 3298)
private val WIZARDS_TOWER_TOP_FLOOR_AREA = ZoneBorders(3103, 3155, 3115, 3165, 2)
object BeginnerTasks {
const val CASTLE_CLIMB_TO_HIGHEST_POINT = 0
const val CASTLE_RAISE_FLAG_ON_ROOF = 1
const val CASTLE_SPEAK_TO_DUKE_HORACIO = 2
const val SPEAK_TO_DOOMSAYER = 3
const val AL_KHARID_PASS_THROUGH_GATE = 4
const val CHAMPIONS_GUILD_MINE_CLAY = 5
const val BARBARIAN_VILLAGE_MAKE_SOFT_CLAY = 6
const val BARBARIAN_VILLAGE_FIRE_A_POT = 7
const val DRAYNOR_ENTER_SPOOKY_MANSION_COURTYARD = 8
const val DRAYNOR_VISIT_MARKET = 9
const val DRAYNOR_TALK_TO_TOWNCRIER_ABOUT_RULES = 10
const val WIZARDS_TOWER_CLIMB_TO_TOP = 11
const val SWAMP_MINE_COPPER_ORE = 12
const val SWAMP_CATCH_SHRIMPS = 13
const val SWAMP_FISHING_TUTOR_GET_A_JOB = 14
const val BROWSE_FATHER_AERECK_GRAVES = 15
const val CHURCH_PLAY_ORGAN = 16
const val LUMBRIDGE_GUIDE_TALK_ABOUT_SOS = 17
const val BROWSE_GENERAL_STORE = 18
const val VISIT_FRED_THE_FARMER = 19
const val WINDMILL_MAKE_FLOUR = 20
}
object EasyTasks {
const val AL_KHARID_MINE_IRON = 0
const val COWFIELD_OBTAIN_COW_HIDE = 1
const val AL_KHARID_TAN_COW_HIDE = 2
const val CRAFT_LEATHER_GLOVES = 3
const val RIVER_CATCH_PIKE = 4
const val SMELT_STEEL_BAR = 5
const val SWAMP_SEARCH_SHED = 6
const val SWAMP_KILL_GIANT_RAT = 7
const val SWAMP_CUT_DEAD_TREE = 8
const val SWAMP_LIGHT_NORMAL_LOGS = 9
const val SWAMP_COOK_RAT_MEAT_ON_CAMPFIRE = 10
const val SWAMP_WATER_ALTAR_CRAFT_RUNE = 11
const val SWAMP_REPLACE_GHOSTSPEAK_AMULET = 12
const val WIZARDS_TOWER_TAUNT_DEMON = 13
const val WIZARDS_TOWER_TELEPORT_ESSENCE_MINE = 14
const val DRAYNOR_ACCESS_BANK = 15
const val DRAYNOR_WISEOLDMAN_CHECK_JUNK = 16
const val DRAYNOR_WISEOLDMAN_PEEK_TELESCOPE = 17
const val DRAYNOR_JAIL_SEWER_KILL_ZOMBIE = 18
}
object MediumTasks {
const val DRAYNOR_JAIL_SEWER_SMITH_STEEL_LONGSWORD = 0
const val RIDE_GNOMECOPTER = 1
const val CAST_LUMBRIDGE_TELEPORT = 2
const val CASTLE_LIGHT_WILLOW_LOGS = 3
const val CASTLE_COOK_LOBSTER_ON_RANGE = 4
const val CASTLE_OBTAIN_ANTIDRAGON_SHIELD = 5
const val RIVER_GATHER_WILLOW_LOGS = 6
const val SMELT_SILVER_BAR = 7
const val CRAFT_HOLY_SYMBOL = 8
const val RIVER_CATCH_SALMON = 9
const val AL_KHARID_MINE_SILVER = 10
const val SWAMP_MINE_COAL = 11
}
}
override val areaTasks
get() = arrayOf(
AreaDiaryTask(
CASTLE_ROOF_AREA,
DiaryLevel.BEGINNER,
BeginnerTasks.CASTLE_CLIMB_TO_HIGHEST_POINT
),
AreaDiaryTask(
WIZARDS_TOWER_TOP_FLOOR_AREA,
DiaryLevel.BEGINNER,
BeginnerTasks.WIZARDS_TOWER_CLIMB_TO_TOP
)
)
override fun onResourceProduced(player: Player, event: ResourceProducedEvent) {
when (player.viewport.region.id) {
12596 -> if (event.itemId == Items.CLAY_434) {
finishTask(
player,
DiaryLevel.BEGINNER,
BeginnerTasks.CHAMPIONS_GUILD_MINE_CLAY
)
}
12593, 12849 -> {
when (event.itemId) {
Items.RAW_SHRIMPS_317 -> {
finishTask(
player,
DiaryLevel.BEGINNER,
BeginnerTasks.SWAMP_CATCH_SHRIMPS
)
}
Items.COPPER_ORE_436 -> {
finishTask(
player,
DiaryLevel.BEGINNER,
BeginnerTasks.SWAMP_MINE_COPPER_ORE
)
}
Items.COAL_453 -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.SWAMP_MINE_COAL
)
}
Items.LOGS_1511 -> {
if (event.source.id in DEAD_TREES) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.SWAMP_CUT_DEAD_TREE
)
}
}
Items.COOKED_MEAT_2142 -> {
if (event.original == Items.RAW_RAT_MEAT_2134) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.SWAMP_COOK_RAT_MEAT_ON_CAMPFIRE
)
}
}
}
}
12850 -> when (event.itemId) {
Items.WILLOW_LOGS_1519 -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.RIVER_GATHER_WILLOW_LOGS
)
}
Items.RAW_PIKE_349 -> {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.RIVER_CATCH_PIKE
)
}
Items.RAW_SALMON_331 -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.RIVER_CATCH_SALMON
)
}
Items.LOBSTER_379 -> {
if (event.original == Items.RAW_LOBSTER_377
&& event.source.id == Scenery.COOKING_RANGE_114
) {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CASTLE_COOK_LOBSTER_ON_RANGE
)
}
}
Items.UNSTRUNG_SYMBOL_1714 -> {
if (event.original == Items.SILVER_BAR_2355
&& event.source.id == Scenery.FURNACE_36956
) {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CRAFT_HOLY_SYMBOL
)
}
}
}
13107 -> when (event.itemId) {
Items.IRON_ORE_440 -> {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.AL_KHARID_MINE_IRON
)
}
Items.SILVER_ORE_442 -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.AL_KHARID_MINE_SILVER
)
}
}
}
}
override fun onNpcKilled(player: Player, event: NPCKillEvent) {
when (player.viewport.region.id) {
12593, 12849 -> if (event.npc.id == NPCs.GIANT_RAT_86) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.SWAMP_KILL_GIANT_RAT
)
}
12438, 12439 -> if (event.npc.id in ZOMBIES) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.DRAYNOR_JAIL_SEWER_KILL_ZOMBIE
)
}
}
}
override fun onTeleported(player: Player, event: TeleportEvent) {
when (event.source) {
is NPC -> if (event.method == TeleportMethod.NPC && event.source.id == NPCs.SEDRIDOR_300) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.WIZARDS_TOWER_TELEPORT_ESSENCE_MINE
)
}
}
}
override fun onFireLit(player: Player, event: LitFireEvent) {
when (player.viewport.region.id) {
12593, 12849 -> if (event.logId == Items.LOGS_1511) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.SWAMP_LIGHT_NORMAL_LOGS
)
}
12850 -> if (event.logId == Items.WILLOW_LOGS_1519) {
if (inBorders(player, CASTLE_COURTYARD_AREA)) {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CASTLE_LIGHT_WILLOW_LOGS
)
}
}
}
}
override fun onInteracted(player: Player, event: InteractionEvent) {
when (player.viewport.region.id) {
12337 -> if (event.target.id == Scenery.RAILING_37668
&& event.option == "taunt-through"
) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.WIZARDS_TOWER_TAUNT_DEMON
)
}
}
}
override fun onAttributeRemoved(player: Player, event: AttributeRemoveEvent) {
when (event.attribute) {
"gc:flying" -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.RIDE_GNOMECOPTER
)
}
}
}
override fun onDialogueOpened(player: Player, event: DialogueOpenEvent) {
if (event.dialogue is DukeHoracioDialogue) {
finishTask(
player,
DiaryLevel.BEGINNER,
BeginnerTasks.CASTLE_SPEAK_TO_DUKE_HORACIO
)
}
}
override fun onDialogueOptionSelected(player: Player, event: DialogueOptionSelectionEvent) {
when (event.dialogue) {
is DukeHoracioDSDialogue -> {
val dragonSlayerStage = questStage(player, "Dragon Slayer")
if ((dragonSlayerStage == 100 && event.currentStage == 4)
|| event.currentStage == 12) {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CASTLE_OBTAIN_ANTIDRAGON_SHIELD
)
}
}
}
}
override fun onPickedUp(player: Player, event: PickUpEvent) {
when (player.viewport.region.id) {
12850, 12851 -> {
if (event.itemId == Items.COWHIDE_1739) {
if (inBorders(player, COW_PEN_AREA_1)
|| inBorders(player, COW_PEN_AREA_2)
) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.COWFIELD_OBTAIN_COW_HIDE
)
}
}
}
}
}
override fun onInterfaceOpened(player: Player, event: InterfaceOpenEvent) {
when (player.viewport.region.id) {
12338 -> if (event.component.id == Components.BANK_V2_MAIN_762) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.DRAYNOR_ACCESS_BANK
)
}
12850 -> if (event.component.id == Components.SHOP_TEMPLATE_620) {
finishTask(
player,
DiaryLevel.BEGINNER,
BeginnerTasks.BROWSE_GENERAL_STORE
)
}
}
}
override fun onSpellCast(player: Player, event: SpellCastEvent) {
when (event.spellId) {
Modern.LUMBRIDGE_TELEPORT -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CAST_LUMBRIDGE_TELEPORT
)
}
}
}
override fun onJobAssigned(player: Player, event: JobAssignmentEvent) {
when (player.viewport.region.id) {
12849 -> if (event.employerNpc.id == NPCs.FISHING_TUTOR_4901) {
finishTask(
player,
DiaryLevel.BEGINNER,
BeginnerTasks.SWAMP_FISHING_TUTOR_GET_A_JOB
)
}
}
}
}

View file

@ -0,0 +1,283 @@
package rs09.game.node.entity.player.link.diary.events
import api.*
import api.events.*
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.item.Item
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.game.interaction.inter.FairyRing
import rs09.game.interaction.item.withnpc.PoisonChaliceOnKingArthurDialogue
import rs09.game.node.entity.player.link.diary.DiaryEventHookBase
import rs09.game.node.entity.player.link.diary.DiaryLevel
class SeersVillageAchivementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) {
companion object {
private const val ATTRIBUTE_CUT_YEW_COUNT = "diary:seers:cut-yew"
private const val ATTRIBUTE_BASS_CAUGHT = "diary:seers:bass-caught"
private const val ATTRIBUTE_SHARK_CAUGHT_COUNT = "diary:seers:shark-caught"
private const val ATTRIBUTE_SHARK_COOKED_COUNT = "diary:seers:shark-cooked"
private const val ATTRIBUTE_ELEMENTAL_KILL_FLAGS = "diary:seers:elemental-kills"
private const val ATTRIBUTE_ARCHER_KILL_FLAGS = "diary:seers:archer-kills"
private const val ATTRIBUTE_COAL_TRUCK_FULL = "diary:seers:coal-truck-full"
private val SEERS_VILLAGE_AREA = ZoneBorders(2687, 3455, 2742, 3507)
private val SEERS_BANK_AREA = ZoneBorders(2721, 3490, 2730, 3493)
private val SEERS_COAL_TRUCKS_AREA = ZoneBorders(2690, 3502, 2699, 3508)
private val RANGING_GUILD_LOCATION = Location(2657, 3439)
private val COMBAT_BRACELETS = arrayOf(
Items.COMBAT_BRACELET_11126, Items.COMBAT_BRACELET4_11118,
Items.COMBAT_BRACELET3_11120, Items.COMBAT_BRACELET2_11122,
Items.COMBAT_BRACELET1_11124
)
private val RANGING_GUILD_ARCHERS = arrayOf(
NPCs.TOWER_ARCHER_688, NPCs.TOWER_ARCHER_689,
NPCs.TOWER_ARCHER_690, NPCs.TOWER_ARCHER_691
)
private val WORKSHOP_ELEMENTALS = arrayOf(
NPCs.FIRE_ELEMENTAL_1019, NPCs.EARTH_ELEMENTAL_1020,
NPCs.AIR_ELEMENTAL_1021, NPCs.WATER_ELEMENTAL_1022
)
object EasyTasks {
const val PICK_5_FLAX = 0
const val WALK_CLOCKWISE_AROUND_MYSTERIOUS_STATUE = 1
const val SIR_GALAHAD_MAKE_TEA = 2
const val TAKE_POISON_TO_KING_ARTHUR = 3
const val SPIN_5_BOW_STRINGS = 4
const val SINCLAIR_MANSION_FILL_5_POTS_WITH_FLOUR = 5
const val FORESTERS_ARMS_GIVE_5_LOCALS_GLASS_OF_CIDER = 6
const val PLANT_JUTE = 7
const val SINCLAIR_MANSION_USE_CHURN = 8
const val BUY_CANDLE = 9
const val PRAY_AT_ALTAR = 10
const val CATCH_MACKEREL = 11
}
object MediumTasks {
const val SINCLAIR_MANSION_USE_FREMENNIK_SHORTCUT = 0
const val THORMAC_SORCERER_TALK_ABOUT_MYSTIC_STAVES = 1
const val TRANSPORT_FULL_LOAD_OF_COAL = 2
const val FIND_HIGHEST_POINT = 3
const val DEFEAT_EACH_ELEMENTAL_TYPE = 4
const val TELEPORT_TO_CAMELOT = 5
const val RANGING_GUILD_KILL_EACH_TOWER_GUARD = 6
const val RANGING_GUILD_JUDGE_1000_ARCHERY_TICKETS = 7
const val RANGING_GUILD_BUY_SOMETHING_FOR_TICKETS = 8
const val USE_FAMILIAR_TO_LIGHT_MAPLE_LOGS = 9
const val HARRY_GET_PET_FISH = 10
const val CATHERBY_CATCH_AND_COOK_BASS = 11
}
object HardTasks {
const val RANGING_GUILD_TELEPORT = 0
const val CUT_5_YEW_LOGS = 1
const val FLETCH_MAGIC_SHORTBOW_INSIDE_BANK = 2
const val ENTER_SEERS_COURTHOUSE_WITH_PIETY = 3
const val DIAL_FAIRY_RING_MCGRUBORS_WOOD = 4
const val LIGHT_MAGIC_LOG = 5
const val HIGH_ALCH_MAGIC_SHORTBOW_INSIDE_BANK = 6
const val CATHERBY_CATCH_5_SHARKS = 7
const val CATHERBY_COOK_5_SHARKS_WITH_COOKING_GAUNTLETS = 8
const val CHARGE_5_WATER_ORBS_AT_ONCE = 9
const val GRAPPLE_FROM_WATER_OBELISK_TO_CATHERBY_SHORE = 10
}
}
override fun onResourceProduced(player: Player, event: ResourceProducedEvent) {
when (player.viewport.region.id) {
10806 -> if (event.itemId == Items.YEW_LOGS_1515) {
progressIncrementalTask(
player,
DiaryLevel.HARD,
HardTasks.CUT_5_YEW_LOGS,
ATTRIBUTE_CUT_YEW_COUNT,
5
)
}
11317 -> when (event.itemId) {
Items.RAW_MACKEREL_353 -> {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.CATCH_MACKEREL
)
}
Items.RAW_BASS_363 -> {
fulfillTaskRequirement(
player,
DiaryLevel.MEDIUM,
MediumTasks.CATHERBY_CATCH_AND_COOK_BASS,
ATTRIBUTE_BASS_CAUGHT
)
}
Items.BASS_365 -> {
whenTaskRequirementFulfilled(player, ATTRIBUTE_BASS_CAUGHT) {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CATHERBY_CATCH_AND_COOK_BASS
)
}
}
Items.RAW_SHARK_383 -> {
progressIncrementalTask(
player,
DiaryLevel.HARD,
HardTasks.CATHERBY_CATCH_5_SHARKS,
ATTRIBUTE_SHARK_CAUGHT_COUNT,
5
)
}
Items.SHARK_385 -> {
if (isEquipped(player, Items.COOKING_GAUNTLETS_775)) {
progressIncrementalTask(
player,
DiaryLevel.HARD,
HardTasks.CATHERBY_COOK_5_SHARKS_WITH_COOKING_GAUNTLETS,
ATTRIBUTE_SHARK_COOKED_COUNT,
5
)
}
}
}
}
}
override fun onNpcKilled(player: Player, event: NPCKillEvent) {
when (player.viewport.region.id) {
10906 -> if (event.npc.id in WORKSHOP_ELEMENTALS) {
progressFlaggedTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.DEFEAT_EACH_ELEMENTAL_TYPE,
ATTRIBUTE_ELEMENTAL_KILL_FLAGS,
1 shl (event.npc.id - NPCs.FIRE_ELEMENTAL_1019),
0xF
)
}
10549 -> if (event.npc.id in RANGING_GUILD_ARCHERS) {
progressFlaggedTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.RANGING_GUILD_KILL_EACH_TOWER_GUARD,
ATTRIBUTE_ARCHER_KILL_FLAGS,
/* Thanks for sequential NPC IDs, Jagex! */
1 shl (event.npc.id - NPCs.TOWER_ARCHER_688),
0xF
)
}
}
}
override fun onTeleported(player: Player, event: TeleportEvent) {
when (event.source) {
is Item -> if (event.source.id in COMBAT_BRACELETS) {
if (event.location == RANGING_GUILD_LOCATION) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.RANGING_GUILD_TELEPORT
)
}
}
}
}
override fun onFireLit(player: Player, event: LitFireEvent) {
when {
inBorders(player, SEERS_VILLAGE_AREA) -> {
if (event.logId == Items.MAGIC_LOGS_1513) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.LIGHT_MAGIC_LOG
)
}
}
}
}
override fun onInteracted(player: Player, event: InteractionEvent) {
when {
inBorders(player, SEERS_COAL_TRUCKS_AREA) -> {
whenTaskRequirementFulfilled(player, ATTRIBUTE_COAL_TRUCK_FULL) {
if (event.option == "remove-coal") {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.TRANSPORT_FULL_LOAD_OF_COAL
)
}
}
}
}
}
override fun onDialogueOptionSelected(player: Player, event: DialogueOptionSelectionEvent) {
when (event.dialogue) {
is PoisonChaliceOnKingArthurDialogue -> {
if (event.currentStage == 4) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.TAKE_POISON_TO_KING_ARTHUR
)
}
}
}
}
override fun onAttributeSet(player: Player, event: AttributeSetEvent) {
when (event.attribute) {
"/save:coal-truck-inventory" -> {
if (event.value !is Int) return
if (event.value >= 120) {
fulfillTaskRequirement(
player,
DiaryLevel.MEDIUM,
MediumTasks.TRANSPORT_FULL_LOAD_OF_COAL,
ATTRIBUTE_COAL_TRUCK_FULL
)
}
}
}
}
override fun onItemAlchemized(player: Player, event: ItemAlchemizationEvent) {
if (inBorders(player, SEERS_BANK_AREA)) {
if (event.itemId == Items.MAGIC_SHORTBOW_861 && event.isHigh) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.HIGH_ALCH_MAGIC_SHORTBOW_INSIDE_BANK
)
}
}
}
override fun onFairyRingDialed(player: Player, event: FairyRingDialEvent) {
if (event.fairyRing == FairyRing.ALS) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.DIAL_FAIRY_RING_MCGRUBORS_WOOD
)
}
}
}

View file

@ -0,0 +1,255 @@
package rs09.game.node.entity.player.link.diary.events
import api.events.*
import api.inBorders
import core.game.content.global.Bones
import core.game.content.global.travel.canoe.Canoe
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Components
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
import rs09.game.content.dialogue.region.varrock.ElsieDialogue
import rs09.game.interaction.inter.FairyRing
import rs09.game.node.entity.player.link.diary.AreaDiaryTask
import rs09.game.node.entity.player.link.diary.DiaryEventHookBase
import rs09.game.node.entity.player.link.diary.DiaryLevel
import rs09.game.node.entity.skill.magic.TeleportMethod
import rs09.game.node.entity.skill.magic.spellconsts.Modern
class VarrockAchivementDiary : DiaryEventHookBase(DiaryType.VARROCK) {
companion object {
private val VARROCK_ROOF_AREA = ZoneBorders(3201, 3467, 3225, 3497, 3)
private val VARROCK_PROVINCE_AREA = ZoneBorders(3077, 3380, 3290, 2509)
private val SOS_LEVEL_2_AREA = ZoneBorders(2040, 5241, 2046, 5246)
private val STRAY_DOGS = arrayOf(
NPCs.STRAY_DOG_4766, NPCs.STRAY_DOG_4767,
NPCs.STRAY_DOG_5917, NPCs.STRAY_DOG_5918
)
object EasyTasks {
const val THESSALIA_BROWSE_CLOTHES = 0
const val AUBURY_TELEPORT_ESSENCE_MINE = 1
const val MINE_IRON_SOUTHEAST = 2
const val MAKE_PLANK_SAWMILL = 3
const val VISIT_SOS_LEVEL2 = 4
const val JUMP_OVER_FENCE_SOUTH = 5
const val LUMBERYARD_CHOP_DYING_TREE = 6
const val BUY_VARROCK_HERALD = 7
const val GIVE_STRAY_DOG_A_BONE = 8
const val BARBARIAN_VILLAGE_SPIN_A_BOWL = 9
const val EDGEVILLE_ENTER_DUNGEON_SOUTH = 10
const val MOVE_POH_TO_VARROCK = 11
const val SPEAK_TO_HAIG_HALEN_50QP = 12
const val ENTER_EARTH_ALTAR = 13
const val ELSIE_TELL_A_STORY = 14
const val PATERDOMUS_MINE_LIMESTONE = 15
const val BARBARIAN_VILLAGE_CATCH_TROUT = 16
const val SEWERS_CUT_COBWEB = 17
const val FIND_HIGHEST_POINT = 18
}
object MediumTasks {
const val APOTHECARY_MAKE_STRENGTH_POTION = 0
const val CHAMPIONS_GUILD_VISIT = 1
const val TAKE_DAGONHAI_CHAOS_PORTAL_SHORTCUT = 2
const val RAT_POLE_FULL_RAT_COMPLEMENT = 3
const val SEWER_GATHER_RED_SPIDERS_EGGS = 4
const val USE_SPIRIT_TREE_NORTH = 5
const val PERFORM_ALL_SOS_EMOTES = 6
const val SELECT_KITTEN_COLOR = 7
const val USE_GE_UNDER_WALL_SHORTCUT = 8
const val ENTER_SOULBANE_RIFT = 9
const val DIGSITE_PENDANT_TELEPORT = 10
const val CRAFT_EARTH_TIARA = 11
const val PALACE_PICKPOCKET_GUARD = 12
const val CAST_VARROCK_TELEPORT_SPELL = 13
const val VANNAKA_GET_SLAYER_TASK = 14
const val SAWMILL_BUY_20_MAHOGANY_PLANKS = 15
const val PICK_FROM_WHITE_TREE = 16
const val HOTAIR_BALLOON_TRAVEL_SOMEWHERE = 17
const val GERTRUDE_GET_CAT_TRAINING_MEDAL = 18
const val DIAL_FAIRY_RING_WEST = 19
const val OZIACH_BROWSE_STORE = 20
}
object HardTasks {
const val PICK_POISON_IVY_FARMING_PATCH = 0
const val USE_MOSS_GIANT_PIPE_SHORTCUT = 1
const val FANCY_DRESS_SELLER_TRADE_FURS = 2
const val SMITH_ADAMANT_MED_HELM_SOUTHEAST = 3
const val SPEAK_TO_ORLANDO_SMITH_153_KUDOS = 4
const val GIVE_WEAKLAX_A_PIE = 5
const val CRAFT_AIR_BATTLESTAFF = 6
const val GIVE_POH_TROPICAL_WOOD_OR_FANCY_STONE_FINISH = 7
const val MAKE_VARROCK_TELEPORT_TABLET_OR_MAHOGANY_LECTERN = 8
const val OBTAIN_NEW_SET_OF_FAMILY_CREST_GAUNTLETS = 9
const val EDGEVILLE_MAKE_WAKA_CANOE = 10
const val EDGEVILLE_TELEPORT_USING_ANCIENT_MAGICKS = 11
const val BARBARIAN_VILLAGE_TELEPORT_USING_SKULL_SCEPTRE = 12
}
}
override val areaTasks get() = arrayOf(
AreaDiaryTask(
VARROCK_ROOF_AREA,
DiaryLevel.EASY,
EasyTasks.FIND_HIGHEST_POINT
),
AreaDiaryTask(
SOS_LEVEL_2_AREA,
DiaryLevel.EASY,
EasyTasks.VISIT_SOS_LEVEL2
)
)
override fun onResourceProduced(player: Player, event: ResourceProducedEvent) {
when (player.viewport.region.id) {
12341 -> if (event.itemId == Items.RAW_TROUT_335) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.BARBARIAN_VILLAGE_CATCH_TROUT
)
}
13108 -> if (event.itemId == Items.IRON_ORE_440) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.MINE_IRON_SOUTHEAST
)
}
13110 -> {
if (event.itemId == Items.LOGS_1511
&& event.source.id == Scenery.DYING_TREE_24168
) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.LUMBERYARD_CHOP_DYING_TREE
)
}
}
13366 -> if (event.itemId == Items.LIMESTONE_3211) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.PATERDOMUS_MINE_LIMESTONE
)
}
}
}
override fun onTeleported(player: Player, event: TeleportEvent) {
when (event.source) {
is NPC -> if (event.method == TeleportMethod.NPC && event.source.id == NPCs.AUBURY_553) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.AUBURY_TELEPORT_ESSENCE_MINE
)
}
}
}
override fun onInteracted(player: Player, event: InteractionEvent) {
when (player.viewport.region.id) {
12342 -> if (event.target.id == 26934) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.EDGEVILLE_ENTER_DUNGEON_SOUTH
)
}
}
}
override fun onButtonClicked(player: Player, event: ButtonClickEvent) {
/* This gets fired even on the login screen, and we don't have a region there, so... */
player.viewport.region?.let {
when (it.id) {
12342 -> {
if (event.iface == Components.CANOE_52
&& Canoe.getCanoeFromChild(event.buttonId) == Canoe.WAKA) {
finishTask(
player,
DiaryLevel.HARD,
HardTasks.EDGEVILLE_MAKE_WAKA_CANOE
)
}
}
}
}
}
override fun onDialogueOptionSelected(player: Player, event: DialogueOptionSelectionEvent) {
when (event.dialogue) {
is ElsieDialogue -> if (event.currentStage == 12) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.ELSIE_TELL_A_STORY
)
}
}
}
override fun onUsedWith(player: Player, event: UseWithEvent) {
when {
inBorders(player, VARROCK_PROVINCE_AREA) -> {
when (event.used) {
in Bones.array -> if (event.with in STRAY_DOGS) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.GIVE_STRAY_DOG_A_BONE
)
}
}
}
}
}
override fun onInterfaceOpened(player: Player, event: InterfaceOpenEvent) {
when (event.component.id) {
Components.THESSALIA_CLOTHES_MALE_591,
Components.THESSALIA_CLOTHES_FEMALE_594 -> {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.THESSALIA_BROWSE_CLOTHES
)
}
}
}
override fun onSpellCast(player: Player, event: SpellCastEvent) {
when (event.spellId) {
Modern.VARROCK_TELEPORT -> {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.CAST_VARROCK_TELEPORT_SPELL
)
}
}
}
override fun onFairyRingDialed(player: Player, event: FairyRingDialEvent) {
if (event.fairyRing == FairyRing.DKR) {
finishTask(
player,
DiaryLevel.MEDIUM,
MediumTasks.DIAL_FAIRY_RING_WEST
)
}
}
}

View file

@ -0,0 +1,110 @@
package rs09.game.node.entity.skill.crafting.silver
import api.*
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import org.rs09.consts.Components
import org.rs09.consts.Items
import org.rs09.consts.Scenery
import rs09.game.interaction.InteractionListener
import rs09.game.interaction.InterfaceListener
import core.game.node.scenery.Scenery as CoreScenery
/**
* Handles silver crafting interface interactions
* as well as silver -> furnace use-with interaction.
*
* @author vddCore
*/
class SilverCraftingListener : InterfaceListener, InteractionListener {
companion object {
private const val OP_MAKE_ONE = 155
private const val OP_MAKE_FIVE = 196
private const val OP_MAKE_ALL = 124
private const val OP_MAKE_X = 199
private val FURNACES = intArrayOf(
Scenery.FURNACE_2966, Scenery.FURNACE_3044, Scenery.FURNACE_3294, Scenery.FURNACE_4304,
Scenery.FURNACE_6189, Scenery.FURNACE_11009, Scenery.FURNACE_11010, Scenery.FURNACE_11666,
Scenery.FURNACE_12100, Scenery.FURNACE_12809, Scenery.FURNACE_18497, Scenery.FURNACE_18525,
Scenery.FURNACE_18526, Scenery.FURNACE_21879, Scenery.FURNACE_22721, Scenery.FURNACE_26814,
Scenery.FURNACE_28433, Scenery.FURNACE_28434, Scenery.FURNACE_30021, Scenery.FURNACE_30510,
Scenery.FURNACE_36956, Scenery.FURNACE_37651
)
private const val ATTRIBUTE_FURNACE_ID = "crafting:silver:furnace_id"
}
override fun defineInterfaceListeners() {
onOpen(Components.CRAFTING_SILVER_CASTING_438) { player, _ ->
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 17, Items.HOLY_SYMBOL_1718)
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 24, Items.UNHOLY_SYMBOL_1724)
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 31, Items.SILVER_SICKLE_2961)
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 38, Items.CONDUCTOR_4201)
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 45, Items.TIARA_5525)
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 53, Items.SILVTHRILL_ROD_7637)
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 60, Items.DEMONIC_SIGIL_6748)
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 67, Items.SILVER_BOLTS_UNF_9382)
sendItemOnInterface(player, Components.CRAFTING_SILVER_CASTING_438, 74, Items.SILVTHRIL_CHAIN_13154)
return@onOpen true
}
on(Components.CRAFTING_SILVER_CASTING_438) { player, _, opcode, buttonID, _, _ ->
val product = SilverProduct.forButtonID(buttonID) ?: return@on true
if (!inInventory(player, product.requiredItemId)) {
sendMessage(
player,
"You need a ${itemDefinition(product.requiredItemId).name.lowercase()} to make this item."
)
return@on true
}
if (product == SilverProduct.SILVTHRILL_ROD || product == SilverProduct.SILVTHRIL_CHAIN) {
sendMessage(player, "You can't do that yet.")
return@on true
}
if (!hasLevelDyn(player, Skills.CRAFTING, product.minimumLevel)) {
sendMessage(player, "You need a Crafting level of ${product.minimumLevel} to make this.")
return@on true
}
when (opcode) {
OP_MAKE_ONE -> make(player, product, 1)
OP_MAKE_FIVE -> make(player, product, 5)
OP_MAKE_ALL -> make(player, product, amountInInventory(player, Items.SILVER_BAR_2355))
OP_MAKE_X -> sendInputDialogue(player, InputType.AMOUNT, "Enter the amount:") { value ->
make(player, product, Integer.parseInt(value.toString()))
}
else -> return@on true
}
return@on true
}
}
override fun defineListeners() {
onUseWith(SCENERY, Items.SILVER_BAR_2355, *FURNACES) { player, _, with ->
setAttribute(player, ATTRIBUTE_FURNACE_ID, with)
openInterface(player, Components.CRAFTING_SILVER_CASTING_438)
return@onUseWith true
}
}
private fun make(player: Player, product: SilverProduct, amount: Int) {
closeInterface(player)
submitIndividualPulse(
player,
SilverCraftingPulse(
player,
product,
getAttribute(player, ATTRIBUTE_FURNACE_ID, CoreScenery(-1, -1, 0)),
amount
)
)
}
}

View file

@ -0,0 +1,51 @@
package rs09.game.node.entity.skill.crafting.silver
import api.*
import api.events.ResourceProducedEvent
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.node.scenery.Scenery
import core.game.system.task.Pulse
import org.rs09.consts.Animations
import org.rs09.consts.Items
/**
* Handles tick-based silver crafting logic.
*
* @author vddCore
*/
class SilverCraftingPulse(
private val player: Player,
private val product: SilverProduct,
private val furnace: Scenery,
private var amount: Int
) : Pulse() {
override fun pulse(): Boolean {
if (amount < 1) return true
if (!inInventory(player, product.requiredItemId) || !inInventory(player, Items.SILVER_BAR_2355)) {
return true
}
animate(player, Animations.HUMAN_FURNACE_SMELTING_3243)
if (removeItem(player, Items.SILVER_BAR_2355, Container.INVENTORY)) {
addItem(player, product.producedItemId, product.amountProduced)
rewardXP(player, Skills.CRAFTING, product.xpReward)
player.dispatch(
ResourceProducedEvent(
product.producedItemId,
product.amountProduced,
furnace,
Items.SILVER_BAR_2355
)
)
} else return true
amount--
delay = 5
return false
}
}

View file

@ -0,0 +1,55 @@
package rs09.game.node.entity.skill.crafting.silver
import org.rs09.consts.Items
private const val BUTTON_UNBLESSED = 16
private const val BUTTON_UNHOLY = 23
private const val BUTTON_SICKLE = 30
private const val BUTTON_TIARA = 44
private const val BUTTON_DEMONIC_SIGIL = 59
private const val BUTTON_SILVTHRIL_CHAIN = 73
private const val BUTTON_LIGHTNING_ROD = 37
private const val BUTTON_SILVTHRILL_ROD = 52
private const val BUTTON_CROSSBOW_BOLTS = 66
/**
* Provides silver crafting product definitions.
*
* @author vddCore
*/
enum class SilverProduct(
val buttonId: Int,
val requiredItemId: Int,
val producedItemId: Int,
val amountProduced: Int,
val minimumLevel: Int,
val xpReward: Double,
val strungId: Int
) {
HOLY(BUTTON_UNBLESSED, Items.HOLY_MOULD_1599, Items.UNSTRUNG_SYMBOL_1714, 1, 16, 50.0, Items.UNBLESSED_SYMBOL_1716),
UNHOLY(BUTTON_UNHOLY, Items.UNHOLY_MOULD_1594, Items.UNSTRUNG_EMBLEM_1720, 1, 17, 50.0, Items.UNHOLY_SYMBOL_1724),
SICKLE(BUTTON_SICKLE, Items.SICKLE_MOULD_2976, Items.SILVER_SICKLE_2961, 1, 18, 50.0, -1),
TIARA(BUTTON_TIARA, Items.TIARA_MOULD_5523, Items.TIARA_5525, 1, 23, 52.5, -1),
SILVTHRIL_CHAIN(BUTTON_SILVTHRIL_CHAIN, Items.CHAIN_LINK_MOULD_13153, Items.SILVTHRIL_CHAIN_13154, 1, 47, 100.0, -1),
LIGHTNING_ROD(BUTTON_LIGHTNING_ROD, Items.CONDUCTOR_MOULD_4200, Items.CONDUCTOR_4201, 1, 20, 50.0, -1),
SILVTHRILL_ROD(BUTTON_SILVTHRILL_ROD, Items.ROD_CLAY_MOULD_7649, Items.SILVTHRILL_ROD_7637, 1, 25, 55.0, -1),
CROSSBOW_BOLTS(BUTTON_CROSSBOW_BOLTS, Items.BOLT_MOULD_9434, Items.SILVER_BOLTS_UNF_9382, 10, 21, 50.0, -1);
companion object {
private val BUTTON_MAP = HashMap<Int, SilverProduct>()
private val PRODUCT_MAP = HashMap<Int, SilverProduct>()
init {
for (product in SilverProduct.values()) {
BUTTON_MAP[product.buttonId] = product
}
for (product in SilverProduct.values()) {
PRODUCT_MAP[product.producedItemId] = product
}
}
fun forButtonID(buttonId: Int): SilverProduct? = BUTTON_MAP[buttonId]
fun forProductID(productId: Int): SilverProduct? = PRODUCT_MAP[productId]
}
}

View file

@ -0,0 +1,36 @@
package rs09.game.node.entity.skill.crafting.silver
import api.addItem
import api.removeItem
import core.game.node.Node
import core.game.node.entity.player.Player
import org.rs09.consts.Items
import rs09.game.interaction.InteractionListener
/**
* Handles ball of wool <-> stringable silver items interaction.
*
* @author vddCore
*/
class SilverStringingListener : InteractionListener {
companion object {
private val STRINGABLE_PRODUCTS = intArrayOf(
Items.UNSTRUNG_SYMBOL_1714,
Items.UNSTRUNG_EMBLEM_1720
)
}
private fun stringSilverProduct(player: Player, used: Node, with: Node): Boolean {
SilverProduct.forProductID(with.id)?.let {
if (removeItem(player, with.id) && removeItem(player, used.id)) {
addItem(player, it.strungId)
}
}
return true
}
override fun defineListeners() {
onUseWith(ITEM, Items.BALL_OF_WOOL_1759, *STRINGABLE_PRODUCTS, handler = ::stringSilverProduct)
}
}

View file

@ -1,5 +1,7 @@
package rs09.game.node.entity.skill.magic
import api.events.ItemAlchemizationEvent
import api.events.TeleportEvent
import api.getAttribute
import core.game.content.activity.mta.impl.GraveyardZone
import core.game.content.global.Bones
@ -15,7 +17,6 @@ import core.game.node.entity.skill.smithing.smelting.Bar
import core.game.node.entity.skill.smithing.smelting.SmeltingPulse
import core.game.node.item.Item
import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders
import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics
import org.rs09.consts.Items
@ -65,7 +66,6 @@ class ModernListeners : SpellListener("modern"){
onCast(Modern.VARROCK_TELEPORT,NONE){player, _->
requires(player,25, arrayOf(Item(Items.FIRE_RUNE_554),Item(Items.AIR_RUNE_556,3),Item(Items.LAW_RUNE_563)))
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK,1, 13)
val alternateTeleport = getAttribute(player, "diaries:varrock:alttele", false)
val dest = if(alternateTeleport) Location.create(3165, 3472, 0) else Location.create(3213, 3424, 0)
sendTeleport(player,35.0, dest)
@ -73,7 +73,6 @@ class ModernListeners : SpellListener("modern"){
onCast(Modern.LUMBRIDGE_TELEPORT,NONE){player,_ ->
requires(player,31, arrayOf(Item(Items.EARTH_RUNE_557),Item(Items.AIR_RUNE_556,3),Item(Items.LAW_RUNE_563)))
player.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 2, 2)
sendTeleport(player,41.0,Location.create(3221, 3219, 0))
}
@ -240,9 +239,7 @@ class ModernListeners : SpellListener("modern"){
if(coins.amount > 0)
player.inventory.add(coins)
if((item.id == Items.MAGIC_SHORTBOW_861 || item.id == Items.MAGIC_LONGBOW_859) && high && ZoneBorders(2721,3493,2730,3487).insideBorder(player)){
player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 2, 6);
}
player.dispatch(ItemAlchemizationEvent(item.id, high))
addXP(player,if(high) 65.0 else 31.0)
showMagicTab(player)
@ -256,7 +253,12 @@ class ModernListeners : SpellListener("modern"){
player.sendMessage("A magical force prevents you from teleporting.")
return
}
if(player.teleporter.send(location,TeleportManager.TeleportType.NORMAL)) {
val teleType = TeleportManager.TeleportType.NORMAL
if (player.teleporter.send(location, teleType)) {
player.dispatch(TeleportEvent(teleType, TeleportMethod.SPELL, -1, location))
removeRunes(player)
addXP(player, xp)
setDelay(player, true)
@ -275,7 +277,9 @@ class ModernListeners : SpellListener("modern"){
return
}
player.teleporter.send(loc,TeleportManager.TeleportType.NORMAL)
val teleType = TeleportManager.TeleportType.NORMAL
player.teleporter.send(loc, teleType)
removeRunes(player)
addXP(player,30.0)
setDelay(player,true)

View file

@ -0,0 +1,7 @@
package rs09.game.node.entity.skill.magic
enum class TeleportMethod {
JEWELRY,
SPELL,
NPC
}