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 - Simon Greedwell

1
I've been using Heretic's Loop Map script and it seems the "lock panorama" script call is bugged. Like the name suggests, it's supposed to prevent the panorama from scrolling along with the character. At first I assumed it was an incompatibility with one of the dozen or so scripts on my game but I tested it in a new project and it still doesn't work.

The Modular Passable script is needed for the script to run. It can be found here. Both scripts on the same message hit the character limit per post. Pity.   

There's the Loop Map script:

#===============================================================================
#
#           HERETIC'S LOOP MAPS [XP]
#           Version - 1.0
#           Wednesday, March 25th, 2015
#
#===============================================================================
#
# ---  Requirements and Installation  ---
#
# *** REQUIRES HERETICS MODULAR PASSABLE SCRIPT ***
#
#  This script should be placed DIRECTLY below Heretic's Modular Passable
#  directly below Modular Collision Optimizer (recommended for performance) if
#  it is used, or directly below Modular Passable.
#
# -----  FEATURES  ------
#
# - Allows Maps to Loop like in RPG Maker VX and VX Ace
# - Can be turned on or off during gameplay
# - Allows for Panorama Tuning to adjust Panorama Speeds or Lock in place
# - Allows for Auto Scrolling of Panorama like in VX and VX Ace
# - Works with Fogs and Panoramas unlike other scripts
# - Compatible with Heretic's Cloud Altitude 2.2
# - Also compatible with Game Guy's Unlimited Fogs if you have Cloud Altitude
#
#
# -----  INSTRUCTIONS  ------
#
#  Install below Heretic's Modular Passable Script and above Main.  You'll
#  probably need to put it above other scripts that have Loop Map Compatability
#  such as the Caterpillar, NPCs on Event Tiles, Diagonal Stairs, Bush Passages
#  Hotfoot Tiles, and my Vehicles script.
#
#  Once installed, scroll down to the Config and set up your game as you
#  see fit.  The Config is intended for maps that you always expect to
#  have a Looping behavior.
#
#  - SDK (if installed)
#  - Heretic's Modular Passable (** Required **)
#  - Heretic's Modular Collision Optimizer (Optional)
#  - Heretic's Loop Maps (This Script)
#
#  Heretic's Modular Collision Optimizer can be exceptionally useful for
#  other scripters to be able to do things with Event Tiles in a manner
#  that is actually efficient enough that collisions with these types
#  of tiles do not affect performance.  This script is NOT intended
#  to be used for only increasing performances.  I have noticed much
#  better performance given the exceptionally high number of scripts
#  that are created in the collection.  Read the Documentation in
#  the Collision Optimizer script for more information.
#
#
#  -----  SCRIPT CALLS  -----
#
#  This script is actually pretty easy to use.  If you want to set a Map to
#  have a Looping property during gameplay, you can adjust it on the fly
#  by using a Script Call: $game_map.loop_type = N  The best results of
#  this script are set in the Config section, so you won't really need
#  to use these Script Calls during gameplay.
#
#  By default, 0 is a Non Looping Map, which is default for all maps, except
#  those specified in the Config.  Loop Type of 1 is a Vertical Loop.  A Loop
#  Type of 2 is a Horizontal Loop.  Loop Type of 3 is to Loop both Horizontal
#  and Vertical.
#
#  @>Script: $game_map.loop_type = 0 - No Loop
#  @>Script: $game_map.loop_type = 1 - Loop Vertical
#  @>Script: $game_map.loop_type = 2 - Loop Horizontal
#  @>Script: $game_map.loop_type = 3 - Loop Vertical and Horizontal
#
#  If you change the LOOP TYPE during gameplay, the Map will "snap" if the
#  screen is displaying over a Map Edge.  Changing the LOOP TYPE will usually
#  look the best to Players if you change it while away from Map Edges so
#  no "snapping" takes place.  You can disable this "snapping" by running
#  a script of $game_system.loop_snap = false, but as soon as the Player
#  tries to move in the direction of the Map Edge, the Map will just
#  "snap" anyway.
#
#  NOTE:  My Caterpillar Script has a feature to allow Characters to go off the
#         edge of maps.  This ONLY works if a Map is NOT Looping for the
#         direction allowed.  Thus, you can make a Map have a Vertical Loop
#         and still allow Characters to walk off the side edges of the Map.
#
#
#  -----  DETECTING LOOPS  -----
#
#  If you need to detect if a Map has Looped for some reason, you can check
#  with a script to $game_map.looped which will return nil until the Player
#  has caused the Map to Loop, at which time, will return the Direction of
#  the way the Map has Looped.  The value will be returned for ONE FRAME
#  of UPDATE, then it will automatically be reset back to nil.
#
#  In a Parallel Event, you can run this:
#
#  @>Conditional Branch: Script: $game_map.looped != nil
#  @>  (your Event Stuff goes here)
#  @>Branch End
#

#  -----  PANORAMA SCROLL ADJUSTMENTS  -----
#
#  Some Panoramas do not tile properly, so it may be useful to "lock" these
#  styles of panoramas in place, either Horizontally or Vertically.  The
#  ability to do this also allows you to alter the Panorama Scroll Speeds.
#
#  Due to the way the Math came out, you'll need to use a value of 4 for
#  you to "lock" a Panorama.  Numbers less than 4 will cause the Panorama
#  to move faster than the current map, and those greater than 4 will
#  make the Panorama scroll slower than the current map.  The default value
#  is 8.  Numbers greater than 8 scroll increasingly slowly, and numbers
#  that are less than 8 will move slower than the map, but faster than the
#  default Panorama Scroll Speed.  This can be useful when you want to make
#  something in the distance appear to be either much nearer or farther
#  away from the Player's plane.
#
#  $game_map.pan_scroll_x = 4 - Lock the X Panorama Scroll
#  $game_map.pan_scroll_y = 4 - Lock the Y Panorama Scroll
#  $game_map.pan_scroll_x = 8 - Default Panorama Scroll Speed
#  $game_map.pan_scroll_y = 8 - Default Panorama Scroll Speed
#  $game_map.pan_scroll_x = 16 - Very Slow Panorama X Scrolling (Distant)
#  $game_map.pan_scroll_y = 16 - Very Slow Panorama Y Scrolling (Distant)
#  $game_map.pan_scroll_x = 5 - Fast Panorama X Scrolling (Close Plane)
#  $game_map.pan_scroll_y = 5 - Fast Panorama Y Scrolling (Close Plane)
#  $game_map.pan_scroll_x = < 4 - Panorama X Scrolls faster than Map
#  $game_map.pan_scroll_y = < 4 - Panorama Y Scrolls faster than Map
#
#
#  -----  PANORAMA AUTO SCROLLING  -----
#
#  You can set a Panorama to Scroll automagically either by setting a value
#  in the Config section, or by making a Script Call.  To enter a Config
#  value for Auto Scrolling, X Scroll Speeds should be the 5th value and
#  likewise, the Y Scroll Speed is the 6th value.
#
#  Map Config: [map_id, loop_type, scroll_x_spd, scroll_y_spd, auto_x, auto_y]
#
#  $game_map.panorama_ax = 4   - Automatically Scroll Panorama X
#  $game_map.panorama_ax = 7.5 - Automatically Scroll Panorama Y
#
#  NOTE: Maps do NOT need to Loop for Panorama Scrolling or Adjustments
#
#
#  -----  KNOWN BUGS  ------
#
#  Loop maps does not appear to work with Pathfinders at this time.
#
#  DOWNHILL ICE DELUXE can cause an "Artifact Glitch" where the bottom
#  of sprites appears at the top of the screen.  You can avoid this Glitch
#  in Mapping Technique.  It only occurs if the Player steps onto Downhill
#  Ice at the very bottom of a Looping Map.  You can allow the Player to
#  slide infinitely, just block access from stepping on to the infinite
#  or looping ice at the very bottom of your map.
#
#
# ------  LOOP MAP CONFIG SECTION  ------

#
# Map ID - Obvious
# Loop Type:
#   0 - No Looping (Normal Maps and Collisions
#   1 - Vertical Loop, no Horizontal
#   2 - Horizontal Loop, no Vertical
#   3 - Loop Horizontal and Vertical

#  -----  CONFIG  -----
#
# Edit these values to suit your game
#
#  Map Config: [map_id, loop_type, scroll_x, scroll_y, auto_x, auto_y]
#
#  NOTE: You don't need to put Names in for each entry
#
#  Example: [map_id = 1, loop_type = 3, nil, 16, -10.5, 14]
LOOP_MAPS = [ # Leave this character here!

  [map_id = 74, loop_type = 3, 8, 8, -10.5, 14], # Put commas if not the last set of []
  [map_id = 479, loop_type = 2],
  [map_id = 73, loop_type = 3],
  [map_id = 72, loop_type = 3, nil, 16, -10.5, 14],
  [map_id = 134, loop_type = 3]
            ] # Leave this character here!

# Adjustment to Top Edge of Map (Default)
LOOP_TOP_OFFSET = 2  #64 pixels or 2 tiles
LOOP_SIDE_OFFSET = 3


#  -----  END CONFIG  -----

# Check for Modular Passable Script - REQUIRED - DO NOT EDIT
unless $Modular_Passable
  print "Fatal Error: Heretics Loop Maps script\n",
        "requires Heretics Modular Passable Script!\n\n",
        "Modular Passable is Not Available or is below this script.\n",
        "Modular Passable MUST be above this script.\n\n",
        "The Game will now Exit"
  exit
end

#==============================================================================
# ** Game_Map - Class
#==============================================================================
class Game_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Game_Map
  #--------------------------------------------------------------------------
  attr_reader    :loop_type        # 0:Off 1:Vertical 2:Horizontal 3:Both
  attr_accessor  :looped           # Returns Direction if Map Looped or nil
  attr_accessor  :fog_ox           # Fog Origin X
  attr_accessor  :fog_oy           # Fog Origin Y
  attr_accessor  :loop_snap        # If corrections to Display on value change
  attr_accessor  :loop_top_offset  # Adjusts Top Edge for larger Maps
  attr_accessor  :loop_side_offset # Adjusts Side Edges for larger Maps
  attr_accessor  :loop_pan_x       # Panorama Adjustment when Looping Horizontal
  attr_accessor  :loop_pan_y       # Panorama Adjustment when Looping Vertical
  attr_accessor  :pan_scroll_x     # Panorama Scroll Rate X Override
  attr_accessor  :pan_scroll_y     # Panorama Scroll Rate Y Override
  attr_accessor  :panorama_ax      # Panorama Auto Scroll X Speed
  attr_accessor  :panorama_ay      # Panorama Auto Scroll Y Speed
  attr_accessor  :pan_ax_counter   # Panorama Adjustment Counter
  attr_accessor  :pan_ay_counter   # Panorama Adjustment Counter
  #--------------------------------------------------------------------------
  # * Setup - Game_Map
  #     map_id : Map ID
  #--------------------------------------------------------------------------
  alias loop_map_setup setup unless $@
  def setup(map_id)
    # Set the Default Loop Type
    @loop_type = 0
    # Returns Direction of Loop for ONE FRAME of UPDATE when a Map has Looped
    @looped = nil
    # Panorama Adjustments for Looping
    @loop_pan_x = 0
    @loop_pan_y = 0
    # Top Loop / Side Offsets from Config
    @loop_top_offset = LOOP_TOP_OFFSET
    @loop_side_offset = LOOP_SIDE_OFFSET
    # Adjust Display Values on Loop Type Change (false due to Bugs, artifacts)
    @loop_snap = true
    # Default Found Loop Map in Config
    found_loop_map = false
    # If Config has Looping Map
    for loops in LOOP_MAPS
      # If Config is set for this Map ID
      if loops[0] == map_id
        # Found the Map
        found_loop_map = true
        # Set Loop Type based on Config
        @loop_type = loops[1]         
        # Panorama Scroll Speed Adjustments
        @pan_scroll_x = (loops[2]) ? loops[2] : nil
        @pan_scroll_y = (loops[3]) ? loops[3] : nil
        # Panorama Auto Scroll Speeds
        @panorama_ax = (loops[4]) ? loops[4] : 0
        @panorama_ay = (loops[5]) ? loops[5] : 0
      end
    end
    # Check Nonexistent Values or Missing Config
    @panorama_ax = 0 if @panorama_ax.nil?
    @panorama_ay = 0 if @panorama_ay.nil?
    # Panorama Adjustment Counters
    @pan_ax_counter = 0
    @pan_ay_counter = 0
    # Call Original or other Aliases of Setup
    loop_map_setup(map_id)
    # If Loop Map Config is not found
    if not found_loop_map
      # Clear these values
      @pan_scroll_x = nil
      @pan_scroll_y = nil
      @panorama_ax = 0
      @panorama_ay = 0
    end   
  end
  #--------------------------------------------------------------------------
  # * Loop_Type= (Setter Method) - Game_Map
  #  - Changes Map Loop Type and Display Values appropriately
  #
  #  NOTE: Buggy!  More work is needed to prevent visual artifacts when
  #        the Display Values are adjusted by a vast degree.  Recommend
  #        to only use in the midde of a map where there is no "snap".
  #--------------------------------------------------------------------------
  def loop_type=(i)
    # If Valid
    if [0,1,2,3].include?(i)
      # Change to New Value
      @loop_type = i
      # Update Display X
      if [0,1].include?(i) and @loop_snap and
         (@display_x < 0 or @display_x > (self.width - 20) * 128)
        # Shorthand for Player X
        x = $game_player.x
        # Max X
        mx = ($game_map.width - 20) * 128
        # Correct Center Screen X
        $game_map.display_x = [0, [x * 128 - Game_Player::CENTER_X,mx].min].max
        # If Map Scene
        if $scene.is_a?(Scene_Map)
          # Correct Map Positions of ALL Events (unless allowed Off Map)
          $game_map.force_event_loop_round_positions
          # Force an Update of ALL Sprite Positions
          $scene.force_sprites_position_update
          # Correct Panorama Positions
          $scene.panorama_update_loop_scroll
        end
      end
      # Update Display Y
      if [0,2].include?(i) and @loop_snap and
         (@display_y < 0 or @display_y > (self.height - 15) * 128)
        # Shorthand for Player Y
        y = $game_player.y
        # Max Y
        my = ($game_map.height - 15) * 128
        # Correct Center Screen
        $game_map.display_y = [0, [y * 128 - Game_Player::CENTER_Y,my].min].max       
        # If Map Scene
        if $scene.is_a?(Scene_Map)
          # Correct Map Positions of ALL Events (unless allowed Off Map)
          $game_map.force_event_loop_round_positions
          # Force an Update of ALL Sprite Positions
          $scene.force_sprites_position_update
          # Correct Panorama Positions
          $scene.panorama_update_loop_scroll
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Loop? - Game_Map
  #--------------------------------------------------------------------------
  def loop?
    # True if Loop is 1, 2, or 3
    return (@loop_type > 0)
  end 
  #--------------------------------------------------------------------------
  # * Loop Horizontally? - Game_Map
  #--------------------------------------------------------------------------
  def loop_horizontal?
    return (@loop_type == 2 or @loop_type == 3)
  end
  #--------------------------------------------------------------------------
  # * Loop Vertically? - Game_Map
  #--------------------------------------------------------------------------
  def loop_vertical?
    return (@loop_type == 1 or @loop_type == 3)
  end
  #--------------------------------------------------------------------------
  # * Determine Valid Coordinates - Game_Map
  #     x          : x-coordinate
  #     y          : y-coordinate
  #     d          : direction (0,2,4,6,8,10)
  #                  *  0,10 = determine if all directions are impassable
  #     self_event : Character calling $game_map.passable 
  #     result     : true or false passed as an arg by Aliases
  #  - Added all available arguments for other Aliases to alter result
  #  - Adjusts X and Y values for Looping Maps
  #--------------------------------------------------------------------------
  alias map_loop_valid? valid? unless $@ 
  def valid?(x, y, d = nil, self_event = nil, result = nil) 
    # Fix X Value to Map Range if Map Loops Horizontally
    x %= @map.width if loop_horizontal?
    # Fix Y Value to Map Range if Map Loops Vertically
    y %= @map.height if loop_vertical?
    # Call Original or other Aliases
    map_loop_valid?(x, y, d, self_event, result)
  end
  #--------------------------------------------------------------------------
  # * Passable? - Game_Map
  #  - Adjusts X and Y values for Looping Maps
  #--------------------------------------------------------------------------
  alias map_loop_passable? passable? unless $@
  def passable?(x, y, d, self_event = nil)
    # Fix X Value to Map Range if Map Loops Horizontally
    x %= @map.width if loop_horizontal?
    # Fix Y Value to Map Range if Map Loops Vertically
    y %= @map.height if loop_vertical?
    # Call Original or other Aliases with updated X and Y
    map_loop_passable?(x, y, d, self_event)
  end
  #--------------------------------------------------------------------------
  # * Scroll Down - Game_Map
  #     distance : scroll distance
  #--------------------------------------------------------------------------
  alias map_loop_scroll_down scroll_down unless $@
  def scroll_down(distance)
    # If Map Loops Vertically
    if loop_vertical?
      # Update Display with no Limiters
      @display_y += distance
    else
      # Call Original or other Aliases
      map_loop_scroll_down(distance)
    end
  end
  #--------------------------------------------------------------------------
  # * Scroll Left - Game_Map
  #     distance : scroll distance
  #--------------------------------------------------------------------------
  alias map_loop_scroll_left scroll_left unless $@
  def scroll_left(distance)
    # If Map Loops Horizontal
    if loop_horizontal?
      # Update Display with no Limiters
      @display_x -= distance
    else
      # Call Original or other Aliases
      map_loop_scroll_left(distance)
    end
  end
  #--------------------------------------------------------------------------
  # * Scroll Right - Game_Map
  #     distance : scroll distance
  #--------------------------------------------------------------------------
  alias map_loop_scroll_right scroll_right unless $@
  def scroll_right(distance)
    # If Map Loops Horizontal
    if loop_horizontal?
      @display_x += distance
    else
      # Call Original or other Aliases
      map_loop_scroll_right(distance)
    end
  end
  #--------------------------------------------------------------------------
  # * Scroll Up - Game_Map
  #     distance : scroll distance
  #--------------------------------------------------------------------------
  alias map_loop_scroll_up scroll_up unless $@
  def scroll_up(distance)
    # If Map Loops Vertically
    if loop_vertical?
      @display_y -= distance
    else
      # Call Original or other Aliases
      map_loop_scroll_up(distance)
    end
  end
  #--------------------------------------------------------------------------
  # * Get Terrain Tag - Game_Map
  #     x          : x-coordinate
  #     y          : y-coordinate
  #--------------------------------------------------------------------------
  alias loop_map_terrain_tag terrain_tag unless $@
  def terrain_tag(x, y)
    # Adjust X Value if Map Loops Horizontally
    x %= width if loop_horizontal?
    # Adjust Y Value if Map Loops Vertically
    y %= height if loop_vertical?
    # Call Original or other Aliases with any Adjusted Arguments
    return loop_map_terrain_tag(x, y)
  end
  #--------------------------------------------------------------------------
  # * Determine Thicket (Bush) - Game_Map
  #     x          : x-coordinate
  #     y          : y-coordinate
  #--------------------------------------------------------------------------
  alias loop_map_bush? bush? unless $@
  def bush?(x, y)
    # Adjust X Value if Map Loops Horizontally
    x %= width if loop_horizontal?
    # Adjust Y Value if Map Loops Vertically
    y %= height if loop_vertical?
    # Call Original or other Aliases with any Adjusted Arguments
    return loop_map_bush?(x, y)
  end 
  #--------------------------------------------------------------------------
  # * Adjust X - Game_Map
  #     x : Real X of Character
  #--------------------------------------------------------------------------
  def adjust_x(x)
    # Display X in "tile values".
    dx = @display_x / 128.0
    # 20 represents the number of horizontal tiles in the screen.
    if loop_horizontal?
      # If Map Loop to the Right and Character close to Left Edge
      return x - dx + @map.width if x < dx - (width - 20) / 2
      # Top Map Edge Adjustment for Sprites at Bottom Edge of Maps
      e = $game_map.loop_side_offset
      # If Map Loop to the Left and Character close to Right Edge
      return x - dx - @map.width if dx < 0 + e and x > dx + (width + 20) / 2
    end
    return x - dx
  end
  #--------------------------------------------------------------------------
  # * Adjust Y - Game_Map
  #  - Limit is "Softened" by 2 tiles to allow proper rendering along
  #    Map Edges so map sizes may need to be increased accordingly
  #     y : Real Y of Character
  #--------------------------------------------------------------------------
  def adjust_y(y)
    # Display Y in "tile values".
    dy = @display_y / 128.0
    # 15 represents the number of vertical tiles in the screen.
    if loop_vertical?
      # If Map Loops to the Bottom and Character close to Top Edge
      return y - dy + @map.height if y < dy - (height - 15) / 2
      # Top Map Edge Adjustment for Sprites at Bottom Edge of Maps
      t = $game_map.loop_top_offset
      # If Map Loops to the Top and Character close to Bottom Edge
      return y - dy - @map.height if dy < 0 + t and y > dy + (height + 15) / 2
    end
    return y - dy
  end
  #--------------------------------------------------------------------------
  # * Force Event Loop Round Positions - Game_Map
  #  - Called when Loop Type is changed to correct all map positions
  #--------------------------------------------------------------------------
  def force_event_loop_round_positions
    # For ALL Events
    for event in @events.values
      # Corrects Looping Map Positions
      event.force_loop_round_positions
    end
  end
end

#==============================================================================
# ** Sprite_Character - Class
#==============================================================================
class Sprite_Character < RPG::Sprite
  #--------------------------------------------------------------------------
  # * Loop Force Position Update
  #  - Called when Loop Type is changed to correct all Sprite Screen Positions
  #--------------------------------------------------------------------------
  def loop_force_position_update
    # Set sprite coordinates
    self.x = @character.screen_x
    self.y = @character.screen_y
    self.z = @character.screen_z(@ch)
  end
end

