Wecoc

Veteran
Veteran
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.

tileset_cliff_muestra01.png


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.

acantilado02.png

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:
acantilado-c-digo.png


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:

Shaz

Global Moderators
Global Mod
Joined
Mar 2, 2012
Messages
44,789
Reaction score
15,914
First Language
English
Primarily Uses
RMMV
Please do not use red or blue text in your post, as these are reserved for moderator and admin actions.
 

Latest Threads

Latest Posts

Forum statistics

Threads
124,331
Messages
1,162,839
Members
163,134
Latest member
GanSan
Top