[XP] Heretic's Magic Compass

Started by Heretic86, November 10, 2014, 06:46:18 am

Previous topic - Next topic

Heretic86

November 10, 2014, 06:46:18 am Last Edit: May 10, 2015, 06:05:44 am by Heretic86
Heretic's Magic Compass [XP]
Authors: Heretic
Version: 1.2
Type: Misc Add-on
Key Term: Misc Add-on



Introduction

This script will allow you to create a Magic Compass that points at either a Map Coordinates or an Event.  Its called a Magic Compass because normal compasses only point North.  This one points at a location Magically!


Features


  • Very easy to Install and Use

  • Should have a very high degree of compatability

  • Can point the Compass at any set of X and Y coordinates

  • Can point the Compass at an Event, even while it is moving around

  • Compass won't point at an Event that is Erased or doesn't have an Active Page

  • Can point at a set of X and Y coordinates that are off the current Map

  • Doesn't glitch when you go to Menu, unlike other Compass Scripts or Event Solutions

  • Uses a Background and Needle Image and positions these things for you!

  • Configuration Options can be altered during Gameplay

  • Limburger Cheese is really stinky but very tasty

  • Does anyone read this stuff?

  • No dependancies on other Scripts




Screenshots

Spoiler: ShowHide


The compass is in the Bottom Right corner.  It updates dynamically as you move about.




Demo

http://downloads.chaos-project.com/heretic86/MagicCompass/MagicCompassDemo.exe


Script

Place above Main and below Scene_Debug.  Anywhere else should be fine in theory.  If there are any problems, try moving this script closer to Main as some scripts replace methods that are aliased in this script.
Spoiler: ShowHide
#===============================================================================
#
#           HERETIC'S MAGIC COMPASS [XP]
#           Version 1.2
#           Wednesday, May 6th, 2015
#
#===============================================================================
#
#  -----  Overview  -----
#
#  This script will allow you to create a Magic Compass that points at either
#  a Map Coordinates or an Event.  Its called a Magic Compass because normal
#  compasses only point North.  This one points at a location Magically!
#
#
#  -----  Features  -----
#
#  - Very easy to install and use
#  - Should be highly compatible
#  - No dependancies on other Scripts
#  - Can point the Compass at any set of X and Y coordinates
#  - Can point the Compass at an Event, even while it is moving around
#  - Can point at a set of X and Y coordinates that are off the current Map
#  - Doesn't glitch when you go to Menu, unlike other Compass Scripts
#  - Uses a Background and Needle Image and positions these things for you
#  - Configuration Options can be altered during gameplay
#  - Limburger Cheese is really stinky but tasty
#  - Does anyone read this stuff?
#
#
#  -----  Version History  -----
#
#
#  Version 1.2 - Wednesday, May 6th, 2015
#    - Fixed a bug where Tone did not match Screen Tone on Initialize
#  Version 1.1 - Thursday, April 30th, 2015
#    - Updated to work with Looping Maps
#     * Compass will point at the closest possible distance to a Target
#  Version 1.0 - Friday, December 26th, 2014
#    - Initial Release
#
#  -----  Instructions  -----
#
#  There are a few very simple script calls.  Put these in Event -> Script
#
#  $game_system.enable_compass = true / false
#    * set to true or false to Show or Hide the Compass
#
#  set_compass_map_target(x, y)
#    * Sets the Compass to point at a Map X and Y Location (off map is a-okay)
#
#  set_compass_event_target(target)
#    * Sets the Compass to point at an Event or Event ID (either is fine)
#
#  clear_compass_target
#    * Clears Map Location and Target Event and causes Needle to float to North
#
#
#  -----  Conditional Branch Scripts  -----
#
#  Put these in Event -> Conditional Branch -> Script
#
#  enable_compass?
#    * returns True or False if the Compass is Enabled
#
#  can_point_compass?
#    * returns True or False if the Compass will Point at a Target
#    * returns False if an Event is Erased or doesn't have an Active Page or
#      the Compass doesn't have a Map Target
#
#  valid_compass_target?
#    * NOTE: This must be run on an Event (recommended for Advanced Users)
#    * $game_map.events[@event_id].valid_compass_target?
#    * returns True or False if the Event ID is not Erased and Page is Active
#
#
#  -----  Usage  -----
#
#  Once you have a Compass displayed on your screen, it will remain there
#  until you call "enable_compass = false".
#
#  The Compass Target will be erased when you change maps.  Transfer Player
#  on the same map will not erase the Compass Target however.
#
#  If you set a Compass Target to an Event, the Event can not be erased
#  and must have an active Page.  For example, you have an Event with
#  just one Page, and that Page has a Page Condition that is not met, such
#  as a Game Switch that is not set to On, then the Compass will not
#  point at that Event.
#
#  If an Event is Erased or Page Conditions are not met while your Compass
#  is displaying, the Compass will simply slowly float back to Due North.
#
#
#  -----  Limitations  -----
#
#  The only Limitation I can think of is that this script in its current state
#  probably won't work with Looping Map Scripts.  I may take a crack at
#  changing this if I ever get around to working on a Looping Map Script
#  for RPG Maker XP.
#
#  This has been fixed in Version 1.1 so the compass will consider the size
#  of the map and point the shortest distance to your Compass Target.
#
#
#  -----  Legal  -----
#
#  You may use this script in commercial products without permission, provided
#  that I am credited for the usage of this script.  You may redistribute this
#  script on any websites.  You may translate this script, provided that I am
#  retained as the original author.  You may make reasonable alterations
#  to this script to suit your needs.
#
#  You may NOT sell this script.
#
#  You may NOT claim this script to be your property or intellectual work.
#
#
#  -----  Layman Legal  -----
#
#  This script is supposed to be free.  Just credit me if you use it in
#  any sort of commercial stuff.
#
#
#  -----  Configuration Options  -----
#
#  There are a number of Configuration Options so that you can customize this
#  script to suit your needs.  The Configuration Options establish default
#  values, and can be changed during gameplay.  Recommended for advanced
#  users, but basically, all the Configuration Options are stored in
#  your $game_system.
#
#  COMPASS_X and COMPASS_Y are the On Screen Position for your Compass
#
#  COMPASS_ZOOM will resize an image without the need to edit the images you
#  use in an editor.  I've found that zooming out looks just a bit better
#  than 100% sized images while rotating.
#
#  COMPASS_BACK_OPACITY allows you to make the Compass Background Image
#  slightly transparent so it does not fully obstruct a Player's view
#  of the current Map.
#
#  COMPASS_HUD_Z is used to put the Compass on top of other Pictures or
#  put the Compass below other Pictures.  Up to you.
#
#  COMPASS_SCREEN_TONE is used to match the Tone of the Compass Images
#  to the Screen Tone.  This is useful if you fade to black and still have
#  the Compass displayed during a Map Change.  If you want the compass
#  to display even when the screen changes Tone, then set this value
#  to False.


# Compass Background Graphic for Player's Compass (Use "" for No Picture)
COMPASS_BACK_GRAPHIC = "Compass Back.png"

# Compass Graphic for Player's Compass (Use "" for No Picture)
COMPASS_NEEDLE_GRAPHIC = "Compass Needle.png"

# Screen Position of Compass (this will change depening on Picture Size)
COMPASS_X = 525
COMPASS_Y = 365

# Adjust Compass Size for both Graphics (Smaller Grpahics rotate a bit better)
COMPASS_ZOOM = 75.0

# Makes the Background Image of the Compass Transparent
COMPASS_BACK_OPACITY = 160.0

# Compass Hud Z-Index - Use -1 for below Pictures and 100+ for above Pictures
COMPASS_HUD_Z = -1

# Make the Compass have a tone Consistent with the Game Screen (true / false)
COMPASS_SCREEN_TONE = true

#==============================================================================
# ** Game_System
#==============================================================================
class Game_System
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Game_System
  #--------------------------------------------------------------------------
  attr_reader    :enable_compass           # Display On Screen Compass
  attr_accessor  :compass_back             # Compass Back Graphic Default
  attr_accessor  :compass_needle           # Compass Needle Graphic Default
  attr_accessor  :compass_x                # Compass Screen X Position
  attr_accessor  :compass_y                # Compass Screen Y Position
  attr_accessor  :compass_zoom             # Zoom of Compass Pictures
  attr_accessor  :compass_screen_tone      # Match Compass Tone to Screen Tone
  attr_accessor  :compass_back_opacity     # Opacity of Compass Background
  attr_accessor  :compass_target_x         # Map X Target Location
  attr_accessor  :compass_target_y         # Map Y Target Location
  attr_accessor  :compass_target_event_id  # Map Target Event 
  #--------------------------------------------------------------------------
  # * Game System Initialization - Game_System
  #  - Default Values for when Compass is changed to Enabled
  #  - Adjusting values in Game System will not affect an existing Compass
  #-------------------------------------------------------------------------- 
  alias compass_game_system_initialize initialize unless $@
  def initialize
    # Call Original or other Aliases
    compass_game_system_initialize
    # Enable or Disable display of Compass
    @enable_compass = false
    # Compass Image Filenames (from Pictures folder)
    @compass_back = COMPASS_BACK_GRAPHIC
    @compass_needle = COMPASS_NEEDLE_GRAPHIC
    # Default Screen Position of Compass Graphics
    @compass_x = COMPASS_X
    @compass_y = COMPASS_Y
    # Default Zoom Level of Compass Graphics
    @compass_zoom = COMPASS_ZOOM
    # Default Opacity of a Compass Background Picture
    @compass_back_opacity = COMPASS_BACK_OPACITY
    # Default Match the two Compass Pictures Tone to the Screen Tone for Effect
    @compass_screen_tone = COMPASS_SCREEN_TONE
    # Map Coordinates for Compass to point at
    @compass_target_x = nil
    @compass_target_y = nil
    # Event for Compass to point at dynamically
    @compass_target_event_id = nil   
  end
  #--------------------------------------------------------------------------
  # * Enable Compass= (Setter Method) - Game_System
  #  - Enables the Compass and creates if needed
  #  - If called from a Common Event while in a Menu or other Scene, then
  #    the Compass Graphics will be created when you return to the Map.
  #--------------------------------------------------------------------------
  def enable_compass=(value)
    # Check Value
    return unless [true, false].include?(value)
    # If True
    if value == true
      # If the Player's Compass doesn't exist and not a Common Event to change
      if not $game_player.compass
        # Create new Compass Object for Player
        $game_player.compass = Game_Compass.new
        # Position the Compass Object on the Screen
        $game_player.compass.position_compass
      end
    end
    # Store the Value
    @enable_compass = value
  end
  #--------------------------------------------------------------------------
  # * Set Compass Map Target - Game_System
  #  - Sets the Target of the Compass to Map Coordinates, even off map
  #     x : x-coordinate of Map
  #     y : y-coordinate of Map
  #-------------------------------------------------------------------------- 
  def set_compass_map_target(x, y)
    # Clears Event Target ID
    @compass_target_event_id = nil
    # Sets a Map Location as a Target
    @compass_target_x = x
    @compass_target_y = y
  end
  #--------------------------------------------------------------------------
  # * Set Compass Event Target - Game_System
  #  - Sets the Target of the Compass to an Event
  #     target : Event or Number
  #-------------------------------------------------------------------------- 
  def set_compass_event_target(target)
    # Clears Map Location as a Target
    @compass_target_x = nil
    @compass_target_y = nil
    # If Target is a Character
    if target.is_a?(Game_Event)
      # Just use the Event's ID
      @compass_target_event_id = target.id
    # Elsif the Target is a Number
    elsif target.is_a?(Numeric)
      # Set the Numeric Value of Target
      @compass_target_event_id = target
    end
  end
  #--------------------------------------------------------------------------
  # * Clear Compass Target - Game_System
  #  - Clears the Compass Target
  #--------------------------------------------------------------------------   
  def clear_compass_target
    # Clears Needle Angle of Picture
    $game_player.compass.needle_angle = nil if $game_player.compass
    # Clears Map Location as a Target
    @compass_target_x = nil
    @compass_target_y = nil
    # Clears Event Target ID
    @compass_target_event_id = nil
  end 