#==============================================================================
# ** Spriteset_Map - Class
#==============================================================================
class Spriteset_Map
  #--------------------------------------------------------------------------
  # * Spriteset Force Position Update - Spriteset_Map
  #  - Called when Loop Type is changed to correct all Sprite Screen Positions
  #--------------------------------------------------------------------------
  def spriteset_force_position_update
    for sprite in @character_sprites
      # Force an Update now of all Sprite Locations due to a Loop Change
      sprite.loop_force_position_update
    end
  end
  #--------------------------------------------------------------------------
  # * Panorama Update Loop Scroll - Spriteset_Map
  #  - Updates Panorama Scrolling on either Looping or Non Looping Maps
  #--------------------------------------------------------------------------
  def panorama_update_loop_scroll
    # If Panorama Scroll X Value is adjusted
    if $game_map.pan_scroll_x
      # Adjust the Panorama X Position
      @panorama.ox = $game_map.display_x / $game_map.pan_scroll_x
    end
    # If Panorama Scroll Y Value is adjusted
    if $game_map.pan_scroll_y
      # Adjust the Panorama Y Position
      @panorama.oy = $game_map.display_y / $game_map.pan_scroll_y
    end
    # Shortcut
    p = @panorama
    # Clear Fog Looping Flags and adjust Auto Scrolling
    @panorama.ox += $game_map.loop_pan_x + $game_map.pan_ax_counter
    @panorama.oy += $game_map.loop_pan_y + $game_map.pan_ay_counter
    # If Panorama
    if @panorama_name != ""
      # Adjust Panorama Counters
      $game_map.pan_ax_counter += $game_map.panorama_ax / 8.0
      $game_map.pan_ay_counter += $game_map.panorama_ay / 8.0
      # Round Values based on size and zoom of Panorama
      $game_map.pan_ax_counter %= @panorama.bitmap.width * @panorama.zoom_x
      $game_map.pan_ay_counter %= @panorama.bitmap.height * @panorama.zoom_y
    end   
  end
  #--------------------------------------------------------------------------
  # * Update - Spriteset_Map
  #  - Adjusts Panorama Position on Looping Maps
  #  - Allows specific control over Panorama Scroll Rates
  #-------------------------------------------------------------------------- 
  alias loop_map_sprite_map_update update unless $@
  def update
    # Call Original or other Aliases
    loop_map_sprite_map_update
    # Update Panorama Scrolling
    panorama_update_loop_scroll
  end
end

class Scene_Map
  #--------------------------------------------------------------------------
  # * Loop Spriteset - Scene_Map
  #  - Just returns the Spriteset Object
  #--------------------------------------------------------------------------
  def loop_spriteset
    return @spriteset
  end 
  #--------------------------------------------------------------------------
  # * Force Sprites Position Update - Scene_Map
  #  - Calls command in the Spriteset Object
  #  - Called when Loop Type is changed
  #--------------------------------------------------------------------------
  def force_sprites_position_update
    @spriteset.spriteset_force_position_update
  end
  #--------------------------------------------------------------------------
  # * Panorama Update Loop Scroll - Scene_Map
  #  - Causes Panorama Positions to Update
  #  - Called when Loop Type is changed
  #--------------------------------------------------------------------------
  def panorama_update_loop_scroll
    @spriteset.panorama_update_loop_scroll
  end
end

#==============================================================================
# ** Interpreter
#==============================================================================
class Interpreter
  #--------------------------------------------------------------------------
  # * Change Map Settings - Interpreter
  #--------------------------------------------------------------------------
  alias loop_map_change_map_settings_command_204 command_204 unless $@
  def command_204
    # Reset Background 2 when Background 1 is changed
    case @parameters[0]
    when 0  # panorama
      # Reset the Counters used for Scrolling
      $game_map.pan_ay_counter = 0
      $game_map.pan_ay_counter = 0
    end
    # Continue
    return loop_map_change_map_settings_command_204
  end
end

#==============================================================================
# ** Game_Character - Class
#==============================================================================
class Game_Character
  #--------------------------------------------------------------------------
  # * Make New XY - Game_Character
  #  - Makes New Coordinates for X and Y (4 Directional Movement)
  #     x      : x-coordinate
  #     y      : y-coordinate
  #     d      : direction (0,2,4,6,8)
  #     result : Array passed as an arg by Aliases
  #
  #  NOTE: Must return an Array of New Map Coordinates [new_x, new_y]
  #    new_x, new_y = make_new_xy(x, y, d) 
  #  - This can be Aliased to alter New Coordinates based on other conditions
  #--------------------------------------------------------------------------
  alias map_loop_make_new_xy make_new_xy unless $@
  def make_new_xy(x, y, d, result = nil)
    # Get the New X and New Y Results of Make New XY
    new_x, new_y = map_loop_make_new_xy(x, y, d, result)
    # Fix X Value to Map Range if Map Loops Horizontally
    new_x %= $game_map.width if $game_map.loop_horizontal?
    # Fix Y Value to Map Range if Map Loops Vertically
    new_y %= $game_map.height if $game_map.loop_vertical?
    # Return Loop Adjusted Values
    return [new_x, new_y]
  end
  #--------------------------------------------------------------------------
  # * Make New XY 8D - Game_Character
  #  - Make New Coordinates for X and Y (8 Directional Movement)
  #     x     : x-coordinate
  #     y     : y-coordinate
  #     d     : direction (0,1,2,3,4,6,7,8,9 no 5)
  #     result : Array passed as an arg by Aliases   
  #  - This method is not called, but is available if needed
  #
  #  Note: Bit Flipping with 10 - d works, 10 - 9 (up right) = 1 (down left)
  #  Note: Must return an Array of New Map Coordinates [new_x, new_y]
  #    new_x, new_y = make_new_xy_8d(x, y, d)
  #--------------------------------------------------------------------------
  alias map_loop_make_new_xy_8d make_new_xy_8d unless $@
  def make_new_xy_8d(x, y, d, result = nil)
    # Get the New X and New Y Results of Make New XY
    new_x, new_y = map_loop_make_new_xy_8d(x, y, d, result)
    # Fix X Value to Map Range if Map Loops Horizontally
    new_x %= $game_map.width if $game_map.loop_horizontal?
    # Fix Y Value to Map Range if Map Loops Vertically
    new_y %= $game_map.height if $game_map.loop_vertical?
    # Return Loop Adjusted Values
    return [new_x, new_y]
  end
  #--------------------------------------------------------------------------
  # * Player Conditions? - Game_Character
  #  - Return true / false if conditions met
  #  - If New Location matches Player Position and Player not Through
  #     x          : x-coordinate
  #     y          : y-coordinate
  #     d          : direction (0,2,4,6,8,10)
  #                  *  0,10 = determine if all directions are impassable
  #     new_x : Target X Coordinate
  #     new_y : Target Y Coordinate 
  #     result     : values other than nil by Aliases override checks here
  #--------------------------------------------------------------------------
  alias loop_map_player_conditions? player_conditions? unless $@
  def player_conditions?(x, y, d, new_x, new_y, result = nil)
    # Ignore other Results and check for Looping Maps
    if $game_map.loop?
      # Game Player Shorthand
      p = $game_player
      # Adjust Player's X Location If map Loops Horizontal
      px = ($game_map.loop_horizontal?) ? p.x % $game_map.width : p.x
      # Adjust Player's Y Location If map Loops Vertical
      py = ($game_map.loop_vertical?) ? p.y % $game_map.height : p.y
      # If Coordinates match Player Location and Player Through is Off
      if px == new_x and py == new_y and not $game_player.through
        # Conditions are met
        return true
      end
    end
    # Call Original or other Aliases
    loop_map_player_conditions?(x, y, d, new_x, new_y, result)
  end 
  #--------------------------------------------------------------------------
  # * Passable? - Game_Character
  #  - Adjusts X and Y Argument Values for Looping Maps
  #--------------------------------------------------------------------------
  alias map_loop_character_passable? passable? unless $@
  def passable?(x, y, d)
    # Fix X Value to Map Range if Map Loops Horizontally
    x %= $game_map.width if $game_map.loop_horizontal?
    # Fix Y Value to Map Range if Map Loops Vertically
    y %= $game_map.height if $game_map.loop_vertical?
    # Call Original or other Aliases with updated X and Y
    map_loop_character_passable?(x, y, d)
  end
  #--------------------------------------------------------------------------
  # * Make Events List - Game_Character
  #  - Similar to Make Passable List
  #  - Intended for use in Non Passable determining methods in other Scripts
  #  - Intended to be aliased where X and Y values can be adjusted as needed
  #  - Excludes other Arguments needed by Make Passable List
  #  - Used by other Scripts with Triggers when X or Y have no arguments to fix
  #     x          : x-coordinate
  #     y          : y-coordinate
  #     results    : Array from other Aliases to override default results
  #--------------------------------------------------------------------------
  alias loop_map_make_events_list make_events_list unless $@
  def make_events_list(x, y, results = nil)
    # Determine Corrected Coordinates for Target
    x = ($game_map.loop_horizontal?) ? x % $game_map.width : x
    y = ($game_map.loop_vertical?) ? y % $game_map.height : y
    # Call Original or other Aliases with Adjusted Arguments
    loop_map_make_events_list(x, y, results)
  end
  #--------------------------------------------------------------------------
  # * Passable Conditions? - Game_Character
  #  - Return true / false if conditions met
  #  - Conditions for running Passability Checks on an Event
  #  - Typically an Event isnt checking itself, Through, and Coordinates match
  #     x          : x-coordinate
  #     y          : y-coordinate
  #     d          : direction (0,2,4,6,8,10)
  #                  *  0,10 = determine if all directions are impassable
  #     new_x      : Target X Coordinate
  #     new_y      : Target Y Coordinate 
  #     event      : Iterated Event made by make_passable_list 
  #     result     : values other than nil by Aliases override checks here
  #--------------------------------------------------------------------------
  alias loop_map_passable_conditions? passable_conditions?
  def passable_conditions?(x, y, d, new_x, new_y, event, result = nil)
    # Ignore other results if Looping Maps
    if $game_map.loop?
      # Adjust Coordinates for Looping Maps
      ex = ($game_map.loop_horizontal?) ? event.x % $game_map.width : event.x
      ey = ($game_map.loop_vertical?) ? event.y % $game_map.height : event.y
      new_x = ($game_map.loop_horizontal?) ? new_x % $game_map.width : new_x
      new_y = ($game_map.loop_vertical?) ? new_y % $game_map.height : new_y
      # Check Adjusted Coordinates for Position Match, Through, and Self
      if ex == new_x and ey == new_y and not event.through and event != self
        # Check this Event
        return true
      end
    end
    # Call Original or other Aliases
    loop_map_passable_conditions?(x, y, d, new_x, new_y, event, result)
  end
  #--------------------------------------------------------------------------
  # * Other Passable? - Game_Character
  #  - Adjusts Arguments of Aliases for Looping Maps
  #  - Used by Heretic's Caterpillar 2.0
  #  - Use any additional conditions for denying Passable
  #     x, new_x : x-coordinate
  #     y, new_y : y-coordinate
  #--------------------------------------------------------------------------
  alias loop_map_other_passable? other_passable? unless $@
  def other_passable?(x, y, d, new_x, new_y, result = nil)
    # If Map Loops Horizontal
    if $game_map.loop_horizontal?
      # Adjust the X Arguments to pass to Original or other Aliases
      x %= $game_map.width
      new_x %= $game_map.width
    end
    # If Map Loops Vertical
    if $game_map.loop_vertical?
      # Adjust the Y Arguments to pass to Original or other Aliases
      y %= $game_map.height
      new_y %= $game_map.height
    end 
    # Call Original or other Aliases with Modified Arguments except Results
    loop_map_other_passable?(x, y, d, new_x, new_y, result)
  end
  #--------------------------------------------------------------------------
  # * MP Match Coordinates - Game_Character
  #  - Modular Passable
  #  - Adjusts Coordinates for Looping Maps without affecting Results
  #     x, tx      : x-coordinate and Target x-coordinate to Match
  #     y, ty      : y-coordinate and Target Y-coordinate to Match
  #--------------------------------------------------------------------------
  alias loop_map_mp_match_coordinates? mp_match_coordinates? unless $@
  def mp_match_coordinates?(x, y, tx, ty)
    # If Map Loops Horizontal
    if $game_map.loop_horizontal?
      # Adjust the X Arguments to pass to Original or other Aliases
      x %= $game_map.width
      tx %= $game_map.width
    end
    # If Map Loops Vertical
    if $game_map.loop_vertical?
      # Adjust the X Arguments to pass to Original or other Aliases
      y %= $game_map.height
      ty %= $game_map.height
    end   
    # Call Original or other Aliases with any Adjusted Coordinates
    loop_map_mp_match_coordinates?(x, y, tx, ty)
  end 
  #--------------------------------------------------------------------------
  # * Character Distance - Game_Character
  #  - Returns the X and Y Distance between self and another Character
  #  - Checks for Maps that Loop either Horizontal or Vertical
  #      target : Character (Player or Event)
  #-------------------------------------------------------------------------- 
  def character_distance(target)
    # Determine Corrected Coordinates for Looping Maps
    x = ($game_map.loop_horizontal?) ? @x % $game_map.width : @x
    y = ($game_map.loop_vertical?) ? @y % $game_map.height : @y
    # Determine Corrected Coordinates for Target
    tx = ($game_map.loop_horizontal?) ? target.x % $game_map.width : target.x
    ty = ($game_map.loop_vertical?) ? target.y % $game_map.height : target.y
    # Get difference in target coordinates
    dx = x - tx
    dy = y - ty
    # If Map Loops Horizontal and Distance is more than Half the Map
    if $game_map.loop_horizontal? and dx.abs > $game_map.width / 2
      # Adjust X Distance for Horizontal Looping Map
      dx += (dx < 0) ? $game_map.width : -$game_map.width
    end
    # If Map Loops Vertical and Distance is more than Half the Map
    if $game_map.loop_vertical? and dy.abs > $game_map.height / 2
      # Adjust X Distance for Vertical Looping Map
      dy += (dy < 0) ? $game_map.height : -$game_map.height
    end
    # Return Difference X and Y values as Array
    return [dx, dy]
  end
  #--------------------------------------------------------------------------
  # * Turn Towards Player - Game_Character
  #--------------------------------------------------------------------------
  def turn_toward_player
    # Don't Turn if Direction Fix is ON
    return if @direction_fix
    # Determine Correct Distance to Target for Looping Maps
    sx, sy = character_distance($game_player)
    # If coordinates are equal
    if sx == 0 and sy == 0
      return
    end   
    # If horizontal distance is longer
    if sx.abs > sy.abs
      # Turn to the right or left towards player
      sx > 0 ? turn_left : turn_right
    # If vertical distance is longer
    else
      # Turn up or down towards player
      sy > 0 ? turn_up : turn_down
    end
  end
  #--------------------------------------------------------------------------
  # * Turn Away from Player - Game_Character
  #--------------------------------------------------------------------------
  def turn_away_from_player
    # Don't Turn if Direction Fix is ON
    return if @direction_fix
    # Determine Correct Distance to Target for Looping Maps
    sx, sy = character_distance($game_player)
    # If coordinates are equal
    if sx == 0 and sy == 0
      return
    end   
    # If horizontal distance is longer
    if sx.abs > sy.abs
      # Turn to the right or left away from player
      sx > 0 ? turn_right : turn_left
    # If vertical distance is longer
    else
      # Turn up or down away from player
      sy > 0 ? turn_down : turn_up
    end
  end
  #--------------------------------------------------------------------------
  # * Move toward Player - Game_Character
  #--------------------------------------------------------------------------
  def move_toward_player
    # Determine Correct Distance to Target for Looping Maps
    sx, sy = character_distance($game_player)
    # If coordinates are equal
    if sx == 0 and sy == 0
      return
    end
    # Get absolute value of difference
    abs_sx = sx.abs
    abs_sy = sy.abs
    # If horizontal and vertical distances are equal
    if abs_sx == abs_sy
      # Increase one of them randomly by 1
      rand(2) == 0 ? abs_sx += 1 : abs_sy += 1
    end
    # If horizontal distance is longer
    if abs_sx > abs_sy
      # Move towards player, prioritize left and right directions
      sx > 0 ? move_left : move_right
      if not moving? and sy != 0
        sy > 0 ? move_up : move_down
      end
    # If vertical distance is longer
    else
      # Move towards player, prioritize up and down directions
      sy > 0 ? move_up : move_down
      if not moving? and sx != 0
        sx > 0 ? move_left : move_right
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Move away from Player
  #--------------------------------------------------------------------------
  def move_away_from_player
    # Determine Correct Distance to Target for Looping Maps
    sx, sy = character_distance($game_player)
    # If coordinates are equal
    if sx == 0 and sy == 0
      return
    end
    # Get absolute value of difference
    abs_sx = sx.abs
    abs_sy = sy.abs
    # If horizontal and vertical distances are equal
    if abs_sx == abs_sy
      # Increase one of them randomly by 1
      rand(2) == 0 ? abs_sx += 1 : abs_sy += 1
    end
    # If horizontal distance is longer
    if abs_sx > abs_sy
      # Move away from player, prioritize left and right directions
      sx > 0 ? move_right : move_left
      if not moving? and sy != 0
        sy > 0 ? move_down : move_up
      end
    # If vertical distance is longer
    else
      # Move away from player, prioritize up and down directions
      sy > 0 ? move_down : move_up
      if not moving? and sx != 0
        sx > 0 ? move_right : move_left
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Make New XY Hash Conditions? - Game_Character
  #  - Determines if Event does not match the Stored Hash Keys
  #  - Used only if Modular Collision Optimizer is installed
  #--------------------------------------------------------------------------   
  def make_new_xy_hash_conditions?(x, y)
    # Correct Arguments for Looping Maps
    x = $game_map.loop_horizontal? ? x % $game_map.width : x
    y = $game_map.loop_vertical? ? y % $game_map.height : y
    # Evaluate the Conditions
    return (@map_hash_x != x or @map_hash_y != y)
  end 
  #--------------------------------------------------------------------------
  # * Make New XY Hash Keys - Game_Character
  #  - Creates X and Y Hash Keys using Rounded X and Y Values
  #  - Used only if Modular Collision Optimizer is installed
  #--------------------------------------------------------------------------   
  def make_new_xy_hash_keys
    x = $game_map.loop_horizontal? ? @x.round % $game_map.width : @x.round
    y = $game_map.loop_vertical? ? @y.round % $game_map.height : @y.round
    return [x,y]
  end 
  #--------------------------------------------------------------------------
  # * Screen X - Game_Character
  #  - Get Screen X-Coordinates
  #--------------------------------------------------------------------------
  def screen_x
    # Adjust for Looping Maps and Ceil to prevent Screen Event Tearing
    return ($game_map.adjust_x(@real_x / 128.0) * 32 + 16).ceil
  end
  #--------------------------------------------------------------------------
  # * Screen Y - Game_Character
  #  - Get Screen Y-Coordinates
  #--------------------------------------------------------------------------
  def screen_y
    # Determine Jump Height
    height = (@jump_peak * @jump_peak - (@jump_count - @jump_peak).abs ** 2) / 2
    # Adjust for Looping Maps and Ceil to prevent Screen Event Tearing
    return ($game_map.adjust_y(@real_y / 128.0) * 32 + 32 - height).ceil
  end
  #--------------------------------------------------------------------------
  # * Screen Z - Game_Character
  #  - Get Screen Z-Coordinates
  #     height : character height
  #--------------------------------------------------------------------------
  alias loop_map_screen_z screen_z unless $@
  def screen_z(height = 0)
    z = loop_map_screen_z(height)
    # Correct Z Index If Map Loops Vertical
    return ($game_map.loop_vertical? and not @always_on_top) ?
      z % ($game_map.height * 32.0) : z
  end
end

#==============================================================================
# ** Game_Event - Class
#==============================================================================
class Game_Event
  #--------------------------------------------------------------------------
  # * Check Event Trigger Touch - Game_Event
  #  - Touch Event Starting Determinant (Event Touches Player)
  #--------------------------------------------------------------------------
  alias loop_map_check_event_trigger_touch check_event_trigger_touch unless $@
  def check_event_trigger_touch(x, y)
    # If event is running
    if $game_system.map_interpreter.running?
      return
    end
    # If trigger is [touch from event] and consistent with player coordinates
    if @trigger == 2 and
       mp_match_coordinates?(x, y, $game_player.x, $game_player.y)
      # If starting determinant other than jumping is front event
      if not jumping? and not over_trigger?
        start
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Check Event Trigger Auto - Game_Event
  #  - Automatic Event Starting Determinant
  #--------------------------------------------------------------------------
  def check_event_trigger_auto
    # If trigger is [touch from event] and consistent with player coordinates
    if @trigger == 2 and
       mp_match_coordinates?(@x, @y, $game_player.x, $game_player.y)     
      # If starting determinant other than jumping is same position event
      if not jumping? and over_trigger?
        start
      end
    end
    # If trigger is [auto run]
    if @trigger == 3
      start
    end
  end
  #--------------------------------------------------------------------------
  # * Force Loop Round Positions - Game_Event
  #  - Called when Map Loop Type is changd to correct positions
  #  - Ignores Map Loop Properties when called
  #--------------------------------------------------------------------------
  def force_loop_round_positions
    # If not Allowed Off Map (Property of Heretic's Caterpillar or Other)
    if not (@through and @allowed_off_map)
      # Round X Coordinates
      @x %= $game_map.width
      # If Moving Horizontal
      d = (@real_x != @x * 128) ? @real_x - @x * 128 : 0
      # Correct Real X Coordinates to suit Animations
      if d.abs > $game_map.width * 64
        @real_x += (d < 0) ? $game_map.width * 128 : $game_map.width * -128
      else
        @real_x %= $game_map.width * 128
      end     
      # Round Y Coordinates
      @y %= $game_map.height
      # If Moving Vertical
      d = (@real_y != @y * 128) ? @real_y - @y * 128 : 0
      # Correct Real Y Coordinates to suit Animations
      if d.abs > $game_map.height * 64
        @real_y += (d < 0) ? $game_map.height * 128 : $game_map.height * -128
      else
        @real_y %= $game_map.height * 128
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Loop Round Coordinates - Game_Event
  #  - Corrects self position based on Looping Maps
  #--------------------------------------------------------------------------
  def loop_round_coordinates
    # If Map Loops Horizontally and Out of Map Range (No X Loop is Caterpillar)
    if $game_map.loop_horizontal? and not @no_x_loop_round and
       (@real_x < 0 or @real_x > $game_map.width * 128)
      # Correct Event's Position
      @x %= $game_map.width
      @real_x %= $game_map.width * 128
    end
    # If Map Loops Vertically and Out of Map Range (No Y Loop is Caterpillar)
    if $game_map.loop_vertical? and not @no_y_loop_round and
       (@real_y < 0 or @real_y > $game_map.height * 128)
      # Correct Event's Position
      @y %= $game_map.height
      @real_y %= $game_map.height * 128
    end   
  end
  #--------------------------------------------------------------------------
  # * Update - Game_Event
  #--------------------------------------------------------------------------
  alias loop_map_event_update update unless $@
  def update
    # Check for Looping Maps and adjust out of range coordinates
    loop_round_coordinates
    # Call Original or other Aliases
    loop_map_event_update
  end
