[XP] Heretic's Downhill Ice Deluxe

Started by Heretic86, April 29, 2015, 08:10:47 pm

Previous topic - Next topic

Heretic86

April 29, 2015, 08:10:47 pm Last Edit: May 10, 2015, 06:07:07 am by Heretic86
Downhill Ice Deluxe XP
Authors: Heretic
Version: 1.01
Type: Custom Movement System
Key Term: Custom Movement System



Introduction

Slide Downhill on Downhill Ice!


Features


  • Downhill Sliding Movment based on Terrain Tags

  • NPCs can interact as expected on Ice (Customizable)

  • Event Collisions work properly

  • NPCs can be prohibited from Event Ice or ALL Event Tiles unless Through

  • Ice Tiles can be covered up with Event Tiles to prevent Sliding!

  • Compatible with Heretic's Caterpillar 2.0+

  • Wheeeeeeeee!!!!  Yeah, going Wheeeee is a Feature!




Screenshots

Spoiler: ShowHide


I'm not much of an Artist when it comes to Tileset Graphics.  The white shiny parts are intended as a placeholder for better looking graphics to be applied.



Demo

http://downloads.chaos-project.com/heretic86/MP/DownhillIceDeluxeDemo.exe


Script

Place below Modular Passable (Required)
Place below Collision Optimizer (Optional)
Place below Loop Maps (Optional)
Place below Heretic's Caterpillar 2.0+ (Optional)
Spoiler: ShowHide
#=============================================================================
#
#           HERETIC'S DOWNHILL ICE DELUXE [XP]
#           Version 1.01
#           Wednesday, May 6th, 2015
#
#=============================================================================
#
# ----- ! IMPORTANT ! -----
#
# *** REQUIRES HERETICS MODULAR PASSABLE SCRIPT ***
# *** REQUIRES HERETICS MODULAR PASSABLE SCRIPT ***
# *** REQUIRES HERETICS MODULAR PASSABLE SCRIPT ***
#
# ***  Downhill Ice is NOT ENABLED by DEFAULT!  ***
#
# In order for Downhill Ice to work as expected you MUST run a Script from
# an Event in order to ENABLE DOWNHILL ICE!!!
#
# - $game_system.enable_ice = true
# - $game_system.event_ice = true (for Events with Tileset Graphics ONLY)
#
# This script handles Ice in an unusual fashion which may cause some
# lag.  I recommend leaving "enable_ice" set to false UNTIL you load
# a Map that requires this script in order to keep your performance
# at a playable rate.  Although it has been heavily tested to optimize
# performance as much as possible, it can still cause lag if run with
# other expensive scripts at the same time.
#
#
# -----  Features  -----
#
# - Downhill Sliding movement based on Terrain Tags
# - NPCs can interact as expected on Ice
# - Compatible with other Scripts based on Modular Passable I wrote
# - Event Collisions work properly
# - NPCs can be prohibited from Event Ice or ALL Event Tiles unless Through
# - Ice Tiles can be covered up with Event Tiles to prevent Sliding!
# - Compatible with Heretic's Caterpillar Version 2.0+
#
#
# ---  Summary  ---
#
# Definition: NPC - Non Player Character, an Event with a Character Graphic.
#
# This script allows you to use Terrain Tags to easily make Characters slide
# downhill while on Ice!  This adds a bit of a Platforming Element to your
# game and allows the creation of Puzzles!  NPC's can also interact with
# both Map Ice and Event Ice!
#
# Oh yeah, and I wrote it, thats why!#
#
#
# ---  Requirements & Installation, Legal  ---
#
# *** REQUIRES HERETICS MODULAR PASSABLE SCRIPT ***
# *** REQUIRES HERETICS MODULAR PASSABLE SCRIPT ***
# *** REQUIRES HERETICS MODULAR PASSABLE SCRIPT ***
#
# Heretic's Modular Passable Script is available for download at:
# http://www.chaos-project.com
#
# LEGAL: You are allowed to share this script, and Modular Passable on
#        other sites as long as you give me credit.  You may NOT
#        sell this script.
#
# This script should be placed BELOW Heretics Modular Passable.
# Heretics Modular Passable should be placed just below the real SDK
# It should work fine as long as it is between Modular Passable and Main.
#
# This script should be placed below Heretics Caterpillar Version 2.0+
# if you use that script.
#
#    Script Order:
#    - Scene Debug
#    - SDK (if used, not required)
#    - Heretic's Modular Passable (REQUIRED)
#    - Heretic's Caterpillar (Version 2.0+, if used, not required)
#    - Other Modular Passable Dependant Scripts can go here (not required)
#    - Heretic's Downhill Ice (THIS SCRIPT, REQUIRED, DUH)
#    - Other Modular Passable Dependant Scripts can go here (not required)
#    - Main
#
# Note: Due to the nature of this script requiring Modular Passable for
#       proper Collision Detection, this script does not have a LITE
#       version. 
#
# ---  Version History  ---
#
# Version 1.0 - Tuesday, October 21st, 2014
# - Initial Release
# Version 1.01 - Wednesday, May 6th, 2015
# - Fixed bug with Set Event Location not nested properly
#
#
# -----  Comment Configuration  -----
#
# The following Comments are intended to be placed within the first several
# lines on each Page where a Comment Feature is desired.  The number of
# lines is controlled by Modular Passable in a constant Configuration Option
# called COMMENT_LIMIT, which is set to 10 in that script by default.
#
#
# \ice             - Allows Character to slide Downhill on Ice
# \no_event_tiles  - Prevents NPC movement on Any Events unless Through
# \no_event_ice    - Prevents NPC movement on Events with Ice Tiles
# \no_player_pass  - Prevents Event Tiles from moving into Player (Collision)
#
# NOTE: NPCs MUST have a \ice Comment to interact with any Ice (Event or Tile).
# NOTE: The Player is automatically enabled to interact with Ice.
#
# -----  Usage  -----
#
# NOTE:  I recommend disabling Ice via a System Option unless you are on a Map
#        that uses Ice.  This is for performance purposes only as this script
#        handles Ice Movement in an irregular way.
#
#  To use Ice, simply edit your Tileset to give a Downhill Ice Tile a Terrain
#  Tag consistent with the ICE_TERRAIN TAG in System Options.  The Player will
#  automatically be made Slide Downhill on ice. 
#
#  $game_player.ice = true / false
#
#  To allow an Event (with a Character or Tile Graphic), the Event MUST have
#  an \ice Comment within the first 10 or so lines on each Page you wish
#  to have Ice Movement enabled for the Event.
#
#  Events with an \ice Comment on the Active Page can also interact with
#  other Events with Ice Tile.  You can override this behavior by adding
#  an additional \no_event_ice Comment so they will "Slide Downhill" on
#  any Tile with an Ice Terrain Tag, but wil STOP if they collide with
#  an Event with an Ice Tile Graphic.
#
#  If you want to use Event with Ice Tiles, you'll need to have a Tile
#  set with an ICE TERRAIN TAG.  This is due to the fact you can not
#  use an Autotile for an Event Graphic.  It may be useful to give
#  a Tile that has no Graphic an ICE TERRAIN TAG so you can "draw" over
#  any Autotiles you wish to cause the "Sliding Downhill" behavior.
#
#  You can also cover up any Ice tiles with an Event with a Tile in order
#  to create Bridges over Icy Terrain!
#
#
# ---  Pathfinding  ---
#
# Avoid Pathfinding around Ice with ALL Pathfinding Scripts as Ice will
# cause the results to end up somewhere other than expected.
#
#
# ---  System Options  ---
#
# There are TWO System Options.
#
# $game_system.enable_ice : true / false - Enable or Disable Ice Movement
# $game_system.event_ice  : true / false - Enable Events with Ice Map Tiles
#
# The System Option for "enable_ice" must be TRUE for ANY Ice related movement
# to occur.  The System Option for "event_ice" will allow you to use an Event
# with a Tile that has an ICE TERRAIN TAG to cause Ice related movement in
# the Player and \ice Comment Events.  If "event_ice" is set to false, you
# will get a bit of a performce increase, but will not be able to use
# any Events with Ice Tiles for Ice related movement.
#
# I recommend leaving both "enable_ice" and "event_ice" off except for on
# specific Maps where you intend to use it.
#
#
# ---  Script Calls  ---
#
# - use_ice    : Causes an Event to now slide down on ice
#
# - clear_ice  : Sets @ice to false
#
# ** Please use these methods to control a Characters @ice property because
#    the methods changes two properties needed for ice, not just one.
#
#
# ---  Additional Script Calls  ---
#
# You can set any of the Ice related properties with attr_accessor methods.
#
# - @ice_speed = N : Call from Move Route -> Script
# - $game_map.event[@id].ice_speed = N : Call from a Script anywhere
#
# - @no_event_ice = true / false
# - $game_map.events[@id].no_event_ice = true / false
#
# You'll probably never ever need anything other than 'use_ice' or 'clear_ice'.
#
#
# -----  Ice Options  -----
#
# There are a couple of configurable Ice Options.
#
# - Ice Terrain Tag : [1-7] A Terrain Tag to apply to Tile in your Tilesets
# - Ice Speed Min   : Minimum Speed to slide downhill.  Should be > 0
# - Ice Speed Max   : Prevents unlimited acceleration
# - Ice Speed Accel : How quickly a character will accelrate on Ice Tiles
# - Ice Speed Decel : How quickly a character will slide back to normal
# - Ice Tile Y OfFfset : Used to determine if a character is standing on ice
#                        in relation to the position of that characters Feet
#                        on a Tile.  Just because a Character moves up or
#                        down, their Feet may still be in contact with the
#                        previous Tile.  Recommended set to 32 for standard
#                        sized Characters.  Offset is based on Real Y
#                        so a Range of 0 - 128 is available.
#
# -----  Looping Maps Compatability  ------
#
# This script will work fine with Looping Maps, with one minor exception.  If
# you use both Looping Maps and Downhill Ice, don't allow players to step on
# to Ice at the very bottom tile of the map.  If the character is on Ice
# already, that is fine, just dont step on to the ice.  The result is that
# some Artifacts of Sprites may appear at the very top of the screen.  You
# can allow Infinite Ice, just dont let the Player step on if on the very
# very bottom tile.
#
# -----  Caterpillar  -----
#
# Downhill Ice is compatible with Heretic's Caterpillar 2.0+ as long as you
# place the Caterpillar Script above Downhill Ice.  The only thing you may
# notice is that the Caterpillar Actors "shake" as they reach maximum speed.
# This is due to the way the two scripts handle the Caterpillar, which does
# what it can to hold the Caterpillar together.  Although Caterpillar Actors
# can slide on Ice, they will only slide down as the Player has moved at that
# location.  The Player can step across a single column of Downhill Ice, and
# by default, will slide down Two Tiles, and the Caterpillar Actors will also
# slide, but will not go down any farther, as if the group were working
# together to cross the Ice.
#
# It is recommended to not use "cat_to_player" and variats at the bottom of
# a Downhill Ice section without further eventing as the player will move
# up, then immediately back down and retrigger cat to player, which causes
# all Caterpillar characters to have unpredictable behavior.
#
#
#  -----  CONFIG  -----
#
#  You can change the Ice Options here to suit your needs

