Fairy ring refactor

Reimplemented the travel log, fixes the issue where all the travel log interface text collapses in on itself
Travel log now displays the relevant code
Log sorting implemented
Fairy ring now remembers the last entered code and automatically re-enters it when opened
Fairy ring no longer skips letters
Direction clicks in quick succession now turn the wheel multiple times
This commit is contained in:
Ceikry 2024-10-06 10:21:58 +00:00 committed by Ryan
parent 8db9060a40
commit 6b0f942598
5 changed files with 129 additions and 104 deletions

View file

@ -2,109 +2,128 @@ package content.global.handlers.iface
import core.api.* import core.api.*
import core.game.event.FairyRingDialEvent import core.game.event.FairyRingDialEvent
import core.game.component.Component import core.game.interaction.InterfaceListener
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager import core.game.node.entity.player.link.TeleportManager
import core.game.system.task.Pulse import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.RegionManager import core.game.world.map.RegionManager
import core.tools.RandomFunction import core.tools.RandomFunction
import core.game.interaction.InterfaceListener
import core.game.world.GameWorld
val RING_1 = arrayOf('a','d','c','b')
val RING_2 = arrayOf('i','l','k','j')
val RING_3 = arrayOf('p','s','r','q')
/** /**
* Handles the fairy ring interface * Handles the fairy ring interface
* @author Ceikry * @author Ceikry
*/ */
class FairyRingInterface : InterfaceListener { class FairyRingInterface : InterfaceListener {
companion object {
val RINGS = 734 const val RINGS_IFACE = 734
val TRAVEL_LOG = 735 const val LOG_IFACE_ID = 735
const val VARP_F_RING = 816
const val VB_LOG_SORT_ORDER = 4618
const val VB_RING_1 = 2341
const val VB_RING_2 = 2342
const val VB_RING_3 = 2343
val RING_1 = arrayOf('a','d','c','b')
val RING_2 = arrayOf('i','l','k','j')
val RING_3 = arrayOf('p','s','r','q')
}
override fun defineInterfaceListeners() { override fun defineInterfaceListeners() {
onOpen(RINGS){player, _ -> onOpen(RINGS_IFACE){ player, _ ->
player.interfaceManager.openSingleTab(Component(TRAVEL_LOG)) openSingleTab(player, LOG_IFACE_ID)
player.setAttribute("fr:ring1", 0) saveVarp(player, VARP_F_RING)
player.setAttribute("fr:ring2", 0)
player.setAttribute("fr:ring3", 0)
FairyRing.drawLog(player)
return@onOpen true return@onOpen true
} }
onClose(RINGS){player, _ -> onOpen(LOG_IFACE_ID){ player, _ ->
closeTabInterface(player) drawLog(player)
player.removeAttribute("fr:ring1") return@onOpen true
player.removeAttribute("fr:ring2") }
player.removeAttribute("fr:ring3")
setVarp(player, 816, 0) onClose(RINGS_IFACE){ player, _ ->
closeTabInterface(player) closeTabInterface(player)
return@onClose true return@onClose true
} }
on(RINGS){player, _, _, buttonID, _, _ -> on(RINGS_IFACE){ player, _, _, buttonID, _, _ ->
if(player.getAttribute("fr:time",0L) > System.currentTimeMillis()) return@on true
var delayIncrementer = 1750L
when(buttonID){ when(buttonID){
23 -> delayIncrementer += increment(player,1) 23 -> increment(player,1)
25 -> delayIncrementer += increment(player,2) 25 -> increment(player,2)
27 -> delayIncrementer += increment(player,3) 27 -> increment(player,3)
24 -> decrement(player,1) 24 -> decrement(player,1)
26 -> decrement(player,2) 26 -> decrement(player,2)
28 -> decrement(player,3) 28 -> decrement(player,3)
21 -> confirm(player) 21 -> confirm(player)
} }
player.setAttribute("fr:time",System.currentTimeMillis() + delayIncrementer)
return@on true return@on true
} }
on(TRAVEL_LOG,12){player, _, _, _, _, _ -> on(LOG_IFACE_ID,12){ player, _, _, _, _, _ ->
toggleSortOrder(player) toggleSortOrder(player)
return@on true return@on true
} }
} }
private fun toggleSortOrder(player: Player): Long{ /**
val ring1index = player.getAttribute("fr:ring1",0) * Draws the travel log interface
var toSet = player.getAttribute("fr:sortorder",true) * Currently, the visited logs is a bool array in globalData. Someone should migrate this to prefs or something at some point.
toSet = !toSet * On transmit of Varp 816, which all used varbits are part of here, the CS2 is invoked to populate the codes in the log and sort them correctly.
player.setAttribute("fr:sortorder",toSet) * @param player The player to draw the interface for
if(toSet) { */
setVarp(player, 816, ring1index) private fun drawLog (player: Player)
player.setAttribute("fr:ring2",0) {
player.setAttribute("fr:ring3",0) for (i in FairyRing.values().indices) {
if (!player.savedData.globalData.hasTravelLog(i)) {
continue
}
val ring = FairyRing.values()[i]
if (ring.childId == -1) {
continue
}
setInterfaceText(player, "<br>${ring.tip}", LOG_IFACE_ID, ring.childId)
} }
return -1750L
} }
fun increment(player: Player,ring: Int): Long{ private fun toggleSortOrder(player: Player) {
val curIndex = player.getAttribute("fr:ring$ring",0) val curSort = getVarbit(player, VB_LOG_SORT_ORDER) == 0
var nextIndex = 0 setVarbit(player, VB_LOG_SORT_ORDER, if (curSort) 1 else 0)
if(curIndex == 3) nextIndex = 0 drawLog(player)
else if(curIndex == 1) nextIndex = 3 }
else if(curIndex == 2) nextIndex = 2
else nextIndex = curIndex + 1 fun increment(player: Player,ring: Int) {
player.setAttribute("fr:ring$ring",nextIndex) val vbit = when(ring) {
return if (curIndex == 1) 1750L else 0L 1 -> VB_RING_1
2 -> VB_RING_2
3 -> VB_RING_3
else -> return
}
val curIndex = getVarbit(player, vbit)
val nextIndex: Int = if(curIndex == 3) 0
else curIndex + 1
setVarbit(player, vbit, nextIndex)
} }
fun decrement(player: Player,ring: Int){ fun decrement(player: Player,ring: Int){
val curIndex = player.getAttribute("fr:ring$ring",0) val vbit = when(ring) {
var nextIndex = 0 1 -> VB_RING_1
if(curIndex == 0) nextIndex = 3 2 -> VB_RING_2
else nextIndex = curIndex - 1 3 -> VB_RING_3
player.setAttribute("fr:ring$ring",nextIndex) else -> return
}
val curIndex = getVarbit(player, vbit)
val nextIndex: Int = if(curIndex == 0) 3
else curIndex - 1
setVarbit(player, vbit, nextIndex)
} }
private fun confirm(player: Player){ private fun confirm(player: Player){
val ring1index = player.getAttribute("fr:ring1",0) val ring1index = getVarbit(player, VB_RING_1)
val ring2index = player.getAttribute("fr:ring2",0) val ring2index = getVarbit(player, VB_RING_2)
val ring3index = player.getAttribute("fr:ring3",0) val ring3index = getVarbit(player, VB_RING_3)
val code = "${RING_1[ring1index]}${RING_2[ring2index]}${RING_3[ring3index]}" val code = "${RING_1[ring1index]}${RING_2[ring2index]}${RING_3[ring3index]}"
val ring: FairyRing? = try { val ring: FairyRing? = try {
FairyRing.valueOf(code.uppercase()) FairyRing.valueOf(code.uppercase())
@ -208,23 +227,4 @@ enum class FairyRing(val tile: Location?, val tip: String = "", val childId: Int
open fun checkAccess(player: Player) : Boolean { open fun checkAccess(player: Player) : Boolean {
return true return true
} }
companion object {
/**
* Draws the travel log.
* @param player the player.
*/
fun drawLog(player: Player) {
for (i in FairyRing.values().indices) {
if (!player.savedData.globalData.hasTravelLog(i)) {
continue
}
val ring = FairyRing.values()[i]
if (ring.childId == -1) {
continue
}
setInterfaceText(player, "<br>${ring.tip}", 735, ring.childId)
}
}
}
} }

View file

@ -1,13 +1,15 @@
package content.region.misc.zanaris.handlers package content.region.misc.zanaris.handlers
import core.api.* import content.global.handlers.iface.FairyRingInterface
import core.game.component.Component import core.api.anyInEquipment
import core.api.hasRequirement
import core.api.openInterface
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
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.world.map.Location import core.game.world.map.Location
import org.rs09.consts.Items import org.rs09.consts.Items
import core.game.interaction.InteractionListener
import core.game.interaction.IntType
/** /**
* Handles interactions with fairy rings * Handles interactions with fairy rings
@ -59,17 +61,7 @@ class FairyRingPlugin : InteractionListener {
return true return true
} }
private fun reset(player: Player) {
player.removeAttribute("fairy-delay")
player.removeAttribute("fairy_location_combo")
for (i in 0..2) {
setVarp(player, 816 + i, 0)
}
}
private fun openFairyRing(player: Player) { private fun openFairyRing(player: Player) {
reset(player) openInterface(player, FairyRingInterface.RINGS_IFACE)
player.interfaceManager.openSingleTab(Component(735))
player.interfaceManager.open(Component(734))
} }
} }

View file

@ -1253,10 +1253,19 @@ fun getVarbit (player: Player, varbitId: Int) : Int {
@JvmOverloads @JvmOverloads
fun setVarp (player: Player, varpIndex: Int, value: Int, save: Boolean = false) { fun setVarp (player: Player, varpIndex: Int, value: Int, save: Boolean = false) {
player.varpMap[varpIndex] = value player.varpMap[varpIndex] = value
player.saveVarp[varpIndex] = save if (player.saveVarp[varpIndex] != true && save)
player.saveVarp[varpIndex] = true //only set if we're choosing to save. Prevents accidental unsaving. if you REALLY want to unsave a varp, use unsaveVarp.
player.packetDispatch.sendVarp(varpIndex, value) player.packetDispatch.sendVarp(varpIndex, value)
} }
fun saveVarp (player: Player, varpIndex: Int) {
player.saveVarp[varpIndex] = true
}
fun unsaveVarp (player: Player, varpIndex: Int) {
player.saveVarp.remove(varpIndex)
}
@JvmOverloads @JvmOverloads
fun setVarbit (player: Player, def: VarbitDefinition, value: Int, save: Boolean = false) { fun setVarbit (player: Player, def: VarbitDefinition, value: Int, save: Boolean = false) {
val mask = def.mask val mask = def.mask

View file

@ -34,7 +34,9 @@ public final class ContainerContext implements Context {
/** /**
* The items. * The items.
*/ */
private final Item[] items; private Item[] items;
public int[] ids;
/** /**
* The length of the array to send. * The length of the array to send.
@ -115,6 +117,17 @@ public final class ContainerContext implements Context {
this.slots = null; this.slots = null;
} }
public ContainerContext(Player player, int interfaceId, int childId, int containerId, int[] items) {
this.player = player;
this.interfaceId = interfaceId;
this.childId = childId;
this.containerId = containerId;
this.ids = items;
this.length = items.length;
this.split = false;
this.slots = null;
}
/** /**
* Constructs a new {@code ContainerContext} {@code Object}. * Constructs a new {@code ContainerContext} {@code Object}.
* @param player The player. * @param player The player.

View file

@ -42,6 +42,16 @@ public final class ContainerPacket implements OutgoingPacket<ContainerContext> {
} }
} }
} else { } else {
if (context.ids != null)
{
buffer.p2(context.getLength());
for (int i = 0; i < context.getLength(); i++)
{
buffer.putS(1);
buffer.p2(context.ids[i] + 1);
}
}
else {
buffer.putShort(context.getItems().length); buffer.putShort(context.getItems().length);
for (Item item : context.getItems()) for (Item item : context.getItems())
if (item != null) { if (item != null) {
@ -57,6 +67,7 @@ public final class ContainerPacket implements OutgoingPacket<ContainerContext> {
} }
} }
} }
}
buffer.cypherOpcode(context.getPlayer().getSession().getIsaacPair().getOutput());context.getPlayer().getSession().write(buffer); buffer.cypherOpcode(context.getPlayer().getSession().getIsaacPair().getOutput());context.getPlayer().getSession().write(buffer);
} }