end

#==============================================================================
# ** Game_Player
#==============================================================================
class Game_Player
  #----------------------------------------------------------------------------
  # * Check Event Trigger Here - Game_Player (FULL REDEFINITION)
  #  - Same Position Starting Determinant
  #  - Fully Redefines method Check Event Trigger Here
  #     triggers : Array of @trigger[0,1,2] Action Button, Player / Event Touch
  #----------------------------------------------------------------------------
  def check_event_trigger_here(triggers)
    result = false
    # If event is running
    if $game_system.map_interpreter.running?
      return result
    end
    # Create an Array of Events to check Triggers
    event_list = make_events_list(@x, @y)
    # Loop Events in List
    for event in event_list
      # If Coordinat Match and Triggers Arg is consistent with Event's Trigger
      if mp_match_coordinates?(@x, @y, event.x, event.y) and
         triggers.include?(event.trigger)
        # If starting determinant is same position event (other than jumping)
        if not event.jumping? and event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end 
  #--------------------------------------------------------------------------
  # * Check Event Trigger There - Game_Player (FULL REDEFINITION)
  #  - Front Envent Starting Determinant
  #      triggers : [0,1,2] for Action Button, Player Touch, Event Touch
  #--------------------------------------------------------------------------
  def check_event_trigger_there(triggers)
    result = false
    # If event is running
    if $game_system.map_interpreter.running?
      return result
    end
    # Calculate front event coordinates
    new_x, new_y = make_new_xy(@x, @y, @direction)
    # Create an Array of Events to check Triggers
    event_list = make_events_list(new_x, new_y)
    # Loop Events in List
    for event in event_list
      # If event coordinates and triggers are consistent
      if mp_match_coordinates?(new_x, new_y, event.x, event.y) and
         triggers.include?(event.trigger)
        # If starting determinant is front event (other than jumping)
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    # If fitting event is not found
    if result == false
      # If front tile is a counter
      if $game_map.counter?(new_x, new_y)
        # Calculate 1 tile inside coordinates
        new_x, new_y = make_new_xy(new_x, new_y, @direction)
        # Create an Array of Events to check Triggers
        event_list = make_events_list(new_x, new_y)
        # Loop Events in List
        for event in event_list
          # If event coordinates and triggers are consistent
          if mp_match_coordinates?(new_x, new_y, event.x, event.y) and
             triggers.include?(event.trigger)
            # If starting determinant is front event (other than jumping)
            if not event.jumping? and not event.over_trigger?
              event.start
              result = true
            end
          end
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # * Check Event Trigger Touch - Game_Player
  #  - Touch Event Starting Determinant
  #--------------------------------------------------------------------------
  alias map_loop_check_event_trigger_touch check_event_trigger_touch unless $@
  def check_event_trigger_touch(x, y)
    # Correct X and Y values for Looping Maps
    x = x % $game_map.width if $game_map.loop_horizontal?
    y = y % $game_map.height if $game_map.loop_vertical?
    # Use Corrected X and Y for Looping Maps to check Touch Triggers
    return map_loop_check_event_trigger_touch(x, y)
  end 
  #--------------------------------------------------------------------------
  # * Center - Game_Player
  #  - Positions Player
  #  - Set Map Display Position to Center of Screen
  #--------------------------------------------------------------------------
  alias loop_map_center center unless $@
  def center(x, y)
    # Call Original or other Aliases
    loop_map_center(x, y)   
    # Recenter Display Horizontally if Map Loops Horizontal
    $game_map.display_x = x * 128 - CENTER_X if $game_map.loop_horizontal?
    # Recenter Display Vertically if Map Loops Vertical
    $game_map.display_y = y * 128 - CENTER_Y if $game_map.loop_vertical?
  end
  #--------------------------------------------------------------------------
  # * Correct Loop Left - Game_Player
  #  - Corrects Player Coordinates, Fogs, and Panoramas on a Map Loop
  #--------------------------------------------------------------------------   
  def correct_loop_left(scroll_dist = 0)
    # Set Looped Property for Scripts to check Value for one frame
    $game_map.looped = 4   
    # Fix Player's Position
    @x %= $game_map.width
    @real_x %= $game_map.width * 128
    # Correct Map Display (Optional Arg for Corrections from other scripts)
    $game_map.display_x %= $game_map.width * 128
    $game_map.display_x += scroll_dist
    # Correct Fog Display
    $game_map.fog_ox -= $game_map.width * 32.0
    # If Game Guy's Unlimited Fogs with Heretic's Cloud Altitude
    if $scene.loop_spriteset.respond_to?(:get_all_multi_fogs)
      # Select each Fog in Spriteset Array
      for i in 1...$scene.loop_spriteset.get_all_multi_fogs.size
        # Shorthand for the Unlimited Fog Object
        fog = $scene.loop_spriteset.get_all_multi_fogs[i]
        # Adjust Fog Position for Loop Display
        fog.real_ox -= $game_map.width * 32.0
      end
    end
    # Panorama Scroll Speed Adjustment
    pscroll_x = ($game_map.pan_scroll_x) ? $game_map.pan_scroll_x / 8.0 : 1.0
    # Correct Panorama Display
    $game_map.loop_pan_x -= $game_map.width * 16.0 / pscroll_x
  end
  #--------------------------------------------------------------------------
  # * Correct Loop Right - Game_Player
  #  - Corrects Player Coordinates, Fogs, and Panoramas on a Map Loop
  #--------------------------------------------------------------------------   
  def correct_loop_right(scroll_dist = 0)
    # Set Looped Property for Scripts to check Value for one frame
    $game_map.looped = 6   
    # Fix Player's Position
    @x %= $game_map.width
    @real_x %= ($game_map.width * 128)
    # Correct Map Display (Optional Arg for Corrections from other scripts)
    $game_map.display_x %= $game_map.width * 128
    $game_map.display_x -= $game_map.width * 128 + scroll_dist
    # Correct Fog Display
    $game_map.fog_ox += $game_map.width * 32.0
    # If Game Guy's Unlimited Fogs with Heretic's Cloud Altitude
    if $scene.loop_spriteset.respond_to?(:get_all_multi_fogs)
      # Select each Fog in Spriteset Array
      for i in 1...$scene.loop_spriteset.get_all_multi_fogs.size
        # Shorthand for the Unlimited Fog Object
        fog = $scene.loop_spriteset.get_all_multi_fogs[i]
        # Adjust Fog Position for Loop Display
        fog.real_ox += $game_map.width * 32.0
      end
    end
    # Panorama Scroll Speed Adjustment
    pscroll_x = ($game_map.pan_scroll_x) ? $game_map.pan_scroll_x / 8.0 : 1.0
    # Correct Panorama Display
    $game_map.loop_pan_x += $game_map.width * 16 / pscroll_x
  end
  #--------------------------------------------------------------------------
  # * Correct Loop Up - Game_Player
  #  - Corrects Player Coordinates, Fogs, and Panoramas on a Map Loop
  #--------------------------------------------------------------------------   
  def correct_loop_up(scroll_dist = 0)
    # Set Looped Property for Scripts to check Value for one frame
    $game_map.looped = 8   
    # Fix Player's Position
    @y %= $game_map.height
    @real_y %= $game_map.height * 128
    # Correct Map Display (Optional Arg for Corrections from other scripts)
    $game_map.display_y %= $game_map.height * 128
    $game_map.display_y += scroll_dist
    # Correct Fog Display
    $game_map.fog_oy -= $game_map.height * 32.0
    # If Game Guy's Unlimited Fogs with Heretic's Cloud Altitude
    if $scene.loop_spriteset.respond_to?(:get_all_multi_fogs)
      # Select each Fog in Spriteset Array
      for i in 1...$scene.loop_spriteset.get_all_multi_fogs.size
        # Shorthand for the Unlimited Fog Object
        fog = $scene.loop_spriteset.get_all_multi_fogs[i]
        # Adjust Fog Position for Loop Display
        fog.real_oy -= $game_map.height * 32.0
      end
    end
    # Panorama Scroll Speed Adjustment
    pscroll_y = ($game_map.pan_scroll_y) ? $game_map.pan_scroll_y / 8.0 : 1.0
    # Correct Panorama Display
    $game_map.loop_pan_y -= $game_map.height * 16.0 / pscroll_y
  end
  #--------------------------------------------------------------------------
  # * Correct Loop Down - Game_Player
  #  - Corrects Player Coordinates, Fogs, and Panoramas on a Map Loop
  #-------------------------------------------------------------------------- 
  def correct_loop_down(scroll_dist = 0)
    # Set Looped Property for Scripts to check Value for one frame
    $game_map.looped = 2   
    # Fix Player's Position
    @y %= $game_map.height
    @real_y %= $game_map.height * 128
    # Correct Map Display (Optional Arg for Corrections from other scripts)
    $game_map.display_y %= $game_map.height * 128
    $game_map.display_y -= $game_map.height * 128 + scroll_dist
    # Correct Fog Display
    $game_map.fog_oy += $game_map.height * 32.0
    # If Game Guy's Unlimited Fogs with Heretic's Cloud Altitude
    if $scene.loop_spriteset.respond_to?(:get_all_multi_fogs)
      # Select each Fog in Spriteset Array
      for i in 1...$scene.loop_spriteset.get_all_multi_fogs.size
        # Shorthand for the Unlimited Fog Object
        fog = $scene.loop_spriteset.get_all_multi_fogs[i]
        # Adjust Fog Position for Loop Display
        fog.real_oy += $game_map.height * 32.0
      end
    end
    # Panorama Scroll Speed Adjustment
    pscroll_y = ($game_map.pan_scroll_y) ? $game_map.pan_scroll_y / 8.0 : 1.0
    # Correct Panorama Display
    $game_map.loop_pan_y += $game_map.height * 16.0 / pscroll_y
  end
  #--------------------------------------------------------------------------
  # * Map Loop Position - Game_Player
  #  - Calls for Corrections when Player triggers a Map Loop
  #-------------------------------------------------------------------------- 
  def map_loop_position
    # Set Looped Property for Scripts to check Value for ONE FRAME
    $game_map.looped = nil   
    # Ignore Corrections if not on a Looping Map
    return unless $game_map.loop_type > 0 and (moving? or jumping?)
    # If Horizontal Map Loop
    if $game_map.loop_horizontal?
      # Correct Positions if outside Map Boundaries
      correct_loop_left if @real_x < 0
      correct_loop_right if @real_x > $game_map.width * 128
    end
    # If Horizontal Map Loop
    if $game_map.loop_vertical?
      # Correct Positions if outside Map Boundaries
      correct_loop_up if @real_y < 0
      correct_loop_down if @real_y > $game_map.height * 128
    end
  end
  #--------------------------------------------------------------------------
  # * Update - Game_Player
  #--------------------------------------------------------------------------
  alias map_loop_update update unless $@
  def update
    # Update Map Loop Positions
    map_loop_position   
    # Call Original or other Aliases
    map_loop_update
  end
end

Thanks in advance.
2
Wecoc's Battle Scope adds more scope options to both items and skills. It's part of his collection that brings features from VX/ACE to XP.

The issue is that it causes skills or items that revive more than one actor to not work at all.
#==============================================================================
# [XP] VX Ace Wecoc Features (ACE_WF) VERSION 1.1
#------------------------------------------------------------------------------
# AC :     #024
# Name :   BATTLE_SCOPE
# Requires : -
# Incompat : -
# Author : Wecoc
#==============================================================================
# Description
#------------------------------------------------------------------------------
# Adds new 'random' scope options to items and skills.
#
#   0: none
#   1: one enemy
#   2: all enemies
#   3: one ally
#   4: all allies
#   5: 1 ally--HP 0
#   6: all allies--HP 0
#   7: the user
#
#   8: 1 random enemy
#   9: 2 random enemies
#  10: 3 random enemies
#  11: 4 random enemies
#  12: 5 random enemies
#  13: 6 random enemies
#  14: 7 random enemies
#
#  15: 1 random ally
#  16: 2 random allies
#  17: 3 random allies
#  18: 4 random allies
#  19: 5 random allies
#  20: 6 random allies
#  21: 7 random allies
#
#  22: 1 random ally--HP 0
#  23: 2 random allies--HP 0
#  24: 3 random allies--HP 0
#  25: 4 random allies--HP 0
#  26: 5 random allies--HP 0
#  27: 6 random allies--HP 0
#  28: 7 random allies--HP 0
#
# - How to call it
#     $data_items[id].scope = n
#     $data_skills[id].scope = n
#==============================================================================

module ACE_WF
  BATTLE_SCOPE = true
end

module RPG
  class Item
    def to_enemy?
      return [1, 2, 8, 9, 10, 11, 12, 13, 14].include?(@scope)
    end
   
    def to_ally?
      return (to_live_ally? or to_dead_ally?)
    end
   
    def to_live_ally?
      return [3, 4, 15, 16, 17, 18, 19, 20, 21].include?(@scope)
    end
   
    def to_dead_ally?
      return [5, 6, 22, 23, 24, 25, 26, 27, 28].include?(@scope)
    end
   
    def to_user?
      return @scope == 7
    end
   
    def to_singular?
      return [1, 3, 5, 7, 8, 15, 22].include?(@scope)
    end
   
    def to_multiple?
      return (not to_singular?)
    end
   
    def to_random?
      return @scope > 7
    end
  end
end

module RPG
  class Skill
    def to_enemy?
      return [1, 2, 8, 9, 10, 11, 12, 13, 14].include?(@scope)
    end
   
    def to_ally?
      return (to_live_ally? or to_dead_ally?)
    end
   
    def to_live_ally?
      return [3, 4, 15, 16, 17, 18, 19, 20, 21].include?(@scope)
    end
   
    def to_dead_ally?
      return [5, 6, 22, 23, 24, 25, 26, 27, 28].include?(@scope)
    end
   
    def to_user?
      return @scope == 7
    end
   
    def to_singular?
      return [1, 3, 5, 7, 8, 15, 22].include?(@scope)
    end
   
    def to_multiple?
      return (not to_singular?)
    end
   
    def to_random?
      return @scope > 7
    end
  end
end

