#=============================================================================
#
# 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