ICE_TERRAIN_TAG = 1
ICE_SPEED_MIN = 2
ICE_SPEED_MAX = 32
ICE_SPEED_ACCEL = 2
ICE_SPEED_DECEL = 8
ICE_TILE_Y_OFFSET = 32 # 0 - 128

# Check for Modular Passable Script - REQUIRED - DO NOT EDIT
unless $Modular_Passable
  print "Fatal Error: Heretics Downhill Ice Deluxe 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"
  # End game before fatal errors
  exit
end

#==============================================================================
# ** Game_System
#==============================================================================
class Game_System
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Game_System
  #--------------------------------------------------------------------------
  attr_accessor :enable_ice         # If Characters can slide on Ice
  attr_accessor :event_ice          # If Event Tiles checked for Ice Tags
  #--------------------------------------------------------------------------
  # * Game System Object Initialization
  #--------------------------------------------------------------------------
  alias ice_initialize initialize unless $@
  def initialize
    # Call Original or other Aliases
    ice_initialize
    # Enable Ice Movement - Dont always enable due to Performance!
    @enable_ice = false
    # Enable NPCs on Ice
    @event_ice = true
  end
end
#==============================================================================
# ** Game_Character
#==============================================================================
class Game_Character
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Game_Character
  #--------------------------------------------------------------------------
  attr_accessor :ice_speed            # Characters Speed for sliding on Ice
  attr_accessor :ice_last_tag         # Stored Values for Terrain Tags
  attr_accessor :ice_need_tag_update  # If Update to Terrain Tag is needed
  attr_accessor :no_event_ice         # This Character Event Ice Prohibited
  attr_reader   :ice                  # If Character Slides on Ice (has WRITER)
  #--------------------------------------------------------------------------
  # * Object Initialization - Game_Character
  #  - Player properties added in Character to maintian Class Structure
  #  - Does not Alias Player Initialize because it causes Incompatability
  #    between Scripts that add properties to the Player Class.  An Alias
  #    of initialize in Game_Player creates an Alias of the Super Method
  #    which localizes it to only the Player Class and prevents Aliases
  #    of the Character initialize method from adding properties to
  #    the Player in additional scripts, so it is added in Character.
  #--------------------------------------------------------------------------
  alias ice_initialize initialize unless $@
  def initialize
    # Default Values for Player
    if self.is_a?(Game_Player)
      # Speed at which this Character will accelerate on Ice
      @ice_speed = 0
      # Add New Property for Ice before Refresh so Player will slide on Ice
      @ice = true
      @ice_need_tag_update = true
      @ice_last_tag = []       
    end
    # Call Original or other Aliases
    ice_initialize
  end
  #--------------------------------------------------------------------------
  # * Ice= - Character - WRITER Method (for self. or outside the Class)
  #  - Used to change Two Properties to Force an Update of Terrain Tags
  #  - self.ice = true / false
  #  - game_map.events[@id].ice = true / false
  #--------------------------------------------------------------------------
  def ice=(value)
    @ice = value
    @ice_need_tag_update = true if @ice
  end
  #--------------------------------------------------------------------------
  # * Use Ice - Game_Character
  #  - use_ice                      : Move Route -> Script
  #  - game_map.events[@id].use_ice : Script (Any Script Entry)
  #  - $game_player.use_ice         : Script (Any Script Entry)
  #--------------------------------------------------------------------------
  def use_ice
    @ice = true
    @ice_need_tag_update = true
  end
  #--------------------------------------------------------------------------
  # * Clear Ice - Game_Character
  #  - clear_ice                      : Move Route -> Script
  #  - game_map.events[@id].clear_ice : Script (Any Script Entry)
  #  - game_player.clear_ice          : Script (Any Script Entry)
  #--------------------------------------------------------------------------
  def clear_ice
    @ice = false
    @ice_need_tag_update = true   
  end
  #--------------------------------------------------------------------------
  # * Update - Game_Character (Alias of Main Update Method)
  #  - Updates Characters Stored Ice Tags and Ice Movement
  #  - Monitors for Tile Event Changes that requires Rescanning Terrain Tags
  #--------------------------------------------------------------------------
  alias ice_update update unless $@
  def update
    # If Event has an Ice Tile
    if @tile_id > 0 and $game_map.terrain_tags[@tile_id] == ICE_TERRAIN_TAG
      # Set the Monitor Flag
      tile_monitor = true
      # Monitor Event Tiles for changes
      x = @x
      y = @y
      tile_id = @tile_id
      through = @through
    end
    # Updates Stored Terrain Tag if needed
    update_ice_tag
    # If Character is standing on Ice
    if on_ice?
      # Update Movement on Ice (checks for Passable)
      update_ice_movement
    # If Character has been accelerated due to Ice and needs to Decelerate
    elsif @ice_speed > ICE_SPEED_MIN
     # Update Deceleration for proper positioning (Passable already checked)
     update_ice_decel_move
    end
    # Call Original or other Aliases of Main Update Method for Character
    ice_update
    # If Monitored Event Tiles have a Change that warrants Expensive Update
    if tile_monitor and
       (tile_id != @tile_id or x != @x or y != @y or through != @through)
      # Set Map Flag to Update all Terrain Tags for Ice Characters
      $game_map.ice_tags_need_update = Graphics.frame_count + 1
    end
  end
  #--------------------------------------------------------------------------
  # * Update Ice Movement - Game_Character
  #  - Updates Characters with ice to Slide Downhill
  #  - Touch Triggers should work correctly
  #  - Allows "skipping" Open Spaces with continued movement
  #--------------------------------------------------------------------------
  def update_ice_movement
    # If Y Position is Greater Than or Equal To the Logical Coordinates
    if @y * 128 <= @real_y
      # If Moving Left or Right while on Ice
      if @real_x != @x * 128
        # If moving left
        if @x * 128 < @real_x
          # If Down is possible for Current and Previous Location
          if passable?(@x, @y, 2) and
             passable?(@x + 1, @y, 2)
            # Increase Character Y Position in method for other Checks
            ice_increase_y
            # Determine if touch here event is triggered by Player
            check_event_trigger_here([1,2]) if self.is_a?(Game_Player)
            # Determine if touch event is triggered
            check_event_trigger_touch(@x, @y + 1)
            check_event_trigger_touch(@x + 1, @y + 1)
          else
            # Not Passable so Reset Ice Sliding Speed - Prevent Deceleration
            @ice_speed = ICE_SPEED_MIN
          end
        # If moving right
        elsif @x * 128 > @real_x
          # If Down is possible for Current and Previous Location
          if passable?(@x, @y, 2) and
             passable?(@x - 1, @y, 2)
            # Increase Character Y Position in method for other Checks
            ice_increase_y
            # Determine if touch here event is triggered by Player
            check_event_trigger_here([1,2]) if self.is_a?(Game_Player)
            # Determine if touch event is triggered
            check_event_trigger_touch(@x, @y + 1)
            check_event_trigger_touch(@x - 1, @y + 1)
          else
            # Not Passable so Reset Ice Sliding Speed - Prevent Deceleration
            @ice_speed = ICE_SPEED_MIN
          end
        end
      # Not Moving Left or Right - If the Tiles Below are Passable
      elsif passable?(@x, @y, 2)
        # Increase Character Y Position in method for other Checks
        ice_increase_y
        # Determine if touch here event is triggered by Player
        check_event_trigger_here([1,2]) if self.is_a?(Game_Player)
        # Determine if touch event is triggered
        check_event_trigger_touch(@x, @y + 1)
      else
        # Not Passable so Reset Ice Sliding Speed - Prevent Deceleration
        @ice_speed = ICE_SPEED_MIN
      end
    end
    # New Real Y determined by Ice Speed, Clamp to next Y value
    ice_accel_real_y(@ice_speed)
    # Accelerate Ice Speed - Clamp at Max Value from Config
    @ice_speed = [@ice_speed + ICE_SPEED_ACCEL, ICE_SPEED_MAX].min   
  end
  #--------------------------------------------------------------------------
  # * Ice Increase Y - Game_Character
  #  - Needed for other scripts to make other checks prior to incrementing
  #--------------------------------------------------------------------------
  def ice_increase_y
    @y += 1
  end
  #--------------------------------------------------------------------------
  # * Ice Accel Real Y - Game_Character
  #  - Needed for other scripts to make other checks prior to incrementing
  #--------------------------------------------------------------------------
  def ice_accel_real_y(ice_speed)
    # New Real Y determined by Ice Speed, Clamp to next Y value
    @real_y = [@real_y + ice_speed, @y * 128].min
  end
  #--------------------------------------------------------------------------
  # * Update Ice Decel Move - Game_Character
  #  - Handles Movement while Decelerating
  #  - Needed for other scripts to make other checks prior to incrementing
  #  - Causes Character to Decelerate quickly while not on ice until stop
  #  - Display Y Adjustement is needed to prevent a Glitch that causes
  #    the bottom of Sprites to get trapped on the screen, which is caused
  #    by the way this script handles Real Y positions conflicting with
  #    the Looping Maps script.  That code fixes the Glitch.
  #--------------------------------------------------------------------------
  def update_ice_decel_move
    # Subtract Deceleration Speed - Clamp to Minimum Speed and next Y value
    if @real_y + @ice_speed >= @y * 128
      # Reset Ice Speed to end Deceleration
      @ice_speed = ICE_SPEED_MIN
    # If Ice Speed Adjustment remains above Minimum Speed
    elsif @ice_speed - ICE_SPEED_DECEL > ICE_SPEED_MIN
      # Decelerate
      @ice_speed -= ICE_SPEED_DECEL
    end     
    # If a Real Y adjustment does not place Character on above Logical Tile Y
    if @real_y - 128 < @y * 128
      # New Real Y determined by Ice Speed, Clamp to next Y value
      ice_accel_real_y(@ice_speed)
    end
    # If Player Not Moving and Display needs an Adjustment
    if @check_ice_map_display and @y * 128 == @real_y and
       $game_map.display_y % 128 != 0 and not $game_map.scrolling?
      # Determine Adjustment for proper Display
      off_y = ($game_map.display_y % 128 - 128).abs
      # Fix the Map Display Y
      $game_map.display_y += off_y
      # Clear the Fix Variable
      @check_ice_map_display = nil
    end
  end 
  # If Heretic's Loop Maps is installed
  if Game_Map.method_defined?(:map_loop_passable?)
    #------------------------------------------------------------------------
    # * Ice Accel Real Y - Game_Character
    #  - Needed for other scripts to make other checks prior to incrementing
    #------------------------------------------------------------------------
    alias loop_map_update_ice_movement update_ice_movement unless $@
    def update_ice_movement
      # Store Last Real Y for Map Scrolling Adjustment
      last_real_y = @real_y
      # Call Original
      loop_map_update_ice_movement
      # Check for Loop
      if $game_map.loop_vertical?
        # If Player is Out of Range
        if self.is_a?(Game_Player) and @real_y >= $game_map.height * 128
          # Store the Adjustment
          @check_ice_map_display = true
          # Adjust Player, Display, Panorama and Fogs
          correct_loop_down(last_real_y - @real_y)
        # If Event is Out of Range
        elsif @real_y > $game_map.height * 128
          # Adjust for Map Loop
          @y %= $game_map.height
          @real_y %= $game_map.height * 128
        end
      end
    end
  end # End Loop Map Definitions
  #--------------------------------------------------------------------------
  # * Moving? - Game_Character
  #--------------------------------------------------------------------------
  alias ice_moving? moving? unless $@
  def moving?
    # If Character is on an Ice Tile
    return (@real_x != @x * 128) if on_ice?
    # Call Original or other Aliases
    ice_moving?
  end
  #--------------------------------------------------------------------------
  # * Ice Move Up - Game_Character
  #  - Prevents Up Movement on Downhill Ice
  #  - When walking Up to an Ice Tile, has a neat effect of a Bounce
  #     turn_enabled : a flag permits direction change on that spot
  #--------------------------------------------------------------------------
  alias ice_move_up move_up unless $@
  def move_up(turn_enabled = true)
    # If Character is standing on an Ice Tile
    if on_ice?
      # Turn down
      if turn_enabled
        turn_up
      end
      # If move animation is ON and Step Animation is OFF
      if self == $game_player and @walk_anime and not @step_anime
        # Increase animation count by 1.5
        @anime_count += 1.5
        # Reset the Stop Count to allow for Step Animation
        @stop_count = -1
      end     
      # Prevent Movement Updating
      return
    end
    # Call Original or other Aliases
    ice_move_up(turn_enabled)
  end   
  #--------------------------------------------------------------------------
  # * Move Down - Game_Character
  #  - Prevents Down Movement on Downhill Ice since Character is moving
  #    anyway which results in Characters just shuffling their feet
  #     turn_enabled : a flag permits direction change on that spot 
  #--------------------------------------------------------------------------
  alias ice_move_down move_down unless $@
  def move_down(turn_enabled = true)
    # If Character is standing on an Ice Tile
    if on_ice?
      # Turn down
      if turn_enabled
        turn_down
      end
      # If move animation is ON and Step Animation is OFF
      if self == $game_player and @walk_anime and not @step_anime
        # Increase animation count by 1.5
        @anime_count += 1.5
        # Reset the Stop Count to allow for Step Animation
        @stop_count = -1
      end
      # Prevent Movement Updating
      return
    end
    # Call Original or other Aliases
    ice_move_down(turn_enabled)
  end
  #--------------------------------------------------------------------------
  # * Ice Move Conditions? - Game_Character
  #  - If Conditions to Not Animate while on Ice
  #  - Needed by another Script to Alias for Caterpillar
  #--------------------------------------------------------------------------
  def ice_no_anime_conditions?
    # Default is just if a Character is On Ice
    return true if on_ice?
  end
  #--------------------------------------------------------------------------
  # * Ice Update Move - Game_Character
  #  - Prevents 2 Adjustments to @real_y while Accelerating on Ice
  #  - Prevents Walk Animations while Sliding
  #--------------------------------------------------------------------------
  alias ice_update_move update_move unless $@
  def update_move
    # If Character is standing On Ice
    if ice_no_anime_conditions?
      # True if Left Right Movement is occuring
      lr_move = @x * 128 != @real_x
      # Characters should NOT Animate while Sliding on Ice despite moving
      if @walk_anime and not @step_anime and not lr_move and
         @ice_last_tag[0] == ICE_TERRAIN_TAG
        # Reset the Animation Counter
        @anime_count = 0
        # Return to original pattern
        @pattern = @original_pattern
      end
    end
    # Call Original or other Aliases to Update Movement
    ice_update_move
  end     
  #--------------------------------------------------------------------------
  # * Ice Allowed? - Game_Character
  #  - Checks System Options, Comment Configurations and DEBUG for Player
  #--------------------------------------------------------------------------
  def ice_allowed?
    return (@ice and $game_system.enable_ice and !jumping? and !ice_debug?)
  end
  #--------------------------------------------------------------------------
  # * On Ice? - Game_Character
  #  - Returns True if a Characters Feet appear to be touching Ice
  #  - Checks Stored Terrain Tag for performance due to Event Scanning
  #--------------------------------------------------------------------------
  def on_ice?
    # If Ice Movement allowed for Character
    return false unless ice_allowed?
    # Check the stored Terrain Tag instead of rescanning for it
    return (@ice_last_tag[0] == ICE_TERRAIN_TAG)
  end
  #--------------------------------------------------------------------------
  # * Need Ice Tag Update? - Game_Character
  #  - If this Character has been changed or Event Tiles changed
  #  - Monitors for changes to Through on the Event with the Tile
  #--------------------------------------------------------------------------
  def ice_tag_need_update?
    # If Character has Ice Movement and Changed or Event Tile changed
    if @ice and (@ice_need_tag_update or $game_map.ice_tags_need_update? or
       (@ice_last_tag[3] and $game_map.events[@ice_last_tag[3]].through))
      # True to indicate an Update to the Stored Terrain Tag is needed
      return true
    end
  end
  #--------------------------------------------------------------------------
  # * Update Ice Tag - Game_Character
  #  - Stores Terrain Tags and Position to prevent Event Scanning
  #  - Updates when Characters Feet are Mid Tile, not half a tile away
  #  - Mid Tile for Horzontal is determined at 50%, Y uses an Offset
  #  - Uses Constant ICE_TILE_Y_OFFSET to define a Mid Tile point for
  #    vertical movement.  Characters Feet are close to the bottom of
  #    tiles, so when moving, this only updates the Terrain Tag when
  #    the Characters Feet are touching the New Tile.
  #--------------------------------------------------------------------------
  def update_ice_tag
    # Calculate X Map Position to check
    x = (@real_x / 128.0).round
    # Calculate Real Coordinate from Logial Position
    logical_real_y = @y * 128
    # Calculate Remainder for Y offset
    r = @real_y - logical_real_y + (logical_real_y > @real_y ? 128 : 0)
    # Determine Vertical Direction
    d = (logical_real_y < @real_y ? 8 : logical_real_y > @real_y ? 2 : 0)
    # Vertical Tile Offset for Real Y Position
    off = ICE_TILE_Y_OFFSET
    # Calculate Y Map Position to check based on Offset and Position on Tile
    y = ((d == 8 and r > off) ? 1 : (d == 2 and r < off) ? -1 : 0) + @y
    # If Stored Coordinates dont match calculated Coordinates
    if x != @ice_last_tag[1] or y != @ice_last_tag[2] or ice_tag_need_update?
      # Clear the Update Needed Flag
      @ice_need_tag_update = false
      # Store New Coordinates of where the stored Terrain Tag was checked
      @ice_last_tag[1] = x
      @ice_last_tag[2] = y
      # Store any Event Tiles with Terrain Tags (when Option Enabled)
      return if update_ice_tag_event_tiles(x, y)
      # No Event Tiles found so store Map Terrain Tag
      @ice_last_tag[0] = $game_map.terrain_tag(x, y)
      # Clear any Stored Event IDs since only a Tile is used for Terrain Tag
      @ice_last_tag[3] = nil
    end
  end
  #--------------------------------------------------------------------------
  # * Update Ice Tag Event Tiles - Game_Character
  #     x : x-coordinate
  #     y : y-coordinate
  #  - This will Store any Terrain Tags found in Events with Tile Graphics
  #  - Allows Events to be used for Ice Terrain Tags
  #  - NPCs can to move across Events with Ice Terrain Tags
  #  - Mappers can "cover up" Icy Terrain with Event Bridges which will
  #    act as a Terrain Tag Override so no Sliding occurs
  #--------------------------------------------------------------------------
  def update_ice_tag_event_tiles(x, y)
    # If Game System Ice Enabled and Option for Event Ice Tiles are on
    if @ice and not @no_event_ice and not @no_event_tiles and
       $game_system.enable_ice and $game_system.event_ice
      # Get List of Events at Map XY
      event_list = make_events_list(x, y)
      # Scan the smaller hash of Events
      for event in event_list
        # Check Through, Self and Coordinates
        if not event.through and self != event and event.tile_id > 0 and
           mp_match_coordinates?(x, y, event.x, event.y)
          # Store Terrain Tag
          @ice_last_tag[0] = $game_map.terrain_tags[event.tile_id]
          # Store Event ID
          @ice_last_tag[3] = event.id
          # Exit Event Tiles Loop because an Event with a Tile was found
          return true
        end
      end
    end
    # No Event Tiles that met conditions were found
    return false
  end
  #--------------------------------------------------------------------------
  # * Event Player Not Passable? - Game_Character
  #  - Checks for Events with Character Graphics trying to move to the
  #    current Location of the Game Player
  #  - Must return False or Nil to allow for Movement 
  #     x     : x-coordinate
  #     y     : y-coordinate
  #     d     : direction (0,2,4,6,8)
  #             * 0 = Determines if all directions are impassable (for jumping)
  #     new_x : Target X Coordinate
  #     new_y : Target Y Coordinate
  #     result : true or false passed as an arg by Aliases   
  #--------------------------------------------------------------------------
  alias ice_event_player_not_passable? event_player_not_passable? unless $@
  def event_player_not_passable?(x, y, d, new_x, new_y, result = nil)
    # If this Event has a Flag to prohibit moving to Player (for Event Tiles)
    if result.nil? and @no_player_pass and
       new_x == $game_player.x and new_y == $game_player.y
      # Impassable - This Event with Flag trying to move to Players Location
      result = true
    end
    # Call Original or other Alias
    ice_event_player_not_passable?(x, y, d, new_x, new_y, result)
  end
  #--------------------------------------------------------------------------
  # * Ice Event Not Passable? - Game_Character
  #  - This allows NPCs to move across Events with Ice Terrain Tag Tiles
  #    which is normally not allowed for any Event unless that Event has
  #    a Through flag, then Collision is not determined at all
  #  - Tile Obstale Bits of the Tile now determines passage
  #     x      : x-coordinate
  #     y      : y-coordinate
  #     d      : direction (0,2,4,6,8)
  #             * 0 = Determines if all directions are impassable (for jumping)
  #     new_x  : Target X Coordinate
  #     new_y  : Target Y Coordinate
  #     event  : Event being checked against in iteration loop
  #     result : results of other Aliases passed as an argument 
  #--------------------------------------------------------------------------
  alias ice_event_not_passable? event_not_passable? unless $@
  def event_not_passable?(x, y, d, new_x, new_y, event, result = nil)
    # If this is an Event and is not the Player
    if self != $game_player
      # Impassable - There is a Flag that prohibits movement on Event Tile
      return true if @no_event_tiles
    end   
    # If target Event has a Tile with an Ice Terain Tag
    if result.nil? and $game_system.event_ice and event.tile_id > 0 and
      $game_map.terrain_tags[event.tile_id] == ICE_TERRAIN_TAG and
      @character_name != "" and not @no_event_ice
      # Change direction (0,2,4,6,8,10) to obstacle bit (0,1,2,4,8,0)
      bit = (1 << (d / 2 - 1)) & 0x0f
      # If obstacle bit is not set
      unless $game_map.passages[tile_id] & bit != 0 or
             $game_map.passages[tile_id] & 0x0f == 0x0f
        # Passable - Conditions Met to allow Passage so false to Impassable
        result = false
      end
    end
    # Call Original or other Aliases   
    ice_event_not_passable?(x, y, d, new_x, new_y, event, result)
  end
  #--------------------------------------------------------------------------
  # * Ice Debug - Game_Character
  #  - Useful during development
  #  - Allows Player to have a Super Method which allows Debug over Ice
  #--------------------------------------------------------------------------
  def ice_debug?
    # Character Debug is not Player, so false, Characters dont Debug
    return false
  end 