end

#==============================================================================
# ** Game_Map
#==============================================================================
class Game_Map
  #--------------------------------------------------------------------------
  # * Setup - Game_Map
  #  - Clears Compass Targets on Map Change
  #  - Transferring the Player on the same Map will retain Targets
  #     map_id : map ID
  #--------------------------------------------------------------------------
  alias compass_map_setup setup unless $@
  def setup(map_id)
    # If a Compass is being dislayed and Target is an Event
    if $game_system.enable_compass and $game_system.compass_target_event_id or
       ($game_system.compass_target_x and $game_system.compass_target_y)
      # If Map Change
      if @map and @map_id > 0 and @map_id != map_id
        # Clear Compass Target (Event and Map Location)
        $game_system.clear_compass_target
      end
    end
    # Call Original or other Aliases
    compass_map_setup(map_id)
  end
end

#==============================================================================
# ** Compass_Picture
#==============================================================================
class Compass_Picture < Game_Picture
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Compass_Picture
  #--------------------------------------------------------------------------
  attr_accessor :number                   # Picture Number and Z-Index
  attr_accessor :name                     # Picture Filename in Pictures Folder
  attr_accessor :origin                   # 0 Top Left - 1 Center (Default)
  attr_accessor :x                        # x-coordinate
  attr_accessor :y                        # y-coordinate
  attr_accessor :zoom_x                   # x directional zoom rate
  attr_accessor :zoom_y                   # y directional zoom rate
  attr_accessor :opacity                  # opacity level
  attr_accessor :blend_type               # blend method
  attr_accessor :tone                     # color tone
  attr_accessor :angle                    # rotation angle
  attr_accessor :angle_target             # target of angle rotation
  attr_accessor :angle_duration           # duration of angle rotation
  attr_accessor :rotate_speed             # repeating rotation
  #--------------------------------------------------------------------------
  # * Object Initialization - Compass_Picture
  #     number : picture number
  #     type   : background or needle
  #  - Creates the Pictures used for the Compass to add to Spriteset Map
  #  - Uses stored values from Game System to allow change during Gameplay
  #  - Changes to Game System do not affect existing Compass
  #  - Other methods available to Game_Picture are still available
  #--------------------------------------------------------------------------
  def initialize(number, type)
    @number = number
    @name = ""
    @type = type   
    @origin = 1
    @x = 0.0
    @y = 0.0
    @zoom_x = $game_system.compass_zoom
    @zoom_y = $game_system.compass_zoom
    @opacity = (type == :back) ? $game_system.compass_back_opacity : 255.0
    @blend_type = 0
    @duration = 0
    @target_x = @x
    @target_y = @y
    @target_zoom_x = @zoom_x
    @target_zoom_y = @zoom_y
    @target_opacity = @opacity
    # If Config to match Screen Tone   
    if $game_system.compass_screen_tone
      # Set Picture Tone to the Tone of the Screen
      @tone = $game_screen.tone
    else
      # Default Tone
      @tone = Tone.new(0, 0, 0, 0)
    end
    @tone_target = @tone.clone
    @tone_duration = 0
    @angle = 0
    @angle_target = @angle
    @angle_duration = 0
    @rotate_speed = 0
  end
  #--------------------------------------------------------------------------
  # * Frame Update - Compass_Picture
  #  - Replaces Game_Picture Update of Super Class so only updates Rotation
  #  - Updates Transitions for X, Y, Zoom_X, Zoom_Y, Opacity, and Tone
  #  - Updates Transition for Angle
  #  - Similar to Game_Picture Update method but allows Rotation Transition
  #--------------------------------------------------------------------------
  def update
    if @duration >= 1
      d = @duration
      @x = (@x * (d - 1) + @target_x) / d
      @y = (@y * (d - 1) + @target_y) / d
      @zoom_x = (@zoom_x * (d - 1) + @target_zoom_x) / d
      @zoom_y = (@zoom_y * (d - 1) + @target_zoom_y) / d
      @opacity = (@opacity * (d - 1) + @target_opacity) / d
      @duration -= 1
    end
    if @tone_duration >= 1
      d = @tone_duration
      @tone.red = (@tone.red * (d - 1) + @tone_target.red) / d
      @tone.green = (@tone.green * (d - 1) + @tone_target.green) / d
      @tone.blue = (@tone.blue * (d - 1) + @tone_target.blue) / d
      @tone.gray = (@tone.gray * (d - 1) + @tone_target.gray) / d
      @tone_duration -= 1
    end
    if @angle_duration == 0 and @rotate_speed != 0
      @angle += @rotate_speed / 2.0
    elsif @angle_duration >= 1
      d = @angle_duration
      @angle = (@angle * (d - 1) + @angle_target) / d
      @angle_duration -= 1
    end
    if @angle < 0 or @angle > 360
      while @angle < 0 or @angle > 360
        @angle += (@angle < 360 ? 360 : -360)
      end
      @angle %= 360
    end   
  end
end

#==============================================================================
# ** Scene_Map
#==============================================================================
class Scene_Map
  #--------------------------------------------------------------------------
  # * Compass Map Spriteset - Scene_Map
  #  - Just returns the Spriteset Map
  #--------------------------------------------------------------------------
  def compass_map_spriteset
    @spriteset
  end
end

#==============================================================================
# ** Spriteset_Map
#==============================================================================
class Spriteset_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Spriteset_Map
  #--------------------------------------------------------------------------
  attr_reader    :compass_back_picture    # Compass Picture for Background
  attr_reader    :compass_needle_picture  # Compass Picture for Needle
  attr_reader    :compass_back_sprite     # Picture Sprite for Compass 
  attr_reader    :compass_needle_sprite   # Picture Sprite for Compass
  #--------------------------------------------------------------------------
  # * Add Compass - Spriteset_Map
  #     compass : Game_Compass
  #  - Uses number as a way to control the Z-Index
  #--------------------------------------------------------------------------
  def add_compass
    # If the Compass Background Sprite does not already exist
    if @compass_back_sprite.nil?
      # Set the HUD's Z-Index as number from the Constant in Config
      number = COMPASS_HUD_Z
      # Create a Compass Picture for the Compass Background (type = :back)
      @compass_back_picture = Compass_Picture.new(number, :back)
      # Set the Picture Name from the Compass Object (refer to $game_system)
      @compass_back_picture.name = $game_system.compass_back
      # Shorthand
      b = @compass_back_picture
      # Create the Sprite for the Compass Background Picture
      @compass_back_sprite = Sprite_Picture.new(@viewport2, b)
    end
    # If the Compass Needle Sprite does not already exist
    if @compass_needle_sprite.nil?
      # Set the HUD's Z-Index as number from the Constant in Config
      number = COMPASS_HUD_Z     
      # Create a Compass Picture for the Compass Needle
      @compass_needle_picture = Compass_Picture.new(number, :needle)
      # If the Compass has a stored Needle Angle
      if not $game_player.compass.needle_angle.nil?
        # Set the Needle Angle before setting the Name or creating Sprite
        @compass_needle_picture.angle = $game_player.compass.needle_angle
      end
      # Set the Picture Name from the Compass Object (refer to $game_system)
      @compass_needle_picture.name = $game_system.compass_needle
      # Shorthand
      n = @compass_needle_picture
      # Create the Sprite for the Compass Needle Picture
      @compass_needle_sprite = Sprite_Picture.new(@viewport2, n)
    end
    # Position Compass Internally
    position_compass
  end
  #--------------------------------------------------------------------------
  # * Position Compass - Spriteset_Map
  #  - Positions the Compass Pictures and Sprites internally
  #-------------------------------------------------------------------------- 
  def position_compass
    # Shorthand - Same as Position Compass called Internally
    back_picture = @compass_back_picture
    needle_picture = @compass_needle_picture
    back_sprite = @compass_back_sprite
    needle_sprite = @compass_needle_sprite
    # Determine X Value as 1/2 of Larger Sprite
    if back_sprite.bitmap.width > needle_sprite.bitmap.width
      # Use the Centered Bitmap Width of the Background Sprite
      sprite_x = back_sprite.bitmap.width / 2
    else
      # Use the Centered Bitmap Width of the Needle Sprite
      sprite_x = needle_sprite.bitmap.width / 2
    end
    # Determine Y Value as 1/2 of Larger Sprite
    if back_sprite.bitmap.height > needle_sprite.bitmap.height
      # Use the Centered Bitmap Height of the Background Sprite
      sprite_y = back_sprite.bitmap.height / 2
    else
      # Use the Centered Bitmap Height of the Needle Sprite
      sprite_y = needle_sprite.bitmap.height / 2
    end
    # Position the Background Picture
    back_picture.x = $game_player.compass.x + sprite_x
    back_picture.y = $game_player.compass.y + sprite_y
    # Position the Needle Picture
    needle_picture.x = $game_player.compass.x + sprite_x
    needle_picture.y = $game_player.compass.y + sprite_y   
  end
  #--------------------------------------------------------------------------
  # * Compass Sprite Update - Spriteset_Map
  #  - Alias of Main Sprite Update Method
  #  - Checks for Missing Compass Sprites on Scene Change (Menu)
  #--------------------------------------------------------------------------
  alias compass_sprite_update update unless $@
  def update
    # If the Compass Option is Enabled
    if $game_system.enable_compass
      # If the Compass Background or Compass Needle Sprites dont exist
      if @compass_back_sprite.nil? or @compass_back_picture.nil?
        # Create new Compass Object for Player unless it exists
        $game_player.compass = Game_Compass.new unless $game_player.compass
        # Add the Pictures and Sprites to Spriteset Map Object
        add_compass
      end
      # Update the Compass Pictures
      @compass_back_picture.update
      @compass_needle_picture.update
      # Update the Compass Sprites with values from Pictures
      @compass_back_sprite.update
      @compass_needle_sprite.update
    elsif @compass_back_sprite
      # Dispose of the Sprite and set the object to nil
      @compass_back_sprite.dispose
      @compass_back_sprite = nil
      # If Needle Sprite exists
      if @compass_needle_sprite
        # Dispose of Needle Sprite and set the object to nil
        @compass_needle_sprite.dispose
        @compass_needle_sprite = nil
      end
      # Dispose of the Pictures
      @compass_back_picture = nil
      @compass_needle_picture = nil
    end
    # Call Original or other Aliases
    compass_sprite_update   
  end
  #--------------------------------------------------------------------------
  # * Dispose - Spriteset Map
  #  - Disposes of Compass Images and Sprites for their Bitmaps (memory leak)
  #--------------------------------------------------------------------------
  alias compass_spriteset_dispose dispose
  def dispose
    # Dispose of the Sprites and Bitmaps
    @compass_back_sprite.dispose if @compass_back_sprite
    @compass_needle_sprite.dispose if @compass_needle_sprite
    # Set Values to nil
    @compass_back_sprite = nil if @compass_back_sprite
    @compass_needle_sprite = nil if @compass_needle_sprite
    # Call Original or other Aliases
    compass_spriteset_dispose
  end
end

#==============================================================================
# ** Game_Character
#==============================================================================
class Game_Character
  #--------------------------------------------------------------------------
  # * Object Initialization - Game_Character
  #  - Add Values before calling Original or other Aliases before Update
  #--------------------------------------------------------------------------
  alias compass_character_initialize initialize unless $@
  def initialize
    # If Player is Initialized by the Character Class (Super) 
    if self.is_a?(Game_Player)
      # Placeholder for Game_Compass Object as a Picture
      @compass = nil
    end
    # Call Original or other Aliases
    compass_character_initialize
  end
end

#==============================================================================
# ** Game_Compass
#==============================================================================
class Game_Compass
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Game_Compass
  #-------------------------------------------------------------------------- 
  attr_accessor    :x                   # Position of Compass on Screen
  attr_accessor    :y                   # Position of Compass on Screen
  attr_accessor    :needle_angle        # Angle of Compass Needle
  #--------------------------------------------------------------------------
  # * Object Initialization - Game_Compass
  #  - Container in Game_Player for the Pictures
  #--------------------------------------------------------------------------
  def initialize
    # Position of Compass on Screen
    @x = $game_system.compass_x
    @y = $game_system.compass_y
    # Angle of the Compass Needle
    @needle_angle = nil
  end
  #--------------------------------------------------------------------------
  # * Back Sprite - Game_Compass
  #  - Returns the Spriteset Map Compass Background Sprite
  #-------------------------------------------------------------------------- 
  def back_sprite
    $scene.compass_map_spriteset.compass_back_sprite
  end
  #--------------------------------------------------------------------------
  # * Needle Sprite - Game_Compass
  #  - Returns the Spriteset Map Compass Background Sprite
  #-------------------------------------------------------------------------- 
  def needle_sprite
    $scene.compass_map_spriteset.compass_needle_sprite
  end
  #--------------------------------------------------------------------------
  # * Back Picture - Game_Compass
  #  - Returns the Spriteset Map Compass Background Picture
  #-------------------------------------------------------------------------- 
  def back_picture
    $scene.compass_map_spriteset.compass_back_picture
  end
  #--------------------------------------------------------------------------
  # * Needle Picture - Game_Compass
  #  - Returns the Spriteset Map Compass Needle Picture
  #-------------------------------------------------------------------------- 
  def needle_picture
    $scene.compass_map_spriteset.compass_needle_picture
  end
  #--------------------------------------------------------------------------
  # * Compass Target Distance - Game_Compass
  #  - Returns Array of Distances between Player and Target Coordinates
  #  - Made into a Method because this is where Looping Map Scripts will
  #    become Incompatible, so one method to fix things hopefully.
  #     target_x : Map Target X Coordinate
  #     target_y : Map Target Y Coordinate 
  #-------------------------------------------------------------------------- 
  def compass_target_distance(target_x, target_y)
    # Distance in Real Values between Player and Target
    x_dist = (target_x - $game_player.real_x) * 1.0
    y_dist = (target_y - $game_player.real_y) * 1.0
    # Return the X and Y Distances as an Array
    return [x_dist, y_dist]
  end
  # If Heretic's Loop Maps is installed
  if Game_Map.method_defined?(:map_loop_passable?) 
    #--------------------------------------------------------------------------
    # * Compass Target Distance - Game_Compass (for Loop Maps)
    #  - Required by Trig function to determine Radian Tangent value for Angle
    #  - Returns Array of Distances between Player and Target Coordinates
    #  - Made into a Method because this is where Looping Map Scripts will
    #    become Incompatible, so one method to fix things hopefully.
    #     target_x : Map Target X Coordinate
    #     target_y : Map Target Y Coordinate 
    #--------------------------------------------------------------------------
    alias loop_map_compass_target_distance compass_target_distance unless $@
    def compass_target_distance(target_x, target_y)
      # Get difference in target coordinates from original method     
      dx, dy = loop_map_compass_target_distance(target_x, target_y)
      # If Map Loops Horizontal and Distance is more than Half the Map (128 / 2)
      if $game_map.loop_horizontal? and dx.abs > $game_map.width * 64
        # Adjust X Distance for Horizontal Looping Map
        dx += (dx < 0) ? $game_map.width * 128 : -$game_map.width * 128
      end
      # If Map Loops Vertical and Distance is more than Half the Map (128 / 2)
      if $game_map.loop_vertical? and dy.abs > $game_map.height * 64
        # Adjust X Distance for Vertical Looping Map
        dy += (dy < 0) ? $game_map.height * 128 : -$game_map.height * 128
      end
      # Return Adjusted Difference X and Y values as Array for Looping Maps
      return [dx, dy]
    end
  end # End Optional Alias Definition
  #--------------------------------------------------------------------------
  # * Update (frame) - Game_Compass
  #  - Points the Compass at Target Location or Event
  #-------------------------------------------------------------------------- 
  def update
    # If Option to keep the Compass Tone same as the Screen
    if $game_system.compass_screen_tone
      # Set the Tone for the Two Images if visible
      back_picture.tone = $game_screen.tone if back_picture.name != ""
      needle_picture.tone = $game_screen.tone if needle_picture.name != ""
    end
    # Shorthand
    target_id = $game_system.compass_target_event_id
    # If Compass is set to use an Event as a Target and Target is Valid
    if target_id and $game_map.events[target_id] and
       $game_map.events[target_id].valid_compass_target?
      # Get the Event from the Game Map
      target_event = $game_map.events[$game_system.compass_target_event_id]
      # Set Target X and Y
      target_x = target_event.real_x * 1.0
      target_y = target_event.real_y * 1.0
    # If Target Coordinates are a Map Location
    elsif $game_system.compass_target_x and $game_system.compass_target_y
      # Set the Target Coordintates for Real X and Y values
      target_x = $game_system.compass_target_x * 128.0
      target_y = $game_system.compass_target_y * 128.0
    end
    # If Target Coordinates for Compass
    if target_x and target_y
      # X and Y Distance between the Player and Target
      x, y = compass_target_distance(target_x, target_y)
      # Clear Angle Transitions
      needle_picture.angle_target = 0
      needle_picture.angle_duration = 0
      # If Coordinate Match and not Rotating
      if x == 0 and y == 0 and needle_picture.rotate_speed == 0
        # Spin the Needle
        needle_picture.rotate(needle_picture.angle > 180 ? -30 : 30)
      end
      # If Same X Position
      if x == 0 and y != 0
        # Clear repeating Rotation
        needle_picture.rotate(0)
        # Set Needle Picture to Up or Down
        #needle_picture.angle = (target_y < $game_player.real_y ? 0 : 180)
        needle_picture.angle = (y < 0 ? 0 : 180)
      # If Same Y Position
      elsif y == 0 and x != 0
        # Clear repeating Rotation
        needle_picture.rotate(0)
        # Set Needle Picture to Left or Right
        needle_picture.angle = (x < 0 ? 90 : 270)
      # Use Trig to determine Angle of Sprite
      elsif x != 0 and y != 0
        # Clear repeating Rotation
        needle_picture.rotate(0)
        # Trig to determine Angle (-180 used to point with the top of picture)
        needle_picture.angle = (Math::atan2(x,y)*180.0/Math::PI).round - 180
      end
      # Store the Needle Angle for Scene Changes (Menu)
      @needle_angle = needle_picture.angle
    # No Compass Target     
    elsif needle_picture.angle != 0 and needle_picture.angle_duration == 0
      # Clear repeating Rotation
      needle_picture.rotate(0)
      # Set the Needle Angle between 0 and 360
      if needle_picture.angle < 0 or needle_picture.angle > 360
        while needle_picture.angle < 0 or needle_picture.angle > 360
          needle_picture.angle += (needle_picture.angle < 360 ? 360 : -360)
        end
        needle_picture.angle %= 360
      end
      # Angle
      a = needle_picture.angle
      # Use a Transition to move the Needle to 0 at 0.5 Degrees per Frame
      needle_picture.angle_target = (a > 180 ? 360.0 : 0.0)
      needle_picture.angle_duration = (a > 180 ? (a - 180) * 2 : a * 2)
    end
  end
  #--------------------------------------------------------------------------
  # * Position Compass - Game_Compass
  #  - Positions the Compass on the Screen and centers the Compass Images
  #    within this Container
  #--------------------------------------------------------------------------   
  def position_compass
    # Make sure the Sprites for the Compass exist in Spriteset Map
    $scene.compass_map_spriteset.add_compass
    # Determine X Value as 1/2 of Larger Sprite
    if back_sprite.bitmap.width > needle_sprite.bitmap.width
      # Use the Centered Bitmap Width of the Background Sprite
      @sprite_x = back_sprite.bitmap.width / 2
    else
      # Use the Centered Bitmap Width of the Needle Sprite
      @sprite_x = needle_sprite.bitmap.width / 2
    end
    # Determine Y Value as 1/2 of Larger Sprite
    if back_sprite.bitmap.height > needle_sprite.bitmap.height
      # Use the Centered Bitmap Height of the Background Sprite
      @sprite_y = back_sprite.bitmap.height / 2
    else
      # Use the Centered Bitmap Height of the Needle Sprite
      @sprite_y = needle_sprite.bitmap.height / 2
    end
    # Position the Background Picture
    back_picture.x = @x + @sprite_x
    back_picture.y = @y + @sprite_y
    # Position the Needle Picture
    needle_picture.x = @x + @sprite_x
    needle_picture.y = @y + @sprite_y
  end
