mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-11 09:00:23 -07:00
Changed most of the doors in Draynor Manor to not autowalk
Implemented Draynor Manor chair NPCs (The ones that follow you around the house)
This commit is contained in:
parent
faf2222f4c
commit
89edf78e54
4 changed files with 208 additions and 0 deletions
|
|
@ -1439,6 +1439,12 @@
|
|||
"fence": "false",
|
||||
"metal": "false"
|
||||
},
|
||||
{
|
||||
"id": "11470",
|
||||
"replaceId": "11471",
|
||||
"fence": "false",
|
||||
"metal": "false"
|
||||
},
|
||||
{
|
||||
"id": "11483",
|
||||
"replaceId": "11708",
|
||||
|
|
|
|||
|
|
@ -6991,6 +6991,10 @@
|
|||
"npc_id": "3288",
|
||||
"loc_data": "{2987,3446,0,1,7}-{3034,3437,0,1,0}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "3293",
|
||||
"loc_data": "{3113,3369,1,0,0}-{3122,3353,0,0,3}-{3124,3360,0,0,2}-{3115,3362,0,0,1}-"
|
||||
},
|
||||
{
|
||||
"npc_id": "3294",
|
||||
"loc_data": "{3014,3339,0,1,2}-"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
package content.region.misthalin.draynor.handlers
|
||||
|
||||
import core.api.hasLineOfSight
|
||||
import core.game.interaction.MovementPulse
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.impl.PulseType
|
||||
import core.game.node.entity.npc.AbstractNPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.plugin.Initializable
|
||||
|
||||
/**
|
||||
* Represents the Draynor Manor Chair NPC, these are the chairs that follow the player
|
||||
* around the manor.
|
||||
*
|
||||
* @author Broseki
|
||||
*/
|
||||
|
||||
private const val DRAYNOR_MANOR_CHAIR_NPC_ID = 3293
|
||||
private const val FOLLOWING_DISTANCE = 5
|
||||
private const val STOP_FOLLOWING_DISTANCE = 30
|
||||
|
||||
@Initializable
|
||||
class DraynorManorChairNPC(id: Int = DRAYNOR_MANOR_CHAIR_NPC_ID, location: Location? = null) :
|
||||
AbstractNPC(id, location) {
|
||||
|
||||
// The player this NPC is currently following, null if nobody is being followed
|
||||
private var following: Player? = null
|
||||
|
||||
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
|
||||
return DraynorManorChairNPC(id, location)
|
||||
}
|
||||
|
||||
override fun handleTickActions() {
|
||||
super.handleTickActions()
|
||||
val closestPlayer = findClosestPlayer()
|
||||
// If there is a player nearby, follow them
|
||||
if (closestPlayer != null && following != closestPlayer) {
|
||||
stopFollowing()
|
||||
following = closestPlayer
|
||||
follow(closestPlayer)
|
||||
following?.let { face(it) }
|
||||
} else {
|
||||
// If we didn't find a player within `FOLLOWING_DISTANCE`
|
||||
// but we are following a player, check that they are still
|
||||
// within `STOP_FOLLOWING_DISTANCE`, if they are gone, stop
|
||||
// trying to follow them.
|
||||
following?.let { player ->
|
||||
if (findDistanceToPlayer(player) > STOP_FOLLOWING_DISTANCE
|
||||
|| !player.isActive
|
||||
|| player.isInvisible) {
|
||||
stopFollowing()
|
||||
} else {
|
||||
if (!pulseManager.hasPulseRunning()) {
|
||||
follow(player)
|
||||
}
|
||||
face(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops following `following`
|
||||
*/
|
||||
fun stopFollowing() {
|
||||
following = null
|
||||
resetWalk()
|
||||
pulseManager.clear(PulseType.STANDARD)
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the closest player to the current entity within `FOLLOWING_DISTANCE`
|
||||
* that is currently in the chair's line of sight.
|
||||
*
|
||||
* @return The Player object representing the closest player, or null if there are no players nearby.
|
||||
*/
|
||||
fun findClosestPlayer(): Player? {
|
||||
val players = RegionManager.getLocalPlayers(this, FOLLOWING_DISTANCE)
|
||||
if (players.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
var closestPlayer: Player? = null
|
||||
var closestDistance = Double.MAX_VALUE
|
||||
|
||||
for (player in players) {
|
||||
// Make sure the chair does not try to start
|
||||
// following a player in another room
|
||||
if (!hasLineOfSight(this, player)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// If the player is invisible, don't follow them
|
||||
if (player.isInvisible) {
|
||||
continue
|
||||
}
|
||||
|
||||
val distance = findDistanceToPlayer(player)
|
||||
if (distance < closestDistance) {
|
||||
closestDistance = distance
|
||||
closestPlayer = player
|
||||
}
|
||||
}
|
||||
|
||||
return closestPlayer
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the distance between the current entity and the specified player.
|
||||
*
|
||||
* @param player The player whose distance from the current entity is to be calculated.
|
||||
* @return The distance between the current entity and the specified player as a Double value.
|
||||
*/
|
||||
fun findDistanceToPlayer(player: Player): Double {
|
||||
return this.location.getDistance(player.location)
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the current entity to follow the specified player using a movement pulse.
|
||||
*
|
||||
* @param player The player that the entity should follow.
|
||||
*/
|
||||
fun follow(player: Player) {
|
||||
pulseManager.run((object : MovementPulse(this, player, Pathfinder.DUMB) {
|
||||
override fun pulse(): Boolean {
|
||||
return false
|
||||
}
|
||||
}), PulseType.STANDARD)
|
||||
}
|
||||
|
||||
override fun getIds(): IntArray {
|
||||
return intArrayOf(DRAYNOR_MANOR_CHAIR_NPC_ID)
|
||||
}
|
||||
|
||||
override fun shouldPreventStacking(mover: Entity?): Boolean {
|
||||
return mover is DraynorManorChairNPC
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package content.region.misthalin.draynor.handlers
|
||||
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager.getLocalNpcs
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.world.map.zone.MapZone
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.ZoneBuilder
|
||||
import core.plugin.Initializable
|
||||
import core.plugin.Plugin
|
||||
|
||||
/**
|
||||
* Represents the interior of Draynor Manor.
|
||||
*
|
||||
* @author Broseki
|
||||
*/
|
||||
@Initializable
|
||||
class DraynorManorHouseZone : MapZone("Draynor Manor House", true), Plugin<Any?> {
|
||||
|
||||
override fun newInstance(arg: Any?): Plugin<Any?> {
|
||||
ZoneBuilder.configure(this)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun move(e: Entity, loc: Location?, destination: Location): Boolean {
|
||||
for (n in getLocalNpcs(e, 5)) {
|
||||
if (n.isInvisible() || n === e) {
|
||||
continue
|
||||
}
|
||||
if (n.shouldPreventStacking(e)) {
|
||||
val s1 = e.size()
|
||||
val s2 = n.size()
|
||||
val x = destination.getX()
|
||||
val y = destination.getY()
|
||||
val l = n.getLocation()
|
||||
if (Pathfinder.isStandingIn(x, y, s1, s1, l.getX(), l.getY(), s2, s2)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun enter(entity: Entity?): Boolean {
|
||||
return super.enter(entity)
|
||||
}
|
||||
|
||||
override fun fireEvent(identifier: String?, vararg args: Any?): Any? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun configure() {
|
||||
register(ZoneBorders(3097, 3373, 3119, 3364))
|
||||
register(ZoneBorders(3090, 3363, 3126, 3354))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue