Files
infinitefusion-e18/Data/Scripts/053_PIF_Hoenn/PokeNav/PokeRadarHoenn/PokeRadarAppScene.rb
T
2026-07-10 15:42:06 -04:00

521 lines
15 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.
# todo:
# When all pokemon in the route are seen, can "scan" for species
# - spawns a pokemon of that species nearby with notice behavior to flee
class PokeRadarAppScene < PokeNavAppScene
INFO_TEXT_Y = 270
def header_name
return _INTL("PokéRadar")
end
def cursor_path
return "Graphics/Pictures/Pokeradar/icon_button"
end
def header_path
return "Graphics/Pictures/Pokeradar/bg_header"
end
def display_mode
return :GRID
end
def x_gap
return 75;
end
def y_gap
return 50;
end
def columns
return 6
end
def visible_rows
return 3
end
def start_x
return 40;
end
def start_y
return 80;
end
def pbStartScene(main_menu_scene)
@unseenPokemon = [] unless @unseenPokemon
@seenPokemon = [] unless @seenPokemon
@pokenav_main_menu_scene = main_menu_scene
if $PokemonTemp.pokeradar
buttons = showCurrentScanningTarget
super(buttons)
else
buttons = showWildPokemonList
super(buttons)
showSelectedPokemonInfo
end
showHeaderInfo
end
def showSelectedPokemonInfo
hover(@buttons[@index]&.id)
if @unseenPokemon.empty? && @seenPokemon.empty?
showEmpty
end
end
def showHeaderInfo
showBattery
showHeaderName
showAreaName
showWeatherIcon
end
def showWildPokemonList
@encounter_type = $PokemonEncounters.encounter_type
@weatherEncounters = $PokemonEncounters.list_weather_encounters_species(@encounter_type)
@unseenPokemon = listPokemonInCurrentRoute(@encounter_type, false, true, true)
@seenPokemon = listPokemonInCurrentRoute(@encounter_type, true, false, true)
buttons = []
@seenPokemon.each do |pokemon_species|
icon_path = pbCheckPokemonIconFiles(pokemon_species)
bmp = load_bitmap(icon_path, false)
button = PokenavButton.new(pokemon_species, bmp)
button.crop_width = button.icon_bitmap.bitmap.width / 2
button.refresh
buttons << button if button
end
@unseenPokemon.each do |pokemon_species|
icon_path = pbCheckPokemonIconFiles(pokemon_species)
bmp = load_bitmap(icon_path, true)
button = PokenavButton.new(pokemon_species, bmp)
button.crop_width = button.icon_bitmap.bitmap.width / 2
button.refresh
buttons << button
end
return buttons
end
def createCursor
return if $PokemonTemp.pokeradar
super
end
def showEmpty
Kernel.pbDisplayText(_INTL("No wild Pokémon found nearby."), Graphics.width / 2, Graphics.height / 2, nil, @text_color_base, @text_color_shadow)
Kernel.pbDisplayText(_INTL("Stand in tall grass to start scanning."), Graphics.width / 2,( Graphics.height / 2)+32, nil, @text_color_base, @text_color_shadow)
end
def showCurrentScanningTarget
scanningPokemon = $PokemonTemp.pokeradar[0]
icon_path = pbCheckPokemonIconFiles(scanningPokemon)
bmp = load_bitmap(icon_path, false)
button = PokenavButton.new(scanningPokemon, bmp)
button.refresh
species_name = GameData::Species.get(scanningPokemon).name
Kernel.pbDisplayText(_INTL("Currently scanning for {1}.", species_name), Graphics.width / 2, 200, 500000, @text_color_base, @text_color_shadow)
Kernel.pbDisplayText(_INTL("Current chain: {1}.", $PokemonTemp.pokeradar[2]), Graphics.width / 2, 230, 500000, @text_color_base, @text_color_shadow)
return [button]
end
def load_bitmap(path, dark = false)
return nil unless path && path != ""
bmp = Bitmap.new(path)
if dark
darken_bitmap(bmp, 220) # strength 0255
end
return AnimatedBitmap.from_bitmap(bmp)
end
def darken_bitmap(bmp, amount)
for x in 0...bmp.width
for y in 0...bmp.height
pixel = bmp.get_pixel(x, y)
next if pixel.alpha == 0
factor = (255 - amount) / 255.0
r = (pixel.red * factor).to_i
g = (pixel.green * factor).to_i
b = (pixel.blue * factor).to_i
bmp.set_pixel(x, y, Color.new(r, g, b, pixel.alpha))
end
end
end
#[rareness, species, minLevel, maxLevel]
def get_encounter(species,include_weather=true)
for encounter in $PokemonEncounters.listPossibleEncounters(@encounter_type, include_weather)
if encounter[1] == species
return encounter
end
end
return nil
end
def get_weather_encounter(species)
for encounter in $PokemonEncounters.list_weather_encounters(@encounter_type)
if encounter[1] == species
return encounter
end
end
return nil
end
def get_energy_for_scan(species)
encounter = get_encounter(species)
if @weatherEncounters.include?(species)
base_rareness = encounter[0]
rareness =calculate_weather_encounter_rareness(encounter,base_rareness)
else
rareness = encounter[0]
end
energy = (110 - rareness) * 5
(energy / 50.0).round * 50
end
def get_rarity_flavor_text(species)
encounter = get_encounter(species,false)
weather_encounter = get_weather_encounter(species)
return unless encounter || weather_encounter
if (encounter && encounter[1] == species) || (weather_encounter && weather_encounter[1] == species)
base_rareness =0
base_rareness = encounter[0] if encounter
base_rareness = weather_encounter[0] if weather_encounter
if @weatherEncounters.include?(species)
rareness = calculate_weather_encounter_rareness(weather_encounter,base_rareness)
else
rareness = base_rareness
end
if rareness < 5
text = _INTL("Very rare")
elsif rareness < 10
text = _INTL("Rare")
elsif rareness < 25
text = _INTL("Uncommon")
elsif rareness < 40
text = _INTL("Common")
else
text = _INTL("Very Common")
end
return text
end
end
def calculate_weather_encounter_rareness(encounter,base_rareness)
map_weather = $game_weather.current_weather[$game_map.map_id]
if map_weather
weather_intensity = map_weather[1]
weather_intensity = 0 if !weather_intensity
chance_of_weather_encounter = $PokemonEncounters.weather_encounter_chance(weather_intensity)
weather_rareness = encounter[0]
return weather_rareness * (chance_of_weather_encounter.to_f / 100) * (base_rareness/100)
end
return 0
end
def click(button_id)
species = button_id
if $PokemonTemp.pokeradar
click_stop_scan(species)
else
if @seenPokemon.include?(species)
click_seen(species)
else
click_unseen
end
end
super
end
def hover(button_id)
return if $PokemonTemp.pokeradar
if @seenPokemon.include?(button_id)
hover_seen(button_id)
else
hover_unseen
end
super
end
def click_stop_scan(species)
species_name = GameData::Species.get(species).name
options = []
cmd_stop_scan = _INTL("Stop Scanning")
cmd_cancel = _INTL("Cancel")
options << cmd_stop_scan
options << cmd_cancel
Kernel.pbClearText()
showHeaderInfo
chosen = pbMessage(_INTL("You are currently scanning for {1}.", species_name), options, options.length)
case options[chosen]
when cmd_stop_scan
$PokemonTemp.pokeradar = nil
pbEndScene
pbStartScene(@pokenav_main_menu_scene)
else
showCurrentScanningTarget
return
end
end
def click_seen(species)
options = []
cmd_scan = _INTL("Scan")
cmd_cancel = _INTL("Cancel")
options << cmd_scan
options << cmd_cancel
Kernel.pbClearText()
showHeaderInfo
chosen = pbMessage(_INTL("What would you like to do?"), options, options.length)
case options[chosen]
when cmd_scan
energy_needed = get_energy_for_scan(species)
if Settings::POKERADAR_BATTERY_STEPS - $PokemonGlobal.pokeradarBattery >= energy_needed
$PokemonGlobal.pokeradarBattery += energy_needed
displayTextElements
@exiting = true
pbEndScene
@pokenav_main_menu_scene.exiting = true
@pokenav_main_menu_scene.pbEndScene
encounter = get_encounter(species)
min_level = encounter[2]
max_level = encounter[3]
level = rand(min_level..max_level)
pbWait(16)
pbMessage(_INTL("Scanning for {1}...\\wtnp[5]", GameData::Species.get(species).name))
possible_tiles = getTerrainTilesNearPlayer(getTerrainType, 3)
position = possible_tiles.sample
if position
set_pokeradar_data(species, level, position)
spawn_pokeradar_pokemon(species, level)
else
pbPokeRadarCancel
pbMessage(_INTL("The Pokéradar scan failed... Try again somewhere else"))
end
else
pbPokeRadarCancel
Kernel.pbClearText()
showHeaderInfo
pbMessage(_INTL("The battery is not charged enough for this scan!"))
showSelectedPokemonInfo
end
else
showSelectedPokemonInfo
return
end
end
def click_unseen
return unless @unseenPokemon.any?
Kernel.pbClearText()
showHeaderInfo
pbMessage(_INTL("You need to encounter the Pokémon before you can scan for it."))
hover_unseen
end
def hover_seen(species)
displayTextElements
pokemon_name = GameData::Species.get(species).name
Kernel.pbDisplayText(pokemon_name, Graphics.width / 2, INFO_TEXT_Y, 99999, @text_color_base, @text_color_shadow)
Kernel.pbDisplayText(get_rarity_flavor_text(species), Graphics.width / 2, INFO_TEXT_Y + 30, 99999, @text_color_base, @text_color_shadow)
Kernel.pbDisplayText(_INTL("Battery for scan: {1}", get_energy_for_scan(species)), Graphics.width / 2, INFO_TEXT_Y + 60, 99999, @text_color_base, @text_color_shadow)
end
def hover_unseen()
return unless @unseenPokemon.any?
displayTextElements
pokemon_name = _INTL("Unknown Pokémon")
Kernel.pbDisplayText(pokemon_name, Graphics.width / 2, INFO_TEXT_Y, 999999, @text_color_base, @text_color_shadow)
end
def displayTextElements
super
showBattery
showAreaName
end
def showBattery
$PokemonGlobal.pokeradarBattery = Settings::POKERADAR_BATTERY_STEPS unless $PokemonGlobal.pokeradarBattery
battery_power = Settings::POKERADAR_BATTERY_STEPS - $PokemonGlobal.pokeradarBattery
Kernel.pbDisplayText(_INTL("{1}/1000", battery_power), 450, HEADER_HEIGHT,nil, @text_color_base, @text_color_shadow)
end
def showAreaName
map_name = getMapName($game_map.map_id)
text = _INTL("{1}", map_name)
encounter_type = get_encounter_type_name
if encounter_type && !encounter_type.empty?
text += _INTL(" ({1})", encounter_type)
end
Kernel.pbDisplayText(text, Graphics.width / 2, 40,nil, @text_color_base, @text_color_shadow)
end
def showWeatherIcon
icon_path = get_current_weather_icon
return unless icon_path
@sprites["weather"] = IconSprite.new(400, 48, @viewport)
@sprites["weather"].setBitmap(icon_path)
@sprites["weather"].z = 100000
end
def get_encounter_type_name
encounter_type = $PokemonEncounters.encounter_type
case encounter_type
when :Land
return _INTL("Grass")
when :Land1
return _INTL("Clovers")
when :Land2
return _INTL("Dry Grass")
when :Land3
return _INTL("Flowers")
when :LandMorning, :LandDay, :LandNight
return _INTL("Grass")
when :WaterMorning, :WaterDay, :WaterNight
return _INTL("Water")
when :TallGrass
return _INTL("Tall Grass")
else
return encounter_type.to_s
end
end
end
def getTerrainType
encounter_type = $PokemonEncounters.encounter_type
case encounter_type
when :Land, :Land1, :Land2, :Land3, :LandMorning, :LandDay, :LandNight, :TallGrass
return :Grass
else
return encounter_type
end
end
def continue_pokeradar_app_chain()
pbWait(12)
species = $PokemonTemp.pokeradar[0]
level = $PokemonTemp.pokeradar[1]
possible_tiles = getTerrainTilesNearPlayer(getTerrainType, 3)
position = possible_tiles.sample
if position
set_pokeradar_data(species, level, position)
spawn_pokeradar_pokemon(species, level)
else
pbPokeRadarCancel
pbMessage(_INTL("The Pokéradar scan failed... Try again somewhere else"))
end
end
def update_pokeradar_overworld_ui
if $PokemonTemp.pokeradar
current_chain = $PokemonTemp.pokeradar[2]
return unless current_chain >= 1
species = $PokemonTemp.pokeradar[0]
$PokemonTemp.pokeradar_ui.dispose if $PokemonTemp.pokeradar_ui
$PokemonTemp.pokeradar_ui = PokeRadar_UI.new([species], [], [])
if current_chain >= 40
$PokemonTemp.pokeradar_ui.set_text(_INTL("PokéRadar Chain: {1}", current_chain), 72, 12, pbColor(:GREEN), pbColor(:DARKGREEN))
else
$PokemonTemp.pokeradar_ui.set_text(_INTL("PokéRadar Chain: {1}", current_chain), 72, 12)
end
else
$PokemonTemp.pokeradar_ui.dispose if $PokemonTemp.pokeradar_ui
end
end
def spawn_pokeradar_pokemon(species, level)
max_attempts = 50
return unless species && level
pbWait(20)
playAnimation(Settings::POKERADAR_LIGHT_ANIMATION_RED_ID, $game_player.x, $game_player.y)
pbWait(10)
spawned_events = nil
radius = 4
max_radius = 8
max_attempts.times do |current_attempt|
radius += 1 if current_attempt > 0 && current_attempt % 10 == 0
radius += (current_attempt / 10).floor
radius = [radius, max_radius].min
spawned_events = spawn_ow_pokemon(species, level, 1, radius)
break if spawned_events&.length.to_i > 0
end
if spawned_events&.length.to_i > 0
event = spawned_events[0]
grass = $PokemonTemp&.pokeradar[3]
if grass && grass[3] == 2
pbSEPlay("shiny", 60)
playAnimation(Settings::SPARKLE_SHORT_ANIMATION_ID, event.x, event.y)
event.make_shiny
end
#todo: MAYBE increase the move frequency past a certain chain number (50?) to make it more difficult
event.behavior_roaming = :look_around_player
event.behavior_noticed = event.pokemon.shiny? ? :curious : :flee
event.update_movement_type
event.turn_away_from_player
playAnimation(Settings::POKERADAR_LIGHT_ANIMATION_RED_ID, event.x, event.y)
else
echoln "failed to spawn after #{max_attempts} attempts"
pbPokeRadarCancel
pbMessage(_INTL("The Pokéradar scan failed... Try again somewhere else"))
end
update_pokeradar_overworld_ui
end
# Reusing the old pokeradar mechanics for chaining
def set_pokeradar_data(species, level, position)
x = position[0]
y = position[1]
existing_chain = ($PokemonTemp.pokeradar && $PokemonTemp.pokeradar[2]) ? $PokemonTemp.pokeradar[2] : 0
$PokemonTemp.pokeradar = [0, 0, 0, []] unless $PokemonTemp.pokeradar
$PokemonTemp.pokeradar[0] = species
$PokemonTemp.pokeradar[1] = level
$PokemonTemp.pokeradar[2] = existing_chain
$PokemonTemp.pokeradar[3] = [x, y, 0, determine_shininess]
end
def determine_shininess
chain_length = ($PokemonTemp.pokeradar && $PokemonTemp.pokeradar[2]) ? $PokemonTemp.pokeradar[2] : 0
rarity = (rand(100) < 25) ? 1 : 0
if chain_length > 0
capped_chain = [chain_length, 40].min
shiny_threshold = [(65536 / Settings::SHINY_POKEMON_CHANCE) - capped_chain * 200, 200].max
shiny_divisor = 0xFFFF / shiny_threshold
shiny_roll = rand(65536) / shiny_divisor
rarity = 2 if shiny_roll == 0
end
return rarity
end
Events.onMapChange += proc { |_sender, e|
pbPokeRadarCancel
}