class Scene_Battle
  def set_target_battlers(scope)
    live_actors = $game_party.actors.select {|x| x.exist? and x.hp0? == false}
    dead_actors = $game_party.actors.select {|x| x.exist? and x.hp0? == true}
    live_enemies = $game_troop.enemies.select {|x| x.exist? and x.hp0? == false}
    dead_enemies = $game_troop.enemies.select {|x| x.exist? and x.hp0? == true}
    # If battler performing action is enemy
    if @active_battler.is_a?(Game_Enemy)
      case scope
      when 1  # single enemy
        index = @active_battler.current_action.target_index
        @target_battlers.push($game_party.smooth_target_actor(index))
      when 2, 11..14  # all enemies
        for actor in live_actors + dead_actors # Bugfix
          @target_battlers.push(actor)
        end
      when 3  # single ally
        index = @active_battler.current_action.target_index
        @target_battlers.push($game_troop.smooth_target_enemy(index))
      when 4  # all allies
        for enemy in live_enemies + dead_enemies # Bugfix
          @target_battlers.push(enemy)
        end
      when 5  # single ally (HP 0)
        index = @active_battler.current_action.target_index
        enemy = $game_troop.enemies[index]
        if enemy != nil and enemy.hp0?
          @target_battlers.push(enemy)
        end
      when 6  # all allies (HP 0)
        for enemy in dead_enemies
          @target_battlers.push(enemy)
        end
      when 7  # user
        @target_battlers.push(@active_battler)
      when 8 # 1 random enemy
        @target_battlers.push(live_actors[rand(live_actors.size)])
      when 9 # 2 random enemies
        if live_actors.size <= 2
          for actor in live_actors
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_actors.size
              rand_array.push(rand(live_actors.size))
            end
            rand_array.uniq!
            if rand_array.size >= 2
              break
            end
          end
          @target_battlers.push(live_actors[rand_array[0]])
          @target_battlers.push(live_actors[rand_array[1]])
        end
      when 10 # 3 random enemies
        if live_actors.size <= 3
          for actor in live_actors
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_actors.size
              rand_array.push(rand(live_actors.size))
            end
            rand_array.uniq!
            if rand_array.size >= 3
              break
            end
          end
          @target_battlers.push(live_actors[rand_array[0]])
          @target_battlers.push(live_actors[rand_array[1]])
          @target_battlers.push(live_actors[rand_array[2]])
        end
      when 15 # 1 random ally
        @target_battlers.push(live_enemies[rand(live_enemies.size)])
      when 16 # 2 random allies
        if live_enemies.size <= 2
          for enemy in live_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 2
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
        end
      when 17 # 3 random allies
        if live_enemies.size <= 3
          for enemy in live_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 3
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
        end
      when 18 # 4 random allies
        if live_enemies.size <= 4
          for enemy in live_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 4
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
          @target_battlers.push(live_enemies[rand_array[3]])
        end
      when 19 # 5 random allies
        if live_enemies.size <= 5
          for enemy in live_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 5
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
          @target_battlers.push(live_enemies[rand_array[3]])
          @target_battlers.push(live_enemies[rand_array[4]])
        end
      when 20 # 6 random allies
        if live_enemies.size <= 6
          for enemy in live_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 6
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
          @target_battlers.push(live_enemies[rand_array[3]])
          @target_battlers.push(live_enemies[rand_array[4]])
          @target_battlers.push(live_enemies[rand_array[5]])
        end
      when 21 # 7 random allies
        if live_enemies.size <= 7
          for enemy in live_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 7
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
          @target_battlers.push(live_enemies[rand_array[3]])
          @target_battlers.push(live_enemies[rand_array[4]])
          @target_battlers.push(live_enemies[rand_array[5]])
          @target_battlers.push(live_enemies[rand_array[6]])
        end
      when 22 # 1 random ally --HP=0
        @target_battlers.push(dead_enemies[rand(live_enemies.size)])
      when 23 # 2 random allies --HP=0
        if dead_enemies.size <= 2
          for enemy in dead_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...dead_enemies.size
              rand_array.push(rand(dead_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 2
              break
            end
          end
          @target_battlers.push(dead_enemies[rand_array[0]])
          @target_battlers.push(dead_enemies[rand_array[1]])
        end
      when 24 # 3 random allies --HP=0
        if dead_enemies.size <= 3
          for enemy in dead_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...dead_enemies.size
              rand_array.push(rand(dead_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 3
              break
            end
          end
          @target_battlers.push(dead_enemies[rand_array[0]])
          @target_battlers.push(dead_enemies[rand_array[1]])
          @target_battlers.push(dead_enemies[rand_array[2]])
        end
      when 25 # 4 random allies --HP=0
        if dead_enemies.size <= 4
          for enemy in dead_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...dead_enemies.size
              rand_array.push(rand(dead_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 4
              break
            end
          end
          @target_battlers.push(dead_enemies[rand_array[0]])
          @target_battlers.push(dead_enemies[rand_array[1]])
          @target_battlers.push(dead_enemies[rand_array[2]])
          @target_battlers.push(dead_enemies[rand_array[3]])
        end
      when 26 # 5 random allies --HP=0
        if dead_enemies.size <= 5
          for enemy in dead_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...dead_enemies.size
              rand_array.push(rand(dead_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 5
              break
            end
          end
          @target_battlers.push(dead_enemies[rand_array[0]])
          @target_battlers.push(dead_enemies[rand_array[1]])
          @target_battlers.push(dead_enemies[rand_array[2]])
          @target_battlers.push(dead_enemies[rand_array[3]])
          @target_battlers.push(dead_enemies[rand_array[4]])
        end
      when 27 # 6 random allies --HP=0
        if dead_enemies.size <= 6
          for enemy in dead_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...dead_enemies.size
              rand_array.push(rand(dead_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 6
              break
            end
          end
          @target_battlers.push(dead_enemies[rand_array[0]])
          @target_battlers.push(dead_enemies[rand_array[1]])
          @target_battlers.push(dead_enemies[rand_array[2]])
          @target_battlers.push(dead_enemies[rand_array[3]])
          @target_battlers.push(dead_enemies[rand_array[4]])
          @target_battlers.push(dead_enemies[rand_array[5]])
        end
      when 28 # 7 random allies --HP=0
        if dead_enemies.size <= 7
          for enemy in dead_enemies
            @target_battlers.push(enemy)
          end
        else
          rand_array = []
          loop do
            for i in 0...dead_enemies.size
              rand_array.push(rand(dead_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 7
              break
            end
          end
          @target_battlers.push(dead_enemies[rand_array[0]])
          @target_battlers.push(dead_enemies[rand_array[1]])
          @target_battlers.push(dead_enemies[rand_array[2]])
          @target_battlers.push(dead_enemies[rand_array[3]])
          @target_battlers.push(dead_enemies[rand_array[4]])
          @target_battlers.push(dead_enemies[rand_array[5]])
          @target_battlers.push(dead_enemies[rand_array[6]])
        end
      end
    end
    # If battler performing action is actor
    if @active_battler.is_a?(Game_Actor)
      case scope
      when 1  # single enemy
        index = @active_battler.current_action.target_index
        @target_battlers.push($game_troop.smooth_target_enemy(index))
      when 2  # all enemies
        for enemy in live_enemies + dead_enemies # Bugfix
          @target_battlers.push(enemy)
        end
      when 3  # single ally
        index = @active_battler.current_action.target_index
        @target_battlers.push($game_party.smooth_target_actor(index))
      when 4, 18..21  # all allies
        for actor in live_actors + dead_actors # Bugfix
          @target_battlers.push(actor)
        end
      when 5  # single ally (HP 0)
        index = @active_battler.current_action.target_index
        actor = $game_party.actors[index]
        if actor != nil and actor.hp0?
          @target_battlers.push(actor)
        end
      when 6, 25..28  # all allies (HP 0)
        for actor in dead_actors
          @target_battlers.push(actor)
        end
      when 7  # user
        @target_battlers.push(@active_battler)
      when 8 # 1 random enemy
        @target_battlers.push(live_enemies[rand(live_enemies.size)])
      when 9 # 2 random enemies
        if live_enemies.size <= 2
          for actor in live_enemies
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 2
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
        end
      when 10 # 3 random enemies
        if live_enemies.size <= 3
          for actor in live_enemies
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 3
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
        end
      when 11 # 4 random enemies
        if live_enemies.size <= 4
          for actor in live_enemies
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 4
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
          @target_battlers.push(live_enemies[rand_array[3]])
        end
      when 12 # 5 random enemies
        if live_enemies.size <= 5
          for actor in live_enemies
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 5
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
          @target_battlers.push(live_enemies[rand_array[3]])
          @target_battlers.push(live_enemies[rand_array[4]])
        end
      when 13 # 6 random enemies
        if live_enemies.size <= 6
          for actor in live_enemies
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 6
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
          @target_battlers.push(live_enemies[rand_array[3]])
          @target_battlers.push(live_enemies[rand_array[4]])
          @target_battlers.push(live_enemies[rand_array[5]])
        end
      when 14 # 7 random enemies
        if live_enemies.size <= 7
          for actor in live_enemies
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_enemies.size
              rand_array.push(rand(live_enemies.size))
            end
            rand_array.uniq!
            if rand_array.size >= 7
              break
            end
          end
          @target_battlers.push(live_enemies[rand_array[0]])
          @target_battlers.push(live_enemies[rand_array[1]])
          @target_battlers.push(live_enemies[rand_array[2]])
          @target_battlers.push(live_enemies[rand_array[3]])
          @target_battlers.push(live_enemies[rand_array[4]])
          @target_battlers.push(live_enemies[rand_array[5]])
          @target_battlers.push(live_enemies[rand_array[6]])
        end
      when 15 # 1 random ally
        @target_battlers.push(live_actors[rand(live_actors.size)])
      when 16 # 2 random allies
        if live_actors.size <= 2
          for actor in live_actors
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_actors.size
              rand_array.push(rand(live_actors.size))
            end
            rand_array.uniq!
            if rand_array.size >= 2
              break
            end
          end
          @target_battlers.push(live_actors[rand_array[0]])
          @target_battlers.push(live_actors[rand_array[1]])
        end
      when 17 # 3 random allies
        if live_actors.size <= 3
          for actor in live_actors
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...live_actors.size
              rand_array.push(rand(live_actors.size))
            end
            rand_array.uniq!
            if rand_array.size >= 3
              break
            end
          end
          @target_battlers.push(live_actors[rand_array[0]])
          @target_battlers.push(live_actors[rand_array[1]])
          @target_battlers.push(live_actors[rand_array[2]])
        end
      when 22 # 1 random ally --HP = 0
        @target_battlers.push(dead_actors[rand(dead_actors.size)])
      when 23 # 2 random allies --HP = 0
        if dead_actors.size <= 2
          for actor in dead_actors
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...dead_actors.size
              rand_array.push(rand(dead_actors.size))
            end
            rand_array.uniq!
            if rand_array.size >= 2
              break
            end
          end
          @target_battlers.push(dead_actors[rand_array[0]])
          @target_battlers.push(dead_actors[rand_array[1]])
        end
      when 24 # 3 random allies --HP = 0
        if dead_actors.size <= 3
          for actor in dead_actors
            @target_battlers.push(actor)
          end
        else
          rand_array = []
          loop do
            for i in 0...dead_actors.size
              rand_array.push(rand(dead_actors.size))
            end
            rand_array.uniq!
            if rand_array.size >= 3
              break
            end
          end
          @target_battlers.push(dead_actors[rand_array[0]])
          @target_battlers.push(dead_actors[rand_array[1]])
          @target_battlers.push(dead_actors[rand_array[2]])
        end
      end
    end
  end
end
3
This mini script allows the creation of a weapon/shield/armor/accessory that recovers HP while walking on the map.  I'd like a edit that allows the same for SP as well as one that recovers both HP/SP. I tried to make the edit myself but it didn't quite work.  :^_^\':

#==============================================================================
    # ** [XP] Wecoc's Tips & Tricks Battle Collection
    #------------------------------------------------------------------------------
    # 78. Healing Mail
    #------------------------------------------------------------------------------
    # Armadura que por cada paso que haces por el mapa llevándola, cura un poco
    # al que la lleva y sube un poco su inteligencia
    # Nota: El personaje que la lleva tiene que estar vivo
    #==============================================================================

    class Game_Party
      alias healing_mail_steps increase_steps unless $@
      def increase_steps
        healing_mail_steps
        for actor in @actors
          next if actor.dead?
          if actor.armor3_id == 17 # ID de la armadura Healing Mail
            #-------- Efecto al andar --------------------------------------------
            actor.hp += actor.maxhp / 10
            if @steps % 10 == 0
              actor.int += 1
            end
            #---------------------------------------------------------------------
          end
        end
      end
    end


Thanks in advance.
4
I'd like to use this counter script found on this very forum:

#==========================================================================
    # ** UL Counter Attack
    #==========================================================================
    # Uncle Lanzer
    # Version 1
    # 21.09.10
    #==========================================================================
    #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
    # 
    #  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.
    # # 
    # #----------------------------------------------------------------------------

    #################
    #               # 
    # CONFIGURATION #
    #               #
    #################
    # IT`S PRETTY SIMPLE........ JUST KILL THE BATMAN! <-- FORGET THAT -.-U
    # MAKE A "(YOUR COUNTER NAME)" STATE
    # UL_COUNTER_STATES = { A => [ B,C]}
    # A = THE COUNTER STATE
    # B = RATE OF SUCCESS
    # C = STRENGHT OF COUNTER ( % OF A NORMAL ATTACK)
    Scene_Battle::UL_Counter_States = { 32 => [100,100]} #ADD MORE BY THE SAME SYNTAX


    # MESSAGGE WHEN COUNTER
    Scene_Battle::UL_Counter_Messages = ['\m Counter!']

    # CHECKING SCRIPT
    if !@ul_counterattack_disabled

    # START
    class Game_Battler
       
      alias lanzer_counter_battler_atkeff attack_effect
      def attack_effect(attacker)
        lanzer_counter_battler_atkeff(attacker)
        if $scene.active_battler == attacker
          $scene.ul_atkcounter_test(self)
        end
      end
     
      alias counter_skill_attacks skill_effect
      def skill_effect(attacker, skill)
        counter_skill_attacks(attacker, skill)
        if $scene.active_battler == attacker and skill.power > 0
          $scene.ul_atkcounter_test(self)
        end
      end
     
    end

    class Scene_Battle
      attr_accessor :active_battler
     
      def ul_atkcounter_test(battler)
        # The actor is applied with a state that prevents movement. Stop counter.
        return unless battler.movable?
       
        ul_temp = UL_Counter_States.keys
        for i in 0...ul_temp.size
          if battler.state?(ul_temp[i])
            if UL_Counter_States[ul_temp[i]][0] > rand(99)
              @ul_counter = UL_Counter_States[ul_temp[i]][1]
              @ul_countertarget = battler
              return
            end
          end
        end
      end
     
      alias lanzer_counter_battle_up4s5 update_phase4_step5
      def update_phase4_step5
        lanzer_counter_battle_up4s5
        if @ul_countertarget != nil
          @phase4_step = 1337  # LEET
          @ul_atkcounter = 28
        end
      end
     
      def ul_counter_update
        if @ul_countertarget.dead? or @ul_atkcounter == 0 or !@ul_countertarget.movable?
          @ul_atkcounter = nil
          @ul_counter = nil
          @ul_countertarget = nil
          @phase4_step = 6
          return
        end
        @ul_atkcounter -= 1
        if @ul_atkcounter == 10
          @ul_countertarget.animation_id = @ul_countertarget.animation1_id
          @active_battler.animation_id = @ul_countertarget.animation2_id
          ul_temp = rand(UL_Counter_Messages.size)
          ul_temp = UL_Counter_Messages[ul_temp].clone
          ul_temp.gsub!(/\\[Mm]/) { @ul_countertarget.name }
          @help_window.set_text(ul_temp, 1)
          @active_battler.attack_effect(@ul_countertarget)
          if !@active_battler.damage.is_a?(String)
            @active_battler.hp += @active_battler.damage
            @active_battler.damage = @active_battler.damage * @ul_counter / 100
            @active_battler.hp -= @active_battler.damage
            @status_window.refresh
          end
          @active_battler.damage_pop = true
        end
      end
     
      alias lanzer_counter_battle_update update
      def update
        if @ul_atkcounter != nil
          ul_counter_update
        end
        lanzer_counter_battle_update
      end
    end

    #--------------------------------------------------------------------------#
    end


After a thorough test, this error popped out when trying to use healing skills from the main menu (I'm currently using the latest version of Stormtronic CMS):

5
This is LockeZ's "HP Sacrifice" script. It allows the creation of skill that consume HP instead of SP.

#==============================================================================
# HP Sacrifice
# By LockeZ
#==============================================================================
# This script allows you to create skills and items that cost HP when used.
#
# Compatible with the default battle system.
# Compatible with Tankentai.
#
# Contact me at ff3lockez@yahoo.com with questions.
#==============================================================================

module LockeZ
  # Do not remove this line
  HP_Sacrifice_Action = {'Skill' => {}, 'Item' => {}}
  # Do not remove this line
 
  # Below here are the lines you can change to control which actions
  #   cost HP, and how much.
 
  # Format for each line:
  # ---------------------
  # HP_Sacrifice_Action[action_type][id] = [chance, formula, amount, anim_id, pop, can_kill]
 
 
  # And here is what each of those things means:
 
  # action_type = Should be set to 'Skill' or 'Item'
  # id          = ID number of the skill/item that costs HP
  #
  # chance  = chance of damaging self
  # formula = How the amount lost is calculated.  Must be 'integer' or 'percent'.
  # amount  = Amount of HP lost, based on formula.  If formula is set to
  #           integer, this is the actual amount lost.  If it's set to percent,
  #           this is the percent lost.
  # anim_id = ID of the animation shown over the user; leave nil or 0 for
  #           no animation
  # pop     = true or false, whether the sacrificed amount pops up visually
  #           over the user's head like damage.
  # can_kill = true or false.  If false the skill will not reduce the user below
  #            1 HP.  If true it can kill the user.
 
 
  # Example Skills
  # The "Darkness" spell (spell #28) now costs 250 HP to cast.  It won't
  #   reduce the caster below 1 HP.
 
  HP_Sacrifice_Action['Skill'][86] = [100, 'percent', 5, nil, false, false]
  # The "Mass Darkness" spell (spell #30) now costs 500 HP to cast.  It can
  #   kill the caster.
 
  HP_Sacrifice_Action['Skill'][86] = [100, 'percent', 5, nil, false, false]
  HP_Sacrifice_Action['Skill'][90] = [100, 'percent', 10, nil, false, false]
  HP_Sacrifice_Action['Skill'][91] = [100, 'percent', 12, nil, false, false]
  HP_Sacrifice_Action['Skill'][93] = [100, 'percent', 5, nil, false, false]
  HP_Sacrifice_Action['Skill'][94] = [100, 'percent', 7, nil, false, false]
  HP_Sacrifice_Action['Skill'][100] = [100, 'percent', 5, nil, false, false]
  HP_Sacrifice_Action['Skill'][99] = [100, 'percent', 5, nil, false, false]
  HP_Sacrifice_Action['Skill'][101] = [100, 'percent', 10, nil, false, false]
  HP_Sacrifice_Action['Skill'][103] = [100, 'percent', 7, nil, false, false] 
  HP_Sacrifice_Action['Skill'][114] = [100, 'percent', 7, nil, false, false]
  HP_Sacrifice_Action['Skill'][115] = [100, 'percent', 12, nil, false, false]
  HP_Sacrifice_Action['Skill'][116] = [100, 'percent', 15, nil, false, false]
  HP_Sacrifice_Action['Skill'][125] = [100, 'percent', 15, nil, false, false]
  HP_Sacrifice_Action['Skill'][200] = [100, 'percent', 18, nil, false, false]
  HP_Sacrifice_Action['Skill'][130] = [100, 'percent', 7, nil, false, false]
  HP_Sacrifice_Action['Skill'][131] = [100, 'percent', 10, nil, false, false]
  HP_Sacrifice_Action['Skill'][126] = [100, 'percent', 15, nil, false, false]
  HP_Sacrifice_Action['Skill'][88] = [100, 'percent', 5, nil, false, false]
  HP_Sacrifice_Action['Skill'][401] = [100, 'percent', 1, nil, false, false]
  HP_Sacrifice_Action['Skill'][117] = [100, 'percent', 10, nil, false, false]
  HP_Sacrifice_Action['Skill'][404] = [100, 'integer', 500, nil, true, false]
  HP_Sacrifice_Action['Skill'][407] = [100, 'percent', 75, nil, false, false]
  HP_Sacrifice_Action['Skill'][104] = [100, 'percent', 10, nil, false, false]
  HP_Sacrifice_Action['Skill'][408] = [100, 'percent', 100, 111, true, true]
  HP_Sacrifice_Action['Skill'][409] = [100, 'percent', 100, 111, true, true]
  end

#==============================================================================
# ** Don't modify anything below this point.
#==============================================================================


#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
#  This class performs battle screen processing.
#==============================================================================

class Scene_Battle
  include LockeZ
 
  #--------------------------------------------------------------------------
  # These 2 methods makes the script compatible with the default battle system.
  #--------------------------------------------------------------------------
  unless respond_to?('step4_part3')
    alias make_skill_action_result_hp_sacrifice make_skill_action_result
    def make_skill_action_result
      make_skill_action_result_hp_sacrifice
      action = @active_battler.current_action
      if action != nil and HP_Sacrifice_Action['Skill'].include?(action.skill_id)
        sacrifice_hp(@active_battler, HP_Sacrifice_Action['Skill'][action.skill_id].dup)
      end
    end
 
    alias make_item_action_result_hp_sacrifice make_item_action_result
    def make_item_action_result
      make_item_action_result_hp_sacrifice
      action = @active_battler.current_action
      if action != nil and HP_Sacrifice_Action['Item'].include?(action.item_id)
        sacrifice_hp(@active_battler, HP_Sacrifice_Action['Item'][action.item_id].dup)
      end
    end
  end
 
  #--------------------------------------------------------------------------
  # Sacrifice HP
  #     battler : active battler
  #     action  : action
  #--------------------------------------------------------------------------
  def sacrifice_hp(battler, action)
    if action[0] >= rand(100)
      if action[1] == 'integer'
        hp_sacrificed = action[2].to_i
      elsif action[1] == 'percent'
        hp_sacrificed = (battler.maxhp * action[2] / 100).to_i
      end
      if action[5] == false
        hp_sacrificed = [battler.hp - 1, hp_sacrificed].min
      end
      if hp_sacrificed != 0
        # This line happens only in the DBS
        # Atoa's CBS does this automatically for all damage
        battler.hp -= hp_sacrificed

        battler.damage = hp_sacrificed
        battler.animation_id = action[3].nil? ? 0 : action[3]
        battler.damage_pop = action[4]
        @status_window.refresh
      end
    end
  end
end


The problem I detected is that you can cast the skills regardless of the HP you currently have. For example, the very first skill in the script consume 5% of the character's current HP and yet it can still be used if the character only have 1 HP, as long as you haven't configured the skill to kill the caster if it eats more HP than they have. This also happens if you've set up an ability that uses a flat number.
6
I'm trying to use this roulette script I found on a Spanish RM forum:

=begin

  Script creado por newold
  Versión 1.0 - 04-10-2014
  De uso libre

  Crea una ruleta con varias opciones y guarda el resultado de la tirada
  en una variable para poder ser usada por los eventos.


                                  INSTRUCCIONES
                                 
  * comando llamar script en los eventos y poner
 
      $ruleta = Roulette.new
     
  * Configuración de la ruleta (escribir dentro del comando llamar script):
 
    $ruleta.width = número  <- Ancho de la ruleta
   
    $ruleta.height = número <- Alto de la ruleta
   
    $ruleta.x = número <- Posición x en la pantalla de la ruleta
   
    $ruleta.y = número <- Posición y en la pantalla de la ruleta
   
    $ruleta.minMov = número <- Menor valor de desplazamiento
                               horizontal del selector
   
    $ruleta.maxMov = número <- Mayor valor de desplazamiento
                               horizontal del selector
   
    $ruleta.mov = número <- Valor fijo para calcular movimiento del selector
   
    $ruleta.randMov = número <- Valor aleatorio para calcular
                                movimiento del selector
   
    $ruleta.se = "Ruta de un efecto de sonido" <- efecto de sonido al
                                                  mover el selector
   
    $ruleta.variable = número <- número de variable a la que se le asignará el
                                 valor de dónde se ha parado la ruleta
                                 (empezando por 0)
                                 
    $ruleta.fontName = "nombre tipografía" <- nombre de la tipografía cuando se
                                              escribe texto
                                             
   
    $ruleta.fontSize = número <- Tamaño del texto
   
    $ruleta.fontColor = color <- Color con el que se dibujará el texto
                                 color = Color.new(0-255,0-255,0-255,0-255)
                                 
  * Añadir datos a la ruleta:
 
    la estructura básica para añadir cosas a la ruleta es como sigue:
   
    $ruleta.set_data(tipo,id,porciento,color de fondo)
 
    - Añadir un objeto: $ruleta.set_data('item',ID item, Porciento, Color fondo)
   
    - Añadir un protector: $ruleta.set_data('armor',ID armor, Porciento, Color fondo)
   
    - Añadir un arma: $ruleta.set_data('weapon',ID weapon, Porciento, Color fondo)
   
    - Añadir una imagen: $ruleta.set_data('ruta imagen',0, Porciento, Color fondo)
 
    - Añadir una texto: $ruleta.set_data('texto',0, Porciento, Color fondo)
   
    - Añadir porción vacía: $ruleta.set_data('',0, Porciento, Color fondo)
   
  * lanzar la ruleta:
 
    Una vez configurada la ruleta y añadido los datos, lanzar la ruleta con
   
        $ruleta.start
       
    la ruleta empezará a girar y al detenerse asignará la posición del cursor
    a la variable especificada en la configuración.
   
    Si por ejemplo has añadido 4 cosas a la ruleta, y cuando se para ésta está
    la segunda cosa que añadiste, el valor de la variable será entonces 1. Si
    está en la primera posición será 0, y así con todos los datos (0,1,2,3,4,5...)
   
    Con ese dato ya puedes configurar un evento para que reaccione con el premio
    que ha tocado :D
=end

#===============================================================================
class Roulette
  # ----------------------------------------------------------------------------
  attr_accessor :width,     :height,      :x,      :y,
                :minMov,    :mod,         :se,     :variable,
                :mov,       :randMov,     :maxMov,
                :fontName,  :fontSize,    :fontColor
  # ----------------------------------------------------------------------------
  def initialize
    @data = []
    @perc = 0
    @width = 320
    @height = 42
    @x = RUBY_VERSION < "1.9" ? 160 : 112
    @y = RUBY_VERSION < "1.9" ? 233 : 369
    @mov = 750
    @randMov = 1000
    @maxMov = 12
    @minMov = 0.2
    @mod = 12
    @se = 'Audio/SE/cursor'
    @variable = 1
    @fontName = ["Verdana","Arial"]
    @fontSize = 18
    @fontColor = Color.new(255,255,255)
  end
  # ----------------------------------------------------------------------------
  def set_data(type,id,perc,color=nil)
    @data << [type,id,perc,(color.is_a?(Color) ? color :
    Color.new(rand(255),rand(255),rand(255)))]
    @perc += perc
  end
  # ----------------------------------------------------------------------------
  def start
    draw
    mov = @mov + rand(@randMov)
    mod = @mod.to_f
    maxMov = @maxMov
    minMov = @minMov
    xx = @line.x
    n = 0
    while true
      Graphics.update
      if mov / mod >= 0.25
        x = [[mov / mod,maxMov].min,minMov].max
        xx += x
        n += x
        if n >= 5
          Audio.se_play(@se)
          n = 0
        end
        @line.x = xx
        if @line.x > @x + @width - 3
          @line.x = @x; xx = @line.x;
        end
        mov -= x
      else
        break
      end
      mod += 1
    end
    12.times {Graphics.update}
    reward = 0
    x = @x + 2
    for i in 0...@data.size
      data = @data[i]
      x2 = x + (data[2] * (@width-4) / @perc)
      if @line.x + 2 >= x and @line.x + 2 <= x2
        break
      else
        reward += 1
        x = x2
        next
      end
    end
    $game_variables[@variable] = reward
    dispose
  end
  # ----------------------------------------------------------------------------
  def draw
    w, h = @width, @height
    @bar = Sprite.new
    @bar.x = @x
    @bar.y = @y
    @bar.z = 10000000
    @bar.bitmap = Bitmap.new(w,h)
    @bar.bitmap.fill_rect(0,0,w,h,Color.new(235,235,235))
    @bar.bitmap.fill_rect(1,1,w-2,h-2,Color.new(160,160,160))
    @bar.bitmap.fill_rect(2,2,w-4,h-4,@data[-1][3])
    b2 = Bitmap.new(w,h)
    x = 2
    sep = []
    for data in @data
      w2 = (data[2] * (w-4) / @perc)
      @bar.bitmap.fill_rect(x,2,w2,h-4,data[3])
      item = nil
      case data[0]
      when 'item','objeto',1
        item = $data_items[data[1]]
      when 'weapon','arma',2
        item = $data_weapons[data[1]]
      when 'armor','armadura',3
        item = $data_armors[data[1]]
      else
        if (data[0].class == Bitmap)
          item = data[0]
        elsif (data[0].class == String)
          begin
            item = Bitmap.new(data[0])
          rescue
            begin
            b = Bitmap.new(1,1)
            b.font.name = @fontName
            b.font.size = @fontSize
            size = b.text_size(data[0])
            b = Bitmap.new(size.width,size.height)
            b.font.name = @fontName
            b.font.size = @fontSize
            b.font.color = @fontColor
            b.draw_text(0,0,b.width,b.height,data[0])
            b2.blt(x+w2/2-b.width/2,(h-4)/2-b.height/2,b,b.rect)
            rescue
            end
          end
        end
      end
      if [RPG::Item,RPG::Weapon,RPG::Armor].include?(item.class)
        b = RPG::Cache.icon(item.icon_name)
        b2.blt(x+w2/2-b.width/2,(h-4)/2-b.height/2,b,b.rect)
      elsif item.is_a?(Bitmap)
        b = item
        b2.blt(x+w2/2-b.width/2,(h-4)/2-b.height/2,b,b.rect)
      end
      x += w2
      sep << x unless data == @data[-1]
    end
    @bar.bitmap.blt(0,0,b2,b2.rect)
   
    color = Color.new(0,0,0)
    sep.each {|x|
      @bar.bitmap.fill_rect(x,2,1,h-4,color)
    }
   
    @line = Sprite.new
    @line.bitmap = Bitmap.new(5,h+4)
    @line.bitmap.fill_rect(0,0,1,h+4,Color.new(255,0,0,55))
    @line.bitmap.fill_rect(1,0,1,h+4,Color.new(255,0,0,160))
    @line.bitmap.fill_rect(2,0,1,h+4,Color.new(255,0,0,255))
    @line.bitmap.fill_rect(3,0,1,h+4,Color.new(255,0,0,160))
    @line.bitmap.fill_rect(4,0,1,h+4,Color.new(255,0,0,55))
    @line.x = @x
    @line.y = @y - 2
    @line.z = 10000001
  end
  # ----------------------------------------------------------------------------
  def dispose
    @bar.dispose
    @line.dispose
  end
  # ----------------------------------------------------------------------------
end
#===============================================================================


In order to use, I need to cram a code similar to this into the script window:



But when I attempt to do the same in my game, this is the result:

a = Roulette.new
a.set_data('',0,20,Color.new(160,0,0,100))
a.set_data('item',1,10)
a.set_data('',0,20,Color.new(160,0,0,100))
a.set_data('armor',1,35)
a.set_data('',0,20,Color.new(160,0,0,100))
a.set_data('weapon',1,10)
a.set_data('',0,20,Color.new(160,0,0,100))


I'm left with a few lines missing due to space constraints. My question is: is there a way to bypass the character limit of the Script window to make this work as intended?

I wish I could ask the author of this script but s/he's nowhere to be found.
7
This version of Paradog's Battle BGM Anti-Reset was edited to play the battle theme as a ME. This way, the map music won't reset after the battle is finished. It works as intended, but there's a problem if you escape from the fight: the battle theme will continue to play until it finishes. Is there a way to fix this?

There's the script:

#==============================================================================
#????Battle BGM Anti-Reset ver. 1.00???
#??Script by ParaDog
#??http://2d6.parasite.jp/
#------------------------------------------------------------------------------
# Prevents the music from starting over when entering combat if both the field
# map's and battlesystem's BMG are the same.  Likewise, the music will not re-
# set upon escaping combat,  or after victory if the  'battle end ME' has been
# turned off (set to 'None).
#------------------------------------------------------------------------------
# For best results of this system, please set the 'Battle End ME'  to ("None)"
# in either the SYSTEM section or through an event command.
#==============================================================================

#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
#  This class performs map screen processing.
#==============================================================================

class Scene_Map
 #--------------------------------------------------------------------------
 # * Battle Call
 #--------------------------------------------------------------------------
 def call_battle
   # Clear battle calling flag
   $game_temp.battle_calling = false
   # Clear menu calling flag
   $game_temp.menu_calling = false
   $game_temp.menu_beep = false
   # Make encounter count
   $game_player.make_encounter_count
   # Memorize map BGM and stop BGM
   $game_temp.map_bgm = $game_system.playing_bgm
   # Play battle start SE
   $game_system.se_play($data_system.battle_start_se)
   # Play battle BGM
   #If Switch 1 is ON
   if $game_switches[1] == true
     # Play same battle BGM as the map BGM
     $game_system.battle_bgm = $game_temp.map_bgm
     $game_system.bgm_play($game_system.battle_bgm)
   #If Switch 2 is ON
   elsif $game_switches[2] == true
     # Play the basic battle BGM
     # ! WILL RESET THE MAP BGM AFTER BATTLE ! #
     # I use this for bosses, so that the battle BGM can loop.
     $game_system.bgm_play($game_system.battle_bgm)
   #Else, if Switch 1 and Switch 2 are OFF
   elsif $game_switches[1] == false and $game_switches[2] == false
   #Play battle BGM as ME (won't loop)
   Audio.me_play("Audio/BGM/" + $game_system.battle_bgm.name, $game_system.battle_bgm.volume, $game_system.battle_bgm.pitch)
   end
   # Straighten player position
   $game_player.straighten
   # Switch to battle screen
   $scene = Scene_Battle.new
 end
end

#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
#  This class performs battle screen processing.
#==============================================================================

class Scene_Battle
 #--------------------------------------------------------------------------
 # * Start After Battle Phase
 #--------------------------------------------------------------------------
 def start_phase5
   # Shift to phase 5
   @phase = 5
   if $game_system.battle_end_me.name != ""
     # Play battle end ME
     $game_system.me_play($game_system.battle_end_me)
   end
   # Return to BGM before battle started
   $game_system.bgm_play($game_temp.map_bgm)
   # Initialize EXP, amount of gold, and treasure
   exp = 0
   gold = 0
   treasures = []
   # Loop
   for enemy in $game_troop.enemies
     # If enemy is not hidden
     unless enemy.hidden
       # Add EXP and amount of gold obtained
       exp += enemy.exp
       gold += enemy.gold
       # Determine if treasure appears
       if rand(100) < enemy.treasure_prob
         if enemy.item_id > 0
           treasures.push($data_items[enemy.item_id])
         end
         if enemy.weapon_id > 0
           treasures.push($data_weapons[enemy.weapon_id])
         end
         if enemy.armor_id > 0
           treasures.push($data_armors[enemy.armor_id])
         end
       end
     end
   end  
   # Treasure is limited to a maximum of 6 items
   treasures = treasures[0..5]
   # Obtaining EXP
   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 += exp
       if actor.level > last_level
         @status_window.level_up(i)
       end
     end
   end
   # Obtaining gold
   $game_party.gain_gold(gold)
   # Obtaining treasure
   for item in treasures
     case item
     when RPG::Item
       $game_party.gain_item(item.id, 1)
     when RPG::Weapon
       $game_party.gain_weapon(item.id, 1)
     when RPG::Armor
       $game_party.gain_armor(item.id, 1)
     end
   end
   # Make battle result window
   @result_window = Window_BattleResult.new(exp, gold, treasures)
   if $game_system.battle_end_me.name != ""
     # Set wait count
     @phase5_wait_count = 100
   else
     # Set wait count
     @phase5_wait_count = 20
   end
 end
end
8
Script Requests / SP damage display
February 05, 2014, 08:21:43 pm
I edited a HP draining script to drain SP. I'd like a way to differentiate between SP drain and normal, round-of-the-mill HP drain i.e different colored damage numbers or something like that.

This is the HP draining script
# HP Absorbption Skills 
# by RPG Advocate


# Sample code used for an 'absorb' common event:
#
#   absorb = $game_temp.damage_hook * -1
#   $scene.active_battler.damage = absorb
#   $scene.active_battler.damage_pop=true
#   $scene.active_battler.hp -= absorb


#==============================================================================
# ** Game_Temp
#------------------------------------------------------------------------------
#  This class handles temporary data that is not included with save data.
#  Refer to "$game_temp" for the instance of this class.
#==============================================================================

class Game_Temp
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :damage_hook              # damage hook
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  alias has_initialize initialize
  def initialize
    # Original call
    has_initialize
    # Initialize damage hook
    @damage_hook = 0
  end
end



#==============================================================================
# ** Game_Battler
#------------------------------------------------------------------------------
#  This class deals with battlers. It's used as a superclass for the Game_Actor
#  and Game_Enemy classes.
#==============================================================================

class Game_Battler
  #--------------------------------------------------------------------------
  # * Apply Skill Effects
  #     user  : the one using skills (battler)
  #     skill : skill
  #--------------------------------------------------------------------------
  alias has_skill_effect skill_effect
  def skill_effect(user, skill, dilute = 1)
    # Original call
    effective = has_skill_effect(user, skill)
    # Set hook to damage
    if self.damage.is_a?(Numeric)
      $game_temp.damage_hook += self.damage
    end
    # End Method
    return effective   
  end
end 
 

 
#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
#  This class performs battle screen processing.
#==============================================================================

class Scene_Battle
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader :active_battler
  #--------------------------------------------------------------------------
  # * Frame Update (main phase step 1 : action preparation)
  #--------------------------------------------------------------------------
  alias has_up4s1 update_phase4_step1
  def update_phase4_step1
    # Reset damage hook
    $game_temp.damage_hook = 0
    # Original call
    has_up4s1
  end
end


And this is the edited SP draining common event call:

absorb = $game_temp.damage_hook * -1
$scene.active_battler.damage = absorb
$scene.active_battler.damage_pop=true
$scene.active_battler.sp -= absorb
9
Blizzard's script keeps throwing an error when I have more than 10 entries in the Custom Beast Info Database. There's the script:

#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Bestiary by Blizzard
# Version: 2.3b
# Type: Enemy Catalogue Display
# Date: 5.7.2006
# Date v1.1: 18.9.2006
# Date v1.2b: 23.2.2007
# Date v1.3b: 7.7.2007
# Date v2.0b: 12.7.2007
# Date v2.1b: 6.8.2007
# Date v2.2b: 24.9.2007
# Date v2.21b: 8.4.2008
# Date v2.3b: 28.7.2009
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#  
#  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:
#
#   98% compatible with SDK v1.x. 70% compatible with SDK v2.x. May cause
#   incompatibility issues with exotic CBS-es. WILL corrupt your old savegames.
#
#
# Features:
#
#   - display of full data of enemies
#   - option to disable different information
#   - integrated support for my "Advanced Analyze System"
#   - press SHIFT/ENTER to change the appearance of the Bestiary window
#   - use LEFT/RIGHT/UP/DOWN to navigate through the information database
#
# new in v1.1b:
#   - bugs fixed
#
# new in v1.2b:
#   - improved coding (uses less RAM now and processes faster)
#
# new in v1.3b:
#   - increased compatibility
#
# new in v2.0b:
#   - completely overworked and fixed compatibility issues
#
# new in v2.1b:
#   - added custom info possibility
#
# new in v2.2b:
#   - rewritten conditions using classic syntax to avoid RGSS conditioning bug
#   - added SORT_BEASTS option
#   - improved coding
#
# new in v2.21b:
#   - improved coding
#
# new in v2.3b:
#   - improved coding
#
#
# Instructions:
#
# - Explanation:
#
#   This script will allow your characters to retrieve information about
#   enemies during battle and show them in a window. It also has built-in
#   compatibility for my "Advanced Analyze System" script and allows adding
#   enemies to it only if enemies were analyzed at least once. This script can
#   easily be used for Pokémon typed games.
#
# - Configuration:
#
#   Configure the part below and make one or more skills, that can analyze
#   enemies. Add the IDs into the array called ANALYZE_IDS and separate them
#   with commas. If you have one or more scripts using dummy elements (e.g. my
#   EQUAP Skills, SephirothSpawn's Limit Break, etc.) be sure to include every
#   dummy element ID in the array called ELM_DUMMIES, also separated by commas.
#   Below is everything explained, how to set the bestiary up. It has
#   additional options for rendering single or all enemies "Unknown" and adding
#   them into the bestiary as such. Later you can use a syntax described below
#   to enable their information display (e.g. like in Pokémon games, you get
#   the real info about a pokémon not when you meet it, but when you catch it).
#   You can use $game_system.bestiary_missing? to check how many enemies were
#   not added into the Bestiary. If you wish to see how many were added, use
#   $game_system.beasts.size
#
#
# Important notes:
#
#   You MUST configure the part below if you have scripts that use dummy
#   elements! Do NOT give your enemies MORE than 11 elements/status effects of
#   one resistance type (e.g. 12 or more elements, that are absorbed), because
#   they won't be displayed.
#
#
# If you find any bugs, please report them here:
# http://forum.chaos-project.com
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

ELM_DUMMIES = [] # include EVERY dummy element ID, that is used by other scripts
STA_DUMMIES = [] # include EVERY dummy status effect ID, that you use
EVASION = 'Eva' # word used to display Evasion
MAP_BACKGROUND = true # true will show the map background, false won't
BESTIARY_SIZE = 999 # change this if to as many
NEVER_ADD = [] # include IDs of enemies which will never be added
SORT_BEASTS = true # set to false if you don't want all enemies to be sorted by ID

# enemy IDs from enemies, that are unknown (e.g. bosses), to make an enemy
# known use $game_system.enable(ENEMY_ID) through the event command
# "Call Script" to enable the display of information

if $override_bestiary
 UNKNOWN = [4] # overrides the commands further below
else
 UNKNOWN = [] # DO NOT TOUCH THIS
end

# every enemy is initially unknown (e.g. for Pokémon games), so you don't have
# to fill the array above with all the IDs of your enemy database

ALL_UNKNOWN = false

# If a display below is disabled, the appropriate part above will be overriden.
# The values below can also be changed during gameplay by just calling the
# "Call script" event command and changing the values like below
# DO NOT SET EVERYTHING TO true! THIS WILL BUG YOUR BESTIARY!

# set to true to disable display of basic info
DISABLE_BEAST_BASIC = false
# set to true to disable display of basic stats
DISABLE_BEAST_STATS = false
# set to true to disable display of extended stats
DISABLE_BEAST_EXTSTATS = false
# set to true to disable display of extreme element weakness
DISABLE_BEAST_XTRWEAK = false
# set to true to disable display of element weakness
DISABLE_BEAST_WEAK = false
# set to true to disable display of element resistance
DISABLE_BEAST_RESIST = false
# set to true to disable display of element nullification
DISABLE_BEAST_NULLIFY = false
# set to true to disable display of element absorbtion
DISABLE_BEAST_ABSORB = false
# set to true to disable display of extreme status effect weakness
DISABLE_BEAST_XTRWEAK_S = false
# set to true to disable display of status effect weakness
DISABLE_BEAST_WEAK_S = false
# set to true to disable display of status effect resistance
DISABLE_BEAST_RESIST_S = false
# set to true to disable display of status effect nullification
DISABLE_BEAST_NULLIFY_S = false
# set to true to disable display of status effect absorbtion
DISABLE_BEAST_ABSORB_S = false
# set to false to enable custom display
DISABLE_BEAST_CUSTOM = false

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Configuration
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

if $DUMMY_ELEMENTS == nil
 $DUMMY_ELEMENTS = ELM_DUMMIES.clone
else
 $DUMMY_ELEMENTS |= ELM_DUMMIES
end
ELM_DUMMIES = nil
if $DUMMY_STATES == nil
 $DUMMY_STATES = STA_DUMMIES.clone
else
 $DUMMY_STATES |= STA_DUMMIES
end
STA_DUMMIES = nil

$bestiary_enabled = 2.3

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

class Game_System
 
 attr_accessor :window_mode
 attr_accessor :known
 
 def get_bestiary_info(id)
   return get_analyze_info(id) if $override_bestiary_info
   case id
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# START Custom Beast Info Database
#
# Use following template to add custom information about monsters:
#
#    when ID then return "STRING"
#
# ID is the enemy ID and STRING is a string with the information that should be
# displayed. Type all the information into one string, the script will slice
# the text by itself. Note that special characters like a " (double quote)
# need the use of the escape character \ (backslash). If you get and error
# with your string or the character doesn't appear right on the screen, try to
# use the escape character (i.e. for a " it would be \" instead of just ").
# The backslash itself needs an escape character (i.e. \\).
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
   when 1 then return "Until now I believed there is no such thing as a ghost. It's hard to not believe in something that is trying to kill you."
   when 2 then return "These creatures can be found in swamps and marshes. They are said to be able to have the ability to turn anything they glaze at into stone. If this rumor is true, these creatures can be considered as part of the family of \"Gorgons\"."
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# END Custom Beast Info Database
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
   end
   return 'Unknown'
 end

 alias init_beast_later initialize
 def initialize
   init_beast_later
   @window_mode, @beasts, @known = 0, [], []
 end
 
 def beasts
   return ($bestiary_override ? @analyzed : @beasts) - NEVER_ADD
 end
 
 def add_beast(beast)
   unless @beasts.include?(beast)
     @beasts.push(beast)
     @beasts.sort! if SORT_BEASTS
   end
 end
 
 def bestiary_missing?
   return (BESTIARY_SIZE - @beasts.size)
 end
 
 def enable(id)
   $game_system.known.push(id) unless $game_system.known.include?(id)
   return
 end
 
end

#==============================================================================
# RPG::Enemy
#==============================================================================

class RPG::Enemy
 
 def known
   return ($game_system.known.include?(self.id)) if ALL_UNKNOWN
   return (!UNKNOWN.include?(self.id))
 end
 
end

#==============================================================================
# Window_Base
#==============================================================================

class Window_Base
 
 def draw_bestiary_battler(enemy, w, h)
   bitmap = RPG::Cache.battler(enemy.battler_name, enemy.battler_hue)
   bitmap_w = bitmap.width / 2
   bitmap_h = bitmap.height / 2
   src_rect = Rect.new(0, 0, bitmap.width, bitmap.height)
   self.contents.blt(w/2 - bitmap_w, h/2 - bitmap_h, bitmap, src_rect, 192)
 end
 
end

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

class Bitmap
 
 def slice_text(text, width)
   words = text.split(' ')
   return words if words.size == 1
   result, current_text = [], words.shift
   words.each_index {|i|
       if self.text_size("#{current_text} #{words[i]}").width > width
         result.push(current_text)
         current_text = words[i]
       else
         current_text = "#{current_text} #{words[i]}"
       end
       result.push(current_text) if i >= words.size - 1}
   return result
 end
 
end

#==============================================================================
# Window_Beast
#==============================================================================

class Window_Beast < Window_Base

 attr_accessor :mode
 
 def initialize
   super(0, 0, 576, 416)
   @index_enemy = 0
   @index_page = 0
   @d = [DISABLE_BEAST_BASIC, DISABLE_BEAST_STATS, DISABLE_BEAST_EXTSTATS,
         DISABLE_BEAST_XTRWEAK, DISABLE_BEAST_WEAK, DISABLE_BEAST_RESIST,
         DISABLE_BEAST_NULLIFY, DISABLE_BEAST_ABSORB, DISABLE_BEAST_XTRWEAK_S,
         DISABLE_BEAST_WEAK_S, DISABLE_BEAST_RESIST_S, DISABLE_BEAST_NULLIFY_S,
         DISABLE_BEAST_ABSORB_S, DISABLE_BEAST_CUSTOM]
   @pages = 14 - ((0..13).find_all {|i| @d[i]}).size
   @mode = $game_system.window_mode
   @enemies = []
   for id in ($override_bestiary ? $game_system.analyzed : $game_system.beasts)
     @enemies.push($data_enemies[id]) if id != nil
   end
   self.contents = Bitmap.new(width - 32, height - 32)
   if $fontface != nil
     self.contents.font.name = $fontface
     self.contents.font.size = $fontsize
   elsif $defaultfonttype != nil
     self.contents.font.name = $defaultfonttype
     self.contents.font.size = $defaultfontsize
   end
   self.x = 320 - self.width / 2
   self.y = 240 - self.height / 2
   refresh
 end
 
 def update
   return if @enemies.size == 0
   if Input.trigger?(Input::RIGHT)
     $game_system.se_play($data_system.cursor_se)
     @index_enemy = (@index_enemy + 1) % @enemies.size
     refresh
   elsif Input.trigger?(Input::LEFT)
     $game_system.se_play($data_system.cursor_se)
     @index_enemy = (@index_enemy + @enemies.size - 1) % @enemies.size
     refresh
   elsif Input.trigger?(Input::DOWN)
     $game_system.se_play($data_system.cursor_se)
     @index_page = (@index_page + 1) % @pages
     refresh
   elsif Input.trigger?(Input::UP)
     $game_system.se_play($data_system.cursor_se)
     @index_page = (@index_page + @pages - 1) % @pages
     refresh
   end
 end
 
 def refresh
   self.contents.clear
   x = y = 0
   ox = x + 64
   enemy = @enemies[@index_enemy]
   if enemy == nil
     self.contents.draw_text(0, 64, 544, 32, 'Bestiary is empty', 1)
     return
   end
   self.contents.draw_text(0, 0, 544, 32, "#{enemy.id}.  #{enemy.name}", 1)
   draw_bestiary_battler(enemy, self.width, self.height)
   if enemy.known
     case @index_page
     when (0 - ((0..0).find_all {|i| @d[i]}).size)
       if enemy.item_id > 0
         drop = $data_items[enemy.item_id]
         t = "#{drop.name} (#{enemy.treasure_prob}% chance)"
       elsif enemy.weapon_id > 0
         drop = $data_weapons[enemy.weapon_id]
         t = "#{drop.name} (#{enemy.treasure_prob}% chance)"
       elsif enemy.armor_id > 0
         drop = $data_armors[enemy.armor_id]
         t = "#{drop.name} (#{enemy.treasure_prob}% chance)"
       end
       self.contents.draw_text(x, 32, 128, 32, $data_system.words.hp)
       self.contents.draw_text(x, 96, 128, 32, $data_system.words.sp)
       self.contents.draw_text(x, 160, 128, 32, 'EXP')
       self.contents.draw_text(x, 224, 128, 32, $data_system.words.gold)
       self.contents.draw_text(x, 288, 128, 32, 'Drops')
       self.contents.draw_text(ox, 64, 256, 32, enemy.maxhp.to_s)
       self.contents.draw_text(ox, 128, 256, 32, enemy.maxsp.to_s)
       self.contents.draw_text(ox, 192, 256, 32, enemy.exp.to_s)
       self.contents.draw_text(ox, 256, 256, 32, enemy.gold.to_s)
       self.contents.draw_text(ox, 320, 256, 32, (drop != nil ? t : 'nothing'))
     when (1 - ((0..1).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 128, 32, $data_system.words.str)
       self.contents.draw_text(x, 96, 128, 32, $data_system.words.dex)
       self.contents.draw_text(x, 160, 128, 32, $data_system.words.agi)
       self.contents.draw_text(x, 224, 128, 32, $data_system.words.int)
       self.contents.draw_text(ox, 64, 256, 32, enemy.str.to_s)
       self.contents.draw_text(ox, 128, 256, 32, enemy.dex.to_s)
       self.contents.draw_text(ox, 256, 256, 32, enemy.agi.to_s)
       self.contents.draw_text(ox, 192, 256, 32, enemy.int.to_s)
     when (2 - ((0..2).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 128, 32, $data_system.words.atk)
       self.contents.draw_text(x, 96, 128, 32, $data_system.words.pdef)
       self.contents.draw_text(x, 160, 128, 32, $data_system.words.mdef)
       self.contents.draw_text(x, 224, 128, 32, EVASION)
       self.contents.draw_text(ox, 64, 256, 32, enemy.atk.to_s)
       self.contents.draw_text(ox, 128, 256, 32, enemy.pdef.to_s)
       self.contents.draw_text(ox, 192, 256, 32, enemy.mdef.to_s)
       self.contents.draw_text(ox, 256, 256, 32, enemy.eva.to_s)
     when (3 - ((0..3).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Extremely efficient elements:')
       draw_elements(enemy, x, 1)
     when (4 - ((0..4).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Efficient elements:')
       draw_elements(enemy, x, 2)
     when (5 - ((0..5).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Elemental resistances:')
       draw_elements(enemy, x, 4)
     when (6 - ((0..6).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Elemental nullifications:')
       draw_elements(enemy, x, 5)
     when (7 - ((0..7).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Elemental absorbtions:')
       draw_elements(enemy, x, 6)
     when (8 - ((0..8).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Extremely efficient status effects:')
       draw_states(enemy, x, 1)
     when (9 - ((0..9).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Efficient status effects:')
       draw_states(enemy, x, 2)
     when (10 - ((0..10).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Status effect resistances:')
       draw_states(enemy, x, 4)
     when (11 - ((0..11).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Strong status effect resistances:')
       draw_states(enemy, x, 5)
     when (12 - ((0..12).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Status effect immunities:')
       draw_states(enemy, x, 6)
     when (13 - ((0..13).find_all {|i| @d[i]}).size)
       self.contents.draw_text(x, 32, 544, 32, 'Informations:')
       draw_info(enemy, x)
     end
   else
     self.contents.draw_text(0, 64, 544, 32, 'Unknown', 1)
   end
 end
 
 def draw_elements(enemy, x, index)
   elements = []
   (1...$data_system.elements.size).each {|id|
       if !$DUMMY_ELEMENTS.include?(id) &&
           index == $data_enemies[@enemies[@index_enemy].id].element_ranks[id]
         elements.push($data_system.elements[id])
       end}
   elements = ['Nothing'] if elements.size == 0
   elements.each_index {|i|
       self.contents.draw_text(x, 64 + i * 32, 544, 32, elements[i])}
 end
   
 def draw_states(enemy, x, index)
   states = []
   (1...$data_states.size).each {|id|
       if !$DUMMY_STATES.include?(id) &&
           index == $data_enemies[@enemies[@index_enemy].id].state_ranks[id]
         states.push($data_states[id].name)
       end}
   states = ['Nothing'] if states.size == 0
   states.each_index {|i|
       self.contents.draw_text(x, 64 + i * 32, 544, 32, states[i])}
 end
 
 def draw_info(enemy, x)
   text = self.contents.slice_text($game_system.get_bestiary_info(enemy.id), 528)
   text.each_index {|i|
       self.contents.draw_text(x, 64 + i*32, 544, 32, text[i])}
 end
   
end

#==============================================================================
# Scene_Bestiary
#==============================================================================

class Scene_Bestiary
 
 def main
   @spriteset = Spriteset_Map.new if MAP_BACKGROUND
   @beast_window = Window_Beast.new
   Graphics.transition
   loop do
     Graphics.update
     Input.update
     update
     break if $scene != self
   end
   Graphics.freeze
   @spriteset.dispose if MAP_BACKGROUND
   @beast_window.dispose
 end
 
 def update
   @beast_window.update
   if MAP_BACKGROUND && (Input.trigger?(Input::A) || Input.trigger?(Input::C))
     Graphics.freeze
     $game_system.se_play($data_system.cursor_se)
     case @beast_window.mode
     when 0 then @beast_window.back_opacity = 128
     when 1 then @beast_window.opacity = 0
     when 2 then @beast_window.opacity = @beast_window.back_opacity = 255
     end
     $game_system.window_mode = ($game_system.window_mode+1) % 3
     @beast_window.mode = $game_system.window_mode
     Graphics.transition(5)
   end
   if Input.trigger?(Input::B)
     $game_system.se_play($data_system.cancel_se)
     $scene = Scene_Map.new
   end
 end


end
 
#==============================================================================
# Scene_Battle
#==============================================================================

class Scene_Battle
 
 alias update_beast_later update
 def update
   if @log == nil && !$override_bestiary
     @log = true
     $game_troop.enemies.each {|enemy| $game_system.add_beast(enemy.id)}
   end
   update_beast_later
 end
 
end


Tgese are the other scripts I'm using:

(*) STCMS - Hybrid Edition
Game_System *
Other Classes *

Gold and Experience Percent Add On
Interpreter Fix
Large Party
HP Absorbption Skills
Custom Equipment Screen
Custom Window Skill
HP/SP bonus in armors
Face
FF-styled Item Scene
Large Party Scene Shop
Break HP Limit for Foes
Advanced Message Script
Absorb_Setup
System
Mods to Classes
Custom Prices

10
Greetings and salutations.

I'd like a standalone version of Blizzard's Multiple Hits script included in Tons of Add-ons. I'm asking for this due to Tons of Add-ons being incompatible with the other scripts in my game.

Those are the scripts I'm currently using:

- FMOD Ex Audio
- Stormtronic Custom Menu Screen
- Interpreter Fix
- Dargor's Large Party Script
- HP Absortion Skills
- Law's Custom Equipment Screen
- Law's Custom Skill Screen
- Weapon/Armor HP/SP Plus by Blizzard
- Jen's Final Fantasy-styled item window
- Large Party Scene Shop & Window Expansion by DerWulfman
- Absorb, Null, and Weak Armors by Bearcat.
11
I recently decided to use Dargor's large party script that allows more than 4 characters in the party. Sadly, I noticed that only the first four characters appear in the shop menu. Is there any way to fix this? I'm using the default shop script if you are wondering.

There's Dargo's script if needed:

#==============================================================================
# ** Large Party
#------------------------------------------------------------------------------
#  Author: Dargor
#  Version 1.3
#  02/08/2007
#==============================================================================

#==============================================================================
# ** Large Party Customization Module
#==============================================================================

module Dargor
 module Large_Party
   # Maximum number of actors allowed in the party
   Max_Size = 9
   # Battle status window refresh rate (used in phase5)
   Battle_Refresh_Rate = 32
 end
end

#==============================================================================
# ** Game_Temp
#------------------------------------------------------------------------------
#  This class handles temporary data that is not included with save data.
#  Refer to "$game_temp" for the instance of this class.
#==============================================================================

class Game_Temp
 #--------------------------------------------------------------------------
 # * Public Instance Variables
 #--------------------------------------------------------------------------
 attr_accessor :battle_actor_index  # @actor_index in battle scene
 #--------------------------------------------------------------------------
 # * Alias Listing
 #--------------------------------------------------------------------------
 alias large_party_temp_initialize initialize
 #--------------------------------------------------------------------------
 # * Object Initialization
 #--------------------------------------------------------------------------
 def initialize
   large_party_temp_initialize
   @battle_actor_index = 0
 end
end

#==============================================================================
# ** Game_Party
#------------------------------------------------------------------------------
#  This class handles the party. It includes information on amount of gold
#  and items. Refer to "$game_party" for the instance of this class.
#==============================================================================

class Game_Party
 #--------------------------------------------------------------------------
 # * Public Instance Variables
 #--------------------------------------------------------------------------
 attr_accessor :max_size   # Max number of actors allowed in the party
 #--------------------------------------------------------------------------
 # * Alias Listing
 #--------------------------------------------------------------------------
 alias large_party_initialize initialize
 alias large_party_add_actor add_actor
 #--------------------------------------------------------------------------
 # * Object Initialization
 #--------------------------------------------------------------------------
 def initialize
   large_party_initialize
   @max_size = Dargor::Large_Party::Max_Size
 end
 #--------------------------------------------------------------------------
 # * Add an Actor
 #     actor_id : actor ID
 #--------------------------------------------------------------------------
 def add_actor(actor_id)
   # Original method
   large_party_add_actor(actor_id)
   # Get actor
   actor = $game_actors[actor_id]
   # If the party has less than 4 members and this actor is not in the party
   if @actors.size < @max_size and not @actors.include?(actor)
     # Add actor
     @actors.push(actor)
     # Refresh player
     $game_player.refresh
   end
 end
end

#==============================================================================
# ** Sprite_Battler
#------------------------------------------------------------------------------
#  This sprite is used to display the battler.It observes the Game_Character
#  class and automatically changes sprite conditions.
#==============================================================================

class Sprite_Battler < RPG::Sprite
 #--------------------------------------------------------------------------
 # * Alias Listing
 #--------------------------------------------------------------------------
 alias large_party_sprite_update update
 #--------------------------------------------------------------------------
 # * Frame Update
 #--------------------------------------------------------------------------
 def update
   # Original method
   large_party_sprite_update
   # Set sprite coordinates
   if @battler.is_a?(Game_Actor)
     self.x = @battler.screen_x - ($game_temp.battle_actor_index / 4) * 640
   end
 end
end
#==============================================================================
# ** Spriteset_Battle
#------------------------------------------------------------------------------
#  This class brings together battle screen sprites. It's used within
#  the Scene_Battle class.
#==============================================================================

class Spriteset_Battle
 #--------------------------------------------------------------------------
 # * Alias Listing
 #--------------------------------------------------------------------------
 alias large_party_spriteset_update update
 #--------------------------------------------------------------------------
 # * Frame Update
 #--------------------------------------------------------------------------
 def update
   # Cycle through all extra actors (4+)
   # Create/update sprites
   for i in 4...$game_party.actors.size
     if @actor_sprites[i].nil?
       @actor_sprites.push(Sprite_Battler.new(@viewport2))
     end
     @actor_sprites[i].battler = $game_party.actors[i]
   end
   # Original method
   large_party_spriteset_update
 end
end

#==============================================================================
# ** Window_MenuStatus
#------------------------------------------------------------------------------
#  This window displays party member status on the menu screen.
#==============================================================================

class Window_MenuStatus < Window_Selectable
 #--------------------------------------------------------------------------
 # * Alias Listing
 #--------------------------------------------------------------------------
 alias large_party_menu_status_initialize initialize
 alias large_party_menu_status_refresh refresh
 alias large_party_menu_status_update_cursor_rect update_cursor_rect
 #--------------------------------------------------------------------------
 # * Object Initialization
 #--------------------------------------------------------------------------
 def initialize
   # Original method
   large_party_menu_status_initialize
   # Adjust contents height
   @item_max = $game_party.actors.size
   height = @item_max * 120
   self.contents = Bitmap.new(width - 32, height - 32)
   # Refresh
   refresh
 end
 #--------------------------------------------------------------------------
 # * Refresh
 #--------------------------------------------------------------------------
 def refresh(*args)
   # Original method
   large_party_menu_status_refresh(*args)
   # Adjust default height
   self.height = 480
 end
 #--------------------------------------------------------------------------
 # * Cursor Rectangle Update
 #--------------------------------------------------------------------------
 def update_cursor_rect
   large_party_menu_status_update_cursor_rect
   row = @index / @column_max
   if row < self.top_row
     self.top_row = row
   end
   if row > self.top_row + (self.page_row_max - 1)
     self.top_row = row - (self.page_row_max - 1)
   end
   cursor_width = self.width / @column_max - 32
   x = @index % @column_max * (cursor_width + 32)
   y = @index / @column_max * 116 - self.oy
   self.cursor_rect.set(x, y, cursor_width, 96)
 end
 #--------------------------------------------------------------------------
 # * Top Row
 #--------------------------------------------------------------------------
 def top_row
   return self.oy / 116
 end
 #--------------------------------------------------------------------------
 # * Set Top Row
 #     row : new row
 #--------------------------------------------------------------------------
 def top_row=(row)
   if row < 0
     row = 0
   end
   if row > row_max - 1
     row = row_max - 1
   end
   self.oy = row * 116
 end
 #--------------------------------------------------------------------------
 # * Page Row Max
 #--------------------------------------------------------------------------
 def page_row_max
   return 4
 end
end

#==============================================================================
# ** Window_BattleStatus
#------------------------------------------------------------------------------
#  This window displays the status of all party members on the battle screen.
#==============================================================================

class Window_BattleStatus < Window_Base
 #--------------------------------------------------------------------------
 # * Alias Listing
 #--------------------------------------------------------------------------
 alias large_party_battle_status_initialize initialize
 alias large_party_battle_status_refresh refresh
 alias large_party_battle_status_update update
 #--------------------------------------------------------------------------
 # * Object Initialization
 #--------------------------------------------------------------------------
 def initialize
   @column_max = 4
   large_party_battle_status_initialize
   width = $game_party.actors.size * 160
   self.contents = Bitmap.new(width - 32, height - 32)
   self.width = 640
   @level_up_flags = []
   for i in 0...$game_party.actors.size
     @level_up_flags << false
   end
   @item_max = $game_party.actors.size
   refresh
 end
 #--------------------------------------------------------------------------
 # * Refresh
 #--------------------------------------------------------------------------
 def refresh
   # Refresh contents when actors are added/removed in-battle
   if $game_party.actors.size != @item_max
     @item_max = $game_party.actors.size
     width = @item_max * 160
     self.contents = Bitmap.new(width - 32, height - 32)
     self.width = 640
   end
   large_party_battle_status_refresh
   column = $game_temp.battle_actor_index / 4
   self.ox = column * 640
 end
end
#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
#  This class performs battle screen processing.
#==============================================================================

class Scene_Battle
 #--------------------------------------------------------------------------
 # * Alias Listing
 #--------------------------------------------------------------------------
 alias large_party_phase3_setup_command_window phase3_setup_command_window
 alias large_party_update_phase4_step2 update_phase4_step2
 alias large_party_start_phase5 start_phase5
 alias large_party_update_phase5 update_phase5
 #--------------------------------------------------------------------------
 # * Actor Command Window Setup
 #--------------------------------------------------------------------------
 def phase3_setup_command_window
   $game_temp.battle_actor_index = @actor_index
   @status_window.refresh
   large_party_phase3_setup_command_window
   @actor_command_window.x = (@actor_index%4) * 160
 end
 #--------------------------------------------------------------------------
 # * Frame Update (main phase step 2 : start action)
 #--------------------------------------------------------------------------
 def update_phase4_step2
   if @active_battler.is_a?(Game_Actor)
     $game_temp.battle_actor_index = @active_battler.index
     @status_window.refresh
   end
   large_party_update_phase4_step2
 end
 #--------------------------------------------------------------------------
 # * Frame Update (main phase step 4 : animation for target)
 #--------------------------------------------------------------------------
 def update_phase4_step4
   if @target_battlers[0] != nil
     $game_temp.battle_actor_index = @target_battlers[0].index
     @status_window.refresh
   end
   # Animation for target
   for target in @target_battlers
     target.animation_id = @animation2_id
     target.animation_hit = (target.damage != "Miss")
   end
   # Animation has at least 8 frames, regardless of its length
   @wait_count = 8
   # Shift to step 5
   @phase4_step = 5
 end
 #--------------------------------------------------------------------------
 # * Start After Battle Phase
 #--------------------------------------------------------------------------
 def start_phase5
   @actor_index = 0
   @status_wait = Graphics.frame_count
   large_party_start_phase5
 end
 #--------------------------------------------------------------------------
 # * Frame Update (after battle phase)
 #--------------------------------------------------------------------------
 def update_phase5
   refresh_rate = Dargor::Large_Party::Battle_Refresh_Rate
   if Graphics.frame_count >= @status_wait + refresh_rate
     $game_temp.battle_actor_index = @actor_index
     @status_window.refresh
     @status_wait = Graphics.frame_count
     max = ($game_party.actors.size.to_f/4).ceil * 4
     @actor_index = (@actor_index+1) % max
   end
   large_party_update_phase5
 end
end
12
Welcome! / Greeting and Salutations
August 13, 2013, 01:30:47 pm
Hello here. While not engaging in a shooting with some rowdy bounty hunters or wishing to be buried with my money, I work on a RMXP project that's actually a remake of an old RPGM 2000 project sadly lost when my old computer went belly up.

I hope we can make the most of it.  :D
13
EDIT: How embarrassing. Let me try this again:

I'm trying to use both Blizzard's Stormtronics CMS and Hiretsukan's FMOD script but the following erros occurs when finishing a battle:

Script 'Other Classes*' line 60 Argument Error ocurred

wrong number of arguments (2 for 1)


This is the FmoDEX script:

#==============================================================================
# ** FMOD Ex Audio
#------------------------------------------------------------------------------
#  Script by            :   Hiretsukan (Kevin Gadd)
#                           janus@luminance.org
#  Modified by:         :   RPG/Cowlol (Firas Assad)
#                           ArePeeGee (AIM name)
#  Last Update          :   September 23rd, 2008
#  Version              :   1.5
#------------------------------------------------------------------------------
# A rewrite of the built-in Audio module to extend its functionality
# using the FMOD Ex library (http://www.fmod.org/). In particular,
# it supports several new formats and has the ability to get current
# playing position and seek to a new one, and to set loop points.
# Extensions to Game_System and Scene_Battle makes the memorize BGM/BGS
# event command remember position as well, and map music to resume
# playing from the position it stopped at before a battle, instead
# of starting all over like default RMXP behavior.
#------------------------------------------------------------------------------
# Usage:
#
# You need to copy the file fmodex.dll to your game folder (folder where
# your Game.exe and project file are). I've provided the DLL with the
# demo, and you can also get the latest version from FMOD's official
# website (http://www.fmod.org/index.php/download).
#
# There are three scripts that could be used, the real script is only
# the first one, but the other scripts are provided for convenience:
#
# FModEx
#           This includes the core functionality and the Audio module
#           rewrite. It's the main script and should be placed on
#           top of all scripts using it. Most people would just add a
#           new section above the Game_System or Game_Temp section at
#           the very top of the script editor and paste script there.
# Game_System
#           This script rewrites parts of the Game_System class to
#           allow memorize_bgm to support remembering position,
#           and to allow the play methods to take an extra parameter
#           specifying position to start playing from.
#           Add it anywhere under the Game_System script section.
#           If you don't need any of these features you don't need this
#           script.
# Other Classes
#           This is really an optional script that modifies the default
#           battle system to memorize map BGM and position instead of
#           starting over after the battle. Add it anywhere under
#           the Scene_Battle classes.
#
# Aside from integration with RMXP's default scripts, you can use
# this script the same way you used the old Audio class You could also
# access the FMod module for more options at a lower level, such as
# setting loop points (FMod.bgm_set_loop_points(first, second) in
# milliseconds) and getting current BGS position (FMod.bgs_position) to
# name a few.
#------------------------------------------------------------------------------
# Compatibility:
#
# This script has different levels of compatibility depending on what
# scripts you use:
#
# FModEx
#           This script overwrites the Audio module, but since
#           few if any other scripts would do that, it's pretty
#           much compatible with the majority of other scripts
#           without modifications.
# Game_System
#           The following methods of Game_System are redefined:
#             bgm_play, bgm_restore, bgs_play, bgs_restore
#           Any other script that redefines these methods may
#           not work well with this one. Most scripts wouldn't
#           do that, except ones dealing with audio as well.
#           I've marked the areas in the script where I made
#           changes to help you resolve any conflicts
#           The following methods of Game_System are aliased:
#             bgm_memorize, bgs_memorize
#           Other scripts that redefine these methods should
#           be placed above the Game_System script.
# Other Classes
#           The following methods of Scene_Battle are redefined:
#             judge, start_phase5, update_phase5
#           Any other script that redefines these methods may
#           not work well with this one. Custom battle system
#           scripts may do that, so you might consider not
#           including the Other Classes section and just
#           manually add position memorizing functionality.
#           I've marked the areas in the script where I made
#           changes to help you resolve any conflicts
#           The following methods of Game_Temp/Scene_Map are aliased:
#             Game_Temp#initialize, Scene_Map #call_battle
#           Other scripts that redefine these methods should
#           be placed above the Other Classes script.
#
# So in other words, FModEx is the most compatible, followed by
# Game_System, and finally the last and optional Other Classes.
# If you use a custom battle system you probably shouldn't include
# Other Classes anyway. This isn't an SDK script and I never tested
# it with the SDK. It'll probably work, but refer to SDK documentation
# for more information.
#------------------------------------------------------------------------------
# Version Info:
#   - Version 1.5:
#       - Made the Volume and Pitch paramters to Audio ME/SE playing
#         methods optional. (Thanks panchokoster!)
#       - Script now uses FMOD's software mixer instead of hardware
#         acceleration. This solves issues with certain sound cards.
#       - A message is now displayed when a file isn't found, instead
#         of just throwing the error number.
#       - Added an independent thread to handle updating Audio module,
#         instead of calling it in $game_system#update. This should
#         ensure that it's called in all scenes. (Thanks Zeriab!)
#       - Updated fading calculations to depend on seconds instead
#         of game frames.
#   - Version 1.4:
#       - Fixed a bug where file isn't found if RTP path doesn't end
#         with a backslash (thanks Atoa!).
#       - Added BGM fading in after a ME is done playing to mimic
#         original Audio class behavior, the volume increment when
#         fading is specified by constant Audio::BGM_FADE_IN_INCREMENT.
#       - Several minor bug fixes and minor behavior changes relating
#         to fading out and stopping sounds.
#   - Version 1.3:
#       - Fixed a bug with ME fading out.
#       - Added methods to get BGM and BGS length.
#       - Providing -1 as loop end point to set_loop_points methods
#         makes the sound file's end the loop end point.
#       - Changed implementation of set_loop_points a bit.
#       - Position of BGM/BGS to be played after fading is now
#         remembered instead of starting all over.
#   - Version 1.2:
#       - Fully documented the script, and fixed some bugs.
#       - Completely rewrote Audio module, allowing FMOD to handle
#         BGMs, BGSs, MEs, and SEs except of just BGMs.
#       - Fixed RTP reading to use registry instead of special files..
#   - Version 1.1:
#       - Added position tracking and adjusting.
#       - Added loop point support.
#       - Implemented BGM fading.
#   - Version 1.0:
#       - Hiretsukan (Kevin Gadd)'s initial release.
#------------------------------------------------------------------------------
# Known bugs:
#
#   - MIDI abrupt start when seeking or restoring from position
#   - Found a bug or have some ideas for the next version? Please tell me!
#------------------------------------------------------------------------------
# Terms of Use:
#
#   Use of this script is subject to the permissive BSD-like license below.
#   That basically means you could use it in any way you like as long
#   as you keep the following copyright and license unchanged and available,
#   and don't use name of copyright holder to promote products based on
#   this software. Note, however, that this license only applies to the
#   script, and not to the FMOD library. For more information about FMOD
#   licenses consult FMOD website: http://www.fmod.org/index.php/sales
#   It's free for non-commercial use, and they provide several types
#   of licenses for different types of developers.
#
# Copyright (c) 2005, Kevin Gadd
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * The name of the contributors may not be used to endorse or promote
#       products derived from this software without specific prior written
#       permission.
#
# THIS SOFTWARE IS PROVIDED BY Kevin Gadd ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Kevin Gadd BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#==============================================================================

#==============================================================================
# ** FModEx
#------------------------------------------------------------------------------
#  FMOD Ex binding by Kevin Gadd (janus@luminance.org)
#==============================================================================

module FModEx
 #--------------------------------------------------------------------------
 # * Constants
 #--------------------------------------------------------------------------
 # FMOD_INITFLAGS flags
 FMOD_INIT_NORMAL = 0
 # FMOD_RESULT flags
 FMOD_OK = 0
 FMOD_ERR_CHANNEL_STOLEN = 11
 FMOD_ERR_FILE_NOT_FOUND = 23
 FMOD_ERR_INVALID_HANDLE = 36
 # FMOD_MODE flags
 FMOD_DEFAULT = 0
 FMOD_LOOP_OFF = 1
 FMOD_LOOP_NORMAL = 2
 FMOD_LOOP_BIDI = 4
 FMOD_LOOP_BITMASK = 7
 FMOD_2D = 8
 FMOD_3D = 16
 FMOD_HARDWARE = 32
 FMOD_SOFTWARE = 64
 FMOD_CREATESTREAM = 128
 FMOD_CREATESAMPLE = 256
 FMOD_OPENUSER = 512
 FMOD_OPENMEMORY = 1024
 FMOD_OPENRAW = 2048
 FMOD_OPENONLY = 4096
 FMOD_ACCURATETIME = 8192
 FMOD_MPEGSEARCH = 16384
 FMOD_NONBLOCKING = 32768
 FMOD_UNIQUE = 65536
 # The default mode that the script uses
 FMOD_DEFAULT_SOFTWARWE = FMOD_LOOP_OFF | FMOD_2D | FMOD_SOFTWARE
 # FMOD_CHANNELINDEX flags
 FMOD_CHANNEL_FREE = -1
 FMOD_CHANNEL_REUSE = -2
 # FMOD_TIMEUNIT_flags
 FMOD_TIMEUNIT_MS = 1
 FMOD_TIMEUNIT_PCM = 2
 # The default time unit the script uses
 FMOD_DEFAULT_UNIT = FMOD_TIMEUNIT_MS
 # Types supported by FMOD Ex
 FMOD_FILE_TYPES = ['ogg', 'aac', 'wma', 'mp3', 'wav', 'it', 'xm', 'mod', 's3m', 'mid', 'midi']
 
 #============================================================================
 # ** DLL
 #----------------------------------------------------------------------------
 #  A class that manages importing functions from the DLL
 #============================================================================
 
 class DLL
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #--------------------------------------------------------------------------
   attr_accessor :filename           # DLL file name for instance    
   attr_accessor :functions          # hash of functions imported (by name)
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     filename  : Name of the DLL
   #--------------------------------------------------------------------------
   def initialize(filename = 'fmodex.dll')
     @filename = filename
     @functions = {}
     @handle = 0            # Handle to the DLL
     # Load specified library into the address space of game process
     w32_LL = Win32API.new('kernel32.dll', 'LoadLibrary', 'p', 'l')
     @handle = w32_LL.call(filename)
     # System functions:
     self.import('System_Create', 'p')
     self.import('System_Init', 'llll')
     self.import('System_Close', 'l')
     self.import('System_Release', 'l')
     self.import('System_CreateSound', 'lpllp')
     self.import('System_CreateStream', 'lpllp')
     self.import('System_PlaySound', 'llllp')
     # Sound functions:
     self.import('Sound_Release', 'l')
     self.import('Sound_GetMode', 'lp')
     self.import('Sound_SetMode', 'll')
     self.import('Sound_SetLoopPoints', 'lllll')
     self.import('Sound_GetLength', 'lpl')
     # Channel functions:
     self.import('Channel_Stop', 'l')
     self.import('Channel_IsPlaying', 'lp')
     self.import('Channel_GetPaused', 'lp')
     self.import('Channel_SetPaused', 'll')
     self.import('Channel_GetVolume', 'lp')
     self.import('Channel_SetVolume', 'll')
     self.import('Channel_GetPan', 'lp')
     self.import('Channel_SetPan', 'll')
     self.import('Channel_GetFrequency', 'lp')
     self.import('Channel_SetFrequency', 'll')
     self.import('Channel_GetPosition', 'lpl')
     self.import('Channel_SetPosition', 'lll')
   end
   #--------------------------------------------------------------------------
   # * Create a Win32API Object And Add it to Hashtable
   #     name      : Function name
   #     args      : Argument types (p = pointer, l = int, v = void)
   #     returnType: Type of value returned by function
   #--------------------------------------------------------------------------
   def import(name, args = '', returnType = 'l')
     @functions[name] = Win32API.new(@filename, 'FMOD_' + name, args, returnType)
   end
   #--------------------------------------------------------------------------
   # * Get Function by Name
   #     key       : Function name
   #--------------------------------------------------------------------------
   def [](key)
     return @functions[key]
   end
   #--------------------------------------------------------------------------
   # * Call a Function With Passed Arguments
   #     name      : Function name
   #     args      : Argument to function
   #--------------------------------------------------------------------------
   def invoke(name, *args)
     fn = @functions[name]
     raise "function not imported: #{name}" if fn.nil?
     result = fn.call(*args)
     unless result == FMOD_OK or result == FMOD_ERR_CHANNEL_STOLEN or
       result == FMOD_ERR_FILE_NOT_FOUND
       raise "FMOD Ex returned error #{result}"
     end
     return result
   end
   #--------------------------------------------------------------------------
   # * Store Float as Binary Int Because Floats Can't be Passed Directly
   #     f         : Float to convert
   #--------------------------------------------------------------------------
   def convertFloat(f)
     # First pack the float in a string as a native binary float
     temp = [f].pack('f')
     # Then unpack the native binary float as an integer
     return unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Unpack Binary Data to Integer
   #     s         : String containing binary data
   #--------------------------------------------------------------------------
   def unpackInt(s)
     return s.unpack('l')[0]
   end
   #--------------------------------------------------------------------------
   # * Unpack Binary Data to Float
   #     s         : String containing binary data
   #--------------------------------------------------------------------------
   def unpackFloat(s)
     return s.unpack('f')[0]
   end
   #--------------------------------------------------------------------------
   # * Unpack Binary Data to Boolean
   #     s         : String containing binary data
   #--------------------------------------------------------------------------
   def unpackBool(s)
     return s.unpack('l')[0] != 0
   end
 end

 #============================================================================
 # ** System
 #----------------------------------------------------------------------------
 #  A class that manages an instance of FMOD::System
 #============================================================================
 
 class System
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #--------------------------------------------------------------------------
   attr_accessor :fmod               # Instance of DLL class (fmodex.dll)
   attr_accessor :handle             # Handle (pointer) to System object
   attr_accessor :maxChannels        # Maximum number of channels
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     fmod            : An instance of DLL class
   #     maxChannels     : Maximum number of used channels
   #     flags           : FMOD_INITFLAGS
   #     extraDriverData : Driver specific data
   #--------------------------------------------------------------------------
   def initialize(theDLL, maxChannels = 32, flags = FMOD_INIT_NORMAL, extraDriverData = 0)
     @fmod = theDLL
     @maxChannels = maxChannels
     # Create and initialize FMOD::System
     temp = 0.chr * 4
     @fmod.invoke('System_Create', temp)
     @handle = @fmod.unpackInt(temp)
     @fmod.invoke('System_Init', @handle, maxChannels, flags, extraDriverData)
   end
   #--------------------------------------------------------------------------
   # * Create FMOD::Sound (fully loaded into memory by default)
   #     filename        : Name of file to open
   #     mode            : FMOD_MODE flags
   #--------------------------------------------------------------------------
   def createSound(filename, mode = FMOD_DEFAULT_SOFTWARWE)
     # Create sound and return it
     temp = 0.chr * 4
     result = @fmod.invoke('System_CreateSound', @handle, filename, mode, 0, temp)
     raise "File not found: \"#{filename}\"" if result == FMOD_ERR_FILE_NOT_FOUND
     newSound = Sound.new(self, @fmod.unpackInt(temp))
     return newSound
   end
   #--------------------------------------------------------------------------
   # * Create Streamed FMOD::Sound (chunks loaded on demand)
   #     filename        : Name of file to open
   #     mode            : FMOD_MODE flags
   #--------------------------------------------------------------------------
   def createStream(filename, mode = FMOD_DEFAULT_SOFTWARWE)
     # Create sound and return it
     temp = 0.chr * 4
     result = @fmod.invoke('System_CreateStream', @handle, filename, mode, 0, temp)
     raise "File not found: \"#{filename}\"" if result == FMOD_ERR_FILE_NOT_FOUND
     newSound = Sound.new(self, @fmod.unpackInt(temp))
     return newSound
   end
   #--------------------------------------------------------------------------
   # * Close And Release System
   #--------------------------------------------------------------------------
   def dispose
     if (@handle > 0)
       @fmod.invoke('System_Close', @handle)
       @fmod.invoke('System_Release', @handle)
       @handle = 0
     end
     @fmod = nil
   end
 end

 #============================================================================
 # ** Sound
 #----------------------------------------------------------------------------
 #  A class that manages an instance of FMOD::Sound
 #============================================================================
 
 class Sound
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #--------------------------------------------------------------------------
   attr_accessor :system             # System that created this Sound
   attr_accessor :fmod               # Instance of DLL class (fmodex.dll)
   attr_accessor :handle             # Handle (pointer) to Sound object
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     theSystem       : The System that created this Sound object
   #     handle          : Handle to the FMOD::Sound object
   #--------------------------------------------------------------------------
   def initialize(theSystem, theHandle)
     @system = theSystem
     @fmod = theSystem.fmod
     @handle = theHandle
   end
   #--------------------------------------------------------------------------
   # * Play Sound
   #     paused          : Start paused?
   #     channel         : Channel allocated to sound (nil for automatic)
   #--------------------------------------------------------------------------
   def play(paused = false, channel = nil)
     # If channel wasn't specified, let FMOD pick a free one,
     # otherwise use the passed channel (id from 0 to maxChannels)
     unless channel
       temp = 0.chr * 4
     else
       temp = [channel].pack('l')
     end
     @fmod.invoke('System_PlaySound', @system.handle,
               (channel == nil) ? FMOD_CHANNEL_FREE : FMOD_CHANNEL_REUSE,
               @handle,
               (paused == true) ? 1 : 0,
               temp)
     theChannel = @fmod.unpackInt(temp)
     # Create a Channel object based on returned channel
     newChannel = Channel.new(self, theChannel)
     return newChannel
   end
   #--------------------------------------------------------------------------
   # * Get FMOD_MODE Bits
   #--------------------------------------------------------------------------
   def mode
     temp = 0.chr * 4
     @fmod.invoke('Sound_GetMode', @handle, temp)
     return @fmod.unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Set FMOD_MODE Bits
   #--------------------------------------------------------------------------
   def mode=(newMode)
     @fmod.invoke('Sound_SetMode', @handle, newMode)
   end
   #--------------------------------------------------------------------------
   # * Get FMOD_LOOP_MODE
   #--------------------------------------------------------------------------  
   def loopMode
     temp = 0.chr * 4
     @fmod.invoke('Sound_GetMode', @handle, temp)
     return @fmod.unpackInt(temp) & FMOD_LOOP_BITMASK
   end
   #--------------------------------------------------------------------------
   # * Set FMOD_LOOP_MODE
   #--------------------------------------------------------------------------  
   def loopMode=(newMode)
     @fmod.invoke('Sound_SetMode', @handle, (self.mode & ~FMOD_LOOP_BITMASK) | newMode)
   end
   #--------------------------------------------------------------------------
   # * Return Sound Length
   #--------------------------------------------------------------------------
   def length(unit = FMOD_DEFAULT_UNIT)
     temp = 0.chr * 4
     @fmod.invoke('Sound_GetLength', @handle, temp, unit)
     return @fmod.unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Loop Points
   #     first           : Loop start point in milliseconds
   #     second          : Loop end point in milliseconds
   #     unit            : FMOD_TIMEUNIT for points
   #--------------------------------------------------------------------------    
   def setLoopPoints(first, second, unit = FMOD_DEFAULT_UNIT)
     @fmod.invoke('Sound_SetLoopPoints', @handle, first, unit, second, unit)
   end
   #--------------------------------------------------------------------------
   # * Release Sound
   #--------------------------------------------------------------------------
   def dispose
     if (@handle > 0)
       @fmod.invoke('Sound_Release', @handle)
       @handle = 0
     end
     @fmod = nil
     @system = nil
   end
 end

 #============================================================================
 # ** Channel
 #----------------------------------------------------------------------------
 #  A class that represents an FMOD::Channel
 #============================================================================
 
 class Channel
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #--------------------------------------------------------------------------
   attr_accessor :system             # System that created the Sound
   attr_accessor :sound              # Sound using the Channel
   attr_accessor :fmod               # Instance of DLL class (fmodex.dll)
   attr_accessor :handle             # Handle (pointer) to Sound object
   #--------------------------------------------------------------------------
   # * Object Initialization
   #     theSound        : The Sound using this Channel object
   #     handle          : Handle to the FMOD::Channel object
   #--------------------------------------------------------------------------
   def initialize(theSound, theHandle)
     @sound = theSound
     @system = theSound.system
     @fmod = theSound.system.fmod
     @handle = theHandle
   end
   #--------------------------------------------------------------------------
   # * Stop Channel and Make it Available for Other Sounds
   #--------------------------------------------------------------------------
   def stop
     @fmod.invoke('Channel_Stop', @handle)
   end
   #--------------------------------------------------------------------------
   # * Is the Channel Handle Valid?
   #--------------------------------------------------------------------------
   def valid?
     temp = 0.chr * 4
     begin
       result = @fmod.invoke('Channel_IsPlaying', @handle, temp)
     rescue
       if (result == FMOD_ERR_INVALID_HANDLE)
         return false
       else
         raise
       end
     end
     # If we get here then it's valid
     return true
   end
   #--------------------------------------------------------------------------
   # * Is the Channel Playing?
   #--------------------------------------------------------------------------
   def playing?
     temp = 0.chr * 4
     @fmod.invoke('Channel_IsPlaying', @handle, temp)
     return @fmod.unpackBool(temp)
   end
   #--------------------------------------------------------------------------
   # * Get Channel Volume Level (0.0 -> 1.0)
   #--------------------------------------------------------------------------
   def volume
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetVolume', @handle, temp)
     return @fmod.unpackFloat(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Channel Volume Level (0.0 -> 1.0)
   #--------------------------------------------------------------------------
   def volume=(newVolume)
     @fmod.invoke('Channel_SetVolume', @handle, @fmod.convertFloat(newVolume))
   end
   #--------------------------------------------------------------------------
   # * Get Channel Pan Position (-1.0 -> 1.0)
   #--------------------------------------------------------------------------
   def pan
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetPan', @handle, temp)
     return @fmod.unpackFloat(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Channel Pan Position (-1.0 -> 1.0)
   #--------------------------------------------------------------------------
   def pan=(newPan)
     @fmod.invoke('Channel_SetPan', @handle, @fmod.convertFloat(newPan))
   end
   #--------------------------------------------------------------------------
   # * Get Channel Frequency in HZ (Speed/Pitch)
   #--------------------------------------------------------------------------
   def frequency
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetFrequency', @handle, temp)
     return @fmod.unpackFloat(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Channel Frequency in HZ (Speed/Pitch)
   #--------------------------------------------------------------------------
   def frequency=(newFrequency)
     @fmod.invoke('Channel_SetFrequency', @handle, @fmod.convertFloat(newFrequency))
   end
   #--------------------------------------------------------------------------
   # * Is Channel Paused?
   #--------------------------------------------------------------------------
   def paused
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetPaused', @handle, temp)
     return @fmod.unpackBool(temp)
   end
   #--------------------------------------------------------------------------
   # * Pause Channel
   #--------------------------------------------------------------------------
   def paused=(newPaused)
     @fmod.invoke('Channel_SetPaused', @handle, (newPaused == true) ? 1 : 0)
   end
   #--------------------------------------------------------------------------
   # * Get Current Playback Position
   #     unit            : FMOD_TIMEUNIT to return position in
   #--------------------------------------------------------------------------  
   def position(unit = FMOD_DEFAULT_UNIT)
     temp = 0.chr * 4
     @fmod.invoke('Channel_GetPosition', @handle, temp, unit)
     return @fmod.unpackInt(temp)
   end
   #--------------------------------------------------------------------------
   # * Set Current Playback Position
   #     newPosition     : New playback position
   #     unit            : FMOD_TIMEUNIT to use when setting position
   #--------------------------------------------------------------------------    
   def position=(newPosition, unit = FMOD_DEFAULT_UNIT)
     @fmod.invoke('Channel_SetPosition', @handle, newPosition, unit)
   end
   #--------------------------------------------------------------------------
   # * Dispose of Channel
   #--------------------------------------------------------------------------  
   def dispose
     @handle = 0
     @sound = nil
     @system = nil
     @fmod = nil
   end
 end
 
end

#==============================================================================
# ** FMod
#------------------------------------------------------------------------------
#  A higher level module to access FMOD Ex
#==============================================================================

module FMod
 
 #============================================================================
 # ** SoundFile
 #----------------------------------------------------------------------------
 #  Represents a Sound file (BGM, BGS, SE, etc.) and associated Channel
 #============================================================================
 
 class SoundFile
   #--------------------------------------------------------------------------
   # * Public Instance Variables
   #--------------------------------------------------------------------------
   attr_accessor :name                     # File name
   attr_accessor :sound                    # FModEx::Sound object
   attr_accessor :channel                  # Channel playing sound
   attr_accessor :volume                   # Volume in RPG::AudioFile format
   attr_accessor :pitch                    # Pitch in RPG::AudioFile format
   attr_accessor :looping                  # Sound loops
   attr_accessor :streaming                # Sound is streamed
   attr_accessor :length                   # Sound length in milliseconds
   #--------------------------------------------------------------------------
   # * Object Initialization
   #--------------------------------------------------------------------------
   def initialize(name, sound, channel, volume, pitch, looping, streaming, length)
     @name = name
     @sound = sound
     @channel = channel
     @volume = volume
     @pitch = pitch
     @looping = looping
     @streaming = streaming
     @length = length
   end
 end
 #--------------------------------------------------------------------------
 # * Instance Variables
 #--------------------------------------------------------------------------
 @fmod_dll = FModEx::DLL.new               # The FMOD Ex DLL
 @fmod = FModEx::System.new(@fmod_dll)     # The global System object
 @fmod_se = []                             # Array of Sound Effects
 @rtp_folder = nil                         # Name of RTP folder
 #--------------------------------------------------------------------------
 # * Get Path of RTP Folder From Registry
 #--------------------------------------------------------------------------
 def self.getRTPFolder
   if @rtp_folder
     return @rtp_folder
   end
   open_key = Win32API.new('advapi32.dll', 'RegOpenKeyExA', 'LPLLP', 'L')
   query_value = Win32API.new('advapi32.dll', 'RegQueryValueExA', 'LPLPPP', 'L')
   close_key = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
   key = 0.chr * 4
   # Open a HKEY_LOCAL_MACHINE with KEY_READ attribute and save handle in key
   open_key.call(0x80000002, 'Software\Enterbrain\RGSS\RTP', 0, 0x20019, key)
   key = @fmod_dll.unpackInt(key)
   type = 0.chr * 4
   size = 0.chr * 4
   # Query to get string size
   query_value.call(key, 'Standard', 0, type, 0, size)
   data = ' ' * @fmod_dll.unpackInt(size)
   # Query the string value itself using size
   query_value.call(key, 'Standard', 0, type, data, size)
   @rtp_folder = data.chop
   close_key.call(key)
   # Make sure the directory ends with a backslash
   @rtp_folder += "\\" if @rtp_folder[-1].chr != "\\"
   return @rtp_folder
 end
 #--------------------------------------------------------------------------
 # * Return Proper File Name (With Extensions)
 #     name            : Name of the file
 #     extensions      : Extensions to add to file name
 #--------------------------------------------------------------------------
 def self.checkExtensions(name, extensions)
   if FileTest.exist?(name)
     return name
   end
   # Add extension if needed
   extensions.each do |ext|
     if FileTest.exist?(name + '.' + ext)
       return name + '.' + ext
     end
   end
   # File doesn't exist
   return name
 end
 #--------------------------------------------------------------------------
 # * Get Valid File Name
 #     name            : Name of the file
 #--------------------------------------------------------------------------
 def self.selectBGMFilename(name)
   name = name.gsub("/", "\\")
   # See if file exists in game folder
   localname = self.checkExtensions(name, FModEx::FMOD_FILE_TYPES)
   # See if file exists in RTP
   commonname = self.checkExtensions(getRTPFolder + name, FModEx::FMOD_FILE_TYPES)
   if FileTest.exist?(localname)
     return localname
   end
   if FileTest.exist?(commonname)
     return commonname
   end
   # An invalid name was provided
   return name
 end
 #--------------------------------------------------------------------------
 # * Play a Sound File Then Return it
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #     position        : Starting position in milliseconds
 #     looping         : Does the sound loop?
 #     streaming       : Stream sound or load whole thing to memory?
 #--------------------------------------------------------------------------
 def self.play(name, volume, pitch, position, looping, streaming)
   # Get a valid file name
   filename = self.selectBGMFilename(name)
   # Create Sound or Stream and set initial values
   sound = streaming ? @fmod.createStream(filename) : @fmod.createSound(filename)
   sound.loopMode = looping ? FModEx::FMOD_LOOP_NORMAL : FModEx::FMOD_LOOP_OFF
   channel = sound.play
   volume = volume * 1.0
   pitch = pitch * 1.0
   file_length = sound.length(FModEx::FMOD_DEFAULT_UNIT)
   sound_file = SoundFile.new(filename, sound, channel, volume,
                               pitch, looping, streaming, file_length)
   sound_file.channel.volume = volume / 100.0
   sound_file.channel.frequency = sound_file.channel.frequency * pitch / 100
   sound_file.channel.position = position
   return sound_file
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of Sound File
 #--------------------------------------------------------------------------
 def self.stop(sound_file)
   unless sound_file and sound_file.channel
     return
   end
   # Stop channel, then clear variables and dispose of bgm
   sound_file.channel.stop
   sound_file.channel = nil
   sound_file.sound.dispose
 end
 #--------------------------------------------------------------------------
 # * Return Length in Milliseconds
 #--------------------------------------------------------------------------
 def self.get_length(sound_file, unit = FModEx::FMOD_DEFAULT_UNIT)
   return sound_file.length(unit)
 end
 #--------------------------------------------------------------------------
 # * Check if Another Sound File is Playing
 #--------------------------------------------------------------------------
 def self.already_playing?(sound_file, name, position = 0)
   # Get a valid file name
   filename = self.selectBGMFilename(name)
   if (sound_file)
     # If the same sound file is already playing don't play it again
     if (sound_file.name == filename and position == 0)
       return true
     end
     # If another sound file is playing, stop it
     if sound_file.channel
       self.stop(sound_file)
     end
   end
   # No sound file is playing or it was already stopped
   return false
 end
 #--------------------------------------------------------------------------
 # * Check if Sound File is Playing
 #--------------------------------------------------------------------------  
 def self.playing?(sound_file)
   unless sound_file and sound_file.channel
     return false
   end
   return sound_file.channel.playing?
 end
 #--------------------------------------------------------------------------
 # * Get Current Sound File Playing Position
 #--------------------------------------------------------------------------
 def self.get_position(sound_file)
   unless sound_file and sound_file.channel
     return 0
   end
   return sound_file.channel.position
 end
 #--------------------------------------------------------------------------
 # * Seek to a New Sound File Playing Position
 #--------------------------------------------------------------------------
 def self.set_position(sound_file, new_pos)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.channel.position = new_pos
 end
 #--------------------------------------------------------------------------
 # * Get Current Sound File Volume
 #--------------------------------------------------------------------------
 def self.get_volume(sound_file)
   unless sound_file
     return 0
   end
   return sound_file.volume
 end
 #--------------------------------------------------------------------------
 # * Set Sound File Volume
 #--------------------------------------------------------------------------
 def self.set_volume(sound_file, volume)
   unless sound_file and sound_file.channel
     return
   end
   sound_file.volume = volume * 1.0
   sound_file.channel.volume = volume / 100.0
 end
 #--------------------------------------------------------------------------
 # * Set Loop Points
 #     first           : Loop start point in milliseconds
 #     second          : Loop end point in milliseconds (-1 for file end)
 #     unit            : FMOD_TIMEUNIT for points
 #--------------------------------------------------------------------------
 def self.set_loop_points(sound_file, first, second, unit = FModEx::FMOD_DEFAULT_UNIT)
   unless sound_file and sound_file.channel
     return
   end
   # If second is -1 then set loop end to the file end
   if second == -1
     second = sound_file.length - 1
   end
   # Set loop points and reflush stream buffer
   sound_file.channel.sound.setLoopPoints(first, second, unit)
   sound_file.channel.position = sound_file.channel.position
   return sound_file
 end
 #--------------------------------------------------------------------------
 # * Play BGM (or ME)
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #     position        : Starting position in milliseconds
 #     looping         : Does the BGM loop?
 #--------------------------------------------------------------------------
 def self.bgm_play(name, volume, pitch, position = 0, looping = true)
   return if self.already_playing?(@fmod_bgm, name, position)
   # Now play the new BGM as a stream
   @fmod_bgm = self.play(name, volume, pitch, position, looping, true)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of BGM
 #--------------------------------------------------------------------------
 def self.bgm_stop
   self.stop(@fmod_bgm)
   @fmod_bgm = nil
 end
 #--------------------------------------------------------------------------
 # * Return BGM Length in Milliseconds
 #--------------------------------------------------------------------------
 def self.bgm_length(sound_file)
   self.get_length(@fmod_bgm)
 end
 #--------------------------------------------------------------------------
 # * Check if a BGM is Playing
 #--------------------------------------------------------------------------  
 def self.bgm_playing?
   return self.playing?(@fmod_bgm)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGM Playing Position
 #--------------------------------------------------------------------------
 def self.bgm_position
   return self.get_position(@fmod_bgm)
 end
 #--------------------------------------------------------------------------
 # * Seek to New BGM Playing Position
 #--------------------------------------------------------------------------
 def self.bgm_position=(new_pos)
   self.set_position(@fmod_bgm, new_pos)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGM Volume
 #--------------------------------------------------------------------------
 def self.bgm_volume
   return self.get_volume(@fmod_bgm)
 end
 #--------------------------------------------------------------------------
 # * Set BGM Volume
 #--------------------------------------------------------------------------
 def self.bgm_volume=(volume)
   self.set_volume(@fmod_bgm, volume)
 end
 #--------------------------------------------------------------------------
 # * Set Loop Points
 #     first           : Loop start point in milliseconds
 #     second          : Loop end point in milliseconds
 #     unit            : FMOD_TIMEUNIT for points
 #--------------------------------------------------------------------------
 def self.bgm_set_loop_points(first, second, unit = FModEx::FMOD_DEFAULT_UNIT)
   @fmod_bgm = self.set_loop_points(@fmod_bgm, first, second, unit)
 end
 #--------------------------------------------------------------------------
 # * Play BGS
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #     position        : Starting position in milliseconds
 #     looping         : Does the BGS loop?
 #--------------------------------------------------------------------------
 def self.bgs_play(name, volume, pitch, position = 0, looping = true)
   return if self.already_playing?(@fmod_bgs, name, position)
   # Now play the new BGS as a stream
   @fmod_bgs = self.play(name, volume, pitch, position, looping, true)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of BGS
 #--------------------------------------------------------------------------
 def self.bgs_stop
   self.stop(@fmod_bgs)
   @fmod_bgs = nil
 end
 #--------------------------------------------------------------------------
 # * Return BGS Length in Milliseconds
 #--------------------------------------------------------------------------
 def self.bgm_length(sound_file)
   self.get_length(@fmod_bgs)
 end
 #--------------------------------------------------------------------------
 # * Check if a BGS is Playing
 #--------------------------------------------------------------------------  
 def self.bgs_playing?
   return self.playing?(@fmod_bgs)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGS Playing Position
 #--------------------------------------------------------------------------
 def self.bgs_position
   return self.get_position(@fmod_bgs)
 end
 #--------------------------------------------------------------------------
 # * Seek to New BGS Playing Position
 #--------------------------------------------------------------------------
 def self.bgs_position=(new_pos)
   self.set_position(@fmod_bgs, new_pos)
 end
 #--------------------------------------------------------------------------
 # * Get Current BGS Volume
 #--------------------------------------------------------------------------
 def self.bgs_volume
   return self.get_volume(@fmod_bgs)
 end
 #--------------------------------------------------------------------------
 # * Set BGS Volume
 #--------------------------------------------------------------------------
 def self.bgs_volume=(volume)
   self.set_volume(@fmod_bgs, volume)
 end
 #--------------------------------------------------------------------------
 # * Set Loop Points
 #     first           : Loop start point in milliseconds
 #     second          : Loop end point in milliseconds
 #     unit            : FMOD_TIMEUNIT for points
 #--------------------------------------------------------------------------
 def self.bgs_set_loop_points(first, second, unit = FModEx::FMOD_DEFAULT_UNIT)
   @fmod_bgs = self.set_loop_points(@fmod_bgs, first, second, unit)
 end
 #--------------------------------------------------------------------------
 # * Play SE
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #--------------------------------------------------------------------------
 def self.se_play(name, volume, pitch)
   if @fmod_se.size > @fmod.maxChannels
     se = @fmod_se.shift
     self.stop(se)
   end
   # Load SE into memory and play it
   @fmod_se << self.play(name, volume, pitch, 0, false, false)
 end
 #--------------------------------------------------------------------------
 # * Stop and Dispose of all SEs
 #--------------------------------------------------------------------------
 def self.se_stop
   for se in @fmod_se
     self.stop(se)
   end
   @fmod_se.clear
 end
 #--------------------------------------------------------------------------
 # * Get Rid of Non-Playing SEs
 #--------------------------------------------------------------------------  
 def self.se_clean
   for se in @fmod_se
     unless self.playing?(se)
       self.stop(se)
       @fmod_se.delete(se)
     end
   end
 end
 #--------------------------------------------------------------------------
 # * Check if There's Some SE in SE Array
 #--------------------------------------------------------------------------  
 def self.se_list_empty?
   return @fmod_se.empty?
 end
 #--------------------------------------------------------------------------
 # * Dispose of Everything
 #--------------------------------------------------------------------------  
 def self.dispose
   self.bgm_stop
   self.bgs_stop
   self.se_stop
   @fmod.dispose
 end
end

#==============================================================================
# ** Audio
#------------------------------------------------------------------------------
#  The module that carries out music and sound processing.
#==============================================================================

module Audio
 #--------------------------------------------------------------------------
 # * Constants
 #--------------------------------------------------------------------------
 BGM_FADE_IN_INCREMENT = 5     # BGM volume incremented 0.2 seconds
 #--------------------------------------------------------------------------
 # * Instance Variables
 #--------------------------------------------------------------------------
 @bgm_fading_out = false       # BGM started fading out
 @bgm_fade_decrement = 0.0     # BGM volume decremented each update
 @bgs_fading_out = false       # BGS started fading out
 @bgs_fade_decrement = 0.0     # BGS volume decremented each update
 @me_fading_out = false        # ME started fading out
 @me_fade_decrement = 0.0      # ME volume decremented each update
 @me_playing = false           # Is some ME playing?
 @playing_bgm = nil            # BGM currently being played
 @next_bgm = nil               # The BGM to be played after fading out
 @next_bgm_position = 0        # Starting position of next bgm
 @next_bgs = nil               # The BGS to be played after fading out
 @next_bgs_position = 0        # Starting position of next bgm
 @next_me = nil                # The ME to be played after fading
 #--------------------------------------------------------------------------
 # * Starts BGM Playback
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #     position        : Starting position in milliseconds
 #--------------------------------------------------------------------------
 def Audio.bgm_play(filename, volume = 100, pitch = 100, position = 0,
                     fade_in = false)
   if @bgm_fading_out and !fade_in
     @next_bgm = RPG::AudioFile.new(filename, volume, pitch)
     @next_bgm_position = position
     return
   end
   start_volume = volume
   if fade_in
     @bgm_target_volume = volume unless @bgm_fading_in
     @bgm_fading_in = true
     start_volume = 0
   end
   @bgm_fading_out = false
   # If a ME is playing we wait until it's over before playing BGM
   unless @me_playing
     FMod::bgm_play(filename, start_volume, pitch, position)
   end
   @playing_bgm = RPG::AudioFile.new(filename, volume, pitch)
   @memorized_bgm = @playing_bgm
   @memorized_bgm_position = position
 end
 #--------------------------------------------------------------------------
 # * Stops BGM Playback
 #--------------------------------------------------------------------------
 def Audio.bgm_stop
   @memorized_bgm = nil
   @playing_bgm = nil
   @bgm_fading_in = false
   @bgm_fading_out = false
   # MEs are internally BGMs, but are stopped with me_stop instead
   if @me_playing
     return
   end
   FMod::bgm_stop
 end
 #--------------------------------------------------------------------------
 # * Starts BGM fadeout.
 #     time            : Length of the fadeout in milliseconds.
 #--------------------------------------------------------------------------
 def Audio.bgm_fade(time)
   return if @me_playing or !FMod::bgm_playing?
   @bgm_fading_out = true
   time = time / 1000
   @bgm_fade_decrement = FMod::bgm_volume / (time * 5)
 end
 #--------------------------------------------------------------------------
 # * Starts BGS Playback
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #     position        : Starting position in milliseconds
 #--------------------------------------------------------------------------
 def Audio.bgs_play(filename, volume = 100, pitch = 100, position = 0)
   if @bgs_fading_out
     @next_bgs = RPG::AudioFile.new(filename, volume, pitch)
     @next_bgs_position = position
     return
   end
   FMod::bgs_play(filename, volume, pitch, position)
 end
 #--------------------------------------------------------------------------
 # * Stops BGS Playback
 #--------------------------------------------------------------------------
 def Audio.bgs_stop
   FMod::bgs_stop
   @bgs_fading_out = false
 end
 #--------------------------------------------------------------------------
 # * Starts BGS fadeout.
 #     time            : Length of the fadeout in milliseconds.
 #--------------------------------------------------------------------------
 def Audio.bgs_fade(time)
   return unless FMod::bgs_playing?
   @bgs_fading_out = true
   time = time / 1000
   @bgs_fade_decrement = FMod::bgs_volume / (time * 5)
 end
 #--------------------------------------------------------------------------
 # * Starts ME Playback
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #--------------------------------------------------------------------------
 def Audio.me_play(filename, volume = 100, pitch = 100)
   if @me_fading_out
     @next_me = RPG::AudioFile.new(filename, volume, pitch)
     return
   end
   if @bgm_fading_out
     self.bgm_stop
   end
   # Memorize playing bgm
   if @playing_bgm and !@me_playing
     bgm = @playing_bgm
     @playing_bgm = RPG::AudioFile.new(bgm.name, FMod::bgm_volume, bgm.pitch)
     @memorized_bgm = @playing_bgm
     @memorized_bgm_position = FMod::bgm_position
   end
   @me_playing = true
   FMod::bgm_play(filename, volume, pitch, 0, false)
 end
 #--------------------------------------------------------------------------
 # * Stops ME Playback
 #--------------------------------------------------------------------------
 def Audio.me_stop
   return unless @me_playing
   @me_playing = false
   @me_fading_out = false
   # Play memorized bgm, fading in
   if @memorized_bgm and !@bgm_fading_out
     bgm = @memorized_bgm
     self.bgm_play(bgm.name, bgm.volume, bgm.pitch, @memorized_bgm_position, true)
   else
     self.bgm_stop
   end
 end
 #--------------------------------------------------------------------------
 # * Starts ME fadeout.
 #     time            : Length of the fadeout in milliseconds.
 #--------------------------------------------------------------------------
 def Audio.me_fade(time)
   return unless FMod::bgm_playing?
   @me_fading_out = true
   time = time / 1000
   @bgm_fade_decrement = FMod::bgm_volume / (time * 5)
 end
 #--------------------------------------------------------------------------
 # * Starts SE Playback
 #     name            : Name of the file
 #     volume          : Channel volume
 #     pitch           : Channel frequency
 #--------------------------------------------------------------------------
 def Audio.se_play(filename, volume = 100, pitch = 100)
   FMod::se_play(filename, volume, pitch)
 end
 #--------------------------------------------------------------------------
 # * Stops SE Playback
 #--------------------------------------------------------------------------
 def Audio.se_stop
   FMod::se_stop
 end
 #--------------------------------------------------------------------------
 # * Update ME Playback, SE Disposal and Fading, Called Each Frame
 #--------------------------------------------------------------------------
 def Audio.update
   # Stop ME when it's over (and continue playing BGM)
   if @me_playing
     unless FMod::bgm_playing?
       self.me_stop
     end
   end
   # Remove any finished SEs
   unless FMod::se_list_empty?
     FMod::se_clean
   end
   if @bgm_fading_in
     # Stop fading when target is reached, otherwise increase volume
     if FMod::bgm_volume >= @bgm_target_volume
       @bgm_fading_in = false
     else
       current_volume = FMod::bgm_volume + BGM_FADE_IN_INCREMENT
       FMod::bgm_volume = current_volume
     end
   end
   if FMod::bgm_playing? and @bgm_fading_out and
       !@me_playing
     if FMod::bgm_volume <= 0
       @bgm_fading_out = false
       self.bgm_stop
       # If another BGM played while fading out, play it (most recent)
       if @next_bgm
         self.bgm_play(@next_bgm.name, @next_bgm.volume,
                       @next_bgm.pitch, @next_bgm_position)
         @next_bgm = nil
       end
     else
       current_volume = FMod::bgm_volume - @bgm_fade_decrement
       FMod::bgm_volume = current_volume
     end
   end
   if FMod::bgs_playing? and @bgs_fading_out
     if FMod::bgs_volume <= 0
       @bgs_fading_out = false
       self.bgs_stop
       # If another BGS played while fading out, play it (most recent)
       if @next_bgs
         self.bgs_play(@next_bgs.name, @next_bgs.volume,
                       @next_bgs.pitch, @next_bgs_position)
         @next_bgs = nil
       end
     else
       current_volume = FMod::bgs_volume - @bgs_fade_decrement
       FMod::bgs_volume = current_volume
     end
   end
   if FMod::bgm_playing? and @me_fading_out
     if FMod::bgm_volume <= 0
       # If another ME played while fading out, play it (most recent)
       if @next_me
         self.me_play(@next_me.name, @next_me.volume, @next_me.pitch)
         @next_me = nil
       else
         @me_fading_out = false
         self.me_stop
       end
     else
       current_volume = FMod::bgm_volume - @bgm_fade_decrement
       FMod::bgm_volume = current_volume
     end
   end
 end
end

# Create an endless loop to update Audio module
Thread.new do
 loop do
   sleep 0.2
   Audio.update
 end
end


And this the script that causes the error:

class Game_Temp
 attr_accessor :map_bgm_pos
 alias :fmodex_old_temp_initialize :initialize unless $@
 def initialize
   fmodex_old_temp_initialize
   @map_bgm_pos = 0
 end
end

class Scene_Map
 alias :fmodex_old_map_call_battle :call_battle unless $@
 def call_battle
   $game_temp.map_bgm_pos = FMod.bgm_position
   fmodex_old_map_call_battle
 end
end

class Scene_Battle
 def judge
   # If all dead determinant is true, or number of members in party is 0
   if $game_party.all_dead? or $game_party.actors.size == 0
     # If possible to lose
     if $game_temp.battle_can_lose
############################################################################
#   ADDED $game_temp.map_bgm_pos AS 2ND PARAMETE TO bgm_play
############################################################################
       # Return to BGM before battle starts
       $game_system.bgm_play($game_temp.map_bgm, $game_temp.map_bgm_pos)
############################################################################        
       # Battle ends
       battle_end(2)
       # Return true
       return true
     end
     # Set game over flag
     $game_temp.gameover = true
     # Return true
     return true
   end
   # Return false if even 1 enemy exists
   for enemy in $game_troop.enemies
     if enemy.exist?
       return false
     end
   end
   # Start after battle phase (win)
   start_phase5
   # Return true
   return true
 end
 
 def start_phase5
   # Shift to phase 5
   @phase = 5
############################################################################
#   ADDED $game_temp.map_bgm_pos AS 2ND PARAMETE TO bgm_play
#   AND SWITCHED PLAY ORDER SO BGM IS PLAYED FIRST
############################################################################
   # Return to BGM before battle started
   $game_system.bgm_play($game_temp.map_bgm, $game_temp.map_bgm_pos)
   # Play battle end ME
   $game_system.me_play($game_system.battle_end_me)
############################################################################
   # Initialize EXP, amount of gold, and treasure
   exp = 0
   gold = 0
   treasures = []
   # Loop
   for enemy in $game_troop.enemies
     # If enemy is not hidden
     unless enemy.hidden
       # Add EXP and amount of gold obtained
       exp += enemy.exp
       gold += enemy.gold
       # Determine if treasure appears
       if rand(100) < enemy.treasure_prob
         if enemy.item_id > 0
           treasures.push($data_items[enemy.item_id])
         end
         if enemy.weapon_id > 0
           treasures.push($data_weapons[enemy.weapon_id])
         end
         if enemy.armor_id > 0
           treasures.push($data_armors[enemy.armor_id])
         end
       end
     end
   end
   # Treasure is limited to a maximum of 6 items
   treasures = treasures[0..5]
   # Obtaining EXP
   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 += exp
       if actor.level > last_level
         @status_window.level_up(i)
       end
     end
   end
   # Obtaining gold
   $game_party.gain_gold(gold)
   # Obtaining treasure
   for item in treasures
     case item
     when RPG::Item
       $game_party.gain_item(item.id, 1)
     when RPG::Weapon
       $game_party.gain_weapon(item.id, 1)
     when RPG::Armor
       $game_party.gain_armor(item.id, 1)
     end
   end
   # Make battle result window
   @result_window = Window_BattleResult.new(exp, gold, treasures)
   # Set wait count
   @phase5_wait_count = 100
 end

 
 def update_phase5
   # If wait count is larger than 0
   if @phase5_wait_count > 0
     # Decrease wait count
     @phase5_wait_count -= 1
     # If wait count reaches 0
     if @phase5_wait_count == 0
       # Show result window
       @result_window.visible = true
       # Clear main phase flag
       $game_temp.battle_main_phase = false
       # Refresh status window
       @status_window.refresh
     end
     return
   end
   # If C button was pressed
   if Input.trigger?(Input::C)
############################################################################
#   REMOVED $game_system.play_bgm BECAUSE IT'S DONE AUTOMATICALLY
#   WHEN ME IS DONE PLAYING
############################################################################
############################################################################
     # Battle ends
     battle_end(0)
   end
 end
end