=begin
================================================================================
** Tile Swap
Author: Tsukihime
Date: May 5, 2013
--------------------------------------------------------------------------------
** Change log
2.3 May 5
-fixed bug where A5 tiles were not being swapped properly. This is because
they were treated as auto-tiles instead of normal tiles
2.2 May 4
-updated to support overlay maps
2.1 Apr 11
-fixed bug where B-E pages weren't handled properly
2.0 Feb 17
-removed use of a new map. Should be more compatible now
-fixed bug where last row of page A4 tiles were skipped
-revised input format
-proper autotile swapping
1.2 Jan 22, 2013
-fixed bug where swap by position didn't handle layers properly
1.1 May 20
-Added support for reverting tiles
1.0 May 16, 2012
-Initial release
--------------------------------------------------------------------------------
** Terms of Use
* Free to use in commercial/non-commercial projects
* The script is provided as-is
* Cannot guarantee that it is compatible with other scripts
* Preserve this header
--------------------------------------------------------------------------------
** Description
This script allows you to change the tiles on a map, and also revert the
changes.
--------------------------------------------------------------------------------
** Compatibility
Let me know.
--------------------------------------------------------------------------------
** Usage
Please refer to the reference section to understand what a tileID is and
how these script calls should be made.
There are three types of tile swaps
1. Change by tile id
-All tiles on the map with the specified ID will be changed to a new tile
Usage: tile_swap(old_tileID, new_tileID, layer, map_id)
2. Change by region id
-All tiles that are covered by the specified region ID will be changed
to a new tile
Usage: region_swap(regionID, tileID, layer, map_id)
3. Change by position
-The tile at the specified position will be changed to a new tile
Usage: pos_swap(x, y, tileID, layer, map_id)
You can undo tile swaps using analogous functions
tile_revert(tid, layer, map_id)
pos_revert(x, y, tid, layer, map_id)
region_revert(rid, layer, map_id)
revert_all(map_id)
--------------------------------------------------------------------------------
** Reference
This script uses the concept of a "tile ID", which is a special string
that represents a particular tile on your tileset.
The format of this tile ID is a letter, followed by a number.
The letters available are based on the tileset names
A, B, C, D, E
The number represents the ID of the tile.
So for example, "A1" would be the the first tile in tileset A, whereas
"B12" would be the 12th tile of tileset B.
To determine the ID of a tile, it is easy: simply look at your tileset and
number the top-left tile as 1. Then, number them from left-to-right,
top-to-bottom as such
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
...
The ID that you want is exactly as it appears on your tileset.
--------------------------------------------------------------------------------
** Credits
KilloZapit, for the excellent auto-tile generation code
================================================================================
=end
$imported = {} if $imported.nil?
$imported["TH_TileSwap"] = true
#===============================================================================
# ** Rest of the script.
#===============================================================================
module TH
module Tile_Swap
Tileset_Map = {
"A" => 0,
"B" => 1,
"C" => 2,
"D" => 3,
"E" => 4,
}
ID_Keys = [128, 80, 48, 16, 0]
ID_Table = {
0 => [48, 2048],
16 => [48, 2816],
48 => [48, 4352],
80 => [48, 5888],
128 => [1, 1536]
}
end
end
class Game_System
include TH::Tile_Swap
#-----------------------------------------------------------------------------
# New. Convert my tileID to an internal tile ID.
#-----------------------------------------------------------------------------
def convert_tid(tileID)
page = tileID[0].upcase
tid = tileID[1..-1].to_i - 1
page = Tileset_Map[page]
if page == 0
ID_Keys.each {|key|
p (tid - key) * ID_Table[key][0] + ID_Table[key][1] if tid >= key
return (tid - key) * ID_Table[key][0] + ID_Table[key][1] if tid >= key
}
else
# pages B, C, D, and E all have 256 icons per page.
tid + (256 * (page - 1))
end
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def initialize_tile_list(map_id, layer)
@swapped_tiles = {} if @swapped_tiles.nil?
@swapped_tiles[map_id] = {} if @swapped_tiles[map_id].nil?
@swapped_tiles[map_id][layer] = {} if @swapped_tiles[map_id][layer].nil?
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def initialize_pos_list(map_id, layer)
@swapped_pos_tiles = {} if @swapped_pos_tiles.nil?
@swapped_pos_tiles[map_id] = {} if @swapped_pos_tiles[map_id].nil?
@swapped_pos_tiles[map_id][layer] = {} if @swapped_pos_tiles[map_id][layer].nil?
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def initialize_region_list(map_id)
@swapped_region_tiles = {} if @swapped_region_tiles.nil?
@swapped_region_tiles[map_id] = {} if @swapped_region_tiles[map_id].nil?
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def has_swap_tiles?(map_id, layer)
return false if @swapped_tiles.nil?
return false if @swapped_tiles[map_id].nil? || @swapped_tiles[map_id].empty?
return false if @swapped_tiles[map_id][layer].nil? || @swapped_tiles[map_id][layer].empty?
return true
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def has_swap_pos?(map_id, layer)
return false if @swapped_pos_tiles.nil?
return false if @swapped_pos_tiles[map_id].nil? || @swapped_pos_tiles[map_id].empty?
return false if @swapped_pos_tiles[map_id][layer].nil? || @swapped_pos_tiles[map_id][layer].empty?
return true
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def has_swap_region?(map_id, layer)
return false if @swapped_region_tiles.nil?
return false if @swapped_region_tiles[map_id].nil? || @swapped_region_tiles[map_id].empty?
return true
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def swapped_tiles(map_id, layer, tid)
initialize_tile_list(map_id, layer)
@swapped_tiles[map_id][layer][tid]
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def swapped_positions(map_id, layer)
initialize_pos_list(map_id, layer)
@swapped_pos_tiles[map_id][layer]
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def swapped_regions(map_id, rid, layer)
initialize_region_list(map_id)
@swapped_region_tiles[map_id][[rid, layer]]
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def add_tile_id(map_id, layer, old_tid, new_tid)
initialize_tile_list(map_id, layer)
old_tid = convert_tid(old_tid)
new_tid = convert_tid(new_tid)
@swapped_tiles[map_id][layer][old_tid] = new_tid
$game_map.load_new_map_data
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def add_region_tile(map_id, rid, layer, tid)
initialize_region_list(map_id)
tid = convert_tid(tid)
@swapped_region_tiles[map_id][[rid, layer]] = tid
$game_map.load_new_map_data
end
#-----------------------------------------------------------------------------
# New.
#-----------------------------------------------------------------------------
def add_position_tile(map_id, x, y, layer, tid)
initialize_pos_list(map_id, layer)
tid = convert_tid(tid)
@swapped_pos_tiles[map_id][layer][[x, y]] = tid
$game_map.load_new_map_data
end
#-----------------------------------------------------------------------------
# New. Remove all custom tiles on the map for a given layer and tileID
#-----------------------------------------------------------------------------
def revert_tile(map_id, layer, tid)
initialize_tile_list(map_id, layer)
tid = convert_tid(tid)
@swapped_tiles[map_id][layer].delete(tid)
$game_map.reload_map
end
#-----------------------------------------------------------------------------
# New. Remove all custom tiles on the map for a given layer and position
#-----------------------------------------------------------------------------
def revert_pos(map_id, x, y, layer)
initialize_pos_list(map_id, layer)
@swapped_pos_tiles[map_id][layer].delete([x, y])
$game_map.reload_map
end
#-----------------------------------------------------------------------------
# New. Remove all custom tiles on the map for a given layer and region
#-----------------------------------------------------------------------------
def revert_region(map_id, layer, rid)
initialize_region_list(map_id)
@swapped_region_tiles[map_id].delete([rid, layer])
$game_map.reload_map
end
#-----------------------------------------------------------------------------
# New. Remove all custom tiles from the given map
#-----------------------------------------------------------------------------
def revert_all(map_id)
@swapped_tiles = {} if @swapped_tiles.nil?
@swapped_pos_tiles = {} if @swapped_pos_tiles.nil?
@swapped_region_tiles = {} if @swapped_region_tiles.nil?
@swapped_tiles[map_id] = {}
@swapped_pos_tiles[map_id] = {}
@swapped_region_tiles[map_id] = {}
$game_map.reload_map
end
end
class Game_Map
#-----------------------------------------------------------------------------
# Aliased. Load new map data after the original map is loaded
#-----------------------------------------------------------------------------
alias :tsuki_tile_swap_setup_map :setup
def setup(map_id)
tsuki_tile_swap_setup_map(map_id)
load_new_map_data
end
#-----------------------------------------------------------------------------
# New. Grab the original map data and load that up
#-----------------------------------------------------------------------------
def reload_map
new_map = load_data(sprintf("Data/Map%03d.rvdata2", @map_id))
@map.data = new_map.data
load_new_map_data
end
#-----------------------------------------------------------------------------
# New. Load custom map data on top of our map
#-----------------------------------------------------------------------------
def load_new_map_data
@updated_tiles = {}
swap_tile_id
swap_tile_region
swap_tile_pos
expand_updated_tiles
update_all_autotiles
end
#-----------------------------------------------------------------------------
# New. Swap tiles by tile ID
#-----------------------------------------------------------------------------
def swap_tile_id
for z in 0...3
next unless $game_system.has_swap_tiles?(@map_id, z)
for x in 0...@map.width
for y in 0...@map.height
old_tid = floor_autotile_id(@map.data[x, y, z])
new_tile = $game_system.swapped_tiles(@map_id, z, old_tid)
if new_tile
@map.data[x, y, z] = new_tile
@updated_tiles[[x,y]] = 1
end
end
end
end
end
#-----------------------------------------------------------------------------
# New. Swap tiles by region
#-----------------------------------------------------------------------------
def swap_tile_region
for z in 0...3
next unless $game_system.has_swap_region?(@map_id, z)
for x in 0...@map.width
for y in 0...@map.height
rid = region_id(x, y)
new_tile = $game_system.swapped_regions(@map_id, rid, z)
if new_tile
@map.data[x, y, z] = new_tile
@updated_tiles[[x,y]] = 1
end
end
end
end
end
#-----------------------------------------------------------------------------
# New. Swap tiles by position
#-----------------------------------------------------------------------------
def swap_tile_pos
for z in 0 ... 3
new_tiles = $game_system.swapped_positions(@map_id, z)
if new_tiles
for new_tile in new_tiles
@map.data[new_tile[0][0], new_tile[0][1], z] = new_tile[1]
@updated_tiles[new_tile[0]] = 1
end
end
end
end
#-----------------------------------------------------------------------------
# New. If it is an auto-tile ID, get the base autotile ID
# (without considering autotile index)
#-----------------------------------------------------------------------------
def floor_autotile_id(id)
return (id >= 2048) ? id - ((id - 2048) % 48) : id
end
#-----------------------------------------------------------------------------
# New. In addition to the updated tile, we must update all adjacent tiles
# as well
#-----------------------------------------------------------------------------
def expand_updated_tiles
new_tiles = {}
@updated_tiles.each {|(x,y), val|
new_tiles[[x,y]] = 1,
new_tiles[[x+1, y]] = 1,
new_tiles[[x-1, y]] = 1,
new_tiles[[x, y+1]] = 1,
new_tiles[[x, y-1]] = 1,
new_tiles[[x+1, y-1]] = 1,
new_tiles[[x+1, y+1]] = 1,
new_tiles[[x-1, y-1]] = 1,
new_tiles[[x-1, y+1]] = 1
}
@updated_tiles = new_tiles
end
#-----------------------------------------------------------------------------
# The following contains auto-tile generation code by KilloZapit
#-----------------------------------------------------------------------------
def autotile_edge(autotile, x, y, z)
# Special dungeon logic
# makes overlay grass tiles "grow" out of walls.
valid?(x, y) && autotile != autotile_type(x, y, z)
end
def autotile_wall_edge(autotile, x, y, z)
if (autotile / 8) % 2 == 1
return false if autotile_type(x, y, z) + 8 == autotile
end
autotile_edge(autotile, x, y, z)
end
def update_all_autotiles
@updated_tiles.each {|(x, y), val|
update_autotile(x, y, 0)
update_autotile(x, y, 1)
}
end
def update_autotile(x, y, z)
autotile = autotile_type(x, y, z)
return if autotile < 0
index = 0
case get_autotile_group(autotile)
when 2
l = autotile_edge(autotile, x - 1, y, z)
r = autotile_edge(autotile, x + 1, y, z)
index = waterfall_autotile_index(l,r)
when 1
l = autotile_wall_edge(autotile, x - 1, y, z)
r = autotile_wall_edge(autotile, x + 1, y, z)
u = autotile_edge(autotile, x, y - 1, z)
d = autotile_edge(autotile, x, y + 1, z)
index = wall_autotile_index(u,d,l,r)
when 0
l = autotile_edge(autotile, x - 1, y, z)
r = autotile_edge(autotile, x + 1, y, z)
u = autotile_edge(autotile, x, y - 1, z)
d = autotile_edge(autotile, x, y + 1, z)
ul = autotile_edge(autotile, x - 1, y - 1, z)
ur = autotile_edge(autotile, x + 1, y - 1, z)
dl = autotile_edge(autotile, x - 1, y + 1, z)
dr = autotile_edge(autotile, x + 1, y + 1, z)
index = normal_autotile_index(u,d,l,r,ul,ur,dl,dr)
end
@map.data[x, y, z] = get_autotile_tile_id(autotile, index)
end
def get_autotile_tile_id(autotile, index)
2048 + (48 * autotile) + index
end
def get_autotile_group(autotile)
return unless autotile
case
when [5, 7, 9, 11, 13, 15].include?(autotile)
return 2
when (48..79).include?(autotile) ||
(88..95).include?(autotile) ||
(104..111).include?(autotile) ||
(120..127).include?(autotile)
return 1
else
return 0
end
end
def waterfall_autotile_index(l,r)
edge = 0
edge |= 1 if l
edge |= 2 if r
return edge
end
def wall_autotile_index(u,d,l,r)
edge = 0
edge |= 1 if l
edge |= 2 if u
edge |= 4 if r
edge |= 8 if d
return edge
end
def normal_autotile_index(u,d,l,r,ul,ur,dl,dr)
edge = 0
edge |= 1 if l
edge |= 2 if u
edge |= 4 if r
edge |= 8 if d
corner = 0
case edge
when 0
corner |= 1 if ul
corner |= 2 if ur
corner |= 4 if dr
corner |= 8 if dl
return corner
when 1
corner |= 1 if ur
corner |= 2 if dr
return 16 | corner
when 2
corner |= 1 if dr
corner |= 2 if dl
return 20 | corner
when 4
corner |= 1 if dl
corner |= 2 if ul
return 24 | corner
when 8
corner |= 1 if ul
corner |= 2 if ur
return 28 | corner
when 5
return 32
when 10
return 33
when 3
return dr ? 35 : 34
when 6
return dl ? 37 : 36
when 12
return ul ? 39 : 38
when 9
return ur ? 41 : 40
when 7
return 42
when 11
return 43
when 13
return 44
when 14
return 45
when 15
return 46
else
return 47
end
end
end
class Game_Interpreter
#swaps the tile at x,y to the specified tile_id
def tile_swap(old_tid, new_tid, layer=0, map_id=$game_map.map_id)
$game_system.add_tile_id(map_id, layer, old_tid, new_tid)
end
def pos_swap(x, y, tid, layer=0, map_id=$game_map.map_id)
$game_system.add_position_tile(map_id, x, y, layer, tid)
end
def region_swap(rid, tid, layer=0, map_id=$game_map.map_id)
$game_system.add_region_tile(map_id, rid, layer, tid)
end
def tile_revert(tid, layer=0, map_id=$game_map.map_id)
$game_system.revert_tile(map_id, layer, tid)
end
def pos_revert(x, y, layer=0, map_id=$game_map.map_id)
$game_system.revert_pos(map_id, x, y, layer)
end
def region_revert(rid, layer=0, map_id=$game_map.map_id)
$game_system.revert_region(map_id, layer, rid)
end
def revert_all(map_id=$game_map.map_id)
$game_system.revert_all(map_id)
end
end
#-------------------------------------------------------------------------------
# Add-on for Overlay Maps
#-------------------------------------------------------------------------------
class Game_Map
alias :th_overlay_naps_load_new_map_data :load_new_map_data
def load_new_map_data
th_overlay_naps_load_new_map_data
@overlay_maps.each {|map| map.load_new_map_data} unless self.is_a?(Game_OverlayMap)
end
alias :th_overlay_maps_reload_map :reload_map
def reload_map
th_overlay_maps_reload_map
@overlay_maps.each {|map| map.reload_map} unless self.is_a?(Game_OverlayMap)
end
end if $imported["TH_OverlayMaps"]