Some conversions + destination override support for option listeners
This commit is contained in:
@@ -13,6 +13,7 @@ import core.game.world.map.path.Pathfinder;
|
|||||||
import core.net.packet.PacketRepository;
|
import core.net.packet.PacketRepository;
|
||||||
import core.net.packet.context.PlayerContext;
|
import core.net.packet.context.PlayerContext;
|
||||||
import core.net.packet.out.ClearMinimapFlag;
|
import core.net.packet.out.ClearMinimapFlag;
|
||||||
|
import kotlin.jvm.functions.Function1;
|
||||||
|
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
|
|
||||||
@@ -73,6 +74,8 @@ public abstract class MovementPulse extends Pulse {
|
|||||||
*/
|
*/
|
||||||
private boolean near;
|
private boolean near;
|
||||||
|
|
||||||
|
private Function1<Node,Location> overrideMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new {@code MovementPulse} {@code Object}.
|
* Constructs a new {@code MovementPulse} {@code Object}.
|
||||||
*
|
*
|
||||||
@@ -141,6 +144,12 @@ public abstract class MovementPulse extends Pulse {
|
|||||||
this.destinationFlag = destinationFlag;
|
this.destinationFlag = destinationFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MovementPulse(Entity mover, Node destination, DestinationFlag destinationFlag, Function1<Node,Location> method){
|
||||||
|
this(mover,destination,null,false);
|
||||||
|
this.destinationFlag = destinationFlag;
|
||||||
|
this.overrideMethod = method;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new {@code MovementPulse} {@code Object}.
|
* Constructs a new {@code MovementPulse} {@code Object}.
|
||||||
*
|
*
|
||||||
@@ -221,9 +230,13 @@ public abstract class MovementPulse extends Pulse {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Location loc = null;
|
Location loc = null;
|
||||||
if (destinationFlag != null) {
|
if (destinationFlag != null && overrideMethod == null) {
|
||||||
loc = destinationFlag.getDestination(mover, destination);
|
loc = destinationFlag.getDestination(mover, destination);
|
||||||
}
|
}
|
||||||
|
if(overrideMethod != null){
|
||||||
|
loc = overrideMethod.invoke(destination);
|
||||||
|
if(loc == destination.getLocation()) loc = destinationFlag.getDestination(mover,destination);
|
||||||
|
}
|
||||||
if (loc == null && optionHandler != null) {
|
if (loc == null && optionHandler != null) {
|
||||||
loc = optionHandler.getDestination(mover, destination);
|
loc = optionHandler.getDestination(mover, destination);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
package core.game.interaction.npc;
|
|
||||||
|
|
||||||
import core.cache.def.impl.NPCDefinition;
|
|
||||||
import core.game.content.dialogue.FacialExpression;
|
|
||||||
import core.game.interaction.OptionHandler;
|
|
||||||
import core.game.node.Node;
|
|
||||||
import core.game.node.entity.npc.NPC;
|
|
||||||
import core.game.node.entity.player.Player;
|
|
||||||
import core.game.node.item.Item;
|
|
||||||
import core.game.world.map.Location;
|
|
||||||
import core.plugin.Initializable;
|
|
||||||
import core.plugin.Plugin;
|
|
||||||
import rs09.game.content.activity.gnomecooking.GnomeCookingJob;
|
|
||||||
import rs09.game.content.activity.gnomecooking.GnomeTipper;
|
|
||||||
|
|
||||||
import static rs09.game.content.activity.gnomecooking.GnomeCookingConstantsKt.*;
|
|
||||||
import static rs09.tools.stringtools.StringToolsKt.colorize;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the NPC talk-to option.
|
|
||||||
* @author Emperor
|
|
||||||
*/
|
|
||||||
@Initializable
|
|
||||||
public final class NPCTalkPlugin extends OptionHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Location getDestination(Node n, Node node) {
|
|
||||||
NPC npc = (NPC) node;
|
|
||||||
if (npc.getAttribute("facing_booth", false)) {
|
|
||||||
int offsetX = npc.getDirection().getStepX() << 1;
|
|
||||||
int offsetY = npc.getDirection().getStepY() << 1;
|
|
||||||
return npc.getLocation().transform(offsetX, offsetY, 0);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean handle(Player player, Node node, String option) {
|
|
||||||
final NPC npc = (NPC) node;
|
|
||||||
if (!npc.getAttribute("facing_booth", false)) {
|
|
||||||
npc.faceLocation(player.getLocation());
|
|
||||||
}
|
|
||||||
//I'm sorry for this but it was honestly the best way to do this
|
|
||||||
if(player.getAttribute(GC_BASE_ATTRIBUTE +":"+ GC_JOB_ORDINAL,-1) != -1){
|
|
||||||
GnomeCookingJob job = GnomeCookingJob.values()[player.getAttribute(GC_BASE_ATTRIBUTE + ":" + GC_JOB_ORDINAL,-1)];
|
|
||||||
if(node.getId() == job.getNpc_id() && !player.getAttribute(GC_BASE_ATTRIBUTE + ":" + GC_JOB_COMPLETE,false)){
|
|
||||||
Item neededItem = player.getAttribute(GC_BASE_ATTRIBUTE + ":" + GC_NEEDED_ITEM,null);
|
|
||||||
if(neededItem != null && player.getInventory().containsItem(neededItem)) {
|
|
||||||
player.getDialogueInterpreter().sendDialogues(job.getNpc_id(), FacialExpression.OLD_HAPPY, "Thank you!");
|
|
||||||
player.getInventory().remove(neededItem);
|
|
||||||
player.getInventory().add(GnomeTipper.getTip(job.getLevel()));
|
|
||||||
player.removeAttribute(GC_BASE_ATTRIBUTE + ":" + GC_JOB_ORDINAL);
|
|
||||||
player.removeAttribute(GC_BASE_ATTRIBUTE + ":" + GC_NEEDED_ITEM);
|
|
||||||
int curPoints = player.getAttribute(GC_BASE_ATTRIBUTE + ":" + GC_POINTS,0);
|
|
||||||
curPoints += 3;
|
|
||||||
if(curPoints == 12){
|
|
||||||
player.getInventory().add(new Item(9474));
|
|
||||||
player.sendMessage(colorize("%RYou have been granted a food delivery token. Use it to have food delivered."));
|
|
||||||
} else if(curPoints % 12 == 0){
|
|
||||||
int curRedeems = player.getAttribute(GC_BASE_ATTRIBUTE + ":" + GC_REDEEMABLE_FOOD,0);
|
|
||||||
player.setAttribute("/save:" + GC_BASE_ATTRIBUTE + ":" + GC_REDEEMABLE_FOOD,curRedeems != 10 ? ++curRedeems : curRedeems);
|
|
||||||
player.sendMessage(colorize("%RYou have been granted a single food delivery charge."));
|
|
||||||
}
|
|
||||||
player.setAttribute("/save:" + GC_BASE_ATTRIBUTE + ":" + GC_POINTS,curPoints);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return player.getDialogueInterpreter().open(npc.getId(), npc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
|
||||||
NPCDefinition.setOptionHandler("talk-to", this);
|
|
||||||
NPCDefinition.setOptionHandler("talk", this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package rs09.game.content.activity.gnomecooking
|
||||||
|
|
||||||
|
import core.game.content.dialogue.FacialExpression
|
||||||
|
import core.game.node.item.Item
|
||||||
|
import rs09.game.content.activity.gnomecooking.GnomeTipper.getTip
|
||||||
|
import rs09.game.content.dialogue.DialogueFile
|
||||||
|
import rs09.tools.END_DIALOGUE
|
||||||
|
import rs09.tools.stringtools.colorize
|
||||||
|
|
||||||
|
class GCCompletionDialogue(val job: GnomeCookingJob) : DialogueFile() {
|
||||||
|
override fun handle(componentID: Int, buttonID: Int) {
|
||||||
|
when(stage){
|
||||||
|
0 -> {
|
||||||
|
val neededItem = player!!.getAttribute<Item>("$GC_BASE_ATTRIBUTE:$GC_NEEDED_ITEM", null)
|
||||||
|
if (neededItem != null && player!!.inventory.containsItem(neededItem)) {
|
||||||
|
player!!.dialogueInterpreter.sendDialogues(job.npc_id, FacialExpression.OLD_HAPPY, "Thank you!")
|
||||||
|
player!!.inventory.remove(neededItem)
|
||||||
|
player!!.inventory.add(getTip(job.level))
|
||||||
|
player!!.removeAttribute("$GC_BASE_ATTRIBUTE:$GC_JOB_ORDINAL")
|
||||||
|
player!!.removeAttribute("$GC_BASE_ATTRIBUTE:$GC_NEEDED_ITEM")
|
||||||
|
var curPoints = player!!.getAttribute("$GC_BASE_ATTRIBUTE:$GC_POINTS", 0)
|
||||||
|
curPoints += 3
|
||||||
|
if (curPoints == 12) {
|
||||||
|
player!!.inventory.add(Item(9474))
|
||||||
|
player!!.sendMessage(colorize("%RYou have been granted a food delivery token. Use it to have food delivered."))
|
||||||
|
} else if (curPoints % 12 == 0) {
|
||||||
|
var curRedeems = player!!.getAttribute("$GC_BASE_ATTRIBUTE:$GC_REDEEMABLE_FOOD", 0)
|
||||||
|
player!!.setAttribute(
|
||||||
|
"/save:$GC_BASE_ATTRIBUTE:$GC_REDEEMABLE_FOOD",
|
||||||
|
if (curRedeems != 10) ++curRedeems else curRedeems
|
||||||
|
)
|
||||||
|
player!!.sendMessage(colorize("%RYou have been granted a single food delivery charge."))
|
||||||
|
}
|
||||||
|
player!!.setAttribute("/save:$GC_BASE_ATTRIBUTE:$GC_POINTS", curPoints)
|
||||||
|
} else {
|
||||||
|
player!!.dialogueInterpreter.sendDialogues(job.npc_id, FacialExpression.ANGRY, "Where's my food?!")
|
||||||
|
}
|
||||||
|
stage = END_DIALOGUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package rs09.game.interaction
|
|||||||
|
|
||||||
import core.game.node.Node
|
import core.game.node.Node
|
||||||
import core.game.node.entity.player.Player
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.world.map.Location
|
||||||
|
|
||||||
abstract class InteractionListener : Listener{
|
abstract class InteractionListener : Listener{
|
||||||
val ITEM = 0
|
val ITEM = 0
|
||||||
@@ -25,4 +26,13 @@ abstract class InteractionListener : Listener{
|
|||||||
fun onUseWith(type: Int, used: IntArray, vararg with: Int, handler: (Player, Node, Node) -> Boolean){
|
fun onUseWith(type: Int, used: IntArray, vararg with: Int, handler: (Player, Node, Node) -> Boolean){
|
||||||
Listeners.add(type,used,with,handler)
|
Listeners.add(type,used,with,handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun defineDestinationOverrides(){}
|
||||||
|
|
||||||
|
fun setDest(type: Int, id: Int,handler: (Node) -> Location){
|
||||||
|
Listeners.addDestOverride(type,id,handler)
|
||||||
|
}
|
||||||
|
fun setDest(type:Int, vararg options: String, handler: (Node) -> Location){
|
||||||
|
Listeners.addDestOverrides(type,options,handler)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,10 +4,12 @@ import core.game.interaction.DestinationFlag
|
|||||||
import core.game.interaction.MovementPulse
|
import core.game.interaction.MovementPulse
|
||||||
import core.game.node.Node
|
import core.game.node.Node
|
||||||
import core.game.node.entity.player.Player
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.world.map.Location
|
||||||
|
|
||||||
object Listeners {
|
object Listeners {
|
||||||
private val listeners = HashMap<String,(Player, Node) -> Boolean>(1000)
|
private val listeners = HashMap<String,(Player, Node) -> Boolean>(1000)
|
||||||
private val useWithListeners = HashMap<String,(Player,Node,Node) -> Boolean>(1000)
|
private val useWithListeners = HashMap<String,(Player,Node,Node) -> Boolean>(1000)
|
||||||
|
private val destinationOverrides = HashMap<String,(Node) -> Location>(100)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun add(id: Int, type: Int, option: Array<out String>, method: (Player,Node) -> Boolean){
|
fun add(id: Int, type: Int, option: Array<out String>, method: (Player,Node) -> Boolean){
|
||||||
@@ -64,6 +66,28 @@ object Listeners {
|
|||||||
return listeners["$type:${option.toLowerCase()}"]
|
return listeners["$type:${option.toLowerCase()}"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun addDestOverride(type: Int, id: Int, method: (Node) -> Location){
|
||||||
|
destinationOverrides["$type:$id"] = method
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun addDestOverrides(type: Int,options: Array<out String>, method: (Node) -> Location){
|
||||||
|
for(opt in options){
|
||||||
|
destinationOverrides["$type:${opt.toLowerCase()}"] = method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getOverride(type: Int,id: Int): ((Node) -> Location)?{
|
||||||
|
return destinationOverrides["$type:$id"]
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getOverride(type: Int,option: String): ((Node) -> Location)?{
|
||||||
|
return destinationOverrides["$type:$option"]
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun run(used: Node, with: Node, type: Int,player: Player): Boolean{
|
fun run(used: Node, with: Node, type: Int,player: Player): Boolean{
|
||||||
val flag = when(type){
|
val flag = when(type){
|
||||||
@@ -72,11 +96,14 @@ object Listeners {
|
|||||||
else -> DestinationFlag.OBJECT
|
else -> DestinationFlag.OBJECT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(player.locks.isInteractionLocked) return false
|
||||||
|
|
||||||
var flipped = false
|
var flipped = false
|
||||||
|
|
||||||
val method = get(used.id,with.id,type) ?: get(with.id,used.id,type).also { flipped = true } ?: return false
|
val method = get(used.id,with.id,type) ?: get(with.id,used.id,type).also { flipped = true } ?: return false
|
||||||
|
|
||||||
if(type != 0) {
|
if(type != 0) {
|
||||||
|
if(player.locks.isMovementLocked) return false
|
||||||
player.pulseManager.run(object : MovementPulse(player, with, flag) {
|
player.pulseManager.run(object : MovementPulse(player, with, flag) {
|
||||||
override fun pulse(): Boolean {
|
override fun pulse(): Boolean {
|
||||||
player.faceLocation(with.location)
|
player.faceLocation(with.location)
|
||||||
@@ -100,10 +127,14 @@ object Listeners {
|
|||||||
else -> DestinationFlag.OBJECT
|
else -> DestinationFlag.OBJECT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(player.locks.isInteractionLocked) return false
|
||||||
|
|
||||||
val method = get(id,type,option) ?: get(option,type) ?: return false
|
val method = get(id,type,option) ?: get(option,type) ?: return false
|
||||||
|
val destOverride = getOverride(type,node.id) ?: getOverride(type,option.toLowerCase())
|
||||||
|
|
||||||
if(type != 0) {
|
if(type != 0) {
|
||||||
player.pulseManager.run(object : MovementPulse(player, node, flag) {
|
if(player.locks.isMovementLocked) return false
|
||||||
|
player.pulseManager.run(object : MovementPulse(player, node, flag, destOverride) {
|
||||||
override fun pulse(): Boolean {
|
override fun pulse(): Boolean {
|
||||||
player.faceLocation(node.location)
|
player.faceLocation(node.location)
|
||||||
method.invoke(player,node)
|
method.invoke(player,node)
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package rs09.game.interaction.npc
|
||||||
|
|
||||||
|
import core.game.node.entity.npc.NPC
|
||||||
|
import rs09.game.content.activity.gnomecooking.*
|
||||||
|
import rs09.game.interaction.InteractionListener
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the NPC talk-to option.
|
||||||
|
* @author Ceikry
|
||||||
|
*/
|
||||||
|
class NPCTalkListener : InteractionListener() {
|
||||||
|
|
||||||
|
override fun defineListeners() {
|
||||||
|
|
||||||
|
on(NPC,"talk-to","talk"){player,node ->
|
||||||
|
val npc = node.asNpc()
|
||||||
|
if (!npc.getAttribute("facing_booth", false)) {
|
||||||
|
npc.faceLocation(player.location)
|
||||||
|
}
|
||||||
|
//I'm sorry for this but it was honestly the best way to do this
|
||||||
|
if (player.getAttribute(GC_BASE_ATTRIBUTE + ":" + GC_JOB_ORDINAL, -1) != -1) {
|
||||||
|
val job = GnomeCookingJob.values()[player.getAttribute(GC_BASE_ATTRIBUTE + ":" + GC_JOB_ORDINAL, -1)]
|
||||||
|
if (node.getId() == job.npc_id && !player.getAttribute(GC_BASE_ATTRIBUTE + ":" + GC_JOB_COMPLETE, false)) {
|
||||||
|
player.dialogueInterpreter.open(GCCompletionDialogue(job))
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return@on player.dialogueInterpreter.open(npc.id, npc)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun defineDestinationOverrides() {
|
||||||
|
setDest(NPC,"talk","talk-to"){node ->
|
||||||
|
val npc = node as NPC
|
||||||
|
if (npc.getAttribute("facing_booth", false)) {
|
||||||
|
val offsetX = npc.direction.stepX shl 1
|
||||||
|
val offsetY = npc.direction.stepY shl 1
|
||||||
|
return@setDest npc.location.transform(offsetX, offsetY, 0)
|
||||||
|
}
|
||||||
|
return@setDest node.location
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,7 +73,9 @@ object PluginManager {
|
|||||||
} catch (e: Exception) {e.printStackTrace()}
|
} catch (e: Exception) {e.printStackTrace()}
|
||||||
}
|
}
|
||||||
result.getSubclasses("rs09.game.interaction.InteractionListener").forEach {
|
result.getSubclasses("rs09.game.interaction.InteractionListener").forEach {
|
||||||
(it.loadClass().newInstance() as InteractionListener).defineListeners()
|
val clazz = it.loadClass().newInstance() as InteractionListener
|
||||||
|
clazz.defineListeners()
|
||||||
|
clazz.defineDestinationOverrides()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user