Boonzeet
Pokémon Secrets of the Ages Developer
- 188
- Posts
- 16
- Years
- United Kingdom
- Seen Feb 18, 2025
Boon's Terrain Tag Side Stairs
![[PokeCommunity.com] [v18] Terrain Tag Side Stairs [PokeCommunity.com] [v18] Terrain Tag Side Stairs](https://i.imgur.com/OIMNjMY.gif)
A simple script to allow placing stair tiles that automatically perform as side stairs, with psuedo-depth effect and support for Followers.
Might conflict with some scripts if they significantly alter Game_Player.
Setup
Version 18
Copy this code above Main.
Code:
#-------------------------------------------------------------------------------
# Boon's Terrain Tag Side Stairs
# v1.2
# By Boonzeet
#-------------------------------------------------------------------------------
# Sideways stairs with pseudo 'depth' effect. Please credit if used
#-------------------------------------------------------------------------------
# v1.2 - Fixed bugs with ledges, surfing and map transfers
# v1.1 - Added v18 support
#-------------------------------------------------------------------------------
PluginManager.register({
:name => "Terrain Tag Side Stairs",
:version => "1.1",
:credits => ["Boonzeet"],
:link => "https://reliccastle.com/resources/397/"
})
#-------------------------------------------------------------------------------
# Config
#-------------------------------------------------------------------------------
module PBTerrain
StairLeft = 19 # Set these to the terrain tags you'd like to use
StairRight = 20
end
#-------------------------------------------------------------------------------
# Existing Class Extensions
#-------------------------------------------------------------------------------
def pbTurnTowardEvent(event,otherEvent)
sx = 0; sy = 0
if $MapFactory
relativePos=$MapFactory.getThisAndOtherEventRelativePos(otherEvent,event)
sx = relativePos[0]
sy = relativePos[1]
else
sx = event.x - otherEvent.x
sy = event.y - otherEvent.y
end
return if sx == 0 and sy == 0
if sx.abs >= sy.abs #added
(sx > 0) ? event.turn_left : event.turn_right
else
(sy > 0) ? event.turn_up : event.turn_down
end
end
class Game_Character
alias initialize_stairs initialize
attr_accessor :offset_x
attr_accessor :offset_y
attr_accessor :real_offset_x
attr_accessor :real_offset_y
def initialize(*args)
@offset_x = 0
@offset_y = 0
@real_offset_x = 0
@real_offset_y = 0
initialize_stairs(*args)
end
alias screen_x_stairs screen_x
def screen_x
@real_offset_x = 0 if @real_offset_x == nil
return screen_x_stairs + @real_offset_x
end
alias screen_y_stairs screen_y
def screen_y
@real_offset_y = 0 if @real_offset_y == nil
return screen_y_stairs + @real_offset_y
end
alias updatemovestairs update_move
def update_move
# compatibility with existing saves
if @real_offset_x == nil || @real_offset_y == nil || @offset_y == nil || @offset_x == nil
@real_offset_x = 0
@real_offset_y = 0
@offset_x = 0
@offset_y = 0
end
if @real_offset_x != @offset_x || @real_offset_y != @offset_y
@real_offset_x = @real_offset_x-2 if @real_offset_x>@offset_x
@real_offset_x = @real_offset_x+2 if @real_offset_x<@offset_x
@real_offset_y = @real_offset_y+2 if @real_offset_y<@offset_y
@real_offset_y = @real_offset_y-2 if @real_offset_y>@offset_y
end
updatemovestairs
end
alias movetostairs moveto
def moveto(x,y)
@real_offset_x = 0
@real_offset_y = 0
@offset_x = 0
@offset_y = 0
movetostairs(x,y)
end
end
class Game_Character
alias move_left_stairs move_left
def move_left(turn_enabled = true)
move_left_stairs(turn_enabled)
if self.map.terrain_tag(@x,@y) == PBTerrain::StairLeft || self.map.terrain_tag(@x,@y) == PBTerrain::StairRight
@offset_y = -16
else
@offset_y = 0
end
end
alias move_right_stairs move_right
def move_right(turn_enabled = true)
move_right_stairs(turn_enabled)
if self.map.terrain_tag(@x,@y) == PBTerrain::StairLeft || self.map.terrain_tag(@x,@y) == PBTerrain::StairRight
@offset_y = -16
else
@offset_y = 0
end
end
end
class Game_Player
alias move_left_stairs move_left
def move_left(turn_enabled = true)
old_tag = self.map.terrain_tag(@x, @y)
old_through = self.through
old_x = @x
if old_tag == PBTerrain::StairLeft
if passable?(@x-1, @y+1, 4) && self.map.terrain_tag(@x-1,@y+1) == PBTerrain::StairLeft
@y += 1
self.through = true
end
elsif old_tag == PBTerrain::StairRight
if passable?(@x-1, @y-1, 6)
@y -= 1
self.through = true
end
end
move_left_stairs(turn_enabled)
new_tag = self.map.terrain_tag(@x, @y)
if old_x != @x
if old_tag != PBTerrain::StairLeft && new_tag == PBTerrain::StairLeft ||
old_tag != PBTerrain::StairRight && new_tag == PBTerrain::StairRight
self.offset_y = -16
@y += 1 if new_tag == PBTerrain::StairLeft
elsif old_tag == PBTerrain::StairLeft && new_tag != PBTerrain::StairLeft ||
old_tag == PBTerrain::StairRight && new_tag != PBTerrain::StairRight
self.offset_y = 0
end
end
self.through = old_through
end
alias move_right_stairs move_right
def move_right(turn_enabled = true)
old_tag = self.map.terrain_tag(@x, @y)
old_through = self.through
old_x = @x
if old_tag == PBTerrain::StairLeft && passable?(@x+1, @y-1, 4)
@y -= 1
self.through = true
elsif old_tag == PBTerrain::StairRight && passable?(@x+1, @y+1, 6)&& self.map.terrain_tag(@x+1,@y+1) == PBTerrain::StairRight
@y += 1
self.through = true
end
move_right_stairs(turn_enabled)
new_tag = self.map.terrain_tag(@x, @y)
if old_x != @x
if old_tag != PBTerrain::StairLeft && new_tag == PBTerrain::StairLeft ||
old_tag != PBTerrain::StairRight && new_tag == PBTerrain::StairRight
self.offset_y = -16
@y += 1 if new_tag == PBTerrain::StairRight
elsif old_tag == PBTerrain::StairLeft && new_tag != PBTerrain::StairLeft ||
old_tag == PBTerrain::StairRight && new_tag != PBTerrain::StairRight
self.offset_y = 0
end
end
self.through = old_through
end
alias center_stairs center
def center(x,y)
center_stairs(x,y)
self.map.display_x = self.map.display_x + (@offset_x || 0)
self.map.display_y = self.map.display_y + (@offset_y || 0)
end
def passable?(x, y, d)
# Get new coordinates
new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
# If coordinates are outside of map
unless $game_map.validLax?(new_x, new_y)
# Impassable
return false
end
if !$game_map.valid?(new_x, new_y)
return false if !$MapFactory
return $MapFactory.isPassableFromEdge?(new_x, new_y)
end
# If debug mode is ON and ctrl key was pressed
if $DEBUG and Input.press?(Input::CTRL)
# Passable
return true
elsif d == 8 && new_y > 0 # prevent player moving up past the top of the stairs
if $game_map.terrain_tag(new_x, new_y) == PBTerrain::StairLeft &&
$game_map.terrain_tag(new_x, new_y-1) != PBTerrain::StairLeft
return false
elsif $game_map.terrain_tag(new_x, new_y) == PBTerrain::StairRight &&
$game_map.terrain_tag(new_x, new_y-1) != PBTerrain::StairRight
return false
end
end
super
end
end
Version 17
Place this script above Main. This version is no longer being supported. Please upgrade Essentials to v18 to get support.
Spoiler:
Code:
# ========================================================================
# Boon's Terrain Tag Side Stairs
# v1.0
# By Boonzeet
# ========================================================================
# Sideways stairs with pseudo 'depth' effect. Please credit if used
# ========================================================================
# ========================================================================
# Config
# ========================================================================
# Set these to whatever terrain tags you want to use
module PBTerrain
StairLeft = 19
StairRight = 20
end
# ========================================================================
# Existing Class Extensions
# ========================================================================
def pbTurnTowardEvent(event,otherEvent)
sx = 0; sy = 0
if $MapFactory
relativePos=$MapFactory.getThisAndOtherEventRelativePos(otherEvent,event)
sx = relativePos[0]
sy = relativePos[1]
else
sx = event.x - otherEvent.x
sy = event.y - otherEvent.y
end
return if sx == 0 and sy == 0
if sx.abs >= sy.abs #added
(sx > 0) ? event.turn_left : event.turn_right
else
(sy > 0) ? event.turn_up : event.turn_down
end
end
class Game_Character
alias initialize_stairs initialize
attr_accessor :offset_x
attr_accessor :offset_y
attr_accessor :real_offset_x
attr_accessor :real_offset_y
def initialize(*args)
@offset_x = 0
@offset_y = 0
@real_offset_x = 0
@real_offset_y = 0
initialize_stairs(*args)
end
alias screen_x_stairs screen_x
def screen_x
@real_offset_x = 0 if @real_offset_x == nil
return screen_x_stairs + @real_offset_x
end
alias screen_y_stairs screen_y
def screen_y
@real_offset_y = 0 if @real_offset_y == nil
return screen_y_stairs + @real_offset_y
end
def update_move
distance = 2**@move_speed
# compatibility with existing saves
if @real_offset_x == nil || @real_offset_y == nil || @offset_y == nil || @offset_x == nil
@real_offset_x = 0
@real_offset_y = 0
@offset_x = 0
@offset_y = 0
end
if @real_offset_x != @offset_x || @real_offset_y != @offset_y
@real_offset_x = @real_offset_x-2 if @real_offset_x>@offset_x
@real_offset_x = @real_offset_x+2 if @real_offset_x<@offset_x
@real_offset_y = @real_offset_y+2 if @real_offset_y<@offset_y
@real_offset_y = @real_offset_y-2 if @real_offset_y>@offset_y
end
realResX = Game_Map.realResX
realResY = Game_Map.realResY
@real_x = [@real_x-distance,@x*realResX].max if @x*realResX<@real_x
@real_x = [@real_x+distance,@x*realResX].min if @x*realResX>@real_x
@real_y = [@real_y+distance,@y*realResY].min if @y*realResY>@real_y
@real_y = [@real_y-distance,@y*realResY].max if @y*realResY<@real_y
if !jumping? && !moving?
Events.onStepTakenFieldMovement.trigger(self,self)
end
if @walk_anime
@anime_count += 1.5
elsif @step_anime
@anime_count += 1
end
end
end
class Game_Character
alias move_left_stairs move_left
def move_left(turn_enabled = true)
move_left_stairs(turn_enabled)
if self.map.terrain_tag(@x,@y) == PBTerrain::StairLeft || self.map.terrain_tag(@x,@y) == PBTerrain::StairRight
@offset_y = -16
else
@offset_y = 0
end
end
alias move_right_stairs move_right
def move_right(turn_enabled = true)
move_right_stairs(turn_enabled)
if self.map.terrain_tag(@x,@y) == PBTerrain::StairLeft || self.map.terrain_tag(@x,@y) == PBTerrain::StairRight
@offset_y = -16
else
@offset_y = 0
end
end
end
class Game_Player
alias move_left_stairs move_left
def move_left(turn_enabled = true)
old_tag = self.map.terrain_tag(@x, @y)
old_through = self.through
old_x = @x
if old_tag == PBTerrain::StairLeft
if passable?(@x-1, @y+1, 4) && self.map.terrain_tag(@x-1,@y+1) == PBTerrain::StairLeft
@y += 1
self.through = true
end
elsif old_tag == PBTerrain::StairRight
if passable?(@x-1, @y-1, 6)
@y -= 1
self.through = true
end
end
move_left_stairs(turn_enabled)
new_tag = self.map.terrain_tag(@x, @y)
if old_x != @x
if old_tag != PBTerrain::StairLeft && new_tag == PBTerrain::StairLeft ||
old_tag != PBTerrain::StairRight && new_tag == PBTerrain::StairRight
self.offset_y = -16
@y += 1 if new_tag == PBTerrain::StairLeft
elsif old_tag == PBTerrain::StairLeft && new_tag != PBTerrain::StairLeft ||
old_tag == PBTerrain::StairRight && new_tag != PBTerrain::StairRight
self.offset_y = 0
end
end
self.through = old_through
end
alias move_right_stairs move_right
def move_right(turn_enabled = true)
old_tag = self.map.terrain_tag(@x, @y)
old_through = self.through
old_x = @x
if old_tag == PBTerrain::StairLeft && passable?(@x+1, @y-1, 4)
@y -= 1
self.through = true
elsif old_tag == PBTerrain::StairRight && passable?(@x+1, @y+1, 6)&& self.map.terrain_tag(@x+1,@y+1) == PBTerrain::StairRight
@y += 1
self.through = true
end
move_right_stairs(turn_enabled)
new_tag = self.map.terrain_tag(@x, @y)
if old_x != @x
if old_tag != PBTerrain::StairLeft && new_tag == PBTerrain::StairLeft ||
old_tag != PBTerrain::StairRight && new_tag == PBTerrain::StairRight
self.offset_y = -16
@y += 1 if new_tag == PBTerrain::StairRight
elsif old_tag == PBTerrain::StairLeft && new_tag != PBTerrain::StairLeft ||
old_tag == PBTerrain::StairRight && new_tag != PBTerrain::StairRight
self.offset_y = 0
end
end
self.through = old_through
end
alias center_stairs center
def center(x,y)
center_stairs(x,y)
self.map.display_x = self.map.display_x + (@offset_x || 0)
self.map.display_y = self.map.display_y + (@offset_y || 0)
end
def passable?(x, y, d)
# Get new coordinates
new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
# If coordinates are outside of map
unless $game_map.validLax?(new_x, new_y)
# Impassable
return false
end
if !$game_map.valid?(new_x, new_y)
return false if !$MapFactory
return $MapFactory.isPassableFromEdge?(new_x, new_y)
end
# If debug mode is ON and ctrl key was pressed
if $DEBUG and Input.press?(Input::CTRL)
# Passable
return true
elsif d == 8 && new_y > 0 # prevent player moving up past the top of the stairs
if $game_map.terrain_tag(new_x, new_y) == PBTerrain::StairLeft &&
$game_map.terrain_tag(new_x, new_y-1) != PBTerrain::StairLeft
return false
elsif $game_map.terrain_tag(new_x, new_y) == PBTerrain::StairRight &&
$game_map.terrain_tag(new_x, new_y-1) != PBTerrain::StairRight
return false
end
end
super
end
end
If you'd like to support followers, change this code inside the Followers script:
Spoiler:
Underneath these lines
Code:
for i in 0...facings.length
facing=facings[i]
tile=$MapFactory.getFacingTile(facing,leader)
Add this block of code:
Code:
if tile[1] > $game_player.x
tile[2] -= 1 if $MapFactory.getTerrainTag(tile[0],tile[1],tile[2]-1) == PBTerrain::StairLeft && $game_map.terrain_tag($game_player.x,$game_player.y) == PBTerrain::StairLeft
elsif tile[1] < $game_player.x
tile[2] += 1 if $MapFactory.getTerrainTag(tile[0],tile[1],tile[2]+1) == PBTerrain::StairLeft
end
if tile[1] > $game_player.x
tile[2] += 1 if $MapFactory.getTerrainTag(tile[0],tile[1],tile[2]+1) == PBTerrain::StairRight
elsif tile[1] < $game_player.x
tile[2] -= 1 if $MapFactory.getTerrainTag(tile[0],tile[1],tile[2]-1) == PBTerrain::StairRight && $game_map.terrain_tag($game_player.x,$game_player.y) == PBTerrain::StairRight
end
Then VERY IMPORTANT: set up your stair tiles with the appropriate terrain tags and this exact passability:
![[PokeCommunity.com] [v18] Terrain Tag Side Stairs [PokeCommunity.com] [v18] Terrain Tag Side Stairs](https://i.imgur.com/nvPxGgs.png)
And it should be good to go! All the movement is handled automatically from here on.
Last edited: