Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - ThallionDarkshine

1
RMXP Script Database / [XP] Event Transitions
November 11, 2013, 07:35:54 pm
Event Transitions
Authors: ThallionDarkshine
Version: 1.1
Type: Event Animation System
Key Term: Environment Add-on



Introduction

This script allows you to transition in or out map events using many different transitions. Examples of possible transitions are found in the instructions section.


Features


  • Transition in or out map events.

  • Use many cool transitions, including using transition graphics.




Screenshots

Spoiler: ShowHide



Demo

Demo


Script

Spoiler: ShowHide
Code: ruby

=begin
 Event Transitions
   Author: ThallionDarkshine
 
 Instructions:
   Sample Arguments for fade_out (i.e. fade_out(ONE_OF_THE_EXAMPLES[, EVENT_ID (-1 for player)])).
     # Slicing Animations (Animation #0)
     #   parameters: (amount_movement)
     [0, 40]
     [0, 20]
     [0, 20, [0.6]]
     # Fading Animations (Animation #1)
     #   parameters: none
     [1, 20]
     [1, 30]
     # Zooming Animations (Animation #2)
     #   parameters: (x_zoom, y_zoom) or (zoom)
     [2, 30]
     [2, 20, [1.2]]
     [2, 30, [1, 0]]
     [2, 30, [0, 1]]
     [2, 30, [1.8, 0.2]]
     [2, 30, [0.2, 1.8]]
     [2, 30, [0.2]]
     # Zooming and Spinning Animations (Animation #3)
     #   parameters: (x_zoom, y_zoom, spin_degrees) or (zoom, spin_degrees)
     [3, 20]
     [3, 40, [1.8, 0.2, 720]]
     [3, 40, [0.2, 810]]
     [3, 40, [0.2, 1.8, 720]]
     # 3D Spin Animations (Animation #4)
     #   parameters: (zoom, num_rotations)
     [4, 40]
     [4, 40, [0, 4]]
     [4, 40, [0.5, 6]]
     [4, 30, [0.7, 2]]
     # Shaking Animations (Animation #7)
     #   parameters: (x_strength, x_speed, y_strength, y_speed) or (x_intensity, y_intensity)
     [7, 40]
     [7, 40, [6..9, 4..7]]
     # Ripple/Distort Animations (Animation #8)
     #   parameters: (x_amplitude, x_wavelength, num_x_ripples, y_amplitude, y_wavelength, num_y_ripples) or (x_amount, num_x_ripples, y_amount, num_y_ripples)
     [8, 40]
     [8, 40, [40, 10, 0.5, 10, 10, 2]]
     [8, 40, [10, 10, 2, 40, 10, 0.5]]
     [8, 40, [10, 40, 2, 10, 10, 2]]
     [8, 40, [10, 10, 2, 10, 40, 2]]
     [8, 40, [10, 10, 3, 10, 10, 2]]
     [8, 40, [10, 10, 2, 10, 10, 3]]
     [8, 10, [10, 40, 0.5, 10, 10, 0.5]]
     [8, 10, [10, 10, 0.5, 10, 40, 0.5]]
     # Dissolve to Sprite Animations (Animation #9)
     #   parameters: (fade_duration)
     #            or (fade_duration, x_size, y_size, negative?, tint_amount,
     #                tint_red, tint_green, tint_blue)
     #            or (fade_duration, x_size, y_size, negative?, tint_amount,
     #                tint_red, tint_green, tint_blue, grayscale_amount)
     #   note - use a float for x_size or y_size to specify it as a fraction
     #     example - 1.0 for the width of the sprite, 0.5 for half the width, and so on
     [9, 40]
     [9, 40, [10, 1.0, 1, false, 50, 200, 50, 50]]
     [9, 40, [10, 5, 5, true, 50, 100, 200, 200]]
     [9, 40, [10, 1, 1.0, false, 0, 0, 0, 0, 100]]
     # Dissolve Animations (Animation #10)
     [10, 40]
     [10, 40, [1, 1.0]]
     [10, 40, [5, 5]]
     [10, 20, [10, 10]]
     # Transition Graphic Animations (Animation #11)
     #   parameters: (transition_graphic_name, fade_duration)
     #     fade_duration - how long it takes for each individual pixel of the
     #       sprite to fade out
     [11, 100]
     [11, 40, ['001-Blind01', 5]]
   Sample Arguments for fade_in (i.e. fade_in(ONE_OF_THE_EXAMPLES[, EVENT_ID (-1 for player)])).
     # Fading Animations (Animation #0)
     #   parameters: none
     [0, 20]
     [0, 30]
     # Zooming Animations (Animation #1)
     #   parameters: (x_zoom, y_zoom) or (zoom)
     [1, 30]
     [1, 20, [1.2]]
     [1, 30, [1, 0]]
     [1, 30, [0, 1]]
     [1, 30, [1.8, 0.2]]
     [1, 30, [0.2, 1.8]]
     [1, 30, [0.2]]
     # Zooming and Spinning Animations (Animation #2)
     #   parameters: (x_zoom, y_zoom, spin_degrees) or (zoom, spin_degrees)
     [2, 20]
     [2, 40, [1.8, 0.2, 720]]
     [2, 40, [0.2, 810]]
     [2, 40, [0.2, 1.8, 720]]
     # 3D Spin Animations (Animation #3)
     #   parameters: (horizontal?, zoom, num_rotations)
     [3, 40]
     [3, 40, [true, 0, 4]]
     [3, 40, [true, 0.5, 6]]
     [3, 30, [true, 0.7, 2]]
     # Shaking Animations (Animation #6)
     #   parameters: (x_strength, x_speed, y_strength, y_speed) or (x_intensity, y_intensity)
     [6, 40]
     [6, 40, [6..9, 4..7]]
     # Transition Graphic Animations (Animation #7)
     #   parameters: (transition_graphic_name, fade_duration)
     #     fade_duration - how long it takes for each individual pixel of the
     #       sprite to fade out
     [7, 100]
     [7, 40, ['001-Blind01', 5]]
=end

unless Object.const_defined?(:Transitions)
 raise 'This script requires ThallionDarkshine\'s Transitions Module'
end

class Interpreter
 def fade_out(params, event_id = @event_id)
   if event_id > 0
     $game_map.events[event_id].fade_out(params)
   elsif event_id == -1
     $game_player.fade_out(params)
   end
 end
 
 def fade_in(params, event_id = @event_id)
   if event_id > 0
     $game_map.events[event_id].fade_in(params)
   elsif event_id == -1
     $game_player.fade_in(params)
   end
 end
end

class Game_Character
 attr_accessor :transition, :trans_dir
 
 alias tdks_ev_trans_init initialize
 def initialize(*args)
   tdks_ev_trans_init(*args)
   @transition = nil
   @trans_dir = 0
 end
 
 def fade_out(params)
   @transition = params
   @trans_dir = 0
 end
 
 def fade_in(params)
   @transition = params
   @trans_dir = 1
 end
end

class Sprite_Character
 alias tdks_ev_trans_init initialize
 def initialize(*args)
   tdks_ev_trans_init(*args)
   @visible = true
   @orig_bmp = nil
   @orig_state = nil
 end
 
 alias tdks_ev_trans_updt update
 def update
   if @visible && !Transitions.transitioning_out?(self) && !Transitions.transitioning_in?(self)
     tdks_ev_trans_updt
   end
   if !@character.transition.nil?
     if @character.trans_dir == 0
       @orig_bmp = self.bitmap.clone
       @orig_state = [self.zoom_x, self.zoom_y, self.opacity, self.ox, self.oy, self.angle, self.src_rect.clone]
     elsif !@orig_bmp.nil?
       sr = @orig_state[6]
       self.bitmap = @orig_bmp.clone
       self.x += @orig_state[3] - self.ox
       self.y += @orig_state[4] - self.oy
       self.zoom_x, self.zoom_y, self.opacity, self.ox, self.oy, self.angle = *@orig_state
       self.src_rect = sr
     end
     @character.trans_dir == 0 ? Transitions.transition_out(self, *@character.transition) : Transitions.transition_in(self, *@character.transition)
     @character.transition = nil
     @visible = @character.trans_dir != 0
   end
 end
end



Instructions

Example arguments for the call to fade_out (i.e. fade_out(ONE_OF_THE_EXAMPLES[, EVENT_ID (-1 for player)])).
Spoiler: ShowHide
Code: ruby

   # Slicing Animations (Animation #0)
   #   parameters: (amount_movement)
   [0, 40],
   [0, 20],
   [0, 20, [0.6]],
   # Fading Animations (Animation #1)
   #   parameters: none
   [1, 20],
   [1, 30],
   # Zooming Animations (Animation #2)
   #   parameters: (x_zoom, y_zoom) or (zoom)
   [2, 30],
   [2, 20, [1.2]],
   [2, 30, [1, 0]],
   [2, 30, [0, 1]],
   [2, 30, [1.8, 0.2]],
   [2, 30, [0.2, 1.8]],
   [2, 30, [0.2]],
   # Zooming and Spinning Animations (Animation #3)
   #   parameters: (x_zoom, y_zoom, spin_degrees) or (zoom, spin_degrees)
   [3, 20],
   [3, 40, [1.8, 0.2, 720]],
   [3, 40, [0.2, 810]],
   [3, 40, [0.2, 1.8, 720]],
   # 3D Spin Animations (Animation #4)
   #   parameters: (zoom, num_rotations)
   [4, 40],
   [4, 40, [0, 4]],
   [4, 40, [0.5, 6]],
   [4, 30, [0.7, 2]],
   # Shaking Animations (Animation #7)
   #   parameters: (x_strength, x_speed, y_strength, y_speed) or (x_intensity, y_intensity)
   [7, 40],
   [7, 40, [6..9, 4..7]],
   # Ripple/Distort Animations (Animation #8)
   #   parameters: (x_amplitude, x_wavelength, num_x_ripples, y_amplitude, y_wavelength, num_y_ripples) or (x_amount, num_x_ripples, y_amount, num_y_ripples)
   [8, 40],
   [8, 40, [40, 10, 0.5, 10, 10, 2]],
   [8, 40, [10, 10, 2, 40, 10, 0.5]],
   [8, 40, [10, 40, 2, 10, 10, 2]],
   [8, 40, [10, 10, 2, 10, 40, 2]],
   [8, 40, [10, 10, 3, 10, 10, 2]],
   [8, 40, [10, 10, 2, 10, 10, 3]],
   [8, 10, [10, 40, 0.5, 10, 10, 0.5]],
   [8, 10, [10, 10, 0.5, 10, 40, 0.5]],
   # Dissolve to Sprite Animations (Animation #9)
   #   parameters: (fade_duration)
   #            or (fade_duration, x_size, y_size, negative?, tint_amount,
   #                tint_red, tint_green, tint_blue)
   #            or (fade_duration, x_size, y_size, negative?, tint_amount,
   #                tint_red, tint_green, tint_blue, grayscale_amount)
   #   note - use a float for x_size or y_size to specify it as a fraction
   #     example - 1.0 for the width of the sprite, 0.5 for half the width, and so on
   [9, 40],
   [9, 40, [10, 1.0, 1, false, 50, 200, 50, 50]],
   [9, 40, [10, 5, 5, true, 50, 100, 200, 200]],
   [9, 40, [10, 1, 1.0, false, 0, 0, 0, 0, 100]],
   # Dissolve Animations (Animation #10)
   [10, 40],
   [10, 40, [1, 1.0]],
   [10, 40, [5, 5]],
   [10, 20, [10, 10]],
   # Transition Graphic Animations (Animation #11)
   #   parameters: (transition_graphic_name, fade_duration)
   #     fade_duration - how long it takes for each individual pixel of the
   #       sprite to fade out
   [11, 100],
   [11, 40, ['001-Blind01', 5]],


Example arguments for the call to fade_in (i.e. fade_in(ONE_OF_THE_EXAMPLES[, EVENT_ID (-1 for player)])).
Spoiler: ShowHide
Code: ruby

   # Fading Animations (Animation #0)
   #   parameters: none
   [0, 20],
   [0, 30],
   # Zooming Animations (Animation #1)
   #   parameters: (x_zoom, y_zoom) or (zoom)
   [1, 30],
   [1, 20, [1.2]],
   [1, 30, [1, 0]],
   [1, 30, [0, 1]],
   [1, 30, [1.8, 0.2]],
   [1, 30, [0.2, 1.8]],
   [1, 30, [0.2]],
   # Zooming and Spinning Animations (Animation #2)
   #   parameters: (x_zoom, y_zoom, spin_degrees) or (zoom, spin_degrees)
   [2, 20],
   [2, 40, [1.8, 0.2, 720]],
   [2, 40, [0.2, 810]],
   [2, 40, [0.2, 1.8, 720]],
   # 3D Spin Animations (Animation #3)
   #   parameters: (horizontal?, zoom, num_rotations)
   [3, 40],
   [3, 40, [true, 0, 4]],
   [3, 40, [true, 0.5, 6]],
   [3, 30, [true, 0.7, 2]],
   # Shaking Animations (Animation #6)
   #   parameters: (x_strength, x_speed, y_strength, y_speed) or (x_intensity, y_intensity)
   [6, 40],
   [6, 40, [6..9, 4..7]],
   # Transition Graphic Animations (Animation #7)
   #   parameters: (transition_graphic_name, fade_duration)
   #     fade_duration - how long it takes for each individual pixel of the
   #       sprite to fade out
   [7, 100],
   [7, 40, ['001-Blind01', 5]],



Compatibility

No issues known atm.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

You'll also need my transitions module for this script to work, as well as this dll.
2
RMXP Script Database / [XP] F12 Stack Level Too Deep Fix
November 08, 2013, 09:13:11 pm
F12 Stack Level Too Deep Fix
Authors: ThallionDarkshine, CoderPuppy
Version: 1.1
Type: Error Fix
Key Term: Misc Add-on



Introduction

Have you ever been really annoyed when you press F12 to restart your game, and all of a sudden, a Stack Level Too Deep error appears? Well, this will fix that.


Features


  • Fix those annoying stack level too deep errors when using the F12 restart.




Screenshots

Not necessary. I can't think of how to show the absence of an error.


Demo

Not at the moment, pretty self-explanatory.


Script

Place at the top of the script list before anything else.
Spoiler: ShowHide
Code: ruby

if Graphics.frame_count > 0
 begin
   # Prepare for transition
   Graphics.freeze
   # Make scene object (title screen)
   $scene = Scene_Title.new
   # Call main method as long as $scene is effective
   while $scene != nil
     $scene.main
   end
   # Fade out
   Graphics.transition(20)
 rescue Errno::ENOENT
   # Supplement Errno::ENOENT exception
   # If unable to open file, display message and end
   filename = $!.message.sub("No such file or directory - ", "")
   print("Unable to find file #{filename}.")
 end
 exit
end



Instructions

None needed. The script is pretty self-explanatory.


Compatibility

No known issues.


Credits and Thanks


  • ThallionDarkshine

  • CoderPuppy (my brother) for the idea (which is basically all the script is)




Author's Notes

None. Use freely, no credit necessary.
3
RMXP Script Database / [XP] Auras
February 16, 2013, 04:10:46 pm
Auras
Authors: ThallionDarkshine
Version: 0.1
Type: Misc Add-on
Key Term: Misc Add-on



Introduction

It's sometimes hard in an RPG Maker game to tell who's talking. Either you can add in an extra little window showing the current speaker's name, or you can add it to the start of the message. Here's another way to let users know who's speaking. This script allows you to create auras on events, causing a custom image to rotate or zoom in and out around them. There are three different animations for the auras at the moment, but you can use any combination of these, allowing you to create many cool effects.


Features


  • Show an aura on the current speaker or a character that you wish to highlight.

  • Use combinations of the three animation effects to create an awesome animation for your aura.

  • Show auras with an easy script call.




Screenshots

Spoiler: ShowHide





Demo

None


Script

Spoiler: ShowHide

module Auras
 # to give an aura to any event or the player, use this script call:
 #   aura(event_id, type)
 #     event_id - the id of the event or -1 for the player
 #       to give an aura to the current event, use @event_id for this value
 #     type - the type of aura set up later in the configuration
 #       set to a value of nil to turn off the aura
 # to turn off all the auras currently showing, use this script call:
 #   close_auras
 
 # whether to allow multiple auras to be shown simultanously on different
 #   characters
 MULTI_AURA = false
 
 # the configuration for the different types of auras
 # to add a new effect, use this template
 #   when TYPE then return {
 #       EFFECTS
 #     }
 # the different effects are:
 #   :filename => FILENAME,
 #     FILENAME - determines the filename of the aura picture in the
 #       Graphics/Pictures folder
 #   :spin => [DURATION, CLOCKWISE],
 #     DURATION - how long the spin effect should take
 #     CLOCKWISE - whether to spin clockwise
 #   :rock => [DURATION, SPIN_DEGREES],
 #     DURATION - how long the rock effect should take
 #     SPIN_DEGREES - how far the aura should spin before rocking back to the
 #       other side
 #   :zoom => [DURATION, ZOOM_AMOUNT],
 #     DURATION - how long the zoom effect should take
 #     ZOOM_AMOUNT - how much the aura should zoom in (or out with a value
 #       less than 1)
 def self.aura(type)
   case type
   when 0 then return {
       :filename => 'aura2',
       :spin => [60, false],
       :rock => [15, 8],
       :zoom => [10, 0.9],
     }
   end
   return {}
 end
end

class Sprite_Aura < Sprite
 def initialize(character, type)
   super(character.viewport)
   @character = character
   @args = Auras.aura(type)
   if @args.keys.include?(:filename)
     self.bitmap = RPG::Cache.picture(@args[:filename]).clone
     self.ox, self.oy = self.bitmap.width / 2, self.bitmap.height / 2
   end
   @args[:rock].push(1) if @args.keys.include?(:rock)
   @args[:zoom].push(1) if @args.keys.include?(:zoom)
   @args.each { |key, val|
     val.push(key == :rock ? val[0] / 2 : 0) if val.is_a?(Array)
   }
   update
 end
 
 def update
   super()
   w = (@character.bitmap.nil? ? 0 : @character.bitmap.width)
   h = (@character.bitmap.nil? ? 0 : @character.bitmap.height)
   self.x = @character.x - @character.ox + @character.src_rect.width / 2
   self.y = @character.y - @character.oy + @character.src_rect.height / 2
   self.z = @character.z + 100
   self.angle = 0
   if @args.keys.include?(:spin)
     s_args = @args[:spin]
     s_args[-1] = (s_args[-1] + 1) % s_args[0]
     self.angle += (s_args[1] ? 1 : -1) * 360 * s_args[-1] / s_args[0]
   end
   if @args.keys.include?(:rock)
     r_args = @args[:rock]
     r_args[-1] += r_args[-2]
     r_ang = r_args[1] * (r_args[-1] - r_args[0] / 2.0) / (r_args[0] / 2.0)
     r_args[-2] = 0-r_args[-2] if r_args[-1] == r_args[0] or r_args[-1] == 0
     self.angle += r_ang
   end
   if @args.keys.include?(:zoom)
     z_args = @args[:zoom]
     z_args[-1] += z_args[-2]
     self.zoom_x = self.zoom_y = 1 + (z_args[1] - 1.0) * z_args[-1] / z_args[0]
     z_args[-2] = 0-z_args[-2] if z_args[-1] == z_args[0] or z_args[-1] == 0
   end
 end
end

module RPG
 class Sprite
   alias tdks_auras_init initialize
   def initialize(viewport = nil)
     tdks_auras_init(viewport)
     @_aura = nil
   end
   
   def aura(type)
     @_aura = Sprite_Aura.new(self, type)
   end
   
   def dispose_aura
     unless @_aura.nil?
       @_aura.bitmap.dispose unless @_aura.bitmap.nil? or @_aura.bitmap.disposed?
       @_aura.dispose
       @_aura = nil
     end
   end
   
   alias tdks_auras_updt update
   def update
     tdks_auras_updt
     unless @_aura.nil?
       @_aura.update
     end
   end
 end
end

class Game_Character
 attr_accessor :aura
 
 alias tdks_auras_init initialize
 def initialize
   tdks_auras_init
   @aura = nil
 end
end

class Sprite_Character
 alias tdks_auras_sc_init initialize
 def initialize(viewport, character = nil)
   tdks_auras_sc_init(viewport, character)
   @old_aura = nil
 end
 
 alias tdks_auras_sc_updt update
 def update
   tdks_auras_sc_updt
   if @character.aura != @old_aura
     unless @character.aura.nil?
       self.aura(@character.aura)
     else
       self.dispose_aura
     end
     @old_aura = @character.aura
   end
 end
end

class Interpreter
 alias tdks_auras_init initialize
 def initialize(depth = 0, main = false)
   tdks_auras_init(depth, main)
   @aura_events = []
 end
 
 def aura(event_id = @event_id, type = nil)
   @aura_events.delete_if { |i| i[0] != $game_map.map_id }
   close_auras unless Auras::MULTI_AURA
   if event_id == -1
     $game_player.aura = type
   else
     $game_map.events[event_id].aura = type
   end
   @aura_events.push([$game_map.map_id, event_id])
 end
 
 def close_auras
   @aura_events.each { |i|
     if i[1] == -1
       $game_player.aura = nil
     else
       $game_map.events[i[1]].aura = nil
     end
   }
   @aura_events = []
 end
end



Instructions

All in the script.


Compatibility

None known.


Credits and Thanks


  • ThallionDarkshine

  • Blizz for making the script that this is based off of




Author's Notes

None
4
RMXP Script Database / [XP] 3D Battle Camera
February 15, 2013, 07:50:29 pm
3D Battle Camera
Authors: ThallionDarkshine
Version: 0.4
Type: Battle Add-on
Key Term: Battle Add-on



Introduction

The default battle system is extremely boring and not dynamic at all. And so, here's a script that zooms in on the currently targeted enemy, using a parallax effect to make it appear somewhat 3D.


Features


  • Liven up the DBS with a 3D battle camera.

  • Customize zoom values and parallax amount.




Screenshots

Spoiler: ShowHide



Demo

None yet.


Script

Spoiler: ShowHide

#__END__
module Battle_Cam
  # the power of the parallax effect (0 - 1)
  #   note - don't use anything too high or it will look a bit weird
  PARALLAX_AMOUNT = 0.3
  # how fast to transition between targets (1 - 10)
  TRANSITION_SPEED = 7
  # how much to zoom in on the currently targeted battler
  TARGET_ZOOM = 1.3
  # how much to zoom in on the active battler
  ACTIVE_ZOOM = 1.2
  # how much to zoom in if there are multiple targets
  MULTI_ZOOM = 1.1
end

class Spriteset_Battle
  alias tdks_3d_cam_init initialize
  def initialize
    @cx = 320
    @cy = 160
    @zoom = 1
    @frames = 0
    @target_ind = -1
    tdks_3d_cam_init
  end
 
  def set_battler(battler = nil, tz = Battle_Cam::ACTIVE_ZOOM, speed = Battle_Cam::TRANSITION_SPEED)
    @target_pos = nil
    pind = @target_ind
    if battler.nil?
      @target_ind = -1
      @tz = 1
    else
      sprite = @enemy_sprites.detect { |i| i.battler == battler }
      @target_ind = @enemy_sprites.index(sprite)
    end
    unless @target_ind == pind and @tz == tz and @target_pos.nil?
      @tz = tz
      @frames = 100 / speed
    end
  end
 
  def set_index(ind = nil, tz = Battle_Cam::ACTIVE_ZOOM, speed = Battle_Cam::TRANSITION_SPEED)
    @target_pos = nil
    unless @target_ind == ind and @tz == tz and @target_pos.nil?
      @target_ind = ind.nil? ? -1 : ind
      @tz = tz
      @frames = 100 / speed
    end
    @tz = 1 if ind.nil?
  end
 
  def set_pos(tx = 320, ty = 160, tz = Battle_Cam::ACTIVE_ZOOM, speed = Battle_Cam::TRANSITION_SPEED)
    unless tx == @target_pos[0] and ty == @target_pos[1] and tz == @target_pos[2]
      @target_pos = [tx, ty]
      @tz = tz
      @frames = 100 / speed
    end
  end
 
  def effect?
    return true if @frames > 0
    # Return true if even 1 effect is being displayed
    for sprite in @enemy_sprites + @actor_sprites
      return true if sprite.effect?
    end
    return false
  end
 
  alias tdks_3d_cam_updt update
  def update
    tdks_3d_cam_updt
    update_3d_camera
  end
 
  def update_3d_camera
    unless @battleback_sprite.bitmap.nil?
      amnt = Battle_Cam::PARALLAX_AMOUNT
      @battleback_sprite.ox = @cx
      @battleback_sprite.oy = @cy
      @battleback_sprite.x, @battleback_sprite.y = 320, 160
      @battleback_sprite.x += (@cx - 320) * amnt * @zoom
      @battleback_sprite.y += (@cy - 160) * amnt * @zoom
      @battleback_sprite.zoom_x = @battleback_sprite.zoom_y = @zoom
    end
    pframes = @frames
    if @frames > 0 and !@target_ind.nil?
      if @target_ind == -1
        tx = 320
        ty = 160
      else
        sprite = @enemy_sprites[@target_ind]
        tx = sprite.battler.screen_x
        height = sprite.bitmap.nil? ? 0 : sprite.bitmap.height
        ty = sprite.battler.screen_y - height / 2
      end
      @frames -= 1
      @cx = @cx * @frames / (@frames + 1.0) + tx / (@frames + 1.0)
      @cy = @cy * @frames / (@frames + 1.0) + ty / (@frames + 1.0)
      @zoom = @zoom * @frames / (@frames + 1.0) + @tz / (@frames + 1.0)
    end
    @enemy_sprites.each { |sprite|
      height = sprite.bitmap.nil? ? 0 : sprite.bitmap.height
      width = sprite.bitmap.nil? ? 0 : sprite.bitmap.width
      tmpz = @zoom
      tmpy = (sprite.battler.screen_y - height / 2 - @cy) * @zoom + 160
      tmpx = (sprite.battler.screen_x - @cx) * @zoom + 320
      tmpoy = height / 2
      tmpox = width / 2
      if Module.constants.include?("Transitions") and Transitions.transitioning_out?(sprite)
        type = Transitions.transition_type(sprite)[1]
        if [3, 4].include?(type) or (type == 2 and Transitions.sprite(sprite)[7])
          sprite.zoom_x *= tmpz
          sprite.zoom_y *= tmpz
        else
          sprite.zoom_x = sprite.zoom_y = tmpz
        end
        if [0, 7].include?(type)
          sprite.ox += tmpox
          sprite.oy += tmpoy
        elsif type == 8
          sprite.ox = tmpox
          sprite.oy = (Transitions.sprite(sprite)[3].height - height) * @zoom / 2 + height / 2.0
        else
          sprite.ox, sprite.oy = tmpox, tmpoy
        end
        sprite.x, sprite.y = tmpx, tmpy
      else
        sprite.zoom_x = sprite.zoom_y = tmpz
        sprite.x, sprite.y = tmpx, tmpy
        sprite.ox, sprite.oy = tmpox, tmpoy
      end
    }
    if $scene.instance_variables.include?('@enemy_arrow') and pframes > 0
      arrow = $scene.instance_variable_get(:@enemy_arrow)
      arrow.update unless arrow.nil?
    end
  end
end

class Sprite_Battler
  alias tdks_3d_cam_updt update
  def update
    tdks_3d_cam_updt
  end
end

class Arrow_Enemy
  alias tdks_3d_cam_updt update
  def update
    tdks_3d_cam_updt
    unless self.enemy.nil?
      sprite = $scene.instance_variable_get(:@spriteset).instance_variable_get(:@enemy_sprites)
      sprite = sprite.detect { |i| i.battler == self.enemy }
      self.x, self.y = sprite.x, sprite.y + sprite.bitmap.height / 2
    end
  end
end

class Scene_Battle
  alias tdks_3d_cam_strt_p2 start_phase2
  def start_phase2
    @spriteset.set_index()
    tdks_3d_cam_strt_p2
  end
 
  alias tdks_3d_cam_strt_p5 start_phase5
  def start_phase5
    @spriteset.set_index()
    tdks_3d_cam_strt_p5
  end
 
  alias tdks_3d_cam_updt_p3_eslct update_phase3_enemy_select
  def update_phase3_enemy_select
    @spriteset.set_battler($game_troop.enemies[@enemy_arrow.index], Battle_Cam::TARGET_ZOOM)
    tdks_3d_cam_updt_p3_eslct
  end
 
  alias tdks_3d_cam_end_eslct end_enemy_select
  def end_enemy_select
    @spriteset.set_index() if Input.trigger?(Input::B)
    tdks_3d_cam_end_eslct
  end
 
  alias tdks_3d_cam_p3_setup_cmd_wndw phase3_setup_command_window
  def phase3_setup_command_window
    tdks_3d_cam_p3_setup_cmd_wndw
    @spriteset.set_index()
  end
 
  alias tdks_3d_cam_updt_p4_s2 update_phase4_step2
  def update_phase4_step2
    tdks_3d_cam_updt_p4_s2
    if @target_battlers.length == 1 and @target_battlers[0].is_a?(Game_Enemy)
      @spriteset.set_battler(@target_battlers[0], Battle_Cam::TARGET_ZOOM)
    elsif @target_battlers.length > 1 and @target_battlers.any? { |i| i.is_a?(Game_Enemy) }
      @spriteset.set_index(-1, Battle_Cam::MULTI_ZOOM)
    elsif @active_battler.is_a?(Game_Enemy)
      @spriteset.set_battler(@active_battler) unless @active_battler.current_action.kind == 0 and @active_battler.current_action.basic == 3
    else
      @spriteset.set_index()
    end
  end
end



Instructions

In the script.


Compatibility

Could have compatibility issues with some custom battle systems.


Credits and Thanks


  • ThallionDarkshine

  • Blizz for giving me the idea




Author's Notes

None
5
Advanced Time and Environment System (ATES)
Authors: Blizzard, ThallionDarkshine
Version: 1.1
Type: Time and Weather System
Key Term: Custom Environment System



Introduction

You all know Blizz's old time system, the ATES. Well, I saw it in his dev pack, and saw that he had never finished implementing all the planned features. So, I decided to finish it for him. This system adds a time and weather system to games that can be turned on and off at will. Every aspect of the script is configurable, from the time system, to the weather system, and even the clock hud.

The time system allows you to create multiple times of day, each with their own unique and configurable tint. At any point within the day, the script will interpolate between the two closest times of day to create the current tint. In turn, these times of day will fall at different times throughout the year. You can set the values for the longest and shortest days of the year, and the script will determine the current times by interpolating between these.

The weather system gives you lots of options, allowing you to customize the bgs, fog, weather effect, and even effects like thunder with screen flashes and sound effects. Each weather effect can be assigned a severity, which influences the likelihood that they will occur. More on this when I talk about seasons. You can also configure a range of durations for each weather effect. When a weather effect starts, a random value in the range will be chosen for its duration.

Both the tint and the weather effects are influenced by the player's current location (outside, inside, or inside a dark place). When outside, all tint and weather effects will be applied at full force. When inside, the engine weather effects (rain, snow, etc) and fog effects will not be applied, and sounds and tints will be dampened. When inside a dark place, everything is the same as for inside, except the screen tint will be set to a fixed configurable value.

The year is divided into seasons set up in the configuration. Each season has a defined temperature range, probability of weather, bad weather, and very bad weather, and set of weather possibilities.

You can also configure various terrains that can influence various aspects of the system. Each terrain has a defined range of temperature modifiers, and a set of weather effect exclusions.

You can create holidays, which have essentially no effect besides changing certain lines of text in the clock. Each holiday can either be defined by date or by a position within the month (i.e. first monday, second to last thursday, etc).

Finally, the clock is fully configurable, and gives you a wide range of information to pull from and various methods to display it. For instance, you can display either the weekday name (replaced by the holiday if applicable) or the weekday abbreviation. More on these in the instructions in the script.

This work is protected by the following license:
Quote
Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
( http://creativecommons.org/licenses/by-nc-sa/3.0/ )

You are free:

to Share - to copy, distribute and transmit the work
to Remix -- to adapt the work

Under the following conditions:

Attribution. You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).

Noncommercial. You may not use this work for commercial purposes.

Share alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.

- For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page.

- Any of the above conditions can be waived if you get permission from the copyright holder.

- Nothing in this license impairs or restricts the author's moral rights.



Features


  • Adds a weather and time system to your game.

  • Disable several pieces of the system at will: the tinting, the weather, the clock, or the entire script.

  • Lock in any particular weather.

  • Jump quickly between time periods configured in the script.

  • Customize your own terrains, weather types, and time periods, as well as the screen tints for these time periods.

  • And much more!




Screenshots

Spoiler: ShowHide








Demo

https://app.box.com/s/vi3hqfkn2l8z0upnlx60


Script

Spoiler: ShowHide

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Advanced Time and Environment System (ATES) by Blizzard and ThallionDarkshine
# Version: 1.1
# Type: Autonomous Timeflow and Environment Controller
# Date v0.3: 11.3.2008
# Date v0.31: 8.4.2009
# Date v0.32: 13.4.2009
# Date v0.33: 4.5.2009
# Date v0.34: 5.5.2009
# Date v1.0: 12.2.2013
# Date v1.01: 28.4.2013
# Date v1.02: 20.3.2015
# Date v1.1: 18.12.2017
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#   
#  This work is protected by the following license:
# #----------------------------------------------------------------------------
# # 
# #  Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# #  ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# # 
# #  You are free:
# # 
# #  to Share - to copy, distribute and transmit the work
# #  to Remix - to adapt the work
# # 
# #  Under the following conditions:
# # 
# #  Attribution. You must attribute the work in the manner specified by the
# #  author or licensor (but not in any way that suggests that they endorse you
# #  or your use of the work).
# # 
# #  Noncommercial. You may not use this work for commercial purposes.
# # 
# #  Share alike. If you alter, transform, or build upon this work, you may
# #  distribute the resulting work only under the same or similar license to
# #  this one.
# # 
# #  - For any reuse or distribution, you must make clear to others the license
# #    terms of this work. The best way to do this is with a link to this web
# #    page.
# # 
# #  - Any of the above conditions can be waived if you get permission from the
# #    copyright holder.
# # 
# #  - Nothing in this license impairs or restricts the author's moral rights.
# # 
# #----------------------------------------------------------------------------
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# Compatibility:
#
#   99% compatible with SDK v1.x. 90% compatible with SDK 2.x. WILL corrupt old
#   savegames. Can cause incompatibilty issues with DNS-es.
#
#
# Features:
#
#   - complete control over and easy manipulating of time and weather
#   - customizable day and night tinting
#   - HUD clock optional
#   - easier to control and more powerful than DDNS
#
#
# IMPORTANT NOTES:
#
# - This system has a working preconfiguration, be aware that a custom setup
#   will need you to understand what each option does, so please read the
#   configuration instructions.
# - Why does this system use switches to determine whether it's day or night?
#   Simple: You can use conditions in enemy attacks to determine whether an
#   attack should be used only at night or only at day.
#
#
# Instructions:
#
# - Explanation:
#
#   This Time System will make your game have daytime and nighttime periods.
#   The screen will be tinted accordingly. You can set up the length of the
#   day. Other features are explained below. Please be sure to configure this
#   system appropriately.
#
#
# - Basic manipulation of ATES:
#
#   This system is based upon your eventing. It will work basically if you
#   want, but with a little bit of using the "Call Script" event command you
#   are able to control this system fully. You can call following commands:
#
#   On/Off Controls
# ------------------------------------------------------------------------------
#     ATES.on
#   Turns ATES on.
#
#     ATES.off
#   Turns ATES off.
#
#     ATES.tint_on
#   Turns ATES's screen tinting on.
#
#     ATES.tint_off
#   Turns ATES's screen tinting off.
#
#     ATES.clock_on
#   Turns ATES's clock display on.
#
#     ATES.clock_off
#   Turns ATES's clock display off.
#
#     ATES.weather_on
#   Turns ATES's weather system on.
#
#     ATES.weather_off
#   Turns ATES's weather system off.
# ------------------------------------------------------------------------------
#   
#   Time Controls
# ------------------------------------------------------------------------------
#     ATES.advance(M, H)
#   This will make the time advanced by M minutes and H hours. Any negative
#   value used will cancel the execution of this command.
#   
#     ATES.make_it_day
#   This is a feature from DDNS which allows you to quickly jump to the
#   daytime.
#   
#     ATES.make_it_night
#   This is a feature from DDNS which allows you to quickly jump to the
#   nighttime.
#
#     ATES.set_time(TIME_INDEX or TIME_NAME)
#   Sets the current time to the time at the index of TIME_INDEX or with the
#   name of TIME_NAME. Its better to use TIME_NAME because some bugs may occur
#   from using TIME_INDEX.
# ------------------------------------------------------------------------------
#   
#   Weather Controls
# ------------------------------------------------------------------------------
#     ATES.lock_weather
#   This allows you to lock the current weather in place without disabling the
#   weather system entirely.
#
#     ATES.unlock_weather
#   This command unlocks the current weather.
#
#     ATES.set_weather(INDEX)
#   Sets the current weather to the weather at index INDEX.
# ------------------------------------------------------------------------------
#
#   Location (inside/outside) Controls
# ------------------------------------------------------------------------------
#     ATES.go_inside
#   A feature from the DDNS which allows you to change the lighting mode to
#   inside.
#
#     ATES.go_inside_dark
#   A feature from the DDNS which allows you to change the lighting mode to
#   inside dark.
#
#     ATES.go_outside
#   A feature from the DDNS which allows you to change the lighting mode to
#   outside.
# ------------------------------------------------------------------------------
#
#   Terrain Controls
# ------------------------------------------------------------------------------
#     ATES.terrain=(TERRAIN_NAME)
#   Sets the terrain to the terrain named TERRAIN_NAME.
# ------------------------------------------------------------------------------
#
#   Conditionals
# ------------------------------------------------------------------------------
#     ATES.active?
#   Returns true if ATES is turned on, otherwise false.
#
#     ATES.tinting?
#   Returns true if ATES tinting is turned on, otherwise false.
#
#     ATES.weather_active?
#   Returns true if the weather system is turned on, otherwise false.
#
#     ATES.day?
#   Returns true if it's day, otherwise false. Alternatively you can check the
#   assigned switch instead.
#
#     ATES.night?
#   Returns true if it's night, otherwise false. Alternatively you can check
#   the assigned switch instead.
# ------------------------------------------------------------------------------
#
#   Getters
# ------------------------------------------------------------------------------
#     ATES.time_name
#   Returns the name of the current time of day.
# ------------------------------------------------------------------------------
#
# - Enhancement hints:
#
#   If you wish to implement the DDNS further into your game and e.g. allow
#   different behavious of monsters during day and night, you only need to
#   check the the state of the appropriate switch. e.g. If NSWITCH is turned
#   on inflict "Sleep" on one enemy. The same is true for temperature (check
#   TVARIABLE) and weather (check WVARIABLE).
#
#
# Additional info:
#
# - The daytime and nighttime tintings were tested appropriately and optimal
#   tinting is being used.
#
# - Keep in mind that all aspects of the ATES are initially turned off, so
#   you'll have to use the commands ATES.on, ATES.tint_on, ATES.clock_on, and
#   ATES.weather_on to enable the components.
#
# - Further instructions can be found in the script database topic:
#   http://forum.chaos-project.com/index.php/topic,12869.0.html
#
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

module ATES
 
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # switch ID of the "day" switch
  DSWITCH = 51
  # switch ID of the "night" switch
  NSWITCH = 52
  # variable ID of the temperature variable
  TVARIABLE = 51
  # variable ID of the weather variable
  WVARIABLE = 52
  # length of a day in seconds in-game, can't be less than 36, is being
  # quantized into intervals of 36 seconds
  LENGTH = 1440
  # the amount to multiply weather sound by when inside
  INSIDE_SOUND = 0.7
  # the amount to multiply tone red, green, blue and gray by when inside
  INSIDE_TONE = 0.0
  # the tone for dark interiors
  DARK_INSIDE_TONE = Tone.new(-85, -85, -85, 85)
  # weather setup, create new types of weather here
  #  note - if you don't want a certain effect such as weather, fog, or sound,
  #    just leave the array for that effect empty
  #        ['NAME', WEATHER_SEVERITY, LOW_STRENGTH..HIGH_STRENGTH,
  #          WEATHER_DURATION_MIN..WEATHER_DURATION_MAX, [WEATHER_TYPE],
  #          [SOUND_NAME, SOUND_VOLUME_MIN..SOUND_VOLUME_MAX, SOUND_PITCH],
  #          [FOG_NAME, FOG_OPACITY, FOG_HUE, FOG_ZOOM, FOG_SX, FOG_SY,
  #            [TONE_RED, TONE_GREEN, TONE_BLUE, TONE_GRAY]],
  #          [SOUND_EFFECT_NAME, SOUND_VOLUME_MIN..SOUND_VOLUME_MAX, SOUND_PITCH,
  #            EFFECT_PROBABILITY, FLASH_DURATION, [FLASH_COLOR_RED,
  #            FLASH_COLOR_GREEN, FLASH_COLOR_BLUE]]]
  WEATHER = [['Drizzling', 0, 1..4, 150..480, [1], ['005-Rain01', 65..80, 100], [], []],
             ['Raining', 0, 5..8, 150..450, [1], ['006-Rain02', 75..90, 100], [], ['061-Thunderclap01', 60..85, 100, 0.0018, 4, [255, 255, 255]]],
             ['Storm', 1, 9..10, 180..450, [1], ['007-Rain03', 80..100, 100], [], ['061-Thunderclap01', 70..95, 110, 0.002, 6, [255, 255, 255]]],
             ['Cloudy', 0, 1..1, 240..720, [], [], ['002-Clouds01', 60, 0, 200, 4, 3, [0, 0, 0, 0]], []],
             ['Raining', 0, 1..4, 150..450, [2], ['006-Rain02', 70..85, 100], [], ['061-Thunderclap01', 65..90, 110, 0.002, 6, [255, 255, 255]]],
             ['Storm', 1, 5..8, 180..450, [2], ['007-Rain03', 75..90, 100], [], ['061-Thunderclap01', 70..95, 110, 0.0022, 7, [255, 255, 255]]],
             ['Storm', 2, 9..10, 180..450, [2], ['007-Rain03', 90..100, 100], [], ['061-Thunderclap01', 85..100, 110, 0.0026, 7, [255, 255, 255]]],
             ['Flurry', 1, 1..4, 150..480, [3], ['002-Wind02', 70..85, 100], [], []],
             ['Snowing', 1, 5..8, 150..450, [3], ['003-Wind03', 80..95, 100], [], []],
             ['Blizzard', 2, 9..10, 180..450, [3], ['004-Wind04', 85..100, 100], [], []]]
  # the name of the default weather type (what gets shown in the clock when
  #   there is no weather)
  DEFAULT_WEATHER_NAME = 'Sunny'
  # season setup, create a new season by using this template
  #          ['NAME', START_DAY, START_MONTH, MIN_TEMP..MAX_TEMP, WEATHER_PROBABILITY,
  #            BAD_WEATHER_PROBABILITY, VERY_BAD_WEATHER_PROBABILITY, WEATHER_POSSIBILITIES]
  SEASONS = [
             ['Spring', 22,  3,   0..25, 0.003, 0.3, 0.05, [0, 1, 2, 3, 4, 5]] ,
             ['Summer', 21,  6,  20..35, 0.003, 0.1, 0.2, [0, 1, 3, 4, 5, 6]]  ,
             ['Autumn', 20,  9,   0..25, 0.003, 0.2, 0.1, [0, 2, 3, 4, 5, 7]]  ,
             ['Winter', 21, 12, -20..5, 0.003, 0.5, 0.1, [0, 2, 3, 4, 7, 8, 9]]
            ]
  # terrain setup, create a new terrain by using this template
  #          ['NAME', MIN_TEMP..MAX_TEMP, WEATHER_EXCLUSIONS]
  TERRAINS = [
              ['Forest', -7..0, [3]],
              ['Desert', 11..16, [8, 9]],
              ['Mountain', -9..-4, []],
              ['Plains', -2..0, []],
              ['Beach', -5..-2, [8, 9]]
             ]
  # longest day date, the date of the longest night is half a year later/earlier
  LONGEST = [21, 6]
  # the tone at which day starts
  DAY_START = "Sunrise"
  # the tone at which night starts
  NIGHT_START = "Dusk"
  # the different screen tones and temperature modifiers at certain points during the day on the longest and shortest days
  # to make a new time of day, add this into TIMES:
  #   NAME => [RED, GREEN, BLUE, GRAY, TEMPERATURE_MODIFIER]
  TIMES = {
           "Dawn" => [-17, -17, 17, 0, -4],
           "Sunrise" => [48, 30, 30, 0, -2],
           "Noon" => [24, 10, 10, 0, 5],
           "Sunset" => [57, -17, -17, 0, 1],
           "Dusk" => [-17, -17, 17, 0, -3],
           "Night" => [-140, -110, -110, 160, -8]
          }
  # once you have customized the tones, put the tones into LONG_TIMES and SHORT_TIMES with [name_of_time, hour, minute]
  LONG_TIMES = [["Dawn", 4, 30],
                ["Sunrise", 5, 30],
                ["Noon", 13, 00],
                ["Sunset", 21, 00],
                ["Dusk", 22, 00],
                ["Night", 1, 30]]
  SHORT_TIMES = [["Dawn", 6, 30],
                ["Sunrise", 7, 30],
                ["Noon", 13, 00],
                ["Sunset", 16, 30],
                ["Dusk", 17, 00],
                ["Night", 23, 30]]
  # the first year in your calender, the player can't scroll further back
  FYEAR = 1990
  # the last year in your calender, the player can't scroll further forth
  LYEAR = 2099
  # the suffix for temperature
  TEMP_SUFFIX = "°C"
  # the different holidays and their dates
  #   the format for adding a new holiday is:
  #     [NAME, SETUP_TYPE, MONTH, (DAY or WEEKDAY, NUMBER)]
  #   whether to use DAY or WEEKDAY, NUMBER depends on SETUP_TYPE:
  #     (0 - DAY; 1 - WDAY, NUMBER)
  # note - the current holiday will replace the weekday in the clock if it is a
  #   holiday
  HOLIDAYS = [
               ["Christmas", 0, 11, 24],
               ["New Year's Day", 0, 0, 0],
               ["Thanksgiving", 1, 10, 4, 4],
               ["Groundhog Day", 0, 1, 1],
               ["Valentine's Day", 0, 1, 13],
               ["Earth Day", 0, 3, 21],
               ["Arbor Day", 1, 3, 5, -1],
               ["Mother's Day", 1, 2, 7, 2],
               ["Father's Day", 1, 5, 7, 3],
               ["Halloween", 0, 9, 30],
             ]
  # HUD clock format
  # default : ['%H:%M%s', '%A', '%d/%m/%Y', '%S']
  # use [] for no clock
  # it means: 1st row - "HOURS:MINUTES SUFFIX"
  #           2nd row - "WEEKDAY"
  #           3rd row - "DAY/MONTH/YEAR"
  #           4th row - "SEASON"
  # different combinations to input ATES information into the clock
  #   %H - Hour
  #   %M - Minute
  #   %s - Suffix (AM or PM) (only if not using 24 hour time)
  #   %A - Weekday
  #   %a - Weekday Abbreviation
  #   %d - Day of the Month
  #   %D - Day of the Year
  #   %m - Month
  #   %n - Month Name
  #   %l - Month Length
  #   %Y - Year
  #   %L - Year Length
  #   %S - Season
  #   %w - Weather
  #   %t - Terrain
  #   %T - Temperature
  #   %p - Time of Day
  CFORMAT = ['%H:%M', '%d/%m/%Y', '%A', '%w', '%p']
  # the width of the clock
  CWIDTH = 180
  # names of your days, automatically sets up a week's length
  WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
              'Saturday']
  WEEKDAY_ABBREVIATIONS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
  # names of your months, automatically sets up a year's length
  MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
            'August', 'September', 'October', 'November', 'December']
  # abbreviations for month names
  MONTH_ABBREVIATIONS = ['Jan', 'Feb', 'March', 'Apr', 'May', 'June', 'July',
                         'Aug', 'Sept', 'Oct', 'Nov', 'Dec']
  # days in each month
  MONTHDAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  # the first day in the game [DAY, MONTH, YEAR, WEEKDAY]
  # set this option to [] if you want the game to start "now"
  START = [24, 11, 2007, 7]
  # set this option to true to turn on 24 hour time
  HOUR24 = true
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
  mon = (LONGEST[1] + MONTHS.length / 2) % 12
  mon = 12 if mon == 0
  day = LONGEST[0] + (MONTHS.length % 2) == 1 ? MONTHDAYS[mon - 1] / 2 : 0
  while day > MONTHDAYS[mon - 1]
    day -= MONTHDAYS[mon - 1]
    mon = (mon + 1) % 12
    mon = 12 if mon == 0
  end
  SHORTEST = [day, mon]
 
  # Perform some simple checks of the config
  if ATES::MONTHS.size > ATES::MONTHDAYS.size
    raise 'ATEScfgError: Not all months have a length in days specified!'
  elsif ATES::LENGTH < 36
    raise 'ATEScfgError: A day\'s length must be equal to or greater than 36 seconds!'
  end

  $ates = 1.0
 
  #============================================================================
  # ATES::Time
  #============================================================================
 
  class Time
   
    attr_accessor :min
    attr_accessor :hour
    attr_accessor :day
    attr_accessor :mon
    attr_accessor :year
    attr_accessor :wday
   
    def initialize(m, h, d, mon, y, w)
      @min, @hour, @day, @mon, @year, @wday = m, h, d, mon, y, w
    end
   
  end
 
  #==============================================================================
  # ATES::Weather
  #==============================================================================
 
  class Weather
    attr_accessor :current_weather, :current_intensity, :locked, :weather_enabled, :weather_count
    attr_reader :weather_duration
   
    def initialize
      @current_weather = -1
      @current_intensity = 0
      @locked = false
      @weather_enabled = true
    end
   
    def update
      if @current_weather != -1 && @weather_enabled && @current_weather[7].length > 0
        weather = @current_weather
        if rand <= weather[7][3]
          high, low = weather[2].first, weather[2].last
          vol = weather[7][1].first + (weather[7][1].last - weather[7][1].first) * (high - @current_intensity).to_f / (high - low)
          vol *= ATES::INSIDE_SOUND if $game_system.ates.map_type > 0
          sound = RPG::AudioFile.new(weather[7][0], vol, weather[7][2])
          $game_system.se_play(sound)
          col = Color.new(0, 0, 0)
          $game_screen.start_flash(Color.new(*weather[7][5]), weather[7][4])
        end
      end
    end
   
    def stop_weather(speed = -1)
      return if @current_weather == -1
      speed = speed == -1 ? rand(10) + 60 : speed
      if @current_weather[4].length > 0
        $game_screen.weather(0, 1, speed)
      end
      if @current_weather[5].length > 0
        $game_system.bgs_fade(speed.to_f / 40)
      end
      if @current_weather[6].length > 0
        $game_map.fog_name = ''
      end
      @current_weather = -1
    end
   
    def pause_weather(speed = -1)
      return if @current_weather == -1
      $game_system.ates.show_weather = false
      speed = speed == -1 ? rand(10) + 60 : speed
      if @current_weather[4].length > 0
        $game_screen.weather(0, 1, speed)
      end
      if @current_weather[5].length > 0
        $game_system.bgs_fade(speed.to_f / 40)
      end
      if @current_weather[6].length > 0
        $game_map.fog_name = ''
      end
    end
   
    def resume_weather(speed = -1)
      return if @current_weather == -1
      $game_system.ates.show_weather = true
      weather = @current_weather
      intensity = @current_intensity
      low, high = weather[2].first, weather[2].last
      speed = speed == -1 ? rand(10) + 60 : speed
      if weather[4].length > 0
        $game_screen.weather(weather[4][0], intensity, speed)
      end
      if weather[5].length > 0
        volume = weather[5][1].first + (weather[5][1].last - weather[5][1].first) * (high - intensity).to_f / (high - low)
        bgm = RPG::AudioFile.new(weather[5][0], volume, weather[5][2])
        $game_system.bgs_play(bgm)
      end
      if weather[6].length > 0
        $game_map.fog_name = weather[6][0]
        $game_map.fog_opacity = weather[6][1]
        $game_map.fog_hue = weather[6][2]
        $game_map.fog_zoom = weather[6][3]
        $game_map.fog_sx = weather[6][4]
        $game_map.fog_sy = weather[6][5]
        $game_map.start_fog_tone_change(Tone.new(*weather[6][6]), 0)
      end
    end
   
    def set_weather(weather, speed = -1)
      stop_weather if @current_weather != -1
      if weather.is_a?(Fixnum)
        weather = WEATHER[weather]
      end
      @weather_count = 0
      @weather_duration = rand(weather[3].max - weather[3].min) + weather[3].min
      low, high = weather[2].first, weather[2].last
      intensity = rand(high + 1 - low) + low
      @current_weather = weather
      @current_intensity = intensity
      return unless @weather_enabled
      speed = speed == -1 ? rand(10) + 60 : speed
      if weather[5].length > 0
        volume = weather[5][1].first + (weather[5][1].last - weather[5][1].first) * (high - intensity).to_f / (high - low)
        volume *= ATES::INSIDE_SOUND if $game_system.ates.map_type > 0
        bgm = RPG::AudioFile.new(weather[5][0], volume, weather[5][2])
        $game_system.bgs_play(bgm)
      end
      return if $game_system.ates.map_type > 0
      if weather[4].length > 0
        if $modified_aws and weather[4].length > 1
          $game_screen.weather(weather[4][0], intensity, speed, weather[3][1])
        else
          $game_screen.weather(weather[4][0], intensity, speed)
        end
      end
      if weather[6].length > 0
        $game_map.fog_name = weather[6][0]
        $game_map.fog_opacity = weather[6][1]
        $game_map.fog_hue = weather[6][2]
        $game_map.fog_zoom = weather[6][3]
        $game_map.fog_sx = weather[6][4]
        $game_map.fog_sy = weather[6][5]
        $game_map.start_fog_tone_change(Tone.new(*weather[6][6]), 0)
      end
    end
  end
 
  def self.on
    $game_system.ates.active = true
    return true
  end
 
  def self.off
    $game_system.ates.active = false
    return true
  end
 
  def self.tint_on(frames = 0)
    $game_screen.start_tone_change($game_system.ates.get_environment[0], frames)
    $game_system.ates.tinting = true
    return true
  end
 
  def self.tint_off(reset = true)
    $game_screen.start_tone_change(Tone.new(0, 0, 0, 0), 0) if reset
    $game_system.ates.tinting = false
    return true
  end
 
  def self.weather_off
    $game_system.ates.weather.weather_enabled = false
    $game_system.ates.weather.pause_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
    return true
  end
 
  def self.weather_on
    $game_system.ates.weather.weather_enabled = true
    $game_system.ates.weather.resume_weather(0) if $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
    return true
  end
 
  def self.weather_active?
    return $game_system.ates.weather.weather_enabled
  end
 
  def self.lock_weather
    $game_system.ates.weather.locked = true
    return true
  end
 
  def self.unlock_weather
    $game_system.ates.weather.locked = false
    return true
  end
 
  def self.clock_on
    $game_system.show_clock = true
    return true
  end
 
  def self.clock_off
    $game_system.show_clock = false
    return true
  end
 
  def self.active?
    return $game_system.ates.active
  end
 
  def self.tinting?
    return $game_system.ates.tinting
  end
 
  def self.day?
    i = $game_system.ates.time_index
    while true
      if $game_system.ates.current_times[i][0] == DAY_START
        return true
      elsif $game_system.ates.current_times[i][0] == NIGHT_START
        return false
      end
     
      i = (i + $game_system.ates.current_times.length - 1) % $game_system.ates.current_times.length
    end
  end
 
  def self.night?
    return !self.day?
  end
 
  def self.make_it_day
    time = $game_system.ates.current_times.select { |time| time[0] == DAY_START }
    h, m = time[0][1], time[0][2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.make_it_night
    time = $game_system.ates.current_times.select { |time| time[0] == NIGHT_START }
    h, m = time[0][1], time[0][2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.set_time(time = 0)
    return unless $game_system
    if time.is_a?(Fixnum)
      time = $game_system.ates.current_times[time.to_i]
    else
      time = $game_system.ates.current_times.select { |current_time| current_time[0] == time }[0]
    end
    h, m = time[1], time[2]
    $game_system.ates.time.hour = h
    $game_system.ates.time.min = m
    return true
  end
 
  def self.day_start
    return DAY_START
  end
 
  def self.night_start
    return NIGHT_START
  end
 
  def self.go_inside_dark
    weather = $game_system.ates.weather.current_weather
    $game_system.ates.map_type = 2
    self.tint_on
    $game_system.ates.weather.pause_weather(0)
    return true if weather == -1
    low, high = weather[2].first, weather[2].last
    intensity = $game_system.ates.weather.current_intensity
    if weather[5].length > 0
      volume = ATES::INSIDE_SOUND * weather[5][1].first + (weather[5][1].last - weather[5][1].first) * (high - intensity).to_f / (high - low)
      bgm = RPG::AudioFile.new(weather[5][0], volume, weather[5][2])
      $game_system.bgs_play(bgm)
    end
    return true
  end
 
  def self.go_inside
    weather = $game_system.ates.weather.current_weather
    $game_system.ates.map_type = 1
    self.tint_on
    $game_system.ates.weather.pause_weather(0)
    return true if weather == -1
    low, high = weather[2].first, weather[2].last
    intensity = $game_system.ates.weather.current_intensity
    if weather[5].length > 0
      volume = ATES::INSIDE_SOUND * weather[5][1].first + (weather[5][1].last - weather[5][1].first) * (high - intensity).to_f / (high - low)
      bgm = RPG::AudioFile.new(weather[5][0], volume, weather[5][2])
      $game_system.bgs_play(bgm)
    end
    return true
  end
 
  def self.go_outside
    $game_system.ates.weather.resume_weather(0)
    $game_system.ates.map_type = 0
    self.tint_on
    return true
  end
 
  def self.set_weather(id)
    $game_system.ates.weather.set_weather(WEATHER[id])
    return true
  end
 
  def self.terrain=(terrain)
    terrain = TERRAINS[terrain.to_i][0] if terrain.is_a?(Fixnum)
    $game_system.ates.terrain = terrain
    return true
  end
 
  def self.advance(m, h, d, mon, y)
    return true if [m, h, d, mon, y].any? {|i| i < 0}
    h += ($game_system.ates.time.min + m) / 60
    $game_system.ates.time.min = ($game_system.ates.time.min + m) % 60
    d += ($game_system.ates.time.hour + h) / 24
    $game_system.ates.time.hour = ($game_system.ates.time.hour + h) % 24
    while d > 0
      if $game_system.ates.time.day < MONTHDAYS[mon]
        $game_system.ates.time.day += 1
      else
        $game_system.ates.time.day = 0
        mon = (mon + 1) % MONTHS.size
      end
      $game_system.ates.time.wday += 1
      $game_system.ates.time.wday %= WEEKDAYS.size
      d -= 1
    end
    y += ($game_system.ates.time.mon + mon) / MONTHS.size
    $game_system.ates.time.mon = ($game_system.ates.time.mon + mon) % MONTHS.size
    $game_system.ates.time.year += y
    return true
  end
 
  def self.time_name
    return $game_system.ates.current_times[$game_system.ates.time_index][0]
  end
 
end

#==============================================================================
# Game_System
#==============================================================================

class Game_System
 
  attr_accessor :ates
  attr_accessor :show_clock
 
  alias init_ates_later initialize
  def initialize
    init_ates_later
    @ates = Game_ATES.new
    @show_clock = false
  end

end

#==============================================================================
# Game_ATES
#==============================================================================

class Game_ATES
 
  attr_accessor :active
  attr_accessor :tinting
  attr_accessor :time
  attr_accessor :weather
  attr_accessor :frame_count
  attr_accessor :current_times
  attr_accessor :tone
  attr_accessor :map_type
  attr_accessor :show_weather
  attr_accessor :terrain
  attr_accessor :temp
  attr_reader   :holiday
  attr_reader   :time_index
 
  def initialize
    if ATES::START.size == 4
      @time = ATES::Time.new(0, 0, ATES::START[0], ATES::START[1],
          ATES::START[2], ATES::START[3])
    else
      @time = Time.now
      @time = ATES::Time.new(@time.min, @time.hour, @time.mday, @time.mon, @time.year, @time.wday)
    end
    @weather = ATES::Weather.new
     
    @long_times = ATES::LONG_TIMES.sort { |t1, t2| t1[1] * 100 + t1[2] <=> t2[1] * 100 + t2[2] }
    @short_times = ATES::SHORT_TIMES.sort { |t1, t2| t1[1] * 100 + t1[2] <=> t2[1] * 100 + t2[2] }
   
    @year_length = ATES::MONTHDAYS.inject { |sum, x| sum + x }
       
    @normal_weather = []
    @bad_weather = []
    @very_bad_weather = []
   
    @terrain = ''
    @current_times = setup_times
    @temp_modifier = (rand(201) - 100) / 100.0
    @tone, @temp = get_environment
    @holiday = get_holiday(@time.mon, @time.day, @time.wday)
    @s_time = get_time(@time.min, @time.hour)
    $game_screen.start_tone_change(@tone, 0) if $game_screen
   
    @active = true
    @tinting = true
    @show_weather = true
    @map_type = 0
    @frame_count = 0
  end
 
  # get the holiday corresponding to a date
  def get_holiday(month, day, wday)
    ATES::HOLIDAYS.each { |el|
      case el[1] # branch by holiday definition
      when 0 # defined by date
        return el if el[2..3] == [month, day]
      when 1 # defined by position in month
        if el[4] > 0 # nth instance of a weekday
          return el if el[2] == month and el[3] == wday and el[4] == (day.to_f / 7 + 1).floor
        elsif el[4] < 0 # nth to last instance of a weekday
          return el if el[2] == month and el[3] == wday and -el[4] == ((ATES::MONTHDAYS[month] - 1 - day).to_f / 7 + 1).floor
        end
      end
    }[0]
  end
 
  # generate the correct tone based on the time of day and current location
  def get_environment
    red = 0
    green = 0
    blue = 0
    grey = 0
    @temp_modifier += (rand(3) - 1) / 100.0 if rand(10) == 0
   
    changed = false
   
    # loop through the times of day to determine where the current time falls
    for i in 0...@current_times.length
      time1 = get_time(@current_times[i][2], @current_times[i][1])
      time2 = get_time(@current_times[(i + 1) % @current_times.length][2], @current_times[(i + 1) % @current_times.length][1])
      current = get_time(@time.min, @time.hour)
      if time2 < time1
        time2 += 24 * 60
      end
      if current < time1
        current += 24 * 60
      end
     
      # found the two times to interpolate between
      if time1 <= current and time2 >= current
        changed = true
        tone1 = @current_times[i]
        tone2 = @current_times[(i + 1) % @current_times.length]
        tone1 = ATES::TIMES[tone1[0]]
        tone2 = ATES::TIMES[tone2[0]]
        max = time2 - time1
       
        # interpolate the current screen tone
        ratios = [(current - time1).to_f / max, (time2 - current).to_f / max]
        red = tone1[0] * ratios[1] + tone2[0] * ratios[0]
        green = tone1[1] * ratios[1] + tone2[1] * ratios[0]
        blue = tone1[2] * ratios[1] + tone2[2] * ratios[0]
        grey = tone1[3] * ratios[1] + tone2[3] * ratios[0]
       
        # deal with temperature (NEEDS REWORK)
        season_data = get_full_season[3]
        temp_range = [season_data.first, season_data.last].sort
        unless @base_temp
          # set up initial temperature
          temp = temp_range[0] + rand(temp_range[1] - temp_range[0] + 1)
          if @terrain != ''
            modifier = get_terrain_full[1]
            modifier = [modifier.first, modifier.last].sort
            modifier = modifier[0] + rand(modifier[1] - modifier[0] + 1)
            temp += modifier
          end
          @base_temp = temp
        else
          temp = @base_temp
        end
       
        # handle temperature changes
        temp_mod = round(tone1[4] * ratios[1] + tone2[4] * ratios[0], 2)
        temp += temp_mod + @temp_modifier
       
        # update the time of day if necessary
        @time_index = ratios[0] < 0.5 ? i : (i + 1) % @current_times.length
       
        break
      end
    end
   
    print "not right" unless changed
   
    # use the generated tone to determine the actual screen tone based on
    #   whether the player is inside, outside, or inside a dark place
    if @map_type == 1
      return Tone.new(red * ATES::INSIDE_TONE, green * ATES::INSIDE_TONE, blue * ATES::INSIDE_TONE, grey * ATES::INSIDE_TONE), temp
    elsif @map_type == 2
      return ATES::DARK_INSIDE_TONE, temp
    else
      return Tone.new(red, green, blue, grey), temp
    end
  end
   
  def get_weather_possibilities(severity = 0)
    weather = []
    season = $game_system.ates.get_full_season
    terrain = get_terrain_full
    ATES::WEATHER.each_with_index { |el, ind|
      weather.push(el) if el[1] == severity && season[7].include?(ind) && (terrain.nil? || !terrain[2].include?(ind))
    }
    return weather
  end
 
  def get_terrain_full
    return ATES::TERRAINS.select { |terrain| terrain[0] == @terrain }[0]
  end
 
  # interpolate between LONG_TIMES and SHORT_TIMES to find the current time of
  #   day changes
  def setup_times
    current_date = [@time.day, @time.mon]
   
    # check for trivial cases
    if current_date == ATES::LONGEST or @long_times == @short_times
      return @long_times
    elsif current_date == ATES::SHORTEST
      return @short_times
    end
   
    short_times = @long_times.clone
    addons = @short_times.clone
    current_date = get_date(*current_date)
    long, short = get_date(*ATES::LONGEST), get_date(*ATES::SHORTEST)
   
    # calculate distances to shortest and longest days
    dists = []
    if (current_date >= short and current_date <= long)
      dists = [current_date - short, long - current_date]
    elsif (current_date >= short and short >= long)
      dists = [current_date - short, long + @year_length - current_date]
    elsif (current_date <= long and long <= short)
      dists = [current_date + @year_length - short, long - current_date]
    elsif (current_date >= long and current_date <= short)
      dists = [current_date - long, short - current_date]
    elsif (current_date <= short and short <= long)
      dists = [current_date + @year_length - long, short - current_date]
    elsif (current_date >= long and long >= short)
      dists = [current_date - long, short + @year_length - current_date]
    end
   
    # generate the time for each time of day by interpolating between short and long
    sum = dists[0] + dists[1]
    short_times.each { |tone|
      addons.each { |addon|
        if tone[0] == addon[0]
          ts = [get_time(tone[2], tone[1]), get_time(addon[2], addon[1])]
          min, max = ts.min, ts.max
          ts = [min + 1440, max] if max - min > min + 1440 - max
          ts = (ts[0] * dists[0] / sum.to_f + ts[1] * dists[1] / sum.to_f) % 1440
          h = (ts / 60).floor
          m = ts.floor - h * 60
          tone[1], tone[2] = h, m
          break
        end
      }
    }
   
    return short_times.sort { |x, y| get_time(x[2], x[1]) <=> get_time(y[2], y[1]) }
  end
 
  # utility function to round a number to specified number of decimal places
  def round(num, places = 0)
    return ((num * 10 ** places).round.to_f) / (10 ** places)
  end
 
  # converts a time to minutes
  def get_time(minutes, hours)
    return minutes + hours * 60
  end
 
  # determine the current season from the date
  def get_season
    get_full_season[0]
  end
 
  # determine the season data from the date
  def get_full_season
    season_list = ATES::SEASONS.sort { |x, y| get_date(x[1], x[2]) <=> get_date(y[1], y[2]) }
    day = @time.day
    month = @time.mon
    current = get_date(day, month)
    for i in 0...season_list.length
      seasons = [season_list[i], season_list[(i + 1) % season_list.length]]
      times = [get_date(seasons[0][1], seasons[0][2]), get_date(seasons[1][1], seasons[1][2])]
      if times[0] <= current and current < times[1]
        return seasons[0]
      end
    end
    return season_list[0]
  end
 
  # get the current day since the start of the year
  def get_date(day, month)
    month = ATES::MONTHS.length if month == 0
    return (ATES::MONTHDAYS[0...month - 1].inject { |sum, x| sum + x } or 0) + day
  end

  # weather update
  def update_weather
    return unless @weather.weather_enabled
   
    if @weather.current_weather != -1
      @weather.weather_count += 1
      if @weather.weather_count >= @weather.weather_duration && !@weather.locked
        @weather.stop_weather
      end
    end

    season = get_full_season
    if !@season or @season != season
      @normal_weather = get_weather_possibilities
      @bad_weather = get_weather_possibilities(1)
      @very_bad_weather = get_weather_possibilities(2)
      @season = season
    end
    unless @weather.locked
      if rand <= season[4] and season[7].length > 0
        if rand <= season[5] and @bad_weather.length > 0
          weather = rand(@bad_weather.length)
          weather = @bad_weather[weather]
          @weather.set_weather(weather)
        elsif rand <= season[6] and @very_bad_weather.length > 0
          weather = rand(@very_bad_weather.length)
          weather = @very_bad_weather[weather]
          @weather.set_weather(weather)
        elsif @normal_weather.length > 0
          weather = rand(@normal_weather.length)
          weather = @normal_weather[weather]
          @weather.set_weather(weather)
        end
      end
    end
  end
 
  # update function
  def update
    if @active
      @frame_count += 1
      if @frame_count % (ATES::LENGTH / 36) == 0
        tmp = @time.day
        ATES.advance(1, 0, 0, 0, 0)
        if @time.day != tmp
          @current_times = setup_times
          @holiday = get_holiday(@time.mon, @time.day, @time.wday)
        end
       
        update_weather
     
        # update the switches if necessary
        if ATES.day?
          $game_map.need_refresh = true if !$game_switches[ATES::DSWITCH]
          $game_switches[ATES::DSWITCH] = true
          $game_switches[ATES::NSWITCH] = false
        else
          $game_map.need_refresh = true if !$game_switches[ATES::NSWITCH]
          $game_switches[ATES::DSWITCH] = false
          $game_switches[ATES::NSWITCH] = true
        end
     
        # update the variables
        @tone, @temp = get_environment
        $game_variables[ATES::TVARIABLE] = @temp
        weather = -1
        if @weather.current_weather != -1
          weather = ATES::WEATHER.index(@weather.current_weather)
        end
        $game_variables[ATES::WVARIABLE] = weather
     
        if @tinting # handle screen tone
          cur_time = get_time(@time.min, @time.hour)
          $game_screen.start_tone_change(@tone, ((@s_time - cur_time).abs < [1440 / ATES::LENGTH, 1].max ? 0 : 20))
        end
      end
     
      # in-game time speed should not affect the weather animations and effects
      @weather.update
    end
  end
end

#==============================================================================
# Bitmap
#==============================================================================

class Bitmap
  if $tons_version == nil || $tons_version < 1.6
    alias draw_text_shaded_later draw_text
  end
  def draw_text_full(x2, y2, w2 = 0, h2 = 0, text2 = '', a2 = 0)
    if x2.is_a?(Rect)
      x, y, w, h, text, a = x2.x, x2.y, x2.width, x2.height, y2, w2
    else
      x, y, w, h, text, a = x2, y2, w2, h2, text2, a2
    end
    save_color = self.font.color.clone
    self.font.color = Color.new(0, 0, 0)
    [x-1, x+1].each {|xx| [y-1, y+1].each {|yy|
            draw_text_shaded_later(xx, yy, w, h, text, a)}}
    self.font.color = save_color
    draw_text_shaded_later(x, y, w, h, text, a)
  end
 
end

#==============================================================================
# Clock_Sprite
#==============================================================================

class Clock_Sprite < Sprite
 
  def initialize
    super
    self.x, self.y, self.z = 640 - 8 - ATES::CWIDTH, 8, 5000
    self.bitmap = Bitmap.new(ATES::CWIDTH, ATES::CFORMAT.length * 32)
    if $fontface != nil
      self.bitmap.font.name = $fontface
    elsif $defaultfonttype != nil
      self.bitmap.font.name = $defaultfonttype
    end
    self.bitmap.font.size = 26
    @odd = 0
    draw if $game_system.ates.active
  end
 
  def draw
    self.bitmap.clear
    hours = $game_system.ates.time.hour
    minutes = sprintf('%02d', $game_system.ates.time.min)
    weekday = ATES::WEEKDAYS[$game_system.ates.time.wday - 1]
    wday_abbr = ATES::WEEKDAY_ABBREVIATIONS[$game_system.ates.time.wday - 1]
    day = $game_system.ates.time.day + 1
    month = $game_system.ates.time.mon + 1
    yday = ATES::MONTHDAYS[0..month - 1].inject { |s, r| s + r } + day
    month_name = ATES::MONTHS[month - 1]
    month_abbr = ATES::MONTH_ABBREVIATIONS[month - 1]
    month_days = ATES::MONTHDAYS[month - 1]
    year = $game_system.ates.time.year
    year_days = ATES::MONTHDAYS.inject { |s, r| s + r }
    season = $game_system.ates.get_season
    terrain = $game_system.ates.terrain
    temp = $game_system.ates.temp.to_s + ATES::TEMP_SUFFIX
    weather = $game_system.ates.weather.current_weather == -1 ? ATES::DEFAULT_WEATHER_NAME : $game_system.ates.weather.current_weather[0]
    tod = $game_system.ates.current_times[$game_system.ates.time_index][0]
    hday = $game_system.ates.holiday
    if hday != nil
      weekday = hday[0]
    end
    clock_text = ATES::CFORMAT.map { |ln| ln.clone }
    unless ATES::HOUR24
      suffix = "PM"
      if hours < 12
        suffix = "AM"
        hours = 12 if hours == 0
      elsif hours > 12
        suffix = "PM"
        hours -= 12
      end
    else
      suffix = ""
      hours = 24 if hours == 0
      hours = sprintf('%02d', hours)
    end
    colon = @odd % 2 == 0 ? " " : ":"
    clock_text.each { |ln|
      ln.gsub!(/%M/, minutes)
      ln.gsub!(/%H/, hours.to_s)
      ln.gsub!(/%A/, weekday)
      ln.gsub!(/%a/, wday_abbr)
      ln.gsub!(/%s/, " " + suffix)
      ln.gsub!(/:/, colon)
      ln.gsub!(/%m/, month.to_s)
      ln.gsub!(/%n/, month_name)
      ln.gsub!(/%l/, month_days.to_s)
      ln.gsub!(/%Y/, year.to_s)
      ln.gsub!(/%L/, year_days.to_s)
      ln.gsub!(/%d/, day.to_s)
      ln.gsub!(/%D/, yday.to_s)
      ln.gsub!(/%S/, season)
      ln.gsub!(/%w/, weather)
      ln.gsub!(/%t/, terrain)
      ln.gsub!(/%T/, temp)
      ln.gsub!(/%p/, tod)
    }
    for i in 0...clock_text.length
      self.bitmap.draw_text_full(0, i * 32, self.bitmap.width, 32, clock_text[i], 1)
    end
    @odd = (@odd + 1) % 2
  end
   
end

#==============================================================================
# Scene_Map
#==============================================================================

class Scene_Map
 
  alias main_ates_later main
  def main
    @clock = Clock_Sprite.new if $game_system.show_clock
    main_ates_later
    @clock.dispose if @clock != nil
  end
 
  alias update_ates_later update
  def update
    $game_system.ates.update
    update_ates_later
    if $game_system.show_clock
      @clock = Clock_Sprite.new if @clock == nil
      @clock.draw if $game_system.ates.frame_count % 20 == 0
    elsif @clock != nil
      @clock.dispose
      @clock = nil
    end
  end
 
end

#==============================================================================
# Scene_Battle
#==============================================================================

class Scene_Battle
  alias update_ates_later update
  def update
    $game_system.ates.update
    update_ates_later
  end
 
end

#==============================================================================
# Game_Map
#==============================================================================

class Game_Map
  alias setup_ates_later setup
  def setup(map_id)
    $game_system.ates.update
    setup_ates_later(map_id)
    if $game_system.ates.show_weather and $game_system.ates.weather.current_weather and $game_system.ates.weather.current_weather != -1
      weather = $game_system.ates.weather.current_weather
      if weather[5].length > 0
        $game_map.fog_name = weather[5][0]
        $game_map.fog_opacity = weather[5][1]
        $game_map.fog_hue = weather[5][2]
        $game_map.fog_zoom = weather[5][3]
        $game_map.fog_sx = weather[5][4]
        $game_map.fog_sy = weather[5][5]
        $game_map.start_fog_tone_change(Tone.new(*weather[5][6]), 0)
      end
    end
   
    @events.each { |ev|
      ev = ev[1]
      if ev.list and ev.list.length > 0 and ev.list[0].code == 108 and ev.list[0].parameters[0] =~ /Terrain='(.+)'/
        $game_system.ates.terrain = $1
      end
    }
  end 
end

#==============================================================================
# Scene_Calendar
#==============================================================================

class Scene_Calendar
  def main
    # Make calendar window
    @calendar_window = Window_Calendar.new
    @calendar_window.active = true
    @calendar_window.z = 1000
    #@day_window = Window_Day.new
    #@day_window.z = 1010
    #@day_window.visible = false
    #@dir = rand(4)
    # Make spriteset
    @spriteset = Spriteset_Map.new
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of window
    @calendar_window.dispose
    #@day_window.dispose
    # Dispose of spriteset
    @spriteset.dispose
  end
 
  def update
    @calendar_window.update
    #@day_window.update
    #if @calendar_window.active
      #if Input.trigger?(Input::C)
      #  @day_window.visible = true
      #  @day_window.active = true
      #  @calendar_window.active = false
      #  @day_window.x, @day_window.y = 80, 80
      #  @day_window.appear(@dir)
      #  @dir = rand(4)
      #end
      if Input.trigger?(Input::B)
        $game_system.se_play($data_system.cancel_se)
        $scene = Scene_Map.new
      end
    #elsif @day_window.active
      #if Input.trigger?(Input::B)
      #  @day_window.disappear(@dir)
      #  @day_window.active = false
      #  @calendar_window.active = true
      #end
    #end
  end
end

#==============================================================================
# Window_Calendar
#==============================================================================

class Window_Calendar < Window_Base
  def initialize
    super(48, 48, 544, 384)
    self.contents = Bitmap.new(width - 32, height - 32)
    @month, @day, @wday, @year = $game_system.ates.time.mon, $game_system.ates.time.day, $game_system.ates.time.wday, $game_system.ates.time.year
    update
    refresh
  end
 
  def update
    prev_mon = @month
    if Input.repeat?(Input::LEFT)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      @day -= 1
      if @day == 0
        @month -= 1
        if @month == 0
          unless @year == ATES::FYEAR
            @year -= 1
            @month = ATES::MONTHS.length
          else
            @day = 1
            @month = 1
            continue = false
          end
        end
        @day = ATES::MONTHDAYS[@month - 1]
      end
      if continue
        @wday = (@wday + ATES::WEEKDAYS.length - 1) % ATES::WEEKDAYS.length
        @wday = ATES::WEEKDAYS.length if @wday == 0
      end
    end
    if Input.repeat?(Input::RIGHT)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      @day += 1
      if @day == ATES::MONTHDAYS[@month - 1] + 1
        @month += 1
        if @month == ATES::MONTHS.length + 1
          unless @year == ATES::LYEAR
            @year += 1
            @month = 1
          else
            @month = ATES::MONTHS.length
            @day = ATES::MONTHDAYS[@month - 1]
            continue = false
          end
        end
        @day = 1
      end
      if continue
        @wday = (@wday + 1) % ATES::WEEKDAYS.length
        @wday = ATES::WEEKDAYS.length if @wday == 0
      end
    end
    if Input.repeat?(Input::UP)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      tmpday = @day
      @day -= ATES::WEEKDAYS.length
      if @day <= 0
        @month -= 1
        if @month == 0
          unless @year == ATES::FYEAR
            @year -= 1
            @month = ATES::MONTHS.length
          else
            @day = tmpday
            @month = 1
            continue = false
          end
        end
        if continue
          tmp = (@wday + ATES::WEEKDAYS.length - @day) % ATES::WEEKDAYS.length
          tmp = ATES::WEEKDAYS.length if tmp == 0
          if @wday > tmp
            tmp = tmp + ATES::WEEKDAYS.length - @wday
          else
            tmp = tmp - @wday
          end
          @day = ATES::MONTHDAYS[@month - 1]
          @day -= tmp
        end
      end
    end
    if Input.repeat?(Input::DOWN)
      $game_system.se_play($data_system.cursor_se)
      continue = true
      tmpday = @day
      @day += ATES::WEEKDAYS.length
      if @day >= ATES::MONTHDAYS[@month - 1] + 1
        @month += 1
        if @month == ATES::MONTHS.length + 1
          unless @year == ATES::LYEAR
            @year += 1
            @month = 1
          else
            @day = tmpday
            @month = ATES::MONTHS.length
            continue = false
          end
        end
        if continue
          tmp = (@wday + ATES::MONTHDAYS[@month - 2] - @day) % ATES::WEEKDAYS.length
          tmp = ATES::WEEKDAYS.length if tmp == 0
          if @wday <= tmp
            tmp -= ATES::WEEKDAYS.length
          end
          @day = @wday - tmp
        end
      end
    end
    super()
    refresh if prev_mon != @month
    row_count = (ATES::MONTHDAYS.max - 2) / ATES::WEEKDAYS.length + 2
    row_height = height - 116
    top_margin = ((row_height % row_count) / 2.0).ceil
    row_height -= row_height % row_count
    row_height /= row_count
    colwidth = width - 32
    margin = ((colwidth % ATES::WEEKDAY_ABBREVIATIONS.length) / 2.0).ceil
    colwidth -= colwidth % ATES::WEEKDAY_ABBREVIATIONS.length
    colwidth /= ATES::WEEKDAY_ABBREVIATIONS.length
    start_wday = (@wday + ATES::WEEKDAYS.length - (@day - 1) % ATES::WEEKDAYS.length) % ATES::WEEKDAYS.length
    start_wday = ATES::WEEKDAYS.length if start_wday == 0
    row = (@day + start_wday - 2) / ATES::WEEKDAYS.length
    self.cursor_rect.set(margin + (@wday - 1) * colwidth, 84 + top_margin + row * row_height, colwidth, 32)
  end
 
  def refresh
    self.contents.clear
    self.contents.font.size = 32
    self.contents.font.color = system_color
    self.contents.draw_text_full(Rect.new(0, 0, width - 32, 32), ATES::MONTHS[@month - 1] + " " + @year.to_s, 1)
    self.contents.font.size = 24
   
    colwidth = width - 32
    margin = ((colwidth % ATES::WEEKDAY_ABBREVIATIONS.length) / 2.0).ceil
    colwidth -= colwidth % ATES::WEEKDAY_ABBREVIATIONS.length
    colwidth /= ATES::WEEKDAY_ABBREVIATIONS.length
   
    for i in 0...ATES::WEEKDAY_ABBREVIATIONS.length
      self.contents.draw_text_full(Rect.new(margin + i * colwidth, 40, colwidth, 32), ATES::WEEKDAY_ABBREVIATIONS[i], 1)
    end
    self.contents.fill_rect(Rect.new(0, 76, width - 32, 2), system_color)
   
    row_count = (ATES::MONTHDAYS.max - 2) / ATES::WEEKDAYS.length + 2
    row_height = height - 116
    top_margin = ((row_height % row_count) / 2.0).ceil
    row_height -= row_height % row_count
    row_height /= row_count
    cur_wday = (@wday + ATES::WEEKDAYS.length - (@day - 1) % ATES::WEEKDAYS.length) % ATES::WEEKDAYS.length
    cur_wday = ATES::WEEKDAYS.length if cur_wday == 0
    start_wday = cur_wday
    cur_day = 1
    cur_row = (cur_day - 1) / 7
    while cur_day <= ATES::MONTHDAYS[@month - 1]
      if (cur_day == $game_system.ates.time.day and @month == $game_system.ates.time.mon and @year == $game_system.ates.time.year)
        self.contents.font.color = Color.new(240, 40, 40)
      elsif $game_system.ates.get_holiday(@month - 1, cur_day - 1, cur_wday) != nil
        self.contents.font.color = Color.new(150, 150, 0)
      else
        self.contents.font.color = normal_color
      end
      self.contents.draw_text_full(Rect.new(margin + (cur_wday - 1) * colwidth, 84 + top_margin + cur_row * row_height, colwidth, 32), cur_day.to_s, 1)
      cur_day += 1
      cur_wday = cur_wday + 1
      if cur_wday > ATES::WEEKDAYS.length
        cur_wday -= ATES::WEEKDAYS.length
        cur_row += 1
      end
    end
  end
end

#==============================================================================
# Window_Day
#==============================================================================

class Window_Day < Window_Base
  def initialize
    #(dir == 2 ? 320 : 48), (dir == 3 ? 240 : 48), (dir % 2 == 0 ? 272 : 544), (dir % 2 == 1 ? 192 : 384)
    super(80, 80, 480, 320)
    self.contents = Bitmap.new(width - 32, height - 32)
  end
 
  def appear(dir, duration = 40)
    @d_pos = [self.x, self.y]
    case dir
    when 0
      self.x = -480
    when 1
      self.y = -320
    when 2
      self.x = 640
    when 3
      self.y = 480
    end
    @s_pos = [self.x, self.y]
    @dir = dir
    @duration = duration
    @frames = 0
    @moving = true
  end
 
  def disappear(dir, duration = 40)
    @s_pos = [self.x, self.y]
    case dir
    when 0
      self.x += 560
    when 1
      self.y -= 400
    when 2
      self.x += 560
    when 3
      self.y += 400
    end
    @d_pos = [self.x, self.y]
    self.x, self.y = *@s_pos
    @dir = dir
    @duration = duration
    @frames = 0
    @moving = true
  end
 
  def update
    if @moving
      self.x = (@d_pos[0] * @frames + @s_pos[0] * (@duration - @frames)) / @duration
      self.y = (@d_pos[1] * @frames + @s_pos[1] * (@duration - @frames)) / @duration
      @moving = ([self.x, self.y] != @d_pos)
      @frames += 1
    end
    super()
  end
end

class Window_Text < Window_Base
  def initialize
    super(48, 48, 544, 384)
    self.contents = Bitmap.new(width - 32, height - 32)
   
    @dual_keys = ['`','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E',
                  'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U',
                  'V','W','X','Y','Z','-','=','[',']','\\',';','\'',',','.','/']
    @single_keys = ['NumberPad 0','NumberPad 1','NumberPad 2','NumberPad 3',
                    'NumberPad 4','NumberPad 5','NumberPad 6','NumberPad 7',
                    'NumberPad 8','NumberPad 9','Space','Enter','Tab']
    @chars1 = ['`','1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f',
               'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
               'x','y','z','-','=','[',']','/',';','\'',',','.','\\']
    @chars2 = ['~','!','@','#','$','%','^','&','*','(',')','A','B','C','D','E','F',
               'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W',
               'X','Y','Z','_','+','{','}','?',':','"','<','>','|']
    @chars = ['0','1','2','3','4','5','6','7','8','9',' ','\n','\t']
   
    @text = ""
    @cursor = true
  end
 
  def update
    @dual_keys.each_with_index { |i, ind|
      if Input.repeat?(Input::Key[i])
        @text += (Input.press?(Input::Key['Shift']) ? @chars2[ind] : @chars1[ind])
      end
    }
    @single_keys.each_with_index { |i, ind|
      if Input.repeat?(Input::Key[i])
        @text += @chars[ind]
      end
    }
    if Input.repeat?(Input::Key['Backspace'])
      @text = @text.split('')
      tmp = @text.pop()
      if (tmp == 'n' or tmp == 't') and @text[@text.length - 1] == '\\'
        @text.pop()
      end
      @text = @text.join('')
    end
    @cursor = !@cursor if Graphics.frame_count % 20 == 0
    refresh
  end
 
  def refresh
    self.contents.clear
   
    tmp = @text.gsub(/((?:\\n)+)\z/, '')
    y_mod = $1 ? $1.length / 2 : 0
    x_pos = y_mod > 0
    lns = tmp.gsub(/\\t/,'    ').split(/\\n/)
    y = 0
    x = 0
    lns.each_with_index { |ln, ind|
      rect = self.contents.text_size(ln)
      rect.height = self.contents.text_size('a').height
      rect.width += 1 unless ln.index(/[vVAwf\/\\]\z/).nil?
      rect.y = y
      self.contents.draw_text(rect, ln)
      y += rect.height
      x = rect.width
    }
    #p lns if lns.length > 1
    height = self.contents.text_size('a').height
    y -= height unless lns.last.nil?
    y += y_mod * height
    x = (x_pos ? 0 : x + 1)
    self.contents.fill_rect(Rect.new(x, y, 2, height), Color.new(0, 0, 0)) if @cursor
    #@cursor = !@cursor
  end
end


unless $BlizzABS or ($tons_version and TONS_OF_ADDONS::CUSTOM_CONTROLS)

  #==============================================================================
  # module Input
  #==============================================================================
 
  module Input
   
    #----------------------------------------------------------------------------
    # Simple ASCII table
    #----------------------------------------------------------------------------
    Key = {'A' => 65, 'B' => 66, 'C' => 67, 'D' => 68, 'E' => 69, 'F' => 70,
           'G' => 71, 'H' => 72, 'I' => 73, 'J' => 74, 'K' => 75, 'L' => 76,
           'M' => 77, 'N' => 78, 'O' => 79, 'P' => 80, 'Q' => 81, 'R' => 82,
           'S' => 83, 'T' => 84, 'U' => 85, 'V' => 86, 'W' => 87, 'X' => 88,
           'Y' => 89, 'Z' => 90,
           '0' => 48, '1' => 49, '2' => 50, '3' => 51, '4' => 52, '5' => 53,
           '6' => 54, '7' => 55, '8' => 56, '9' => 57,
           'NumberPad 0' => 45, 'NumberPad 1' => 35, 'NumberPad 2' => 40,
           'NumberPad 3' => 34, 'NumberPad 4' => 37, 'NumberPad 5' => 12,
           'NumberPad 6' => 39, 'NumberPad 7' => 36, 'NumberPad 8' => 38,
           'NumberPad 9' => 33,
           'F1' => 112, 'F2' => 113, 'F3' => 114, 'F4' => 115, 'F5' => 116,
           'F6' => 117, 'F7' => 118, 'F8' => 119, 'F9' => 120, 'F10' => 121,
           'F11' => 122, 'F12' => 123,
           ';' => 186, '=' => 187, ',' => 188, '-' => 189, '.' => 190, '/' => 220,
           '\\' => 191, '\'' => 222, '[' => 219, ']' => 221, '`' => 192,
           'Backspace' => 8, 'Tab' => 9, 'Enter' => 13, 'Shift' => 16,
           'Left Shift' => 160, 'Right Shift' => 161, 'Left Ctrl' => 162,
           'Right Ctrl' => 163, 'Left Alt' => 164, 'Right Alt' => 165,
           'Ctrl' => 17, 'Alt' => 18, 'Esc' => 27, 'Space' => 32, 'Page Up' => 33,
           'Page Down' => 34, 'End' => 35, 'Home' => 36, 'Insert' => 45,
           'Delete' => 46, 'Arrow Left' => 37, 'Arrow Up' => 38,
           'Arrow Right' => 39, 'Arrow Down' => 40,
           'Mouse Left' => 1, 'Mouse Right' => 2, 'Mouse Middle' => 4,
           'Mouse 4' => 5, 'Mouse 5' => 6}
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # START Configuration
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    UP = [Key['Arrow Up']]
    LEFT = [Key['Arrow Left']]
    DOWN = [Key['Arrow Down']]
    RIGHT = [Key['Arrow Right']]
    A = [Key['Shift']]
    B = [Key['Esc'], Key['NumberPad 0'], Key['X']]
    C = [Key['Space'], Key['Enter'], Key['C']]
    X = [Key['A']]
    Y = [Key['S']]
    Z = [Key['D']]
    L = [Key['Q'], Key['Page Down']]
    R = [Key['W'], Key['Page Up']]
    F5 = [Key['F5']]
    F6 = [Key['F6']]
    F7 = [Key['F7']]
    F8 = [Key['F8']]
    F9 = [Key['F9']]
    SHIFT = [Key['Shift']]
    CTRL = [Key['Ctrl']]
    ALT = [Key['Alt']]
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # END Configuration
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    # All keys
    KEY_COUNT = 256
    ALL_KEYS = (0...KEY_COUNT).to_a
    # Win32 API calls
    GetKeyboardState = Win32API.new('user32', 'GetKeyboardState', 'P', 'I')
    GetKeyboardLayout = Win32API.new('user32', 'GetKeyboardLayout', 'L', 'L')
    MapVirtualKeyEx = Win32API.new('user32', 'MapVirtualKeyEx', 'IIL', 'I')
    ToUnicodeEx = Win32API.new('user32', 'ToUnicodeEx', 'LLPPILL', 'L')
    # some other constants
    DOWN_STATE_MASK = 0x80
    DEAD_KEY_MASK = 0x80000000
    # data
    @state = "\0" * KEY_COUNT
    @triggered = Array.new(KEY_COUNT, false)
    @pressed = Array.new(KEY_COUNT, false)
    @released = Array.new(KEY_COUNT, false)
    @repeatedKey = -1
    @repeatedCount = 0
    #----------------------------------------------------------------------------
    # update
    #  Updates input.
    #----------------------------------------------------------------------------
    def self.update
      # get current language layout
      @language_layout = GetKeyboardLayout.call(0)
      # get new keyboard state
      GetKeyboardState.call(@state)
      # this special code is used because Ruby 1.9.x does not return a char
      # when using String#[] but another String
      key = 0
      @state.each_byte {|byte|
          # if pressed state
          if (byte & DOWN_STATE_MASK) == DOWN_STATE_MASK
            # not released anymore
            @released[key] = false
            # if not pressed yet
            if !@pressed[key]
              # pressed and triggered
              @pressed[key] = true
              @triggered[key] = true
              @repeatedKey = key
              @repeatedCount = 0
            else
              # not triggered anymore
              @triggered[key] = false
            end
            # update of repeat counter
            if key == @repeatedKey
              @repeatedCount < 17 ? @repeatedCount += 1 : @repeatedCount = 15
            end
          # not released yet
          elsif !@released[key]
            # if still pressed
            if @pressed[key]
              # not triggered, pressed or repeated, but released
              @triggered[key] = false
              @pressed[key] = false
              @released[key] = true
              if key == @repeatedKey
                @repeatedKey = -1
                @repeatedCount = 0
              end
            end
          else
            # not released anymore
            @released[key] = false
          end
          key += 1}
    end
    #----------------------------------------------------------------------------
    # dir4
    #  4 direction check.
    #----------------------------------------------------------------------------
    def self.dir4
      return 2 if self.press?(DOWN)
      return 4 if self.press?(LEFT)
      return 6 if self.press?(RIGHT)
      return 8 if self.press?(UP)
      return 0
    end
    #----------------------------------------------------------------------------
    # dir8
    #  8 direction check.
    #----------------------------------------------------------------------------
    def self.dir8
      down = self.press?(DOWN)
      left = self.press?(LEFT)
      return 1 if down && left
      right = self.press?(RIGHT)
      return 3 if down && right
      up = self.press?(UP)
      return 7 if up && left
      return 9 if up && right
      return 2 if down
      return 4 if left
      return 6 if right
      return 8 if up
      return 0
    end
    #----------------------------------------------------------------------------
    # trigger?
    #  Test if key was triggered once.
    #----------------------------------------------------------------------------
    def self.trigger?(keys)
      keys = [keys] unless keys.is_a?(Array)
      return keys.any? {|key| @triggered[key]}
    end
    #----------------------------------------------------------------------------
    # press?
    #  Test if key is being pressed.
    #----------------------------------------------------------------------------
    def self.press?(keys)
      keys = [keys] unless keys.is_a?(Array)
      return keys.any? {|key| @pressed[key]}
    end
    #----------------------------------------------------------------------------
    # repeat?
    #  Test if key is being pressed for repeating.
    #----------------------------------------------------------------------------
    def self.repeat?(keys)
      keys = [keys] unless keys.is_a?(Array)
      return (@repeatedKey >= 0 && keys.include?(@repeatedKey) &&
          (@repeatedCount == 1 || @repeatedCount == 16))
    end
    #----------------------------------------------------------------------------
    # release?
    #  Test if key was released.
    #----------------------------------------------------------------------------
    def self.release?(keys)
      keys = [keys] unless keys.is_a?(Array)
      return keys.any? {|key| @released[key]}
    end
    #----------------------------------------------------------------------------
    # get_character
    #  vk - virtual key
    #  Gets the character from keyboard input using the input locale identifier
    #  (formerly called keyboard layout handles).
    #----------------------------------------------------------------------------
    def self.get_character(vk)
      # get corresponding character from virtual key
      c = MapVirtualKeyEx.call(vk, 2, @language_layout)
      # stop if character is non-printable and not a dead key
      return '' if c < 32 && (c & DEAD_KEY_MASK != DEAD_KEY_MASK)
      # get scan code
      vsc = MapVirtualKeyEx.call(vk, 0, @language_layout)
      # result string is never longer than 4 bytes (Unicode)
      result = "\0" * 4
      # get input string from Win32 API
      length = ToUnicodeEx.call(vk, vsc, @state, result, 4, 0, @language_layout)
      return (length == 0 ? '' : result)
    end
    #----------------------------------------------------------------------------
    # get_input_string
    #  Gets the string that was entered using the keyboard over the input locale
    #  identifier (formerly called keyboard layout handles).
    #----------------------------------------------------------------------------
    def self.get_input_string
      result = ''
      # check every key
      ALL_KEYS.each {|key|
          # if repeated
          if self.repeat?(key)
            # get character from keyboard state
            c = self.get_character(key)
            # add character if there is a character
            result += c if c != ''
          end}
      # empty if result is empty
      return '' if result == ''
      # convert string from Unicode to UTF-8
      return self.unicode_to_utf8(result)
    end
    #----------------------------------------------------------------------------
    # unicode_to_utf8
    #  string - string in Unicode format
    #  Converts a string from Unicode format to UTF-8 format as RGSS does not
    #  support Unicode.
    #----------------------------------------------------------------------------
    def self.unicode_to_utf8(string)
      result = ''
      # L* format means a bunch of 4-byte wide-chars
      string.unpack('L*').each {|c|
          # characters under 0x80 are 1 byte characters
          if c < 0x0080
            result += c.chr
          # other characters under 0x800 are 2 byte characters
          elsif c < 0x0800
            result += (0xC0 | (c >> 6)).chr
            result += (0x80 | (c & 0x3F)).chr
          # other characters under 0x10000 are 3 byte characters
          elsif c < 0x10000
            result += (0xE0 | (c >> 12)).chr
            result += (0x80 | ((c >> 6) & 0x3F)).chr
            result += (0x80 | (c & 0x3F)).chr
          # other characters under 0x200000 are 4 byte characters
          elsif c < 0x200000
            result += (0xF0 | (c >> 18)).chr
            result += (0x80 | ((c >> 12) & 0x3F)).chr
            result += (0x80 | ((c >> 6) & 0x3F)).chr
            result += (0x80 | (c & 0x3F)).chr
          # other characters under 0x4000000 are 5 byte characters
          elsif c < 0x4000000
            result += (0xF8 | (c >> 24)).chr
            result += (0x80 | ((c >> 18) & 0x3F)).chr
            result += (0x80 | ((c >> 12) & 0x3F)).chr
            result += (0x80 | ((c >> 6) & 0x3F)).chr
            result += (0x80 | (c & 0x3F)).chr
          # other characters under 0x80000000 are 6 byte characters
          elsif c < 0x80000000
            result += (0xFC | (c >> 30)).chr
            result += (0x80 | ((c >> 24) & 0x3F)).chr
            result += (0x80 | ((c >> 18) & 0x3F)).chr
            result += (0x80 | ((c >> 12) & 0x3F)).chr
            result += (0x80 | ((c >> 6) & 0x3F)).chr
            result += (0x80 | (c & 0x3F)).chr
          end}
      return result
    end
 
  end

end



Instructions

All in the script.


Compatibility

No known issues, but may not work with other scripts that change the tint unless you turn tinting off.


Credits and Thanks


  • Blizzard

  • ThallionDarkshine




Author's Notes

This is a finished and rereleased version of the original ATES script found here. If you are having questions or problems, please first read the original topic!
6
RMXP Script Database / [XP] Design a HUD
February 11, 2013, 06:49:18 pm
Design a HUD
Authors: ThallionDarkshine
Version: 0.1
Type: Heads Up Display (HUD)
Key Term: Misc Add-on



Introduction

Have you ever seen some beautiful HUD and thought "I wish I knew how to script well enough to make something like that"? Well, now you don't need to. This is a framework allowing non-scripters to create stunning heads-up-displays using a simple (sort-of), html-based language. The HUD that you create can have custom pictures, icons, and gradient bars, as well as formatted text. You can align text, make it bold or italic, change its color, font, or size. The possibilities are endless (not quite) with the new Design a HUD framework.


Features


  • Create amazing HUDs easily with no scripting knowledge.

  • Display the values of variables in the HUD.

  • Display gradient bars for actors in the HUD.

  • Absolutely position elements or align them to different sides of the HUD.




Screenshots

Spoiler: ShowHide



Demo

No demo yet.


Script

Spoiler: ShowHide


module DesignHUD
  # This HUD uses an easy to use format for configuration much like html
  #   it has many types of tags, each inserting different information into the
  #   HUD, such as icons, hp/sp/xp bars, and different information about the
  #   actors.
  #
  # Tags:
  #
  #  Formatting Elements:
  #   * <i></i>
  #     - italicizes text
  #   * <b></b>
  #     - bolds text
  #   * <c=R:G:B[:A]></c>
  #     - changes the color to Color.new(R, G, B, A) (A is unnecessary)
  #   * <font=NAME:SIZE></font>
  #     - changes the font to NAME and the font size to SIZE
  #  Graphical Elements:
  #   * <ico=FILENAME>
  #     - inserts the icon named FILENAME
  #   * <pic=FILENAME>
  #     - inserts the picture named FILENAME
  #   * <bar style=STYLE type=TYPE cstyle=COLORSTYLE1:COLORSTYLE2... text=TEXT
  #      neaten=NEATEN lines=LINES shape=SHAPE dimensions=WIDTH:HEIGHT>
  #     - inserts a gradient bar with certain parameters that you can customize
  #     - types: :hp, :mp, :exp, :lvl
  #     - styles: 0 - 34
  #         0-6 - Linear top-to-bottom
  #           some are ease in or ease out or bilinear (starts from center)
  #         7-13 - Linear top-to-bottom stripes
  #           same as 0-6 except it uses stripes defined by four color styles
  #             instead of 2
  #         14-34 - Linear left-to-right
  #           some are ease in or ease out or bilinear or fade out on the top
  #             and bottom
  #     - shapes: 0 - 3
  #         0 - Rectangular
  #         1 - Slant Left
  #         2 - Rounded
  #         3 - Slant Right
  #     - color styles: 0 - 12
  #         color styles define the two endpoints of the gradient's colors
  #           for styles 7 - 13 use four color styles
  #         main two colors defined by the type
  #           :hp - Red and Green
  #           :mp - Red and Blue
  #           :exp - Orange and Yellow
  #           :lvl - Blue and Purple
  #         two mixed colors are defined by the percentage of the bar remaining
  #           Mixed1 - At 0% full, Color1, at 100% full, Color2
  #           Mixed2 - At 0% full, Color2, at 100% full, Color1
  #         real colors defined by color style
  #           0 - Color1
  #           1 - Color2
  #           2 - Black
  #           3 - Mixed1
  #           4 - Mixed2
  #           5 - Highlight of Color1
  #           6 - Highlight of Color2
  #           7 - Highlight of Mixed1
  #           8 - Highlight of Mixed2
  #           9 - Shadow of Color1
  #           10 - Shadow of Color2
  #           11 - Shadow of Mixed1
  #           12 - Shadow of Mixed2
  #  Positioning Elements:
  #   * <pos x=VALX y=VALY></pos>
  #     - positions the contents at an x position of VALX and
  #         at a y position of VALY
  #   * <offset x=VALX y=VALY></offset>
  #     - adds VALX and VALY to the position of the contents
  #   * <table></table>
  #     - starts a table
  #   * <tr></tr>
  #     - adds a row to a table
  #   * <td></td>
  #     - adds a cell to a row of a table
  #   * <left></left>
  #     - aligns the contents to the left
  #   * <center></center>
  #     - aligns the contents in the center
  #   * <right></right>
  #     - aligns the contents to the right
  #   * <ln></ln>
  #     - denotes one line in the HUD
  #   * <width=VAL></width>
  #     - sets the width of the contents to VAL
  #   * <height=VAL></height>
  #     - sets the height of the contents to VAL
  #  HUD Properties:
  #   * <hud>
  #     - this tag has many properties, listed below
  #   * windowskin='FILENAME'
  #     - sets the windowskin of the HUD to the windowskin named FILENAME
  #   * bg='FILENAME'
  #     - sets the background image of the HUD to the picture named FILENAME
  #   * align=ALIGN
  #     - sets the align of the HUD to ALIGN
  #     - possible aligns: TL, TC, TR, ML, MC, MR, BL, BC, BR (top-left,
  #         top-center, top-right, middle-left, middle-center, middle-right,
  #         bottom-left, bottom-center, bottom-right)
  #   * offsetx=VAL
  #     - sets the xoffset of the HUD to VAL
  #   * offsety=VAL
  #     - and the yoffset of the HUD to VAL
  #   * width=VAL
  #     - sets the width of the HUD to VAL
  #   * height=VAL
  #     - sets the height of the HUD to VAL
  #   * back_opacity=VAL
  #     - sets the back opacity of the HUD to VAL
  #   * contents_opacity=VAL
  #     - sets the contents opacity of the HUD to VAL
  #   * opacity=VAL
  #     - sets the opacity of the HUD to VAL
 
  HUD = <<-HUD
    <hud width=220 align=TL offsetx=16 offsety=16 opacity=0>
    <ln><center><var=name></center></ln>
    <ln>HP: <right><bar neaten=true lines=true text=false style=20 cstyle=0:3 shape=2></right></ln>
    <ln>SP: <right><bar type=:mp neaten=true lines=true text=false style=20 cstyle=0:3 shape=2></right></ln>
    <ln>EXP: <right><bar type=:exp neaten=true lines=true text=false style=20 cstyle=0:3 shape=2></right></ln>
    <ln>Level: <right><bar type=:lvl neaten=true lines=true text=false style=20 cstyle=0:3 shape=2></right></ln>
  HUD
 
  NO_END = ['ico', 'pic', 'hud', 'var', 'bar', 'shape']
 
  BLOCK_ELS = ['ln']
 
  def self.var_expression(name)
    case name
    when 'gold' then return proc { $game_party.gold }
    when 'name' then return proc { $game_party.actors[0].name }
    else return proc {}
    end
  end
 
  SPATTERN = /<([\w\-]+)(?:\s*=\s*([\w\"\'\-\_\:\$\.\s\+]+))?((?:\s*\w+\s*=\s*[\w\"\'\-\_\:\$\.\s\+]+)*)>/
end
class HUD < Window_Base
  attr_accessor :tmp_attrs
  def initialize(text)
    super(0, 0, 33, 33)
    self.contents = Bitmap.new(1, 1)
    self.visible = false
    @align = 'TL'
    @xoffset, @yoffset = 0, 0
    @tmp_attrs = {}
    @text = text
    Element.reset_id
    parse_text
    setup_hud
    setup_align
    @dom.delete_if { |el| el.el_type == 'hud' }
    self.width = [self.width, 33].max
    self.height = [self.height, 33].max
    self.contents = Bitmap.new(width - 32, height - 32)
    tmp = self.contents
    render_hud
  end
 

  def update
    redim = []
    vars = []
    redraw = []
    @var_nodes.each { |el|
      val = el.val
      if val != el.attrs[:val]
        vars.push(el)
        redim |= [el.last_line]
        pos = el.attrs[:pos]
        rect = el.attrs[:size]
        rect.x, rect.y = *pos
        rect.x += el.attrs[:ox]
        rect.y += el.attrs[:oy]
        self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
        el.attrs[:val] = val
      end
    }
    @dom.each { |el|
      comp = false
      el.each_child_ex2(proc { |child|
        comp = false
      }) { |child|
        if child.attrs[:size] and !comp
          pos = child.attrs[:pos]
          rect = child.attrs[:size]
          rect.x, rect.y = *pos
          rect.x += child.attrs[:ox] if child.attrs[:ox]
          rect.y += child.attrs[:oy] if child.attrs[:oy]
          if vars.select { |el|
            pos = el.attrs[:pos]
            tmp = el.attrs[:size]
            tmp.x, tmp.y = *pos
            tmp.x += el.attrs[:ox] if el.attrs[:ox]
            tmp.y += el.attrs[:oy] if el.attrs[:oy]
            tmp.intersect?(rect)
          }.length > 0
            redraw.push(child)
            self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
            comp = true
          end
        end
      }
    }
    redraw ||= vars
   
    if redim.length > 0
      redetermine_size(redim)
      setup_align
    end
    if redraw.length > 0
      redraw_hud(redraw)
    end
  end
 
  def redetermine_size(els)
    @tmp_attrs[:ox] = 0
    @tmp_attrs[:oy] = 0
   
    pos = [0, 0]
   
    @dom.each { |el|
      ln_height = ln_width = 0
   
      if els.include?(el)
        pos = el.attrs[:pos].clone unless @tmp_attrs[:tmp]
        if @tmp_attrs[:tmp]
          @tmp_attrs[:tmp].push(true)
        else
          @tmp_attrs[:tmp] = [true]
        end
      end

      case el.el_type
      when 'ln'
        el.each_child_ex(proc { |child|
          if @tmp_attrs[:tmp]
            unless child.attrs[:size].nil?
              rect = child.attrs[:size]
              rect.x, rect.y = *child.attrs[:pos]
              self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
            end
            if @tmp_attrs[:abs_pos]
              child.attrs[:pos] = [@tmp_attrs[:abs_pos].last[0], @tmp_attrs[:abs_pos].last[1]]
            else
              child.attrs[:pos] = [pos[0], pos[1]]
            end
            child.attrs[:ox], child.attrs[:oy] = @tmp_attrs[:ox], @tmp_attrs[:oy]
          end
          if els.include?(child)
            pos = child.attrs[:pos].clone unless @tmp_attrs[:tmp]
            if @tmp_attrs[:tmp]
              @tmp_attrs[:tmp].push(true)
            else
              @tmp_attrs[:tmp] = [true]
            end
          end
          case child
          when FormatNode
            tmp = child.attrs[:start].call(child, self)
            child.attrs = tmp if tmp and tmp.is_a?(Hash)
          end
        },
        proc { |child|
          case child
          when FormatNode
            tmp = child.attrs[:finish].call(child, self)
            child.attrs = tmp if tmp and tmp.is_a?(Hash)
          end
          if @tmp_attrs[:tmp]
            if els.include?(child)
              @tmp_attrs[:tmp].pop
              @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0
            end
          end
          unless child.children.empty?
            resize(child)
          end
        }) { |child|
          if @tmp_attrs[:tmp]
            case child
            when TextNode
              size = self.contents.text_size(child.attrs[:val])
              child.attrs[:size] = size
              ln_height = [size.height, ln_height].max
              if @tmp_attrs[:abs_pos]
                tmp = @tmp_attrs[:abs_pos]
                ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
                @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
              else
                ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
                pos[0] += size.width
              end
            when VariableNode
              size = self.contents.text_size(child.val.to_s)
              child.attrs[:size] = size
              ln_height = [size.height, ln_height].max
              if @tmp_attrs[:abs_pos]
                tmp = @tmp_attrs[:abs_pos]
                ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
                @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
              else
                ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
                pos[0] += size.width
              end
            when IconNode, PictureNode, ShapeNode
              size = child.attrs[:bitmap].rect
              child.attrs[:size] = size
              ln_height = [size.height, ln_height].max
              if @tmp_attrs[:abs_pos]
                tmp = @tmp_attrs[:abs_pos]
                ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
                @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
              else
                ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
                pos[0] += size.width
              end
            when BarNode
              size = Rect.new(0,0,*child.attrs[:dimensions])
              child.attrs[:size] = size
              ln_height = [size.height, ln_height].max
              if @tmp_attrs[:abs_pos]
                tmp = @tmp_attrs[:abs_pos]
                ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
                @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
              else
                ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
                pos[0] += size.width
              end
            end
          end
        }
      end
     
      if @tmp_attrs[:tmp]
        if els.include?(el)
          @tmp_attrs[:tmp].pop
          @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0
        end
      end
    }
    @dom.each { |child|
      if child.block?
        child.attrs[:size].width = self.width - 32
        child.attrs[:size].height = child.attrs[:height] || child.attrs[:size].height
        child.attrs[:size].width = child.attrs[:width] || child.attrs[:size].width
      end
    }
  end
 
  def redraw_hud(els)
    @tmp_attrs = {}
   
    @dom.each { |el|
   
      align = 0
     
      case el.el_type
      when 'ln'
        if els.include?(el)
          pos = el.attrs[:pos].clone unless @tmp_attrs[:tmp]
          if @tmp_attrs[:tmp]
            @tmp_attrs[:tmp].push(true)
          else
            @tmp_attrs[:tmp] = [true]
          end
        end
        el.each_child_ex(proc { |child|
          if els.include?(child)
            pos = child.attrs[:pos].clone unless @tmp_attrs[:tmp]
            if @tmp_attrs[:tmp]
              @tmp_attrs[:tmp].push(true)
            else
              @tmp_attrs[:tmp] = [true]
            end
          end
          case child
          when FormatNode
            child.attrs[:start].call(child, self)
          end
        },
        proc { |child|
          case child
          when FormatNode
            child.attrs[:finish].call(child, self)
          end
          if @tmp_attrs[:tmp]
            if els.include?(child)
              @tmp_attrs[:tmp].pop
              @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0
            end
          end
        }) { |child|
          if @tmp_attrs[:tmp]
            draw_node(child)
          end
        }
      end
    }
  end
 
  def draw_node(node)
    case node
    when TextNode
      pos = node.attrs[:pos]
      ox, oy = node.attrs[:ox], node.attrs[:oy]
      text = node.attrs[:val]
      size = node.attrs[:size]
      self.contents.draw_text(Rect.new(pos[0] + ox, pos[1] + oy, size.width, size.height), text)
    when VariableNode
      pos = node.attrs[:pos]
      ox, oy = node.attrs[:ox], node.attrs[:oy]
      text = node.val.to_s
      size = node.attrs[:size]
      self.contents.draw_text(Rect.new(pos[0] + ox, pos[1] + oy, size.width, size.height), text)
    when IconNode, PictureNode, ShapeNode
      pos = node.attrs[:pos]
      ox, oy = node.attrs[:ox], node.attrs[:oy]
      bitmap = node.attrs[:bitmap]
      self.contents.blt(pos[0] + ox, pos[1] + oy, bitmap, bitmap.rect)
    when BarNode
      ln = node.last_line
      pos = node.attrs[:pos]
      ox, oy = node.attrs[:ox], node.attrs[:oy]
      size = node.attrs[:size]
      oy += (ln.attrs[:size].height - size.height) / 2
      type = node.attrs[:type]
      style = node.attrs[:style]
      shape = node.attrs[:shape]
      cstyle = node.attrs[:cstyle]
      text = node.attrs[:text]
      lines = node.attrs[:lines]
      neaten = node.attrs[:neaten]
      actor = node.attrs[:actor]
      self.contents.gradient_bar(type, style, shape, cstyle, actor, pos[0] + ox, pos[1] + oy, size.width, size.height, text, lines, neaten)
    end
  end
 
  def parse_text
    text = @text.clone
    @dom, @var_nodes = [], []
    index = 0
    current_id = -1
    current_el = nil
    parent = nil
    parent_els = []
    spattern = /<([\w\-]+)(?:\s*=\s*([\w\"\'\-\_\:\$\.\s\+]+))?((?:\s*\w+\s*=\s*[\w\"\'\-\_\:\$\.\s]+)*)>/
    epattern = /<\/[\w\-]+>/
    while text.length != 0
      s_ind = text.index(DesignHUD::SPATTERN)
      if s_ind != nil
        contents = nil
        el_name = $1
        el_val = $2 || ''
        el_attrs = {}
        tmp = $3.strip
        tmp.gsub(/(\w+)\s+=\s+([\w\"\'\-\:\+]+)/, "\\1=\\2").split(/\s+/).each { |el| el_attrs[el.split('=')[0].to_sym] = get_val(el.split('=')[1]) }
        el_val.gsub!(/[\'\"]/, '') if el_val
        el_attrs[:val] = el_val
        level, tmp_name, tmp_ind = 0, '', s_ind
        if !DesignHUD::NO_END.include?(el_name)
          loop do
            text.sub!(DesignHUD::SPATTERN, '')
            tmp = [text.index(/(<#{el_name}(?:=[\w\"\'\-\:]+)?(?:\s*\w+=[\w\"\'\-\:]+)*>)/, tmp_ind)]
            tmp.push(text.index(/<\/#{el_name}>/, tmp_ind))
            if !tmp[1]
              contents = text[s_ind...text.length - 4 - el_name.length]
              text = ''
            elsif !tmp[0]
              contents = text[s_ind...text.length - 4 - el_name.length]
              text = ''
            elsif tmp[1] < tmp[0]
              contents = text[s_ind...tmp[1]]
              text = text[tmp[1]...text.length]
            else
              level += 1
              tmp_ind = tmp[0] + 2 + el_name.length
            end
            break if contents != nil
          end
          case el_name
          when 'ln'
            element = ContainerNode.new('ln', el_attrs, nil, contents)
            @dom.push(element)
          end
        else
          text.sub!(DesignHUD::SPATTERN, '')
          case el_name
          when 'hud'
            element = HudNode.new('hud', el_attrs)
            @dom.push(element)
          end
        end
      end
    end
  end
 
  def setup_hud
    @bg = Sprite.new
    @bg.z = self.z - 1
    @bg.visible = false
    @dom.each { |el|
      el.each_child { |tmp|
        if tmp.el_type == 'hud'
          self.width = tmp.attrs[:width].to_i if tmp.attrs[:width]
          self.height = tmp.attrs[:height].to_i if tmp.attrs[:height]
          @align = tmp.attrs[:align] if tmp.attrs[:align]
          @xoffset = tmp.attrs[:offsetx].to_i if tmp.attrs[:offsetx]
          @yoffset = tmp.attrs[:offsety].to_i if tmp.attrs[:offsety]
          self.opacity = tmp.attrs[:opacity].to_i if tmp.attrs[:opacity]
          self.back_opacity = tmp.attrs[:back_opacity].to_i if tmp.attrs[:back_opacity]
          self.contents_opacity = tmp.attrs[:contents_opacity].to_i if tmp.attrs[:contents_opacity]
          begin
            self.windowskin = ((tmp.attrs[:windowskin] == '') ? Bitmap.new(1, 1) : RPG::Cache.windowskin(tmp.attrs[:windowskin])) if tmp.attrs[:windowskin]
          rescue
            self.windowskin = Bitmap.new(1, 1)
          end
          if tmp.attrs[:bg]
            @bg.bitmap = RPG::Cache.picture(tmp.attrs[:bg])
            @bg.visible = true
          end
        end
      }
    }
   
    tmp_width, tmp_height = get_dimensions
   
    if self.width == 33
      self.width = [tmp_width, 1].max + 32
    end
    if self.height == 33
      self.height = [tmp_height, 1].max + 32
    end
    amnt = 0
    @dom.each_with_index { |child, ind|
      if child.block?
        child.attrs[:size].width = self.width - 32
        #child.attrs[:size].height = child.attrs[:height] || child.attrs[:size].height
        child.attrs[:size].width = child.attrs[:width] || child.attrs[:size].width
        if child.attrs[:height]
          tmp = child.attrs[:size].height
          amnt += child.attrs[:height] - tmp
          child.attrs[:size].height = child.attrs[:height]
          unless ind == @dom.length - 1
            @dom[ind + 1...@dom.length].each { |i|
              i.attrs[:pos][1] += child.attrs[:height] - tmp
            }
          end
        end
      end
    }
    self.height += amnt
    @align.downcase!
    xmod = (['l','c'].include?(@align[1..1]) ? 1 : -1)
    ymod = (['t','m'].include?(@align[0..0]) ? 1 : -1)
    xstrt = case @align[1..1]
    when 'l' then 0
    when 'r' then 640 - self.width
    when 'c' then (640 - self.width) / 2
    end
    ystrt = case @align[0..0]
    when 't' then 0
    when 'b' then 480 - self.height
    when 'm' then (480 - self.height) / 2
    end
    self.x = xstrt + xmod * @xoffset
    self.y = ystrt + ymod * @yoffset
    if @bg.visible
      @bg.x = self.x + (self.width - @bg.bitmap.width) / 2
      @bg.y = self.y + (self.height - @bg.bitmap.height) / 2
    end
    self.visible = true
  end
 
  def get_dimensions
    ln_widths = []
    height = 0
    @tmp_attrs[:ox] = 0
    @tmp_attrs[:oy] = 0
    @tmp_attrs[:align] = 0
   
    pos = [0, 0]
   
    @dom.each { |el|
   
      pos[0] = 0
      ln_width = 0
      ln_height = 0
     
      case el.el_type
      when 'ln'
        el.attrs[:pos] = pos.clone
        el.attrs[:align] = @tmp_attrs[:abs_pos]
        el.attrs[:abs] = 0
        el.each_child_ex(proc { |child| # start proc
          child.attrs[:align] = (@tmp_attrs[:abs_pos] ? 0 : @tmp_attrs[:align])
          if @tmp_attrs[:abs_pos]
            child.attrs[:pos] = @tmp_attrs[:abs_pos].last.clone
            child.attrs[:abs] = @tmp_attrs[:abs_pos].length
          else
            child.attrs[:pos] = pos.clone
            child.attrs[:abs] = 0
          end
          child.attrs[:ox], child.attrs[:oy] = @tmp_attrs[:ox], @tmp_attrs[:oy]
          case child
          when FormatNode
            tmp = child.attrs[:start].call(child, self)
            child.attrs = tmp if tmp and tmp.is_a?(Hash)
          end
        },
        proc { |child| # end proc
          case child
          when FormatNode
            tmp = child.attrs[:finish].call(child, self)
            child.attrs = tmp if tmp and tmp.is_a?(Hash)
          end
          if !child.children.empty?
            resize(child)
          elsif child.block? or ![TextNode, VariableNode, IconNode, PictureNode, BarNode, ShapeNode].include?(child.class)
            child.attrs[:size] = Rect.new(0, 0, 0, 0)
          end
        }) { |child| # main proc
          case child
          when TextNode
            size = self.contents.text_size(child.attrs[:val])
            child.attrs[:size] = size
            ln_height = [size.height, ln_height].max
            if @tmp_attrs[:abs_pos]
              tmp = @tmp_attrs[:abs_pos]
              ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
              @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
            else
              ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
              pos[0] += size.width
            end
          when VariableNode
            size = self.contents.text_size(child.val.to_s)
            child.attrs[:size] = size
            ln_height = [size.height, ln_height].max
            if @tmp_attrs[:abs_pos]
              tmp = @tmp_attrs[:abs_pos]
              ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
              @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
            else
              ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
              pos[0] += size.width
            end
            @var_nodes.push(child)
          when IconNode, PictureNode, ShapeNode
            size = child.attrs[:bitmap].rect
            child.attrs[:size] = size
            ln_height = [size.height, ln_height].max
            if @tmp_attrs[:abs_pos]
              tmp = @tmp_attrs[:abs_pos]
              ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
              @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
            else
              ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
              pos[0] += size.width
            end
          when BarNode
            size = Rect.new(0,0,*child.attrs[:dimensions])
            child.attrs[:size] = size
            ln_height = [size.height, ln_height].max
            if @tmp_attrs[:abs_pos]
              tmp = @tmp_attrs[:abs_pos]
              ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
              @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
            else
              ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
              pos[0] += size.width
            end
            @var_nodes.push(child)
          end
        }
      end
     
      pos[1] += ln_height + @tmp_attrs[:oy]
      ln_widths.push(ln_width)
    }
   
    height = pos[1]
    width = ln_widths.max
    return width, height
  end
 
  def resize(el)
    size = Rect.new(0, 0, 0, 0)
    x1, y1 = 640, 480
    x2 = y2 = 0
    len = el.attrs[:abs]
    el.children.each { |i|
      next if i.attrs[:abs] > len
      x, y = *i.attrs[:pos]
      ns = i.attrs[:size]
      x1 = [x1, x].min
      y1 = [y1, y].min
      x2 = [x2, x + ns.width].max
      y2 = [y2, y + ns.height].max
    }
    size.width = x2 - x1
    size.height = y2 - y1
    pos = el.block? ? el.attrs[:pos] : [x1, y1]
    el.attrs[:pos], el.attrs[:size] = pos, size
  end
 
  def setup_align
    aligned = nil
    la = 0
    blocks = []
    @dom.each { |el|
      case el.el_type
      when 'ln'
        el.each_child_ex(proc{|child|},proc{|child|
          if child.attrs[:tmp]
            child.attrs.delete_if { |i| i[0] == :tmp }
            aligned = nil
          end
        }) { |child|
          unless child.attrs[:abs] > 0 or !aligned.nil?
            aligned = true
            child.attrs[:tmp] = true
            la = child.attrs[:align]
            blocks |= [child.last_block]
            child.last_block.attrs[:aels] = (child.last_block.attrs[:aels] || []).concat([child])
          end
        }
      end
    }
    blocks.each { |el|
      rw = el.attrs[:aels].inject(0) { |s, n| s + (n.attrs[:align] == 2 ? n.attrs[:size].width : 0) }
      cw = el.attrs[:aels].inject(0) { |s, n| s + (n.attrs[:align] == 1 ? n.attrs[:size].width : 0) }
      lx = el.attrs[:pos][0]
      rx = el.attrs[:pos][0] + el.attrs[:size].width - rw
      cx = el.attrs[:pos][0] + (el.attrs[:size].width) / 2
      el.attrs[:aels].each { |child|
        case child.attrs[:align]
        when 0
          ox = child.attrs[:pos][0]
          child.attrs[:pos][0] = lx
          child.each_child_ex(proc{},proc{}) { |i|
            i.attrs[:pos][0] += lx - ox
          }
          lx += child.attrs[:size].width
        when 1
          cx -= child.attrs[:size].width / 2
        when 2
          ox = child.attrs[:pos][0]
          child.attrs[:pos][0] = rx
          child.each_child_ex(proc{},proc{}) { |i|
            i.attrs[:pos][0] += rx - ox
          }
          rx += child.attrs[:size].width
        end
      }
      el.attrs[:aels].select { |i| i.attrs[:align] == 1 }.each { |child|
        ox = child.attrs[:pos][0]
        child.attrs[:pos][0] = cx
        child.each_child_ex(proc{},proc{}) { |i|
          i.attrs[:pos][0] += cx - ox
        }
        cx += child.attrs[:size].width
      }
      el.attrs.delete(:aels)
    }
  end
 
  def render_hud
   
    @dom.each { |el|
   
      align = 0
   
      case el.el_type
      when 'ln'
        el.each_child_ex(proc { |child|
          case child
          when FormatNode
            child.attrs[:start].call(child, self)
          end
        },
        proc { |child|
          case child
            when FormatNode
              child.attrs[:finish].call(child, self)
          end
        }) { |child|
          draw_node(child)
        }
      end
    }
  end
 
  def get_val(str)
    separators = [':', '.', ',']
    val = nil
    vp = []
    sp = []
    loop do
      tmpstr = eval('str' + sp.map{|i|'['+i.to_s+']'}.join(''))
      if tmpstr.nil?
        sp.pop
        vp.pop
        if vp.length == 0
          break
        end
        sp[-1] += 1
        vp[-1] += 1
        next
      end
      if tmpstr.index(separators[sp.length]) != nil
        begin
          eval('val' + vp.map{|i|'['+i.to_s+']'}.join('') + "=eval('#{tmpstr}')")
          if sp.length > 0 and sp.last < eval('str' + sp[0..sp.length - 2].map{|i|'['+i.to_s+']'}.join('')).length
            sp[-1] += 1
            vp[-1] += 1
          else
            break if vp.length == 0
            vp.pop
            sp.pop
            break if vp.length == 0
            sp[-1] += 1
            vp[-1] += 1
          end
        rescue Exception
          eval('str' + sp.map{|i|'['+i.to_s+']'}.join('') + '=tmpstr.split(separators[sp.length])')
          eval('val' + vp.map{|i|'['+i.to_s+']'}.join('') + '=[]')
          vp.push(0)
          sp.push(0)
        end
      else
        begin
          eval('val' + vp.map{|i|'['+i.to_s+']'}.join('') + "=eval('#{tmpstr}')")
        rescue Exception
          eval('val' + vp.map{|i|'['+i.to_s+']'}.join('') + '=tmpstr')
        end
        etxt = 'str'
        etxt += sp[0..sp.length - 2].map{|i|'['+i.to_s+']'}.join('') if sp.length > 1
        if sp.length > 0 and sp.last < eval(etxt).length
          sp[-1] += 1
          vp[-1] += 1
        else
          break if vp.length == 0
          vp.pop
          sp.pop
          break if vp.length == 0
          sp[-1] += 1
          vp[-1] += 1
        end
      end
    end
    val
  end
 
  def get_el(path)
    el = @dom[path[0]]
    if path.length > 1
      path[1..path.length - 1].each { |tmp|
        el = el.children[tmp]
      }
    end
    el
  end
end

class Element
  @@id = 0
  attr_accessor :children, :el_type, :attrs, :el_id, :parent
 
  def initialize(el_type, attrs, parent)
    @children = []
    @el_type = el_type.downcase
    @attrs = attrs
    @parent = parent
    @contents = ''
    @el_id = @@id
    @@id += 1
  end
 
  def get_val(str)
    separators = [':', '.', ',']
    val = nil
    vp = []
    sp = []
    loop do
      tmpstr = eval('str' + sp.map{|i|'['+i.to_s+']'}.join(''))
      if tmpstr.nil?
        sp.pop
        vp.pop
        if vp.length == 0
          break
        end
        sp[-1] += 1
        vp[-1] += 1
        next
      end
      if tmpstr.index(separators[sp.length]) != nil
        begin
          eval('val' + vp.map{|i|'['+i.to_s+']'}.join('') + "=eval('#{tmpstr}')")
          if sp.length > 0 and sp.last < eval('str' + sp[0..sp.length - 2].map{|i|'['+i.to_s+']'}.join('')).length
            sp[-1] += 1
            vp[-1] += 1
          else
            break if vp.length == 0
            vp.pop
            sp.pop
            break if vp.length == 0
            sp[-1] += 1
            vp[-1] += 1
          end
        rescue Exception
          eval('str' + sp.map{|i|'['+i.to_s+']'}.join('') + '=tmpstr.split(separators[sp.length])')
          eval('val' + vp.map{|i|'['+i.to_s+']'}.join('') + '=[]')
          vp.push(0)
          sp.push(0)
        end
      else
        begin
          eval('val' + vp.map{|i|'['+i.to_s+']'}.join('') + "=eval('#{tmpstr}')")
        rescue Exception
          eval('val' + vp.map{|i|'['+i.to_s+']'}.join('') + '=tmpstr')
        end
        etxt = 'str'
        etxt += sp[0..sp.length - 2].map{|i|'['+i.to_s+']'}.join('') if sp.length > 1
        if sp.length > 0 and sp.last < eval(etxt).length
          sp[-1] += 1
          vp[-1] += 1
        else
          break if vp.length == 0
          vp.pop
          sp.pop
          break if vp.length == 0
          sp[-1] += 1
          vp[-1] += 1
        end
      end
    end
    val
  end
 
  def block?
    return DesignHUD::BLOCK_ELS.include?(@el_type)
  end
 
  def inline?
    return !DesignHUD::BLOCK_ELS.include?(@el_type)
  end
 
  def self.reset_id
    @@id = 0
  end
 
  def parents
    if @parent != nil
      parents = [@parent]
      parent = @parent
      while parent.parent != nil
        parents.push(parent.parent)
        parent = parent.parent
      end
      return parents
    else
      return []
    end
  end
 
  def last_block
    if @parent != nil
      last = self
      parent = @parent
      while last.inline?
        last = parent
        parent = parent.parent
        break if parent.nil?
      end
      return last
    else
      return nil
    end
  end
 
  def last_line
    if @parent != nil
      last = self
      parent = @parent
      while last.el_type != 'ln'
        last = parent
        parent = parent.parent
        break if parent.nil?
      end
      return last
    else
      return nil
    end
  end
 
  def each_child(&block)
    block.call(self)
    path = [0]
    cur = self
    loop {
      child = cur.children[path.last]
      if child
        block.call(child)
        cur = child
        path.push(0)
      else
        cur = cur.parent
        path.pop
        break unless cur
        path[path.length - 1] += 1
      end
    }
  end
 
  def each_child_ex(start, finish, &block)
    path = [0]
    cur = self
    loop {
      child = cur.children[path.last]
      if child
        start.call(child)
        block.call(child)
        cur = child
        path.push(0)
      else
        finish.call(cur)
        cur = cur.parent
        path.pop
        break unless cur and path.length > 0
        path[path.length-1] += 1
      end
    }
  end
 
  def each_child_ex2(finish, &block)
    block.call(self)
    path = [0]
    cur = self
    loop {
      child = cur.children[path.last]
      if child
        block.call(child)
        cur = child
        path.push(0)
      else
        finish.call(cur)
        cur = cur.parent
        path.pop
        break unless cur
        path[path.length - 1] += 1
      end
    }
  end
 
  def parse_contents(text)
    @tmp_attrs = {}
    spattern = /<([\w\-]+)(?:\s*=\s*([\w\"\'\-\_\:\$\.\s]+))?((?:\s*\w+\s*=\s*[\w\"\'\-\_\:\$\.\s]+)*)>/
    epattern = /<\/[\w\-]+>/
    while text != ''
      s_ind = text.index(DesignHUD::SPATTERN)
      if s_ind != nil
        if s_ind > 0
          contents = text[0...s_ind]
          text = text[s_ind...text.length]
          element = TextNode.new('', self, contents)
          @children.push(element)
        end
        contents = nil
        el_name = $1
        el_val = $2 || ''
        el_attrs = {}
        tmp = $3.strip
        tmp.gsub(/(\w+)\s+=\s+([\w\"\'\-\:]+)/, "\\1=\\2").split(/\s+/).each { |el| el_attrs[el.split('=')[0].to_sym] = get_val(el.split('=')[1]) }
        el_val.gsub!(/[\'\"]/, '') if el_val
        el_attrs[:val] = el_val
        level, tmp_name, tmp_ind = 0, '', 0
        if !DesignHUD::NO_END.include?(el_name)
          text.sub!(DesignHUD::SPATTERN, '')
          last_ind = nil
          loop do
            tmp = [text.index(/(<#{el_name}(?:=[\w\"\'\-\:]+)?(?:\s*\w+=[\w\"\'\-\:]+)*>)/, tmp_ind)]
            tmp2 = tmp_ind
            (level+1).times {
              i = text.index(/<\/#{el_name}>/, tmp2)
              tmp2 = i + 2 + el_name.length unless i.nil?
            }
            tmp.push(tmp2 - 2 - el_name.length)
            if !tmp[1]
              contents = text[0...text.length]
              text = ''
            elsif !tmp[0]
              contents = text[0...tmp[1]]
              text = text[tmp[1] + 3 + el_name.length...text.length]
              level = [level - 1, 0].max
            elsif tmp[1] < tmp[0]
              contents = text[0...tmp[1]]
              text = text[tmp[1] + 3 + el_name.length...text.length]
              level = [level - 1, 0].max
            else
              level += 1 unless last_ind != nil and tmp[0] > last_ind[1]
              tmp_ind = tmp[0] + 2 + el_name.length
            end
            last_ind = tmp
            break if contents != nil
          end
          case el_name
          when 'ln'
            element = ContainerNode.new('ln', el_attrs, self, contents)
            @children.push(element)
          when 'b'
            element = FormatNode.new('b', self, contents, proc { |child, hud|
              if !@tmp_attrs[:tmpb]
                @tmp_attrs[:tmpb] = [hud.contents.font.bold]
              else
                @tmp_attrs[:tmpb].push(hud.contents.font.bold)
              end
              hud.contents.font.bold = true
            },
            proc { |child, hud|
              hud.contents.font.bold = @tmp_attrs[:tmpb].pop
            })
            @children.push(element)
          when 'i'
            element = FormatNode.new('i', self, contents, proc { |child, hud|
              if !@tmp_attrs[:tmpi]
                @tmp_attrs[:tmpi] = [hud.contents.font.italic]
              else
                @tmp_attrs[:tmpi].push(hud.contents.font.italic)
              end
              hud.contents.font.italic = true
            },
            proc { |child, hud|
              hud.contents.font.italic = @tmp_attrs[:tmpi].pop
            })
            @children.push(element)
          when 'c'
            element = FormatNode.new('c', self, contents, proc { |child, hud|
              if !hud.tmp_attrs[:tmpc]
                hud.tmp_attrs[:tmpc] = [hud.contents.font.color.clone]
              else
                hud.tmp_attrs[:tmpc].push(hud.contents.font.color.clone)
              end
              hud.contents.font.color = Color.new(*child.attrs[:val].split(':').map { |i| i.to_i })
            },
            proc { |child, hud|
              hud.contents.font.color = hud.tmp_attrs[:tmpc].pop
            }, el_val)
            @children.push(element)
          when 'font'
            element = FormatNode.new('font', self, contents, proc { |child, hud|
              if !@tmp_attrs[:tmpfn]
                hud.tmp_attrs[:tmpfn] = [[hud.contents.font.name.clone, hud.contents.font.size]]
              else
                hud.tmp_attrs[:tmpfn].push([hud.contents.font.name.clone, hud.contents.font.size])
              end
              if Font.exist?(child.attrs[:val].split(':')[0])
                hud.contents.font.name = child.attrs[:val].split(':')[0]
                hud.contents.font.size = child.attrs[:val].split(':')[1].to_i
              end
            },
            proc { |child, hud|
              hud.contents.font.name, hud.contents.font.size = *hud.tmp_attrs[:tmpfn].pop
            }, el_val)
            @children.push(element)
          when 'pos'
            element = FormatNode.new('pos', self, contents, proc { |child, hud|
            if !hud.tmp_attrs[:abs_pos]
                hud.tmp_attrs[:abs_pos] = [[child.attrs[:x], child.attrs[:y]]]
              else
                hud.tmp_attrs[:abs_pos].push([child.attrs[:x], child.attrs[:y]])
              end
            },
            proc { |child, hud|
              hud.tmp_attrs[:abs_pos].pop
              hud.tmp_attrs.delete(:abs_pos) if hud.tmp_attrs[:abs_pos].length == 0
            }, el_val, el_attrs)
            @children.push(element)
          when 'offset'
            element = FormatNode.new('offset', self, contents, proc { |child, hud|
              if !hud.tmp_attrs[:tmpofst]
                hud.tmp_attrs[:tmpofst] = [[hud.tmp_attrs[:ox], hud.tmp_attrs[:oy]]]
              else
                hud.tmp_attrs[:tmpofst].push([hud.tmp_attrs[:ox], hud.tmp_attrs[:oy]])
              end
              hud.tmp_attrs[:ox], hud.tmp_attrs[:oy] = child.attrs[:x], child.attrs[:y]
            },
            proc { |child, hud|
              hud.tmp_attrs[:ox], hud.tmp_attrs[:oy] = *hud.tmp_attrs[:tmpofst].pop
            }, el_val, el_attrs)
            @children.push(element)
          when 'right'
            element = FormatNode.new('right', self, contents, proc { |child, hud|
              if !hud.tmp_attrs[:tmpalign]
                hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]]
              else
                hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align])
              end
              hud.tmp_attrs[:align] = 2
              child.attrs[:align] = 2
            },
            proc { |child, hud|
              hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop
            }, el_val, el_attrs)
            @children.push(element)
          when 'center'
            element = FormatNode.new('center', self, contents, proc { |child, hud|
              if !hud.tmp_attrs[:tmpalign]
                hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]]
              else
                hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align])
              end
              hud.tmp_attrs[:align] = 1
              child.attrs[:align] = 1
            },
            proc { |child, hud|
              hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop
            }, el_val, el_attrs)
            @children.push(element)
          when 'left'
            element = FormatNode.new('left', self, contents, proc { |child, hud|
              if !hud.tmp_attrs[:tmpalign]
                hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]]
              else
                hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align])
              end
              hud.tmp_attrs[:align] = 0
              child.attrs[:align] = 0
            },
            proc { |child, hud|
              hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop
            }, el_val, el_attrs)
            @children.push(element)
          end
        else
          text.sub!(DesignHUD::SPATTERN, '')
          case el_name
          when 'hud'
            element = HudNode.new('hud', el_attrs, self)
            @children.push(element)
          when 'var'
            element = VariableNode.new(self, el_val)
            @children.push(element)
          when 'ico'
            element = IconNode.new(self, el_val)
            @children.push(element)
          when 'pic'
            element = PictureNode.new(self, el_val)
            @children.push(element)
          when 'bar'
            element = BarNode.new(self, el_attrs)
            @children.push(element)
          when 'shape'
            element = ShapeNode.new(self, el_attrs)
            @children.push(element)
          end
        end
      else
        contents = text
        text = ''
        element = TextNode.new('', self, contents)
        @children.push(element)
      end
    end
  end
end

class TextNode < Element
  def initialize(type, parent, text)
    super(type, {}, parent)
    @attrs[:val] = text
  end
end

class PictureNode < Element
  def initialize(parent, val)
    super('pic', {}, parent)
    @attrs[:bitmap] = RPG::Cache.picture(val)
  end
end

class IconNode < Element
  def initialize(parent, val)
    super('ico', {}, parent)
    @attrs[:bitmap] = RPG::Cache.icon(el_val).clone
  end
end

class VariableNode < Element
  def initialize(parent, name)
    super('var', {}, parent)
    @attrs[:expr] = DesignHUD.var_expression(name)
    @attrs[:val] = @attrs[:expr].call || 0
  end
 
  def val
    tmp = @attrs[:expr].call
    return (tmp.nil? ? 0 : tmp)
  end
end

class ShapeNode < Element
  def initialize(parent, attrs)
    super('shape', attrs, parent)
    @attrs[:width] ||= 50
    @attrs[:height] ||= 50
    bitmap = Bitmap.new(@attrs[:width], @attrs[:height])
    case @attrs[:type].to_s.downcase
    when 'rect'
      @attrs[:color] ||= [0, 0, 0]
      bitmap.fill_rect(bitmap.rect, Color.new(*@attrs[:color]))
    when 'hgrect'
      @attrs[:color] ||= [[0, 0, 0], [255, 255, 255]]
      tmp = @attrs[:color]
      bitmap.width.times { |i|
        r = tmp[0][0] * (bitmap.width - 1 - i) / (bitmap.width - 1) + tmp[1][0] * i / (bitmap.width - 1)
        g = tmp[0][1] * (bitmap.width - 1 - i) / (bitmap.width - 1) + tmp[1][1] * i / (bitmap.width - 1)
        b = tmp[0][2] * (bitmap.width - 1 - i) / (bitmap.width - 1) + tmp[1][2] * i / (bitmap.width - 1)
        bitmap.fill_rect(i, 0, 1, bitmap.height, Color.new(r, g, b))
      }
    when 'vgrect'
      @attrs[:color] ||= [[0, 0, 0], [255, 255, 255]]
      tmp = @attrs[:color]
      bitmap.height.times { |i|
        r = tmp[0][0] * (bitmap.height - 1 - i) / (bitmap.height - 1) + tmp[1][0] * i / (bitmap.height - 1)
        g = tmp[0][1] * (bitmap.height - 1 - i) / (bitmap.height - 1) + tmp[1][1] * i / (bitmap.height - 1)
        b = tmp[0][2] * (bitmap.height - 1 - i) / (bitmap.height - 1) + tmp[1][2] * i / (bitmap.height - 1)
        bitmap.fill_rect(0, i, bitmap.width, 1, Color.new(r, g, b))
      }
    end
    @attrs[:bitmap] = bitmap
  end
end

class BarNode < Element
  def initialize(parent, attrs)
    super('bar', attrs, parent)
    @attrs[:type] ||= :hp
    @attrs[:style] ||= 0
    @attrs[:shape] ||= 0
    @attrs[:cstyle] ||= [3, 2, 4, 2]
    @attrs[:lines] = false if @attrs[:lines].nil?
    @attrs[:neaten] = true if @attrs[:neaten].nil?
    @attrs[:dimensions] ||= [120, 16]
    @attrs[:text] = true if @attrs[:text].nil?
    @attrs[:actor] ||= 1
    @attrs[:actor] = $game_actors[@attrs[:actor]]
    @attrs[:val] = val
  end
 
  def val
    case @attrs[:type]
    when :hp
      return [@attrs[:actor].hp, @attrs[:actor].maxhp]
    when :mp
      return [@attrs[:actor].sp, @attrs[:actor].maxsp]
    when :exp
      return @attrs[:actor].exp
    when :lvl
      return @attrs[:actor].level
    end
  end
end

class HudNode < Element
  def initialize(type, attrs, parent = nil)
    super('hud', attrs, parent)
  end
end

class ContainerNode < Element
  def initialize(type, attrs, parent, contents)
    super(type, attrs, parent)
   
    parse_contents(contents)
  end
end

class FormatNode < Element
  def initialize(type, parent, contents, start, finish, val=nil, attrs = {})
    super(type, attrs, parent)
   
    parse_contents(contents)
    @attrs[:val] = val if val
    @attrs[:start] = start
    @attrs[:finish] = finish
  end
end

class Rect
  def intersect?(rect)
    return false if rect.width * rect.height == 0 or self.width * self.height == 0
    return true if (self.x.between?(rect.x - 1, rect.x + rect.width) or
                   (self.x + self.width).between?(rect.x - 1, rect.x + rect.width)) and
                   (self.y.between?(rect.y - 1, rect.y + rect.height) or
                   (self.y + self.height).between?(rect.y - 1, rect.y + rect.height))
    return false
  end
end

class Bitmap
  def get_colors(type, actor, cstyle)
    bc = Color.new(0, 0, 0)
    case type
    when :hp
      c1 = Color.new(200, 0, 0)
      c2 = Color.new(0, 200, 0)
      p = actor.hp * 100 / actor.maxhp
    when :mp
      c1 = Color.new(200, 0, 0)
      c2 = Color.new(0, 0, 200)
      p = actor.sp * 100 / actor.maxsp
    when :exp
      c1 = Color.new(170, 85, 0)
      c2 = Color.new(150, 150, 0)
      elist = actor.instance_variable_get(:@exp_list)
      if elist[actor.level + 1]
        nexp = elist[actor.level + 1] - elist[actor.level]
        cexp = actor.exp - elist[actor.level]
        p = (nexp <= 0 ? 100 : cexp * 100 / nexp)
      else
        p = 100
      end
    when :lvl
      c1 = Color.new(0, 85, 170)
      c2 = Color.new(150, 0, 150)
      p = actor.level * 100 / (actor.respond_to?(:final_level) ? actor.final_level : $data_actors[actor.id].final_level)
    end
    r = c2.red * p / 100 + c1.red * (100 - p) / 100
    g = c2.green * p / 100 + c1.green * (100 - p) / 100
    b = c2.blue * p / 100 + c1.blue * (100 - p) / 100
    pc1 = Color.new(r, g, b)
    r = c1.red * p / 100 + c2.red * (100 - p) / 100
    g = c1.green * p / 100 + c2.green * (100 - p) / 100
    b = c1.blue * p / 100 + c2.blue * (100 - p) / 100
    pc2 = Color.new(r, g, b)
    c = cstyle.map { |i|
      case i
      when 0 then c1
      when 1 then c2
      when 2 then bc
      when 3 then pc1
      when 4 then pc2
      when 5 then lcol(c1)
      when 6 then lcol(c2)
      when 7 then lcol(pc1)
      when 8 then lcol(pc2)
      when 9 then dcol(c1)
      when 10 then dcol(c2)
      when 11 then dcol(pc1)
      when 12 then dcol(pc2)
      end
    }
    return c, bc
  end
 
  def lcol(c)
    return Color.new(c.red * 1.3, c.green * 1.3, c.blue * 1.3)
  end
 
  def dcol(c)
    return Color.new(c.red * 0.7, c.green * 0.7, c.blue * 0.7)
  end
 
  def gradient_bar_back(color, shape, x, y, w, h, lines, extend = true)
    rw = w
    w += 10 if extend
    fill_rect(x, y, w, h, color)
    case shape
    when 0
      unless lines
        fill_rect(x + 1, y + 1, rw - 2, 1, Color.new(255, 255, 255))
        fill_rect(x + 1, y + h - 2, rw - 2, 1, Color.new(255, 255, 255))
        fill_rect(x + 1, y + 1, 1, h - 2, Color.new(255, 255, 255))
        fill_rect(x + w - 2, y + 1, 1, h - 2, Color.new(255, 255, 255))
      end
    when 1
      h.times { |i|
        fill_rect(x + i, y + i + 1, 1, h - 1 - i, Color.new(0, 0, 0, 0))
        fill_rect(x + w - 1 - i, y, 1, h - 1 - i, Color.new(0, 0, 0, 0))
        set_pixel(x + i + 1, y + i, Color.new(255, 255, 255)) unless i == 0 or i == h - 1
      }
      fill_rect(x + h, y + h - 2, rw - 2 - h, 1, Color.new(255, 255, 255))
    when 2
      fill_rect(x, y, w, 1, Color.new(0, 0, 0, 127))
      fill_rect(x, y + h - 1, w, 1, Color.new(0, 0, 0, 127))
      t = (h / 2.0).floor
      h.times { |i|
        v = ((t + 1) * (1 - Math.sin(Math::PI * (i + 1) / (h + 1)))).floor
        unless v == 0
          fill_rect(x, y + i, v, 1, Color.new(0, 0, 0, 0))
          fill_rect(x + w - v, y + i, v, 1, Color.new(0, 0, 0, 0))
        end
        unless [0, h - 1].include?(i)
          set_pixel(x + v, y + i, Color.new(0, 0, 0, 85))
          set_pixel(x + w - v, y + i, Color.new(0, 0, 0, 85))
        end
      }
    when 3
      h.times { |i|
        fill_rect(x + i, y, 1, h - 1 - i, Color.new(0, 0, 0, 0))
        fill_rect(x + w - 1 - i, y + i + 1, 1, h - 1 - i, Color.new(0, 0, 0, 0))
        set_pixel(x + h - i, y + i, Color.new(255, 255, 255)) unless i == 0 or i == h - 1
      }
      fill_rect(x + 2, y + h - 2, w - (extend ? 7 : 2) - h, 1, Color.new(255, 255, 255))
      #w -= h - 1
    end
    if extend
      tmp = self.clone
      fill_rect(x + w - 20, y, 20, h, Color.new(0, 0, 0, 0))
      20.times { |i|
        blt(x + w - 20 + i, y, tmp, Rect.new(x + w - 20 + i, y, 1, h), 255 * (19 - i) / 19)
      }
    end
  end
 
  def gradient_bar_front(colors, bgcolor, style, shape, sx, sy, w, h, rate)
    sbmap = self.clone
    t = (h / 2.0).ceil
    if style.between?(0, 6)
      h.times { |i|
        rect = Rect.new(sx, sy + i, w * rate, 1)
        case shape
        when 1
          rect.width -= h - 1
          rect.x += i
        when 2
          t = (h / 2.0).floor
          v = ((t + 1) * (1 - Math.sin(Math::PI * (i + 1) / (h + 1)))).floor
          rect.x += v
          rect.width -= 2 * v
        when 3
          rect.width -= h - 1
          rect.x += h - 1 - i
        end
        case style
        when 0
          r = colors[1].red * i / (h - 1) + colors[0].red * (h - 1 - i) / (h - 1)
          g = colors[1].green * i / (h - 1) + colors[0].green * (h - 1 - i) / (h - 1)
          b = colors[1].blue * i / (h - 1) + colors[0].blue * (h - 1 - i) / (h - 1)
        when 1
          t = (h / 2.0).ceil
          if i >= t
            d = i - t + (h % 2 == 1 ? 1 : 0)
          else
            d = t - i - 1
          end
          t -= 1 if h % 2 == 1
          r = colors[1].red * d / (t) + colors[0].red * (t - d) / (t)
          g = colors[1].green * d / (t) + colors[0].green * (t - d) / (t)
          b = colors[1].blue * d / (t) + colors[0].blue * (t - d) / (t)
        when 2
          s = Math.sin(Math::PI * i / (h - 1) / 2)
          r = colors[1].red * s + colors[0].red * (1 - s)
          g = colors[1].green * s + colors[0].green * (1 - s)
          b = colors[1].blue * s + colors[0].blue * (1 - s)
        when 3
          s = 2 * Math.sin(Math::PI * i / (h - 1) / 6)
          r = colors[1].red * s + colors[0].red * (1 - s)
          g = colors[1].green * s + colors[0].green * (1 - s)
          b = colors[1].blue * s + colors[0].blue * (1 - s)
        when 4
          s = 1 - 2 * Math.sin(Math::PI * i / (h - 1) / 6)
          r = colors[0].red * s + colors[1].red * (1 - s)
          g = colors[0].green * s + colors[1].green * (1 - s)
          b = colors[0].blue * s + colors[1].blue * (1 - s)
        when 5
          s = Math.sin(Math::PI * i / (h - 1))
          r = colors[0].red * s + colors[1].red * (1 - s)
          g = colors[0].green * s + colors[1].green * (1 - s)
          b = colors[0].blue * s + colors[1].blue * (1 - s)
        when 6
          s = Math.sin(Math::PI / 2 + Math::PI * i / (h - 1)).abs
          r = colors[1].red * s + colors[0].red * (1 - s)
          g = colors[1].green * s + colors[0].green * (1 - s)
          b = colors[1].blue * s + colors[0].blue * (1 - s)
        end
        fill_rect(rect, Color.new(r, g, b))
      }
    elsif style.between?(7, 13)
      amnt = 8
      case shape
      when 1, 3
        w -= h - 1
      end
      at = (w.to_f * rate / amnt).ceil
      h.times { |i|
        at.times { |e|
          rect = Rect.new(sx + amnt * e, sy + i, amnt, 1)
          dw = w * rate
          case shape
          when 0
            rect.width = [rect.width, sx + dw - rect.x].min
          when 1
            rect.x += i
            rect.width = [rect.width, sx + dw + i - rect.x].min
          when 2
            v = ((t + 1) * (1 - Math.sin(Math::PI * (i + 1) / (h + 1)))).floor
            rect.x += v if e == 0
            tmp = 0
            if e == 0
              rect.width -= v
              tmp += v
            end
            if e == at - 1
              rect.width -= v
              tmp += v
            end
            rect.width = [rect.width, sx + dw - tmp - rect.x].min
          when 3
            rect.x += h - 1 - i
            rect.width = [rect.width, sx + dw + h - 1 - i - rect.x].min
          end
          tmpcolors = (e % 2 == 0 ? colors[0..1] : colors[2..3])
          case style
          when 7
            r = tmpcolors[1].red * i / (h - 1) + tmpcolors[0].red * (h - 1 - i) / (h - 1)
            g = tmpcolors[1].green * i / (h - 1) + tmpcolors[0].green * (h - 1 - i) / (h - 1)
            b = tmpcolors[1].blue * i / (h - 1) + tmpcolors[0].blue * (h - 1 - i) / (h - 1)
          when 8
            if i >= t
              d = i - t + (h % 2 == 1 ? 1 : 0)
            else
              d = t - i - 1
            end
            t -= 1 if h % 2 == 1
            r = tmpcolors[1].red * d / (t) + tmpcolors[0].red * (t - d) / (t)
            g = tmpcolors[1].green * d / (t) + tmpcolors[0].green * (t - d) / (t)
            b = tmpcolors[1].blue * d / (t) + tmpcolors[0].blue * (t - d) / (t)
          when 9
            s = Math.sin(Math::PI * i / (h - 1) / 2)
            r = tmpcolors[1].red * s + tmpcolors[0].red * (1 - s)
            g = tmpcolors[1].green * s + tmpcolors[0].green * (1 - s)
            b = tmpcolors[1].blue * s + tmpcolors[0].blue * (1 - s)
          when 10
            s = 2 * Math.sin(Math::PI * i / (h - 1) / 6)
            r = tmpcolors[1].red * s + tmpcolors[0].red * (1 - s)
            g = tmpcolors[1].green * s + tmpcolors[0].green * (1 - s)
            b = tmpcolors[1].blue * s + tmpcolors[0].blue * (1 - s)
          when 11
            s = 1 - 2 * Math.sin(Math::PI * i / (h - 1) / 6)
            r = tmpcolors[0].red * s + tmpcolors[1].red * (1 - s)
            g = tmpcolors[0].green * s + tmpcolors[1].green * (1 - s)
            b = tmpcolors[0].blue * s + tmpcolors[1].blue * (1 - s)
          when 12
            s = Math.sin(Math::PI * i / (h - 1))
            r = tmpcolors[0].red * s + tmpcolors[1].red * (1 - s)
            g = tmpcolors[0].green * s + tmpcolors[1].green * (1 - s)
            b = tmpcolors[0].blue * s + tmpcolors[1].blue * (1 - s)
          when 13
            s = Math.sin(Math::PI / 2 + Math::PI * i / (h - 1)).abs
            r = tmpcolors[1].red * s + tmpcolors[0].red * (1 - s)
            g = tmpcolors[1].green * s + tmpcolors[0].green * (1 - s)
            b = tmpcolors[1].blue * s + tmpcolors[0].blue * (1 - s)
          end
          fill_rect(rect, Color.new(r, g, b))
        }
      }
    elsif style.between?(14, 34)
      case shape
      when 2
        t = (h / 2.0).floor
        v = []
        h.times { |i|
          v.push(((t + 1) * (1 - Math.sin(Math::PI * (i + 1) / (h + 1)))).floor)
        }
      end
      dw = (w * rate).to_i
      dw.times { |i|
        rect = Rect.new(sx + i, sy, 1, h)
        case shape
        when 1
          if i < h
            rect.height -= h - 1 - i
          end
          if i > dw - h
            rect.y += i - dw + h
            rect.height -= i - dw + h
          end
        when 2
          if i <= v.max
            ind = v.index(v.detect { |val| val <= i })
            rect.y += ind
            rect.height -= ind * 2
          elsif w - 1 - i <= v.max
            ind = v.index(v.detect { |val| val <= w - 1 - i })
            rect.y += ind
            rect.height -= ind * 2
          end
        when 3
          if i < h
            rect.y += h - 1 - i
            rect.height -= h - 1 - i
          end
          if i > w - h
            rect.height -= i - w + h
          end
        end
        case style
        when 14, 17, 20, 23, 26, 29, 32
          r = colors[1].red * i / (w - 1) + colors[0].red * (w - 1 - i) / (w - 1)
          g = colors[1].green * i / (w - 1) + colors[0].green * (w - 1 - i) / (w - 1)
          b = colors[1].blue * i / (w - 1) + colors[0].blue * (w - 1 - i) / (w - 1)
        when 15, 18, 21, 24, 27, 30, 33
          s = Math.sin(Math::PI * i / (w - 1) / 2)
          r = colors[1].red * s + colors[0].red * (1 - s)
          g = colors[1].green * s + colors[0].green * (1 - s)
          b = colors[1].blue * s + colors[0].blue * (1 - s)
        when 16, 19, 22, 25, 28, 31, 34
          s = 2 * Math.sin(Math::PI * i / (w - 1) / 6)
          r = colors[1].red * s + colors[0].red * (1 - s)
          g = colors[1].green * s + colors[0].green * (1 - s)
          b = colors[1].blue * s + colors[0].blue * (1 - s)
        end
        fill_rect(rect, Color.new(r, g, b))
      }
      if style.between?(17, 34)
        bmap = self.clone
        h.times { |i|
          case style
          when 17, 18, 19
            t = (h / 2.0).ceil
            if i >= t
              d = i - t + (h % 2 == 1 ? 1 : 0)
            else
              d = t - i - 1
            end
            t -= 1 if h % 2 == 1
            a = 255 * (t - d) / t
          when 20, 21, 22
            s = Math.sin(Math::PI * i / (h - 1))
            a = 255 * s
          when 23, 24, 25
            s = 1 - Math.sin(Math::PI / 2 + Math::PI * i / (h - 1)).abs
            a = 255 * s
          when 26, 27, 28
            a = 255 * (h - 1 - i) / (h - 1)
          when 29, 30, 31
            s = 1 - Math.sin(Math::PI * i / (h - 1) / 2)
            a = 255 * s
          when 32, 33, 34
            s = 1 - 2 * Math.sin(Math::PI * i / (h - 1) / 6)
            a = 255 * s
          end
          r = Rect.new(sx, sy + i, w, 1)
          blt(r.x, r.y, sbmap, r)
          blt(r.x, r.y, bmap, r, a)
        }
      end
    end
    case shape
    when 2
      bmap = self.clone
      t.times { |i|
        r = Rect.new(sx + i, sy, 1, h)
        blt(r.x, r.y, sbmap, r)
        blt(r.x, r.y, bmap, r, 255 * i / t)
        r = Rect.new(sx + w * rate - 1 - i, sy, 1, h)
        blt(r.x, r.y, sbmap, r)
        blt(r.x, r.y, bmap, r, 255 * i / t)
        bmap = self.clone
      }
    end
  end
 
  def gradient_bar(type, style, shape, cstyle, actor, x, y, w, h, text = false, lines = false, fix = true)
    colors, bgcolor = get_colors(type, actor, cstyle)
    if fix
      case shape
      when 0
        w = (w - (lines ? 2 : 4)) / 8 * 8 + (lines ? 2 : 4)
      when 1
        w = (w - 3 - h + 1)
        w = w / 8 * 8
        w = w + h - 1 + 3
      when 2
        w = (w - 4) / 8 * 8 + 4
      when 3
        w = (w - 2 - h + 1)
        w = w / 8 * 8
        w = w + h - 1 + 2
      end
    end
    gradient_bar_back(bgcolor, shape, x, y, w, h, lines, false)
    case shape
    when 0
      x += (lines ? 1 : 2)
      y += (lines ? 1 : 2)
      w -= (lines ? 2 : 4)
      h -= (lines ? 2 : 4)
    when 1
      x += 3
      y += 1
      w -= 6
      h -= 3
    when 2
      x += 2
      y += 2
      w -= 4
      h -= 4
    when 3
      x += 3
      y += 1
      w -= 5
      h -= 3
    end
    case type
    when :hp
      rate = actor.hp.to_f / actor.maxhp
      str = actor.hp.to_s + '/' + actor.maxhp.to_s
    when :mp
      rate = actor.sp.to_f / actor.maxsp
      str = actor.sp.to_s + '/' + actor.maxsp.to_s
    when :exp
      elist = actor.instance_variable_get(:@exp_list)
      if elist[actor.level + 1]
        nexp = elist[actor.level + 1] - elist[actor.level]
        cexp = actor.exp - elist[actor.level]
        rate = (nexp <= 0 ? 1 : cexp.to_f / nexp)
      else
        rate = 1
      end
      str = actor.exp_s + '/' + actor.next_exp_s
    when :lvl
      rate = actor.level.to_f / (actor.respond_to?(:final_level) ? actor.final_level : $data_actors[actor.id].final_level)
      str = actor.level.to_s + '/' + (actor.respond_to?(:final_level) ? actor.final_level : $data_actors[actor.id].final_level).to_s
    end
    bgcolors = get_bgcolors(type, cstyle)
    gradient_bar_front(bgcolors, bgcolor, style, shape, x, y, w, h, 1)
    gradient_bar_front(colors, bgcolor, style, shape, x, y, w, h, rate)
    draw_lines(bgcolor, shape, x, y, w, h) if lines
    psize, pcol = font.size, font.color
    font.size = h
    font.color = Color.new(255, 255, 255)
    draw_text(x, y, w, h, str, 1) if text
    font.size, font.color = psize, pcol
  end
 
  def draw_lines(color, shape, x, y, w, h)
    case shape
    when 1, 3
      w -= h - 1
    when 2
      t = (h / 2.0).floor
      v = []
      h.times { |i|
        v.push(((t + 1) * (1 - Math.sin(Math::PI * (i + 1) / (h + 1)))).floor)
      }
    end
    w.times { |i|
      if [0, 7].include?(i % 8)
        case shape
        when 0
          fill_rect(x + i, y, 1, h, color)
        when 1
          h.times { |e|
            set_pixel(x + i + e, y + e, color)
          }
        when 2
          if i <= v.max
            ind = v.index(v.detect { |val| val <= i })
          elsif w - 1 - i <= v.max
            ind = v.index(v.detect { |val| val <= w - 1 - i })
          else
            ind = 0
          end
          fill_rect(x + i, y + ind, 1, h - (ind) * 2, color)
        when 3
          h.times { |e|
            set_pixel(x + i + h - 1 - e, y + e, color)
          }
        end
      end
    }
  end
 
  def get_bgcolors(type, cstyle)
    bc = Color.new(0, 0, 0)
    case type
    when :hp
      c1 = Color.new(100, 30, 30)
      c2 = Color.new(30, 100, 30)
    when :mp
      c1 = Color.new(100, 30, 30)
      c2 = Color.new(30, 30, 100)
    when :exp
      c1 = Color.new(100, 47, 22)
      c2 = Color.new(80, 80, 22)
    when :lvl
      c1 = Color.new(22, 47, 100)
      c2 = Color.new(80, 22, 80)
    end
    c = cstyle.map { |i|
      case i
      when 0 then c1
      when 1 then c2
      when 2 then bc
      when 3 then c2
      when 4 then c1
      when 5 then lcol(c1)
      when 6 then lcol(c2)
      when 7 then lcol(c2)
      when 8 then lcol(c1)
      when 9 then dcol(c1)
      when 10 then dcol(c2)
      when 11 then dcol(c2)
      when 12 then dcol(c1)
      end
    }
    return c
  end
end


class Scene_Map
  alias tdks_hud_main main
  def main
    @hud = HUD.new(DesignHUD::HUD)
    tdks_hud_main
    @hud.dispose
  end
 
  alias tdks_hud_updt update
  def update
    @hud.update
    tdks_hud_updt
  end
end



Instructions

Just set up the HUD text and start creating amazing HUDs. And read about the different elements in the script.


Compatibility

None known.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

None.
7
Here's a pack of about 80 transitions I made for RMXP. They're pretty simple, and just are gradients with gimp filters applied to them.
https://www.box.com/s/j46l15k2ual61s0c7su7

And some examples of the cooler ones:
Spoiler: ShowHide






8
RMXP Script Database / [XP] Cool Damage
January 23, 2013, 07:43:11 pm
Cool Damage
Authors: ThallionDarkshine
Version: 0.4
Type: Graphical Damage Add-on
Key Term: Battle Add-on



Introduction

As you all should have noticed, the default damage display in battles is pretty pathetic. If any of you have seen Blizz's game Chaos Project, then you'll get what I mean when I say that you can never appreciate the default again after playing CP. So, I made my own version of it, complete with four different text appearance styles and four different text disappearance styles. I also included a few other features, including changing the font properties of the text.


Features


  • Gives damage text cool animation!

  • Choose from six different appearance styles and four different disappearance styles.

  • Customize font properties of the text.




Screenshots

Spoiler: ShowHide

Spoiler: ShowHide



Demo

None yet.


Script

Spoiler: ShowHide

module RPG
  class Sprite
    # whether to use the cool damage (set it to false if you never wanted this
    #   script)
    COOL_DAMAGE = true
    # the font name of the damage text
    DAMAGE_FONT_NAME = "Times New Roman"
    # the font size of the damage text
    DAMAGE_FONT_SIZE = 32
    # whether to make the damage text bold
    DAMAGE_FONT_BOLD = true
    # whether to make the damage text italic
    DAMAGE_FONT_ITALIC = true
    # the colors for the damage text
    #   directions for setup will be found in the script topic on Chaos Project
    DAMAGE_COLORS = [
      [proc { |val, crit| val.is_a?(Numeric) and val < 0 }, Color.new(176, 255, 144)],
      [proc { |val, crit| crit }, Color.new(255, 0, 0)]
    ]
    # the horizontal and vertical distance between the letters at the end of
    #   their movement
    LETTER_SEPARATION = [0, 5]
    # how much the damage's actual position can differ from the normal position
    #   (can help with scripts that show multiple damage numbers in quick
    #   succession)
    POSITION_VARIANCE = [0..0, 0..0]
    # the duration of the appearance of the damage
    APPEAR_DURATION = 20
    # the duration of the fading in of the damage
    #   note - should be less than APPEAR_DURATION
    APPEAR_FADE_DURATION = 5
    # the amount of frames of movement between each letter
    APPEAR_OFFSET = 5
    # the amplitude of the letters' movement
    #   suggested values
    #     modes 0 and 1
    #       5 - 15
    #     modes 2, 4
    #       -0.5 - 0 or 0.0 - 2
    #     mode 3
    #       0.5 - 1.5
    #     mode 4
    #       0.5 - 2.0
    #     mode 5
    #       Color.new(FLASH_RED, FLASH_GREEN, FLASH_BLUE, FLASH_AMOUNT)
    APPEAR_AMP = 10
    # how far the letters should rotate when appearing (degrees)
    APPEAR_ANGLE = 0
    # the appearance mode
    #  letter animations:
    #   0 - float
    #   1 - bounce
    #   2 - sink in
    #   3 - 3d-spin
    #  non-letter animations:
    #   4 - sink in
    #   5 - flash (can be used with a color with an alpha of 0 to achieve some
    #     cool effects by setting APPEAR_ANGLE)
    APPEAR_MODE = 0
    # whether to have the letters enter in a random order
    # note - no effect on non-letter animations
    APPEAR_RANDOM = false
    # how long to show the letters before they begin to disappear
    WAIT_DURATION = 10
    # the duration of the disappearance of the damage
    DISAPPEAR_DURATION = 15
    # the duration of the fading out of the damage
    #   note - should be less than DISAPPEAR_DURATION
    DISAPPEAR_FADE_DURATION = 12
    # the amount of frames of movement between each letter
    DISAPPEAR_OFFSET = 2
    # the amplitude of the letters' movement
    #   suggested values
    #     modes 0 and 1
    #       5 - 15
    #     mode 2
    #       1 - 2
    #     mode 3
    #       0.5 - 1.5
    DISAPPEAR_AMP = 1.5
    # how far the letters should rotate when disappearing (degrees)
    DISAPPEAR_ANGLE = 100
    # which way to have the letters disappear
    #  letter animations:
    #   0 - float
    #   1 - bounce
    #   2 - fall away
    #   3 - 3d-spin
    DISAPPEAR_MODE = 2
    # whether to have the letters exit in a random order
    DISAPPEAR_RANDOM = false
   
    alias tdks_dmg_txt_init initialize
    def initialize(viewport = nil)
      tdks_dmg_txt_init(viewport)
      @_cdamage_duration = 0
    end
   
    alias tdks_dmg_txt_dmg damage
    def damage(value, critical)
      unless RPG::Sprite::COOL_DAMAGE
        return tdks_dmg_txt_dmg(value, critical)
      end
      dispose_damage
      if value.is_a?(Numeric)
        damage_string = value.abs.to_s
      else
        damage_string = value.to_s
      end
      obmp = bitmap
      bmp = Bitmap.new(1, 1)
      bmp.font.name = RPG::Sprite::DAMAGE_FONT_NAME
      bmp.font.size = RPG::Sprite::DAMAGE_FONT_SIZE
      bmp.font.bold = RPG::Sprite::DAMAGE_FONT_BOLD
      bmp.font.italic = RPG::Sprite::DAMAGE_FONT_ITALIC
      bmp.font.color.set(0, 0, 0)
      @_cdamage_sprites = []
      size = bmp.text_size(damage_string)
      usep_bmp = Bitmap.new(size.width + 2 + RPG::Sprite::LETTER_SEPARATION[0] * (damage_string.length - 1), size.height + 2 + RPG::Sprite::LETTER_SEPARATION[1] * (damage_string.length - 1))
      x = 0
      y = 0
      rx = (160 - size.width) / 2 - 80
      pv = RPG::Sprite::POSITION_VARIANCE.map { |i| i.first + rand(i.last - i.first + 1) }
      damage_string = damage_string.split('')
      ofsx = damage_string.length * RPG::Sprite::LETTER_SEPARATION[0] / 2
      ofsy = damage_string.length * RPG::Sprite::LETTER_SEPARATION[1] / 2
      damage_string.each_with_index { |i, ind|
        r = bmp.text_size(i)
        r.x += 1
        r.y += 1
        bitmap = Bitmap.new(r.width+2, r.height+2)
        bitmap.font = bmp.font
        usep_bmp.font = bmp.font
        (-1..1).each{|v|
          next if v==0
          bitmap.draw_text(r.x + v, r.y, r.width, r.height, i, 1)
          bitmap.draw_text(r.x, r.y + v, r.width, r.height, i, 1)
          usep_bmp.draw_text(x + RPG::Sprite::LETTER_SEPARATION[0] * ind + 1 + v, RPG::Sprite::LETTER_SEPARATION[1] * ind + 1, r.width, r.height, i, 1)
          usep_bmp.draw_text(x + RPG::Sprite::LETTER_SEPARATION[0] * ind + 1, RPG::Sprite::LETTER_SEPARATION[1] * ind + 1 + v, r.width, r.height, i, 1)
        }
        bitmap.font.color.set(255, 255, 255)
        usep_bmp.font.color.set(255, 255, 255)
        RPG::Sprite::DAMAGE_COLORS.each { |col|
          if col[0].call(value, critical)
            bitmap.font.color = col[1]
            usep_bmp.font.color = col[1]
          end
        }
        bitmap.draw_text(r, i, 1)
        usep_bmp.draw_text(x + RPG::Sprite::LETTER_SEPARATION[0] * ind + 1, RPG::Sprite::LETTER_SEPARATION[1] * ind + 1, r.width, r.height, i, 1)
        sprite = ::Sprite.new(self.viewport)
        sprite.z = 3000
        sprite.bitmap = bitmap
        case RPG::Sprite::APPEAR_MODE
        when 0,1, 3:
          sprite.ox = bitmap.width / 2
          sprite.oy = bitmap.height / 2
        when 2:
          sprite.ox = 0
          sprite.oy = bitmap.height
        end
        sprite.x = self.x + rx + x + sprite.ox + RPG::Sprite::LETTER_SEPARATION[0] * ind - ofsx + pv[0]
        sprite.y = self.y - self.oy / 2 - 20 + 12 + sprite.oy + RPG::Sprite::LETTER_SEPARATION[1] * ind - ofsy + pv[1]
        sprite.opacity = 0
        x += r.width
        @_cdamage_sprites.push(sprite)
      }
      sprite = Sprite.new(self.viewport)
      sprite.bitmap = usep_bmp
      case RPG::Sprite::APPEAR_MODE
      when 4:
        sprite.ox = sprite.bitmap.width / 2
        sprite.oy = sprite.bitmap.height / 2
      end
      sprite.x = self.x + rx - ofsx + sprite.ox + pv[0]
      sprite.y = self.y - self.oy / 2 - 20 + 12 - ofsy + sprite.oy + pv[1]
      sprite.opacity = 0
      sprite.z = 3000
      if RPG::Sprite::APPEAR_MODE.between?(0, 3)
        sprite.visible = false
      else
        @_cdamage_sprites.each{|i|i.visible=false}
      end
      @_cdamage_sprites.push(sprite)
     
      l = @_cdamage_sprites.length
      tmp = Array.new(l) { |i| i }
      @_cdamage_rind = Array.new(l) { v=tmp[rand(tmp.length)];tmp.delete(v);v }
      @_cdamage_spos = @_cdamage_sprites.map { |i| [i.x, i.y] }
      @_cdamage_duration = RPG::Sprite::APPEAR_DURATION + RPG::Sprite::WAIT_DURATION + RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ((RPG::Sprite::DISAPPEAR_MODE.between?(0, 3) ? RPG::Sprite::DISAPPEAR_OFFSET : 0) + (RPG::Sprite::APPEAR_MODE.between?(0, 3) ? RPG::Sprite::APPEAR_OFFSET : 0))
      @_damage_duration = 0
    end
   
    alias tdks_dmg_txt_effect? effect?
    def effect?
      return tdks_dmg_txt_effect?() || @_cdamage_duration > 0
    end
   
    alias tdks_dmg_txt_updt update
    def update
      tdks_dmg_txt_updt
      if @_cdamage_duration > 0
        @_cdamage_duration -= 1
        amnt = 50
        ofs = RPG::Sprite::APPEAR_OFFSET
        ofs2 = RPG::Sprite::DISAPPEAR_OFFSET
        l = @_cdamage_sprites.length - 1
        if @_cdamage_duration > RPG::Sprite::DISAPPEAR_DURATION + RPG::Sprite::WAIT_DURATION + (l - 1) * (RPG::Sprite::DISAPPEAR_MODE.between?(0, 3) ? ofs2 : 0)
          frames = @_cdamage_duration - RPG::Sprite::DISAPPEAR_DURATION - RPG::Sprite::WAIT_DURATION - (l - 1) * (RPG::Sprite::DISAPPEAR_MODE.between?(0, 3) ? ofs2 : 0)
          if RPG::Sprite::APPEAR_MODE.between?(0, 3)
            @_cdamage_sprites[0...l].each_with_index { |i, ind|
              rind = ind
              ind = @_cdamage_rind[ind] if RPG::Sprite::APPEAR_RANDOM
              if RPG::Sprite::APPEAR_DURATION + (l - 1) * ofs - frames - ind * ofs > 0 and (l - 1 - ind) * ofs - frames < 0
                fadedur = [RPG::Sprite::APPEAR_FADE_DURATION, RPG::Sprite::APPEAR_DURATION].min
                if RPG::Sprite::APPEAR_DURATION + (l - 1) * ofs - frames - ind * ofs <= fadedur - 1
                  i.opacity = 255 * (RPG::Sprite::APPEAR_DURATION + (l - 1) * ofs - frames - ind * ofs + 1) / fadedur
                end
                case RPG::Sprite::APPEAR_MODE
                when 0:
                  s = 0-Math.cos(Math::PI * 3 * (RPG::Sprite::APPEAR_DURATION + (l - 1) * ofs - frames - ind * ofs) / (RPG::Sprite::APPEAR_DURATION - 1) / 2)
                  i.y = @_cdamage_spos[rind][1] - RPG::Sprite::APPEAR_AMP * s
                when 1:
                  s = 2 * Math.cos(Math::PI * 4 * (RPG::Sprite::APPEAR_DURATION + (l - 1) * ofs - frames - ind * ofs) / (RPG::Sprite::APPEAR_DURATION - 1) / 3).abs - 1
                  i.y = @_cdamage_spos[rind][1] - RPG::Sprite::APPEAR_AMP * s
                when 2:
                  i.zoom_x = i.zoom_y = RPG::Sprite::APPEAR_AMP - (RPG::Sprite::APPEAR_AMP - 1) * (RPG::Sprite::APPEAR_DURATION + (l - 1) * ofs - frames - ind * ofs).to_f / (RPG::Sprite::APPEAR_DURATION - 1)
                when 3:
                  angle = (360 * RPG::Sprite::APPEAR_AMP * (RPG::Sprite::APPEAR_DURATION + (l - 1) * ofs - frames - ind * ofs).to_f / (RPG::Sprite::APPEAR_DURATION - 1) - RPG::Sprite::APPEAR_AMP * 360) % 360
                  while angle < 0;angle += 360;end
                  if angle < 90
                    i.mirror = false
                    i.zoom_x = Math.sin((90 - angle) * Math::PI / 180)
                  elsif angle < 180
                    i.mirror = true
                    i.zoom_x = Math.sin((angle - 90) * Math::PI / 180)
                  elsif angle < 270
                    i.mirror = true
                    i.zoom_x = Math.sin((270 - angle) * Math::PI / 180)
                  else
                    i.mirror = false
                    i.zoom_x = Math.sin((angle - 270) * Math::PI / 180)
                  end
                end
                i.angle = (RPG::Sprite::APPEAR_ANGLE) * (RPG::Sprite::APPEAR_DURATION + (l - 1) * ofs - frames - ind * ofs) / (RPG::Sprite::APPEAR_DURATION - 1) - RPG::Sprite::APPEAR_ANGLE
              end
            }
          else
            sprite = @_cdamage_sprites[-1]
            sprite.angle = (RPG::Sprite::APPEAR_ANGLE) * (RPG::Sprite::APPEAR_DURATION - frames) / (RPG::Sprite::APPEAR_DURATION - 1) - RPG::Sprite::APPEAR_ANGLE
            fadedur = [RPG::Sprite::APPEAR_FADE_DURATION, RPG::Sprite::APPEAR_DURATION].min
            if RPG::Sprite::APPEAR_DURATION - frames <= fadedur - 1
              sprite.opacity = 255 * (RPG::Sprite::APPEAR_DURATION - frames + 1) / fadedur
            end
            case RPG::Sprite::APPEAR_MODE
            when 4:
              sprite.zoom_x = sprite.zoom_y = 1.0 + RPG::Sprite::APPEAR_AMP.to_f * (frames - 1) / RPG::Sprite::APPEAR_DURATION
            when 5:
              col = RPG::Sprite::APPEAR_AMP.clone
              col.alpha *= 1-(2 * (RPG::Sprite::APPEAR_DURATION + 1.0 - frames) / RPG::Sprite::APPEAR_DURATION - 1).abs
              sprite.color = col
            end
          end
          if @_cdamage_duration == RPG::Sprite::DISAPPEAR_DURATION + RPG::Sprite::WAIT_DURATION + (l - 1) * ofs2 + 1
            tmp = Array.new(l) { |e| e }
            @_cdamage_rind = Array.new(l) { v=tmp[rand(tmp.length)];tmp.delete(v);v }
            @_cdamage_sprites.each_with_index { |e, tind|
              oox = e.ox
              ooy = e.oy
              case RPG::Sprite::DISAPPEAR_MODE
              when 0,1,2:
                e.ox = 0
                e.oy = e.bitmap.height
              when 3:
                e.ox = e.bitmap.width / 2
                e.oy = e.bitmap.height / 2
              end
              e.x += e.ox - oox
              e.y += e.oy - ooy
              @_cdamage_spos[tind] = [e.x, e.y]
            }
            if RPG::Sprite::DISAPPEAR_MODE.between?(0, 3)
              @_cdamage_sprites[-1].visible = false
              @_cdamage_sprites[0...l].each { |i| i.visible = true;i.opacity = 255 }
            else
              @_cdamage_sprites[-1].visible = true
              @_cdamage_sprites[-1].opacity = 255
              @_cdamage_sprites[0...l].each { |i| i.visible = false }
            end
          end
        elsif @_cdamage_duration.between?(1, RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ofs2)
          @_cdamage_sprites[0...l].each_with_index { |i, ind|
            rind = ind
            ind = @_cdamage_rind[ind] if RPG::Sprite::DISAPPEAR_RANDOM
            frames = @_cdamage_duration
            if RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ofs2 - frames - ind * ofs2 > 0 and RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ofs2 - frames - ind * ofs2 < RPG::Sprite::DISAPPEAR_DURATION
              case RPG::Sprite::DISAPPEAR_MODE
              when 0:
                s = Math.sin(Math::PI * 2 * (RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ofs2 - frames - ind * ofs2) / (RPG::Sprite::DISAPPEAR_DURATION - 1) / 3)
                i.y = @_cdamage_spos[rind][1] - RPG::Sprite::DISAPPEAR_AMP * s
              when 1:
                s = Math.sin(Math::PI * (RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ofs2 - frames - ind * ofs2) / (RPG::Sprite::DISAPPEAR_DURATION - 1)).abs
                i.y = @_cdamage_spos[rind][1] + RPG::Sprite::DISAPPEAR_AMP * s
              when 2:
                i.y += RPG::Sprite::DISAPPEAR_AMP * 1.2 ** ((RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ofs2 - frames - ind * ofs2) / (RPG::Sprite::DISAPPEAR_DURATION - 1))
              when 3:
                angle = (360 * RPG::Sprite::DISAPPEAR_AMP * (RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ofs2 - frames - ind * ofs2).to_f / (RPG::Sprite::DISAPPEAR_DURATION - 1)) % 360
                while angle < 0;angle += 360;end
                if angle < 90
                  i.mirror = false
                  i.zoom_x = Math.sin((90 - angle) * Math::PI / 180)
                elsif angle < 180
                  i.mirror = true
                  i.zoom_x = Math.sin((angle - 90) * Math::PI / 180)
                elsif angle < 270
                  i.mirror = true
                  i.zoom_x = Math.sin((270 - angle) * Math::PI / 180)
                else
                  i.mirror = false
                  i.zoom_x = Math.sin((angle - 270) * Math::PI / 180)
                end
              end
              i.angle = (RPG::Sprite::DISAPPEAR_ANGLE) * (RPG::Sprite::DISAPPEAR_DURATION + (l - 1) * ofs2 - frames - ind * ofs2) / (RPG::Sprite::DISAPPEAR_DURATION - 1)
            end
            fadedur = [RPG::Sprite::DISAPPEAR_FADE_DURATION, RPG::Sprite::DISAPPEAR_DURATION].min
            if frames - (l - 1 - ind) * ofs2 < fadedur
              i.opacity = 255 * (frames - (l - 1 - ind) * ofs2) / fadedur
            end
          }
        end
        if @_cdamage_duration == 0
          @_cdamage_sprites.each{|i|i.bitmap.dispose;i.dispose}
        end
      end
    end
  end
end



Instructions

Configure the script and that's pretty much it. I'll put in a little on how to configure the damage color section soon.

And here are the instructions:
To add a new damage color, use this template:
[proc { |val, crit| CONDITION }, Color.new(RED, GREEN, BLUE[, ALPHA])]

The ALPHA/opacity parameter is optional. The condition is pretty easy to set up: all you have to do is insert a condition statement, such as:
val > 0

which would check if the damage was greater than 0.
Note - If you are going to use a condition to compare the damage to a number, add this to the start of your condition:
val.is_a?(Numeric) and 

Other than that, the parameters are all pretty much self-explanatory.


Compatibility

Should be compatible with anything that utilizes the default damage method.


Credits and Thanks


  • ThallionDarkshine

  • Blizz for the inspiration to write this




Author's Notes

Nothing
9
RMXP Script Database / [XP] Arrow Add-on
January 18, 2013, 09:17:45 pm
Arrow Add-on
Authors: ThallionDarkshine
Version: 0.2
Type: Battle Arrow Add-on
Key Term: Battle Add-on



Introduction

Have you ever looked at the default arrow animation system and thought, "this looks horrible". Well, this script allows you to customize many aspects of the arrows' animation, allowing you to make the arrows grow/shrink, bob, spin, fade, and colorize. You can also use the default option, though why would you, unless in conjunction with other animations.


Features


  • Give your battle arrows cool animations!

  • Use any combination of the animations.




Screenshots




Demo

No demo.


Script

Spoiler: ShowHide

module Arrow_Config
  # whether to use the normal animation, switching between the two arrow graphics
  NORMAL = true
  # how long each graphic should be shown for (RMXP default is 4)
  NORMAL_DURATION = 4
 
  # whether to use a 3D-Spin animation
  SPIN3D = false
  # the duration of one rotation (360 degrees)
  SPIN3D_DURATION = 120
 
  # whether to use a spin animation
  SPIN = false
  # the duration of one rotation (360 degrees)
  SPIN_DURATION = 120
 
  # whether to use a fade animation
  FADE = false
  # how long it should take to fade out fully
  FADE_DURATION = 10
  # how much to fade out
  FADE_AMOUNT = 85
 
  # whether to use a colorize animation
  COLORIZE = false
  # how long it should take to fully colorize
  COLORIZE_DURATION = 20
  # how much to colorize
  COLORIZE_AMOUNT = 127
  # the color to colorize with
  COLORIZE_COLOR = Color.new(255, 0, 0)
 
  # whether to use a grow/shrink animation
  BULGE = false
  # how long to take to fully grow/shrink
  BULGE_DURATION = 20
  # how much to grow (use a negative for shrinking)
  BULGE_AMOUNT = -0.2
 
  # whether to use a bob animation
  BOB = false
  # how much to bob
  BOB_AMOUNT = 3
  # the duration of one bob
  BOB_DURATION = 40
 
  # whether to use a rock animation
  ROCK = false
  # how much to rock (degrees)
  ROCK_AMOUNT = 10
  # the duration of one rock
  ROCK_DURATION = 20
 
  # whether to use a 3D-Rock animation
  ROCK3D = false
  # how much to rock(degrees)
  ROCK3D_AMOUNT = 60
  # the duration of one rock
  ROCK3D_DURATION = 40
 
  # whether to reset all the animations when the player switches between targets
  RESET_ON_SWITCH = false
end

class Arrow_Base
  alias tdks_arrow_init initialize
  def initialize(vpt)
    @oy = 0
    tdks_arrow_init(vpt)
    self.src_rect.set(128, 96, 32, 32)
    self.oy = 16
    @angle = 0
    @angle2d = 0
    @fade_count = 0
    @colorize_count = 0
    @bulge_count = 0
    @bob_count = 0
    @rock_count = Arrow_Config::ROCK_DURATION / 2
    @rock3d_count = Arrow_Config::ROCK3D_DURATION / 2
    @initialized = true
  end
 
  def update
    return if @initialized.nil?
    if (!@lind or @lind != @index) and Arrow_Config::RESET_ON_SWITCH == true
      @lind = @index
      @bob_count = @blink_count = @angle = @angle2d = @fade_count = @colorize_count = 0
      @rock_count = Arrow_Config::ROCK_DURATION / 2
      @rock3d_count = Arrow_Config::ROCK3D_DURATION / 2
    end
    if Arrow_Config::NORMAL
      # Update blink count
      @blink_count = (@blink_count + 1) % (Arrow_Config::NORMAL_DURATION * 2)
      # Set forwarding origin rectangle
      if @blink_count < Arrow_Config::NORMAL_DURATION
        self.src_rect.set(128, 96, 32, 32)
      else
        self.src_rect.set(160, 96, 32, 32)
      end
    end
   
    if Arrow_Config::SPIN3D
      @angle = (@angle + 1) % Arrow_Config::SPIN3D_DURATION
      angle = @angle * 360 / Arrow_Config::SPIN3D_DURATION
      if angle < 90
        self.zoom_x = Math.sin((90 - angle) * Math::PI / 180)
      elsif angle < 180
        self.mirror = true
        self.zoom_x = Math.sin((angle - 90) * Math::PI / 180)
      elsif angle < 270
        self.mirror = true
        self.zoom_x = Math.sin((270 - angle) * Math::PI / 180)
      else
        self.zoom_x = Math.sin((angle - 270) * Math::PI / 180)
      end
    end
   
    if Arrow_Config::ROCK3D
      @rock3d_count = (@rock3d_count + 1) % (2 * Arrow_Config::ROCK3D_DURATION)
      angle = (@rock3d_count < Arrow_Config::ROCK3D_DURATION ? 0-Arrow_Config::ROCK3D_AMOUNT+Arrow_Config::ROCK3D_AMOUNT * 2 * @rock3d_count / Arrow_Config::ROCK3D_DURATION : Arrow_Config::ROCK3D_AMOUNT - Arrow_Config::ROCK3D_AMOUNT * 2 * (@rock3d_count - Arrow_Config::ROCK3D_DURATION) / Arrow_Config::ROCK3D_DURATION)
      if angle < 90
        self.zoom_x = Math.sin((90 - angle) * Math::PI / 180)
      elsif angle < 180
        self.mirror = true
        self.zoom_x = Math.sin((angle - 90) * Math::PI / 180)
      elsif angle < 270
        self.mirror = true
        self.zoom_x = Math.sin((270 - angle) * Math::PI / 180)
      else
        self.zoom_x = Math.sin((angle - 270) * Math::PI / 180)
      end
    end
   
    if Arrow_Config::SPIN
      @angle2d = (@angle2d + 1) % Arrow_Config::SPIN_DURATION
      self.angle = @angle2d * 360 / Arrow_Config::SPIN_DURATION
    end
   
    if Arrow_Config::ROCK
      @rock_count = (@rock_count + 1) % (2 * Arrow_Config::ROCK_DURATION)
      self.angle = (@rock_count < Arrow_Config::ROCK_DURATION ? 0-Arrow_Config::ROCK_AMOUNT+Arrow_Config::ROCK_AMOUNT * 2 * @rock_count / Arrow_Config::ROCK_DURATION : Arrow_Config::ROCK_AMOUNT - Arrow_Config::ROCK_AMOUNT * 2 * (@rock_count - Arrow_Config::ROCK_DURATION) / Arrow_Config::ROCK_DURATION)
    end
   
    if Arrow_Config::FADE
      @fade_count = (@fade_count + 1) % (Arrow_Config::FADE_DURATION * 2)
      self.opacity = (@fade_count < Arrow_Config::FADE_DURATION ? 255 - Arrow_Config::FADE_AMOUNT * @fade_count / Arrow_Config::FADE_DURATION : 255 - Arrow_Config::FADE_AMOUNT * (Arrow_Config::FADE_DURATION * 2 - @fade_count) / Arrow_Config::FADE_DURATION)
    end
   
    if Arrow_Config::COLORIZE
      @colorize_count = (@colorize_count + 1) % (Arrow_Config::COLORIZE_DURATION * 2)
      self.color = Arrow_Config::COLORIZE_COLOR
      self.color.alpha = Arrow_Config::COLORIZE_AMOUNT * (@colorize_count < Arrow_Config::COLORIZE_DURATION ? @colorize_count.to_f / Arrow_Config::COLORIZE_DURATION : (Arrow_Config::COLORIZE_DURATION * 2 - @colorize_count.to_f) / Arrow_Config::COLORIZE_DURATION)
    end
   
    if Arrow_Config::BULGE
      @bulge_count = (@bulge_count + 1) % (Arrow_Config::BULGE_DURATION * 2)
      z = Arrow_Config::BULGE_AMOUNT * (@bulge_count < Arrow_Config::BULGE_DURATION ? @bulge_count.to_f / Arrow_Config::BULGE_DURATION : (Arrow_Config::BULGE_DURATION * 2 - @bulge_count.to_f) / Arrow_Config::BULGE_DURATION)
      self.zoom_x = self.zoom_y = 1 + z
    end
   
    if Arrow_Config::BOB
      @bob_count = (@bob_count + 1) % (Arrow_Config::BOB_DURATION)
      @oy = Arrow_Config::BOB_AMOUNT * Math.sin(@bob_count * Math::PI * 2 / Arrow_Config::BOB_DURATION)
    end
   
    # Update help text (update_help is defined by the subclasses)
    if @help_window != nil
      update_help
    end
  end
end

class Arrow_Enemy
  alias tdks_arrow_updt update
  def update
    tdks_arrow_updt
    self.y -= 48 - @oy
  end
end

class Arrow_Actor
  alias tdks_arrow_updt update
  def update
    tdks_arrow_updt
    self.y -= 48 - @oy
  end
end



Instructions

Just paste in the script and set up the configuration.


Compatibility

May not work with other scripts that modify the battle arrows.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

None.
10
RPG Maker Scripts / [VXA] Design a HUD (WIP)
December 29, 2012, 04:53:22 pm
Alright, so I'm working on a really customizable HUD framework. It uses a language sort of like HTML, only not as great. Right now I'm working on adding new features and elements and stuff like that, but if anyone would like to try it out, here's the script. This is basically a tool for non-scripters to create awesome-looking huds that look exactly how they want them to look.

I have finished the first version of the RMXP script, and it will be ported back to Ace soon. However, in the meantime you can check out the pure awesomeness of the new RMXP version, which I will be posting shortly.

Spoiler: ShowHide


module DesignHUD
 # This HUD uses an easy to use format for configuration much like html
 #   it has many types of tags, each inserting different information into the
 #   HUD, such as icons, hp/sp/xp bars, and different information about the
 #   actors.
 #
 # Tags:
 #
 #  Formatting Elements:
 #   * <i></i>
 #     - italicizes text
 #   * <b></b>
 #     - bolds text
 #   * <c=R:G:B[:A]></c>
 #     - changes the color to Color.new(R, G, B, A) (A is unnecessary)
 #   * <font=NAME:SIZE></font>
 #     - changes the font to NAME and the font size to SIZE
 #  Graphical Elements:
 #   * <ico=X:Y>
 #     - inserts the icon in the iconset with an offset of X, Y
 #   * <pic='FILENAME'>
 #     - inserts the picture named FILENAME
 #   * <bar='TYPE:STYLE:WIDTH'>
 #     - inserts the blizzart bar (if using blizzart bars) in style STYLE
 #         and with colors corresponding to the stat TYPE with width WIDTH
 #     - types: HP, SP, EXP
 #  Positioning Elements:
 #   * <pos x=VALX y=VALY></pos>
 #     - positions the contents at an x position of VALX and
 #         at a y position of VALY
 #   * <offset x=VALX y=VALY></offset>
 #     - adds VALX and VALY to the position of the contents
 #   * <table></table>
 #     - starts a table
 #   * <tr></tr>
 #     - adds a row to a table
 #   * <td></td>
 #     - adds a cell to a row of a table
 #   * <left></left>
 #     - aligns the contents to the left
 #   * <center></center>
 #     - aligns the contents in the center
 #   * <right></right>
 #     - aligns the contents to the right
 #   * <ln></ln>
 #     - denotes one line in the HUD
 #   * <width=VAL></width>
 #     - sets the width of the contents to VAL
 #   * <height=VAL></height>
 #     - sets the height of the contents to VAL
 #  HUD Properties:
 #   * <hud>
 #     - this tag has many properties, listed below
 #   * skin_tone=R:G:B
 #     - sets the tone of the windowskin
 #   * bg='FILENAME'
 #     - sets the background image of the HUD to the picture named FILENAME
 #   * align=ALIGN
 #     - sets the align of the HUD to ALIGN
 #     - possible aligns: TL, TC, TR, ML, MC, MR, BL, BC, BR (top-left,
 #         top-center, top-right, middle-left, middle-center, middle-right,
 #         bottom-left, bottom-center, bottom-right)
 #   * offsetx=VAL
 #     - sets the xoffset of the HUD to VAL
 #   * offsety=VAL
 #     - and the yoffset of the HUD to VAL
 #   * width=VAL
 #     - sets the width of the HUD to VAL
 #   * height=VAL
 #     - sets the height of the HUD to VAL
 #   * back_opacity=VAL
 #     - sets the back opacity of the HUD to VAL
 #   * contents_opacity=VAL
 #     - sets the contents opacity of the HUD to VAL
 #   * opacity=VAL
 #     - sets the opacity of the HUD to VAL
 HUD = <<-HUD
   <hud bg=Cdd1I windowskin=Window skin_tone=255:-127:10 align='Bc' width=128 offsetx=0 offsety=0 opacity=0 contents_opacity=255>
   <ln><right><c=255:255:0><var=gold>G</c></right></ln>
   <ln><font=Times New Roman:24>Test</font></ln>
 HUD
 
 NO_END = ['ico', 'pic', 'hud', 'var']
 
 BLOCK_ELS = ['ln']
 
 def self.var_expression(name)
   case name
   when 'gold' then return proc { $game_party.gold }
   else return proc {}
   end
 end
end

class HUD < Window_Base
 attr_accessor :tmp_attrs
 def initialize(text)
   super(0, 0, 33, 33)
   create_contents
   self.visible = false
   @align = 'TL'
   @xoffset, @yoffset = 0, 0
   @tmp_attrs = {}
   @text = text
   Element.reset_id
   parse_text
   setup_hud
   setup_align
   @dom.delete_if { |el| el.el_type == 'hud' }
   create_contents
   tmp = self.contents
   render_hud
 end
 

 def update
   redim = []
   vars = []
   redraw = []
   @var_nodes.each { |el|
     val = el.val
     if val != el.attrs[:val]
       vars.push(el)
       redim |= [el.last_line]
       pos = el.attrs[:pos]
       rect = el.attrs[:size]
       rect.x, rect.y = *pos
       self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
       
       el.attrs[:val] = val
     end
   }
   @dom.each { |el|
     comp = false
     el.each_child_ex2(proc { |child|
       comp = false
     }) { |child|
       if child.attrs[:size] and !comp
         pos = child.attrs[:pos]
         rect = child.attrs[:size]
         rect.x, rect.y = *pos
         if vars.select { |el| pos = el.attrs[:pos];tmp = el.attrs[:size];tmp.x, tmp.y = *pos;tmp.intersect?(rect) }.length > 0
           redraw.push(child)
           comp = true
         end
       end
     }
   }
   redraw ||= vars
   
   redetermine_size(redim) if redim.length > 0
   setup_align
   redraw_hud(redraw) if redraw.length > 0
 end
 
 def redetermine_size(els)
   @tmp_attrs[:ox] = 0
   @tmp_attrs[:oy] = 0
   
   pos = [0, 0]
   
   @dom.each { |el|
     ln_height = ln_width = 0
   
     if els.include?(el)
       pos = el.attrs[:pos].clone unless @tmp_attrs[:tmp]
       if @tmp_attrs[:tmp]
         @tmp_attrs[:tmp].push(true)
       else
         @tmp_attrs[:tmp] = [true]
       end
     end
   
     case el.el_type
     when 'ln'
       el.each_child_ex(proc { |child|
         if @tmp_attrs[:tmp]
           unless child.attrs[:size].nil?
             rect = child.attrs[:size]
             rect.x, rect.y = *child.attrs[:pos]
             self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
           end
           if @tmp_attrs[:abs_pos]
             child.attrs[:pos] = [@tmp_attrs[:abs_pos].last[0] + @tmp_attrs[:ox], @tmp_attrs[:abs_pos].last[1] + @tmp_attrs[:oy]]
           else
             child.attrs[:pos] = [pos[0] + @tmp_attrs[:ox], pos[1] + @tmp_attrs[:oy]]
           end
         end
         if els.include?(child)
           pos = child.attrs[:pos].clone unless @tmp_attrs[:tmp]
           if @tmp_attrs[:tmp]
             @tmp_attrs[:tmp].push(true)
           else
             @tmp_attrs[:tmp] = [true]
           end
         end
         case child
         when FormatNode
           tmp = child.attrs[:start].call(child, self)
           child.attrs = tmp if tmp and tmp.is_a?(Hash)
         end
       },
       proc { |child|
         case child
         when FormatNode
           tmp = child.attrs[:finish].call(child, self)
           child.attrs = tmp if tmp and tmp.is_a?(Hash)
         end
         if @tmp_attrs[:tmp]
           if els.include?(child)
             @tmp_attrs[:tmp].pop
             @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0
           end
         end
         unless child.children.empty?
           resize(child)
         end
       }) { |child|
         if @tmp_attrs[:tmp]
           case child
           when TextNode
             size = self.contents.text_size(child.attrs[:val])
             child.attrs[:size] = size
             ln_height = [size.height, ln_height].max
             if @tmp_attrs[:abs_pos]
               tmp = @tmp_attrs[:abs_pos]
               ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
               @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
             else
               ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
               pos[0] += size.width
             end
           when VariableNode
             size = self.contents.text_size(child.val)
             child.attrs[:size] = size
             ln_height = [size.height, ln_height].max
             if @tmp_attrs[:abs_pos]
               tmp = @tmp_attrs[:abs_pos]
               ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
               @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
             else
               ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
               pos[0] += size.width
             end
           when IconNode, PictureNode
             size = child.attrs[:bitmap].rect
             child.attrs[:size] = size
             ln_height = [size.height, ln_height].max
             if @tmp_attrs[:abs_pos]
               tmp = @tmp_attrs[:abs_pos]
               ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
               @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
             else
               ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
               pos[0] += size.width
             end
           end
         end
       }
     end
     
     #pos[1] += ln_height + @tmp_attrs[:oy]
     #ln_widths.push(ln_width)
     
     if @tmp_attrs[:tmp]
       if els.include?(el)
         @tmp_attrs[:tmp].pop
         @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0
       end
     end
   }
   @dom.each { |child|
     if child.block?
       child.attrs[:size].width = self.width - padding * 2
     end
   }
 end
 
 def redraw_hud(els)
   @tmp_attrs = {}
   
   @dom.each { |el|
   
     align = 0
     
     case el.el_type
     when 'ln'
       if els.include?(el)
         pos = el.attrs[:pos].clone unless @tmp_attrs[:tmp]
         if @tmp_attrs[:tmp]
           @tmp_attrs[:tmp].push(true)
         else
           @tmp_attrs[:tmp] = [true]
         end
       end
       el.each_child_ex(proc { |child|
         if els.include?(child)
           pos = child.attrs[:pos].clone unless @tmp_attrs[:tmp]
           if @tmp_attrs[:tmp]
             @tmp_attrs[:tmp].push(true)
           else
             @tmp_attrs[:tmp] = [true]
           end
         end
         case child
         when FormatNode
           child.attrs[:start].call(child, self)
         end
       },
       proc { |child|
         case child
         when FormatNode
           child.attrs[:finish].call(child, self)
         end
         if @tmp_attrs[:tmp]
           if els.include?(child)
             @tmp_attrs[:tmp].pop
             @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0
           end
         end
       }) { |child|
         if @tmp_attrs[:tmp]
           case child
           when TextNode
             pos = child.attrs[:pos]
             text = child.attrs[:val]
             size = child.attrs[:size]#self.contents.text_size(text)
             #ln_height = [size.height, ln_height].max
             self.contents.draw_text(Rect.new(pos[0], pos[1], size.width, size.height), text)
           when VariableNode
             pos = child.attrs[:pos]
             text = child.val
             size = child.attrs[:size]
             self.contents.draw_text(Rect.new(pos[0], pos[1], size.width, size.height), text)
           when IconNode, PictureNode
             pos = child.attrs[:pos]
             bitmap = child.attrs[:bitmap]
             self.contents.blt(pos[0], pos[1], bitmap, bitmap.rect)
           end
         end
       }
       #if ind <= text.length - 1
       #  text[ind..text.length - 1].each { |i|
       #    self.contents.draw_text(Rect.new(x, y, self.width, 32), i)
       #    x += self.contents.text_size(i).width
       #  }
       #end
     end
   }
 end
 
 def parse_text
   text = @text.clone
   @dom, @var_nodes = [], []
   index = 0
   current_id = -1
   current_el = nil
   parent = nil
   parent_els = []
   spattern = /<([\w\-]+)(?:=([\w\"\'\-\_\:\$\.]+))?((?:\s*\w+=[\w\"\'\-\_\:\$\.]+)*)>/
   epattern = /<\/[\w\-]+>/
   while text.length != 0
     s_ind = text.index(spattern)
     if s_ind != nil
       contents = nil
       el_name = $1
       el_val = $2 || ''
       el_attrs = {}
       tmp = $3.strip
       tmp.gsub(/(\w+)\s+=\s+([\w\"\'\-\:]+)/, "\\1=\\2").split(/\s+/).each { |el| el_attrs[el.split('=')[0].to_sym] = el.split('=')[1].gsub(/[\'\"]/, '') }
       el_val.gsub!(/[\'\"]/, '') if el_val
       el_attrs[:val] = el_val
       level, tmp_name, tmp_ind = 0, '', s_ind
       if !DesignHUD::NO_END.include?(el_name)
         loop do
           text.sub!(spattern, '')
           tmp = [text.index(/(<#{el_name}(?:=[\w\"\'\-\:]+)?(?:\s*\w+=[\w\"\'\-\:]+)*>)/, tmp_ind)]
           tmp.push(text.index(/<\/#{el_name}>/, tmp_ind))
           if !tmp[1]
             contents = text[s_ind...text.length - 4 - el_name.length]
             text = ''
           elsif !tmp[0]
             contents = text[s_ind...text.length - 4 - el_name.length]
             text = ''
           elsif tmp[1] < tmp[0]
             contents = text[s_ind...tmp[1]]
             text = text[tmp[1]...text.length]
           else
             level += 1
             tmp_ind = tmp[0] + 2 + el_name.length
           end
           break if contents != nil
         end
         case el_name
         when 'ln'
           element = ContainerNode.new('ln', el_attrs, nil, contents)
           @dom.push(element)
         end
       else
         text.sub!(spattern, '')
         case el_name
         when 'hud'
           element = HudNode.new('hud', el_attrs)
           @dom.push(element)
         end
       end
     end
   end
 end
 
 def setup_hud
   @dom.each { |el|
     el.each_child { |tmp|
       if tmp.el_type == 'hud'
         self.width = tmp.attrs[:width].to_i if tmp.attrs[:width]
         self.height = tmp.attrs[:height].to_i if tmp.attrs[:height]
         @align = tmp.attrs[:align] if tmp.attrs[:align]
         @xoffset = tmp.attrs[:offsetx].to_i if tmp.attrs[:offsetx]
         @yoffset = tmp.attrs[:offsety].to_i if tmp.attrs[:offsety]
         self.opacity = tmp.attrs[:opacity].to_i if tmp.attrs[:opacity]
         self.back_opacity = tmp.attrs[:back_opacity].to_i if tmp.attrs[:back_opacity]
         self.contents_opacity = tmp.attrs[:contents_opacity].to_i if tmp.attrs[:contents_opacity]
         begin
           self.windowskin = ((tmp.attrs[:windowskin] == '') ? Bitmap.new(1, 1) : Cache.system(tmp.attrs[:windowskin])) if tmp.attrs[:windowskin]
         rescue
           self.windowskin = Bitmap.new(1, 1)
         end
         self.tone = Tone.new(*tmp.attrs[:skin_tone].split(':').map{|i|i.to_f}) if tmp.attrs[:skin_tone]
         @bg = Sprite.new
         @bg.z = self.z - 1
         if tmp.attrs[:bg]
           @bg.bitmap = Cache.picture(tmp.attrs[:bg])
         else
           @bg.visible = false
         end
       end
     }
   }
   
   tmp_width, tmp_height = get_dimensions
   
   if self.width == 33
     self.width = [tmp_width, 1].max + 32
   end
   if self.height == 33
     self.height = [tmp_height, 1].max + 32
   end
   @dom.each { |child|
     if child.block?
       child.attrs[:size].width = self.width - padding * 2
     end
   }
   @align.downcase!
   xmod = (['l','c'].include?(@align[1..1]) ? 1 : -1)
   ymod = (['t','m'].include?(@align[0..0]) ? 1 : -1)
   xstrt = case @align[1..1]
   when 'l' then 0
   when 'r' then Graphics.width - self.width
   when 'c' then (Graphics.width - self.width) / 2
   end
   ystrt = case @align[0..0]
   when 't' then 0
   when 'b' then Graphics.height - self.height
   when 'm' then (Graphics.height - self.height) / 2
   end
   self.x = xstrt + xmod * @xoffset
   self.y = ystrt + ymod * @yoffset
   if @bg.visible
     @bg.x = self.x + (self.width - @bg.bitmap.width) / 2
     @bg.y = self.y + (self.height - @bg.bitmap.height) / 2
   end
   self.visible = true
 end
 
 def get_dimensions
   ln_widths = []
   height = 0
   @tmp_attrs[:ox] = 0
   @tmp_attrs[:oy] = 0
   @tmp_attrs[:align] = 0
   
   pos = [0, 0]
   
   @dom.each { |el|
   
     pos[0] = 0
     ln_width = 0
     ln_height = 0
     
     case el.el_type
     when 'ln'
       el.attrs[:pos] = pos.clone
       el.attrs[:align] = @tmp_attrs[:abs_pos]
       el.attrs[:abs] = 0
       el.each_child_ex(proc { |child| # start proc
         child.attrs[:align] = (@tmp_attrs[:abs_pos] ? 0 : @tmp_attrs[:align])
         if @tmp_attrs[:abs_pos]
           child.attrs[:pos] = [@tmp_attrs[:abs_pos].last[0] + @tmp_attrs[:ox], @tmp_attrs[:abs_pos].last[1] + @tmp_attrs[:oy]]
           child.attrs[:abs] = @tmp_attrs[:abs_pos].length
         else
           child.attrs[:pos] = [pos[0] + @tmp_attrs[:ox], pos[1] + @tmp_attrs[:oy]]
           child.attrs[:abs] = 0
         end
         case child
         when FormatNode
           tmp = child.attrs[:start].call(child, self)
           child.attrs = tmp if tmp and tmp.is_a?(Hash)
         end
       },
       proc { |child| # end proc
         case child
         when FormatNode
           tmp = child.attrs[:finish].call(child, self)
           child.attrs = tmp if tmp and tmp.is_a?(Hash)
         end
         if !child.children.empty?
           resize(child)
         elsif child.block?
           child.attrs[:size] = Rect.new(0, 0, 0, 0)
         end
       }) { |child| # main proc
         case child
         when TextNode
           size = self.contents.text_size(child.attrs[:val])
           child.attrs[:size] = size
           ln_height = [size.height, ln_height].max
           if @tmp_attrs[:abs_pos]
             tmp = @tmp_attrs[:abs_pos]
             ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
             @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
           else
             ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
             pos[0] += size.width
           end
         when VariableNode
           size = self.contents.text_size(child.val.to_s)
           child.attrs[:size] = size
           ln_height = [size.height, ln_height].max
           if @tmp_attrs[:abs_pos]
             tmp = @tmp_attrs[:abs_pos]
             ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
             @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
           else
             ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
             pos[0] += size.width
           end
           @var_nodes.push(child)
         when IconNode, PictureNode
           size = child.attrs[:bitmap].rect
           child.attrs[:size] = size
           ln_height = [size.height, ln_height].max
           if @tmp_attrs[:abs_pos]
             tmp = @tmp_attrs[:abs_pos]
             ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max
             @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width
           else
             ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max
             pos[0] += size.width
           end
         end
       }
     end
     
     pos[1] += ln_height + @tmp_attrs[:oy]
     ln_widths.push(ln_width)
   }
   
   height = pos[1]
   width = ln_widths.max
   return width, height
 end
 
 def resize(el)
   size = Rect.new(0, 0, 0, 0)
   x1, y1 = 640, 480
   x2 = y2 = 0
   len = el.attrs[:abs]
   el.children.each { |i|
     next if i.attrs[:abs] > len
     x, y = *i.attrs[:pos]
     ns = i.attrs[:size]
     x1 = [x1, x].min
     y1 = [y1, y].min
     x2 = [x2, x + ns.width].max
     y2 = [y2, y + ns.height].max
   }
   size.width = x2 - x1
   size.height = y2 - y1
   pos = [x1, y1]
   el.attrs[:pos], el.attrs[:size] = pos, size
 end
 
 def setup_align
   aligned = nil
   @dom.each { |el|
     case el.el_type
     when 'ln'
       el.each_child_ex(proc {|child|},
       proc { |child| # end proc
         case child
         when FormatNode
           if child.attrs[:tmp]
             child.attrs.delete_at(:tmp)
             aligned.pop
             aligned = nil if aligned.empty?
           end
         end
       }) { |child| # main proc
         break unless aligned.nil?
         if ['right', 'left', 'center'].include?(child.el_type)
           child.attrs[:tmp] = true
           if aligned
             aligned.push(true)
           else
             aligned = [true]
           end
         end
         case child.attrs[:align]
         when 0
           pos = child.attrs[:pos]
           fb = child.last_block
           np = fb.attrs[:pos]
           child.attrs[:pos] = np.clone
           child.each_child_ex(proc{},proc{}) { |i|
             i.attrs[:pos][0] += np[0] - pos[0]
             i.attrs[:pos][1] += np[1] - pos[1]
           }
         when 1
           pos = child.attrs[:pos]
           fb = child.last_block
           fbw = fb.attrs[:size].width
           fbp = fb.attrs[:pos]
           w = child.attrs[:size].width
           np = [(fbw - w) / 2, pos[1]]
           child.attrs[:pos] = np.clone
           child.each_child_ex(proc{},proc{}) { |i|
             i.attrs[:pos][0] += np[0] - pos[0]
             i.attrs[:pos][1] += np[1] - pos[1]
           }
         when 2
           pos = child.attrs[:pos]
           fb = child.last_block
           fbw = fb.attrs[:size].width
           fbp = fb.attrs[:pos]
           w = child.attrs[:size].width
           np = [fbw - w, pos[1]]
           child.attrs[:pos] = np.clone
           child.each_child_ex(proc{},proc{}) { |i|
             i.attrs[:pos][0] += np[0] - pos[0]
             i.attrs[:pos][1] += np[1] - pos[1]
           }
         end
       }
     end
   }
 end
 
#~   def realign
#~     aligned = nil
#~     @dom.each { |el|
#~       case el.el_type
#~       when 'ln'
#~         el.each_child_ex(proc { |child| # start proc
#~           case child
#~           when FormatNode
#~             tmp = child.attrs[:start].call(child, self)
#~             child.attrs = tmp if tmp and tmp.is_a?(Hash)
#~           end
#~         },
#~         proc { |child| # end proc
#~           case child
#~           when FormatNode
#~             tmp = child.attrs[:finish].call(child, self)
#~             child.attrs = tmp if tmp and tmp.is_a?(Hash)
#~             if child.attrs[:tmp]
#~               child.attrs.delete_at(:tmp)
#~               aligned.pop
#~               aligned = nil if aligned.empty?
#~             end
#~           end
#~         }) { |child| # main proc
#~           break unless aligned.nil?
#~           if ['right', 'left', 'center'].include?(child.el_type)
#~             child.attrs[:tmp] = true
#~             if aligned
#~               aligned.push(true)
#~             else
#~               aligned = [true]
#~             end
#~           end
#~           case child.attrs[:align]
#~           when 0
#~             pos = child.attrs[:pos]
#~             fb = child.last_block
#~             np = fb.attrs[:pos]
#~             child.attrs[:pos] = np.clone
#~             child.each_child_ex(proc{},proc{}) { |i|
#~               i.attrs[:pos][0] += np[0] - pos[0]
#~               i.attrs[:pos][1] += np[1] - pos[1]
#~             }
#~           when 1
#~             pos = child.attrs[:pos]
#~             fb = child.last_block
#~             fbw = fb.attrs[:size].width
#~             fbp = fb.attrs[:pos]
#~             w = child.attrs[:size].width
#~             np = [(fbw - w) / 2, pos[1]]
#~             child.attrs[:pos] = np.clone
#~             child.each_child_ex(proc{},proc{}) { |i|
#~               i.attrs[:pos][0] += np[0] - pos[0]
#~               i.attrs[:pos][1] += np[1] - pos[1]
#~             }
#~           when 2
#~             pos = child.attrs[:pos]
#~             fb = child.last_block
#~             fbw = fb.attrs[:size].width
#~             fbp = fb.attrs[:pos]
#~             w = child.attrs[:size].width
#~             np = [fbw - w, pos[1]]
#~             child.attrs[:pos] = np.clone
#~             child.each_child_ex(proc{},proc{}) { |i|
#~               i.attrs[:pos][0] += np[0] - pos[0]
#~               i.attrs[:pos][1] += np[1] - pos[1]
#~             }
#~           end
#~         }
#~       end
#~     }
#~   end
 
 def render_hud
   
   @dom.each { |el|
   
     align = 0
   
     case el.el_type
     when 'ln'
       el.each_child_ex(proc { |child|
         case child
         when FormatNode
           child.attrs[:start].call(child, self)
         end
       },
       proc { |child|
         case child
           when FormatNode
             child.attrs[:finish].call(child, self)
         end
       }) { |child|
         case child
         when TextNode
           pos = child.attrs[:pos]
           text = child.attrs[:val]
           size = child.attrs[:size]#self.contents.text_size(text)
           #ln_height = [size.height, ln_height].max
#~             if @tmp_attrs[:tmpalign]
#~               case @tmp_attrs[:tmpalign].last
#~               when 'r'
#~                 pos = pos.clone
#~                 pos[0] = contents.width - pos[0] - size.width
#~               end
#~             end
           self.contents.draw_text(Rect.new(pos[0], pos[1], size.width, size.height), text)
         when VariableNode
           pos = child.attrs[:pos]
           text = child.val.to_s
           size = child.attrs[:size]
#~             if @tmp_attrs[:tmpalign]
#~               case @tmp_attrs[:tmpalign].last
#~               when 'r'
#~                 pos = pos.clone
#~                 pos[0] = contents.width - pos[0] - size.width
#~               end
#~             end
           self.contents.draw_text(Rect.new(pos[0], pos[1], size.width, size.height), text)
         when IconNode, PictureNode
           pos = child.attrs[:pos]
           bitmap = child.attrs[:bitmap]
           self.contents.blt(pos[0], pos[1], bitmap, bitmap.rect)
         end
       }
     end
   }
 end
 
 def get_el(path)
   el = @dom[path[0]]
   if path.length > 1
     path[1..path.length - 1].each { |tmp|
       el = el.children[tmp]
     }
   end
   el
 end
end

class Element
 @@id = 0
 attr_accessor :children, :el_type, :attrs, :el_id, :parent
 
 def initialize(el_type, attrs, parent)
   @children = []
   @el_type = el_type.downcase
   @attrs = attrs
   @parent = parent
   @contents = ''
   @el_id = @@id
   @@id += 1
 end
 
 def block?
   return DesignHUD::BLOCK_ELS.include?(@el_type)
 end
 
 def inline?
   return !DesignHUD::BLOCK_ELS.include?(@el_type)
 end
 
 def self.reset_id
   @@id = 0
 end
 
 def parents
   if @parent != nil
     parents = [@parent]
     parent = @parent
     while parent.parent != nil
       parents.push(parent.parent)
       parent = parent.parent
     end
     return parents
   else
     return []
   end
 end
 
 def last_block
   if @parent != nil
     last = self
     parent = @parent
     while last.inline?
       last = parent
       parent = parent.parent
       break if parent.nil?
     end
     return last
   else
     return nil
   end
 end
 
 def last_line
   if @parent != nil
     last = self
     parent = @parent
     while last.el_type != 'ln'
       last = parent
       parent = parent.parent
       break if parent.nil?
     end
     return last
   else
     return nil
   end
 end
 
 def each_child(&block)
   block.call(self)
   path = [0]
   cur = self
   loop {
     child = cur.children[path.last]
     if child
       block.call(child)
       cur = child
       path.push(0)
     else
       cur = cur.parent
       path.pop
       break unless cur
       path[path.length - 1] += 1
     end
   }
 end
 
 def each_child_ex(start, finish, &block)
   path = [0]
   cur = self
   loop {
     child = cur.children[path.last]
     if child
       start.call(child)
       block.call(child)
       cur = child
       path.push(0)
     else
       finish.call(cur)
       cur = cur.parent
       path.pop
       break unless cur and path.length > 0
       path[path.length-1] += 1
     end
   }
 end
 
 def each_child_ex2(finish, &block)
   block.call(self)
   path = [0]
   cur = self
   loop {
     child = cur.children[path.last]
     if child
       block.call(child)
       cur = child
       path.push(0)
     else
       finish.call(cur)
       cur = cur.parent
       path.pop
       break unless cur
       path[path.length - 1] += 1
     end
   }
 end
 
 def parse_contents(text)
   @tmp_attrs = {}
   spattern = /<([\w\-]+)(?:=([\w\"\'\-\_\:\$\.\s]+))?((?:\s*\w+=[\w\"\'\-\_\:\$\.]+)*)>/
   epattern = /<\/[\w\-]+>/
   while text != ''
     s_ind = text.index(spattern)
     if s_ind != nil
       if s_ind > 0
         contents = text[0...s_ind]
         text = text[s_ind...text.length]
         element = TextNode.new('', self, contents)
         @children.push(element)
       end
       contents = nil
       el_name = $1
       el_val = $2 || ''
       el_attrs = {}
       tmp = $3.strip
       tmp.gsub(/(\w+)\s+=\s+([\w\"\'\-\:]+)/, "\\1=\\2").split(/\s+/).each { |el| el_attrs[el.split('=')[0].to_sym] = eval(el.split('=')[1]) }
       el_val.gsub!(/[\'\"]/, '') if el_val
       el_attrs[:val] = el_val
       level, tmp_name, tmp_ind = 0, '', 0
       if !DesignHUD::NO_END.include?(el_name)
         text.sub!(spattern, '')
         last_ind = nil
         loop do
           tmp = [text.index(/(<#{el_name}(?:=[\w\"\'\-\:]+)?(?:\s*\w+=[\w\"\'\-\:]+)*>)/, tmp_ind)]
           tmp2 = tmp_ind
           for i in 0..level
             tmp2 = text.index(/<\/#{el_name}>/, tmp2) + 2 + el_name.length
           end
           tmp.push(tmp2 - 2 - el_name.length)
           if !tmp[1]
             contents = text[0...text.length]
             text = ''
           elsif !tmp[0]
             contents = text[0...tmp[1]]
             text = text[tmp[1] + 3 + el_name.length...text.length]
             level = [level - 1, 0].max
           elsif tmp[1] < tmp[0]
             contents = text[0...tmp[1]]
             text = text[tmp[1] + 3 + el_name.length...text.length]
             level = [level - 1, 0].max
           else
             level += 1 unless last_ind != nil and tmp[0] > last_ind[1]
             tmp_ind = tmp[0] + 2 + el_name.length
           end
           last_ind = tmp
           break if contents != nil
         end
         case el_name
         when 'ln'
           element = ContainerNode.new('ln', el_attrs, self, contents)
           @children.push(element)
         when 'b'
           element = FormatNode.new('b', self, contents, proc { |child, hud|
             if !@tmp_attrs[:tmpb]
               @tmp_attrs[:tmpb] = [hud.contents.font.bold]
             else
               @tmp_attrs[:tmpb].push(hud.contents.font.bold)
             end
             hud.contents.font.bold = true
           },
           proc { |child, hud|
             hud.contents.font.bold = @tmp_attrs[:tmpb].pop
           })
           @children.push(element)
         when 'i'
           element = FormatNode.new('i', self, contents, proc { |child, hud|
             if !@tmp_attrs[:tmpi]
               @tmp_attrs[:tmpi] = [hud.contents.font.italic]
             else
               @tmp_attrs[:tmpi].push(hud.contents.font.italic)
             end
             hud.contents.font.italic = true
           },
           proc { |child, hud|
             hud.contents.font.italic = @tmp_attrs[:tmpi].pop
           })
           @children.push(element)
         when 'c'
           element = FormatNode.new('c', self, contents, proc { |child, hud|
             if !hud.tmp_attrs[:tmpc]
               hud.tmp_attrs[:tmpc] = [hud.contents.font.color.clone]
             else
               hud.tmp_attrs[:tmpc].push(hud.contents.font.color.clone)
             end
             hud.contents.font.color = Color.new(*child.attrs[:val].split(':').map { |i| i.to_i })
           },
           proc { |child, hud|
             hud.contents.font.color = hud.tmp_attrs[:tmpc].pop
           }, el_val)
           @children.push(element)
         when 'font'
           element = FormatNode.new('font', self, contents, proc { |child, hud|
             if !@tmp_attrs[:tmpfn]
               hud.tmp_attrs[:tmpfn] = [[hud.contents.font.name.clone, hud.contents.font.size]]
             else
               hud.tmp_attrs[:tmpfn].push([hud.contents.font.name.clone, hud.contents.font.size])
             end
             if Font.exist?(child.attrs[:val].split(':')[0])
               hud.contents.font.name = child.attrs[:val].split(':')[0]
               hud.contents.font.size = child.attrs[:val].split(':')[1].to_i
             end
           },
           proc { |child, hud|
             hud.contents.font.name, hud.contents.font.size = *hud.tmp_attrs[:tmpfn].pop
           }, el_val)
           @children.push(element)
         when 'pos'
           element = FormatNode.new('pos', self, contents, proc { |child, hud|
           if !hud.tmp_attrs[:abs_pos]
               hud.tmp_attrs[:abs_pos] = [[child.attrs[:x], child.attrs[:y]]]
             else
               hud.tmp_attrs[:abs_pos].push([child.attrs[:x], child.attrs[:y]])
             end
           },
           proc { |child, hud|
             hud.tmp_attrs[:abs_pos].pop
             hud.tmp_attrs.delete(:abs_pos) if hud.tmp_attrs[:abs_pos].length == 0
           }, el_val, el_attrs)
           @children.push(element)
         when 'offset'
           element = FormatNode.new('offset', self, contents, proc { |child, hud|
             if !hud.tmp_attrs[:tmpofst]
               hud.tmp_attrs[:tmpofst] = [[hud.tmp_attrs[:ox], hud.tmp_attrs[:oy]]]
             else
               hud.tmp_attrs[:tmpofst].push([hud.tmp_attrs[:ox], hud.tmp_attrs[:oy]])
             end
             hud.tmp_attrs[:ox], hud.tmp_attrs[:oy] = child.attrs[:x], child.attrs[:y]
           },
           proc { |child, hud|
             hud.tmp_attrs[:ox], hud.tmp_attrs[:oy] = *hud.tmp_attrs[:tmpofst].pop
           }, el_val, el_attrs)
           @children.push(element)
         when 'right'
           element = FormatNode.new('right', self, contents, proc { |child, hud|
             if !hud.tmp_attrs[:tmpalign]
               hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]]
             else
               hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align])
             end
             hud.tmp_attrs[:align] = 2
             child.attrs[:align] = 2
           },
           proc { |child, hud|
             hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop
           }, el_val, el_attrs)
           @children.push(element)
         when 'center'
           element = FormatNode.new('center', self, contents, proc { |child, hud|
             if !hud.tmp_attrs[:tmpalign]
               hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]]
             else
               hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align])
             end
             hud.tmp_attrs[:align] = 1
             child.attrs[:align] = 1
           },
           proc { |child, hud|
             hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop
           }, el_val, el_attrs)
           @children.push(element)
         when 'left'
           element = FormatNode.new('left', self, contents, proc { |child, hud|
             if !hud.tmp_attrs[:tmpalign]
               hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]]
             else
               hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align])
             end
             hud.tmp_attrs[:align] = 0
             child.attrs[:align] = 0
           },
           proc { |child, hud|
             hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop
           }, el_val, el_attrs)
           @children.push(element)
         end
       else
         text.sub!(spattern, '')
         case el_name
         when 'hud'
           element = HudNode.new('hud', el_attrs, self)
           @children.push(element)
         when 'var'
           element = VariableNode.new(self, el_val)
           @children.push(element)
         when 'ico'
           element = IconNode.new(self, el_val)
           @children.push(element)
         when 'pic'
           element = PictureNode.new(self, el_val)
           @children.push(element)
         end
       end
     else
       contents = text
       text = ''
       element = TextNode.new('', self, contents)
       @children.push(element)
     end
   end
 end
end

class TextNode < Element
 def initialize(type, parent, text)
   super(type, {}, parent)
   @attrs[:val] = text
 end
end

class PictureNode < Element
 def initialize(parent, val)
   super('pic', {}, parent)
   @attrs[:bitmap] = Cache.picture(val)
 end
end

class IconNode < Element
 def initialize(parent, val)
   super('ico', {}, parent)
   offset = val.split(':').map { |i| i.to_i * 24 }
   @attrs[:bitmap] = Bitmap.new(24, 24)
   iconset = Cache.system('IconSet')
   @attrs[:bitmap].blt(0, 0, iconset, Rect.new(offset[0], offset[1], 24, 24))
 end
end

class VariableNode < Element
 def initialize(parent, name)
   super('var', {}, parent)
   @attrs[:expr] = DesignHUD.var_expression(name)
   @attrs[:val] = @attrs[:expr].call || 0
 end
 
 def val
   tmp = @attrs[:expr].call
   return (tmp.nil? ? 0 : tmp)
 end
end

class BarNode < Element
 
end

class HudNode < Element
 def initialize(type, attrs, parent = nil)
   super('hud', attrs, parent)
 end
end

class ContainerNode < Element
 def initialize(type, attrs, parent, contents)
   super(type, attrs, parent)
   
   parse_contents(contents)
 end
end

class FormatNode < Element
 def initialize(type, parent, contents, start, finish, val=nil, attrs = {})
   super(type, attrs, parent)
   
   parse_contents(contents)
   @attrs[:val] = val if val
   @attrs[:start] = start
   @attrs[:finish] = finish
 end
end

class Rect
 def intersect?(rect)
   return false if rect.width * rect.height == 0 or self.width * self.height == 0
   return true if (self.x.between?(rect.x - 1, rect.x + rect.width) or
                  (self.x + self.width).between?(rect.x - 1, rect.x + rect.width)) and
                  (self.y.between?(rect.y - 1, rect.y + rect.height) or
                  (self.y + self.height).between?(rect.y - 1, rect.y + rect.height))
   return false
 end
end

         


 And apparently the first time I tried to post this, something went wrong and the entire list of tags that I had created vanished. So, here it is (notes on what each element/property does is in the script header, this is just a list of what's implemented):


<hud>
 Properties Implemented:
   windowskin=FILENAME
   bg=FILENAME
   width=WIDTH
   height=HEIGHT
   align=ALIGN
   offsetx=OFFSETX
   offsety=OFFSETY
   back_opacity=OPACITY
   contents_opacity=OPACITY
   opacity=OPACITY
   skin_tone=R:G:B (VXA only)
<ln></ln>
<right></right>
<left></left>
<center></center>
<pos x=X y=Y></pos>
<offset x=X y=Y></pos>
<ico=X:Y> (VXA only)
<ico=FILENAME> (XP only)
<pic=FILENAME>
<b></b>
<i></i>
<c=R:G:B[:A]></c>
<font=NAME:SIZE></font>

11
RMXP Script Database / [XP] Event Templates
December 29, 2012, 04:22:45 pm
Template Events
Authors: ThallionDarkshine
Version: 1.0
Type: Misc Add-on
Key Term: Misc Add-on



Introduction

You ever want to create lots of one event dynamically during the game? Well, this script allows you to create template events, which allow you to create many identical events, and all from one event.


Features


  • Easily create template events in the editor.

  • Create as many template events as you want.

  • Create events from templates at any position on the map.




Screenshots

They wouldn't really show much, just an event sitting on a map.


Demo

It's pretty easy to use, but I'll put up a demo if requested.


Script

Spoiler: ShowHide

# Instructions
#   To create an event template, simply create an event with <template> in its
#     name. What's left of the event's name is the name of the template. These
#     template events will be automatically removed from the map when created.
#   You can create an event from a template event with:
#     create_event_from_template(NAME, X, Y[, SAVED])
#       NAME - the name of the template
#       X, Y - the x and y coordinates for the event, respectively
#       SAVED - whether the event should be saved (default true)

class Game_Map
 attr_accessor :saved_events
 attr_reader :template_events
 alias tdks_template_evnt_init initialize
 def initialize
   tdks_template_evnt_init
   @template_events = {}
   @saved_events = {}
 end
 
 alias tdks_template_evnt_setup setup
 def setup(map_id)
   tdks_template_evnt_setup(map_id)
   @events.each { |key, ev|
     unless ev.instance_variable_get(:@event).name.gsub!(/\<template\>/, '').nil?
       @template_events[ev.instance_variable_get(:@event).name] = ev
       @events.delete(key)
     end
   }
   @saved_events[@map_id] ||= []
   @saved_events[@map_id].each { |event|
     nind = (1..@events.keys.max+1).detect{|i|!$game_map.events.keys.include?(i)}
     @events[nind] = event
   }
 end
end

class Interpreter
 def create_event_from_template(name, x, y, save=true)
   ev = $game_map.template_events[name]
   unless ev.nil?
     ind = (1..$game_map.events.keys.max + 1).detect { |i| !$game_map.events.keys.include?(i) }
     tmp = ev.clone
     tmp.instance_variable_get(:@event).id = ind
     tmp.instance_variable_set(:@id, ind)
     tmp.moveto(x, y)
     $game_map.events[ind] = tmp
     
     if $scene.is_a?(Scene_Map)
       spriteset = $scene.instance_variable_get(:@spriteset)
       char_sprites = spriteset.instance_variable_get(:@character_sprites)
       char_sprites.push(Sprite_Character.new(spriteset.instance_variable_get(:@viewport1), tmp))
       spriteset.instance_variable_set(:@character_sprites, char_sprites)
     end
     
     if save
       $game_map.saved_events[$game_map.map_id].push(tmp)
     end
     
     $game_map.need_refresh = true
   end
 end
end



Instructions

In the script.


Compatibility

I don't think there will be any compatibility issues.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

None
12
Transition Pack Edit
Authors: Fantasist, ForeverZero, ThallionDarkshine
Version: 0.22
Type: Transition Script
Key Term: Misc Add-on



Introduction

You know Fantasist's awesome transition pack, allowing you to have really cool transitions. Well, in Chaos Project (the game) I saw that blizz had modified his version of the script to transition directly to the new scene. I modified Fantasist's script, adding a few transitions along with support for showing the new scene in the background.


Features


  • Extra-cool Transitions

  • Show next scene in the background during the transition




Screenshots




Demo

None yet.


Script

Spoiler: ShowHide

#==============================================================================
# ** Transition Pack
#------------------------------------------------------------------------------
# by Fantasist
# extra transitions by ForeverZero
# edited by ThallionDarkshine
# Version: 0.22
# Date: 5 March 2014
#------------------------------------------------------------------------------
# Description:
#
#     This script adds some exotic transitions which can't be attained by
#   regular transition graphics.
#------------------------------------------------------------------------------
# Compatibility:
#
#     This script replaces Scene_Map#transfer_player method.
#==============================================================================
# Instructions:
#
#     This script NEEDS "screenshot.dll"! Place it in the game folder.
#     Place this script below Scene_Debug and above Main. To use this, instead
#   of calling a scene directly like this:
#
#           $scene = Scene_Something.new
#
#   call it like this:
#
#           $scene = Transition.new(Scene_Something.new)
#
#     Before calling it, you can change "$game_temp.transition_type" to
#   activate the transiton.
#
#     As of version 1.11 and above, the battle, menu, name, shop and save scenes
#   automatically use the predefined transition effects, so all you have to do
#   is call the scenes using the event command.
#
#     You can also call a certain effect like this:
#
#           Transition.new(NEXT_SCENE, EFFECT_TYPE, EFFECT_TYPE_ARGUMENTS)
#
#
#   Here is the list of transitions (as of version 1.11):
#
#    -1 - Uses the default effect (in most cases, simple transition)
#     0 - Zoom In
#     1 - Zoom Out
#     2 - Shred Horizontal
#     3 - Shred Vertical
#     4 - Fade
#     5 - Explode
#     6 - Explode (Chaos Project Style)
#     7 - Transpose (by Blizzard)
#     8 - Shutter
#     9 - Drop Off
#
#   For Scripters:
#
#     For adding new transitions, check the method Transition#call_effect.
#   Simply add a new case for "type" and add your method. Don't forget to
#   add the *args version, it makes it easier to pass arguments when calling
#   transitions. Check out the call_effect method for reference.
#------------------------------------------------------------------------------
# Configuration:
#
#     Scroll down a bit and you'll see the configuration.
#
#   BATTLE_EFFECT: Effect to be used for calling battles
#   SHOP_EFFECT: Effect to be used for calling the Shop scene
#   NAME_EFFECT: Effect to be used for calling the Name scene
#   MENU_EFFECT: Effect to be used for calling the Menu scene
#   SAVE_EFFECT: Effect to be used for calling the Save scene
#
#   - Set to any number (-1 to 9) to use the respective effect.
#   - Set to "nil" to use the effect defined in "$game_temp.transition_type".
#   - Use an array to use any random effect. For example, setting BATTLE_EFFECT
#     to [1, 3, 6, 8, 9] will use any of those effects each time the battle
#     scene is called.
#
#   Explosion_Sound: Filename of the SE for Explosion transitions
#       Clink_Sound: Filename of the SE for Drop Off transition
#------------------------------------------------------------------------------
# Issues:
#
#     None that I know of.
#------------------------------------------------------------------------------
# Credits and Thanks:
#
#   Fantasist, for making this script
#   Blizzard, for the Transpose effect
#   shdwlink1993, for keeping the demo for so long
#   Ryexander, for helping me with an important scripting aspect
#   Memor-X, for pointing out some bugs
#------------------------------------------------------------------------------
# Notes:
#
#     If you have any problems, suggestions or comments, you can find me at:
#
#  - forum.chaos-project.com
#
#   Enjoy ^_^
#==============================================================================

#==============================================================================
# ** Screen Module
#------------------------------------------------------------------------------
#  This module handles taking screenshots for the transitions.
#==============================================================================
module Screen
 
  @screen = Win32API.new 'screenshot.dll', 'Screenshot', %w(l l l l p l l), ''
  @readini = Win32API.new 'kernel32', 'GetPrivateProfileStringA', %w(p p p p l p), 'l'
  @findwindow = Win32API.new 'user32', 'FindWindowA', %w(p p), 'l'
  #--------------------------------------------------------------------------
  # * Snap (take screenshot)
  #--------------------------------------------------------------------------
  def self.snap(file_name='scrn_tmp', file_type=0)
    game_name = "\0" * 256
    @readini.call('Game', 'Title', '', game_name, 255, '.\Game.ini')
    game_name.delete!("\0")
    window = @findwindow.call('RGSS Player', game_name)
    @screen.call(0, 0, 640, 480, file_name, window, file_type)
  end
end

#==============================================================================
# ** Transition
#------------------------------------------------------------------------------
#  This scene handles transition effects while switching to another scene.
#==============================================================================
class Transition
  attr_reader :started
 
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # * CONFIG BEGIN
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  BATTLE_EFFECT = [6, 7, 8, 9, 14, 17] # randomly choose from any of those
  BATTLE_USE_BACK = true
  SHOP_EFFECT = [16, 17, 18]
  SHOP_USE_BACK = true
  NAME_EFFECT = nil # uses default effect set in $game_temp.transition_type
  NAME_USE_BACK = false
  MENU_EFFECT = 16
  MENU_USE_BACK = true
  SAVE_EFFECT = -1 # disable effect/use default
  SAVE_USE_BACK = false
 
 
  Explosion_Sound = nil
      Clink_Sound = nil
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # * CONFIG END
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
  #--------------------------------------------------------------------------
  # * Call Effect
  #     type : Transition type
  #     args : Arguments for specified transition type
  #--------------------------------------------------------------------------
  def call_effect(type, args)
    # if "type" is an array, choose a random element.
    if type.is_a?(Array)
      type = type[rand(type.size)]
    end
    # Call appropriate method with or without arguments depending
    # on values of type and args.
    no_args = args.nil? || args == []
    if no_args
      case type
      when 0 then zoom_in
      when 1 then zoom_out
      when 2 then shred_h
      when 3 then shred_v
      when 4 then fade
      when 5 then explode
      when 6 then explode_cp
      when 7 then transpose
      when 8 then shutter
      when 9 then drop_off
      when 10 then ff_IV_style
      when 11 then downward_spiral
      when 12 then blackhole
      when 13 then wave_distort
      when 14 then radial_break
      when 15 then double_zoom
      when 16 then cover
      when 17 then uncover
      when 18 then shift
      end
    else
      case type
      when 0 then zoom_in(*args)
      when 1 then zoom_out(*args)
      when 2 then shred_h(*args)
      when 3 then shred_v(*args)
      when 4 then fade(*args)
      when 5 then explode(*args)
      when 6 then explode_cp(*args)
      when 7 then transpose(*args)
      when 8 then shutter(*args)
      when 9 then drop_off(*args)
      when 10 then ff_IV_style(*args)
      when 11 then downward_spiral(*args)
      when 12 then blackhole(*args)
      when 13 then wave_distort(*args)
      when 14 then radial_break(*args)
      when 15 then double_zoom(*args)
      when 16 then cover(*args)
      when 17 then uncover(*args)
      when 18 then shift(*args)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Initialize
  #     next_scene : Instance of the scene to transition into
  #           type : Transition type
  #          *args : Arguments for specified transition type
  #--------------------------------------------------------------------------
  def initialize(next_scene=Scene_Menu.new, type=nil, show_next=nil, *args)
    @next_scene = next_scene
    @args = args
    # If transition type is specified, use it.
    # Otherwise, use default.
    @type = type.nil? ? $game_temp.transition_type : type
    @show_next = show_next.nil? ? $game_temp.use_back : show_next
  end
  #--------------------------------------------------------------------------
  # * Main
  #--------------------------------------------------------------------------
  def main
    if @type == -1
      $scene = @next_scene
      return
    end
    @started = true
    # Take screenshot and prepare sprite
    path = ENV['appdata'] + "\\scrn_tmp"
    Screen.snap(path)
    @sprite = Sprite.new
    @sprite.bitmap = Bitmap.new(path)
    @sprite.x = @sprite.ox = @sprite.bitmap.width / 2
    @sprite.y = @sprite.oy = @sprite.bitmap.height / 2
    @sprite.z = 100000
    @sprite.disposable = true
    @next_scene.main if @show_next == true
    # Activate effect
    Graphics.transition(0)
    call_effect(@type, @args)
    # Freeze screen and clean up and switch scene
    Graphics.freeze
    @sprite.bitmap.dispose unless @sprite.bitmap.nil?
    @sprite.dispose unless @sprite.nil?
    $skip_trans = @show_next
    #File.delete(path)
    $scene = @next_scene
    $game_system.disposables.each { |el| el.dispose }
    $game_system.disposables = []
  end
  #--------------------------------------------------------------------------
  # * Play SE
  #     filename : Filename of the SE file in Audio/SE folder
  #        pitch : Pitch of sound (50 - 100)
  #       volume : Volume of sound (0 - 100)
  #--------------------------------------------------------------------------
  def play_se(filename, pitch=nil, volume=nil)
    se = RPG::AudioFile.new(filename)
    se.pitch  = pitch unless pitch.nil?
    se.volume = volume unless volume.nil?
    Audio.se_play('Audio/SE/' + se.name, se.volume, se.pitch)
  end
 
  def tile_sprites(tilesize)
    tiles = []
    # Iterate through main sprite, creating sprites for each square.
    (0...@sprite.bitmap.width / tilesize).each {|x|
      (0...@sprite.bitmap.height / tilesize).each {|y|
        sprite = Sprite.new(@sprite.viewport)
        sprite.x, sprite.y = x*tilesize, y*tilesize
        sprite.bitmap = Bitmap.new(tilesize, tilesize)
        rect = Rect.new(sprite.x, sprite.y, tilesize, tilesize)
        sprite.bitmap.blt(0, 0, @sprite.bitmap, rect)
        tiles.push(sprite)
      }
    }
    @sprite.opacity = 0
    return tiles
  end
 
  def double_zoom(frames = 30, zoom1 = 12, zoom2 = 32)
    # Calculate the stages. Account for final zoom being longer.
    stage3 = (frames * (zoom1.to_f / zoom2)).round
    stages = [(frames - stage3) / 2, (frames - stage3) / 2, stage3]
    # Calculate the zoom rates to apply each frame, for each stage.
    zoom_rates, opacity_rate = [zoom1-1, -zoom1+1, zoom2], (255 / frames.to_f)
    zoom_rates.each_index {|i| zoom_rates[i] /= stages[i].to_f }
    # Initialize local variable to keep track of current stage being executed.
    current_stage = 0
    3.times do
      # Iterate each stage, using the calculated rates for each one.
      stages[current_stage].times do
        @sprite.zoom_x += zoom_rates[current_stage]
        @sprite.zoom_y += zoom_rates[current_stage]
        @sprite.opacity -= opacity_rate
        Graphics.update
      end
      current_stage += 1
    end
  end


 
  #==========================================================================
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  # ** Effect Library
  #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  #==========================================================================
 
  #--------------------------------------------------------------------------
  # * Zoom In
  #     frames : Effect duration in frames
  #   max_zoom : The max amount the screen zooms out
  #--------------------------------------------------------------------------
  def zoom_in(frames=20, max_zoom=12)
    # Calculate difference b/w current and target
    # zooms (1 and max_zoom)
    zoom_diff = max_zoom - 1
    # Calculate unit values
    unit_zoom = zoom_diff.to_f / frames
    unit_opacity = (255.0 / frames).ceil
    # Apply unit values to sprite
    frames.times do
      @sprite.zoom_x += unit_zoom
      @sprite.zoom_y += unit_zoom
      @sprite.opacity -= unit_opacity
      Graphics.update
    end
  end
  #--------------------------------------------------------------------------
  # * Zoom Out
  #     frames : Effect duration in frames
  #--------------------------------------------------------------------------
  def zoom_out(frames=20)
    # Calculate unit values
    unit_zoom = 1.0 / frames
    unit_opacity = (255.0 / frames).ceil
    # Apply unit values to sprite
    frames.times do
      @sprite.zoom_x -= unit_zoom
      @sprite.zoom_y -= unit_zoom
      @sprite.opacity -= unit_opacity
      Graphics.update
    end
  end
  #--------------------------------------------------------------------------
  # * Shred Horizontal
  #      thickness : Shred thickness
  #       slowness : How slow the screens move out
  #    start_speed : Speed of first step in pixels
  #--------------------------------------------------------------------------
  def shred_h(thickness=4, slowness=4, start_speed=8)
    t = thickness
    # Shred screen
    sprite2 = Sprite.new(@sprite.viewport)
    sprite2.bitmap = Bitmap.new(@sprite.bitmap.width, @sprite.bitmap.height)
    sprite2.x = sprite2.ox = sprite2.bitmap.width / 2
    sprite2.y = sprite2.oy = sprite2.bitmap.height / 2
    for i in 0..(480/t)
      sprite2.bitmap.blt(0, i*t*2, @sprite.bitmap, Rect.new(0, i*t*2, 640, t))
      @sprite.bitmap.fill_rect(0, i*t*2, 640, t, Color.new(0, 0, 0, 0))
    end
    # Make sure starting step is not zero
    start_speed = slowness if start_speed < slowness
    # Move sprites
    dist = 640 - @sprite.x + start_speed
    loop do
      x_diff = (dist - (640 - @sprite.x)) / slowness
      @sprite.x += x_diff
      sprite2.x -= x_diff
      Graphics.update
      break if @sprite.x >= 640 + 320
    end
    sprite2.bitmap.dispose
    sprite2.dispose
  end
  #--------------------------------------------------------------------------
  # * Shred Vertical
  #      thickness : Shred thickness
  #       slowness : How slow the screens move out
  #    start_speed : Speed of first step in pixels
  #--------------------------------------------------------------------------
  def shred_v(thickness=4, slowness=4, start_speed=8)
    t = thickness
    # Shred screen
    sprite2 = Sprite.new(@sprite.viewport)
    sprite2.bitmap = Bitmap.new(@sprite.bitmap.width, @sprite.bitmap.height)
    sprite2.x = sprite2.ox = sprite2.bitmap.width / 2
    sprite2.y = sprite2.oy = sprite2.bitmap.height / 2
    # Shred bitmap
    for i in 0..(640/t)
      sprite2.bitmap.blt(i*t*2, 0, @sprite.bitmap, Rect.new(i*t*2, 0, t, 480))
      @sprite.bitmap.fill_rect(i*t*2, 0, t, 480, Color.new(0, 0, 0, 0))
    end
    # Make sure starting step is not zero
    start_speed = slowness if start_speed < slowness
    # Move sprites
    dist = 480 - @sprite.y + start_speed
    loop do
      y_diff = (dist - (480 - @sprite.y)) / slowness
      @sprite.y += y_diff
      sprite2.y -= y_diff
      Graphics.update
      break if @sprite.y >= 480 + 240
    end
    sprite2.bitmap.dispose
    sprite2.dispose
  end
  #--------------------------------------------------------------------------
  # * Shred Grid
  #      thickness : Shred thickness
  #       slowness : How slow the screens move out
  #    start_speed : Speed of first step in pixels
  #       priority : Which direction comes first (0 - vertical, 1 - horizontal)
  #--------------------------------------------------------------------------
  def shred_g(thickness=4, slowness=4, start_speed=8, priority = 0)
    t = thickness
    # Shred screen
    sprite2 = Sprite.new(@sprite.viewport)
    sprite2.bitmap = Bitmap.new(@sprite.bitmap.width, @sprite.bitmap.height)
    sprite2.x = sprite2.ox = sprite2.bitmap.width / 2
    sprite2.y = sprite2.oy = sprite2.bitmap.height / 2
    sprite3 = Sprite.new(@sprite.viewport)
    sprite3.bitmap = Bitmap.new(@sprite.bitmap.width, @sprite.bitmap.height)
    sprite3.x = sprite3.ox = sprite3.bitmap.width / 2
    sprite3.y = sprite3.oy = sprite3.bitmap.height / 2
    sprite4 = Sprite.new(@sprite.viewport)
    sprite4.bitmap = @sprite.bitmap.clone
    sprite4.x = sprite4.ox = sprite4.bitmap.width / 2
    sprite4.y = sprite4.oy = sprite4.bitmap.height / 2
    #sprite2.visible = sprite3.visible = sprite4.visible = false
    # Shred bitmap
    if priority == 0
      for i in 0..(640/t)
        sprite2.bitmap.blt(i*t*2, 0, @sprite.bitmap, Rect.new(i*t*2, 0, t, 480))
        @sprite.bitmap.fill_rect(i*t*2, 0, t, 480, Color.new(0, 0, 0, 0))
        sprite4.bitmap.fill_rect(i*t*2, 0, t, 480, Color.new(0, 0, 0, 0))
        sprite2.z = 4
        sprite3.z = 3
        @sprite.z = 2
        sprite4.z = 1
      end
      for i in 0..(480/t)
        sprite3.bitmap.blt(0, i*t*2, @sprite.bitmap, Rect.new(0, i*t*2, 640, t))
        @sprite.bitmap.fill_rect(0, i*t*2, 640, t, Color.new(0, 0, 0, 0))
        sprite4.bitmap.fill_rect(0, i*t*2, 640, t, Color.new(0, 0, 0, 0))
      end
    else
      for i in 0..(480/t)
        sprite3.bitmap.blt(0, i*t*2, @sprite.bitmap, Rect.new(0, i*t*2, 640, t))
        @sprite.bitmap.fill_rect(0, i*t*2, 640, t, Color.new(0, 0, 0, 0))
        sprite4.bitmap.fill_rect(0, i*t*2, 640, t, Color.new(0, 0, 0, 0))
        sprite3.z = 4
        sprite2.z = 3
        @sprite.z = 2
        sprite4.z = 1
      end
      for i in 0..(640/t)
        sprite2.bitmap.blt(i*t*2, 0, @sprite.bitmap, Rect.new(i*t*2, 0, t, 480))
        @sprite.bitmap.fill_rect(i*t*2, 0, t, 480, Color.new(0, 0, 0, 0))
        sprite4.bitmap.fill_rect(i*t*2, 0, t, 480, Color.new(0, 0, 0, 0))
      end
    end
    # Make sure starting step is not zero
    start_speed = slowness if start_speed < slowness
    # Move sprites
    disty = 480 - sprite4.y + start_speed
    distx = 640 - @sprite.y + start_speed
    loop do
      y_diff = (disty - (480 - sprite4.y)) / slowness
      x_diff = (distx - (640 - @sprite.x)) / slowness
      sprite4.y += y_diff
      sprite2.y -= y_diff
      @sprite.x += x_diff
      sprite3.x -= x_diff
      Graphics.update
      break if @sprite.x >= 640 + 320
    end
    sprite2.bitmap.dispose
    sprite2.dispose
    sprite3.bitmap.dispose
    sprite3.dispose
    sprite4.bitmap.dispose
    sprite4.dispose
  end
 
  def custom_tile_sprites(size_x, size_y, conditions, properties, centered = true)
    raise "Tile Error: not the same amount of conditions and properties" if conditions.length != properties.length
    tiles = []
    # Iterate through main sprite, creating sprites for each square.
    (0...@sprite.bitmap.width / size_x).each {|col|
      (0...@sprite.bitmap.height / size_y).each {|row|
        sprite = Sprite.new(@sprite.viewport)
        sprite.x += col*size_x
        sprite.y += row*size_y
        sprite.bitmap = Bitmap.new(size_x, size_y)
        rect = Rect.new(sprite.x, sprite.y, size_x, size_y)
        sprite.bitmap.blt(0, 0, @sprite.bitmap, rect)
        for i in 0...conditions.length
          if conditions[i].call(col, row)
            properties[i].each { |prop|
              sprite.send("#{prop[0]}=", prop[1])
              #sprite.zoom_x = 1
              #sprite.zoom_y = 1
            }
            break
          end
        end
        if centered
          sprite.ox = size_x / 2
          sprite.oy = size_y / 2
          sprite.x += size_x / 2
          sprite.y += size_y / 2
        end
        tiles.push(sprite)
      }
    }
    @sprite.opacity = 0
    return tiles
  end
 
  def effect3(size_x = 640, size_y = 4)
    tiles = custom_tile_sprites(size_x, size_y, [proc { true }], [{}])
    # Make sure starting step is not zero
    #start_speed = slowness if start_speed < slowness
   
    frames = 0
   
    while (tiles.select { |i| i.visible == true }).length > 0
      selected_length = (tiles.select { |i| i.visible == true }).length
      frames += 1
      for i in tiles
        i.visible = false if rand(selected_length / 4) == 0
      end
      Graphics.update
    end
   
    tiles.each { |tile|
      tile.bitmap.dispose
      tile.dispose
    }
  end
 
  def effect2(fade_length = 10, size_x = 20, size_y = 20)
    tiles = custom_tile_sprites(size_x, size_y, [proc { true }], [{}])
    # Make sure starting step is not zero
    #start_speed = slowness if start_speed < slowness
   
    frames = 0
    opac_diff = 255 / fade_length
   
    while (tiles.select { |i| i.visible == true }).length > 0
      selected_length = (tiles.select { |i| i.visible == true }).length
      frames += 1
      for i in tiles
        i.opacity -= opac_diff if (i.opacity != 255 and i.opacity > 0) or rand(selected_length / 4) == 0
        i.visible = false if i.opacity <= 0 and i.visible
      end
      Graphics.update
    end
   
    tiles.each { |tile|
      tile.bitmap.dispose
      tile.dispose
    }
  end
 
  def cover(dir = 0, duration = 40)
    frames = 0
    x_mod = case dir;when 7,0,1 then -640; when 3,4,5 then 640;else 0;end
    y_mod = case dir;when 1,2,3 then -480; when 5,6,7 then 480;else 0;end
    s_pos = []
    d_pos = []
    $game_system.disposables.each { |i|
      if i.respond_to?(:x=) and i.respond_to?(:y=)
        d_pos.push([i.x, i.y])
        i.x += x_mod
        i.y += y_mod
        s_pos.push([i.x, i.y])
      elsif i.is_a?(Tilemap)
        d_pos.push([i.ox, i.oy])
        i.ox -= x_mod
        i.oy -= y_mod
        s_pos.push([i.ox, i.oy])
      else
        d_pos.push([0, 0])
        s_pos.push([0, 0])
      end
      i.z = 100000 if i.respond_to?(:z=)
    }
    loop do
      frames += 1
      $game_system.disposables.each_with_index { |i, ind|
        if i.respond_to?(:x=) and i.respond_to?(:y=)
          ts_pos = s_pos[ind]
          td_pos = d_pos[ind]
          i.x = (ts_pos[0] * (duration - frames) + td_pos[0] * frames) / duration
          i.y = (ts_pos[1] * (duration - frames) + td_pos[1] * frames) / duration
        elsif i.is_a?(Tilemap)
          ts_pos = s_pos[ind]
          td_pos = d_pos[ind]
          i.ox = (ts_pos[0] * (duration - frames) + td_pos[0] * frames) / duration
          i.oy = (ts_pos[1] * (duration - frames) + td_pos[1] * frames) / duration
        end
        i.z = 100000 if i.respond_to?(:z=)
      }
      Graphics.update
      break if frames == duration
    end
  end
 
  def uncover(dir = 0, duration = 40)
    frames = 0
    x_mod = case dir;when 7,0,1 then -640; when 3,4,5 then 640;else 0;end
    y_mod = case dir;when 1,2,3 then -480; when 5,6,7 then 480;else 0;end
    s_pos = [@sprite.x, @sprite.y]
    d_pos = [s_pos[0] + x_mod, s_pos[1] + y_mod]
    loop do
      frames += 1
      @sprite.x = (s_pos[0] * (duration - frames) + d_pos[0] * frames) / duration
      @sprite.y = (s_pos[1] * (duration - frames) + d_pos[1] * frames) / duration
      Graphics.update
      break if frames == duration
    end
  end
 
  def shift(dir = 0, duration = 40)
    frames = 0
    x_mod = case dir;when 0 then -640; when 2 then 640;else 0;end
    y_mod = case dir;when 1 then -480; when 3 then 480;else 0;end
    s_pos = []
    d_pos = []
    $game_system.disposables.each { |i|
      if i.respond_to?(:x=) and i.respond_to?(:y=)
        d_pos.push([i.x, i.y])
        i.x += x_mod
        i.y += y_mod
        s_pos.push([i.x, i.y])
      else
        d_pos.push([0, 0])
        s_pos.push([0, 0])
      end
      i.z = 100000 if i.respond_to?(:z=)
    }
    s_pos.push([@sprite.x, @sprite.y])
    d_pos.push([@sprite.x - x_mod, @sprite.y - y_mod])
    @sprite.x, @sprite.y = *s_pos.last
    loop do
      frames += 1
      $game_system.disposables.each_with_index { |i, ind|
        if i.respond_to?(:x=) and i.respond_to?(:y=)
          ts_pos = s_pos[ind]
          td_pos = d_pos[ind]
          i.x = (ts_pos[0] * (duration - frames) + td_pos[0] * frames) / duration
          i.y = (ts_pos[1] * (duration - frames) + td_pos[1] * frames) / duration
        end
        i.z = 100000 if i.respond_to?(:z=)
      }
      ts_pos = s_pos.last
      td_pos = d_pos.last
      @sprite.x = (ts_pos[0] * (duration - frames) + td_pos[0] * frames) / duration
      @sprite.y = (ts_pos[1] * (duration - frames) + td_pos[1] * frames) / duration
      Graphics.update
      break if frames == duration
    end
  end
 
  #--------------------------------------------------------------------------
  # * Fade
  #     target_color : Color to fade to
  #           frames : Effect duration in frames
  #--------------------------------------------------------------------------
  def fade(target_color=Color.new(255, 255, 255), frames=10)
    loop do
      r = (@sprite.color.red   * (frames - 1) + target_color.red)   / frames
      g = (@sprite.color.green * (frames - 1) + target_color.green) / frames
      b = (@sprite.color.blue  * (frames - 1) + target_color.blue)  / frames
      a = (@sprite.color.alpha * (frames - 1) + target_color.alpha) / frames
      @sprite.color.red   = r
      @sprite.color.green = g
      @sprite.color.blue  = b
      @sprite.color.alpha = a
      frames -= 1
      Graphics.update
      break if frames <= 0
    end
    Graphics.freeze
  end
  #--------------------------------------------------------------------------
  # * Explode
  #     explosion_sound : The SE filename to use for explosion sound
  #--------------------------------------------------------------------------
  def explode(explosion_sound=Explosion_Sound)
    shake_count = 2
    shakes = 40
    tone = 0
    shakes.times do
      @sprite.ox = 320 + (rand(2) == 0 ? -1 : 1) * shake_count
      @sprite.oy = 240 + (rand(2) == 0 ? -1 : 1) * shake_count
      shake_count += 0.2
      tone += 128/shakes
      @sprite.tone.set(tone, tone, tone)
      Graphics.update
    end
    @sprite.ox, @sprite.oy = 320, 240
    Graphics.update
    bitmap = @sprite.bitmap.clone
    viewport = @sprite.viewport
    @sprite.bitmap.dispose
    @sprite.dispose
    # Slice bitmap and create nodes (sprite parts)
    hor = []
    20.times do |i|
      ver = []
      15.times do |j|
        # Set node properties
        s = Sprite.new(viewport)
        s.ox, s.oy = 8 + rand(25), 8 + rand(25)
        s.x, s.y = s.ox + 32 * i, s.oy + 32 * j
        s.bitmap = Bitmap.new(32, 32)
        s.bitmap.blt(0, 0, bitmap, Rect.new(i * 32, j * 32, 32, 32))
        s.tone.set(128, 128, 128)
        # Set node physics
        angle  = (rand(2) == 0 ? -1 : 1) * (4 + rand(4) * 10)
        zoom_x = (rand(2) == 0 ? -1 : 1) * (rand(2) + 1).to_f / 100
        zoom_y = (rand(2) == 0 ? -1 : 1) * (rand(2) + 1).to_f / 100
        (zoom_x > zoom_y) ? (zoom_y = -zoom_x) : (zoom_x = -zoom_y)
        x_rand = (2 + rand(2) == 0 ? -2 : 2)
        y_rand = (1 + rand(2) == 0 ? -1 : 1)
        # Store node and it's physics
        ver.push([s, angle, zoom_x, zoom_y, x_rand, y_rand])
      end
      hor.push(ver)
    end
    bitmap.dispose
    # Play sound
    play_se(explosion_sound) if explosion_sound != nil
    # Move pics
    40.times do |k|
      hor.each_with_index do |ver, i|
        ver.each_with_index do |data, j|
          # Get node and it's physics
          s, angle, zoom_x, zoom_y = data[0], data[1], data[2], data[3]
          x_rand, y_rand = data[4], data[5]
          # Manipulate nodes
          s.x += (i - 10) * x_rand
          s.y += (j - 8) * y_rand + (k - 20)/2
          s.zoom_x += zoom_x
          s.zoom_y += zoom_y
          tone = s.tone.red - 8
          s.tone.set(tone, tone, tone)
          s.opacity -= 13 if k > 19
          s.angle += angle % 360
        end
      end
      Graphics.update
    end
    # Dispose
    for ver in hor
      for data in ver
        data[0].bitmap.dispose
        data[0].dispose
      end
    end
    hor = nil
  end
  #--------------------------------------------------------------------------
  # * Explode (Chaos Project Style)
  #     explosion_sound : The SE filename to use for explosion sound
  #--------------------------------------------------------------------------
  def explode_cp(explosion_sound=Explosion_Sound)
    bitmap = @sprite.bitmap.clone
    viewport = @sprite.viewport
    @sprite.bitmap.dispose
    @sprite.dispose
    # Slice bitmap and create nodes (sprite parts)
    hor = []
    20.times do |i|
      ver = []
      15.times do |j|
        # Set node properties
        s = Sprite.new(viewport)
        s.ox = s.oy = 16
        s.x, s.y = s.ox + 32 * i, s.oy + 32 * j
        s.bitmap = Bitmap.new(32, 32)
        s.bitmap.blt(0, 0, bitmap, Rect.new(i * 32, j * 32, 32, 32))
        # Set node physics
        angle  = (rand(2) == 0 ? -1 : 1) * rand(8)
        zoom_x = (rand(2) == 0 ? -1 : 1) * (rand(2) + 1).to_f / 100
        zoom_y = (rand(2) == 0 ? -1 : 1) * (rand(2) + 1).to_f / 100
        # Store node and it's physics
        ver.push([s, angle, zoom_x, zoom_y])
      end
      hor.push(ver)
    end
    bitmap.dispose
    # Play sound
    play_se(explosion_sound) if explosion_sound != nil
    # Move pics
    40.times do |k|
      hor.each_with_index do |ver, i|
        ver.each_with_index do |data, j|
          # Get node and it's physics
          s, angle, zoom_x, zoom_y = data[0], data[1], data[2], data[3]
          # Manipulate node
          s.x += i - 9
          s.y += j - 8 + k
          s.zoom_x += zoom_x
          s.zoom_y += zoom_y
          s.angle += angle % 360
        end
      end
      Graphics.update
    end
    # Dispose
    for ver in hor
      for data in ver
        data[0].bitmap.dispose
        data[0].dispose
      end
    end
    hor = nil
  end
  #--------------------------------------------------------------------------
  # * Transpose (bt Blizzard)
  #     frames : Effect duration in frames
  #   max_zoom : The max amount the screen zooms out
  #      times : Number of times screen is zoomed (times * 3 / 2)
  #--------------------------------------------------------------------------
  def transpose(frames=80, max_zoom=12, times=3)
    max_zoom -= 1 # difference b/w zooms
    max_zoom = max_zoom.to_f / frames / times # unit zoom
    unit_opacity = (255.0 / frames).ceil
    spr_opacity = (255.0 * times / 2 / frames).ceil
    @sprites = []
    (times * 3 / 2).times {
      s = Sprite.new(@sprite.viewport)
      s.x, s.y, s.ox, s.oy = 320, 240, 320, 240
      s.bitmap = @sprite.bitmap
      s.blend_type = 1
      s.opacity = 128
      s.visible = false
      @sprites.push(s)}
    count = 0
    loop {
        @sprites[count].visible = true
        count += 1 if count < times * 3 / 2 - 1
        (frames / times / 2).times {
            @sprites.each {|s|
                break if !s.visible
                s.zoom_x += max_zoom
                s.zoom_y += max_zoom
                s.opacity -= spr_opacity}
            @sprite.opacity -= unit_opacity
        Graphics.update}
        break if @sprite.opacity == 0}
    @sprites.each {|s| s.dispose}
  end
  #--------------------------------------------------------------------------
  # * Shutter
  #       open_gap : How much the shutters open before moving away
  #       flip_dir : Whether or not the direction of shutters if reversed
  #       slowness : How slow the screens move out
  #    start_speed : Speed of first step in pixels
  #--------------------------------------------------------------------------
  def shutter(flip_dir=true, open_gap=16, slowness=4, start_speed=8)
    # Shred screen
    sprite2 = Sprite.new(@sprite.viewport)
    sprite2.bitmap = Bitmap.new(@sprite.bitmap.width, @sprite.bitmap.height)
    sprite2.x = sprite2.ox = sprite2.bitmap.width / 2
    sprite2.y = sprite2.oy = sprite2.bitmap.height / 2
    if flip_dir
      ver_step = 1
      sprite2.bitmap.blt(0, 240, @sprite.bitmap, Rect.new(0, 240, 640, 240))
      @sprite.bitmap.fill_rect(0, 240, 640, 240, Color.new(0, 0, 0, 0))
    else
      ver_step = -1
      sprite2.bitmap.blt(0, 0, @sprite.bitmap, Rect.new(0, 0, 640, 240))
      @sprite.bitmap.fill_rect(0, 0, 640, 240, Color.new(0, 0, 0, 0))
    end
    # Move the shutters apart
    open_gap.times do
      @sprite.y -= ver_step
      sprite2.y += ver_step
      Graphics.update
    end
    # Make sure starting step is not zero
    start_speed = slowness if start_speed < slowness
    # Move sprites
    dist = 640 - @sprite.x + start_speed
    loop do
      x_diff = (dist - (640 - @sprite.x)) / slowness
      @sprite.x += x_diff
      sprite2.x -= x_diff
      Graphics.update
      break if @sprite.x >= 640 + 320
    end
    sprite2.bitmap.dispose
    sprite2.dispose
  end
  #--------------------------------------------------------------------------
  # * Drop Off
  #     clink_sound : The SE filename to use for clinking sound
  #--------------------------------------------------------------------------
  def drop_off(clink_sound=Clink_Sound)
    bitmap = @sprite.bitmap.clone
    viewport = @sprite.viewport
    @sprite.bitmap.dispose
    @sprite.dispose
    # Slice bitmap and create nodes (sprite parts)
    max_time = 0
    hor = []
    10.times do |i|
      ver = []
      8.times do |j|
        # Set node properties
        s = Sprite.new(viewport)
        s.ox = rand(32)
        s.oy = 0
        s.x = s.ox + 64 * i
        s.y = s.oy + 64 * j
        s.bitmap = Bitmap.new(64, 64)
        s.bitmap.blt(0, 0, bitmap, Rect.new(i * 64, j * 64, 64, 64))
        # Set node physics
        angle = rand(4) * 2
        angle *= rand(2) == 0 ? -1 : 1
        start_time = rand(30)
        max_time = start_time if max_time < start_time
        # Store node and it's physics
        ver.push([s, angle, start_time])
      end
      hor.push(ver)
    end
    bitmap.dispose
    # Play sound
    play_se(clink_sound) if clink_sound != nil
    # Move pics
    (40 + max_time).times do |k|
      hor.each_with_index do |ver, i|
        ver.each_with_index do |data, j|
          # Get node and it's physics
          s, angle, start_time = data[0], data[1], data[2]
          # Manipulate node
          if k > start_time
            tone = s.tone.red - 6
            s.tone.set(tone, tone, tone)
            s.y += k - start_time
            s.angle += angle % 360
          elsif k == start_time
            tone = 128
            s.tone.set(tone, tone, tone)
            $game_system.se_play(Clink_Sound) if clink_sound != nil
          end
        end
      end
      Graphics.update
    end
    # Dispose
    for ver in hor
      for data in ver
        data[0].bitmap.dispose
        data[0].dispose
      end
    end
    hor = nil
  end
 
  def ff_IV_style(zoom1 = 1.2, zoom2 = 32)
    # Set number of frames and zoom rates for each stage.
    stages = [4, 4, 4, 4, 20]
    zooms = [zoom1, -zoom1, zoom1, -zoom1, zoom2]
    zooms.each_index {|i| zooms[i] /= stages[i].to_f }
    current_stage = 0
    5.times do
      # Begin processing.
      stages[current_stage].times do
        @sprite.zoom_x += zooms[current_stage]
        @sprite.zoom_y += zooms[current_stage]
        @sprite.opacity -= 12 if current_stage == 4
        Graphics.update
      end
      # Increase current stage.
      current_stage += 1
    end
  end

  def downward_spiral(frames = 40, rotation_speed = 15)
    # Calculate the zoom to subtract each frame.
    zoom, opacity = 1.0 / frames, 128.0 / frames
    frames.times do
      # Begin processing.
      @sprite.zoom_x -= zoom
      @sprite.zoom_y -= zoom
      @sprite.opacity -= opacity
      @sprite.angle += rotation_speed
      Graphics.update
    end
  end

  def blackhole(speed = 4, tilesize = 12, source = [320, 240])
    # Initialize squares array to hold each sprite.
    tiles = tile_sprites(tilesize)
    # Make each sprite slightly smaller than full size.
    tiles.each {|tile| tile.zoom_x = tile.zoom_y = 0.85 }
    # Begin looping until all sprites have been disposed.
    until tiles.compact == []
      # Iterate each tiles.
      tiles.each_index {|i|
        next if tiles[i] == nil
        # Get distance of this sprite from the source for each axis.
        sx = source[0] - tiles[i].x
        sy = source[1] - tiles[i].y
        # Calculate total distance and set base speed for each axis.
        dist = Math.hypot(sx, sy).to_f
        move_x = (dist / (sx == 0 ? 1 : sx))
        move_y = (dist / (sy == 0 ? 1 : sy))
        # Add a little randomness to the mix.
        move_x += move_x < 0 ? -rand(speed) : rand(speed)
        move_y += move_y < 0 ? -rand(speed) : rand(speed)
        # Apply movement.
        tiles[i].x += move_x
        tiles[i].y += move_y
        tiles[i].angle += rand(20)
        # If tile is within its own size from source, dispose it.
        if sx.abs <= tilesize && sy.abs <= tilesize
           tiles[i].bitmap.dispose
           tiles[i] = tiles[i].dispose
        end
      }
      Graphics.update
    end
  end

  def wave_distort(frames = 60, direction = 2, power = 0.4)
    radius, tiles = 0, tile_sprites(16)
    # Define starting point for zoom, depending on direction.
    origin = case direction
    when 2 then [@sprite.bitmap.width / 2, @sprite.bitmap.height]
    when 4 then [0, @sprite.bitmap.height / 2]
    when 6 then [@sprite.bitmap.width, @sprite.bitmap.height / 2]
    when 8 then [@sprite.bitmap.width / 2, 0]
    end
    # Initialize local variable for the rate the radius will increase.
    rate = Math.hypot(@sprite.bitmap.width, @sprite.bitmap.height) / frames
    # Begin processing.
    frames.times do
      # Iterate through each tile, calculating distance from focal point.
      tiles.each {|tile|
        dist = Math.hypot((origin[0] - tile.x), (origin[1] - tile.y))
        # Zoom tile on one axis, depending on direction.
        next if radius < dist
        [4, 6].include?(direction) ? tile.zoom_x += power : tile.zoom_y += power
      }
      # Increase radius for next iteration.
      radius += rate
      Graphics.update
    end
    # Dispose each bitmap and sprite used for the tiles.
    tiles.each {|tile| tile.bitmap.dispose; tile.dispose }
  end

 
  def radial_break(frames = 60, tilesize = 16, direction = 4, speed = 9)
    radius, tiles = 0, tile_sprites(tilesize)
    # Define starting point for zoom, depending on direction.
    origin = case direction
    when 2 then [@sprite.bitmap.width / 2, @sprite.bitmap.height]
    when 4 then [0, @sprite.bitmap.height / 2]
    when 6 then [@sprite.bitmap.width, @sprite.bitmap.height / 2]
    when 8 then [@sprite.bitmap.width / 2, 0]
    end
    # Initialize local variable for the rate the radius will increase.
    rate = Math.hypot(@sprite.bitmap.width, @sprite.bitmap.height) / frames
    # Begin processing.
    until tiles == []
      tiles.compact!
      # Iterate through each tile, calculating distance from focal point.
      tiles.each_index {|i|
        # Get distance of this sprite from the source for each axis.
        sx = origin[0] - tiles[i].x
        sy = origin[1] - tiles[i].y
        dist = Math.hypot(sx, sy).to_f
        # Zoom tile on one axis, depending on direction.
        next if radius < dist
        # Calculate total distance and set base speed for each axis.
        move_x = (dist / (sx == 0 ? 1 : sx))
        move_y = (dist / (sy == 0 ? 1 : sy))
        # Add a little randomness to the mix.
        move_x += move_x < 0 ? -rand(speed) : rand(speed)
        move_y += move_y < 0 ? -rand(speed) : rand(speed)
        # Half distance of one axis, depending on rate.
        [2, 8].include?(direction) ? move_x /= 2 : move_y /= 2
        # Apply movement.
        tiles[i].x += move_x
        tiles[i].y += move_y
        angle = (tiles[i].object_id % 2 == 0) ? rand(25) : -rand(25)
        tiles[i].angle += (angle + 5)
        # If tile is within its own size from source, dispose it.
        if sx.abs <= tilesize || sy.abs <= tilesize
           tiles[i].bitmap.dispose
           tiles[i] = tiles[i].dispose
        end
      }
      # Increase radius for next iteration.
      radius += rate / 2
      Graphics.update
    end
  end
end
#==============================================================================
# ** Game_Temp
#------------------------------------------------------------------------------
#  Added transition_type attribute which controls transition shown.
#==============================================================================
class Game_Temp 
  attr_accessor :transition_type
  attr_accessor :use_back
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  alias transpack_game_temp_init initialize
  def initialize
    @transition_type = 0
    @use_back = false
    transpack_game_temp_init
  end
end
#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
#  Scene_Map modded to use the transition effect when battle begins.
#==============================================================================
class Scene_Map
  #--------------------------------------------------------------------------
  # * Battle Call
  #--------------------------------------------------------------------------
  alias transpack_call_battle call_battle
  def call_battle
    transpack_call_battle
    $scene = Transition.new($scene, Transition::BATTLE_EFFECT, Transition::BATTLE_USE_BACK)
  end
  #--------------------------------------------------------------------------
  # * Shop Call
  #--------------------------------------------------------------------------
  alias transpack_call_shop call_shop
  def call_shop
    transpack_call_shop
    $scene = Transition.new($scene, Transition::SHOP_EFFECT, Transition::SHOP_USE_BACK, rand(4))
  end
  #--------------------------------------------------------------------------
  # * Name Input Call
  #--------------------------------------------------------------------------
  alias transpack_call_name call_name
  def call_name
    transpack_call_name
    $scene = Transition.new($scene, Transition::NAME_EFFECT, Transition::NAME_USE_BACK)
  end
  #--------------------------------------------------------------------------
  # * Menu Call
  #--------------------------------------------------------------------------
  alias transpack_call_menu call_menu
  def call_menu
    transpack_call_menu
    $scene = Transition.new($scene, Transition::MENU_EFFECT, Transition::MENU_USE_BACK, rand(8))
  end
  #--------------------------------------------------------------------------
  # * Save Call
  #--------------------------------------------------------------------------
  alias transpack_call_save call_save
  def call_save
    transpack_call_save
    $scene = Transition.new($scene, Transition::SAVE_EFFECT, Transition::SAVE_USE_BACK)
  end
  #--------------------------------------------------------------------------
  # * Player Place Move
  #--------------------------------------------------------------------------
  def transfer_player
    # Clear player place move call flag
    $game_temp.player_transferring = false
    # If move destination is different than current map
    if $game_map.map_id != $game_temp.player_new_map_id
      # Set up a new map
      $game_map.setup($game_temp.player_new_map_id)
    end
    # Set up player position
    $game_player.moveto($game_temp.player_new_x, $game_temp.player_new_y)
    # Set player direction
    case $game_temp.player_new_direction
    when 2  # down
      $game_player.turn_down
    when 4  # left
      $game_player.turn_left
    when 6  # right
      $game_player.turn_right
    when 8  # up
      $game_player.turn_up
    end
    # Straighten player position
    $game_player.straighten
    # Update map (run parallel process event)
    $game_map.update
    # Remake sprite set
    @spriteset.dispose
    @spriteset = Spriteset_Map.new
    # If processing transition
    if $game_temp.transition_processing
      # Clear transition processing flag
      $game_temp.transition_processing = false
      # Execute transition
      $scene = Transition.new($scene)
    end
    # Run automatic change for BGM and BGS set on the map
    $game_map.autoplay
    # Frame reset
    Graphics.frame_reset
    # Update input information
    Input.update
  end
end

class Game_System
  attr_accessor :disposables
 
  alias transition_init initialize
  def initialize
    transition_init
    @disposables = []
  end
end

module Modifier
  def self.included(mod)
    mod.module_eval {
      alias_method :tdks_trans_updt, :update
      define_method(:update) {
        return tdks_trans_updt() unless $scene.is_a?(Transition) or $skip_trans
      }
    }
  end
end

class Scene_Title;include Modifier;end
class Scene_Map;include Modifier;end
class Scene_Menu;include Modifier;end
class Scene_Item;include Modifier;end
class Scene_Skill;include Modifier;end
class Scene_Equip;include Modifier;end
class Scene_Status;include Modifier;end
class Scene_Save;include Modifier;end
class Scene_Load;include Modifier;end
class Scene_End;include Modifier;end
class Scene_Battle;include Modifier;end
class Scene_Shop;include Modifier;end
class Scene_Name;include Modifier;end
class Scene_Gameover;include Modifier;end
class Scene_Debug;include Modifier;end

module Disposable
  def self.included(mod)
    mod.module_eval {
      attr_accessor :disposable
   
      alias_method :tdks_trans_init, :initialize
      define_method(:initialize) { |*args|
        tdks_trans_init(*args)
        @disposable = false
      }
   
      alias_method :tdks_trans_disp, :dispose
      define_method(:dispose) {
        if $scene.is_a?(Transition) and (($scene.started and !@disposable)) and !self.is_a?(Sprite_Battler)
          if respond_to?(:z=)
            self.z -= 1000
          end
          if self.is_a?(Spriteset_Map) or self.is_a?(Spriteset_Battle)
            tdks_trans_disp
          end
          if (self.is_a?(Sprite) or self.is_a?(Plane)) and self.viewport != nil
            self.tone = self.viewport.tone.clone
            self.color = self.viewport.color.clone
          end
          if self.is_a?(Viewport)
            self.tone = Tone.new(0, 0, 0)
            self.color = Color.new(0, 0, 0, 0)
          end
          $game_system.disposables.push(self)
          return nil
        elsif self.is_a?(Window_Base) && self.disposed?
        else
          tdks_trans_disp
        end
      }
    }
  end
end

class Tilemap
  include Disposable
 
  alias tdks_trans_tileset tileset
  def tileset
    return tdks_trans_tileset unless self.disposed?
    return Bitmap.new(1, 1)
  end
 
  alias tdks_trans_autotiles autotiles
  def autotiles
    return tdks_trans_autotiles unless self.disposed?
    return Array.new(7) { Bitmap.new(1, 1) }
  end
end

class Plane
  include Disposable
end

class Sprite
  include Disposable
end

class Viewport
  include Disposable
end

class Window_Base
  include Disposable
end

class Bitmap
  include Disposable
end

class Spriteset_Map
  include Disposable
end

class Spriteset_Battle
  include Disposable
end

module RPG
  class Weather
    include Disposable
  end
end

module Graphics
  class << self
    alias new_transition transition unless method_defined?(:new_transition)
    alias new_update update unless method_defined?(:new_update)
  end
 
  def self.transition(*args)
    args.push(10) if args.length == 0
    args[0] = 0 if $scene.is_a?(Transition) or $skip_trans
    $skip_trans = nil if $skip_trans
    self.new_transition(*args)
  end
 
  def self.update
    self.new_update
    if $scene.is_a?(Transition) and $scene.started
      $game_system.disposables.each { |disp| disp.update if !(disp.is_a?(Tilemap) or disp.is_a?(Spriteset_Map) or disp.is_a?(Spriteset_Battle)) and disp.respond_to?(:update) }
    end
  end
end



Instructions

In the script.


Compatibility

None known, except transitions to Scene_Map showing the background won't work because of the way Tilemap is written.


Credits and Thanks


  • Fantasist

  • ForeverZero

  • ThallionDarkshine




Author's Notes

Note, you need this dll for this script to work.
13
RMXP Script Database / [XP] Ring Command Window
December 13, 2012, 08:42:10 pm
Ring Command Window
Authors: ThallionDarkshine
Version: 0.1
Type: Scripting Tool
Key Term: Scripting Tool



Introduction

This is just a script that aids in the creation of ring menus. It is a scripting tool that allows scripters to create ring command windows with icons and textual commands as well.


Features


  • Easily create ring command windows.




Screenshots




Demo

None.


Script

Spoiler: ShowHide

class Window_RingCommand
  OPEN_DURATION = 40
  ROTATE_DURATION = 20
 
  attr_reader :index
 
  def initialize(commands, radius, x, y)
    @commands = commands.map { |i| i[0] }
    @icons = commands.map { |i| RPG::Cache.icon(i[1]) }
    @angle = 270
    @radius = 0
    @opacity = 0
    @dest_rad = radius
    @pos = [x, y]
    @spriteset = Spriteset_Ring.new(commands, radius, x, y)
    @opening = false
    @closing = false
    @rotating = false
    @index = 0
    self.open(OPEN_DURATION, 180, 64)
    update
  end
 
  def update
    if Input.repeat?(Input::LEFT) and !@opening and !@closing and !@rotating
      @index = (@index + 1) % @icons.length
      angle = (270 + 360 * (@icons.length - @index) / @icons.length) % 360
      duration = ROTATE_DURATION
      self.rotate(duration, angle, false)
    end
    if Input.repeat?(Input::RIGHT) and !@opening and !@closing and !@rotating
      @index = (@index + @icons.length - 1) % @icons.length
      angle = (270 + 360 * (@icons.length - @index) / @icons.length) % 360
      duration = ROTATE_DURATION
      self.rotate(duration, angle, true)
    end
    if @opening
      @frames += 1
      @radius = @dest_rad * @frames / @duration
      @angle = @s_angle + (270 - @s_angle) * @frames / @duration
      @opacity = 255 * 2 * @frames / @duration
      if @frames == @duration
        @opening = false
      end
    elsif @closing
      @frames += 1
      @radius = @s_rad * (@duration - @frames) / @duration
      @angle = @s_angle * @frames / @duration + @d_angle * (@duration - @frames) / @duration
      @opacity = 255 * (@duration - @frames) * 2 / @duration
      if @frames == @duration
        @closing = false
      end
    elsif @rotating
      @frames += 1
      @angle = @d_angle * @frames / @duration + @s_angle * (@duration - @frames) / @duration
      if @frames == @duration
        @rotating = false
      end
    end
    @spriteset.set(@radius, @angle, @pos, @opacity)
  end
 
  def open(duration, angle, radius)
    @s_angle = @angle = @angle - angle
    @dest_rad = radius
    @radius = 0
    @duration = duration
    @frames = 0
    @opening = true
  end
 
  def close(duration, angle)
    @s_angle = @angle
    @d_angle = @angle - angle
    @s_rad = @radius
    @duration = duration
    @frames = 0
    @closing = true
  end
 
  def rotate(duration, angle, right)
    @s_angle = @angle
    @d_angle = angle
    if right
      while @d_angle < @s_angle
        @d_angle += 360
      end
      while @d_angle - @s_angle > 360
        @d_angle -= 360
      end
    elsif !right
      while @d_angle > @s_angle
        @d_angle -= 360
      end
      while @s_angle - @d_angle > 360
        @d_angle += 360
      end
    end
    @duration = duration
    @frames = 0
    @rotating = true
  end
 
  def dispose
    @icons.each { |i| i.dispose }
    @spriteset.dispose
  end
end

class Spriteset_Ring
  def initialize(commands, radius, x, y)
    @commands = commands.map { |i| i[0] }
    @icons = commands.map { |i| RPG::Cache.icon(i[1]) }
    @icon_sprites = @icons.map { |icon| s=Sprite.new;s.bitmap=icon;s }
    @angle = 270
    @radius = radius
    @pos = [x, y]
    @tsprites = @commands.map { |i|
      s=Sprite.new
      s.bitmap=Bitmap.new(1,1)
      rect=s.bitmap.text_size(i)
      s.bitmap=Bitmap.new(rect.width,rect.height)
      s.bitmap.draw_text(rect,i,1)
      s.ox=rect.width/2
      s.oy=rect.height/2
      s.x,s.y=*@pos
      s
    }
  end
 
  def set(radius, angle, pos, opacity)
    @radius = radius
    @angle = angle
    @pos = pos
    @icon_sprites.each { |i| i.opacity = opacity }
    @tsprites.each { |s| s.x,s.y=*@pos }
    update
  end
 
  def update
    @icon_sprites.each_with_index { |icon, ind|
      angle = (@angle + 360 * ind / @icons.length) % 360
      d = 360 / @icons.length
      if angle > 270 - d and angle < 270 + d
        dist = (angle - 270).abs
        vals = [-120 * dist / d, 100 * dist / d]
        alpha = 255 * (d - dist) / d
        icon.tone = Tone.new(vals[0], vals[0], vals[0], vals[1])
        @tsprites[ind].opacity = alpha
      else
        icon.tone = Tone.new(-120, -120, -120, 100)
        @tsprites[ind].opacity = 0
      end
      angle *= Math::PI / 180
      x, y = Math.cos(angle) * @radius + @pos[0] - icon.bitmap.width / 2, Math.sin(angle) * @radius + @pos[1] - icon.bitmap.height / 2
      icon.x, icon.y = x, y
    }
  end
 
  def dispose
    @icon_sprites.each { |i| i.dispose }
    @icons.each { |i| i.dispose }
    @tsprites.each { |i| i.dispose }
  end
end



Instructions

To create a ring command window use this:
Window_RingCommand.new(commands, radius, x, y)

commands should be an array of arrays containing the icon name and the command name.


Compatibility

There shouldn't be any.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

None
14
RMXP Script Database / [XP] Window Message Mod
December 13, 2012, 08:14:08 pm
Window Message Mod
Authors: ThallionDarkshine
Version: 2.1
Type: Message Add-on
Key Term: Message Add-on



Introduction

This is a small Window_Message mod I made a while ago to allow letter-by-letter text. It now also includes a way to create text animations such as growing, shrinking, rotating, or shaking text. You can also format text with things like bold, underline, etc.

New feature! You can now create text gradients!

Text Animations:

  • Grow

  • Rotate (rock back and forth)

  • Shrink

  • Shake

  • Float

  • Hue Rotate

  • Bounce

  • Letter Grow

  • Letter Swivel

  • Letter Shrink

  • Letter Colorize

  • Letter Fade

  • Letter Bounce

  • Letter Float



Formatting Properties

  • Bold

  • Italic

  • Underline

  • Overline (pretty much useless but I made it anyways)

  • Strikethrough




Features


  • Specify how many letters are added at a time, and at what interval they are added.

  • Specify word-by-word text

  • Message shortcut to change letter-by-letter options from default.

  • Create animated text!

  • Format text, making it bold, italic, etc.




Screenshots

I'll put some up if requested, but all this does is allow letter-by-letter text.


Demo

None yet.


Script

Spoiler: ShowHide

# Instructions on use of this script
#   - To change the letter-by-letter mode, use:
#       \l[CHAR_AMOUNT, FRAMES]
#         CHAR_AMOUNT - How many chars to add to the string every time it updates
#           note - Use 0 for word-by-word or any negative number for no letter-by-letter
#         FRAMES - How often to add CHAR_AMOUNT characters to the string
#   - To create animated text, use:
#       \a[TYPE]
#         TYPE - Which type of animation the text should have
#           0  - Turn off Animation
#           1  - Grow
#           2  - Rock
#           3  - Shrink
#           4  - Shake
#           5  - Float
#           6  - Color Rotate
#           7  - Bounce
#           8  - Fade
#           9  - Letter Grow (one at a time)
#           10 - Letter Grow (two at a time)
#           11 - Letter Swivel
#           12 - Letter Colorize
#           13 - Letter Fade (one at a time)
#           14 - Letter Fade (two at a time)
#           15 - Letter Shrink (one at a time)
#           16 - Letter Shrink (two at a time)
#           17 - Letter Bounce
#           18 - Letter Float
#      note - you can use simply \a to turn off the animation
#   - Formatting Stuff
#       Bold - <b></b>
#       Italic - <i></i>
#       Underline - <u></u>
#       Overline - <o></o>
#       Strikethrough - <s></s>
#   - To create gradient text, use:
#       <grad=COLOR1:COLOR2></grad>
#         COLOR1 - The left color.
#         COLOR2 - The right color.
#         note - colors can be specified either as RED, GREEN, BLUE or as COLOR_ID
#           or as #RRGGBB (hexadecimal)
#   - The \c[COLOR] command now allows you to specify colors as either RED, GREEN,
#       BLUE or as COLOR_ID or as #RRGGBB (hexadecimal)
#   - To make the letter-by-letter feature wait for a certain length at a some
#       point in the message, use:
#       \w[DURATION]
#         DURATION - How long to delay. Use 0 to wait for the accept button to
#           be pressed.
#         note - You can also use simply \w to wait for the accept button to be
#           pressed.

class Window_Message
 # text mode:
 #   0 - Normal
 #   1 - Letter-by-Letter
 #   2 - Word-by-Word
 DEFAULT_MODE = 1
 # default amount of characters at a time
 DEFAULT_CHARS = 1
 # default number of frames to characters
 DEFAULT_FRAMES = 5
 
 def get_text
   text = $game_temp.message_text
   @wait_points = []
   @wait_count = nil
   if text.gsub!(/\\l(?:\[([\-\d]+)(?:\s*\,\s*([\-\d]+))?\])?/, '') != nil
     @l_l = true
     @l_amnt = $1.nil? ? Window_Message::DEFAULT_CHARS : $1.to_i
     @l_frames = $2.nil? ? Window_Message::DEFAULT_FRAMES : $2.to_i
     @frames = 0
     @length = 0
     if @l_amnt < 0
       @l_l = false
     end
   else
     case Window_Message::DEFAULT_MODE
     when 0:
       @l_l = false
     when 1:
       @l_l = true
       @l_amnt = Window_Message::DEFAULT_CHARS
       @l_frames = Window_Message::DEFAULT_FRAMES
       @frames = 0
       @length = 0
     when 2:
       @l_l = true
       @l_amnt = 0
       @l_frames = Window_Message::DEFAULT_FRAMES
       @frames = 0
       @length = 0
     end
   end
   @text = ""
   begin
     last_text = text.clone
     text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
   end until text == last_text
   text.gsub!(/\\[Nn]\[([0-9]+)\]/) do
     $game_actors[$1.to_i] != nil ? $game_actors[$1.to_i].name : ""
   end
   # Change "\\\\" to "\000" for convenience
   text.gsub!(/\\\\/) { "\000" }
   unformatted = text.clone
   unformatted.gsub!(/\\[Cc]\[((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\]/, "")
   unformatted.gsub!(/\\[Aa]\[(\d+)\]/, "")
   unformatted.gsub!(/\<\/?[a-z]+\>/, '')
   unformatted.gsub!(/\<\/?grad\=((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\:((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\>/, '')
   unformatted.gsub!(/\\[Gg]/, '')
   # Change "\\C" to "\001"
   text.gsub!(/\\[Cc]\[((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\]/) { "\001[#{$1}]" }
   if text.gsub!(/\\[Gg]/, '') != nil and @l_l
     @gold_window = Window_Gold.new
     @gold_window.x = 560 - @gold_window.width
     if $game_temp.in_battle
       @gold_window.y = 192
     else
       @gold_window.y = self.y >= 128 ? 32 : 384
     end
     @gold_window.opacity = self.opacity
     @gold_window.back_opacity = self.back_opacity
   end
   tmp = unformatted.gsub(/[\n\r]/, '')
   while !(ind=tmp.index(/\\[Ww](?:\[(\d+)\])?/)).nil?
     unformatted.sub!(/\\[Ww](?:\[(\d+)\])?/, "")
     tmp.sub!(/\\[Ww](?:\[(\d+)\])?/, "")
     text.sub!(/\\[Ww](?:\[(\d+)\])?/, "")
     @wait_points.push([ind, ($1.nil? ? 0 : $1.to_i)])
   end
   x, y = 0, 0
   gradients = []
   @gradients = []
   # Get 1 text character in c (loop until unable to get text)
   while ((c = text.slice!(/./m)) != nil)
     @text += c
     if c == "\001" or c == "\002"
       next
     end
     if c == "<"    
       if text.index(/grad\=((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\:((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\>/) == 0
         gradient = [$1, $2, 4 + x, 32 * y, 0, 32]
         gradients.push(gradient)
         @text = @text.split('')
         @text = (@text.length == 1 ? "" : @text[0..@text.length - 2].join(''))
         text.sub!(/(grad\=((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\:((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\>)/, '')
         next
       elsif text.index('/grad>') == 0
         unless gradients.length == 0 or gradients.last[0].nil?
           gradient = gradients.pop()
           w = [gradient[4], x + 4 - gradient[2]].max
           h = [gradient[5], y * 32 - gradient[3]].max
           rect = Rect.new(gradient[2], gradient[3], w, h)
           @gradients.push([gradient[0], gradient[1], rect])
         end
         @text = @text.split('')
         @text = @text[0..@text.length - 2].join('')
         text.sub!(/(\/?[a-z]+\>)/, '')
         next
       end
       if text.index(/\/?[a-z]+\>/) == 0
         text.sub!(/(\/?[a-z]+\>)/, '')
         @text += $1
       end
     end
     if c == "\n"
       unless gradients.length == 0 or gradients.last[0].nil?
         gradients[-1][4] = [gradients[-1][3], x + 4 - gradients[-1][1]].max
         gradients[-1][5] += 32
       end
       x = 0
       y += 32
       if y >= $game_temp.choice_start
         x = 8
       end
     end
     x += self.contents.text_size(c).width
   end
   unless gradients.length == 0 or gradients.last[0].nil?
     gradient = gradients.pop()
     w = [gradient[4], x + 4 - gradient[2]].max
     h = [gradient[5], y * 32 - gradient[3]].max
     rect = Rect.new(gradient[2], gradient[3], w, h)
     @gradients.push([gradient[0], gradient[1], rect])
   end
   @unformatted = unformatted.clone
   @length = unformatted.length unless @l_l
 end
 
 alias tdks_message_refresh refresh
 def refresh
   if !$game_temp.message_text.nil?
     get_text
     @animations.each { |ani| ani.bitmap.dispose;ani.dispose } unless @animations.nil?
     @letter_animations.each { |ani| ani.dispose } unless @letter_animations.nil?
   end
   @animations = []
   @letter_animations = []
   self.contents.clear
   self.contents.font.color = normal_color
   x = y = 0
   @cursor_width = 0
   # Indent if choice
   if $game_temp.choice_start == 0
     x = 8
   end
   # If waiting for a message to be displayed
   if @text != nil
     self.contents.font = Font.new
     self.contents.font.underline = false
     self.contents.font.overline = false
     self.contents.font.strikethrough = false
     text = @text.clone
     real_index = 0
     index = 1
     animation = [0, []]
     lanimation = [0, []]
     p_bold = p_italic = p_underline = p_overline = p_strikethrough = []
     # Control text processing
     begin
       last_text = text.clone
       text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
     end until text == last_text
     text.gsub!(/\\[Nn]\[([0-9]+)\]/) do
       $game_actors[$1.to_i] != nil ? $game_actors[$1.to_i].name : ""
     end
     # Change "\\\\" to "\000" for convenience
     text.gsub!(/\\\\/) { "\000" }
     if @length == @text.length
       text.gsub!(/\\[Aa]/) { "\002" }
     else
       text.gsub!(/\\[Aa](?:\[(\d+)\])?/, "")
     end
     # Get 1 text character in c (loop until unable to get text)
     while ((c = text.slice!(/./m)) != nil)
       break if @length == 0
       real_index += 1
       # If \\
       if c == "\000"
         # Return to original text
         c = "\\"
       end
       # If \C[n]
       if c == "\001"
         # Change text color
         text.sub!(/\[((?:\d+(?:\s*\,\s*\d+)*)|(?:\#[\da-f]{6}))\]/, "")
         self.contents.font.color = get_color($1)
         # go to next text
         next
       end
       if c == "\002" and @length == @text.length
         if animation[0] != 0
           animation[1][-1].width = x + 4 - animation[1][-1].x
           @animations.push(animation)
         elsif lanimation[0] != 0
           @letter_animations.push(lanimation)
         end
         animation = [0, []]
         lanimation = [0, []]
         if text.index(/\[(\d+)\]/) == 0
           text.sub!(/\[(\d+)\]/, "")
           type = $1.to_i
           if type == 0
             animation[1] = []
           elsif type <= 8
             animation[0] = $1.to_i
             animation[1].push(Rect.new(4 + x, 32 * y, 0, 32))
           else
             lanimation[0] = $1.to_i - 8
           end
         else
           animation[0] = 0
           lanimation[0] = 0
         end
         next
       end
       if c == "<"
         if text.index('b>') == 0
           p_bold.push(self.contents.font.bold)
           self.contents.font.bold = true
         elsif text.index('i>') == 0
           p_italic.push(self.contents.font.italic)
           self.contents.font.italic = true
         elsif text.index('u>') == 0
           p_underline.push(self.contents.font.underline)
           self.contents.font.underline = true
         elsif text.index('o>') == 0
           p_overline.push(self.contents.font.overline)
           self.contents.font.overline = true
         elsif text.index('s>') == 0
           p_strikethrough.push(self.contents.font.strikethrough)
           self.contents.font.strikethrough = true
         end
         if text.index('/b>') == 0
           self.contents.font.bold = p_bold.pop
         elsif text.index('/i>') == 0
           self.contents.font.italic = p_italic.pop
         elsif text.index('/u>') == 0
           self.contents.font.underline = p_underline.pop
         elsif text.index('/o>') == 0
           self.contents.font.overline = p_overline.pop
         elsif text.index('/s>') == 0
           self.contents.font.strikethrough = p_strikethrough.pop
         end
         font = self.contents.font
         if text.index(/\/?[a-z]+\>/) == 0
           text.sub!(/\/?[a-z]+\>/, '')
           next
         end
       end
       # If new line text
       if c == "\n"
         # Update cursor width if choice
         if y >= $game_temp.choice_start
           @cursor_width = [@cursor_width, x].max
         end
         if animation[0] != 0
           animation[1][-1].width = x + 4 - animation[1][-1].x
         end
         # Add 1 to y
         y += 1
         x = 0
         # Indent if choice
         if y >= $game_temp.choice_start
           x = 8
         end
         if animation[0] != 0
           animation[1].push(Rect.new(x + 4, y * 32, 0, 32))
         end
         # go to next text
         next
       end
       # Draw text
       self.contents.draw_text(4 + x, 32 * y, 40, 32, c)
       # Add x to drawn text width
       size = self.contents.text_size(c)
       if lanimation[0] != 0
         lanimation[1].push(Rect.new(x + 4, y * 32, size.width, 32))
       end
       x += size.width
       index += 1
       break if index > @length
     end
     if animation[0] != 0
       animation[1][-1].width = x + 4 - animation[1][-1].x
       @animations.push(animation)
     elsif lanimation[0] != 0
       @letter_animations.push(lanimation)
     end
   end
   # If choice
   if $game_temp.choice_max > 0
     @item_max = $game_temp.choice_max
     self.active = true
     self.index = 0
   end
   # If number input
   if $game_temp.num_input_variable_id > 0
     digits_max = $game_temp.num_input_digits_max
     number = $game_variables[$game_temp.num_input_variable_id]
     @input_number_window = Window_InputNumber.new(digits_max)
     @input_number_window.number = number
     @input_number_window.x = self.x + 8
     @input_number_window.y = self.y + $game_temp.num_input_start * 32
   end
   $game_temp.message_text = nil
   overlay_grad = Win32API.new('overlay_grad.dll', 'overlay_grad', 'liiiiiiiiii', 'b')
   @gradients.reverse.each { |i|
     c1 = get_color(i[0])
     c2 = get_color(i[1])
     overlay_grad.call(self.contents.__id__, i[2].x, i[2].y, i[2].width, i[2].height, c1.red, c1.green, c1.blue, c2.red, c2.green, c2.blue)
   }
   if @length == @text.length
     @animations = @animations.map { |ani| AnimationSprite.new(ani[0], self.x + 16, self.y + 16, self.z + 1, ani[1], self.contents) }
     @letter_animations = @letter_animations.map { |ani| AnimationLetters.new(ani[0], self.x + 16, self.y + 16, self.z + 1, ani[1], self.contents) }
     @animations.each { |i| i.opacity = (@fade_in ? 0 : 255) }
     @letter_animations.each { |i| i.opacity = (@fade_in ? 0 : 255) }
   end
 end
 
 def get_color(str)
   if !str.index(',').nil?
     return Color.new(*str.split(/\s*\,\s*/))
   elsif str[0..0] == '#'
     return Color.new(str[1..2].hex, str[3..4].hex, str[5..6].hex)
   else
     return text_color(str.to_i)
   end
 end
 
 alias tdks_message_update update
 def update
   super
   if !@wait_count.nil?
     if @wait_count > 0
       @wait_count -= 1
       @wait_count = nil if @wait_count == 0
     else
       self.pause = true if !self.pause
       @wait_count = nil if Input.trigger?(Input::C)
     end
     return
   end
   # If letter-by-letter
   if !(@fade_in or (@fade_out == false and $game_temp.message_text != nil)) and @l_l and self.contents_opacity == 255
     @frames += 1
     if Input.trigger?(Input::C)
       @length = @text.length
     end
     return unless @frames % @l_frames == 0
     prev_len = @length
     unless @l_amnt == 0
       @length = [@length + @l_amnt, @text.length].min
     else
       s_text = @unformatted[0...@length]
       e_text = @unformatted[@length...@unformatted.length].clone
       e_text.gsub!(/\A[\n\r]+/, '')
       if e_text.index(/\w+/) == 0
         e_text.sub(/(\w+)/, '')
         @length += $1.length
         e_text = @unformatted[@length...@unformatted.length]
         if e_text.index(/[^\w]+/) == 0
           e_text.sub(/([^\w]+)/, '')
           tmp = $1.gsub(/[\n\r]/, '')
           @length += tmp.length
         end
       elsif e_text.index(/[^\w]+/) == 0
         e_text.sub(/([^\w]+)/, '')
         tmp = $1.gsub(/[\n\r]/, '')
         @length += tmp.length
         e_text = @unformatted[@length...@unformatted.length]
         if e_text.index(/\w+/) == 0
           e_text.sub(/(\w+)/, '')
           @length += $1.length
         end
       end
     end
     unless Input.trigger?(Input::C)
       if (wait = @wait_points.detect { |i| i[0].between?(prev_len, @length) }) != nil
         frames = wait[1]
         @wait_points.delete(wait)
         @wait_count = frames
         @length = wait[0]
       end
     end
     len = @unformatted.gsub(/[\n\r]/, '').length
     if @length >= len
       @length = @text.length
       @l_l = false
     end
     refresh
     return
   end
   @animations.each { |ani| ani.update } unless @animations.nil? or @animations.empty? or @fade_out
   @letter_animations.each { |ani| ani.update } unless @letter_animations.nil? or @fade_out
   # If fade in
   if @fade_in
     self.contents_opacity += 24
     @animations.each { |i| i.opacity = self.contents_opacity } unless @animations.nil?
     @letter_animations.each { |i| i.opacity = self.contents_opacity } unless @letter_animations.nil?
     if @input_number_window != nil
       @input_number_window.contents_opacity += 24
     end
     if self.contents_opacity == 255
       @fade_in = false
     end
     return
   end
   # If inputting number
   if @input_number_window != nil
     @input_number_window.update
     # Confirm
     if Input.trigger?(Input::C)
       $game_system.se_play($data_system.decision_se)
       $game_variables[$game_temp.num_input_variable_id] =
         @input_number_window.number
       $game_map.need_refresh = true
       # Dispose of number input window
       @input_number_window.dispose
       @input_number_window = nil
       terminate_message
     end
     return
   end
   # If message is being displayed
   if @contents_showing
     # If choice isn't being displayed, show pause sign
     if $game_temp.choice_max == 0
       self.pause = true
     end
     # Cancel
     if Input.trigger?(Input::B)
       if $game_temp.choice_max > 0 and $game_temp.choice_cancel_type > 0
         $game_system.se_play($data_system.cancel_se)
         $game_temp.choice_proc.call($game_temp.choice_cancel_type - 1)
         terminate_message
       end
     end
     # Confirm
     if Input.trigger?(Input::C)
       if $game_temp.choice_max > 0
         $game_system.se_play($data_system.decision_se)
         $game_temp.choice_proc.call(self.index)
       end
       terminate_message
     end
     return
   end
   # If display wait message or choice exists when not fading out
   if @fade_out == false and $game_temp.message_text != nil
     @contents_showing = true
     $game_temp.message_window_showing = true
     reset_window
     @fade_in = true
     refresh
     Graphics.frame_reset
     self.visible = true
     self.contents_opacity = 0
     if @input_number_window != nil
       @input_number_window.contents_opacity = 0
     end
     return
   end
   # If message which should be displayed is not shown, but window is visible
   if self.visible
     @fade_out = true
     self.opacity -= 48
     @animations.each { |i| i.opacity = self.opacity } unless @animations.nil?
     @letter_animations.each { |i| i.opacity = self.opacity } unless @letter_animations.nil?
     if self.opacity == 0
       self.visible = false
       @animations.each { |i| i.bitmap.dispose;i.dispose }
       @letter_animations.each { |i| i.dispose }
       @fade_out = false
       $game_temp.message_window_showing = false
     end
     return
   end
 end
end

class Font
 attr_accessor :underline, :overline, :strikethrough
 attr_accessor :outline, :outline_color, :outline_distance
 attr_accessor :shadow, :shadow_color, :shadow_ox, :shadow_oy
 
 alias tdks_message_init initialize
 def initialize(*args)
   tdks_message_init(*args)
   @underline = false
   @overline = false
   @strikethrough = false
   @outline, @outline_color, @outline_distance = false, Color.new(0, 0, 0), 0
   @shadow, @shadow_color, @shadow_ox, @shadow_oy = false, Color.new(127, 127, 127, 170), 2, 2
 end
end

class Bitmap
 alias tdks_message_draw_text draw_text
 def draw_text(*args)
   unless args[0].is_a?(Rect)
     args[0..3] = Rect.new(*args[0..3])
   end
   args[2] = 0 if args[2].nil?
   args[3] = 1 if args[3].nil?
   case args[3]
   when 0
     args[0].height = text_size(args[1]).height
   when 1
     h = text_size(args[1]).height
     args[0].y += (args[0].height - h) / 2
     args[0].height = h
   when 2
     h = text_size(args[1]).height
     args[0].y += args[0].height
     args[0].height = h
   end
   text = args[1].clone
   text = text.split(/[\n\r]/)
   rect = args[0].clone
   case args[3]
   when 1
     amnt = (text.length / 2.0).floor
     text[0...amnt].each { |ln| rect.y -= text_size(ln).height } if amnt > 0
     rect.y += text_size(text[0]).height / 2 if amnt % 2 == 1
   when 2
     text.each { |ln| rect.y -= text_size(ln).height }
   end
   text.each { |ln|
     orig_x = rect.x
     size = text_size(ln)
     case args[2]
     when 1
       rect.x += (rect.width - size.width) / 2
     when 2
       rect.x += rect.width - size.width
     end
     if font.shadow
       prev_color = font.color.clone
       font.color = font.shadow_color
       tdks_message_draw_text(rect.x + font.shadow_ox, rect.y + font.shadow_oy, rect.width, rect.height, ln)
       font.color = prev_color
     end
     if font.outline
       prev_color = font.color.clone
       font.color = font.outline_color
       (-font.outline_distance..font.outline_distance).each { |ox|
         (-font.outline_distance..font.outline_distance).each { |oy|
           next if ox == 0 and oy == 0
           tdks_message_draw_text(rect.x + ox, rect.y + oy, rect.width, rect.height, ln)
         }
       }
       font.color = prev_color
     end
     tdks_message_draw_text(rect, ln)
     if font.overline
       fill_rect(rect.x, rect.y + (size.height / 15.0).ceil, size.width, (size.height / 15.0).ceil, font.color)
     end
     if font.strikethrough
       fill_rect(rect.x, rect.y + size.height / 2, size.width, (size.height / 15.0).ceil, font.color)
     end
     rect.y += size.height
     if font.underline
       fill_rect(rect.x, rect.y - (2 * size.height / 15.0).ceil, size.width, (size.height / 15.0).ceil, font.color)
     end
     rect.x = orig_x
   }
 end
 
 def draw_gradient_text(c1, c2, *args)
   unless args[0].is_a?(Rect)
     args[0..3] = Rect.new(*args[0..3])
   end
   rect = args[0]
   tmp = Bitmap.new(rect.width, rect.height)
   tmp.draw_text(tmp.rect, *args[1...args.length])
   overlay_grad = Win32API.new('overlay_grad.dll', 'overlay_grad', 'liiiiiiiiii', 'b')
   overlay_grad.call(tmp.__id__, args[0].x, args[0].y, args[0].width, args[0].height, c1.red, c1.green, c1.blue, c2.red, c2.green, c2.blue)
   blt(rect.x, rect.y, tmp, tmp.rect)
 end
end

class AnimationSprite < Sprite
 def initialize(type, x, y, z, rects, src_bitmap)
   super()
   @type = type
   rects.delete_if { |rect| rect.width == 0 or rect.height == 0 }
   ry = rects.min { |i, e| i.y <=> e.y }.y
   rx = rects.min { |i, e| i.x <=> e.x }.x
   h = rects.max { |i, e| i.y + i.height <=> e.y + e.height }
   h = h.y + h.height - ry
   w = rects.max { |i, e| i.x + i.width <=> e.x + e.width }
   w = w.x + w.width - rx
   self.x, self.y, self.z = x + rx, y + ry, z
   self.ox, self.oy = w / 2, h / 2
   self.x += ox
   self.y += oy
   self.bitmap = Bitmap.new(w, h)
   rects.each { |rect|
     bitmap.blt(rect.x - rx, rect.y - ry, src_bitmap, rect)
     src_bitmap.fill_rect(rect, Color.new(0, 0, 0, 0))
   }
   @frames = 0
   @fplus = 1
   case @type
   when 4:
     @shake = [0, 0]
     @shaked = 1
   when 6:
     @frames = -40
   when 7:
     @frames = 2
   end
 end
 
 def update
   return if self.disposed?
   @frames += @fplus
   case @type
   when 1:
     z = 1.0 + @frames * 0.1 / 20
     @fplus = -1 if @frames == 20
     @fplus = 1 if @frames == 0
     self.zoom_x = z
     self.zoom_y = z
   when 2:
     a = @frames * 5.0 / 12
     @fplus = -1 if @frames == 12
     @fplus = 1 if @frames == -12
     self.angle = a
   when 3:
     z = 1.0 - @frames * 0.1 / 20
     @fplus = -1 if @frames == 20
     @fplus = 1 if @frames == 0
     self.zoom_x = z
     self.zoom_y = z
   when 4:
     shake_power = 1
     shake_speed = 10
     delta = (shake_power * shake_speed * @fplus) / 15.0 + rand(3) - 1
     @shake[0] += delta
     if @shake[0] > shake_power
       @fplus = -1
     end
     if @shake[0] < - shake_power
       @fplus = 1
     end
     delta = (shake_power * shake_speed * @shaked) / 15.0 + rand(3) - 1
     @shake[1] += delta
     if @shake[1] > shake_power
       @shaked = -1
     end
     if @shake[1] < - shake_power
       @shaked = 1
     end
     self.ox = self.bitmap.width / 2 + @shake[0]
     self.oy = self.bitmap.height / 2 + @shake[1]
   when 5:
     amnt = 5
     amnt *= Math.sin(Math::PI * @frames / 30.0)
     self.oy = self.bitmap.height / 2 + amnt
   when 6:
     if @frames < 0
       a = 255 + @frames * 255 / 40
       self.color.set(255, 0, 0, a)
       return
     end
     r = g = b = 0
     tmp = (@frames % 360) * 255 / 360
     while tmp < 0
       tmp += 255
     end
     if tmp < 85
       g = tmp * 3
       r = (85 - tmp) * 3
     elsif tmp < 170
       b = (tmp - 85) * 3
       g = (170 - tmp) * 3
     else
       r = (tmp - 170) * 3
       b = (255 - tmp) * 3
     end
     self.color.set(r, g, b)
   when 7:
     amnt = 10
     amnt *= Math.sin(Math::PI * @frames / 30.0).abs
     self.oy = self.bitmap.height / 2 + amnt - 5
   when 8:
     self.opacity = 255 - 170 * @frames / 20
     @fplus = -1 if @frames == 20
     @fplus = 1 if @frames == 0
   end
 end
end

class AnimationLetters
 def initialize(type, x, y, z, rects, src_bitmap)
   @type = type
   @sprites = []
   @data = []
   tmp_data = get_tmp_data(type, rects.length)
   rects.each { |rect|
     sprite = Sprite.new
     sprite.x, sprite.y, sprite.z = x + rect.x, y + rect.y, z
     sprite.bitmap = Bitmap.new(rect.width, rect.height)
     sprite.bitmap.blt(0, 0, src_bitmap, rect)
     sprite.ox, sprite.oy = rect.width / 2, rect.height / 2
     sprite.x += sprite.ox
     sprite.y += sprite.oy
     src_bitmap.fill_rect(rect, Color.new(0, 0, 0, 0))
     @sprites.push(sprite)
     @data.push(get_data(type, tmp_data))
   }
   case @type
   when 4:
     @frames = -40
   else
     @frames = 0
   end
   @fplus = 1
 end
 
 def get_tmp_data(type, length)
   case type
   when 1, 5, 7:
     data = Array.new(length) { |i| i }
     @duration = length * 31
     @no_end = true
   when 2, 6, 8:
     len = (length / 2.0).floor
     data = Array.new(len) { |i| i }
     data = data.concat(data.clone)
     if len % 2 == 1
       data.push(rand(len))
     end
     @duration = len * 31
     @no_end = true
   when 9, 10:
     data = Array.new(length) { |i| i }
   when 11, 12:
     tmp = Array.new(length) { |i| i }
     data = []
     length.times {
       ind = rand(tmp.length)
       data.push(tmp[ind])
       tmp.delete_at(ind)
     }
   else
     data = []
   end
   data
 end
 
 def get_data(type, tmp_data)
   data = {}
   case type
   when 1, 2, 5, 6, 7, 8:
     tmp = rand(tmp_data.length)
     data[:start] = tmp_data[tmp] * 31 + rand(11) - 5
     data[:middle] = data[:start] + 15
     while data[:start] < 0
       data[:start] += @duration
     end
     data[:end] = (data[:middle] + 15) % @duration
     tmp_data.delete_at(tmp)
   when 4:
     data[:hue] = rand(255)
     data[:mod] = rand(5) - 2
     while data[:mod] == 0
       data[:mod] = rand(5) - 2
     end
   when 9, 10, 11, 12:
     data[:end] = false
     len = tmp_data.length
     ind = tmp_data.shift
     len += ind
     data[:offset] = -ind * Math::PI / len
   end
   data
 end
 
 def update
   return if @sprites.any? { |i| i.disposed? }
   @frames += @fplus
   case @type
   when 1, 2:
     @frames %= @duration
     @sprites.each_with_index { |sprite, i|
       data = @data[i]
       cur_frames = @frames
       start = data[:start]
       middle = data[:middle]
       endf = data[:end]
       while endf < start
         endf += @duration
       end
       while middle < start
         middle += @duration
       end
       while cur_frames < start
         cur_frames += @duration
       end
       while cur_frames > endf
         cur_frames -= @duration
       end
       while (cur_frames - start) > @duration
         cur_frames -= @duration
       end
       while (start - cur_frames) > @duration
         cur_frames += @duration
       end
       if cur_frames.between?(start, middle)
         @no_end = false
         z = 1.0 + (cur_frames - start) * 0.5 / (middle - start)
         sprite.zoom_x = sprite.zoom_y = z
       elsif cur_frames.between?(middle, endf) and !@no_end
         z = 1.0 + (endf - cur_frames) * 0.5 / (endf - middle)
         sprite.zoom_x = sprite.zoom_y = z
       else
         sprite.zoom_x = sprite.zoom_y = 1.0
       end
       mod = rand(5) - 2
       @data[i][:start] += mod
       @data[i][:middle] += mod
       @data[i][:end] += mod
     }
   when 3:
     a = @frames * 10.0 / 12
     @fplus = -1 if @frames == 30
     @fplus = 1 if @frames == -30
     @sprites.each { |i| i.angle = a }
   when 4:
     if @frames < 0
       a = 255 + @frames * 255 / 40
       @sprites.each_with_index { |sprite, i|
         @data[i][:hue] += @data[i][:mod]
         color = get_color(@data[i][:hue])
         color.alpha = a
         sprite.color = color
       }
       return
     end
     @sprites.each_with_index { |sprite, i|
       @data[i][:hue] += @data[i][:mod]
       color = get_color(@data[i][:hue])
       sprite.color = color
     }
   when 5, 6:
     @frames %= @duration
     @sprites.each_with_index { |sprite, i|
       data = @data[i]
       cur_frames = @frames
       start = data[:start]
       middle = data[:middle]
       endf = data[:end]
       while endf < start
         endf += @duration
       end
       while middle < start
         middle += @duration
       end
       while cur_frames < start
         cur_frames += @duration
       end
       while cur_frames > endf
         cur_frames -= @duration
       end
       while (cur_frames - start) > @duration
         cur_frames -= @duration
       end
       while (start - cur_frames) > @duration
         cur_frames += @duration
       end
       if cur_frames.between?(start, middle)
         @no_end = false
         sprite.opacity = 255 - (cur_frames - start) * 170 / (middle - start)
       elsif cur_frames.between?(middle, endf) and !@no_end
         sprite.opacity = 255 - (endf - cur_frames) * 170 / (endf - middle)
       else
         sprite.opacity = 255
       end
       mod = rand(5) - 2
       @data[i][:start] += mod
       @data[i][:middle] += mod
       @data[i][:end] += mod
     }
   when 7, 8:
     @frames %= @duration
     @sprites.each_with_index { |sprite, i|
       data = @data[i]
       cur_frames = @frames
       start = data[:start]
       middle = data[:middle]
       endf = data[:end]
       while endf < start
         endf += @duration
       end
       while middle < start
         middle += @duration
       end
       while cur_frames < start
         cur_frames += @duration
       end
       while cur_frames > endf
         cur_frames -= @duration
       end
       while (cur_frames - start) > @duration
         cur_frames -= @duration
       end
       while (start - cur_frames) > @duration
         cur_frames += @duration
       end
       if cur_frames.between?(start, middle)
         @no_end = false
         z = 1.0 - (cur_frames - start) * 0.5 / (middle - start)
         sprite.zoom_x = sprite.zoom_y = z
       elsif cur_frames.between?(middle, endf) and !@no_end
         z = 1.0 - (endf - cur_frames) * 0.5 / (endf - middle)
         sprite.zoom_x = sprite.zoom_y = z
       else
         sprite.zoom_x = sprite.zoom_y = 1.0
       end
       mod = rand(5) - 2
       @data[i][:start] += mod
       @data[i][:middle] += mod
       @data[i][:end] += mod
     }
   when 9, 11:
     @sprites.each_with_index { |sprite, i|
       data = @data[i]
       mod = 10 * Math.sin(Math::PI * @frames / 45.0 + data[:offset]).abs - 5
       mod2 = 10 * Math.sin(Math::PI * (@frames + 1) / 45.0 + data[:offset]).abs - 5
       if mod > 0 and mod <= 10 * Math.sin(Math::PI * 6 / 30.0).abs - 5 and mod2 > 0
         @data[i][:end] = true
       else
         next unless @data[i][:end]
       end
       sprite.oy = sprite.bitmap.height / 2 + mod
     }
   when 10, 12:
     @sprites.each_with_index { |sprite, i|
       data = @data[i]
       mod = 5 * Math.sin(Math::PI * @frames / 30.0 + data[:offset])
       mod2 = 5 * Math.sin(Math::PI * (@frames + 1) / 30.0 + data[:offset])
       #p 10 * Math.sin(Math::PI * 2 * 3 / 30.0) - 5
       #p mod
       if mod > 0 and mod <= 5 * Math.sin(Math::PI * 6 / 30.0) and mod2 > 0
         @data[i][:end] = true
       else
         next unless @data[i][:end]
       end
       sprite.oy = sprite.bitmap.height / 2 + mod
     }
   end
 end
 
 def get_color(hue)
   r = g = b = 0
   tmp = hue % 255
   while tmp < 0
     tmp += 255
   end
   if tmp < 85
     g = tmp * 3
     r = (85 - tmp) * 3
   elsif tmp < 170
     b = (tmp - 85) * 3
     g = (170 - tmp) * 3
   else
     r = (tmp - 170) * 3
     b = (255 - tmp) * 3
   end
   return Color.new(r, g, b)
 end
 
 def opacity=(val)
   @sprites.each { |i| i.opacity = val }
 end
 
 def dispose
   @sprites.each { |i| i.bitmap.dispose;i.dispose }
 end
end



Instructions

You can configure default message options. Instructions on how to configure are in the script.
Instructions on the different message tags you can use are also in the script.
A dll is now required for the gradient text feature. It is found here.


Compatibility

Probably won't work with any other custom message scripts, but if you like, I'll try to tweak it to work with that specific script.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

A dll is now required for the gradient text feature. It is found here.
15
RMXP Script Database / [XP] Troop Treasures
December 13, 2012, 08:04:41 pm
Troop Treasures
Authors: ThallionDarkshine
Version: 0.1
Type: Treasure Add-on
Key Term: Enemy Add-on



Introduction

You ever have a troop filled with many small creatures at the start of your game? You want them to give you exp and gold, but assigning individual rewards would give the player way too much exp/gold. Enter Troop Treasures. This script allows you to setup treasures by encounter, in addition to normal rewards.


Features


  • Add as many item drops as you want, each with its own drop chance

  • Configure rewards by encounter, as well as by monster




Screenshots

It would just be a picture of the battle result window, and you all can imagine that, right?


Demo

None yet.


Script

Spoiler: ShowHide

module Treasure_Config
  def self.troop_treasures(troop_id)
    case troop_id
    when 6 then return [3, 5, []]
    when 7 then return [1, 2, []]
    else return []
    end
  end
end

class Scene_Battle
  alias tdks_treasure_strt_p5 start_phase5
  def start_phase5
    tdks_treasure_strt_p5
    t_treasures = Treasure_Config.troop_treasures(@troop_id)
    if t_treasures.length > 0
      $game_party.gain_gold(t_treasures[1])
      for i in 0...$game_party.actors.size
        actor = $game_party.actors[i]
        if actor.cant_get_exp? == false
          last_level = actor.level
          actor.exp += t_treasures[0]
          if actor.level > last_level
            @status_window.level_up(i)
          end
        end
      end
      new_treasures = []
      t_treasures[2].each { |treasure|
        if rand(100) < treasure[0]
          case treasure[1]
          when 0:
            new_treasures.push($data_items[treasure[2]])
            $game_party.gain_item(treasure[2], treasure[3])
          when 1:
            new_treasures.push($data_weapons[treasure[2]])
            $game_party.gain_weapon(treasure[2], treasure[3])
          when 2:
            new_treasures.push($data_armors[treasure[2]])
            $game_party.gain_armor(treasure[2], treasure[3])
          end
        end
      }
     
      @result_window.exp += t_treasures[0]
      @result_window.gold += t_treasures[1]
      @result_window.treasures += new_treasures
      @result_window.height += new_treasures.length * 32
      @result_window.contents = Bitmap.new(@result_window.width - 32, @result_window.height - 32)
      @result_window.refresh
    end
  end
end

class Window_BattleResult
  attr_accessor :exp, :gold, :treasures
end



Instructions

To add a new treasure, go to this line:
def self.troop_treasures(troop_id)

Insert treasures using this template:
when TROOP_ID then return [EXP_DROP, GOLD_DROP, ITEMS_ARRAY]

To insert an item into the items array, use this template:
[DROP_CHANCE, ITEM_TYPE, ITEM_ID, ITEM_AMOUNT]

The item types are as follows:
  0 - Item
  1 - Weapon
  2 - Armor



Compatibility

Might be issues with some CBSs.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

None
16
RMXP Script Database / [XP] Battler States
December 13, 2012, 07:53:47 pm
Battler States
Authors: ThallionDarkshine
Version: 0.1
Type: Battle Add-on
Key Term: Battle Add-on



Introduction

Another script with a quite ambiguous name from me. This script allows users to configure different ranges of health that each have their own custom tag that is added to enemies' names. Actors have these health "states" too, but they are not shown in their names. This is another cool feature from Blizz's game that I really liked because it allows players to see enemies health without giving away actual numbers.


Features


  • Add health "states" to battlers

  • Create different "states" for different ranges of health

  • Show custom tags in enemy names for each "state"




Screenshots

None required, would just be a picture showing a tag like "[Excellent]" in an enemy's name.


Demo

None yet.


Script

Spoiler: ShowHide

class Game_Battler
  attr_reader :state
 
  STATES = [
    [0..6, '[Critical]'],
    [7..36, '[Bad]'],
    [37..65, '[OK]'],
    [66..92, '[Good]'],
    [93..100, '[Excellent]'],
  ]
 
  alias tdks_state_init initialize
  def initialize(*args)
    tdks_state_init(*args)
    @state = Game_Battler::STATES.detect { |i| 100.between?(i[0].first, i[0].last) }[1]
  end
 
  alias tdks_state_hp= hp=
  def hp=(val)
    self.tdks_state_hp=(val)
    percent = (@hp * 100.0 / maxhp).ceil
    @state = Game_Battler::STATES.detect { |i| percent.between?(i[0].first, i[0].last) }[1] unless @hp == 0
  end
end

class Game_Enemy
  alias tdks_state_name name
  def name
    return tdks_state_name + ' ' + @state
  end
end



Instructions

Just paste the script in, configure the states like this:
[HEALTH_RANGE_MIN..HEALTH_RANGE_MAX, TAG_NAME]



Compatibility

I don't think there are any issues.


Credits and Thanks


  • ThallionDarkshine

  • Blizz for making CP




Author's Notes

None
17
RMXP Script Database / [XP] Windowskin Creator
November 23, 2012, 10:22:19 pm
Windowskin Creator
Authors: ThallionDarkshine
Version: 1.0
Type: Options Menu
Key Term: Menu Add-on



Introduction

This script allows users to customize their own windowskins using the windowskins included in the windowskins folder. They can use parts of the existing windowskins to customize their own windowskin. Also allows them to change some font settings such as bold, italic, size, and normal_color, system_color, critical_color, etc. And once they are done creating their windowskins, they can save them.


Features


  • Allow users to create custom windowskins.

  • Allow users to recolor their windowskins.

  • Choose whether or not to use the RTP windowskins.

  • Allow users to save their windowskins.

  • Allow users to customize font properties.




Screenshots

Spoiler: ShowHide





Demo

No demo yet.


Script

Spoiler: ShowHide

module Windowskin_Config
 USE_RTP = false
end

class Scene_Windowskin
 def initialize
   @old_wskin = $game_system.config.windowskin_bitmap.clone
   @windowskins = []
   @bitmaps = []
   @inds = $game_system.config.wskin_inds.clone
   @names = $game_system.config.wskin_names.clone
   @props = $game_system.config.wskin_props.clone
   @old_font = Font.new
   @old_font.color = $game_system.config.normal_color
   @font = [$game_system.config.font_size, Font.default_bold, Font.default_italic]
   @normal_color, @system_color, @disabled_color, @crisis_color, @knockout_color = $game_system.config.normal_color.clone, $game_system.config.system_color.clone, $game_system.config.disabled_color.clone, $game_system.config.crisis_color.clone, $game_system.config.knockout_color.clone
   @windowskins.push('None')
   @bitmaps.push(Bitmap.new(192, 128))
   paths = []
   ini = Win32API.new('kernel32', 'GetPrivateProfileStringA', 'PPPPLP', 'L')
   library = "\0" * 256
   ini.call('Game', 'Library', '', @library, 256, '.\\Game.ini')
   library.delete!("\0")
   getpath = Win32API.new(library, 'RGSSGetRTPPath', 'l', 'p')
   (1..3).each { |i| tmp = getpath.call(i);paths.push(tmp) unless tmp == '' } if Windowskin_Config::USE_RTP
   paths.push('')
   paths.each { |path|
     Dir[path + (path == '' ? '' : '/') + 'Graphics/Windowskins/*.{png,jpg,gif}'].each { |i|
       @windowskins.push(File.basename(i, '.*'))
       @bitmaps.push(RPG::Cache.windowskin(@windowskins.last))
     }
   }
 end
 
 def main
   # Create Main Command Window
   #  - This window displays windowskin options for designing and recoloring
   #   windowskins.
   s = ['Window Background', 'Window Frame', 'Scroll Arrows', 'Selection Bar', 'Pause Graphic', 'Battle Arrows']
   @command_window = Window_Command.new(256, s)
   @command_window.active = false
   # Create Windowskins Command Window
   #  - This window displays a list of all the windowskins for designing a
   #   windowskin.
   s = @windowskins.clone
   @wcommand_window = Window_Command.new(256, s)
   @wcommand_window.height = 256
   @wcommand_window.y = 224
   @wcommand_window.visible = @wcommand_window.active = false
   # Create Initial Command Window
   #  - This window displays the main choices.
   s = ['Windowskin Creation', 'Windowskin Recolors', 'Font Options', 'Save Config', 'Load Config', 'Exit']
   @scommand_window = Window_Command.new(288, s)
   @scommand_window.x = 176
   @scommand_window.y = 128
   @scommand_window.z = 1000
   # Create Recolor Command Window
   #  - This window displays recolor options such as hue and saturation.
   s = Array.new(3) { '' }
   @rcommand_window = Window_Command.new(256, s)
   @rcommand_window.height = 256
   @rcommand_window.y = 224
   @rcommand_window.active = @rcommand_window.visible = false
   # Create Font Command Window
   #  - This window displays options for changing font options.
   s = ['Font', 'Normal Color', 'System Color', 'Disabled Color', 'Crisis Color', 'Knockout Color']
   @fcommand_window = Window_Command.new(256, s)
   @fcommand_window.active = @fcommand_window.visible = false
   # Create Font Command Window
   #  - This window displays options for changing default font options.
   s = Array.new(4) { '' }
   @fcommand_window2 = Window_Command.new(256, s)
   @fcommand_window2.height = 256
   @fcommand_window2.y = 224
   @fcommand_window2.active = @fcommand_window2.visible = false
   # Create Color Command Window
   #  - This window displays options for choosing colors.
   s = Array.new(4) { '' }
   @ccommand_window = Window_Command.new(256, s)
   @ccommand_window.height = 256
   @ccommand_window.y = 224
   @ccommand_window.active = @ccommand_window.visible = false
   # Create Load Command Window
   #  - This window displays options for loading configurations.
   s = $data_configs.keys
   s = [''] if s.empty?
   @lcommand_window = Window_Command.new(288, s)
   @lcommand_window.height = 224
   @lcommand_window.x = 176
   @lcommand_window.y = 128
   @lcommand_window.z = 1000
   @lcommand_window.active = @lcommand_window.visible = false
   # Create Viewport
   #  - This dims the windows in the background.
   @viewport = Viewport.new(0, 0, 640, 480)
   @viewport.z = 999
   @viewport.tone = Tone.new(-70, -70, -70, 100)
   # Create 1st Windowskin Preview Window
   #  - This window displays the current chosen option while recoloring and
   #   designing windowskins.
   @preview_window = Window_WindowskinPreview.new(0)
   @preview_window.x = 256
   # Create 2nd Windowskin Preview Window
   #  - This window displays a preview of new windowskin options.
   @preview_window2 = Window_WindowskinPreview.new(1)
   @preview_window2.x = 256
   @preview_window2.y = 224
   @preview_window2.height = 256
   @preview_window2.visible = false
   # Create 1st Font Preview Window
   #  - This window displays the current chosen options while customizing fonts.
   font = Font.new
   font.color = @preview_window.normal_color
   @fpreview_window = Window_FontPreview.new(font, $game_system.config.font_size)
   @fpreview_window.x = 256
   @fpreview_window.visible = false
   # Create 2nd Font Preview Window
   #  - This window displays a preview of new font options.
   @fpreview_window2 = Window_FontPreview.new(font, $game_system.config.font_size)
   @fpreview_window2.x = 256
   @fpreview_window2.y = 224
   @fpreview_window2.height = 256
   @fpreview_window2.visible = false
   # Create Dummy Window
   #  - This window displays a preview of what the new windowskin would look like.
   @dummy_window = Window_Base.new(0, 224, 640, 256)
   @dummy_window.contents = Bitmap.new(642, 258)
   @dummy_window.contents.font.color = @normal_color.clone
   @dummy_window.contents.draw_text(Rect.new(1, 1, 640, 32), "This is an example window to demonstrate the windowskin you have", 0)
   @dummy_window.contents.draw_text(Rect.new(1, 33, 640, 32), "created.", 0)
   @contents = @dummy_window.contents.clone
   @dummy_window.cursor_rect.set(0, 64, 608, 64)
   @dummy_window.pause = true
   @dummy_window.ox = @dummy_window.oy = 1
   # Create Text Window
   #  - This window allows the user to choose a name for their config.
   @text_window = Window_Text.new(192, 208, 256, 64)
   @text_window.z = 1000
   @text_window.multi_line = false
   @text_window.active = @text_window.visible = false
   # Execute Transition
   Graphics.transition
   # Main loop
   loop do
     # Update game screen
     Graphics.update
     # Update input information
     Input.update
     # Frame update
     update
     # Abort loop if screen is changed
     if $scene != self
       break
     end
   end
   # Prepare for transition
   Graphics.freeze
   $game_system.config.wskin_inds = @inds.clone
   $game_system.config.wskin_names = @names.clone
   $game_system.config.wskin_props = @props.clone.map { |i| i.clone if i.is_a?(Array) }
   $game_system.config.normal_color, $game_system.config.system_color, $game_system.config.disabled_color, $game_system.config.crisis_color, $game_system.config.knockout_color = @normal_color.clone, @system_color.clone, @disabled_color.clone, @crisis_color.clone, @knockout_color.clone
   # Dispose of windows
   @command_window.dispose
   @wcommand_window.dispose
   @scommand_window.dispose
   @rcommand_window.dispose
   @fcommand_window.dispose
   @fcommand_window2.dispose
   @ccommand_window.dispose
   @lcommand_window.dispose
   @viewport.dispose
   @preview_window.dispose
   @preview_window2.dispose
   @fpreview_window.dispose
   @fpreview_window2.dispose
   @dummy_window.dispose
   @text_window.dispose
 end
 
 def update
   if @command_window.active
     update_command
   elsif @wcommand_window.active
     update_chooser
   elsif @scommand_window.active
     update_scommand
   elsif @rcommand_window.active
     update_recolor
   elsif @fcommand_window.active
     update_text
   elsif @fcommand_window2.active
     update_font
   elsif @ccommand_window.active
     update_color
   elsif @text_window.active
     update_save
   elsif @lcommand_window.active
     update_load
   end
 end
 
 def update_command
   if Input.trigger?(Input::B)
     $game_system.se_play($data_system.cancel_se)
     Graphics.freeze
     @viewport.tone = Tone.new(-70, -70, -70, 100)
     @scommand_window.visible = @scommand_window.active = true
     if @mode == 1
       s = @command_window.commands.clone
       s.shift
       @command_window.dispose
       @command_window = Window_Command.new(256, s)
       @command_window.windowskin = @old_wskin
       @command_window.contents.font = @old_font
       @command_window.refresh
     end
     @command_window.active = false
     Graphics.transition
   end
   @command_window.update
   @dummy_window.update
   if Input.trigger?(Input::C)
     $game_system.se_play($data_system.decision_se)
     Graphics.freeze
     case @mode
     when 0:
       @command_window.active = @dummy_window.active = @dummy_window.visible = false
       @wcommand_window.visible = @preview_window2.visible = @wcommand_window.active = @preview_window2.active = true
       @preview_window.set(1, @command_window.index)
       @wcommand_window.index = @inds[@command_window.index]
       @preview_window2.set(1, @command_window.index, @windowskins[@wcommand_window.index])
     when 1:
       @command_window.active = @dummy_window.active = @dummy_window.visible = false
       @rcommand_window.visible = @preview_window2.visible = @rcommand_window.active = @preview_window2.active = true
       @preview_window.set(1, (@command_window.index == 0 ? 6 : @command_window.index - 1), (@command_window.index == 0 ? '' : @names[@command_window.index - 1]))
       @preview_window.set_props(@props[@command_window.index])
       @saved_props = @props[@command_window.index]
       @preview_window2.set(1, (@command_window.index == 0 ? 6 : @command_window.index - 1), (@command_window.index == 0 ? '' : @names[@command_window.index - 1]))
       refresh_props
     end
     Graphics.transition
   end
 end
 
 def update_scommand
   if Input.trigger?(Input::B)
     $game_system.se_play($data_system.cancel_se)
     $scene = Scene_Map.new
   end
   if Input.trigger?(Input::C)
     $game_system.se_play($data_system.decision_se) unless @scommand_window.index == 5
     Graphics.freeze
     case @scommand_window.index
     when 0:
       @mode = 0
       @viewport.tone = Tone.new(0, 0, 0)
       @scommand_window.visible = @scommand_window.active = false
       @command_window.active = true
     when 1:
       @mode = 1
       @viewport.tone = Tone.new(0, 0, 0)
       @scommand_window.visible = @scommand_window.active = false
       s = @command_window.commands.clone
       s.unshift('Windowskin')
       @command_window.dispose
       @command_window = Window_Command.new(256, s)
       @command_window.height -= 32
       @command_window.windowskin = @old_wskin
       @command_window.refresh
     when 2:
       @viewport.tone = Tone.new(0, 0, 0)
       @scommand_window.visible = @scommand_window.active = @command_window.visible = @preview_window.visible = @preview_window2.visible = false
       @fcommand_window.visible = @fcommand_window.active = @fpreview_window.visible = true
       @fpreview_window.set()
       refresh_font
     when 3:
       @scommand_window.visible = @scommand_window.active = false
       @text_window.active = @text_window.visible = true
       @text_window.text = ''
       @text_window.refresh
     when 4:
       @scommand_window.visible = @scommand_window.active = false
       @lcommand_window.visible = @lcommand_window.active = true
       if $data_configs.keys.empty?
         @lcommand_window.cursor_rect.empty
         @lcommand_window.contents = Bitmap.new(256, 192)
         @lcommand_window.contents.draw_text(@lcommand_window.contents.rect, 'No Configs Available to Load', 1)
       end
     when 5:
       $game_system.se_play($data_system.cancel_se)
       $scene = Scene_Map.new
     end
     Graphics.transition
   end
   @scommand_window.update
 end
 
 def update_load
   @lcommand_window.update unless $data_configs.keys.empty?
   if Input.trigger?(Input::B)
     $game_system.se_play($data_system.cancel_se)
     Graphics.freeze
     @scommand_window.visible = @scommand_window.active = true
     @lcommand_window.visible = @lcommand_window.active = false
     Graphics.transition
   end
   
   if Input.trigger?(Input::C) and !$data_configs.keys.empty?
     $game_system.se_play($data_system.decision_se)
     $game_system.config = $data_configs[$data_configs.keys[@lcommand_window.index]]
     $game_system.config.font_bold = $game_system.config.font_bold
     $game_system.config.font_italic = $game_system.config.font_italic
     $scene = Scene_Windowskin.new
   end
 end
 
 def update_save
   @text_window.update
   if Input.trigger?(Input::Key['Esc'])
     $game_system.se_play($data_system.cancel_se)
     Graphics.freeze
     @scommand_window.visible = @scommand_window.active = true
     @text_window.active = @text_window.visible = false
     @text_window.text = ''
     Graphics.transition
   end
   if Input.trigger?(Input::Key['Enter'])
     text = @text_window.text.clone
     if text.length == 0
       $game_system.se_play($data_system.buzzer_se)
     else
       $game_system.se_play($data_system.decision_se)
       $data_configs[text] = $game_system.config.clone
       $data_configs[text].name = text
       $data_skins[text] = [$game_system.config.windowskin_bitmap.clone, $game_system.config.rwskin_bitmap.clone]
       $game_system.config.name = text
       file = File.open("Configs/Configs.rxdata", "w")
       Marshal.dump($data_configs, file)
       $data_skins.each { |key, val|
         next if key == 'default'
         val[0].make_png(key, 'Configs/')
         val[1].make_png('r_'+key, 'Configs/')
       }
       s = $data_configs.keys
       @lcommand_window.dispose
       @lcommand_window = Window_Command.new(288, s)
       @lcommand_window.height = 224
       @lcommand_window.x = 176
       @lcommand_window.y = 128
       @lcommand_window.z = 1000
       @lcommand_window.active = @lcommand_window.visible = false
       @lcommand_window.windowskin = @old_wskin
       @lcommand_window.contents.font = @old_font
       @lcommand_window.refresh
       Graphics.freeze
       @scommand_window.visible = @scommand_window.active = true
       @text_window.active = @text_window.visible = false
       @text_window.text = ''
       Graphics.transition
     #  if text.index(/\.rxdata/) == -1
     #    text += '.rxdata'
     #  end
     #  file = File.open('Configs/' + text, 'w')
     #  Marshal.dump($game_system.config, file)
     end
   end
 end
 
 def update_chooser
   if Input.trigger?(Input::B)
     $game_system.se_play($data_system.cancel_se)
     Graphics.freeze
     @command_window.active = @dummy_window.active = @dummy_window.visible = true
     @wcommand_window.visible = @preview_window2.visible = @wcommand_window.active = @preview_window2.active = false
     @preview_window.set(0)
     recreate_dummy
     Graphics.transition
   end
   if Input.trigger?(Input::C)
     $game_system.se_play($data_system.decision_se)
     Graphics.freeze
     @inds[@command_window.index] = @wcommand_window.index
     @names[@command_window.index] = @windowskins[@wcommand_window.index]
     source = @bitmaps[@wcommand_window.index].clone
     bitmap = $game_system.config.rwskin_bitmap
     case @command_window.index
     when 0:
       bitmap.fill_rect(Rect.new(0, 0, 128, 128), Color.new(0, 0, 0, 0))
       bitmap.blt(0, 0, source, Rect.new(0, 0, 128, 128))
     when 1:
       bitmap.fill_rect(Rect.new(128, 0, 64, 16), Color.new(0, 0, 0, 0))
       bitmap.fill_rect(Rect.new(128, 16, 16, 32), Color.new(0, 0, 0, 0))
       bitmap.fill_rect(Rect.new(176, 16, 16, 32), Color.new(0, 0, 0, 0))
       bitmap.fill_rect(Rect.new(128, 48, 64, 16), Color.new(0, 0, 0, 0))
       bitmap.blt(128, 0, source, Rect.new(128, 0, 64, 16))
       bitmap.blt(128, 16, source, Rect.new(128, 16, 16, 32))
       bitmap.blt(176, 16, source, Rect.new(176, 16, 16, 32))
       bitmap.blt(128, 48, source, Rect.new(128, 48, 64, 16))
     when 2:
       bitmap.fill_rect(Rect.new(144, 16, 32, 32), Color.new(0, 0, 0, 0))
       bitmap.blt(144, 16, source, Rect.new(144, 16, 32, 32))
     when 3:
       bitmap.fill_rect(Rect.new(128, 64, 32, 32), Color.new(0, 0, 0, 0))
       bitmap.blt(128, 64, source, Rect.new(128, 64, 32, 32))
     when 4:
       bitmap.fill_rect(Rect.new(160, 64, 32, 32), Color.new(0, 0, 0, 0))
       bitmap.blt(160, 64, source, Rect.new(160, 64, 32, 32))
     when 5:
       bitmap.fill_rect(Rect.new(128, 96, 64, 32), Color.new(0, 0, 0, 0))
       bitmap.blt(128, 96, source, Rect.new(128, 96, 64, 32))
     end
     refresh_wskin
     @preview_window.set(1, @command_window.index)
     Graphics.transition
   end
   ind = @wcommand_window.index
   @wcommand_window.update
   if @wcommand_window.index != ind
     @preview_window2.set(1, @command_window.index, @windowskins[@wcommand_window.index])
   end
 end
 
 def update_text
   @fcommand_window.update
   if Input.trigger?(Input::C)
     Graphics.freeze
     case @fcommand_window.index
     when 0:
       @fcommand_window.active = @dummy_window.visible = false
       @fcommand_window2.active = @fcommand_window2.visible = @fpreview_window2.visible = true
     else
       @fcommand_window.active = @dummy_window.visible = false
       @ccommand_window.active = @ccommand_window.visible = @fpreview_window2.visible = true
       refresh_color
       @fpreview_window.font.color = @fpreview_window2.font.color.clone
       @fpreview_window.refresh
     end
     Graphics.transition
   end
   if Input.trigger?(Input::B)
     Graphics.freeze
     @viewport.tone = Tone.new(-70, -70, -70, 100)
     @scommand_window.visible = @scommand_window.active = @command_window.visible = @preview_window.visible = true
     @fcommand_window.visible = @fcommand_window.active = @fpreview_window.visible = false
     Graphics.transition
   end
 end
 
 def update_font
   @fcommand_window2.update
   if Input.repeat?(Input::LEFT)
     case @fcommand_window2.index
     when 0:
       @font[0] = [@font[0] - 1, 50].max
     when 1:
       @font[1] = !@font[1]
     when 2:
       @font[2] = !@font[2]
     end
     refresh_font
   end
   if Input.repeat?(Input::RIGHT)
     case @fcommand_window2.index
     when 0:
       @font[0] = [@font[0] + 1, 150].min
     when 1:
       @font[1] = !@font[1]
     when 2:
       @font[2] = !@font[2]
     end
     refresh_font
   end
   if Input.trigger?(Input::C) and @fcommand_window2.index == 3
     $game_system.config.font_size, $game_system.config.font_bold, $game_system.config.font_italic = *@font
     @fpreview_window.set()
   end
   if Input.trigger?(Input::B)
     @font = @fpreview_window.props.clone
     Graphics.freeze
     refresh_font
     @fcommand_window.active = true
     @fcommand_window2.active = @fcommand_window2.visible = @fpreview_window2.visible = false
     recreate_dummy
     Graphics.transition
   end
 end
 
 def update_color
   @ccommand_window.update
   if Input.repeat?(Input::LEFT)
     case @fcommand_window.index
     when 1:
       color = @normal_color
     when 2:
       color = @system_color
     when 3:
       color = @disabled_color
     when 4:
       color = @crisis_color
     when 5:
       color = @knockout_color
     end
     case @ccommand_window.index
     when 0:
       color.red = [color.red - 1, 0].max
     when 1:
       color.green = [color.green - 1, 0].max
     when 2:
       color.blue = [color.blue - 1, 0].max
     end
     refresh_color
   end
   if Input.repeat?(Input::RIGHT)
     case @fcommand_window.index
     when 1:
       color = @normal_color
     when 2:
       color = @system_color
     when 3:
       color = @disabled_color
     when 4:
       color = @crisis_color
     when 5:
       color = @knockout_color
     end
     case @ccommand_window.index
     when 0:
       color.red = [color.red + 1, 255].min
     when 1:
       color.green = [color.green + 1, 255].min
     when 2:
       color.blue = [color.blue + 1, 255].min
     end
     refresh_color
   end
   if Input.trigger?(Input::C) and @ccommand_window.index == 3
     font = Font.new
     case @fcommand_window.index
     when 1:
       font.color = @normal_color.clone
     when 2:
       font.color = @system_color.clone
     when 3:
       font.color = @disabled_color.clone
     when 4:
       font.color = @crisis_color.clone
     when 5:
       font.color = @knockout_color.clone
     end
     @fpreview_window.set(font, 100.0)
   end
   if Input.trigger?(Input::B)
     color = @fpreview_window.props[3].clone
     case @fcommand_window.index
     when 1:
       @normal_color = color
     when 2:
       @system_color = color
     when 3:
       @disabled_color = color
     when 4:
       @crisis_color = color
     when 5:
       @knockout_color = color
     end
     Graphics.freeze
     refresh_color
     @fpreview_window.set()
     @fcommand_window.active = true
     @ccommand_window.active = @ccommand_window.visible = @fpreview_window2.visible = false
     recreate_dummy
     Graphics.transition
   end
 end
 
 def update_recolor
   @rcommand_window.update
   if Input.repeat?(Input::LEFT)
     props = @props[@command_window.index]
     case @rcommand_window.index
     when 0:
       props[0] = [props[0] - 1, 0].max
     when 1:
       props[1] = [props[1] - 1, 0].max
     end
     refresh_props unless @rcommand_window.index == 2
   end
   if Input.repeat?(Input::RIGHT)
     props = @props[@command_window.index]
     case @rcommand_window.index
     when 0:
       props[0] = [props[0] + 1, 360].min
     when 1:
       props[1] = [props[1] + 1, 100].min
     end
     refresh_props unless @rcommand_window.index == 2
   end
   if Input.trigger?(Input::C) and @rcommand_window.index == 2
     bitmap = $game_system.config.rwskin_bitmap
     source = @preview_window2.bitmap
     case @command_window.index
     when 1:
       bitmap.fill_rect(Rect.new(0, 0, 128, 128), Color.new(0, 0, 0, 0))
       bitmap.blt(0, 0, source, source.rect)
     when 2:
       bitmap.fill_rect(Rect.new(128, 0, 64, 16), Color.new(0, 0, 0, 0))
       bitmap.fill_rect(Rect.new(128, 16, 16, 32), Color.new(0, 0, 0, 0))
       bitmap.fill_rect(Rect.new(176, 16, 16, 32), Color.new(0, 0, 0, 0))
       bitmap.fill_rect(Rect.new(128, 48, 64, 16), Color.new(0, 0, 0, 0))
       bitmap.blt(128, 0, source, Rect.new(0, 0, 64, 16))
       bitmap.blt(128, 16, source, Rect.new(0, 16, 16, 32))
       bitmap.blt(176, 16, source, Rect.new(48, 16, 16, 32))
       bitmap.blt(128, 48, source, Rect.new(0, 48, 64, 16))
     when 3:
       bitmap.fill_rect(Rect.new(144, 16, 32, 32), Color.new(0, 0, 0, 0))
       bitmap.blt(144, 16, source, source.rect)
     when 4:
       bitmap.fill_rect(Rect.new(128, 64, 32, 32), Color.new(0, 0, 0, 0))
       bitmap.blt(128, 64, source, source.rect)
     when 5:
       bitmap.fill_rect(Rect.new(160, 64, 32, 32), Color.new(0, 0, 0, 0))
       bitmap.blt(160, 64, source, source.rect)
     when 6:
       bitmap.fill_rect(Rect.new(128, 96, 64, 32), Color.new(0, 0, 0, 0))
       bitmap.blt(128, 96, source, source.rect)
     end
     refresh_wskin
     @preview_window.set((@command_window.index == 0 ? 0 : 1), (@command_window.index == 0 ? 6 : @command_window.index - 1))
     #@preview_window.set_props([0, 100])#@props[@command_window.index])
     @saved_props = @props[@command_window.index]
   end
   if Input.trigger?(Input::B)
     @props[@command_window.index] = @saved_props
     @command_window.active = true
     recreate_dummy
     @rcommand_window.visible = @preview_window2.visible = @rcommand_window.active = @preview_window2.active = false
     @preview_window.set(0)
   end
 end
 
 def refresh_font
   @fcommand_window2.commands = ['Font Size: ' + @font[0].to_s + '%', 'Font Bold: ' + @font[1].to_s, 'Font Italic: ' + @font[2].to_s]
   @fcommand_window2.commands.push('Save Changes')
   @fcommand_window2.refresh
   font = Font.new(false)
   font.bold = @font[1]
   font.italic = @font[2]
   @fpreview_window2.set(font, @font[0])
 end
 
 def refresh_color
   color = Color.new(0, 0, 0)
   case @fcommand_window.index
   when 1:
     color = @normal_color.clone
   when 2:
     color = @system_color.clone
   when 3:
     color = @disabled_color.clone
   when 4:
     color = @crisis_color.clone
   when 5:
     color = @knockout_color.clone
   end
   @ccommand_window.commands = ['Red: ' + color.red.to_s, 'Green: ' + color.green.to_s, 'Blue: ' + color.blue.to_s]
   @ccommand_window.commands.push('Save Changes')
   @ccommand_window.refresh
   font = Font.new(false)
   font.color = color.clone
   @fpreview_window2.set(font, $game_system.config.font_size)
 end
 
 def refresh_props
   props = @props[@command_window.index]
   @rcommand_window.commands = ['Hue: ' + props[0].to_s, 'Gray: ' + props[1].to_s]
   @rcommand_window.commands.push('Save Changes')
   @rcommand_window.refresh
   @preview_window2.set_props(props)
 end
 
 def refresh_wskin
   $game_system.config.windowskin_bitmap = $game_system.config.rwskin_bitmap.clone
   $game_system.config.windowskin_bitmap.hue_change(@props[0][0])
   grayscale = Win32API.new('rgss_addon', 'grayscale', 'li', 'b')
   grayscale.call($game_system.config.windowskin_bitmap.__id__, 100 - @props[0][1])
 end
 
 def recreate_dummy
   @dummy_window.dispose
   @dummy_window = Window_Base.new(0, 224, 640, 256)
   @dummy_window.contents = Bitmap.new(@contents.width, @contents.height)
   @dummy_window.contents.font.color = @normal_color.clone
   @dummy_window.contents.draw_text(Rect.new(1, 1, 640, 32), "This is an example window to demonstrate the windowskin you have", 0)
   @dummy_window.contents.draw_text(Rect.new(1, 33, 640, 32), "created.", 0)
   @dummy_window.cursor_rect.set(0, 64, 608, 64)
   @dummy_window.pause = true
   @dummy_window.ox = @dummy_window.oy = 1
 end
end

class Window_WindowskinPreview < Window_Base
 attr_reader :bitmap, :real_bitmap, :props
 
 def initialize(type, subtype = 0)
   super(0, 0, 384, 224)
   self.contents = Bitmap.new(width - 32, height - 32)
   @props = [0, 100]
   @type = type
   @subtype = subtype if @type == 1
   @bitmap = (type == 0 ? $game_system.config.windowskin_bitmap.clone : $game_system.config.rwskin_bitmap.clone)
   if @type == 1
     case @subtype
     when 0:
       bitmap = Bitmap.new(128, 128)
       bitmap.blt(0, 0, @bitmap, Rect.new(0, 0, 128, 128))
     when 1:
       bitmap = Bitmap.new(64, 64)
       bitmap.blt(0, 0, @bitmap, Rect.new(128, 0, 64, 16))
       bitmap.blt(0, 16, @bitmap, Rect.new(128, 16, 16, 32))
       bitmap.blt(48, 16, @bitmap, Rect.new(176, 16, 16, 32))
       bitmap.blt(0, 48, @bitmap, Rect.new(128, 48, 64, 16))
     when 2:
       bitmap = Bitmap.new(32, 32)
       bitmap.blt(0, 0, @bitmap, Rect.new(144, 16, 32, 32))
     when 3:
       bitmap = Bitmap.new(32, 32)
       bitmap.blt(0, 0, @bitmap, Rect.new(128, 64, 32, 32))
     when 4:
       bitmap = Bitmap.new(32, 32)
       bitmap.blt(0, 0, @bitmap, Rect.new(160, 64, 32, 32))
     when 5:
       bitmap = Bitmap.new(64, 32)
       bitmap.blt(0, 0, @bitmap, Rect.new(128, 96, 64, 32))
     when 6:
       bitmap = @bitmap
     end
     @bitmap = bitmap.clone
   end
   refresh
 end
 
 def update
   super()
 end
 
 def refresh
   self.contents.clear
   x, y = (self.contents.width - @bitmap.width) / 2, (self.contents.height - @bitmap.height) / 2
   self.contents.fill_rect(Rect.new(x - 1, y - 1, @bitmap.width + 2, @bitmap.height + 2), Color.new(0, 0, 0))
   self.contents.blt(x, y, @bitmap, @bitmap.rect)
 end
 
 def set(type, subtype = 0, name = '')
   @type = type
   @subtype = subtype if @type == 1
   @props = [0, 100]
   @bitmap = (name == '' ? (type == 0 ? $game_system.config.windowskin_bitmap.clone : $game_system.config.rwskin_bitmap.clone) : (name == 'None' ? Bitmap.new(192, 128) : RPG::Cache.windowskin(name).clone))
   if @type == 1
     case @subtype
     when 0:
       bitmap = Bitmap.new(128, 128)
       bitmap.blt(0, 0, @bitmap, Rect.new(0, 0, 128, 128))
     when 1:
       bitmap = Bitmap.new(64, 64)
       bitmap.blt(0, 0, @bitmap, Rect.new(128, 0, 64, 16))
       bitmap.blt(0, 16, @bitmap, Rect.new(128, 16, 16, 32))
       bitmap.blt(48, 16, @bitmap, Rect.new(176, 16, 16, 32))
       bitmap.blt(0, 48, @bitmap, Rect.new(128, 48, 64, 16))
     when 2:
       bitmap = Bitmap.new(32, 32)
       bitmap.blt(0, 0, @bitmap, Rect.new(144, 16, 32, 32))
     when 3:
       bitmap = Bitmap.new(32, 32)
       bitmap.blt(0, 0, @bitmap, Rect.new(128, 64, 32, 32))
     when 4:
       bitmap = Bitmap.new(32, 32)
       bitmap.blt(0, 0, @bitmap, Rect.new(160, 64, 32, 32))
     when 5:
       bitmap = Bitmap.new(64, 32)
       bitmap.blt(0, 0, @bitmap, Rect.new(128, 96, 64, 32))
     when 6:
       bitmap = @bitmap
     end
     @real_bitmap = bitmap.clone
     @bitmap = @real_bitmap.clone
   end
   refresh
 end
 
 def set_props(props)
   @props = props.clone
   grayscale = Win32API.new('rgss_addon', 'grayscale', 'li', 'b')
   @bitmap = @real_bitmap.clone
   @bitmap.hue_change(props[0])
   grayscale.call(@bitmap.__id__, 100 - props[1])
   refresh
 end
end

class Window_FontPreview < Window_Base
 attr_accessor :font
 attr_reader :props
 
 def initialize(font, size)
   super(0, 0, 384, 224)
   self.contents = Bitmap.new(width - 32, height - 32)
   @font = font.clone
   @real_size = @font.size
   @font.real_size = @real_size * size / 100
   @props = [size, font.bold, font.italic, font.color]
   refresh
 end
 
 def set(*args)
   @args = args
   if args.empty?
     font = Font.new
     font.color = $scene.instance_variable_get(:@normal_color).clone
     font.real_size = font.size
     size = $game_system.config.font_size
   else
     font = args[0]
     size = args[1]
   end
   @font = font.clone
   @real_size = @font.size
   @font.real_size = @real_size * size / $game_system.config.font_size
   @props = [size, font.bold, font.italic, font.color]
   refresh
 end
 
 def refresh
   self.contents.clear
   self.contents.font = @font
   self.contents.font.real_size = @font.size.to_f
   self.contents.draw_text(Rect.new(0, 0, self.contents.width, 32), 'This is example text created to')
   self.contents.draw_text(Rect.new(0, 32, self.contents.width, 32), 'demonstrate your chosen font.')
   self.contents.draw_text(Rect.new(0, 64, self.contents.width, 32), 'More Text')
 end
end

class Game_System
 attr_accessor :config
 
 alias tdks_wskin_init initialize
 def initialize
   tdks_wskin_init
   @config = Game_Wskin_Config.new    
   $data_configs = {}
   if FileTest.exists?("Configs/Configs.rxdata")
     $data_configs = Marshal.load(File.open("Configs/Configs.rxdata"))
   end
   $data_skins = {}
   $data_configs.keys.each { |i|
     $data_skins[i] = [RPG::Cache.load_bitmap("Configs/", i).clone, RPG::Cache.load_bitmap("Configs/", "r_" + i).clone]
   }
   $data_skins["default"] = Array.new(2) { RPG::Cache.windowskin($data_system.windowskin_name) }
 end
end

class Game_Wskin_Config
 attr_accessor :wskin_inds, :wskin_props, :wskin_names
 attr_accessor :normal_color, :system_color, :disabled_color, :crisis_color, :knockout_color
 attr_accessor :font_size
 attr_accessor :name
 attr_reader   :font_bold, :font_italic
 
 def initialize
   @name = 'default'
   #@windowskin_bitmap = RPG::Cache.windowskin($data_system.windowskin_name).clone
   #@rwskin_bitmap = @windowskin_bitmap.clone
   paths = []
   windowskins = []
   ini = Win32API.new('kernel32', 'GetPrivateProfileStringA', 'PPPPLP', 'L')
   library = "\0" * 256
   ini.call('Game', 'Library', '', @library, 256, '.\\Game.ini')
   library.delete!("\0")
   getpath = Win32API.new(library, 'RGSSGetRTPPath', 'l', 'p')
   (1..3).each { |i| tmp = getpath.call(i);paths.push(tmp) unless tmp == '' } if Windowskin_Config::USE_RTP
   paths.push('')
   paths.each { |path|
     Dir[path + (path == '' ? '' : '/') + 'Graphics/Windowskins/*.{png,jpg,gif}'].each { |i|
       windowskins.push(File.basename(i, '.*'))
     }
   }
   ind = windowskins.index($data_system.windowskin_name) + 1
   @wskin_inds = Array.new(6) { ind }
   @wskin_names = Array.new(6) { $data_system.windowskin_name }
   @wskin_props = Array.new(7) { [0, 100].clone }
   @normal_color = Color.new(255, 255, 255, 255)
   @system_color = Color.new(192, 224, 255, 255)
   @disabled_color = Color.new(255, 255, 255, 128)
   @crisis_color = Color.new(255, 255, 64, 255)
   @knockout_color = Color.new(255, 64, 0)
   @font_size = 100
   @font_bold = false
   @font_italic = false
 end
 
 def rwskin_bitmap
   $data_skins[@name][1]
 end
 def windowskin_bitmap
   $data_skins[@name][0]
 end
 
 def rwskin_bitmap=(val)
   $data_skins[@name][1] = val
 end
 def windowskin_bitmap=(val)
   $data_skins[@name][0] = val
 end
 
 def font_bold=(val)
   @font_bold = Font.default_bold = val
 end
 def font_italic=(val)
   @font_italic = Font.default_italic = val
 end
end

class Window_Base
 alias tdks_wskin_init initialize
 def initialize(*args)
   tdks_wskin_init(*args)
   self.windowskin = $game_system.config.windowskin_bitmap.clone
 end
 
 def normal_color
   return $game_system.config.normal_color
 end
 
 def disabled_color
   return $game_system.config.disabled_color
 end
 
 def system_color
   return $game_system.config.system_color
 end
 
 def crisis_color
   return $game_system.config.crisis_color
 end
 
 def knockout_color
   return $game_system.config.knockout_color
 end
end

class Arrow_Base
 alias tdks_wskin_init initialize
 def initialize(*args)
   tdks_wskin_init(*args)
   self.bitmap = $game_system.config.windowskin_bitmap.clone
 end
end

class Game_Map
 alias tdks_wskin_updt update
 def update
   if Input.trigger?(Input::F7)
     $game_system.se_play($data_system.decision_se)
     $scene = Scene_Windowskin.new
   end
   tdks_wskin_updt
 end
end

class Window_Command
 attr_accessor :commands
end

class Font
 alias tdks_wskin_init initialize
 def initialize(*args)
   tdks_wskin_init(*args)
   @real_size = (args.length > 1 ? args[2] : Font.default_size)
   if args.length == 1 and args[0] == false
     self.name = Font.default_name
     self.real_size = @real_size
   else
     self.size = @real_size
   end
 end
 
 alias tdks_wskin_size size
 def size
   return @real_size
 end
 
 def real_size
   return tdks_wskin_size
 end
 
 alias tdks_wskin_size= size=
 def size=(val)
   val = Font.default_size if val == nil
   @real_size = val
   val = [val * $game_system.config.font_size / 100, 96].min if $game_system != nil
   self.tdks_wskin_size=(val)
 end
 
 def real_size=(val)
   val = [val, 96].min
   @real_size = val
   self.tdks_wskin_size=(val)
 end
 
 def inspect
   str = super()
   str = str[0...str.length - 1]
   props = [:name, :size, :bold, :italic, :color, :real_size]
   props.each { |i| str += ' ' + i.to_s + ' = ';str += ' ' + eval("self.#{i.to_s}").inspect }
   str
 end
end

#==============================================================================
# module Input
#==============================================================================

module Input
 
 #----------------------------------------------------------------------------
 # Simple ASCII table
 #----------------------------------------------------------------------------
 Key = {'A' => 65, 'B' => 66, 'C' => 67, 'D' => 68, 'E' => 69, 'F' => 70,
        'G' => 71, 'H' => 72, 'I' => 73, 'J' => 74, 'K' => 75, 'L' => 76,
        'M' => 77, 'N' => 78, 'O' => 79, 'P' => 80, 'Q' => 81, 'R' => 82,
        'S' => 83, 'T' => 84, 'U' => 85, 'V' => 86, 'W' => 87, 'X' => 88,
        'Y' => 89, 'Z' => 90,
        '0' => 48, '1' => 49, '2' => 50, '3' => 51, '4' => 52, '5' => 53,
        '6' => 54, '7' => 55, '8' => 56, '9' => 57,
        'NumberPad 0' => 45, 'NumberPad 1' => 35, 'NumberPad 2' => 40,
        'NumberPad 3' => 34, 'NumberPad 4' => 37, 'NumberPad 5' => 12,
        'NumberPad 6' => 39, 'NumberPad 7' => 36, 'NumberPad 8' => 38,
        'NumberPad 9' => 33,
        'F1' => 112, 'F2' => 113, 'F3' => 114, 'F4' => 115, 'F5' => 116,
        'F6' => 117, 'F7' => 118, 'F8' => 119, 'F9' => 120, 'F10' => 121,
        'F11' => 122, 'F12' => 123,
        ';' => 186, '=' => 187, ',' => 188, '-' => 189, '.' => 190, '/' => 220,
        '\\' => 191, '\'' => 222, '[' => 219, ']' => 221, '`' => 192,
        'Backspace' => 8, 'Tab' => 9, 'Enter' => 13, 'Shift' => 16,
        'Left Shift' => 160, 'Right Shift' => 161, 'Left Ctrl' => 162,
        'Right Ctrl' => 163, 'Left Alt' => 164, 'Right Alt' => 165,
        'Ctrl' => 17, 'Alt' => 18, 'Esc' => 27, 'Space' => 32, 'Page Up' => 33,
        'Page Down' => 34, 'End' => 35, 'Home' => 36, 'Insert' => 45,
        'Delete' => 46, 'Arrow Left' => 37, 'Arrow Up' => 38,
        'Arrow Right' => 39, 'Arrow Down' => 40,
        'Mouse Left' => 1, 'Mouse Right' => 2, 'Mouse Middle' => 4,
        'Mouse 4' => 5, 'Mouse 5' => 6}
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 UP = [Key['Arrow Up']]
 LEFT = [Key['Arrow Left']]
 DOWN = [Key['Arrow Down']]
 RIGHT = [Key['Arrow Right']]
 A = [Key['Shift']]
 B = [Key['Esc'], Key['NumberPad 0'], Key['X']]
 C = [Key['Space'], Key['Enter'], Key['C']]
 X = [Key['A']]
 Y = [Key['S']]
 Z = [Key['D']]
 L = [Key['Q'], Key['Page Down']]
 R = [Key['W'], Key['Page Up']]
 F5 = [Key['F5']]
 F6 = [Key['F6']]
 F7 = [Key['F7']]
 F8 = [Key['F8']]
 F9 = [Key['F9']]
 SHIFT = [Key['Shift']]
 CTRL = [Key['Ctrl']]
 ALT = [Key['Alt']]
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 # All keys
 KEY_COUNT = 256
 ALL_KEYS = (0...KEY_COUNT).to_a
 # Win32 API calls
 GetKeyboardState = Win32API.new('user32', 'GetKeyboardState', 'P', 'I')
 GetKeyboardLayout = Win32API.new('user32', 'GetKeyboardLayout', 'L', 'L')
 MapVirtualKeyEx = Win32API.new('user32', 'MapVirtualKeyEx', 'IIL', 'I')
 ToUnicodeEx = Win32API.new('user32', 'ToUnicodeEx', 'LLPPILL', 'L')
 # some other constants
 DOWN_STATE_MASK = 0x80
 DEAD_KEY_MASK = 0x80000000
 # data
 @state = "\0" * KEY_COUNT
 @triggered = Array.new(KEY_COUNT, false)
 @pressed = Array.new(KEY_COUNT, false)
 @released = Array.new(KEY_COUNT, false)
 @repeatedKey = -1
 @repeatedCount = 0
 #----------------------------------------------------------------------------
 # update
 #  Updates input.
 #----------------------------------------------------------------------------
 def self.update
   # get current language layout
   @language_layout = GetKeyboardLayout.call(0)
   # get new keyboard state
   GetKeyboardState.call(@state)
   # this special code is used because Ruby 1.9.x does not return a char
   # when using String#[] but another String
   key = 0
   @state.each_byte {|byte|
       # if pressed state
       if (byte & DOWN_STATE_MASK) == DOWN_STATE_MASK
         # not released anymore
         @released[key] = false
         # if not pressed yet
         if !@pressed[key]
           # pressed and triggered
           @pressed[key] = true
           @triggered[key] = true
           @repeatedKey = key
           @repeatedCount = 0
         else
           # not triggered anymore
           @triggered[key] = false
         end
         # update of repeat counter
         if key == @repeatedKey
           @repeatedCount < 17 ? @repeatedCount += 1 : @repeatedCount = 15
         end
       # not released yet
       elsif !@released[key]
         # if still pressed
         if @pressed[key]
           # not triggered, pressed or repeated, but released
           @triggered[key] = false
           @pressed[key] = false
           @released[key] = true
           if key == @repeatedKey
             @repeatedKey = -1
             @repeatedCount = 0
           end
         end
       else
         # not released anymore
         @released[key] = false
       end
       key += 1}
 end
 #----------------------------------------------------------------------------
 # dir4
 #  4 direction check.
 #----------------------------------------------------------------------------
 def self.dir4
   return 2 if self.press?(DOWN)
   return 4 if self.press?(LEFT)
   return 6 if self.press?(RIGHT)
   return 8 if self.press?(UP)
   return 0
 end
 #----------------------------------------------------------------------------
 # dir8
 #  8 direction check.
 #----------------------------------------------------------------------------
 def self.dir8
   down = self.press?(DOWN)
   left = self.press?(LEFT)
   return 1 if down && left
   right = self.press?(RIGHT)
   return 3 if down && right
   up = self.press?(UP)
   return 7 if up && left
   return 9 if up && right
   return 2 if down
   return 4 if left
   return 6 if right
   return 8 if up
   return 0
 end
 #----------------------------------------------------------------------------
 # trigger?
 #  Test if key was triggered once.
 #----------------------------------------------------------------------------
 def self.trigger?(keys)
   keys = [keys] unless keys.is_a?(Array)
   return keys.any? {|key| @triggered[key]}
 end
 #----------------------------------------------------------------------------
 # press?
 #  Test if key is being pressed.
 #----------------------------------------------------------------------------
 def self.press?(keys)
   keys = [keys] unless keys.is_a?(Array)
   return keys.any? {|key| @pressed[key]}
 end
 #----------------------------------------------------------------------------
 # repeat?
 #  Test if key is being pressed for repeating.
 #----------------------------------------------------------------------------
 def self.repeat?(keys)
   keys = [keys] unless keys.is_a?(Array)
   return (@repeatedKey >= 0 && keys.include?(@repeatedKey) &&
       (@repeatedCount == 1 || @repeatedCount == 16))
 end
 #----------------------------------------------------------------------------
 # release?
 #  Test if key was released.
 #----------------------------------------------------------------------------
 def self.release?(keys)
   keys = [keys] unless keys.is_a?(Array)
   return keys.any? {|key| @released[key]}
 end
 #----------------------------------------------------------------------------
 # get_character
 #  vk - virtual key
 #  Gets the character from keyboard input using the input locale identifier
 #  (formerly called keyboard layout handles).
 #----------------------------------------------------------------------------
 def self.get_character(vk)
   # get corresponding character from virtual key
   c = MapVirtualKeyEx.call(vk, 2, @language_layout)
   # stop if character is non-printable and not a dead key
   return '' if c < 32 && (c & DEAD_KEY_MASK != DEAD_KEY_MASK)
   # get scan code
   vsc = MapVirtualKeyEx.call(vk, 0, @language_layout)
   # result string is never longer than 4 bytes (Unicode)
   result = "\0" * 4
   # get input string from Win32 API
   length = ToUnicodeEx.call(vk, vsc, @state, result, 4, 0, @language_layout)
   return (length == 0 ? '' : result)
 end
 #----------------------------------------------------------------------------
 # get_input_string
 #  Gets the string that was entered using the keyboard over the input locale
 #  identifier (formerly called keyboard layout handles).
 #----------------------------------------------------------------------------
 def self.get_input_string
   result = ''
   # check every key
   ALL_KEYS.each {|key|
       # if repeated
       if self.repeat?(key)
         # get character from keyboard state
         c = self.get_character(key)
         # add character if there is a character
         result += c if c != ''
       end}
   # empty if result is empty
   return '' if result == ''
   # convert string from Unicode to UTF-8
   return self.unicode_to_utf8(result)
 end
 #----------------------------------------------------------------------------
 # unicode_to_utf8
 #  string - string in Unicode format
 #  Converts a string from Unicode format to UTF-8 format as RGSS does not
 #  support Unicode.
 #----------------------------------------------------------------------------
 def self.unicode_to_utf8(string)
   result = ''
   # L* format means a bunch of 4-byte wide-chars
   string.unpack('L*').each {|c|
       # characters under 0x80 are 1 byte characters
       if c < 0x0080
         result += c.chr
       # other characters under 0x800 are 2 byte characters
       elsif c < 0x0800
         result += (0xC0 | (c >> 6)).chr
         result += (0x80 | (c & 0x3F)).chr
       # other characters under 0x10000 are 3 byte characters
       elsif c < 0x10000
         result += (0xE0 | (c >> 12)).chr
         result += (0x80 | ((c >> 6) & 0x3F)).chr
         result += (0x80 | (c & 0x3F)).chr
       # other characters under 0x200000 are 4 byte characters
       elsif c < 0x200000
         result += (0xF0 | (c >> 18)).chr
         result += (0x80 | ((c >> 12) & 0x3F)).chr
         result += (0x80 | ((c >> 6) & 0x3F)).chr
         result += (0x80 | (c & 0x3F)).chr
       # other characters under 0x4000000 are 5 byte characters
       elsif c < 0x4000000
         result += (0xF8 | (c >> 24)).chr
         result += (0x80 | ((c >> 18) & 0x3F)).chr
         result += (0x80 | ((c >> 12) & 0x3F)).chr
         result += (0x80 | ((c >> 6) & 0x3F)).chr
         result += (0x80 | (c & 0x3F)).chr
       # other characters under 0x80000000 are 6 byte characters
       elsif c < 0x80000000
         result += (0xFC | (c >> 30)).chr
         result += (0x80 | ((c >> 24) & 0x3F)).chr
         result += (0x80 | ((c >> 18) & 0x3F)).chr
         result += (0x80 | ((c >> 12) & 0x3F)).chr
         result += (0x80 | ((c >> 6) & 0x3F)).chr
         result += (0x80 | (c & 0x3F)).chr
       end}
   return result
 end

end

class Window_Text < Window_Base
 attr_accessor :multi_line, :text
 
 def initialize(*args)
   super(*args)
   self.contents = Bitmap.new(width - 32, height - 32)
   
   @dual_keys = ['`','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E',
                 'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U',
                 'V','W','X','Y','Z','-','=','[',']','\\',';','\'',',','.','/']
   @single_keys = ['NumberPad 0','NumberPad 1','NumberPad 2','NumberPad 3',
                   'NumberPad 4','NumberPad 5','NumberPad 6','NumberPad 7',
                   'NumberPad 8','NumberPad 9','Space','Tab']
   @multi_keys = ['Enter']
   @chars1 = ['`','1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f',
              'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
              'x','y','z','-','=','[',']','/',';','\'',',','.','\\']
   @chars2 = ['~','!','@','#','$','%','^','&','*','(',')','A','B','C','D','E','F',
              'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W',
              'X','Y','Z','_','+','{','}','?',':','"','<','>','|']
   @chars = ['0','1','2','3','4','5','6','7','8','9',' ','\t']
   @multi_chars = ['\n']
   
   @multi_line = true
   @text = ""
   @cursor = true
 end
 
 def update
   @dual_keys.each_with_index { |i, ind|
     if Input.repeat?(Input::Key[i])
       @text += (Input.press?(Input::Key['Shift']) ? @chars2[ind] : @chars1[ind])
     end
   }
   @single_keys.each_with_index { |i, ind|
     if Input.repeat?(Input::Key[i])
       @text += @chars[ind]
     end
   }
   if @multi_line
     @multi_keys.each_with_index { |i, ind|
       if Input.repeat?(Input::Key[i])
         @text += @multi_chars[ind]
       end
     }
   end
   if Input.repeat?(Input::Key['Backspace'])
     @text = @text.split('')
     tmp = @text.pop()
     if (tmp == 'n' or tmp == 't') and @text[@text.length - 1] == '\\'
       @text.pop()
     end
     @text = @text.join('')
   end
   @cursor = !@cursor if Graphics.frame_count % 20 == 0
   refresh
 end
 
 def refresh
   self.contents.clear
   
   tmp = @text.gsub(/((?:\\n)+)\z/, '')
   y_mod = $1 ? $1.length / 2 : 0
   x_pos = y_mod > 0
   lns = tmp.gsub(/\\t/,'    ').split(/\\n/)
   y = 0
   x = 0
   lns.each_with_index { |ln, ind|
     rect = self.contents.text_size(ln)
     rect.height = self.contents.text_size('a').height
     rect.width += 1 unless ln.index(/[vVAwf\/\\]\z/).nil?
     rect.y = y
     self.contents.draw_text(rect, ln)
     y += rect.height
     x = rect.width
   }
   height = self.contents.text_size('a').height
   y -= height unless lns.last.nil?
   y += y_mod * height
   x = (x_pos ? 0 : x + 1)
   self.contents.fill_rect(Rect.new(x, y, 2, height), Color.new(0, 0, 0)) if @cursor
 end
end

module Zlib
 class Png_File < GzipWriter
   #--------------------------------------------------------------------------
   # ● 主处理
   #--------------------------------------------------------------------------
   def make_png(bitmap_Fx,mode)
     @mode = mode
     @bitmap_Fx = bitmap_Fx
     self.write(make_header)
     self.write(make_ihdr)
     self.write(make_idat)
     self.write(make_iend)
   end
   #--------------------------------------------------------------------------
   # ● PNG文件头数据块
   #--------------------------------------------------------------------------
   def make_header
     return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
   end
   #--------------------------------------------------------------------------
   # ● PNG文件情报头数据块(IHDR)
   #--------------------------------------------------------------------------
   def make_ihdr
     ih_size = [13].pack("N")
     ih_sign = "IHDR"
     ih_width = [@bitmap_Fx.width].pack("N")
     ih_height = [@bitmap_Fx.height].pack("N")
     ih_bit_depth = [8].pack("C")
     ih_color_type = [6].pack("C")
     ih_compression_method = [0].pack("C")
     ih_filter_method = [0].pack("C")
     ih_interlace_method = [0].pack("C")
     string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
              ih_compression_method + ih_filter_method + ih_interlace_method
     ih_crc = [Zlib.crc32(string)].pack("N")
     return ih_size + string + ih_crc
   end
   #--------------------------------------------------------------------------
   # ● 生成图像数据(IDAT)
   #--------------------------------------------------------------------------
   def make_idat
     header = "\x49\x44\x41\x54"
     case @mode # 请54~
     when 1
       data = make_bitmap_data#1
     else
       data = make_bitmap_data
     end
     data = Zlib::Deflate.deflate(data, 8)
     crc = [Zlib.crc32(header + data)].pack("N")
     size = [data.length].pack("N")
     return size + header + data + crc
   end
   #--------------------------------------------------------------------------
   # ● 从Bitmap对象中生成图像数据 mode 1(请54~)
   #--------------------------------------------------------------------------
   def make_bitmap_data1
     w = @bitmap_Fx.width
     h = @bitmap_Fx.height
     data = []
     for y in 0...h
       data.push(0)
       for x in 0...w
         color = @bitmap_Fx.get_pixel(x, y)
         red = color.red
         green = color.green
         blue = color.blue
         alpha = color.alpha
         data.push(red)
         data.push(green)
         data.push(blue)
         data.push(alpha)
       end
     end
     return data.pack("C*")
   end
   #--------------------------------------------------------------------------
   # ● 从Bitmap对象中生成图像数据 mode 0
   #--------------------------------------------------------------------------
   def make_bitmap_data
     gz = Zlib::GzipWriter.open('hoge.gz')
     t_Fx = 0
     w = @bitmap_Fx.width
     h = @bitmap_Fx.height
     data = []
     for y in 0...h
       data.push(0)
       for x in 0...w
         t_Fx += 1
         if t_Fx % 10000 == 0
           Graphics.update
         end
         if t_Fx % 100000 == 0
           s = data.pack("C*")
           gz.write(s)
           data.clear
           #GC.start
         end
         color = @bitmap_Fx.get_pixel(x, y)
         red = color.red
         green = color.green
         blue = color.blue
         alpha = color.alpha
         data.push(red)
         data.push(green)
         data.push(blue)
         data.push(alpha)
       end
     end
     s = data.pack("C*")
     gz.write(s)
     gz.close    
     data.clear
     gz = Zlib::GzipReader.open('hoge.gz')
     data = gz.read
     gz.close
     File.delete('hoge.gz')
     return data
   end
   #--------------------------------------------------------------------------
   # ● PNG文件尾数据块(IEND)
   #--------------------------------------------------------------------------
   def make_iend
     ie_size = [0].pack("N")
     ie_sign = "IEND"
     ie_crc = [Zlib.crc32(ie_sign)].pack("N")
     return ie_size + ie_sign + ie_crc
   end
 end
end
#==============================================================================
# ■ Bitmap
#------------------------------------------------------------------------------
#  关联到Bitmap。
#==============================================================================
class Bitmap
 #--------------------------------------------------------------------------
 # ● 关联
 #--------------------------------------------------------------------------
 def make_png(name="like", path="",mode=0)
   make_dir(path) if path != ""
   Zlib::Png_File.open("temp.gz") {|gz|
     gz.make_png(self,mode)
   }
   Zlib::GzipReader.open("temp.gz") {|gz|
     $read = gz.read
   }
   name += ".png" if name.index(/.png\Z/).nil?
   f = File.open(path + name,"wb")
   f.write($read)
   f.close
   File.delete('temp.gz')
   end
 #--------------------------------------------------------------------------
 # ● 生成保存路径
 #--------------------------------------------------------------------------
 def make_dir(path)
   dir = path.split("/")
   for i in 0...dir.size
     unless dir == "."
       add_dir = dir[0..i].join("/")
       begin
         Dir.mkdir(add_dir)
       rescue
       end
     end
   end
 end
end



Instructions

Just put the windowskins you want users to be able to customize from in the windowskins folder. Press F7 to bring up the windowskin customization menu.


Compatibility

No issues known.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

Also, you'll need this dll for the script to work.
18
News / Suggestions / Feedback / Script Database Error?
November 22, 2012, 10:39:42 am
So I recently saw that Blizz moved my script "Battler Transitions" to the script database. However, I checked today, and it wasn't there. The topic was still there, but I couldn't find it in the database. Is it just me, or is there a big bug in the script database?
19
RMXP Script Database / [XP] Enemy Elements
November 14, 2012, 04:12:45 pm
Enemy Elements
Authors: ThallionDarkshine
Version: 0.2
Type: Enemy Stat Add-on
Key Term: Enemy Add-on



Introduction

This script adds some variety to your random battles. You can define different "elements" for enemies, each of which can change different stats such as MaxHP, MaxSP, Strength, Dexterity, and many more. Then, you can give each enemy a different set of possible "elements" that the script will randomly choose from to apply. Thus, you could make weaker enemies with the "element" of minion, as I did in the script.


Features


  • Spices up random battles.

  • You don't have to give any enemy an "element" if you don't want to.

  • Use an unlimited number of "elements".

  • Use combinations of elements.




Screenshots

You can't really capture stat changes in a screenshot.


Demo

None as of yet.


Script

Spoiler: ShowHide

class Game_Enemy
 ELEMENTS = {
   :minion => [[:maxhp, -50], [:atk, -25], [:maxsp, -63], [:exp, -50], [:gold, -50]],
   :brute => [[:maxhp, 12], [:atk, 3], [:maxsp, -21], [:exp, 4], [:gold, 4], [:dex, -9], [:agi, -8], [:mdef, -14]],
 }
 
 def self.elements(id)
   return case id
          when 0 then []
          else []
          end
 end
 
 alias tdks_elmnt_init initialize
 def initialize(troop_id, member_index)
   @maxhp_mod = @maxsp_mod = 100
   tdks_elmnt_init(troop_id, member_index)
   elements = Game_Enemy.elements(@enemy_id)
   @elements = elements.length > 0 ? elements[rand(elements.length)] : nil
   @atk_mod=@pdef_mod=@mdef_mod=@str_mod=@dex_mod=@agi_mod=@int_mod=@maxhp_mod=@maxsp_mod=@eva_mod=@exp_mod=@gold_mod=100
   @elements.each{|element|Game_Enemy::ELEMENTS[element].each{|i|instance_variable_set("@#{i[0]}_mod",i[1]+instance_variable_get("@#{i[0]}_mod"))}if Game_Enemy::ELEMENTS.keys.include?(element)}if @elements
   @hp = maxhp
   @sp = maxsp
 end
 
 alias tdks_eels_base_maxhp base_maxhp
 def base_maxhp
   return tdks_eels_base_maxhp * @maxhp_mod / 100
 end
 
 alias tdks_eels_base_maxsp base_maxsp
 def base_maxsp
   return tdks_eels_base_maxsp * @maxsp_mod / 100
 end
 
 alias tdks_eels_base_str base_str
 def base_str
   return tdks_eels_base_str * @str_mod / 100
 end
 
 alias tdks_eels_base_dex base_dex
 def base_dex
   return tdks_eels_base_dex * @dex_mod / 100
 end
 
 alias tdks_eels_base_agi base_agi
 def base_agi
   return tdks_eels_base_agi * @agi_mod / 100
 end
 
 alias tdks_eels_base_int base_int
 def base_int
   return tdks_eels_base_int * @int_mod / 100
 end
 
 alias tdks_eels_base_atk base_atk
 def base_atk
   return tdks_eels_base_atk * @atk_mod / 100
 end
 
 alias tdks_eels_base_pdef base_pdef
 def base_pdef
   return tdks_eels_base_pdef * @pdef_mod / 100
 end
 
 alias tdks_eels_base_mdef base_mdef
 def base_mdef
   return tdks_eels_base_mdef * @mdef_mod / 100
 end
 
 alias tdks_eels_base_eva base_eva
 def base_eva
   return tdks_eels_base_eva * @eva_mod / 100
 end
 
 alias tdks_eels_exp exp
 def exp
   return tdks_eels_exp * @exp_mod / 100
 end
 
 alias tdks_eels_gold gold
 def gold
   return tdks_eels_gold * @gold_mod / 100
 end
end



Instructions

To configure the script, go to the line 2.
Add any elements you want into the hash, using the format:
ELEMENT_NAME_AS_SYMBOL (that means it starts with ":") => [[STAT_NAME_AS_SYMBOL, PERCENT_CHANGE], [STAT_NAME_AS_SYMBOL, PERCENT_CHANGE]]

The different stats you can change are:
MaxHP -
:maxhp

MaxSP -
:maxsp

Strength -
:str

Dexterity -
:dex

Agility -
:agi

Intelligence -
:int

Attack -
:atk

Physical Defense -
:pdef

Magic Defence -
:mdef

Evasion -
:eva

Experience -
:exp

Gold Drop -
:gold


To make different enemies have a possibility of having different elements, go to line 7 of the script.
Add this to add a new enemy that has elements:
when ENEMY_ID then [[ELEMENT1_SET1, ELEMENT2_SET1], [ELEMENT1_SET2, ELEMENT2_SET2, ELEMENT2_SET3]]

Add as many element sets and elements as you want.


Compatibility

Probably compatible with everything except maybe enemy leveling scripts.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

Nothing
--------------------------------------------------------------------------------
20
RMXP Script Database / [XP] Battler Transitions
November 02, 2012, 08:58:49 pm
Battler Transitions
Authors: ThallionDarkshine
Version: 2.1
Type: Graphical Battle Add-on
Key Term: Battle Add-on



Introduction

I just finished playing through Blizz's game "Chaos Project", and I saw a ton of cool scripted addons he made for it. Well now, you can use one of the best features of his game in yours. This script allows you to insert exit transitions for the enemies, such as slicing apart, simply fading out, 3d spin, and many more. And thus begins my quest to replicate every amazing feature of CP.

In this new version, I'm proud to announce that the default transition graphics can be used to transition sprites out. I've also separated out the transitions module that was originally included in this script so I can more easily work on the module script. This is not a new dependency for this script, it's just something that was originally included and is now a separate script.



Features


  • Many amazing transitions for enemies.

  • Can use the default transition graphics to transition out enemies.




Screenshots
Spoiler: ShowHide






Demo

None yet.


Script

Spoiler: ShowHide

#===================================================================
#
#           BATTLER TRANSITIONS
#           Author - ThallionDarkshine
#           Version - 2.1
#
#===================================================================

module Battler_Trans
 # Example Animations
 #   parameters: (animation_type, animation_duration, animation_parameters, ease)
 #            or (animation_type, animation_duration, ease)
 #   note - the script no longer uses this set of animations, it is just in the script
 #     to show the different effects
 @trans = [
   # Slicing Animations (Animation #0)
   #   parameters: (amount_movement)
   [0, 40],
   [0, 20],
   [0, 20, [0.6]],
   # Fading Animations (Animation #1)
   #   parameters: none
   [1, 20],
   [1, 30],
   # Zooming Animations (Animation #2)
   #   parameters: (x_zoom, y_zoom) or (zoom)
   [2, 30],
   [2, 20, [1.2]],
   [2, 30, [1, 0]],
   [2, 30, [0, 1]],
   [2, 30, [1.8, 0.2]],
   [2, 30, [0.2, 1.8]],
   [2, 30, [0.2]],
   # Zooming and Spinning Animations (Animation #3)
   #   parameters: (x_zoom, y_zoom, spin_degrees) or (zoom, spin_degrees)
   [3, 20],
   [3, 40, [1.8, 0.2, 720]],
   [3, 40, [0.2, 810]],
   [3, 40, [0.2, 1.8, 720]],
   # 3D Spin Animations (Animation #4)
   #   parameters: (zoom, num_rotations)
   [4, 40],
   [4, 40, [0, 4]],
   [4, 40, [0.5, 6]],
   [4, 30, [0.7, 2]],
   # Slide-In Animations (Animation #5)
   #   parameters: (slide_direction)
   [5, 24],
   [5, 24, [-1]],
   # Fold Animations (Animation #6)
   #   parameters: none
   [6, 30],
   # Shaking Animations (Animation #7)
   #   parameters: (x_strength, x_speed, y_strength, y_speed) or (x_intensity, y_intensity)
   [7, 40],
   [7, 40, [6..9, 4..7]],
   # Ripple/Distort Animations (Animation #8)
   #   parameters: (x_amplitude, x_wavelength, num_x_ripples, y_amplitude, y_wavelength, num_y_ripples) or (x_amount, num_x_ripples, y_amount, num_y_ripples)
   [8, 40],
   [8, 40, [40, 10, 0.5, 10, 10, 2]],
   [8, 40, [10, 10, 2, 40, 10, 0.5]],
   [8, 40, [10, 40, 2, 10, 10, 2]],
   [8, 40, [10, 10, 2, 10, 40, 2]],
   [8, 40, [10, 10, 3, 10, 10, 2]],
   [8, 40, [10, 10, 2, 10, 10, 3]],
   [8, 10, [10, 40, 0.5, 10, 10, 0.5]],
   [8, 10, [10, 10, 0.5, 10, 40, 0.5]],
   # Dissolve to Sprite Animations (Animation #9)
   #   parameters: (fade_duration)
   #            or (fade_duration, x_size, y_size, negative?, tint_amount,
   #                tint_red, tint_green, tint_blue)
   #            or (fade_duration, x_size, y_size, negative?, tint_amount,
   #                tint_red, tint_green, tint_blue, grayscale_amount)
   #   note - use a float for x_size or y_size to specify it as a fraction
   #     example - 1.0 for the width of the sprite, 0.5 for half the width, and so on
   [9, 40],
   [9, 40, [10, 1.0, 1, false, 50, 200, 50, 50]],
   [9, 40, [10, 5, 5, true, 50, 100, 200, 200]],
   [9, 40, [10, 1, 1.0, false, 0, 0, 0, 0, 100]],
   # Dissolve Animations (Animation #10)
   [10, 40],
   [10, 40, [1, 1.0]],
   [10, 40, [5, 5]],
   [10, 20, [10, 10]],
   # Transition Graphic Animations (Animation #11)
   #   parameters: (transition_graphic_name, fade_duration)
   #     fade_duration - how long it takes for each individual pixel of the
   #       sprite to fade out
   [11, 100],
   [11, 40, ['001-Blind01', 5]],
 ]
 
 # Setup for Enemy-Specific Transitions
 #     Delete the line that reads "when 0 then return @trans".
 #     Add this code for every enemy you want to have a specific set of
 #       transitions:
 #        when ENEMY_ID then return [
 #            TRANSITION_1,
 #            TRANSITION_2,
 #            TRANSITION_3,
 #            etc...
 #          ]
 # where ENEMY_ID is the id of the enemy whose transitions you are setting,
 #   and TRANSITION_1, 2, and so on are the possible transitions you want it
 #   to use
 def self.transitions(enemy_id)
   case enemy_id
   when 0 then return @trans
   else return @trans
   end
 end
 
 def self.trans=(val)
   @trans = val
 end
 
 def self.trans
   @trans
 end
end

unless Object.const_defined?(:Transitions)
 raise 'This script requires ThallionDarkshine\'s Transitions Module'
end

class Sprite_Battler
 attr_accessor :pos
 
 alias tdks_transitions_collapse collapse
 def collapse
   trans = Battler_Trans.transitions(@battler.id)
   if trans.length > 0
     rnd = rand(trans.length)
     rnd = trans[rnd].map { |i| (i.is_a?(Array) ? i.clone : i) }
     Transitions.transition_out(self, *rnd)
     @pos = [self.x, self.y]
   else
     tdks_transitions_collapse
   end
 end
 
 alias tdks_transitions_update update
 def update
   tdks_transitions_update
   if defined?(@pos)
     self.x, self.y = *@pos
   end
 end
end



Instructions

See script for instructions.


Compatibility

I don't think there would be any compatibility problems, but you might have some with some 3d battle camera like the one in CP.


Credits and Thanks


  • ThallionDarkshine

  • Blizzard, for giving me the idea and making the script this is based off of.




Author's Notes

You'll need my transitions module for this script to work (that's the script that actual makes the cool transitions).
Also, you'll need this dll for the script.
21
RPG Maker Scripts / Random Battle Transitions
June 20, 2012, 11:27:31 am
Random Battle Transitions



  Alright, I'm not quite sure if this is the right place for this, because it's just a script snippet. If you are like me, then you'd like some randomness in your games. It gets really annoying when the engine always uses the same transition for Scene_Battle.

First, go into the Script Editor. Next go to Scene_Battle1. Now look in the main method for where it says:


if $data_system.battle_transition == ""
  Graphics.transition(20)
else
  Graphics.transition(40, "Graphics/Transitions/" + $data_system.battle_transition)
end


Replace those lines with:


trans = []
Dir['Graphics/Transitions/*.{png,jpg,bmp}'].each{ |file|
  trans.push(File.basename(file, '.*'))
}
if FileTest.directory?('C:\Program Files/Common Files/Enterbrain/RGSS/Standard/Graphics/Windowskins')
  Dir['C:\Program Files/Common Files/Enterbrain/RGSS/Standard/Graphics/Transitions/*.{png,jpg,bmp}'].each{ |file|
    trans.push(File.basename(file, '.*'))
  }
end
trans_index = rand(trans.size)
Graphics.transition(40, "Graphics/Transitions/" + trans[trans_index])


And there you have it, random battle transitions.
Note. It works even if you don't use the RTP.
22
New Projects / Spawn of Darkness
June 13, 2012, 08:54:31 pm

Spawn of Darkness

Setting
Spoiler: ShowHide

Spawn of Darkness is set in a world of monsters and magic, demons and priestesses, good and evil. Vicious battles constantly rage between the savage demon hordes and the holy crusaders of the north. All the citizens of the realm live in constant fear of attack by demons or conscription by the crusaders. And though they are forced to rely on the northern crusaders for protection from the demons, none of them truely feel that their so-called allies have their best interests in mind.

Story
Spoiler: ShowHide

19 years before the game begins, the world was a peaceful place. Aside from the occasional invasion of a demon, or a raiding party of petty monsters, everyone lived a life of peace and quiet, the weather made calm by the spells of their guardian priestesses, morale kept high by the lighthearted mood throughout the land. However, one day a powerful demon found his way to Earth. His tactics differed greatly from those of his fellow demons. While other demons would've immediately stormed the nearest human village in a killing rage, he instead settled down as an ordinary human, and contented himself to observe. To be sure, he fully intended to unleash his wrath upon Earth, but only when the time was right. However, Earth was saved for a time, as he fell in love with a beautiful human priestess. She discovered his identity, but it did not phase her, as can happen with love (especially enhanced by the power of magic). Eventually, they had a son, and named him Sejan. However, others soon noticed that the boy was different from other children, and the demon and the priestess were forced to flee to a mysterious swamp. The townsfolk confronted them there, and the priestess was forced to use the last of her energy to shield her child from the townspeople. The resulting burst of energy served as a beacon for nearby demons, and soon a vast army was assembled. Led by Sejan's father, they sought to wreak havok on Earth to repay them for the pain they had caused him. As for Sejan, he was transported to a remote town in the mountains, secluded, for the time being at least, from the conflict...


Screenshots
Spoiler: ShowHide


23
Dynamic Weather and Time System
Authors: ThallionDarkshine
Version: 1.0
Type: Custom Environment System
Key Term: Custom Environment System



Introduction

This script changes the screen tint to correspond with the current game time. It also dynamically changes the weather, complete with sound and screen tint.


Features


  • Changes screen tint with game time

  • Random weather can be disabled ingame.

  • Can disable weather on certain maps by adding (in) to the map name




Screenshots




Demo
https://rapidshare.com/files/2898565759/Weather_Demo.exe


Script

For right now, see demo for script.


Instructions

To use, place directly under main.
To turn on or off random weather (replace true with false to turn off):
Code: text
$weather.rand_weather = true
$weather.update

To change the varience of weather:
Code: text
$weather.varience = 

To change the base time between weather changes:
Code: text
$weather.base = 

To change the second equivalent of one minute realtime:
Code: text
$weather.min_equiv = 



Compatibility

May be issues with other weather systems.


Credits and Thanks


  • ThallionDarkshine




Author's Notes

Use freely, no credit necessary.
24
RPG Maker Scripts / Help with Win32API needed
May 20, 2012, 08:52:34 am
So, for my RGSS Addon, I decided they I should use the win32api to set pixels and that sort of stuff. So, I got the handle of device context, and I tried to set several pixels in the window, but the function keeps returning -1 (failure). There's probably something that I'm missing, but could someone help me figure this out.

My code:
def win32test
@find_window = Win32API.new("user32", "FindWindow", "LL", "L")
@set_pixel = Win32API.new("gdi32", "SetPixel", "PIIP", "I")
window = @find_window.call("RGSS Player", "Test")
color = 0x00FF0000
result = @set_pixel.call(window, 0, 0, color)
print result
end
25
RPG Maker Scripts / RGSS Addon
May 17, 2012, 10:41:23 pm
Who here thinks that it would be a good idea to add on to the built in RGSS classes such as bitmap. Well, I'm starting doing it. So far I have added in several RGSS2 bitmap functions missing from RGSS.

Functions completed:

Bitmap:
draw_gradient(rectangle, color1, color2, gradient_type[, subtype])
     rectangle - rectangle in which to draw gradient
     color1, color2 - starting and ending colors
     gradient_type:
       0 - horizontal, 1 - vertical, 2 - diagonal, 3 - radial
     subtype - for diagonal:
       0 - top-left to bottom-right, 1 - top-right to bottom-left
    - this method is very laggy, especially with anything other than horizontal or vertical

draw_circle(rectangle, color[, border, border_size, border_color])
     rectange - rectangle in which to draw circle
     color - color of the circle
     border - whether to draw a border (default false)
     border_size - how large the border is (default 0)
     border_color - color of the border (default black)
    - this method doesn't lag as much as the gradient, but it still lags

blur
    - this method only lags a bit compared to the other functions

sharpen
    - this method lags a little more than blur

draw_line(x1, y1, x2, y2, color[, width])
     x1, y1, x2, y2 - starting and ending coordinates of line
     color - color in which to draw the line
     width - thickness of the line
26
RMXP Script Database / [XP] Tileset Creator Edit
May 06, 2012, 03:59:26 pm
Tileset Creator Edit
Authors: game_guy, ThallionDarkshine
Version: 1.0
Type: Tileset Creator
Key Term: Game Utility



Introduction

Some of you may remember game_guy's old tileset creator. Well I just downloaded it a few days ago, and it is Awesome!! However, I found a few errors in it, and a few functions that I found it lacking in. So here is my edit of the tileset creator, complete with several new features and a few bug fixes.

Note. I just finished working out changing opacity and saturation in the tileset creator. After I finish the documentation for it I will post a link to the updated version.


Features


  • Choose from many different tiles

  • Snap to Grid or Point

  • Drag in erase mode to erase multiple tiles

  • Change Tileset Height!!!




Screenshots

Spoiler: ShowHide

Spoiler: ShowHide

Spoiler: ShowHide

Spoiler: ShowHide



Demo

https://rapidshare.com/files/2657394064/Tileset_Creator.zip
http://www.sendspace.com/file/1ko075


Script

You should just download the demo.


Instructions

Instructions are in the script.


Compatibility

None that I know of.


Credits and Thanks


  • game_guy

  • ThallionDarkshine




Author's Notes

Use freely.