mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
6.6 update
This commit is contained in:
547
Data/Scripts/004_Game classes/004_Game_Map.rb
Normal file
547
Data/Scripts/004_Game classes/004_Game_Map.rb
Normal file
@@ -0,0 +1,547 @@
|
||||
#==============================================================================
|
||||
# ** 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
|
||||
attr_accessor :map_id
|
||||
attr_accessor :tileset_name # tileset file name
|
||||
attr_accessor :autotile_names # autotile file name
|
||||
attr_reader :passages # passage table
|
||||
attr_reader :priorities # priority table
|
||||
attr_reader :terrain_tags # terrain tag table
|
||||
attr_reader :events # events
|
||||
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 :fog_ox # fog x-coordinate starting point
|
||||
attr_accessor :fog_oy # fog y-coordinate starting point
|
||||
|
||||
attr_accessor :fog2_ox # fog x-coordinate starting point
|
||||
attr_accessor :fog2_oy # fog y-coordinate starting point
|
||||
attr_accessor :fog2_sx # fog sx
|
||||
attr_accessor :fog2_sy # fog sy
|
||||
attr_accessor :fog2_opacity # fog sy
|
||||
|
||||
attr_reader :fog_tone # fog color tone
|
||||
attr_accessor :battleback_name # battleback file name
|
||||
attr_reader :display_x # display x-coordinate * 128
|
||||
attr_reader :display_y # display y-coordinate * 128
|
||||
attr_accessor :need_refresh # refresh request flag
|
||||
attr_accessor :scroll_direction
|
||||
|
||||
TILE_WIDTH = 32
|
||||
TILE_HEIGHT = 32
|
||||
X_SUBPIXELS = 4
|
||||
Y_SUBPIXELS = 4
|
||||
REAL_RES_X = TILE_WIDTH * X_SUBPIXELS
|
||||
REAL_RES_Y = TILE_HEIGHT * Y_SUBPIXELS
|
||||
|
||||
def initialize
|
||||
@map_id = 0
|
||||
@display_x = 0
|
||||
@display_y = 0
|
||||
end
|
||||
|
||||
def setup(map_id)
|
||||
@map_id = map_id
|
||||
@map = load_data(sprintf("Data/Map%03d.rxdata", map_id))
|
||||
tileset = $data_tilesets[@map.tileset_id]
|
||||
updateTileset
|
||||
@fog_ox = 0
|
||||
@fog_oy = 0
|
||||
|
||||
@fog2_ox = 0
|
||||
@fog2_oy = 0
|
||||
@fog2_sx = 0
|
||||
@fog2_sy = 0
|
||||
@fog2_opacity = 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
|
||||
self.display_x = 0
|
||||
self.display_y = 0
|
||||
@need_refresh = false
|
||||
Events.onMapCreate.trigger(self, map_id, @map, tileset)
|
||||
@events = {}
|
||||
for i in @map.events.keys
|
||||
@events[i] = Game_Event.new(@map_id, @map.events[i], self)
|
||||
end
|
||||
@common_events = {}
|
||||
for i in 1...$data_common_events.size
|
||||
@common_events[i] = Game_CommonEvent.new(i)
|
||||
end
|
||||
@scroll_direction = 2
|
||||
@scroll_rest = 0
|
||||
@scroll_speed = 4
|
||||
end
|
||||
|
||||
def updateTileset
|
||||
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
|
||||
end
|
||||
|
||||
def width
|
||||
return @map.width;
|
||||
end
|
||||
|
||||
def height
|
||||
return @map.height;
|
||||
end
|
||||
|
||||
def encounter_list
|
||||
return @map.encounter_list;
|
||||
end
|
||||
|
||||
def encounter_step
|
||||
return @map.encounter_step;
|
||||
end
|
||||
|
||||
def data
|
||||
return @map.data;
|
||||
end
|
||||
|
||||
def tileset_id;
|
||||
return @map.tileset_id;
|
||||
end
|
||||
|
||||
def name
|
||||
ret = pbGetMessage(MessageTypes::MapNames, @map_id)
|
||||
ret.gsub!(/\\PN/, $Trainer.name) if $Trainer
|
||||
return ret
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Autoplays background music
|
||||
# Plays music called "[normal BGM]_n" if it's night time and it exists
|
||||
#-----------------------------------------------------------------------------
|
||||
def autoplayAsCue
|
||||
if @map.autoplay_bgm
|
||||
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/" + @map.bgm.name + "_n")
|
||||
pbCueBGM(@map.bgm.name + "_n", 1.0, @map.bgm.volume, @map.bgm.pitch)
|
||||
else
|
||||
pbCueBGM(@map.bgm, 1.0)
|
||||
end
|
||||
end
|
||||
if @map.autoplay_bgs
|
||||
pbBGSPlay(@map.bgs)
|
||||
end
|
||||
end
|
||||
|
||||
def setFog2(filename,sx=0,sy=0,opacity=32)
|
||||
@fog2_sx=sx
|
||||
@fog2_sy=-sy
|
||||
@fog2_opacity = opacity
|
||||
$scene.spriteset.setFog2(filename)
|
||||
end
|
||||
|
||||
def eraseFog2()
|
||||
@fog2_sx=0
|
||||
@fog2_sy=-0
|
||||
@fog2_opacity = 0
|
||||
$scene.spriteset.disposeFog2()
|
||||
end
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# * Plays background music
|
||||
# Plays music called "[normal BGM]_n" if it's night time and it exists
|
||||
#-----------------------------------------------------------------------------
|
||||
def autoplay
|
||||
if @map.autoplay_bgm
|
||||
if PBDayNight.isNight? && FileTest.audio_exist?("Audio/BGM/" + @map.bgm.name + "_n")
|
||||
pbBGMPlay(@map.bgm.name + "_n", @map.bgm.volume, @map.bgm.pitch)
|
||||
else
|
||||
pbBGMPlay(@map.bgm)
|
||||
end
|
||||
end
|
||||
if @map.autoplay_bgs
|
||||
pbBGSPlay(@map.bgs)
|
||||
end
|
||||
end
|
||||
|
||||
def valid?(x, y)
|
||||
return x >= 0 && x < width && y >= 0 && y < height
|
||||
end
|
||||
|
||||
def validLax?(x, y)
|
||||
return x >= -10 && x <= width + 10 && y >= -10 && y <= height + 10
|
||||
end
|
||||
|
||||
def passable?(x, y, d, self_event = nil)
|
||||
return false if !valid?(x, y)
|
||||
bit = (1 << (d / 2 - 1)) & 0x0f
|
||||
for event in events.values
|
||||
next if event.tile_id <= 0
|
||||
next if event == self_event
|
||||
next if !event.at_coordinate?(x, y)
|
||||
next if event.through
|
||||
next if GameData::TerrainTag.try_get(@terrain_tags[event.tile_id]).ignore_passability
|
||||
passage = @passages[event.tile_id]
|
||||
return false if passage & bit != 0
|
||||
return false if passage & 0x0f == 0x0f
|
||||
return true if @priorities[event.tile_id] == 0
|
||||
end
|
||||
return playerPassable?(x, y, d, self_event) if self_event == $game_player
|
||||
# All other events
|
||||
newx = x
|
||||
newy = y
|
||||
case d
|
||||
when 1
|
||||
newx -= 1
|
||||
newy += 1
|
||||
when 2
|
||||
newy += 1
|
||||
when 3
|
||||
newx += 1
|
||||
newy += 1
|
||||
when 4
|
||||
newx -= 1
|
||||
when 6
|
||||
newx += 1
|
||||
when 7
|
||||
newx -= 1
|
||||
newy -= 1
|
||||
when 8
|
||||
newy -= 1
|
||||
when 9
|
||||
newx += 1
|
||||
newy -= 1
|
||||
end
|
||||
return false if !valid?(newx, newy)
|
||||
for i in [2, 1, 0]
|
||||
tile_id = data[x, y, i]
|
||||
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
|
||||
# If already on water, only allow movement to another water tile
|
||||
if self_event != nil && terrain.can_surf_freely
|
||||
for j in [2, 1, 0]
|
||||
facing_tile_id = data[newx, newy, j]
|
||||
return false if facing_tile_id == nil
|
||||
facing_terrain = GameData::TerrainTag.try_get(@terrain_tags[facing_tile_id])
|
||||
if facing_terrain.id != :None && !facing_terrain.ignore_passability
|
||||
return facing_terrain.can_surf_freely
|
||||
end
|
||||
end
|
||||
return false
|
||||
# Can't walk onto ice
|
||||
# removed for mahogany gym. idk if this will cause problems, hopefully not
|
||||
# elsif terrain.ice
|
||||
# return false
|
||||
elsif self_event != nil && self_event.x == x && self_event.y == y
|
||||
# Can't walk onto ledges
|
||||
for j in [2, 1, 0]
|
||||
facing_tile_id = data[newx, newy, j]
|
||||
return false if facing_tile_id == nil
|
||||
facing_terrain = GameData::TerrainTag.try_get(@terrain_tags[facing_tile_id])
|
||||
return false if facing_terrain.ledge
|
||||
break if facing_terrain.id != :None && !facing_terrain.ignore_passability
|
||||
end
|
||||
end
|
||||
# Regular passability checks
|
||||
if !terrain || !terrain.ignore_passability
|
||||
passage = @passages[tile_id]
|
||||
return false if passage & bit != 0 || passage & 0x0f == 0x0f
|
||||
return true if @priorities[tile_id] == 0
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def playerPassable?(x, y, d, self_event = nil)
|
||||
bit = (1 << (d / 2 - 1)) & 0x0f
|
||||
for i in [2, 1, 0]
|
||||
tile_id = data[x, y, i]
|
||||
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
|
||||
passage = @passages[tile_id]
|
||||
if terrain
|
||||
# Ignore bridge tiles if not on a bridge
|
||||
next if terrain.bridge && $PokemonGlobal.bridge == 0
|
||||
# Make water tiles passable if player is surfing
|
||||
return true if $PokemonGlobal.surfing && terrain.can_surf && !terrain.waterfall
|
||||
# Prevent cycling in really tall grass/on ice
|
||||
return false if $PokemonGlobal.bicycle && terrain.must_walk
|
||||
# Depend on passability of bridge tile if on bridge
|
||||
if terrain.bridge && $PokemonGlobal.bridge > 0
|
||||
return (passage & bit == 0 && passage & 0x0f != 0x0f)
|
||||
end
|
||||
end
|
||||
# Regular passability checks
|
||||
if !terrain || !terrain.ignore_passability
|
||||
return false if passage & bit != 0 || passage & 0x0f == 0x0f
|
||||
return true if @priorities[tile_id] == 0
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
# Returns whether the position x,y is fully passable (there is no blocking
|
||||
# event there, and the tile is fully passable in all directions)
|
||||
def passableStrict?(x, y, d, self_event = nil)
|
||||
return false if !valid?(x, y)
|
||||
for event in events.values
|
||||
next if event == self_event || event.tile_id < 0 || event.through
|
||||
next if !event.at_coordinate?(x, y)
|
||||
next if GameData::TerrainTag.try_get(@terrain_tags[event.tile_id]).ignore_passability
|
||||
return false if @passages[event.tile_id] & 0x0f != 0
|
||||
return true if @priorities[event.tile_id] == 0
|
||||
end
|
||||
for i in [2, 1, 0]
|
||||
tile_id = data[x, y, i]
|
||||
next if GameData::TerrainTag.try_get(@terrain_tags[tile_id]).ignore_passability
|
||||
return false if @passages[tile_id] & 0x0f != 0
|
||||
return true if @priorities[tile_id] == 0
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def bush?(x, y)
|
||||
for i in [2, 1, 0]
|
||||
tile_id = data[x, y, i]
|
||||
return false if GameData::TerrainTag.try_get(@terrain_tags[tile_id]).bridge &&
|
||||
$PokemonGlobal.bridge > 0
|
||||
return true if @passages[tile_id] & 0x40 == 0x40
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def deepBush?(x, y)
|
||||
for i in [2, 1, 0]
|
||||
tile_id = data[x, y, i]
|
||||
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
|
||||
return false if terrain.bridge && $PokemonGlobal.bridge > 0
|
||||
return true if terrain.deep_bush && @passages[tile_id] & 0x40 == 0x40
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def counter?(x, y)
|
||||
for i in [2, 1, 0]
|
||||
tile_id = data[x, y, i]
|
||||
passage = @passages[tile_id]
|
||||
return true if passage & 0x80 == 0x80
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def terrain_tag(x, y, countBridge = false)
|
||||
if valid?(x, y)
|
||||
for i in [2, 1, 0]
|
||||
tile_id = data[x, y, i]
|
||||
terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
|
||||
next if terrain.id == :None || terrain.ignore_passability
|
||||
next if !countBridge && terrain.bridge && $PokemonGlobal.bridge == 0
|
||||
return terrain
|
||||
end
|
||||
end
|
||||
return GameData::TerrainTag.get(:None)
|
||||
end
|
||||
|
||||
# Unused.
|
||||
def check_event(x, y)
|
||||
for event in self.events.values
|
||||
return event.id if event.at_coordinate?(x, y)
|
||||
end
|
||||
end
|
||||
|
||||
def event_at_position(x, y)
|
||||
for event in self.events.values
|
||||
return true if event.at_coordinate?(x, y)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def get_event_at_position(x, y, excluding_IDs = [])
|
||||
for event in self.events.values
|
||||
next if excluding_IDs.include?(event.id)
|
||||
return event if event.at_coordinate?(x, y)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def display_x=(value)
|
||||
return if @display_x == value
|
||||
@display_x = value
|
||||
if GameData::MapMetadata.exists?(self.map_id) && GameData::MapMetadata.get(self.map_id).snap_edges
|
||||
max_x = (self.width - Graphics.width * 1.0 / TILE_WIDTH) * REAL_RES_X
|
||||
@display_x = [0, [@display_x, max_x].min].max
|
||||
end
|
||||
$MapFactory.setMapsInRange if $MapFactory
|
||||
end
|
||||
|
||||
def display_y=(value)
|
||||
return if @display_y == value
|
||||
@display_y = value
|
||||
if GameData::MapMetadata.exists?(self.map_id) && GameData::MapMetadata.get(self.map_id).snap_edges
|
||||
max_y = (self.height - Graphics.height * 1.0 / TILE_HEIGHT) * REAL_RES_Y
|
||||
@display_y = [0, [@display_y, max_y].min].max
|
||||
end
|
||||
$MapFactory.setMapsInRange if $MapFactory
|
||||
end
|
||||
|
||||
def scroll_up(distance)
|
||||
self.display_y -= distance
|
||||
end
|
||||
|
||||
def scroll_down(distance)
|
||||
self.display_y += distance
|
||||
end
|
||||
|
||||
def scroll_left(distance)
|
||||
self.display_x -= distance
|
||||
end
|
||||
|
||||
def scroll_right(distance)
|
||||
self.display_x += distance
|
||||
end
|
||||
|
||||
def start_scroll(direction, distance, speed)
|
||||
@scroll_direction = direction
|
||||
if direction == 2 || direction == 8 # down or up
|
||||
@scroll_rest = distance * REAL_RES_Y
|
||||
else
|
||||
@scroll_rest = distance * REAL_RES_X
|
||||
end
|
||||
@scroll_speed = speed
|
||||
end
|
||||
|
||||
def scrolling?
|
||||
return @scroll_rest > 0
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
def refresh
|
||||
for event in @events.values
|
||||
event.refresh
|
||||
end
|
||||
for common_event in @common_events.values
|
||||
common_event.refresh
|
||||
end
|
||||
@need_refresh = false
|
||||
end
|
||||
|
||||
def update
|
||||
# refresh maps if necessary
|
||||
if $MapFactory
|
||||
for i in $MapFactory.maps
|
||||
i.refresh if i.need_refresh
|
||||
end
|
||||
$MapFactory.setCurrentMap
|
||||
end
|
||||
# If scrolling
|
||||
if @scroll_rest > 0
|
||||
distance = (1 << @scroll_speed) * 40.0 / Graphics.frame_rate
|
||||
distance = @scroll_rest if distance > @scroll_rest
|
||||
case @scroll_direction
|
||||
when 2 then
|
||||
scroll_down(distance)
|
||||
when 4 then
|
||||
scroll_left(distance)
|
||||
when 6 then
|
||||
scroll_right(distance)
|
||||
when 8 then
|
||||
scroll_up(distance)
|
||||
end
|
||||
@scroll_rest -= distance
|
||||
end
|
||||
# Only update events that are on-screen
|
||||
for event in @events.values
|
||||
event.update
|
||||
end
|
||||
# Update common events
|
||||
for common_event in @common_events.values
|
||||
common_event.update
|
||||
end
|
||||
# Update fog
|
||||
@fog_ox -= @fog_sx / 8.0
|
||||
@fog_oy -= @fog_sy / 8.0
|
||||
|
||||
@fog2_ox -= @fog2_sx / 8.0 if @fog2_ox
|
||||
@fog2_oy -= @fog2_sy / 8.0 if @fog2_oy
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
def pbScrollMap(direction, distance, speed)
|
||||
if speed == 0
|
||||
case direction
|
||||
when 2 then
|
||||
$game_map.scroll_down(distance * Game_Map::REAL_RES_Y)
|
||||
when 4 then
|
||||
$game_map.scroll_left(distance * Game_Map::REAL_RES_X)
|
||||
when 6 then
|
||||
$game_map.scroll_right(distance * Game_Map::REAL_RES_X)
|
||||
when 8 then
|
||||
$game_map.scroll_up(distance * Game_Map::REAL_RES_Y)
|
||||
end
|
||||
else
|
||||
$game_map.start_scroll(direction, distance, speed)
|
||||
oldx = $game_map.display_x
|
||||
oldy = $game_map.display_y
|
||||
loop do
|
||||
Graphics.update
|
||||
Input.update
|
||||
break if !$game_map.scrolling?
|
||||
pbUpdateSceneMap
|
||||
break if $game_map.display_x == oldx && $game_map.display_y == oldy
|
||||
oldx = $game_map.display_x
|
||||
oldy = $game_map.display_y
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user