- Joined
- Jul 4, 2021
- Messages
- 81
- Reaction score
- 256
- First Language
- Catalan
- Primarily Uses
- RMXP
By default, on RPG maker XP there are two types of cliffs, tall and short ones.
Their passability and priority is different:
- On tall cliffs you CAN'T reach the edge, but you CAN walk below it.
- On short cliffs you CAN reach the edge, but you CAN'T walk below it.
This script allows to get the best of both cases on a single cliff type, so you CAN reach the edge and CAN walk below it; it basically acts one way or another based on where you got from.
I must say it's not the most intuitive script, but maybe in a future I will also release a configuration helper. For now the instructions are on the script, and if anyone has doubts about it, don't hesitate to ask them here. Sadly it also isn't the most compatible script ever, it overwrites some methods of both Game_Character and Game_Event, so have that in mind.
This script is also compatible with Extended Map Sprite Tiles & Autotiles (EMSTA). The script doesn't require it, but I recommend using both because it helps on the most complex cases.
Author: Wecoc
First Release: October 2018
Last Version: November 2018
Terms of use
- Giving credits (Wecoc) for using this script is optional, but appreciated.
- You can repost this code.
- You can edit this code freely, and distribute the edits as well.
- This code can be used on commercial games.
Instructions
On the database you must define those tiles as if they were tall cliffs. Each tileset supports as many cliffs as you want.
Then you must include those tile IDs on TOP_TILES and CORNER_TILES (see instructions on the script for more details).
Each tile type uses a distinct letter on the configuration:
There are also some constants con the configuration (see instructions on the script).
Script calls
In case you define an event on a map coordinate that has a cliff tile, it may be ambiguous to where should it appear, on top or below the cliff. By default it will appear below, but you can change that with this script call:
$game_map.events[ID].top_mode = true
You can't interact with an event that isn't on the same altitude as the player by default, even if it's in front of it by coordinate. To fix that (for example a flying event) use both the script call to send it on top and this one:
$game_map.events[ID].passable_touch = true
Code
Their passability and priority is different:
- On tall cliffs you CAN'T reach the edge, but you CAN walk below it.
- On short cliffs you CAN reach the edge, but you CAN'T walk below it.

This script allows to get the best of both cases on a single cliff type, so you CAN reach the edge and CAN walk below it; it basically acts one way or another based on where you got from.

I must say it's not the most intuitive script, but maybe in a future I will also release a configuration helper. For now the instructions are on the script, and if anyone has doubts about it, don't hesitate to ask them here. Sadly it also isn't the most compatible script ever, it overwrites some methods of both Game_Character and Game_Event, so have that in mind.
This script is also compatible with Extended Map Sprite Tiles & Autotiles (EMSTA). The script doesn't require it, but I recommend using both because it helps on the most complex cases.
Author: Wecoc
First Release: October 2018
Last Version: November 2018
Terms of use
- Giving credits (Wecoc) for using this script is optional, but appreciated.
- You can repost this code.
- You can edit this code freely, and distribute the edits as well.
- This code can be used on commercial games.
Instructions
On the database you must define those tiles as if they were tall cliffs. Each tileset supports as many cliffs as you want.
Then you must include those tile IDs on TOP_TILES and CORNER_TILES (see instructions on the script for more details).
By default, the tile on the top-left has ID = 0. The script has an option to include autotiles (non-recommended), therefore tha tile would have ID = 384 instead. Then it increases by one and there are 8 in each row, so a tile with coordinates X=7, Y=3 on the tileset will be 0 + 8*3 + 7 = 31. If you're using WecTools or MENTOR they have options to easily get the tile ID as well.
Each tile type uses a distinct letter on the configuration:

There are also some constants con the configuration (see instructions on the script).
Script calls
In case you define an event on a map coordinate that has a cliff tile, it may be ambiguous to where should it appear, on top or below the cliff. By default it will appear below, but you can change that with this script call:
$game_map.events[ID].top_mode = true
You can't interact with an event that isn't on the same altitude as the player by default, even if it's in front of it by coordinate. To fix that (for example a flying event) use both the script call to send it on top and this one:
$game_map.events[ID].passable_touch = true
Code
Ruby:
#==============================================================================
# ** [XP] Cliff Bugfix v1.1
#------------------------------------------------------------------------------
# Author: Wecoc (credits are optional but appreciated)
#==============================================================================
# By default RPG maker XP has a little problem, the top of the cliffs can be
# either over or under the player, but not both. This script solves that issue.
# Also it goes further and fixes it for events so you can't interact with them
# from above or from below, you must be on the same altitude.
# This script is a bit complicated in some cases so it's not for newbies.
#------------------------------------------------------------------------------
# I recommend using it with Extended Map Sprite Tiles & Autotiles (EMSTA)
# The script doesn't require it but it helps solving some more complex cases
# between cliffs of distint altitude.
#==============================================================================
# ** Configuration
#==============================================================================
# On the database the cliff tiles must be defined as a default tall cliff, the
# script will read it like a short cliff when you're on top.
# You must configurate the CliffTop module, on the very start of the code.
#------------------------------------------------------------------------------
# TOP_TILES defines the tiles than can be either above or below the player.
# You define them using Tileset ID => [tiles]
# Each object on that list is an array with [Tile ID, Position]
# * Tileset ID - The number of the tileset on the database list
# * Tile ID - Tile index inside the tileset. You can count it manually or
# using tools to get it, for example WecTools or MENTOR.
# * Position: 'L': Left, 'C': Center, 'R': Right
#------------------------------------------------------------------------------
# CORNER_TILES defines the tiles that correspond to the superior corners
# of the cliff. It's defined the same way as in TOP_TILES, except
# * Position: 'CL': (Corner)Left, 'CR': (Corner)Right
#------------------------------------------------------------------------------
# INCLUDE_AUTOTILES defines if on Tile IDs defined previously you should
# include autotiles. In that case you will have to add 384 to their value.
#------------------------------------------------------------------------------
# PASSABLE_TRIGGER_FIX doesn't allow interaction with events that aren't on
# the same altitude as the player.
#------------------------------------------------------------------------------
# MULTICOUNTER_FIX is a little bugfix on the Counter option in the Database.
# It allows to interact with events even if more that one counter tile
# separates them.
#==============================================================================
# ** Script calls
#==============================================================================
# If you create an event on a map coordinate that contains a cliff tile, it
# will be created below the cliff by default. You can send it on top using
# this from another event on Parallel Process:
# $game_map.events[ID].top_mode = true
#
# Change 'ID' to the Event ID you want to move. If there's more than one, you
# can change them all from the same event.
#==============================================================================
#==============================================================================
# ** CliffTop
#==============================================================================
module CliffTop
#----------------------------------------------------------------------------
# Configuration
#----------------------------------------------------------------------------
TOP_TILES = {}
CORNER_TILES = {}
INCLUDE_AUTOTILES = false
#----------------------------------------------------------------------------
# 004: Mountain
TOP_TILES[4] = [[40,'L'], [41,'C'], [42,'R'], [29,'L'], [30,'C'], [31,'R']]
CORNER_TILES[4] = [[43,'CL'], [44,'CR'], [67,'CL'], [68,'CR']]
# 005: Beach
TOP_TILES[5] = [[24,'L'], [25,'C'], [26,'R'], [29,'L'], [30,'C'], [31,'R']]
CORNER_TILES[5] = [[27,'CL'], [28,'CR'], [51,'CL'], [52,'CR']]
# 006: Desert
TOP_TILES[6] = [[40,'L'], [41,'C'], [42,'R'], [45,'L'], [46,'C'], [47,'R']]
CORNER_TILES[6] = [[43,'CL'], [44,'CR'], [67,'CL'], [68,'CR']]
# 008: Showfield
TOP_TILES[8] = [[48,'L'], [49,'C'], [50,'R'], [37,'L'], [38,'C'], [39,'R']]
CORNER_TILES[8] = [[51,'CL'], [52,'CR'], [75,'CL'], [76,'CR']]
# 017: MineTown
TOP_TILES[17] = [[49,'L'], [50,'C'], [51,'R']]
CORNER_TILES[17] = [[52,'CL'], [53,'CR']]
# 019: DesertTown
TOP_TILES[19] = [[40,'L'], [41,'C'], [42,'R']]
CORNER_TILES[19] = [[43,'CL'], [44,'CR']]
# 023: FarmVillage
TOP_TILES[23] = [[64,'L'], [65,'C'], [66,'R'], [69,'L'], [70,'C'], [71,'R']]
CORNER_TILES[23] = [[67,'CL'], [68,'CR'], [91,'CL'], [92,'CR']]
# 032: Heaven
TOP_TILES[32] = [[16,'L'], [17,'C'], [18,'R'], [21,'L'], [22,'C'], [23,'R']]
CORNER_TILES[32] = [[35,'CL'], [36,'CR'], [19,'CL'], [20,'CR']]
# 034: Bridge
TOP_TILES[34] = [[16,'L'], [17,'C'], [18,'R']]
CORNER_TILES[34] = [[19,'CL'], [20,'CR']]
# 037: Fort
TOP_TILES[37] = [[24,'L'], [25,'C'], [26,'R']]
CORNER_TILES[37] = [[27,'CL'], [28,'CR']]
# 039: Tower
TOP_TILES[39] = [[16,'L'], [17,'C'], [18,'R']]
CORNER_TILES[39] = [[19,'CL'], [20,'CR']]
# 041: EvilCastle
TOP_TILES[41] = [[32,'L'], [33,'C'], [34,'R'], [37,'L'], [38,'C'], [39,'R']]
CORNER_TILES[41] = [[35,'CL'], [36,'CR'], [59,'CL'], [60,'CR']]
# 042: EvilCastle (interior)
TOP_TILES[42] = [[21,'L'], [22,'C'], [23,'R']]
CORNER_TILES[42] = [[35,'CL'], [36,'CR']]
# 043: Cave
TOP_TILES[43] = [[37,'L'], [38,'C'], [39,'R']]
CORNER_TILES[43] = [[59,'CL'], [60,'CR'], [67,'CL'], [68,'CR']]
# 044: Cave 2
TOP_TILES[44] = [[37,'L'], [38,'C'], [39,'R']]
CORNER_TILES[44] = [[59,'CL'], [60,'CR'], [67,'CL'], [68,'CR']]
# 045: Cave 3
TOP_TILES[45] = [[37,'L'], [38,'C'], [39,'R']]
CORNER_TILES[45] = [[59,'CL'], [60,'CR'], [67,'CL'], [68,'CR']]
# 046: Cave 4
TOP_TILES[46] = [[37,'L'], [38,'C'], [39,'R']]
CORNER_TILES[46] = [[59,'CL'], [60,'CR'], [67,'CL'], [68,'CR']]
# 047: Mine
TOP_TILES[47] = [[21,'L'], [22,'C'], [23,'R']]
CORNER_TILES[47] = [[35,'CL'], [36,'CR']]
# 049: InnerBody
TOP_TILES[49] = [[45,'L'], [46,'C'], [47,'R']]
CORNER_TILES[49] = [[67,'CL'], [68,'CR']]
# 050: DarkSpace
TOP_TILES[50] = [[53,'L'], [54,'C'], [55,'R'], [48,'L'], [49,'C'], [50,'R']]
CORNER_TILES[50] = [[28,'CL'], [29,'CR'], [51,'CL'], [52,'CR']]
#----------------------------------------------------------------------------
PASSABLE_TRIGGER_FIX = true
MULTICOUNTER_FIX = true
#----------------------------------------------------------------------------
TOP_TILES.default = [] # Don't chage
CORNER_TILES.default = [] # Don't chage
end
#==============================================================================
# ** Tile_Passage [Scripter's Tool]
#==============================================================================
class Tile_Passage
attr_accessor :bit
def initialize(bit)
@bit = bit
@square = bit & 0x10
@ladder = bit & 0x20 # Unused
@bush = bit & 0x40
@counter = bit & 0x80
@passage = bit - @square - @ladder - @bush - @counter
end
def passage=(passage)
@passage = passage
@bit = @passage + @square + @ladder + @bush + @counter
end
end
#==============================================================================
# ** Game_Map
#==============================================================================
class Game_Map
#----------------------------------------------------------------------------
# * Get the current tileset ID
#----------------------------------------------------------------------------
def tileset_id
return @map.tileset_id
end
#----------------------------------------------------------------------------
# * Get the tiles on a given a coordinate
#----------------------------------------------------------------------------
def get_tiles(x, y)
return [data[x, y, 0], data[x, y, 1], data[x, y, 2]]
end
#----------------------------------------------------------------------------
# * Get the passages on a given coordinate
#----------------------------------------------------------------------------
def map_flag_passages(x, y)
t = get_tiles(x, y)
return [@passages[t[0]], @passages[t[1]], @passages[t[2]]]
end
#----------------------------------------------------------------------------
# * Get the priorities on a given coordinate
#----------------------------------------------------------------------------
def map_flag_priorities(x, y)
t = get_tiles(x, y)
return [@priorities[t[0]], @priorities[t[1]], @priorities[t[2]]]
end
#----------------------------------------------------------------------------
# * Check passability given passable and priority data
#----------------------------------------------------------------------------
def flag_passable?(passable_array, priority_array, d)
bit = (1 << (d / 2 - 1)) & 0x0f
for i in [2, 1, 0]
passage = passable_array[i]
priority = priority_array[i]
if passage & bit != 0
return false
elsif passage & 0x0f == 0x0f
return false
elsif priority == 0
return true
end
end
return true
end
end
#==============================================================================
# ** Game_Character
#==============================================================================
class Game_Character
#----------------------------------------------------------------------------
attr_accessor :top_mode, :top_mode_temp_move, :top_mode_temp_stop
attr_accessor :top_emsta_tiles
attr_accessor :passable_touch
attr_reader :move_count
#----------------------------------------------------------------------------
unless $@
alias top_mode_ini initialize
alias top_mode_screen_z screen_z
alias top_mode_stop update_stop
alias top_mode_move update_move
end
#----------------------------------------------------------------------------
# * Start
#----------------------------------------------------------------------------
def initialize(*args)
top_mode_ini(*args)
@top_mode = false
@top_mode_temp_move = false
@top_mode_temp_stop = false
@top_emsta_tiles = []
@move_count = 0
@passable_touch = false
end
#----------------------------------------------------------------------------
# * Get character width
#----------------------------------------------------------------------------
def character_width
return 32 if @tile_id > 0
return 0 if @character_name == ""
return RPG::Cache.character(@character_name, 0).width / 4
end
#----------------------------------------------------------------------------
# * Get character height
#----------------------------------------------------------------------------
def character_height
return 32 if @tile_id > 0
return 0 if @character_name == ""
return RPG::Cache.character(@character_name, 0).height / 4
end
#----------------------------------------------------------------------------
# * Get event Z
#----------------------------------------------------------------------------
def screen_z(*args)
result = top_mode_screen_z(*args)
if @top_mode || @top_mode_temp_move || @top_mode_temp_stop
if self.character_height <= 32
result += 32
else
result += 1
end
end
return result
end
#----------------------------------------------------------------------------
# * Update event (stop)
#----------------------------------------------------------------------------
def update_stop
top_mode_stop
@move_count = 0
@top_mode_temp_stop = false
end
#----------------------------------------------------------------------------
# * Update event (move)
#----------------------------------------------------------------------------
def update_move
top_mode_move
if @move_count > 0
@top_mode_temp_move = false
if (@real_x / 4) % 32 == 0 && (@real_y / 4) % 32 == 0
if @top_emsta_tiles.size > 0
for tile in @top_emsta_tiles
$game_map.sprite_tiles.delete($game_map.sprite_tiles.key(tile))
end
end
@top_mode_temp_stop = false
end
end
@move_count += 1
end
#----------------------------------------------------------------------------
# * Move down
#----------------------------------------------------------------------------
def move_down(turn_enabled = true)
turn_down if turn_enabled
if passable?(@x, @y, 2)
if @top_mode == true && @always_on_top == false
current_tiles = $game_map.get_tiles(@x, @y)
target_tiles = $game_map.get_tiles(@x, @y + 1)
move_v_set_top_(current_tiles, target_tiles)
if @top_mode == false
@top_mode_temp_move = true
end
end
turn_down
@y += 1
increase_steps
else
check_event_trigger_touch(@x, @y+1)
end
end
#----------------------------------------------------------------------------
# * Move left
#----------------------------------------------------------------------------
def move_left(turn_enabled = true)
turn_left if turn_enabled
if passable?(@x, @y, 4)
if @always_on_top == false
current_tiles = $game_map.get_tiles(@x, @y)
target_tiles = $game_map.get_tiles(@x - 1, @y)
move_h_set_top_(current_tiles, target_tiles)
end
turn_left
@x -= 1
increase_steps
else
check_event_trigger_touch(@x-1, @y)
end
end
#----------------------------------------------------------------------------
# * Move right
#----------------------------------------------------------------------------
def move_right(turn_enabled = true)
turn_right if turn_enabled
if passable?(@x, @y, 6)
if @always_on_top == false
current_tiles = $game_map.get_tiles(@x, @y)
target_tiles = $game_map.get_tiles(@x + 1, @y)
move_h_set_top_(current_tiles, target_tiles)
end
turn_right
@x += 1
increase_steps
else
check_event_trigger_touch(@x+1, @y)
end
end
#----------------------------------------------------------------------------
# * Move up
#----------------------------------------------------------------------------
def move_up(turn_enabled = true)
turn_up if turn_enabled
if passable?(@x, @y, 8)
if @top_mode == false && @always_on_top == false
current_tiles = $game_map.get_tiles(@x, @y)
target_tiles = $game_map.get_tiles(@x, @y - 1)
move_v_set_top_(current_tiles, target_tiles)
end
turn_up
@y -= 1
increase_steps
else
check_event_trigger_touch(@x, @y-1)
end
end
#----------------------------------------------------------------------------
# * Check passability
#----------------------------------------------------------------------------
def passable?(x, y, d)
new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
# Check if the new coordinate is still on the map
return false unless $game_map.valid?(new_x, new_y)
# Check if the event has the through flag activated
return true if @through
# Check if it can move from the current tile
passages, priorities = *passable_get_current_tile_(x, y, new_x, new_y, d)
return false unless $game_map.flag_passable?(passages, priorities, d)
# Check if it can move to the new tile
passages, priorities = *passable_get_target_tile_(x, y, new_x, new_y, d)
return false unless $game_map.flag_passable?(passages, priorities, 10 - d)
# Check if there's any event on the new tile
return false if passable_events_(x, y, new_x, new_y, d) == false
return true
end
#----------------------------------------------------------------------------
# * Check if the event is over bush
#----------------------------------------------------------------------------
def bush_mode
return false if @tile_id > 0 or @always_on_top
return false if @jump_count > 0
# Tile bush
for i in [2, 1, 0]
next if @top_mode and i == 0
tile_id = $game_map.data[@x, @y, i]
return true if $game_map.passages[tile_id] & 0x40 == 0x40
end
# Event bush
for event in $game_map.events.values
next if event == self
if event.x == @x && event.y == @y
if event.tile_id > 0
next if @top_mode != event.top_mode
return true if $game_map.passages[event.tile_id] & 0x40 == 0x40
end
end
end
return false
end
#----------------------------------------------------------------------------
# * Get the bush height
#----------------------------------------------------------------------------
def bush_depth
if bush_mode
return 12
else
return 0
end
end
#----------------------------------------------------------------------------
# * [Private] Get if the player is moving on top/below the cliff (vertical)
#----------------------------------------------------------------------------
def move_v_set_top_(current_tiles, target_tiles)
top_tiles = CliffTop::TOP_TILES[$game_map.tileset_id].clone
top_tiles.collect! {|t| t[0] }
if CliffTop::INCLUDE_AUTOTILES == false
top_tiles.map! {|t| t + 384 }
end
@top_mode = false
if @direction == 2
for tile in current_tiles
return if top_tiles.include?(tile)
end
end
for tile in target_tiles
@top_mode = true if top_tiles.include?(tile)
end
end
#----------------------------------------------------------------------------
# * [Private] Get if the player is moving on top/below the cliff (horizontal)
#----------------------------------------------------------------------------
def move_h_set_top_(current_tiles, target_tiles)
top_tiles = CliffTop::TOP_TILES[$game_map.tileset_id].clone
corner_tiles = CliffTop::CORNER_TILES[$game_map.tileset_id].clone
top_tiles.collect! {|t| t[0] }
corner_tiles_cr = corner_tiles.select{|t| t[1] == 'CR'}
corner_tiles_cl = corner_tiles.select{|t| t[1] == 'CL'}
corner_tiles_cr.collect! {|t| t[0] }
corner_tiles_cl.collect! {|t| t[0] }
if CliffTop::INCLUDE_AUTOTILES == false
top_tiles.map! {|t| t + 384 }
corner_tiles_cr.map! {|t| t + 384 }
corner_tiles_cl.map! {|t| t + 384 }
end
if @top_mode == false
from_top = false
if @direction == 4
for tile in current_tiles
if corner_tiles_cl.include?(tile)
from_top = true
end
end
end
if @direction == 6
for tile in current_tiles
if corner_tiles_cr.include?(tile)
from_top = true
end
end
end
if from_top == true
for tile in target_tiles
if top_tiles.include?(tile)
@top_mode = true
end
end
end
if @top_mode == true
if $game_map.respond_to?(:set_sprite_tile)
for tile in current_tiles
if top_tiles.include?(tile)
move_top_emsta_exit_(tile)
end
end
end
end
else
stay_in_top = false
for tile in target_tiles
if top_tiles.include?(tile)
stay_in_top = true
end
end
if stay_in_top
if @direction == 4
for tile in target_tiles
if corner_tiles_cr.include?(tile)
stay_in_top = false
end
end
end
if @direction == 6
for tile in target_tiles
if corner_tiles_cl.include?(tile)
stay_in_top = false
end
end
end
if stay_in_top == false
if $game_map.respond_to?(:set_sprite_tile)
for tile in target_tiles
if top_tiles.include?(tile)
move_top_emsta_enter_(tile)
end
end
end
end
end
if stay_in_top == false
@top_mode = false
@top_mode_temp_stop = true
end
end
end
#----------------------------------------------------------------------------
# * [Private] Draw EMSTA when entering on a conflitive event Corner + Cliff
#----------------------------------------------------------------------------
def move_top_emsta_enter_(tile)
d = @direction
new_x = @x + (d == 6 ? 1 : d == 4 ? -1 : 0)
new_y = @y + (d == 2 ? 1 : d == 8 ? -1 : 0)
$game_map.set_sprite_tile(new_x, new_y, tile)
sprite = $game_map.sprite_tiles.values.select do |t|
t[0] == new_x && t[1] == new_y && t[3] == tile
end[0]
sprite[4] = 1
@top_emsta_tiles.push(sprite)
end
#----------------------------------------------------------------------------
# * [Private] Draw EMSTA when exiting a conflictive event Corner + Cliff
#----------------------------------------------------------------------------
def move_top_emsta_exit_(tile)
$game_map.set_sprite_tile(@x, @y, tile)
sprite = $game_map.sprite_tiles.values.select do |t|
t[0] == @x && t[1] == @y && t[3] == tile
end[0]
sprite[4] = 1
@top_emsta_tiles.push(sprite)
end
#----------------------------------------------------------------------------
# * [Private] Get passage and priority flags of the current tile
#----------------------------------------------------------------------------
def passable_get_current_tile_(x, y, new_x, new_y, d)
passages = $game_map.map_flag_passages(x, y)
priorities = $game_map.map_flag_priorities(x, y)
current_tiles = $game_map.get_tiles(x, y)
top_tiles = CliffTop::TOP_TILES[$game_map.tileset_id].clone
corner_tiles = CliffTop::CORNER_TILES[$game_map.tileset_id].clone
if CliffTop::INCLUDE_AUTOTILES == false
current_tiles.map! {|t| t - 384 }
end
if @top_mode == true
for i in 0...current_tiles.size
tile = current_tiles[i]
check_top = top_tiles.select{|t| t[0] == tile}[0]
if !check_top.nil?
priorities[i] = 0
bit_data = Tile_Passage.new(passages[i])
case check_top[1]
when 'L'
bit_data.passage = 0x0A
when 'C'
bit_data.passage = 0x08
when 'R'
bit_data.passage = 0x0C
end
passages[i] = bit_data.bit
end
end
else
for i in 0...current_tiles.size
tile = current_tiles[i]
check_top = corner_tiles.select{|t| t[0] == tile}[0]
if !check_top.nil?
bit_data = Tile_Passage.new(passages[i])
case check_top[1]
when 'CL', 'CR'
bit_data.passage = 0x00
end
passages[i] = bit_data.bit
end
end
end
return [passages, priorities]
end
#----------------------------------------------------------------------------
# * [Private] Get passage and priority flags of the new tile
#----------------------------------------------------------------------------
def passable_get_target_tile_(x, y, new_x, new_y, d)
passages = $game_map.map_flag_passages(new_x, new_y)
priorities = $game_map.map_flag_priorities(new_x, new_y)
from_top = false
current_tiles = $game_map.get_tiles(x, y)
corner_tiles = CliffTop::CORNER_TILES[$game_map.tileset_id].clone
corner_tiles_cr = corner_tiles.select{|t| t[1] == 'CR'}
corner_tiles_cl = corner_tiles.select{|t| t[1] == 'CL'}
corner_tiles_cr.collect! {|t| t[0] }
corner_tiles_cl.collect! {|t| t[0] }
if CliffTop::INCLUDE_AUTOTILES == false
corner_tiles_cr.map! {|t| t + 384 }
corner_tiles_cl.map! {|t| t + 384 }
end
if d == 2 || d == 8
for tile in current_tiles
from_top = true if corner_tiles_cr.include?(tile)
from_top = true if corner_tiles_cl.include?(tile)
end
end
if d == 4
for tile in current_tiles
from_top = true if corner_tiles_cl.include?(tile)
end
end
if d == 6
for tile in current_tiles
from_top = true if corner_tiles_cr.include?(tile)
end
end
target_tiles = $game_map.get_tiles(new_x, new_y)
top_tiles = CliffTop::TOP_TILES[$game_map.tileset_id].clone
corner_tiles = CliffTop::CORNER_TILES[$game_map.tileset_id].clone
if CliffTop::INCLUDE_AUTOTILES == false
target_tiles.map! {|t| t - 384 }
end
if @top_mode == false
if (d == 8 || from_top == true)
for i in 0...target_tiles.size
tile = target_tiles[i]
check_top = top_tiles.select{|t| t[0] == tile}[0]
if !check_top.nil?
priorities[i] = 0
bit_data = Tile_Passage.new(passages[i])
case check_top[1]
when 'L'
bit_data.passage = 0x0A
when 'C'
bit_data.passage = 0x08
when 'R'
bit_data.passage = 0x0C
end
passages[i] = bit_data.bit
end
end
end
else
for i in 0...target_tiles.size
tile = target_tiles[i]
check_top = corner_tiles.select{|t| t[0] == tile}[0]
if !check_top.nil?
bit_data = Tile_Passage.new(passages[i])
case check_top[1]
when 'CL', 'CR'
bit_data.passage = 0x00
end
passages[i] = bit_data.bit
end
end
end
return [passages, priorities]
end
#----------------------------------------------------------------------------
# * [Private] Get passable flag by event
#----------------------------------------------------------------------------
def passable_events_(x, y, new_x, new_y, d)
current_from_top = false
target_from_top = false
current_tiles = $game_map.get_tiles(x, y)
target_tiles = $game_map.get_tiles(new_x, new_y)
top_tiles = CliffTop::TOP_TILES[$game_map.tileset_id].clone
corner_tiles = CliffTop::CORNER_TILES[$game_map.tileset_id].clone
top_tiles.collect! {|t| t[0] }
corner_tiles.collect! {|t| t[0] }
if CliffTop::INCLUDE_AUTOTILES == false
top_tiles.map! {|t| t + 384 }
corner_tiles.map! {|t| t + 384 }
end
for tile in current_tiles
current_from_top = true if corner_tiles.include?(tile)
end
for tile in target_tiles
target_from_top = true if corner_tiles.include?(tile)
end
for event in $game_map.events.values
if event.x == new_x and event.y == new_y
next if self == event
next if event.through
next if event.character_name == "" && event.tile_id == 0
self_from_top = current_from_top
event_from_top = target_from_top
self_from_top = true if self.top_mode
event_from_top = true if event.top_mode
same_height = (self_from_top == event_from_top)
same_height = true if d == 8 && (!self_from_top && event_from_top)
same_height = true if d == 2 && (self_from_top && !event_from_top)
if d == 8 && (!self_from_top && !event_from_top)
for tile in target_tiles
self_from_top = true if top_tiles.include?(tile)
end
same_height = false if self_from_top
end
if same_height
return false if event.tile_id == 0
bit = (1 << (d / 2 - 1)) & 0x0f
return false if $game_map.passages[event.tile_id] & bit != 0
return false if $game_map.passages[event.tile_id] & 0x0f == 0x0f
end
end
end
if $game_player.x == new_x and $game_player.y == new_y
next if self == $game_player
next if $game_player.through or self.character_name == ""
self_from_top = current_from_top
player_from_top = target_from_top
self_from_top = true if self.top_mode
player_from_top = true if $game_player.top_mode
same_height = (self_from_top == player_from_top)
same_height = true if d == 8 && (!self_from_top && player_from_top)
same_height = true if d == 2 && (self_from_top && !player_from_top)
if d == 8 && (!self_from_top && !player_from_top)
for tile in target_tiles
self_from_top = true if top_tiles.include?(tile)
end
same_height = false if self_from_top
end
return false if same_height
end
return true
end
end
#==============================================================================
# ** Game_Event
#==============================================================================
class Game_Event < Game_Character
#----------------------------------------------------------------------------
# * Check if the player if over the event
#----------------------------------------------------------------------------
alias top_mode_over_trigger? over_trigger? unless $@
def over_trigger?
return false if top_mode_over_trigger? == false
return false if $game_player.top_mode != self.top_mode
return true
end
end
#==============================================================================
# ** Game_Player
#==============================================================================
class Game_Player < Game_Character
#--------------------------------------------------------------------------
# * Activate event when key trigger
#--------------------------------------------------------------------------
def check_event_trigger_there(triggers)
result = false
return result if $game_system.map_interpreter.running?
new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
d = @direction
current_from_top = false
target_from_top = false
current_tiles = $game_map.get_tiles(@x, @y)
target_tiles = $game_map.get_tiles(new_x, new_y)
top_tiles = CliffTop::TOP_TILES[$game_map.tileset_id].clone
corner_tiles = CliffTop::CORNER_TILES[$game_map.tileset_id].clone
top_tiles.collect! {|t| t[0] }
corner_tiles.collect! {|t| t[0] }
if CliffTop::INCLUDE_AUTOTILES == false
top_tiles.map! {|t| t + 384 }
corner_tiles.map! {|t| t + 384 }
end
for tile in current_tiles
current_from_top = true if corner_tiles.include?(tile)
end
for tile in target_tiles
target_from_top = true if corner_tiles.include?(tile)
end
# Press C in front of the event
for event in $game_map.events.values
if event.x == new_x and event.y == new_y and
triggers.include?(event.trigger)
if not event.jumping? and not event.top_mode_over_trigger?
if CliffTop::PASSABLE_TRIGGER_FIX && event.passable_touch == false
passages, priorities = *passable_get_current_tile_(@x, @y,
new_x, new_y, d)
next if !$game_map.flag_passable?(passages, priorities, d)
end
self_from_top = current_from_top
event_from_top = target_from_top
self_from_top = true if self.top_mode
event_from_top = true if event.top_mode
same_height = (self_from_top == event_from_top)
same_height = true if d == 8 && (!self_from_top && event_from_top)
same_height = true if d == 2 && (self_from_top && !event_from_top)
if d == 8 && (!self_from_top && !event_from_top)
for tile in target_tiles
self_from_top = true if top_tiles.include?(tile)
end
same_height = false if self_from_top
end
if same_height
event.start
result = true
end
end
end
end
if result == false
# Press C in front of the event (counter mode)
if $game_map.counter?(new_x, new_y)
if CliffTop::MULTICOUNTER_FIX
loop do
new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
break if !$game_map.counter?(new_x, new_y)
end
else
new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
end
for event in $game_map.events.values
if event.x == new_x and event.y == new_y and
triggers.include?(event.trigger)
if not event.jumping? and not event.over_trigger?
event.start
result = true
end
end
end
end
end
return result
end
#--------------------------------------------------------------------------
# * Activate event on touch
#--------------------------------------------------------------------------
def check_event_trigger_touch(x, y)
result = false
d = @direction
return result if $game_system.map_interpreter.running?
for event in $game_map.events.values
if event.x == x and event.y == y and [1,2].include?(event.trigger)
if not event.jumping? and not event.over_trigger?
if CliffTop::PASSABLE_TRIGGER_FIX && event.passable_touch == false
passages, priorities = *passable_get_current_tile_(@x, @y, x, y, d)
next if !$game_map.flag_passable?(passages, priorities, d)
end
event.start
result = true
end
end
end
return result
end
end
This code was made possible thanks to Silvanash, Ledai, Teivko, Eron, Orochii, AsFzKakarotto and schM0ggi.
Last edited: