#==============================================================================
# ** RPG Maker XP MENTOR | Custom Map Editor
#··············································································
# Author: Eron
#
# Credits:
#
# Wecoc - WecTools base & basic support
# KGC - KGC_BitmapExtension [ TRGSSX ]
# Glitchfinder - Input & Mouse
#
# Collaborators:
#
# Mundo Maker (forum)
#
#==============================================================================
module MENTOR
TRGSSX = true # Use the TRGSSX library to write code texts (recommended)
end
#==============================================================================
# ** Win32API Globals
#==============================================================================
class Win32API
GPPS = self.new('kernel32', 'GetPrivateProfileString','PPPPLP', 'L')
WPPS = Win32API.new('kernel32', 'WritePrivateProfileString', 'PPPP', 'L')
GPPSA = Win32API.new('kernel32', 'GetPrivateProfileStringA', 'PPPPLP', 'L')
WPPSA = Win32API.new('kernel32', 'WritePrivateProfileStringA', 'PPPP', 'L')
AllocConsole = self.new('kernel32', 'AllocConsole', 'v', 'l')
FindWindow = self.new('user32', 'FindWindow', 'PP', 'I')
FindWindowA = self.new('user32', 'FindWindowA', 'pp', 'i')
SetForegroundWindow = self.new('user32', 'SetForegroundWindow','l','l')
SetConsoleTitleA = self.new('kernel32','SetConsoleTitleA','p','s')
WriteConsoleOutput = self.new('kernel32', 'WriteConsoleOutput', 'lpllp', 'l' )
SetWindowLong = self.new('user32', 'SetWindowLong', 'LIL', 'L')
SetWindowPos = self.new('user32', 'SetWindowPos', 'LLIIIII', 'I')
GetWindowRect = self.new('user32', 'SystemParametersInfo', 'IIPI', 'I')
dll = "\0" * 255
GPPSA.call('Game', 'Library', '', dll, 255, '.\\Game.ini')
dll.delete!("\0")
RGSS_DLL = dll
RGSSEval = self.new(dll, 'RGSSEval', 'P', 'S')
title = "\0" * 255
GPPSA.call('Game', 'Title', '', title, 255, '.\\Game.ini')
title.delete!("\0")
GAME_TITLE = title
end
#==============================================================================
# ** Console & Window Console Extensions
#==============================================================================
module Console
extend self
def init
Win32API::AllocConsole.call
handle = Win32API::FindWindowA.call('RGSS Player', 0)
Win32API::SetForegroundWindow.call(handle)
Win32API::SetConsoleTitleA.call("RGSS Console")
$stdout.reopen('CONOUT$')
end
def log(*data)
puts(*data.collect{|d| d.is_a?(String) ? d : d.inspect})
end
end
#------------------------------------------------------------------------------
module WinConsole
extend self
OPTION_OK = 0x00000000
OPTION_OKCANCEL = 0x00000001
OPTION_YESNOCANCEL = 0x00000003
OPTION_YESNO = 0x00000004
OPTION_RETRYCANCEL = 0x00000005
ICON_NONE = 0x00000000
ICON_ERROR = 0x00000010
ICON_QUESTION = 0x00000020
ICON_WARNING = 0x00000030
ICON_INFO = 0x00000040
def init
@@dialog = Win32API.new('user32', 'MessageBox', 'LPPL', 'I')
end
def log(text, options=OPTION_OK, icon=ICON_NONE, index=0)
text = String.utf82ansi(text)
index *= 256
mbtype = options | icon | index
result = @@dialog.call(0, text, 'MapEditor', mbtype)
return case result
when 1: "Ok"
when 2: "Cancel"
when 3: "Abort"
when 4: "Retry"
when 5: "Ignore"
when 6: "Yes"
when 7: "No"
when 10: "Try again"
when 11: "Continue"
end
end
end
#==============================================================================
# ** String Formats
#==============================================================================
class String
#------------------------------------------------------------------------
CP_ACP = 0 # ANSI
CP_OEM = 1 # OEM
CP_UTF8 = 65001 # UTF-8
@@mb2wc = Win32API.new('kernel32', 'MultiByteToWideChar', 'ILPIPI', 'L')
@@wc2mb = Win32API.new('kernel32', 'WideCharToMultiByte', 'ILPIPIPP', 'L')
#------------------------------------------------------------------------
def self.utf82ansi(str)
to_multibyte(to_widechar(str, CP_UTF8), CP_ACP )
end
#------------------------------------------------------------------------
def self.ansi2utf8(str)
to_multibyte(to_widechar(str, CP_ACP), CP_UTF8 )
end
#------------------------------------------------------------------------
def self.utf82oem(str)
to_multibyte(to_widechar(str, CP_UTF8), CP_OEM )
end
#------------------------------------------------------------------------
def self.oem2utf8(str)
to_multibyte(to_widechar(str, CP_OEM), CP_UTF8 )
end
#------------------------------------------------------------------------
def self.to_widechar(str , codepage)
length = @@mb2wc.call(codepage, 0, str, -1, nil, 0)
unless length.zero?
b = "\x00" * (length << 1)
unless (@@mb2wc.call(codepage, 0, str, -1, b, length)).zero?
return b
else
return ""
end
else
return ""
end
end
#------------------------------------------------------------------------
def self.to_multibyte(str, codepage)
length = @@wc2mb.call(codepage, 0, str, -1, nil, 0, nil, nil)
unless length.zero?
b = "\x00" * length
unless (@@wc2mb.call(codepage, 0, str, -1, b, b.size, nil, nil)).zero?
return b
else
return ""
end
else
return ""
end
end
#------------------------------------------------------------------------
def character_at(index)
return self.split("")[index]
end
#------------------------------------------------------------------------
def delete_character_at(index)
result = self.split("")
result.delete_at(index)
self.replace(result.join)
end
#------------------------------------------------------------------------
def insert_character(index, str)
result = self.split("")
result.insert(index, str)
self.replace(result.join)
end
#------------------------------------------------------------------------
def character_size
return self.split("").size
end
#------------------------------------------------------------------------
end
#==============================================================================
# ** Autotile Data
#==============================================================================
module AutotileData
module_function
#--------------------------------------------------------------------------
NEIGHBORS = {
2 => { 0 => 20, 1 => 20, 2 => 20, 3 => 20,
4 => 21, 5 => 21, 6 => 21, 7 => 21,
8 => 22, 9 => 22, 10 => 22, 11 => 22,
12 => 23, 13 => 23, 14 => 23, 15 => 23,
16 => 34, 17 => 34, 18 => 35, 19 => 35,
24 => 36, 25 => 37, 26 => 36, 27 => 37,
28 => 33, 29 => 33, 30 => 33, 31 => 33,
32 => 42, 38 => 45, 39 => 45, 40 => 43,
41 => 43, 44 => 46 },
4 => { 0 => 24, 1 => 26, 2 => 24, 3 => 26,
4 => 24, 5 => 26, 6 => 24, 7 => 26,
8 => 25, 9 => 27, 10 => 25, 11 => 27,
12 => 25, 13 => 27, 14 => 25, 15 => 27,
16 => 32, 17 => 32, 18 => 32, 19 => 32,
20 => 36, 21 => 36, 22 => 37, 23 => 37,
28 => 38, 29 => 39, 30 => 38, 31 => 39,
33 => 45, 34 => 42, 35 => 42, 40 => 44,
41 => 44, 43 => 46 },
6 => { 0 => 16, 1 => 16, 2 => 17, 3 => 17,
4 => 18, 5 => 18, 6 => 19, 7 => 19,
8 => 16, 9 => 16, 10 => 17, 11 => 17,
12 => 18, 13 => 18, 14 => 19, 15 => 19,
20 => 34, 21 => 35, 22 => 34, 23 => 35,
24 => 32, 25 => 32, 26 => 32, 27 => 32,
28 => 40, 29 => 40, 30 => 41, 31 => 41,
33 => 43, 36 => 42, 37 => 42, 38 => 44,
39 => 44, 45 => 46 },
8 => { 0 => 28, 1 => 29, 2 => 30, 3 => 31,
4 => 28, 5 => 29, 6 => 30, 7 => 31,
8 => 28, 9 => 29, 10 => 30, 11 => 31,
12 => 28, 13 => 29, 14 => 30, 15 => 31,
16 => 40, 17 => 41, 18 => 40, 19 => 41,
20 => 33, 21 => 33, 22 => 33, 23 => 33,
24 => 38, 25 => 38, 26 => 39, 27 => 39,
32 => 44, 34 => 43, 35 => 43, 36 => 45,
37 => 45, 42 => 46 },
1 => { 0 => 2, 1 => 3, 4 => 6, 5 => 7,
8 => 10, 9 => 11, 12 => 14, 13 => 15,
16 => 17, 18 => 19, 28 => 30, 29 => 31,
40 => 41 },
3 => { 0 => 1, 2 => 3, 4 => 5, 6 => 7,
8 => 9, 10 => 11, 12 => 13, 14 => 15,
24 => 26, 25 => 27, 28 => 29, 30 => 31,
38 => 39 },
7 => { 0 => 4, 1 => 5, 2 => 7, 3 => 8,
8 => 12, 9 => 13, 10 => 14, 11 => 15,
16 => 18, 17 => 19, 20 => 21, 22 => 23,
34 => 35 },
9 => { 0 => 8, 1 => 9, 2 => 10, 3 => 11,
4 => 12, 5 => 13, 6 => 14, 7 => 15,
20 => 22, 21 => 23, 24 => 25, 26 => 27,
36 => 37 }
}
#--------------------------------------------------------------------------
n = nil
NEIGHBOR_PATTERNS =
{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]}
#--------------------------------------------------------------------------
def get_autotile_frame(pattern)
result = NEIGHBOR_PATTERNS.values.clone
for i in 0...9
next if pattern[i].nil?
result.delete_if{|x| x[i] != nil && x[i] != pattern[i]}
end
return nil if result.size == 0
return NEIGHBOR_PATTERNS.key(result[0])
end
#--------------------------------------------------------------------------
SEEN_FROM = {
2 => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, 34, 35, 36, 37, 42],
4 => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 36, 37, 38, 39, 45],
6 => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 28, 29, 30, 31, 33, 34, 35, 40, 41, 43],
8 => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 24, 25, 26, 27, 28, 29, 30, 31, 32, 38, 39, 40, 41, 44],
1 => [0, 1, 2, 3, 4, 5, 6, 7, 20, 21, 24, 26, 36],
3 => [0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 20, 22, 34],
7 => [0, 2, 4, 6, 8, 10, 12, 14, 24, 25, 28, 30, 38],
9 => [0, 1, 4, 5, 8, 9, 12, 13, 16, 18, 28, 29, 40]
}
#--------------------------------------------------------------------------
DECONSTRUCT_ARRAY_XP =
[27, 28, 5, 28, 27, 6, 5, 6, 27, 28, 5, 28, 27, 6, 5, 6,
33, 34, 33, 34, 33, 34, 33, 34, 33, 12, 33, 12, 33, 12, 33, 12,
27, 28, 5, 28, 27, 6, 5, 6, 27, 28, 5, 28, 27, 6, 5, 6,
11, 34, 11, 34, 11, 34, 11, 34, 11, 12, 11, 12, 11, 12, 11, 12,
25, 26, 25, 6, 25, 26, 25, 6, 15, 16, 15, 16, 15, 16, 15, 16,
31, 32, 31, 32, 31, 12, 31, 12, 21, 22, 21, 12, 11, 22, 11, 12,
29, 30, 29, 30, 5, 30, 5, 30, 39, 40, 5, 40, 39, 6, 5, 6,
35, 36, 11, 36, 35, 36, 11, 36, 45, 46, 45, 46, 45, 46, 45, 46,
25, 30, 15, 16, 13, 14, 13, 14, 17, 18, 17, 18, 41, 42, 5, 42,
31, 36, 45, 46, 19, 20, 19, 12, 23, 24, 11, 24, 47, 48, 47, 48,
37, 38, 37, 6, 13, 18, 13, 14, 37, 42, 17, 18, 13, 18, 1, 2,
43, 44, 43, 44, 19, 24, 43, 44, 43, 48, 47, 48, 43, 48, 7, 8]
#--------------------------------------------------------------------------
DECONSTRUCT_ARRAY_VX =
[19, 18, 3, 18, 19, 4, 3, 4, 19, 18, 3, 18, 19, 4, 3, 4,
15, 14, 15, 14, 15, 14, 15, 14, 15, 8, 15, 8, 15, 8, 15, 8,
19, 18, 3, 18, 19, 4, 3, 4, 19, 18, 3, 18, 19, 4, 3, 4,
7, 14, 7, 14, 7, 14, 7, 14, 7, 8, 7, 8, 7, 8, 7, 8,
17, 18, 17, 4, 17, 18, 17, 4, 11, 10, 11, 10, 11, 10, 11, 10,
13, 14, 13, 14, 13, 8, 13, 8, 15, 14, 15, 8, 7, 14, 7, 8,
19, 20, 19, 20, 3, 20, 3, 20, 19, 18, 3, 18, 19, 4, 3, 4,
15, 16, 7, 16, 15, 16, 7, 16, 23, 22, 23, 22, 23, 22, 23, 22,
17, 20, 11, 10, 9, 10, 9, 10, 11, 12, 11, 12, 19, 20, 3, 20,
13, 16, 23, 22, 13, 14, 13, 8, 15, 16, 7, 16, 23, 24, 23, 24,
17, 18, 17, 4, 9, 12, 9, 10, 17, 20, 11, 12, 9, 12, 1, 2,
21, 22, 21, 22, 13, 16, 21, 22, 21, 24, 23, 24, 21, 24, 5, 6]
#--------------------------------------------------------------------------
end
#==============================================================================
# ** Other fixes
#==============================================================================
module RPG
class MapInfo
attr_accessor :id
attr_accessor :parent_list
end
end
class Hash
def key(val)
for k in self.keys
return k if self[k] == val
end
return nil
end
end
#==============================================================================
# ** Editor Caller
#==============================================================================
begin
title = "\0" * 256
Win32API::GPPS.call("Game", "Title", "", title, 256, ".\\Game.ini")
title.delete!("\0")
$MAP_EDITOR = (Win32API::FindWindow.call("RGSS Player", title) == 0)
if $MAP_EDITOR
def load_scripts(folder, sfolder)
files = Dir.open(folder).entries.select do |f|
File.ftype("#{folder}/#{f}") == "file"
end
for filename in files
p "Load Script ... #{sfolder + filename}"
f = File.open(folder + filename, "rb")
script = String.ansi2utf8(f.read)
Win32API::RGSSEval.call(script)
f.close
end
end
module Kernel
def console; Console; end
def p(*args)
ary = []
for a in args
if a.is_a?(String)
ary.push(String.utf82oem(a))
else
ary.push(a)
end
end
console.log(*ary)
end
end
Console.init
WinConsole.init
Graphics.frame_rate = 60
load_scripts("#{Dir.getwd}/MapEditor/", "")
load_scripts("#{Dir.getwd}/MapEditor/Plugins/", "Plugins/")
end
end
#------------------------------------------------------------------------------
class Scene_Title
alias map_editor_main main unless $@
def main
if $MAP_EDITOR == false
map_editor_main
return
end
# Resolution
window = Win32API::FindWindow.call("RGSS Player", "MapEditor")
Win32API::GetWindowRect.call(0x30, 0, rect = [0, 0, 0, 0].pack('l4'), 0)
rect = rect.unpack('l4')
r = Rect.new(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1])
Win32API::SetWindowLong.call(window, -16, 0x14CA0000)
Win32API::SetWindowPos.call(window, 0, r.x, r.y, r.width, r.height, 0)
Graphics.width = r.width - 8
Graphics.height = r.height - 32
$scene = Scene_MapEditor.new
end
end
#==============================================================================
# ** Resolution & Other fixes
#==============================================================================
module Graphics
#--------------------------------------------------------------------------
def self.width
return @@width
end
def self.height
return @@height
end
def self.width=(width)
@@width = width
end
def self.height=(height)
@@height = height
end
#--------------------------------------------------------------------------
class << self
alias fps_upd update unless $@
end
@@fps = 0
@@fps_inc = 0
@@fps_tsec = Time.new.sec
@@fps_tsol = @@fps_tsec
def self.update(*args)
self.fps_upd(*args)
@@fps_inc += 1
@@fps_tsec = Time.new.sec
if @@fps_tsec != @@fps_tsol
@@fps_tsol = @@fps_tsec
@@fps = @@fps_inc
@@fps_inc = 0
end
end
def self.fps
@@fps
end
#--------------------------------------------------------------------------
end
class Plane < Sprite
attr_reader :bitmap
def bitmap=(tile)
return if @bitmap == tile
@bitmap = tile
if bitmap.is_a?(Bitmap)
xx = 1 + (Graphics.width.to_f / tile.width).ceil
yy = 1 + (Graphics.height.to_f / tile.height).ceil
plane = Bitmap.new(@bitmap.width * xx, @bitmap.height * yy)
(0..xx).each {|x| (0..yy).each {|y|
plane.blt(x * @bitmap.width, y * @bitmap.height, @bitmap, @bitmap.rect)
}}
super(plane)
end
end
end
class Bitmap
if MENTOR::TRGSSX == true
DrawCodeText = Win32API.new("TRGSSX", 'DrawTextNAA', 'pllllpplpll', 'l')
def draw_code_text(x, y, width, height, text)
dest_info = [self.object_id, self.width, self.height].pack('l!3')
n = 0; flag = 0
n |= self.font.color.alpha.to_i << 24
n |= self.font.color.red.to_i << 16
n |= self.font.color.green.to_i << 8
n |= self.font.color.blue.to_i
color = [n, 0, 0xFF000000, 0].pack('l!4')
flag |= 0x0001 if self.font.bold == true
flag |= 0x0002 if self.font.italic == true
DrawCodeText.call(dest_info, x, y, width, height, text.dup,
self.font.name, self.font.size - 2, color, 0, flag)
end
else
def draw_code_text(x, y, width, height, text)
draw_text(x, y, width, height, text)
end
end
end