end

#==============================================================================
# ** Game_Player
#==============================================================================
class Game_Player < Game_Character
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Game_Player
  #--------------------------------------------------------------------------
  attr_accessor :compass          # Compass Object for Player
  #--------------------------------------------------------------------------
  # * Update - Game_Player
  #  - Updates the Player's Compass
  #--------------------------------------------------------------------------
  alias player_compass_update update unless $@
  def update
    # Call Original or other Aliases
    player_compass_update
    # If Player has a Compass
    if $game_system.enable_compass and $scene.is_a?(Scene_Map)
      # If the Compass Picture doesn't exist
      if @compass.nil?
        # Create the new Game Compass
        @compass = Game_Compass.new
        # Position the Compass on the Screen
        @compass.position_compass
      end
      # Update the Compass Picture Sprites from within the Object
      @compass.update
    # Compass is Disabled but Compass exists
    elsif @compass
      # Clear the Compass ojbect
      @compass = nil
    end   
  end
end

#==============================================================================
# ** Game_Event
#==============================================================================
class Game_Event < Game_Character
  #--------------------------------------------------------------------------
  # * Valid Compass Target? - Game_Event
  #  - Valid Compass Targets should have an Active Page and are not Erased
  #--------------------------------------------------------------------------
  def valid_compass_target?
    return (not @erased and not @page.nil?)
  end