end

#============================================================================
# ** Game_Map - Class
#============================================================================
class Game_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Game Map
  #--------------------------------------------------------------------------
  attr_accessor :ice_tags_need_update # Causes Events with Ice to Rescan Tags
  #--------------------------------------------------------------------------
  # * Initialize - Game Map
  #  - Adds new Property for Ice Riders to rescan Events
  #--------------------------------------------------------------------------
  alias ice_initialize initialize unless $@
  def initialize
    # Call Original or other Aliases
    ice_initialize
    # New Properties
    @ice_tags_need_update = 0
  end
  #--------------------------------------------------------------------------
  # * Frame Update - Game Map
  #--------------------------------------------------------------------------
  alias ice_update update unless $@
  def update
    # Call Original or other Aliases
    ice_update
    # Clear the Flag for All Characters to update Stored Terrain Tags
    @ice_tags_need_update = 0 if @ice_tags_need_update == Graphics.frame_count
    # If Update was Missed due to Battle, Save, or Scene Change
    if @ice_tags_need_update > 0 and
       @ice_tags_need_update < Graphics.frame_count
      # Do an expensive Update on all Ice Characters next frame
      @ice_tags_need_update = Graphics.frame_count + 1
    end
  end
  #--------------------------------------------------------------------------
  # * Ice Tags Need Update? - Game Map
  #  - If Ice Riders need to do an Expensive Rescan on this Frame Count
  #--------------------------------------------------------------------------
  def ice_tags_need_update?
    # If Need to Update this Frame
    return (@ice_tags_need_update == Graphics.frame_count)
  end 
end

#==============================================================================
# ** Interpreter - Class
#==============================================================================
class Interpreter
  #--------------------------------------------------------------------------
  # * Set Event Location - Interpreter (command_202)
  #  - Set Map Ice Tags Need Update if either Event has a Tile
  #--------------------------------------------------------------------------
  alias ice_command_202 command_202 unless $@
  def command_202
    # If in battle
    if $game_temp.in_battle
      # Continue
      return true
    end   
    # Get character
    character = get_character(@parameters[0])
    # If no character exists
    if character == nil
      # Continue
      return true
    end
    # Get character 2 (Exchange with Another Event)
    character2 = get_character(@parameters[2])
    # Check for Tiles of Characters for Map Ice Tags Need Update
    if character.tile_id > 0 or (character2 and character2.tile_id > 0)
      # Set Map Flag to Update all Terrain Tags for Ice Characters
      $game_map.ice_tags_need_update = Graphics.frame_count + 1
    end
    # Call Original or other Aliases (Set Event Location)
    ice_command_202
  end
end

#==============================================================================
# ** Game_Player - Class
#==============================================================================
class Game_Player < Game_Character
  #--------------------------------------------------------------------------
  # * Ice Debug - Game_Player
  #  - Useful during development
  #  - Allows Player to move normally over Ice
  #--------------------------------------------------------------------------
  def ice_debug?
    # Debug Movement for Player is Active   
    return true if $DEBUG and Input.press?(Input::CTRL)
    # Return Parent Method of same name for other checks during scripting
    return super
  end
