#==============================================================================
# ** Game_Map
#------------------------------------------------------------------------------
# This class handles the map. It includes scrolling and passable determining
# functions. Refer to "$game_map" for the instance of this class.
#==============================================================================
class Game_Map
#--------------------------------------------------------------------------
# * Public Instance Variables
#
# Event Hashes (events_at_x and events_at_y) are updated by Event Methods
#--------------------------------------------------------------------------
attr_accessor :events_at_x # Has of All Events sorted by X
attr_accessor :events_at_y # Has of All Events sorted by Y
#--------------------------------------------------------------------------
# * Setup
# map_id : map ID
#--------------------------------------------------------------------------
def setup(map_id)
# Put map ID in @map_id memory
@map_id = map_id
# Load map from file and set @map
@map = load_data(sprintf("Data/Map%03d.rxdata", @map_id))
# set tile set information in opening instance variables
tileset = $data_tilesets[@map.tileset_id]
@tileset_name = tileset.tileset_name
@autotile_names = tileset.autotile_names
@panorama_name = tileset.panorama_name
@panorama_hue = tileset.panorama_hue
@fog_name = tileset.fog_name
@fog_hue = tileset.fog_hue
@fog_opacity = tileset.fog_opacity
@fog_blend_type = tileset.fog_blend_type
@fog_zoom = tileset.fog_zoom
@fog_sx = tileset.fog_sx
@fog_sy = tileset.fog_sy
@battleback_name = tileset.battleback_name
@passages = tileset.passages
@priorities = tileset.priorities
@terrain_tags = tileset.terrain_tags
# Initialize displayed coordinates
@display_x = 0
@display_y = 0
# Clear refresh request flag
@need_refresh = false
# Set map event data
@events = {}
# Hashes to hold coordinates, Default Hash for each Coordinate Value
@events_at_x = Hash.new { |hash, key| hash[key] = {} }
@events_at_y = Hash.new { |hash, key| hash[key] = {} }
for i in @map.events.keys
# Create Event
event = Game_Event.new(@map_id, @map.events[i])
# Add to Events Hash
@events[i] = event
# Events indexed by X coordinates as Key, then Id as Key in Sub Hash
@events_at_x[@events[i].x][event.id] = event
# Events indexed by Y coordinates as Key, then Id as Key in Sub Hash
@events_at_y[@events[i].y][event.id] = event
# Update Map Coordinates for Event
@events[i].map_stored_x = @events[i].x
@events[i].map_stored_y = @events[i].y
end
# Set common event data
@common_events = {}
for i in 1...$data_common_events.size
@common_events[i] = Game_CommonEvent.new(i)
end
# Initialize all fog information
@fog_ox = 0
@fog_oy = 0
@fog_tone = Tone.new(0, 0, 0, 0)
@fog_tone_target = Tone.new(0, 0, 0, 0)
@fog_tone_duration = 0
@fog_opacity_duration = 0
@fog_opacity_target = 0
# Initialize scroll information
@scroll_direction = 2
@scroll_rest = 0
@scroll_speed = 4
end
#--------------------------------------------------------------------------
# * Events At XY (x, y)
#
# http://stackoverflow.com/questions/5551168/performance-of-arrays-and-hashes-in-ruby
#
# This is designed as a replacement for iterating through every single
# event in a $game_map. Events exist in both the x and y hashes so to
# speed things up, the smaller hash is returned.
#
# This is much faster than doing an intersection of two arrays.
#
# Call by using $game_map.events_at_xy(x, y).values cuz keys (id's) are
# also returned.
#--------------------------------------------------------------------------
def events_at_xy(x, y)
# Event is in both Hashes, return the smaller one for speed
if @events_at_x[x].size > @events_at_y[y].size
# Y array is Smaller so return it for less iteration
return @events_at_y[y]
else
# X array is Smaller so return it for less iteration
return @events_at_x[x]
end
end
#--------------------------------------------------------------------------
# * Get Designated Position Event ID
# x : x-coordinate
# y : y-coordinate
#--------------------------------------------------------------------------
def check_event(x, y)
#for event in $game_map.events.values
for event in $game_map.events_at_xy(x, y).values
if event.x == x and event.y == y
return event.id
end
end
end
end
#==============================================================================
# ** Game_Event
#------------------------------------------------------------------------------
# This class deals with events. It handles functions including event page
# switching via condition determinants, and running parallel process events.
# It's used within the Game_Map class.
#==============================================================================
class Game_Event < Game_Character
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :map_stored_x # Position for @events_at_x
attr_accessor :map_stored_y # Position for @events_at_x
#--------------------------------------------------------------------------
# * Object Initialization
# map_id : map ID
# event : event (RPG::Event)
#--------------------------------------------------------------------------
alias events_at_xy_initialize initialize
def initialize(map_id, event)
# Call Original or other Alias
events_at_xy_initialize(map_id, event)
# New Properties
@map_stored_x = 0
@map_stored_y = 0
end
#--------------------------------------------------------------------------
# * Updates Events Location in Map Coordinates
#--------------------------------------------------------------------------
def update_map_x_hashes
# Delete Old Hash Key Value Pair
$game_map.events_at_x[@map_stored_x].delete(id)
# Push Id into current Hash
$game_map.events_at_x[@x][@id] = self
# Update Map Position
@map_stored_x = @x
end
#--------------------------------------------------------------------------
# * Updates Events Location in Map Coordinates
#--------------------------------------------------------------------------
def update_map_y_hashes
# Delete Old Hash Key Value Pair
$game_map.events_at_y[@map_stored_y].delete(@id)
# Push Id into current Hash
$game_map.events_at_y[@y][@id] = self
# Update Map Position
@map_stored_y = @y
end
#--------------------------------------------------------------------------
# * Frame Update for Event
#--------------------------------------------------------------------------
alias events_at_xy_update update
def update
# Update Map X Location if stored coordinates do not match
update_map_x_hashes if @x != @map_stored_x
# Update Map Y Location if stored coordinates do not match
update_map_y_hashes if @y != @map_stored_y
# Call Original or other Alias
events_at_xy_update
end
end
#==============================================================================
# ** Game_Character
#------------------------------------------------------------------------------
# This class deals with characters. It's used as a superclass for the
# Game_Player and Game_Event classes.
#==============================================================================
class Game_Character
#--------------------------------------------------------------------------
# * Determine if Passable - Redefinition
# x : x-coordinate
# y : y-coordinate
# d : direction (0,2,4,6,8)
# * 0 = Determines if all directions are impassable (for jumping)
#--------------------------------------------------------------------------
def passable?(x, y, d)
# Get new coordinates
new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
# If coordinates are outside of map
unless $game_map.valid?(new_x, new_y)
# impassable
return false
end
# If through is ON
if @through
# passable
return true
end
# If unable to leave first move tile in designated direction
unless $game_map.passable?(x, y, d, self)
# impassable
return false
end
# If unable to enter move tile in designated direction
unless $game_map.passable?(new_x, new_y, 10 - d)
# impassable
return false
end
# Loop all events
#for event in $game_map.events.values
for event in $game_map.events_at_xy(new_x, new_y).values
# If event coordinates are consistent with move destination
if event.x == new_x and event.y == new_y
# If through is OFF
unless event.through
# If self is event
if self != $game_player
# impassable
return false
end
# With self as the player and partner graphic as character
if event.character_name != ""
# impassable
return false
end
end
end
end
# If player coordinates are consistent with move destination
if $game_player.x == new_x and $game_player.y == new_y
# If through is OFF
unless $game_player.through
# If your own graphic is the character
if @character_name != ""
# impassable
return false
end
end
end
# passable
return true
end
end
#==============================================================================
# ** Game_Player
#------------------------------------------------------------------------------
# This class handles the player. Its functions include event starting
# determinants and map scrolling. Refer to "$game_player" for the one
# instance of this class.
#==============================================================================
class Game_Player < Game_Character
#--------------------------------------------------------------------------
# * Same Position Starting Determinant
#--------------------------------------------------------------------------
def check_event_trigger_here(triggers)
result = false
# If event is running
if $game_system.map_interpreter.running?
return result
end
# All event loops
#for event in $game_map.events.values
for event in $game_map.events_at_xy(@x, @y).values
# If event coordinates and triggers are consistent
if event.x == @x and event.y == @y and triggers.include?(event.trigger)
# If starting determinant is same position event (other than jumping)
if not event.jumping? and event.over_trigger?
event.start
result = true
end
end
end
return result
end
#--------------------------------------------------------------------------
# * Front Envent Starting Determinant
#--------------------------------------------------------------------------
def check_event_trigger_there(triggers)
result = false
# If event is running
if $game_system.map_interpreter.running?
return result
end
# Calculate front event coordinates
new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
# All event loops
#for event in $game_map.events.values
for event in $game_map.events_at_xy(new_x, new_y).values
# If event coordinates and triggers are consistent
if event.x == new_x and event.y == new_y and
triggers.include?(event.trigger)
# If starting determinant is front event (other than jumping)
if not event.jumping? and not event.over_trigger?
event.start
result = true
end
end
end
# If fitting event is not found
if result == false
# If front tile is a counter
if $game_map.counter?(new_x, new_y)
# Calculate 1 tile inside coordinates
new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
# All event loops
#for event in $game_map.events.values
for event in $game_map.events_at_xy(new_x, new_y).values
# If event coordinates and triggers are consistent
if event.x == new_x and event.y == new_y and
triggers.include?(event.trigger)
# If starting determinant is front event (other than jumping)
if not event.jumping? and not event.over_trigger?
event.start
result = true
end
end
end
end
end
return result
end
#--------------------------------------------------------------------------
# * Touch Event Starting Determinant
#--------------------------------------------------------------------------
def check_event_trigger_touch(x, y)
result = false
# If event is running
if $game_system.map_interpreter.running?
return result
end
# All event loops
#for event in $game_map.events.values
for event in $game_map.events_at_xy(x, y).values
# If event coordinates and triggers are consistent
if event.x == x and event.y == y and [1,2].include?(event.trigger)
# If starting determinant is front event (other than jumping)
if not event.jumping? and not event.over_trigger?
event.start
result = true
end
end
end
return result
end
end