end

#==============================================================================
# ** Interpreter
#==============================================================================
class Interpreter
  #--------------------------------------------------------------------------
  # * Set Compass Map Target - Interpreter
  #  - Sets the Target of the Compass to Map Coordinates, even off map
  #     x : x-coordinate of Map
  #     y : y-coordinate of Map
  #--------------------------------------------------------------------------   
  def set_compass_map_target(x, y)
    # Pass the Arguments along to the Game System method
    $game_system.set_compass_map_target(x, y)
  end
  #--------------------------------------------------------------------------
  # * Set Compass Event Target - Interpreter
  #  - Sets the Target of the Compass to an Event
  #     target : Event or Event ID
  #--------------------------------------------------------------------------   
  def set_compass_event_target(target)
    # Pass the Arguments along to the Game System method
    $game_system.set_compass_event_target(target)
  end
  #--------------------------------------------------------------------------
  # * Clear Compass Target - Interpreter
  #  - Clears the Compass Target
  #--------------------------------------------------------------------------   
  def clear_compass_target
    # Call the method in Game System
    $game_system.clear_compass_target
  end
  #--------------------------------------------------------------------------
  # * Enable Compass? - Interpreter (Setter Method)
  #  - Returns True or False from the Game System
  #--------------------------------------------------------------------------
  def enable_compass?
    return ($game_system.enable_compass == true)
  end
  #--------------------------------------------------------------------------
  # * Can Point Compass? - Interpreter
  #  - Checks if the Compass has a Target that will cause it to Point
  #--------------------------------------------------------------------------
  def can_point_compass?
    # Shorthand for Game System
    s = $game_system
    # If Compass has a Target
    if (s.compass_target_x and s.compass_target_y) or
       (s.compass_target_event_id and
        $game_map.events[s.compass_target_event_id] and
        $game_map.events[s.compass_target_event_id].valid_compass_target?)
      # Compass will point at a Target
      return true
    end
    # Default - Needed for Event Conditional Branch -> Script Evaluation
    return false
  end 