end

#==============================================================================
# ** Game_Event - Class
#==============================================================================
class Game_Event < Game_Character
  #--------------------------------------------------------------------------
  # * Public Instance Variables - Game_Event
  #--------------------------------------------------------------------------
  attr_accessor  :no_event_tiles  # Prevents NPCs on Events with ANY Tiles
  attr_accessor  :no_player_pass  # Prevents Event Tiles from moving to Player
  #--------------------------------------------------------------------------
  # * Object Initialization - Game_Event
  #     map_id : map ID
  #     event  : event (RPG::Event)
  #  - Adds properties needed for Downhill Ice Movement
  #--------------------------------------------------------------------------
  alias ice_game_event_initialize initialize unless $@
  def initialize(map_id, event)
    # New Properties required for Initialization prior to Update or Refresh
    @ice = nil
    @ice_speed = 0
    @ice_last_tag = []
    # Call Original or other Aliases
    ice_game_event_initialize(map_id, event)
  end
  #--------------------------------------------------------------------------
  # * Refresh - Game_Event
  #  - Causes a Rescan of Event Tiles when this Events Tiles change
  #--------------------------------------------------------------------------
  alias ice_refresh refresh unless $@
  def refresh
    # Copy of Current Page
    page = @page
    # Copy of Current Tile
    tile_id = @tile_id
    # Call Original or other Aliases
    ice_refresh
    # If Event Not Erased and Page has changed
    unless @erased
      # If Page is not Nil (Page Conditions) and Page Change is occuring
      if @page != page and tile_id != @tile_id
        # Set Map Flag to Update all Terrain Tags for Ice Characters
        $game_map.ice_tags_need_update = Graphics.frame_count + 1
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Ice Reset Page Comment Config - Game_Event
  #  - Used to initialize New Values and Reset on Refresh
  #  - @ice_speed is only set when initialized
  #--------------------------------------------------------------------------
  alias ice_reset_page_comment_config reset_page_comment_config unless $@
  def reset_page_comment_config
    # Speed at which this Character will move on Ice
    @ice_speed = 0 if @ice.nil?
    @ice_need_tag_update = false if @ice.nil?
    # Stores Last Terrain Tag[0], X[1], and Y[2] where Terrain Tag was checked
    @ice_last_tag = [] if @ice.nil?
    # Resets the Ice Property (Note: set to false, not nil for @ice.nil?)
    @ice = false
    # Clears Flags that prohibit Events with Tiles from passing thru Player
    @no_player_pass = nil
    # Clear Character Flags that prohibit movement on Events with ANY Tiles
    @no_event_tiles = nil
    # Clear Flags that prohibit movement only on Events with Ice Tiles
    @no_event_ice = nil
    # Resets other Page Comment Configuration Variables here made by Aliases
    return ice_reset_page_comment_config
  end
  #--------------------------------------------------------------------------
  # * Ice Check Comment Page Config - Game_Event
  #     comment : the Comment to be checked to adjust Page Properties
  #     count   : integer of which List of Event Commands is checked
  #
  #   Note: When aliasing, please return the value of aliased methods for
  #         the local variable count to be altered as needed.
  #   return alias_check_page_comment_config(comment, count)
  #--------------------------------------------------------------------------
  alias ice_check_page_comment_config check_page_comment_config unless $@
  def check_page_comment_config(comment, count)
    # Checks for \ice Comments and Return if \ice is found (for Characters)
    comment.gsub(/^\\ice\z/i){@ice = true; return count}
    # Calls for Stored Terrain Tag to be Updated
    @ice_need_tag_update = true if @ice
    # Checks for \no_player_pass Comments and Return if found (for Terrain)
    comment.gsub(/^\\no_player_pass\z/i){@no_player_pass = true; return count}
    # Looks for "\no_event_tiles" in the Comments (Use on Character Events)
    comment.gsub(/^\\no_event_tiles\z/i){@no_event_tiles = true; return count}
    # Looks for "\no_event_ice" in the Comments (Use on Character Events)
    comment.gsub(/^\\no_event_ice\z/i){@no_event_ice = true; return count}
    # Return adjusted or unadjusted counter
    return ice_check_page_comment_config(comment, count)
  end 
