mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-09 06:04:59 +00:00
Initial commit
This commit is contained in:
211
Data/Scripts/001_Technical/001_Ruby Utilities.rb
Normal file
211
Data/Scripts/001_Technical/001_Ruby Utilities.rb
Normal file
@@ -0,0 +1,211 @@
|
||||
#===============================================================================
|
||||
# class Class
|
||||
#===============================================================================
|
||||
class Class
|
||||
def to_sym
|
||||
return self.to_s.to_sym
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# module Comparable
|
||||
#===============================================================================
|
||||
unless Comparable.method_defined? :clamp
|
||||
module Comparable
|
||||
def clamp(min, max)
|
||||
if max-min<0
|
||||
raise ArgumentError("min argument must be smaller than max argument")
|
||||
end
|
||||
return (self>max) ? max : (self<min) ? min : self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# class Boolean
|
||||
#===============================================================================
|
||||
class Boolean
|
||||
def to_i
|
||||
return self ? 1 : 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# class String
|
||||
#===============================================================================
|
||||
class String
|
||||
def starts_with?(str)
|
||||
proc = (self[0...str.length] == str) if self.length >= str.length
|
||||
return proc ? proc : false
|
||||
end
|
||||
|
||||
def ends_with?(str)
|
||||
e = self.length - 1
|
||||
proc = (self[(e-str.length)...e] == str) if self.length >= str.length
|
||||
return proc ? proc : false
|
||||
end
|
||||
|
||||
def starts_with_vowel?
|
||||
return ['a','e','i','o','u'].include?(self[0,1].downcase)
|
||||
end
|
||||
|
||||
def first(n=1)
|
||||
return self[0...n]
|
||||
end
|
||||
|
||||
def last(n=1)
|
||||
return self[-n..-1] || self
|
||||
end
|
||||
|
||||
def bytesize
|
||||
return self.size
|
||||
end
|
||||
|
||||
def capitalize
|
||||
proc = self.scan(/./)
|
||||
proc[0] = proc[0].upcase
|
||||
string = ""
|
||||
for letter in proc
|
||||
string += letter
|
||||
end
|
||||
return string
|
||||
end
|
||||
|
||||
def capitalize!
|
||||
self.replace(self.capitalize)
|
||||
end
|
||||
|
||||
def blank?
|
||||
blank = true
|
||||
s = self.scan(/./)
|
||||
for l in s
|
||||
blank = false if l != ""
|
||||
end
|
||||
return blank
|
||||
end
|
||||
|
||||
def cut(bitmap,width)
|
||||
string = self
|
||||
width -= bitmap.text_size("...").width
|
||||
string_width = 0
|
||||
text = []
|
||||
for char in string.scan(/./)
|
||||
wdh = bitmap.text_size(char).width
|
||||
next if (wdh+string_width) > width
|
||||
string_width += wdh
|
||||
text.push(char)
|
||||
end
|
||||
text.push("...") if text.length < string.length
|
||||
new_string = ""
|
||||
for char in text
|
||||
new_string += char
|
||||
end
|
||||
return new_string
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# class Numeric
|
||||
#===============================================================================
|
||||
class Numeric
|
||||
# Turns a number into a string formatted like 12,345,678.
|
||||
def to_s_formatted
|
||||
return self.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\1,').reverse
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# class Integer
|
||||
#===============================================================================
|
||||
class Integer
|
||||
# Returns an array containing each digit of the number in turn.
|
||||
def digits(base=10)
|
||||
quotient, remainder = divmod(base)
|
||||
(quotient==0) ? [remainder] : quotient.digits(base).push(remainder)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# class Array
|
||||
#===============================================================================
|
||||
class Array
|
||||
def first
|
||||
return self[0]
|
||||
end
|
||||
|
||||
def last
|
||||
return self[self.length-1]
|
||||
end
|
||||
|
||||
def ^(other) # xor of two arrays
|
||||
return (self|other)-(self&other)
|
||||
end
|
||||
|
||||
def shuffle
|
||||
dup.shuffle!
|
||||
end unless method_defined? :shuffle
|
||||
|
||||
def shuffle!
|
||||
(size-1).times do |i|
|
||||
r = i+rand(size-i)
|
||||
self[i], self[r] = self[r], self[i]
|
||||
end
|
||||
self
|
||||
end unless method_defined? :shuffle!
|
||||
end
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# module Enumerable
|
||||
#===============================================================================
|
||||
module Enumerable
|
||||
def transform
|
||||
ret = []
|
||||
self.each { |item| ret.push(yield(item)) }
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# Kernel methods
|
||||
#===============================================================================
|
||||
def rand(*args)
|
||||
Kernel.rand(*args)
|
||||
end
|
||||
|
||||
class << Kernel
|
||||
alias oldRand rand unless method_defined?(:oldRand)
|
||||
def rand(a = nil, b = nil)
|
||||
if a.is_a?(Range)
|
||||
lo = a.min
|
||||
hi = a.max
|
||||
return lo + oldRand(hi - lo + 1)
|
||||
elsif a.is_a?(Numeric)
|
||||
if b.is_a?(Numeric)
|
||||
return a + oldRand(b - a + 1)
|
||||
else
|
||||
return oldRand(a)
|
||||
end
|
||||
elsif a.nil?
|
||||
return (b) ? oldRand(b) : oldRand(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def nil_or_empty?(string)
|
||||
return string.nil? || !string.is_a?(String) || string.size == 0
|
||||
end
|
||||
608
Data/Scripts/001_Technical/002_RGSS2Compatibility.rb
Normal file
608
Data/Scripts/001_Technical/002_RGSS2Compatibility.rb
Normal file
@@ -0,0 +1,608 @@
|
||||
$TEST = true if $DEBUG
|
||||
$DEBUG = true if $TEST
|
||||
$scene = nil
|
||||
Font.default_shadow = false if Font.respond_to?(:default_shadow)
|
||||
Graphics.frame_rate = 40
|
||||
|
||||
|
||||
|
||||
=begin
|
||||
class Win32API
|
||||
class << self
|
||||
unless defined?(debug_new)
|
||||
alias debug_new new
|
||||
end
|
||||
|
||||
def new(*args)
|
||||
File.open("winapi.txt","ab") { |f| f.write("new(#{args[0]},#{args[1]})\r\n") }
|
||||
b=debug_new(*args)
|
||||
b.setDllName(args[0],args[1])
|
||||
return b
|
||||
end
|
||||
end
|
||||
|
||||
unless defined?(debug_call)
|
||||
alias debug_call call
|
||||
end
|
||||
|
||||
def setDllName(a,b)
|
||||
@w32dll=a
|
||||
@w32name=b
|
||||
end
|
||||
|
||||
def call(*args)
|
||||
if @w32name!="GetAsyncKeyState"
|
||||
File.open("winapi.txt","ab") { |f|
|
||||
f.write("call(#{@w32dll},#{@w32name},#{args.inspect})\r\n")
|
||||
}
|
||||
end
|
||||
debug_call(*args)
|
||||
end
|
||||
end
|
||||
|
||||
class Bitmap
|
||||
class << self
|
||||
unless defined?(debug_new)
|
||||
alias debug_new new
|
||||
end
|
||||
|
||||
def new(*args)
|
||||
if args.length==1
|
||||
File.open("winapib.txt","ab") { |f| f.write("new(#{args[0]})\r\n") }
|
||||
end
|
||||
debug_new(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
alias debug_load_data load_data
|
||||
|
||||
def load_data(*args)
|
||||
File.open("winapif.txt","ab") { |f| f.write("load(#{args[0]})\r\n") }
|
||||
debug_load_data(*args)
|
||||
end
|
||||
=end
|
||||
|
||||
|
||||
|
||||
class Hangup < Exception; end
|
||||
|
||||
|
||||
|
||||
if false
|
||||
p (Tilemap.instance_methods-Kernel.instance_methods-Object.instance_methods).sort
|
||||
# no changes
|
||||
p (Plane.instance_methods-Kernel.instance_methods-Object.instance_methods).sort
|
||||
# no changes
|
||||
p (Viewport.instance_methods-Kernel.instance_methods-Object.instance_methods).sort
|
||||
p (Bitmap.instance_methods-Kernel.instance_methods-Object.instance_methods).sort
|
||||
# openness(=)
|
||||
p (Window.instance_methods-Kernel.instance_methods-Object.instance_methods).sort
|
||||
p (Sprite.instance_methods-Kernel.instance_methods-Object.instance_methods).sort
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Animation
|
||||
attr_accessor :id
|
||||
attr_accessor :name
|
||||
attr_accessor :animation_name
|
||||
attr_accessor :animation_hue
|
||||
attr_accessor :position
|
||||
attr_accessor :frame_max
|
||||
attr_accessor :frames
|
||||
attr_accessor :timings
|
||||
|
||||
def initialize
|
||||
@id = 0
|
||||
@name = ""
|
||||
@animation_name = ""
|
||||
@animation_hue = 0
|
||||
@position = 1
|
||||
@frame_max = 1
|
||||
@frames = [RPG::Animation::Frame.new]
|
||||
@timings = []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Animation
|
||||
class Frame
|
||||
attr_accessor :cell_max
|
||||
attr_accessor :cell_data
|
||||
|
||||
def initialize
|
||||
@cell_max = 0
|
||||
@cell_data = Table.new(0, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Animation
|
||||
class Timing
|
||||
attr_accessor :frame
|
||||
attr_accessor :se
|
||||
attr_accessor :flash_scope
|
||||
attr_accessor :flash_color
|
||||
attr_accessor :flash_duration
|
||||
attr_accessor :condition
|
||||
|
||||
def initialize
|
||||
@frame = 0
|
||||
@se = RPG::AudioFile.new("", 80)
|
||||
@flash_scope = 0
|
||||
@flash_color = Color.new(255,255,255,255)
|
||||
@flash_duration = 5
|
||||
@condition = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class System
|
||||
attr_accessor :magic_number
|
||||
attr_accessor :party_members
|
||||
attr_accessor :elements
|
||||
attr_accessor :switches
|
||||
attr_accessor :variables
|
||||
attr_accessor :windowskin_name
|
||||
attr_accessor :title_name
|
||||
attr_accessor :gameover_name
|
||||
attr_accessor :battle_transition
|
||||
attr_accessor :title_bgm
|
||||
attr_accessor :battle_bgm
|
||||
attr_accessor :battle_end_me
|
||||
attr_accessor :gameover_me
|
||||
attr_accessor :cursor_se
|
||||
attr_accessor :decision_se
|
||||
attr_accessor :cancel_se
|
||||
attr_accessor :buzzer_se
|
||||
attr_accessor :equip_se
|
||||
attr_accessor :shop_se
|
||||
attr_accessor :save_se
|
||||
attr_accessor :load_se
|
||||
attr_accessor :battle_start_se
|
||||
attr_accessor :escape_se
|
||||
attr_accessor :actor_collapse_se
|
||||
attr_accessor :enemy_collapse_se
|
||||
attr_accessor :words
|
||||
attr_accessor :test_battlers
|
||||
attr_accessor :test_troop_id
|
||||
attr_accessor :start_map_id
|
||||
attr_accessor :start_x
|
||||
attr_accessor :start_y
|
||||
attr_accessor :battleback_name
|
||||
attr_accessor :battler_name
|
||||
attr_accessor :battler_hue
|
||||
attr_accessor :edit_map_id
|
||||
|
||||
def initialize
|
||||
@magic_number = 0
|
||||
@party_members = [1]
|
||||
@elements = [nil, ""]
|
||||
@switches = [nil, ""]
|
||||
@variables = [nil, ""]
|
||||
@windowskin_name = ""
|
||||
@title_name = ""
|
||||
@gameover_name = ""
|
||||
@battle_transition = ""
|
||||
@title_bgm = RPG::AudioFile.new
|
||||
@battle_bgm = RPG::AudioFile.new
|
||||
@battle_end_me = RPG::AudioFile.new
|
||||
@gameover_me = RPG::AudioFile.new
|
||||
@cursor_se = RPG::AudioFile.new("", 80)
|
||||
@decision_se = RPG::AudioFile.new("", 80)
|
||||
@cancel_se = RPG::AudioFile.new("", 80)
|
||||
@buzzer_se = RPG::AudioFile.new("", 80)
|
||||
@equip_se = RPG::AudioFile.new("", 80)
|
||||
@shop_se = RPG::AudioFile.new("", 80)
|
||||
@save_se = RPG::AudioFile.new("", 80)
|
||||
@load_se = RPG::AudioFile.new("", 80)
|
||||
@battle_start_se = RPG::AudioFile.new("", 80)
|
||||
@escape_se = RPG::AudioFile.new("", 80)
|
||||
@actor_collapse_se = RPG::AudioFile.new("", 80)
|
||||
@enemy_collapse_se = RPG::AudioFile.new("", 80)
|
||||
@words = RPG::System::Words.new
|
||||
@test_battlers = []
|
||||
@test_troop_id = 1
|
||||
@start_map_id = 1
|
||||
@start_x = 0
|
||||
@start_y = 0
|
||||
@battleback_name = ""
|
||||
@battler_name = ""
|
||||
@battler_hue = 0
|
||||
@edit_map_id = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Tileset
|
||||
attr_accessor :id
|
||||
attr_accessor :name
|
||||
attr_accessor :tileset_name
|
||||
attr_accessor :autotile_names
|
||||
attr_accessor :panorama_name
|
||||
attr_accessor :panorama_hue
|
||||
attr_accessor :fog_name
|
||||
attr_accessor :fog_hue
|
||||
attr_accessor :fog_opacity
|
||||
attr_accessor :fog_blend_type
|
||||
attr_accessor :fog_zoom
|
||||
attr_accessor :fog_sx
|
||||
attr_accessor :fog_sy
|
||||
attr_accessor :battleback_name
|
||||
attr_accessor :passages
|
||||
attr_accessor :priorities
|
||||
attr_accessor :terrain_tags
|
||||
|
||||
def initialize
|
||||
@id = 0
|
||||
@name = ""
|
||||
@tileset_name = ""
|
||||
@autotile_names = [""]*7
|
||||
@panorama_name = ""
|
||||
@panorama_hue = 0
|
||||
@fog_name = ""
|
||||
@fog_hue = 0
|
||||
@fog_opacity = 64
|
||||
@fog_blend_type = 0
|
||||
@fog_zoom = 200
|
||||
@fog_sx = 0
|
||||
@fog_sy = 0
|
||||
@battleback_name = ""
|
||||
@passages = Table.new(384)
|
||||
@priorities = Table.new(384)
|
||||
@priorities[0] = 5
|
||||
@terrain_tags = Table.new(384)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class CommonEvent
|
||||
attr_accessor :id
|
||||
attr_accessor :name
|
||||
attr_accessor :trigger
|
||||
attr_accessor :switch_id
|
||||
attr_accessor :list
|
||||
|
||||
def initialize
|
||||
@id = 0
|
||||
@name = ""
|
||||
@trigger = 0
|
||||
@switch_id = 1
|
||||
@list = [RPG::EventCommand.new]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Map
|
||||
attr_accessor :tileset_id
|
||||
attr_accessor :width
|
||||
attr_accessor :height
|
||||
attr_accessor :autoplay_bgm
|
||||
attr_accessor :bgm
|
||||
attr_accessor :autoplay_bgs
|
||||
attr_accessor :bgs
|
||||
attr_accessor :encounter_list
|
||||
attr_accessor :encounter_step
|
||||
attr_accessor :data
|
||||
attr_accessor :events
|
||||
|
||||
def initialize(width, height)
|
||||
@tileset_id = 1
|
||||
@width = width
|
||||
@height = height
|
||||
@autoplay_bgm = false
|
||||
@bgm = RPG::AudioFile.new
|
||||
@autoplay_bgs = false
|
||||
@bgs = RPG::AudioFile.new("", 80)
|
||||
@encounter_list = []
|
||||
@encounter_step = 30
|
||||
@data = Table.new(width, height, 3)
|
||||
@events = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class MapInfo
|
||||
attr_accessor :name
|
||||
attr_accessor :parent_id
|
||||
attr_accessor :order
|
||||
attr_accessor :expanded
|
||||
attr_accessor :scroll_x
|
||||
attr_accessor :scroll_y
|
||||
|
||||
def initialize
|
||||
@name = ""
|
||||
@parent_id = 0
|
||||
@order = 0
|
||||
@expanded = false
|
||||
@scroll_x = 0
|
||||
@scroll_y = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Event
|
||||
attr_accessor :id
|
||||
attr_accessor :name
|
||||
attr_accessor :x
|
||||
attr_accessor :y
|
||||
attr_accessor :pages
|
||||
|
||||
def initialize(x, y)
|
||||
@id = 0
|
||||
@name = ""
|
||||
@x = x
|
||||
@y = y
|
||||
@pages = [RPG::Event::Page.new]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Event
|
||||
class Page
|
||||
attr_accessor :condition
|
||||
attr_accessor :graphic
|
||||
attr_accessor :move_type
|
||||
attr_accessor :move_speed
|
||||
attr_accessor :move_frequency
|
||||
attr_accessor :move_route
|
||||
attr_accessor :walk_anime
|
||||
attr_accessor :step_anime
|
||||
attr_accessor :direction_fix
|
||||
attr_accessor :through
|
||||
attr_accessor :always_on_top
|
||||
attr_accessor :trigger
|
||||
attr_accessor :list
|
||||
|
||||
def initialize
|
||||
@condition = RPG::Event::Page::Condition.new
|
||||
@graphic = RPG::Event::Page::Graphic.new
|
||||
@move_type = 0
|
||||
@move_speed = 3
|
||||
@move_frequency = 3
|
||||
@move_route = RPG::MoveRoute.new
|
||||
@walk_anime = true
|
||||
@step_anime = false
|
||||
@direction_fix = false
|
||||
@through = false
|
||||
@always_on_top = false
|
||||
@trigger = 0
|
||||
@list = [RPG::EventCommand.new]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Event
|
||||
class Page
|
||||
class Condition
|
||||
attr_accessor :switch1_valid
|
||||
attr_accessor :switch2_valid
|
||||
attr_accessor :variable_valid
|
||||
attr_accessor :self_switch_valid
|
||||
attr_accessor :switch1_id
|
||||
attr_accessor :switch2_id
|
||||
attr_accessor :variable_id
|
||||
attr_accessor :variable_value
|
||||
attr_accessor :self_switch_ch
|
||||
|
||||
def initialize
|
||||
@switch1_valid = false
|
||||
@switch2_valid = false
|
||||
@variable_valid = false
|
||||
@self_switch_valid = false
|
||||
@switch1_id = 1
|
||||
@switch2_id = 1
|
||||
@variable_id = 1
|
||||
@variable_value = 0
|
||||
@self_switch_ch = "A"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Event
|
||||
class Page
|
||||
class Graphic
|
||||
attr_accessor :tile_id
|
||||
attr_accessor :character_name
|
||||
attr_accessor :character_hue
|
||||
attr_accessor :direction
|
||||
attr_accessor :pattern
|
||||
attr_accessor :opacity
|
||||
attr_accessor :blend_type
|
||||
|
||||
def initialize
|
||||
@tile_id = 0
|
||||
@character_name = ""
|
||||
@character_hue = 0
|
||||
@direction = 2
|
||||
@pattern = 0
|
||||
@opacity = 255
|
||||
@blend_type = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class EventCommand
|
||||
attr_accessor :code
|
||||
attr_accessor :indent
|
||||
attr_accessor :parameters
|
||||
|
||||
def initialize(code = 0, indent = 0, parameters = [])
|
||||
@code = code
|
||||
@indent = indent
|
||||
@parameters = parameters
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class MoveRoute
|
||||
attr_accessor :repeat
|
||||
attr_accessor :skippable
|
||||
attr_accessor :list
|
||||
|
||||
def initialize
|
||||
@repeat = true
|
||||
@skippable = false
|
||||
@list = [RPG::MoveCommand.new]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class MoveCommand
|
||||
attr_accessor :code
|
||||
attr_accessor :parameters
|
||||
|
||||
def initialize(code = 0, parameters = [])
|
||||
@code = code
|
||||
@parameters = parameters
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class System
|
||||
class Words
|
||||
attr_accessor :gold
|
||||
attr_accessor :hp
|
||||
attr_accessor :sp
|
||||
attr_accessor :str
|
||||
attr_accessor :dex
|
||||
attr_accessor :agi
|
||||
attr_accessor :int
|
||||
attr_accessor :atk
|
||||
attr_accessor :pdef
|
||||
attr_accessor :mdef
|
||||
attr_accessor :weapon
|
||||
attr_accessor :armor1
|
||||
attr_accessor :armor2
|
||||
attr_accessor :armor3
|
||||
attr_accessor :armor4
|
||||
attr_accessor :attack
|
||||
attr_accessor :skill
|
||||
attr_accessor :guard
|
||||
attr_accessor :item
|
||||
attr_accessor :equip
|
||||
|
||||
def initialize
|
||||
@gold = ""
|
||||
@hp = ""
|
||||
@sp = ""
|
||||
@str = ""
|
||||
@dex = ""
|
||||
@agi = ""
|
||||
@int = ""
|
||||
@atk = ""
|
||||
@pdef = ""
|
||||
@mdef = ""
|
||||
@weapon = ""
|
||||
@armor1 = ""
|
||||
@armor2 = ""
|
||||
@armor3 = ""
|
||||
@armor4 = ""
|
||||
@attack = ""
|
||||
@skill = ""
|
||||
@guard = ""
|
||||
@item = ""
|
||||
@equip = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class System
|
||||
class TestBattler
|
||||
attr_accessor :actor_id
|
||||
attr_accessor :level
|
||||
attr_accessor :weapon_id
|
||||
attr_accessor :armor1_id
|
||||
attr_accessor :armor2_id
|
||||
attr_accessor :armor3_id
|
||||
attr_accessor :armor4_id
|
||||
|
||||
def initialize
|
||||
@actor_id = 1
|
||||
@level = 1
|
||||
@weapon_id = 0
|
||||
@armor1_id = 0
|
||||
@armor2_id = 0
|
||||
@armor3_id = 0
|
||||
@armor4_id = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class AudioFile
|
||||
attr_accessor :name
|
||||
attr_accessor :volume
|
||||
attr_accessor :pitch
|
||||
|
||||
def initialize(name = "", volume = 100, pitch = 100)
|
||||
@name = name
|
||||
@volume = volume
|
||||
@pitch = pitch
|
||||
end
|
||||
|
||||
# def play
|
||||
# end
|
||||
end
|
||||
end
|
||||
534
Data/Scripts/001_Technical/003_RPG__Sprite.rb
Normal file
534
Data/Scripts/001_Technical/003_RPG__Sprite.rb
Normal file
@@ -0,0 +1,534 @@
|
||||
class SpriteAnimation
|
||||
@@_animations = []
|
||||
@@_reference_count = {}
|
||||
|
||||
def initialize(sprite)
|
||||
@sprite = sprite
|
||||
end
|
||||
|
||||
%w[
|
||||
x y ox oy viewport flash src_rect opacity tone
|
||||
].each_with_index do |s, i|
|
||||
eval <<-__END__
|
||||
|
||||
def #{s}(*arg)
|
||||
@sprite.#{s}(*arg)
|
||||
end
|
||||
|
||||
__END__
|
||||
end
|
||||
|
||||
def self.clear
|
||||
@@_animations.clear
|
||||
end
|
||||
|
||||
def dispose
|
||||
dispose_animation
|
||||
dispose_loop_animation
|
||||
end
|
||||
|
||||
def animation(animation, hit, height = 3)
|
||||
dispose_animation
|
||||
@_animation = animation
|
||||
return if @_animation == nil
|
||||
@_animation_hit = hit
|
||||
@_animation_height = height
|
||||
@_animation_duration = @_animation.frame_max
|
||||
fr = 20
|
||||
if @_animation.name[/\[\s*(\d+?)\s*\]\s*$/]
|
||||
fr = $~[1].to_i
|
||||
end
|
||||
@_animation_frame_skip = Graphics.frame_rate / fr
|
||||
animation_name = @_animation.animation_name
|
||||
animation_hue = @_animation.animation_hue
|
||||
bitmap = pbGetAnimation(animation_name, animation_hue)
|
||||
if @@_reference_count.include?(bitmap)
|
||||
@@_reference_count[bitmap] += 1
|
||||
else
|
||||
@@_reference_count[bitmap] = 1
|
||||
end
|
||||
@_animation_sprites = []
|
||||
if @_animation.position != 3 or not @@_animations.include?(animation)
|
||||
for i in 0..15
|
||||
sprite = ::Sprite.new(self.viewport)
|
||||
sprite.bitmap = bitmap
|
||||
sprite.visible = false
|
||||
@_animation_sprites.push(sprite)
|
||||
end
|
||||
unless @@_animations.include?(animation)
|
||||
@@_animations.push(animation)
|
||||
end
|
||||
end
|
||||
update_animation
|
||||
end
|
||||
|
||||
def loop_animation(animation)
|
||||
return if animation == @_loop_animation
|
||||
dispose_loop_animation
|
||||
@_loop_animation = animation
|
||||
return if @_loop_animation == nil
|
||||
@_loop_animation_index = 0
|
||||
fr = 20
|
||||
if @_animation.name[/\[\s*(\d+?)\s*\]\s*$/]
|
||||
fr = $~[1].to_i
|
||||
end
|
||||
@_loop_animation_frame_skip = Graphics.frame_rate / fr
|
||||
animation_name = @_loop_animation.animation_name
|
||||
animation_hue = @_loop_animation.animation_hue
|
||||
bitmap = pbGetAnimation(animation_name, animation_hue)
|
||||
if @@_reference_count.include?(bitmap)
|
||||
@@_reference_count[bitmap] += 1
|
||||
else
|
||||
@@_reference_count[bitmap] = 1
|
||||
end
|
||||
@_loop_animation_sprites = []
|
||||
for i in 0..15
|
||||
sprite = ::Sprite.new(self.viewport)
|
||||
sprite.bitmap = bitmap
|
||||
sprite.visible = false
|
||||
@_loop_animation_sprites.push(sprite)
|
||||
end
|
||||
update_loop_animation
|
||||
end
|
||||
|
||||
def dispose_animation
|
||||
return if @_animation_sprites == nil
|
||||
sprite = @_animation_sprites[0]
|
||||
if sprite != nil
|
||||
@@_reference_count[sprite.bitmap] -= 1
|
||||
if @@_reference_count[sprite.bitmap] == 0
|
||||
sprite.bitmap.dispose
|
||||
end
|
||||
end
|
||||
for sprite in @_animation_sprites
|
||||
sprite.dispose
|
||||
end
|
||||
@_animation_sprites = nil
|
||||
@_animation = nil
|
||||
end
|
||||
|
||||
def dispose_loop_animation
|
||||
return if @_loop_animation_sprites == nil
|
||||
sprite = @_loop_animation_sprites[0]
|
||||
if sprite != nil
|
||||
@@_reference_count[sprite.bitmap] -= 1
|
||||
if @@_reference_count[sprite.bitmap] == 0
|
||||
sprite.bitmap.dispose
|
||||
end
|
||||
end
|
||||
for sprite in @_loop_animation_sprites
|
||||
sprite.dispose
|
||||
end
|
||||
@_loop_animation_sprites = nil
|
||||
@_loop_animation = nil
|
||||
end
|
||||
|
||||
def active?
|
||||
return @_loop_animation_sprites != nil || @_animation_sprites != nil
|
||||
end
|
||||
|
||||
def effect?
|
||||
return @_animation_duration > 0
|
||||
end
|
||||
|
||||
def update
|
||||
if @_animation != nil
|
||||
quick_update = true
|
||||
if Graphics.frame_count % @_animation_frame_skip == 0
|
||||
@_animation_duration -= 1
|
||||
quick_update = false
|
||||
end
|
||||
update_animation(quick_update)
|
||||
end
|
||||
if @_loop_animation != nil
|
||||
quick_update = (Graphics.frame_count % @_loop_animation_frame_skip != 0)
|
||||
update_loop_animation(quick_update)
|
||||
if !quick_update
|
||||
@_loop_animation_index += 1
|
||||
@_loop_animation_index %= @_loop_animation.frame_max
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update_animation(quick_update = false)
|
||||
if @_animation_duration <= 0
|
||||
dispose_animation
|
||||
return
|
||||
end
|
||||
frame_index = @_animation.frame_max - @_animation_duration
|
||||
cell_data = @_animation.frames[frame_index].cell_data
|
||||
position = @_animation.position
|
||||
animation_set_sprites(@_animation_sprites, cell_data, position, quick_update)
|
||||
return if quick_update
|
||||
for timing in @_animation.timings
|
||||
next if timing.frame != frame_index
|
||||
animation_process_timing(timing, @_animation_hit)
|
||||
end
|
||||
end
|
||||
|
||||
def update_loop_animation(quick_update = false)
|
||||
frame_index = @_loop_animation_index
|
||||
cell_data = @_loop_animation.frames[frame_index].cell_data
|
||||
position = @_loop_animation.position
|
||||
animation_set_sprites(@_loop_animation_sprites, cell_data, position, quick_update)
|
||||
return if quick_update
|
||||
for timing in @_loop_animation.timings
|
||||
next if timing.frame != frame_index
|
||||
animation_process_timing(timing, true)
|
||||
end
|
||||
end
|
||||
|
||||
def animation_set_sprites(sprites, cell_data, position, quick_update = false)
|
||||
sprite_x = 320
|
||||
sprite_y = 240
|
||||
if position == 3
|
||||
if self.viewport != nil
|
||||
sprite_x = self.viewport.rect.width / 2
|
||||
sprite_y = self.viewport.rect.height - 160
|
||||
end
|
||||
else
|
||||
sprite_x = self.x - self.ox + self.src_rect.width / 2
|
||||
sprite_y = self.y - self.oy + self.src_rect.height / 2
|
||||
sprite_y -= self.src_rect.height / 4 if position == 0
|
||||
sprite_y += self.src_rect.height / 4 if position == 2
|
||||
end
|
||||
for i in 0..15
|
||||
sprite = sprites[i]
|
||||
pattern = cell_data[i, 0]
|
||||
if sprite == nil or pattern == nil or pattern == -1
|
||||
sprite.visible = false if sprite != nil
|
||||
next
|
||||
end
|
||||
sprite.x = sprite_x + cell_data[i, 1]
|
||||
sprite.y = sprite_y + cell_data[i, 2]
|
||||
next if quick_update
|
||||
sprite.visible = true
|
||||
sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192)
|
||||
case @_animation_height
|
||||
when 0; sprite.z = 1
|
||||
when 1; sprite.z = sprite.y+32+15
|
||||
when 2; sprite.z = sprite.y+32+32+17
|
||||
else; sprite.z = 2000
|
||||
end
|
||||
sprite.ox = 96
|
||||
sprite.oy = 96
|
||||
sprite.zoom_x = cell_data[i, 3] / 100.0
|
||||
sprite.zoom_y = cell_data[i, 3] / 100.0
|
||||
sprite.angle = cell_data[i, 4]
|
||||
sprite.mirror = (cell_data[i, 5] == 1)
|
||||
sprite.tone = self.tone
|
||||
sprite.opacity = cell_data[i, 6] * self.opacity / 255.0
|
||||
sprite.blend_type = cell_data[i, 7]
|
||||
end
|
||||
end
|
||||
|
||||
def animation_process_timing(timing, hit)
|
||||
if (timing.condition == 0) or
|
||||
(timing.condition == 1 and hit == true) or
|
||||
(timing.condition == 2 and hit == false)
|
||||
if timing.se.name != ""
|
||||
se = timing.se
|
||||
pbSEPlay(se)
|
||||
end
|
||||
case timing.flash_scope
|
||||
when 1
|
||||
self.flash(timing.flash_color, timing.flash_duration * 2)
|
||||
when 2
|
||||
if self.viewport != nil
|
||||
self.viewport.flash(timing.flash_color, timing.flash_duration * 2)
|
||||
end
|
||||
when 3
|
||||
self.flash(nil, timing.flash_duration * 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def x=(x)
|
||||
sx = x - self.x
|
||||
return if sx == 0
|
||||
if @_animation_sprites != nil
|
||||
for i in 0..15
|
||||
@_animation_sprites[i].x += sx
|
||||
end
|
||||
end
|
||||
if @_loop_animation_sprites != nil
|
||||
for i in 0..15
|
||||
@_loop_animation_sprites[i].x += sx
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def y=(y)
|
||||
sy = y - self.y
|
||||
return if sy == 0
|
||||
if @_animation_sprites != nil
|
||||
for i in 0..15
|
||||
@_animation_sprites[i].y += sy
|
||||
end
|
||||
end
|
||||
if @_loop_animation_sprites != nil
|
||||
for i in 0..15
|
||||
@_loop_animation_sprites[i].y += sy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module RPG
|
||||
class Sprite < ::Sprite
|
||||
def initialize(viewport = nil)
|
||||
super(viewport)
|
||||
@_whiten_duration = 0
|
||||
@_appear_duration = 0
|
||||
@_escape_duration = 0
|
||||
@_collapse_duration = 0
|
||||
@_damage_duration = 0
|
||||
@_animation_duration = 0
|
||||
@_blink = false
|
||||
@animations = []
|
||||
@loopAnimations = []
|
||||
end
|
||||
|
||||
def dispose
|
||||
dispose_damage
|
||||
dispose_animation
|
||||
dispose_loop_animation
|
||||
super
|
||||
end
|
||||
|
||||
def whiten
|
||||
self.blend_type = 0
|
||||
self.color.set(255, 255, 255, 128)
|
||||
self.opacity = 255
|
||||
@_whiten_duration = 16
|
||||
@_appear_duration = 0
|
||||
@_escape_duration = 0
|
||||
@_collapse_duration = 0
|
||||
end
|
||||
|
||||
def appear
|
||||
self.blend_type = 0
|
||||
self.color.set(0, 0, 0, 0)
|
||||
self.opacity = 0
|
||||
@_appear_duration = 16
|
||||
@_whiten_duration = 0
|
||||
@_escape_duration = 0
|
||||
@_collapse_duration = 0
|
||||
end
|
||||
|
||||
def escape
|
||||
self.blend_type = 0
|
||||
self.color.set(0, 0, 0, 0)
|
||||
self.opacity = 255
|
||||
@_escape_duration = 32
|
||||
@_whiten_duration = 0
|
||||
@_appear_duration = 0
|
||||
@_collapse_duration = 0
|
||||
end
|
||||
|
||||
def collapse
|
||||
self.blend_type = 1
|
||||
self.color.set(255, 64, 64, 255)
|
||||
self.opacity = 255
|
||||
@_collapse_duration = 48
|
||||
@_whiten_duration = 0
|
||||
@_appear_duration = 0
|
||||
@_escape_duration = 0
|
||||
end
|
||||
|
||||
def damage(value, critical)
|
||||
dispose_damage
|
||||
damage_string = (value.is_a?(Numeric)) ? value.abs.to_s : value.to_s
|
||||
bitmap = Bitmap.new(160, 48)
|
||||
bitmap.font.name = "Arial Black"
|
||||
bitmap.font.size = 32
|
||||
bitmap.font.color.set(0, 0, 0)
|
||||
bitmap.draw_text(-1, 12-1, 160, 36, damage_string, 1)
|
||||
bitmap.draw_text(+1, 12-1, 160, 36, damage_string, 1)
|
||||
bitmap.draw_text(-1, 12+1, 160, 36, damage_string, 1)
|
||||
bitmap.draw_text(+1, 12+1, 160, 36, damage_string, 1)
|
||||
if value.is_a?(Numeric) and value < 0
|
||||
bitmap.font.color.set(176, 255, 144)
|
||||
else
|
||||
bitmap.font.color.set(255, 255, 255)
|
||||
end
|
||||
bitmap.draw_text(0, 12, 160, 36, damage_string, 1)
|
||||
if critical
|
||||
bitmap.font.size = 20
|
||||
bitmap.font.color.set(0, 0, 0)
|
||||
bitmap.draw_text(-1, -1, 160, 20, "CRITICAL", 1)
|
||||
bitmap.draw_text(+1, -1, 160, 20, "CRITICAL", 1)
|
||||
bitmap.draw_text(-1, +1, 160, 20, "CRITICAL", 1)
|
||||
bitmap.draw_text(+1, +1, 160, 20, "CRITICAL", 1)
|
||||
bitmap.font.color.set(255, 255, 255)
|
||||
bitmap.draw_text(0, 0, 160, 20, "CRITICAL", 1)
|
||||
end
|
||||
@_damage_sprite = ::Sprite.new(self.viewport)
|
||||
@_damage_sprite.bitmap = bitmap
|
||||
@_damage_sprite.ox = 80
|
||||
@_damage_sprite.oy = 20
|
||||
@_damage_sprite.x = self.x
|
||||
@_damage_sprite.y = self.y - self.oy / 2
|
||||
@_damage_sprite.z = 3000
|
||||
@_damage_duration = 40
|
||||
end
|
||||
|
||||
def pushAnimation(array, anim)
|
||||
for i in 0...array.length
|
||||
next if array[i] && array[i].active?
|
||||
array[i] = anim
|
||||
return
|
||||
end
|
||||
array.push(anim)
|
||||
end
|
||||
|
||||
def animation(animation, hit, height = 3)
|
||||
anim = SpriteAnimation.new(self)
|
||||
anim.animation(animation,hit,height)
|
||||
pushAnimation(@animations,anim)
|
||||
end
|
||||
|
||||
def loop_animation(animation)
|
||||
anim = SpriteAnimation.new(self)
|
||||
anim.loop_animation(animation)
|
||||
pushAnimation(@loopAnimations,anim)
|
||||
end
|
||||
|
||||
def dispose_damage
|
||||
return if @_damage_sprite == nil
|
||||
@_damage_sprite.bitmap.dispose
|
||||
@_damage_sprite.dispose
|
||||
@_damage_sprite = nil
|
||||
@_damage_duration = 0
|
||||
end
|
||||
|
||||
def dispose_animation
|
||||
for a in @animations
|
||||
a.dispose_animation if a
|
||||
end
|
||||
@animations.clear
|
||||
end
|
||||
|
||||
def dispose_loop_animation
|
||||
for a in @loopAnimations
|
||||
a.dispose_loop_animation if a
|
||||
end
|
||||
@loopAnimations.clear
|
||||
end
|
||||
|
||||
def blink_on
|
||||
return if @_blink
|
||||
@_blink = true
|
||||
@_blink_count = 0
|
||||
end
|
||||
|
||||
def blink_off
|
||||
return unless @_blink
|
||||
@_blink = false
|
||||
self.color.set(0, 0, 0, 0)
|
||||
end
|
||||
|
||||
def blink?
|
||||
return @_blink
|
||||
end
|
||||
|
||||
def effect?
|
||||
return true if @_whiten_duration > 0
|
||||
return true if @_appear_duration > 0
|
||||
return true if @_escape_duration > 0
|
||||
return true if @_collapse_duration > 0
|
||||
return true if @_damage_duration > 0
|
||||
for a in @animations
|
||||
return true if a.effect?
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
if @_whiten_duration > 0
|
||||
@_whiten_duration -= 1
|
||||
self.color.alpha = 128 - (16 - @_whiten_duration) * 10
|
||||
end
|
||||
if @_appear_duration > 0
|
||||
@_appear_duration -= 1
|
||||
self.opacity = (16 - @_appear_duration) * 16
|
||||
end
|
||||
if @_escape_duration > 0
|
||||
@_escape_duration -= 1
|
||||
self.opacity = 256 - (32 - @_escape_duration) * 10
|
||||
end
|
||||
if @_collapse_duration > 0
|
||||
@_collapse_duration -= 1
|
||||
self.opacity = 256 - (48 - @_collapse_duration) * 6
|
||||
end
|
||||
if @_damage_duration > 0
|
||||
@_damage_duration -= 1
|
||||
case @_damage_duration
|
||||
when 38..39
|
||||
@_damage_sprite.y -= 4
|
||||
when 36..37
|
||||
@_damage_sprite.y -= 2
|
||||
when 34..35
|
||||
@_damage_sprite.y += 2
|
||||
when 28..33
|
||||
@_damage_sprite.y += 4
|
||||
end
|
||||
@_damage_sprite.opacity = 256 - (12 - @_damage_duration) * 32
|
||||
if @_damage_duration == 0
|
||||
dispose_damage
|
||||
end
|
||||
end
|
||||
for a in @animations
|
||||
a.update
|
||||
end
|
||||
for a in @loopAnimations
|
||||
a.update
|
||||
end
|
||||
if @_blink
|
||||
@_blink_count = (@_blink_count + 1) % 32
|
||||
if @_blink_count < 16
|
||||
alpha = (16 - @_blink_count) * 6
|
||||
else
|
||||
alpha = (@_blink_count - 16) * 6
|
||||
end
|
||||
self.color.set(255, 255, 255, alpha)
|
||||
end
|
||||
SpriteAnimation.clear
|
||||
end
|
||||
|
||||
def update_animation
|
||||
for a in @animations
|
||||
a.update_animation if a && a.active?
|
||||
end
|
||||
end
|
||||
|
||||
def update_loop_animation
|
||||
for a in @loopAnimations
|
||||
a.update_loop_animation if a && a.active?
|
||||
end
|
||||
end
|
||||
|
||||
def x=(x)
|
||||
for a in @animations
|
||||
a.x = x if a
|
||||
end
|
||||
for a in @loopAnimations
|
||||
a.x = x if a
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
def y=(y)
|
||||
for a in @animations
|
||||
a.y = y if a
|
||||
end
|
||||
for a in @loopAnimations
|
||||
a.y = y if a
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
104
Data/Scripts/001_Technical/004_Win32API.rb
Normal file
104
Data/Scripts/001_Technical/004_Win32API.rb
Normal file
@@ -0,0 +1,104 @@
|
||||
class Win32API
|
||||
@@RGSSWINDOW = nil
|
||||
@@GetCurrentThreadId = Win32API.new('kernel32','GetCurrentThreadId', '%w()','l')
|
||||
@@GetWindowThreadProcessId = Win32API.new('user32','GetWindowThreadProcessId', '%w(l p)','l')
|
||||
@@FindWindowEx = Win32API.new('user32','FindWindowEx', '%w(l l p p)','l')
|
||||
|
||||
def Win32API.SetWindowText(text)
|
||||
hWnd = pbFindRgssWindow
|
||||
swp = Win32API.new('user32','SetWindowTextA',%(l, p),'i')
|
||||
swp.call(hWnd, text.to_s)
|
||||
end
|
||||
|
||||
# Added by Peter O. as a more reliable way to get the RGSS window
|
||||
def Win32API.pbFindRgssWindow
|
||||
return @@RGSSWINDOW if @@RGSSWINDOW
|
||||
processid = [0].pack('l')
|
||||
threadid = @@GetCurrentThreadId.call
|
||||
nextwindow = 0
|
||||
begin
|
||||
nextwindow = @@FindWindowEx.call(0,nextwindow,"RGSS Player",0)
|
||||
if nextwindow!=0
|
||||
wndthreadid = @@GetWindowThreadProcessId.call(nextwindow,processid)
|
||||
if wndthreadid==threadid
|
||||
@@RGSSWINDOW = nextwindow
|
||||
return @@RGSSWINDOW
|
||||
end
|
||||
end
|
||||
end until nextwindow==0
|
||||
raise "Can't find RGSS player window"
|
||||
return 0
|
||||
end
|
||||
|
||||
def Win32API.SetWindowPos(w, h)
|
||||
hWnd = pbFindRgssWindow
|
||||
windowrect = Win32API.GetWindowRect
|
||||
clientsize = Win32API.client_size
|
||||
xExtra = windowrect.width-clientsize[0]
|
||||
yExtra = windowrect.height-clientsize[1]
|
||||
swp = Win32API.new('user32','SetWindowPos',%(l,l,i,i,i,i,i),'i')
|
||||
win = swp.call(hWnd,0,windowrect.x,windowrect.y,w+xExtra,h+yExtra,0)
|
||||
return win
|
||||
end
|
||||
|
||||
def Win32API.client_size
|
||||
hWnd = pbFindRgssWindow
|
||||
rect = [0,0,0,0].pack('l4')
|
||||
Win32API.new('user32','GetClientRect',%w(l p),'i').call(hWnd,rect)
|
||||
width,height = rect.unpack('l4')[2..3]
|
||||
return width,height
|
||||
end
|
||||
|
||||
def Win32API.GetWindowRect
|
||||
hWnd = pbFindRgssWindow
|
||||
rect = [0,0,0,0].pack('l4')
|
||||
Win32API.new('user32','GetWindowRect',%w(l p),'i').call(hWnd,rect)
|
||||
x,y,width,height = rect.unpack('l4')
|
||||
return Rect.new(x,y,width-x,height-y)
|
||||
end
|
||||
|
||||
def Win32API.focusWindow
|
||||
window = Win32API.new('user32','ShowWindow','LL','L')
|
||||
hWnd = pbFindRgssWindow
|
||||
window.call(hWnd,9)
|
||||
end
|
||||
|
||||
def Win32API.fillScreen
|
||||
setWindowLong = Win32API.new('user32','SetWindowLong','LLL','L')
|
||||
setWindowPos = Win32API.new('user32','SetWindowPos','LLIIIII','I')
|
||||
metrics = Win32API.new('user32', 'GetSystemMetrics', 'I', 'I')
|
||||
hWnd = pbFindRgssWindow
|
||||
width = metrics.call(0)
|
||||
height = metrics.call(1)
|
||||
setWindowLong.call(hWnd,-16,0x00000000)
|
||||
setWindowPos.call(hWnd,0,0,0,width,height,0)
|
||||
Win32API.focusWindow
|
||||
return [width,height]
|
||||
end
|
||||
|
||||
def Win32API.restoreScreen
|
||||
setWindowLong = Win32API.new('user32','SetWindowLong','LLL','L')
|
||||
setWindowPos = Win32API.new('user32','SetWindowPos','LLIIIII','I')
|
||||
metrics = Win32API.new('user32','GetSystemMetrics','I','I')
|
||||
hWnd = pbFindRgssWindow
|
||||
width = SCREEN_WIDTH*$ResizeFactor
|
||||
height = SCREEN_HEIGHT*$ResizeFactor
|
||||
if $PokemonSystem && $PokemonSystem.border==1
|
||||
width += BORDER_WIDTH*2*$ResizeFactor
|
||||
height += BORDER_HEIGHT*2*$ResizeFactor
|
||||
end
|
||||
x = [(metrics.call(0)-width)/2,0].max
|
||||
y = [(metrics.call(1)-height)/2,0].max
|
||||
setWindowLong.call(hWnd,-16,0x14CA0000)
|
||||
setWindowPos.call(hWnd,0,x,y,width+6,height+29,0)
|
||||
Win32API.focusWindow
|
||||
return [width,height]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Well done for finding this place.
|
||||
# DO NOT EDIT THESE
|
||||
ESSENTIALS_VERSION = "18"
|
||||
ERROR_TEXT = ""
|
||||
696
Data/Scripts/001_Technical/005_Sockets.rb
Normal file
696
Data/Scripts/001_Technical/005_Sockets.rb
Normal file
@@ -0,0 +1,696 @@
|
||||
module Win32
|
||||
def copymem(len)
|
||||
buf = "\0" * len
|
||||
Win32API.new("kernel32", "RtlMoveMemory", "ppl", "").call(buf, self, len)
|
||||
buf
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Extends the numeric class.
|
||||
class Numeric
|
||||
include Win32
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Extends the string class.
|
||||
class String
|
||||
include Win32
|
||||
end
|
||||
|
||||
|
||||
|
||||
module Winsock
|
||||
DLL = "ws2_32"
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Accept Connection
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.accept(*args)
|
||||
Win32API.new(DLL, "accept", "ppl", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Bind
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.bind(*args)
|
||||
Win32API.new(DLL, "bind", "ppl", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Close Socket
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.closesocket(*args)
|
||||
Win32API.new(DLL, "closesocket", "p", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Connect
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.connect(*args)
|
||||
Win32API.new(DLL, "connect", "ppl", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Get host (Using Adress)
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.gethostbyaddr(*args)
|
||||
Win32API.new(DLL, "gethostbyaddr", "pll", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Get host (Using Name)
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.gethostbyname(*args)
|
||||
Win32API.new(DLL, "gethostbyname", "p", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Get host's Name
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.gethostname(*args)
|
||||
Win32API.new(DLL, "gethostname", "pl", "").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Get Server (Using Name)
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.getservbyname(*args)
|
||||
Win32API.new(DLL, "getservbyname", "pp", "p").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Convert Host Long To Network Long
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.htonl(*args)
|
||||
Win32API.new(DLL, "htonl", "l", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Convert Host Short To Network Short
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.htons(*args)
|
||||
Win32API.new(DLL, "htons", "l", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Inet Adress
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.inet_addr(*args)
|
||||
Win32API.new(DLL, "inet_addr", "p", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Inet N To A
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.inet_ntoa(*args)
|
||||
Win32API.new(DLL, "inet_ntoa", "l", "p").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Listen
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.listen(*args)
|
||||
Win32API.new(DLL, "listen", "pl", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Recieve
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.recv(*args)
|
||||
Win32API.new(DLL, "recv", "ppll", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Select
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.select(*args)
|
||||
Win32API.new(DLL, "select", "lpppp", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Send
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.send(*args)
|
||||
Win32API.new(DLL, "send", "ppll", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Set Socket Options
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.setsockopt(*args)
|
||||
Win32API.new(DLL, "setsockopt", "pllpl", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Shutdown
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.shutdown(*args)
|
||||
Win32API.new(DLL, "shutdown", "pl", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Socket
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.socket(*args)
|
||||
Win32API.new(DLL, "socket", "lll", "l").call(*args)
|
||||
end
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Get Last Error
|
||||
#-----------------------------------------------------------------------------
|
||||
def self.WSAGetLastError(*args)
|
||||
Win32API.new(DLL, "WSAGetLastError", "", "l").call(*args)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if !Object.const_defined?(:Socket) # for compatibility
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# ** Socket - Creates and manages sockets.
|
||||
#-------------------------------------------------------------------------------
|
||||
# Author Ruby
|
||||
# Version 1.8.1
|
||||
#===============================================================================
|
||||
class Socket
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Constants
|
||||
#-----------------------------------------------------------------------------
|
||||
AF_UNSPEC = 0
|
||||
AF_UNIX = 1
|
||||
AF_INET = 2
|
||||
AF_IPX = 6
|
||||
AF_APPLETALK = 16
|
||||
PF_UNSPEC = 0
|
||||
PF_UNIX = 1
|
||||
PF_INET = 2
|
||||
PF_IPX = 6
|
||||
PF_APPLETALK = 16
|
||||
SOCK_STREAM = 1
|
||||
SOCK_DGRAM = 2
|
||||
SOCK_RAW = 3
|
||||
SOCK_RDM = 4
|
||||
SOCK_SEQPACKET = 5
|
||||
IPPROTO_IP = 0
|
||||
IPPROTO_ICMP = 1
|
||||
IPPROTO_IGMP = 2
|
||||
IPPROTO_GGP = 3
|
||||
IPPROTO_TCP = 6
|
||||
IPPROTO_PUP = 12
|
||||
IPPROTO_UDP = 17
|
||||
IPPROTO_IDP = 22
|
||||
IPPROTO_ND = 77
|
||||
IPPROTO_RAW = 255
|
||||
IPPROTO_MAX = 256
|
||||
SOL_SOCKET = 65535
|
||||
SO_DEBUG = 1
|
||||
SO_REUSEADDR = 4
|
||||
SO_KEEPALIVE = 8
|
||||
SO_DONTROUTE = 16
|
||||
SO_BROADCAST = 32
|
||||
SO_LINGER = 128
|
||||
SO_OOBINLINE = 256
|
||||
SO_RCVLOWAT = 4100
|
||||
SO_SNDTIMEO = 4101
|
||||
SO_RCVTIMEO = 4102
|
||||
SO_ERROR = 4103
|
||||
SO_TYPE = 4104
|
||||
SO_SNDBUF = 4097
|
||||
SO_RCVBUF = 4098
|
||||
SO_SNDLOWAT = 4099
|
||||
TCP_NODELAY = 1
|
||||
MSG_OOB = 1
|
||||
MSG_PEEK = 2
|
||||
MSG_DONTROUTE = 4
|
||||
IP_OPTIONS = 1
|
||||
IP_DEFAULT_MULTICAST_LOOP = 1
|
||||
IP_DEFAULT_MULTICAST_TTL = 1
|
||||
IP_MULTICAST_IF = 2
|
||||
IP_MULTICAST_TTL = 3
|
||||
IP_MULTICAST_LOOP = 4
|
||||
IP_ADD_MEMBERSHIP = 5
|
||||
IP_DROP_MEMBERSHIP = 6
|
||||
IP_TTL = 7
|
||||
IP_TOS = 8
|
||||
IP_MAX_MEMBERSHIPS = 20
|
||||
EAI_ADDRFAMILY = 1
|
||||
EAI_AGAIN = 2
|
||||
EAI_BADFLAGS = 3
|
||||
EAI_FAIL = 4
|
||||
EAI_FAMILY = 5
|
||||
EAI_MEMORY = 6
|
||||
EAI_NODATA = 7
|
||||
EAI_NONAME = 8
|
||||
EAI_SERVICE = 9
|
||||
EAI_SOCKTYPE = 10
|
||||
EAI_SYSTEM = 11
|
||||
EAI_BADHINTS = 12
|
||||
EAI_PROTOCOL = 13
|
||||
EAI_MAX = 14
|
||||
AI_PASSIVE = 1
|
||||
AI_CANONNAME = 2
|
||||
AI_NUMERICHOST = 4
|
||||
AI_MASK = 7
|
||||
AI_ALL = 256
|
||||
AI_V4MAPPED_CFG = 512
|
||||
AI_ADDRCONFIG = 1024
|
||||
AI_DEFAULT = 1536
|
||||
AI_V4MAPPED = 2048
|
||||
#--------------------------------------------------------------------------
|
||||
# * Returns the associated IP address for the given hostname.
|
||||
#--------------------------------------------------------------------------
|
||||
def self.getaddress(host)
|
||||
gethostbyname(host)[3].unpack("C4").join(".")
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Returns the associated IP address for the given hostname.
|
||||
#--------------------------------------------------------------------------
|
||||
def self.getservice(serv)
|
||||
case serv
|
||||
when Numeric
|
||||
return serv
|
||||
when String
|
||||
return getservbyname(serv)
|
||||
else
|
||||
raise "Please use an integer or string for services."
|
||||
end
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Returns information about the given hostname.
|
||||
#--------------------------------------------------------------------------
|
||||
def self.gethostbyname(name)
|
||||
raise SocketError::ENOASSOCHOST if (ptr = Winsock.gethostbyname(name)) == 0
|
||||
host = ptr.copymem(16).unpack("iissi")
|
||||
[host[0].copymem(64).split("\0")[0], [], host[2], host[4].copymem(4).unpack("l")[0].copymem(4)]
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Returns the user's hostname.
|
||||
#--------------------------------------------------------------------------
|
||||
def self.gethostname
|
||||
buf = "\0" * 256
|
||||
Winsock.gethostname(buf, 256)
|
||||
buf.strip
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Returns information about the given service.
|
||||
#--------------------------------------------------------------------------
|
||||
def self.getservbyname(name)
|
||||
case name
|
||||
when /echo/i
|
||||
return 7
|
||||
when /daytime/i
|
||||
return 13
|
||||
when /ftp/i
|
||||
return 21
|
||||
when /telnet/i
|
||||
return 23
|
||||
when /smtp/i
|
||||
return 25
|
||||
when /time/i
|
||||
return 37
|
||||
when /http/i
|
||||
return 80
|
||||
when /pop/i
|
||||
return 110
|
||||
else
|
||||
#Network.testing? != 0 ? (Network.testresult(true)) : (raise "Service not recognized.")
|
||||
#return if Network.testing? == 2
|
||||
end
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Creates an INET-sockaddr struct.
|
||||
#--------------------------------------------------------------------------
|
||||
def self.sockaddr_in(port, host)
|
||||
begin
|
||||
[AF_INET, getservice(port)].pack("sn") + gethostbyname(host)[3] + [].pack("x8")
|
||||
rescue
|
||||
#Network.testing? != 0 ? (Network.testresult(true)): (nil)
|
||||
#return if Network.testing? == 2
|
||||
rescue Hangup
|
||||
#Network.testing? != 0 ? (Network.testresult(true)): (nil)
|
||||
#return if Network.testing? == 2
|
||||
end
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Creates a new socket and connects it to the given host and port.
|
||||
#--------------------------------------------------------------------------
|
||||
def self.open(*args)
|
||||
socket = new(*args)
|
||||
if block_given?
|
||||
begin
|
||||
yield socket
|
||||
ensure
|
||||
socket.close
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Creates a new socket.
|
||||
#--------------------------------------------------------------------------
|
||||
def initialize(domain, type, protocol)
|
||||
SocketError.check if (@fd = Winsock.socket(domain, type, protocol)) == -1
|
||||
@fd
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Accepts incoming connections.
|
||||
#--------------------------------------------------------------------------
|
||||
def accept(flags = 0)
|
||||
buf = "\0" * 16
|
||||
SocketError.check if Winsock.accept(@fd, buf, flags) == -1
|
||||
buf
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Binds a socket to the given sockaddr.
|
||||
#--------------------------------------------------------------------------
|
||||
def bind(sockaddr)
|
||||
SocketError.check if (ret = Winsock.bind(@fd, sockaddr, sockaddr.size)) == -1
|
||||
ret
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Closes a socket.
|
||||
#--------------------------------------------------------------------------
|
||||
def close
|
||||
SocketError.check if (ret = Winsock.closesocket(@fd)) == -1
|
||||
ret
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Connects a socket to the given sockaddr.
|
||||
#--------------------------------------------------------------------------
|
||||
def connect(sockaddr)
|
||||
#return if Network.testing? == 2
|
||||
SocketError.check if (ret = Winsock.connect(@fd, sockaddr, sockaddr.size)) == -1
|
||||
ret
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Listens for incoming connections.
|
||||
#--------------------------------------------------------------------------
|
||||
def listen(backlog)
|
||||
SocketError.check if (ret = Winsock.listen(@fd, backlog)) == -1
|
||||
ret
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Checks waiting data's status.
|
||||
#--------------------------------------------------------------------------
|
||||
def select(timeout) # timeout in seconds
|
||||
SocketError.check if (ret = Winsock.select(1, [1, @fd].pack("ll"), 0, 0, [timeout.to_i,
|
||||
(timeout * 1000000).to_i].pack("ll"))) == -1
|
||||
ret
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Checks if data is waiting.
|
||||
#--------------------------------------------------------------------------
|
||||
def ready?
|
||||
not select(0) == 0
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Reads data from socket.
|
||||
#--------------------------------------------------------------------------
|
||||
def read(len)
|
||||
buf = "\0" * len
|
||||
Win32API.new("msvcrt", "_read", "lpl", "l").call(@fd, buf, len)
|
||||
buf
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Returns received data.
|
||||
#--------------------------------------------------------------------------
|
||||
def recv(len, flags = 0)
|
||||
retString=""
|
||||
remainLen=len
|
||||
while remainLen > 0
|
||||
buf = "\0" * remainLen
|
||||
retval=Winsock.recv(@fd, buf, buf.size, flags)
|
||||
SocketError.check if retval == -1
|
||||
# Note: Return value may not equal requested length
|
||||
remainLen-=retval
|
||||
retString+=buf[0,retval]
|
||||
end
|
||||
return retString
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Sends data to a host.
|
||||
#--------------------------------------------------------------------------
|
||||
def send(data, flags = 0)
|
||||
SocketError.check if (ret = Winsock.send(@fd, data, data.size, flags)) == -1
|
||||
ret
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Recieves file from a socket
|
||||
# size : file size
|
||||
# scene : update scene boolean
|
||||
#--------------------------------------------------------------------------
|
||||
def recv_file(size,scene=false,file="")
|
||||
data = []
|
||||
size.times do |i|
|
||||
if scene == true
|
||||
$scene.recv_update(size,i,file) if i%((size/1000)+1)== 0
|
||||
else
|
||||
Graphics.update if i%1024 == 0
|
||||
end
|
||||
data << recv(1)
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
def recvTimeout
|
||||
if select(10)==0
|
||||
raise Hangup.new("Timeout")
|
||||
end
|
||||
return recv(1)
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Gets
|
||||
#--------------------------------------------------------------------------
|
||||
def gets
|
||||
# Create buffer
|
||||
message = ""
|
||||
# Loop Until "end of line"
|
||||
count=0
|
||||
while true
|
||||
x=select(0.05)
|
||||
if x==0
|
||||
count+=1
|
||||
Graphics.update if count%10==0
|
||||
raise Errno::ETIMEOUT if count>200
|
||||
next
|
||||
end
|
||||
ch = recv(1)
|
||||
break if ch == "\n"
|
||||
message += ch
|
||||
end
|
||||
# Return recieved data
|
||||
return message
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Writes data to socket.
|
||||
#--------------------------------------------------------------------------
|
||||
def write(data)
|
||||
Win32API.new("msvcrt", "_write", "lpl", "l").call(@fd, data, 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# ** TCPSocket - Creates and manages TCP sockets.
|
||||
#-------------------------------------------------------------------------------
|
||||
# Author Ruby
|
||||
# Version 1.8.1
|
||||
#===============================================================================
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Begin SDK Enabled Check
|
||||
#-------------------------------------------------------------------------------
|
||||
class TCPSocket < Socket
|
||||
#--------------------------------------------------------------------------
|
||||
# * Creates a new socket and connects it to the given host and port.
|
||||
#--------------------------------------------------------------------------
|
||||
def self.open(*args)
|
||||
socket = new(*args)
|
||||
if block_given?
|
||||
begin
|
||||
yield socket
|
||||
ensure
|
||||
socket.close
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
#--------------------------------------------------------------------------
|
||||
# * Creates a new socket and connects it to the given host and port.
|
||||
#--------------------------------------------------------------------------
|
||||
def initialize(host, port)
|
||||
super(AF_INET, SOCK_STREAM, IPPROTO_TCP)
|
||||
connect(Socket.sockaddr_in(port, host))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# ** SocketError
|
||||
#------------------------------------------------------------------------------
|
||||
# Default exception class for sockets.
|
||||
#==============================================================================
|
||||
class SocketError < StandardError
|
||||
ENOASSOCHOST = "getaddrinfo: no address associated with hostname."
|
||||
|
||||
def self.check
|
||||
errno = Winsock.WSAGetLastError
|
||||
#if not Network.testing? == 1
|
||||
raise Errno.const_get(Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno })
|
||||
#else
|
||||
# errno != 0 ? (Network.testresult(true)) : (Network.testresult(false))
|
||||
#end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end # !Object.const_defined?(:Socket)
|
||||
|
||||
|
||||
#############################
|
||||
#
|
||||
# HTTP utility functions
|
||||
#
|
||||
#############################
|
||||
def pbPostData(url, postdata, filename=nil, depth=0)
|
||||
if url[/^http:\/\/([^\/]+)(.*)$/]
|
||||
host = $1
|
||||
path = $2
|
||||
path = "/" if path.length==0
|
||||
userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.14) Gecko/2009082707 Firefox/3.0.14"
|
||||
body = postdata.map { |key, value|
|
||||
keyString = key.to_s
|
||||
valueString = value.to_s
|
||||
keyString.gsub!(/[^a-zA-Z0-9_\.\-]/n) { |s| sprintf('%%%02x', s[0]) }
|
||||
valueString.gsub!(/[^a-zA-Z0-9_\.\-]/n) { |s| sprintf('%%%02x', s[0]) }
|
||||
next "#{keyString}=#{valueString}"
|
||||
}.join('&')
|
||||
request = "POST #{path} HTTP/1.1\r\n"
|
||||
request += "Host: #{host}\r\n"
|
||||
request += "Proxy-Connection: Close\r\n"
|
||||
request += "Content-Length: #{body.length}\r\n"
|
||||
request += "Pragma: no-cache\r\n"
|
||||
request += "User-Agent: #{userAgent}\r\n"
|
||||
request += "Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
request += "\r\n"
|
||||
request += body
|
||||
return pbHttpRequest(host, request, filename, depth)
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
def pbDownloadData(url, filename=nil, depth=0)
|
||||
raise "Redirection level too deep" if depth>10
|
||||
if url[/^http:\/\/([^\/]+)(.*)$/]
|
||||
host = $1
|
||||
path = $2
|
||||
path = "/" if path.length==0
|
||||
userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.14) Gecko/2009082707 Firefox/3.0.14"
|
||||
request = "GET #{path} HTTP/1.1\r\n"
|
||||
request += "User-Agent: #{userAgent}\r\n"
|
||||
request += "Pragma: no-cache\r\n"
|
||||
request += "Host: #{host}\r\n"
|
||||
request += "Proxy-Connection: Close\r\n"
|
||||
request += "\r\n"
|
||||
return pbHttpRequest(host, request, filename, depth)
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
def pbHttpRequest(host, request, filename=nil, depth=0)
|
||||
raise "Redirection level too deep" if depth>10
|
||||
socket = ::TCPSocket.new(host, 80)
|
||||
time = Time.now.to_i
|
||||
begin
|
||||
socket.send(request)
|
||||
result = socket.gets
|
||||
data = ""
|
||||
# Get the HTTP result
|
||||
if result[/^HTTP\/1\.[01] (\d+).*/]
|
||||
errorcode = $1.to_i
|
||||
raise "HTTP Error #{errorcode}" if errorcode>=400 && errorcode<500
|
||||
headers = {}
|
||||
# Get the response headers
|
||||
while true
|
||||
result = socket.gets.sub(/\r$/,"")
|
||||
break if result==""
|
||||
if result[/^([^:]+):\s*(.*)/]
|
||||
headers[$1] = $2
|
||||
end
|
||||
end
|
||||
length = -1
|
||||
chunked = false
|
||||
if headers["Content-Length"]
|
||||
length = headers["Content-Length"].to_i
|
||||
end
|
||||
if headers["Transfer-Encoding"]=="chunked"
|
||||
chunked = true
|
||||
end
|
||||
if headers["Location"] && errorcode>=300 && errorcode<400
|
||||
socket.close rescue socket = nil
|
||||
return pbDownloadData(headers["Location"],filename,depth+1)
|
||||
end
|
||||
if chunked
|
||||
# Chunked content
|
||||
while true
|
||||
lengthline = socket.gets.sub(/\r$/,"")
|
||||
length = lengthline.to_i(16)
|
||||
break if length==0
|
||||
while Time.now.to_i-time>=5 || socket.select(10)==0
|
||||
time = Time.now.to_i
|
||||
Graphics.update
|
||||
end
|
||||
data += socket.recv(length)
|
||||
socket.gets
|
||||
end
|
||||
elsif length==-1
|
||||
# No content length specified
|
||||
while true
|
||||
break if socket.select(500)==0
|
||||
while Time.now.to_i-time>=5 || socket.select(10)==0
|
||||
time = Time.now.to_i
|
||||
Graphics.update
|
||||
end
|
||||
data += socket.recv(1)
|
||||
end
|
||||
else
|
||||
# Content length specified
|
||||
while length>0
|
||||
chunk = [length,4096].min
|
||||
while Time.now.to_i-time>=5 || socket.select(10)==0
|
||||
time = Time.now.to_i
|
||||
Graphics.update
|
||||
end
|
||||
data += socket.recv(chunk)
|
||||
length -= chunk
|
||||
end
|
||||
end
|
||||
end
|
||||
return data if !filename
|
||||
File.open(filename,"wb") { |f| f.write(data) }
|
||||
ensure
|
||||
socket.close rescue socket = nil
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
def pbDownloadToString(url)
|
||||
begin
|
||||
data = pbDownloadData(url)
|
||||
return data
|
||||
rescue
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
def pbDownloadToFile(url, file)
|
||||
begin
|
||||
pbDownloadData(url,file)
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
def pbPostToString(url, postdata)
|
||||
begin
|
||||
data = pbPostData(url, postdata)
|
||||
return data
|
||||
rescue
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
def pbPostToFile(url, postdata, file)
|
||||
begin
|
||||
pbPostData(url, postdata,file)
|
||||
rescue
|
||||
end
|
||||
end
|
||||
158
Data/Scripts/001_Technical/006_DebugConsole.rb
Normal file
158
Data/Scripts/001_Technical/006_DebugConsole.rb
Normal file
@@ -0,0 +1,158 @@
|
||||
module Console
|
||||
attr_reader :bufferHandle
|
||||
GENERIC_READ = 0x80000000
|
||||
GENERIC_WRITE = 0x40000000
|
||||
FILE_SHARE_READ = 0x00000001
|
||||
FILE_SHARE_WRITE = 0x00000002
|
||||
CONSOLE_TEXTMODE_BUFFER = 0x00000001
|
||||
|
||||
def Console::AllocConsole
|
||||
return @apiAllocConsole.call
|
||||
end
|
||||
|
||||
def Console::CreateConsoleScreenBuffer(dwDesiredAccess,dwShareMode,dwFlags)
|
||||
return @apiCreateConsoleScreenBuffer.call(dwDesiredAccess,dwShareMode,nil,dwFlags,nil)
|
||||
end
|
||||
|
||||
def Console::WriteConsole(lpBuffer)
|
||||
hFile = @bufferHandle
|
||||
return if !hFile
|
||||
return @apiWriteConsole.call(hFile,lpBuffer,lpBuffer.size,0,0)
|
||||
end
|
||||
|
||||
def Console::ReadConsole(lpBuffer)
|
||||
hFile = @bufferHandle
|
||||
return @apiReadConsole.call(hFile,lpBuffer,lpBuffer.size,0,0)
|
||||
end
|
||||
|
||||
def Console::SetConsoleActiveScreenBuffer(hScreenBuffer)
|
||||
return @apiSetConsoleActiveScreenBuffer.call(hScreenBuffer)
|
||||
end
|
||||
|
||||
def Console::SetConsoleScreenBufferSize(hScreenBuffer,x,y)
|
||||
return @apiSetConsoleScreenBufferSize.call(hScreenBuffer,[x,y].pack("vv"))
|
||||
end
|
||||
|
||||
def Console::SetConsoleTitle(title)
|
||||
return @apiSetConsoleTitle.call(title)
|
||||
end
|
||||
|
||||
def self.setup_console
|
||||
return unless $DEBUG
|
||||
@apiAllocConsole = Win32API.new("kernel32","AllocConsole","","l")
|
||||
@apiCreateConsoleScreenBuffer = Win32API.new("kernel32","CreateConsoleScreenBuffer","nnpnp","l")
|
||||
@apiSetConsoleActiveScreenBuffer = Win32API.new("kernel32","SetConsoleActiveScreenBuffer","l","s")
|
||||
@apiWriteConsole = Win32API.new("kernel32","WriteConsole","lpnnn","S")
|
||||
@apiReadConsole = Win32API.new("kernel32","ReadConsole","lpnnn","S")
|
||||
@apiSetConsoleScreenBufferSize = Win32API.new("kernel32","SetConsoleScreenBufferSize","lp","S")
|
||||
@apiSetConsoleTitle = Win32API.new("kernel32","SetConsoleTitle","p","s")
|
||||
access = (GENERIC_READ | GENERIC_WRITE)
|
||||
sharemode = (FILE_SHARE_READ | FILE_SHARE_WRITE)
|
||||
returnCode = AllocConsole()
|
||||
@bufferHandle = CreateConsoleScreenBuffer(access,sharemode,CONSOLE_TEXTMODE_BUFFER)
|
||||
f = File.open("Game.ini")
|
||||
lines = f.readlines()
|
||||
s = lines[3]
|
||||
len = s.size
|
||||
title = (s[6,len - 7])
|
||||
SetConsoleScreenBufferSize(@bufferHandle,100,2000)
|
||||
SetConsoleTitle("Debug Console -- #{title}")
|
||||
echo "#{title} Output Window\n"
|
||||
echo "-------------------------------\n"
|
||||
echo "If you are seeing this window, you are running\n"
|
||||
echo "#{title} in Debug Mode. This means\n"
|
||||
echo "that you're either playing a Debug Version, or\n"
|
||||
echo "you are playing from within RPG Maker XP.\n"
|
||||
echo "\n"
|
||||
echo "Closing this window will close the game. If \n"
|
||||
echo "you want to get rid of this window, run the\n"
|
||||
echo "program from the Shell, or download a Release\n"
|
||||
echo "version.\n"
|
||||
echo "\n"
|
||||
echo "Gameplay will be paused while the console has\n"
|
||||
echo "focus. To resume playing, switch to the Game\n"
|
||||
echo "Window.\n"
|
||||
echo "-------------------------------\n"
|
||||
echo "Debug Output:\n"
|
||||
echo "-------------------------------\n\n"
|
||||
SetConsoleActiveScreenBuffer(@bufferHandle)
|
||||
end
|
||||
|
||||
def self.readInput
|
||||
length=20
|
||||
buffer=0.chr*length
|
||||
eventsread=0.chr*4
|
||||
done=false
|
||||
input=""
|
||||
while !done
|
||||
echo("waiting for input")
|
||||
begin
|
||||
@apiReadConsole.call(@bufferHandle,buffer,1,eventsread)
|
||||
rescue Hangup
|
||||
return
|
||||
end
|
||||
offset=0
|
||||
events=eventsread.unpack("V")
|
||||
echo("got input [eventsread #{events}")
|
||||
for i in 0...events[0]
|
||||
keyevent=buffer[offset,20]
|
||||
keyevent=keyevent.unpack("vCvvvvV")
|
||||
if keyevent[0]==1 && keyevent[1]>0
|
||||
input+=keyevent[4].chr
|
||||
if keyevent[4].chr=="\n"
|
||||
done=true
|
||||
break
|
||||
end
|
||||
end
|
||||
offset+=20
|
||||
end
|
||||
end
|
||||
return input
|
||||
end
|
||||
|
||||
def self.readInput2
|
||||
buffer=0.chr
|
||||
done=false
|
||||
input=""
|
||||
eventsread=0.chr*4
|
||||
while !done
|
||||
if ReadConsole(buffer)==0
|
||||
getlast = Win32API.new("kernel32","GetLastError","","n")
|
||||
echo(sprintf("failed (%d)\r\n",getlast.call()))
|
||||
break
|
||||
end
|
||||
offset=0
|
||||
events=eventsread.unpack("V")
|
||||
if events[0]>0
|
||||
echo("got input [eventsread #{events}][buffer #{buffer}]\r\n")
|
||||
key=buffer[0,events[0]]
|
||||
input+=key
|
||||
if key=="\n"
|
||||
break
|
||||
end
|
||||
Graphics.update
|
||||
end
|
||||
end
|
||||
return input
|
||||
end
|
||||
|
||||
def self.get_input
|
||||
echo self.readInput2
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module Kernel
|
||||
def echo(string)
|
||||
unless $DEBUG
|
||||
return
|
||||
end
|
||||
Console::WriteConsole(string.is_a?(String) ? string : string.inspect)
|
||||
end
|
||||
|
||||
def echoln(string)
|
||||
echo(string)
|
||||
echo("\r\n")
|
||||
end
|
||||
end
|
||||
757
Data/Scripts/001_Technical/007_Sprite_Resizer.rb
Normal file
757
Data/Scripts/001_Technical/007_Sprite_Resizer.rb
Normal file
@@ -0,0 +1,757 @@
|
||||
#===============================================================================
|
||||
# Overriding Sprite, Viewport, and Plane to support resizing
|
||||
# By Peter O.
|
||||
# Modified by Luka S.J. and Maruno to support fullscreen and more sizes.
|
||||
# -- This is a stand-alone RGSS script. --
|
||||
#===============================================================================
|
||||
$ResizeFactor = 1.0
|
||||
$ResizeFactorMul = 100
|
||||
$ResizeOffsetX = 0
|
||||
$ResizeOffsetY = 0
|
||||
$ResizeFactorSet = false
|
||||
$HaveResizeBorder = false
|
||||
|
||||
if true # Disables using Alt+Enter to go fullscreen
|
||||
regHotKey = Win32API.new('user32', 'RegisterHotKey', 'LIII', 'I')
|
||||
regHotKey.call(0, 1, 1, 0x0D)
|
||||
end
|
||||
|
||||
def pbSetResizeFactor(factor=1,norecalc=false)
|
||||
factor = [0.5,1.0,2.0,-1][factor] if !norecalc
|
||||
(factor<0) ? pbConfigureFullScreen : pbConfigureWindowedScreen(factor)
|
||||
end
|
||||
|
||||
def pbSetResizeFactor2(factor,force=false)
|
||||
if $ResizeFactor!=factor || force
|
||||
$ResizeFactor = factor
|
||||
$ResizeFactorMul = (factor*100).to_i
|
||||
pbRefreshResizeFactor if $ResizeFactorSet
|
||||
end
|
||||
$ResizeFactorSet = true
|
||||
$ResizeBorder.refresh if $HaveResizeBorder
|
||||
begin
|
||||
if Graphics.haveresizescreen
|
||||
Graphics.oldresizescreen(
|
||||
(Graphics.width+$ResizeOffsetX*2)*factor,
|
||||
(Graphics.height+$ResizeOffsetY*2)*factor
|
||||
)
|
||||
end
|
||||
Win32API.SetWindowPos(
|
||||
(Graphics.width+$ResizeOffsetX*2)*factor,
|
||||
(Graphics.height+$ResizeOffsetY*2)*factor
|
||||
)
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
def pbRefreshResizeFactor
|
||||
ObjectSpace.each_object(Sprite) { |o|
|
||||
next if o.disposed?
|
||||
o.x = o.x
|
||||
o.y = o.y
|
||||
o.ox = o.ox
|
||||
o.oy = o.oy
|
||||
o.zoom_x = o.zoom_x
|
||||
o.zoom_y = o.zoom_y
|
||||
}
|
||||
ObjectSpace.each_object(Viewport) { |o|
|
||||
begin
|
||||
o.rect = o.rect
|
||||
o.ox = o.ox
|
||||
o.oy = o.oy
|
||||
rescue RGSSError
|
||||
end
|
||||
}
|
||||
ObjectSpace.each_object(Plane) { |o|
|
||||
next if o.disposed?
|
||||
o.zoom_x = o.zoom_x
|
||||
o.zoom_y = o.zoom_y
|
||||
}
|
||||
end
|
||||
|
||||
def pbConfigureFullScreen
|
||||
params = Win32API.fillScreen
|
||||
fullgamew = gamew = SCREEN_WIDTH
|
||||
fullgameh = gameh = SCREEN_HEIGHT
|
||||
if !BORDER_FULLY_SHOWS && $PokemonSystem && $PokemonSystem.border==1
|
||||
fullgamew += BORDER_WIDTH * 2
|
||||
fullgameh += BORDER_HEIGHT * 2
|
||||
end
|
||||
# factor_x = ((2*params[0])/fullgamew).floor
|
||||
# factor_y = ((2*params[1])/fullgameh).floor
|
||||
# factor = [factor_x,factor_y].min/2.0
|
||||
factor_x = (params[0]/fullgamew).floor
|
||||
factor_y = (params[1]/fullgameh).floor
|
||||
factor = [factor_x,factor_y].min
|
||||
offset_x = (params[0]-gamew*factor)/(2*factor)
|
||||
offset_y = (params[1]-gameh*factor)/(2*factor)
|
||||
$ResizeOffsetX = offset_x
|
||||
$ResizeOffsetY = offset_y
|
||||
ObjectSpace.each_object(Viewport) { |o|
|
||||
begin
|
||||
next if o.rect.nil?
|
||||
ox = o.rect.x-$ResizeOffsetX
|
||||
oy = o.rect.y-$ResizeOffsetY
|
||||
o.rect.x = ox+offset_x
|
||||
o.rect.y = oy+offset_y
|
||||
rescue RGSSError
|
||||
end
|
||||
}
|
||||
pbSetResizeFactor2(factor,true)
|
||||
end
|
||||
|
||||
def pbConfigureWindowedScreen(value)
|
||||
border = $PokemonSystem ? $PokemonSystem.border : 0
|
||||
$ResizeOffsetX = [0,BORDER_WIDTH][border]
|
||||
$ResizeOffsetY = [0,BORDER_HEIGHT][border]
|
||||
pbSetResizeFactor2(value,true)
|
||||
Win32API.restoreScreen
|
||||
end
|
||||
|
||||
def setScreenBorderName(border)
|
||||
if !$HaveResizeBorder
|
||||
$ResizeBorder = ScreenBorder.new
|
||||
$HaveResizeBorder = true
|
||||
end
|
||||
$ResizeBorder.bordername = border if $ResizeBorder
|
||||
end
|
||||
|
||||
|
||||
|
||||
module Graphics
|
||||
## Nominal screen size
|
||||
@@width = SCREEN_WIDTH
|
||||
@@height = SCREEN_HEIGHT
|
||||
|
||||
def self.width
|
||||
return @@width.to_i
|
||||
end
|
||||
|
||||
def self.height
|
||||
return @@height.to_i
|
||||
end
|
||||
|
||||
@@fadeoutvp = Viewport.new(0,0,640,480)
|
||||
@@fadeoutvp.z = 0x3FFFFFFF
|
||||
@@fadeoutvp.color = Color.new(0,0,0,0)
|
||||
|
||||
def self.brightness
|
||||
return 255-@@fadeoutvp.color.alpha
|
||||
end
|
||||
|
||||
def self.brightness=(value)
|
||||
value = 0 if value<0
|
||||
value = 255 if value>255
|
||||
@@fadeoutvp.color.alpha = 255-value
|
||||
end
|
||||
|
||||
def self.fadein(frames)
|
||||
return if frames<=0
|
||||
curvalue = self.brightness
|
||||
count = (255-self.brightness)
|
||||
frames.times do |i|
|
||||
self.brightness = curvalue+(count*i/frames)
|
||||
self.update
|
||||
end
|
||||
end
|
||||
|
||||
def self.wait(frames)
|
||||
return if frames<=0
|
||||
frames.times do |i|
|
||||
self.update
|
||||
end
|
||||
end
|
||||
|
||||
def self.fadeout(frames)
|
||||
return if frames<=0
|
||||
curvalue = self.brightness
|
||||
count = self.brightness
|
||||
frames.times do |i|
|
||||
self.brightness = curvalue-(count*i/frames)
|
||||
self.update
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
begin
|
||||
x = @@haveresizescreen
|
||||
rescue NameError # If exception is caught, the class
|
||||
if !method_defined?(:oldresizescreen) # variable wasn't defined yet
|
||||
begin
|
||||
alias oldresizescreen resize_screen
|
||||
@@haveresizescreen = true
|
||||
rescue
|
||||
@@haveresizescreen = false
|
||||
end
|
||||
else
|
||||
@@haveresizescreen = false
|
||||
end
|
||||
end
|
||||
|
||||
def haveresizescreen
|
||||
@@haveresizescreen
|
||||
end
|
||||
end
|
||||
|
||||
def self.resize_screen(w,h)
|
||||
@@width = w
|
||||
@@height = h
|
||||
pbSetResizeFactor($ResizeFactor,true)
|
||||
end
|
||||
|
||||
@@deletefailed = false
|
||||
|
||||
def self.snap_to_bitmap(resize=true)
|
||||
tempPath = ENV["TEMP"]+"\\tempscreen.bmp"
|
||||
if safeExists?(tempPath) && @@deletefailed
|
||||
begin
|
||||
File.delete(tempPath)
|
||||
@@deletefailed = false
|
||||
rescue Errno::EACCES
|
||||
@@deletefailed = true
|
||||
return nil
|
||||
end
|
||||
end
|
||||
if safeExists?("./rubyscreen.dll")
|
||||
takescreen = Win32API.new("rubyscreen.dll","TakeScreenshot","p","i")
|
||||
takescreen.call(tempPath)
|
||||
end
|
||||
bm = nil
|
||||
if safeExists?(tempPath)
|
||||
bm = Bitmap.new(tempPath)
|
||||
begin
|
||||
File.delete(tempPath)
|
||||
@@deletefailed = false
|
||||
rescue Errno::EACCES
|
||||
@@deletefailed = true
|
||||
end
|
||||
end
|
||||
bm.asOpaque if bm && bm.get_pixel(0,0).alpha==0
|
||||
if resize
|
||||
if bm && $ResizeOffsetX && $ResizeOffsetY && ($ResizeOffsetX!=0 || $ResizeOffsetY!=0)
|
||||
tmpbitmap = Bitmap.new(Graphics.width*$ResizeFactor,Graphics.height*$ResizeFactor)
|
||||
tmpbitmap.blt(0,0,bm,Rect.new(
|
||||
$ResizeOffsetX*$ResizeFactor,$ResizeOffsetY*$ResizeFactor,tmpbitmap.width,tmpbitmap.height))
|
||||
bm.dispose
|
||||
bm = tmpbitmap
|
||||
end
|
||||
if bm && (bm.width!=Graphics.width || bm.height!=Graphics.height)
|
||||
newbitmap = Bitmap.new(Graphics.width,Graphics.height)
|
||||
newbitmap.stretch_blt(newbitmap.rect,bm,Rect.new(0,0,bm.width,bm.height))
|
||||
bm.dispose
|
||||
bm = newbitmap
|
||||
end
|
||||
else
|
||||
# Thise code is used only for taking screenshots with F8.
|
||||
# Doesn't crop out the screen border, doesn't normalise to 1x zoom.
|
||||
# Fixes screenshots being 1 pixel too tall.
|
||||
fullw = (Graphics.width+$ResizeOffsetX*2)*$ResizeFactor
|
||||
fullh = (Graphics.height+$ResizeOffsetY*2)*$ResizeFactor
|
||||
if bm && $ResizeOffsetX && $ResizeOffsetY && $ResizeFactor &&
|
||||
(bm.width!=fullw || bm.height!=fullh)
|
||||
tmpbitmap = Bitmap.new(fullw,fullh)
|
||||
tmpbitmap.blt(0,0,bm,Rect.new(0,0,fullw,fullh))
|
||||
bm.dispose
|
||||
bm = tmpbitmap
|
||||
end
|
||||
end
|
||||
return bm
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class Sprite
|
||||
unless @SpriteResizerMethodsAliased
|
||||
alias _initialize_SpriteResizer initialize
|
||||
alias _x_SpriteResizer x
|
||||
alias _y_SpriteResizer y
|
||||
alias _ox_SpriteResizer ox
|
||||
alias _oy_SpriteResizer oy
|
||||
alias _zoomx_SpriteResizer zoom_x
|
||||
alias _zoomy_SpriteResizer zoom_y
|
||||
alias _xeq_SpriteResizer x=
|
||||
alias _yeq_SpriteResizer y=
|
||||
alias _oxeq_SpriteResizer ox=
|
||||
alias _oyeq_SpriteResizer oy=
|
||||
alias _zoomxeq_SpriteResizer zoom_x=
|
||||
alias _zoomyeq_SpriteResizer zoom_y=
|
||||
alias _bushdeptheq_SpriteResizer bush_depth=
|
||||
@SpriteResizerMethodsAliased = true
|
||||
end
|
||||
|
||||
def initialize(viewport=nil)
|
||||
_initialize_SpriteResizer(viewport)
|
||||
@resizedX=0
|
||||
@resizedY=0
|
||||
@resizedOx=0
|
||||
@resizedOy=0
|
||||
@resizedBushDepth=0
|
||||
@resizedZoomX=1.0
|
||||
@resizedZoomY=1.0
|
||||
if $ResizeOffsetX!=0 && $ResizeOffsetY!=0 && !viewport
|
||||
_xeq_SpriteResizer($ResizeOffsetX.to_f*$ResizeFactorMul/100)
|
||||
_yeq_SpriteResizer($ResizeOffsetY.to_f*$ResizeFactorMul/100)
|
||||
end
|
||||
_zoomxeq_SpriteResizer(@resizedZoomX*$ResizeFactorMul/100)
|
||||
_zoomyeq_SpriteResizer(@resizedZoomY*$ResizeFactorMul/100)
|
||||
end
|
||||
|
||||
def x
|
||||
return @resizedX
|
||||
end
|
||||
|
||||
def y
|
||||
return @resizedY
|
||||
end
|
||||
|
||||
def x=(val)
|
||||
if $ResizeFactorMul!=100
|
||||
offset=(self.viewport) ? 0 : $ResizeOffsetX
|
||||
value=(val+offset).to_f*$ResizeFactorMul/100
|
||||
_xeq_SpriteResizer(value.to_i)
|
||||
@resizedX=val.to_i
|
||||
elsif self.viewport
|
||||
_xeq_SpriteResizer(val)
|
||||
@resizedX=val
|
||||
else
|
||||
_xeq_SpriteResizer(val + $ResizeOffsetX)
|
||||
@resizedX=val
|
||||
end
|
||||
end
|
||||
|
||||
def y=(val)
|
||||
if $ResizeFactorMul!=100
|
||||
offset=(self.viewport) ? 0 : $ResizeOffsetY
|
||||
value=(val+offset).to_f*$ResizeFactorMul/100
|
||||
_yeq_SpriteResizer(value.to_i)
|
||||
@resizedY=val.to_i
|
||||
elsif self.viewport
|
||||
_yeq_SpriteResizer(val)
|
||||
@resizedY=val
|
||||
else
|
||||
_yeq_SpriteResizer(val + $ResizeOffsetY)
|
||||
@resizedY=val
|
||||
end
|
||||
end
|
||||
|
||||
def ox
|
||||
return @resizedOx
|
||||
end
|
||||
|
||||
def oy
|
||||
return @resizedOy
|
||||
end
|
||||
|
||||
def ox=(val)
|
||||
@resizedOx=val
|
||||
_oxeq_SpriteResizer(val)
|
||||
end
|
||||
|
||||
def oy=(val)
|
||||
@resizedOy=val
|
||||
_oyeq_SpriteResizer(val)
|
||||
end
|
||||
|
||||
def zoom_x
|
||||
return @resizedZoomX
|
||||
end
|
||||
|
||||
def zoom_y
|
||||
return @resizedZoomY
|
||||
end
|
||||
|
||||
def zoom_x=(val)
|
||||
value=val
|
||||
if $ResizeFactorMul!=100
|
||||
value=(val.to_f*$ResizeFactorMul/100)
|
||||
if (value-0.5).abs<=0.001
|
||||
value=0.5
|
||||
elsif (value-1.0).abs<=0.001
|
||||
value=1.0
|
||||
elsif (value-1.5).abs<=0.001
|
||||
value=1.5
|
||||
elsif (value-2.0).abs<=0.001
|
||||
value=2.0
|
||||
end
|
||||
end
|
||||
_zoomxeq_SpriteResizer(value)
|
||||
@resizedZoomX=val
|
||||
end
|
||||
|
||||
def zoom_y=(val)
|
||||
value=val
|
||||
if $ResizeFactorMul!=100
|
||||
value=(val.to_f*$ResizeFactorMul/100)
|
||||
if (value-0.5).abs<=0.001
|
||||
value=0.5
|
||||
elsif (value-1.0).abs<=0.001
|
||||
value=1.0
|
||||
elsif (value-1.5).abs<=0.001
|
||||
value=1.5
|
||||
elsif (value-2.0).abs<=0.001
|
||||
value=2.0
|
||||
end
|
||||
end
|
||||
_zoomyeq_SpriteResizer(value)
|
||||
@resizedZoomY=val
|
||||
end
|
||||
|
||||
def bush_depth
|
||||
return @resizedBushDepth
|
||||
end
|
||||
|
||||
def bush_depth=(val)
|
||||
value=((val.to_i)*$ResizeFactorMul/100)
|
||||
_bushdeptheq_SpriteResizer(value.to_i)
|
||||
@resizedBushDepth=val.to_i
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class NotifiableRect < Rect
|
||||
def setNotifyProc(proc)
|
||||
@notifyProc = proc
|
||||
end
|
||||
|
||||
def set(x,y,width,height)
|
||||
super
|
||||
@notifyProc.call(self) if @notifyProc
|
||||
end
|
||||
|
||||
def x=(value)
|
||||
super
|
||||
@notifyProc.call(self) if @notifyProc
|
||||
end
|
||||
|
||||
def y=(value)
|
||||
super
|
||||
@notifyProc.call(self) if @notifyProc
|
||||
end
|
||||
|
||||
def width=(value)
|
||||
super
|
||||
@notifyProc.call(self) if @notifyProc
|
||||
end
|
||||
|
||||
def height=(value)
|
||||
super
|
||||
@notifyProc.call(self) if @notifyProc
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class Viewport
|
||||
unless @SpriteResizerMethodsAliased
|
||||
alias _initialize_SpriteResizer initialize
|
||||
alias _rect_ViewportResizer rect
|
||||
alias _recteq_SpriteResizer rect=
|
||||
alias _oxeq_SpriteResizer ox=
|
||||
alias _oyeq_SpriteResizer oy=
|
||||
@SpriteResizerMethodsAliased=true
|
||||
end
|
||||
|
||||
def initialize(*arg)
|
||||
args=arg.clone
|
||||
@oldrect=Rect.new(0,0,100,100)
|
||||
_initialize_SpriteResizer(@oldrect)
|
||||
newRect=NotifiableRect.new(0,0,0,0)
|
||||
@resizedRectProc=Proc.new { |r|
|
||||
if $ResizeFactorMul==100
|
||||
@oldrect.set(
|
||||
r.x.to_i+$ResizeOffsetX,
|
||||
r.y.to_i+$ResizeOffsetY,
|
||||
r.width.to_i,
|
||||
r.height.to_i
|
||||
)
|
||||
self._recteq_SpriteResizer(@oldrect)
|
||||
else
|
||||
@oldrect.set(
|
||||
((r.x+$ResizeOffsetX)*$ResizeFactorMul/100).to_i,
|
||||
((r.y+$ResizeOffsetY)*$ResizeFactorMul/100).to_i,
|
||||
(r.width*$ResizeFactorMul/100).to_i,
|
||||
(r.height*$ResizeFactorMul/100).to_i
|
||||
)
|
||||
self._recteq_SpriteResizer(@oldrect)
|
||||
end
|
||||
}
|
||||
newRect.setNotifyProc(@resizedRectProc)
|
||||
if arg.length==1
|
||||
newRect.set(args[0].x,args[0].y,args[0].width,args[0].height)
|
||||
else
|
||||
newRect.set(args[0],args[1],args[2],args[3])
|
||||
end
|
||||
@resizedRect=newRect
|
||||
@resizedOx=0
|
||||
@resizedOy=0
|
||||
end
|
||||
|
||||
def ox
|
||||
return @resizedOx
|
||||
end
|
||||
|
||||
def ox=(val)
|
||||
return if !val
|
||||
_oxeq_SpriteResizer(val.to_f*$ResizeFactorMul/100)
|
||||
@resizedOx=val
|
||||
end
|
||||
|
||||
def oy
|
||||
return @resizedOy
|
||||
end
|
||||
|
||||
def oy=(val)
|
||||
return if !val
|
||||
_oyeq_SpriteResizer(val.to_f*$ResizeFactorMul/100)
|
||||
@resizedOy=val
|
||||
end
|
||||
|
||||
def rect
|
||||
return @resizedRect
|
||||
end
|
||||
|
||||
def rect=(val)
|
||||
if val
|
||||
newRect=NotifiableRect.new(0,0,100,100)
|
||||
newRect.setNotifyProc(@resizedRectProc)
|
||||
newRect.set(val.x.to_i,val.y.to_i,val.width.to_i,val.height.to_i)
|
||||
@resizedRect=newRect
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class Plane
|
||||
unless @SpriteResizerMethodsAliased
|
||||
alias _initialize_SpriteResizer initialize
|
||||
alias _zoomxeq_SpriteResizer zoom_x=
|
||||
alias _zoomyeq_SpriteResizer zoom_y=
|
||||
alias _oxeq_SpriteResizer ox=
|
||||
alias _oyeq_SpriteResizer oy=
|
||||
@SpriteResizerMethodsAliased=true
|
||||
end
|
||||
|
||||
def initialize(viewport=nil)
|
||||
_initialize_SpriteResizer(viewport)
|
||||
@resizedZoomX=1.0
|
||||
@resizedZoomY=1.0
|
||||
@resizedOx=0
|
||||
@resizedOy=0
|
||||
_zoomxeq_SpriteResizer(@resizedZoomX*$ResizeFactorMul/100)
|
||||
_zoomyeq_SpriteResizer(@resizedZoomY*$ResizeFactorMul/100)
|
||||
end
|
||||
|
||||
def ox
|
||||
return @resizedOx
|
||||
end
|
||||
|
||||
def ox=(val)
|
||||
return if !val
|
||||
_oxeq_SpriteResizer(val.to_f*$ResizeFactorMul/100)
|
||||
@resizedOx=val
|
||||
end
|
||||
|
||||
def oy
|
||||
return @resizedOy
|
||||
end
|
||||
|
||||
def oy=(val)
|
||||
return if !val
|
||||
_oyeq_SpriteResizer(val.to_f*$ResizeFactorMul/100)
|
||||
@resizedOy=val
|
||||
end
|
||||
|
||||
def zoom_x
|
||||
return @resizedZoomX
|
||||
end
|
||||
|
||||
def zoom_x=(val)
|
||||
return if !val
|
||||
_zoomxeq_SpriteResizer(val*$ResizeFactorMul/100)
|
||||
@resizedZoomX=val
|
||||
end
|
||||
|
||||
def zoom_y
|
||||
return @resizedZoomY
|
||||
end
|
||||
|
||||
def zoom_y=(val)
|
||||
return if !val
|
||||
_zoomyeq_SpriteResizer(val*$ResizeFactorMul/100)
|
||||
@resizedZoomY=val
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
class ScreenBorder
|
||||
def initialize
|
||||
initializeInternal
|
||||
refresh
|
||||
end
|
||||
|
||||
def initializeInternal
|
||||
@maximumZ=500000
|
||||
@bordername=""
|
||||
@sprite=IconSprite.new(0,0) rescue Sprite.new
|
||||
@defaultwidth=640
|
||||
@defaultheight=480
|
||||
@defaultbitmap=Bitmap.new(@defaultwidth,@defaultheight)
|
||||
end
|
||||
|
||||
def dispose
|
||||
@borderbitmap.dispose if @borderbitmap
|
||||
@defaultbitmap.dispose
|
||||
@sprite.dispose
|
||||
end
|
||||
|
||||
def adjustZ(z)
|
||||
if z>=@maximumZ
|
||||
@maximumZ=z+1
|
||||
@sprite.z=@maximumZ
|
||||
end
|
||||
end
|
||||
|
||||
def bordername=(value)
|
||||
@bordername=value
|
||||
refresh
|
||||
end
|
||||
|
||||
def refresh
|
||||
@sprite.z=@maximumZ
|
||||
@sprite.x=-BORDER_WIDTH
|
||||
@sprite.y=-BORDER_HEIGHT
|
||||
@sprite.visible=($PokemonSystem && $PokemonSystem.border==1)
|
||||
@sprite.bitmap=nil
|
||||
if @sprite.visible
|
||||
if @bordername!=nil && @bordername!=""
|
||||
setSpriteBitmap("Graphics/Pictures/"+@bordername)
|
||||
else
|
||||
setSpriteBitmap(nil)
|
||||
@sprite.bitmap=@defaultbitmap
|
||||
end
|
||||
end
|
||||
@defaultbitmap.clear
|
||||
@defaultbitmap.fill_rect(0,0,@defaultwidth,$ResizeOffsetY,Color.new(0,0,0))
|
||||
@defaultbitmap.fill_rect(0,$ResizeOffsetY,
|
||||
$ResizeOffsetX,@defaultheight-$ResizeOffsetY,Color.new(0,0,0))
|
||||
@defaultbitmap.fill_rect(@defaultwidth-$ResizeOffsetX,$ResizeOffsetY,
|
||||
$ResizeOffsetX,@defaultheight-$ResizeOffsetY,Color.new(0,0,0))
|
||||
@defaultbitmap.fill_rect($ResizeOffsetX,@defaultheight-$ResizeOffsetY,
|
||||
@defaultwidth-$ResizeOffsetX*2,$ResizeOffsetY,Color.new(0,0,0))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setSpriteBitmap(x)
|
||||
if (@sprite.is_a?(IconSprite) rescue false)
|
||||
@sprite.setBitmap(x)
|
||||
else
|
||||
@sprite.bitmap=x ? RPG::Cache.load_bitmap("",x) : nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class Bitmap
|
||||
# Fast methods for retrieving bitmap data
|
||||
RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
|
||||
RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i')
|
||||
SwapRgb = Win32API.new('./rubyscreen.dll', 'SwapRgb', 'pi', '') rescue nil
|
||||
|
||||
def setData(x)
|
||||
RtlMoveMemory_ip.call(self.address, x, x.length)
|
||||
end
|
||||
|
||||
def getData
|
||||
data = "rgba" * width * height
|
||||
RtlMoveMemory_pi.call(data, self.address, data.length)
|
||||
return data
|
||||
end
|
||||
|
||||
def swap32(x)
|
||||
return ((x>>24)&0x000000FF)|
|
||||
((x>>8)&0x0000FF00)|
|
||||
((x<<8)&0x00FF0000)|
|
||||
((x<<24)&0xFF000000)
|
||||
end
|
||||
|
||||
def asOpaque
|
||||
data=getData
|
||||
j=3
|
||||
for i in 0...width*height
|
||||
data[j]=0xFF
|
||||
j+=4
|
||||
end
|
||||
setData(data)
|
||||
end
|
||||
|
||||
def saveToPng(filename)
|
||||
bytes=[
|
||||
0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,0x0D
|
||||
].pack("CCCCCCCCCCCC")
|
||||
ihdr=[
|
||||
0x49,0x48,0x44,0x52,swap32(self.width),swap32(self.height),
|
||||
0x08,0x06,0x00,0x00,0x00
|
||||
].pack("CCCCVVCCCCC")
|
||||
crc=Zlib::crc32(ihdr)
|
||||
ihdr+=[swap32(crc)].pack("V")
|
||||
bytesPerScan=self.width*4
|
||||
row=(self.height-1)*bytesPerScan
|
||||
data=self.getData
|
||||
data2=data.clone
|
||||
width=self.width
|
||||
x=""
|
||||
len=bytesPerScan*self.height
|
||||
ttt=Time.now
|
||||
if SwapRgb
|
||||
SwapRgb.call(data2,data2.length)
|
||||
else
|
||||
# the following is considerably slower
|
||||
b=0;c=2;while b!=len
|
||||
data2[b]=data[c]
|
||||
data2[c]=data[b]
|
||||
b+=4;c+=4;
|
||||
end
|
||||
end
|
||||
#$times.push(Time.now-ttt)
|
||||
filter="\0"
|
||||
while row>=0
|
||||
thisRow=data2[row,bytesPerScan]
|
||||
x.concat(filter)
|
||||
x.concat(thisRow)
|
||||
row-=bytesPerScan
|
||||
end
|
||||
x=Zlib::Deflate.deflate(x)
|
||||
length=x.length
|
||||
x="IDAT"+x
|
||||
crc=Zlib::crc32(x)
|
||||
idat=[swap32(length)].pack("V")
|
||||
idat.concat(x)
|
||||
idat.concat([swap32(crc)].pack("V"))
|
||||
idat.concat([0,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82].pack("VCCCCCCCC"))
|
||||
File.open(filename,"wb") { |f|
|
||||
f.write(bytes)
|
||||
f.write(ihdr)
|
||||
f.write(idat)
|
||||
}
|
||||
end
|
||||
|
||||
def address
|
||||
if !@address
|
||||
buffer, ad = "rgba", object_id * 2 + 16
|
||||
RtlMoveMemory_pi.call(buffer, ad, 4)
|
||||
ad = buffer.unpack("L")[0] + 8
|
||||
RtlMoveMemory_pi.call(buffer, ad, 4)
|
||||
ad = buffer.unpack("L")[0] + 16
|
||||
RtlMoveMemory_pi.call(buffer, ad, 4)
|
||||
@address=buffer.unpack("L")[0]
|
||||
end
|
||||
return @address
|
||||
end
|
||||
end
|
||||
376
Data/Scripts/001_Technical/008_Plugin_Manager.rb
Normal file
376
Data/Scripts/001_Technical/008_Plugin_Manager.rb
Normal file
@@ -0,0 +1,376 @@
|
||||
#==============================================================================#
|
||||
# Plugin Manager #
|
||||
# by Marin #
|
||||
#------------------------------------------------------------------------------#
|
||||
# Provides a simple interface that allows plugins to require dependencies #
|
||||
# at specific versions, and to specify incompatibilities between plugins. #
|
||||
#------------------------------------------------------------------------------#
|
||||
# Usage: #
|
||||
# #
|
||||
# A Pokémon Essentials plugin should register itself using the PluginManager. #
|
||||
# The simplest way to do so, for a plugin without dependencies, is as follows: #
|
||||
# #
|
||||
# PluginManager.register({ #
|
||||
# :name => "Basic Plugin", #
|
||||
# :version => "1.0", #
|
||||
# :link => "https://reliccastle.com/link-to-the-plugin/", #
|
||||
# :credits => "Marin" #
|
||||
# }) #
|
||||
# #
|
||||
# The link portion here is optional, but recommended. This will be shown in #
|
||||
# the error message if the PluginManager detects that this plugin needs to be #
|
||||
# updated. #
|
||||
# #
|
||||
# A plugin's version is typically in the format X.Y.Z, but the number of #
|
||||
# digits does not matter. You can also use Xa, Xb, Xc, Ya, etc. #
|
||||
# What matters is that you use it consistently, so that it can be compared. #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# Now let's say we create a new plugin titled "Simple Extension", which #
|
||||
# requires our previously created "Basic Plugin" to work. #
|
||||
# #
|
||||
# PluginManager.register({ #
|
||||
# :name => "Simple Extension", #
|
||||
# :version => "1.0", #
|
||||
# :link => "https://reliccastle.com/link-to-the-plugin/", #
|
||||
# :credits => ["Marin", "Maruno"], #
|
||||
# :dependencies => ["Basic Plugin"] #
|
||||
# }) #
|
||||
# #
|
||||
# This plugin has two credits as an array, instead of one string. Furthermore, #
|
||||
# this code will ensure that "Basic Plugin" is installed, ignoring its #
|
||||
# version. If you have only one dependency, you can omit the array brackets #
|
||||
# like so: #
|
||||
# #
|
||||
# :dependencies => "Basic Plugin" #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# To require a minimum version of a dependency plugin, you should turn the #
|
||||
# dependency's name into an array which contains the name and the version #
|
||||
# (both as strings). For example, to require "Basic Plugin" version 1.2 or #
|
||||
# higher, you would write: #
|
||||
# #
|
||||
# PluginManager.register({ #
|
||||
# :name => "Simple Extension", #
|
||||
# :version => "1.0", #
|
||||
# :link => "https://reliccastle.com/link-to-the-plugin/", #
|
||||
# :credits => "Marin", #
|
||||
# :dependencies => [ #
|
||||
# ["Basic Plugin", "1.2"] #
|
||||
# ] #
|
||||
# }) #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# To require a specific version (no higher and no lower) of a dependency #
|
||||
# plugin, you should add the :exact flag as the first thing in the array for #
|
||||
# that dependency: #
|
||||
# #
|
||||
# PluginManager.register({ #
|
||||
# :name => "Simple Extension", #
|
||||
# :version => "1.0", #
|
||||
# :link => "https://reliccastle.com/link-to-the-plugin/", #
|
||||
# :credits => "Marin", #
|
||||
# :dependencies => [ #
|
||||
# [:exact, "Basic Plugin", "1.2"] #
|
||||
# ] #
|
||||
# }) #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# If your plugin is known to be incompatible with another plugin, you should #
|
||||
# list that other plugin as such. Only one of the two plugins needs to list #
|
||||
# that it is incompatible with the other. #
|
||||
# #
|
||||
# PluginManager.register({ #
|
||||
# :name => "QoL Improvements", #
|
||||
# :version => "1.0", #
|
||||
# :link => "https://reliccastle.com/link-to-the-plugin/", #
|
||||
# :credits => "Marin", #
|
||||
# :incompatibilities => [ #
|
||||
# "Simple Extension" #
|
||||
# ] #
|
||||
# }) #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# If your plugin can work without another plugin, but is known to be #
|
||||
# incompatible with an old version of that other plugin, you should list it as #
|
||||
# an optional dependency. If that other plugin is present in a game, then this #
|
||||
# optional dependency will ensure it meets the minimum version required for #
|
||||
# your plugin. Write it in the same way as any other dependency as described #
|
||||
# above, but use the :optional flag instead. #
|
||||
# You do not need to list a plugin as an optional dependency at all if all #
|
||||
# versions of that other plugin are compatible with your plugin. #
|
||||
# #
|
||||
# PluginManager.register({ #
|
||||
# :name => "Other Plugin", #
|
||||
# :version => "1.0", #
|
||||
# :link => "https://reliccastle.com/link-to-the-plugin/", #
|
||||
# :credits => "Marin", #
|
||||
# :dependencies => [ #
|
||||
# [:optional, "QoL Improvements", "1.1"] #
|
||||
# ] #
|
||||
# }) #
|
||||
# #
|
||||
# The :optional_exact flag is a combination of :optional and :exact. #
|
||||
#------------------------------------------------------------------------------#
|
||||
# Please give credit when using this. #
|
||||
#==============================================================================#
|
||||
|
||||
module PluginManager
|
||||
# Win32API MessageBox function for custom errors.
|
||||
MBOX = Win32API.new('user32', 'MessageBox', ['I','P','P','I'], 'I')
|
||||
# Holds all registered plugin data.
|
||||
@@Plugins = {}
|
||||
|
||||
# Registers a plugin and tests its dependencies and incompatibilities.
|
||||
def self.register(options)
|
||||
name = nil
|
||||
version = nil
|
||||
link = nil
|
||||
dependencies = nil
|
||||
incompats = nil
|
||||
credits = []
|
||||
order = [:name, :version, :link, :dependencies, :incompatibilities, :credits]
|
||||
# Ensure it first reads the plugin's name, which is used in error reporting,
|
||||
# by sorting the keys
|
||||
keys = options.keys.sort do |a, b|
|
||||
idx_a = order.index(a)
|
||||
idx_a = order.size if idx_a == -1
|
||||
idx_b = order.index(b)
|
||||
idx_b = order.size if idx_b == -1
|
||||
next idx_a <=> idx_b
|
||||
end
|
||||
for key in keys
|
||||
value = options[key]
|
||||
case key
|
||||
when :name # Plugin name
|
||||
if nil_or_empty?(value)
|
||||
self.error("Plugin name must be a non-empty string.")
|
||||
end
|
||||
if !@@Plugins[value].nil?
|
||||
self.error("A plugin called '#{value}' already exists.")
|
||||
end
|
||||
name = value
|
||||
when :version # Plugin version
|
||||
if nil_or_empty?(value)
|
||||
self.error("Plugin version must be a string.")
|
||||
end
|
||||
version = value
|
||||
when :link # Plugin website
|
||||
if nil_or_empty?(value)
|
||||
self.error("Plugin link must be a non-empty string.")
|
||||
end
|
||||
link = value
|
||||
when :dependencies # Plugin dependencies
|
||||
dependencies = value
|
||||
dependencies = [dependencies] if !dependencies.is_a?(Array) || !dependencies[0].is_a?(Array)
|
||||
for dep in value
|
||||
if dep.is_a?(String) # "plugin name"
|
||||
if !self.installed?(dep)
|
||||
self.error("Plugin '#{name}' requires plugin '#{dep}' to be installed above it.")
|
||||
end
|
||||
elsif dep.is_a?(Array)
|
||||
case dep.size
|
||||
when 1 # ["plugin name"]
|
||||
if dep[0].is_a?(String)
|
||||
dep_name = dep[0]
|
||||
if !self.installed?(dep_name)
|
||||
self.error("Plugin '#{name}' requires plugin '#{dep_name}' to be installed above it.")
|
||||
end
|
||||
else
|
||||
self.error("Expected the plugin name as a string, but got #{dep[0].inspect}.")
|
||||
end
|
||||
when 2 # ["plugin name", "version"]
|
||||
if dep[0].is_a?(Symbol)
|
||||
self.error("A plugin version comparator symbol was given but no version was given.")
|
||||
elsif dep[0].is_a?(String) && dep[1].is_a?(String)
|
||||
dep_name = dep[0]
|
||||
dep_version = dep[1]
|
||||
next if self.installed?(dep_name, dep_version)
|
||||
if self.installed?(dep_name) # Have plugin but lower version
|
||||
msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} or higher, " +
|
||||
"but the installed version is #{self.version(dep_name)}."
|
||||
if dep_link = self.link(dep_name)
|
||||
msg += "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'."
|
||||
end
|
||||
self.error(msg)
|
||||
else # Don't have plugin
|
||||
self.error("Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} " +
|
||||
"or higher to be installed above it.")
|
||||
end
|
||||
end
|
||||
when 3 # [:optional/:exact/:optional_exact, "plugin name", "version"]
|
||||
if !dep[0].is_a?(Symbol)
|
||||
self.error("Expected first dependency argument to be a symbol, but got #{dep[0].inspect}.")
|
||||
end
|
||||
if !dep[1].is_a?(String)
|
||||
self.error("Expected second dependency argument to be a plugin name, but got #{dep[1].inspect}.")
|
||||
end
|
||||
if !dep[2].is_a?(String)
|
||||
self.error("Expected third dependency argument to be the plugin version, but got #{dep[2].inspect}.")
|
||||
end
|
||||
dep_arg = dep[0]
|
||||
dep_name = dep[1]
|
||||
dep_version = dep[2]
|
||||
optional = false
|
||||
exact = false
|
||||
case def_arg
|
||||
when :optional; optional = true
|
||||
when :exact; exact = true
|
||||
when :optional_exact; optional = true; exact = true
|
||||
else
|
||||
self.error("Expected first dependency argument to be one of " +
|
||||
":optional, :exact or :optional_exact, but got #{dep_arg.inspect}.")
|
||||
end
|
||||
if optional
|
||||
if self.installed?(dep_name) && # Have plugin but lower version
|
||||
!self.installed?(dep_name, dep_version, exact)
|
||||
msg = "Plugin '#{name}' requires plugin '#{dep_name}', if installed, to be version #{dep_version}"
|
||||
msg << " or higher" if !exact
|
||||
msg << ", but the installed version was #{self.version(dep_name)}."
|
||||
if dep_link = self.link(dep_name)
|
||||
msg << "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'."
|
||||
end
|
||||
self.error(msg)
|
||||
end
|
||||
elsif !self.installed?(dep_name, dep_version, exact)
|
||||
if self.installed?(dep_name) # Have plugin but lower version
|
||||
msg = "Plugin '#{name}' requires plugin '#{dep_name}' to be version #{dep_version}"
|
||||
msg << " or later" if !exact
|
||||
msg << ", but the installed version was #{self.version(dep_name)}."
|
||||
if dep_link = self.link(dep_name)
|
||||
msg << "\r\nCheck #{dep_link} for an update to plugin '#{dep_name}'."
|
||||
end
|
||||
self.error(msg)
|
||||
else # Don't have plugin
|
||||
msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} "
|
||||
msg << "or later" if !exact
|
||||
msg << "to be installed above it."
|
||||
self.error(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
when :incompatibilities # Plugin incompatibilities
|
||||
incompats = value
|
||||
incompats = [incompats] if !incompats.is_a?(Array)
|
||||
for incompat in incompats
|
||||
if self.installed?(incompat)
|
||||
self.error("Plugin '#{name}' is incompatible with '#{incompat}'. " +
|
||||
"They cannot both be used at the same time.")
|
||||
end
|
||||
end
|
||||
when :credits # Plugin credits
|
||||
value = [value] if value.is_a?(String)
|
||||
if value.is_a?(Array)
|
||||
for entry in value
|
||||
if !entry.is_a?(String)
|
||||
self.error("Plugin '#{name}'s credits array contains a non-string value.")
|
||||
else
|
||||
credits << entry
|
||||
end
|
||||
end
|
||||
else
|
||||
self.error("Plugin '#{name}'s credits field must contain a string, or a string array.")
|
||||
end
|
||||
else
|
||||
self.error("Invalid plugin registry key '#{key}'.")
|
||||
end
|
||||
end
|
||||
for plugin in @@Plugins.values
|
||||
if plugin[:incompatibilities] && plugin[:incompatibilities].include?(name)
|
||||
self.error("Plugin '#{plugin[:name]}' is incompatible with '#{name}'. " +
|
||||
"They cannot both be used at the same time.")
|
||||
end
|
||||
end
|
||||
# Add plugin to class variable
|
||||
@@Plugins[name] = {
|
||||
:name => name,
|
||||
:version => version,
|
||||
:link => link,
|
||||
:dependencies => dependencies,
|
||||
:incompatibilities => incompats,
|
||||
:credits => credits
|
||||
}
|
||||
end
|
||||
|
||||
# Throws a pure error message without stack trace or any other useless info.
|
||||
def self.error(msg)
|
||||
Graphics.update
|
||||
t = Thread.new do
|
||||
MBOX.call(Win32API.pbFindRgssWindow, msg, "Plugin Error", 0x10)
|
||||
Thread.exit
|
||||
end
|
||||
while t.status
|
||||
Graphics.update
|
||||
end
|
||||
Kernel.exit! true
|
||||
end
|
||||
|
||||
# Returns true if the specified plugin is installed.
|
||||
# If the version is specified, this version is taken into account.
|
||||
# If mustequal is true, the version must be a match with the specified version.
|
||||
def self.installed?(plugin_name, plugin_version = nil, mustequal = false)
|
||||
plugin = @@Plugins[plugin_name]
|
||||
return false if plugin.nil?
|
||||
return true if plugin_version.nil?
|
||||
comparison = compare_versions(plugin[:version], plugin_version)
|
||||
return true if !mustequal && comparison >= 0
|
||||
return true if mustequal && comparison == 0
|
||||
end
|
||||
|
||||
# Returns the string names of all installed plugins.
|
||||
def self.plugins
|
||||
return @@Plugins.keys
|
||||
end
|
||||
|
||||
# Returns the installed version of the specified plugin.
|
||||
def self.version(plugin_name)
|
||||
return if !installed?(plugin_name)
|
||||
return @@Plugins[plugin_name][:version]
|
||||
end
|
||||
|
||||
# Returns the link of the specified plugin.
|
||||
def self.link(plugin_name)
|
||||
return if !installed?(plugin_name)
|
||||
return @@Plugins[plugin_name][:link]
|
||||
end
|
||||
|
||||
# Returns the credits of the specified plugin.
|
||||
def self.credits(plugin_name)
|
||||
return if !installed?(plugin_name)
|
||||
return @@Plugins[plugin_name][:credits]
|
||||
end
|
||||
|
||||
# Compares two versions given in string form. v1 should be the plugin version
|
||||
# you actually have, and v2 should be the minimum/desired plugin version.
|
||||
# Return values:
|
||||
# 1 if v1 is higher than v2
|
||||
# 0 if v1 is equal to v2
|
||||
# -1 if v1 is lower than v2
|
||||
def self.compare_versions(v1, v2)
|
||||
d1 = v1.split("")
|
||||
d1.insert(0, "0") if d1[0] == "." # Turn ".123" into "0.123"
|
||||
while d1[-1] == "."; d1 = d1[0..-2]; end # Turn "123." into "123"
|
||||
d2 = v2.split("")
|
||||
d2.insert(0, "0") if d2[0] == "." # Turn ".123" into "0.123"
|
||||
while d2[-1] == "."; d2 = d2[0..-2]; end # Turn "123." into "123"
|
||||
for i in 0...[d1.size, d2.size].max # Compare each digit in turn
|
||||
c1 = d1[i]
|
||||
c2 = d2[i]
|
||||
if c1
|
||||
return 1 if !c2
|
||||
return 1 if c1.to_i(16) > c2.to_i(16)
|
||||
return -1 if c1.to_i(16) < c2.to_i(16)
|
||||
else
|
||||
return -1 if c2
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user