mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-19 13:29:54 +00:00
557 lines
19 KiB
Ruby
557 lines
19 KiB
Ruby
#==============================================================================
|
||
# ** 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
|
||
Скажи, нужно ли блокирование света стенами (тени/окклюзия).
|