end

#==============================================================================
# ** Scene_Load
#==============================================================================
class Scene_Load < Scene_File
  #--------------------------------------------------------------------------
  # * Read Save Data - Scene_Load
  #     file : file object for reading (opened)
  #  - Checks for Uninitialized Values that Crash Savegames
  #--------------------------------------------------------------------------
  alias compass_read_save_data read_save_data unless $@
  def read_save_data(file)
    # Call Original or other Aliases
    compass_read_save_data(file)
    # Set Game System Compass to False for later Evaluation in Script Calls
    $game_system.enable_compass = false if $game_system.enable_compass.nil?
    # If Game System Compass Filenames are nil
    if $game_system.compass_back.nil?
      # Initialize from the Constant Value
      $game_system.compass_back = COMPASS_BACK_GRAPHIC
    end
    # If Game System Compass Filenames are nil
    if $game_system.compass_needle.nil?
      # Initialize from the Constant Value
      $game_system.compass_needle = COMPASS_NEEDLE_GRAPHIC
    end
    # If Game System Compass Background Opacity is
    if $game_system.compass_back_opacity.nil?
      # Initialize from the Constant Value
      $game_system.compass_back_opacity = COMPASS_BACK_OPACITY
    end
    # If Game System Compass Screen Tone value not set
    if $game_system.compass_screen_tone.nil?
      # Initialize from the Constant Value
      $game_system.compass_screen_tone = (COMPASS_SCREEN_TONE) ? true : false
    end   
    # If Game System Zoom is nil?
    $game_system.compass_zoom = COMPASS_ZOOM if $game_system.compass_zoom.nil?
    # If Game System Compass X or Y are nil?
    $game_system.compass_x = COMPASS_X if $game_system.compass_x.nil?
    $game_system.compass_y = COMPASS_Y if $game_system.compass_y.nil?
  end
end
 



Instructions

This script is quite easy to use.

Once installed somewhere above main, you can mess with the Options if you'd like.

To display the Compass, run a Script $game_system.enable_compass = true
To hide the Compass, run a Script $game_system.enable_compass = false

NOTE: I ran into some issues with the game hanging because of an Interpreter Bug.  You can use Zeriab's command_355 fix to take care of the issue, or put another line in your script that says "return true".  The command_355 fix is really the way to go.

Now that your Compass is shown, it needs a Target to point at!  Just three important script calls.
- set_compass_map_target(x, y)          # Use for a Map Location (offscreen is fine)
- set_compass_event_target(event_id) # Use to point the Compass at an existing Event
- clear_compass_target()                   # Clears Compass Targets

There are more commands and features available, described in documentation.



Compatibility

May not be compatible with any Looping Map Scripts at this time.


Credits and Thanks


  • I'd like to thank the Meteor that wiped out the Dinosaurs 65 million years ago.

  • Without that Meteor, we wouldn't be here today and I might be all scaley and have dry skin.




Author's Notes

The point of Scripts is to make things easy for others.  It is possible to create a Compass purely out of Events, however, Event solutions have drawbacks as well as they may require more work than is necessary to pull off.  Just try the Demo.  It's small and will show you why this script is superior.

I would like to make this script compatible with Looping / Repeating Map Scripts for XP.  There is one method in this script that I believe may be aliased or replaced by said Looping / Repeating Map scripts for compatability.  That can be discussed if you're interested in getting these scripts to play nice with each other.  Besides Looping Map Scripts, there should be no other conflicts with this script.
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

Zexion


Heretic86

Quote from: Zexion on November 10, 2014, 06:52:42 am
I read everything >:]


He he he, yes, Limburger Cheese is a Feature!  :p
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

ForeverZer0

* Fixes tag in the title so it displays in the database *
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Heretic86

Oop, [XP] goes on the left.  Got it!

So how about a Repeating / Looping Map Script or two?
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)