end

#==============================================================================
# ** Scene_Load
#==============================================================================
class Scene_Load < Scene_File
  #--------------------------------------------------------------------------
  # * Read Save Data - Scene_Load
  #     file : file object for reading (opened)
  #  - This prevents Save Games from Crashing when script is newly installed
  #    due to checks against the properties corrected here
  #  - You'll still need to use a Script call to change $game_system Options
  #--------------------------------------------------------------------------
  alias ice_read_save_data read_save_data unless $@
  def read_save_data(file)
    # Call Original or other Aliases
    ice_read_save_data(file)
    # Check for fixing missing properties for the Player that cause Crashes
    if $game_player.ice_speed.nil?
      # Fix these Properties with Default Values
      $game_player.ice_speed = 0
    end
    # Prevents Corrupted Save Data when Event with Ice Tag deleted after Save
    $game_player.ice_last_tag = []   
    # Check EVERY Event on Map
    for event in $game_map.events.values
      # If properties not already set
      if event.ice_speed.nil?
        # Fix these Properties with Default Values
        event.ice_speed = 0
      end
      # Prevents Corrupted Save Data when Event w/ Ice Tag deleted after Save
      event.ice_last_tag = []
    end
  end
end

#============================================================================
#   ***  ---  Heretic's Caterpillar Compatability  ---  ***
#
#  Everything below here will be used with Heretic's Caterpillar 2.0+ to
#  make the Caterpillar Movements on Ice perform correctly.  It is NOT
#  required if you do not use Heretics Caterpillar.  It will not
#  work with Heretic's Caterpillar version 1.99.5 and below.
#============================================================================
if defined?(Game_Caterpillar) and
   Game_Character.method_defined?('cat_moves_list_other_passable?')
  #===========================================================================
  # ** Game_Caterpillar - Class
  #===========================================================================
  class Game_Caterpillar
    #-------------------------------------------------------------------------
    # * Public Instance Variables - Game_Caterpillar
    #-------------------------------------------------------------------------
    attr_accessor :move_list                # Stores each Cat Actors Movements
    #-------------------------------------------------------------------------
    # * Register Player Move - Game_Caterpillar - Alias
    #  - Records each of the Players Moves so the Caterpillar can follow
    #  - This Alias prevents Cat Actor Upward Movement on Downhill Ice
    #-------------------------------------------------------------------------
    alias ice_register_player_move register_player_move unless $@
    def register_player_move(move_speed, *args)
      # If Game System Ice Enabled and Option for Event Ice Tiles are on
      if $game_player.ice and $game_system.enable_ice and
         not $game_player.ice_debug?
        # If the Move Command is to Move Up, Up Left, or Up Right
        if ["move_up","move_upper_left","move_upper_right"].include?(args[0])
          # X and Y Coordinates from the Move to Register for Caterpillar
          x = args[2][0]
          y = args[2][1]
          # Get the Map Terrain Tag from the Move to Register X, Y
          tag = $game_map.terrain_tag(x, y)         
          # If Player will use Events with Terrain Tiles with Ice Tags
          if $game_system.event_ice
            # For each Event that uses a Graphic from the Tileset
            for event in $game_map.event_tiles.values
              # If Event Tile is at Coordinates of the Move to Register
              if not event.through and event.x == x and event.y == y
                # Get the Terrain Tag from the Tile and Replace Map Tag
                tag = $game_map.terrain_tags[event.tile_id]
                # Exit the For Loop
                break
              end
            end
          end
          # If the Move to Register is on Ice
          if tag == ICE_TERRAIN_TAG
            # Increase the Y Coordinate to prevent Actors moving Up on Ice
            args[2][1] += 1
            # Replace the Move Command with a Turn Command
            args[0] = "turn_up"
          end
        end
      end
      # Call the Original or other Aliases
      ice_register_player_move(move_speed, *args)
    end
    #-------------------------------------------------------------------------
    # * Update Actor Movement - Game_Caterpillar
    #  - Converts stored Move List Movement to a Move Route to Force
    #-------------------------------------------------------------------------
    alias ice_update_actor_movement update_actor_movement unless $@
    def update_actor_movement
      # For each Actor or Follower in the Caterpillar
      for i in 0...@actors.size
        # If there is a Command in @move_list to be executed
        if i < @move_list.size
          # Command for this Cat Actor / Follower Movement from @move_list
          command = @move_list[i]
          # Sets Actor to an Iteration of Actors in @actors
          actor = @actors[i]
          # Ice Property controlled by Registered Moves
          actor.ice = true
          # Cat Ice set by Player On Ice at this Location from Args
          cat_ice = command[1][2][2]  # [@x, @y, @ice_speed]
          # if Command is a Movement across Ice
          if cat_ice and not actor.cat_ice
            # Cat Actors and Follower Accelerate while this tag is True
            actor.cat_ice = true
            # Set the Ice Speed for the Cat Actor to MIN
            actor.cat_ice_speed = ICE_SPEED_MIN
          # Else Command is NOT a Movement across Ice and not on Ice
          elsif not cat_ice and actor.cat_ice and
                actor.ice_last_tag[0] != ICE_TERRAIN_TAG
            # Ice Property controlled by Registered Moves
            actor.ice = false
            # Clear Flag that allows Cat Actors and Followers to Accelerate
            actor.cat_ice = false
            # Clear the Cat Ice Speed
            actor.cat_ice_speed = nil
          end
        end
      end
      # Call the Original or other Aliases
      ice_update_actor_movement
    end 
  end
  #===========================================================================
  # ** Game_Character - Class
  #===========================================================================
  class Game_Character
    #-------------------------------------------------------------------------
    # * Cat Ice Allowed? - Game_Character - Alias
    #  - Prevents all Active Cat Actors and Followers from Ice Movement while
    #    in the Caterpillar.  Active Cat Actors and Followers need to have
    #    their Ice Movement handled in a completely different way than
    #    the way that other "standard ice" Characters are handled.
    #-------------------------------------------------------------------------
    alias cat_ice_allowed? ice_allowed? unless $@
    def ice_allowed?
      # Call Original or other Aliases
      original_result = cat_ice_allowed?
      # If Ice NPC is a Cat Actor or Follower
      if original_result and (@caterpillar_actor or @cat_follower)
        # Prevent Cat Actors and Followers from Ice Movement in Caterpillar
        unless $game_switches[Game_Caterpillar::CATERPILLAR_PAUSE_SWITCH] or
           not $game_switches[Game_Caterpillar::CATERPILLAR_ACTIVE_SWITCH] or
           not $game_system.caterpillar.actors.include?(self)
          # Do Not Allow on Ice (bypassed elsewhere to handle differently)
          return false
        end
      end
      # Return Original or Alias Result
      return original_result
    end   
    #-------------------------------------------------------------------------
    # * Ice Move Conditions? - Game_Character - Alias
    #  - If Conditions to Not Animate while on Ice
    #  - Needed by another Script to Alias for Caterpillar
    #-------------------------------------------------------------------------
    alias cat_ice_no_anime_conditions? ice_no_anime_conditions? unless $@
    def ice_no_anime_conditions?
      if @cat_ice and $game_system.enable_ice and
         @ice_last_tag[0] == ICE_TERRAIN_TAG
        # This Cat Actor / Follower is Sliding and should not Animate
        return true
      end
      # Call Original or other Aliases
      cat_ice_no_anime_conditions?
    end
  end
  #===========================================================================
  # ** Game_Player - Class
  #===========================================================================
  class Game_Player
    #-------------------------------------------------------------------------
    # * Ice Increase Y - Game_Player
    #  - When Sliding Down on Ice, Registers as a Caterpillar Movement
    #-------------------------------------------------------------------------
    def ice_increase_y
      # Call Method in Parent Class
      super
      # Shorthand - "G"ame_"S"ystem."C"aterpillar
      gsc = $game_system.caterpillar
      # Register the Sliding Ice Downhill Movement as a Caterpillar Movement
      gsc.register_player_move(@move_speed, 'move_down', [], [@x, @y, :ice])
      # Force the Caterpillar Actors to Move without Input Commands
      gsc.update_actor_movement
    end
  end
  #===========================================================================
  # ** Game_Event - Class
  #===========================================================================
  class Game_Event < Game_Character
    #-------------------------------------------------------------------------
    # * Public Instance Variables - Game_Event
    #-------------------------------------------------------------------------
    attr_accessor :cat_ice          # Allows Caterpillar to accelerate on Ice
    attr_accessor :cat_ice_speed    # Speed of Movement while on Downhill Ice
    #-------------------------------------------------------------------------
    # * Cat Need Ice Tag Update? - Game_Event
    #  - Allows this Event to be treated as a Cat Actor on Downhill Ice
    #-------------------------------------------------------------------------
    def cat_ice_valid?
      # If the following Conditions are met for Cat Actor Ice Movement
      if @cat_ice and (@caterpillar_actor or @cat_follower) and
         $game_player.ice and not $game_player.ice_debug? and
         $game_switches[Game_Caterpillar::CATERPILLAR_ACTIVE_SWITCH] and
         not $game_switches[Game_Caterpillar::CATERPILLAR_PAUSE_SWITCH] and
         $game_system.enable_ice and @ice_last_tag[0] == ICE_TERRAIN_TAG         
         $game_system.caterpillar.actors.include?(self) and not jumping?
        # Valid Cat Actor or Follower on Ice
        return true
      end
    end
    #-------------------------------------------------------------------------
    # * Cat Need Ice Tag Update? - Game_Event
    #  - Updates Cat Actors even if they dont slide on Ice the same as others
    #-------------------------------------------------------------------------
    alias cat_ice_tag_need_update? ice_tag_need_update? unless $@
    def ice_tag_need_update?
      # If this Event is a Cat Actor and is Valid for Ice Movement
      if cat_ice_valid?
        # If Player has Ice Movement and Changed or Event Tile changed
        if (@ice_need_tag_update or $game_map.ice_tags_need_update? or
           (@ice_last_tag[3] and $game_map.events[@ice_last_tag[3]].through))
          # True to indicate an Update to the Stored Terrain Tag is needed
          return true
        end
      end
      # Call Original or other Aliases
      cat_ice_tag_need_update?
    end   
    #-------------------------------------------------------------------------
    # * Cat Need Ice Tag Update? - Game_Event
    #  - Updates Cat Actors even if they dont slide on Ice the same as others
    #-------------------------------------------------------------------------
    alias cat_ice_update update unless $@
    def update
      # Call Original or other Aliases of Event Update
      cat_ice_update
      # If Valid for this Cat Actor to have Ice Movement
      if cat_ice_valid?
        # Clamp Maximum Real Y is next Map Coordinate
        @real_y = [@real_y + @cat_ice_speed, @y * 128].min
        # Check if Real Y is Out of Range
        if @real_y > $game_map.height * 128
          # Correct Y and Real Y for Map Coordinates
          @y %= $game_map.height
          @real_y %= $game_map.height * 128
        end
        # If this Cat Actor or Follower is Moving Vertically
        if @real_y != (@real_y / 128.0).ceil * 128 or $game_player.moving?
          # Accelerate Ice Speed - Clamp at Max Value
          @cat_ice_speed = [@cat_ice_speed + ICE_SPEED_ACCEL,ICE_SPEED_MAX].min
        # Else if Player Not Moving? and need to Decelerate
        elsif not $game_player.moving?
          # Decelerate Ice Speed to Minimum
          @cat_ice_speed = [@cat_ice_speed - ICE_SPEED_DECEL,ICE_SPEED_MIN].max
        end
      end
    end   
  end
end # End of Optional Heretic's Caterpillar Classes



Instructions

Edit your Tileset and assign a Tile or Autotile a Terrain Tag of 1, then use these Tiles to cause your Characters to slide!

For Events:

Add a Comment:
\ice

Events with \ice will be able to also slide downhill!


Compatibility

No known fatal issues.

Don't try to Pathfind over Downhill Ice.


Credits and Thanks


  • I'd like to thank three very important people in my life, me, myself, and I!




Author's Notes

Downhill Ice is a very good tool for creating a logical one way movement.  More importantly, it can be used to create Platforming types of Puzzles for your Players.  Everything else is spelled out in the Demo.
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.)