Implemented the proper interaction for low-alchemy option on the Explorer's Ring
Implemented a generic item selection ContentAPI method Added ContentAPI method for running CS2 scripts Added development command for running CS2 scripts
This commit is contained in:
+2
-2
@@ -696,9 +696,9 @@ style:
|
|||||||
UseOrEmpty:
|
UseOrEmpty:
|
||||||
active: true
|
active: true
|
||||||
UseRequire:
|
UseRequire:
|
||||||
active: true
|
active: false
|
||||||
UseRequireNotNull:
|
UseRequireNotNull:
|
||||||
active: true
|
active: false
|
||||||
UselessCallOnNotNull:
|
UselessCallOnNotNull:
|
||||||
active: true
|
active: true
|
||||||
UtilityClassWithPublicConstructor:
|
UtilityClassWithPublicConstructor:
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package content.global.handlers.iface
|
||||||
|
|
||||||
|
import core.api.*
|
||||||
|
import core.tools.*
|
||||||
|
import core.game.interaction.*
|
||||||
|
import core.game.system.task.Pulse
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
|
||||||
|
class GenericItemSelect : InterfaceListener {
|
||||||
|
val GENERIC_ITEM_SELECT_IFACE = 12
|
||||||
|
|
||||||
|
override fun defineInterfaceListeners() {
|
||||||
|
onOpen(GENERIC_ITEM_SELECT_IFACE) {player, _ ->
|
||||||
|
player.pulseManager.run(object : Pulse() {
|
||||||
|
override fun pulse() : Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
override fun stop() {
|
||||||
|
super.stop()
|
||||||
|
player.interfaceManager.closeSingleTab()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return@onOpen true
|
||||||
|
}
|
||||||
|
|
||||||
|
on(GENERIC_ITEM_SELECT_IFACE){player, _, opcode, buttonID, slot, _ ->
|
||||||
|
processResponse(player, opcode, slot)
|
||||||
|
return@on true
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose(GENERIC_ITEM_SELECT_IFACE) {player, _ ->
|
||||||
|
removeAttribute(player, "itemselect-callback")
|
||||||
|
return@onClose true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processResponse (player: Player, opcode: Int, slot: Int) {
|
||||||
|
val callback = getAttribute<((Int, Int) -> Unit)?>(player, "itemselect-callback", null)
|
||||||
|
if (callback == null) {
|
||||||
|
log (this::class.java, Log.WARN, "${player.name} is trying to use an item select prompt with no callback!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val optionIndex = when (opcode) {
|
||||||
|
155 -> 0
|
||||||
|
196 -> 1
|
||||||
|
124 -> 2
|
||||||
|
199 -> 3
|
||||||
|
234 -> 4
|
||||||
|
9 -> 10
|
||||||
|
else -> -1
|
||||||
|
}
|
||||||
|
if (optionIndex == -1) {
|
||||||
|
log (this::class.java, Log.WARN, "${player.name} is clicking a right-click index that we don't know the opcode for yet, lol. Here's the opcode: $opcode")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.invoke(slot, optionIndex)
|
||||||
|
removeAttribute (player, "itemselect-callback")
|
||||||
|
player.interfaceManager.closeSingleTab()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
package content.global.handlers.item
|
package content.global.handlers.item
|
||||||
|
|
||||||
import core.api.hasLevelStat
|
import core.api.*
|
||||||
import core.api.sendMessage
|
|
||||||
import core.api.teleport
|
|
||||||
import core.api.visualize
|
|
||||||
import core.game.node.entity.player.Player
|
import core.game.node.entity.player.Player
|
||||||
import core.game.node.entity.player.link.TeleportManager.TeleportType
|
import core.game.node.entity.player.link.TeleportManager.TeleportType
|
||||||
import core.game.node.entity.skill.Skills
|
import core.game.node.entity.skill.Skills
|
||||||
@@ -15,12 +12,8 @@ import core.ServerStore.Companion.getBoolean
|
|||||||
import core.ServerStore.Companion.getInt
|
import core.ServerStore.Companion.getInt
|
||||||
import core.game.interaction.IntType
|
import core.game.interaction.IntType
|
||||||
import core.game.interaction.InteractionListener
|
import core.game.interaction.InteractionListener
|
||||||
|
import content.global.skill.magic.modern.ModernListeners
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the explorers ring.
|
|
||||||
*
|
|
||||||
* @author Vexia
|
|
||||||
*/
|
|
||||||
class ExplorersRingPlugin : InteractionListener {
|
class ExplorersRingPlugin : InteractionListener {
|
||||||
|
|
||||||
val RINGS = intArrayOf(Items.EXPLORERS_RING_1_13560, Items.EXPLORERS_RING_2_13561, Items.EXPLORERS_RING_3_13562)
|
val RINGS = intArrayOf(Items.EXPLORERS_RING_1_13560, Items.EXPLORERS_RING_2_13561, Items.EXPLORERS_RING_3_13562)
|
||||||
@@ -44,19 +37,30 @@ class ExplorersRingPlugin : InteractionListener {
|
|||||||
return@on true
|
return@on true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Sources Used
|
||||||
|
// - https://www.youtube.com/watch?v=PEA0fkRK0-A&t=64s&pp=ygUcMjAwOSBydW5lc2NhcGUgZXhwbG9yZXIgcmluZw%3D%3D
|
||||||
|
// - https://runescape.wiki/w/Explorer%27s_ring?oldid=899927
|
||||||
on(RINGS, IntType.ITEM, "low-alchemy"){ player, _ ->
|
on(RINGS, IntType.ITEM, "low-alchemy"){ player, _ ->
|
||||||
if (!hasLevelStat(player, Skills.MAGIC, 21)) {
|
if (!hasLevelStat(player, Skills.MAGIC, 21)) {
|
||||||
sendMessage(player,"You need a Magic level of 21 in order to do that.")
|
sendMessage(player,"You need a Magic level of 21 in order to do that.")
|
||||||
return@on true
|
return@on true
|
||||||
}
|
}
|
||||||
if(getStoreFile().getBoolean(player.username.toLowerCase() + ":alchs")){
|
val remaining = getStoreFile().getInt(player.username.lowercase() + ":alchs", 30)
|
||||||
sendMessage(player, "You have claimed all the charges you can for one day.")
|
if (remaining <= 0) {
|
||||||
|
sendMessage(player, "You have used up all of your charges for the day.")
|
||||||
return@on true
|
return@on true
|
||||||
}
|
}
|
||||||
sendMessage(player,"You grant yourself with 30 free low alchemy charges.") // todo this implementation is not correct, see https://www.youtube.com/watch?v=UbUIF2Kw_Dw
|
sendDialogue(player, "Choose the item you wish to convert to coins.")
|
||||||
|
addDialogueAction (player) {_,_ ->
|
||||||
getStoreFile()[player.username.toLowerCase() + ":alchs"] = true
|
sendItemSelect (player, "Choose") { slot, optionIndex ->
|
||||||
|
val item = player.inventory[slot]
|
||||||
|
if (item == null)
|
||||||
|
return@sendItemSelect
|
||||||
|
if (!ModernListeners().alchemize(player, item, false))
|
||||||
|
return@sendItemSelect
|
||||||
|
getStoreFile()[player.username.lowercase() + ":alchs"] = remaining - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
return@on true
|
return@on true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -221,19 +221,19 @@ class ModernListeners : SpellListener("modern"){
|
|||||||
setDelay(player,false)
|
setDelay(player,false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun alchemize(player: Player,item: Item,high:Boolean){
|
public fun alchemize(player: Player, item: Item, high: Boolean) : Boolean {
|
||||||
if(item.name == "Coins") player.sendMessage("You can't alchemize something that's already gold!").also { return }
|
if(item.name == "Coins") player.sendMessage("You can't alchemize something that's already gold!").also { return false }
|
||||||
if(!item.definition.isTradeable) player.sendMessage("You can't cast this spell on something like that.").also { return }
|
if(!item.definition.isTradeable) player.sendMessage("You can't cast this spell on something like that.").also { return false }
|
||||||
|
|
||||||
if(player.zoneMonitor.isInZone("Alchemists' Playground")){
|
if(player.zoneMonitor.isInZone("Alchemists' Playground")){
|
||||||
player.sendMessage("You can only alch items from the cupboards!")
|
player.sendMessage("You can only alch items from the cupboards!")
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val coins = Item(995, item.definition.getAlchemyValue(high))
|
val coins = Item(995, item.definition.getAlchemyValue(high))
|
||||||
if (coins.amount > 0 && !player.inventory.hasSpaceFor(coins)) {
|
if (coins.amount > 0 && !player.inventory.hasSpaceFor(coins)) {
|
||||||
player.sendMessage("Not enough space in your inventory!")
|
player.sendMessage("Not enough space in your inventory!")
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.pulseManager.current !is MovementPulse) {
|
if (player.pulseManager.current !is MovementPulse) {
|
||||||
@@ -259,6 +259,7 @@ class ModernListeners : SpellListener("modern"){
|
|||||||
addXP(player, if (high) 65.0 else 31.0)
|
addXP(player, if (high) 65.0 else 31.0)
|
||||||
showMagicTab(player)
|
showMagicTab(player)
|
||||||
setDelay(player, 5)
|
setDelay(player, 5)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendTeleport(player: Player, xp: Double, location: Location){
|
private fun sendTeleport(player: Player, xp: Double, location: Location){
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ public final class SlayerMasterDialogue extends DialoguePlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(int interfaceId, int buttonId) {
|
public boolean handle(int interfaceId, int buttonId) {
|
||||||
rerolls = ServerStore.getInt(getStoreFile(), player.getUsername().toLowerCase());
|
rerolls = ServerStore.getInt(getStoreFile(), player.getUsername().toLowerCase(), 0);
|
||||||
if (isDiary) {
|
if (isDiary) {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case 999:
|
case 999:
|
||||||
|
|||||||
@@ -101,14 +101,14 @@ class ServerStore : PersistWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun JSONObject.getInt(key: String): Int {
|
fun JSONObject.getInt(key: String, default: Int = 0): Int {
|
||||||
return when(val value = this[key]){
|
return when(val value = this[key]){
|
||||||
is Long -> value.toInt()
|
is Long -> value.toInt()
|
||||||
is Double -> value.toInt()
|
is Double -> value.toInt()
|
||||||
is Float -> value.toInt()
|
is Float -> value.toInt()
|
||||||
is Int -> value
|
is Int -> value
|
||||||
is Nothing -> 0
|
is Nothing -> default
|
||||||
else -> 0
|
else -> default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1585,6 +1585,50 @@ fun <G> sendGraphics(gfx: G, location: Location) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instructs the given player's client to execute a given CS2 script with the given arguments
|
||||||
|
* @param player the Player
|
||||||
|
* @param scriptId the ID of the CS2 script to execute
|
||||||
|
* @param arguments the various arguments passed to the script.
|
||||||
|
**/
|
||||||
|
fun runcs2 (player: Player, scriptId: Int, vararg arguments: Any) {
|
||||||
|
var typeString = StringBuilder()
|
||||||
|
var finalArgs = Array<Any?> (arguments.size) { null }
|
||||||
|
try {
|
||||||
|
for (i in 0 until arguments.size) {
|
||||||
|
val arg = arguments[i]
|
||||||
|
if (arg is Int)
|
||||||
|
typeString.append("i")
|
||||||
|
else if (arg is String)
|
||||||
|
typeString.append("s")
|
||||||
|
else
|
||||||
|
throw IllegalArgumentException("Argument at index $i ($arg) is not an acceptable type! Only string and int are accepted.")
|
||||||
|
finalArgs[arguments.size - i - 1] = arg
|
||||||
|
}
|
||||||
|
player.packetDispatch.sendRunScript(scriptId, typeString.toString(), *finalArgs)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a generic item selection prompt with a glowing background, with your own callback to handle the selection.
|
||||||
|
* @param player the player we are openinig the prompt for
|
||||||
|
* @param options the right-click options the items should have
|
||||||
|
* @param callback a callback to handle the selection. The parameters passed to the callback are the slot in the inventory of the selected item, and the 0-9 index of the option clicked.
|
||||||
|
**/
|
||||||
|
fun sendItemSelect (player: Player, vararg options: String, callback: (slot: Int, optionIndex: Int) -> Unit) {
|
||||||
|
player.interfaceManager.openSingleTab(Component(12))
|
||||||
|
val scriptArgs = arrayOf ((12 shl 16) + 18, 93, 4, 7, 0, -1, "", "", "", "", "", "", "", "", "")
|
||||||
|
for (i in 0 until kotlin.math.min(9, options.size))
|
||||||
|
scriptArgs[6 + i] = options[i]
|
||||||
|
runcs2(player, 150, *scriptArgs)
|
||||||
|
val settings = IfaceSettingsBuilder()
|
||||||
|
.enableOptions(0 until 9)
|
||||||
|
.build()
|
||||||
|
player.packetDispatch.sendIfaceSettings(settings, 18, 12, 0, 28)
|
||||||
|
setAttribute(player, "itemselect-callback", callback)
|
||||||
|
}
|
||||||
|
|
||||||
fun announceIfRare(player: Player, item: Item) {
|
fun announceIfRare(player: Player, item: Item) {
|
||||||
if (item.definition.getConfiguration(ItemConfigParser.RARE_ITEM, false)) {
|
if (item.definition.getConfiguration(ItemConfigParser.RARE_ITEM, false)) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import core.game.system.command.Privilege
|
|||||||
import java.io.BufferedWriter
|
import java.io.BufferedWriter
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
|
import java.util.Arrays
|
||||||
import core.net.packet.PacketWriteQueue
|
import core.net.packet.PacketWriteQueue
|
||||||
import core.tools.Log
|
import core.tools.Log
|
||||||
|
|
||||||
@@ -41,6 +42,20 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define("cs2", Privilege.ADMIN, "::cs2 id args", "Allows you to call arbitrary cs2 scripts during runtime") {player, args ->
|
||||||
|
var scriptArgs = ArrayList<Any>()
|
||||||
|
if (args.size == 2) {
|
||||||
|
runcs2(player, args[1].toIntOrNull() ?: return@define)
|
||||||
|
return@define
|
||||||
|
}
|
||||||
|
else if (args.size > 2) {
|
||||||
|
for (i in 2 until args.size) {
|
||||||
|
scriptArgs.add(args[i].toIntOrNull() ?: args[i])
|
||||||
|
}
|
||||||
|
runcs2(player, args[1].toIntOrNull() ?: return@define, *(scriptArgs.toTypedArray().also { player.debug (Arrays.toString(it)) }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
define("cleardiary", Privilege.ADMIN) { player, _ ->
|
define("cleardiary", Privilege.ADMIN) { player, _ ->
|
||||||
for (type in DiaryType.values()) {
|
for (type in DiaryType.values()) {
|
||||||
val diary = player.achievementDiaryManager.getDiary(type)
|
val diary = player.achievementDiaryManager.getDiary(type)
|
||||||
|
|||||||
Reference in New Issue
Block a user