forked from 2009Scape/Server
Refactored canoe handling
Canoe station should now have the full animation suite Canoe making now scales with axe and level of woodcutting Interfaces are now fully updated with proper hide/show/animation Canoes now sink at the end of the journey Added a black screen backdrop overlay seen only in HD
This commit is contained in:
parent
b87a3821dd
commit
e9fd74b379
7 changed files with 379 additions and 453 deletions
|
|
@ -1,86 +0,0 @@
|
|||
package content.global.travel.canoe;
|
||||
|
||||
/**
|
||||
* Represents a canoe to craft.
|
||||
* @author 'Vexia
|
||||
* @date 09/11/2013
|
||||
*/
|
||||
public enum Canoe {
|
||||
LOG(12, 30, 30,0,0),
|
||||
DUGOUT(27, 60, 31,9,3),
|
||||
STABLE_DUGOUT(42, 90, 32,10,2),
|
||||
WAKA(57, 150, 33,8,5);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Canoe.java} {@code Object}.
|
||||
* @param level the woodcutting level requirement.
|
||||
* @param experience the experience.
|
||||
* @param child the child.
|
||||
*/
|
||||
Canoe(final int level, final double experience, final int child, final int silhouetteChild, final int textChild) {
|
||||
this.level = level;
|
||||
this.experience = experience;
|
||||
this.child = child;
|
||||
this.silhouetteChild = silhouetteChild;
|
||||
this.textChild = textChild;
|
||||
this.maxDist = ordinal() + 1;
|
||||
}
|
||||
|
||||
public final int silhouetteChild;
|
||||
public final int textChild;
|
||||
public final int maxDist;
|
||||
|
||||
/**
|
||||
* Represents the woodcutting level requirement to craft the canoe.
|
||||
*/
|
||||
private final int level;
|
||||
|
||||
/**
|
||||
* Represents the experience received for crafting the canoe.
|
||||
*/
|
||||
private final double experience;
|
||||
|
||||
/**
|
||||
* Represents the child's id on the interface.
|
||||
*/
|
||||
private final int child;
|
||||
|
||||
/**
|
||||
* Gets the woodcutting level requirement.
|
||||
* @return The required level.
|
||||
*/
|
||||
public int getRequiredLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the experience received.
|
||||
* @return The experience amount.
|
||||
*/
|
||||
public double getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the child.
|
||||
* @return The child.
|
||||
*/
|
||||
public int getChild() {
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to get the canoe from the child.
|
||||
* @param child the child.
|
||||
* @return <code>True</code> if so
|
||||
*/
|
||||
public static Canoe getCanoeFromChild(final int child) {
|
||||
for (Canoe canoe : values()) {
|
||||
if(canoe.getChild() == child)
|
||||
{
|
||||
return canoe;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
package content.global.travel.canoe
|
||||
|
||||
import core.api.*
|
||||
import core.cache.def.impl.VarbitDefinition
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.data.skill.SkillingTool
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.net.packet.PacketRepository
|
||||
import core.net.packet.context.MinimapStateContext
|
||||
import core.net.packet.out.MinimapState
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Components
|
||||
import core.game.interaction.InterfaceListener
|
||||
import kotlin.math.abs
|
||||
|
||||
class CanoeInterfaceListeners : InterfaceListener {
|
||||
|
||||
val SHAPE_INTERFACE = Components.CANOE_52
|
||||
val DESTINATION_INTERFACE = Components.CANOE_STATIONS_MAP_53
|
||||
|
||||
private val boatChilds = intArrayOf(47, 48, 3, 6, 49)
|
||||
private val locationChilds = intArrayOf(50, 47, 44, 36)
|
||||
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
|
||||
onOpen(SHAPE_INTERFACE){player, _ ->
|
||||
CanoeUtils.checkCanoe(player, Canoe.DUGOUT)
|
||||
CanoeUtils.checkCanoe(player, Canoe.STABLE_DUGOUT)
|
||||
CanoeUtils.checkCanoe(player, Canoe.WAKA)
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
on(SHAPE_INTERFACE) { player, _, _, buttonID, _, _ ->
|
||||
player.interfaceManager.close()
|
||||
val canoe = Canoe.getCanoeFromChild(buttonID)
|
||||
val varbit = player.getAttribute("canoe-varbit", VarbitDefinition.forObjectID(0))
|
||||
|
||||
val axe: SkillingTool? = SkillingTool.getHatchet(player)
|
||||
if (axe == null) {
|
||||
player.packetDispatch.sendMessage("You do not have an axe which you have the woodcutting level to use.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
lock(player, 4)
|
||||
animate(player, CanoeUtils.getShapeAnimation(axe))
|
||||
player.pulseManager.run(object : Pulse(3) {
|
||||
override fun pulse(): Boolean {
|
||||
if (RandomFunction.random(if (canoe == Canoe.WAKA) 8 else 6) == 1) {
|
||||
setVarbit(player,varbit, CanoeUtils.getCraftValue(canoe, false))
|
||||
player.skills.addExperience(Skills.WOODCUTTING, canoe.experience)
|
||||
player.unlock()
|
||||
return true
|
||||
}
|
||||
animate(player, CanoeUtils.getShapeAnimation(axe))
|
||||
return false
|
||||
}
|
||||
})
|
||||
return@on true
|
||||
}
|
||||
|
||||
onOpen(DESTINATION_INTERFACE){player, component ->
|
||||
val varbit = player.getAttribute("canoe-varbit",VarbitDefinition.forObjectID(0))
|
||||
val canoe = CanoeUtils.getCanoeFromVarbit(player, varbit)
|
||||
val stationIndex = CanoeUtils.getStationIndex(player.location)
|
||||
val maxDistance = canoe.maxDist
|
||||
player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,boatChilds[stationIndex],true)
|
||||
player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,locationChilds[stationIndex],false)
|
||||
if(canoe != Canoe.WAKA){
|
||||
player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,49,true)
|
||||
for(i in 0..3){
|
||||
if(i == stationIndex) continue
|
||||
if(abs(i - stationIndex) > maxDistance){
|
||||
player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,boatChilds[i],true)
|
||||
player.packetDispatch.sendInterfaceConfig(DESTINATION_INTERFACE,locationChilds[i],true)
|
||||
}
|
||||
}
|
||||
}
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
on(DESTINATION_INTERFACE){player, _, _, buttonID, _, _ ->
|
||||
val dest = CanoeUtils.getDestinationFromButtonID(buttonID)
|
||||
val destIndex = CanoeUtils.getStationIndex(dest)
|
||||
val arrivalMessage = CanoeUtils.getNameByIndex(destIndex)
|
||||
val stationIndex = CanoeUtils.getStationIndex(player.location)
|
||||
val interfaceAnimationId = CanoeUtils.getTravelAnimation(stationIndex, destIndex)
|
||||
var travelAnimDur = 15
|
||||
val varbit = player.getAttribute("canoe-varbit",VarbitDefinition.forObjectID(0))
|
||||
|
||||
if (player.familiarManager.hasFamiliar()) {
|
||||
player.sendMessage("You can't take a follower on a canoe.")
|
||||
return@on true
|
||||
}
|
||||
if (interfaceAnimationId != 0) {
|
||||
travelAnimDur = Animation(interfaceAnimationId).duration
|
||||
}
|
||||
|
||||
lock(player, travelAnimDur + 4)
|
||||
player.interfaceManager.close()
|
||||
player.pulseManager.run(object : Pulse(){
|
||||
var counter = 0
|
||||
override fun pulse(): Boolean {
|
||||
when(counter++){
|
||||
0 -> {
|
||||
player.interfaceManager.openOverlay(Component(Components.FADE_TO_BLACK_120))
|
||||
player.interfaceManager.open(Component(Components.CANOE_TRAVEL_758))
|
||||
animateInterface(player, Components.CANOE_TRAVEL_758, 3, interfaceAnimationId)
|
||||
}
|
||||
2 -> {
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2))
|
||||
player.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 11, 12)
|
||||
}
|
||||
travelAnimDur+1 -> {
|
||||
player.properties.teleportLocation = dest
|
||||
player.interfaceManager.close(Component(Components.CANOE_TRAVEL_758))
|
||||
player.interfaceManager.closeOverlay()
|
||||
player.interfaceManager.openOverlay(Component(Components.FADE_FROM_BLACK_170))
|
||||
}
|
||||
travelAnimDur+3 -> {
|
||||
player.unlock()
|
||||
player.interfaceManager.restoreTabs()
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0))
|
||||
player.sendMessage("You arrive at $arrivalMessage.")
|
||||
player.sendMessage("Your canoe sinks from the long journey.")
|
||||
if(destIndex == 4){
|
||||
player.sendMessage("There are no trees nearby to make a new canoe. Guess you're walking.")
|
||||
}
|
||||
setVarbit(player,varbit,0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
372
Server/src/main/content/global/travel/canoe/CanoeListener.kt
Normal file
372
Server/src/main/content/global/travel/canoe/CanoeListener.kt
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
package content.global.travel.canoe
|
||||
|
||||
import content.data.skill.SkillingTool
|
||||
import core.api.*
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.InterfaceListener
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.scenery.SceneryBuilder
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.net.packet.PacketRepository
|
||||
import core.net.packet.context.MinimapStateContext
|
||||
import core.net.packet.out.MinimapState
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.Scenery
|
||||
import org.rs09.consts.Sounds
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* Interaction and interface listener for canoe along river Lum.
|
||||
* This handles Components.CANOE_52, Components.CANOE_STATIONS_MAP_53 and Components.CANOE_TRAVEL_758 globally.
|
||||
*/
|
||||
class CanoeListener : InteractionListener, InterfaceListener {
|
||||
companion object {
|
||||
const val CANOE_STATION_VARBIT_ATTRIBUTE = "canoeStationVarbit" // Index of Canoe Stations (0-4)
|
||||
const val CANOE_SELECTED_ATTRIBUTE = "canoeSelected" // Index of Canoes (0-3)
|
||||
|
||||
const val CANOE_SHAPING_INTERFACE = Components.CANOE_52
|
||||
const val CANOE_DESTINATION_INTERFACE = Components.CANOE_STATIONS_MAP_53
|
||||
const val CANOE_TRAVEL_INTERFACE = Components.CANOE_TRAVEL_758
|
||||
|
||||
val CANOE_SHAPING_SILHOUETTE = arrayOf(0, 9, 10, 8)
|
||||
val CANOE_SHAPING_TEXT = arrayOf(0, 3, 2, 5)
|
||||
val CANOE_SHAPING_BUTTONS = arrayOf(30, 31, 32, 33)
|
||||
|
||||
val CANOE_DESTINATION_BUTTONS = arrayOf(47, 48, 3, 6, 49)
|
||||
val CANOE_DESTINATION_HIDE_ROW = arrayOf(10, 11, 12, 20, 18)
|
||||
val CANOE_DESTINATION_YOU_ARE_HERE = arrayOf(25, 24, 23, 19, 0)
|
||||
|
||||
val CANOE_TREE_FALLING_ANIMATION = Animation(3304)
|
||||
val CANOE_PLAYER_PUSHING_ANIMATION = Animation(3301)
|
||||
val CANOE_PUSHING_ANIMATION = Animation(3304)
|
||||
val CANOE_SINKING_ANIMATION = Animation(3305)
|
||||
/** Canoe travel interface animations. A 2D array mapping [ origin ][ destination ]. Index 0-4 for Lumbridge to Wilderness. */
|
||||
val CANOE_TRAVEL_ANIMATIONS = arrayOf(
|
||||
arrayOf(0, 9890, 9889, 9888, 9887),
|
||||
arrayOf(9906, 0, 9893, 9892, 9891),
|
||||
arrayOf(9904, 9905, 0, 9895, 9894),
|
||||
arrayOf(9901, 9902, 9903, 0, 9896),
|
||||
arrayOf(9897, 9898, 9899, 9900, 0),
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun getAxeAnimation(axe: SkillingTool): Animation {
|
||||
return when (axe) {
|
||||
SkillingTool.BRONZE_AXE -> Animation(6744)
|
||||
SkillingTool.IRON_AXE -> Animation(6743)
|
||||
SkillingTool.STEEL_AXE -> Animation(6742)
|
||||
SkillingTool.BLACK_AXE -> Animation(6741)
|
||||
SkillingTool.MITHRIL_AXE -> Animation(6740)
|
||||
SkillingTool.ADAMANT_AXE -> Animation(6739)
|
||||
SkillingTool.RUNE_AXE -> Animation(6738)
|
||||
SkillingTool.DRAGON_AXE -> Animation(6745)
|
||||
else -> axe.animation
|
||||
}
|
||||
}
|
||||
|
||||
/** To scale woodcutting success. Follows WoodcuttingNode values at 15,30,45,60 (3 levels 'harder'). */
|
||||
private fun checkSuccess(player: Player, resource: Canoes, tool: SkillingTool): Boolean {
|
||||
val skill = Skills.WOODCUTTING
|
||||
val level: Int = getDynLevel(player, skill) + getFamiliarBoost(player, skill)
|
||||
val hostRatio = RandomFunction.randomDouble(100.0)
|
||||
val lowMod: Double = if (tool == SkillingTool.BLACK_AXE) resource.tierModLow / 2 else resource.tierModLow
|
||||
val low: Double = resource.baseLow + tool.ordinal * lowMod
|
||||
val highMod: Double = if (tool == SkillingTool.BLACK_AXE) resource.tierModHigh / 2 else resource.tierModHigh
|
||||
val high: Double = resource.baseHigh + tool.ordinal * highMod
|
||||
val clientRatio = RandomFunction.getSkillSuccessChance(low, high, level)
|
||||
return hostRatio < clientRatio
|
||||
}
|
||||
|
||||
/** Maps canoe stations stages to related properties. */
|
||||
enum class CanoeStationSceneries(val sceneryId: Int, val varbitValue: Int) {
|
||||
// Stage 1 - Tree is standing, option to chop-down.
|
||||
TREE_STANDING(Scenery.CANOE_STATION_12144, 0),
|
||||
|
||||
// Stage 2 - The tree is falling via an animation, denies player of options.
|
||||
TREE_FALLING(Scenery.CANOE_STATION_12145, 9),
|
||||
|
||||
// Stage 3 - Tree is on the cradle after the chop, option to shape the boat via an interface.
|
||||
TREE_FALLEN(Scenery.CANOE_STATION_12146, 10),
|
||||
|
||||
// Stage 4 - Tree gets shaped into 1 of 4 canoes, option to push it into the water.
|
||||
TREE_SHAPED_LOG(Scenery.CANOE_STATION_12147, 1),
|
||||
TREE_SHAPED_DUGOUT(Scenery.CANOE_STATION_12148, 2),
|
||||
TREE_SHAPED_STABLE_DUGOUT(Scenery.CANOE_STATION_12149, 3),
|
||||
TREE_SHAPED_WAKA(Scenery.CANOE_STATION_12150, 4),
|
||||
|
||||
// Stage 5 - Canoe is being pushed into the water via an animation, option to travel is available.
|
||||
CANOE_PUSHING_LOG(Scenery.CANOE_STATION_12151, 5),
|
||||
CANOE_PUSHING_DUGOUT(Scenery.CANOE_STATION_12152, 6),
|
||||
CANOE_PUSHING_STABLE_DUGOUT(Scenery.CANOE_STATION_12153, 7),
|
||||
CANOE_PUSHING_WAKA(Scenery.CANOE_STATION_12154, 8),
|
||||
|
||||
// Stage 6 - Canoe is in the water, option to travel via an interface.
|
||||
CANOE_FLOATING_LOG(Scenery.CANOE_STATION_12155, 11),
|
||||
CANOE_FLOATING_DUGOUT(Scenery.CANOE_STATION_12156, 12),
|
||||
CANOE_FLOATING_STABLE_DUGOUT(Scenery.CANOE_STATION_12157, 13),
|
||||
CANOE_FLOATING_WAKA(Scenery.CANOE_STATION_12158, 14),
|
||||
|
||||
// Stage 7 - Canoe is animated to be sunk at the end of the ride. NO VARBITS, NOT PART OF THE CANOE_STATION SCENERY.
|
||||
CANOE_SINKING_LOG(Scenery.A_SINKING_CANOE_12159, 0),
|
||||
CANOE_SINKING_DUGOUT(Scenery.A_SINKING_CANOE_12160, 0),
|
||||
CANOE_SINKING_STABLE_DUGOUT(Scenery.A_SINKING_CANOE_12161, 0),
|
||||
CANOE_SINKING_WAKA(Scenery.A_SINKING_CANOE_12162, 0);
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val stationIdMap = values().associateBy { it.sceneryId }
|
||||
val stationIdArray = stationIdMap.values.map { it.sceneryId }.toIntArray()
|
||||
}
|
||||
}
|
||||
|
||||
/** Enums to map canoes to related properties. */
|
||||
enum class Canoes(val level: Int, val experience: Double, val maxDistance: Int, val baseLow: Double, val baseHigh: Double, val tierModLow: Double, val tierModHigh: Double, val treeShaped: CanoeStationSceneries, val canoePushing: CanoeStationSceneries, val canoeFloating: CanoeStationSceneries, val canoeSinking: CanoeStationSceneries) {
|
||||
LOG (12, 30.0, 1, 32.0, 100.0, 16.0, 50.0, CanoeStationSceneries.TREE_SHAPED_LOG, CanoeStationSceneries.CANOE_PUSHING_LOG, CanoeStationSceneries.CANOE_FLOATING_LOG, CanoeStationSceneries.CANOE_SINKING_LOG),
|
||||
DUGOUT (27, 60.0, 2, 16.0, 50.0, 8.0, 25.0, CanoeStationSceneries.TREE_SHAPED_DUGOUT, CanoeStationSceneries.CANOE_PUSHING_DUGOUT, CanoeStationSceneries.CANOE_FLOATING_DUGOUT, CanoeStationSceneries.CANOE_SINKING_DUGOUT),
|
||||
STABLE_DUGOUT (42, 90.0, 3, 8.0, 25.0, 4.0, 12.5, CanoeStationSceneries.TREE_SHAPED_STABLE_DUGOUT, CanoeStationSceneries.CANOE_PUSHING_STABLE_DUGOUT, CanoeStationSceneries.CANOE_FLOATING_STABLE_DUGOUT, CanoeStationSceneries.CANOE_SINKING_STABLE_DUGOUT),
|
||||
WAKA (57, 150.0, 4, 4.0, 12.5, 2.0, 6.25, CanoeStationSceneries.TREE_SHAPED_WAKA, CanoeStationSceneries.CANOE_PUSHING_WAKA, CanoeStationSceneries.CANOE_FLOATING_WAKA, CanoeStationSceneries.CANOE_SINKING_WAKA);
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val indexMap = Canoes.values().associateBy { it.ordinal }
|
||||
}
|
||||
}
|
||||
|
||||
/** Enums to map canoe stations locations to related properties. */
|
||||
enum class CanoeStationLocations(val stationRegion: Int, val stationVarbit: Int, val playerChopLocation: Location, val playerFloatLocation: Location, val playerFacingLocation: Location, val canoeSinkLocation: Location, val playerDestination: Location, val locationName: String) {
|
||||
LUMBRIDGE(12850, 1839, Location(3243, 3235), Location(3243, 3237), Location(-1, 0), Location(3239, 3242), Location(3240, 3242), "Lumbridge"),
|
||||
CHAMPIONS(12852, 1840, Location(3204, 3343), Location(3202, 3343), Location(0, -1), Location(3199, 3344), Location(3199, 3344), "the Champion's Guild"),
|
||||
BARBARIAN(12341, 1841, Location(3112, 3409), Location(3112, 3411), Location(-1, 0), Location(3109, 3411), Location(3109, 3415), "Barbarian Village"),
|
||||
EDGEVILLE(12342, 1842, Location(3132, 3508), Location(3132, 3510), Location(-1, 0), Location(3132, 3510), Location(3132, 3510), "Edgeville"),
|
||||
WILDERNESS(12603, 0, Location(0, 0), Location(0, 0), Location(0, 0), Location(3142, 3795), Location(3139, 3796), "the Wilderness Pond");
|
||||
|
||||
companion object {
|
||||
private val stationRegionMap = CanoeStationLocations.values().associateBy { it.stationRegion }
|
||||
|
||||
@JvmStatic
|
||||
fun getCanoeStationbyLocation(location: Location): CanoeStationLocations {
|
||||
return stationRegionMap[location.regionId]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineDestinationOverrides() {
|
||||
// Set player's standing location when chopping down the tree.
|
||||
setDest(IntType.SCENERY, CanoeStationSceneries.stationIdArray, "chop-down") { _, node ->
|
||||
return@setDest CanoeStationLocations.getCanoeStationbyLocation(node.location).playerChopLocation
|
||||
}
|
||||
// Set player's standing location when shaping and floating the canoe.
|
||||
setDest(IntType.SCENERY, CanoeStationSceneries.stationIdArray, "shape-canoe", "float canoe", "float log", "float waka") { _, node ->
|
||||
return@setDest CanoeStationLocations.getCanoeStationbyLocation(node.location).playerFloatLocation
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
// Stage 1 - 2: Tree is standing, option to chop-down.
|
||||
on(CanoeStationSceneries.stationIdArray, IntType.SCENERY, "chop-down") { player, node ->
|
||||
val canoeStation = CanoeStationLocations.getCanoeStationbyLocation(node.location)
|
||||
val axe: SkillingTool? = SkillingTool.getHatchet(player)
|
||||
val stationVarbit = node.asScenery().definition.configFile
|
||||
if (axe == null) {
|
||||
sendMessage(player, "You do not have an axe which you have the woodcutting level to use.")
|
||||
return@on true
|
||||
}
|
||||
if (getStatLevel(player, Skills.WOODCUTTING) < 12) {
|
||||
sendMessage(player, "You need a woodcutting level of at least 12 to chop down this tree.")
|
||||
return@on true
|
||||
}
|
||||
lock(player, axe.animation.duration + CANOE_TREE_FALLING_ANIMATION.duration)
|
||||
face(player, canoeStation.playerChopLocation.transform(canoeStation.playerFacingLocation))
|
||||
animate(player, axe.animation)
|
||||
queueScript(player, axe.animation.duration, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
player.animator.stop()
|
||||
setVarbit(player, stationVarbit, CanoeStationSceneries.TREE_FALLING.varbitValue)
|
||||
animateScenery(player, node.asScenery(), CANOE_TREE_FALLING_ANIMATION.id)
|
||||
return@queueScript delayScript(player, CANOE_TREE_FALLING_ANIMATION.duration)
|
||||
}
|
||||
1 -> {
|
||||
setVarbit(player, stationVarbit, CanoeStationSceneries.TREE_FALLEN.varbitValue)
|
||||
unlock(player)
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
// Stage 3: Tree is on the cradle after the chop, option to shape-canoe via interface CANOE_52.
|
||||
on(CanoeStationSceneries.stationIdArray, IntType.SCENERY, "shape-canoe") { player, node ->
|
||||
val canoeStation = CanoeStationLocations.getCanoeStationbyLocation(node.location)
|
||||
setAttribute(player, CANOE_STATION_VARBIT_ATTRIBUTE, canoeStation.stationVarbit)
|
||||
face(player, canoeStation.playerFloatLocation.transform(canoeStation.playerFacingLocation))
|
||||
openInterface(player, CANOE_SHAPING_INTERFACE)
|
||||
openOverlay(player, 333) // Black overlay
|
||||
return@on true
|
||||
}
|
||||
|
||||
// Stage 4 - 5: Tree gets shaped into 1 of 4 canoes, option to float-canoe.
|
||||
on(CanoeStationSceneries.stationIdArray, IntType.SCENERY, "float canoe", "float log", "float waka") { player, node ->
|
||||
val canoeStation = CanoeStationLocations.getCanoeStationbyLocation(node.location)
|
||||
val canoe = Canoes.indexMap[getAttribute(player, CANOE_SELECTED_ATTRIBUTE, 0)]!!
|
||||
setVarbit(player, canoeStation.stationVarbit, canoe.canoePushing.varbitValue)
|
||||
lock(player, CANOE_PLAYER_PUSHING_ANIMATION.duration)
|
||||
playAudio(player, Sounds.CANOE_ROLL_2731)
|
||||
face(player, canoeStation.playerFloatLocation.transform(canoeStation.playerFacingLocation))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
|
||||
when (stage) {
|
||||
0 -> {
|
||||
animate(player, CANOE_PLAYER_PUSHING_ANIMATION)
|
||||
animateScenery(player, node.asScenery(), CANOE_PUSHING_ANIMATION.id)
|
||||
return@queueScript delayScript(player, CANOE_PLAYER_PUSHING_ANIMATION.duration)
|
||||
}
|
||||
1 -> {
|
||||
setVarbit(player, canoeStation.stationVarbit, canoe.canoeFloating.varbitValue)
|
||||
unlock(player)
|
||||
player.animator.stop()
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
else -> return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
// Stage 6: Canoe is in the water, option to paddle via interface CANOE_STATIONS_MAP_53.
|
||||
on(CanoeStationSceneries.stationIdArray, IntType.SCENERY, "paddle log", "paddle canoe") { player, _ ->
|
||||
closeInterface(player)
|
||||
openInterface(player, Components.CANOE_STATIONS_MAP_53)
|
||||
openOverlay(player, 333) // Black overlay
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
var temp = 14
|
||||
override fun defineInterfaceListeners() {
|
||||
|
||||
// Stage 3: Opening interface 52
|
||||
onOpen(CANOE_SHAPING_INTERFACE) { player, _ ->
|
||||
Canoes.values().forEach {
|
||||
if (getStatLevel(player, Skills.WOODCUTTING) >= it.level && it != Canoes.LOG) {
|
||||
setComponentVisibility(player, CANOE_SHAPING_INTERFACE, CANOE_SHAPING_SILHOUETTE[it.ordinal], true)
|
||||
setComponentVisibility(player, CANOE_SHAPING_INTERFACE, CANOE_SHAPING_TEXT[it.ordinal], false)
|
||||
}
|
||||
}
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
// Stage 3: On button click interface 52
|
||||
on(CANOE_SHAPING_INTERFACE) { player, _, _, buttonID, _, _ ->
|
||||
closeInterface(player)
|
||||
val canoe = Canoes.indexMap[CANOE_SHAPING_BUTTONS.indexOf(buttonID)]!!
|
||||
val stationVarbit = getAttribute(player, CANOE_STATION_VARBIT_ATTRIBUTE, 1839)
|
||||
val axe: SkillingTool? = SkillingTool.getHatchet(player)
|
||||
if (axe == null) {
|
||||
sendMessage(player, "You do not have an axe which you have the woodcutting level to use.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
lock(player, 4)
|
||||
animate(player, getAxeAnimation(axe))
|
||||
submitIndividualPulse(player, object : Pulse(3) {
|
||||
override fun pulse(): Boolean {
|
||||
if (checkSuccess(player, canoe, axe)) {
|
||||
setAttribute(player, CANOE_SELECTED_ATTRIBUTE, CANOE_SHAPING_BUTTONS.indexOf(buttonID))
|
||||
setVarbit(player, stationVarbit, canoe.treeShaped.varbitValue)
|
||||
rewardXP(player, Skills.WOODCUTTING, canoe.experience)
|
||||
unlock(player)
|
||||
return true
|
||||
}
|
||||
animate(player, getAxeAnimation(axe))
|
||||
return false
|
||||
}
|
||||
})
|
||||
return@on true
|
||||
}
|
||||
|
||||
onOpen(CANOE_DESTINATION_INTERFACE) { player, component ->
|
||||
val canoe = Canoes.indexMap[getAttribute(player, CANOE_SELECTED_ATTRIBUTE, 0)]!!
|
||||
val origin = CanoeStationLocations.getCanoeStationbyLocation(player.location)
|
||||
for (i in CanoeStationLocations.values()) {
|
||||
setComponentVisibility(player, component.id, CANOE_DESTINATION_HIDE_ROW[i.ordinal], true)
|
||||
if (i == CanoeStationLocations.WILDERNESS) {
|
||||
if (canoe == Canoes.WAKA) {
|
||||
// setComponentVisibility(player, component.id, 22, false) // Some red text on Wildy text.
|
||||
setComponentVisibility(player, component.id, CANOE_DESTINATION_HIDE_ROW[i.ordinal], false)
|
||||
}
|
||||
} else if (i.ordinal == origin.ordinal) {
|
||||
setComponentVisibility(player, component.id, CANOE_DESTINATION_YOU_ARE_HERE[i.ordinal], false)
|
||||
}else if (abs(i.ordinal - origin.ordinal) <= canoe.maxDistance) {
|
||||
setComponentVisibility(player, component.id, CANOE_DESTINATION_HIDE_ROW[i.ordinal], false)
|
||||
}
|
||||
}
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
on(CANOE_DESTINATION_INTERFACE) { player, _, _, buttonID, _, _ ->
|
||||
val origin = CanoeStationLocations.getCanoeStationbyLocation(player.location)
|
||||
var destination: CanoeStationLocations = CanoeStationLocations.LUMBRIDGE
|
||||
when (buttonID) {
|
||||
CANOE_DESTINATION_BUTTONS[0] -> destination = CanoeStationLocations.LUMBRIDGE
|
||||
CANOE_DESTINATION_BUTTONS[1] -> destination = CanoeStationLocations.CHAMPIONS
|
||||
CANOE_DESTINATION_BUTTONS[2] -> destination = CanoeStationLocations.BARBARIAN
|
||||
CANOE_DESTINATION_BUTTONS[3] -> destination = CanoeStationLocations.EDGEVILLE
|
||||
CANOE_DESTINATION_BUTTONS[4] -> destination = CanoeStationLocations.WILDERNESS
|
||||
}
|
||||
val arrivalMessage = destination.locationName
|
||||
val interfaceAnimationId = CANOE_TRAVEL_ANIMATIONS[origin.ordinal][destination.ordinal]
|
||||
|
||||
if (player.familiarManager.hasFamiliar()) {
|
||||
sendMessage(player, "You can't take a follower on a canoe.")
|
||||
return@on true
|
||||
}
|
||||
lock(player, Animation(interfaceAnimationId).duration + 1 + Animation(Components.FADE_FROM_BLACK_170).duration)
|
||||
// Tried using queueScript here, but it doesn't work as interfaces and overlays can't open. Maybe its because this is within an interface listener.
|
||||
submitIndividualPulse(player, object : Pulse() {
|
||||
var counter = 0
|
||||
override fun pulse(): Boolean {
|
||||
when (counter++) {
|
||||
0 -> {
|
||||
openInterface(player, CANOE_TRAVEL_INTERFACE)
|
||||
openOverlay(player, 333) // Only call openOverlay(player, 333) after openInterface
|
||||
animateInterface(player, CANOE_TRAVEL_INTERFACE, 3, interfaceAnimationId)
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 2))
|
||||
player.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6, 11, 12)
|
||||
}
|
||||
Animation(interfaceAnimationId).duration + 1 -> {
|
||||
teleport(player, destination.playerDestination)
|
||||
closeInterface(player)
|
||||
closeOverlay(player)
|
||||
openOverlay(player, Components.FADE_FROM_BLACK_170)
|
||||
}
|
||||
Animation(interfaceAnimationId).duration + 1 + Animation(Components.FADE_FROM_BLACK_170).duration -> {
|
||||
unlock(player)
|
||||
player.interfaceManager.restoreTabs()
|
||||
PacketRepository.send(MinimapState::class.java, MinimapStateContext(player, 0))
|
||||
val sinkingScenery = SceneryBuilder.add(core.game.node.scenery.Scenery(Scenery.A_SINKING_CANOE_12159, destination.canoeSinkLocation, 1), 3) as core.game.node.scenery.Scenery
|
||||
animateScenery(sinkingScenery, CANOE_SINKING_ANIMATION.id)
|
||||
sendMessage(player, "You arrive at $arrivalMessage.")
|
||||
sendMessage(player, "Your canoe sinks from the long journey.")
|
||||
if (destination == CanoeStationLocations.WILDERNESS) {
|
||||
sendMessage(player, "There are no trees nearby to make a new canoe. Guess you're walking.")
|
||||
}
|
||||
setVarbit(player, origin.stationVarbit, 0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
package content.global.travel.canoe
|
||||
|
||||
import core.game.component.Component
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.data.skill.SkillingTool
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import org.rs09.consts.Components
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
|
||||
import core.api.*
|
||||
import core.game.interaction.QueueStrength
|
||||
import org.rs09.consts.Sounds
|
||||
|
||||
class CanoeStationListener : InteractionListener {
|
||||
|
||||
private val STATION_IDs = intArrayOf(12140, 12141, 12142, 12143, 12144, 12145, 12146, 12147, 12148, 12151, 12152, 12153, 12154, 12155, 12156, 12157, 12158, 12149, 12150)
|
||||
private val STAGE_TREE_NONINTERACTABLE = 9
|
||||
private val STAGE_LOG_CHOPPED = 10
|
||||
private val SHAPING_INTERFACE = Components.CANOE_52
|
||||
private val PUSH = Animation(3301)
|
||||
private val FALL = Animation(3303)
|
||||
private val FLOAT = Animation(3304)
|
||||
|
||||
override fun defineDestinationOverrides() {
|
||||
setDest(IntType.SCENERY,STATION_IDs,"chop-down"){ _, node ->
|
||||
return@setDest CanoeUtils.getChopLocation(node.location)
|
||||
}
|
||||
setDest(IntType.SCENERY,STATION_IDs,"shape-canoe","float canoe","float log","float waka"){ _, node ->
|
||||
return@setDest CanoeUtils.getCraftFloatLocation(node.location)
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(STATION_IDs, IntType.SCENERY, "chop-down"){ player, node ->
|
||||
val axe: SkillingTool? = SkillingTool.getHatchet(player)
|
||||
val varbit = node.asScenery().definition.configFile
|
||||
if(varbit.getValue(player) != 0){
|
||||
setVarbit(player,varbit,0)
|
||||
}
|
||||
|
||||
if (axe == null) {
|
||||
player.packetDispatch.sendMessage("You do not have an axe which you have the woodcutting level to use.")
|
||||
return@on true
|
||||
}
|
||||
if (player.skills.getLevel(Skills.WOODCUTTING) < 12) {
|
||||
player.packetDispatch.sendMessage("You need a woodcutting level of at least 12 to chop down this tree.")
|
||||
return@on true
|
||||
}
|
||||
lock(player, 5)
|
||||
setVarp(player, varbit.varpId, 0)
|
||||
player.faceLocation(CanoeUtils.getFaceLocation(player.location))
|
||||
player.animate(axe.animation)
|
||||
setVarbit(player,varbit,STAGE_TREE_NONINTERACTABLE)
|
||||
queueScript(player, 4, QueueStrength.SOFT) {
|
||||
player.animator.stop()
|
||||
setVarbit(player,varbit,STAGE_LOG_CHOPPED)
|
||||
player.packetDispatch.sendSceneryAnimation(node.asScenery().getChild(player), FALL, false)
|
||||
player.unlock()
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(STATION_IDs, IntType.SCENERY, "shape-canoe"){ player, node ->
|
||||
val varbit = node.asScenery().definition.configFile
|
||||
if(varbit.getValue(player) != STAGE_LOG_CHOPPED){
|
||||
setVarbit(player,varbit,0)
|
||||
return@on true
|
||||
}
|
||||
player.faceLocation(CanoeUtils.getFaceLocation(player.location))
|
||||
player.interfaceManager.open(Component(SHAPING_INTERFACE))
|
||||
player.setAttribute("canoe-varbit",varbit)
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(STATION_IDs, IntType.SCENERY, "float canoe","float log","float waka"){ player, node ->
|
||||
val varbit = node.asScenery().definition.configFile
|
||||
val canoe = CanoeUtils.getCanoeFromVarbit(player, varbit)
|
||||
player.animator.animate(PUSH)
|
||||
lock(player, 2)
|
||||
playAudio(player, Sounds.CANOE_ROLL_2731)
|
||||
player.faceLocation(CanoeUtils.getFaceLocation(player.location))
|
||||
player.pulseManager.run(object : Pulse(){
|
||||
override fun pulse(): Boolean {
|
||||
setVarbit(player,varbit, CanoeUtils.getCraftValue(canoe, true))
|
||||
player.packetDispatch.sendSceneryAnimation(node.asScenery(), FLOAT, false)
|
||||
player.unlock()
|
||||
return true
|
||||
}
|
||||
})
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(STATION_IDs, IntType.SCENERY, "paddle log","paddle canoe"){ player, node ->
|
||||
player.interfaceManager.open(Component(Components.CANOE_STATIONS_MAP_53))
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
package content.global.travel.canoe
|
||||
|
||||
import core.cache.def.impl.VarbitDefinition
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import content.data.skill.SkillingTool
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import org.rs09.consts.Components
|
||||
|
||||
object CanoeUtils {
|
||||
private const val SHAPE_INTERFACE = Components.CANOE_52
|
||||
|
||||
private val FROM_LUMBRIDGE = mapOf(4 to 9887, 3 to 9888, 2 to 9889, 1 to 9890)
|
||||
private val FROM_CHAMPIONS = mapOf(4 to 9891, 3 to 9892, 2 to 9893, 0 to 9906)
|
||||
private val FROM_BARBARIAN = mapOf(4 to 9894, 3 to 9895, 1 to 9905, 0 to 9906)
|
||||
private val FROM_EDGE = mapOf(4 to 9896, 2 to 9903, 1 to 9902, 0 to 9901)
|
||||
private val FROM_WILDERNESS = mapOf(3 to 9900, 2 to 9899, 1 to 9898, 0 to 9897)
|
||||
|
||||
fun checkCanoe(player: Player, canoe: Canoe){
|
||||
if(player.skills.getLevel(Skills.WOODCUTTING) < canoe.requiredLevel) return
|
||||
player.packetDispatch.sendInterfaceConfig(SHAPE_INTERFACE,canoe.silhouetteChild,true)
|
||||
player.packetDispatch.sendInterfaceConfig(SHAPE_INTERFACE,canoe.textChild,false)
|
||||
}
|
||||
|
||||
fun getCanoeFromVarbit(player: Player, varbit: VarbitDefinition): Canoe {
|
||||
var bit = varbit.getValue(player)
|
||||
if(bit > 10) bit -= 10
|
||||
return Canoe.values()[bit - 1]
|
||||
}
|
||||
|
||||
fun getCraftValue(canoe: Canoe, floating: Boolean): Int{
|
||||
return 1 + (canoe.ordinal + if (floating) 10 else 0)
|
||||
}
|
||||
|
||||
fun getStationIndex(location: Location): Int{
|
||||
return when(location.regionId){
|
||||
12850 -> 0
|
||||
12852,12596 -> 1
|
||||
12341 -> 2
|
||||
12342 -> 3
|
||||
12603 -> 4
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
fun getTravelAnimation(stationId: Int, destId: Int): Int {
|
||||
return when(stationId){
|
||||
0 -> FROM_LUMBRIDGE.getOrDefault(destId,0)
|
||||
1 -> FROM_CHAMPIONS.getOrDefault(destId,0)
|
||||
2 -> FROM_BARBARIAN.getOrDefault(destId,0)
|
||||
3 -> FROM_EDGE.getOrDefault(destId,0)
|
||||
4 -> FROM_WILDERNESS.getOrDefault(destId,0)
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
fun getShapeAnimation(axe: SkillingTool): Animation{
|
||||
return when(axe){
|
||||
SkillingTool.BRONZE_AXE -> Animation(6744)
|
||||
SkillingTool.IRON_AXE -> Animation(6743)
|
||||
SkillingTool.STEEL_AXE -> Animation(6742)
|
||||
SkillingTool.BLACK_AXE -> Animation(6741)
|
||||
SkillingTool.MITHRIL_AXE -> Animation(6740)
|
||||
SkillingTool.ADAMANT_AXE -> Animation(6739)
|
||||
SkillingTool.RUNE_AXE -> Animation(6738)
|
||||
SkillingTool.DRAGON_AXE -> Animation(6745)
|
||||
else -> axe.animation
|
||||
}
|
||||
}
|
||||
|
||||
fun getDestinationFromButtonID(buttonID: Int): Location {
|
||||
return when(buttonID){
|
||||
47 -> Location.create(3240, 3242, 0)
|
||||
48 -> Location.create(3199, 3344, 0)
|
||||
3 -> Location.create(3109, 3415, 0)
|
||||
6 -> Location.create(3132, 3510, 0)
|
||||
49 -> Location.create(3139, 3796, 0)
|
||||
else -> Location.create(3240, 3242, 0)
|
||||
}
|
||||
}
|
||||
|
||||
fun getNameByIndex(index: Int): String{
|
||||
return when(index){
|
||||
0 -> "Lumbridge"
|
||||
1 -> "the Champion's Guild."
|
||||
2 -> "Barbarian Village"
|
||||
3 -> "Edgeville"
|
||||
4 -> "the Wilderness Pond"
|
||||
else -> "Uhhh report this."
|
||||
}
|
||||
}
|
||||
|
||||
fun getFaceLocation(location: Location): Location{
|
||||
return when(getStationIndex(location)){
|
||||
1 -> location.transform(0,-1,0)
|
||||
0,2,3 -> location.transform(-1,0,0)
|
||||
else -> location
|
||||
}
|
||||
}
|
||||
|
||||
fun getChopLocation(location: Location): Location{
|
||||
return when(getStationIndex(location)){
|
||||
0 -> Location.create(3243, 3235, 0)
|
||||
1 -> Location.create(3204, 3343, 0)
|
||||
2 -> Location.create(3112, 3409, 0)
|
||||
3 -> Location.create(3132, 3508, 0)
|
||||
else -> Location.create(0,0)
|
||||
}
|
||||
}
|
||||
|
||||
fun getCraftFloatLocation(location: Location): Location{
|
||||
return when(getStationIndex(location)){
|
||||
0 -> Location.create(3243, 3237, 0)
|
||||
1 -> Location.create(3202, 3343, 0)
|
||||
2 -> Location.create(3112, 3411, 0)
|
||||
3 -> Location.create(3132, 3510, 0)
|
||||
else -> Location.create(0,0)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package content.region.misthalin.varrock.diary
|
||||
|
||||
import content.global.skill.prayer.Bones
|
||||
import 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
|
||||
|
|
@ -13,6 +12,7 @@ import org.rs09.consts.Scenery
|
|||
import content.region.misthalin.varrock.dialogue.ElsieDialogue
|
||||
import content.global.handlers.iface.FairyRing
|
||||
import content.global.skill.magic.TeleportMethod
|
||||
import content.global.travel.canoe.CanoeListener
|
||||
import core.api.getStatLevel
|
||||
import core.api.inBorders
|
||||
import core.game.diary.AreaDiaryTask
|
||||
|
|
@ -219,8 +219,8 @@ class VarrockAchivementDiary : DiaryEventHookBase(DiaryType.VARROCK) {
|
|||
player.viewport.region?.let {
|
||||
when (it.id) {
|
||||
12342 -> {
|
||||
if (event.iface == Components.CANOE_52
|
||||
&& Canoe.getCanoeFromChild(event.buttonId) == Canoe.WAKA) {
|
||||
if (event.iface == CanoeListener.CANOE_SHAPING_INTERFACE
|
||||
&& event.buttonId == CanoeListener.CANOE_SHAPING_BUTTONS[CanoeListener.Companion.Canoes.WAKA.ordinal]) {
|
||||
finishTask(
|
||||
player,
|
||||
DiaryLevel.HARD,
|
||||
|
|
|
|||
|
|
@ -206,6 +206,10 @@ public final class InterfaceManager {
|
|||
player.removeAttribute("runscript");
|
||||
player.getPacketDispatch().sendRunScript(101, "");
|
||||
}
|
||||
// Component 333 is an immediate(no-fading) full-screen HD-mode black screen which auto-clears when interrupted.
|
||||
if (overlay != null && overlay.getId() == 333) {
|
||||
closeOverlay();
|
||||
}
|
||||
if (opened != null && opened.close(player)) {
|
||||
if (opened != null && (!opened.getDefinition().isWalkable() || opened.getId() == 14)) {
|
||||
PacketRepository.send(CloseInterface.class, new InterfaceContext(player, opened.getDefinition().getWindowPaneId(isResizable()), opened.getDefinition().getChildId(isResizable()), opened.getId(), opened.getDefinition().isWalkable()));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue