This script allows to change the tiles on the map in a way that the autotiles don't lose their property to join properly.
Author: Wecoc
First Release: February 2018
Last Version: February 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.
Ruby:
#==============================================================================# ** [XP] Map Tile Setter v1.0#------------------------------------------------------------------------------# This script allows to change the tiles on the map in a way that the autotiles# don't lose their property to join properly.#------------------------------------------------------------------------------# Script calls:# * Set tile# $game_map.set_tile(x, y, layer, tile_id)# x, y: Map coordinates# layer: Map layer (0 - bottom, 1 - middle, 2 - top)# tile_id: Tile ID, either 0 for blank or greater than 384 for any tile# on the tileset# * Set autotile# $game_map.set_autotile(x, y, layer, autotile_id)# autotile_id: Autotile index, from 1 to 7# * Change the property to autocomplete the autotiles# $game_system.autotile_autocomplete = true / false#------------------------------------------------------------------------------# Author: Wecoc (no credits required)#==============================================================================#==============================================================================# ** AutotileData#==============================================================================module AutotileData module_function #---------------------------------------------------------------------------- SUBTILES = {0 => [27, 28, 33, 34], 1 => [ 5, 28, 33, 34], 2 => [27, 6, 33, 34], 3 => [ 5, 6, 33, 34], 4 => [27, 28, 33, 12], 5 => [ 5, 28, 33, 12], 6 => [27, 6, 33, 12], 7 => [ 5, 6, 33, 12], 8 => [27, 28, 11, 34], 9 => [ 5, 28, 11, 34], 10 => [27, 6, 11, 34], 11 => [ 5, 6, 11, 34], 12 => [27, 28, 11, 12], 13 => [ 5, 28, 11, 12], 14 => [27, 6, 11, 12], 15 => [ 5, 6, 11, 12], 16 => [25, 26, 31, 32], 17 => [25, 6, 31, 32], 18 => [25, 26, 31, 12], 19 => [25, 6, 31, 12], 20 => [15, 16, 21, 22], 21 => [15, 16, 21, 12], 22 => [15, 16, 11, 22], 23 => [15, 16, 11, 12], 24 => [29, 30, 35, 36], 25 => [29, 30, 11, 36], 26 => [ 5, 30, 35, 36], 27 => [ 5, 30, 11, 36], 28 => [39, 40, 45, 46], 29 => [ 5, 40, 45, 46], 30 => [39, 6, 45, 46], 31 => [ 5, 6, 45, 46], 32 => [25, 30, 31, 36], 33 => [15, 16, 45, 46], 34 => [13, 14, 19, 20], 35 => [13, 14, 19, 12], 36 => [17, 18, 23, 24], 37 => [17, 18, 11, 24], 38 => [41, 42, 47, 48], 39 => [ 5, 42, 47, 48], 40 => [37, 38, 43, 44], 41 => [37, 6, 43, 44], 42 => [13, 18, 19, 24], 43 => [13, 14, 43, 44], 44 => [37, 42, 43, 48], 45 => [17, 18, 47, 48], 46 => [13, 18, 43, 48], 47 => [ 1, 2, 7, 8]} #---------------------------------------------------------------------------- n = nil NEIGHBORTILES = {0 => [1, 1, 1, 1, n, 1, 1, 1, 1], 1 => [0, 1, 1, 1, n, 1, 1, 1, 1], 2 => [1, 1, 0, 1, n, 1, 1, 1, 1], 3 => [0, 1, 0, 1, n, 1, 1, 1, 1], 4 => [1, 1, 1, 1, n, 1, 1, 1, 0], 5 => [0, 1, 1, 1, n, 1, 1, 1, 0], 6 => [1, 1, 0, 1, n, 1, 1, 1, 0], 7 => [0, 1, 0, 1, n, 1, 1, 1, 0], 8 => [1, 1, 1, 1, n, 1, 0, 1, 1], 9 => [0, 1, 1, 1, n, 1, 0, 1, 1], 10 => [1, 1, 0, 1, n, 1, 0, 1, 1], 11 => [0, 1, 0, 1, n, 1, 0, 1, 1], 12 => [1, 1, 1, 1, n, 1, 0, 1, 0], 13 => [0, 1, 1, 1, n, 1, 0, 1, 0], 14 => [1, 1, 0, 1, n, 1, 0, 1, 0], 15 => [0, 1, 0, 1, n, 1, 0, 1, 0], 16 => [n, 1, 1, 0, n, 1, n, 1, 1], 17 => [n, 1, 0, 0, n, 1, n, 1, 1], 18 => [n, 1, 1, 0, n, 1, n, 1, 0], 19 => [n, 1, 0, 0, n, 1, n, 1, 0], 20 => [n, 0, n, 1, n, 1, 1, 1, 1], 21 => [n, 0, n, 1, n, 1, 1, 1, 0], 22 => [n, 0, n, 1, n, 1, 0, 1, 1], 23 => [n, 0, n, 1, n, 1, 0, 1, 0], 24 => [1, 1, n, 1, n, 0, 1, 1, n], 25 => [1, 1, n, 1, n, 0, 0, 1, n], 26 => [0, 1, n, 1, n, 0, 1, 1, n], 27 => [0, 1, n, 1, n, 0, 0, 1, n], 28 => [1, 1, 1, 1, n, 1, n, 0, n], 29 => [0, 1, 1, 1, n, 1, n, 0, n], 30 => [1, 1, 0, 1, n, 1, n, 0, n], 31 => [0, 1, 0, 1, n, 1, n, 0, n], 32 => [n, 1, n, 0, n, 0, n, 1, n], 33 => [n, 0, n, 1, n, 1, n, 0, n], 34 => [n, 0, n, 0, n, 1, n, 1, 1], 35 => [n, 0, n, 0, n, 1, n, 1, 0], 36 => [n, 0, n, 1, n, 0, 1, 1, n], 37 => [n, 0, n, 1, n, 0, 0, 1, n], 38 => [1, 1, n, 1, n, 0, n, 0, n], 39 => [0, 1, n, 1, n, 0, n, 0, n], 40 => [n, 1, 1, 0, n, 1, n, 0, n], 41 => [n, 1, 0, 0, n, 1, n, 0, n], 42 => [n, 0, n, 0, n, 0, n, 1, n], 43 => [n, 0, n, 0, n, 1, n, 0, n], 44 => [n, 1, n, 0, n, 0, n, 0, n], 45 => [n, 0, n, 1, n, 0, n, 0, n], 46 => [n, 0, n, 0, n, 0, n, 0, n]} #-------------------------------------------------------------------------- # * [Internal] Get the autotile frame based on the sorroundings #-------------------------------------------------------------------------- def get_autotile_frame(pattern) result = NEIGHBORTILES.values.clone for i in 0...9 next if pattern
.nil? result.delete_if{|x| x != nil && x != pattern} end return nil if result.size == 0 return NEIGHBORTILES.key(result[0]) endend#==============================================================================# ** Hash#==============================================================================class Hash def key(value) for k in self.keys return k if self[k] == value end return nil endend#==============================================================================# ** Game_System#==============================================================================class Game_System attr_accessor :autotile_autocomplete alias autotile_comp_ini initialize unless $@ def initialize autotile_comp_ini @autotile_autocomplete = true endend#==============================================================================# ** Game_Map#==============================================================================class Game_Map #-------------------------------------------------------------------------- # * [Internal] Get autotile #-------------------------------------------------------------------------- def get_autotile(x, y, layer=0) tile = self.data[x, y, layer] return nil if tile.nil? or tile >= 384 or tile == 0 return tile end #-------------------------------------------------------------------------- # * [Internal] Get tile #-------------------------------------------------------------------------- def get_tile(x, y, layer=0) tile = self.data[x, y, layer] return nil if tile.nil? or (tile < 384 and tile != 0) return tile end #-------------------------------------------------------------------------- # * [Internal] Fix autotile based on sorroundings #-------------------------------------------------------------------------- def fix_autotile(x, y, layer, autotile_id) pattern = [] for iy in -1..1 for ix in -1..1 tile = self.data[x + ix, y + iy, layer] if tile == nil or (ix == 0 && iy == 0) pattern.push(nil) next end if tile < 384 && same_autotile?((tile.to_f / 48).floor, autotile_id) pattern.push(1) else pattern.push(0) end end end frame = AutotileData.get_autotile_frame(pattern) return if frame.nil? self.data[x, y, layer] = autotile_id * 48 + frame end #-------------------------------------------------------------------------- # * [Internal] Check if two autotiles are the same #-------------------------------------------------------------------------- def same_autotile?(a, b) return true if a == b return false end #-------------------------------------------------------------------------- # * Set tile #-------------------------------------------------------------------------- def set_tile(x, y, layer, new_tile) tile = self.data[x, y, layer] return nil if tile.nil? or (new_tile < 384 and new_tile != 0) autotile = get_autotile(x, y, layer) self.data[x, y, layer] = new_tile return unless $game_system.autotile_autocomplete return if autotile.nil? autotile_id = (tile.to_f / 48).floor for iy in -1..1 for ix in -1..1 current = self.data[x + ix, y + iy, layer] next if current.nil? next if current >= 384 or current == 0 next if !same_autotile?((current.to_f / 48).floor, autotile_id) fix_autotile(x + ix, y + iy, layer, autotile_id) end end end #-------------------------------------------------------------------------- # * Set autotile #-------------------------------------------------------------------------- def set_autotile(x, y, layer, new_autotile_id) tile = self.data[x, y, layer] return nil if tile.nil? or (new_autotile_id < 1 and new_autotile_id > 7) self.data[x, y, layer] = (new_autotile_id) * 48 return unless $game_system.autotile_autocomplete for iy in -1..1 for ix in -1..1 current = self.data[x + ix, y + iy, layer] next if current.nil? next if current >= 384 or current == 0 autotile_id = (current.to_f / 48).floor fix_autotile(x + ix, y + iy, layer, autotile_id) end end endend#==============================================================================# ** [Optional] Bugfix for autotiles that are bound together (like RTP Ocean)#==============================================================================class Bitmap def same_as?(bitmap, check_max = nil) return false if self.width != bitmap.width or self.height != bitmap.height i = 0 for iy in 0...self.height for ix in 0...self.width i += 1 a = self.get_pixel(ix, iy) b = bitmap.get_pixel(ix, iy) return false if a != b return true if (check_max != nil && i >= check_max) end end return true endendclass Game_Map alias shared_tiles_setup setup unless $@ def setup(*args) shared_tiles_setup(*args) @shared_tiles = {} for i in 0...7 autotile = @autotile_names next if autotile.nil? autotile = RPG::Cache.autotile(autotile) next if autotile.height == 32 tile = Bitmap.new(32, 32) tile.blt(0, 0, autotile, Rect.new(0, 0, 32, 32)) for j in 0...7 next if i == j autotile = @autotile_names[j] next if autotile.nil? autotile = RPG::Cache.autotile(autotile) next if autotile.height == 32 shared = Bitmap.new(32, 32) shared.blt(0, 0, autotile, Rect.new(32, 0, 32, 32)) if tile.same_as?(shared, 32) if @shared_tiles.keys.include?(tile) @shared_tiles[j].push(i) else @shared_tiles[j] = end end end end end def same_autotile?(a, b) return true if a == b if @shared_tiles.keys.include?(a) return true if @shared_tiles[a].include?(b) end return false endend
I think the best way to explain what this script does is with images.
By default you can change the map tile using $game_map.data[x, y, layer] = ID
If you try to set a grass tile over a water tile, this will happen:

This still works as always, I didn't change any of that.
But now, with this script you have the option to use this call instead: $game_map.set_tile(x, y, layer, ID)
If you have the autocomplete flag activated on the script, now this will happen:

The last part of the script is optional and allows bounded autotiles (like the RTP Ocean) to work properly as well, this way it works exactly like in the editor.
本贴来自国际rpgmaker官方论坛作者:Wecoc处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/map-tile-setter.138723/