设为首页收藏本站同能贴吧 切换语言 繁体中文
开启辅助访问 切换到窄版
扫描二维码关注官方公众号
返回列表
+ 发新帖
查看: 51|回复: 0

[转载发布] Cliff Bugfix - Avoiding the biggest cliff problem on XP

[复制链接]
累计送礼:
0 个
累计收礼:
1 个
  • TA的每日心情
    开心
    前天 04:10
  • 签到天数: 209 天

    连续签到: 2 天

    [LV.7]常住居民III

    4469

    主题

    864

    回帖

    2万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    7
    卡币
    22945
    OK点
    16
    推广点
    0
    同能卷
    50
    积分
    28308

    灌水之王

    发表于 3 天前 | 显示全部楼层 |阅读模式
    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
    [/quote]

    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 ID[quote]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 chageend#==============================================================================# ** 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  endend#==============================================================================# ** 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      priority = priority_array      if passage & bit != 0        return false      elsif passage & 0x0f == 0x0f        return false      elsif priority == 0        return true      end    end    return true  endend#==============================================================================# ** 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        check_top = top_tiles.select{|t| t[0] == tile}[0]        if !check_top.nil?          priorities = 0          bit_data = Tile_Passage.new(passages)          case check_top[1]          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[0] == tile}[0]        if !check_top.nil?          bit_data = Tile_Passage.new(passages)          case check_top[1]          when 'CL', 'CR'            bit_data.passage = 0x00          end          passages = 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          check_top = top_tiles.select{|t| t[0] == tile}[0]          if !check_top.nil?            priorities = 0            bit_data = Tile_Passage.new(passages)            case check_top[1]            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[0] == tile}[0]        if !check_top.nil?          bit_data = Tile_Passage.new(passages)          case check_top[1]          when 'CL', 'CR'            bit_data.passage = 0x00          end          passages = 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  endend#==============================================================================# ** 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  endend#==============================================================================# ** 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  endend


    Spoiler: Agreements
    This 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/

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x
    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    简体中文
    繁體中文
    English(英语)
    日本語(日语)
    Deutsch(德语)
    Русский язык(俄语)
    بالعربية(阿拉伯语)
    Türkçe(土耳其语)
    Português(葡萄牙语)
    ภาษาไทย(泰国语)
    한어(朝鲜语/韩语)
    Français(法语)
    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2026-7-14 17:53 , Processed in 0.126442 second(s), 55 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表