mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-07 13:15:01 +00:00
1075 lines
39 KiB
Ruby
1075 lines
39 KiB
Ruby
#===============================================================================
|
|
#
|
|
#===============================================================================
|
|
class UI::TownMapVisuals < UI::BaseVisuals
|
|
attr_reader :region, :visited_regions
|
|
|
|
GRAPHICS_FOLDER = "Town Map/" # Subfolder in Graphics/UI
|
|
MAP_TOP_LEFT = [16, 16] # Top left of map's display area in pixels
|
|
MAP_SIZE = [480, 320] # Size of display area for map in pixels, NOT the map graphic's size
|
|
MAP_SCROLL_PADDING = [64, 64] # In pixels. Don't make these more than half of MAP_SIZE!
|
|
CURSOR_MOVE_TIME = 0.08 # In seconds
|
|
ZOOM_TIME = 0.2 # In seconds
|
|
ZOOM_CURSOR_POSITION = [MAP_SIZE[0] / 4, MAP_SIZE[1] / 2]
|
|
MARKINGS_COUNT = 4 # Number of markings a point can have
|
|
MARKING_SPACING = 8 # In the markings panel (where markings are changed)
|
|
|
|
def initialize(region = 0, mode = :normal)
|
|
@region = region
|
|
@mode = mode
|
|
@cursor_offset = {:x => 0, :y => 0}
|
|
load_region_data
|
|
find_visited_regions
|
|
super()
|
|
set_player_position
|
|
@sprites[:cursor].x, @sprites[:cursor].y = point_to_screen(@cursor_pos[:x], @cursor_pos[:y])
|
|
center_map_on_cursor
|
|
end
|
|
|
|
def initialize_viewport
|
|
@map_viewport = Viewport.new(*MAP_TOP_LEFT, *MAP_SIZE)
|
|
@map_viewport.z = 99999
|
|
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
|
|
@viewport.z = @map_viewport.z + 1
|
|
end
|
|
|
|
def initialize_bitmaps
|
|
@bitmaps[:input_icons] = AnimatedBitmap.new(UI_FOLDER + "input_icons")
|
|
@bitmaps[:map_markings] = AnimatedBitmap.new(graphics_folder + "map_markings")
|
|
@bitmaps[:details_marking_bg] = AnimatedBitmap.new(graphics_folder + themed_filename("details_marking_bg"))
|
|
end
|
|
|
|
def initialize_background
|
|
addBackgroundPlane(@sprites, :background, self.class::GRAPHICS_FOLDER + themed_filename(self.class::BACKGROUND_FILENAME), @viewport)
|
|
@sprites[:background].z = -1000
|
|
end
|
|
|
|
def initialize_overlay
|
|
add_overlay(:map_name_overlay, 234, 32)
|
|
@sprites[:map_name_overlay].x = 262
|
|
@sprites[:map_name_overlay].y = Graphics.height - 40
|
|
if @mode == :wall_map
|
|
@sprites[:map_name_overlay].x = (Graphics.width - @sprites[:map_name_overlay].width) / 2
|
|
@sprites[:map_name_overlay].y += 4
|
|
end
|
|
add_overlay(:input_helpers_overlay, 256, 42)
|
|
@sprites[:input_helpers_overlay].y = Graphics.height - 42
|
|
end
|
|
|
|
def initialize_sprites
|
|
initialize_map_sprite
|
|
initialize_map_overlay
|
|
initialize_pins
|
|
initialize_cursor
|
|
initialize_details_panel
|
|
initialize_marking_panel
|
|
generate_fly_icons if @mode == :fly
|
|
end
|
|
|
|
def initialize_map_sprite
|
|
add_icon_sprite(:map, 0, 0, graphics_folder + @map_data.filename)
|
|
@sprites[:map].viewport = @map_viewport
|
|
end
|
|
|
|
# An overlay sprite for the map, which zooms in as it does. Used for drawing
|
|
# unlockable things onto the map.
|
|
def initialize_map_overlay
|
|
add_overlay(:map_overlay, @sprites[:map].width, @sprites[:map].height)
|
|
@sprites[:map_overlay].viewport = @map_viewport
|
|
@sprites[:map_overlay].z = 1
|
|
end
|
|
|
|
# These are anything drawn onto the map but which will not enlarge if the map
|
|
# is zoomed in.
|
|
def initialize_pins
|
|
@pins_pos ||= {}
|
|
# Markings
|
|
$PokemonGlobal.townMapMarkings ||= []
|
|
$PokemonGlobal.townMapMarkings[@region] ||= []
|
|
@sprites.each_pair { |key, sprite| sprite.dispose if key.to_s.include?("mark_") }
|
|
@sprites.delete_if { |key, sprite| key.to_s.include?("mark_") }
|
|
@pins_pos.delete_if { |key, sprite| key.to_s.include?("mark_") }
|
|
$PokemonGlobal.townMapMarkings[@region].each do |marking|
|
|
next if !marking || marking[2].all?(0)
|
|
key = "mark_#{marking[0]}_#{marking[1]}".to_sym
|
|
create_pin(key, marking[0], marking[1], graphics_folder + themed_filename("icon_marking"), 50)
|
|
end
|
|
# Roamer icons
|
|
@sprites.each_pair { |key, sprite| sprite.dispose if key.to_s.include?("roamer_") }
|
|
@sprites.delete_if { |key, sprite| key.to_s.include?("roamer_") }
|
|
@pins_pos.delete_if { |key, sprite| key.to_s.include?("roamer_") }
|
|
if @mode != :wall_map
|
|
each_active_roamer do |roamer, i|
|
|
next if !roamer[:icon]
|
|
roamer_map = GameData::MapMetadata.try_get($PokemonGlobal.roamPosition[i])
|
|
return if !roamer_map || !roamer_map.town_map_position
|
|
return if roamer_map.town_map_position[0] != @region
|
|
key = "roamer_#{i}".to_sym
|
|
@pins_pos[key] = [roamer_map.town_map_position[1], roamer_map.town_map_position[2]]
|
|
if roamer_map.town_map_size
|
|
area_width = roamer_map.town_map_size[0]
|
|
area_height = (roamer_map.town_map_size[1].length.to_f / roamer_map.town_map_size[0]).ceil
|
|
@pins_pos[key][0] += (area_width.to_f - 1) / 2
|
|
@pins_pos[key][1] += (area_height.to_f - 1) / 2
|
|
end
|
|
create_pin(key, @pins_pos[key][0], @pins_pos[key][1], graphics_folder + roamer[:icon], 80)
|
|
end
|
|
end
|
|
# Overrides's head showing their current location
|
|
if !@pins_pos[:player]
|
|
create_pin(:player, 0, 0, GameData::TrainerType.player_map_icon_filename($player.trainer_type), 100)
|
|
end
|
|
end
|
|
|
|
def create_pin(key, this_x, this_y, filename, this_z)
|
|
@pins_pos[key] = [this_x, this_y]
|
|
add_icon_sprite(key, 0, 0, filename)
|
|
@sprites[key].x, @sprites[key].y = point_to_screen(this_x, this_y)
|
|
@sprites[key].z = this_z
|
|
@sprites[key].ox = @sprites[key].width / 2
|
|
@sprites[key].oy = @sprites[key].height / 2
|
|
@sprites[key].viewport = @map_viewport
|
|
end
|
|
|
|
def initialize_cursor
|
|
@cursor_pos = {:x => 0, :y => 0} # In points, not pixels
|
|
@sprites[:cursor] = AnimatedSprite.create(
|
|
graphics_folder + themed_filename("cursor"), 2, 5, @map_viewport # 2 frames, 5/20 seconds per frame
|
|
)
|
|
@sprites[:cursor].z = 1000
|
|
@sprites[:cursor].ox = @sprites[:cursor].height / 2
|
|
@sprites[:cursor].oy = @sprites[:cursor].height / 2
|
|
@sprites[:cursor].play
|
|
end
|
|
|
|
def initialize_details_panel
|
|
return if !Settings::ENABLE_TOWN_MAP_ZOOM_IN_FOR_DETAILS
|
|
add_icon_sprite(:details, 256, 16, graphics_folder + themed_filename("details_panel"))
|
|
@sprites[:details].z = 900
|
|
@sprites[:details].visible = false
|
|
add_overlay(:details_overlay, @sprites[:details].width, @sprites[:details].height)
|
|
@sprites[:details_overlay].x = @sprites[:details].x
|
|
@sprites[:details_overlay].y = @sprites[:details].y
|
|
@sprites[:details_overlay].z = @sprites[:details].z + 1
|
|
@sprites[:details_overlay].visible = false
|
|
end
|
|
|
|
def initialize_marking_panel
|
|
# Background
|
|
add_icon_sprite(:marking_bg, 0, 0, graphics_folder + themed_filename("marking_bg"))
|
|
@sprites[:marking_bg].z = 1000
|
|
@sprites[:marking_bg].visible = false
|
|
# Overlay
|
|
add_overlay(:marking_overlay, @sprites[:marking_bg].width, @sprites[:marking_bg].height)
|
|
@sprites[:marking_overlay].x = @sprites[:marking_bg].x
|
|
@sprites[:marking_overlay].y = @sprites[:marking_bg].y
|
|
@sprites[:marking_overlay].z = @sprites[:marking_bg].z + 1
|
|
@sprites[:marking_overlay].visible = false
|
|
# Cursor
|
|
@sprites[:marking_cursor] = AnimatedSprite.create(
|
|
graphics_folder + themed_filename("marking_cursor"), 2, 5, @viewport # 2 frames, 5/20 seconds per frame
|
|
)
|
|
@sprites[:marking_cursor].z = @sprites[:marking_overlay].z + 1
|
|
@sprites[:marking_cursor].ox = @sprites[:marking_cursor].height / 2
|
|
@sprites[:marking_cursor].oy = @sprites[:marking_cursor].height / 2
|
|
@sprites[:marking_cursor].visible = false
|
|
@sprites[:marking_cursor].play
|
|
end
|
|
|
|
def dispose
|
|
super
|
|
@map_viewport.dispose
|
|
@viewport.dispose
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def themed_filename(base_filename)
|
|
return filename_with_appendix(base_filename, "_wall") if @mode == :wall_map
|
|
# NOTE: The Pokégear theme would be manually chosen by the player, and would
|
|
# not depend on the player's gender. However, because there isn't a
|
|
# variable that contains the Pokégear's theme, so for the sake of
|
|
# example, the player's gender matters here.
|
|
return filename_with_appendix(base_filename, "_f") if $player&.female?
|
|
return base_filename
|
|
end
|
|
|
|
def load_region_data
|
|
if !GameData::TownMap.exists?(@region)
|
|
raise _INTL("No Town Map data is defined for region {1}.", @region)
|
|
end
|
|
@map_data = GameData::TownMap.get(@region)
|
|
end
|
|
|
|
def find_visited_regions
|
|
@visited_regions = []
|
|
GameData::MapMetadata.each do |map_data|
|
|
next if !map_data.town_map_position || @visited_regions.include?(map_data.town_map_position[0])
|
|
next if !$PokemonGlobal.visitedMaps[map_data.id]
|
|
@visited_regions.push(map_data.town_map_position[0])
|
|
end
|
|
end
|
|
|
|
def set_region(new_region)
|
|
return if @region == new_region
|
|
@region = new_region
|
|
load_region_data
|
|
@sprites[:map].setBitmap(graphics_folder + @map_data.filename)
|
|
initialize_pins
|
|
set_player_position
|
|
@sprites[:cursor].x, @sprites[:cursor].y = point_to_screen(@cursor_pos[:x], @cursor_pos[:y])
|
|
center_map_on_cursor
|
|
refresh
|
|
end
|
|
|
|
def each_fly_point
|
|
@map_data.points.each do |point|
|
|
yield point if point[:fly_spot]
|
|
end
|
|
end
|
|
|
|
def get_point_data(this_x = -1, this_y = -1)
|
|
this_x = @cursor_pos[:x] if this_x < 0
|
|
this_y = @cursor_pos[:y] if this_y < 0
|
|
@map_data.points.each do |point|
|
|
next if point[:position][0] != this_x || point[:position][1] != this_y
|
|
return nil if point[:switch] && (@mode == :wall_map || point[:switch] <= 0 || !$game_switches[point[:switch]])
|
|
return point
|
|
end
|
|
return nil
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
# Positions the player's head on the town map. It is invisible if the player
|
|
# isn't in a map belonging to that town map. Also sets the cursor's position
|
|
# to the same point.
|
|
def set_player_position
|
|
map_pos = $game_map.metadata&.town_map_position
|
|
if map_pos.nil? || map_pos[0] != @region
|
|
set_cursor_pos((@map_data.size[0] - 1) / 2, (@map_data.size[1] - 1) / 2) # Middle of the map
|
|
@sprites[:player].visible = false
|
|
return
|
|
end
|
|
@pins_pos[:player] = [map_pos[1], map_pos[2]]
|
|
map_size = $game_map.metadata&.town_map_size
|
|
if map_size
|
|
area_width = map_size[0]
|
|
area_height = (map_size[1].length.to_f / map_size[0]).ceil
|
|
@pins_pos[:player][0] += ($game_player.x * area_width / $game_map.width).floor if area_width > 1
|
|
@pins_pos[:player][1] += ($game_player.y * area_height / $game_map.height).floor if area_height > 1
|
|
end
|
|
@sprites[:player].x, @sprites[:player].y = point_to_screen(*@pins_pos[:player])
|
|
@sprites[:player].visible = true
|
|
set_cursor_pos(*@pins_pos[:player]) # In points
|
|
end
|
|
|
|
def can_move_to_point?(new_x, new_y)
|
|
return false if new_x < 0 || new_x >= @map_data.size[0]
|
|
return false if new_y < 0 || new_y >= @map_data.size[1]
|
|
return true
|
|
end
|
|
|
|
def cursor_moving?
|
|
return @cursor_offset[:x] != 0 || @cursor_offset[:y] != 0
|
|
end
|
|
|
|
def set_cursor_pos(new_x, new_y)
|
|
changed = (@cursor_pos[:x] != new_x) || (@cursor_pos[:y] != new_y)
|
|
@cursor_pos[:x] = new_x
|
|
@cursor_pos[:y] = new_y
|
|
refresh_on_cursor_move if changed
|
|
end
|
|
|
|
def point_to_screen(point_x, point_y)
|
|
return point_x_to_screen_x(point_x), point_y_to_screen_y(point_y)
|
|
end
|
|
|
|
# Returns the x coordinate of the middle of the point.
|
|
def point_x_to_screen_x(value)
|
|
return ((value * @map_data.point_size[0]) + (@map_data.point_size[0] / 2) + @map_data.margins[0]) * @sprites[:map].zoom_x
|
|
end
|
|
|
|
# Returns the y coordinate of the middle of the point.
|
|
def point_y_to_screen_y(value)
|
|
return ((value * @map_data.point_size[1]) + (@map_data.point_size[1] / 2) + @map_data.margins[1]) * @sprites[:map].zoom_y
|
|
end
|
|
|
|
# Called during initialization only.
|
|
def center_map_on_cursor
|
|
@map_viewport.ox = @sprites[:cursor].x - (MAP_SIZE[0] / 2)
|
|
@map_viewport.oy = @sprites[:cursor].y - (MAP_SIZE[1] / 2)
|
|
clamp_map_position
|
|
end
|
|
|
|
def clamp_map_position
|
|
max_ox = ((@map_data.size[0] * @map_data.point_size[0]) + (@map_data.margins[0] * 2)) * @sprites[:map].zoom_x
|
|
max_oy = ((@map_data.size[1] * @map_data.point_size[1]) + (@map_data.margins[1] * 2)) * @sprites[:map].zoom_y
|
|
if zoomed?
|
|
max_ox -= ZOOM_CURSOR_POSITION[0] * 2
|
|
max_oy -= ZOOM_CURSOR_POSITION[1] * 2
|
|
else
|
|
max_ox -= MAP_SIZE[0]
|
|
max_oy -= MAP_SIZE[1]
|
|
end
|
|
@map_viewport.ox = max_ox if @map_viewport.ox > max_ox
|
|
@map_viewport.oy = max_oy if @map_viewport.oy > max_oy
|
|
@map_viewport.ox = 0 if @map_viewport.ox < 0
|
|
@map_viewport.oy = 0 if @map_viewport.oy < 0
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def screen_menu_options
|
|
ret = []
|
|
MenuHandlers.each_available(:town_map_menu, self) do |option, _hash, _name|
|
|
ret.push(option)
|
|
end
|
|
return ret
|
|
end
|
|
|
|
def can_access_screen_menu?
|
|
return false if @mode != :normal || @sub_mode == :fly || zoomed?
|
|
return screen_menu_options.length > 1 # At least 1 command (plus "Cancel")
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def zoomed?
|
|
return @sprites[:map].zoom_x > 1
|
|
end
|
|
|
|
def can_zoom?
|
|
return Settings::ENABLE_TOWN_MAP_ZOOM_IN_FOR_DETAILS && @mode == :normal && !zoomed?
|
|
end
|
|
|
|
def zoom_in
|
|
@sprites[:details].visible = true
|
|
@sprites[:details_overlay].visible = true
|
|
@sprites[:input_helpers_overlay].visible = false
|
|
refresh_details_panel(false)
|
|
start_ox = @map_viewport.ox
|
|
start_oy = @map_viewport.oy
|
|
max_ox = (((@map_data.size[0] * @map_data.point_size[0]) + (@map_data.margins[0] * 2)) * 2) - (MAP_SIZE[0] / 2)
|
|
max_oy = (((@map_data.size[1] * @map_data.point_size[1]) + (@map_data.margins[1] * 2)) * 2) - MAP_SIZE[1]
|
|
end_ox = (@sprites[:cursor].x * 2) - ZOOM_CURSOR_POSITION[0]
|
|
end_ox = 0 if end_ox < 0
|
|
end_ox = max_ox if end_ox > max_ox
|
|
end_oy = (@sprites[:cursor].y * 2) - ZOOM_CURSOR_POSITION[1]
|
|
end_oy = 0 if end_oy < 0
|
|
end_oy = max_oy if end_oy > max_oy
|
|
# Animate the zoom in
|
|
animate_zoom(1, 2, start_ox, end_ox, start_oy, end_oy)
|
|
@sprites[:input_helpers_overlay].visible = true
|
|
refresh_input_helpers
|
|
end
|
|
|
|
def zoom_out
|
|
@sprites[:input_helpers_overlay].visible = false
|
|
start_ox = @map_viewport.ox
|
|
start_oy = @map_viewport.oy
|
|
max_ox = (@map_data.size[0] * @map_data.point_size[0]) + (@map_data.margins[0] * 2) - MAP_SIZE[0]
|
|
max_oy = (@map_data.size[1] * @map_data.point_size[1]) + (@map_data.margins[1] * 2) - MAP_SIZE[1]
|
|
end_ox = @sprites[:cursor].x - MAP_SIZE[0] / 2
|
|
end_ox = 0 if end_ox < 0
|
|
end_ox = max_ox if end_ox > max_ox
|
|
end_oy = @sprites[:cursor].y - MAP_SIZE[1] / 2
|
|
end_oy = 0 if end_oy < 0
|
|
end_oy = max_oy if end_oy > max_oy
|
|
# Animate the zoom in
|
|
animate_zoom(2, 1, start_ox, end_ox, start_oy, end_oy)
|
|
@sprites[:details].visible = false
|
|
@sprites[:details_overlay].visible = false
|
|
@sprites[:input_helpers_overlay].visible = true
|
|
refresh_input_helpers
|
|
end
|
|
|
|
def animate_zoom(start_zoom, end_zoom, start_ox, end_ox, start_oy, end_oy)
|
|
timer_start = System.uptime
|
|
loop do
|
|
Graphics.update
|
|
update_visuals
|
|
now = System.uptime
|
|
@map_viewport.ox = lerp(start_ox, end_ox, ZOOM_TIME, timer_start, now)
|
|
@map_viewport.oy = lerp(start_oy, end_oy, ZOOM_TIME, timer_start, now)
|
|
@sprites[:map].zoom_x = lerp(start_zoom, end_zoom, ZOOM_TIME, timer_start, now)
|
|
@sprites[:map].zoom_y = @sprites[:map].zoom_x
|
|
@sprites[:map_overlay].zoom_x = @sprites[:map].zoom_x
|
|
@sprites[:map_overlay].zoom_y = @sprites[:map].zoom_y
|
|
update_pin_positions_while_zooming
|
|
break if timer_start + ZOOM_TIME <= now
|
|
end
|
|
end
|
|
|
|
def update_pin_positions_while_zooming
|
|
@sprites[:cursor].x, @sprites[:cursor].y = point_to_screen(@cursor_pos[:x], @cursor_pos[:y])
|
|
# Overrides, roamers, markings
|
|
@pins_pos.each_pair do |key, pos|
|
|
@sprites[key].x, @sprites[key].y = point_to_screen(*pos)
|
|
end
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def can_mark?
|
|
return Settings::ENABLE_TOWN_MAP_MARKING && @mode == :normal && !can_zoom?
|
|
end
|
|
|
|
# Returns the [x, y, [markings]] for the given point. Creates and returns an
|
|
# empty set of markings for that point if there isn't an existing one.
|
|
def markings_of_point(this_x, this_y)
|
|
ret = [@cursor_pos[:x], @cursor_pos[:y], [0] * MARKINGS_COUNT]
|
|
$PokemonGlobal.townMapMarkings[@region].each do |marking|
|
|
next if !marking || marking[0] != @cursor_pos[:x] || marking[1] != @cursor_pos[:y]
|
|
ret = marking
|
|
end
|
|
return ret
|
|
end
|
|
|
|
def apply_new_markings(new_markings)
|
|
if new_markings[2].all?(0)
|
|
$PokemonGlobal.townMapMarkings[@region].delete_if { |marking| marking[0] == new_markings[0] && marking[1] == new_markings[1] }
|
|
former_key = "mark_#{new_markings[0]}_#{new_markings[1]}".to_sym
|
|
@sprites.each_pair { |key, sprite| sprite.dispose if key == former_key }
|
|
@sprites.delete(former_key)
|
|
@pins_pos.delete(former_key)
|
|
else
|
|
found_existing = false
|
|
$PokemonGlobal.townMapMarkings[@region].each_with_index do |marking, i|
|
|
next if marking[0] != new_markings[0] || marking[1] != new_markings[1]
|
|
found_existing = true
|
|
$PokemonGlobal.townMapMarkings[@region][i] = new_markings
|
|
break
|
|
end
|
|
if !found_existing
|
|
$PokemonGlobal.townMapMarkings[@region].push(new_markings)
|
|
key = "mark_#{new_markings[0]}_#{new_markings[1]}".to_sym
|
|
create_pin(key, new_markings[0], new_markings[1], graphics_folder + themed_filename("icon_marking"), 50)
|
|
end
|
|
end
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def has_fly_points?
|
|
ret = false
|
|
each_fly_point do |point|
|
|
if !$DEBUG || !Input.press?(Input::CTRL)
|
|
next if point[:switch] && (point[:switch] <= 0 || !$game_switches[point[:switch]])
|
|
next if !$PokemonGlobal.visitedMaps[point[:fly_spot][0]]
|
|
end
|
|
ret = true
|
|
break
|
|
end
|
|
return ret
|
|
end
|
|
|
|
def start_fly_mode
|
|
return if @mode == :fly || @sub_mode == :fly
|
|
set_sub_mode(:fly)
|
|
generate_fly_icons
|
|
refresh_input_helpers
|
|
end
|
|
|
|
def end_fly_mode
|
|
set_sub_mode
|
|
clear_fly_icons
|
|
refresh_input_helpers
|
|
end
|
|
|
|
def generate_fly_icons
|
|
@fly_coords = []
|
|
counter = 0
|
|
each_fly_point do |point|
|
|
if !$DEBUG || !Input.press?(Input::CTRL)
|
|
next if point[:switch] && (point[:switch] <= 0 || !$game_switches[point[:switch]])
|
|
next if !$PokemonGlobal.visitedMaps[point[:fly_spot][0]]
|
|
end
|
|
@fly_coords.push(point[:position])
|
|
next if point[:hide_fly_icon]
|
|
counter += 1
|
|
sprite_key = "fly_icon_#{counter}".to_sym
|
|
@sprites[sprite_key] = AnimatedSprite.create(
|
|
graphics_folder + "icon_fly", 2, 10, @map_viewport # 2 frames, 10/20 seconds per frame
|
|
)
|
|
@sprites[sprite_key].x, @sprites[sprite_key].y = point_to_screen(*point[:position])
|
|
if point[:fly_icon_offset]
|
|
@sprites[sprite_key].x += point[:fly_icon_offset][0]
|
|
@sprites[sprite_key].y += point[:fly_icon_offset][1]
|
|
end
|
|
@sprites[sprite_key].z = 900
|
|
@sprites[sprite_key].ox = @sprites[sprite_key].bitmap.height / 2
|
|
@sprites[sprite_key].oy = @sprites[sprite_key].bitmap.height / 2
|
|
@sprites[sprite_key].play
|
|
end
|
|
end
|
|
|
|
def clear_fly_icons
|
|
@sprites.each_pair do |key, sprite|
|
|
next if !key.to_s.include?("fly_icon_")
|
|
sprite.dispose
|
|
@sprites[key] = nil
|
|
end
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def refresh
|
|
super
|
|
refresh_map_overlay
|
|
refresh_on_cursor_move
|
|
end
|
|
|
|
def refresh_overlay
|
|
super
|
|
refresh_input_helpers
|
|
refresh_map_name
|
|
end
|
|
|
|
def refresh_map_overlay
|
|
@sprites[:map_overlay].bitmap.clear
|
|
Settings::REGION_MAP_EXTRAS.each do |graphic|
|
|
next if graphic[0] != @region
|
|
next if !graphic[5] && @mode == :wall_map
|
|
return if graphic[1] <= 0 || !$game_switches[graphic[1]]
|
|
draw_image(graphics_folder + graphic[4],
|
|
graphic[2] * @map_data.point_size[0], graphic[3] * @map_data.point_size[1], overlay: :map_overlay)
|
|
end
|
|
end
|
|
|
|
def refresh_on_cursor_move
|
|
refresh_map_name
|
|
refresh_details_panel
|
|
end
|
|
|
|
def refresh_map_name
|
|
@sprites[:map_name_overlay].bitmap.clear
|
|
point_data = get_point_data
|
|
if point_data && point_data[:real_name]
|
|
name = pbGetMessageFromHash(MessageTypes::REGION_LOCATION_NAMES, point_data[:real_name])
|
|
name = name.gsub(/\\PN/, $player.name)
|
|
name = name.gsub(/\\v\[(\d+)\]/) { |num| $game_variables[$~[1].to_i].to_s }
|
|
theme = (@mode == :wall_map) ? :black : :white
|
|
draw_text(name, @sprites[:map_name_overlay].width / 2, 6, align: :center, theme: theme, overlay: :map_name_overlay)
|
|
end
|
|
end
|
|
|
|
def refresh_input_helpers
|
|
@sprites[:input_helpers_overlay].bitmap.clear
|
|
input_spacing = 24
|
|
icon_text_spacing = 6
|
|
input_x = 4
|
|
action_icon_y = 4
|
|
action_text_y = 12
|
|
draw_input = lambda do |number, action_text|
|
|
draw_image(@bitmaps[:input_icons], input_x, action_icon_y,
|
|
number * @bitmaps[:input_icons].height, 0,
|
|
@bitmaps[:input_icons].height, @bitmaps[:input_icons].height,
|
|
overlay: :input_helpers_overlay)
|
|
draw_text(action_text, input_x + @bitmaps[:input_icons].height + icon_text_spacing, action_text_y,
|
|
theme: :white, overlay: :input_helpers_overlay)
|
|
input_x += @bitmaps[:input_icons].height + icon_text_spacing
|
|
input_x += @sprites[:input_helpers_overlay].bitmap.text_size(action_text).width
|
|
input_x += input_spacing
|
|
end
|
|
if @mode == :fly || @sub_mode == :fly
|
|
draw_input.call(0, _INTL("Fly to here"))
|
|
return
|
|
end
|
|
if can_zoom?
|
|
draw_input.call(0, _INTL("Zoom"))
|
|
elsif can_mark?
|
|
draw_input.call(0, _INTL("Mark"))
|
|
end
|
|
if can_access_screen_menu?
|
|
options = screen_menu_options
|
|
if options.length == 2 && options.include?(:fly_mode) # Also contains :cancel
|
|
draw_input.call(2, _INTL("Fly"))
|
|
else
|
|
draw_input.call(2, _INTL("Menu"))
|
|
end
|
|
end
|
|
end
|
|
|
|
def refresh_details_panel(skip_if_not_visible = true)
|
|
return if skip_if_not_visible && !@sprites[:details]&.visible
|
|
@sprites[:details_overlay].bitmap.clear
|
|
draw_markings_on_details_panel
|
|
draw_point_details_on_details_panel
|
|
end
|
|
|
|
def draw_markings_on_details_panel
|
|
return if !Settings::ENABLE_TOWN_MAP_MARKING
|
|
MARKINGS_COUNT.times do |i|
|
|
draw_image(@bitmaps[:details_marking_bg],
|
|
38 + (168 * (i % 2)) - (@bitmaps[:details_marking_bg].width / 2),
|
|
44 + (52 * (i / 2)) - (@bitmaps[:details_marking_bg].height / 2),
|
|
overlay: :details_overlay)
|
|
end
|
|
$PokemonGlobal.townMapMarkings[@region].each do |marking|
|
|
next if !marking || marking[0] != @cursor_pos[:x] || marking[1] != @cursor_pos[:y]
|
|
next if !marking[2]
|
|
marking[2].each_with_index do |mark, i|
|
|
next if mark == 0
|
|
draw_image(@bitmaps[:map_markings],
|
|
38 + (168 * (i % 2)) - (@bitmaps[:map_markings].height / 2),
|
|
44 + (52 * (i / 2)) - (@bitmaps[:map_markings].height / 2),
|
|
@bitmaps[:map_markings].height * (mark - 1), 0,
|
|
@bitmaps[:map_markings].height, @bitmaps[:map_markings].height,
|
|
overlay: :details_overlay)
|
|
end
|
|
break
|
|
end
|
|
end
|
|
|
|
def draw_point_details_on_details_panel
|
|
point_data = get_point_data
|
|
return if !point_data
|
|
if point_data[:image]
|
|
draw_image(graphics_folder + point_data[:image], 74, 22, overlay: :details_overlay)
|
|
end
|
|
if point_data[:real_description]
|
|
description = pbGetMessageFromHash(MessageTypes::REGION_LOCATION_DESCRIPTIONS, point_data[:real_description])
|
|
description = description.gsub(/\\PN/, $player.name)
|
|
description = description.gsub(/\\v\[(\d+)\]/) { |num| $game_variables[$~[1].to_i].to_s }
|
|
draw_formatted_text(description, 18, 144, 210, theme: :white, overlay: :details_overlay)
|
|
end
|
|
end
|
|
|
|
def refresh_markings_panel
|
|
@sprites[:marking_overlay].bitmap.clear
|
|
draw_point_name_on_markings_panel
|
|
draw_marking_slots_on_markings_panel
|
|
draw_markings_lineup_on_markings_panel
|
|
end
|
|
|
|
def draw_point_name_on_markings_panel
|
|
point_data = get_point_data
|
|
if point_data && point_data[:real_name]
|
|
name = pbGetMessageFromHash(MessageTypes::REGION_LOCATION_NAMES, point_data[:real_name])
|
|
name = name.gsub(/\\PN/, $player.name)
|
|
name = name.gsub(/\\v\[(\d+)\]/) { |num| $game_variables[$~[1].to_i].to_s }
|
|
draw_text(name, @sprites[:marking_overlay].width / 2, 114, align: :center, theme: :black, overlay: :marking_overlay)
|
|
end
|
|
end
|
|
|
|
def draw_marking_slots_on_markings_panel
|
|
# Draw current markings
|
|
middle_y = 168
|
|
MARKINGS_COUNT.times do |i|
|
|
middle_x = (Graphics.width / 2) + ((@bitmaps[:details_marking_bg].width + MARKING_SPACING) * (i - ((MARKINGS_COUNT.to_f - 1) / 2)))
|
|
draw_image(@bitmaps[:details_marking_bg],
|
|
middle_x - (@bitmaps[:details_marking_bg].width / 2),
|
|
middle_y - (@bitmaps[:details_marking_bg].height / 2),
|
|
overlay: :marking_overlay)
|
|
if @markings[2][i] > 0
|
|
draw_image(@bitmaps[:map_markings],
|
|
middle_x - (@bitmaps[:map_markings].height / 2),
|
|
middle_y - (@bitmaps[:map_markings].height / 2),
|
|
@bitmaps[:map_markings].height * (@markings[2][i] - 1), 0,
|
|
@bitmaps[:map_markings].height, @bitmaps[:map_markings].height,
|
|
overlay: :marking_overlay)
|
|
end
|
|
end
|
|
end
|
|
|
|
def draw_markings_lineup_on_markings_panel
|
|
# Draw all markings to choose from
|
|
middle_y = 292
|
|
icons_count = 1 + (@bitmaps[:map_markings].width / @bitmaps[:map_markings].height)
|
|
icons_count.times do |i|
|
|
middle_x = (Graphics.width / 2) + ((@bitmaps[:details_marking_bg].width + MARKING_SPACING) * (i - ((icons_count.to_f - 1) / 2)))
|
|
draw_image(@bitmaps[:details_marking_bg],
|
|
middle_x - (@bitmaps[:details_marking_bg].width / 2),
|
|
middle_y - (@bitmaps[:details_marking_bg].height / 2),
|
|
overlay: :marking_overlay)
|
|
next if i == 0
|
|
draw_image(@bitmaps[:map_markings],
|
|
middle_x - (@bitmaps[:map_markings].height / 2),
|
|
middle_y - (@bitmaps[:map_markings].height / 2),
|
|
@bitmaps[:map_markings].height * (i - 1), 0,
|
|
@bitmaps[:map_markings].height, @bitmaps[:map_markings].height,
|
|
overlay: :marking_overlay)
|
|
end
|
|
end
|
|
|
|
def refresh_markings_cursor
|
|
if @marking_new_index >= 0
|
|
spaces_count = 1 + (@bitmaps[:map_markings].width / @bitmaps[:map_markings].height)
|
|
space_index = @marking_new_index
|
|
else
|
|
spaces_count = MARKINGS_COUNT
|
|
space_index = @marking_index
|
|
end
|
|
middle_x = (Graphics.width / 2) + ((@bitmaps[:details_marking_bg].width + MARKING_SPACING) * (space_index - ((spaces_count.to_f - 1) / 2)))
|
|
@sprites[:marking_cursor].x = middle_x
|
|
@sprites[:marking_cursor].y = (@marking_new_index >= 0) ? 292 : 168
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def update_input
|
|
return if cursor_moving? && update_move_cursor
|
|
# Check for cursor movement
|
|
update_direction_input
|
|
if cursor_moving?
|
|
@cursor_timer_start ||= System.uptime
|
|
return
|
|
end
|
|
# Check for interaction
|
|
if Input.trigger?(Input::USE)
|
|
return update_interaction(Input::USE)
|
|
elsif Input.trigger?(Input::BACK)
|
|
return update_interaction(Input::BACK)
|
|
elsif Input.trigger?(Input::ACTION)
|
|
return update_interaction(Input::ACTION)
|
|
end
|
|
return nil
|
|
end
|
|
|
|
# Moves the cursor after a direction input has said it should move. Returns
|
|
# whether the cursor is still moving.
|
|
def update_move_cursor
|
|
now = System.uptime
|
|
if @cursor_offset[:x] && @cursor_offset[:x] != 0
|
|
point_x = lerp(@cursor_pos[:x] - @cursor_offset[:x], @cursor_pos[:x],
|
|
CURSOR_MOVE_TIME * @cursor_offset[:x].abs * @sprites[:map].zoom_x,
|
|
@cursor_timer_start, now)
|
|
@sprites[:cursor].x = point_x_to_screen_x(point_x)
|
|
@cursor_offset[:x] = 0 if @cursor_timer_start + (CURSOR_MOVE_TIME * @cursor_offset[:x].abs * @sprites[:map].zoom_x) <= now
|
|
end
|
|
if @cursor_offset[:y] && @cursor_offset[:y] != 0
|
|
point_y = lerp(@cursor_pos[:y] - @cursor_offset[:y], @cursor_pos[:y],
|
|
CURSOR_MOVE_TIME * @cursor_offset[:y].abs * @sprites[:map].zoom_y,
|
|
@cursor_timer_start, now)
|
|
@sprites[:cursor].y = point_y_to_screen_y(point_y)
|
|
@cursor_offset[:y] = 0 if @cursor_timer_start + (CURSOR_MOVE_TIME * @cursor_offset[:y].abs * @sprites[:map].zoom_y) <= now
|
|
end
|
|
update_map_offset
|
|
return true if cursor_moving?
|
|
@cursor_timer_start = nil
|
|
return false
|
|
end
|
|
|
|
def update_direction_input
|
|
x_offset = 0
|
|
y_offset = 0
|
|
x_offset = -1 if Input.press?(Input::LEFT)
|
|
x_offset = 1 if Input.press?(Input::RIGHT)
|
|
y_offset = -1 if Input.press?(Input::UP)
|
|
y_offset = 1 if Input.press?(Input::DOWN)
|
|
return if x_offset == 0 && y_offset == 0
|
|
x_offset = 0 if x_offset != 0 && !can_move_to_point?(@cursor_pos[:x] + x_offset, @cursor_pos[:y])
|
|
y_offset = 0 if y_offset != 0 && !can_move_to_point?(@cursor_pos[:x], @cursor_pos[:y] + y_offset)
|
|
return if x_offset == 0 && y_offset == 0
|
|
@cursor_offset[:x] = x_offset
|
|
@cursor_offset[:y] = y_offset
|
|
set_cursor_pos(@cursor_pos[:x] + @cursor_offset[:x], @cursor_pos[:y] + @cursor_offset[:y])
|
|
end
|
|
|
|
def update_interaction(input)
|
|
case input
|
|
when Input::USE
|
|
if @mode == :fly || @sub_mode == :fly
|
|
if @fly_coords.include?([@cursor_pos[:x], @cursor_pos[:y]])
|
|
pbPlayDecisionSE
|
|
return :use_fly
|
|
end
|
|
elsif can_zoom?
|
|
pbPlayDecisionSE
|
|
zoom_in
|
|
elsif can_mark?
|
|
pbPlayDecisionSE
|
|
return :marking
|
|
end
|
|
when Input::ACTION
|
|
if can_access_screen_menu?
|
|
pbPlayDecisionSE
|
|
options = screen_menu_options
|
|
return :fly_mode if options.length == 2 && options.include?(:fly_mode) # Also contains :cancel
|
|
return :screen_menu
|
|
end
|
|
when Input::BACK
|
|
if @sub_mode == :fly
|
|
pbPlayCancelSE
|
|
end_fly_mode
|
|
elsif zoomed?
|
|
pbPlayCancelSE
|
|
zoom_out
|
|
else
|
|
pbPlayCloseMenuSE
|
|
return :quit
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
# Ensures the cursor remains in the display area by shifting the map sprite's
|
|
# viewport's ox/oy.
|
|
def update_map_offset
|
|
changed = false
|
|
if zoomed?
|
|
if @map_viewport.ox != @sprites[:cursor].x - ZOOM_CURSOR_POSITION[0]
|
|
@map_viewport.ox = @sprites[:cursor].x - ZOOM_CURSOR_POSITION[0]
|
|
changed = true
|
|
end
|
|
if @map_viewport.oy != @sprites[:cursor].y - ZOOM_CURSOR_POSITION[1]
|
|
@map_viewport.oy = @sprites[:cursor].y - ZOOM_CURSOR_POSITION[1]
|
|
changed = true
|
|
end
|
|
else
|
|
if @sprites[:cursor].x - (@map_data.point_size[0] / 2) < @map_viewport.ox + MAP_SCROLL_PADDING[0]
|
|
@map_viewport.ox = @sprites[:cursor].x - (@map_data.point_size[0] / 2) - MAP_SCROLL_PADDING[0]
|
|
changed = true
|
|
elsif @sprites[:cursor].x + (@map_data.point_size[0] / 2) > @map_viewport.ox + MAP_SIZE[0] - MAP_SCROLL_PADDING[0] - @map_data.margins[0]
|
|
@map_viewport.ox = @sprites[:cursor].x + (@map_data.point_size[0] / 2) - MAP_SIZE[0] + MAP_SCROLL_PADDING[0] + @map_data.margins[0]
|
|
changed = true
|
|
end
|
|
if @sprites[:cursor].y - (@map_data.point_size[1] / 2) < @map_viewport.oy + MAP_SCROLL_PADDING[1]
|
|
@map_viewport.oy = @sprites[:cursor].y - (@map_data.point_size[1] / 2) - MAP_SCROLL_PADDING[1]
|
|
changed = true
|
|
elsif @sprites[:cursor].y + (@map_data.point_size[1] / 2) > @map_viewport.oy + MAP_SIZE[1] - MAP_SCROLL_PADDING[1] - @map_data.margins[1]
|
|
@map_viewport.oy = @sprites[:cursor].y + (@map_data.point_size[1] / 2) - MAP_SIZE[1] + MAP_SCROLL_PADDING[1] + @map_data.margins[1]
|
|
changed = true
|
|
end
|
|
end
|
|
clamp_map_position if changed
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def update_input_marking
|
|
# Check for movement to a new marking
|
|
if Input.repeat?(Input::LEFT)
|
|
if @marking_new_index >= 0
|
|
@marking_new_index -= 1
|
|
icons_count = 1 + (@bitmaps[:map_markings].width / @bitmaps[:map_markings].height)
|
|
@marking_new_index += icons_count if @marking_new_index < 0
|
|
else
|
|
@marking_index -= 1
|
|
@marking_index += MARKINGS_COUNT if @marking_index < 0
|
|
end
|
|
elsif Input.repeat?(Input::RIGHT)
|
|
if @marking_new_index >= 0
|
|
@marking_new_index += 1
|
|
icons_count = 1 + (@bitmaps[:map_markings].width / @bitmaps[:map_markings].height)
|
|
@marking_new_index -= icons_count if @marking_new_index >= icons_count
|
|
else
|
|
@marking_index += 1
|
|
@marking_index -= MARKINGS_COUNT if @marking_index >= MARKINGS_COUNT
|
|
end
|
|
end
|
|
# Check for up/down movement between marking rows (doesn't apply changes)
|
|
if Input.trigger?(Input::UP) && @marking_new_index >= 0
|
|
pbPlayCursorSE
|
|
@marking_new_index = -1
|
|
refresh_markings_cursor
|
|
elsif Input.trigger?(Input::DOWN) && @marking_new_index < 0
|
|
pbPlayCursorSE
|
|
@marking_new_index = @markings[2][@marking_index]
|
|
refresh_markings_cursor
|
|
end
|
|
# Check for interaction
|
|
if Input.trigger?(Input::USE)
|
|
pbPlayDecisionSE
|
|
if @marking_new_index >= 0 # Chosen a new marking
|
|
if @markings[2][@marking_index] != @marking_new_index
|
|
@markings[2][@marking_index] = @marking_new_index
|
|
refresh_markings_panel
|
|
end
|
|
@marking_new_index = -1
|
|
refresh_markings_cursor
|
|
else # Start to choose a new marking
|
|
@marking_new_index = @markings[2][@marking_index]
|
|
refresh_markings_cursor
|
|
end
|
|
elsif Input.trigger?(Input::BACK)
|
|
if @marking_new_index >= 0 # Cancel choosing a new marking
|
|
pbPlayCancelSE
|
|
@marking_new_index = -1
|
|
refresh_markings_cursor
|
|
else # Close the markings panel
|
|
pbPlayCloseMenuSE
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
def navigate_markings
|
|
# Setup
|
|
@sprites[:marking_bg].visible = true
|
|
@sprites[:marking_overlay].visible = true
|
|
@sprites[:marking_cursor].visible = true
|
|
@markings = markings_of_point(@cursor_pos[:x], @cursor_pos[:y])
|
|
@marking_index = 0
|
|
@marking_new_index = -1
|
|
refresh_markings_panel
|
|
refresh_markings_cursor
|
|
# Navigate loop
|
|
loop do
|
|
Graphics.update
|
|
Input.update
|
|
update_visuals
|
|
old_marking_index = @marking_index
|
|
old_marking_new_index = @marking_new_index
|
|
break if update_input_marking
|
|
if @marking_index != old_marking_index ||
|
|
(@marking_new_index != old_marking_new_index && (@marking_new_index == -1) == (old_marking_new_index == -1))
|
|
pbPlayCursorSE
|
|
refresh_markings_cursor
|
|
end
|
|
end
|
|
# Clean up
|
|
@sprites[:marking_bg].visible = false
|
|
@sprites[:marking_overlay].visible = false
|
|
@sprites[:marking_cursor].visible = false
|
|
apply_new_markings(@markings)
|
|
@marking_index = nil
|
|
@marking_new_index = nil
|
|
end
|
|
end
|
|
|
|
#===============================================================================
|
|
#
|
|
#===============================================================================
|
|
class UI::TownMap < UI::BaseScreen
|
|
SCREEN_ID = :town_map_screen
|
|
|
|
# mode is one of:
|
|
# :normal
|
|
# :wall_map - Doesn't show unlockable content, can't change region, can't fly
|
|
# :fly - Can't zoom or change region, choose a point to fly to
|
|
def initialize(this_region = -1, mode: :normal)
|
|
@region = this_region
|
|
if @region < 0
|
|
this_map_data = $game_map.metadata&.town_map_position
|
|
@region = (this_map_data) ? this_map_data[0] : 0
|
|
end
|
|
@mode = mode
|
|
super()
|
|
end
|
|
|
|
def initialize_visuals
|
|
@visuals = UI::TownMapVisuals.new(@region, @mode)
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def visited_regions
|
|
return @visuals.visited_regions
|
|
end
|
|
|
|
def region
|
|
return @visuals.region
|
|
end
|
|
|
|
def set_region(new_region)
|
|
@visuals.set_region(new_region)
|
|
end
|
|
|
|
def has_fly_points?
|
|
return @visuals.has_fly_points?
|
|
end
|
|
|
|
def start_fly_mode
|
|
@visuals.start_fly_mode
|
|
end
|
|
|
|
def set_fly_destination
|
|
point_data = @visuals.get_point_data
|
|
if !point_data || !point_data[:fly_spot]
|
|
raise _INTL("No data for this point defined in town_map.txt somehow.")
|
|
end
|
|
if @mode != :fly
|
|
map_name = pbGetMapNameFromId(point_data[:fly_spot][0])
|
|
return false if !show_confirm_message(_INTL("Would you like to use Fly to go to {1}?", map_name))
|
|
end
|
|
@result = point_data[:fly_spot]
|
|
return true
|
|
end
|
|
end
|
|
|
|
#===============================================================================
|
|
#
|
|
#===============================================================================
|
|
# Shows a choice menu using the MenuHandlers options below.
|
|
UIActionHandlers.add(UI::TownMap::SCREEN_ID, :screen_menu, {
|
|
:menu => :town_map_menu,
|
|
:menu_message => proc { |screen| _INTL("Choose an option.") }
|
|
})
|
|
|
|
UIActionHandlers.add(UI::TownMap::SCREEN_ID, :fly_mode, {
|
|
:effect => proc { |screen|
|
|
screen.start_fly_mode
|
|
}
|
|
})
|
|
|
|
UIActionHandlers.add(UI::TownMap::SCREEN_ID, :use_fly, {
|
|
:returns_value => true,
|
|
:effect => proc { |screen|
|
|
next (screen.set_fly_destination) ? :quit : :none
|
|
}
|
|
})
|
|
|
|
UIActionHandlers.add(UI::TownMap::SCREEN_ID, :change_region, {
|
|
:effect => proc { |screen|
|
|
commands = {}
|
|
index = 0
|
|
screen.visited_regions.each do |region|
|
|
region_data = GameData::TownMap.get(region)
|
|
index = commands.length if region_data.id == screen.region
|
|
commands[region] = region_data.name
|
|
end
|
|
commands[:cancel] = _INTL("Cancel")
|
|
region = screen.show_choice_message(_INTL("Which region's map do you want to view?"), commands, screen.region)
|
|
screen.set_region(region) if region && region != :cancel
|
|
}
|
|
})
|
|
|
|
UIActionHandlers.add(UI::TownMap::SCREEN_ID, :marking, {
|
|
:effect => proc { |screen|
|
|
screen.visuals.navigate_markings
|
|
screen.refresh
|
|
}
|
|
})
|
|
|
|
#===============================================================================
|
|
# Menu options for choice menus that exist in the party screen.
|
|
#===============================================================================
|
|
MenuHandlers.add(:town_map_menu, :fly_mode, {
|
|
"name" => _INTL("Fly"),
|
|
"order" => 10,
|
|
"condition" => proc { |screen|
|
|
this_map_data = $game_map.metadata&.town_map_position
|
|
current_region = (this_map_data) ? this_map_data[0] : 0
|
|
next Settings::CAN_FLY_FROM_TOWN_MAP && pbCanFly? && screen.mode == :normal &&
|
|
current_region == screen.region && screen.has_fly_points?
|
|
}
|
|
})
|
|
|
|
MenuHandlers.add(:town_map_menu, :change_region, {
|
|
"name" => _INTL("Change region"),
|
|
"order" => 20,
|
|
"condition" => proc { |screen|
|
|
next screen.mode == :normal && screen.visited_regions.length >= 2
|
|
}
|
|
})
|
|
|
|
MenuHandlers.add(:town_map_menu, :cancel, {
|
|
"name" => _INTL("Cancel"),
|
|
"order" => 9999
|
|
})
|
|
|
|
#===============================================================================
|
|
#
|
|
#===============================================================================
|
|
def pbShowMap(region = -1, wall_map = true)
|
|
mode = (wall_map) ? :wall_map : :normal
|
|
pbFadeOutIn do
|
|
town_map_screen = UI::TownMap.new(region, mode: mode)
|
|
town_map_screen.main
|
|
$game_temp.fly_destination = town_map_screen.result if town_map_screen.result
|
|
end
|
|
end
|