mirror of
https://github.com/bakustarver/rpgmakermlinux-cicpoffs.git
synced 2025-03-28 14:56:21 +01:00
Add files via upload
This commit is contained in:
parent
240d2aa919
commit
862b9d8238
33 changed files with 23009 additions and 0 deletions
129
Kawariki-patches/README.md
Normal file
129
Kawariki-patches/README.md
Normal file
|
@ -0,0 +1,129 @@
|
|||
Kawariki MKXP runtime
|
||||
=====================
|
||||
|
||||
The MKXP runtime handles games based on the `Ruby Game Scripting System`, RGSS.
|
||||
|
||||
The RPG Maker editions based on RGSS are:
|
||||
- RPGMaker XP (RGSS1)
|
||||
- RPGMaker VX (RGSS2)
|
||||
- RPGMaker VX Ace (RGSS3)
|
||||
|
||||
[Official RPGMaker Website][rpgmakerweb]
|
||||
|
||||
MKXP-Z
|
||||
------
|
||||
|
||||
The specific implementation used in Kawariki is [mkxp-z][mkxp-z] by Roza/Struma,
|
||||
itself based on the original [mkxp][mkxp-github] by Ancurio.
|
||||
|
||||
Currently, a [repackaged distribution][mkxp-z-repack] of the [official releases][mkxp-z-releases] are used.
|
||||
This is required mostly for ease of automatic downloading in Kawariki.
|
||||
|
||||
Links: [mkxp-z GitHub][mkxp-z-github]
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
### mkxp.json
|
||||
|
||||
The mkxp-z configuration is merged from a number of files in order:
|
||||
- `<kawariki>/mkxp/mkxp.json`: Global mkxp config
|
||||
- `<game>/kawariki-mkxp.json`: Overrides specific for this game
|
||||
|
||||
See the [default included with mkxp-z for reference][mkxp-z-config]
|
||||
Note that the runtime doesn't understand JSON comments for now,
|
||||
unlike mkxp-z itself.
|
||||
|
||||
#### RTPs
|
||||
The situation with RTPs is not optimal at the moment, but they
|
||||
can be specified globally in `<kawariki>/mkxp/mkxp.json`:
|
||||
```json
|
||||
{
|
||||
"RTP": ["/path/to/rtp"]
|
||||
}
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
- `KAWARIKI_MKXP_DUMP_SCRIPTS=<dirname>`: Dump scripts to <dirname> before applying patches
|
||||
- `KAWARIKI_MKXP_DUMP_PATCHED_SCRIPTS=<dirname>`: Dump scripts to <dirname> after applying patches
|
||||
- `KAWARIKI_MKXP_FILTER_SCRIPTS=<name>[,...]`: Blacklist scripts/plugins by name
|
||||
- `KAWARIKI_MKXP_DRY_RUN=1`: Exit after patching scripts, don't run game
|
||||
- `KAWARIKI_MKXP_NO_FONT_EFFECTS=1`: Disable all font effects. See relevant patch in `pathces.rb`
|
||||
- `KAWARIKI_NO_OVERLAYNS=1` Disallow usage of overlayns-static
|
||||
|
||||
### versions.json
|
||||
This file specifies the mkxp-z versions known to the runtime:
|
||||
- `variant` *required string* Must be `"mkxp-z"` for now
|
||||
- `version` *required array-of-numbers* The version of this distribution (e.g. `[2,3,0]`)
|
||||
- `dist` *required string* The name of the directory the distribution is stored in.
|
||||
- `dist_url` *optional string* An URL to download the distribution from if not already available. It must point to a gzip/bzip2/xz compressed tar-archive.
|
||||
- `name` *optional string* An optional name given to the distribution. Defaults to the value of `dist`.
|
||||
|
||||
RGSS Plugins
|
||||
------------
|
||||
|
||||
All functionality in RGSS-based games is derived from the core scripts
|
||||
of it's respective RPGMaker edition and extended by usually rather large
|
||||
numbers of third-party engine plugins.
|
||||
|
||||
Unfortunately, as a consequence of RGSS being a rather simplistic engine
|
||||
and also being Windows-only, a lot of these plugins rely on assumptions
|
||||
that don't hold true on Linux (though MKXP already implements case-insensitive
|
||||
path lookups) or depend on the Win32 API or other (possibly custom) native
|
||||
Windows libraries by way of a FFI (`Win32API` in RGSS).
|
||||
As such, the runtime must apply a considerable amount of patches to a game
|
||||
to allow it to run on Linux/MXKP-Z.
|
||||
|
||||
### Ports
|
||||
|
||||
Ports are modifications or re-implementations of third-party plugins to make
|
||||
them work on Linux/MKXP-Z. They are contained in the `ports/` directory.
|
||||
|
||||
All ports retain their original license terms. If you are the original author
|
||||
of one of the included scripts and want it removed, please open an issue on GitHub.
|
||||
|
||||
### Patches
|
||||
|
||||
A patch tries to identify a third-party plugin and then either modify it's code
|
||||
or outright replace the plugin with a port from `ports/`. Patches are defined
|
||||
in [`patches.rb`](patches.rb)
|
||||
|
||||
### Win32API Stubs
|
||||
Win32API stubs are implemented in [`libs/Win32API.rb`](libs/Win32API.rb).
|
||||
They are automatically loaded if any reference to Win32API is found in plugin
|
||||
code after all patches are applied.
|
||||
|
||||
It is usually easier to port a heavily Win32API-dependent plugin instead of
|
||||
trying to re-implement the relevant Win32 APIs.
|
||||
|
||||
Currently, implementations are included for these common APIs:
|
||||
- kernel32/GetPrivateProfileString
|
||||
- kernel32/GetPrivateProfileInt
|
||||
- kernel32/WritePrivateProfileString
|
||||
|
||||
### Preload
|
||||
|
||||
The preload script `preload.rb` is registered with MKXP-Z and is responsible for
|
||||
applying the patches defined in `patches.rb`.
|
||||
|
||||
Some methods are provided for use in ports/patches:
|
||||
- `Preload::require()`: Require a library from the `libs/` directory (see below)
|
||||
- `Preload::print()`: Print to stderr. Note that Kernel.print may open a message box depending on RGSS version
|
||||
|
||||
### Libraries
|
||||
The `libs/` directory contains a few libraries to support porting plugins.
|
||||
- `ruby18.rb`: Some low-hanging compatibility modifications for RGSS1, which used Ruby 1.8
|
||||
- `Win32API.rb`: Wrapper around Win32API to intercept imports with included ruby implementations
|
||||
- `PreloadIni.rb`: Simple INI parser/generator for implementing {Get,Write}PrivateProfileString
|
||||
- `XP_TileMapOverrideLib.rb`: Workaround for a MKXP-Z issue related to GL texture sizes
|
||||
|
||||
|
||||
<!-- References -->
|
||||
[mkxp-z]: https://roza-gb.gitbook.io/mkxp-z
|
||||
[mkxp-z-config]: https://github.com/mkxp-z/mkxp-z/blob/release/mkxp.json
|
||||
[mkxp-z-github]: https://github.com/mkxp-z/mkxp-z
|
||||
[mkxp-z-releases]: https://github.com/mkxp-z/mkxp-z/releases
|
||||
[mkxp-z-repack]: https://github.com/Orochimarufan/Kawariki/releases/tag/mkxp-2.3.0-kk
|
||||
|
||||
[mkxp-github]: https://github.com/Ancurio/mkxp
|
||||
[rpgmakerweb]: https://www.rpgmakerweb.com/
|
439
Kawariki-patches/libs/PreloadIni.rb
Normal file
439
Kawariki-patches/libs/PreloadIni.rb
Normal file
|
@ -0,0 +1,439 @@
|
|||
# INI file tools for replacing Win32API usage
|
||||
# Key and Section names are case-preserving
|
||||
# Authors: Taeyeon Mori
|
||||
|
||||
module Preload
|
||||
module Ini
|
||||
# ********** Machinery **********
|
||||
class DummyReadFile
|
||||
def each_line(&p)
|
||||
end
|
||||
end
|
||||
|
||||
class IniBase
|
||||
def initialize(file)
|
||||
@file = file
|
||||
@section = ""
|
||||
@section_lc = ""
|
||||
end
|
||||
|
||||
attr_reader :section, :section_lc
|
||||
|
||||
def self.open(filename)
|
||||
if block_given? then
|
||||
File.open(filename, self::FileMode) do |file|
|
||||
yield self.new file
|
||||
end
|
||||
else
|
||||
return self.new File.new(filename, self::FileMode)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class IniWriter < IniBase
|
||||
FileMode = "wt"
|
||||
|
||||
def initialize(file)
|
||||
super file
|
||||
@newline = 1
|
||||
end
|
||||
|
||||
def writeLine(line=nil)
|
||||
if line.nil? || line.empty? then
|
||||
@file.write "\r\n"
|
||||
@newline += 1
|
||||
else
|
||||
@file.write "#{line}\r\n"
|
||||
@newline = 0
|
||||
end
|
||||
end
|
||||
|
||||
def writeComment(text)
|
||||
writeLine "; #{text}"
|
||||
end
|
||||
|
||||
def writeSection(name)
|
||||
lc = name.downcase
|
||||
return if lc == @section_lc
|
||||
writeLine if @newline < 1
|
||||
writeLine "[#{name}]"
|
||||
@section = name
|
||||
@section_lc = lc
|
||||
end
|
||||
|
||||
def writeKey(key, value)
|
||||
value = value.to_s
|
||||
value = "\"#{value}\"" if value.strip != value
|
||||
writeLine "#{key}=#{value}"
|
||||
end
|
||||
|
||||
def writeEntry(section, key, value)
|
||||
writeSection section
|
||||
writeKey key, value
|
||||
end
|
||||
|
||||
def forward(token, *args)
|
||||
# Can receive tokens from IniReader directly
|
||||
case token
|
||||
when :comment
|
||||
writeComment *args
|
||||
when :section
|
||||
writeSection *args
|
||||
when :key
|
||||
writeKey *args
|
||||
when :line
|
||||
writeLine *args
|
||||
when :empty
|
||||
writeLine
|
||||
when :eof
|
||||
else
|
||||
raise "Unknown token: #{token}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class IniReader < IniBase
|
||||
FileMode = "rt"
|
||||
|
||||
def self.open(filename)
|
||||
# Pretend file is empty if it doesn't exist
|
||||
if !File.exist? filename then
|
||||
if block_given? then
|
||||
yield self.new DummyReadFile.new
|
||||
else
|
||||
return self.new DummyReadFile.new
|
||||
end
|
||||
else
|
||||
return super
|
||||
end
|
||||
end
|
||||
|
||||
def readComment(line)
|
||||
line.slice!(0, line[1] == " " ? 2 : 1)
|
||||
[line]
|
||||
end
|
||||
|
||||
def readSection(line)
|
||||
raise "Malformed section header: '#{line}'" if line[0] != '[' || line[-1] != ']'
|
||||
@section = line[1...-1]
|
||||
@section_lc = @section.downcase
|
||||
return [@section]
|
||||
end
|
||||
|
||||
def readKey(line)
|
||||
key, value = line.split('=', 2)
|
||||
value.strip!
|
||||
# Allow quoting to keep surrounding whitespace
|
||||
value = value[1...-1] if value.size > 1 && "'\"".include?(value[0]) && value[0] == value[-1]
|
||||
[key.strip, value]
|
||||
rescue ArgumentError => e
|
||||
puts "Error processing line: #{line.inspect} - #{e.message}"
|
||||
nil
|
||||
end
|
||||
|
||||
def readLine(line)
|
||||
if line.valid_encoding?
|
||||
line.strip!
|
||||
else
|
||||
# Optionally, handle the invalid encoding here:
|
||||
# You can choose to skip the line, replace invalid characters, or log it.
|
||||
line = line.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '?')
|
||||
end
|
||||
return [:empty] if line.empty?
|
||||
return :comment, *readComment(line) if line[0] == ';'
|
||||
return :section, *readSection(line) if line[0] == '['
|
||||
return :key, *readKey(line) if line.include? '='
|
||||
# Just pass it through as last resort
|
||||
return :line, line
|
||||
end
|
||||
|
||||
def read
|
||||
raise "Must be called with block" unless block_given?
|
||||
last = nil
|
||||
@file.each_line do |line|
|
||||
tok = readLine line
|
||||
# Collapse empty lines
|
||||
next if tok[0] == :empty && last == :empty
|
||||
last = tok[0]
|
||||
yield tok
|
||||
end
|
||||
yield :eof
|
||||
end
|
||||
end
|
||||
|
||||
# ********** Simple API **********
|
||||
# Read
|
||||
def self.readIniString(filename, section, key)
|
||||
# Intended to be compatible with ReadPrivateProfileString
|
||||
section_lc = section.downcase
|
||||
key_lc = key.downcase
|
||||
found_section = section.empty?
|
||||
IniReader.open filename do |ir|
|
||||
ir.read do |type, *args|
|
||||
case type
|
||||
when :section
|
||||
found_section = ir.section_lc == section_lc
|
||||
when :key
|
||||
fkey, fval = *args
|
||||
return fval if found_section && fkey.downcase == key_lc
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.readIniStrings(filename, section, keys=nil)
|
||||
result = {}
|
||||
section_lc = section.downcase
|
||||
keys_lc = {}
|
||||
keys.each {|key| keys_lc[key.downcase] = key} unless keys.nil?
|
||||
found_section = section.empty?
|
||||
IniReader.open filename do |ir|
|
||||
ir.read do |type, *args|
|
||||
case type
|
||||
when :section
|
||||
found_section = ir.section_lc == section_lc
|
||||
when :key
|
||||
if found_section then
|
||||
fkey, fval = *args
|
||||
if keys.nil? then
|
||||
result[fkey] = fval
|
||||
else
|
||||
zkey = keys_lc[fkey.downcase]
|
||||
result[zkey] = fval unless zkey.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
def self.readIniPaths(filename, paths=nil)
|
||||
result = {}
|
||||
paths_lc = {}
|
||||
paths.each {|path| lc = path.downcase; paths_lc[lc] = path unless paths_lc.include? lc} unless paths.nil?
|
||||
section_all = paths.nil? || paths.include?("/*")
|
||||
section_all_name = nil
|
||||
IniReader.open filename do |ir|
|
||||
ir.read do |type, *args|
|
||||
case type
|
||||
when :section
|
||||
unless paths.nil? then
|
||||
section_all_name = paths_lc["#{ir.section_lc}/*"]
|
||||
section_all = !section_all_name.nil?
|
||||
section_all_name.slice!(-2...) if section_all
|
||||
end
|
||||
when :key
|
||||
fkey, fval = *args
|
||||
if section_all then
|
||||
fpath = "#{section_all_name.nil? ? ir.section : section_all_name}/#{fkey}"
|
||||
result[fpath] = fval
|
||||
else
|
||||
fpath = "#{ir.section_lc}/#{fkey.downcase}"
|
||||
result[paths_lc[fpath]] = fval if paths_lc.key? fpath
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def self.readIniSections(filename)
|
||||
# Get a list of sections in the file
|
||||
# Note: may contain (possibly case-mismatched) duplicates.
|
||||
sections = []
|
||||
IniReader.open filename do |ir|
|
||||
ir.read do |type, *args|
|
||||
case type
|
||||
when :section
|
||||
sections.push args[0]
|
||||
end
|
||||
end
|
||||
end
|
||||
return sections
|
||||
end
|
||||
|
||||
def self.readIniKeys(filename, section)
|
||||
# Get a list of keys in a section
|
||||
# Note: may contain (possibly case-mismatched) duplicates.
|
||||
keys = []
|
||||
section_lc = section.downcase
|
||||
found_section = section.empty?
|
||||
IniReader.open filename do |ir|
|
||||
ir.read do |type, *args|
|
||||
case type
|
||||
when :section
|
||||
found_section = ir.section_lc == section_lc
|
||||
when :key
|
||||
keys.push args[0] if found_section
|
||||
end
|
||||
end
|
||||
end
|
||||
return keys
|
||||
end
|
||||
|
||||
# Write
|
||||
def self.writeIniString(filename, section, key, value)
|
||||
# Intended to be compatible with WritePrivateProfileString
|
||||
# Write to new file then rename over top.
|
||||
section_lc = section.downcase
|
||||
key_lc = key.downcase unless key.nil?
|
||||
found_section = section.empty?
|
||||
written = key.nil? || value.nil? # Delete instead if nil
|
||||
temp_name = "#{filename}.tmp"
|
||||
IniWriter.open temp_name do |iw|
|
||||
IniReader.open filename do |ir|
|
||||
ir.read do |type, *args|
|
||||
case type
|
||||
when :section
|
||||
# Insert new key before leaving section
|
||||
if found_section && !written then
|
||||
iw.writeKey key, value
|
||||
written = true
|
||||
end
|
||||
# Start new section or omit whole section if key == nil
|
||||
found_section = ir.section_lc == section_lc
|
||||
iw.writeSection ir.section unless found_section && key.nil?
|
||||
when :key
|
||||
fkey, fval = *args
|
||||
if found_section then
|
||||
if fkey.downcase == key_lc then
|
||||
# Replace matching key
|
||||
iw.writeKey key, value unless written
|
||||
written = true
|
||||
elsif !key.nil? then
|
||||
# Copy other keys
|
||||
iw.writeKey fkey, fval
|
||||
end
|
||||
else
|
||||
iw.writeKey fkey, fval
|
||||
end
|
||||
when :eof
|
||||
# Add to end of file if not found earlier
|
||||
iw.writeEntry section, key, value unless written
|
||||
else
|
||||
iw.forward type, *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
File.rename(temp_name, filename)
|
||||
end
|
||||
|
||||
def self.writeIniStrings(filename, section, hash)
|
||||
# Write to new file then rename over top.
|
||||
section_lc = section.downcase
|
||||
hash_lc = {}
|
||||
written = []
|
||||
hash.each_pair do |key, value|
|
||||
key_lc = key.downcase
|
||||
hash_lc[key_lc] = [key, value] unless value.nil?
|
||||
written.push key_lc if value.nil?
|
||||
end
|
||||
found_section = section.empty?
|
||||
temp_name = "#{filename}.tmp"
|
||||
IniWriter.open temp_name do |iw|
|
||||
IniReader.open filename do |ir|
|
||||
ir.read do |type, *args|
|
||||
case type
|
||||
when :section
|
||||
# Insert new keys before leaving section
|
||||
if found_section && !hash_lc.empty? then
|
||||
hash_lc.each_pair {|key_lc, kv| iw.writeKey *kv}
|
||||
written.push *hash_lc.keys
|
||||
hash_lc.clear
|
||||
end
|
||||
# Start new section or omit whole section if key == nil
|
||||
found_section = ir.section_lc == section_lc
|
||||
iw.writeSection ir.section
|
||||
when :key
|
||||
fkey, fval = *args
|
||||
if found_section then
|
||||
fkey_lc = fkey.downcase
|
||||
entry = hash_lc.delete fkey_lc
|
||||
if !entry.nil? then
|
||||
# Replace matching key
|
||||
iw.writeKey *entry
|
||||
written.push fkey_lc
|
||||
next
|
||||
elsif written.include? fkey_lc then
|
||||
next
|
||||
end
|
||||
end
|
||||
iw.writeKey fkey, fval
|
||||
when :eof
|
||||
# Add to end of file if not found earlier
|
||||
if !hash_lc.empty? then
|
||||
iw.writeSection section
|
||||
hash_lc.each_value {|key, value| iw.writeKey key, value}
|
||||
end
|
||||
else
|
||||
iw.forward type, *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
File.rename(temp_name, filename)
|
||||
end
|
||||
|
||||
def self.writeIniPaths(filename, hash)
|
||||
# Write to new file then rename over top.
|
||||
sections = {}
|
||||
hash.each_pair do |path, value|
|
||||
section, _, key = path.rpartition '/'
|
||||
section_lc = section.downcase
|
||||
sections[section_lc] = {name: section, written: [], keys: {}} unless sections.key? section_lc
|
||||
sections[section_lc][:keys][key.downcase] = [key, value]
|
||||
end
|
||||
current_section = sections[""]
|
||||
temp_name = "#{filename}.tmp"
|
||||
IniWriter.open temp_name do |iw|
|
||||
IniReader.open filename do |ir|
|
||||
ir.read do |type, *args|
|
||||
case type
|
||||
when :section
|
||||
# Write new keys before leaving section
|
||||
if !current_section.nil? then
|
||||
current_section[:keys].each_value {|key, value| iw.writeKey key, value}
|
||||
current_section[:written].push *current_section[:keys].keys
|
||||
current_section[:keys].clear
|
||||
end
|
||||
# new section
|
||||
iw.writeSection ir.section
|
||||
current_section = sections[ir.section_lc]
|
||||
when :key
|
||||
fkey, fval = *args
|
||||
fkey_lc = fkey.downcase
|
||||
# Replace matching key
|
||||
if !current_section.nil? then
|
||||
replacement = current_section[:keys].delete fkey_lc
|
||||
if !replacement.nil? then
|
||||
iw.writeKey *replacement unless replacement[1].nil?
|
||||
current_section[:written].push fkey_lc
|
||||
next
|
||||
elsif current_section[:written].include? fkey_lc then
|
||||
next
|
||||
end
|
||||
end
|
||||
# Copy other keys
|
||||
iw.writeKey fkey, fval
|
||||
when :eof
|
||||
# Add sections not previously seen
|
||||
sections.each_value do |sect|
|
||||
if !sect[:keys].empty? then
|
||||
iw.writeSection sect[:name]
|
||||
sect[:keys].each_value do |key, value|
|
||||
iw.writeKey key, value
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
iw.forward type, *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
File.rename(temp_name, filename)
|
||||
end
|
||||
end
|
||||
end
|
130
Kawariki-patches/libs/Win32API.rb
Normal file
130
Kawariki-patches/libs/Win32API.rb
Normal file
|
@ -0,0 +1,130 @@
|
|||
=begin
|
||||
Win32API emulation
|
||||
|
||||
MKXP-Z exposes an implementation of the Win32API module (called MiniFFI) by default.
|
||||
However, this alias is only actually useful on Windows. Therefore, we replace it
|
||||
with a pure-ruby version specifically implementing the most common imports.
|
||||
Real native libraries can still be accessed through MiniFII.new (e.g. in ports)
|
||||
|
||||
Lambdas are used for implementations as they replicate Win32API's #call interface.
|
||||
=end
|
||||
|
||||
# Don't expose MiniFFI as Win32API
|
||||
Object.remove_const :Win32API
|
||||
|
||||
module Win32API
|
||||
module Kernel32
|
||||
GetPrivateProfileInt = GetPrivateProfileIntA = ->(appname, keyname, default, filename) do
|
||||
Preload.require "PreloadIni.rb"
|
||||
s = Preload::Ini.readIniString filename, appname, keyname
|
||||
s.nil? ? default : s.to_i
|
||||
end
|
||||
GetPrivateProfileString = GetPrivateProfileStringA = ->(appname, keyname, default, ret, size, filename) do
|
||||
Preload.require "PreloadIni.rb"
|
||||
if appname.nil? then
|
||||
res = Preload::Ini.readIniSections(filename).join("\0") + "\0"
|
||||
elsif keyname.nil? then
|
||||
res = Preload::Ini.readIniKeys(filename, appname).join("\0") + "\0"
|
||||
else
|
||||
s = Preload::Ini.readIniString filename, appname, keyname
|
||||
res = s.nil? ? (default.nil? ? "" : default) : s
|
||||
end
|
||||
# C-String dance
|
||||
size -= 1
|
||||
if res.size > size then
|
||||
res.slice!(size...)
|
||||
res[size-1] = "\0" if appname.nil? or keyname.nil?
|
||||
end
|
||||
ret[...res.size] = res
|
||||
ret[res.size] = "\0"
|
||||
res.size
|
||||
end
|
||||
WritePrivateProfileString = WritePrivateProfileStringA = ->(appname, keyname, value, filename) do
|
||||
Preload.require "PreloadIni.rb"
|
||||
Preload::Ini.writeIniString filename, appname, keyname, value
|
||||
end
|
||||
end
|
||||
|
||||
module User32
|
||||
FindWindow = FindWindowA = ->(cls, wnd) do
|
||||
return 1
|
||||
end
|
||||
FindWindowEx = ->(parent, ca, cls, wnd) do
|
||||
return 1
|
||||
end
|
||||
GetAsyncKeyState = ->(key) do
|
||||
# Very naive
|
||||
return 128 if Input.pressex? key
|
||||
return 0
|
||||
end
|
||||
GetClientRect = ->(hWnd, out_rect) do
|
||||
return 0 unless hWnd == 1
|
||||
# out_rect.byteslice(0, 16, [0, 0, Graphics.width, Graphics.height].pack("llll"))
|
||||
out_rect[0, 16] = [0, 0, Graphics.width, Graphics.height].pack("llll")
|
||||
return 1
|
||||
end
|
||||
GetCursorPos = ->(out_point) do
|
||||
# Pack mouse coordinates into a binary string
|
||||
packed_coords = [Input.mouse_x, Input.mouse_y].pack("ll")
|
||||
|
||||
# Update the out_point string with the packed data (overwrite first 8 bytes)
|
||||
out_point[0, 8] = packed_coords
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
|
||||
GetKeyboardLayout = ->(thread) do
|
||||
return 0
|
||||
end
|
||||
GetSystemMetrics = ->(index) do
|
||||
return Graphics.width if index == 0 # SM_CXSCREEN - Primary screen width
|
||||
return Graphics.height if index == 1 # SM_CYSCREEN - Primary screen height
|
||||
return 0 if index == 4 # SM_CYCAPTION - Height of caption area (title bar?)
|
||||
return 0 if index == 5 # SM_CXBORDER - Width of window borders
|
||||
return 0 if index == 6 # SM_CYBORDER - Height of window borders
|
||||
return 0 if index == 23 # SM_SWAPBUTTON - Swap left/right mouse buttons
|
||||
return 0 if index == 45 # SM_CXEDGE - Width of 3D window borders
|
||||
Preload.print("Warning: user32#GetSystemMetrics index #{index} not implemented")
|
||||
return 0
|
||||
end
|
||||
GetWindowRect = ->(hWnd, out_rect) do
|
||||
return 0 unless hWnd == 1
|
||||
# out_rect.byteslice(0, 16, [0, 0, Graphics.width, Graphics.height].pack("llll"))
|
||||
out_rect[0, 16] = [0, 0, Graphics.width, Graphics.height].pack("llll")
|
||||
return 1
|
||||
end
|
||||
MapVirtualKeyEx = ->(code, map, layout) do
|
||||
return 0 unless layout == 0
|
||||
return code
|
||||
end
|
||||
ScreenToClient = ->(hWnd, point) do
|
||||
return 1 unless hWnd != 1
|
||||
return 0
|
||||
end
|
||||
ShowCursor = ->(show) do
|
||||
Graphics.show_cursor = show == 1
|
||||
return show
|
||||
end
|
||||
end
|
||||
|
||||
module SteamAPI
|
||||
# TODO: Forward to native steamapi?
|
||||
SteamAPI_Init = ->{1}
|
||||
SteamAPI_Shutdown = ->{}
|
||||
end
|
||||
|
||||
Libraries = {
|
||||
"kernel32" => Kernel32,
|
||||
"user32" => User32,
|
||||
"steam_api" => SteamAPI,
|
||||
}
|
||||
|
||||
def self.new(dllname, func, *rest)
|
||||
dllname = dllname[...-4] if dllname[...-4] == ".dll"
|
||||
lib = Libraries[dllname]
|
||||
return lib.const_get(func, false) if lib.const_defined?(func, false) unless lib.nil?
|
||||
Preload.print("Warning: Win32API not implemented: #{dllname}##{func}")
|
||||
return ->(*args){Preload.print "(STUB) #{dllname}##{func}: #{args}"}
|
||||
end
|
||||
end
|
346
Kawariki-patches/libs/Win32APIl.rb
Normal file
346
Kawariki-patches/libs/Win32APIl.rb
Normal file
|
@ -0,0 +1,346 @@
|
|||
=begin
|
||||
Win32API emulation
|
||||
|
||||
MKXP-Z exposes an implementation of the Win32API module (called MiniFFI) by default.
|
||||
However, this alias is only actually useful on Windows. Therefore, we replace it
|
||||
with a pure-ruby version specifically implementing the most common imports.
|
||||
Real native libraries can still be accessed through MiniFII.new (e.g. in ports)
|
||||
|
||||
Lambdas are used for implementations as they replicate Win32API's #call interface.
|
||||
=end
|
||||
|
||||
|
||||
module Scancodes
|
||||
SDL = { :UNKNOWN => 0x00,
|
||||
:A => 0x04, :B => 0x05, :C => 0x06, :D => 0x07,
|
||||
:E => 0x08, :F => 0x09, :G => 0x0A, :H => 0x0B,
|
||||
:I => 0x0C, :J => 0x0D, :K => 0x0E, :L => 0x0F,
|
||||
:M => 0x10, :N => 0x11, :O => 0x12, :P => 0x13,
|
||||
:Q => 0x14, :R => 0x15, :S => 0x16, :T => 0x17,
|
||||
:U => 0x18, :V => 0x19, :W => 0x1A, :X => 0x1B,
|
||||
:Y => 0x1C, :Z => 0x1D, :N1 => 0x1E, :N2 => 0x1F,
|
||||
:N3 => 0x20, :N4 => 0x21, :N5 => 0x22, :N6 => 0x23,
|
||||
:N7 => 0x24, :N8 => 0x25, :N9 => 0x26, :N0 => 0x27,
|
||||
:RETURN => 0x28, :ESCAPE => 0x29, :BACKSPACE => 0x2A, :TAB => 0x2B,
|
||||
:SPACE => 0x2C, :MINUS => 0x2D, :EQUALS => 0x2E, :LEFTBRACKET => 0x2F,
|
||||
:RIGHTBRACKET => 0x30, :BACKSLASH => 0x31, :NONUSHASH => 0x32, :SEMICOLON => 0x33,
|
||||
:APOSTROPHE => 0x34, :GRAVE => 0x35, :COMMA => 0x36, :PERIOD => 0x37,
|
||||
:SLASH => 0x38, :CAPSLOCK => 0x39, :F1 => 0x3A, :F2 => 0x3B,
|
||||
:F3 => 0x3C, :F4 => 0x3D, :F5 => 0x3E, :F6 => 0x3F,
|
||||
:F7 => 0x40, :F8 => 0x41, :F9 => 0x42, :F10 => 0x43,
|
||||
:F11 => 0x44, :F12 => 0x45, :PRINTSCREEN => 0x46, :SCROLLLOCK => 0x47,
|
||||
:PAUSE => 0x48, :INSERT => 0x49, :HOME => 0x4A, :PAGEUP => 0x4B,
|
||||
:DELETE => 0x4C, :END => 0x4D, :PAGEDOWN => 0x4E, :RIGHT => 0x4F,
|
||||
:LEFT => 0x50, :DOWN => 0x51, :UP => 0x52, :NUMLOCKCLEAR => 0x53,
|
||||
:KP_DIVIDE => 0x54, :KP_MULTIPLY => 0x55, :KP_MINUS => 0x56, :KP_PLUS => 0x57,
|
||||
:KP_ENTER => 0x58, :KP_1 => 0x59, :KP_2 => 0x5A, :KP_3 => 0x5B,
|
||||
:KP_4 => 0x5C, :KP_5 => 0x5D, :KP_6 => 0x5E, :KP_7 => 0x5F,
|
||||
:KP_8 => 0x60, :KP_9 => 0x61, :KP_0 => 0x62, :KP_PERIOD => 0x63,
|
||||
:NONUSBACKSLASH => 0x64, :APPLICATION => 0x65, :POWER => 0x66, :KP_EQUALS => 0x67,
|
||||
:F13 => 0x68, :F14 => 0x69, :F15 => 0x6A, :F16 => 0x6B,
|
||||
:F17 => 0x6C, :F18 => 0x6D, :F19 => 0x6E, :F20 => 0x6F,
|
||||
:F21 => 0x70, :F22 => 0x71, :F23 => 0x72, :F24 => 0x73,
|
||||
:EXECUTE => 0x74, :HELP => 0x75, :MENU => 0x76, :SELECT => 0x77,
|
||||
:STOP => 0x78, :AGAIN => 0x79, :UNDO => 0x7A, :CUT => 0x7B,
|
||||
:COPY => 0x7C, :PASTE => 0x7D, :FIND => 0x7E, :MUTE => 0x7F,
|
||||
:VOLUMEUP => 0x80, :VOLUMEDOWN => 0x81, :LOCKINGCAPSLOCK => 0x82, :LOCKINGNUMLOCK => 0x83,
|
||||
:LOCKINGSCROLLLOCK => 0x84, :KP_COMMA => 0x85, :KP_EQUALSAS400 => 0x86, :INTERNATIONAL1 => 0x87,
|
||||
:INTERNATIONAL2 => 0x88, :INTERNATIONAL3 => 0x89, :INTERNATIONAL4 => 0x8A, :INTERNATIONAL5 => 0x8B,
|
||||
:INTERNATIONAL6 => 0x8C, :INTERNATIONAL7 => 0x8D, :INTERNATIONAL8 => 0x8E, :INTERNATIONAL9 => 0x8F,
|
||||
:LANG1 => 0x90, :LANG2 => 0x91, :LANG3 => 0x92, :LANG4 => 0x93,
|
||||
:LANG5 => 0x94, :LANG6 => 0x95, :LANG7 => 0x96, :LANG8 => 0x97,
|
||||
:LANG9 => 0x98, :ALTERASE => 0x99, :SYSREQ => 0x9A, :CANCEL => 0x9B,
|
||||
:CLEAR => 0x9C, :PRIOR => 0x9D, :RETURN2 => 0x9E, :SEPARATOR => 0x9F,
|
||||
:OUT => 0xA0, :OPER => 0xA1, :CLEARAGAIN => 0xA2, :CRSEL => 0xA3,
|
||||
:EXSEL => 0xA4, :KP_00 => 0xB0, :KP_000 => 0xB1, :THOUSANDSSEPARATOR => 0xB2,
|
||||
:DECIMALSEPARATOR => 0xB3, :CURRENCYUNIT => 0xB4, :CURRENCYSUBUNIT => 0xB5, :KP_LEFTPAREN => 0xB6,
|
||||
:KP_RIGHTPAREN => 0xB7, :KP_LEFTBRACE => 0xB8, :KP_RIGHTBRACE => 0xB9, :KP_TAB => 0xBA,
|
||||
:KP_BACKSPACE => 0xBB, :KP_A => 0xBC, :KP_B => 0xBD, :KP_C => 0xBE,
|
||||
:KP_D => 0xBF, :KP_E => 0xC0, :KP_F => 0xC1, :KP_XOR => 0xC2,
|
||||
:KP_POWER => 0xC3, :KP_PERCENT => 0xC4, :KP_LESS => 0xC5, :KP_GREATER => 0xC6,
|
||||
:KP_AMPERSAND => 0xC7, :KP_DBLAMPERSAND => 0xC8, :KP_VERTICALBAR => 0xC9, :KP_DBLVERTICALBAR => 0xCA,
|
||||
:KP_COLON => 0xCB, :KP_HASH => 0xCC, :KP_SPACE => 0xCD, :KP_AT => 0xCE,
|
||||
:KP_EXCLAM => 0xCF, :KP_MEMSTORE => 0xD0, :KP_MEMRECALL => 0xD1, :KP_MEMCLEAR => 0xD2,
|
||||
:KP_MEMADD => 0xD3, :KP_MEMSUBTRACT => 0xD4, :KP_MEMMULTIPLY => 0xD5, :KP_MEMDIVIDE => 0xD6,
|
||||
:KP_PLUSMINUS => 0xD7, :KP_CLEAR => 0xD8, :KP_CLEARENTRY => 0xD9, :KP_BINARY => 0xDA,
|
||||
:KP_OCTAL => 0xDB, :KP_DECIMAL => 0xDC, :KP_HEXADECIMAL => 0xDD, :LCTRL => 0xE0,
|
||||
:LSHIFT => 0xE1, :LALT => 0xE2, :LGUI => 0xE3, :RCTRL => 0xE4,
|
||||
:RSHIFT => 0xE5, :RALT => 0xE6, :RGUI => 0xE7, :MODE => 0x101,
|
||||
:AUDIONEXT => 0x102, :AUDIOPREV => 0x103, :AUDIOSTOP => 0x104, :AUDIOPLAY => 0x105,
|
||||
:AUDIOMUTE => 0x106, :MEDIASELECT => 0x107, :WWW => 0x108, :MAIL => 0x109,
|
||||
:CALCULATOR => 0x10A, :COMPUTER => 0x10B, :AC_SEARCH => 0x10C, :AC_HOME => 0x10D,
|
||||
:AC_BACK => 0x10E, :AC_FORWARD => 0x10F, :AC_STOP => 0x110, :AC_REFRESH => 0x111,
|
||||
:AC_BOOKMARKS => 0x112, :BRIGHTNESSDOWN => 0x113, :BRIGHTNESSUP => 0x114, :DISPLAYSWITCH => 0x115,
|
||||
:KBDILLUMTOGGLE => 0x116, :KBDILLUMDOWN => 0x117, :KBDILLUMUP => 0x118, :EJECT => 0x119,
|
||||
:SLEEP => 0x11A, :APP1 => 0x11B, :APP2 => 0x11C
|
||||
}
|
||||
|
||||
SDL.default = SDL[:UNKNOWN]
|
||||
|
||||
WIN32 = {
|
||||
:LBUTTON => 0x01, :RBUTTON => 0x02, :MBUTTON => 0x04,
|
||||
|
||||
:BACK => 0x08, :TAB => 0x09, :RETURN => 0x0D, :SHIFT => 0x10,
|
||||
:CONTROL => 0x11, :MENU => 0x12, :PAUSE => 0x13, :CAPITAL => 0x14,
|
||||
:ESCAPE => 0x1B, :SPACE => 0x20, :PRIOR => 0x21, :NEXT => 0x22,
|
||||
:END => 0x23, :HOME => 0x24, :LEFT => 0x25, :UP => 0x26,
|
||||
:RIGHT => 0x27, :DOWN => 0x28, :PRINT => 0x2A, :INSERT => 0x2D,
|
||||
:DELETE => 0x2E,
|
||||
|
||||
:N0 => 0x30, :N1 => 0x31, :N2 => 0x32, :N3 => 0x33,
|
||||
:N4 => 0x34, :N5 => 0x35, :N6 => 0x36, :N7 => 0x37, :N8 => 0x38,
|
||||
:N9 => 0x39,
|
||||
|
||||
:A => 0x41, :B => 0x42, :C => 0x43, :D => 0x44, :E => 0x45, :F => 0x46,
|
||||
:G => 0x47, :H => 0x48, :I => 0x49, :J => 0x4A, :K => 0x4B, :L => 0x4C,
|
||||
:M => 0x4D, :N => 0x4E, :O => 0x4F, :P => 0x50, :Q => 0x51, :R => 0x52,
|
||||
:S => 0x53, :T => 0x54, :U => 0x55, :V => 0x56, :W => 0x57, :X => 0x58,
|
||||
:Y => 0x59, :Z => 0x5A,
|
||||
|
||||
:LWIN => 0x5B, :RWIN => 0x5C,
|
||||
|
||||
:NUMPAD0 => 0x60, :NUMPAD1 => 0x61, :NUMPAD2 => 0x62, :NUMPAD3 => 0x63,
|
||||
:NUMPAD4 => 0x64, :NUMPAD5 => 0x65, :NUMPAD6 => 0x66, :NUMPAD7 => 0x67,
|
||||
:NUMPAD8 => 0x68, :NUMPAD9 => 0x69,
|
||||
:MULTIPLY => 0x6A, :ADD => 0x6B, :SEPARATOR => 0x6C, :SUBSTRACT => 0x6D,
|
||||
:DECIMAL => 0x6E, :DIVIDE => 0x6F,
|
||||
|
||||
:F1 => 0x70, :F2 => 0x71, :F3 => 0x72, :F4 => 0x73,
|
||||
:F5 => 0x74, :F6 => 0x75, :F7 => 0x76, :F8 => 0x77,
|
||||
:F9 => 0x78, :F10 => 0x79, :F11 => 0x7A, :F12 => 0x7B,
|
||||
:F13 => 0x7C, :F14 => 0x7D, :F15 => 0x7E, :F16 => 0x7F,
|
||||
:F17 => 0x80, :F18 => 0x81, :F19 => 0x82, :F20 => 0x83,
|
||||
:F21 => 0x84, :F22 => 0x85, :F23 => 0x86, :F24 => 0x87,
|
||||
|
||||
:NUMLOCK => 0x90, :SCROLL => 0x91,
|
||||
:LSHIFT => 0xA0, :RSHIFT => 0xA1, :LCONTROL => 0xA2, :RCONTROL => 0xA3,
|
||||
:LMENU => 0xA4, :RMENU => 0xA5, :OEM_1 => 0xBA,
|
||||
:OEM_PLUS => 0xBB, :OEM_COMMA => 0xBC, :OEM_MINUS => 0xBD, :OEM_PERIOD => 0xBE,
|
||||
:OEM_2 => 0xBF, :OEM_3 => 0xC0, :OEM_4 => 0xDB, :OEM_5 => 0xDC,
|
||||
:OEM_6 => 0xDD, :OEM_7 => 0xDE
|
||||
}
|
||||
|
||||
WIN32INV = WIN32.invert
|
||||
|
||||
WIN2SDL = {
|
||||
:BACK => :BACKSPACE,
|
||||
:CAPITAL => :CAPSLOCK,
|
||||
:PRIOR => :PAGEUP, :NEXT => :PAGEDOWN,
|
||||
:PRINT => :PRINTSCREEN,
|
||||
|
||||
:LWIN => :LGUI, :RWIN => :RGUI,
|
||||
|
||||
:NUMPAD0 => :KP_0, :NUMPAD1 => :KP_1, :NUMPAD2 => :KP_2, :NUMPAD3 => :KP_3,
|
||||
:NUMPAD4 => :KP_4, :NUMPAD5 => :KP_5, :NUMPAD6 => :KP_6, :NUMPAD7 => :KP_7,
|
||||
:NUMPAD8 => :KP_8, :NUMPAD9 => :KP_9,
|
||||
:MULTIPLY => :KP_MULTIPLY, :ADD => :KP_PLUS, :SUBSTRACT => :KP_MINUS,
|
||||
:DECIMAL => :KP_DECIMAL, :DIVIDE => :KP_DIVIDE,
|
||||
|
||||
:NUMLOCK => :NUMLOCKCLEAR, :SCROLL => :SCROLLLOCK,
|
||||
:LCONTROL => :LCTRL, :RCONTROL => :RCTRL,
|
||||
# FIXME: Fill these out
|
||||
:LMENU => :LALT, :RMENU => :RALT, :OEM_1 => :SEMICOLON,
|
||||
:OEM_PLUS => :UNKNOWN, :OEM_COMMA => :UNKNOWN, :OEM_MINUS => :UNKNOWN, :OEM_PERIOD => :UNKNOWN,
|
||||
:OEM_2 => :UNKNOWN, :OEM_3 => :UNKNOWN, :OEM_4 => :UNKNOWN, :OEM_5 => :UNKNOWN,
|
||||
:OEM_6 => :UNKNOWN, :OEM_7 => :UNKNOWN
|
||||
}
|
||||
|
||||
WIN2SDL.default = :UNKNOWN
|
||||
end
|
||||
|
||||
$win32KeyStates = nil
|
||||
|
||||
module Graphics
|
||||
class << self
|
||||
alias_method(:win32wrap_update, :update)
|
||||
def update
|
||||
win32wrap_update
|
||||
$win32KeyStates = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_raw_keystates
|
||||
if $win32KeyStates == nil
|
||||
$win32KeyStates = Input.raw_key_states
|
||||
end
|
||||
|
||||
return $win32KeyStates
|
||||
end
|
||||
|
||||
def common_keystate(vkey)
|
||||
vkey_name = Scancodes::WIN32INV[vkey]
|
||||
|
||||
states = get_raw_keystates
|
||||
pressed = false
|
||||
|
||||
if vkey_name == :LBUTTON
|
||||
pressed = Input.press?(Input::MOUSELEFT)
|
||||
elsif vkey_name == :RBUTTON
|
||||
pressed = Input.press?(Input::MOUSERIGHT)
|
||||
elsif vkey_name == :MBUTTON
|
||||
pressed = Input.press?(Input::MOUSEMIDDLE)
|
||||
elsif vkey_name == :SHIFT
|
||||
pressed = double_state(states, :LSHIFT, :RSHIFT)
|
||||
elsif vkey_name == :MENU
|
||||
pressed = double_state(states, :LALT, :RALT)
|
||||
elsif vkey_name == :CONTROL
|
||||
pressed = double_state(states, :LCTRL, :RCTRL)
|
||||
else
|
||||
scan = nil
|
||||
if Scancodes::SDL.key?(vkey_name)
|
||||
scan = vkey_name
|
||||
else
|
||||
scan = Scancodes::WIN2SDL[vkey_name]
|
||||
end
|
||||
|
||||
pressed = state_pressed(states, scan)
|
||||
end
|
||||
|
||||
return pressed ? 1 : 0
|
||||
end
|
||||
|
||||
def memcpy_string(dst, src)
|
||||
i = 0
|
||||
src.each_byte do |b|
|
||||
dst.setbyte(i, b)
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
def state_pressed(states, sdl_scan)
|
||||
return states[Scancodes::SDL[sdl_scan]]
|
||||
end
|
||||
|
||||
def double_state(states, left, right)
|
||||
return state_pressed(states, left) || state_pressed(states, right)
|
||||
end
|
||||
|
||||
# Don't expose MiniFFI as Win32API
|
||||
Object.remove_const :Win32API
|
||||
|
||||
module Win32API
|
||||
module Kernel32
|
||||
GetPrivateProfileInt = GetPrivateProfileIntA = ->(appname, keyname, default, filename) do
|
||||
Preload.require "PreloadIni.rb"
|
||||
s = Preload::Ini.readIniString filename, appname, keyname
|
||||
s.nil? ? default : s.to_i
|
||||
end
|
||||
GetPrivateProfileString = GetPrivateProfileStringA = ->(appname, keyname, default, ret, size, filename) do
|
||||
Preload.require "PreloadIni.rb"
|
||||
if appname.nil? then
|
||||
res = Preload::Ini.readIniSections(filename).join("\0") + "\0"
|
||||
elsif keyname.nil? then
|
||||
res = Preload::Ini.readIniKeys(filename, appname).join("\0") + "\0"
|
||||
else
|
||||
s = Preload::Ini.readIniString filename, appname, keyname
|
||||
res = s.nil? ? (default.nil? ? "" : default) : s
|
||||
end
|
||||
# C-String dance
|
||||
size -= 1
|
||||
if res.size > size then
|
||||
res.slice!(size...)
|
||||
res[size-1] = "\0" if appname.nil? or keyname.nil?
|
||||
end
|
||||
ret[...res.size] = res
|
||||
ret[res.size] = "\0"
|
||||
res.size
|
||||
end
|
||||
WritePrivateProfileString = WritePrivateProfileStringA = ->(appname, keyname, value, filename) do
|
||||
Preload.require "PreloadIni.rb"
|
||||
Preload::Ini.writeIniString filename, appname, keyname, value
|
||||
end
|
||||
MultiByteToWideChar = MultiByteToWideCharA = ->(codepage, flags, input_str, input_len, buffer, buffer_size) do
|
||||
puts codepage, flags, input_str, input_len, buffer, buffer_size
|
||||
|
||||
#Preload.require "PreloadIni.rb"
|
||||
#Preload::Ini.writeIniString filename, appname, keyname, value
|
||||
end
|
||||
end
|
||||
|
||||
module User32
|
||||
FindWindow = FindWindowA = ->(cls, wnd) do
|
||||
return 1
|
||||
end
|
||||
FindWindowEx = ->(parent, ca, cls, wnd) do
|
||||
return 1
|
||||
end
|
||||
GetAsyncKeyState = ->(key) do
|
||||
# Very naive
|
||||
return 128 if Input.pressex? key
|
||||
return 0
|
||||
end
|
||||
GetClientRect = ->(hWnd, out_rect) do
|
||||
return 0 unless hWnd == 1
|
||||
# out_rect.byteslice(0, 16, [0, 0, Graphics.width, Graphics.height].pack("llll"))
|
||||
out_rect[0, 16] = [0, 0, Graphics.width, Graphics.height].pack("llll")
|
||||
return 1
|
||||
end
|
||||
GetCursorPos = ->(out_point) do
|
||||
# Pack mouse coordinates into a binary string
|
||||
packed_coords = [Input.mouse_x, Input.mouse_y].pack("ll")
|
||||
|
||||
# Update the out_point string with the packed data (overwrite first 8 bytes)
|
||||
out_point[0, 8] = packed_coords
|
||||
|
||||
return 1
|
||||
end
|
||||
GetKeyState = ->(vkey) do
|
||||
puts 'bbb'
|
||||
return common_keystate(vkey[0])
|
||||
end
|
||||
|
||||
GetKeyboardLayout = ->(thread) do
|
||||
return 0
|
||||
end
|
||||
GetSystemMetrics = ->(index) do
|
||||
return Graphics.width if index == 0 # SM_CXSCREEN - Primary screen width
|
||||
return Graphics.height if index == 1 # SM_CYSCREEN - Primary screen height
|
||||
return 0 if index == 4 # SM_CYCAPTION - Height of caption area (title bar?)
|
||||
return 0 if index == 5 # SM_CXBORDER - Width of window borders
|
||||
return 0 if index == 6 # SM_CYBORDER - Height of window borders
|
||||
return 0 if index == 23 # SM_SWAPBUTTON - Swap left/right mouse buttons
|
||||
return 0 if index == 45 # SM_CXEDGE - Width of 3D window borders
|
||||
Preload.print("Warning: user32#GetSystemMetrics index #{index} not implemented")
|
||||
return 0
|
||||
end
|
||||
GetWindowRect = ->(hWnd, out_rect) do
|
||||
return 0 unless hWnd == 1
|
||||
# out_rect.byteslice(0, 16, [0, 0, Graphics.width, Graphics.height].pack("llll"))
|
||||
out_rect[0, 16] = [0, 0, Graphics.width, Graphics.height].pack("llll")
|
||||
return 1
|
||||
end
|
||||
MapVirtualKeyEx = ->(code, map, layout) do
|
||||
return 0 unless layout == 0
|
||||
return code
|
||||
end
|
||||
ScreenToClient = ->(hWnd, point) do
|
||||
return 1 unless hWnd != 1
|
||||
return 0
|
||||
end
|
||||
ShowCursor = ->(show) do
|
||||
Graphics.show_cursor = show == 1
|
||||
return show
|
||||
end
|
||||
end
|
||||
|
||||
module SteamAPI
|
||||
# TODO: Forward to native steamapi?
|
||||
SteamAPI_Init = ->{1}
|
||||
SteamAPI_Shutdown = ->{}
|
||||
end
|
||||
|
||||
Libraries = {
|
||||
"kernel32" => Kernel32,
|
||||
"user32" => User32,
|
||||
"steam_api" => SteamAPI,
|
||||
}
|
||||
|
||||
def self.new(dllname, func, *rest)
|
||||
dllname = dllname[...-4] if dllname[...-4] == ".dll"
|
||||
lib = Libraries[dllname]
|
||||
return lib.const_get(func, false) if lib.const_defined?(func, false) unless lib.nil?
|
||||
Preload.print("Warning: Win32API not implemented: #{dllname}##{func}")
|
||||
return ->(*args){Preload.print "(STUB) #{dllname}##{func}: #{args}"}
|
||||
end
|
||||
end
|
136
Kawariki-patches/libs/XP_TilemapOverrideLib.rb
Normal file
136
Kawariki-patches/libs/XP_TilemapOverrideLib.rb
Normal file
|
@ -0,0 +1,136 @@
|
|||
# ======================================================================
|
||||
# MKXP-Z Custom tilemap workaround tools
|
||||
#
|
||||
# Authors: Roza, Taeyeon Mori
|
||||
#
|
||||
# Contains library code only, must be added to custom
|
||||
# tilemap classes using a preload patch or similar.
|
||||
# ======================================================================
|
||||
# SUPER TILEMAP VERTICAL WRAPPER THING
|
||||
#
|
||||
# This is a little fix for Pokemon Essentials' custom tilemap code
|
||||
# that works around MKXP's GPU texture size limit that would normally
|
||||
# stop you from playing a lot of games.
|
||||
#
|
||||
# The concept is simple enough: If your tileset is too big, a new
|
||||
# bitmap will be constructed with all the excess pixels sent to the
|
||||
# image's right side. This basically means that you now have a limit
|
||||
# far higher than you should ever actually need.
|
||||
#
|
||||
# 1024 -> 4096
|
||||
# 2048 -> 16384 (enough to get the normal limit)
|
||||
# 4096 -> 65536 (enough to load pretty much any tileset)
|
||||
# 8192 -> 262144
|
||||
# 16384 -> 1048576 (what most people have at this point)
|
||||
#
|
||||
# Because of the extra math the game will have to do to find the right
|
||||
# pixels, this will probably cause a slight performance hit while on these
|
||||
# maps which would normally be megasurfaces.
|
||||
#
|
||||
# This script was written for games based on 17.1. This workaround is
|
||||
# already implemented in 19.
|
||||
#
|
||||
# ~Roza/Zoroark
|
||||
#=======================================================================
|
||||
|
||||
module TileWrap
|
||||
|
||||
MAX_TEX_SIZE = Bitmap.max_size
|
||||
TILESET_WIDTH = 0x100
|
||||
MAX_TEX_SIZE_BOOSTED = MAX_TEX_SIZE**2/TILESET_WIDTH
|
||||
|
||||
def self.clamp(val, min, max)
|
||||
val = max if val > max
|
||||
val = min if val < min
|
||||
return val
|
||||
end
|
||||
|
||||
def self.wrapTileset(originalbmp)
|
||||
width = originalbmp.width
|
||||
height = originalbmp.height
|
||||
if width == TILESET_WIDTH && originalbmp.mega?
|
||||
columns = (height / MAX_TEX_SIZE.to_f).ceil
|
||||
|
||||
if columns * TILESET_WIDTH > MAX_TEX_SIZE
|
||||
raise "Tilemap is too long!\n\nSIZE: #{originalbmp.height}px\nHARDWARE LIMIT: #{MAX_TEX_SIZE}px\nBOOSTED LIMIT: #{MAX_TEX_SIZE_BOOSTED}px"
|
||||
end
|
||||
bmp = Bitmap.new(TILESET_WIDTH*columns, MAX_TEX_SIZE)
|
||||
remainder = height % MAX_TEX_SIZE
|
||||
|
||||
columns.times{|col|
|
||||
srcrect = Rect.new(0, col * MAX_TEX_SIZE, width, (col + 1 == columns) ? remainder : MAX_TEX_SIZE)
|
||||
bmp.blt(col*TILESET_WIDTH, 0, originalbmp, srcrect)
|
||||
}
|
||||
return bmp
|
||||
end
|
||||
|
||||
return originalbmp
|
||||
end
|
||||
|
||||
def self.wrapRect(srcrect)
|
||||
column, y = srcrect.y.divmod MAX_TEX_SIZE
|
||||
raise "Rect split across column wrap!" if y + srcrect.height > MAX_TEX_SIZE
|
||||
return srcrect if column == 0
|
||||
Rect.new(column * MAX_TEX_SIZE + srcrect.x, y, srcrect.width, srcrect.height)
|
||||
end
|
||||
|
||||
def self.wrapRect!(rect)
|
||||
column, y = rect.y.divmod MAX_TEX_SIZE
|
||||
raise "Rect split across column wrap!" if y + rect.height > MAX_TEX_SIZE
|
||||
return if column == 0
|
||||
rect.x = column * MAX_TEX_SIZE + rect.x
|
||||
rect.y = y
|
||||
end
|
||||
|
||||
def self.blitWrappedPixels(destX, destY, dest, src, srcrect)
|
||||
if (srcrect.y + srcrect.width < MAX_TEX_SIZE)
|
||||
# Save the processing power
|
||||
return dest.blt(destX, destY, src, srcrect)
|
||||
end
|
||||
merge = (srcrect.y % MAX_TEX_SIZE) > ((srcrect.y + srcrect.height) % MAX_TEX_SIZE)
|
||||
|
||||
srcrect.x = clamp(srcrect.x, 0,TILESET_WIDTH)
|
||||
srcrect.width = clamp(srcrect.width, 0, TILESET_WIDTH - srcrect.x)
|
||||
col = (srcrect.y / MAX_TEX_SIZE.to_f).floor
|
||||
srcX = col * TILESET_WIDTH + srcrect.x
|
||||
srcY = srcrect.y % MAX_TEX_SIZE
|
||||
|
||||
if !merge
|
||||
dest.blt(destX, destY, src, Rect.new(srcX, srcY, srcrect.width, srcrect.height))
|
||||
else
|
||||
#FIXME won't work on heights longer than two columns, but nobody should need
|
||||
# more than 32k pixels high at once anyway
|
||||
side = {:a => MAX_TEX_SIZE - srcY, :b => srcrect.height - (MAX_TEX_SIZE - srcY)}
|
||||
dest.blt(destX, destY, src, Rect.new(srcX, srcY, srcrect.width, side[:a]))
|
||||
dest.blt(destX, destY + side[:a], src, Rect.new(srcX + TILESET_WIDTH, 0, srcrect.width, side[:b]))
|
||||
end
|
||||
end
|
||||
|
||||
# May be applied using Module#prepend
|
||||
# it's probably better to integrate custom tilemap code manually
|
||||
# XXX: is it OK to dispose of the original bitmaps?
|
||||
module TilemapPatch
|
||||
def tileset=(value)
|
||||
if value.mega?
|
||||
super TileWrap::wrapTileset value
|
||||
value.dispose
|
||||
else
|
||||
super value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module SpritePatch
|
||||
def bitmap=(bmp)
|
||||
if bmp.mega?
|
||||
super TileWrap.wrapTileset bmp
|
||||
bmp.dispose
|
||||
else
|
||||
super bmp
|
||||
end
|
||||
end
|
||||
def src_rect=(rect)
|
||||
super TileWrap.wrapRect rect
|
||||
end
|
||||
end
|
||||
end
|
71
Kawariki-patches/libs/ruby18.rb
Normal file
71
Kawariki-patches/libs/ruby18.rb
Normal file
|
@ -0,0 +1,71 @@
|
|||
# Ruby 1.8 compat
|
||||
module Ruby18
|
||||
module ObjectPatch
|
||||
# Object#type used to be an alias to Object#class
|
||||
def type
|
||||
self.class
|
||||
end
|
||||
end
|
||||
|
||||
class IncludeStringArray < Array
|
||||
def include?(thing)
|
||||
if thing.is_a?(String) then
|
||||
super(thing.to_sym)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module KernelPatch
|
||||
# Used to return a string array
|
||||
def methods(*)
|
||||
IncludeStringArray.new super
|
||||
end
|
||||
|
||||
def singleton_methods(*)
|
||||
IncludeStringArray.new super
|
||||
end
|
||||
end
|
||||
|
||||
module ModulePatch
|
||||
# Used to return string array.
|
||||
# Fix instance_methods.include? use-case by patching it to work with strings
|
||||
# The array will still be of symbols however
|
||||
def instance_methods(*)
|
||||
IncludeStringArray.new super
|
||||
end
|
||||
|
||||
def public_instance_methods(*)
|
||||
IncludeStringArray.new super
|
||||
end
|
||||
|
||||
def private_instance_methods(*)
|
||||
IncludeStringArray.new super
|
||||
end
|
||||
end
|
||||
|
||||
module ArrayPatch
|
||||
def nitems
|
||||
count {|i| !i.nil?}
|
||||
end
|
||||
|
||||
def choice
|
||||
sample
|
||||
end
|
||||
end
|
||||
|
||||
module HashPatch
|
||||
def index(value)
|
||||
key value
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Apply Patches
|
||||
Object.prepend ObjectPatch
|
||||
Module.prepend ModulePatch
|
||||
Kernel.prepend KernelPatch
|
||||
Array.prepend ArrayPatch
|
||||
Hash.prepend HashPatch
|
||||
end
|
237
Kawariki-patches/patches.rb
Normal file
237
Kawariki-patches/patches.rb
Normal file
|
@ -0,0 +1,237 @@
|
|||
# Kawariki MKXP patch/port collection
|
||||
# See preload.rb for Patch implementation
|
||||
|
||||
module Preload
|
||||
Patches = [
|
||||
# Ports
|
||||
Patch.new("Zeus Fullscreen: Use mkxp builtin fullscreen instead (Alt+Enter)")
|
||||
.imported?(:Zeus_Fullscreen)
|
||||
.replace!("Zeus_Fullscreen++.rb"),
|
||||
Patch.new("Zeus_Map_Effects fix")
|
||||
.imported?(:Zeus_Map_Effects)
|
||||
.sub!(":zoom_blur_length, :motion_blur_rate", ":zoom_blur_length, :motion_blur_rate\ndef update_animation_Integer(str,str2,str3,str4,str5,str6) @wave_amp = 0.0; end"),
|
||||
Patch.new("Zeus_Lights_Shadows fix")
|
||||
.imported?(:Zeus_Lights_Shadows)
|
||||
.sub!(/^RPG_VERSION =.*/, "RPG_VERSION ="+ ENV["vcode"])
|
||||
.sub!(" def update_animation_value", "def update_animation_Integer(str,str2,str3,str4,str5) @wave_amp = 0.0; end\ndef update_animation_value"),
|
||||
Patch.new("cyanic-SteamUserStatsLite fix")
|
||||
.include?('Win32API.new(self.steam_dll_name')
|
||||
# .remove!,
|
||||
.replace!("achievements.rb"),
|
||||
# Patch.new("Advanced Text System fix")
|
||||
# .include?('Advanced Text System')
|
||||
# .include?('modern algebra (rmrk.net)')
|
||||
# # .remove!,
|
||||
# .replace!("Advanced-Text-System.rb"),
|
||||
Patch.new("NWConst::Warp plugin fix")
|
||||
.include?('module NWConst::Warp')
|
||||
.include?('@popup_confirm_window.select(0)')
|
||||
.sub!('@popup_confirm_window.select(0)', "items = @popup_confirm_window.instance_variable_get(:@list)\nif items.is_a?(Array) && !items.empty?\n@popup_confirm_window.select(0)\nend"),
|
||||
Patch.new("NWRegexpBaseItemfix plugin fix")
|
||||
.include?('module NWConst::Shop')
|
||||
# .replace!("NWRegexpBaseItemfix.rb"),
|
||||
.sub!('@select_actor_window.show.activate.select(0)', "if @select_actor_window.show.activate.is_a?(Array) && @select_actor_window.show.activate.empty?\n@select_actor_window.show.activate.select(0)\nend"),
|
||||
Patch.new("NWConst::Synthesize plugin fix")
|
||||
.include?('module NWConst::Synthesize')
|
||||
.include?('Container.item')
|
||||
# .replace!("NWRegexpBaseItemfix.rb"),
|
||||
.sub!('@popup_confirm_window.select(0)', "if @popup_confirm_window.is_a?(Array) && @popup_confirm_window.empty?\n@popup_confirm_window.select(0)\nend")
|
||||
.sub!('@before_actors_window.show.activate.select(0)', "if @before_actors_window.show.activate.is_a?(Array) && @before_actors_window.show.activate.empty?\n@before_actors_window.show.activate.select(0)\nend")
|
||||
.sub!('@after_actors_window.show.activate.select(0)', "if @after_actors_window.show.activate.is_a?(Array) && @after_actors_window.show.activate.empty?\n@after_actors_window.show.activate.select(0)\nend"),
|
||||
Patch.new("AudioUtilities plugin fix")
|
||||
.include?('waveOutOpen=Win32API.new("winmm.dll","waveOutOpen","plplll","l")')
|
||||
.include?('def pbPlaySoundData(samples,volume,async=false,sampleFreq=11025)')
|
||||
# .remove!,
|
||||
# .replace!("dummyAudioUtilities.rb")
|
||||
.sub!(/when (\d+):/, 'when \1'),
|
||||
Patch.new("dummyPSystem_Utilities plugin fix")
|
||||
.include?('pbNextComb')
|
||||
# .include?('def pbIsJsonString')
|
||||
# .remove!,
|
||||
.replace!("dummyPSystem_Utilities.rb"),
|
||||
# .sub!(/when (\d+):/, 'when \1'),
|
||||
Patch.new("XIV's Simple Reputation System (SRS) for RGSS3 fix") #XIV's Simple Reputation System (SRS) for RGSS3 Romance Level Version: 1.1
|
||||
.include?("Simple Reputation System (SRS)")
|
||||
.sub!("$scene1 = Scene_Menu.new(0)", "$scene1 = Scene_Menu.new"),
|
||||
Patch.new("Nergal's Item Finding patch fix") #Nergal's Item Finding
|
||||
.include?("SEARCH_TYPES = [ ITEMS_TO_FIND_PERSON, ITEMS_TO_FIND_SCHOOL,")
|
||||
.include?("$scene1 = Scene_Menu.new(0)")
|
||||
.sub!("$scene1 = Scene_Menu.new(0)", "$scene1 = Scene_Menu.new"),
|
||||
Patch.new("Nergal's XP Gain") #Nergal's XP Gain
|
||||
.include?("CustomGab.display_message(stat + XpLevel::MAX_LVL_MESSAGE)")
|
||||
.include?("$scene4 = Scene_Menu.new(0)")
|
||||
.sub!("$scene4 = Scene_Menu.new(0)", "$scene4 = Scene_Menu.new"),
|
||||
Patch.new("Audio_EX2 WF-RGSS patch") #【WF-RGSS】共通rev29 base
|
||||
.include?("module WFRGSS_AudioEX")
|
||||
# .sub!("return true if @audio__init", "return true"),
|
||||
# .include?("self.to_widechar(")
|
||||
.replace!("dummy_Audio_EX2.rb"),
|
||||
Patch.new("WF-RGSS base patch") #【WF-RGSS】共通rev29 base
|
||||
.include?("MultiByteToWideChar")
|
||||
.include?("to_widechar(")
|
||||
.replace!("testencode.rb"),
|
||||
Patch.new("window check content height fix (mgq paradox)") #Window_Base
|
||||
.if? {|script| script.name == "Window_Base"}
|
||||
# .replace!("basewt.rb"),
|
||||
.sub!("if contents_width > 0 && contents_height > 0", "if contents_height > 10000\nself.contents = Bitmap.new(1, 1)\nelsif contents_width > 0 && contents_height > 0")
|
||||
.sub!("result = text.to_s.clone","result = text.to_s.clone\nresult = result.dup if result.frozen?"),
|
||||
Patch.new("temp bitmap load crash fix monster girl paradox disable preview") #ベース/Module
|
||||
#maybe the memory buffer is filled up too much??
|
||||
# .if? {|script| script.name == "Window_Base"}
|
||||
.include?('thumnail_file = "Save/Save#{Regexp.last_match(1)}.png"')
|
||||
.sub!("@thumbnails[Regexp.last_match(1).to_i - 1] = Bitmap.new(thumnail_file)", "@thumbnails[Regexp.last_match(1).to_i - 1] = @dummy_thumbnail #Bitmap.new(thumnail_file)"),
|
||||
# .replace!("savebitmanwin32api.rb"),
|
||||
Patch.new("WF-RGSS Exit-EX patch test") #▼ メイン【WF-RGSS】Exit-EX 終了処理
|
||||
.include?("Win32API.new('System/WFExit','hookExit','v','l')")
|
||||
# .remove!,
|
||||
.replace!("wxexittest.rb"),
|
||||
Patch.new("HimeWorks' Event Trigger Labels: Fix any_key_pressed? implementation")
|
||||
.imported?(:TH_EventTriggerLabels)
|
||||
.replace!("TH_EventTriggerLabels.rb"),
|
||||
Patch.new("HimeWorks' Simple Audio Encryption: Re-Implement with direct path detection")
|
||||
.imported?(:TH_SimpleAudioEncryption)
|
||||
.replace!("TH_SimpleAudioEncryption.rb"),
|
||||
Patch.new("MOG_Anti_Lag: Fix visible type error")
|
||||
.imported?(:mog_anti_lag)
|
||||
.sub!("self.visible = @character.can_update", "self.visible = !!@character.can_update"),
|
||||
Patch.new("KGC_BitmapExtension ? XP/VX ? error")
|
||||
.imported?(:BitmapExtension)
|
||||
# .sub!("class Win32API", "module Win32API"),
|
||||
.remove!,
|
||||
Patch.new("Galv's Event Pop-Ups: Fix bitmap constructor call")
|
||||
.imported?("Galv_Map_Popups")
|
||||
.match?(/\.font\.shadow\s*=\s*\d+/)
|
||||
.sub!(/\.font\.shadow\s*=\s*\d+/, ".font.shadow = true"),
|
||||
Patch.new("Basic Mouse Plugin test disable for now")
|
||||
.imported?(nil)
|
||||
.if? {|script| script.name == "BasicMouse"}
|
||||
.include?("include IBasicMouse")
|
||||
.sub!("def VZ; return @curr.lZ / 120; end", "def VZ; return 0 if @curr.nil? || @curr.lZ.nil?; return @curr.lZ / 120.0 end"),
|
||||
Patch.new("Screenshot plugin")
|
||||
.imported?(nil)
|
||||
.include?('SAVE_NAME = "ScreenShot/%Y%m%d%H%M%S.png"')
|
||||
# .sub!("def VZ; return @curr.lZ / 120; end", "def VZ; return 0 if @curr.nil? || @curr.lZ.nil?; return @curr.lZ / 120.0 end"),
|
||||
# .replace!("BasicMouse.rb"),
|
||||
.remove!,
|
||||
Patch.new("Super simple mouse script: Use mkxp mouse API")
|
||||
.imported?(nil)
|
||||
.include?("SUPER SIMPLE MOUSE SCRIPT")
|
||||
.replace!("Mouse.rb"),
|
||||
Patch.new("RMXP CustomResolution plugin")
|
||||
.imported?(nil)
|
||||
.include?("def snapshot(filename = 'Data/snap', quality = 0)")
|
||||
.replace!("XP_CustomResolution.rb"),
|
||||
Patch.new("Glitchfinder's Key Input: Shim with MKXP builtins")
|
||||
.imported?(nil)
|
||||
.include?("unless method_defined?(:keyinputmodule_input_update)")
|
||||
.replace!("Glitchfinder_Keyboard_Stub.rb"),
|
||||
Patch.new("Auto Font Install: Already included in MKXP")
|
||||
.imported?(nil)
|
||||
.include?("# ** Auto Font Install")
|
||||
.remove!,
|
||||
Patch.new("Extended Music Script: MKXP already supports .mod. other formats aren't available.")
|
||||
.imported?(nil)
|
||||
.include?("# Extended Music Script Version 3.5")
|
||||
.then!{|script|
|
||||
return if script.context.flag? :incompatible_bgm_checked
|
||||
unsupp = "wma,psf,minipsf,psf2,minipsf2,gsf,minigsf,usf,miniusf,hps,dsp,spc,gym,cym".split(",")
|
||||
# TODO: Find unsupported files in Audio/BGM. Then show msgbox if no converted versions available
|
||||
# Official MKXP-Z also doesn't support mp3
|
||||
script.context.mark :incompatible_bgm_checked
|
||||
}
|
||||
.remove!,
|
||||
Patch.new("CRDJ Input script: Use MKXP-Z input extensions")
|
||||
.imported?(nil)
|
||||
.include?("# A module that handles input data from a gamepad or keyboard.\r\n# Managed by symbols rather than button numbers in RGSS3.")
|
||||
.replace!("CRDJ_Input.rb"),
|
||||
# Specific Inline Patches
|
||||
Patch.new("Shokushu de sennou patch")
|
||||
.imported?(nil)
|
||||
.include?("alias _cao_log_terminate_message terminate_message")
|
||||
#.replace!("oldregex1.rb"),
|
||||
.sub!("@text.gsub!(/[", "#"),
|
||||
Patch.new("Try to fix superclass mismatches from MP Scene_Base")
|
||||
.imported?(nil)
|
||||
.include?("======\nMoonpearl's Scene_Base\n-----")
|
||||
.flag!(:redefinitions_overwrite_class),
|
||||
# Generic Inline Patches
|
||||
Patch.new("Disable all font effects")
|
||||
.flag?(:no_font_effects) # KAWARIKI_MKXP_NO_FONT_EFFECTS
|
||||
.match?(/(\.f|F)ont\.(default_)?(italic|outline|shadow|bold)/)
|
||||
# Font is a built-in API, so it's already available in preload
|
||||
.then!{Font.default_italic = Font.default_outline = Font.default_shadow = Font.default_bold = false}
|
||||
.sub!(/Font\.default_(italic|outline|shadow|bold)\s*=/, "Font.default_\\1 = false &&")
|
||||
.sub!(/\.font\.(italic|outline|shadow|bold)\s*\=/, ".font.\\1 = false &&"),
|
||||
Patch.new("Improve Ruby 1.8 Compatibility")
|
||||
.if?{|script| script.context[:rgss_version] < 3} # Never on VX Ace, which shipped 1.9
|
||||
.match?("self.type", /\Wtype\.to_s\W/, /\Winstance_methods\.include\?\(['"%]/)
|
||||
.then!{require "ruby18.rb"},
|
||||
Patch.new("Game_Player fix")
|
||||
.imported?(nil)
|
||||
.if? {|script| script.name == "Game_Player"}
|
||||
.if? {|script| script.source.include? "else return true"}
|
||||
.sub!("else return true", "true"),
|
||||
Patch.new("KGC Bitmap Extension fix")
|
||||
.imported?(nil)
|
||||
.if? {|script| script.source.include? "@@reel_stop = RPG::SE.new(CAO::PSLOT::SOUND_REEL_STOP"}
|
||||
.sub!("@@reel_stop =", "@reel_stop ="),
|
||||
Patch.new("Response improvement remove")
|
||||
.imported?(nil)
|
||||
.match?(/#.*_wdtk_resinp_update/)
|
||||
.remove!,
|
||||
Patch.new("Response improvement patch")
|
||||
.imported?(nil)
|
||||
# .if? {|script| script.name == "Response improvement script"}
|
||||
#.include?('@@press_count.each do')
|
||||
.if? {|script| script.source.include? "_wdtk_resinp_update" }
|
||||
.sub!('@@press_count', "@press_count")
|
||||
.sub!(/\b_wdtk_resinp_update\b(?!\s*update)/, "_wdtk_resinp_update;\n@press_count ||= {}"),
|
||||
# .sub!(/^(?!#.*)\b_wdtk_resinp_update\b(?!\s*update)/, "_wdtk_resinp_update;\n@press_count ||= {}"),
|
||||
# .sub!(/^(?!#.*)\b_wdtk_resinp_update\b(?!\s*update)/) { "_wdtk_resinp_update;\n@press_count ||= {}" },
|
||||
Patch.new("Item Script")
|
||||
.imported?(nil)
|
||||
# .if? {|script| script.name == "Response improvement script"}
|
||||
#.include?('@@press_count.each do')
|
||||
.include?("CATEGORIZE ITEM SCENE v1.0 ")
|
||||
# .if? {|script| script.source.include? "_wdtk_resinp_update"}
|
||||
.sub!("CATEGORY_IDENTIFIER.index(ITEM_DEFAULT_CATEGORY)", "CATEGORY_IDENTIFIER.keys.index(ITEM_DEFAULT_CATEGORY)")
|
||||
.sub!("CATEGORY_IDENTIFIER.index(:", "CATEGORY_IDENTIFIER.key(:"),
|
||||
Patch.new("Vitaminpl fix")
|
||||
.imported?(nil)
|
||||
.if? {|script| script.name == "Police"}
|
||||
.if? {|script| script.source.include? "Lucida Sans Unicode"}
|
||||
.if? {|script| script.source = "Font.default_size = 16"},
|
||||
Patch.new("Vitaminpl 2 fix")
|
||||
.imported?(nil)
|
||||
.include?("module Wora_NSS")
|
||||
.sub!("SCREENSHOT_IMAGE = true", "SCREENSHOT_IMAGE = false")
|
||||
.sub!("PREMADE_IMAGE = true", "PREMADE_IMAGE = false"),
|
||||
Patch.new("Dark Hero Party")
|
||||
.imported?(nil)
|
||||
.include?('text.push(self.to_s.scan(/#<(\S+):/)[0][0].to_s)')
|
||||
.remove!,
|
||||
# Patch.new("tktk_bitmap dll test debug")
|
||||
# .imported?(nil)
|
||||
# .include?("DLL_NAME = 'tktk_bitmap'")
|
||||
# # .remove!,
|
||||
# .replace!("bitmap_tktk.rb"),
|
||||
Patch.new("HN_Light tktk dll disable ")
|
||||
.imported?(nil)
|
||||
.include?("HN_Light version")
|
||||
.include?("tktkgame")
|
||||
.sub!("@dark_sprite.update", "@dark_sprite.dispose"),
|
||||
# .replace!("lamp.rb"),
|
||||
Patch.new("message_npi fix")
|
||||
.imported?(nil)
|
||||
.include?("module MessageTextDataBase")
|
||||
.include?("BlueRedZone")
|
||||
# #.sub!("@dark_sprite.update", "@dark_sprite.dispose"),
|
||||
.replace!("message_npi.rb"),
|
||||
Patch.new("Flirt quest")
|
||||
.imported?(nil)
|
||||
.include?('class Spriteset_BattleUnit')
|
||||
.include?('Spriteset_Kiseki')
|
||||
.sub!(/\bsuper\b(?!\s*\()/, 'super()'),
|
||||
|
||||
]
|
||||
end
|
178
Kawariki-patches/patchesm.rb
Normal file
178
Kawariki-patches/patchesm.rb
Normal file
|
@ -0,0 +1,178 @@
|
|||
# Kawariki MKXP patch/port collection
|
||||
# See preload.rb for Patch implementation
|
||||
|
||||
module Preload
|
||||
Patches = [
|
||||
# Ports
|
||||
Patch.new("Zeus Fullscreen: Use mkxp builtin fullscreen instead (Alt+Enter)")
|
||||
.imported?(:Zeus_Fullscreen)
|
||||
.replace!("Zeus_Fullscreen++.rb"),
|
||||
Patch.new("Zeus_Map_Effects fix")
|
||||
.imported?(:Zeus_Map_Effects)
|
||||
.sub!(":zoom_blur_length, :motion_blur_rate", ":zoom_blur_length, :motion_blur_rate\ndef update_animation_Integer(str,str2,str3,str4,str5,str6) @wave_amp = 0.0; end"),
|
||||
Patch.new("cyanic-SteamUserStatsLite fix")
|
||||
.include?('Win32API.new(self.steam_dll_name')
|
||||
# .remove!,
|
||||
.replace!("achievements.rb"),
|
||||
Patch.new("XIV's Simple Reputation System (SRS) for RGSS3 fix") #XIV's Simple Reputation System (SRS) for RGSS3 Romance Level Version: 1.1
|
||||
.include?("Simple Reputation System (SRS)")
|
||||
.sub!("$scene1 = Scene_Menu.new(0)", "$scene1 = Scene_Menu.new"),
|
||||
Patch.new("Nergal's Item Finding patch fix") #Nergal's Item Finding
|
||||
.include?("SEARCH_TYPES = [ ITEMS_TO_FIND_PERSON, ITEMS_TO_FIND_SCHOOL,")
|
||||
.include?("$scene1 = Scene_Menu.new(0)")
|
||||
.sub!("$scene1 = Scene_Menu.new(0)", "$scene1 = Scene_Menu.new"),
|
||||
Patch.new("Nergal's XP Gain") #Nergal's XP Gain
|
||||
.include?("CustomGab.display_message(stat + XpLevel::MAX_LVL_MESSAGE)")
|
||||
.include?("$scene4 = Scene_Menu.new(0)")
|
||||
.sub!("$scene4 = Scene_Menu.new(0)", "$scene4 = Scene_Menu.new"),
|
||||
Patch.new("WF-RGSS base patch") #【WF-RGSS】共通rev29 base
|
||||
.include?("'MultiByteToWideChar', %w(i l p i p i)")
|
||||
# .remove!,
|
||||
.replace!("testencode.rb"), #Window_Base
|
||||
Patch.new("window check content height fix (mgq paradox)")
|
||||
.if? {|script| script.name == "Window_Base"}
|
||||
# .replace!("basewt.rb"),
|
||||
.sub!("if contents_width > 0 && contents_height > 0", " if contents_height > 10000\nself.contents = Bitmap.new(1, 1)\nelsif contents_width > 0 && contents_height > 0"),
|
||||
Patch.new("temp bitmap load crash fix monster girl paradox disable preview") #ベース/Module
|
||||
#maybe the memory buffer is filled up too much??
|
||||
# .if? {|script| script.name == "Window_Base"}
|
||||
.include?('thumnail_file = "Save/Save#{Regexp.last_match(1)}.png"')
|
||||
.sub!("@thumbnails[Regexp.last_match(1).to_i - 1] = Bitmap.new(thumnail_file)", "@thumbnails[Regexp.last_match(1).to_i - 1] = @dummy_thumbnail #Bitmap.new(thumnail_file)"),
|
||||
# .replace!("savebitmanwin32api.rb"),
|
||||
Patch.new("WF-RGSS Exit-EX patch test") #▼ メイン【WF-RGSS】Exit-EX 終了処理
|
||||
.include?("Win32API.new('System/WFExit','hookExit','v','l')")
|
||||
# .remove!,
|
||||
.replace!("wxexittest.rb"),
|
||||
Patch.new("HimeWorks' Event Trigger Labels: Fix any_key_pressed? implementation")
|
||||
.imported?(:TH_EventTriggerLabels)
|
||||
.replace!("TH_EventTriggerLabels.rb"),
|
||||
Patch.new("HimeWorks' Simple Audio Encryption: Re-Implement with direct path detection")
|
||||
.imported?(:TH_SimpleAudioEncryption)
|
||||
.replace!("TH_SimpleAudioEncryption.rb"),
|
||||
Patch.new("MOG_Anti_Lag: Fix visible type error")
|
||||
.imported?(:mog_anti_lag)
|
||||
.sub!("self.visible = @character.can_update", "self.visible = !!@character.can_update"),
|
||||
Patch.new("KGC_BitmapExtension ? XP/VX ? error")
|
||||
.imported?(:BitmapExtension)
|
||||
# .sub!("class Win32API", "module Win32API"),
|
||||
.remove!,
|
||||
Patch.new("Galv's Event Pop-Ups: Fix bitmap constructor call")
|
||||
.imported?("Galv_Map_Popups")
|
||||
.match?(/\.font\.shadow\s*=\s*\d+/)
|
||||
.sub!(/\.font\.shadow\s*=\s*\d+/, ".font.shadow = true"),
|
||||
Patch.new("Basic Mouse Plugin test disable for now")
|
||||
.imported?(nil)
|
||||
.if? {|script| script.name == "BasicMouse"}
|
||||
.include?("include IBasicMouse")
|
||||
.sub!("def VZ; return @curr.lZ / 120; end", "def VZ; return 0 if @curr.nil? || @curr.lZ.nil?; return @curr.lZ / 120.0 end"),
|
||||
Patch.new("Screenshot plugin")
|
||||
.imported?(nil)
|
||||
.include?('SAVE_NAME = "ScreenShot/%Y%m%d%H%M%S.png"')
|
||||
# .sub!("def VZ; return @curr.lZ / 120; end", "def VZ; return 0 if @curr.nil? || @curr.lZ.nil?; return @curr.lZ / 120.0 end"),
|
||||
# .replace!("BasicMouse.rb"),
|
||||
.remove!,
|
||||
Patch.new("Super simple mouse script: Use mkxp mouse API")
|
||||
.imported?(nil)
|
||||
.include?("SUPER SIMPLE MOUSE SCRIPT")
|
||||
.replace!("Mouse.rb"),
|
||||
Patch.new("RMXP CustomResolution plugin")
|
||||
.imported?(nil)
|
||||
.include?("def snapshot(filename = 'Data/snap', quality = 0)")
|
||||
.replace!("XP_CustomResolution.rb"),
|
||||
Patch.new("Glitchfinder's Key Input: Shim with MKXP builtins")
|
||||
.imported?(nil)
|
||||
.include?("unless method_defined?(:keyinputmodule_input_update)")
|
||||
.replace!("Glitchfinder_Keyboard_Stub.rb"),
|
||||
Patch.new("Auto Font Install: Already included in MKXP")
|
||||
.imported?(nil)
|
||||
.include?("# ** Auto Font Install")
|
||||
.remove!,
|
||||
Patch.new("Extended Music Script: MKXP already supports .mod. other formats aren't available.")
|
||||
.imported?(nil)
|
||||
.include?("# Extended Music Script Version 3.5")
|
||||
.then!{|script|
|
||||
return if script.context.flag? :incompatible_bgm_checked
|
||||
unsupp = "wma,psf,minipsf,psf2,minipsf2,gsf,minigsf,usf,miniusf,hps,dsp,spc,gym,cym".split(",")
|
||||
# TODO: Find unsupported files in Audio/BGM. Then show msgbox if no converted versions available
|
||||
# Official MKXP-Z also doesn't support mp3
|
||||
script.context.mark :incompatible_bgm_checked
|
||||
}
|
||||
.remove!,
|
||||
Patch.new("CRDJ Input script: Use MKXP-Z input extensions")
|
||||
.imported?(nil)
|
||||
.include?("# A module that handles input data from a gamepad or keyboard.\r\n# Managed by symbols rather than button numbers in RGSS3.")
|
||||
.replace!("CRDJ_Input.rb"),
|
||||
# Specific Inline Patches
|
||||
Patch.new("Shokushu de sennou patch")
|
||||
.imported?(nil)
|
||||
.include?("alias _cao_log_terminate_message terminate_message")
|
||||
#.replace!("oldregex1.rb"),
|
||||
.sub!("@text.gsub!(/[", "#"),
|
||||
Patch.new("Try to fix superclass mismatches from MP Scene_Base")
|
||||
.imported?(nil)
|
||||
.include?("======\nMoonpearl's Scene_Base\n-----")
|
||||
.flag!(:redefinitions_overwrite_class),
|
||||
# Generic Inline Patches
|
||||
Patch.new("Disable all font effects")
|
||||
.flag?(:no_font_effects) # KAWARIKI_MKXP_NO_FONT_EFFECTS
|
||||
.match?(/(\.f|F)ont\.(default_)?(italic|outline|shadow|bold)/)
|
||||
# Font is a built-in API, so it's already available in preload
|
||||
.then!{Font.default_italic = Font.default_outline = Font.default_shadow = Font.default_bold = false}
|
||||
.sub!(/Font\.default_(italic|outline|shadow|bold)\s*=/, "Font.default_\\1 = false &&")
|
||||
.sub!(/\.font\.(italic|outline|shadow|bold)\s*\=/, ".font.\\1 = false &&"),
|
||||
Patch.new("Improve Ruby 1.8 Compatibility")
|
||||
.if?{|script| script.context[:rgss_version] < 3} # Never on VX Ace, which shipped 1.9
|
||||
.match?("self.type", /\Wtype\.to_s\W/, /\Winstance_methods\.include\?\(['"%]/)
|
||||
.then!{require "ruby18.rb"},
|
||||
Patch.new("Game_Player fix")
|
||||
.imported?(nil)
|
||||
.if? {|script| script.name == "Game_Player"}
|
||||
.if? {|script| script.source.include? "else return true"}
|
||||
.sub!("else return true", "true"),
|
||||
Patch.new("KGC Bitmap Extension fix")
|
||||
.imported?(nil)
|
||||
.if? {|script| script.source.include? "@@reel_stop = RPG::SE.new(CAO::PSLOT::SOUND_REEL_STOP"}
|
||||
.sub!("@@reel_stop =", "@reel_stop ="),
|
||||
Patch.new("Response improvement remove")
|
||||
.imported?(nil)
|
||||
.match?(/#.*_wdtk_resinp_update/)
|
||||
.remove!,
|
||||
Patch.new("Response improvement patch")
|
||||
.imported?(nil)
|
||||
# .if? {|script| script.name == "Response improvement script"}
|
||||
#.include?('@@press_count.each do')
|
||||
.if? {|script| script.source.include? "_wdtk_resinp_update" }
|
||||
.sub!('@@press_count', "@press_count")
|
||||
.sub!(/\b_wdtk_resinp_update\b(?!\s*update)/, "_wdtk_resinp_update;\n@press_count ||= {}"),
|
||||
# .sub!(/^(?!#.*)\b_wdtk_resinp_update\b(?!\s*update)/, "_wdtk_resinp_update;\n@press_count ||= {}"),
|
||||
# .sub!(/^(?!#.*)\b_wdtk_resinp_update\b(?!\s*update)/) { "_wdtk_resinp_update;\n@press_count ||= {}" },
|
||||
Patch.new("Item Script")
|
||||
.imported?(nil)
|
||||
# .if? {|script| script.name == "Response improvement script"}
|
||||
#.include?('@@press_count.each do')
|
||||
.include?("CATEGORIZE ITEM SCENE v1.0 ")
|
||||
# .if? {|script| script.source.include? "_wdtk_resinp_update"}
|
||||
.sub!("CATEGORY_IDENTIFIER.index(ITEM_DEFAULT_CATEGORY)", "CATEGORY_IDENTIFIER.keys.index(ITEM_DEFAULT_CATEGORY)")
|
||||
.sub!("CATEGORY_IDENTIFIER.index(:", "CATEGORY_IDENTIFIER.key(:"),
|
||||
Patch.new("Vitaminpl fix")
|
||||
.imported?(nil)
|
||||
.if? {|script| script.name == "Police"}
|
||||
.if? {|script| script.source.include? "Lucida Sans Unicode"}
|
||||
.if? {|script| script.source = "Font.default_size = 16"},
|
||||
Patch.new("Vitaminpl 2 fix")
|
||||
.imported?(nil)
|
||||
.include?("module Wora_NSS")
|
||||
.sub!("SCREENSHOT_IMAGE = true", "SCREENSHOT_IMAGE = false")
|
||||
.sub!("PREMADE_IMAGE = true", "PREMADE_IMAGE = false"),
|
||||
Patch.new("Dark Hero Party")
|
||||
.imported?(nil)
|
||||
.include?('text.push(self.to_s.scan(/#<(\S+):/)[0][0].to_s)')
|
||||
.remove!,
|
||||
Patch.new("Flirt quest")
|
||||
.imported?(nil)
|
||||
.include?('class Spriteset_BattleUnit')
|
||||
.include?('Spriteset_Kiseki')
|
||||
.sub!(/\bsuper\b(?!\s*\()/, 'super()'),
|
||||
|
||||
]
|
||||
end
|
3708
Kawariki-patches/ports/Advanced-Text-System-.rb
Normal file
3708
Kawariki-patches/ports/Advanced-Text-System-.rb
Normal file
File diff suppressed because it is too large
Load diff
604
Kawariki-patches/ports/Advanced-Text-System.rb
Normal file
604
Kawariki-patches/ports/Advanced-Text-System.rb
Normal file
|
@ -0,0 +1,604 @@
|
|||
#==============================================================================
|
||||
# ATS: Special Message Codes [VXA]
|
||||
# Version: 1.0.6
|
||||
# Author: modern algebra (rmrk.net)
|
||||
# Date: 18 October 2012
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Description:
|
||||
#
|
||||
# This script allows you to use a number of additional special codes in the
|
||||
# message system, which will function similar to the default codes like
|
||||
# \v[n], \c[n], etc. Please see the list of special message codes starting at
|
||||
# line 54 for a full idea of what is added. Basically, it gives you greater
|
||||
# control over the delivery of a message, allows you to make use of font
|
||||
# effects like bolding and italicizing, and allows you to retrieve and
|
||||
# display useful data like the names of weapons and armors.
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# ATS Series:
|
||||
#
|
||||
# This script is part of the Advanced Text System series of scripts. These
|
||||
# scripts are based off the Advanced Text System for RMVX, but since RMVX Ace
|
||||
# has a much more sensibly designed message system, it is no longer necessary
|
||||
# that it be one large script. For that reason, and responding to feedback on
|
||||
# the ATS, I have split the ATS into multiple different scripts so that you
|
||||
# only need to pick up the components for the features that you want. It is
|
||||
# therefore easier to customize and configure.
|
||||
#
|
||||
# To find more scripts in the ATS Series, please visit:
|
||||
# http://rmrk.net/index.php/topic,44525.0.html
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Instructions:
|
||||
#
|
||||
# This script is not difficult to use or configure. There are only ten
|
||||
# configuration options for this script. These are:
|
||||
#
|
||||
# :message_speed :font_italic
|
||||
# :show_fast_speed :font_outline
|
||||
# :font_name :font_shadow
|
||||
# :font_size :font_underline
|
||||
# :font_bold :font_highlight
|
||||
#
|
||||
# :message_speed allows you to set the default number of frames to wait
|
||||
# between drawing each letter in the message window. :show_fast_speed allows
|
||||
# you to control the amount it speeds up when the player presses enter. You
|
||||
# can gain instructions on setting the default value for both at line 180.
|
||||
#
|
||||
# All of the :font_ settings simply let you set the initial values for the
|
||||
# font when used.
|
||||
#
|
||||
# As with other ATS scripts, you can change the value of these options in
|
||||
# game with the following codes in a script call:
|
||||
#
|
||||
# ats_next(:message_option, x)
|
||||
# ats_all(:message_option, x)
|
||||
#
|
||||
# Where :message_option is the symbol you want (:message_speed or
|
||||
# :show_fast_speed) and x is the value you want to change it to. ats_next
|
||||
# will only change it for the very next message, while ats_all will change it
|
||||
# for every message to follow.
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# List of Special Message Codes:
|
||||
#
|
||||
# The default message codes are retained, and this script adds a number of
|
||||
# other desirable features. The following is a complete list of the message
|
||||
# codes at your disposal. Simply insert them into a Display Message command,
|
||||
# Choice Branches, or any other message related system.
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Font Effects:
|
||||
#
|
||||
# \fn[fontname] - Change the font to fontname. If you put multiple fontnames
|
||||
# separated by commas, then it will take the first one the user has installed
|
||||
# \fs[n] - Change the font size to n.
|
||||
# \{ - Increase the font size by 8.
|
||||
# \} - Decrease the font size by 8.
|
||||
# \c[n] - Set the colour of the text being drawn to the nth colour of the
|
||||
# Windowskin palette. 0 is the normal color and 16 is the system color.
|
||||
# \hc[RRGGBB] or \c[#RRGGBB] - Set the colour of the text being drawn to any
|
||||
# colour, using hexadecimal values. You can set each colour (red, green,
|
||||
# blue) to anything from 0-255 (00-FF). You must use hexadecimal values. If
|
||||
# so desired, you can add an additional hex value from 00-FF to change the
|
||||
# alpha.
|
||||
# \b - Turn bold on. Text drawn after this code will be bolded.
|
||||
# /b - Turn bold off.
|
||||
# \i - Turn italic on. Text drawn after this code will be italicized.
|
||||
# /i - Turn italic off.
|
||||
# \o - Turn outline on.
|
||||
# /o - Turn outline off.
|
||||
# \s - Turn shadow on. Text drawn after this code will have a shadow.
|
||||
# /s - Turn shadow off.
|
||||
# \u - Turn underline on. Text drawn after this code will be underlined.
|
||||
# /u - Turn underline off.
|
||||
# \hl[n] - Turn highlight on. Text drawn after this code will be highlighted
|
||||
# with colour n + 1 from the windowskin palette
|
||||
# /hl OR \hl[0] - Turn highlight off.
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Message Control:
|
||||
#
|
||||
# \s[n] - Sets the message speed to wait n frames between drawing every letter.
|
||||
# 0 is instant.
|
||||
# \s[+n] - Sets the message speed to wait an additional n frames between drawing
|
||||
# every letter.
|
||||
# \s[-n] - Sets the message speed to wait n less frames between drawing every
|
||||
# letter.
|
||||
# \. - Wait 15 frames before drawing the next character
|
||||
# \| - Wait 60 frames before drawing the next character
|
||||
# \w[n] - Wait n frames before drawing the next character
|
||||
# \! - Pause text and wait for player to press Enter
|
||||
# \^ - Skip Pause; allows you to close a message window without requiring player
|
||||
# input.
|
||||
# \> - Show line fast.
|
||||
# \< - Stop showing line fast.
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Replacement Codes:
|
||||
#
|
||||
# \p[n] - Draw the name of the actor in the xth position in the party. 1 is
|
||||
# the party leader, 2 is the second member, etc.
|
||||
# \n[n] - Draw the name of the actor with ID n
|
||||
# \nn[n] - Draw the nickname of the actor with ID n.
|
||||
# \pid[n] - Draw the ID of the actor in the nth position in the party.
|
||||
# \ac[n] - Draw the class name of the actor with ID n.
|
||||
# \al[n] - Draw the level of the actor with ID n.
|
||||
# \ni[n] - Draw the name of the item with ID n.
|
||||
# \nw[n] - Draw the name of the weapon with ID n.
|
||||
# \na[n] - Draw the name of the armor with ID n.
|
||||
# \ns[n] - Draw the name of the skill with ID n.
|
||||
# \nt[n] - Draw the name of the state with ID n.
|
||||
# \nc[n] - Draw the name of the class with ID n.
|
||||
# \ne[n] - Draw the name of the event with ID n on the current map.
|
||||
# \nm[n] - Draw the name of the enemy with ID n.
|
||||
# \nv[n] - Draw the name of the variable with ID n.
|
||||
# \nsw[n] - Draw the name of the switch with ID n.
|
||||
# \nl[n] - Draw the name of the element with ID n.
|
||||
# \nwt[n] - Draw the name of the weapon type with ID n.
|
||||
# \nat[n] - Draw the name of the armor type with ID n.
|
||||
# \nst[n] - Draw the name of the skill type with ID n.
|
||||
# \np[n] - Draw the name of the actor in the nth position in the party.
|
||||
# \map - Draw the name of the map the player is currently on.
|
||||
# \map[n] - Draw the name of the map with ID n.
|
||||
# \pg - Draws the amount of money the party has.
|
||||
# \g - Draws the unit of currency.
|
||||
# \vocab[method] - Will draw whatever Vocab.method returns, if it is a valid
|
||||
# method call. Suitable values for method are: level, level_a, hp, hp_a,
|
||||
# mp, mp_a, tp, tp_a, fight, escape, attack, guard, item, skill, equip,
|
||||
# status, formation, save, game_end, weapon, armor, key_item, equip2,
|
||||
# optimize, clear, new_game, continue, shutdown, to_title, cancel,
|
||||
# currency_unit
|
||||
# \vocab[param, n] - Will draw the label for parameter with ID n. 0 => Max HP;
|
||||
# 1 => Max MP; 2 => Attack; 3 => Defence; 4 => Magic; 5 => Magic Defence;
|
||||
# 6 => Agility; 7 => Luck
|
||||
# \vocab[etype, n] - Will draw the label for equipment type with ID n.
|
||||
# 0 => Weapon; 1 => Shield; 2 => Head; 3 => Body; 4 => Accessory
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Other Effects:
|
||||
#
|
||||
# \$ - Opens a window which shows the party's gold.
|
||||
# \n - line break
|
||||
# \i[n] - Draw icon with index n.
|
||||
# \ii[n] - Draw icon of the item with ID n.
|
||||
# \iw[n] - Draw icon of the weapon with ID n.
|
||||
# \ia[n] - Draw icon of the armor with ID n.
|
||||
# \is[n] - Draw icon of the skill with ID n.
|
||||
# \it[n] - Draw icon of the state with ID n.
|
||||
# \x[n] - Draw next character at pixel n of the window contents.
|
||||
# \s{n,text} - Will only draw text if the switch with ID n is ON.
|
||||
# \s!{n,text} - Will only draw text if the switch with ID n is OFF.
|
||||
# \#{code} - This will evaluate code. So, if you know scipting, you can place
|
||||
# any code there and it will draw whatever is returned by it. For instance:
|
||||
# \#{$game_system.save_count} would draw the number of times the player has
|
||||
# saved the current game.
|
||||
#==============================================================================
|
||||
|
||||
$imported = {} unless $imported
|
||||
$imported[:ATS_SpecialMessageCodes] = true
|
||||
|
||||
#==============================================================================
|
||||
# ** Game_ATS
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Summary of Changes:
|
||||
# new public instance variables - message_speed; special_message_codes
|
||||
#==============================================================================
|
||||
|
||||
class Game_ATS
|
||||
CONFIG = {} unless $imported[:AdvancedTextSystem]
|
||||
CONFIG[:special_message_codes] = {
|
||||
special_message_codes: true,
|
||||
#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
# EDITABLE REGION
|
||||
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
# :message_speed => x,
|
||||
# Changing the value of x determines the default number of frames to
|
||||
# wait between drawing letters in a message window. 0 is instant.
|
||||
:message_speed => 1,
|
||||
# :show_fast_speed => x
|
||||
# Changing the value of x determines the number of frames to wait
|
||||
# between drawing letters when the player is holding enter. 0 is
|
||||
# instant
|
||||
:show_fast_speed => 0,
|
||||
# Font Settings - Set the default settings for the font you are using here.
|
||||
:font_name => Font.default_name, # String or Array of Strings
|
||||
:font_size => Font.default_size, # Integer
|
||||
:font_bold => Font.default_bold, # true or false
|
||||
:font_italic => Font.default_italic, # true or false
|
||||
:font_outline => Font.default_outline, # true or false
|
||||
:font_shadow => Font.default_shadow, # true or false
|
||||
:font_underline => false, # true or false
|
||||
:font_highlight => -1, # Integer for colour of highlight
|
||||
#||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
# END EDITABLE REGION
|
||||
#////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Public Instance Variables
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
CONFIG[:special_message_codes].keys.each { |key| attr_accessor key }
|
||||
end
|
||||
|
||||
#==============================================================================
|
||||
# Initialize Common ATS Data if no other ATS script interpreted first
|
||||
#==============================================================================
|
||||
|
||||
if !$imported[:AdvancedTextSystem]
|
||||
#============================================================================
|
||||
# *** DataManager
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Summary of Changes:
|
||||
# aliased method - create_game_objects; make_save_contents;
|
||||
# extract_save_contents
|
||||
#============================================================================
|
||||
module DataManager
|
||||
class << self
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Create Game Objects
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias modb_ats_crtgmobj_6yh7 create_game_objects
|
||||
def create_game_objects(*args, &block)
|
||||
modb_ats_crtgmobj_6yh7(*args, &block)
|
||||
$game_ats = Game_ATS.new
|
||||
$game_ats.init_new_installs
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Make Save Contents
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias mlba_ats_mksave_5tg9 make_save_contents
|
||||
def make_save_contents(*args, &block)
|
||||
contents = mlba_ats_mksave_5tg9(*args, &block)
|
||||
contents[:ats] = $game_ats
|
||||
contents
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Extract Save Contents
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias ma_ats_extrcsvcon_8uj2 extract_save_contents
|
||||
def extract_save_contents(contents, *args, &block)
|
||||
ma_ats_extrcsvcon_8uj2(contents, *args, &block)
|
||||
$game_ats = contents[:ats] ? contents[:ats] : Game_ATS.new
|
||||
$game_ats.init_new_installs
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#============================================================================
|
||||
# ** Game_ATS
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# This class holds the default data for all scripts in the ATS series
|
||||
#============================================================================
|
||||
|
||||
class Game_ATS
|
||||
def initialize; reset; end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Reset any or all installed ATS scripts
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
def reset(script_name = nil)
|
||||
if script_name.is_a? (Symbol) # If script to reset specified
|
||||
CONFIG[script_name].each_pair { |key, value|
|
||||
self.send("#{key}=".to_sym, value)
|
||||
$game_message.send("#{key}=".to_sym, value)
|
||||
}
|
||||
else # Reset all ATS scripts
|
||||
CONFIG.keys.each { |script| reset(script) }
|
||||
end
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Initialize any newly installed ATS scripts
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
def init_new_installs
|
||||
CONFIG.keys.each { |script| reset(script) unless self.send(script) }
|
||||
end
|
||||
end
|
||||
|
||||
#============================================================================
|
||||
# ** Game_Message
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Summary of Changes:
|
||||
# aliased method - clear
|
||||
#============================================================================
|
||||
|
||||
class Game_Message
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Clear
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias mlb_ats_clrats_5tv1 clear
|
||||
def clear(*args, &block)
|
||||
mlb_ats_clrats_5tv1(*args, &block) # Run Original Method
|
||||
return if !$game_ats
|
||||
Game_ATS::CONFIG.values.each { |installed|
|
||||
installed.keys.each { |key| self.send("#{key}=".to_sym, $game_ats.send(key)) }
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
#============================================================================
|
||||
# ** Game_Interpreter
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Summary of Changes:
|
||||
# new methods - ats_all; ats_next
|
||||
#============================================================================
|
||||
|
||||
class Game_Interpreter
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * ATS All
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
def ats_all(sym, *args, &block)
|
||||
$game_ats.send("#{sym}=".to_sym, *args, &block)
|
||||
ats_next(sym, *args, &block)
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * ATS Next
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
def ats_next(sym, *args, &block)
|
||||
$game_message.send("#{sym}=".to_sym, *args, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
$imported[:AdvancedTextSystem] = true
|
||||
|
||||
class Game_Message
|
||||
Game_ATS::CONFIG[:special_message_codes].keys.each { |key| attr_accessor key }
|
||||
end
|
||||
|
||||
#==============================================================================
|
||||
# ** Game_Event
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Summary of Changes:
|
||||
# new method - name
|
||||
#==============================================================================
|
||||
|
||||
class Game_Event
|
||||
def name
|
||||
return @event ? @event.name : ""
|
||||
end
|
||||
end
|
||||
|
||||
#==============================================================================
|
||||
# ** Window_Base
|
||||
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Summary of Changes:
|
||||
# aliased methods - initialize; convert_escape_characters; calc_line_height;
|
||||
# process_escape_character; process_normal_character
|
||||
#==============================================================================
|
||||
|
||||
class Window_Base
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Object Initialization
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias mlgb_atssmc_init_3do9 initialize
|
||||
def initialize(*args, &block)
|
||||
mlgb_atssmc_init_3do9(*args, &block) # Run Original Method
|
||||
@underline = false
|
||||
@highlight = -1
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Convert Escape Characters
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias ma_atssmc_convesc_4rc1 convert_escape_characters
|
||||
def convert_escape_characters(text, *args, &block)
|
||||
result = ma_atssmc_convesc_4rc1(text, *args, &block) # Run Original Method
|
||||
# Party
|
||||
result.gsub!(/\ePID\[(\d+)\]/i) { $1.to_i >= 1 ? $game_party.members[$1.to_i - 1].id.to_s : "1" }
|
||||
result.gsub!(/\ePG/i) { $game_party.gold }
|
||||
# Message Speed
|
||||
result.gsub!(/\eS\[([\+-]?\d+)\]/i) { "\eMS\[#{$1}\]" }
|
||||
result.gsub!(/\e%/) { "\eDS%"}
|
||||
# Hex Colour
|
||||
result.gsub!(/\eC\[#/i) { "\eHC[" }
|
||||
# Icons
|
||||
result.gsub!(/\eII\[(\d+)\]/i) { "\eI\[#{$data_items[$1.to_i].icon_index}\]" rescue "" }
|
||||
result.gsub!(/\eIW\[(\d+)\]/i) { "\eI\[#{$data_weapons[$1.to_i].icon_index}\]" rescue "" }
|
||||
result.gsub!(/\eIA\[(\d+)\]/i) { "\eI\[#{$data_armors[$1.to_i].icon_index}\]" rescue "" }
|
||||
result.gsub!(/\eIS\[(\d+)\]/i) { "\eI\[#{$data_skills[$1.to_i].icon_index}\]" rescue "" }
|
||||
result.gsub!(/\eIT\[(\d+)\]/i) { "\eI\[#{$data_states[$1.to_i].icon_index}\]" rescue "" }
|
||||
# Actor Stats
|
||||
result.gsub!(/\eAC\[(\d+)\]/i) { $data_classes[$game_actors[$1.to_i].class_id].name }
|
||||
result.gsub!(/\eAL\[(\d+)\]/i) { $game_actors[$1.to_i].level.to_s }
|
||||
# Names
|
||||
result.gsub!(/\eMAP\[(\d+)\]/i) { load_data(sprintf("Data/Map%03d.rvdata2", $1.to_i)).display_name rescue "" }
|
||||
result.gsub!(/\eMAP/i) { $game_map.display_name rescue "" }
|
||||
result.gsub!(/\eNP\[(\d+)\]/i) { $game_party.members[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNE\[(\d+)\]/i) { $game_map.events[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNN\[(\d+)\]/i) { $game_actors[$1.to_i].nickname rescue "" }
|
||||
result.gsub!(/\eNI\[(\d+)\]/i) { $data_items[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNW\[(\d+)\]/i) { $data_weapons[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNA\[(\d+)\]/i) { $data_armors[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNS\[(\d+)\]/i) { $data_skills[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNT\[(\d+)\]/i) { $data_states[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNM\[(\d+)\]/i) { $data_enemies[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNC\[(\d+)\]/i) { $data_classes[$1.to_i].name rescue "" }
|
||||
result.gsub!(/\eNV\[(\d+)\]/i) { $data_system.variables[$1.to_i] }
|
||||
result.gsub!(/\eNSW\[(\d+)\]/i) { $data_system.switches[$1.to_i] }
|
||||
result.gsub!(/\eNWT\[(\d+)\]/i) { $data_system.weapon_types[$1.to_i] }
|
||||
result.gsub!(/\eNAT\[(\d+)\]/i) { $data_system.armor_types[$1.to_i] }
|
||||
result.gsub!(/\eNST\[(\d+)\]/i) { $data_system.skill_types[$1.to_i] }
|
||||
result.gsub!(/\eNL\[(\d+)\]/i) { $data_system.elements[$1.to_i] }
|
||||
# Vocab
|
||||
result.gsub!(/\eVOCAB\[(\w+),\s*(\d+)\s*\]/i) { Vocab.send($1.downcase, $2.to_i) rescue "" }
|
||||
result.gsub!(/\eVOCAB\[(\w+)\]/i) { Vocab.send($1.downcase) rescue "" }
|
||||
# Font Settings
|
||||
result.gsub!(/\eB/i) { "\eFE[0]" } # Bold On
|
||||
result.gsub!(/\/B/i) { "\eFE[1]" } # Bold Off
|
||||
result.gsub!(/\eI([^\[])/i) { "\eFE[2]#{$1}" } # Italics On
|
||||
result.gsub!(/\/I/i) { "\eFE[3]" } # Italics Off
|
||||
result.gsub!(/\eO/i) { "\eFE[4]" } # Outline On
|
||||
result.gsub!(/\/O/i) { "\eFE[5]" } # Outline Off
|
||||
result.gsub!(/\eS([^\[!])/i) { "\eFE[6]#{$1}" } # Shadow On
|
||||
result.gsub!(/\/S/i) { "\eFE[7]" } # Shadow Off
|
||||
result.gsub!(/\eU/i) { "\eFE[8]" } # Underline On
|
||||
result.gsub!(/\/U/i) { "\e\FE[9]" } # Underline Off
|
||||
result.gsub!(/\eHL\[(\d+)\]/i) { "\eHL[#{$1.to_i}]" } # Highlight On: custom colour
|
||||
result.gsub!(/\eHL([^\[])/i) { "\eHL[17]#{$1}" }# Highlight On: system colour
|
||||
result.gsub!(/\/HL/i) { "\eHL[0]" } # Hightlight Off
|
||||
result.gsub!(/\/FN/i) { "\eFN[]" } # Default Font
|
||||
result.gsub!(/\/FS/i) { "\eFS[#{Font.default_size}]" } # Default Font
|
||||
# Conditional Text
|
||||
result.gsub!(/\eS\[(\d+)[,;:](.+?)\]/mi) { $game_switches[$1.to_i] ? $2 : "" }
|
||||
result.gsub!(/\eS!\[(\d+)[,;:](.+?)\]/mi) { $game_switches[$1.to_i] ? "" : $2 }
|
||||
result.gsub!(/\eS\{(\d+)[,;:](.+?)\}/mi) { $game_switches[$1.to_i] ? $2 : "" }
|
||||
result.gsub!(/\eS!\{(\d+)[,;:](.+?)\}/mi) { $game_switches[$1.to_i] ? "" : $2 }
|
||||
# Evaluation
|
||||
result.gsub!(/\e#\{(.+?)\}/im) { (eval($1)).to_s rescue "" }
|
||||
# Do resubstitutions if requested
|
||||
if result.sub!(/\eRESUB/i, "") != nil
|
||||
result = convert_escape_characters(result, *args, &block)
|
||||
end
|
||||
result.gsub!(/\e(N|LB)/i, "\n") # Line Break
|
||||
result # Return result
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Calculate Line Height
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias ma_atssmc_clclnhght_3ek9 calc_line_height
|
||||
def calc_line_height(text, *args, &block)
|
||||
res = ma_atssmc_clclnhght_3ek9(text, *args, &block) # Run Original Method
|
||||
text.slice(/^.*$/).scan(/\eFS\[(\d+)\]/i) { |num| res = [res, num[0].to_i].max }
|
||||
res
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Process Normal Character
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias mlra_atssmc_procnorm_5fg2 process_normal_character
|
||||
def process_normal_character(c, pos, *args, &block)
|
||||
draw_highlight_underline(c, pos) if @underline || @highlight
|
||||
mlra_atssmc_procnorm_5fg2(c, pos, *args, &block) # Run Original Method
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Process Escape Character
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias ma_atssmc_procesc_7gv1 process_escape_character
|
||||
def process_escape_character(code, text, pos, *args, &block)
|
||||
case code.upcase
|
||||
when 'X' then pos[:x] = obtain_escape_param(text)
|
||||
when 'HC' # Hex Colour
|
||||
hex = text.slice!(/^\[([ABCDEF\d]+)\]/i)
|
||||
rgb = $1.scan(/../).map { |hex| hex.to_i(16) }
|
||||
change_color(Color.new(*rgb)) if rgb.size.between?(3,4)
|
||||
when 'FE' # Font Settings
|
||||
param = obtain_escape_param(text)
|
||||
case param / 2
|
||||
when 0 then contents.font.bold = ((param % 2) == 0) # Bold
|
||||
when 1 then contents.font.italic = ((param % 2) == 0) # Italic
|
||||
when 2 then contents.font.outline = ((param % 2) == 0) # Outline
|
||||
when 3 then contents.font.shadow = ((param % 2) == 0) # Shadow
|
||||
when 4 then @underline = ((param % 2) == 0) # Underline
|
||||
end
|
||||
when 'HL' then @highlight = obtain_escape_param(text) - 1 # Highlight
|
||||
when 'FN' # Font Name
|
||||
text.slice!(/^\[(.*?\])/)
|
||||
param = $1
|
||||
if param.nil? || param == ']'
|
||||
contents.font.name = Font.default_name
|
||||
else
|
||||
ary = []
|
||||
while param.slice!(/\s*(.+?)\s*[,;:\]]/) != nil do ary.push($1) end
|
||||
contents.font.name = ary
|
||||
end
|
||||
when 'FS' # Font Size
|
||||
text.slice!(/^\[(\d+)\]/)
|
||||
contents.font.size = [[$1.to_i, 16].max, 64].min
|
||||
else
|
||||
ma_atssmc_procesc_7gv1(code, text, pos, *args, &block) # Run Original Method
|
||||
end
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Draw Highlighting and Underlining
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
def draw_highlight_underline(c, pos)
|
||||
text_width = text_size(c).width
|
||||
y_space = (pos[:height] - contents.font.size) / 2
|
||||
if @underline # Underlining
|
||||
y = pos[:y] + pos[:height]
|
||||
y -= [2, y_space].max
|
||||
contents.fill_rect(pos[:x], y, text_width, 2, contents.font.color)
|
||||
end
|
||||
if @highlight >= 0 # Highlighting
|
||||
y = pos[:y]
|
||||
y += y_space - 1 if y_space > 0
|
||||
text_height = [contents.font.size + 2, pos[:height]].min
|
||||
colour = text_color(@highlight)
|
||||
colour.alpha = 128 if colour.alpha > 128
|
||||
contents.fill_rect(pos[:x], y, text_width, text_height, colour)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** Window_Message
|
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Summary of Changes:
|
||||
# aliased method - clear_instance_variables; process_escape_character;
|
||||
# update_show_fast; wait_for_one_character
|
||||
# overwritten super method - reset_font_settings
|
||||
#===============================================================================
|
||||
|
||||
class Window_Message
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Clear Instance Variables
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias ma_atssmc_clrinsvar_3dq9 clear_instance_variables
|
||||
def clear_instance_variables(*args, &block)
|
||||
ma_atssmc_clrinsvar_3dq9(*args, &block) # Run Original Method
|
||||
@skip_disabled = false
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Reset Font Settings
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
def reset_font_settings(*args, &block)
|
||||
change_color(normal_color)
|
||||
contents.font.name = $game_message.font_name
|
||||
contents.font.size = $game_message.font_size
|
||||
contents.font.bold = $game_message.font_bold
|
||||
contents.font.italic = $game_message.font_italic
|
||||
contents.font.outline = $game_message.font_outline
|
||||
contents.font.shadow = $game_message.font_shadow
|
||||
@underline = $game_message.font_underline
|
||||
@highlight = $game_message.font_highlight
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Process Escape Character
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias mnaa_atssmc_escchar_3dr9 process_escape_character
|
||||
def process_escape_character(code, text, pos, *args, &block)
|
||||
case code.upcase
|
||||
when 'MS' # Set Message Speed
|
||||
if !text[/^\[([+-])/].nil?
|
||||
text.sub!(/^\[([\+-])/, '[' )
|
||||
sign = $1
|
||||
else
|
||||
sign = ""
|
||||
end
|
||||
param = obtain_escape_param(text)
|
||||
sign.empty? ? $game_message.message_speed = param : $game_message.message_speed += "#{sign}#{param}".to_i
|
||||
when 'DS'
|
||||
text.slice!(/^%/) # Delete buffer to ensure code isn't overextended
|
||||
@skip_disabled = !@skip_disabled
|
||||
when 'W' then wait(obtain_escape_param(text))
|
||||
else
|
||||
mnaa_atssmc_escchar_3dr9(code, text, pos, *args, &block) # Run Original Method
|
||||
end
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Update Show Fast
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias mlg_atssmc_updshwfast_7yb1 update_show_fast
|
||||
def update_show_fast(*args, &block)
|
||||
mlg_atssmc_updshwfast_7yb1(*args, &block)
|
||||
if $game_message.message_speed < 1
|
||||
@show_fast = true
|
||||
elsif @skip_disabled
|
||||
@show_fast = false
|
||||
elsif $game_message.show_fast_speed > 0
|
||||
@show_fast = Input.press?(:C)
|
||||
end
|
||||
end
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# * Wait for One Character
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
alias mdrnl_smcats_waitonechar_5rf1 wait_for_one_character
|
||||
def wait_for_one_character(*args, &block)
|
||||
mdrnl_smcats_waitonechar_5rf1(*args, &block) # Run Original Method
|
||||
if (@show_fast || @line_show_fast) && $game_message.show_fast_speed > 0
|
||||
wait($game_message.show_fast_speed)
|
||||
elsif $game_message.message_speed > 1
|
||||
wait($game_message.message_speed - 1)
|
||||
end
|
||||
end
|
||||
end
|
158
Kawariki-patches/ports/BasicMouse.rb
Normal file
158
Kawariki-patches/ports/BasicMouse.rb
Normal file
|
@ -0,0 +1,158 @@
|
|||
module Input
|
||||
class BasicMouse
|
||||
include IBasicMouse
|
||||
|
||||
# コンストラクタ
|
||||
def initialize()
|
||||
# 関連付けられたウィンドウのハンドル
|
||||
@hWnd = 0
|
||||
|
||||
# 前回のマウスの状態
|
||||
@prev = nil
|
||||
|
||||
# 現在のマウスの状態
|
||||
@curr = nil
|
||||
|
||||
# ボタンの配列
|
||||
@buttons = Array.new(self.NumButtons()){ |i| i = ButtonInfo.new() }
|
||||
|
||||
# 何かボタンが押されているか
|
||||
@isPressedAnyButton = false
|
||||
|
||||
# ステータス情報文字列を更新すべきか
|
||||
@needToUpdate = true
|
||||
end
|
||||
|
||||
# 初期化処理
|
||||
def Initialize(hWnd)
|
||||
@hWnd = hWnd
|
||||
@curr = DIMOUSESTATE2.new(hWnd)
|
||||
end
|
||||
|
||||
# 更新処理
|
||||
def Update
|
||||
# マウスの更新処理
|
||||
@prev = @curr
|
||||
@curr.Update()
|
||||
|
||||
@isPressedAnyButton = false
|
||||
for i in 0..NumButtons() - 1
|
||||
@buttons[i].Update((@curr.rgbButtons[i] & 0x80) == 128 ? ButtonStatus::Pressed : ButtonStatus::Released)
|
||||
|
||||
if @buttons[i].Pressed()
|
||||
@isPressedAnyButton = true;
|
||||
end
|
||||
end
|
||||
|
||||
@needToUpdate = true
|
||||
end
|
||||
|
||||
# IBasicMouse::GetStatusString() オーバーライド
|
||||
def GetStatusString
|
||||
if @needToUpdate
|
||||
def Static
|
||||
leftButton = Keys::Key.new(0, "LeftButton", "左ボタン")
|
||||
rightButton = Keys::Key.new(1, "RightButton", "右ボタン")
|
||||
middleButton = Keys::Key.new(2, "MiddleButton", "中央ボタン")
|
||||
xButton1 = Keys::Key.new(3, "XButton1", "Xボタン1")
|
||||
xButton2 = Keys::Key.new(4, "XButton2", "Xボタン2")
|
||||
xButton3 = Keys::Key.new(5, "XButton3", "Xボタン3")
|
||||
xButton4 = Keys::Key.new(6, "XButton4", "Xボタン4")
|
||||
xButton5 = Keys::Key.new(7, "XButton5", "Xボタン5")
|
||||
@keyTable =
|
||||
[
|
||||
leftButton,
|
||||
rightButton,
|
||||
middleButton,
|
||||
xButton1,
|
||||
xButton2,
|
||||
xButton3,
|
||||
xButton4,
|
||||
xButton5
|
||||
]
|
||||
end
|
||||
self.Static()
|
||||
|
||||
puts sprintf("Position : (%5d,%5d)", self.X(), self.Y())
|
||||
puts sprintf("Velocity : (%5d,%5d,%5d)", self.VX(), self.VY(), self.VZ())
|
||||
puts "[ButtonName] [Pressed] [Released] [Repeated]"
|
||||
|
||||
for i in 0..(NumButtons() - 1)
|
||||
puts sprintf(
|
||||
"%-20s %4s%4s%6d %4s%4s %4s%6d",
|
||||
@keyTable[i].GetName(),
|
||||
@buttons[i].Pressed() ? "ON" : "OFF",
|
||||
@buttons[i].JustPressed() ? "ON" : "OFF",
|
||||
@buttons[i].GetContinuousCount(),
|
||||
@buttons[i].Released() ? "ON" : "OFF",
|
||||
@buttons[i].JustReleased() ? "ON" : "OFF",
|
||||
@buttons[i].Repeated() ? "ON" : "OFF",
|
||||
@buttons[i].GetRepeatCount()
|
||||
)
|
||||
end
|
||||
print("\n")
|
||||
end
|
||||
end
|
||||
|
||||
# マウスの最大ボタン数
|
||||
def NumButtons; return 8; end
|
||||
|
||||
# IBasicMouse::GetPosition() オーバーライド
|
||||
def GetPosition
|
||||
pos = System::Math::Vector2.Zero()
|
||||
pos.x = @curr.lX; pos.y = @curr.lY;
|
||||
return pos;
|
||||
end
|
||||
|
||||
# IBasicMouse::SetPosition() オーバーライド
|
||||
def SetPosition(x, y); Win32RGSS::Cursor::SetCursorPos(x, y); end
|
||||
|
||||
# IBasicMouse::GetVelocity() オーバーライド
|
||||
def GetVelocity
|
||||
pos = System::Math::Vector2.Zero()
|
||||
pos.x = @curr.lX; pos.y = @curr.lY;
|
||||
return pos
|
||||
end
|
||||
|
||||
# IBasicMouse::X() オーバーライド
|
||||
def X; return @curr.lX; end
|
||||
|
||||
# IBasicMouse::Y() オーバーライド
|
||||
def Y; return @curr.lY; end
|
||||
|
||||
# IBasicMouse::VX() オーバーライド
|
||||
def VX; return @curr.lX - @prev.lX; end
|
||||
|
||||
# IBasicMouse::VY() オーバーライド
|
||||
def VY; return @curr.lY - @prev.lY; end
|
||||
|
||||
# IBasicMouse::VZ() オーバーライド
|
||||
# def VZ; return @curr.lZ / 120; end
|
||||
def VZ
|
||||
# Check if @curr and @curr.lZ are valid (not nil)
|
||||
return 0 if @curr.nil? || @curr.lZ.nil?
|
||||
return @curr.lZ / 120.0 # Ensure division results in a float
|
||||
end
|
||||
|
||||
# IBasicMouse::LeftButton() オーバーライド
|
||||
def LeftButton; return @buttons[0]; end
|
||||
|
||||
# IBasicMouse::RightButton() オーバーライド
|
||||
def RightButton; return @buttons[1]; end
|
||||
|
||||
# IBasicMouse::MiddleButton() オーバーライド
|
||||
def MiddleButton; return @buttons[2]; end
|
||||
|
||||
# IBasicMouse::XButton1() オーバーライド
|
||||
def XButton1; return @buttons[3]; end
|
||||
|
||||
# IBasicMouse::XButton2() オーバーライド
|
||||
def XButton2; return @buttons[4]; end
|
||||
|
||||
# IBasicMouse::GetButtonState() オーバーライド
|
||||
def GetButtonState(index); return @buttons[index]; end
|
||||
|
||||
# 1つ以上のボタンが押し下げられている時にはtrueを返します。
|
||||
def IsPressedAnyButton; return @isPressedAnyButton; end
|
||||
end
|
||||
end
|
452
Kawariki-patches/ports/CRDJ_Input.rb
Normal file
452
Kawariki-patches/ports/CRDJ_Input.rb
Normal file
|
@ -0,0 +1,452 @@
|
|||
# CRDJ_Input.rb Kawariki MKXP-Z port
|
||||
# Date: 2023-06-01
|
||||
# TODO: - handle modified configuration
|
||||
# - Properly deal with the layout stuff?
|
||||
#==============================================================================
|
||||
# ** Input
|
||||
#-------------------------------------------------------------------------------
|
||||
# Created By Cidiomar R. Dias Junior
|
||||
# Originally posted at
|
||||
#
|
||||
# Terms of Use: Credit "Cidiomar R. Dias Junior"
|
||||
#
|
||||
# Maintained on Hime Works
|
||||
#-------------------------------------------------------------------------------
|
||||
# ** Description
|
||||
#
|
||||
# A module that handles input data from a gamepad or keyboard.
|
||||
# Managed by symbols rather than button numbers in RGSS3.
|
||||
#-------------------------------------------------------------------------------
|
||||
# ** Usage
|
||||
#
|
||||
# Scroll down to the configuration section. It is around line 185.
|
||||
# You can set up your key mappings there. Use the reference to get the names
|
||||
# of the keys.
|
||||
#
|
||||
#===============================================================================
|
||||
|
||||
module CRDJ_Input
|
||||
#--------------------------------------------------------------------------
|
||||
# * Keymap in symbols
|
||||
# To get a key from the keymap, you can use Input.key(sym) or Input:KEYMAP[sym]
|
||||
# Or if you want to use a symbol in a input function, just pass the symbol
|
||||
# as argument.
|
||||
#--------------------------------------------------------------------------
|
||||
KEYMAP = {
|
||||
LBUTTON: 0x01, RBUTTON: 0x02,
|
||||
CANCEL: 0x03, MBUTTON: 0x04,
|
||||
XBUTTON1: 0x05, XBUTTON2: 0x06,
|
||||
BACK: 0x08, TAB: 0x09,
|
||||
CLEAR: 0x0c, RETURN: 0x0d,
|
||||
SHIFT: 0x10, CONTROL: 0x11,
|
||||
MENU: 0x12, PAUSE: 0x13,
|
||||
CAPITAL: 0x14, KANA: 0x15,
|
||||
JUNJA: 0x17, FINAL: 0x18,
|
||||
HANJA: 0x19,
|
||||
ESCAPE: 0x1b, CONVERT: 0x1c,
|
||||
NONCONVERT: 0x1d, ACCEPT: 0x1e,
|
||||
MODECHANGE: 0x1f, SPACE: 0x20,
|
||||
PRIOR: 0x21, NEXT: 0x22,
|
||||
END: 0x23, HOME: 0x24,
|
||||
LEFT: 0x25, UP: 0x26,
|
||||
RIGHT: 0x27, DOWN: 0x28,
|
||||
SELECT: 0x29, PRINT: 0x2a,
|
||||
EXECUTE: 0x2b, SNAPSHOT: 0x2c,
|
||||
INSERT: 0x2d, DELETE: 0x2e,
|
||||
HELP: 0x2f, N0: 0x30,
|
||||
KEY_1: 0x31, KEY_2: 0x32,
|
||||
KEY_3: 0x33, KEY_4: 0x34,
|
||||
KEY_5: 0x35, KEY_6: 0x36,
|
||||
KEY_7: 0x37, KEY_8: 0x38,
|
||||
KEY_9: 0x39, colon: 0x3a,
|
||||
semicolon: 0x3b, less: 0x3c,
|
||||
equal: 0x3d, greater: 0x3e,
|
||||
question: 0x3f, at: 0x40,
|
||||
LETTER_A: 0x41, LETTER_B: 0x42,
|
||||
LETTER_C: 0x43, LETTER_D: 0x44,
|
||||
LETTER_E: 0x45, LETTER_F: 0x46,
|
||||
LETTER_G: 0x47, LETTER_H: 0x48,
|
||||
LETTER_I: 0x49, LETTER_J: 0x4a,
|
||||
LETTER_K: 0x4b, LETTER_L: 0x4c,
|
||||
LETTER_M: 0x4d, LETTER_N: 0x4e,
|
||||
LETTER_O: 0x4f, LETTER_P: 0x50,
|
||||
LETTER_Q: 0x51, LETTER_R: 0x52,
|
||||
LETTER_S: 0x53, LETTER_T: 0x54,
|
||||
LETTER_U: 0x55, LETTER_V: 0x56,
|
||||
LETTER_W: 0x57, LETTER_X: 0x58,
|
||||
LETTER_Y: 0x59, LETTER_Z: 0x5a,
|
||||
LWIN: 0x5b, RWIN: 0x5c,
|
||||
APPS: 0x5d, asciicircum: 0x5e,
|
||||
SLEEP: 0x5f, NUMPAD0: 0x60,
|
||||
NUMPAD1: 0x61, NUMPAD2: 0x62,
|
||||
NUMPAD3: 0x63, NUMPAD4: 0x64,
|
||||
NUMPAD5: 0x65, NUMPAD6: 0x66,
|
||||
NUMPAD7: 0x67, NUMPAD8: 0x68,
|
||||
NUMPAD9: 0x69, MULTIPLY: 0x6a,
|
||||
ADD: 0x6b, SEPARATOR: 0x6c,
|
||||
SUBTRACT: 0x6d, DECIMAL: 0x6e,
|
||||
DIVIDE: 0x6f, F1: 0x70,
|
||||
F2: 0x71, F3: 0x72,
|
||||
F4: 0x73, F5: 0x74,
|
||||
F6: 0x75, F7: 0x76,
|
||||
F8: 0x77, F9: 0x78,
|
||||
F10: 0x79, F11: 0x7a,
|
||||
F12: 0x7b, F13: 0x7c,
|
||||
F14: 0x7d, F15: 0x7e,
|
||||
F16: 0x7f, F17: 0x80,
|
||||
F18: 0x81, F19: 0x82,
|
||||
F20: 0x83, F21: 0x84,
|
||||
F22: 0x85, F23: 0x86,
|
||||
F24: 0x87, NUMLOCK: 0x90,
|
||||
SCROLL: 0x91, LSHIFT: 0xa0,
|
||||
RSHIFT: 0xa1, LCONTROL: 0xa2,
|
||||
RCONTROL: 0xa3, LMENU: 0xa4,
|
||||
RMENU: 0xa5, BROWSER_BACK: 0xa6,
|
||||
BROWSER_FORWARD: 0xa7, BROWSER_REFRESH: 0xa8,
|
||||
BROWSER_STOP: 0xa9, BROWSER_SEARCH: 0xaa,
|
||||
BROWSER_FAVORITES: 0xab, BROWSER_HOME: 0xac,
|
||||
VOLUME_MUTE: 0xad, VOLUME_DOWN: 0xae,
|
||||
VOLUME_UP: 0xaf, MEDIA_NEXT_TRACK: 0xb0,
|
||||
MEDIA_PREV_TRACK: 0xb1, MEDIA_STOP: 0xb2,
|
||||
MEDIA_PLAY_PAUSE: 0xb3, LAUNCH_MAIL: 0xb4,
|
||||
LAUNCH_MEDIA_SELECT: 0xb5, LAUNCH_APP1: 0xb6,
|
||||
LAUNCH_APP2: 0xb7, cedilla: 0xb8,
|
||||
onesuperior: 0xb9, masculine: 0xba,
|
||||
guillemotright: 0xbb, onequarter: 0xbc,
|
||||
onehalf: 0xbd, threequarters: 0xbe,
|
||||
questiondown: 0xbf, Agrave: 0xc0,
|
||||
Aacute: 0xc1, Acircumflex: 0xc2,
|
||||
Atilde: 0xc3, Adiaeresis: 0xc4,
|
||||
Aring: 0xc5, AE: 0xc6,
|
||||
Ccedilla: 0xc7, Egrave: 0xc8,
|
||||
Eacute: 0xc9, Ecircumflex: 0xca,
|
||||
Ediaeresis: 0xcb, Igrave: 0xcc,
|
||||
Iacute: 0xcd, Icircumflex: 0xce,
|
||||
Idiaeresis: 0xcf, ETH: 0xd0,
|
||||
Ntilde: 0xd1, Ograve: 0xd2,
|
||||
Oacute: 0xd3, Ocircumflex: 0xd4,
|
||||
Otilde: 0xd5, Odiaeresis: 0xd6,
|
||||
multiply: 0xd7, Oslash: 0xd8,
|
||||
Ugrave: 0xd9, Uacute: 0xda,
|
||||
Ucircumflex: 0xdb, Udiaeresis: 0xdc,
|
||||
Yacute: 0xdd, THORN: 0xde,
|
||||
ssharp: 0xdf, agrave: 0xe0,
|
||||
aacute: 0xe1, acircumflex: 0xe2,
|
||||
atilde: 0xe3, adiaeresis: 0xe4,
|
||||
PROCESSKEY: 0xe5, ae: 0xe6,
|
||||
PACKET: 0xe7, egrave: 0xe8,
|
||||
eacute: 0xe9, ecircumflex: 0xea,
|
||||
ediaeresis: 0xeb, igrave: 0xec,
|
||||
iacute: 0xed, icircumflex: 0xee,
|
||||
idiaeresis: 0xef, eth: 0xf0,
|
||||
ntilde: 0xf1, ograve: 0xf2,
|
||||
oacute: 0xf3, ocircumflex: 0xf4,
|
||||
otilde: 0xf5, ATTN: 0xf6,
|
||||
CRSEL: 0xf7, EXSEL: 0xf8,
|
||||
EREOF: 0xf9, PLAY: 0xfa,
|
||||
ZOOM: 0xfb, NONAME: 0xfc,
|
||||
PA1: 0xfd, thorn: 0xfe,
|
||||
ydiaeresis: 0xff
|
||||
}
|
||||
|
||||
KEYMAP[:WIN] = [KEYMAP[:LWIN], KEYMAP[:RWIN]]
|
||||
|
||||
#===============================================================================
|
||||
# Configuration
|
||||
#===============================================================================
|
||||
#--------------------------------------------------------------------------
|
||||
# * Default Keys, you can configure here instead of by pressing F1.
|
||||
#--------------------------------------------------------------------------
|
||||
UP = [KEYMAP[:UP]]
|
||||
DOWN = [KEYMAP[:DOWN]]
|
||||
LEFT = [KEYMAP[:LEFT]]
|
||||
RIGHT = [KEYMAP[:RIGHT]]
|
||||
A = [KEYMAP[:SHIFT]]
|
||||
B = [KEYMAP[:ESCAPE], KEYMAP[:LETTER_X]]
|
||||
C = [KEYMAP[:RETURN], KEYMAP[:LETTER_Z]]
|
||||
X = []
|
||||
Y = []
|
||||
Z = []
|
||||
L = [KEYMAP[:PRIOR]]
|
||||
R = [KEYMAP[:NEXT]]
|
||||
F5 = [KEYMAP[:F5]]
|
||||
F6 = [KEYMAP[:F6]]
|
||||
F7 = [KEYMAP[:F7]]
|
||||
F8 = [KEYMAP[:F8]]
|
||||
F9 = [KEYMAP[:F9]]
|
||||
SHIFT = [KEYMAP[:SHIFT]]
|
||||
CTRL = [KEYMAP[:CONTROL]]
|
||||
ALT = [KEYMAP[:MENU]]
|
||||
|
||||
#===============================================================================
|
||||
# Rest of script
|
||||
#===============================================================================
|
||||
#--------------------------------------------------------------------------
|
||||
# * Symbol version of default keys.
|
||||
#--------------------------------------------------------------------------
|
||||
SYM_KEYS = {
|
||||
:UP => UP,
|
||||
:LEFT => LEFT,
|
||||
:DOWN => DOWN,
|
||||
:RIGHT => RIGHT,
|
||||
:A => A,
|
||||
:B => B,
|
||||
:C => C,
|
||||
:X => X,
|
||||
:Y => Y,
|
||||
:Z => Z,
|
||||
:L => L,
|
||||
:R => R,
|
||||
:F5 => F5,
|
||||
:F6 => F6,
|
||||
:F7 => F7,
|
||||
:F8 => F8,
|
||||
:F9 => F9,
|
||||
:SHIFT => SHIFT,
|
||||
:CTRL => CTRL,
|
||||
:ALT => ALT
|
||||
}
|
||||
|
||||
# Letters that can have accent
|
||||
PssbLetters = "AEIOUCNYaeioucny"
|
||||
# Accents, in ASCII, configured at runtime to avoid encoding troubles
|
||||
Accents = [96.chr, 180.chr, 94.chr, 126.chr, 168.chr].join
|
||||
NonCompatChars = [180, 168]
|
||||
|
||||
module InputExtension
|
||||
#--------------------------------------------------------------------------
|
||||
# * Determines whether the button corresponding to the symbol sym is
|
||||
# currently being pressed.
|
||||
#
|
||||
# If the button is being pressed, returns TRUE. If not, returns FALSE.
|
||||
#
|
||||
# if Input.press?(:C)
|
||||
# do_something
|
||||
# end
|
||||
#--------------------------------------------------------------------------
|
||||
def press?(keys)
|
||||
if keys.is_a?(Numeric)
|
||||
k = keys.to_i
|
||||
return (self.pressex? k)
|
||||
elsif keys.is_a?(Array)
|
||||
return keys.any? {|key| self.pressex?(key) }
|
||||
elsif keys.is_a?(Symbol)
|
||||
if SYM_KEYS.key?(keys)
|
||||
return super(keys)
|
||||
return SYM_KEYS[keys].any? {|key| self.pressex?(key) }
|
||||
elsif KEYMAP.key?(keys)
|
||||
k = KEYMAP[keys]
|
||||
return self.pressex?(k)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# * Determines whether the button corresponding to the symbol sym is
|
||||
# currently being pressed again.
|
||||
# "Pressed again" is seen as time having passed between the button being
|
||||
# not pressed and being pressed.
|
||||
#
|
||||
# If the button is being pressed, returns TRUE. If not, returns FALSE.
|
||||
#--------------------------------------------------------------------------
|
||||
def trigger?(keys)
|
||||
if keys.is_a?(Numeric)
|
||||
return Input.triggerex?(keys.to_i)
|
||||
elsif keys.is_a?(Array)
|
||||
return keys.any? {|key| self.triggerex?(key)}
|
||||
elsif keys.is_a?(Symbol)
|
||||
if SYM_KEYS.key?(keys)
|
||||
return super(keys)
|
||||
Preload.print "Trigger #{keys} #{SYM_KEYS[keys]} #{x}"
|
||||
return SYM_KEYS[keys].any? {|key| self.triggerex?(key)}
|
||||
elsif KEYMAP.key?(keys)
|
||||
return self.triggerex?(KEYMAP[keys])
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# * Determines whether the button corresponding to the symbol sym is
|
||||
# currently being pressed again.
|
||||
# Unlike trigger?, takes into account the repeated input of a button being
|
||||
# held down continuously.
|
||||
#
|
||||
# If the button is being pressed, returns TRUE. If not, returns FALSE.
|
||||
#--------------------------------------------------------------------------
|
||||
def repeat?(keys)
|
||||
if keys.is_a?(Numeric)
|
||||
key = keys.to_i
|
||||
return self.repeatex?(key)
|
||||
elsif keys.is_a?(Array)
|
||||
return keys.any? {|key| self.repeatex?(key)}
|
||||
elsif keys.is_a?(Symbol)
|
||||
if SYM_KEYS.key?(keys)
|
||||
return super(keys)
|
||||
return SYM_KEYS[keys].any? {|key| self.repeatex?(key)}
|
||||
elsif KEYMAP.key?(keys)
|
||||
return self.repeatex?(KEYMAP[keys])
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# * Determines whether the button corresponding to the symbol sym
|
||||
# was released.
|
||||
#
|
||||
# If the button was released, returns TRUE. If not, returns FALSE.
|
||||
#--------------------------------------------------------------------------
|
||||
def release?(keys)
|
||||
if keys.is_a?(Numeric)
|
||||
return self.releaseex? keys.to_i
|
||||
elsif keys.is_a?(Array)
|
||||
return keys.any? {|key| self.release?(key)}
|
||||
elsif keys.is_a?(Symbol)
|
||||
if SYM_KEYS.key?(keys)
|
||||
return super(keys)
|
||||
return SYM_KEYS[keys].any? {|key| self.releaseex?(key)}
|
||||
elsif KEYMAP.key?(keys)
|
||||
return self.releaseex?(KEYMAP[keys])
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# * Checks the status of the directional buttons, translates the data into
|
||||
# a specialized 4-direction input format, and returns the number pad
|
||||
# equivalent (2, 4, 6, 8).
|
||||
#
|
||||
# If no directional buttons are being pressed (or the equivalent), returns 0.
|
||||
#--------------------------------------------------------------------------
|
||||
# def dir4
|
||||
# return 2 if self.press?(DOWN)
|
||||
# return 4 if self.press?(LEFT)
|
||||
# return 6 if self.press?(RIGHT)
|
||||
# return 8 if self.press?(UP)
|
||||
# return 0
|
||||
# end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# * Checks the status of the directional buttons, translates the data into
|
||||
# a specialized 8-direction input format, and returns the number pad
|
||||
# equivalent (1, 2, 3, 4, 6, 7, 8, 9).
|
||||
#
|
||||
#If no directional buttons are being pressed (or the equivalent), returns 0.
|
||||
#--------------------------------------------------------------------------
|
||||
# def dir8
|
||||
# down = self.press?(DOWN)
|
||||
# left = self.press?(LEFT)
|
||||
# return 1 if down and left
|
||||
# right = self.press?(RIGHT)
|
||||
# return 3 if down and right
|
||||
# up = self.press?(UP)
|
||||
# return 7 if up and left
|
||||
# return 9 if up and right
|
||||
# return 2 if down
|
||||
# return 4 if left
|
||||
# return 6 if right
|
||||
# return 8 if up
|
||||
# return 0
|
||||
# end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# * Gets the character that correspond to vk using the keyboard layout
|
||||
#--------------------------------------------------------------------------
|
||||
def get_character(vk)
|
||||
# FIXME: do something smarter
|
||||
return vk
|
||||
end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# * Accents Table, to bo used in conversion from ASCII to UTF8
|
||||
#--------------------------------------------------------------------------
|
||||
AccentsCharsConv = {
|
||||
"A" => ["A", "A", "A", "A", "A"],
|
||||
"E" => ["E", "E", "E", 0, "E"],
|
||||
"I" => ["I", "I", "I", 0, "I"],
|
||||
"O" => ["O", "O", "O", "O", "O"],
|
||||
"U" => ["U", "U", "U", 0, "U"],
|
||||
"C" => [ 0 , "C", 0 , 0, 0 ],
|
||||
"N" => [ 0 , 0, 0 , "N", 0 ],
|
||||
"Y" => [ 0 , "Y", 0 , 0, "?"],
|
||||
"a" => ["a", "a", "a", "a", "a"],
|
||||
"e" => ["e", "e", "e", 0 , "e"],
|
||||
"i" => ["i", "i", "i", 0 , "i"],
|
||||
"o" => ["o", "o", "o", "o", "o"],
|
||||
"u" => ["u", "u", "u", 0 , "u"],
|
||||
"c" => [ 0 , "c", 0 , 0 , 0 ],
|
||||
"n" => [ 0 , 0 , 0 , "n", 0 ],
|
||||
"y" => [ 0 , "y", 0 , 0 , "y"],
|
||||
}
|
||||
|
||||
@last_accent = nil
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# * Get inputed string transcoded to UTF8
|
||||
#--------------------------------------------------------------------------
|
||||
def UTF8String
|
||||
result = ""
|
||||
31.upto(255) {|key|
|
||||
if self.repeat?(key)
|
||||
c = self.get_character(key)
|
||||
if (cc = c.unpack("C")[0]) and NonCompatChars.include?(cc)
|
||||
result += cc.chr
|
||||
else
|
||||
result += UNICODE_TO_UTF8.convertc if c != ""
|
||||
end
|
||||
end
|
||||
}
|
||||
return "" if result == ""
|
||||
if @last_accent
|
||||
result = @last_accent + result
|
||||
@last_accent = nil
|
||||
end
|
||||
f_result = ""
|
||||
jump = false
|
||||
for i in 0 ... result.length
|
||||
c = result[i]
|
||||
if jump
|
||||
jump = false
|
||||
next
|
||||
end
|
||||
if Accents.include?c
|
||||
if (nc = result[i+1]) != nil
|
||||
if PssbLetters.include?(nc)
|
||||
if (ac = AccentsCharsConv[nc][Accents.indexc]) != 0
|
||||
f_result << ac
|
||||
jump = true
|
||||
else
|
||||
f_result << c
|
||||
f_result << nc
|
||||
jump = true
|
||||
end
|
||||
elsif Accents.include?(nc)
|
||||
f_result << c
|
||||
f_result << nc
|
||||
jump = true
|
||||
else
|
||||
f_result << c
|
||||
f_result << nc
|
||||
jump = true
|
||||
end
|
||||
else
|
||||
@last_accent = c
|
||||
end
|
||||
else
|
||||
f_result << c
|
||||
end
|
||||
end
|
||||
return f_result
|
||||
end
|
||||
end
|
||||
|
||||
Input.singleton_class.prepend InputExtension
|
||||
Input.const_set :KEYMAP, KEYMAP
|
||||
end
|
254
Kawariki-patches/ports/Glitchfinder_Keyboard_Stub.rb
Normal file
254
Kawariki-patches/ports/Glitchfinder_Keyboard_Stub.rb
Normal file
|
@ -0,0 +1,254 @@
|
|||
# Glitchfinder's Key Input MKXP stub
|
||||
# Only press? trigger? release? repeat? implemented
|
||||
# Direct forwarding to respective MKXP Input.*ex? methods
|
||||
# Key constants copied from 1.30 source
|
||||
# ANYKEY is not implemented by MKXP
|
||||
#
|
||||
# Authors: Glitchfinder, Taeyeon Mori
|
||||
# Date: 2022-01-31
|
||||
|
||||
module Keys
|
||||
# ****************************** Key names ********************************
|
||||
#--------------------------------------------------------------------------
|
||||
# * Miscellaneous Keys
|
||||
#--------------------------------------------------------------------------
|
||||
CANCEL = 0x03 # Control-Break Processing
|
||||
BACKSPACE = 0x08 # Backspace Key
|
||||
TAB = 0x09 # Tab Key
|
||||
CLEAR = 0x0C # Clear Key
|
||||
RETURN = 0x0D # Enter Key
|
||||
SHIFT = 0x10 # Shift Key
|
||||
CONTROL = 0x11 # Ctrl Key
|
||||
MENU = 0x12 # Alt Key
|
||||
PAUSE = 0x13 # Pause Key
|
||||
ESCAPE = 0x1B # Esc Key
|
||||
CONVERT = 0x1C # IME Convert Key
|
||||
NONCONVERT = 0x1D # IME Nonconvert Key
|
||||
ACCEPT = 0x1E # IME Accept Key
|
||||
SPACE = 0x20 # Space Bar Key (Space, usually blank)
|
||||
PRIOR = 0x21 # Page Up Key
|
||||
NEXT = 0x22 # Page Down Key
|
||||
ENDS = 0x23 # End Key
|
||||
HOME = 0x24 # Home Key
|
||||
LEFT = 0x25 # Left Arrow Key
|
||||
UP = 0x26 # Up Arrow Key
|
||||
RIGHT = 0x27 # Right Arrow Key
|
||||
DOWN = 0x28 # Down Arrow Key
|
||||
SELECT = 0x29 # Select Key
|
||||
PRINT = 0x2A # Print Key
|
||||
EXECUTE = 0x2B # Execute Key
|
||||
SNAPSHOT = 0x2C # Print Screen Key
|
||||
DELETE = 0x2E # Delete Key
|
||||
HELP = 0x2F # Help Key
|
||||
LSHIFT = 0xA0 # Left Shift Key
|
||||
RSHIFT = 0xA1 # Right Shift Key
|
||||
LCONTROL = 0xA2 # Left Control Key (Ctrl)
|
||||
RCONTROL = 0xA3 # Right Control Key (Ctrl)
|
||||
LMENU = 0xA4 # Left Menu Key (Alt)
|
||||
RMENU = 0xA5 # Right Menu Key (Alt)
|
||||
PACKET = 0xE7 # Used to Pass Unicode Characters as Keystrokes
|
||||
#--------------------------------------------------------------------------
|
||||
# * Number Keys
|
||||
#--------------------------------------------------------------------------
|
||||
N0 = 0x30 # 0 Key
|
||||
N1 = 0x31 # 1 Key
|
||||
N2 = 0x32 # 2 Key
|
||||
N3 = 0x33 # 3 Key
|
||||
N4 = 0x34 # 4 Key
|
||||
N5 = 0x35 # 5 Key
|
||||
N6 = 0x36 # 6 Key
|
||||
N7 = 0x37 # 7 Key
|
||||
N8 = 0x38 # 8 Key
|
||||
N9 = 0x39 # 9 Key
|
||||
#--------------------------------------------------------------------------
|
||||
# * Letter Keys
|
||||
#--------------------------------------------------------------------------
|
||||
A = 0x41 # A Key
|
||||
B = 0x42 # B Key
|
||||
C = 0x43 # C Key
|
||||
D = 0x44 # D Key
|
||||
E = 0x45 # E Key
|
||||
F = 0x46 # F Key
|
||||
G = 0x47 # G Key
|
||||
H = 0x48 # H Key
|
||||
I = 0x49 # I Key
|
||||
J = 0x4A # J Key
|
||||
K = 0x4B # K Key
|
||||
L = 0x4C # L Key
|
||||
M = 0x4D # M Key
|
||||
N = 0x4E # N Key
|
||||
O = 0x4F # O Key
|
||||
P = 0x50 # P Key
|
||||
Q = 0x51 # Q Key
|
||||
R = 0x52 # R Key
|
||||
S = 0x53 # S Key
|
||||
T = 0x54 # T Key
|
||||
U = 0x55 # U Key
|
||||
V = 0x56 # V Key
|
||||
W = 0x57 # W Key
|
||||
X = 0x58 # X Key
|
||||
Y = 0x59 # Y Key
|
||||
Z = 0x5A # Z Key
|
||||
#--------------------------------------------------------------------------
|
||||
# * Windows Keys
|
||||
#--------------------------------------------------------------------------
|
||||
LWIN = 0x5B # Left Windows Key (Natural keyboard)
|
||||
RWIN = 0x5C # Right Windows Key (Natural Keyboard)
|
||||
APPS = 0x5D # Applications Key (Natural keyboard)
|
||||
SLEEP = 0x5F # Computer Sleep Key
|
||||
BROWSER_BACK = 0xA6 # Browser Back Key
|
||||
BROWSER_FORWARD = 0xA7 # Browser Forward Key
|
||||
BROWSER_REFRESH = 0xA8 # Browser Refresh Key
|
||||
BROWSER_STOP = 0xA9 # Browser Stop Key
|
||||
BROWSER_SEARCH = 0xAA # Browser Search Key
|
||||
BROWSER_FAVORITES = 0xAB # Browser Favorites Key
|
||||
BROWSER_HOME = 0xAC # Browser Start and Home Key
|
||||
VOLUME_MUTE = 0xAD # Volume Mute Key
|
||||
VOLUME_DOWN = 0xAE # Volume Down Key
|
||||
VOLUME_UP = 0xAF # Volume Up Key
|
||||
MEDIA_NEXT_TRACK = 0xB0 # Next Track Key
|
||||
MEDIA_PREV_TRACK = 0xB1 # Previous Track Key
|
||||
MEDIA_STOP = 0xB2 # Stop Media Key
|
||||
MEDIA_PLAY_PAUSE = 0xB3 # Play/Pause Media Key
|
||||
LAUNCH_MAIL = 0xB4 # Start Mail Key
|
||||
LAUNCH_MEDIA_SELECT = 0xB5 # Select Media Key
|
||||
LAUNCH_APP1 = 0xB6 # Start Application 1 Key
|
||||
LAUNCH_APP2 = 0xB7 # Start Application 2 Key
|
||||
PROCESSKEY = 0xE5 # IME Process Key
|
||||
ATTN = 0xF6 # Attn Key
|
||||
CRSEL = 0xF7 # CrSel Key
|
||||
EXSEL = 0xF8 # ExSel Key
|
||||
EREOF = 0xF9 # Erase EOF Key
|
||||
PLAY = 0xFA # Play Key
|
||||
ZOOM = 0xFB # Zoom Key
|
||||
PA1 = 0xFD # PA1 Key
|
||||
#--------------------------------------------------------------------------
|
||||
# * Number Pad Keys
|
||||
#--------------------------------------------------------------------------
|
||||
NUMPAD0 = 0x60 # Numeric Keypad 0 Key
|
||||
NUMPAD1 = 0x61 # Numeric Keypad 1 Key
|
||||
NUMPAD2 = 0x62 # Numeric Keypad 2 Key
|
||||
NUMPAD3 = 0x63 # Numeric Keypad 3 Key
|
||||
NUMPAD4 = 0x64 # Numeric Keypad 4 Key
|
||||
NUMPAD5 = 0x65 # Numeric Keypad 5 Key
|
||||
NUMPAD6 = 0x66 # Numeric Keypad 6 Key
|
||||
NUMPAD7 = 0x67 # Numeric Keypad 7 Key
|
||||
NUMPAD8 = 0x68 # Numeric Keypad 8 Key
|
||||
NUMPAD9 = 0x69 # Numeric Keypad 9 Key
|
||||
MULTIPLY = 0x6A # Multiply Key (*)
|
||||
ADD = 0x6B # Add Key (+)
|
||||
SEPARATOR = 0x6C # Separator Key
|
||||
SUBTRACT = 0x6D # Subtract Key (-)
|
||||
DECIMAL = 0x6E # Decimal Key (.)
|
||||
DIVIDE = 0x6F # Divide Key (/)
|
||||
#--------------------------------------------------------------------------
|
||||
# * Function Keys
|
||||
#--------------------------------------------------------------------------
|
||||
F1 = 0x70 # F1 Key
|
||||
F2 = 0x71 # F2 Key
|
||||
F3 = 0x72 # F3 Key
|
||||
F4 = 0x73 # F4 Key
|
||||
F5 = 0x74 # F5 Key
|
||||
F6 = 0x75 # F6 Key
|
||||
F7 = 0x76 # F7 Key
|
||||
F8 = 0x77 # F8 Key
|
||||
F9 = 0x78 # F9 Key
|
||||
F10 = 0x79 # F10 Key
|
||||
F11 = 0x7A # F11 Key
|
||||
F12 = 0x7B # F12 Key
|
||||
F13 = 0x7C # F13 Key
|
||||
F14 = 0x7D # F14 Key
|
||||
F15 = 0x7E # F15 Key
|
||||
F16 = 0x7F # F16 Key
|
||||
F17 = 0x80 # F17 Key
|
||||
F18 = 0x81 # F18 Key
|
||||
F19 = 0x82 # F19 Key
|
||||
F20 = 0x83 # F20 Key
|
||||
F21 = 0x84 # F21 Key
|
||||
F22 = 0x85 # F22 Key
|
||||
F23 = 0x86 # F23 Key
|
||||
F24 = 0x87 # F24 Key
|
||||
#--------------------------------------------------------------------------
|
||||
# * Toggle Keys
|
||||
#--------------------------------------------------------------------------
|
||||
CAPITAL = 0x14 # Caps Lock Key
|
||||
KANA = 0x15 # IME Kana Mode Key
|
||||
HANGUL = 0x15 # IME Hangul Mode Key
|
||||
JUNJA = 0x17 # IME Junja Mode Key
|
||||
FINAL = 0x18 # IME Final Mode Key
|
||||
HANJA = 0x19 # IME Hanja Mode Key
|
||||
KANJI = 0x19 # IME Kanji Mode Key
|
||||
MODECHANGE = 0x1F # IME Mode Change Request Key
|
||||
INSERT = 0x2D # Insert Key
|
||||
NUMLOCK = 0x90 # Num Lock Key
|
||||
SCROLL = 0x91 # Scroll Lock Key
|
||||
#--------------------------------------------------------------------------
|
||||
# * OEM Keys (Vary by keyboard)
|
||||
#--------------------------------------------------------------------------
|
||||
OEM_1 = 0xBA # Misc Characters (; : in USA 101/102 Keyboards)
|
||||
OEM_SEMICOLON = 0xBA
|
||||
OEM_PLUS = 0xBB # + = Key
|
||||
OEM_COMMA = 0xBC # , < Key
|
||||
OEM_MINUS = 0xBD # - _ Key
|
||||
OEM_PERIOD = 0xBE # . > Key
|
||||
OEM_2 = 0xBF # Misc Characters (/ ? in USA 101/102 Keyboards)
|
||||
OEM_SLASH = 0xBF
|
||||
OEM_3 = 0xC0 # Misc Characters (` ~ in USA 101/102 Keyboards)
|
||||
OEM_GRAVE = 0xC0
|
||||
OEM_4 = 0xDB # Misc Characters ([ { in USA 101/102 Keyboards)
|
||||
OEM_OPENBRACKET = 0xDB
|
||||
OEM_5 = 0xDC # Misc Characters (\ | in USA 101/102 Keyboards)
|
||||
OEM_BACKSLASH = 0xDC
|
||||
OEM_6 = 0xDD # Misc Characters (] } in USA 101/102 Keyboards)
|
||||
OEM_CLOSEBRACKET = 0xDD
|
||||
OEM_7 = 0xDE # Misc Characters (' " in USA 101/102 Keyboards)
|
||||
OEM_APOSTROPHE = 0xDE
|
||||
OEM_8 = 0xDF # Misc Characters (Varies by Keyboard)
|
||||
OEM_9 = 0xE1 # OEM Specific
|
||||
OEM_10 = 0x92 # OEM Specific
|
||||
OEM_11 = 0x93 # OEM Specific
|
||||
OEM_12 = 0x94 # OEM Specific
|
||||
OEM_13 = 0x95 # OEM Specific
|
||||
OEM_14 = 0x96 # OEM Specific
|
||||
OEM_15 = 0xE3 # OEM Specific
|
||||
OEM_16 = 0xE4 # OEM Specific
|
||||
OEM_17 = 0xE6 # OEM Specific
|
||||
OEM_18 = 0xE9 # OEM Specific
|
||||
OEM_19 = 0xEA # OEM Specific
|
||||
OEM_20 = 0xEB # OEM Specific
|
||||
OEM_21 = 0xEC # OEM Specific
|
||||
OEM_22 = 0xED # OEM Specific
|
||||
OEM_23 = 0xEE # OEM Specific
|
||||
OEM_24 = 0xEF # OEM Specific
|
||||
OEM_25 = 0xF1 # OEM Specific
|
||||
OEM_26 = 0xF2 # OEM Specific
|
||||
OEM_27 = 0xF3 # OEM Specific
|
||||
OEM_28 = 0xF4 # OEM Specific
|
||||
OEM_29 = 0xF5 # OEM Specific
|
||||
OEM_102 = 0xE2 # Angle Bracket or Backslash on RT-102 Keyboards
|
||||
OEM_CLEAR = 0xFE # Clear Key
|
||||
#--------------------------------------------------------------------------
|
||||
# * Special Keys
|
||||
#--------------------------------------------------------------------------
|
||||
#ANYKEY = 0x100 # Any Key
|
||||
|
||||
# ********************************* Stub **********************************
|
||||
def self.update
|
||||
end
|
||||
|
||||
def self.press?(key)
|
||||
return Input.pressex? key
|
||||
end
|
||||
|
||||
def self.trigger?(key)
|
||||
return Input.triggerex? key
|
||||
end
|
||||
|
||||
def self.repeat?(key)
|
||||
return Input.repeatex? key
|
||||
end
|
||||
|
||||
def self.release?(key)
|
||||
return Input.releaseex? key
|
||||
end
|
||||
end
|
1052
Kawariki-patches/ports/Mouse.rb
Normal file
1052
Kawariki-patches/ports/Mouse.rb
Normal file
File diff suppressed because it is too large
Load diff
315
Kawariki-patches/ports/TH_EventTriggerLabels.rb
Normal file
315
Kawariki-patches/ports/TH_EventTriggerLabels.rb
Normal file
|
@ -0,0 +1,315 @@
|
|||
=begin
|
||||
#==============================================================================
|
||||
Title: Event Trigger Labels
|
||||
Author: Hime
|
||||
Date: Dec 22, 2014
|
||||
------------------------------------------------------------------------------
|
||||
** Change log
|
||||
Sep 09, 2022
|
||||
- Add mkxp-z 2.4 support
|
||||
Feb 13, 2022
|
||||
- MKXP(-Z) port by Taeyeon Mori
|
||||
- Replace any_key_pressed? implementation based on Win32API with
|
||||
one using System.raw_key_states
|
||||
Dec 22, 2014
|
||||
- fixed bug where page list is not properly reset after execution
|
||||
- added a flag for post-event processing for whether an event was triggered
|
||||
Nov 6, 2014
|
||||
- completely refactored code
|
||||
- implemented "any key pressed?" check
|
||||
- moved key item triggers and touch triggers into separate scripts
|
||||
Jan 30, 2014
|
||||
-refactored code
|
||||
-added compatibility with instance items
|
||||
Dec 27, 2013
|
||||
-optimized performance by not clearing out the key item variable on update
|
||||
Nov 19, 2013
|
||||
-fixed bug where stepping on event with no active page crashed the game
|
||||
Sep 26, 2013
|
||||
-added support for "player touch" trigger label
|
||||
Sep 6, 2013
|
||||
-fixed bug where trigger labels as the first command doesn't register properly
|
||||
Mar 22, 2013
|
||||
-fixed bug where you can still trigger events after they have been erased
|
||||
Dec 5, 2012
|
||||
-fixed issue where event was checked before page was setup
|
||||
Oct 20, 2012
|
||||
-fixed issue where using key item in succession crashes game
|
||||
-added support for key item triggers
|
||||
Aug 22, 2012
|
||||
-Support input names greater than one character (eg: F5 vs C)
|
||||
Aug 18, 2012
|
||||
-fixed label parsing to store all buttons
|
||||
Jun 13, 2012
|
||||
-initial release
|
||||
------------------------------------------------------------------------------
|
||||
** Terms of Use
|
||||
* Free to use in non-commercial projects
|
||||
* Contact me for commercial use
|
||||
* No real support. The script is provided as-is
|
||||
* Will do bug fixes, but no compatibility patches
|
||||
* Features may be requested but no guarantees, especially if it is non-trivial
|
||||
* Credits to Hime Works in your project
|
||||
* Preserve this header
|
||||
------------------------------------------------------------------------------
|
||||
** Description:
|
||||
|
||||
This script allows you to assign multiple action triggers to an event.
|
||||
Every page can have its own set of action triggers.
|
||||
|
||||
The action button, by default, is the C button (on keyboards, it is by default
|
||||
the Z key, Enter, or Space). So when you press the action button when you're
|
||||
standing beside an event, you will execute its action trigger and the event
|
||||
will begin running.
|
||||
|
||||
Multiple action triggers allow you to set up your event to run different
|
||||
sets of commands depending on which button you pressed. For example, you can
|
||||
press the C button to interact with the event normally, or you can press the
|
||||
X button (default A key) to initiate a mini-game.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
** Installation
|
||||
|
||||
Place this script below Materials and above Main
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
** Usage
|
||||
|
||||
Instead of treating your page as one list of commands, you should instead
|
||||
treat it as different sections of commands. Each section will have its own
|
||||
label, specified in a specific format.
|
||||
|
||||
To create a section, add a Label command and then write
|
||||
|
||||
button?(:C)
|
||||
|
||||
This means that any commands under this label will be executed when you press
|
||||
the C button (remember that the C button is the Z key on your keyboard).
|
||||
|
||||
You can create as many sections as you want, each with their own buttons.
|
||||
Press F1 in-game and then go to the keyboard tab to see which buttons are
|
||||
available.
|
||||
|
||||
#==============================================================================
|
||||
=end
|
||||
$imported = {} if $imported.nil?
|
||||
$imported[:TH_EventTriggerLabels] = true
|
||||
#==============================================================================
|
||||
# ** Configuration
|
||||
#==============================================================================
|
||||
module TH
|
||||
module Event_Trigger_Labels
|
||||
|
||||
# this is what you need to type for all your labels if you want to use
|
||||
# the input branching
|
||||
Button_Format = "button?"
|
||||
|
||||
#==============================================================================
|
||||
# ** Rest of the script
|
||||
#==============================================================================
|
||||
Button_Regex = /#{Regexp.escape(Button_Format)}\(\:(.*)\)/
|
||||
end
|
||||
end
|
||||
|
||||
module Input
|
||||
class << self
|
||||
alias :th_any_key_pressed_check_update :update
|
||||
end
|
||||
|
||||
# Not every key should be checked
|
||||
Keys_To_Check = 4.upto(99) # SDL scancodes, most standard keys, no modifiers
|
||||
|
||||
if Input.respond_to?(:raw_key_states) then # MKXP-Z 2.4 +
|
||||
def self.update
|
||||
th_any_key_pressed_check_update
|
||||
state = Input.raw_key_states
|
||||
@any_key_pressed = Keys_To_Check.any?{|key| state[key]}
|
||||
end
|
||||
else
|
||||
def self.update
|
||||
th_any_key_pressed_check_update
|
||||
state = System.raw_key_states
|
||||
@any_key_pressed = Keys_To_Check.any?{|key| state[key] != 0}
|
||||
end
|
||||
end
|
||||
|
||||
def self.any_key_pressed?
|
||||
@any_key_pressed
|
||||
end
|
||||
end
|
||||
|
||||
module RPG
|
||||
class Event::Page
|
||||
|
||||
attr_accessor :button_labels
|
||||
|
||||
def button_labels
|
||||
return @button_labels ||= []
|
||||
end
|
||||
|
||||
alias :th_event_trigger_labels_list :list
|
||||
def list
|
||||
setup_trigger_labels unless @trigger_labels_set
|
||||
th_event_trigger_labels_list
|
||||
end
|
||||
|
||||
def setup_trigger_labels
|
||||
@trigger_labels_set = true
|
||||
nulls = []
|
||||
if @trigger < 3
|
||||
@list.each_with_index do |cmd, index|
|
||||
if cmd.code == 118
|
||||
label = cmd.parameters[0]
|
||||
# Check for extra buttons
|
||||
if trigger_label?(label)
|
||||
nulls << index
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# insert "exit event processing" before each "event branch"
|
||||
nulls.reverse.each {|index|
|
||||
@list.insert(index, RPG::EventCommand.new(115))
|
||||
}
|
||||
end
|
||||
|
||||
def trigger_label?(label)
|
||||
if label =~ TH::Event_Trigger_Labels::Button_Regex
|
||||
self.button_labels << $1.to_sym
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Player < Game_Character
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Alias. Try to avoid hardcoding it
|
||||
#-----------------------------------------------------------------------------
|
||||
alias :th_trigger_labels_nonmoving :update_nonmoving
|
||||
def update_nonmoving(last_moving)
|
||||
return if $game_map.interpreter.running?
|
||||
if trigger_conditions_met?
|
||||
pre_trigger_event_processing
|
||||
triggered = check_event_label_trigger
|
||||
post_trigger_event_processing(triggered)
|
||||
end
|
||||
th_trigger_labels_nonmoving(last_moving)
|
||||
end
|
||||
|
||||
def trigger_conditions_met?
|
||||
movable? && Input.any_key_pressed?
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
def pre_trigger_event_processing
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# New. Clean up.
|
||||
#-----------------------------------------------------------------------------
|
||||
def post_trigger_event_processing(triggered)
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# New. Check for any valid events in the area
|
||||
#-----------------------------------------------------------------------------
|
||||
def check_event_label_trigger
|
||||
positions_to_check_for_event.each do |x, y|
|
||||
$game_map.events_xy(x, y).each do |event|
|
||||
label = event.check_trigger_label
|
||||
|
||||
# If no label was found, check next event
|
||||
next unless label
|
||||
|
||||
# If the event can run, insert a jump to label command at
|
||||
# the beginning before running it
|
||||
if check_action_event
|
||||
text = [label]
|
||||
command = RPG::EventCommand.new(119, 0, text)
|
||||
event.list.insert(0, command)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# New. Positions to check events
|
||||
#-----------------------------------------------------------------------------
|
||||
def positions_to_check_for_event
|
||||
positions = [[@x, @y]]
|
||||
x2 = $game_map.round_x_with_direction(@x, @direction)
|
||||
y2 = $game_map.round_y_with_direction(@y, @direction)
|
||||
positions << [x2, y2]
|
||||
return positions unless $game_map.counter?(x2, y2)
|
||||
x3 = $game_map.round_x_with_direction(x2, @direction)
|
||||
y3 = $game_map.round_y_with_direction(y2, @direction)
|
||||
positions << [x3, y3]
|
||||
return positions
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Event
|
||||
|
||||
attr_reader :page
|
||||
attr_reader :erased
|
||||
attr_accessor :list
|
||||
|
||||
alias :th_event_trigger_labels_setup_page_settings :setup_page_settings
|
||||
def setup_page_settings(*args)
|
||||
th_event_trigger_labels_setup_page_settings
|
||||
@list = Marshal.load(Marshal.dump(@page.list.clone))
|
||||
end
|
||||
|
||||
def check_trigger_label
|
||||
return nil if @erased
|
||||
label = get_trigger_label
|
||||
if label
|
||||
# Reset the commands (Since we maybe have inserted a jump command before)
|
||||
@needs_reset = true
|
||||
end
|
||||
return label
|
||||
end
|
||||
|
||||
def get_trigger_label
|
||||
label = check_button_trigger
|
||||
return label if label
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# New. Check whether the button triggers the event
|
||||
#-----------------------------------------------------------------------------
|
||||
def check_button_trigger
|
||||
return unless button_trigger_met?
|
||||
@page.button_labels.each do |button|
|
||||
if Input.trigger?(button)
|
||||
return "#{TH::Event_Trigger_Labels::Button_Format}(:#{button})"
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def button_trigger_met?
|
||||
return false unless @page
|
||||
return false if @page.button_labels.empty?
|
||||
return true
|
||||
end
|
||||
|
||||
alias :th_event_trigger_labels_update :update
|
||||
def update
|
||||
th_event_trigger_labels_update
|
||||
reset_page if @needs_reset
|
||||
end
|
||||
|
||||
def reset_page
|
||||
@needs_reset = false
|
||||
@list = Marshal.load(Marshal.dump(@page.list.clone))
|
||||
end
|
||||
end
|
110
Kawariki-patches/ports/TH_SimpleAudioEncryption.rb
Normal file
110
Kawariki-patches/ports/TH_SimpleAudioEncryption.rb
Normal file
|
@ -0,0 +1,110 @@
|
|||
=begin
|
||||
#===============================================================================
|
||||
Title: Simple Audio Encryption MKXP-Z
|
||||
Author: Taeyeon Mori
|
||||
Date: Feb 23, 2022
|
||||
Original Title: Simple Audio Encryption
|
||||
Original Author: Hime
|
||||
Original Date: Mar 22, 2014
|
||||
Original URL: http://www.himeworks.com/2014/03/21/simple-audio-encryption/
|
||||
--------------------------------------------------------------------------------
|
||||
** Original Terms of Use
|
||||
* Free to use in non-commercial projects
|
||||
* Contact me for commercial use
|
||||
* No real support. The script is provided as-is
|
||||
* Will do bug fixes, but no compatibility patches
|
||||
* Features may be requested but no guarantees, especially if it is non-trivial
|
||||
* Credits to Hime Works in your project
|
||||
* Preserve this header
|
||||
#===============================================================================
|
||||
=end
|
||||
|
||||
$imported = {} if $imported.nil?
|
||||
$imported[:TH_SimpleAudioEncryption] = true
|
||||
|
||||
module TH
|
||||
module Crypt
|
||||
@@video_extensions = [".ogv"]
|
||||
@@audio_extensions = ["", ".ogg", ".mp3", ".mid", ".wav"]
|
||||
@@cache = {}
|
||||
|
||||
def self.find_real_path(path, exts)
|
||||
# return unmodified if we can verify that it exists outside archive
|
||||
return path if exts.any? {|ext| File.exist? (path + ext)}
|
||||
exts.each do|ext|
|
||||
# There is no way to check if a file exists in the archive from Ruby
|
||||
# So we try to load it to a string and see if it fails.
|
||||
# This is expensive so make sure to cache the result of this method
|
||||
candidate = "Data/" + path + ext
|
||||
begin
|
||||
# MKXP-Z extension
|
||||
load_data candidate, true
|
||||
rescue
|
||||
next
|
||||
end
|
||||
Preload.print "TH_SAE: Found #{path} at #{candidate}"
|
||||
return candidate
|
||||
end
|
||||
# return nil if not found
|
||||
return nil
|
||||
end
|
||||
|
||||
def self.real_path(path, exts)
|
||||
# Check cache
|
||||
real_path = @@cache[path]
|
||||
return real_path unless real_path.nil?
|
||||
# Try to find
|
||||
real_path = self.find_real_path path, exts
|
||||
# Just fall back to the original path if not found
|
||||
# Otherwise, we'll repeat the expensive lookup
|
||||
# whenever this path comes up
|
||||
real_path = path if real_path.nil?
|
||||
# Save to cache
|
||||
@@cache[path] = real_path
|
||||
return real_path
|
||||
end
|
||||
|
||||
def self.real_audio_path(path)
|
||||
self.real_path path, @@audio_extensions
|
||||
end
|
||||
|
||||
def self.real_video_path(path)
|
||||
self.real_path path, @@video_extensions
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Audio
|
||||
class << self
|
||||
alias :th_simple_audio_decryption_bgm_play :bgm_play
|
||||
alias :th_simple_audio_decryption_bgs_play :bgs_play
|
||||
alias :th_simple_audio_decryption_me_play :me_play
|
||||
alias :th_simple_audio_decryption_se_play :se_play
|
||||
end
|
||||
|
||||
def self.bgm_play(name, *args)
|
||||
th_simple_audio_decryption_bgm_play(TH::Crypt::real_audio_path(name), *args)
|
||||
end
|
||||
|
||||
def self.bgs_play(name, *args)
|
||||
th_simple_audio_decryption_bgs_play(TH::Crypt::real_audio_path(name), *args)
|
||||
end
|
||||
|
||||
def self.me_play(name, *args)
|
||||
th_simple_audio_decryption_me_play(TH::Crypt::real_audio_path(name), *args)
|
||||
end
|
||||
|
||||
def self.se_play(name, *args)
|
||||
th_simple_audio_decryption_se_play(TH::Crypt::real_audio_path(name), *args)
|
||||
end
|
||||
end
|
||||
|
||||
module Graphics
|
||||
class << self
|
||||
alias :th_simple_audio_encryption_play_movie :play_movie
|
||||
end
|
||||
|
||||
def self.play_movie(name, *args)
|
||||
th_simple_audio_encryption_play_movie(TH::Crypt::real_video_path(name), *args)
|
||||
end
|
||||
end
|
815
Kawariki-patches/ports/XP_CustomResolution.rb
Normal file
815
Kawariki-patches/ports/XP_CustomResolution.rb
Normal file
|
@ -0,0 +1,815 @@
|
|||
#===============================================================================
|
||||
# Custom Resolution
|
||||
# Authors: ForeverZer0, KK20
|
||||
# Version: 0.96b
|
||||
# Date: 11.15.2013
|
||||
#===============================================================================
|
||||
# MKXP Port
|
||||
# Authors: Taeyeon Mori
|
||||
# Date: 01/30/2022
|
||||
#
|
||||
# Includes tilemap texture size workaround
|
||||
Preload.require 'XP_TilemapOverrideLib.rb'
|
||||
#===============================================================================
|
||||
# KK20's Notes
|
||||
#===============================================================================
|
||||
# Introduction:
|
||||
#
|
||||
# This script is intended to create screen resolutions other than 640 x 480.
|
||||
# The script comes with its own Tilemap rewrite in order to combat larger
|
||||
# screen resolutions (because anything beyond 640 x 480 is not drawn).
|
||||
#
|
||||
# Instructions:
|
||||
#
|
||||
# Place script above 'Main'. Probably best to put it below all your other
|
||||
# custom scripts.
|
||||
# You will also need 'screenshot.dll' included in your project. You can find
|
||||
# that in Fantasist's Transitions Pack linked below.
|
||||
#
|
||||
# Things to Consider:
|
||||
#
|
||||
# - Fullscreen will change the resolution back to 640 x 480. A solution is in
|
||||
# the works.
|
||||
# - Transitions do not work properly on larger resolutions. You can use a
|
||||
# Transitions Add-Ons script if you want better transitions (otherwise, all
|
||||
# you will get is the default fade in/out). Links listed below.
|
||||
# - Custom scripts that draw windows to the screen will most likely need edits.
|
||||
# - Larger resolutions = more processing power = more lag
|
||||
#
|
||||
# ***************************************************************************
|
||||
# * THIS IS STILL A WORK IN PROGRESS; IF YOU FIND ANYTHING PLEASE REPORT IT *
|
||||
# ***************************************************************************
|
||||
#
|
||||
# Links:
|
||||
# - Fantasist's Transitions Pack (w/ screenshot.dll)
|
||||
# http://forum.chaos-project.com/index.php/topic,1390.0.html
|
||||
# - ForeverZer0's Add-ons
|
||||
# http://forum.chaos-project.com/index.php/topic,7862.0.html
|
||||
# - ThallionDarkshine's Add-ons
|
||||
# http://forum.chaos-project.com/index.php/topic,12655.0.html
|
||||
# - Drago Transition Pack
|
||||
# http://forum.chaos-project.com/index.php/topic,13488.0.html
|
||||
#
|
||||
#===============================================================================
|
||||
# ForeverZer0's Notes from v0.93 (outdated information)
|
||||
#===============================================================================
|
||||
# Introduction:
|
||||
#
|
||||
# My goal in creating this script was to create a system that allowed the user
|
||||
# to set the screen size to something other than 640 x 480, but not have make
|
||||
# huge sacrifices in compatibility and performance. Although the script is
|
||||
# not simply Plug-and-Play, it is about as close as one can achieve with a
|
||||
# script of this nature.
|
||||
#
|
||||
# Instructions:
|
||||
#
|
||||
# - Place the "screenshot.dll" from Fantasist's Transition Pack script, which
|
||||
# can be found here: http://www.sendspace.com/file/yjd54h in your game folder
|
||||
# - Place this script above main, below default scripts.
|
||||
# - In my experience, unchecking "Reduce Screen Flickering" actually helps the
|
||||
# screen not to flicker. Open menu with F1 while playing and set this to what
|
||||
# you get the best results with.
|
||||
#
|
||||
# Features:
|
||||
#
|
||||
# - Totally re-written Tilemap and Plane class. Both classes were written to
|
||||
# display the map across any screen size automatically. The Tilemap class
|
||||
# is probably even more efficient than the original, which will help offset
|
||||
# any increased lag due to using a larger screen size with more sprites
|
||||
# being displayed.
|
||||
# - Every possible autotile graphic (48 per autotile) will be cached for the
|
||||
# next time that tile is used.
|
||||
# - Autotile animation has been made as efficient as possible, with a system
|
||||
# that stores their coodinates, but only if they change. This greatly reduces
|
||||
# the number of iterations at each update.
|
||||
# - System creates an external file to save pre-cached data priorities and
|
||||
# autotiles. This will decrease any loading times even more, and only takes a
|
||||
# second, depending on the number of maps you have.
|
||||
# - User defined autotile animation speed. Can change with script calls.
|
||||
# - Automatic re-sizing of Bitmaps and Viewports that are 640 x 480 to the
|
||||
# defined resolution, unless explicitely over-ridden in the method call.
|
||||
# The graphics themselves will not be resized, but any existing scripts that
|
||||
# use the normal screen size will already be configured to display different
|
||||
# sizes of graphics for transitions, battlebacks, pictures, fogs, etc.
|
||||
# - Option to have a log file ouput each time the game is ran, which can alert
|
||||
# you to possible errors with map sizes, etc.
|
||||
#
|
||||
# Issues/Bugs/Possible Bugs:
|
||||
#
|
||||
# - Graphic related scripts and your graphics will need to be customized to
|
||||
# fit the new screen size, so this script is not for everyone.
|
||||
# - The Z-axis for the Plane class, which is used for Fogs and Panoramas has
|
||||
# been altered. It is now multiplied by 1000. This will likely be a minor
|
||||
# issue for most, since this class is very rarely used except for Fogs and
|
||||
# Panoramas, which are already far above and below respectfully.
|
||||
# - Normal transitions using graphics cannot be used. With the exception of
|
||||
# a standard fade, like that used when no graphic is defined will be used.
|
||||
# Aside from that, only special transitions from Transition Pack can be
|
||||
# used.
|
||||
#===============================================================================
|
||||
# Credits/Thanks:
|
||||
# - ForeverZer0, for script.
|
||||
# - Creators of the Transition Pack and Screenshot.dll
|
||||
# - Selwyn, for base resolution script
|
||||
# - KK20, for Version 0.94 and above and the Tilemap class
|
||||
#===============================================================================
|
||||
# CONFIGURATION
|
||||
#===============================================================================
|
||||
# FIXME: need to exfiltrate this in the preload patch process
|
||||
|
||||
SCREEN = [1024, 576]
|
||||
# Define the resolution of the game screen. These values can be anything
|
||||
# within reason. Centering, viewports, etc. will all be taken care of, but it
|
||||
# is recommended that you use values divisible by 32 for best results.
|
||||
|
||||
UPDATE_COUNT = 8
|
||||
# Define the number of frames between autotile updates. The lower the number,
|
||||
# the faster the animations cycle. This can be changed in-game with the
|
||||
# following script call: $game_map.autotile_speed = SPEED
|
||||
|
||||
RESOLUTION_LOG = true
|
||||
# This will create a log in the Game directory each time the game is ran in
|
||||
# DEBUG mode, which will list possible errors with map sizes, etc.
|
||||
|
||||
#===============================================================================
|
||||
# ** Resolution
|
||||
#===============================================================================
|
||||
|
||||
class Resolution
|
||||
|
||||
attr_reader :version
|
||||
|
||||
def initialize
|
||||
# Define version.
|
||||
@version = 0.96
|
||||
# Resize screen
|
||||
Graphics.resize_screen(SCREEN[0], SCREEN[1])
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
def size
|
||||
# Returns the screen size of the machine.
|
||||
# FIXME: available in MKXP?
|
||||
return [1920, 1080]
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
def snapshot(filename = 'Data/snap', quality = 0)
|
||||
# FILENAME = Filename that the picture will be saved as.
|
||||
# FILETYPE = 0 = High Quality 1 = Low Quality (ignored)
|
||||
Graphics.screenshot(filename)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** RPG::Cache
|
||||
#===============================================================================
|
||||
|
||||
module RPG::Cache
|
||||
|
||||
AUTO_INDEX = [
|
||||
[27,28,33,34], [5,28,33,34], [27,6,33,34], [5,6,33,34],
|
||||
[27,28,33,12], [5,28,33,12], [27,6,33,12], [5,6,33,12],
|
||||
[27,28,11,34], [5,28,11,34], [27,6,11,34], [5,6,11,34],
|
||||
[27,28,11,12], [5,28,11,12], [27,6,11,12], [5,6,11,12],
|
||||
[25,26,31,32], [25,6,31,32], [25,26,31,12], [25,6,31,12],
|
||||
[15,16,21,22], [15,16,21,12], [15,16,11,22], [15,16,11,12],
|
||||
[29,30,35,36], [29,30,11,36], [5,30,35,36], [5,30,11,36],
|
||||
[39,40,45,46], [5,40,45,46], [39,6,45,46], [5,6,45,46],
|
||||
[25,30,31,36], [15,16,45,46], [13,14,19,20], [13,14,19,12],
|
||||
[17,18,23,24], [17,18,11,24], [41,42,47,48], [5,42,47,48],
|
||||
[37,38,43,44], [37,6,43,44], [13,18,19,24], [13,14,43,44],
|
||||
[37,42,43,48], [17,18,47,48], [13,18,43,48], [1,2,7,8]
|
||||
]
|
||||
|
||||
def self.autotile(filename)
|
||||
key = "Graphics/Autotiles/#{filename}"
|
||||
if !@cache.include?(key) || @cache[key].disposed?
|
||||
# Cache the autotile graphic.
|
||||
@cache[key] = (filename == '') ? Bitmap.new(128, 96) : Bitmap.new(key)
|
||||
# Cache each configuration of this autotile.
|
||||
new_bm = self.format_autotiles(@cache[key], filename)
|
||||
@cache[key].dispose
|
||||
@cache[key] = new_bm
|
||||
end
|
||||
return @cache[key]
|
||||
end
|
||||
|
||||
def self.format_autotiles(bitmap, filename)
|
||||
if bitmap.height > 32
|
||||
frames = bitmap.width / 96
|
||||
template = Bitmap.new(256*frames,192)
|
||||
# Create a bitmap to use as a template for creation.
|
||||
(0..frames-1).each{|frame|
|
||||
(0...6).each {|i| (0...8).each {|j| AUTO_INDEX[8*i+j].each {|number|
|
||||
number -= 1
|
||||
x, y = 16 * (number % 6), 16 * (number / 6)
|
||||
rect = Rect.new(x + (frame * 96), y, 16, 16)
|
||||
template.blt((32 * j + x % 32) + (frame * 256), 32 * i + y % 32, bitmap, rect)
|
||||
}}}}
|
||||
return template
|
||||
else
|
||||
return bitmap
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** Tilemap_DataTable
|
||||
#===============================================================================
|
||||
class Tilemap_DataTable
|
||||
attr_accessor :updates
|
||||
attr_accessor :table
|
||||
def initialize(table)
|
||||
@table = table
|
||||
@updates = []
|
||||
end
|
||||
|
||||
def updated
|
||||
return @updates.size >= 1
|
||||
end
|
||||
|
||||
def [](x,y=nil,z=nil)
|
||||
return @table[x,y,z] unless z.nil?
|
||||
return @table[x,y] unless y.nil?
|
||||
return @table[x]
|
||||
end
|
||||
|
||||
def []=(x,y,z=nil,t_id=nil)
|
||||
@updates.push([x,y,z,t_id]) unless t_id.nil?
|
||||
t_id.nil? ? (z.nil? ? @table[x] = y : @table[x,y] = z) : @table[x,y,z] = t_id
|
||||
end
|
||||
|
||||
def xsize; return @table.xsize; end
|
||||
def ysize; return @table.ysize; end
|
||||
def zsize; return @table.zsize; end
|
||||
|
||||
def resize(x,y=nil,z=nil); @table.resize(x,y,z); end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** Tilemap
|
||||
#===============================================================================
|
||||
|
||||
class Tilemap
|
||||
|
||||
attr_reader :tileset, :map_data, :ox, :oy, :viewport
|
||||
attr_accessor :autotiles, :priorities
|
||||
|
||||
# +++ MKXP +++
|
||||
def tileset=(value)
|
||||
# Need to wrap tilesets that don't fit into texture
|
||||
if value.mega?
|
||||
@tileset = TileWrap::wrapTileset(value)
|
||||
value.dispose
|
||||
else
|
||||
@tileset = value
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(viewport)
|
||||
# Initialize instance variables to store required data.
|
||||
@viewport, @autotiles, @tile_sprites, @ox, @oy = viewport, [], [], 0, 0
|
||||
@current_frame, @total_frames = [], []
|
||||
@tilemap_drawn = false
|
||||
@ox_oy_set = [false, false]
|
||||
# Get priority data for this tileset from instance of Game_Map.
|
||||
@priorities = $game_map.priorities
|
||||
# Holds all the Sprite instances of animating tiles (keys based on tile's ID)
|
||||
@animating_tiles = {}
|
||||
# Game map's x/y location of the top left corner tile
|
||||
@corner_tile_loc = [-1,-1]
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Initialize all tile sprites. Draws three sprites per (x,y).
|
||||
#-----------------------------------------------------------------------------
|
||||
def init_tiles
|
||||
# Determine how many frames of animation this autotile has
|
||||
for i in 0..6
|
||||
bm = @autotiles[i]
|
||||
if bm.nil?
|
||||
@total_frames = 1
|
||||
elsif bm.height > 32
|
||||
@total_frames[i] = bm.width / 256
|
||||
else
|
||||
@total_frames[i] = bm.width / 32
|
||||
end
|
||||
@current_frame[i] = 0
|
||||
end
|
||||
# Turn on flag that the tilemap sprites have been initialized
|
||||
@tilemap_drawn = true
|
||||
|
||||
@animating_tiles.clear
|
||||
# Create a sprite and viewport to use for each priority level.
|
||||
(0...((SCREEN[0]/32+2) * (SCREEN[1]/32+2))*3).each{|i|
|
||||
@tile_sprites[i/3] = [] if @tile_sprites[i/3].nil?
|
||||
@tile_sprites[i/3][i%3] = Sprite.new(@viewport) unless @tile_sprites[i/3][i%3].is_a?(Sprite)
|
||||
# Rename to something shorter and easier to work with for below
|
||||
tile = @tile_sprites[i/3][i%3]
|
||||
# Assign tile's respective ID value
|
||||
tile.tile_sprite_id = i
|
||||
# Draw sprite at index location (ex. ID 0 should always be the top-left sprite)
|
||||
tile.x = (i % ((SCREEN[0]/32+2)*3) / 3 * 32) - 32 + (@ox % 32)
|
||||
tile.y = (i / ((SCREEN[0]/32+2)*3) * 32) - 32 + (@oy % 32)
|
||||
|
||||
map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
|
||||
@corner_tile_loc = [map_x, map_y] if i == 0
|
||||
# If the tile happens to be drawn along the outside borders of the map
|
||||
if map_x < 0 || map_x >= $game_map.width || map_y < 0 || map_y >= $game_map.height
|
||||
update_tile_id tile, 0
|
||||
else # Tile is actually on the map
|
||||
update_tile_id tile, @map_data[map_x, map_y, i%3]
|
||||
end
|
||||
}
|
||||
# Sprite ID located at top left corner (ranges from 0..map_width * map_height
|
||||
@corner_index = 0
|
||||
end
|
||||
|
||||
# Common code for setting the tile by id
|
||||
def update_tile_id(tile, tile_id)
|
||||
if tile_id == 0 # empty tile
|
||||
tile.z = 0
|
||||
tile.bitmap = RPG::Cache.picture('')#@tileset
|
||||
tile.src_rect.set(0,0,0,0)
|
||||
return
|
||||
end
|
||||
if @priorities[tile_id] == 0
|
||||
tile.z = 0
|
||||
else
|
||||
tile.z = tile.y + @priorities[tile_id] * 32 + 32
|
||||
end
|
||||
if tile_id >= 384 # non-autotile
|
||||
tile.bitmap = @tileset
|
||||
tile.src_rect.set(((tile_id - 384) % 8) * 32,
|
||||
((tile_id - 384) / 8) * 32,
|
||||
32, 32)
|
||||
# Fix rect for possibly wrapped tileset
|
||||
TileWrap.wrapRect! tile.src_rect
|
||||
else # autotile
|
||||
auto_id = tile_id/48-1
|
||||
tile.bitmap = @autotiles[auto_id]
|
||||
tile.src_rect.set(((tile_id % 48) % 8) * 32 + @current_frame[auto_id] * 256,
|
||||
((tile_id % 48) / 8) * 32,
|
||||
32, 32)
|
||||
@animating_tiles[tile.tile_sprite_id] = tile if @total_frames[auto_id] > 1
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Makes update to ox and oy. Sprites out of range will be moved based on these
|
||||
# two values.
|
||||
#-----------------------------------------------------------------------------
|
||||
def ox=(ox)
|
||||
#
|
||||
unless @tilemap_drawn
|
||||
@ox = ox
|
||||
@ox_oy_set[0] = true
|
||||
return
|
||||
end
|
||||
|
||||
return if @ox == ox
|
||||
# Shift all tiles left or right by the difference
|
||||
shift = @ox - ox
|
||||
|
||||
@tile_sprites.each {|set| set.each{|tile| tile.x += shift }}
|
||||
@ox = ox
|
||||
# Determine if columns need to be shifted
|
||||
col_num = @corner_index
|
||||
#return unless @tile_sprites[col_num][0].x <= -49 || @tile_sprites[col_num][0].x >= -17
|
||||
while @tile_sprites[col_num][0].x <= -49 || @tile_sprites[col_num][0].x >= -17
|
||||
|
||||
@corner_tile_loc[0] += (shift < 0 ? 1 : -1)
|
||||
modTileId = ((SCREEN[0]+64)*(SCREEN[1]+64))/1024
|
||||
# If new ox is greater than old ox
|
||||
if shift < 0
|
||||
# Move all sprites in left column to the right side and change bitmaps
|
||||
# and z-values
|
||||
(0...(SCREEN[1]/32+2)).each{|n|
|
||||
j = ((SCREEN[0]/32+2) * n + col_num) % modTileId
|
||||
@tile_sprites[j].each_index{|i|
|
||||
tile = @tile_sprites[j][i]
|
||||
@animating_tiles.delete(tile.tile_sprite_id)
|
||||
tile.x += 64 + SCREEN[0]
|
||||
|
||||
map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
|
||||
tile_id = @map_data[map_x,map_y,i]
|
||||
|
||||
if tile_id.nil?
|
||||
tile.z = [map_y * 32, 0].max
|
||||
tile.bitmap = RPG::Cache.picture('')
|
||||
tile.src_rect.set(0,0,0,0)
|
||||
next
|
||||
end
|
||||
|
||||
update_tile_id tile, tile_id
|
||||
}
|
||||
}
|
||||
# New corner should be the tile immediately right of the previous tile
|
||||
col_num /= SCREEN[0]/32+2
|
||||
col_num *= SCREEN[0]/32+2
|
||||
@corner_index = (@corner_index + 1) % (SCREEN[0]/32+2) + col_num
|
||||
else
|
||||
# Shift right column to the left
|
||||
# Gets the right column
|
||||
row_index = col_num / (SCREEN[0]/32+2)
|
||||
row_index *= (SCREEN[0]/32+2)
|
||||
col_num = (@corner_index - 1) % (SCREEN[0]/32+2) + row_index
|
||||
|
||||
(0...(SCREEN[1]/32+2)).each{|n|
|
||||
j = ((SCREEN[0]/32+2) * n + col_num) % modTileId
|
||||
@tile_sprites[j].each_index{|i|
|
||||
tile = @tile_sprites[j][i]
|
||||
@animating_tiles.delete(tile.tile_sprite_id)
|
||||
tile.x -= 64 + SCREEN[0]
|
||||
|
||||
map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
|
||||
tile_id = @map_data[map_x,map_y,i]
|
||||
if tile_id.nil?
|
||||
tile.z = [map_y * 32, 0].max
|
||||
tile.bitmap = @tileset
|
||||
tile.src_rect.set(0,0,0,0)
|
||||
next
|
||||
end
|
||||
|
||||
update_tile_id tile, tile_id
|
||||
}
|
||||
}
|
||||
col_num /= SCREEN[0]/32+2
|
||||
col_num *= SCREEN[0]/32+2
|
||||
@corner_index = (@corner_index - 1) % (SCREEN[0]/32+2) + col_num
|
||||
end
|
||||
col_num = @corner_index
|
||||
end #end of while
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def oy=(oy)
|
||||
#
|
||||
unless @tilemap_drawn
|
||||
@oy = oy
|
||||
@ox_oy_set[1] = true
|
||||
return
|
||||
end
|
||||
|
||||
return if @oy == oy
|
||||
# Shift all tiles up or down by the difference, and change z-value
|
||||
shift = @oy - oy
|
||||
|
||||
@tile_sprites.each {|set| set.each{|tile| tile.y += shift; tile.z += shift unless tile.z == 0 }}
|
||||
@oy = oy
|
||||
# Determine if rows need to be shifted
|
||||
row_num = @corner_index
|
||||
#return unless @tile_sprites[row_num][0].y <= -49 || @tile_sprites[row_num][0].y >= -17
|
||||
while @tile_sprites[row_num][0].y <= -49 || @tile_sprites[row_num][0].y >= -17
|
||||
|
||||
|
||||
# Needed for resetting the new corner index much later.
|
||||
modTileId = ((SCREEN[0]+64)*(SCREEN[1]+64))/1024
|
||||
@corner_tile_loc[1] += (shift < 0 ? 1 : -1)
|
||||
# If new oy is greater than old oy
|
||||
if shift < 0
|
||||
row_num /= SCREEN[0]/32+2
|
||||
row_num *= SCREEN[0]/32+2
|
||||
# Move all sprites in top row to the bottom side and change bitmaps
|
||||
# and z-values
|
||||
(0...(SCREEN[0]/32+2)).each{|n|
|
||||
# Run through each triad of sprites from left to right
|
||||
j = n + row_num
|
||||
@tile_sprites[j].each_index{|i|
|
||||
# Get each individual tile on each layer
|
||||
tile = @tile_sprites[j][i]
|
||||
@animating_tiles.delete(tile.tile_sprite_id)
|
||||
tile.y += 64 + SCREEN[1]
|
||||
# Determine what map coordinate this tile now resides at...
|
||||
map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
|
||||
# ...and get its tile_id
|
||||
tile_id = @map_data[map_x,map_y,i]
|
||||
# If no tile exists here (effectively out of array bounds)
|
||||
if tile_id.nil?
|
||||
tile.z = [map_y * 32, 0].max
|
||||
tile.bitmap = RPG::Cache.picture('')
|
||||
tile.src_rect.set(0,0,0,0)
|
||||
next
|
||||
end
|
||||
|
||||
update_tile_id tile, tile_id
|
||||
}
|
||||
}
|
||||
|
||||
@corner_index = (@corner_index + (SCREEN[0]/32+2)) % modTileId
|
||||
else
|
||||
row_num = (@corner_index - (SCREEN[0]/32+2)) % modTileId
|
||||
row_num /= SCREEN[0]/32+2
|
||||
row_num *= SCREEN[0]/32+2
|
||||
(0...(SCREEN[0]/32+2)).each{|n|
|
||||
# Run through each triad of sprites from left to right
|
||||
j = n + row_num
|
||||
@tile_sprites[j].each_index{|i|
|
||||
# Get each individual tile on each layer
|
||||
tile = @tile_sprites[j][i]
|
||||
@animating_tiles.delete(tile.tile_sprite_id)
|
||||
tile.y -= 64 + SCREEN[1]
|
||||
# Determine what map coordinate this tile now resides at...
|
||||
map_x, map_y = (tile.x+@ox)/32, (tile.y+@oy)/32
|
||||
# ...and get its tile_id
|
||||
tile_id = @map_data[map_x,map_y,i]
|
||||
# If no tile exists here (effectively out of array bounds)
|
||||
if tile_id.nil?
|
||||
tile.z = [map_y * 32, 0].max
|
||||
tile.bitmap = RPG::Cache.picture('')
|
||||
tile.src_rect.set(0,0,0,0)
|
||||
next
|
||||
end
|
||||
|
||||
update_tile_id tile, tile_id
|
||||
}
|
||||
}
|
||||
@corner_index = (@corner_index - (SCREEN[0]/32+2)) % modTileId
|
||||
end
|
||||
row_num = @corner_index
|
||||
end # end of while
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# Dispose all the tile sprites
|
||||
#-----------------------------------------------------------------------------
|
||||
def dispose
|
||||
# Dispose all of the sprites
|
||||
@tile_sprites.each {|set| set.each{|tile| tile.dispose }}
|
||||
@tile_sprites.clear
|
||||
@animating_tiles.clear
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# Set map data
|
||||
#-----------------------------------------------------------------------------
|
||||
def map_data=(data)
|
||||
# Set the map data to new class
|
||||
if data.is_a?(Tilemap_DataTable)
|
||||
@map_data = data
|
||||
else
|
||||
@map_data = Tilemap_DataTable.new(data)
|
||||
end
|
||||
@map_data.table = @map_data.table.clone
|
||||
@map_data.updates = []
|
||||
|
||||
@animating_tiles.clear
|
||||
@tilemap_drawn = false
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# Update the tile sprites; make changes to the map_data and update autotiles
|
||||
#-----------------------------------------------------------------------------
|
||||
def update
|
||||
# Can't update anything if the ox and oy have not yet been set
|
||||
return if @ox_oy_set != [true, true]
|
||||
# If the tilemap sprites have not been initialized, GO DO IT
|
||||
if !@tilemap_drawn
|
||||
init_tiles
|
||||
end
|
||||
|
||||
# If made any changes to $game_map.data, the proper graphics will be drawn
|
||||
if @map_data.updated
|
||||
@map_data.updates.each{|item|
|
||||
x,y,z,tile_id = item
|
||||
# If this changed tile is visible on screen
|
||||
if x.between?(@corner_tile_loc[0], @corner_tile_loc[0]+(SCREEN[0]/32 + 1)) and
|
||||
y.between?(@corner_tile_loc[1], @corner_tile_loc[1]+(SCREEN[1]/32 + 1))
|
||||
|
||||
x_dif = x - @corner_tile_loc[0]
|
||||
y_dif = y - @corner_tile_loc[1]
|
||||
|
||||
id = @corner_index + x_dif
|
||||
id -= SCREEN[0]/32+2 if id/(SCREEN[0]/32+2) > @corner_index/(SCREEN[0]/32+2)
|
||||
|
||||
id += y_dif * (SCREEN[0]/32+2)
|
||||
id -= (SCREEN[0]/32+2)*(SCREEN[1]/32+2) if id >= (SCREEN[0]/32+2)*(SCREEN[1]/32+2)
|
||||
|
||||
tile = @tile_sprites[id][z]
|
||||
@animating_tiles.delete(tile.tile_sprite_id)
|
||||
|
||||
update_tile_id tile, tile_id
|
||||
end
|
||||
}
|
||||
@map_data.updates = []
|
||||
end
|
||||
|
||||
# Update the sprites.
|
||||
if Graphics.frame_count % $game_map.autotile_speed == 0
|
||||
# Increase current frame of tile by one, looping by width.
|
||||
for i in 0..6
|
||||
@current_frame[i] = (@current_frame[i] + 1) % @total_frames[i]
|
||||
end
|
||||
@animating_tiles.each_value{|tile|
|
||||
frames = tile.bitmap.width
|
||||
tile.src_rect.set((tile.src_rect.x + 256) % frames, tile.src_rect.y, 32, 32)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Game_Map
|
||||
#===============================================================================
|
||||
|
||||
class Game_Map
|
||||
|
||||
attr_reader :tile_size, :autotile_speed, :autotile_data, :priority_data
|
||||
|
||||
alias zer0_load_autotile_data_init initialize
|
||||
def initialize
|
||||
# Call original method.
|
||||
zer0_load_autotile_data_init
|
||||
# Store the screen dimensions in tiles to save on calculations later.
|
||||
@tile_size = [SCREEN[0], SCREEN[1]].collect {|n| (n / 32.0).ceil }
|
||||
@autotile_speed = UPDATE_COUNT
|
||||
end
|
||||
|
||||
alias zer0_map_edge_setup setup
|
||||
def setup(map_id)
|
||||
# Call original method.
|
||||
zer0_map_edge_setup(map_id)
|
||||
# Change Map's data into a special Table class
|
||||
@map.data = Tilemap_DataTable.new(@map.data)
|
||||
# Find the displayed area of the map in tiles. No calcualting every step.
|
||||
@map_edge = [self.width - @tile_size[0], self.height - @tile_size[1]]
|
||||
@map_edge.collect! {|size| size * 128 }
|
||||
end
|
||||
|
||||
def scroll_down(distance)
|
||||
# Find point that the map edge meets the screen edge, using custom size.
|
||||
@display_y = [@display_y + distance, @map_edge[1]].min
|
||||
end
|
||||
|
||||
def scroll_right(distance)
|
||||
# Find point that the map edge meets the screen edge, using custom size.
|
||||
@display_x = [@display_x + distance, @map_edge[0]].min
|
||||
end
|
||||
|
||||
def autotile_speed=(speed)
|
||||
# Keep the speed above 0 to prevent the ZeroDivision Error.
|
||||
@autotile_speed = speed
|
||||
@autotile_speed = 1 if @autotile_speed < 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** Game_Player
|
||||
#===============================================================================
|
||||
|
||||
class Game_Player
|
||||
|
||||
CENTER_X = ((SCREEN[0] / 2) - 16) * 4 # Center screen x-coordinate * 4
|
||||
CENTER_Y = ((SCREEN[1] / 2) - 16) * 4 # Center screen y-coordinate * 4
|
||||
|
||||
def center(x, y)
|
||||
# Recalculate the screen center based on the new resolution.
|
||||
max_x = ($game_map.width - $game_map.tile_size[0]) * 128
|
||||
max_y = ($game_map.height - $game_map.tile_size[1]) * 128
|
||||
$game_map.display_x = [0, [x * 128 - CENTER_X, max_x].min].max
|
||||
$game_map.display_y = [0, [y * 128 - CENTER_Y, max_y].min].max
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** Sprite
|
||||
#===============================================================================
|
||||
class Sprite
|
||||
attr_accessor :tile_sprite_id
|
||||
alias tile_sprite_id_init initialize
|
||||
def initialize(view = nil)
|
||||
# No defined ID
|
||||
@tile_sprite_id = nil
|
||||
# Call original method.
|
||||
tile_sprite_id_init(view)
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** Viewport
|
||||
#===============================================================================
|
||||
class Viewport
|
||||
|
||||
alias zer0_viewport_resize_init initialize
|
||||
def initialize(x=0, y=0, width=SCREEN[0], height=SCREEN[1], override=false)
|
||||
if x.is_a?(Rect)
|
||||
# If first argument is a Rectangle, just use it as the argument.
|
||||
zer0_viewport_resize_init(x)
|
||||
elsif [x, y, width, height] == [0, 0, 640, 480] && !override
|
||||
# Resize fullscreen viewport, unless explicitly overridden.
|
||||
zer0_viewport_resize_init(Rect.new(0, 0, SCREEN[0], SCREEN[1]))
|
||||
else
|
||||
# Call method normally.
|
||||
zer0_viewport_resize_init(Rect.new(x, y, width, height))
|
||||
end
|
||||
end
|
||||
|
||||
def resize(*args)
|
||||
# Resize the viewport. Can call with (X, Y, WIDTH, HEIGHT) or (RECT).
|
||||
self.rect = args[0].is_a?(Rect) ? args[0] : Rect.new(*args)
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** Plane
|
||||
#===============================================================================
|
||||
|
||||
# class Plane < Sprite
|
||||
|
||||
# def z=(z)
|
||||
# # Change the Z value of the viewport, not the sprite.
|
||||
# super(z * 1000)
|
||||
# end
|
||||
|
||||
# def ox=(ox)
|
||||
# return if @bitmap == nil
|
||||
# # Have viewport stay in loop on X-axis.
|
||||
# super(ox % @bitmap.width)
|
||||
# end
|
||||
|
||||
# def oy=(oy)
|
||||
# return if @bitmap == nil
|
||||
# # Have viewport stay in loop on Y-axis.
|
||||
# super(oy % @bitmap.height)
|
||||
# end
|
||||
|
||||
# def bitmap
|
||||
# # Return the single bitmap, before it was tiled.
|
||||
# return @bitmap
|
||||
# end
|
||||
|
||||
# def bitmap=(tile)
|
||||
# @bitmap = tile
|
||||
# # Calculate the number of tiles it takes to span screen in both directions.
|
||||
# xx = 1 + (SCREEN[0].to_f / tile.width).ceil
|
||||
# yy = 1 + (SCREEN[1].to_f / tile.height).ceil
|
||||
# # Create appropriately sized bitmap, then tile across it with source image.
|
||||
# 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)
|
||||
# }}
|
||||
# # Set the bitmap to the sprite through its super class (Sprite).
|
||||
# super(plane)
|
||||
# end
|
||||
|
||||
# # Redefine methods dealing with coordinates (defined in super) to do nothing.
|
||||
# def x; end
|
||||
# def y; end
|
||||
# def x=(x); end
|
||||
# def y=(y); end
|
||||
# end
|
||||
#===============================================================================
|
||||
# ** Integer
|
||||
#===============================================================================
|
||||
|
||||
class Integer
|
||||
|
||||
def gcd(num)
|
||||
# Returns the greatest common denominator of self and num.
|
||||
min, max = self.abs, num.abs
|
||||
while min > 0
|
||||
tmp = min
|
||||
min = max % min
|
||||
max = tmp
|
||||
end
|
||||
return max
|
||||
end
|
||||
|
||||
def lcm(num)
|
||||
# Returns the lowest common multiple of self and num.
|
||||
return [self, num].include?(0) ? 0 : (self / self.gcd(num) * num).abs
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# ** Resolution Log
|
||||
#===============================================================================
|
||||
if RESOLUTION_LOG
|
||||
undersize, mapinfo = [], load_data('Data/MapInfos.rxdata')
|
||||
# Create a text file and write the header.
|
||||
file = File.open('Resolution Log.txt', 'wb')
|
||||
file.write("[RESOLUTION LOG]\r\n\r\n")
|
||||
time = Time.now.strftime("%x at %I:%M:%S %p")
|
||||
file.write(" Logged on #{time}\r\n\r\n")
|
||||
lcm = SCREEN[0].lcm(SCREEN[1]).to_f
|
||||
aspect = [(lcm / SCREEN[1]), (lcm / SCREEN[0])].collect {|num| num.round }
|
||||
file.write("RESOLUTION:\r\n #{SCREEN[0].to_i} x #{SCREEN[1].to_i}\r\n")
|
||||
file.write("ASPECT RATIO:\r\n #{aspect[0]}:#{aspect[1]}\r\n")
|
||||
file.write("MINIMUM MAP SIZE:\r\n #{(SCREEN[0] / 32).ceil} x #{(SCREEN[1] / 32).ceil}\r\n\r\n")
|
||||
file.write("UNDERSIZED MAPS:\r\n")
|
||||
mapinfo.keys.each {|key|
|
||||
map = load_data(sprintf("Data/Map%03d.rxdata", key))
|
||||
next if map.width*32 >= SCREEN[0] && map.height*32 >= SCREEN[1]
|
||||
undersize.push(key)
|
||||
}
|
||||
unless undersize.empty?
|
||||
file.write("The following maps are too small for the defined resolution. They should be adjusted to prevent graphical errors.\r\n\r\n")
|
||||
undersize.sort.each {|id| file.write(" MAP[#{id}]: #{mapinfo[id].name}\r\n") }
|
||||
file.write("\r\n")
|
||||
else
|
||||
file.write(' All maps are sized correctly.')
|
||||
end
|
||||
file.close
|
||||
end
|
||||
|
||||
# Call the resolution, setting it to a global variable for plug-ins.
|
||||
$resolution = Resolution.new
|
61
Kawariki-patches/ports/Zeus_Fullscreen++.rb
Normal file
61
Kawariki-patches/ports/Zeus_Fullscreen++.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
# Zeus81 Fullscreen++ MKXP API Shim
|
||||
# Authors: Taeyeon Mori
|
||||
|
||||
Preload.require 'PreloadIni.rb'
|
||||
|
||||
# Fullscreen++ v2.2 for VX and VXace by Zeus81
|
||||
# Free for non commercial and commercial use
|
||||
# Licence : http://creativecommons.org/licenses/by-sa/3.0/
|
||||
# Contact : zeusex81@gmail.com
|
||||
# (fr) Manuel d'utilisation : http://pastebin.com/raw.php?i=1TQfMnVJ
|
||||
# (en) User Guide : http://pastebin.com/raw.php?i=EgnWt9ur
|
||||
|
||||
$imported ||= {}
|
||||
$imported[:Zeus_Fullscreen] = __FILE__
|
||||
|
||||
class << Graphics
|
||||
Disable_VX_Fullscreen = true
|
||||
|
||||
unless method_defined?(:zeus_fullscreen_update)
|
||||
alias zeus_fullscreen_update update
|
||||
end
|
||||
|
||||
def load_fullscreen_settings
|
||||
fullscreen = (Preload::Ini.readIniString('./Game.ini', 'Fullscreen++', 'Fullscreen') || '0') == '1'
|
||||
end
|
||||
def save_fullscreen_settings
|
||||
Preload::Ini.writeIniString('./Game.ini', 'Fullscreen++', 'Fullscreen', fullscreen ? '1' : '0')
|
||||
end
|
||||
|
||||
def fullscreen?
|
||||
fullscreen
|
||||
end
|
||||
def vx_fullscreen?
|
||||
false
|
||||
end
|
||||
def toggle_fullscreen
|
||||
fullscreen = !fullscreen
|
||||
end
|
||||
def toggle_vx_fullscreen
|
||||
end
|
||||
def vx_fullscreen_mode
|
||||
end
|
||||
def fullscreen_mode
|
||||
fullscreen = true
|
||||
end
|
||||
def windowed_mode
|
||||
fullscreen = false
|
||||
end
|
||||
def toggle_ratio
|
||||
end
|
||||
def ratio
|
||||
1
|
||||
end
|
||||
def ratio=(r)
|
||||
end
|
||||
def update
|
||||
zeus_fullscreen_update
|
||||
toggle_fullscreen if Input.trigger?(Input::F5)
|
||||
end
|
||||
end
|
||||
Graphics.load_fullscreen_settings
|
530
Kawariki-patches/ports/Zeus_Map_Effects.rb
Normal file
530
Kawariki-patches/ports/Zeus_Map_Effects.rb
Normal file
|
@ -0,0 +1,530 @@
|
|||
# Map Effects v1.4.1 for VX and VXace by Zeus81
|
||||
# €30 for commercial use
|
||||
# Licence : http://creativecommons.org/licenses/by-nc-nd/4.0/
|
||||
# Contact : zeusex81@gmail.com
|
||||
# (fr) Manuel d'utilisation : https://www.dropbox.com/s/lb1d3q9jmx53taf/Map%20Effects%20Doc%20Fr.txt
|
||||
# (en) User Guide : https://www.dropbox.com/s/sk3uwq2bleoxr7s/Map%20Effects%20Doc%20En.txt
|
||||
# Demo : https://www.dropbox.com/s/2ex6906dyehl7an/Map%20Effects.zip
|
||||
|
||||
$imported ||= {}
|
||||
$imported[:Zeus_Map_Effects] = __FILE__
|
||||
|
||||
def xp?() false end ; def vx?() false end ; def vxace?() false end
|
||||
RUBY_VERSION == '1.8.1' ? defined?(Hangup) ?
|
||||
def xp?() true end : def vx?() true end : def vxace?() true end
|
||||
|
||||
class << Graphics
|
||||
def snap_elements_to_bitmap(*elements)
|
||||
if !@snap_elements_back or @snap_elements_back.disposed?
|
||||
@snap_elements_back = Sprite.new
|
||||
@snap_elements_back.bitmap = Bitmap.new(1, 1)
|
||||
@snap_elements_back.bitmap.set_pixel(0, 0, Color.new(0, 0, 0))
|
||||
@snap_elements_back.z = 0x0FFF_FFFF
|
||||
end
|
||||
@snap_elements_back.zoom_x = width
|
||||
@snap_elements_back.zoom_y = height
|
||||
@snap_elements_back.visible = true
|
||||
elements.each {|element| element.z += 0x1FFF_FFFF}
|
||||
bmp = snap_to_bitmap rescue retry
|
||||
@snap_elements_back.visible = false
|
||||
elements.each {|element| element.z -= 0x1FFF_FFFF}
|
||||
return bmp
|
||||
end
|
||||
end
|
||||
|
||||
module Math
|
||||
module_function
|
||||
def min(x, y) x < y ? x : y end
|
||||
def max(x, y) x < y ? y : x end
|
||||
def middle(min, x, max) x < max ? x < min ? min : x : max end
|
||||
end
|
||||
|
||||
module Zeus
|
||||
module Animation
|
||||
def animate(variable, target_value, duration=0, ext=nil)
|
||||
@za_animations ||= {}
|
||||
base_value = Marshal.load(Marshal.dump(instance_variable_get(variable)))
|
||||
if duration < 1
|
||||
update_animation_value(variable, base_value, target_value, 1, 1, ext)
|
||||
@za_animations.delete(variable)
|
||||
else
|
||||
@za_animations[variable] = [base_value, target_value, 0, duration.to_i, ext]
|
||||
end
|
||||
end
|
||||
def animating?
|
||||
@za_animations and !@za_animations.empty?
|
||||
end
|
||||
def clear_animations
|
||||
@za_animations and @za_animations.clear
|
||||
end
|
||||
def memorize_animations(variables = instance_variables)
|
||||
data = {}
|
||||
variables.each {|var| data[var.to_sym] = instance_variable_get(var)}
|
||||
data.delete(:@za_memorize)
|
||||
@za_memorize = Marshal.dump(data)
|
||||
end
|
||||
def restore_animations
|
||||
return unless @za_memorize
|
||||
Marshal.load(@za_memorize).each {|var,value| instance_variable_set(var,value)}
|
||||
end
|
||||
def update_animations
|
||||
return unless @za_animations
|
||||
@za_animations.delete_if do |variable, data|
|
||||
data[2] += 1
|
||||
update_animation_value(variable, *data)
|
||||
data[2] == data[3]
|
||||
end
|
||||
end
|
||||
private
|
||||
def calculate_next_value(base_value, target_value, duration, duration_total)
|
||||
base_value + (target_value - base_value) * duration / duration_total
|
||||
end
|
||||
def update_animation_value(variable, base_value, target_value, duration, duration_total, ext)
|
||||
method_name = "update_animation_variable_#{variable.to_s[1..-1]}"
|
||||
method_name = "update_animation_#{base_value.class}" unless respond_to?(method_name)
|
||||
send(method_name, variable, base_value, target_value, duration, duration_total, ext)
|
||||
end
|
||||
def update_animation_Color(variable, base_value, target_value, duration, duration_total, ext)
|
||||
value = instance_variable_get(variable)
|
||||
value.red = calculate_next_value(base_value.red , target_value.red , duration, duration_total)
|
||||
value.green = calculate_next_value(base_value.green, target_value.green, duration, duration_total)
|
||||
value.blue = calculate_next_value(base_value.blue , target_value.blue , duration, duration_total)
|
||||
value.alpha = calculate_next_value(base_value.alpha, target_value.alpha, duration, duration_total)
|
||||
end
|
||||
def update_animation_Tone(variable, base_value, target_value, duration, duration_total, ext)
|
||||
value = instance_variable_get(variable)
|
||||
value.red = calculate_next_value(base_value.red , target_value.red , duration, duration_total)
|
||||
value.green = calculate_next_value(base_value.green, target_value.green, duration, duration_total)
|
||||
value.blue = calculate_next_value(base_value.blue , target_value.blue , duration, duration_total)
|
||||
value.gray = calculate_next_value(base_value.gray , target_value.gray , duration, duration_total)
|
||||
end
|
||||
def update_animation_Float(variable, base_value, target_value, duration, duration_total, ext)
|
||||
value = calculate_next_value(base_value, target_value, duration, duration_total)
|
||||
instance_variable_set(variable, value)
|
||||
end
|
||||
alias update_animation_Fixnum update_animation_Float
|
||||
alias update_animation_Bignum update_animation_Float
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Map_Effects
|
||||
include Zeus::Animation
|
||||
attr_accessor :active, :refresh_rate, :back, :x, :y, :ox, :oy, :angle,
|
||||
:zoom_x, :zoom_y, :mirror, :opacity, :blend_type, :color, :tone,
|
||||
:hue, :wave_amp, :wave_length, :wave_speed, :wave_phase,
|
||||
:pixelize, :blur_division, :blur_fade, :blur_animation,
|
||||
:gaussian_blur_length, :linear_blur_angle, :linear_blur_length,
|
||||
:radial_blur_angle, :zoom_blur_length, :motion_blur_rate
|
||||
def initialize
|
||||
@active = true
|
||||
@refresh_rate = 30.0
|
||||
clear
|
||||
end
|
||||
def clear
|
||||
@back = false
|
||||
@x = @ox = Graphics.width / 2
|
||||
@y = @oy = Graphics.height / 2
|
||||
@zoom_x = 1.0
|
||||
@zoom_y = 1.0
|
||||
@zoom2 = Math.sqrt(100.0)
|
||||
@angle = 0.0
|
||||
@wave_amp = 0.0
|
||||
@wave_length = 180
|
||||
@wave_speed = 360
|
||||
@wave_phase = 0.0
|
||||
@mirror = false
|
||||
@opacity = 255
|
||||
@blend_type = 0
|
||||
@color ||= Color.new(0, 0, 0, 0)
|
||||
@color.set(0, 0, 0, 0)
|
||||
@tone ||= Tone.new(0, 0, 0, 0)
|
||||
@tone.set(0, 0, 0, 0)
|
||||
@hue = 0
|
||||
@pixelize = 1.0
|
||||
@pixelize2 = Math.sqrt(100.0)
|
||||
@blur_division = 4.0
|
||||
@blur_fade = 1.0
|
||||
@blur_animation = 0.0
|
||||
@gaussian_blur_length = 0.0
|
||||
@linear_blur_angle = 0.0
|
||||
@linear_blur_length = 0.0
|
||||
@radial_blur_angle = 0.0
|
||||
@zoom_blur_length = 0.0
|
||||
@motion_blur_rate = 0.0
|
||||
clear_animations
|
||||
end
|
||||
alias memorize memorize_animations
|
||||
alias restore restore_animations
|
||||
alias update update_animations
|
||||
def active?
|
||||
return false unless @active
|
||||
animating? or blur? or @mirror or @blend_type != 0 or
|
||||
@zoom_x != 1 or @zoom_y != 1 or @pixelize > 1 or
|
||||
@angle % 360 != 0 or @hue.to_i % 360 != 0 or @color.alpha != 0 or
|
||||
@tone.red != 0 or @tone.green != 0 or @tone.blue != 0 or @tone.gray != 0 or
|
||||
(@wave_amp * @zoom_x >= 1 and @wave_length * @zoom_y >= 1)
|
||||
end
|
||||
def blur?
|
||||
return false if @blur_division < 1
|
||||
@gaussian_blur_length != 0 or @linear_blur_length != 0 or
|
||||
@radial_blur_angle != 0 or @zoom_blur_length != 0 or @motion_blur_rate != 0
|
||||
end
|
||||
def refresh_bitmap?
|
||||
@refresh_rate > 0 and
|
||||
Graphics.frame_count % (Graphics.frame_rate / @refresh_rate.to_f) < 1
|
||||
end
|
||||
def tilemap_wave_sync(tilemap_oy)
|
||||
return 0 if @wave_length == 0
|
||||
tilemap_oy * @wave_speed / @wave_length.to_f
|
||||
end
|
||||
def blur_animation_offset
|
||||
return 0 if @blur_animation == 0
|
||||
1 - @blur_animation * Graphics.frame_count / Graphics.frame_rate.to_f % 1
|
||||
end
|
||||
def refresh_motion_blur?
|
||||
@blur_division >= 1 and @motion_blur_rate > 0 and
|
||||
Graphics.frame_count % @motion_blur_rate < 1
|
||||
end
|
||||
def set_origin(x, y, duration=0)
|
||||
x = x * Graphics.width / 100
|
||||
y = y * Graphics.height / 100
|
||||
animate(:@x , x, duration)
|
||||
animate(:@y , y, duration)
|
||||
animate(:@ox, x, duration)
|
||||
animate(:@oy, y, duration)
|
||||
end
|
||||
def set_zoom(zoom, duration=0, center_on_player=true)
|
||||
zoom = Math.sqrt(Math.max(1, zoom))
|
||||
animate(:@zoom2, zoom, duration, center_on_player)
|
||||
end
|
||||
def update_animation_variable_zoom2(variable, base_value, target_value, duration, duration_total, center_on_player)
|
||||
update_animation_Float(variable, base_value, target_value, duration, duration_total, nil)
|
||||
@zoom_y = @zoom_x = @zoom2 ** 2 / 100.0
|
||||
display_ratio = Game_Map::DisplayRatio.to_f
|
||||
if center_on_player
|
||||
x = $game_player.real_x / display_ratio
|
||||
y = $game_player.real_y / display_ratio
|
||||
else
|
||||
x = $game_map.display_x / display_ratio + $game_map.screen_tile_x / 2
|
||||
y = $game_map.display_y / display_ratio + $game_map.screen_tile_y / 2
|
||||
end
|
||||
$game_player.center(x, y)
|
||||
end
|
||||
def set_angle(angle, duration=0)
|
||||
animate(:@angle, angle, duration)
|
||||
end
|
||||
def set_opacity(opacity, duration=0)
|
||||
opacity = opacity * 255 / 100
|
||||
animate(:@opacity, opacity, duration)
|
||||
end
|
||||
def set_color(red, green, blue, alpha, duration=0)
|
||||
animate(:@color, Color.new(red, green, blue, alpha), duration)
|
||||
end
|
||||
def set_tone(red, green, blue, gray, duration=0)
|
||||
animate(:@tone, Tone.new(red, green, blue, gray), duration)
|
||||
end
|
||||
def set_hue(hue, duration=0)
|
||||
animate(:@hue, hue, duration)
|
||||
end
|
||||
def set_wave(amp, length, speed, duration=0)
|
||||
animate(:@wave_amp , amp , duration)
|
||||
animate(:@wave_length, length, duration)
|
||||
animate(:@wave_speed , speed , duration)
|
||||
end
|
||||
def set_pixelize(pixelize, duration=0)
|
||||
pixelize = Math.sqrt(Math.max(100, pixelize))
|
||||
animate(:@pixelize2, pixelize, duration)
|
||||
end
|
||||
def update_animation_variable_pixelize2(variable, base_value, target_value, duration, duration_total, ext)
|
||||
update_animation_Float(variable, base_value, target_value, duration, duration_total, ext)
|
||||
@pixelize = @pixelize2 ** 2 / 100.0
|
||||
end
|
||||
def setup_blur(division, fade, animation, duration=0)
|
||||
division = Math.middle(0, division, 16)
|
||||
animate(:@blur_division , division , duration)
|
||||
animate(:@blur_fade , fade , duration)
|
||||
animate(:@blur_animation, animation, duration)
|
||||
end
|
||||
def set_gaussian_blur(length, duration=0)
|
||||
animate(:@gaussian_blur_length, length, duration)
|
||||
end
|
||||
def set_linear_blur(angle, length, duration=0)
|
||||
animate(:@linear_blur_angle , angle , duration)
|
||||
animate(:@linear_blur_length, length, duration)
|
||||
end
|
||||
def set_radial_blur(angle, duration=0)
|
||||
animate(:@radial_blur_angle, angle, duration)
|
||||
end
|
||||
def set_zoom_blur(zoom, duration=0)
|
||||
length = Math.max(1, zoom) / 100.0 - 1
|
||||
animate(:@zoom_blur_length, length, duration)
|
||||
end
|
||||
def set_motion_blur(rate, duration=0)
|
||||
animate(:@motion_blur_rate, rate, duration)
|
||||
end
|
||||
end
|
||||
|
||||
class Spriteset_Map_Effects
|
||||
Blur_Offset = [[0.7,0.7], [-0.7,-0.7], [-0.7,0.7], [0.7,-0.7],
|
||||
[0,1], [0,-1], [1,0], [-1,0]]
|
||||
def initialize(*viewports)
|
||||
@map_viewports = viewports
|
||||
@viewport = Viewport.new(viewports[0].rect)
|
||||
@viewport.z = viewports[0].z
|
||||
@viewport.visible = false
|
||||
@effects_sprites = []
|
||||
@effects_bitmaps = []
|
||||
@data = $game_map.effects
|
||||
end
|
||||
def dispose(dispose_viewport=true)
|
||||
@effects_sprites.each {|sprite| sprite.dispose}
|
||||
@effects_sprites.clear
|
||||
@effects_bitmaps.each {|bitmap| bitmap.dispose if bitmap}
|
||||
@effects_bitmaps.clear
|
||||
@pixelize_bitmap.dispose if @pixelize_bitmap
|
||||
@pixelize_bitmap = nil
|
||||
@back_sprite.dispose if @back_sprite
|
||||
@back_sprite = nil
|
||||
if dispose_viewport
|
||||
@viewport.dispose
|
||||
else
|
||||
@viewport.visible = false
|
||||
@map_viewports.each {|viewport| viewport.visible = true}
|
||||
end
|
||||
end
|
||||
def update(tilemap_oy = 0)
|
||||
unless @data.active?
|
||||
dispose(false) if @viewport.visible
|
||||
return
|
||||
end
|
||||
@viewport.visible = true
|
||||
@motion_blur_refresh ||= @data.refresh_motion_blur?
|
||||
refresh_sprites
|
||||
if !@effects_bitmaps[0] or @data.refresh_bitmap?
|
||||
refresh_bitmaps
|
||||
refresh_pixelize
|
||||
end
|
||||
refresh_back
|
||||
wave_sync = @data.tilemap_wave_sync(tilemap_oy)
|
||||
blur_offset = @data.blur_animation_offset
|
||||
@effects_sprites.each_with_index do |sprite, id|
|
||||
update_effects(sprite, id, wave_sync)
|
||||
update_pixelize(sprite) if @pixelize_bitmap
|
||||
update_blur(sprite, id, blur_offset) if id > 0
|
||||
end
|
||||
@data.wave_phase = @effects_sprites[0].wave_phase - wave_sync
|
||||
end
|
||||
def refresh_sprites
|
||||
n = (@data.blur? ? @data.blur_division.to_i+1 : 1) - @effects_sprites.size
|
||||
n.times {@effects_sprites << Sprite.new(@viewport)}
|
||||
(-n).times {@effects_sprites.pop.dispose}
|
||||
end
|
||||
def refresh_bitmaps
|
||||
n = (@data.motion_blur_rate == 0 ? 1 : @effects_sprites.size) - @effects_bitmaps.size
|
||||
n.times {@effects_bitmaps << nil}
|
||||
(-n).times {bmp = @effects_bitmaps.pop and bmp.dispose}
|
||||
@map_viewports.each {|viewport| viewport.visible = true}
|
||||
@effects_bitmaps.unshift(@effects_bitmaps.pop) if @motion_blur_refresh
|
||||
@effects_bitmaps[0].dispose if @effects_bitmaps[0]
|
||||
@effects_bitmaps[0] = Graphics.snap_elements_to_bitmap(*@map_viewports)
|
||||
@effects_bitmaps[0].hue_change(@data.hue % 360) if @data.hue.to_i % 360 != 0
|
||||
@map_viewports.each {|viewport| viewport.visible = false}
|
||||
@motion_blur_refresh = false
|
||||
end
|
||||
def refresh_pixelize
|
||||
if @data.pixelize > 1
|
||||
bmp = @effects_bitmaps[0]
|
||||
@pixelize_rect ||= Rect.new(0, 0, 0, 0)
|
||||
@pixelize_rect.width = Math.max(1, bmp.width / @data.pixelize)
|
||||
@pixelize_rect.height = Math.max(1, bmp.height / @data.pixelize)
|
||||
@pixelize_bitmap ||= Bitmap.new(bmp.width, bmp.height)
|
||||
@pixelize_bitmap.clear
|
||||
@pixelize_bitmap.stretch_blt(@pixelize_rect, bmp, bmp.rect)
|
||||
elsif @pixelize_bitmap
|
||||
@pixelize_bitmap.dispose
|
||||
@pixelize_bitmap = nil
|
||||
end
|
||||
end
|
||||
def refresh_back
|
||||
if @data.back
|
||||
@back_sprite ||= Sprite.new(@viewport)
|
||||
@back_sprite.bitmap = @effects_bitmaps[0]
|
||||
elsif @back_sprite
|
||||
@back_sprite.dispose
|
||||
@back_sprite = nil
|
||||
end
|
||||
end
|
||||
def update_effects(sprite, id, wave_sync)
|
||||
sprite.bitmap = @effects_bitmaps[id] || @effects_bitmaps[0]
|
||||
sprite.x = @data.x
|
||||
sprite.y = @data.y
|
||||
sprite.z = id + 1
|
||||
sprite.ox = @data.ox
|
||||
sprite.oy = @data.oy
|
||||
sprite.zoom_x = @data.zoom_x
|
||||
sprite.zoom_y = @data.zoom_y
|
||||
sprite.angle = @data.angle % 360
|
||||
sprite.wave_amp = @data.wave_amp * @data.zoom_x
|
||||
sprite.wave_length = @data.wave_length * @data.zoom_y
|
||||
sprite.wave_speed = @data.wave_speed * @data.zoom_y
|
||||
sprite.wave_phase = @data.wave_phase + wave_sync
|
||||
sprite.mirror = @data.mirror
|
||||
sprite.opacity = @data.opacity
|
||||
sprite.blend_type = @data.blend_type
|
||||
sprite.color = @data.color
|
||||
sprite.tone = @data.tone
|
||||
sprite.update
|
||||
end
|
||||
def update_pixelize(sprite)
|
||||
pzx = @pixelize_bitmap.width / @pixelize_rect.width.to_f
|
||||
pzy = @pixelize_bitmap.height / @pixelize_rect.height.to_f
|
||||
sprite.bitmap = @pixelize_bitmap
|
||||
sprite.src_rect = @pixelize_rect
|
||||
sprite.x -= sprite.ox - (sprite.ox /= pzx).to_i * pzx
|
||||
sprite.y -= sprite.oy - (sprite.oy /= pzy).to_i * pzy
|
||||
sprite.zoom_x *= pzx
|
||||
sprite.zoom_y *= pzy
|
||||
end
|
||||
def update_blur(sprite, id, blur_offset)
|
||||
update_blur_opacity(sprite, id-blur_offset)
|
||||
update_gaussian_blur(sprite, id) if @data.gaussian_blur_length != 0
|
||||
update_linear_blur(sprite, id-blur_offset) if @data.linear_blur_length != 0
|
||||
update_radial_blur(sprite, id-blur_offset) if @data.radial_blur_angle != 0
|
||||
update_zoom_blur(sprite, id-blur_offset) if @data.zoom_blur_length != 0
|
||||
end
|
||||
def update_blur_opacity(sprite, id)
|
||||
sprite.opacity /= (id < 1 ? 2 : id+1) **
|
||||
(1 + @data.blur_fade / (@data.blur_division*20.0))
|
||||
end
|
||||
def update_gaussian_blur(sprite, id)
|
||||
box, boy = *Blur_Offset[(id-1)%8]
|
||||
offset = ((id+3)/4) / ((@data.blur_division.to_i+3)/4).to_f *
|
||||
@data.gaussian_blur_length
|
||||
sprite.x += (offset.ceil * box).round
|
||||
sprite.y += (offset.ceil * boy).round
|
||||
end
|
||||
def update_linear_blur(sprite, id)
|
||||
radian = @data.linear_blur_angle * Math::PI / 180
|
||||
offset = id * @data.linear_blur_length / @data.blur_division.to_f
|
||||
sprite.x += offset * Math.cos( radian)
|
||||
sprite.y += offset * Math.sin(-radian)
|
||||
end
|
||||
def update_zoom_blur(sprite, id)
|
||||
zoom = 1 + id * @data.zoom_blur_length / @data.blur_division.to_f
|
||||
sprite.zoom_x *= zoom
|
||||
sprite.zoom_y *= zoom
|
||||
end
|
||||
def update_radial_blur(sprite, id)
|
||||
sprite.angle += id * @data.radial_blur_angle / @data.blur_division.to_f
|
||||
sprite.angle %= 360
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Map
|
||||
if vx?
|
||||
def screen_tile_x() Graphics.width / 32 end
|
||||
def screen_tile_y() Graphics.height / 32 end
|
||||
DisplayRatio = 256
|
||||
else
|
||||
DisplayRatio = 1
|
||||
end
|
||||
def zoom_ox
|
||||
return 0 unless effects.active and effects.zoom_x > 1
|
||||
(1 - 1 / effects.zoom_x) * screen_tile_x / 2
|
||||
end
|
||||
def zoom_oy
|
||||
return 0 unless effects.active and effects.zoom_y > 1
|
||||
(1 - 1 / effects.zoom_y) * screen_tile_y / 2
|
||||
end
|
||||
def limit_x(x)
|
||||
ox = zoom_ox
|
||||
min = DisplayRatio * -ox
|
||||
max = DisplayRatio * (width - screen_tile_x + ox)
|
||||
x < max ? x < min ? min : x : max
|
||||
end
|
||||
def limit_y(y)
|
||||
oy = zoom_oy
|
||||
min = DisplayRatio * -oy
|
||||
max = DisplayRatio * (height - screen_tile_y + oy)
|
||||
y < max ? y < min ? min : y : max
|
||||
end
|
||||
def set_display_x(x)
|
||||
x = loop_horizontal? ? x % (width * DisplayRatio) : limit_x(x)
|
||||
@parallax_x += x - @display_x if @parallax_loop_x or !loop_horizontal?
|
||||
@display_x = x
|
||||
end
|
||||
def set_display_y(y)
|
||||
y = loop_vertical? ? y % (height * DisplayRatio) : limit_y(y)
|
||||
@parallax_y += y - @display_y if @parallax_loop_y or !loop_vertical?
|
||||
@display_y = y
|
||||
end
|
||||
def set_display_pos(x, y) set_display_x(x); set_display_y(y) end
|
||||
def scroll_down(distance) set_display_y(@display_y + distance) end
|
||||
def scroll_left(distance) set_display_x(@display_x - distance) end
|
||||
def scroll_right(distance) set_display_x(@display_x + distance) end
|
||||
def scroll_up(distance) set_display_y(@display_y - distance) end
|
||||
def effects() @effects ||= Game_Map_Effects.new end
|
||||
alias zeus_map_effects_update update
|
||||
def update(*args)
|
||||
zeus_map_effects_update(*args)
|
||||
effects.update
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Interpreter
|
||||
def map_effects
|
||||
$game_map.effects
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Player
|
||||
def center(x, y)
|
||||
$game_map.set_display_pos(x*256-CENTER_X, y*256-CENTER_Y)
|
||||
end
|
||||
end if vx?
|
||||
|
||||
class Spriteset_Map
|
||||
alias zeus_map_effects_update update
|
||||
def update
|
||||
zeus_map_effects_update
|
||||
@map_effects ||= Spriteset_Map_Effects.new(@viewport1)
|
||||
@map_effects.update(@tilemap.oy)
|
||||
end
|
||||
alias zeus_map_effects_dispose dispose
|
||||
def dispose
|
||||
zeus_map_effects_dispose
|
||||
@map_effects.dispose
|
||||
end
|
||||
end
|
||||
|
||||
$imported[:Zeus_Weather_Viewport] ||= __FILE__
|
||||
if $imported[:Zeus_Weather_Viewport] == __FILE__
|
||||
|
||||
class Spriteset_Map
|
||||
alias zeus_weather_viewport_create_weather create_weather
|
||||
def create_weather
|
||||
zeus_weather_viewport_create_weather
|
||||
@weather.weather_viewport = @viewport1
|
||||
end
|
||||
end
|
||||
|
||||
class Spriteset_Weather
|
||||
if vx?
|
||||
def weather_viewport=(viewport)
|
||||
for sprite in @sprites
|
||||
sprite.viewport = viewport
|
||||
sprite.z = 0x8000
|
||||
end
|
||||
end
|
||||
else
|
||||
attr_accessor :weather_viewport
|
||||
alias zeus_weather_viewport_add_sprite add_sprite
|
||||
def add_sprite
|
||||
zeus_weather_viewport_add_sprite
|
||||
@sprites[-1].viewport = @weather_viewport
|
||||
@sprites[-1].z = 0x8000
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
386
Kawariki-patches/ports/achievements.rb
Normal file
386
Kawariki-patches/ports/achievements.rb
Normal file
|
@ -0,0 +1,386 @@
|
|||
# [122] 29075340: achievements
|
||||
# cyanic's Quick and Easy Steamworks Achievements Integration for Ruby
|
||||
# https://github.com/GMMan/RGSS_SteamUserStatsLite
|
||||
# r4 06/16/16
|
||||
#
|
||||
# Drop steam_api.dll into the root of your project. Requires Steamworks SDK version >= 1.37.
|
||||
#
|
||||
# "Miller complained about how hard achievements were to implement in C++, so this was born."
|
||||
#
|
||||
|
||||
$imported ||= {}
|
||||
$imported['cyanic-SteamUserStatsLite'] = 4 # Slightly unorthodox, it's a version number.
|
||||
|
||||
# A context class to get Steamworks pointers to interfaces.
|
||||
#
|
||||
# @author cyanic
|
||||
class SteamAPIContext
|
||||
STEAMCLIENT_INTERFACE_VERSION = 'SteamClient017'
|
||||
STEAMUSERSTATS_INTERFACE_VERSION = 'STEAMUSERSTATS_INTERFACE_VERSION011'
|
||||
STEAMAPPS_INTERFACE_VERSION = 'STEAMAPPS_INTERFACE_VERSION008'
|
||||
|
||||
# Instantiates a new instance of +SteamAPIContext+.
|
||||
def initialize
|
||||
# @initted = false
|
||||
# @h_steam_user = # @@dll_SteamAPI_GetHSteamUser.call
|
||||
# if (@h_steam_pipe = # @@dll_SteamAPI_GetHSteamPipe.call) != 0
|
||||
# return if (@steam_client = # @@dll_SteamInternal_CreateInterface.call(STEAMCLIENT_INTERFACE_VERSION)) == 0
|
||||
# return if (@steam_user_stats = # @@dll_SteamAPI_ISteamClient_GetISteamUserStats.call(@steam_client, @h_steam_user, @h_steam_pipe, STEAMUSERSTATS_INTERFACE_VERSION)) == 0
|
||||
# return if (@steam_apps = # @@dll_SteamAPI_ISteamClient_GetISteamApps.call(@steam_client, @h_steam_user, @h_steam_pipe, STEAMAPPS_INTERFACE_VERSION)) == 0
|
||||
#
|
||||
# @initted = true
|
||||
# end
|
||||
end
|
||||
|
||||
# Checks if context is initialized.
|
||||
#
|
||||
# @return [true, false] Whether context is initialized.
|
||||
def initted?
|
||||
@initted
|
||||
end
|
||||
|
||||
# Gets the ISteamClient pointer
|
||||
#
|
||||
# @return [Fixnum, nil] The ISteamClient pointer if context is initialized, otherwise +nil+.
|
||||
def steam_client
|
||||
@steam_client if initted?
|
||||
end
|
||||
|
||||
# Gets the ISteamUserStats pointer
|
||||
#
|
||||
# @return [Fixnum, nil] The ISteamUserStats pointer if context is initialized, otherwise +nil+.
|
||||
def steam_user_stats
|
||||
@steam_user_stats if initted?
|
||||
end
|
||||
|
||||
# Gets the ISteamApps pointer
|
||||
#
|
||||
# @return [Fixnum, nil] The ISteamUserStats pointer if context is initialized, otherwise +nil+.
|
||||
def steam_apps
|
||||
@steam_apps if initted?
|
||||
end
|
||||
|
||||
private
|
||||
def self.is_64bit?
|
||||
# Probably very bad detection of whether current runtime is 64-bit
|
||||
(/x64/ =~ RUBY_PLATFORM) != nil
|
||||
end
|
||||
|
||||
def self.steam_dll_name
|
||||
# @@dll_name ||= self.is_64bit? ? 'steam_api64' : 'steam_api'
|
||||
end
|
||||
|
||||
# @@dll_SteamAPI_GetHSteamUser = Win32API.new(self.steam_dll_name, 'SteamAPI_GetHSteamUser', '', 'I')
|
||||
# @@dll_SteamAPI_GetHSteamPipe = Win32API.new(self.steam_dll_name, 'SteamAPI_GetHSteamPipe', '', 'I')
|
||||
# @@dll_SteamInternal_CreateInterface = Win32API.new(self.steam_dll_name, 'SteamInternal_CreateInterface', 'P', 'I')
|
||||
# @@dll_SteamAPI_ISteamClient_GetISteamUserStats = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamClient_GetISteamUserStats', 'IIIP', 'I')
|
||||
# @@dll_SteamAPI_ISteamClient_GetISteamApps = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamClient_GetISteamApps', 'IIIP', 'I')
|
||||
|
||||
end
|
||||
|
||||
# A simple class for Steamworks UserStats integration.
|
||||
#
|
||||
# @author cyanic
|
||||
class SteamUserStatsLite
|
||||
|
||||
# Instantiates a new instance of +SteamUserStatsLite+.
|
||||
def initialize
|
||||
@initted = false
|
||||
api_initted = # @@dll_SteamAPI_Init.call % 256 != 0
|
||||
if api_initted
|
||||
@context = SteamAPIContext.new
|
||||
if @context.initted?
|
||||
@i_apps = @context.steam_apps
|
||||
@i_user_stats = @context.steam_user_stats
|
||||
@initted = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Shuts down Steamworks.
|
||||
#
|
||||
# @return [void]
|
||||
def shutdown
|
||||
if @initted
|
||||
@i_apps = nil
|
||||
@i_user_stats = nil
|
||||
# @@dll_SteamAPI_Shutdown.call
|
||||
@initted = false
|
||||
end
|
||||
end
|
||||
|
||||
# Checks if Steamworks is initialized.
|
||||
#
|
||||
# @return [true, false] Whether Steamworks is initialized.
|
||||
def initted?
|
||||
@initted
|
||||
end
|
||||
|
||||
# Restarts the app if Steamworks is not availble.
|
||||
#
|
||||
# @param app_id [Integer] The app ID to relaunch as.
|
||||
# @return [true, false] +true+ if current instance should exit, +false+ if not.
|
||||
def self.restart_app_if_necessary(app_id)
|
||||
# @@dll_SteamAPI_RestartAppIfNecessary.call(app_id) % 256 != 0
|
||||
end
|
||||
|
||||
# Runs Steam callbacks.
|
||||
#
|
||||
# @return [void]
|
||||
def update
|
||||
# @@dll_SteamAPI_RunCallbacks.call if initted?
|
||||
end
|
||||
|
||||
# Checks if current app is owned.
|
||||
#
|
||||
# @return [true, false, nil] Whether the current user has a license for the current app. +nil+ is returned if ownership status can't be retrieved.
|
||||
def is_subscribed
|
||||
if initted?
|
||||
# @@dll_SteamAPI_ISteamApps_BIsSubscribed.call(@i_apps) % 256 != 0
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Checks if a DLC is installed.
|
||||
#
|
||||
# @param app_id [Integer] The app ID of the DLC to check.
|
||||
# @return [true, false, nil] Whether the DLC is installed. +nil+ is returned if the installation status can't be retrieved.
|
||||
def is_dlc_installed(app_id)
|
||||
if initted?
|
||||
# @@dll_SteamAPI_ISteamApps_BIsDlcInstalled.call(@i_apps, app_id) % 256 != 0
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Pulls current user's stats from Steam.
|
||||
#
|
||||
# @return [true, false] Whether the stats have been successfully pulled.
|
||||
def request_current_stats
|
||||
if initted?
|
||||
# @@dll_SteamAPI_ISteamUserStats_RequestCurrentStats.call(@i_user_stats) % 256 != 0
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the value of an INT stat.
|
||||
#
|
||||
# @param name [String] The name of the stat.
|
||||
# @return [Integer, nil] The value of the stat, or +nil+ if the stat cannot be retrieved.
|
||||
def get_stat_int(name)
|
||||
if initted?
|
||||
val = ' ' * 4
|
||||
ok = # @@dll_SteamAPI_ISteamUserStats_GetStat.call(@i_user_stats, name, val) % 256 != 0
|
||||
ok ? val.unpack('I')[0] : nil
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the value of an FLOAT stat.
|
||||
#
|
||||
# @param name [String] The name of the stat.
|
||||
# @return [Float, nil] The value of the stat, or +nil+ if the stat cannot be retrieved.
|
||||
def get_stat_float(name)
|
||||
if initted?
|
||||
val = ' ' * 4
|
||||
ok = # @@dll_SteamAPI_ISteamUserStats_GetStat0.call(@i_user_stats, name, val) % 256 != 0
|
||||
ok ? val.unpack('f')[0] : nil
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the value of a stat.
|
||||
#
|
||||
# @param name [String] The name of the stat.
|
||||
# @param val [Integer, Float] The value of the stat.
|
||||
# @return [true, false] Whether the stat was successfully updated.
|
||||
# @example
|
||||
# steam = SteamUserStatsLite.instance
|
||||
# steam.set_stat 'YOUR_STAT_ID_HERE', 100
|
||||
# steam.update
|
||||
def set_stat(name, val)
|
||||
if initted?
|
||||
|
||||
# @@dll_SteamAPI_ISteamUserStats_StoreStats.call(@i_user_stats) % 256 != 0 && ok
|
||||
end
|
||||
end
|
||||
|
||||
# Updates an AVGRATE stat.
|
||||
#
|
||||
# @param name [String] The name of the stat.
|
||||
# @param count_this_session [Float] The value during this session.
|
||||
# @param session_length [Float] The length of this session.
|
||||
# @return [true, false] Whether the stat was successfully updated.
|
||||
def update_avg_rate_stat(name, count_this_session, session_length)
|
||||
if initted?
|
||||
packed = self.class.pack_double session_length
|
||||
end
|
||||
end
|
||||
|
||||
# Gets an achievement's state.
|
||||
#
|
||||
# @param name [String] The name of the achievement.
|
||||
# @return [true, false, nil] Whether the achievement has unlocked, or +nil+ if the achievement cannot be retrieved.
|
||||
def get_achievement(name)
|
||||
if initted?
|
||||
val = ' '
|
||||
ok = # @@dll_SteamAPI_ISteamUserStats_GetAchievement.call(@i_user_stats, name, val) % 256 != 0
|
||||
ok ? val.unpack('C')[0] != 0 : nil
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Sets an achievement as unlocked.
|
||||
#
|
||||
# @param name [String] The name of the achievement.
|
||||
# @return [true, false] Whether the achievement was set successfully.
|
||||
# @example
|
||||
# steam = SteamUserStatsLite.instance
|
||||
# steam.set_achievement 'YOUR_ACH_ID_HERE'
|
||||
# steam.update
|
||||
def set_achievement(name)
|
||||
# if initted?
|
||||
# ok = # @@dll_SteamAPI_ISteamUserStats_SetAchievement.call(@i_user_stats, name) % 256 != 0
|
||||
# # @@dll_SteamAPI_ISteamUserStats_StoreStats.call(@i_user_stats) % 256 != 0 && ok
|
||||
# # else
|
||||
# # false
|
||||
# end
|
||||
end
|
||||
|
||||
# Sets an achievement as locked.
|
||||
#
|
||||
# @param name [String] The name of the achievement.
|
||||
# @return [true, false] Whether the achievement was cleared successfully.
|
||||
def clear_achievement(name)
|
||||
# if initted?
|
||||
# ok = # @@dll_SteamAPI_ISteamUserStats_ClearAchievement.call(@i_user_stats, name) % 256 != 0
|
||||
# # @@dll_SteamAPI_ISteamUserStats_StoreStats.call(@i_user_stats) % 256 != 0 && ok
|
||||
# else
|
||||
# false
|
||||
# end
|
||||
end
|
||||
|
||||
# Gets an achievement's state and unlock time.
|
||||
#
|
||||
# @param name [String] The name of the achievement.
|
||||
# @return [<Object, Time>] The achievement's state (+true+ or +false+) and the time it was unlocked.
|
||||
def get_achievement_and_unlock_time(name)
|
||||
if initted?
|
||||
achieved = ' '
|
||||
unlock_time = ' ' * 4
|
||||
ok = # @@dll_SteamAPI_ISteamUserStats_GetAchievementAndUnlockTime.call(@i_user_stats, name, achieved, unlock_time) % 256 != 0
|
||||
ok ? [achieved.unpack('C')[0] != 0, Time.at(unlock_time.unpack('L')[0])] : nil
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the value of an achievement's display attribute.
|
||||
#
|
||||
# @param name [String] The name of the achievement.
|
||||
# @param key [String] The key of the display attribute.
|
||||
# @return [String] The value of the display attribute.
|
||||
def get_achievement_display_attribute(name, key)
|
||||
if initted?
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute.call @i_user_stats, name, key
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the number of achievements.
|
||||
#
|
||||
# @return [Integer, nil] The number of achievements, or +nil+ if the number cannot be retrieved.
|
||||
def get_num_achievements
|
||||
if initted?
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetNumAchievements.call @i_user_stats
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the name of an achievement by its index.
|
||||
#
|
||||
# @param achievement [Integer] The index of the achievement.
|
||||
# @return [String] The name of the achievement.
|
||||
def get_achievement_name(achievement)
|
||||
if initted?
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetAchievementName.call @i_user_stats, achievement
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Resets all stats.
|
||||
#
|
||||
# @param achievements_too [true, false] Whether to reset achievements as well.
|
||||
# @return [true, false] Whether achievements have been reset.
|
||||
def reset_all_stats(achievements_too)
|
||||
# if initted?
|
||||
# ok = # @@dll_SteamAPI_ISteamUserStats_ResetAllStats.call(@i_user_stats, achievements_too ? 1 : 0) % 256 != 0
|
||||
# # @@dll_SteamAPI_ISteamUserStats_StoreStats.call(@i_user_stats) % 256 != 0 && ok
|
||||
# else
|
||||
# false
|
||||
# end
|
||||
end
|
||||
|
||||
# Gets the global instance of SteamUserStatsLite.
|
||||
#
|
||||
# @return [SteamUserStatsLite] The global instance of the class.
|
||||
def self.instance
|
||||
@@instance
|
||||
end
|
||||
|
||||
private
|
||||
def self.is_64bit?
|
||||
# Probably very bad detection of whether current runtime is 64-bit
|
||||
(/x64/ =~ RUBY_PLATFORM) != nil
|
||||
end
|
||||
|
||||
def self.steam_dll_name
|
||||
# @@dll_name ||= self.is_64bit? ? 'steam_api64' : 'steam_api'
|
||||
end
|
||||
|
||||
# Function imports
|
||||
# @@dll_SteamAPI_RestartAppIfNecessary = Win32API.new(self.steam_dll_name, 'SteamAPI_RestartAppIfNecessary', 'I', 'I')
|
||||
# @@dll_SteamAPI_Init = Win32API.new(self.steam_dll_name, 'SteamAPI_Init', '', 'I')
|
||||
# @@dll_SteamAPI_Shutdown = Win32API.new(self.steam_dll_name, 'SteamAPI_Shutdown', '', 'V')
|
||||
# @@dll_SteamAPI_RunCallbacks = Win32API.new(self.steam_dll_name, 'SteamAPI_RunCallbacks', '', 'V')
|
||||
# @@dll_SteamAPI_ISteamUserStats_RequestCurrentStats = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_RequestCurrentStats', 'P', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetStat = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_GetStat', 'PPP', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetStat0 = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_GetStat0', 'PPP', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_SetStat = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_SetStat', 'PPL', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_SetStat0 = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_SetStat0', 'PPI', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_UpdateAvgRateStat = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_UpdateAvgRateStat', 'PPIII', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetAchievement = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_GetAchievement', 'PPP', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_SetAchievement = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_SetAchievement', 'PP', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_ClearAchievement = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_ClearAchievement', 'PP', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetAchievementAndUnlockTime = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_GetAchievementAndUnlockTime', 'PPPP', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute', 'PPP', 'P')
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetNumAchievements = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_GetNumAchievements', 'P', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_GetAchievementName = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_GetAchievementName', 'PI', 'P')
|
||||
# @@dll_SteamAPI_ISteamUserStats_StoreStats = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_StoreStats', 'P', 'I')
|
||||
# @@dll_SteamAPI_ISteamUserStats_ResetAllStats = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamUserStats_ResetAllStats', 'PI', 'I')
|
||||
# @@dll_SteamAPI_ISteamApps_BIsSubscribed = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamApps_BIsSubscribed', 'P', 'I')
|
||||
# @@dll_SteamAPI_ISteamApps_BIsDlcInstalled = Win32API.new(self.steam_dll_name, 'SteamAPI_ISteamApps_BIsDlcInstalled', 'PI', 'I')
|
||||
|
||||
@@instance = self.new
|
||||
|
||||
def self.pack_float(val)
|
||||
# Packs number to a string, then unpack to an int
|
||||
inter = [val].pack 'e'
|
||||
inter.unpack('I')[0]
|
||||
end
|
||||
|
||||
def self.pack_double(val)
|
||||
# Packs number to a string, then unpack to an array of two ints
|
||||
inter = [val].pack 'd'
|
||||
inter.unpack 'II'
|
||||
end
|
||||
|
||||
end
|
281
Kawariki-patches/ports/bitmap_tktk.rb
Normal file
281
Kawariki-patches/ports/bitmap_tktk.rb
Normal file
|
@ -0,0 +1,281 @@
|
|||
# coding: utf-8
|
||||
=begin
|
||||
= Bitmapクラスの拡張 (DLL版)
|
||||
RPGツクールXP/VX共用
|
||||
Bitmapクラスに機能を追加します。
|
||||
- Marshaldump可能に
|
||||
- PNGファイルとして保存
|
||||
- 色調変更
|
||||
- モザイク効果
|
||||
- 色の反転
|
||||
- ぼかし効果
|
||||
- マスクを用いた切り抜き
|
||||
- ブレンディング
|
||||
|
||||
■ 注意
|
||||
このスクリプトの他に"tktk_bitmap.dll"(ver0.1.2.6以上)が必要になります。
|
||||
|
||||
Author:: 半生
|
||||
Date:: 2010/12/13
|
||||
Version:: 0.1.2.6
|
||||
URL:: http://www.tktkgame.com/
|
||||
|
||||
############################################
|
||||
2010/12/13 ver 0.1.2.6
|
||||
dllの名称を"hn_rg_bitmap.dll"から"tktk_bitmap.dll"に変更
|
||||
LARGE_BITMAP機能でメモリを確保できなかった場合の処理を追加
|
||||
2010/10/12 ver 0.1.2.5(デンジャラスベータ版)
|
||||
大きいサイズのBitmapオブジェクトを機能を試験的に実装(危険)
|
||||
2010/03/24 ver 0.1.2.2
|
||||
ブレンディング機能関連の軽量化。
|
||||
画像連結系メソッドの分離。
|
||||
2010/03/24 ver 0.1.2.1
|
||||
ブレンディング機能関連のバグフィックス
|
||||
2010/03/22 ver 0.1.2.0
|
||||
加算合成等のブレンディング機能の追加
|
||||
2010/02/07 ver 0.1.1.0
|
||||
マーシャル化の処理の一部をDLLに移動
|
||||
2010/01/17 ver 0.1.0.0
|
||||
dllの名称を"hn_rx_bitmap.dll"から"hn_rg_bitmap.dll"に変更
|
||||
モザイク効果・色反転・ぼかし効果の追加
|
||||
############################################
|
||||
=end
|
||||
|
||||
def dummy_blend_blt(dest_id, x, y, src_id, src_x, src_y, width, height, blend_mode, opacity)
|
||||
puts "Blending operation started!"
|
||||
puts "Destination Image ID: #{dest_id}"
|
||||
puts "Source Image ID: #{src_id}"
|
||||
puts "Blending Position: (#{x}, #{y})"
|
||||
puts "Source Image Rectangle: (#{src_x}, #{src_y}, #{width}, #{height})"
|
||||
puts "Blend Mode: #{blend_mode}"
|
||||
puts "Opacity: #{opacity}"
|
||||
puts "Simulating image blending operation..."
|
||||
# More logic to simulate the blending can go here
|
||||
puts "Finished blending images with the specified settings."
|
||||
end
|
||||
|
||||
# Example usage:
|
||||
# dest_bmp = Object.new
|
||||
# src_bmp = Object.new
|
||||
# rect = OpenStruct.new(x: 0, y: 0, width: 100, height: 100)
|
||||
|
||||
# Call the dummy blend function directly without a class
|
||||
# dummy_blend_blt(
|
||||
# dest_bmp.object_id, 10, 20, src_bmp.object_id, rect.x, rect.y, rect.width, rect.height, 'multiply', 0.7
|
||||
# )
|
||||
|
||||
module TKTK_Bitmap
|
||||
LARGE_BITMAP = true # 大容量のBitmap作成機能を使うかどうか
|
||||
DLL_NAME = 'tktk_bitmap'
|
||||
|
||||
ERROR_ALLOCATE_FAILED = -110002
|
||||
|
||||
@@png_save = Win32API.new(DLL_NAME, 'PngSaveA', 'p n i i', 'i')
|
||||
@@blur = Win32API.new(DLL_NAME, 'Blur', 'n i', 'i')
|
||||
@@change_tone = Win32API.new(DLL_NAME, 'ChangeTone', 'n i i i i', 'i')
|
||||
@@clip_mask = Win32API.new(DLL_NAME, 'ClipMask', 'n n i i i', 'i')
|
||||
@@invert = Win32API.new(DLL_NAME, 'InvertColor', 'n', 'i')
|
||||
@@mosaic = Win32API.new(DLL_NAME, 'Mosaic', 'n i i i i i i', 'i')
|
||||
@@address = Win32API.new(DLL_NAME, 'GetAddress', 'n', 'n')
|
||||
@@get_pixel_data = Win32API.new(DLL_NAME, 'GetPixelData', 'n p i', 'i')
|
||||
@@set_pixel_data = Win32API.new(DLL_NAME, 'SetPixelData', 'n p i', 'i')
|
||||
@@blend_blt = Win32API.new(DLL_NAME, 'BlendBlt', 'n i i n i i i i i i', 'i')
|
||||
#@@get_hwnd = Win32API.new(DLL_NAME, 'GetGameHWND', 'v', 'l')
|
||||
@@change_size = Win32API.new(DLL_NAME, 'ChangeSize', 'n i i', 'i')
|
||||
module_function
|
||||
|
||||
# PNG形式で保存
|
||||
def png_save(bitmap,file_name,compression_level,filter)
|
||||
return @@png_save.call(file_name, bitmap.object_id, compression_level, filter)
|
||||
end
|
||||
|
||||
# ぼかし効果
|
||||
def blur(bitmap, r = 1)
|
||||
return @@blur.call(bitmap.object_id, r)
|
||||
end
|
||||
|
||||
# カラーバランス変更?
|
||||
def change_tone(bitmap, red = 0, green = 0, blue = 0, simplify = 1)
|
||||
return @@change_tone.call(bitmap.object_id, red, green, blue, simplify)
|
||||
end
|
||||
|
||||
# マスクによる画像の切り抜き(アルファとの乗算)
|
||||
def clip_mask(g_bitmap, m_bitmap, x=0, y=0, outer=0)
|
||||
return @@clip_mask.call(g_bitmap.object_id, m_bitmap.object_id, x, y, outer)
|
||||
end
|
||||
|
||||
# 色の反転
|
||||
def invert(bitmap)
|
||||
# $game_self_switches.delete(7,["A"])
|
||||
# puts "ggg"
|
||||
# $game_switches.each_with_index do |
|
||||
# switch, index|
|
||||
# # puts "Switch #{index + 1}: #{switch}"
|
||||
# end
|
||||
$game_switches[11] = false
|
||||
# puts $game_switches[8]
|
||||
# puts $game_switches[9]
|
||||
# puts $game_switches[10]
|
||||
# puts $game_switches[11]
|
||||
# puts $game_switches[12]
|
||||
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
# モザイク効果
|
||||
def mosaic(bitmap, msw=5, msh=5)
|
||||
return self.mosaic_rect(bitmap, bitmap.rect, msw, msh)
|
||||
end
|
||||
|
||||
# モザイク効果(範囲指定)
|
||||
def mosaic_rect(bitmap, rect, msw=5, msh=5)
|
||||
return @@mosaic.call(bitmap.object_id,
|
||||
rect.x, rect.y, rect.width, rect.height, msw, msh)
|
||||
end
|
||||
|
||||
# ビットマップデータのアドレスを取得
|
||||
def address(bitmap)
|
||||
return @@address.call(bitmap.object_id)
|
||||
end
|
||||
|
||||
# ビットマップのバイナリデータを取得
|
||||
def get_pixel_data(bitmap)
|
||||
buffer = "bgra" * bitmap.width * bitmap.height
|
||||
@@get_pixel_data.call(bitmap.object_id, buffer, buffer.size)
|
||||
return buffer
|
||||
end
|
||||
|
||||
# ビットマップのバイナリデータを置き換え
|
||||
def set_pixel_data(bitmap, data)
|
||||
return @@set_pixel_data.call(bitmap.object_id, data, data.size)
|
||||
end
|
||||
|
||||
def blend_blt(dest_bmp, x, y, src_bmp, rect, blend_type=0, opacity=255)
|
||||
$game_switches[11] = false
|
||||
|
||||
# @@blend_blt.call(dest_bmp.object_id, x, y, src_bmp.object_id,
|
||||
# rect.x, rect.y, rect.width, rect.height,
|
||||
# blend_type, opacity)
|
||||
# return 0
|
||||
# dest_bmp.object_id, 10, 20, src_bmp.object_id, rect.x, rect.y, rect.width, rect.height, 'multiply', 0.7
|
||||
# dest_bmp.object_id, 10, 20, src_bmp.object_id, rect.x, rect.y, rect.width, rect.height, 'multiply', 0.7
|
||||
|
||||
end
|
||||
|
||||
|
||||
# ビットマップのサイズを変更(危険)
|
||||
def change_size(bitmap, new_width, new_height)
|
||||
return -1 if (new_width <=0 or new_height <= 0)
|
||||
result = @@change_size.call(bitmap.object_id, new_width, new_height)
|
||||
if result == ERROR_ALLOCATE_FAILED
|
||||
raise("tktk_bitmap:ERROR ALLOCATE FAILED")
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Font
|
||||
def marshal_dump;end
|
||||
def marshal_load(obj);end
|
||||
end
|
||||
class Bitmap
|
||||
# PNG圧縮用フィルタ
|
||||
PNG_NO_FILTERS = 0x00
|
||||
PNG_FILTER_NONE = 0x08
|
||||
PNG_FILTER_SUB = 0x10
|
||||
PNG_FILTER_UP = 0x20
|
||||
PNG_FILTER_AVG = 0x40
|
||||
PNG_FILTER_PAETH = 0x80
|
||||
PNG_ALL_FILTERS = (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP |
|
||||
PNG_FILTER_AVG | PNG_FILTER_PAETH)
|
||||
|
||||
# Marshal_dump
|
||||
def _dump(limit)
|
||||
return "" if self.disposed?
|
||||
data = TKTK_Bitmap.get_pixel_data(self)
|
||||
[width, height, Zlib::Deflate.deflate(data)].pack("LLa*") # ついでに圧縮
|
||||
end
|
||||
|
||||
# Marshal_load
|
||||
def self._load(str)
|
||||
if str == ""
|
||||
b = Bitmap.new(1,1)
|
||||
b.dispose
|
||||
return b
|
||||
end
|
||||
w, h, zdata = str.unpack("LLa*"); b = new(w, h)
|
||||
TKTK_Bitmap.set_pixel_data(b, Zlib::Inflate.inflate(zdata))
|
||||
return b
|
||||
end
|
||||
|
||||
def address
|
||||
TKTK_Bitmap.address(self)
|
||||
end
|
||||
|
||||
# ぼかし効果
|
||||
def blur2(r=1)
|
||||
TKTK_Bitmap.blur(self, r)
|
||||
end
|
||||
|
||||
# 色調変更
|
||||
def change_tone(red, green, blue, simplify = 1)
|
||||
TKTK_Bitmap.change_tone(self, red, green, blue, simplify)
|
||||
end
|
||||
|
||||
# クリッピング
|
||||
def clip_mask(bitmap, x=0, y=0, outer=0)
|
||||
TKTK_Bitmap.clip_mask(self, bitmap, x, y, outer)
|
||||
end
|
||||
|
||||
# 色の反転
|
||||
def invert
|
||||
TKTK_Bitmap.invert(self)
|
||||
end
|
||||
|
||||
# モザイク効果
|
||||
def mosaic(msw=5, msh=5)
|
||||
TKTK_Bitmap.mosaic(self, msw, msh)
|
||||
end
|
||||
|
||||
# モザイク効果(領域指定)
|
||||
def mosaic_rect(rect=self.rect, msw=5, msh=5)
|
||||
TKTK_Bitmap.mosaic_rect(self, rect, msw, msh)
|
||||
end
|
||||
|
||||
# ブレンディング
|
||||
def blend_blt(x, y, src_bmp, rect, blend_type=0, opacity=255)
|
||||
return if opacity <= 0
|
||||
TKTK_Bitmap.blend_blt(self, x, y, src_bmp, rect, blend_type, opacity)
|
||||
end
|
||||
|
||||
#png形式で保存
|
||||
def png_save(outp, level = 9, filter = PNG_NO_FILTERS)
|
||||
if (TKTK_Bitmap.png_save(self, outp, level, filter) != 0)
|
||||
raise("Bitmap\#png_save failed")
|
||||
end
|
||||
end
|
||||
|
||||
# 大きいサイズのBitmap.newを可能に(危険)
|
||||
# width * height が大体1073741823位まで
|
||||
if TKTK_Bitmap::LARGE_BITMAP
|
||||
class << self
|
||||
unless method_defined?(:_hn_large_bm__new)
|
||||
alias :_hn_large_bm__new :new
|
||||
end
|
||||
def new(*args)
|
||||
if args.size == 2 && args[0] * args[1] >= 4194304
|
||||
new_width = args[0]
|
||||
new_height = args[1]
|
||||
# とりあえず小さなサイズで作成
|
||||
bitmap = _hn_large_bm__new(16, 16)
|
||||
TKTK_Bitmap.change_size(bitmap, new_width, new_height)
|
||||
return bitmap
|
||||
else
|
||||
_hn_large_bm__new(*args)
|
||||
end
|
||||
end
|
||||
end # Bitmap.new
|
||||
end
|
||||
end # CLASS Bitmap
|
236
Kawariki-patches/ports/bitmap_tktkk.rb
Normal file
236
Kawariki-patches/ports/bitmap_tktkk.rb
Normal file
|
@ -0,0 +1,236 @@
|
|||
# coding: utf-8
|
||||
=begin
|
||||
= Bitmapクラスの拡張 (DLL版)
|
||||
RPGツクールXP/VX共用
|
||||
Bitmapクラスに機能を追加します。
|
||||
- Marshaldump可能に
|
||||
- PNGファイルとして保存
|
||||
- 色調変更
|
||||
- モザイク効果
|
||||
- 色の反転
|
||||
- ぼかし効果
|
||||
- マスクを用いた切り抜き
|
||||
- ブレンディング
|
||||
|
||||
■ 注意
|
||||
このスクリプトの他に"tktk_bitmap.dll"(ver0.1.2.6以上)が必要になります。
|
||||
|
||||
Author:: 半生
|
||||
Date:: 2010/12/13
|
||||
Version:: 0.1.2.6
|
||||
URL:: http://www.tktkgame.com/
|
||||
|
||||
############################################
|
||||
2010/12/13 ver 0.1.2.6
|
||||
dllの名称を"hn_rg_bitmap.dll"から"tktk_bitmap.dll"に変更
|
||||
LARGE_BITMAP機能でメモリを確保できなかった場合の処理を追加
|
||||
2010/10/12 ver 0.1.2.5(デンジャラスベータ版)
|
||||
大きいサイズのBitmapオブジェクトを機能を試験的に実装(危険)
|
||||
2010/03/24 ver 0.1.2.2
|
||||
ブレンディング機能関連の軽量化。
|
||||
画像連結系メソッドの分離。
|
||||
2010/03/24 ver 0.1.2.1
|
||||
ブレンディング機能関連のバグフィックス
|
||||
2010/03/22 ver 0.1.2.0
|
||||
加算合成等のブレンディング機能の追加
|
||||
2010/02/07 ver 0.1.1.0
|
||||
マーシャル化の処理の一部をDLLに移動
|
||||
2010/01/17 ver 0.1.0.0
|
||||
dllの名称を"hn_rx_bitmap.dll"から"hn_rg_bitmap.dll"に変更
|
||||
モザイク効果・色反転・ぼかし効果の追加
|
||||
############################################
|
||||
=end
|
||||
|
||||
module TKTK_Bitmap
|
||||
LARGE_BITMAP = true # 大容量のBitmap作成機能を使うかどうか
|
||||
DLL_NAME = 'tktk_bitmap'
|
||||
|
||||
ERROR_ALLOCATE_FAILED = -110002
|
||||
|
||||
@@png_save = Win32API.new(DLL_NAME, 'PngSaveA', 'p n i i', 'i')
|
||||
@@blur = Win32API.new(DLL_NAME, 'Blur', 'n i', 'i')
|
||||
@@change_tone = Win32API.new(DLL_NAME, 'ChangeTone', 'n i i i i', 'i')
|
||||
@@clip_mask = Win32API.new(DLL_NAME, 'ClipMask', 'n n i i i', 'i')
|
||||
@@invert = Win32API.new(DLL_NAME, 'InvertColor', 'n', 'i')
|
||||
@@mosaic = Win32API.new(DLL_NAME, 'Mosaic', 'n i i i i i i', 'i')
|
||||
@@address = Win32API.new(DLL_NAME, 'GetAddress', 'n', 'n')
|
||||
@@get_pixel_data = Win32API.new(DLL_NAME, 'GetPixelData', 'n p i', 'i')
|
||||
@@set_pixel_data = Win32API.new(DLL_NAME, 'SetPixelData', 'n p i', 'i')
|
||||
@@blend_blt = Win32API.new(DLL_NAME, 'BlendBlt', 'n i i n i i i i i i', 'i')
|
||||
#@@get_hwnd = Win32API.new(DLL_NAME, 'GetGameHWND', 'v', 'l')
|
||||
@@change_size = Win32API.new(DLL_NAME, 'ChangeSize', 'n i i', 'i')
|
||||
module_function
|
||||
|
||||
# PNG形式で保存
|
||||
def png_save(bitmap,file_name,compression_level,filter)
|
||||
return file_name, bitmap.object_id, compression_level, filter
|
||||
end
|
||||
|
||||
# ぼかし効果
|
||||
def blur(bitmap, r = 1)
|
||||
return bitmap.object_id, r
|
||||
end
|
||||
|
||||
# カラーバランス変更?
|
||||
def change_tone(bitmap, red = 0, green = 0, blue = 0, simplify = 1)
|
||||
return bitmap.object_id, red, green, blue, simplify
|
||||
end
|
||||
|
||||
# マスクによる画像の切り抜き(アルファとの乗算)
|
||||
def clip_mask(g_bitmap, m_bitmap, x=0, y=0, outer=0)
|
||||
return g_bitmap.object_id, m_bitmap.object_id, x, y, outer
|
||||
end
|
||||
|
||||
# 色の反転
|
||||
def invert(bitmap)
|
||||
return bitmap.object_id
|
||||
end
|
||||
|
||||
# モザイク効果
|
||||
def mosaic(bitmap, msw=5, msh=5)
|
||||
return bitmap, bitmap.rect, msw, msh
|
||||
end
|
||||
|
||||
# モザイク効果(範囲指定)
|
||||
def mosaic_rect(bitmap, rect, msw=5, msh=5)
|
||||
return bitmap.object_id, rect.x, rect.y, rect.width, rect.height, msw, msh
|
||||
end
|
||||
|
||||
# ビットマップデータのアドレスを取得
|
||||
def address(bitmap)
|
||||
return bitmap.object_id
|
||||
end
|
||||
|
||||
# ビットマップのバイナリデータを取得
|
||||
def get_pixel_data(bitmap)
|
||||
buffer = "bgra" * bitmap.width * bitmap.height
|
||||
@@get_pixel_data.call(bitmap.object_id, buffer, buffer.size)
|
||||
return buffer
|
||||
end
|
||||
|
||||
# ビットマップのバイナリデータを置き換え
|
||||
def set_pixel_data(bitmap, data)
|
||||
return bitmap.object_id, data, data.size
|
||||
end
|
||||
|
||||
def blend_blt(dest_bmp, x, y, src_bmp, rect, blend_type=0, opacity=255)
|
||||
dest_bmp.object_id, x, y, src_bmp.object_id,
|
||||
rect.x, rect.y, rect.width, rect.height,
|
||||
blend_type, opacity
|
||||
end
|
||||
|
||||
# ビットマップのサイズを変更(危険)
|
||||
def change_size(bitmap, new_width, new_height)
|
||||
return -1 if (new_width <=0 or new_height <= 0)
|
||||
result = @@change_size.call(bitmap.object_id, new_width, new_height)
|
||||
if result == ERROR_ALLOCATE_FAILED
|
||||
raise("tktk_bitmap:ERROR ALLOCATE FAILED")
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Font
|
||||
def marshal_dump;end
|
||||
def marshal_load(obj);end
|
||||
end
|
||||
class Bitmap
|
||||
# PNG圧縮用フィルタ
|
||||
PNG_NO_FILTERS = 0x00
|
||||
PNG_FILTER_NONE = 0x08
|
||||
PNG_FILTER_SUB = 0x10
|
||||
PNG_FILTER_UP = 0x20
|
||||
PNG_FILTER_AVG = 0x40
|
||||
PNG_FILTER_PAETH = 0x80
|
||||
PNG_ALL_FILTERS = (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP |
|
||||
PNG_FILTER_AVG | PNG_FILTER_PAETH)
|
||||
|
||||
# Marshal_dump
|
||||
def _dump(limit)
|
||||
return "" if self.disposed?
|
||||
data = TKTK_Bitmap.get_pixel_data(self)
|
||||
[width, height, Zlib::Deflate.deflate(data)].pack("LLa*") # ついでに圧縮
|
||||
end
|
||||
|
||||
# Marshal_load
|
||||
def self._load(str)
|
||||
if str == ""
|
||||
b = Bitmap.new(1,1)
|
||||
b.dispose
|
||||
return b
|
||||
end
|
||||
w, h, zdata = str.unpack("LLa*"); b = new(w, h)
|
||||
TKTK_Bitmap.set_pixel_data(b, Zlib::Inflate.inflate(zdata))
|
||||
return b
|
||||
end
|
||||
|
||||
def address
|
||||
TKTK_Bitmap.address(self)
|
||||
end
|
||||
|
||||
# ぼかし効果
|
||||
def blur2(r=1)
|
||||
TKTK_Bitmap.blur(self, r)
|
||||
end
|
||||
|
||||
# 色調変更
|
||||
def change_tone(red, green, blue, simplify = 1)
|
||||
TKTK_Bitmap.change_tone(self, red, green, blue, simplify)
|
||||
end
|
||||
|
||||
# クリッピング
|
||||
def clip_mask(bitmap, x=0, y=0, outer=0)
|
||||
TKTK_Bitmap.clip_mask(self, bitmap, x, y, outer)
|
||||
end
|
||||
|
||||
# 色の反転
|
||||
def invert
|
||||
TKTK_Bitmap.invert(self)
|
||||
end
|
||||
|
||||
# モザイク効果
|
||||
def mosaic(msw=5, msh=5)
|
||||
TKTK_Bitmap.mosaic(self, msw, msh)
|
||||
end
|
||||
|
||||
# モザイク効果(領域指定)
|
||||
def mosaic_rect(rect=self.rect, msw=5, msh=5)
|
||||
TKTK_Bitmap.mosaic_rect(self, rect, msw, msh)
|
||||
end
|
||||
|
||||
# ブレンディング
|
||||
def blend_blt(x, y, src_bmp, rect, blend_type=0, opacity=255)
|
||||
return if opacity <= 0
|
||||
TKTK_Bitmap.blend_blt(self, x, y, src_bmp, rect, blend_type, opacity)
|
||||
end
|
||||
|
||||
#png形式で保存
|
||||
def png_save(outp, level = 9, filter = PNG_NO_FILTERS)
|
||||
if (TKTK_Bitmap.png_save(self, outp, level, filter) != 0)
|
||||
raise("Bitmap\#png_save failed")
|
||||
end
|
||||
end
|
||||
|
||||
# 大きいサイズのBitmap.newを可能に(危険)
|
||||
# width * height が大体1073741823位まで
|
||||
if TKTK_Bitmap::LARGE_BITMAP
|
||||
class << self
|
||||
unless method_defined?(:_hn_large_bm__new)
|
||||
alias :_hn_large_bm__new :new
|
||||
end
|
||||
def new(*args)
|
||||
if args.size == 2 && args[0] * args[1] >= 4194304
|
||||
new_width = args[0]
|
||||
new_height = args[1]
|
||||
# とりあえず小さなサイズで作成
|
||||
bitmap = _hn_large_bm__new(16, 16)
|
||||
TKTK_Bitmap.change_size(bitmap, new_width, new_height)
|
||||
return bitmap
|
||||
else
|
||||
_hn_large_bm__new(*args)
|
||||
end
|
||||
end
|
||||
end # Bitmap.new
|
||||
end
|
||||
end # CLASS Bitmap
|
613
Kawariki-patches/ports/debug/basewt.rb
Normal file
613
Kawariki-patches/ports/debug/basewt.rb
Normal file
|
@ -0,0 +1,613 @@
|
|||
#==============================================================================
|
||||
# ■ Window_Base
|
||||
#------------------------------------------------------------------------------
|
||||
# ゲーム中の全てのウィンドウのスーパークラスです。
|
||||
#==============================================================================
|
||||
|
||||
class Window_Base < Window
|
||||
#--------------------------------------------------------------------------
|
||||
# ● オブジェクト初期化
|
||||
#--------------------------------------------------------------------------
|
||||
def initialize(x, y, width, height)
|
||||
super
|
||||
self.windowskin = Cache.system("Window")
|
||||
update_padding
|
||||
update_tone
|
||||
create_contents
|
||||
@opening = @closing = false
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 解放
|
||||
#--------------------------------------------------------------------------
|
||||
def dispose
|
||||
contents.dispose unless disposed?
|
||||
super
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 行の高さを取得
|
||||
#--------------------------------------------------------------------------
|
||||
def line_height
|
||||
return 24
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 標準パディングサイズの取得
|
||||
#--------------------------------------------------------------------------
|
||||
def standard_padding
|
||||
return 12
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● パディングの更新
|
||||
#--------------------------------------------------------------------------
|
||||
def update_padding
|
||||
self.padding = standard_padding
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウ内容の幅を計算
|
||||
#--------------------------------------------------------------------------
|
||||
def contents_width
|
||||
width - standard_padding * 2
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウ内容の高さを計算
|
||||
#--------------------------------------------------------------------------
|
||||
def contents_height
|
||||
height - standard_padding * 2
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 指定行数に適合するウィンドウの高さを計算
|
||||
#--------------------------------------------------------------------------
|
||||
def fitting_height(line_number)
|
||||
line_number * line_height + standard_padding * 2
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 色調の更新
|
||||
#--------------------------------------------------------------------------
|
||||
def update_tone
|
||||
self.tone.set($game_system.window_tone)
|
||||
end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウ内容の作成
|
||||
#--------------------------------------------------------------------------
|
||||
def create_contents
|
||||
test5 = contents_width
|
||||
testf = contents_height
|
||||
# Debugging: Log the current types and values of contents_width and contents_height
|
||||
puts "Before disposing, contents width: #{contents_width}, height: #{contents_height}"
|
||||
puts "Before disposing, contents width type: #{contents_width.class}, height type: #{contents_height.class}"
|
||||
|
||||
contents.dispose
|
||||
|
||||
# Check for nil and ensure that contents_width and contents_height are integers
|
||||
if contents_width.nil? || contents_height.nil?
|
||||
puts "sadada disposing, contents width: #{contents_width}, height: #{contents_height}"
|
||||
puts "Warning: contents_width or contents_height is nil, setting default values."
|
||||
contents_width = 190 # Default width (you can adjust this to your needs)
|
||||
contents_height = 120 # Default height (you can adjust this to your needs)
|
||||
end
|
||||
|
||||
# Ensure contents_width and contents_height are valid integers before proceeding
|
||||
# if contents_width.is_a?(Integer) && contents_height.is_a?(Integer)
|
||||
if contents_width > 0 && contents_height > 0
|
||||
# Limit height to a maximum of 2048 pixels
|
||||
# contents_height = 2048 if contents_height > 2048
|
||||
self.contents = Bitmap.new(contents_width, contents_height)
|
||||
puts "Created new bitmap with dimensions: #{contents_width} x #{contents_height}"
|
||||
else
|
||||
puts "Invalid dimensions: creating fallback 1x1 bitmap"
|
||||
self.contents = Bitmap.new(1, 1)
|
||||
end
|
||||
# else
|
||||
# # If contents_width or contents_height are not valid integers, create a fallback 1x1 bitmap
|
||||
# puts "Warning: Invalid types for contents width or height. Creating fallback 1x1 bitmap."
|
||||
# self.contents = Bitmap.new(1, 1)
|
||||
# end
|
||||
end
|
||||
def create_contents
|
||||
# puts "vv Before disposing, contents width: #{contents_width}, height: #{contents_height}"
|
||||
# puts "vv Before disposing, contents width type: #{contents_width.class}, height type: #{contents_height.class}"
|
||||
contents.dispose
|
||||
# puts "Before disposing, contents width: #{contents_width}, height: #{contents_height}"
|
||||
# puts "Before disposing, contents width type: #{contents_width.class}, height type: #{contents_height.class}"
|
||||
|
||||
# end
|
||||
if contents_height > 10000
|
||||
self.contents = Bitmap.new(1, 1)
|
||||
elsif contents_width > 0 && contents_height > 0
|
||||
self.contents = Bitmap.new(contents_width, contents_height)
|
||||
puts "Created new bitmap with dimensions: #{contents_width} x #{contents_height}"
|
||||
else
|
||||
self.contents = Bitmap.new(1, 1)
|
||||
end
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● フレーム更新
|
||||
#--------------------------------------------------------------------------
|
||||
def update
|
||||
super
|
||||
update_tone
|
||||
update_open if @opening
|
||||
update_close if @closing
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 開く処理の更新
|
||||
#--------------------------------------------------------------------------
|
||||
def update_open
|
||||
self.openness += 48
|
||||
@opening = false if open?
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 閉じる処理の更新
|
||||
#--------------------------------------------------------------------------
|
||||
def update_close
|
||||
self.openness -= 48
|
||||
@closing = false if close?
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウを開く
|
||||
#--------------------------------------------------------------------------
|
||||
def open
|
||||
@opening = true unless open?
|
||||
@closing = false
|
||||
self
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウを閉じる
|
||||
#--------------------------------------------------------------------------
|
||||
def close
|
||||
@closing = true unless close?
|
||||
@opening = false
|
||||
self
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウの表示
|
||||
#--------------------------------------------------------------------------
|
||||
def show
|
||||
self.visible = true
|
||||
self
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウの非表示
|
||||
#--------------------------------------------------------------------------
|
||||
def hide
|
||||
self.visible = false
|
||||
self
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウのアクティブ化
|
||||
#--------------------------------------------------------------------------
|
||||
def activate
|
||||
self.active = true
|
||||
self
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ウィンドウの非アクティブ化
|
||||
#--------------------------------------------------------------------------
|
||||
def deactivate
|
||||
self.active = false
|
||||
self
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 文字色取得
|
||||
# n : 文字色番号(0..31)
|
||||
#--------------------------------------------------------------------------
|
||||
def text_color(n)
|
||||
windowskin.get_pixel(64 + (n % 8) * 8, 96 + (n / 8) * 8)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 各種文字色の取得
|
||||
#--------------------------------------------------------------------------
|
||||
def normal_color; text_color(0); end; # 通常
|
||||
def system_color; text_color(16); end; # システム
|
||||
def crisis_color; text_color(17); end; # ピンチ
|
||||
def knockout_color; text_color(18); end; # 戦闘不能
|
||||
def gauge_back_color; text_color(19); end; # ゲージ背景
|
||||
def hp_gauge_color1; text_color(20); end; # HP ゲージ 1
|
||||
def hp_gauge_color2; text_color(21); end; # HP ゲージ 2
|
||||
def mp_gauge_color1; text_color(22); end; # MP ゲージ 1
|
||||
def mp_gauge_color2; text_color(23); end; # MP ゲージ 2
|
||||
def mp_cost_color; text_color(23); end; # 消費 TP
|
||||
def power_up_color; text_color(24); end; # 装備 パワーアップ
|
||||
def power_down_color; text_color(25); end; # 装備 パワーダウン
|
||||
def tp_gauge_color1; text_color(28); end; # TP ゲージ 1
|
||||
def tp_gauge_color2; text_color(29); end; # TP ゲージ 2
|
||||
def tp_cost_color; text_color(29); end; # 消費 TP
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 保留項目の背景色を取得
|
||||
#--------------------------------------------------------------------------
|
||||
def pending_color
|
||||
windowskin.get_pixel(80, 80)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 半透明描画用のアルファ値を取得
|
||||
#--------------------------------------------------------------------------
|
||||
def translucent_alpha
|
||||
return 160
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● テキスト描画色の変更
|
||||
# enabled : 有効フラグ。false のとき半透明で描画
|
||||
#--------------------------------------------------------------------------
|
||||
def change_color(color, enabled = true)
|
||||
contents.font.color.set(color)
|
||||
contents.font.color.alpha = translucent_alpha unless enabled
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● テキストの描画
|
||||
# args : Bitmap#draw_text と同じ
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_text(*args)
|
||||
contents.draw_text(*args)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● テキストサイズの取得
|
||||
#--------------------------------------------------------------------------
|
||||
def text_size(str)
|
||||
contents.text_size(str)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 制御文字つきテキストの描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_text_ex(x, y, text)
|
||||
reset_font_settings
|
||||
text = convert_escape_characters(text)
|
||||
pos = {:x => x, :y => y, :new_x => x, :height => calc_line_height(text)}
|
||||
process_character(text.slice!(0, 1), text, pos) until text.empty?
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● フォント設定のリセット
|
||||
#--------------------------------------------------------------------------
|
||||
def reset_font_settings
|
||||
change_color(normal_color)
|
||||
contents.font.size = Font.default_size
|
||||
contents.font.bold = false
|
||||
contents.font.italic = false
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 制御文字の事前変換
|
||||
# 実際の描画を始める前に、原則として文字列に変わるものだけを置き換える。
|
||||
# 文字「\」はエスケープ文字(\e)に変換。
|
||||
#--------------------------------------------------------------------------
|
||||
def convert_escape_characters(text)
|
||||
result = text.to_s.clone
|
||||
result.gsub!(/\\/) { "\e" }
|
||||
result.gsub!(/\e\e/) { "\\" }
|
||||
result.gsub!(/\eV\[(\d+)\]/i) { $game_variables[$1.to_i] }
|
||||
result.gsub!(/\eV\[(\d+)\]/i) { $game_variables[$1.to_i] }
|
||||
result.gsub!(/\eN\[(\d+)\]/i) { actor_name($1.to_i) }
|
||||
result.gsub!(/\eP\[(\d+)\]/i) { party_member_name($1.to_i) }
|
||||
result.gsub!(/\eG/i) { Vocab::currency_unit }
|
||||
result
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● アクター n 番の名前を取得
|
||||
#--------------------------------------------------------------------------
|
||||
def actor_name(n)
|
||||
actor = n >= 1 ? $game_actors[n] : nil
|
||||
actor ? actor.name : ""
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● パーティメンバー n 番の名前を取得
|
||||
#--------------------------------------------------------------------------
|
||||
def party_member_name(n)
|
||||
actor = n >= 1 ? $game_party.members[n - 1] : nil
|
||||
actor ? actor.name : ""
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 文字の処理
|
||||
# c : 文字
|
||||
# text : 描画処理中の文字列バッファ(必要なら破壊的に変更)
|
||||
# pos : 描画位置 {:x, :y, :new_x, :height}
|
||||
#--------------------------------------------------------------------------
|
||||
def process_character(c, text, pos)
|
||||
case c
|
||||
when "\n" # 改行
|
||||
process_new_line(text, pos)
|
||||
when "\f" # 改ページ
|
||||
process_new_page(text, pos)
|
||||
when "\e" # 制御文字
|
||||
process_escape_character(obtain_escape_code(text), text, pos)
|
||||
else # 普通の文字
|
||||
process_normal_character(c, pos)
|
||||
end
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 通常文字の処理
|
||||
#--------------------------------------------------------------------------
|
||||
def process_normal_character(c, pos)
|
||||
text_width = text_size(c).width
|
||||
draw_text(pos[:x], pos[:y], text_width * 2, pos[:height], c)
|
||||
pos[:x] += text_width
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 改行文字の処理
|
||||
#--------------------------------------------------------------------------
|
||||
def process_new_line(text, pos)
|
||||
pos[:x] = pos[:new_x]
|
||||
pos[:y] += pos[:height]
|
||||
pos[:height] = calc_line_height(text)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 改ページ文字の処理
|
||||
#--------------------------------------------------------------------------
|
||||
def process_new_page(text, pos)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 制御文字の本体を破壊的に取得
|
||||
#--------------------------------------------------------------------------
|
||||
def obtain_escape_code(text)
|
||||
text.slice!(/^[\$\.\|\^!><\{\}\\]|^[A-Z]+/i)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 制御文字の引数を破壊的に取得
|
||||
#--------------------------------------------------------------------------
|
||||
def obtain_escape_param(text)
|
||||
text.slice!(/^\[\d+\]/)[/\d+/].to_i rescue 0
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 制御文字の処理
|
||||
# code : 制御文字の本体部分(「\C[1]」なら「C」)
|
||||
#--------------------------------------------------------------------------
|
||||
def process_escape_character(code, text, pos)
|
||||
case code.upcase
|
||||
when 'C'
|
||||
change_color(text_color(obtain_escape_param(text)))
|
||||
when 'I'
|
||||
process_draw_icon(obtain_escape_param(text), pos)
|
||||
when '{'
|
||||
make_font_bigger
|
||||
when '}'
|
||||
make_font_smaller
|
||||
end
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 制御文字によるアイコン描画の処理
|
||||
#--------------------------------------------------------------------------
|
||||
def process_draw_icon(icon_index, pos)
|
||||
draw_icon(icon_index, pos[:x], pos[:y])
|
||||
pos[:x] += 24
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● フォントを大きくする
|
||||
#--------------------------------------------------------------------------
|
||||
def make_font_bigger
|
||||
contents.font.size += 8 if contents.font.size <= 64
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● フォントを小さくする
|
||||
#--------------------------------------------------------------------------
|
||||
def make_font_smaller
|
||||
contents.font.size -= 8 if contents.font.size >= 16
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 行の高さを計算
|
||||
# restore_font_size : 計算後にフォントサイズを元に戻す
|
||||
#--------------------------------------------------------------------------
|
||||
def calc_line_height(text, restore_font_size = true)
|
||||
result = [line_height, contents.font.size].max
|
||||
last_font_size = contents.font.size
|
||||
text.slice(/^.*$/).scan(/\e[\{\}]/).each do |esc|
|
||||
make_font_bigger if esc == "\e{"
|
||||
make_font_smaller if esc == "\e}"
|
||||
result = [result, contents.font.size].max
|
||||
end
|
||||
contents.font.size = last_font_size if restore_font_size
|
||||
result
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ゲージの描画
|
||||
# rate : 割合(1.0 で満タン)
|
||||
# color1 : グラデーション 左端
|
||||
# color2 : グラデーション 右端
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_gauge(x, y, width, rate, color1, color2)
|
||||
fill_w = (width * rate).to_i
|
||||
gauge_y = y + line_height - 8
|
||||
contents.fill_rect(x, gauge_y, width, 6, gauge_back_color)
|
||||
contents.gradient_fill_rect(x, gauge_y, fill_w, 6, color1, color2)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● アイコンの描画
|
||||
# enabled : 有効フラグ。false のとき半透明で描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_icon(icon_index, x, y, enabled = true)
|
||||
bitmap = Cache.system("Iconset")
|
||||
rect = Rect.new(icon_index % 16 * 24, icon_index / 16 * 24, 24, 24)
|
||||
contents.blt(x, y, bitmap, rect, enabled ? 255 : translucent_alpha)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 顔グラフィックの描画
|
||||
# enabled : 有効フラグ。false のとき半透明で描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_face(face_name, face_index, x, y, enabled = true)
|
||||
bitmap = Cache.face(face_name)
|
||||
rect = Rect.new(face_index % 4 * 96, face_index / 4 * 96, 96, 96)
|
||||
contents.blt(x, y, bitmap, rect, enabled ? 255 : translucent_alpha)
|
||||
bitmap.dispose
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 歩行グラフィックの描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_character(character_name, character_index, x, y)
|
||||
return unless character_name
|
||||
bitmap = Cache.character(character_name)
|
||||
sign = character_name[/^[\!\$]./]
|
||||
if sign && sign.include?('$')
|
||||
cw = bitmap.width / 3
|
||||
ch = bitmap.height / 4
|
||||
else
|
||||
cw = bitmap.width / 12
|
||||
ch = bitmap.height / 8
|
||||
end
|
||||
n = character_index
|
||||
src_rect = Rect.new((n%4*3+1)*cw, (n/4*4)*ch, cw, ch)
|
||||
contents.blt(x - cw / 2, y - ch, bitmap, src_rect)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● HP の文字色を取得
|
||||
#--------------------------------------------------------------------------
|
||||
def hp_color(actor)
|
||||
return knockout_color if actor.hp == 0
|
||||
return crisis_color if actor.hp < actor.mhp / 4
|
||||
return normal_color
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● MP の文字色を取得
|
||||
#--------------------------------------------------------------------------
|
||||
def mp_color(actor)
|
||||
return crisis_color if actor.mp < actor.mmp / 4
|
||||
return normal_color
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● TP の文字色を取得
|
||||
#--------------------------------------------------------------------------
|
||||
def tp_color(actor)
|
||||
return normal_color
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● アクターの歩行グラフィック描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_graphic(actor, x, y)
|
||||
draw_character(actor.character_name, actor.character_index, x, y)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● アクターの顔グラフィック描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_face(actor, x, y, enabled = true)
|
||||
draw_face(actor.face_name, actor.face_index, x, y, enabled)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 名前の描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_name(actor, x, y, width = 112)
|
||||
change_color(hp_color(actor))
|
||||
draw_text(x, y, width, line_height, actor.name)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 職業の描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_class(actor, x, y, width = 112)
|
||||
change_color(normal_color)
|
||||
draw_text(x, y, width, line_height, actor.class.name)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 二つ名の描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_nickname(actor, x, y, width = 180)
|
||||
change_color(normal_color)
|
||||
draw_text(x, y, width, line_height, actor.nickname)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● レベルの描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_level(actor, x, y)
|
||||
change_color(system_color)
|
||||
draw_text(x, y, 32, line_height, Vocab::level_a)
|
||||
change_color(normal_color)
|
||||
draw_text(x + 32, y, 24, line_height, actor.level, 2)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● ステートおよび強化/弱体のアイコンを描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_icons(actor, x, y, width = 96)
|
||||
icons = (actor.state_icons + actor.buff_icons)[0, width / 24]
|
||||
icons.each_with_index {|n, i| draw_icon(n, x + 24 * i, y) }
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 現在値/最大値を分数形式で描画
|
||||
# current : 現在値
|
||||
# max : 最大値
|
||||
# color1 : 現在値の色
|
||||
# color2 : 最大値の色
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_current_and_max_values(x, y, width, current, max, color1, color2)
|
||||
change_color(color1)
|
||||
xr = x + width
|
||||
if width < 96
|
||||
draw_text(xr - 40, y, 42, line_height, current, 2)
|
||||
else
|
||||
draw_text(xr - 92, y, 42, line_height, current, 2)
|
||||
change_color(color2)
|
||||
draw_text(xr - 52, y, 12, line_height, "/", 2)
|
||||
draw_text(xr - 42, y, 42, line_height, max, 2)
|
||||
end
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● HP の描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_hp(actor, x, y, width = 124)
|
||||
draw_gauge(x, y, width, actor.hp_rate, hp_gauge_color1, hp_gauge_color2)
|
||||
change_color(system_color)
|
||||
draw_text(x, y, 30, line_height, Vocab::hp_a)
|
||||
draw_current_and_max_values(x, y, width, actor.hp, actor.mhp,
|
||||
hp_color(actor), normal_color)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● MP の描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_mp(actor, x, y, width = 124)
|
||||
draw_gauge(x, y, width, actor.mp_rate, mp_gauge_color1, mp_gauge_color2)
|
||||
change_color(system_color)
|
||||
draw_text(x, y, 30, line_height, Vocab::mp_a)
|
||||
draw_current_and_max_values(x, y, width, actor.mp, actor.mmp,
|
||||
mp_color(actor), normal_color)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● TP の描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_tp(actor, x, y, width = 124)
|
||||
draw_gauge(x, y, width, actor.tp_rate, tp_gauge_color1, tp_gauge_color2)
|
||||
change_color(system_color)
|
||||
draw_text(x, y, 30, line_height, Vocab::tp_a)
|
||||
change_color(tp_color(actor))
|
||||
draw_text(x + width - 42, y, 42, line_height, actor.tp.to_i, 2)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● シンプルなステータスの描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_simple_status(actor, x, y)
|
||||
draw_actor_name(actor, x, y)
|
||||
draw_actor_level(actor, x, y + line_height * 1)
|
||||
draw_actor_icons(actor, x, y + line_height * 2)
|
||||
draw_actor_class(actor, x + 120, y)
|
||||
draw_actor_hp(actor, x + 120, y + line_height * 1)
|
||||
draw_actor_mp(actor, x + 120, y + line_height * 2)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 能力値の描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_actor_param(actor, x, y, param_id)
|
||||
change_color(system_color)
|
||||
draw_text(x, y, 120, line_height, Vocab::param(param_id))
|
||||
change_color(normal_color)
|
||||
draw_text(x + 120, y, 36, line_height, actor.param(param_id), 2)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● アイテム名の描画
|
||||
# enabled : 有効フラグ。false のとき半透明で描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_item_name(item, x, y, enabled = true, width = 172)
|
||||
return unless item
|
||||
draw_icon(item.icon_index, x, y, enabled)
|
||||
change_color(normal_color, enabled)
|
||||
draw_text(x + 24, y, width, line_height, item.name)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 通貨単位つき数値(所持金など)の描画
|
||||
#--------------------------------------------------------------------------
|
||||
def draw_currency_value(value, unit, x, y, width)
|
||||
cx = text_size(unit).width
|
||||
change_color(normal_color)
|
||||
draw_text(x, y, width - cx - 2, line_height, value, 2)
|
||||
change_color(system_color)
|
||||
draw_text(x, y, width, line_height, unit, 2)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 能力値変化の描画色取得
|
||||
#--------------------------------------------------------------------------
|
||||
def param_change_color(change)
|
||||
return power_up_color if change > 0
|
||||
return power_down_color if change < 0
|
||||
return normal_color
|
||||
end
|
||||
end
|
2723
Kawariki-patches/ports/debug/savebitmanwin32api.rb
Normal file
2723
Kawariki-patches/ports/debug/savebitmanwin32api.rb
Normal file
File diff suppressed because it is too large
Load diff
1351
Kawariki-patches/ports/dummyAudioUtilities.rb
Normal file
1351
Kawariki-patches/ports/dummyAudioUtilities.rb
Normal file
File diff suppressed because it is too large
Load diff
2510
Kawariki-patches/ports/dummyPSystem_Utilities.rb
Normal file
2510
Kawariki-patches/ports/dummyPSystem_Utilities.rb
Normal file
File diff suppressed because it is too large
Load diff
1745
Kawariki-patches/ports/dummy_Audio_EX2.rb
Normal file
1745
Kawariki-patches/ports/dummy_Audio_EX2.rb
Normal file
File diff suppressed because it is too large
Load diff
332
Kawariki-patches/ports/lamp.rb
Normal file
332
Kawariki-patches/ports/lamp.rb
Normal file
|
@ -0,0 +1,332 @@
|
|||
=begin
|
||||
HN_Light version 1.0.1.2 for VX Ace
|
||||
by 半生
|
||||
http://www.tktkgame.com
|
||||
|
||||
要HN_RG_BITMAP(ver 0.1.2.1以降)
|
||||
|
||||
2012/01/02 ver 1.0.1.2
|
||||
バグ修正
|
||||
2012/01/02 ver 1.0.1.0
|
||||
隊列歩行の仲間に対応
|
||||
|
||||
=end
|
||||
|
||||
# ----- ▽ 設定ここから ▽ -----
|
||||
module HN_Light
|
||||
# 簡略化 0:(メタボ)~2:(荒めだけど軽い)
|
||||
SIMPLIFY = 1
|
||||
|
||||
# プレイヤーの灯りタイプに使う変数番号
|
||||
PLAYER_LIGHT_TYPE = 48
|
||||
|
||||
# 仲間の灯りタイプに使う変数番号
|
||||
FOLLOWER_LIGHT_TYPE = 48
|
||||
|
||||
# 暗闇判定に使うスイッチ
|
||||
DARK_SWITCH = 9
|
||||
|
||||
# 灯りイベント識別用の正規表現
|
||||
REGEX_LIGHT = /@灯り(\d+)/
|
||||
|
||||
# 灯り画像のディレクトリ
|
||||
LIGHT_IMG_DIR = "Graphics/Pictures/"
|
||||
|
||||
# 灯りBitmap設定
|
||||
LIGHTS = [
|
||||
# [FILENAME, CELLS, ZOOM, OFFSET_Y, HUE]
|
||||
["light5", 1, 5.5, 0, 0],
|
||||
["light5", 1, 15.0, 0, 0],
|
||||
["light3", 1, 0.8, 0, 0],
|
||||
["light4", 1, 1.0, -16, 0],
|
||||
["light5", 1, 2.0, 0, 0],
|
||||
["light6", 1, 10.0, 0, 0],
|
||||
["light7", 1, 5.0, -16, 0],
|
||||
["light8", 1, 5.0, -16, 0],
|
||||
["light9", 1, 2.0, -16, 0],
|
||||
["light4", 1, 3.0, -16, 0],
|
||||
]
|
||||
end
|
||||
# ----- △ 設定ここまで △ -----
|
||||
|
||||
module HN_Light
|
||||
# イベントへのmix-in用
|
||||
module LightEvent
|
||||
attr_reader :light_type
|
||||
def initialize
|
||||
super()
|
||||
@light_type = 0
|
||||
end
|
||||
|
||||
def check_light
|
||||
@light_type = 0
|
||||
return if @list.nil?
|
||||
@list.each do |command|
|
||||
break if @light_type > 0
|
||||
if command.code == 108 or command.code == 408
|
||||
command.parameters.each do |line|
|
||||
if line =~ REGEX_LIGHT
|
||||
@light_type = $1.to_i
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end # END @list.each
|
||||
end
|
||||
|
||||
end # END module LightEvent
|
||||
|
||||
|
||||
class Light
|
||||
attr_reader :bitmap
|
||||
attr_reader :cells
|
||||
attr_reader :width
|
||||
attr_reader :height
|
||||
attr_reader :ox
|
||||
attr_reader :oy
|
||||
def initialize(light_type, s_zoom = 1)
|
||||
light = LIGHTS[light_type - 1]
|
||||
if light.nil?
|
||||
# 本来ならここには来ないはず
|
||||
@bitmap = Bitmap.new(32, 32)
|
||||
@cels = 1
|
||||
@zoom = 1.0
|
||||
@oy = 16
|
||||
@ox = 16
|
||||
@width = 32
|
||||
@height = 32
|
||||
else
|
||||
@bitmap = Bitmap.new(LIGHT_IMG_DIR + light[0])
|
||||
@bitmap.invert()
|
||||
@cells = light[1].to_i
|
||||
@cells = 1 if (@cells < 1 or @cells > @bitmap.width)
|
||||
@zoom = light[2].to_f
|
||||
@zoom = 1.0 if @zoom <= 0.0
|
||||
@zoom /= s_zoom
|
||||
@width = @bitmap.width / @cells
|
||||
@height = @bitmap.height
|
||||
|
||||
# 拡大縮小処理
|
||||
if @zoom != 1.0
|
||||
new_width = (@width * @zoom).round
|
||||
new_height = (@height * @zoom).round
|
||||
if new_width * new_height < 1
|
||||
@zoom = 1.0
|
||||
else
|
||||
@width = new_width
|
||||
@height = new_height
|
||||
new_bitmap = Bitmap.new(@width * @cells, @height)
|
||||
new_bitmap.stretch_blt(new_bitmap.rect,@bitmap, @bitmap.rect)
|
||||
@bitmap.dispose
|
||||
@bitmap = new_bitmap
|
||||
end
|
||||
end
|
||||
@ox = @width / 2
|
||||
@oy = @height / 2 - light[3].to_i / s_zoom
|
||||
|
||||
# 色相変換
|
||||
if ( (hue = light[4].to_i) != 0)
|
||||
@bitmap.hue_change(hue)
|
||||
end
|
||||
end
|
||||
end # End def initialize
|
||||
|
||||
# 終了処理
|
||||
def dispose
|
||||
@bitmap.dispose
|
||||
@bitmap = nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Game_Event
|
||||
include HN_Light::LightEvent
|
||||
alias :_hn_light__setup :setup_page unless method_defined?(:_hn_light__setup)
|
||||
def setup_page(new_page)
|
||||
_hn_light__setup(new_page)
|
||||
check_light()
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Player
|
||||
def light_type
|
||||
return $game_variables[HN_Light::PLAYER_LIGHT_TYPE]
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Follower
|
||||
def light_type
|
||||
return 0 if !self.visible?
|
||||
return $game_variables[HN_Light::FOLLOWER_LIGHT_TYPE]
|
||||
end
|
||||
end
|
||||
|
||||
class Game_Map
|
||||
attr_reader :light_events
|
||||
|
||||
# 灯りイベントリストの更新
|
||||
def refresh_lights
|
||||
@light_events = []
|
||||
@events.values.each do |event|
|
||||
if (event.light_type > 0)
|
||||
@light_events.push(event)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
alias :_hn_light__setup_events :setup_events unless method_defined?(:_hn_light__setup_events)
|
||||
def setup_events
|
||||
_hn_light__setup_events()
|
||||
refresh_lights()
|
||||
end
|
||||
|
||||
alias :_hn_light__refresh :refresh unless method_defined?(:_hn_light__refresh)
|
||||
def refresh
|
||||
_hn_light__refresh()
|
||||
refresh_lights()
|
||||
end
|
||||
end
|
||||
|
||||
class Sprite_Dark < Sprite
|
||||
@@base_color = Color.new(255,255,255)
|
||||
|
||||
def initialize(viewport = nil)
|
||||
super(viewport)
|
||||
@width = Graphics.width
|
||||
@height = Graphics.height
|
||||
|
||||
case HN_Light::SIMPLIFY
|
||||
when 1
|
||||
@zoom = 2
|
||||
when 2
|
||||
@zoom = 4
|
||||
else
|
||||
@zoom = 1
|
||||
end
|
||||
@width /= @zoom
|
||||
@height /= @zoom
|
||||
self.zoom_x = @zoom.to_f
|
||||
self.zoom_y = @zoom.to_f
|
||||
|
||||
self.bitmap = Bitmap.new(@width, @height)
|
||||
self.bitmap.fill_rect(self.bitmap.rect, @@base_color)
|
||||
self.blend_type = 2 # ブレンドタイプ(減算)
|
||||
self.z = 500
|
||||
self.visible = false
|
||||
@light_cache = {}
|
||||
end
|
||||
|
||||
# 灯りを追加する
|
||||
def add_light(charactor)
|
||||
return if charactor.nil?
|
||||
light_type = charactor.light_type
|
||||
return if (light_type < 1 or light_type > HN_Light::LIGHTS.size)
|
||||
unless @light_cache.key?(light_type)
|
||||
@light_cache[light_type] = HN_Light::Light.new(light_type, @zoom)
|
||||
end
|
||||
light = @light_cache[light_type]
|
||||
|
||||
# 画面外の場合は何もしない
|
||||
if @zoom == 1
|
||||
return if (charactor.screen_x < 0 - light.width + light.ox)
|
||||
return if (charactor.screen_x > @width + light.ox)
|
||||
return if (charactor.screen_y < 0 - light.height + light.oy)
|
||||
return if (charactor.screen_y > @height + light.oy)
|
||||
else
|
||||
return if (charactor.screen_x < 0 - (light.width + light.ox) * @zoom)
|
||||
return if (charactor.screen_x > (@width + light.ox) * @zoom)
|
||||
return if (charactor.screen_y < 0 - (light.height + light.oy) * @zoom)
|
||||
return if (charactor.screen_y > (@height + light.oy) * @zoom)
|
||||
end
|
||||
|
||||
# アニメーション判定
|
||||
if light.cells > 1
|
||||
index = (Graphics.frame_count / 4) % light.cells
|
||||
rect = Rect.new(index * light.width , 0, light.width, light.height)
|
||||
else
|
||||
rect = light.bitmap.rect
|
||||
end
|
||||
if @zoom != 1
|
||||
p_x = charactor.screen_x / @zoom - light.ox
|
||||
p_y = (charactor.screen_y - 16) / @zoom - light.oy
|
||||
else
|
||||
p_x = charactor.screen_x - light.ox
|
||||
p_y = charactor.screen_y - 16 - light.oy
|
||||
end
|
||||
|
||||
# 乗算合成(3)
|
||||
self.bitmap.blend_blt(p_x, p_y, light.bitmap, rect, 3)
|
||||
end
|
||||
|
||||
|
||||
def refresh
|
||||
self.bitmap.fill_rect(self.bitmap.rect, @@base_color)
|
||||
$game_map.light_events.each do |event|
|
||||
next if HN_Light::LIGHTS[event.light_type - 1].nil?
|
||||
add_light(event)
|
||||
end
|
||||
add_light($game_player)
|
||||
$game_player.followers.each{|f| add_light(f)}
|
||||
end
|
||||
|
||||
# 更新
|
||||
def update
|
||||
super
|
||||
refresh()
|
||||
end
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 解放
|
||||
#--------------------------------------------------------------------------
|
||||
def dispose
|
||||
self.bitmap.dispose
|
||||
@light_cache.values.each do |light|
|
||||
light.dispose
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Spriteset_Map
|
||||
# 暗闇スプライトの作成
|
||||
def create_dark
|
||||
@dark_sprite = Sprite_Dark.new(@viewport1)
|
||||
end
|
||||
|
||||
# 暗闇スプライトの更新
|
||||
def update_dark
|
||||
if (@dark_sprite.visible = $game_switches[HN_Light::DARK_SWITCH])
|
||||
# @dark_sprite.update
|
||||
@dark_sprite.dispose
|
||||
end
|
||||
end
|
||||
|
||||
# 暗闇スプライトの破棄
|
||||
def dispose_dark
|
||||
@dark_sprite.dispose
|
||||
end
|
||||
|
||||
# 初期化
|
||||
alias :_dark__initialize :initialize unless private_method_defined?(:_dark__initialize)
|
||||
def initialize
|
||||
_dark__initialize()
|
||||
create_dark()
|
||||
update_dark()
|
||||
end
|
||||
|
||||
# 更新
|
||||
alias :_dark__update :update unless method_defined?(:_dark__update)
|
||||
def update
|
||||
_dark__update()
|
||||
update_dark() if !@dark_sprite.nil? and !@dark_sprite.disposed?
|
||||
end
|
||||
|
||||
# 終了処理
|
||||
alias :_dark__dispose :dispose unless method_defined?(:_dark__dispose)
|
||||
def dispose
|
||||
dispose_dark()
|
||||
_dark__dispose()
|
||||
end
|
||||
end
|
1092
Kawariki-patches/ports/message_npi.rb
Normal file
1092
Kawariki-patches/ports/message_npi.rb
Normal file
File diff suppressed because it is too large
Load diff
1080
Kawariki-patches/ports/testencode.rb
Normal file
1080
Kawariki-patches/ports/testencode.rb
Normal file
File diff suppressed because it is too large
Load diff
195
Kawariki-patches/ports/wxexittest.rb
Normal file
195
Kawariki-patches/ports/wxexittest.rb
Normal file
|
@ -0,0 +1,195 @@
|
|||
# ===========================================================================
|
||||
# ★ WF-RGSS Scripts ★
|
||||
# Exit-EX 終了処理スクリプト(共通実行スクリプト VXAce版)
|
||||
# バージョン : rev-2.1 (2012-1-24)
|
||||
# 作者 : A Crying Minister (WHITE-FLUTE)
|
||||
# サポート先URI: http://www.whiteflute.org/wfrgss/
|
||||
# ---------------------------------------------------------------------------
|
||||
# 機能:
|
||||
# ・VXAceの終了処理をXP/VX形式(SystemExit送出)に設定します。
|
||||
# ・VXAceに限り、共通実行スクリプトと同様に使えます。
|
||||
# ---------------------------------------------------------------------------
|
||||
# 設置場所 :Mainセクション(一番最後)に上書き
|
||||
# または、Mainセクションの直前
|
||||
# 必要スクリプト:
|
||||
# ・共通スクリプト
|
||||
# 必要DLL
|
||||
# ・WFExit.dll
|
||||
# 注意事項:
|
||||
# ▽ 共通スクリプトが必要です。
|
||||
# 改造して使用することを推奨しますが、そのまま使ってもOKです。
|
||||
# ▽ デバッグモードでエラーを記録する場合、
|
||||
# 現在のユーザで書き込みを行えることが必要になります。
|
||||
# ▽ スクリプトが実行されます。これ以降のセクションは実行されません。
|
||||
#==============================================================================
|
||||
# ◆ Main ( Execute )
|
||||
#------------------------------------------------------------------------------
|
||||
# 各クラスの定義が終わった後、ここから実際の処理が始まります。
|
||||
#==============================================================================
|
||||
#module Exit
|
||||
# # ---------------------------------------------------------------------------
|
||||
# # ◆ カスタマイズポイント セットアップ処理を記述します。
|
||||
# # ---------------------------------------------------------------------------
|
||||
# def self.setup
|
||||
# end
|
||||
# # ---------------------------------------------------------------------------
|
||||
# # ◆ カスタマイズポイント 解放処理を記述します。
|
||||
# # ---------------------------------------------------------------------------
|
||||
# def self.dispose
|
||||
# DataManager.save_system
|
||||
# end
|
||||
#end
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ 以下の内容は変更する必要はありません。
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
#==============================================================================
|
||||
# ◆ Exit モジュール
|
||||
#------------------------------------------------------------------------------
|
||||
def hook_exit()
|
||||
# Simulate what the hookExit function might do
|
||||
# puts "Simulated hookExit called with parameter:"
|
||||
# You can add more simulated behavior here, like logging, altering global variables, etc.
|
||||
end
|
||||
module Exit
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ 処理実行
|
||||
# ---------------------------------------------------------------------------
|
||||
begin
|
||||
@@hook = method(:hook_exit)
|
||||
@@exit = method(:hook_exit)
|
||||
@@quit = method(:hook_exit)
|
||||
@@reset = method(:hook_exit)
|
||||
@@clear = method(:hook_exit)
|
||||
|
||||
#@@hook = Win32API.new('System/WFExit','hookExit','v','l')
|
||||
#@@exit = Win32API.new('System/WFExit','getToExit','v','l')
|
||||
#@@quit = Win32API.new('System/WFExit','Quit','v','v')
|
||||
#@@reset = Win32API.new('System/WFExit','getToReset','v','l')
|
||||
#@@clear = Win32API.new('System/WFExit','clearReset','v','v')
|
||||
rescue Exception
|
||||
raise if $TEST
|
||||
raise( LoadError , "cannot read modules.(WFExit.dll)")
|
||||
end
|
||||
@@hook.call()
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ 終了を監視する
|
||||
# ---------------------------------------------------------------------------
|
||||
def self.toexit
|
||||
raise SystemExit.new(0) if @@exit.call() == 1
|
||||
end
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ F12リセットを監視する
|
||||
# ---------------------------------------------------------------------------
|
||||
def self.toreset
|
||||
raise RGSSReset if @duration && @duration <= 0 if @@reset.call() == 1
|
||||
if @duration && @duration > 0
|
||||
@duration -= 1
|
||||
@@clear.call()
|
||||
end
|
||||
end
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ 本当の終了処理
|
||||
# ---------------------------------------------------------------------------
|
||||
def self.quit
|
||||
@@quit.call()
|
||||
end
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ リセットカウントをクリア
|
||||
# ---------------------------------------------------------------------------
|
||||
def self.clearreset(wait = false)
|
||||
@@clear.call()
|
||||
@duration = wait ? 120 : 0
|
||||
end
|
||||
end
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ 終了監視をセット
|
||||
# ---------------------------------------------------------------------------
|
||||
class << Graphics
|
||||
alias __wfexit_uodate__ update
|
||||
def Graphics.update
|
||||
__wfexit_uodate__
|
||||
Exit.toexit
|
||||
Exit.toreset
|
||||
end
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ セットアップをセット
|
||||
# ---------------------------------------------------------------------------
|
||||
class << SceneManager
|
||||
alias __wfexit_run__ run
|
||||
#--------------------------------------------------------------------------
|
||||
# ● 実行
|
||||
#--------------------------------------------------------------------------
|
||||
def SceneManager.run
|
||||
if Exit.respond_to?(:setup)
|
||||
Exit.setup
|
||||
end
|
||||
Exit.clearreset(true)
|
||||
__wfexit_run__
|
||||
end
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ◆ 処理実行
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
begin
|
||||
rgss_main { SceneManager.run }
|
||||
# 以下、例外処理
|
||||
rescue BugDetected, InternalBugDetected => errobj
|
||||
begin
|
||||
MessageBox.fatalerror( errobj )
|
||||
raise SystemExit.new(1)
|
||||
rescue Hangup
|
||||
nil
|
||||
end
|
||||
|
||||
rescue SyntaxError => errobj
|
||||
# -------------------------------------------------------------------------
|
||||
# ◆ 例外 SyntaxError
|
||||
# -------------------------------------------------------------------------
|
||||
# この例外はバグかセットアップが適切にされていない状況で無い限り、
|
||||
# 補足されることはない
|
||||
begin
|
||||
raise( BugDetected,
|
||||
"[FATAL] The invalidated exception was detected. \n\n" +
|
||||
"Exception:\n#{errobj}")
|
||||
rescue BugDetected => errobj
|
||||
begin
|
||||
MessageBox.fatalerror( errobj )
|
||||
raise SystemExit.new(1)
|
||||
rescue Hangup
|
||||
nil
|
||||
end
|
||||
end
|
||||
rescue SystemExit
|
||||
# 終了を補足する。エラーメッセージに書き加えない。
|
||||
rescue Exception => errobj
|
||||
# -------------------------------------------------------------------------
|
||||
# ◆ 例外処理
|
||||
# 特に指定されていない例外を補足します。
|
||||
# ※ rev-2 より、Errno::ENOENT もここで補足します。
|
||||
# -------------------------------------------------------------------------
|
||||
begin
|
||||
MessageBox.fatalerror( errobj )
|
||||
raise SystemExit.new(1)
|
||||
rescue Hangup
|
||||
nil
|
||||
end
|
||||
|
||||
ensure
|
||||
# -------------------------------------------------------------------------
|
||||
# ● 後処理
|
||||
# -------------------------------------------------------------------------
|
||||
# 後処理を担当します。
|
||||
# スクリプト内容によってはここで解放処理が必要になることがあります。
|
||||
if Exit.respond_to?(:dispose)
|
||||
Exit.dispose
|
||||
# ★ ----------------------------------------------------------------------
|
||||
Exit.quit # フックを解放する。実行しないと終了しない危険性大
|
||||
end
|
||||
end
|
||||
|
||||
exit # Mainセクションが後に控えている時に処理が渡らないようにする
|
709
Kawariki-patches/preload.rb
Normal file
709
Kawariki-patches/preload.rb
Normal file
|
@ -0,0 +1,709 @@
|
|||
# Kawariki MKXP preload infrastructure
|
||||
|
||||
module Preload
|
||||
# Kawariki mkxp resources location
|
||||
Path = File.dirname __FILE__
|
||||
|
||||
# Require common libs
|
||||
def self.require(name)
|
||||
Kernel.require File.join(Path, "libs", name)
|
||||
end
|
||||
|
||||
module Common
|
||||
# In RMXP mode, Kernel.print opens message boxes
|
||||
def print(text)
|
||||
STDOUT.puts("[preload] " + text.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
extend Common
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Patches
|
||||
# -------------------------------------------------------------------------
|
||||
class Context
|
||||
include Common
|
||||
|
||||
def initialize(scripts)
|
||||
@scripts = scripts
|
||||
@script_instances = {}
|
||||
@options = {}
|
||||
@blacklist = []
|
||||
@delay = {}
|
||||
@script_id_digits = Math.log10(scripts.size).ceil
|
||||
end
|
||||
|
||||
attr_reader :script_id_digits, :script_loc_format
|
||||
|
||||
# Scripts
|
||||
def script(i)
|
||||
@script_instances[i] ||= Script.new self, i, @scripts[i]
|
||||
end
|
||||
|
||||
def script_count
|
||||
@scripts.size
|
||||
end
|
||||
|
||||
def each_script
|
||||
(0...@scripts.size).each {|i| yield script i}
|
||||
end
|
||||
|
||||
def last_script
|
||||
script (script_count - 1)
|
||||
end
|
||||
|
||||
def script_loc(scriptid)
|
||||
return script(scriptid).loc
|
||||
end
|
||||
|
||||
def blacklisted?(script)
|
||||
@blacklist.include? script.name
|
||||
end
|
||||
|
||||
# def add_script(name, code)
|
||||
# # Find an empty script slot (if any) to reuse (check for empty string)
|
||||
# empty_slot = @scripts.find { |script| script[0].is_a?(String) && script[0].empty? }
|
||||
#
|
||||
# if empty_slot
|
||||
# # Reuse the empty slot
|
||||
# empty_slot[0] = name # Set the script name
|
||||
# empty_slot[3] = code # Set the script code
|
||||
# else
|
||||
# # No empty slot found, so we pop the last script and push a new one
|
||||
# @scripts.pop
|
||||
# @scripts.push [name, "", nil, code]
|
||||
# end
|
||||
# end
|
||||
def add_script(name, code)
|
||||
# Find the first empty slot (check for empty string) that is not the last slot
|
||||
empty_slot = @scripts.find { |script| script[0].is_a?(String) && script[0].empty? && @scripts.index(script) < @scripts.length - 1 }
|
||||
|
||||
if empty_slot
|
||||
# Reuse the empty slot and replace it with the new script
|
||||
empty_slot[0] = name # Set the script name
|
||||
empty_slot[3] = code # Set the script code
|
||||
else
|
||||
# No empty slot found, so insert the new script 5 positions before the end
|
||||
insert_index = [@scripts.length - 5, 0].max # Ensure the index is not negative
|
||||
@scripts.insert(insert_index, [name, "", nil, code])
|
||||
end
|
||||
end
|
||||
# def add_script(name, code)
|
||||
# @scripts.pop
|
||||
# @scripts.push [name, "", nil, code]
|
||||
# # TODO: Find an empty script to canibalize instead
|
||||
# end
|
||||
|
||||
# Read options from environment
|
||||
FalseEnvValues = [nil, "", "0", "no"]
|
||||
def read_env(env=ENV)
|
||||
env_bool = ->(name) {!FalseEnvValues.include?(env[name])}
|
||||
env_str = ->(name) {e = env[name]; e unless e == ""}
|
||||
env_list = ->(name, delim) {e = env[name]; e.nil? ? [] : e.split(delim)}
|
||||
|
||||
set :dump_scripts_raw, env_str.("KAWARIKI_MKXP_DUMP_SCRIPTS")
|
||||
set :dump_scripts_patched, env_str.("KAWARIKI_MKXP_DUMP_PATCHED_SCRIPTS")
|
||||
mark :dont_run_game if env_bool.("KAWARIKI_MKXP_DRY_RUN")
|
||||
mark :no_font_effects if env_bool.("KAWARIKI_MKXP_NO_FONT_EFFECTS")
|
||||
@blacklist = env_list.("KAWARIKI_MKXP_FILTER_SCRIPTS", ",")
|
||||
end
|
||||
|
||||
def read_system(system=System)
|
||||
# TODO: Non mkxp-z variants
|
||||
set :mkxp_version, system::VERSION
|
||||
set :mkxp_version_tuple, (system::VERSION.split ".").map{|d| d.to_i}
|
||||
|
||||
if (self[:mkxp_version_tuple] <=> [2, 4]) >= 0 then
|
||||
mark :mkxpz_24
|
||||
_config = CFG
|
||||
else
|
||||
_config = system::CONFIG
|
||||
end
|
||||
# set :rgss_version, _config["rgssVersion"].to_i
|
||||
# puts "jj"+_config["gameFolder"].to_s
|
||||
# Preload.require "PreloadIni.rb"
|
||||
# puts "vvv"+ENV["rpgvers"]
|
||||
set :rgss_version, ENV["rpgvers"].to_i
|
||||
|
||||
# puts self[:zeusrpgver]
|
||||
# puts vcode
|
||||
if defined?(RGSS_VERSION) && RGSS_VERSION == "3.0.1" then
|
||||
# See mkxp-z/mri-binding.cpp
|
||||
# puts "vvv"+RGSS_VERSION
|
||||
set :rgss_version, 3
|
||||
end
|
||||
|
||||
# FIXME: can this be reliably retrieved from MKXP if set to 0 in config?
|
||||
if self[:rgss_version] == 0 then
|
||||
print "Warning: rgssVersion not set in MKXP config. Are you running mkxp directly?"
|
||||
if RGSS_VERSION == "3.0.1" then
|
||||
# See mkxp-z/mri-binding.cpp
|
||||
set :rgss_version, 3
|
||||
else
|
||||
print "Warning: Cannot guess RGSS version. Kawariki should automatically set it correctly."
|
||||
end
|
||||
end
|
||||
if self[:mkxp_version] == "MKXPZ_VERSION" then
|
||||
print "Note: Using mkxp-z with broken System::VERSION reporting. Cannot detect real mkxp-z version"
|
||||
set :mkxp_version, "mkxp-z"
|
||||
end
|
||||
end
|
||||
|
||||
# Options
|
||||
def set(sym, value=true)
|
||||
@options.store sym, value unless value.nil?
|
||||
end
|
||||
|
||||
def [](sym)
|
||||
@options[sym]
|
||||
end
|
||||
|
||||
def mark(*flags)
|
||||
flags.each{|flag| set flag, true}
|
||||
end
|
||||
|
||||
def flag?(flag)
|
||||
@options.key? flag
|
||||
end
|
||||
|
||||
# Delay
|
||||
DelaySlots = [:after_patches]
|
||||
|
||||
def delay(slot, &p)
|
||||
raise "Unknown delay slot #{slot}" unless DelaySlots.include? slot
|
||||
@delay[slot] = [] unless @delay.key? slot
|
||||
@delay[slot].push p
|
||||
end
|
||||
|
||||
def run_delay_slot(slot, *args)
|
||||
raise "Unknown delay slot #{slot}" unless DelaySlots.include? slot
|
||||
if @delay[slot] then
|
||||
@delay[slot].each {|p| p.call(self, *args)}
|
||||
@delay.delete slot
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Script
|
||||
|
||||
def initialize(context, i, script)
|
||||
@context = context
|
||||
@index = i
|
||||
@script = script
|
||||
@log = []
|
||||
end
|
||||
|
||||
attr_reader :context
|
||||
attr_reader :index
|
||||
|
||||
def log(msg=nil)
|
||||
@log.push msg unless msg.nil? || @log.last == msg
|
||||
@log
|
||||
end
|
||||
|
||||
def loc
|
||||
"##{index.to_s.rjust @context.script_id_digits} '#{name}'"
|
||||
end
|
||||
|
||||
def [](i)
|
||||
@script[i]
|
||||
end
|
||||
|
||||
def name
|
||||
@script[1]
|
||||
end
|
||||
|
||||
|
||||
def source
|
||||
@script[3]
|
||||
end
|
||||
|
||||
def sub!(*p)
|
||||
@script[3].gsub!(*p)
|
||||
end
|
||||
|
||||
|
||||
def source=(code)
|
||||
@script[3] = code
|
||||
end
|
||||
|
||||
def load_file(path)
|
||||
log "replaced with #{File.basename path}"
|
||||
@script[3] = File.read(path)
|
||||
end
|
||||
|
||||
def remove
|
||||
log "removed"
|
||||
@script[3] = ""
|
||||
end
|
||||
|
||||
# Extract $imported key only once
|
||||
# $imported['Hello'] = 1
|
||||
# $imported[:Hello] = true
|
||||
# ($imported ||= {})["Hello"] = true
|
||||
# Type (String/Symbol) is preserved
|
||||
ImportedKeyExpr = /^\s*(?:\$imported|\(\s*\$imported(?:\s*\|\|=\s*\{\s*\})?\s*\))\[(:\w+|'[^']+'|"[^"]+")\]\s*=\s*(.+)\s*$/
|
||||
|
||||
def _extract_imported
|
||||
if source.nil?
|
||||
puts "Warning: 'source' is nil at the beginning of _extract_imported"
|
||||
return
|
||||
end
|
||||
|
||||
# Ensure 'source' is a string, and log the class type if it's not
|
||||
unless source.is_a?(String)
|
||||
puts "Warning: 'source' is not a string, it's a #{source.class}!"
|
||||
return
|
||||
end
|
||||
|
||||
# Log the encoding type for debugging purposes
|
||||
# puts "Source encoding before: #{source.encoding.name}"
|
||||
|
||||
# Force early return if source is unexpectedly nil just before encoding
|
||||
if source.nil?
|
||||
puts "Warning: 'source' unexpectedly nil before encoding"
|
||||
return
|
||||
end
|
||||
|
||||
# Backup the original source value before encoding, to see if it changes unexpectedly
|
||||
original_source = source.dup
|
||||
|
||||
# Force encode to ASCII-8BIT (binary ASCII), replacing non-ASCII characters with '?'
|
||||
if source.encoding.name != "ASCII-8BIT"
|
||||
begin
|
||||
# puts "Attempting to encode source..."
|
||||
# Try encoding, but ensure that source remains unchanged if encoding fails
|
||||
encoded_source = source.encode("ASCII-8BIT", invalid: :replace, undef: :replace, replace: "?")
|
||||
|
||||
# If encoding results in an empty string or nil, restore original source
|
||||
if encoded_source.nil? || encoded_source.empty?
|
||||
# puts "Warning: 'source' became nil or empty after encoding! Reverting to original source."
|
||||
source = original_source
|
||||
return
|
||||
else
|
||||
# Otherwise, use the encoded result
|
||||
source = encoded_source
|
||||
end
|
||||
|
||||
# puts "Encoding successful, source encoding is now: #{source.encoding.name}"
|
||||
rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError => e
|
||||
puts "Encoding failed: #{e.message}"
|
||||
return
|
||||
rescue StandardError => e
|
||||
puts "Unexpected error during encoding: #{e.message}"
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# Check source after encoding to ensure it isn't nil
|
||||
if source.nil?
|
||||
# puts "Warning: 'source' is nil after encoding!"
|
||||
return
|
||||
end
|
||||
|
||||
# After encoding (or skipping), match the regex pattern
|
||||
match = ImportedKeyExpr.match(source)
|
||||
|
||||
# Check if a match was found
|
||||
@imported_entry = !match.nil?
|
||||
|
||||
return unless @imported_entry
|
||||
|
||||
# Extract the imported key and value from the match result
|
||||
@imported_key = match[1][0] == ':' ? match[1][1..].to_sym : match[1][1...-1]
|
||||
@imported_value = match[2]
|
||||
|
||||
end
|
||||
|
||||
def imported_entry?
|
||||
_extract_imported if @imported_entry.nil?
|
||||
@imported_entry
|
||||
end
|
||||
|
||||
def imported_key
|
||||
_extract_imported if @imported_entry.nil?
|
||||
@imported_key
|
||||
end
|
||||
|
||||
def imported_value
|
||||
_extract_imported if @imported_entry.nil?
|
||||
@imported_value
|
||||
end
|
||||
end
|
||||
|
||||
class Patch
|
||||
include Common
|
||||
|
||||
def initialize(desc=nil)
|
||||
@description = desc
|
||||
@conditions = []
|
||||
@actions = []
|
||||
@terminal = false
|
||||
end
|
||||
|
||||
def is_applicable(script)
|
||||
return @conditions.all? {|cond| cond.call(script)}
|
||||
end
|
||||
|
||||
def apply(script)
|
||||
print "Patch #{script.loc}: #{@description}"
|
||||
@actions.each {|action| action.call script}
|
||||
@terminal
|
||||
end
|
||||
|
||||
def eval(script)
|
||||
apply script if is_applicable script
|
||||
end
|
||||
|
||||
# --- Conditions ---
|
||||
# Arbitrary condition
|
||||
def if?(&p)
|
||||
@conditions.push p
|
||||
self
|
||||
end
|
||||
|
||||
# Source code contains text
|
||||
def include?(str)
|
||||
# XXX: maybe should restrict this to the start of the script for performance?
|
||||
if? {|script| script.source.include? str}
|
||||
end
|
||||
|
||||
# Source code matches (any) pattern
|
||||
def match?(*ps)
|
||||
pattern = Regexp.union(*ps)
|
||||
if? {|script| script.source.match? pattern}
|
||||
end
|
||||
|
||||
# Script sets $imported[key]
|
||||
def imported?(key)
|
||||
if? {|script| script.imported_key == key}
|
||||
end
|
||||
|
||||
# Global flag set
|
||||
def flag?(flag)
|
||||
if? {|script| script.context.flag? flag}
|
||||
end
|
||||
|
||||
# --- Actions ---
|
||||
# Arbitrary action
|
||||
def then!(&p)
|
||||
@actions.push p
|
||||
self
|
||||
end
|
||||
|
||||
# Run arbitrary action later
|
||||
def delay!(slot, &p)
|
||||
@actions.push proc{|script|script.context.delay(slot, &p)}
|
||||
self
|
||||
end
|
||||
|
||||
# Substitute text
|
||||
def sub!(pattern, replacement)
|
||||
@actions.push proc{|script| script.source.gsub! pattern, replacement}
|
||||
self
|
||||
end
|
||||
|
||||
# Set a global flag for later reference
|
||||
def flag!(*flags)
|
||||
@actions.push proc{|script| script.context.mark *flags}
|
||||
self
|
||||
end
|
||||
|
||||
# Remove the script (terminal)
|
||||
def remove!
|
||||
@actions.push proc{|script| script.remove }
|
||||
@terminal = true
|
||||
self
|
||||
end
|
||||
|
||||
# Replace the whole script with a file from ports/ (terminal)
|
||||
def replace!(filename)
|
||||
puts filename
|
||||
@actions.push proc{|script| script.load_file File.join(Path, "ports", filename)}
|
||||
@terminal = true
|
||||
self
|
||||
end
|
||||
|
||||
# Stop processing this script if patch is applicable (terminal)
|
||||
def next!
|
||||
@terminal = true
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Apply Patches
|
||||
# -------------------------------------------------------------------------
|
||||
class ClassInfo
|
||||
include Common
|
||||
|
||||
def initialize(name, script, supername)
|
||||
@name = name
|
||||
@defs = [[script, supername]]
|
||||
@superdef = 0
|
||||
end
|
||||
|
||||
attr_reader :name
|
||||
attr_reader :defs
|
||||
|
||||
def first_script
|
||||
return @defs[0][0]
|
||||
end
|
||||
|
||||
def super_name
|
||||
return @defs[@superdef][1]
|
||||
end
|
||||
|
||||
def super_script
|
||||
return @defs[@superdef][0]
|
||||
end
|
||||
|
||||
def first_loc
|
||||
return first_script.loc
|
||||
end
|
||||
|
||||
def super_loc
|
||||
return super_script.loc
|
||||
end
|
||||
|
||||
def add_definition(script, supername)
|
||||
if !supername.nil? && super_name != supername then
|
||||
print "Warning: Redefinition of class '#{name}' in #{script.loc} with inconsistent superclass '#{supername}'. Previous definition in #{super_loc} has superclass '#{super_name}'"
|
||||
@superdef = @defs.size
|
||||
end
|
||||
@defs.push [script, supername]
|
||||
end
|
||||
|
||||
def inconsistent?
|
||||
return @superdef > 0
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_class_defs(ctx)
|
||||
classes = {}
|
||||
expr = /^class\s+(\w+)\s*(?:<\s*(\w+)\s*)?$/
|
||||
ctx.each_script do |script|
|
||||
# Encoding is all kinds of messed up in RM
|
||||
e = script.source.encoding
|
||||
script.source.force_encoding Encoding.find("ASCII-8BIT")
|
||||
script.source.scan(expr) do |groups|
|
||||
name, supername = *groups
|
||||
if !classes.include? name then
|
||||
classes[name] = ClassInfo.new name, script, supername
|
||||
else
|
||||
classes[name].add_definition script, supername
|
||||
end
|
||||
end
|
||||
script.source.force_encoding e
|
||||
end
|
||||
return classes
|
||||
end
|
||||
|
||||
def self.overwrite_redefinitions(ctx)
|
||||
classes = get_class_defs ctx
|
||||
classes.each_pair do |name, cls|
|
||||
if cls.inconsistent? then
|
||||
print "Eliminating definitions of class '#{name}' before #{cls.super_loc}. First in #{cls.first_loc}"
|
||||
cls.super_script.sub!(Regexp.new("^(class\\s+#{name}\\s*<\\s*#{cls.super_name}\\s*)$"),
|
||||
"Object.remove_const :#{name}\n\\1")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.patch_scripts(ctx)
|
||||
ctx.each_script do |script|
|
||||
# Remove blacklisted scripts
|
||||
if ctx.blacklisted? script then
|
||||
print "Removed #{script.loc}: Blacklisted"
|
||||
script.remove
|
||||
next
|
||||
end
|
||||
# Encodings are a mess in RGSS. Can break Regexp matching
|
||||
e = script.source.encoding
|
||||
script.source.force_encoding "ASCII-8BIT"
|
||||
# Apply patches
|
||||
script.source.gsub!(".encode('SHIFT_JIS')", '')
|
||||
|
||||
Patches.each do |patch|
|
||||
break if patch.eval script
|
||||
end
|
||||
print "Patched #{script.loc}: #{script.log.join(', ')}" if script.log.size > 0
|
||||
# Warn if Win32API references in source
|
||||
if script.source.include? "Win32API.new" then
|
||||
|
||||
print "Warning: Script #{script.loc} uses Win32API."
|
||||
script.source.gsub!(/class\s+Win32API/, 'module Win32API')
|
||||
require "Win32API.rb"
|
||||
end
|
||||
# Restore encoding
|
||||
script.source.force_encoding e
|
||||
end
|
||||
ctx.run_delay_slot :after_patches
|
||||
end
|
||||
|
||||
NoFilenameChars = "/$|*#="
|
||||
|
||||
def self.dump_scripts(ctx, opt)
|
||||
# Dump all scripts to a folder specified by opt
|
||||
if ctx.flag? opt then
|
||||
dump = ctx[opt]
|
||||
print "Dumping all scripts to %s" % dump
|
||||
Dir.mkdir dump unless Dir.exist? dump
|
||||
fn_format = "%0#{ctx.script_id_digits}d%s%s%s"
|
||||
ctx.each_script do |script|
|
||||
filename = fn_format % [script.index,
|
||||
script.name.empty? ? "" : " ",
|
||||
script.name.tr(NoFilenameChars, "_"),
|
||||
script.source.empty? ? "" : ".rb"]
|
||||
File.write File.join(dump, filename), script.source
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Logic
|
||||
# -------------------------------------------------------------------------
|
||||
RgssVersionNames = ["Unknown", "XP", "VX", "VX Ace"]
|
||||
|
||||
|
||||
|
||||
@on_preload = []
|
||||
@on_load = []
|
||||
@on_boot = []
|
||||
@ctx = nil
|
||||
|
||||
def self._run_preload
|
||||
# Initialize
|
||||
@ctx = ctx = Context.new $RGSS_SCRIPTS
|
||||
# ctx.add_script("5555555555555555555555555555555555555555Script1", "puts 'Hello, world!'")
|
||||
ctx.read_system
|
||||
ctx.read_env
|
||||
|
||||
# Preload[:vcode] = vcode
|
||||
# Preload.Context.set(:vscode, vcode)
|
||||
# puts vcode
|
||||
# set :zeusrpgver, vcode
|
||||
# set :zeusrpgver, vcode
|
||||
# puts vcode
|
||||
# set :zeusrpgver, vcode
|
||||
# print "#{ctx[:zeusrpgver]}"
|
||||
print "MKXP mkxp-z #{ctx[:mkxp_version]} RGSS #{ctx[:rgss_version]} (#{RgssVersionNames[ctx[:rgss_version]]})\n"
|
||||
# Run preload hooks
|
||||
@on_preload.each{|p| p.call ctx}
|
||||
ctx.each_script do |script|
|
||||
print "Script ##{script.index}: #{script.name}#{"\t[#{script.imported_key}]" if script.imported_key}"
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Patch Scripts
|
||||
dump_scripts ctx, :dump_scripts_raw
|
||||
patch_scripts ctx
|
||||
overwrite_redefinitions ctx if ctx.flag? :redefinitions_overwrite_class
|
||||
dump_scripts ctx, :dump_scripts_patched
|
||||
# Try to inject hook after most (plugin) scripts are loaded but before game starts
|
||||
ctx.last_script.source= "Preload._run_boot\n\n" + ctx.last_script.source
|
||||
# ctx.add_script('cheat1', File.read(script_file, encoding: 'ASCII-8BIT')) if File.exist?(script_file)
|
||||
# ctx.add_script('cheat2', File.read(script_file2)) if File.exist?(script_file2)
|
||||
|
||||
# Done
|
||||
if ctx.flag? :dont_run_game then
|
||||
print "KAWARIKI_MKXP_DRY_RUN is set, not continuing to game code"
|
||||
exit 123
|
||||
end
|
||||
end
|
||||
|
||||
def self._run_load
|
||||
@on_load.each {|p| p.call @ctx}
|
||||
end
|
||||
|
||||
def self._run_boot
|
||||
@on_boot.each {|p| p.call @ctx}
|
||||
end
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Callbacks for user-scripts
|
||||
# -------------------------------------------------------------------------
|
||||
# Register block to be called with preload context
|
||||
def self.on_preload(&p)
|
||||
@on_preload.push p
|
||||
end
|
||||
|
||||
# Register block to be called after patches are applied
|
||||
def self.on_load(&p)
|
||||
@on_load.push p
|
||||
end
|
||||
|
||||
# Register block to be called on RGSS boot
|
||||
def self.on_boot(&p)
|
||||
@on_boot.push p
|
||||
end
|
||||
end
|
||||
_config = CFG
|
||||
|
||||
# puts "hhh"
|
||||
def find_game_ini_in_directory(directory)
|
||||
# Search for "game.ini" within the specified directory, case-insensitive
|
||||
files = Dir.glob("#{directory}/Game.ini", File::FNM_CASEFOLD)
|
||||
|
||||
# If the file exists, return the full path
|
||||
if files.any?
|
||||
return files.first # Return the full path of the first match
|
||||
else
|
||||
return nil # Return nil if no file is found
|
||||
end
|
||||
end
|
||||
game_ini_path = find_game_ini_in_directory(_config["gameFolder"].to_s)
|
||||
# puts Dir.pwd
|
||||
|
||||
|
||||
|
||||
def checkini(file_path)
|
||||
# Check if the file exists
|
||||
file_path = file_path.nil? || file_path.empty? ? Dir.pwd : file_path
|
||||
|
||||
if File.exist?(file_path)
|
||||
# Read the content of the file
|
||||
input_string = File.read(file_path, encoding: 'ASCII-8BIT')
|
||||
|
||||
# Match the content of the file and return the appropriate value
|
||||
# Match the pattern in the input string and return corresponding values
|
||||
if input_string =~ /rvdata2/
|
||||
return 3
|
||||
elsif input_string =~ /rvdata/
|
||||
return 2
|
||||
elsif input_string =~ /rxdata/
|
||||
return 1
|
||||
else
|
||||
return 3 # Return nil if none of the patterns match
|
||||
end
|
||||
else
|
||||
puts "File does not exist!"
|
||||
return nil
|
||||
end
|
||||
end
|
||||
vers = checkini(game_ini_path)
|
||||
|
||||
rgssversioncodes = ["Unknown", ":xp", ":vx", ":vxace"]
|
||||
|
||||
# vcode =
|
||||
# set :zeusrpgver, vcode
|
||||
ENV["vcode"] = rgssversioncodes[vers]
|
||||
puts ENV["vcode"]
|
||||
ENV["rpgvers"] = vers.to_s
|
||||
# puts "nbnn"+ENV["vcode"]
|
||||
# Ensure Zlib is loaded
|
||||
system("testecho.sh 55555")
|
||||
Kernel.require 'zlib' unless Kernel.const_defined? :Zlib
|
||||
# Load patch definitions
|
||||
Kernel.require File.join(Preload::Path, 'patches.rb')
|
||||
|
||||
# Inject user scripts
|
||||
Dir['*.kawariki.rb'].each do |filename|
|
||||
Preload.print "Loading user script #{filename}"
|
||||
Kernel.require filename
|
||||
end
|
||||
# Apply patches to scripts
|
||||
Preload._run_preload
|
||||
# Run load hooks just before control returns to MKXP to run the scripts
|
||||
Preload._run_load
|
31
Kawariki-patches/versions.json
Normal file
31
Kawariki-patches/versions.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"$schema": "../versions.schema.json",
|
||||
"format": 2,
|
||||
"name": "mkxp",
|
||||
"common": {
|
||||
"slug": "{variant}-{version!v}-{platform}"
|
||||
},
|
||||
"versions": [
|
||||
{
|
||||
"variant": "mkxp-z",
|
||||
"version": [2, 4, 0],
|
||||
"platforms": ["linux-x86_64"],
|
||||
"binary": "mkxp-z",
|
||||
"url": "https://github.com/Orochimarufan/Kawariki/releases/download/mkxp-2.3.0-kk/mkxp-z-{version!v}-{platform}.tar.xz"
|
||||
},
|
||||
{
|
||||
"variant": "mkxp-z",
|
||||
"version": [2, 3, 1],
|
||||
"platforms": ["linux-x86_64"],
|
||||
"binary": "mkxp-z.x86_64",
|
||||
"url": "https://github.com/Orochimarufan/Kawariki/releases/download/mkxp-2.3.0-kk/mkxp-z_2.3.1_x64.tar.xz"
|
||||
},
|
||||
{
|
||||
"variant": "mkxp-z",
|
||||
"version": [2, 3, 0],
|
||||
"platforms": ["linux-x86_64"],
|
||||
"binary": "mkxp-z.x86_64",
|
||||
"url": "https://github.com/Orochimarufan/Kawariki/releases/download/mkxp-2.3.0-kk/mkxp-z_2.3.0_x64.tar.xz"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Add table
Reference in a new issue