mkxp-sunshine/scripts/Game_Map.rb
2026-06-26 22:33:18 +04:00

557 lines
19 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#==============================================================================
# ** 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
#--------------------------------------------------------------------------
attr_accessor :tileset_name # tileset file name
attr_accessor :autotile_names # autotile file name
attr_accessor :panorama_name # panorama file name
attr_accessor :panorama_hue # panorama hue
attr_accessor :fog_name # fog file name
attr_accessor :fog_hue # fog hue
attr_accessor :fog_opacity # fog opacity level
attr_accessor :fog_blend_type # fog blending method
attr_accessor :fog_zoom # fog zoom rate
attr_accessor :fog_sx # fog sx
attr_accessor :fog_sy # fog sy
attr_accessor :battleback_name # battleback file name
attr_accessor :display_x # display x-coordinate * 128
attr_accessor :display_y # display y-coordinate * 128
attr_accessor :wrap_x # display x-coordinate * 128 for wrap
attr_accessor :wrap_y # display y-coordinate * 128 for wrap
attr_accessor :need_refresh # refresh request flag
attr_accessor :bg_name # bg file name
attr_accessor :particles_type # particles name
attr_accessor :clamped_x # panorama is horizontally clamped?
attr_accessor :clamped_y # panorama is vertically clamped?
attr_accessor :always_moving # panorama is always moving
attr_accessor :pan_move_offset # panorama moving offset
attr_accessor :pan_onetoone # panorama is 1:1
attr_accessor :pan_animate # panorama is animated
attr_accessor :pan_fade_animate # panorama is fade animated
attr_accessor :pan_zoom # panorama zoom
attr_accessor :wrapping # map is wrapping?
attr_accessor :pan_offset_y # offset of y-coord of panorama
attr_accessor :ambient # ambient light
attr_reader :passages # passage table
attr_reader :priorities # prioroty table
attr_reader :terrain_tags # terrain tag table
attr_reader :events # events
attr_reader :fog_ox # fog x-coordinate starting point
attr_reader :fog_oy # fog y-coordinate starting point
attr_reader :fog_tone # fog color tone
#--------------------------------------------------------------------------
# * List of clamped panorama images
#--------------------------------------------------------------------------
CLAMPED = [
'red',
'red_distort',
'codebg'
]
CLAMPED_X = [
]
CLAMPED_Y = [
'red_obsdesk',
]
ANIMATED = [
'blue_water',
]
FADE_ANIMATION_PANORAMA = []
ONETOONE = [
'blue_water',
'green_water',
'dark_water',
]
NOZOOM = [
'dark_water',
'green_water',
]
ALWAYS_MOVING = [
'codebg'
]
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
@map_id = 0
@display_x = 0
@display_y = 0
end
#--------------------------------------------------------------------------
# * Setup
# map_id : map ID
#--------------------------------------------------------------------------
def setup(map_id)
# Put map ID in @map_id memory
@map_id = map_id
puts 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]
if @map.tileset_id > 0
$game_temp.footstep_sfx = FOOTSTEP_SFX[@map.tileset_id - 1]
else
$game_temp.footstep_sfx = nil
end
@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
@wrap_x = 0
@wrap_y = 0
# Clear refresh request flag
@need_refresh = false
# Set map event data
@events = {}
for i in @map.events.keys
@events[i] = Game_Event.new(@map_id, @map.events[i])
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
# Clear BG
@bg_name = ""
# Clear particles
@particles_type = nil
# Unclamp panorama
if CLAMPED.include? @panorama_name
@clamped_x = true
@clamped_y = true
elsif CLAMPED_X.include? @panorama_name
@clamped_x = true
@clamped_y = false
elsif CLAMPED_Y.include? @panorama_name
@clamped_x = false
@clamped_y = true
else
@clamped_x = false
@clamped_y = false
end
@always_moving = ALWAYS_MOVING.include? @panorama_name
@pan_move_offset = 0
# Animated/One-to-one/zoom
@pan_animate = ANIMATED.include? @panorama_name
@pan_fade_animate = FADE_ANIMATION_PANORAMA.include? @panorama_name
@pan_onetoone = ONETOONE.include? @panorama_name
@pan_zoom = NOZOOM.include?(@panorama_name) ? 1 : 2
# Unwrap map
@wrapping = false
@pan_offset_y = 0
# Full bright ambient light
@ambient = Tone.new(0, 0, 0, 0)
# Construct map name path
mapinfo = load_data("Data/MapInfos.rxdata")
@map_name = ""
i = @map_id
begin
@map_name.insert(0, "/" + mapinfo[i].name)
i = mapinfo[i].parent_id
end while i > 0
end
#--------------------------------------------------------------------------
# * Get Map ID
#--------------------------------------------------------------------------
def map_id
return @map_id
end
#--------------------------------------------------------------------------
# * Get Map Name
#--------------------------------------------------------------------------
def map_name
return @map_name
end
#--------------------------------------------------------------------------
# * Get Width
#--------------------------------------------------------------------------
def width
return @map.width
end
#--------------------------------------------------------------------------
# * Get Height
#--------------------------------------------------------------------------
def height
return @map.height
end
#--------------------------------------------------------------------------
# * Get Encounter List
#--------------------------------------------------------------------------
def encounter_list
return @map.encounter_list
end
#--------------------------------------------------------------------------
# * Get Encounter Steps
#--------------------------------------------------------------------------
def encounter_step
return @map.encounter_step
end
#--------------------------------------------------------------------------
# * Get Map Data
#--------------------------------------------------------------------------
def data
return @map.data
end
#--------------------------------------------------------------------------
# * Automatically Change Background Music and Backround Sound
#--------------------------------------------------------------------------
def autoplay
if @map.autoplay_bgm
$game_system.bgm_play(@map.bgm)
end
if @map.autoplay_bgs
$game_system.bgs_play(@map.bgs)
end
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
# If map ID is effective
if @map_id > 0
# Refresh all map events
for event in @events.values
event.refresh
end
# Refresh all common events
for common_event in @common_events.values
common_event.refresh
end
end
# Clear refresh request flag
@need_refresh = false
end
#--------------------------------------------------------------------------
# * Scroll Down
# distance : scroll distance
#--------------------------------------------------------------------------
def scroll_down(distance)
if $game_switches[98] == true
if self.height < Graphics.height / 28
@display_y = self.height / 2
else
@display_y = [@display_y + distance, (self.height - Graphics.height / 28) * 128].min
end
else
@display_y += distance
end
end
#--------------------------------------------------------------------------
# * Scroll Left
# distance : scroll distance
#--------------------------------------------------------------------------
def scroll_left(distance)
if $game_switches[98] == true
@display_x = [@display_x - distance, 0].max
else
@display_x -= distance
end
end
#--------------------------------------------------------------------------
# * Scroll Right
# distance : scroll distance
#--------------------------------------------------------------------------
def scroll_right(distance)
if $game_switches[98] == true
@display_x = [@display_x + distance, (self.width - (Graphics.width / 32)) * 128].min
else
@display_x += distance
end
end
#--------------------------------------------------------------------------
# * Scroll Up
# distance : scroll distance
#--------------------------------------------------------------------------
def scroll_up(distance)
if $game_switches[98] == true
if self.height < Graphics.height / 28
@display_y = self.height / 2
else
@display_y = [@display_y - distance, 0].max
end
else
@display_y -= distance
end
end
#--------------------------------------------------------------------------
# * Determine Valid Coordinates
# x : x-coordinate
# y : y-coordinate
#--------------------------------------------------------------------------
def valid?(x, y)
return true if @wrapping
return (x >= 0 and x < width and y >= 0 and y < height)
end
#--------------------------------------------------------------------------
# * Determine if Passable
# x : x-coordinate
# y : y-coordinate
# d : direction (0,2,4,6,8,10)
# * 0,10 = determine if all directions are impassable
# self_event : Self (If event is determined passable)
#--------------------------------------------------------------------------
def passable?(x, y, d, self_event = nil)
# If coordinates given are outside of the map
unless valid?(x, y)
# impassable
return false
end
x %= self.width
y %= self.height
# Change direction (0,2,4,6,8,10) to obstacle bit (0,1,2,4,8,0)
bit = (1 << (d / 2 - 1)) & 0x0f
# Loop in all events
for event in events.values
# If tiles other than self are consistent with coordinates
if event.tile_id >= 0 and event != self_event and
event.x == x and event.y == y and not event.through
# If blank tile
if event.tile_id == 0 && event.character_name.empty?
return false
# If obstacle bit is set
elsif @passages[event.tile_id] & bit != 0
# impassable
return false
# If obstacle bit is set in all directions
elsif @passages[event.tile_id] & 0x0f == 0x0f
# impassable
return false
# If priorities other than that are 0
elsif @priorities[event.tile_id] == 0
# passable
return true
end
end
end
# Loop searches in order from top of layer
blank = 0
[2, 1, 0].each do |i|
# Get tile ID
tile_id = data[x, y, i]
# Tile ID acquistion failure
next if tile_id == nil
# Only handle blank if all three layers are blank
if tile_id < 48 && i > 0
blank += 1
next if blank < 3
end
# If obstacle bit is set
if @passages[tile_id] & bit != 0
# impassable
return false
# If obstacle bit is set in all directions
elsif @passages[tile_id] & 0x0f == 0x0f
# impassable
return false
# If priorities other than that are 0
elsif @priorities[tile_id] == 0
# passable
return true
end
end
# passable
return true
end
#--------------------------------------------------------------------------
# * Determine Thicket
# x : x-coordinate
# y : y-coordinate
#--------------------------------------------------------------------------
def bush?(x, y)
if @map_id != 0
for i in [2, 1, 0]
tile_id = data[x, y, i]
if tile_id == nil
return false
elsif @passages[tile_id] & 0x40 == 0x40
return true
end
end
end
return false
end
#--------------------------------------------------------------------------
# * Determine Counter
# x : x-coordinate
# y : y-coordinate
#--------------------------------------------------------------------------
def counter?(x, y)
if @map_id != 0
for i in [2, 1, 0]
tile_id = data[x, y, i]
if tile_id == nil
return false
elsif @passages[tile_id] & 0x80 == 0x80
return true
end
end
end
return false
end
#--------------------------------------------------------------------------
# * Get Terrain Tag
# x : x-coordinate
# y : y-coordinate
#--------------------------------------------------------------------------
def terrain_tag(x, y)
if @map_id != 0
for i in [2, 1, 0]
tile_id = data[x, y, i]
if tile_id == nil
next #return 0
elsif @terrain_tags[tile_id] > 0
return @terrain_tags[tile_id]
end
end
end
return 0
end
#--------------------------------------------------------------------------
# * Get Designated Position Event ID
# x : x-coordinate
# y : y-coordinate
#--------------------------------------------------------------------------
def check_event(x, y)
for event in $game_map.events.values
if event.x == x and event.y == y
return event.id
end
end
end
#--------------------------------------------------------------------------
# * Start Scroll
# direction : scroll direction
# distance : scroll distance
# speed : scroll speed
#--------------------------------------------------------------------------
def start_scroll(direction, distance, speed)
@scroll_direction = direction
@scroll_rest = distance * 128
@scroll_speed = speed
end
#--------------------------------------------------------------------------
# * Determine if Scrolling
#--------------------------------------------------------------------------
def scrolling?
return @scroll_rest > 0
end
#--------------------------------------------------------------------------
# * Start Changing Fog Color Tone
# tone : color tone
# duration : time
#--------------------------------------------------------------------------
def start_fog_tone_change(tone, duration)
@fog_tone_target = tone.clone
@fog_tone_duration = duration
if @fog_tone_duration == 0
@fog_tone = @fog_tone_target.clone
end
end
#--------------------------------------------------------------------------
# * Start Changing Fog Opacity Level
# opacity : opacity level
# duration : time
#--------------------------------------------------------------------------
def start_fog_opacity_change(opacity, duration)
@fog_opacity_target = opacity * 1.0
@fog_opacity_duration = duration
if @fog_opacity_duration == 0
@fog_opacity = @fog_opacity_target
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Refresh map if necessary
if $game_map.need_refresh
refresh
end
# If scrolling
if @scroll_rest > 0
# Change from scroll speed to distance in map coordinates
distance = 2 ** @scroll_speed
# Execute scrolling
case @scroll_direction
when 2 # Down
scroll_down(distance)
when 4 # Left
scroll_left(distance)
when 6 # Right
scroll_right(distance)
when 8 # Up
scroll_up(distance)
end
# Subtract distance scrolled
@scroll_rest -= distance
end
# Update map event
for event in @events.values
event.update
end
# Update common event
for common_event in @common_events.values
common_event.update
end
# Manage fog scrolling
@fog_ox -= @fog_sx / 8.0
@fog_oy -= @fog_sy / 8.0
# Manage change in fog color tone
if @fog_tone_duration >= 1
d = @fog_tone_duration
target = @fog_tone_target
@fog_tone.red = (@fog_tone.red * (d - 1) + target.red) / d
@fog_tone.green = (@fog_tone.green * (d - 1) + target.green) / d
@fog_tone.blue = (@fog_tone.blue * (d - 1) + target.blue) / d
@fog_tone.gray = (@fog_tone.gray * (d - 1) + target.gray) / d
@fog_tone_duration -= 1
end
# Manage change in fog opacity level
if @fog_opacity_duration >= 1
d = @fog_opacity_duration
@fog_opacity = (@fog_opacity * (d - 1) + @fog_opacity_target) / d
@fog_opacity_duration -= 1
end
end
end
Скажи, нужно ли блокирование света стенами (тени/окклюзия).