じ☆ve冰风 发表于 2026-7-11 09:16:09

Cliff Bugfix - Avoiding the biggest cliff problem on XP

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.

Spoiler: Screen


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

Spoiler: How to get the tile IDBy 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:       
#==============================================================================# ** 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 => # Each object on that list is an array with #* 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.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: MountainTOP_TILES = [, , , , , ]CORNER_TILES = [, , , ]# 005: BeachTOP_TILES = [, , , , , ]CORNER_TILES = [, , , ]# 006: DesertTOP_TILES = [, , , , , ]CORNER_TILES = [, , , ]# 008: ShowfieldTOP_TILES = [, , , , , ]CORNER_TILES = [, , , ]# 017: MineTownTOP_TILES = [, , ]CORNER_TILES = [, ]# 019: DesertTownTOP_TILES = [, , ]CORNER_TILES = [, ]# 023: FarmVillageTOP_TILES = [, , , , , ]CORNER_TILES = [, , , ]# 032: HeavenTOP_TILES = [, , , , , ]CORNER_TILES = [, , , ]# 034: BridgeTOP_TILES = [, , ]CORNER_TILES = [, ]# 037: FortTOP_TILES = [, , ]CORNER_TILES = [, ]# 039: TowerTOP_TILES = [, , ]CORNER_TILES = [, ]# 041: EvilCastleTOP_TILES = [, , , , , ]CORNER_TILES = [, , , ]# 042: EvilCastle (interior)TOP_TILES = [, , ]CORNER_TILES = [, ]# 043: CaveTOP_TILES = [, , ]CORNER_TILES = [, , , ]# 044: Cave 2TOP_TILES = [, , ]CORNER_TILES = [, , , ]# 045: Cave 3TOP_TILES = [, , ]CORNER_TILES = [, , , ]# 046: Cave 4TOP_TILES = [, , ]CORNER_TILES = [, , , ]# 047: MineTOP_TILES = [, , ]CORNER_TILES = [, ]# 049: InnerBodyTOP_TILES = [, , ]CORNER_TILES = [, ]# 050: DarkSpaceTOP_TILES = [, , , , , ]CORNER_TILES = [, , , ]#----------------------------------------------------------------------------PASSABLE_TRIGGER_FIX = trueMULTICOUNTER_FIX = true#----------------------------------------------------------------------------TOP_TILES.default = []    # Don't chageCORNER_TILES.default = [] # Don't chageend#==============================================================================# ** Tile_Passage #==============================================================================class Tile_Passageattr_accessor :bitdef initialize(bit)    @bit = bit    @square= bit & 0x10    @ladder= bit & 0x20 # Unused    @bush    = bit & 0x40    @counter = bit & 0x80    @passage = bit - @square - @ladder - @bush - @counterenddef passage=(passage)    @passage = passage    @bit = @passage + @square + @ladder + @bush + @counterendend#==============================================================================# ** Game_Map#==============================================================================class Game_Map#----------------------------------------------------------------------------# * Get the current tileset ID#----------------------------------------------------------------------------def tileset_id    return @map.tileset_idend#----------------------------------------------------------------------------# * Get the tiles on a given a coordinate#----------------------------------------------------------------------------def get_tiles(x, y)    return , data, data]end#----------------------------------------------------------------------------# * Get the passages on a given coordinate#----------------------------------------------------------------------------def map_flag_passages(x, y)    t = get_tiles(x, y)    return [@passages], @passages], @passages]]end#----------------------------------------------------------------------------# * Get the priorities on a given coordinate#----------------------------------------------------------------------------def map_flag_priorities(x, y)    t = get_tiles(x, y)    return [@priorities], @priorities], @priorities]]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       passage = passable_array      priority = priority_array      if passage & bit != 0      return false      elsif passage & 0x0f == 0x0f      return false      elsif priority == 0      return true      end    end    return trueendend#==============================================================================# ** Game_Character#==============================================================================class Game_Character#----------------------------------------------------------------------------attr_accessor :top_mode, :top_mode_temp_move, :top_mode_temp_stopattr_accessor :top_emsta_tilesattr_accessor :passable_touchattr_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_moveend#----------------------------------------------------------------------------# * 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 = falseend#----------------------------------------------------------------------------# * 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 / 4end#----------------------------------------------------------------------------# * 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 / 4end#----------------------------------------------------------------------------# * 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 resultend#----------------------------------------------------------------------------# * Update event (stop)#----------------------------------------------------------------------------def update_stop    top_mode_stop    @move_count = 0    @top_mode_temp_stop = falseend#----------------------------------------------------------------------------# * 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 += 1end#----------------------------------------------------------------------------# * 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)    endend#----------------------------------------------------------------------------# * 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)    endend#----------------------------------------------------------------------------# * 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)    endend#----------------------------------------------------------------------------# * 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)    endend#----------------------------------------------------------------------------# * 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 ifthe 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 trueend#----------------------------------------------------------------------------# * 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       next if @top_mode and i == 0      tile_id = $game_map.data[@x, @y, i]      return true if $game_map.passages & 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 & 0x40 == 0x40      end      end    end    return falseend#----------------------------------------------------------------------------# * Get the bush height#----------------------------------------------------------------------------def bush_depth    if bush_mode      return 12    else      return 0    endend#----------------------------------------------------------------------------# * 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 }    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)    endend#----------------------------------------------------------------------------# * 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 }    corner_tiles_cr = corner_tiles.select{|t| t == 'CR'}    corner_tiles_cl = corner_tiles.select{|t| t == 'CL'}    corner_tiles_cr.collect! {|t| t }    corner_tiles_cl.collect! {|t| t }    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    endend#----------------------------------------------------------------------------# * 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 == new_x && t == new_y && t == tile    end    sprite = 1    @top_emsta_tiles.push(sprite)end#----------------------------------------------------------------------------# * 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 == @x && t == @y && t == tile    end    sprite = 1    @top_emsta_tiles.push(sprite)end#----------------------------------------------------------------------------# * 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      check_top = top_tiles.select{|t| t == tile}      if !check_top.nil?          priorities = 0          bit_data = Tile_Passage.new(passages)          case check_top          when 'L'            bit_data.passage = 0x0A          when 'C'            bit_data.passage = 0x08          when 'R'            bit_data.passage = 0x0C          end          passages = bit_data.bit      end      end    else      for i in 0...current_tiles.size      tile = current_tiles      check_top = corner_tiles.select{|t| t == tile}      if !check_top.nil?          bit_data = Tile_Passage.new(passages)          case check_top          when 'CL', 'CR'            bit_data.passage = 0x00          end          passages = bit_data.bit      end      end    end    return end#----------------------------------------------------------------------------# * 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 == 'CR'}    corner_tiles_cl = corner_tiles.select{|t| t == 'CL'}    corner_tiles_cr.collect! {|t| t }    corner_tiles_cl.collect! {|t| t }    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          check_top = top_tiles.select{|t| t == tile}          if !check_top.nil?            priorities = 0            bit_data = Tile_Passage.new(passages)            case check_top            when 'L'            bit_data.passage = 0x0A            when 'C'            bit_data.passage = 0x08            when 'R'            bit_data.passage = 0x0C            end            passages = bit_data.bit          end      end      end    else      for i in 0...target_tiles.size      tile = target_tiles      check_top = corner_tiles.select{|t| t == tile}      if !check_top.nil?          bit_data = Tile_Passage.new(passages)          case check_top          when 'CL', 'CR'            bit_data.passage = 0x00          end          passages = bit_data.bit      end      end    end    return end#----------------------------------------------------------------------------# * 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 }    corner_tiles.collect! {|t| t }    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 & bit != 0          return false if $game_map.passages & 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 trueendend#==============================================================================# ** 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 trueendend#==============================================================================# ** 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 }    corner_tiles.collect! {|t| t }    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 resultend#--------------------------------------------------------------------------# * 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 .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 resultendend


Spoiler: AgreementsThis code was made possible thanks to Silvanash, Ledai, Teivko, Eron, Orochii, AsFzKakarotto and schM0ggi.


本贴来自国际rpgmaker官方论坛作者:Wecoc处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/cliff-bugfix-avoiding-the-biggest-cliff-problem-on-xp.138508/
页: [1]
查看完整版本: Cliff Bugfix - Avoiding the biggest cliff problem on XP