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.