Initial commit

This commit is contained in:
Maruno17
2020-09-04 22:00:59 +01:00
commit ba94119d02
300 changed files with 227558 additions and 0 deletions

View 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

View 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

View 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

View 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 = ""

View 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

View 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

View 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

View 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