diff --git a/Data/Scripts/003_Game processing/002_Scene_Map.rb b/Data/Scripts/003_Game processing/002_Scene_Map.rb index ceafdadef..d09d9ac90 100644 --- a/Data/Scripts/003_Game processing/002_Scene_Map.rb +++ b/Data/Scripts/003_Game processing/002_Scene_Map.rb @@ -156,7 +156,7 @@ class Scene_Map @spritesetGlobal.update pbDayNightTint(@map_renderer) @map_renderer.update - Events.onMapUpdate.trigger(self) + EventHandlers.trigger(:on_frame_update) end def update @@ -214,7 +214,7 @@ class Scene_Map elsif $game_temp.interact_calling $game_temp.interact_calling = false $game_player.straighten - Events.onAction.trigger(self) + EventHandlers.trigger(:on_player_interact) end end end diff --git a/Data/Scripts/003_Game processing/005_Event_Handlers.rb b/Data/Scripts/003_Game processing/005_Event_Handlers.rb index d2efe92d3..03d000989 100644 --- a/Data/Scripts/003_Game processing/005_Event_Handlers.rb +++ b/Data/Scripts/003_Game processing/005_Event_Handlers.rb @@ -60,7 +60,38 @@ class Event end #=============================================================================== -# +# Same as class Event, but each registered proc has a name (a symbol) so it can +# be referenced individually. +#=============================================================================== +class NamedEvent + def initialize + @callbacks = {} + end + + # Adds an event handler procedure from the event. + def add(key, proc) + @callbacks[key] = proc if !@callbacks.has_key?(key) + end + + # Removes an event handler procedure from the event. + def remove(key) + @callbacks.delete(key) + end + + # Clears the event of event handlers. + def clear + @callbacks.clear + end + + # Triggers the event and calls all its event handlers. Normally called only + # by the code where the event occurred. + def trigger(*args) + @callbacks.each_value { |callback| callback.call(*args) } + end +end + +#=============================================================================== +# Unused. #=============================================================================== class HandlerHash def initialize(mod) @@ -144,7 +175,8 @@ end #=============================================================================== # A stripped-down version of class HandlerHash which only deals with symbols and -# doesn't care about whether those symbols actually relate to a defined thing. +# doesn't care about whether those symbols are defined as constants in a class +# or module. #=============================================================================== class HandlerHash2 def initialize diff --git a/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb b/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb new file mode 100644 index 000000000..eeb0ccc92 --- /dev/null +++ b/Data/Scripts/003_Game processing/006_Event_HandlerCollections.rb @@ -0,0 +1,65 @@ +#=============================================================================== +# This module stores events that can happen during the game. A procedure can +# subscribe to an event by adding itself to the event. It will then be called +# whenever the event occurs. Existing events are: +#------------------------------------------------------------------------------- +# :on_game_map_setup - When a Game_Map is set up. Typically changes map data. +# :on_new_spriteset_map - When a Spriteset_Map is created. Adds more things to +# show in the overworld. +# :on_frame_update - Once per frame. Various frame/time counters. +# :on_leave_map - When leaving a map. End weather/expired effects. +# :on_enter_map - Upon entering a new map. Set up new effects, end expired +# effects. +# :on_map_or_spriteset_change - Upon entering a new map or when spriteset was +# made. Show things on-screen. +#------------------------------------------------------------------------------- +# :on_player_change_direction - When the player turns in a different direction. +# :on_leave_tile - When any event or the player starts to move from a tile. +# :on_step_taken - When any event or the player finishes a step. +# :on_player_step_taken - When the player finishes a step/ends surfing, except +# as part of a move route. Step-based counters. +# :on_player_step_taken_can_transfer - When the player finishes a step/ends +# surfing, except as part of a move route. Step-based effects that can +# transfer the player elsewhere. +# :on_player_interact - When the player presses the Use button in the +# overworld. +#------------------------------------------------------------------------------- +# :on_trainer_load - When an NPCTrainer is generated (to battle against or as +# a registered partner). Various modifications to that trainer and their +# Pokémon. +# :on_wild_species_chosen - When a species/level have been chosen for a wild +# encounter. Changes the species/level (e.g. roamer, Poké Radar chain). +# :on_wild_pokemon_created - When a Pokemon object has been created for a wild +# encounter. Various modifications to that Pokémon. +# :on_calling_wild_battle - When a wild battle is called. Prevents that wild +# battle and instead starts a different kind of battle (e.g. Safari Zone). +# :on_start_battle - Just before a battle starts. Memorize/reset information +# about party Pokémon, which is used after battle for evolution checks. +# :on_end_battle - Just after a battle ends. Evolution checks, Pickup/Honey +# Gather, blacking out. +# :on_wild_battle_end - After a wild battle. Updates Poké Radar chain info. +#=============================================================================== +module EventHandlers + @@events = {} + + # Add a named callback for the given event. + def self.add(event, key, proc) + @@events[event] = NamedEvent.new if !@@events.has_key?(event) + @@events[event].add(key, proc) + end + + # Remove a named callback from the given event. + def self.remove(event, key) + @@events[event]&.remove(key) + end + + # Clear all callbacks for the given event. + def self.clear(key) + @@events[key]&.clear + end + + # Trigger all callbacks from an Event if it has been defined. + def self.trigger(event, *args) + return @@events[event]&.trigger(*args) + end +end diff --git a/Data/Scripts/003_Game processing/006_Event_OverworldEvents.rb b/Data/Scripts/003_Game processing/006_Event_OverworldEvents.rb deleted file mode 100644 index 6d91bc9de..000000000 --- a/Data/Scripts/003_Game processing/006_Event_OverworldEvents.rb +++ /dev/null @@ -1,172 +0,0 @@ -#=============================================================================== -# This module stores events that can happen during the game. A procedure can -# subscribe to an event by adding itself to the event. It will then be called -# whenever the event occurs. -#=============================================================================== -module Events - @@OnMapCreate = Event.new - @@OnMapUpdate = Event.new - @@OnMapChange = Event.new - @@OnMapChanging = Event.new - @@OnMapSceneChange = Event.new - @@OnSpritesetCreate = Event.new - @@OnAction = Event.new - @@OnStepTaken = Event.new - @@OnLeaveTile = Event.new - @@OnStepTakenFieldMovement = Event.new - @@OnStepTakenTransferPossible = Event.new - @@OnStartBattle = Event.new - @@OnEndBattle = Event.new - @@OnWildPokemonCreate = Event.new - @@OnWildBattleOverride = Event.new - @@OnWildBattleEnd = Event.new - @@OnTrainerPartyLoad = Event.new - @@OnChangeDirection = Event.new - - # Fires whenever a map is created. Event handler receives two parameters: the - # map (RPG::Map) and the tileset (RPG::Tileset) - def self.onMapCreate; @@OnMapCreate; end - def self.onMapCreate=(v); @@OnMapCreate = v; end - - # Fires each frame during a map update. - def self.onMapUpdate; @@OnMapUpdate; end - def self.onMapUpdate=(v); @@OnMapUpdate = v; end - - # Fires whenever one map is about to change to a different one. Event handler - # receives the new map ID and the Game_Map object representing the new map. - # When the event handler is called, $game_map still refers to the old map. - def self.onMapChanging; @@OnMapChanging; end - def self.onMapChanging=(v); @@OnMapChanging = v; end - - # Fires whenever the player moves to a new map. Event handler receives the old - # map ID or 0 if none. Also fires when the first map of the game is loaded - def self.onMapChange; @@OnMapChange; end - def self.onMapChange=(v); @@OnMapChange = v; end - - # Fires whenever the map scene is regenerated and soon after the player moves - # to a new map. - # Parameters: - # e[0] - Scene_Map object. - # e[1] - Whether the player just moved to a new map (either true or false). If - # false, some other code had called $scene.createSpritesets to - # regenerate the map scene without transferring the player elsewhere - def self.onMapSceneChange; @@OnMapSceneChange; end - def self.onMapSceneChange=(v); @@OnMapSceneChange = v; end - - # Fires whenever a spriteset is created. - # Parameters: - # e[0] - Spriteset being created. e[0].map is the map associated with the - # spriteset (not necessarily the current map). - # e[1] - Viewport used for tilemap and characters - def self.onSpritesetCreate; @@OnSpritesetCreate; end - def self.onSpritesetCreate=(v); @@OnSpritesetCreate = v; end - - # Triggers when the player presses the Action button on the map. - def self.onAction; @@OnAction; end - def self.onAction=(v); @@OnAction = v; end - - # Fires whenever the player takes a step. - def self.onStepTaken; @@OnStepTaken; end - def self.onStepTaken=(v); @@OnStepTaken = v; end - - # Fires whenever the player or another event leaves a tile. - # Parameters: - # e[0] - Event that just left the tile. - # e[1] - Map ID where the tile is located (not necessarily - # the current map). Use "$map_factory.getMap(e[1])" to - # get the Game_Map object corresponding to that map. - # e[2] - X-coordinate of the tile - # e[3] - Y-coordinate of the tile - def self.onLeaveTile; @@OnLeaveTile; end - def self.onLeaveTile=(v); @@OnLeaveTile = v; end - - # Fires whenever the player or another event enters a tile. - # Parameters: - # e[0] - Event that just entered a tile. - def self.onStepTakenFieldMovement; @@OnStepTakenFieldMovement; end - def self.onStepTakenFieldMovement=(v); @@OnStepTakenFieldMovement = v; end - - # Fires whenever the player takes a step. The event handler may possibly move - # the player elsewhere. - # Parameters: - # e[0] - Array that contains a single boolean value. If an event handler moves - # the player to a new map, it should set this value to true. Other - # event handlers should check this parameter's value. - def self.onStepTakenTransferPossible; @@OnStepTakenTransferPossible; end - def self.onStepTakenTransferPossible=(v); @@OnStepTakenTransferPossible = v; end - - def self.onStartBattle; @@OnStartBattle; end - def self.onStartBattle=(v); @@OnStartBattle = v; end - - def self.onEndBattle; @@OnEndBattle; end - def self.onEndBattle=(v); @@OnEndBattle = v; end - - # Triggers whenever a wild Pokémon is created - # Parameters: - # e[0] - Pokémon being created - def self.onWildPokemonCreate; @@OnWildPokemonCreate; end - def self.onWildPokemonCreate=(v); @@OnWildPokemonCreate = v; end - - # Triggers at the start of a wild battle. Event handlers can provide their - # own wild battle routines to override the default behavior. - def self.onWildBattleOverride; @@OnWildBattleOverride; end - def self.onWildBattleOverride=(v); @@OnWildBattleOverride = v; end - - # Triggers whenever a wild Pokémon battle ends - # Parameters: - # e[0] - Pokémon species - # e[1] - Pokémon level - # e[2] - Battle result (1-win, 2-loss, 3-escaped, 4-caught, 5-draw) - def self.onWildBattleEnd; @@OnWildBattleEnd; end - def self.onWildBattleEnd=(v); @@OnWildBattleEnd = v; end - - # Triggers whenever an NPC trainer's Pokémon party is loaded - # Parameters: - # e[0] - Trainer - # e[1] - Items possessed by the trainer - # e[2] - Party - def self.onTrainerPartyLoad; @@OnTrainerPartyLoad; end - def self.onTrainerPartyLoad=(v); @@OnTrainerPartyLoad = v; end - - # Fires whenever the player changes direction. - def self.onChangeDirection; @@OnChangeDirection; end - def self.onChangeDirection=(v); @@OnChangeDirection = v; end -end - -#=============================================================================== -# -#=============================================================================== -def pbOnSpritesetCreate(spriteset, viewport) - Events.onSpritesetCreate.trigger(nil, spriteset, viewport) -end - -#=============================================================================== -# This module stores encounter-modifying events that can happen during the game. -# A procedure can subscribe to an event by adding itself to the event. It will -# then be called whenever the event occurs. -#=============================================================================== -module EncounterModifier - @@procs = [] - @@procsEnd = [] - - def self.register(p) - @@procs.push(p) - end - - def self.registerEncounterEnd(p) - @@procsEnd.push(p) - end - - def self.trigger(encounter) - @@procs.each do |prc| - encounter = prc.call(encounter) - end - return encounter - end - - def self.triggerEncounterEnd - @@procsEnd.each do |prc| - prc.call - end - end -end diff --git a/Data/Scripts/004_Game classes/001_Switches and Variables/001_Game_Temp.rb b/Data/Scripts/004_Game classes/001_Switches and Variables/001_Game_Temp.rb index ce1627aa5..4e3d285a0 100644 --- a/Data/Scripts/004_Game classes/001_Switches and Variables/001_Game_Temp.rb +++ b/Data/Scripts/004_Game classes/001_Switches and Variables/001_Game_Temp.rb @@ -9,7 +9,7 @@ class Game_Temp attr_accessor :menu_calling # menu calling flag attr_accessor :ready_menu_calling # ready menu calling flag attr_accessor :debug_calling # debug calling flag - attr_accessor :interact_calling # trigger Events.onAction flag + attr_accessor :interact_calling # EventHandlers.trigger(:on_player_interact) flag attr_accessor :battle_abort # battle flag: interrupt (unused) attr_accessor :title_screen_calling # return to title screen flag attr_accessor :common_event_id # common event ID to start diff --git a/Data/Scripts/004_Game classes/004_Game_Map.rb b/Data/Scripts/004_Game classes/004_Game_Map.rb index c6e9b6af4..b11e96041 100644 --- a/Data/Scripts/004_Game classes/004_Game_Map.rb +++ b/Data/Scripts/004_Game classes/004_Game_Map.rb @@ -57,7 +57,7 @@ class Game_Map self.display_x = 0 self.display_y = 0 @need_refresh = false - Events.onMapCreate.trigger(self, map_id, @map, tileset) + EventHandlers.trigger(:on_game_map_setup, map_id, @map, tileset) @events = {} @map.events.keys.each do |i| @events[i] = Game_Event.new(@map_id, @map.events[i], self) diff --git a/Data/Scripts/004_Game classes/006_Game_MapFactory.rb b/Data/Scripts/004_Game classes/006_Game_MapFactory.rb index bf0a72af8..3a6c48caf 100644 --- a/Data/Scripts/004_Game classes/006_Game_MapFactory.rb +++ b/Data/Scripts/004_Game classes/006_Game_MapFactory.rb @@ -145,16 +145,16 @@ class PokemonMapFactory end def setMapChanging(newID, newMap) - Events.onMapChanging.trigger(self, newID, newMap) + EventHandlers.trigger(:on_leave_map, newID, newMap) end def setMapChanged(prevMap) - Events.onMapChange.trigger(self, prevMap) + EventHandlers.trigger(:on_enter_map, prevMap) @mapChanged = true end def setSceneStarted(scene) - Events.onMapSceneChange.trigger(self, scene, @mapChanged) + EventHandlers.trigger(:on_map_or_spriteset_change, scene, @mapChanged) @mapChanged = false end diff --git a/Data/Scripts/004_Game classes/007_Game_Character.rb b/Data/Scripts/004_Game classes/007_Game_Character.rb index 757e9e934..83a44b806 100644 --- a/Data/Scripts/004_Game classes/007_Game_Character.rb +++ b/Data/Scripts/004_Game classes/007_Game_Character.rb @@ -382,7 +382,7 @@ class Game_Character def triggerLeaveTile if @oldX && @oldY && @oldMap && (@oldX != self.x || @oldY != self.y || @oldMap != self.map.map_id) - Events.onLeaveTile.trigger(self, self, @oldMap, @oldX, @oldY) + EventHandlers.trigger(:on_leave_tile, self, @oldMap, @oldX, @oldY) end @oldX = self.x @oldY = self.y @@ -918,7 +918,7 @@ class Game_Character end # End of a step, so perform events that happen at this time if !jumping? && !moving? - Events.onStepTakenFieldMovement.trigger(self, self) + EventHandlers.trigger(:on_step_taken, self) calculate_bush_depth @stopped_this_frame = true elsif !@moved_last_frame || @stopped_last_frame # Started a new step diff --git a/Data/Scripts/004_Game classes/009_Game_Player.rb b/Data/Scripts/004_Game classes/009_Game_Player.rb index 9984a5205..6d2022972 100644 --- a/Data/Scripts/004_Game classes/009_Game_Player.rb +++ b/Data/Scripts/004_Game classes/009_Game_Player.rb @@ -141,7 +141,7 @@ class Game_Player < Game_Character old_direction = @direction super(dir) if @direction != old_direction && !@move_route_forcing && !pbMapInterpreterRunning? - Events.onChangeDirection.trigger(self, self) + EventHandlers.trigger(:on_player_change_direction) $game_temp.encounter_triggered = false if !keep_enc_indicator end end diff --git a/Data/Scripts/005_Sprites/007_Spriteset_Map.rb b/Data/Scripts/005_Sprites/007_Spriteset_Map.rb index 9be78e3a9..09fc2bc11 100644 --- a/Data/Scripts/005_Sprites/007_Spriteset_Map.rb +++ b/Data/Scripts/005_Sprites/007_Spriteset_Map.rb @@ -59,7 +59,7 @@ class Spriteset_Map @character_sprites.push(sprite) end @weather = RPG::Weather.new(@@viewport1) - pbOnSpritesetCreate(self, @@viewport1) + EventHandlers.trigger(:on_new_spriteset_map, self, @@viewport1) update end diff --git a/Data/Scripts/010_Data/001_Hardcoded data/011_TerrainTag.rb b/Data/Scripts/010_Data/001_Hardcoded data/011_TerrainTag.rb index dd737bebd..575dee5ef 100644 --- a/Data/Scripts/010_Data/001_Hardcoded data/011_TerrainTag.rb +++ b/Data/Scripts/010_Data/001_Hardcoded data/011_TerrainTag.rb @@ -170,8 +170,9 @@ GameData::TerrainTag.register({ :ignore_passability => true }) -# NOTE: This is referenced by ID in an Events.onStepTakenFieldMovement proc that -# adds soot to the Soot Sack if the player walks over one of these tiles. +# NOTE: This is referenced by ID in the :pick_up_soot proc added to +# EventHandlers. It adds soot to the Soot Sack if the player walks over +# one of these tiles. GameData::TerrainTag.register({ :id => :SootGrass, :id_number => 14, diff --git a/Data/Scripts/012_Overworld/001_Overworld visuals/002_Overworld_Overlays.rb b/Data/Scripts/012_Overworld/001_Overworld visuals/002_Overworld_Overlays.rb index 68ba42f30..0ba7e1c61 100644 --- a/Data/Scripts/012_Overworld/001_Overworld visuals/002_Overworld_Overlays.rb +++ b/Data/Scripts/012_Overworld/001_Overworld visuals/002_Overworld_Overlays.rb @@ -205,22 +205,22 @@ end -Events.onSpritesetCreate += proc { |_sender, e| - spriteset = e[0] # Spriteset being created - viewport = e[1] # Viewport used for tilemap and characters - map = spriteset.map # Map associated with the spriteset (not necessarily the current map) - map.events.keys.each do |i| - if map.events[i].name[/^outdoorlight\((\w+)\)$/i] - filename = $~[1].to_s - spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i], viewport, map, filename)) - elsif map.events[i].name[/^outdoorlight$/i] - spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i], viewport, map)) - elsif map.events[i].name[/^light\((\w+)\)$/i] - filename = $~[1].to_s - spriteset.addUserSprite(LightEffect_Basic.new(map.events[i], viewport, map, filename)) - elsif map.events[i].name[/^light$/i] - spriteset.addUserSprite(LightEffect_Basic.new(map.events[i], viewport, map)) +EventHandlers.add(:on_new_spriteset_map, :add_light_effects, + proc { |spriteset, viewport| + map = spriteset.map # Map associated with the spriteset (not necessarily the current map) + map.events.keys.each do |i| + if map.events[i].name[/^outdoorlight\((\w+)\)$/i] + filename = $~[1].to_s + spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i], viewport, map, filename)) + elsif map.events[i].name[/^outdoorlight$/i] + spriteset.addUserSprite(LightEffect_DayNight.new(map.events[i], viewport, map)) + elsif map.events[i].name[/^light\((\w+)\)$/i] + filename = $~[1].to_s + spriteset.addUserSprite(LightEffect_Basic.new(map.events[i], viewport, map, filename)) + elsif map.events[i].name[/^light$/i] + spriteset.addUserSprite(LightEffect_Basic.new(map.events[i], viewport, map)) + end end - end - spriteset.addUserSprite(Particle_Engine.new(viewport, map)) -} + spriteset.addUserSprite(Particle_Engine.new(viewport, map)) + } +) diff --git a/Data/Scripts/012_Overworld/001_Overworld.rb b/Data/Scripts/012_Overworld/001_Overworld.rb index 552746f98..8e36aef11 100644 --- a/Data/Scripts/012_Overworld/001_Overworld.rb +++ b/Data/Scripts/012_Overworld/001_Overworld.rb @@ -2,17 +2,18 @@ # Constant checks #=============================================================================== # Pokérus check -Events.onMapUpdate += proc { |_sender, _e| - next if !$player - last = $PokemonGlobal.pokerusTime - now = pbGetTimeNow - if !last || last.year != now.year || last.month != now.month || last.day != now.day - $player.pokemon_party.each do |i| - i.lowerPokerusCount +EventHandlers.add(:on_frame_update, :pokerus_counter, + proc { + next if !$player + last = $PokemonGlobal.pokerusTime + next if !last + now = pbGetTimeNow + if last.year != now.year || last.month != now.month || last.day != now.day + $player.pokemon_party.each { |pkmn| pkmn.lowerPokerusCount } + $PokemonGlobal.pokerusTime = now end - $PokemonGlobal.pokerusTime = now - end -} + } +) # Returns whether the Poké Center should explain Pokérus to the player, if a # healed Pokémon has it. @@ -46,70 +47,74 @@ def pbBatteryLow? return false end -Events.onMapUpdate += proc { |_sender, _e| - if !$game_temp.warned_low_battery && pbBatteryLow? && - !$game_temp.in_menu && !$game_temp.in_battle && !$game_player.move_route_forcing && - !$game_temp.message_window_showing && !pbMapInterpreterRunning? && - pbGetTimeNow.sec == 0 - pbMessage(_INTL("The game has detected that the battery is low. You should save soon to avoid losing your progress.")) +EventHandlers.add(:on_frame_update, :low_battery_warning, + proc { + next if $game_temp.warned_low_battery || !pbBatteryLow? + next if $game_temp.in_menu || $game_temp.in_battle || $game_player.move_route_forcing || + $game_temp.message_window_showing || pbMapInterpreterRunning? + next if pbGetTimeNow.sec != 0 $game_temp.warned_low_battery = true - end - if $game_temp.cue_bgm_frame_delay + pbMessage(_INTL("The game has detected that the battery is low. You should save soon to avoid losing your progress.")) + } +) + +EventHandlers.add(:on_frame_update, :cue_bgm_after_delay, + proc { + next if $game_temp.cue_bgm_frame_delay.nil? $game_temp.cue_bgm_frame_delay -= 1 - if $game_temp.cue_bgm_frame_delay <= 0 - $game_temp.cue_bgm_frame_delay = nil - pbBGMPlay($game_temp.cue_bgm) if $game_system.getPlayingBGM.nil? - end - end -} - - + next if $game_temp.cue_bgm_frame_delay > 0 + $game_temp.cue_bgm_frame_delay = nil + pbBGMPlay($game_temp.cue_bgm) if $game_system.getPlayingBGM.nil? + } +) #=============================================================================== # Checks per step #=============================================================================== # Party Pokémon gain happiness from walking -Events.onStepTaken += proc { - $PokemonGlobal.happinessSteps = 0 if !$PokemonGlobal.happinessSteps - $PokemonGlobal.happinessSteps += 1 - if $PokemonGlobal.happinessSteps >= 128 +EventHandlers.add(:on_player_step_taken, :gain_happiness, + proc { + $PokemonGlobal.happinessSteps = 0 if !$PokemonGlobal.happinessSteps + $PokemonGlobal.happinessSteps += 1 + next if $PokemonGlobal.happinessSteps < 128 $player.able_party.each do |pkmn| pkmn.changeHappiness("walking") if rand(2) == 0 end $PokemonGlobal.happinessSteps = 0 - end -} + } +) # Poison party Pokémon -Events.onStepTakenTransferPossible += proc { |_sender, e| - handled = e[0] - next if handled[0] - if $PokemonGlobal.stepcount % 4 == 0 && Settings::POISON_IN_FIELD +EventHandlers.add(:on_player_step_taken_can_transfer, :poison_party, + proc { |handled| + # handled is an array: [nil]. If [true], a message has already been shown + # because of this step, so don't do anything that might show another one + next if handled[0] + next if !Settings::POISON_IN_FIELD || $PokemonGlobal.stepcount % 4 != 0 flashed = false - $player.able_party.each do |i| - if i.status == :POISON && !i.hasAbility?(:IMMUNITY) - if !flashed - pbFlash(Color.new(255, 0, 0, 128), 8) - flashed = true - end - i.hp -= 1 if i.hp > 1 || Settings::POISON_FAINT_IN_FIELD - if i.hp == 1 && !Settings::POISON_FAINT_IN_FIELD - i.status = :NONE - pbMessage(_INTL("{1} survived the poisoning.\\nThe poison faded away!\1", i.name)) - next - elsif i.hp == 0 - i.changeHappiness("faint") - i.status = :NONE - pbMessage(_INTL("{1} fainted...", i.name)) - end - if $player.able_pokemon_count == 0 - handled[0] = true - pbCheckAllFainted - end + $player.able_party.each do |pkmn| + next if pkmn.status != :POISON || pkmn.hasAbility?(:IMMUNITY) + if !flashed + pbFlash(Color.new(255, 0, 0, 128), 8) + flashed = true + end + pkmn.hp -= 1 if pkmn.hp > 1 || Settings::POISON_FAINT_IN_FIELD + if pkmn.hp == 1 && !Settings::POISON_FAINT_IN_FIELD + pkmn.status = :NONE + pbMessage(_INTL("{1} survived the poisoning.\\nThe poison faded away!\1", pkmn.name)) + next + elsif pkmn.hp == 0 + pkmn.changeHappiness("faint") + pkmn.status = :NONE + pbMessage(_INTL("{1} fainted...", pkmn.name)) + end + if $player.able_pokemon_count == 0 + handled[0] = true + pbCheckAllFainted end end - end -} + } +) def pbCheckAllFainted if $player.able_pokemon_count == 0 @@ -122,67 +127,74 @@ def pbCheckAllFainted end # Gather soot from soot grass -Events.onStepTakenFieldMovement += proc { |_sender, e| - event = e[0] # Get the event affected by field movement - thistile = $map_factory.getRealTilePos(event.map.map_id, event.x, event.y) - map = $map_factory.getMap(thistile[0]) - [2, 1, 0].each do |i| - tile_id = map.data[thistile[1], thistile[2], i] - next if tile_id.nil? - next if GameData::TerrainTag.try_get(map.terrain_tags[tile_id]).id != :SootGrass - if event == $game_player && $bag.has?(:SOOTSACK) - old_soot = $player.soot - $player.soot += 1 - $stats.soot_collected += $player.soot - old_soot if $player.soot > old_soot +EventHandlers.add(:on_step_taken, :pick_up_soot, + proc { |event| + thistile = $map_factory.getRealTilePos(event.map.map_id, event.x, event.y) + map = $map_factory.getMap(thistile[0]) + [2, 1, 0].each do |i| + tile_id = map.data[thistile[1], thistile[2], i] + next if tile_id.nil? + next if GameData::TerrainTag.try_get(map.terrain_tags[tile_id]).id != :SootGrass + if event == $game_player && $bag.has?(:SOOTSACK) + old_soot = $player.soot + $player.soot += 1 + $stats.soot_collected += $player.soot - old_soot if $player.soot > old_soot + end + map.erase_tile(thistile[1], thistile[2], i) + break end - map.erase_tile(thistile[1], thistile[2], i) - break - end -} + } +) -# Show grass rustle animation, and auto-move the player over waterfalls and ice -Events.onStepTakenFieldMovement += proc { |_sender, e| - event = e[0] # Get the event affected by field movement - if $scene.is_a?(Scene_Map) +# Show grass rustle animation +EventHandlers.add(:on_step_taken, :grass_rustling, + proc { |event| + next if !$scene.is_a?(Scene_Map) event.each_occupied_tile do |x, y| - if $map_factory.getTerrainTag(event.map.map_id, x, y, true).shows_grass_rustle - $scene.spriteset.addUserAnimation(Settings::GRASS_ANIMATION_ID, x, y, true, 1) - end + next if !$map_factory.getTerrainTag(event.map.map_id, x, y, true).shows_grass_rustle + $scene.spriteset.addUserAnimation(Settings::GRASS_ANIMATION_ID, x, y, true, 1) end - if event == $game_player - currentTag = $game_player.pbTerrainTag - if currentTag.waterfall_crest - pbDescendWaterfall - elsif currentTag.ice && !$PokemonGlobal.sliding - pbSlideOnIce - end + } +) + +# Auto-move the player over waterfalls and ice +EventHandlers.add(:on_step_taken, :auto_move_player, + proc { |event| + next if !$scene.is_a?(Scene_Map) + next if event != $game_player + currentTag = $game_player.pbTerrainTag + if currentTag.waterfall_crest + pbDescendWaterfall + elsif currentTag.ice && !$PokemonGlobal.sliding + pbSlideOnIce end - end -} + } +) def pbOnStepTaken(eventTriggered) if $game_player.move_route_forcing || pbMapInterpreterRunning? - Events.onStepTakenFieldMovement.trigger(nil, $game_player) + EventHandlers.trigger(:on_step_taken, $game_player) return end $PokemonGlobal.stepcount = 0 if !$PokemonGlobal.stepcount $PokemonGlobal.stepcount += 1 $PokemonGlobal.stepcount &= 0x7FFFFFFF repel_active = ($PokemonGlobal.repel > 0) - Events.onStepTaken.trigger(nil) -# Events.onStepTakenFieldMovement.trigger(nil,$game_player) + EventHandlers.trigger(:on_player_step_taken) handled = [nil] - Events.onStepTakenTransferPossible.trigger(nil, handled) + EventHandlers.trigger(:on_player_step_taken_can_transfer, handled) return if handled[0] pbBattleOnStepTaken(repel_active) if !eventTriggered && !$game_temp.in_menu $game_temp.encounter_triggered = false # This info isn't needed here end # Start wild encounters while turning on the spot -Events.onChangeDirection += proc { - repel_active = ($PokemonGlobal.repel > 0) - pbBattleOnStepTaken(repel_active) if !$game_temp.in_menu -} +EventHandlers.add(:on_player_change_direction, :trigger_encounter, + proc { + repel_active = ($PokemonGlobal.repel > 0) + pbBattleOnStepTaken(repel_active) if !$game_temp.in_menu + } +) def pbBattleOnStepTaken(repel_active) return if $player.able_pokemon_count == 0 @@ -192,11 +204,11 @@ def pbBattleOnStepTaken(repel_active) return if !$PokemonEncounters.encounter_triggered?(encounter_type, repel_active) $game_temp.encounter_type = encounter_type encounter = $PokemonEncounters.choose_wild_pokemon(encounter_type) - encounter = EncounterModifier.trigger(encounter) + EventHandlers.trigger(:on_wild_species_chosen, encounter) if $PokemonEncounters.allow_encounter?(encounter, repel_active) if $PokemonEncounters.have_double_wild_battle? encounter2 = $PokemonEncounters.choose_wild_pokemon(encounter_type) - encounter2 = EncounterModifier.trigger(encounter2) + EventHandlers.trigger(:on_wild_species_chosen, encounter2) pbDoubleWildBattle(encounter[0], encounter[1], encounter2[0], encounter2[1]) else pbWildBattle(encounter[0], encounter[1]) @@ -205,7 +217,6 @@ def pbBattleOnStepTaken(repel_active) $game_temp.encounter_triggered = true end $game_temp.force_single_battle = false - EncounterModifier.triggerEncounterEnd end @@ -216,67 +227,94 @@ end # Clears the weather of the old map, if the old map has defined weather and the # new map either has the same name as the old map or doesn't have defined # weather. -Events.onMapChanging += proc { |_sender, e| - new_map_ID = e[0] - next if new_map_ID == 0 - old_map_metadata = $game_map.metadata - next if !old_map_metadata || !old_map_metadata.weather - map_infos = pbLoadMapInfos - if $game_map.name == map_infos[new_map_ID].name - new_map_metadata = GameData::MapMetadata.try_get(new_map_ID) - next if new_map_metadata&.weather - end - $game_screen.weather(:None, 0, 0) -} +EventHandlers.add(:on_leave_map, :end_weather, + proc { |new_map_id, new_map| + next if new_map_id == 0 + old_map_metadata = $game_map.metadata + next if !old_map_metadata || !old_map_metadata.weather + map_infos = pbLoadMapInfos + if $game_map.name == map_infos[new_map_id].name + new_map_metadata = GameData::MapMetadata.try_get(new_map_id) + next if new_map_metadata&.weather + end + $game_screen.weather(:None, 0, 0) + } +) # Set up various data related to the new map -Events.onMapChange += proc { |_sender, e| - old_map_ID = e[0] # previous map ID, is 0 if no map ID - new_map_metadata = $game_map.metadata - if new_map_metadata&.teleport_destination - $PokemonGlobal.healingSpot = new_map_metadata.teleport_destination - end - $PokemonMap&.clear - $PokemonEncounters&.setup($game_map.map_id) - $PokemonGlobal.visitedMaps[$game_map.map_id] = true - next if old_map_ID == 0 || old_map_ID == $game_map.map_id - next if !new_map_metadata || !new_map_metadata.weather - map_infos = pbLoadMapInfos - if $game_map.name == map_infos[old_map_ID].name - old_map_metadata = GameData::MapMetadata.try_get(old_map_ID) - next if old_map_metadata&.weather - end - new_weather = new_map_metadata.weather - $game_screen.weather(new_weather[0], 9, 0) if rand(100) < new_weather[1] -} +EventHandlers.add(:on_enter_map, :setup_new_map, + proc { |old_map_id| # previous map ID, is 0 if no map ID + # Record new Teleport destination + new_map_metadata = $game_map.metadata + if new_map_metadata&.teleport_destination + $PokemonGlobal.healingSpot = new_map_metadata.teleport_destination + end + # End effects that apply only while on the map they were used + $PokemonMap&.clear + # Setup new wild encounter tables + $PokemonEncounters&.setup($game_map.map_id) + # Record the new map as having been visited + $PokemonGlobal.visitedMaps[$game_map.map_id] = true + # Set weather if new map has weather + next if old_map_id == 0 || old_map_id == $game_map.map_id + next if !new_map_metadata || !new_map_metadata.weather + map_infos = pbLoadMapInfos + if $game_map.name == map_infos[old_map_id].name + old_map_metadata = GameData::MapMetadata.try_get(old_map_id) + next if old_map_metadata&.weather + end + new_weather = new_map_metadata.weather + $game_screen.weather(new_weather[0], 9, 0) if rand(100) < new_weather[1] + } +) -Events.onMapSceneChange += proc { |_sender, e| - scene = e[0] - mapChanged = e[1] - next if !scene || !scene.spriteset - # Update map trail - if $game_map +# Update trail of which maps the player has most recently visited. +EventHandlers.add(:on_enter_map, :add_to_trail, + proc { |_old_map_id| + next if !$game_map $PokemonGlobal.mapTrail = [] if !$PokemonGlobal.mapTrail if $PokemonGlobal.mapTrail[0] != $game_map.map_id && $PokemonGlobal.mapTrail.length >= 4 $PokemonGlobal.mapTrail.pop end $PokemonGlobal.mapTrail = [$game_map.map_id] + $PokemonGlobal.mapTrail - end - # Display darkness circle on dark maps - map_metadata = $game_map.metadata - if map_metadata&.dark_map - $game_temp.darkness_sprite = DarknessSprite.new - scene.spriteset.addUserSprite($game_temp.darkness_sprite) - if $PokemonGlobal.flashUsed - $game_temp.darkness_sprite.radius = $game_temp.darkness_sprite.radiusMax + } +) + +# Force cycling/walking. +EventHandlers.add(:on_enter_map, :force_cycling, + proc { |_old_map_id| + if $game_map.metadata&.always_bicycle + pbMountBike + elsif !pbCanUseBike?($game_map.map_id) + pbDismountBike end - else - $PokemonGlobal.flashUsed = false - $game_temp.darkness_sprite&.dispose - $game_temp.darkness_sprite = nil - end - # Show location signpost - if mapChanged && map_metadata && map_metadata.announce_location + } +) + +# Display darkness circle on dark maps. +EventHandlers.add(:on_map_or_spriteset_change, :show_darkness, + proc { |scene, _map_changed| + next if !scene || !scene.spriteset + map_metadata = $game_map.metadata + if map_metadata&.dark_map + $game_temp.darkness_sprite = DarknessSprite.new + scene.spriteset.addUserSprite($game_temp.darkness_sprite) + if $PokemonGlobal.flashUsed + $game_temp.darkness_sprite.radius = $game_temp.darkness_sprite.radiusMax + end + else + $PokemonGlobal.flashUsed = false + $game_temp.darkness_sprite&.dispose + $game_temp.darkness_sprite = nil + end + } +) + +# Show location signpost. +EventHandlers.add(:on_map_or_spriteset_change, :show_location_window, + proc { |scene, map_changed| + next if !scene || !scene.spriteset + next if !map_changed || !$game_map.metadata&.announce_location nosignpost = false if $PokemonGlobal.mapTrail[1] (Settings::NO_SIGNPOSTS.length / 2).times do |i| @@ -291,14 +329,8 @@ Events.onMapSceneChange += proc { |_sender, e| nosignpost = true if $game_map.name == oldmapname end scene.spriteset.addUserSprite(LocationWindow.new($game_map.name)) if !nosignpost - end - # Force cycling/walking - if map_metadata&.always_bicycle - pbMountBike - elsif !pbCanUseBike?($game_map.map_id) - pbDismountBike - end -} + } +) @@ -683,7 +715,7 @@ def pbRegisterPartner(tr_type, tr_name, tr_id = 0) tr_type = GameData::TrainerType.get(tr_type).id pbCancelVehicles trainer = pbLoadTrainer(tr_type, tr_name, tr_id) - Events.onTrainerPartyLoad.trigger(nil, trainer) + EventHandlers.trigger(:on_trainer_load, trainer) trainer.party.each do |i| i.owner = Pokemon::Owner.new_from_trainer(trainer) i.calc_stats diff --git a/Data/Scripts/012_Overworld/002_Battle triggering/001_Overworld_BattleStarting.rb b/Data/Scripts/012_Overworld/002_Battle triggering/001_Overworld_BattleStarting.rb index f0a2e8e2c..5ea0469f7 100644 --- a/Data/Scripts/012_Overworld/002_Battle triggering/001_Overworld_BattleStarting.rb +++ b/Data/Scripts/012_Overworld/002_Battle triggering/001_Overworld_BattleStarting.rb @@ -188,18 +188,20 @@ def pbGetEnvironment return ret end -Events.onStartBattle += proc { |_sender| - # Record current levels of Pokémon in party, to see if they gain a level - # during battle and may need to evolve afterwards - $game_temp.party_levels_before_battle = [] - $game_temp.party_critical_hits_dealt = [] - $game_temp.party_direct_damage_taken = [] - $player.party.each_with_index do |pkmn, i| - $game_temp.party_levels_before_battle[i] = pkmn.level - $game_temp.party_critical_hits_dealt[i] = 0 - $game_temp.party_direct_damage_taken[i] = 0 - end -} +# Record current levels of Pokémon in party, to see if they gain a level during +# battle and may need to evolve afterwards +EventHandlers.add(:on_start_battle, :record_party_status, + proc { + $game_temp.party_levels_before_battle = [] + $game_temp.party_critical_hits_dealt = [] + $game_temp.party_direct_damage_taken = [] + $player.party.each_with_index do |pkmn, i| + $game_temp.party_levels_before_battle[i] = pkmn.level + $game_temp.party_critical_hits_dealt[i] = 0 + $game_temp.party_direct_damage_taken[i] = 0 + end + } +) def pbCanDoubleBattle? return $PokemonGlobal.partner || $player.able_pokemon_count >= 2 @@ -230,7 +232,7 @@ def pbWildBattleCore(*args) end # Record information about party Pokémon to be used at the end of battle (e.g. # comparing levels for an evolution check) - Events.onStartBattle.trigger(nil) + EventHandlers.trigger(:on_start_battle) # Generate wild Pokémon based on the species and level foeParty = [] sp = nil @@ -314,8 +316,8 @@ def pbWildBattle(species, level, outcomeVar = 1, canRun = true, canLose = false) # Potentially call a different pbWildBattle-type method instead (for roaming # Pokémon, Safari battles, Bug Contest battles) handled = [nil] - Events.onWildBattleOverride.trigger(nil, species, level, handled) - return handled[0] if handled[0] != nil + EventHandlers.trigger(:on_calling_wild_battle, species, level, handled) + return handled[0] if !handled[0].nil? # Set some battle rules setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 setBattleRule("cannotRun") if !canRun @@ -323,7 +325,7 @@ def pbWildBattle(species, level, outcomeVar = 1, canRun = true, canLose = false) # Perform the battle decision = pbWildBattleCore(species, level) # Used by the Poké Radar to update/break the chain - Events.onWildBattleEnd.trigger(nil, species, level, decision) + EventHandlers.trigger(:on_wild_battle_end, species, level, decision) # Return false if the player lost or drew the battle, and true if any other result return (decision != 2 && decision != 5) end @@ -375,7 +377,7 @@ def pbTrainerBattleCore(*args) end # Record information about party Pokémon to be used at the end of battle (e.g. # comparing levels for an evolution check) - Events.onStartBattle.trigger(nil) + EventHandlers.trigger(:on_start_battle) # Generate trainers and their parties based on the arguments given foeTrainers = [] foeItems = [] @@ -394,7 +396,7 @@ def pbTrainerBattleCore(*args) trainer = pbLoadTrainer(arg[0], arg[1], arg[2]) pbMissingTrainer(arg[0], arg[1], arg[2]) if !trainer return 0 if !trainer - Events.onTrainerPartyLoad.trigger(nil, trainer) + EventHandlers.trigger(:on_trainer_load, trainer) foeTrainers.push(trainer) foePartyStarts.push(foeParty.length) trainer.party.each { |pkmn| foeParty.push(pkmn) } @@ -495,7 +497,7 @@ def pbTrainerBattle(trainerID, trainerName, endSpeech = nil, trainer = pbLoadTrainer(trainerID, trainerName, trainerPartyID) pbMissingTrainer(trainerID, trainerName, trainerPartyID) if !trainer return false if !trainer - Events.onTrainerPartyLoad.trigger(nil, trainer) + EventHandlers.trigger(:on_trainer_load, trainer) # If there is exactly 1 other triggered trainer event, and this trainer has # 6 or fewer Pokémon, record this trainer for a double battle caused by the # other triggered trainer event @@ -580,34 +582,34 @@ def pbAfterBattle(decision, canLose) $player.party.each { |pkmn| pkmn.heal } (Graphics.frame_rate / 4).times { Graphics.update } end - Events.onEndBattle.trigger(nil, decision, canLose) + EventHandlers.trigger(:on_end_battle, decision, canLose) $game_player.straighten end -Events.onEndBattle += proc { |_sender, e| - decision = e[0] - canLose = e[1] - # Check for evolutions - pbEvolutionCheck if Settings::CHECK_EVOLUTION_AFTER_ALL_BATTLES || - (decision != 2 && decision != 5) # not a loss or a draw - $game_temp.party_levels_before_battle = nil - $game_temp.party_critical_hits_dealt = nil - $game_temp.party_direct_damage_taken = nil - # Check for blacking out or gaining Pickup/Huney Gather items - case decision - when 1, 4 # Win, capture - $player.pokemon_party.each do |pkmn| - pbPickup(pkmn) - pbHoneyGather(pkmn) +EventHandlers.add(:on_end_battle, :evolve_and_black_out, + proc { |decision, canLose| + # Check for evolutions + pbEvolutionCheck if Settings::CHECK_EVOLUTION_AFTER_ALL_BATTLES || + (decision != 2 && decision != 5) # not a loss or a draw + $game_temp.party_levels_before_battle = nil + $game_temp.party_critical_hits_dealt = nil + $game_temp.party_direct_damage_taken = nil + # Check for blacking out or gaining Pickup/Huney Gather items + case decision + when 1, 4 # Win, capture + $player.pokemon_party.each do |pkmn| + pbPickup(pkmn) + pbHoneyGather(pkmn) + end + when 2, 5 # Lose, draw + if !canLose + $game_system.bgm_unpause + $game_system.bgs_unpause + pbStartOver + end end - when 2, 5 # Lose, draw - if !canLose - $game_system.bgm_unpause - $game_system.bgs_unpause - pbStartOver - end - end -} + } +) def pbEvolutionCheck $player.party.each_with_index do |pkmn, i| diff --git a/Data/Scripts/012_Overworld/002_Battle triggering/003_Overworld_WildEncounters.rb b/Data/Scripts/012_Overworld/002_Battle triggering/003_Overworld_WildEncounters.rb index 02ce86a2e..45f21a9ce 100644 --- a/Data/Scripts/012_Overworld/002_Battle triggering/003_Overworld_WildEncounters.rb +++ b/Data/Scripts/012_Overworld/002_Battle triggering/003_Overworld_WildEncounters.rb @@ -446,7 +446,7 @@ def pbGenerateWildPokemon(species, level, isRoamer = false) end end # Trigger events that may alter the generated Pokémon further - Events.onWildPokemonCreate.trigger(nil, genwildpoke) + EventHandlers.trigger(:on_wild_pokemon_created, genwildpoke) return genwildpoke end @@ -455,11 +455,11 @@ end def pbEncounter(enc_type) $game_temp.encounter_type = enc_type encounter1 = $PokemonEncounters.choose_wild_pokemon(enc_type) - encounter1 = EncounterModifier.trigger(encounter1) + EventHandlers.trigger(:on_wild_species_chosen, encounter1) return false if !encounter1 if $PokemonEncounters.have_double_wild_battle? encounter2 = $PokemonEncounters.choose_wild_pokemon(enc_type) - encounter2 = EncounterModifier.trigger(encounter2) + EventHandlers.trigger(:on_wild_species_chosen, encounter2) return false if !encounter2 pbDoubleWildBattle(encounter1[0], encounter1[1], encounter2[0], encounter2[1]) else @@ -467,6 +467,5 @@ def pbEncounter(enc_type) end $game_temp.encounter_type = nil $game_temp.force_single_battle = false - EncounterModifier.triggerEncounterEnd return true end diff --git a/Data/Scripts/012_Overworld/002_Battle triggering/004_Overworld_EncounterModifiers.rb b/Data/Scripts/012_Overworld/002_Battle triggering/004_Overworld_EncounterModifiers.rb index 203c76027..d1c3d6b1b 100644 --- a/Data/Scripts/012_Overworld/002_Battle triggering/004_Overworld_EncounterModifiers.rb +++ b/Data/Scripts/012_Overworld/002_Battle triggering/004_Overworld_EncounterModifiers.rb @@ -6,35 +6,36 @@ ################################################################################ # Make all wild Pokémon shiny while a certain Switch is ON (see Settings). -Events.onWildPokemonCreate += proc { |_sender, e| - pkmn = e[0] - if $game_switches[Settings::SHINY_WILD_POKEMON_SWITCH] - pkmn.shiny = true - end -} +EventHandlers.add(:on_wild_pokemon_created, :make_shiny_switch, + proc { |pkmn| + pkmn.shiny = true if $game_switches[Settings::SHINY_WILD_POKEMON_SWITCH] + } +) -# Used in the random dungeon map. Makes the levels of all wild Pokémon in that +# Used in the random dungeon map. Makes the levels of all wild Pokémon in that # map depend on the levels of Pokémon in the player's party. # This is a simple method, and can/should be modified to account for evolutions # and other such details. Of course, you don't HAVE to use this code. -Events.onWildPokemonCreate += proc { |_sender, e| - pkmn = e[0] - if $game_map.map_id == 51 +EventHandlers.add(:on_wild_pokemon_created, :level_depends_on_party, + proc { |pkmn| + next if $game_map.map_id != 51 new_level = pbBalancedLevel($player.party) - 4 + rand(5) # For variety new_level = new_level.clamp(1, GameData::GrowthRate.max_level) pkmn.level = new_level pkmn.calc_stats pkmn.reset_moves - end -} + } +) # This is the basis of a trainer modifier. It works both for trainers loaded # when you battle them, and for partner trainers when they are registered. # Note that you can only modify a partner trainer's Pokémon, and not the trainer # themselves nor their items this way, as those are generated from scratch # before each battle. -#Events.onTrainerPartyLoad += proc { |_sender, trainer| -# if trainer # An NPCTrainer object containing party/items/lose text, etc. -# YOUR CODE HERE -# end -#} +#EventHandlers.trigger(:on_trainer_load, :put_a_name_here, +# proc { |trainer| +# if trainer # An NPCTrainer object containing party/items/lose text, etc. +# YOUR CODE HERE +# end +# } +#) diff --git a/Data/Scripts/012_Overworld/002_Battle triggering/005_Overworld_RoamingPokemon.rb b/Data/Scripts/012_Overworld/002_Battle triggering/005_Overworld_RoamingPokemon.rb index ed4ef4943..3b2f26463 100644 --- a/Data/Scripts/012_Overworld/002_Battle triggering/005_Overworld_RoamingPokemon.rb +++ b/Data/Scripts/012_Overworld/002_Battle triggering/005_Overworld_RoamingPokemon.rb @@ -93,16 +93,17 @@ end # When the player moves to a new map (with a different name), make all roaming # Pokémon roam. -Events.onMapChange += proc { |_sender, e| - oldMapID = e[0] - # Get and compare map names - mapInfos = pbLoadMapInfos - next if mapInfos && oldMapID > 0 && mapInfos[oldMapID] && - mapInfos[oldMapID].name && $game_map.name == mapInfos[oldMapID].name - # Make roaming Pokémon roam - pbRoamPokemon - $PokemonGlobal.roamedAlready = false -} +EventHandlers.add(:on_enter_map, :move_roaming_pokemon, + proc { |old_map_id| + # Get and compare map names + mapInfos = pbLoadMapInfos + next if mapInfos && old_map_id > 0 && mapInfos[old_map_id] && + mapInfos[old_map_id].name && $game_map.name == mapInfos[old_map_id].name + # Make roaming Pokémon roam + pbRoamPokemon + $PokemonGlobal.roamedAlready = false + } +) @@ -135,64 +136,69 @@ def pbRoamingMethodAllowed(roamer_method) return false end -EncounterModifier.register(proc { |encounter| - $game_temp.roamer_index_for_encounter = nil - next nil if !encounter - # Give the regular encounter if encountering a roaming Pokémon isn't possible - next encounter if $PokemonGlobal.roamedAlready - next encounter if $PokemonGlobal.partner - next encounter if $game_temp.poke_radar_data - next encounter if rand(100) < 75 # 25% chance of encountering a roaming Pokémon - # Look at each roaming Pokémon in turn and decide whether it's possible to - # encounter it - currentRegion = pbGetCurrentRegion - currentMapName = $game_map.name - possible_roamers = [] - Settings::ROAMING_SPECIES.each_with_index do |data, i| - # data = [species, level, Game Switch, roamer method, battle BGM, area maps hash] - next if !GameData::Species.exists?(data[0]) - next if data[2] > 0 && !$game_switches[data[2]] # Isn't roaming - next if $PokemonGlobal.roamPokemon[i] == true # Roaming Pokémon has been caught - # Get the roamer's current map - roamerMap = $PokemonGlobal.roamPosition[i] - if !roamerMap - mapIDs = pbRoamingAreas(i).keys # Hash of area patrolled by the roaming Pokémon - next if !mapIDs || mapIDs.length == 0 # No roaming area defined somehow - roamerMap = mapIDs[rand(mapIDs.length)] - $PokemonGlobal.roamPosition[i] = roamerMap +EventHandlers.add(:on_wild_species_chosen, :roaming_pokemon, + proc { |encounter| + $game_temp.roamer_index_for_encounter = nil + next if !encounter + # Give the regular encounter if encountering a roaming Pokémon isn't possible + next if $PokemonGlobal.roamedAlready + next if $PokemonGlobal.partner + next if $game_temp.poke_radar_data + next if rand(100) < 75 # 25% chance of encountering a roaming Pokémon + # Look at each roaming Pokémon in turn and decide whether it's possible to + # encounter it + currentRegion = pbGetCurrentRegion + currentMapName = $game_map.name + possible_roamers = [] + Settings::ROAMING_SPECIES.each_with_index do |data, i| + # data = [species, level, Game Switch, roamer method, battle BGM, area maps hash] + next if !GameData::Species.exists?(data[0]) + next if data[2] > 0 && !$game_switches[data[2]] # Isn't roaming + next if $PokemonGlobal.roamPokemon[i] == true # Roaming Pokémon has been caught + # Get the roamer's current map + roamerMap = $PokemonGlobal.roamPosition[i] + if !roamerMap + mapIDs = pbRoamingAreas(i).keys # Hash of area patrolled by the roaming Pokémon + next if !mapIDs || mapIDs.length == 0 # No roaming area defined somehow + roamerMap = mapIDs[rand(mapIDs.length)] + $PokemonGlobal.roamPosition[i] = roamerMap + end + # If roamer isn't on the current map, check if it's on a map with the same + # name and in the same region + if roamerMap != $game_map.map_id + map_metadata = GameData::MapMetadata.try_get(roamerMap) + next if !map_metadata || !map_metadata.town_map_position || + map_metadata.town_map_position[0] != currentRegion + next if pbGetMapNameFromId(roamerMap) != currentMapName + end + # Check whether the roamer's roamer method is currently possible + next if !pbRoamingMethodAllowed(data[3]) + # Add this roaming Pokémon to the list of possible roaming Pokémon to encounter + possible_roamers.push([i, data[0], data[1], data[4]]) # [i, species, level, BGM] end - # If roamer isn't on the current map, check if it's on a map with the same - # name and in the same region - if roamerMap != $game_map.map_id - map_metadata = GameData::MapMetadata.try_get(roamerMap) - next if !map_metadata || !map_metadata.town_map_position || - map_metadata.town_map_position[0] != currentRegion - next if pbGetMapNameFromId(roamerMap) != currentMapName - end - # Check whether the roamer's roamer method is currently possible - next if !pbRoamingMethodAllowed(data[3]) - # Add this roaming Pokémon to the list of possible roaming Pokémon to encounter - possible_roamers.push([i, data[0], data[1], data[4]]) # [i, species, level, BGM] - end - # No encounterable roaming Pokémon were found, just have the regular encounter - next encounter if possible_roamers.length == 0 - # Pick a roaming Pokémon to encounter out of those available - roamer = possible_roamers[rand(possible_roamers.length)] - $PokemonGlobal.roamEncounter = roamer - $game_temp.roamer_index_for_encounter = roamer[0] - $PokemonGlobal.nextBattleBGM = roamer[3] if roamer[3] && !roamer[3].empty? - $game_temp.force_single_battle = true - next [roamer[1], roamer[2]] # Species, level -}) + # No encounterable roaming Pokémon were found, just have the regular encounter + next if possible_roamers.length == 0 + # Pick a roaming Pokémon to encounter out of those available + roamer = possible_roamers.sample + $PokemonGlobal.roamEncounter = roamer + $game_temp.roamer_index_for_encounter = roamer[0] + $PokemonGlobal.nextBattleBGM = roamer[3] if roamer[3] && !roamer[3].empty? + $game_temp.force_single_battle = true + encounter[0] = roamer[1] # Species + encounter[1] = roamer[2] # Level + } +) -Events.onWildBattleOverride += proc { |_sender, e| - species = e[0] - level = e[1] - handled = e[2] - next if handled[0] != nil - next if !$PokemonGlobal.roamEncounter || $game_temp.roamer_index_for_encounter.nil? - handled[0] = pbRoamingPokemonBattle(species, level) -} +EventHandlers.add(:on_calling_wild_battle, :roaming_pokemon, + proc { |species, level, handled| + # handled is an array: [nil]. If [true] or [false], the battle has already + # been overridden (the boolean is its outcome), so don't do anything that + # would override it again + next if !handled[0].nil? + next if !$PokemonGlobal.roamEncounter || $game_temp.roamer_index_for_encounter.nil? + handled[0] = pbRoamingPokemonBattle(species, level) + } +) def pbRoamingPokemonBattle(species, level) # Get the roaming Pokémon to encounter; generate it based on the species and @@ -214,12 +220,9 @@ def pbRoamingPokemonBattle(species, level) end $PokemonGlobal.roamEncounter = nil $PokemonGlobal.roamedAlready = true + $game_temp.roamer_index_for_encounter = nil # Used by the Poké Radar to update/break the chain - Events.onWildBattleEnd.trigger(nil, species, level, decision) + EventHandlers.trigger(:on_wild_battle_end, species, level, decision) # Return false if the player lost or drew the battle, and true if any other result return (decision != 2 && decision != 5) end - -EncounterModifier.registerEncounterEnd(proc { - $game_temp.roamer_index_for_encounter = nil -}) diff --git a/Data/Scripts/012_Overworld/004_Overworld_FieldMoves.rb b/Data/Scripts/012_Overworld/004_Overworld_FieldMoves.rb index bda89da78..6b2128b98 100644 --- a/Data/Scripts/012_Overworld/004_Overworld_FieldMoves.rb +++ b/Data/Scripts/012_Overworld/004_Overworld_FieldMoves.rb @@ -49,7 +49,7 @@ end # Unused def pbHiddenMoveEvent - Events.onAction.trigger(nil) + EventHandlers.trigger(:on_player_interact) end def pbCheckHiddenMoveBadge(badge = -1, showmsg = true) @@ -383,22 +383,24 @@ def pbTransferUnderwater(mapid, x, y, direction = $game_player.direction) } end -Events.onAction += proc { |_sender, _e| - if $PokemonGlobal.diving - surface_map_id = nil - GameData::MapMetadata.each do |map_data| - next if !map_data.dive_map_id || map_data.dive_map_id != $game_map.map_id - surface_map_id = map_data.id - break +EventHandlers.add(:on_player_interact, :diving, + proc { + if $PokemonGlobal.diving + surface_map_id = nil + GameData::MapMetadata.each do |map_data| + next if !map_data.dive_map_id || map_data.dive_map_id != $game_map.map_id + surface_map_id = map_data.id + break + end + if surface_map_id && + $map_factory.getTerrainTag(surface_map_id, $game_player.x, $game_player.y).can_dive + pbSurfacing + end + elsif $game_player.terrain_tag.can_dive + pbDive end - if surface_map_id && - $map_factory.getTerrainTag(surface_map_id, $game_player.x, $game_player.y).can_dive - pbSurfacing - end - elsif $game_player.terrain_tag.can_dive - pbDive - end -} + } +) HiddenMoveHandlers::CanUseMove.add(:DIVE, proc { |move, pkmn, showmsg| next false if !pbCheckHiddenMoveBadge(Settings::BADGE_FOR_DIVE, showmsg) @@ -703,10 +705,12 @@ def pbStrength return false end -Events.onAction += proc { |_sender, _e| - facingEvent = $game_player.pbFacingEvent - pbStrength if facingEvent && facingEvent.name[/strengthboulder/i] -} +EventHandlers.add(:on_player_interact, :strength_event, + proc { + facingEvent = $game_player.pbFacingEvent + pbStrength if facingEvent && facingEvent.name[/strengthboulder/i] + } +) HiddenMoveHandlers::CanUseMove.add(:STRENGTH, proc { |move, pkmn, showmsg| next false if !pbCheckHiddenMoveBadge(Settings::BADGE_FOR_STRENGTH, showmsg) @@ -796,13 +800,15 @@ def pbTransferSurfing(mapid, xcoord, ycoord, direction = $game_player.direction) } end -Events.onAction += proc { |_sender, _e| - next if $PokemonGlobal.surfing - next if $game_map.metadata&.always_bicycle - next if !$game_player.pbFacingTerrainTag.can_surf_freely - next if !$game_map.passable?($game_player.x, $game_player.y, $game_player.direction, $game_player) - pbSurf -} +EventHandlers.add(:on_player_interact, :start_surfing, + proc { + next if $PokemonGlobal.surfing + next if $game_map.metadata&.always_bicycle + next if !$game_player.pbFacingTerrainTag.can_surf_freely + next if !$game_map.passable?($game_player.x, $game_player.y, $game_player.direction, $game_player) + pbSurf + } +) HiddenMoveHandlers::CanUseMove.add(:SURF, proc { |move, pkmn, showmsg| next false if !pbCheckHiddenMoveBadge(Settings::BADGE_FOR_SURF, showmsg) @@ -1001,14 +1007,16 @@ def pbWaterfall return false end -Events.onAction += proc { |_sender, _e| - terrain = $game_player.pbFacingTerrainTag - if terrain.waterfall - pbWaterfall - elsif terrain.waterfall_crest - pbMessage(_INTL("A wall of water is crashing down with a mighty roar.")) - end -} +EventHandlers.add(:on_player_interact, :waterfall, + proc { + terrain = $game_player.pbFacingTerrainTag + if terrain.waterfall + pbWaterfall + elsif terrain.waterfall_crest + pbMessage(_INTL("A wall of water is crashing down with a mighty roar.")) + end + } +) HiddenMoveHandlers::CanUseMove.add(:WATERFALL, proc { |move, pkmn, showmsg| next false if !pbCheckHiddenMoveBadge(Settings::BADGE_FOR_WATERFALL, showmsg) diff --git a/Data/Scripts/012_Overworld/006_Overworld_BerryPlants.rb b/Data/Scripts/012_Overworld/006_Overworld_BerryPlants.rb index 1b692e018..0e17f8c2d 100644 --- a/Data/Scripts/012_Overworld/006_Overworld_BerryPlants.rb +++ b/Data/Scripts/012_Overworld/006_Overworld_BerryPlants.rb @@ -290,16 +290,16 @@ end #=============================================================================== # #=============================================================================== -Events.onSpritesetCreate += proc { |_sender, e| - spriteset = e[0] - viewport = e[1] - map = spriteset.map - map.events.each do |event| - next if !event[1].name[/berryplant/i] - spriteset.addUserSprite(BerryPlantMoistureSprite.new(event[1], map, viewport)) - spriteset.addUserSprite(BerryPlantSprite.new(event[1], map, viewport)) - end -} +EventHandlers.add(:on_new_spriteset_map, :add_berry_plant_graphics, + proc { |spriteset, viewport| + map = spriteset.map + map.events.each do |event| + next if !event[1].name[/berryplant/i] + spriteset.addUserSprite(BerryPlantMoistureSprite.new(event[1], map, viewport)) + spriteset.addUserSprite(BerryPlantSprite.new(event[1], map, viewport)) + end + } +) #=============================================================================== # diff --git a/Data/Scripts/012_Overworld/007_Overworld_DayCare.rb b/Data/Scripts/012_Overworld/007_Overworld_DayCare.rb index 44f9c5f99..b10188289 100644 --- a/Data/Scripts/012_Overworld/007_Overworld_DayCare.rb +++ b/Data/Scripts/012_Overworld/007_Overworld_DayCare.rb @@ -557,9 +557,11 @@ end # With each step taken, add Exp to Pokémon in the Day Care and try to generate # an egg. #=============================================================================== -Events.onStepTaken += proc { |_sender, _e| - $PokemonGlobal.day_care.update_on_step_taken -} +EventHandlers.add(:on_player_step_taken, :update_day_care, + proc { + $PokemonGlobal.day_care.update_on_step_taken + } +) #=============================================================================== # Deprecated methods diff --git a/Data/Scripts/012_Overworld/008_Overworld_RandomDungeons.rb b/Data/Scripts/012_Overworld/008_Overworld_RandomDungeons.rb index dcbfd4088..b68e7bfe7 100644 --- a/Data/Scripts/012_Overworld/008_Overworld_RandomDungeons.rb +++ b/Data/Scripts/012_Overworld/008_Overworld_RandomDungeons.rb @@ -643,27 +643,27 @@ module RandomDungeonGenerator end end -Events.onMapCreate += proc { |_sender, e| - mapID = e[0] - map = e[1] - next if !GameData::MapMetadata.try_get(mapID)&.random_dungeon - # this map is a randomly generated dungeon - dungeon = RandomDungeonGenerator::Dungeon.new(map.width, map.height) - dungeon.generate - dungeon.generateMapInPlace(map) - roomtiles = [] - # Reposition events - map.events.values.each do |event| +EventHandlers.add(:on_game_map_setup, :random_dungeon, + proc { |map_id, map, _tileset_data| + next if !GameData::MapMetadata.try_get(map_id)&.random_dungeon + # this map is a randomly generated dungeon + dungeon = RandomDungeonGenerator::Dungeon.new(map.width, map.height) + dungeon.generate + dungeon.generateMapInPlace(map) + roomtiles = [] + # Reposition events + map.events.values.each do |event| + tile = RandomDungeonGenerator.pbRandomRoomTile(dungeon, roomtiles) + if tile + event.x = tile[0] + event.y = tile[1] + end + end + # Override transfer X and Y tile = RandomDungeonGenerator.pbRandomRoomTile(dungeon, roomtiles) if tile - event.x = tile[0] - event.y = tile[1] + $game_temp.player_new_x = tile[0] + $game_temp.player_new_y = tile[1] end - end - # Override transfer X and Y - tile = RandomDungeonGenerator.pbRandomRoomTile(dungeon, roomtiles) - if tile - $game_temp.player_new_x = tile[0] - $game_temp.player_new_y = tile[1] - end -} + } +) diff --git a/Data/Scripts/013_Items/002_Item_Effects.rb b/Data/Scripts/013_Items/002_Item_Effects.rb index 563c92ea7..94635e7d2 100644 --- a/Data/Scripts/013_Items/002_Item_Effects.rb +++ b/Data/Scripts/013_Items/002_Item_Effects.rb @@ -134,25 +134,27 @@ ItemHandlers::UseInField.add(:MAXREPEL, proc { |item| next pbRepel(item, 250) }) -Events.onStepTaken += proc { - next if $PokemonGlobal.repel <= 0 || $game_player.terrain_tag.ice # Shouldn't count down if on ice - $PokemonGlobal.repel -= 1 - next if $PokemonGlobal.repel > 0 - repels = [] - GameData::Item.each { |itm| repels.push(itm.id) if itm.has_flag?("Repel") } - if repels.none? { |item| $bag.has?(item) } - pbMessage(_INTL("The repellent's effect wore off!")) - next - end - next if !pbConfirmMessage(_INTL("The repellent's effect wore off! Would you like to use another one?")) - ret = nil - pbFadeOutIn { - scene = PokemonBag_Scene.new - screen = PokemonBagScreen.new(scene, $bag) - ret = screen.pbChooseItemScreen(proc { |item| repels.include?(item) }) +EventHandlers.add(:on_player_step_taken, :repel_counter, + proc { + next if $PokemonGlobal.repel <= 0 || $game_player.terrain_tag.ice # Shouldn't count down if on ice + $PokemonGlobal.repel -= 1 + next if $PokemonGlobal.repel > 0 + repels = [] + GameData::Item.each { |itm| repels.push(itm.id) if itm.has_flag?("Repel") } + if repels.none? { |item| $bag.has?(item) } + pbMessage(_INTL("The repellent's effect wore off!")) + next + end + next if !pbConfirmMessage(_INTL("The repellent's effect wore off! Would you like to use another one?")) + ret = nil + pbFadeOutIn { + scene = PokemonBag_Scene.new + screen = PokemonBagScreen.new(scene, $bag) + ret = screen.pbChooseItemScreen(proc { |item| repels.include?(item) }) + } + pbUseItem($bag, ret) if ret } - pbUseItem($bag, ret) if ret -} +) ItemHandlers::UseInField.add(:BLACKFLUTE, proc { |item| pbUseItemMessage(item) diff --git a/Data/Scripts/013_Items/004_Item_Phone.rb b/Data/Scripts/013_Items/004_Item_Phone.rb index b949c9450..4b4c26e88 100644 --- a/Data/Scripts/013_Items/004_Item_Phone.rb +++ b/Data/Scripts/013_Items/004_Item_Phone.rb @@ -131,47 +131,48 @@ end #=============================================================================== # Phone-related counters #=============================================================================== -Events.onMapUpdate += proc { |_sender, _e| - next if !$player || !$player.has_pokegear - # Reset time to next phone call if necessary - if !$PokemonGlobal.phoneTime || $PokemonGlobal.phoneTime <= 0 - $PokemonGlobal.phoneTime = 20 * 60 * Graphics.frame_rate - $PokemonGlobal.phoneTime += rand(20 * 60 * Graphics.frame_rate) - end - # Don't count down various phone times if other things are happening - $PokemonGlobal.phoneNumbers = [] if !$PokemonGlobal.phoneNumbers - next if $game_temp.in_menu || $game_temp.in_battle || $game_temp.message_window_showing - next if $game_player.move_route_forcing || pbMapInterpreterRunning? - # Count down time to next phone call - $PokemonGlobal.phoneTime -= 1 - # Count down time to next can-battle for each trainer contact - if $PokemonGlobal.phoneTime % Graphics.frame_rate == 0 # Every second - $PokemonGlobal.phoneNumbers.each do |num| - next if !num[0] || num.length != 8 # if not visible or not a trainer - # Reset time to next can-battle if necessary - if num[4] == 0 - num[3] = rand(20...40) * 60 # 20-40 minutes - num[4] = 1 - end - # Count down time to next can-battle - num[3] -= 1 - # Ready to battle - if num[3] <= 0 && num[4] == 1 - num[4] = 2 # set ready-to-battle flag - pbSetReadyToBattle(num) +EventHandlers.add(:on_frame_update, :phone_call_counter, + proc { + next if !$player&.has_pokegear + # Reset time to next phone call if necessary + if !$PokemonGlobal.phoneTime || $PokemonGlobal.phoneTime <= 0 + $PokemonGlobal.phoneTime = rand(20...40) * 60 * Graphics.frame_rate + end + # Don't count down various phone times if other things are happening + $PokemonGlobal.phoneNumbers = [] if !$PokemonGlobal.phoneNumbers + next if $game_temp.in_menu || $game_temp.in_battle || $game_temp.message_window_showing + next if $game_player.move_route_forcing || pbMapInterpreterRunning? + # Count down time to next phone call + $PokemonGlobal.phoneTime -= 1 + # Count down time to next can-battle for each trainer contact + if $PokemonGlobal.phoneTime % Graphics.frame_rate == 0 # Every second + $PokemonGlobal.phoneNumbers.each do |num| + next if !num[0] || num.length != 8 # if not visible or not a trainer + # Reset time to next can-battle if necessary + if num[4] == 0 + num[3] = rand(20...40) * 60 # 20-40 minutes + num[4] = 1 + end + # Count down time to next can-battle + num[3] -= 1 + # Ready to battle + if num[3] <= 0 && num[4] == 1 + num[4] = 2 # set ready-to-battle flag + pbSetReadyToBattle(num) + end end end - end - # Time for a random phone call; generate one - if $PokemonGlobal.phoneTime <= 0 - # find all trainer phone numbers - phonenum = pbRandomPhoneTrainer - if phonenum - call = pbPhoneGenerateCall(phonenum) - pbPhoneCall(call, phonenum) + # Time for a random phone call; generate one + if $PokemonGlobal.phoneTime <= 0 + # find all trainer phone numbers + phonenum = pbRandomPhoneTrainer + if phonenum + call = pbPhoneGenerateCall(phonenum) + pbPhoneCall(call, phonenum) + end end - end -} + } +) #=============================================================================== # Player calls a contact diff --git a/Data/Scripts/013_Items/005_Item_PokeRadar.rb b/Data/Scripts/013_Items/005_Item_PokeRadar.rb index 0cb9fc353..0da167dd4 100644 --- a/Data/Scripts/013_Items/005_Item_PokeRadar.rb +++ b/Data/Scripts/013_Items/005_Item_PokeRadar.rb @@ -151,90 +151,102 @@ end ################################################################################ # Event handlers ################################################################################ -EncounterModifier.register(proc { |encounter| - if GameData::EncounterType.get($game_temp.encounter_type).type != :land || - $PokemonGlobal.bicycle || $PokemonGlobal.partner - pbPokeRadarCancel - next encounter - end - ring = pbPokeRadarGetShakingGrass - if ring >= 0 # Encounter triggered by stepping into rustling grass - # Get rarity of shaking grass - rarity = 0 # 0 = rustle, 1 = vigorous rustle, 2 = shiny rustle - $game_temp.poke_radar_data[3].each { |g| rarity = g[3] if g[2] == ring } - if $game_temp.poke_radar_data[2] > 0 # Chain count, i.e. is chaining - if rarity == 2 || - rand(100) < 58 + (ring * 10) + ([$game_temp.poke_radar_data[2], 40].min / 4) + ($game_temp.poke_radar_data[4] ? 10 : 0) - # Continue the chain - encounter = [$game_temp.poke_radar_data[0], $game_temp.poke_radar_data[1]] - $game_temp.force_single_battle = true - else - # Break the chain, force an encounter with a different species - 100.times do - break if encounter && encounter[0] != $game_temp.poke_radar_data[0] - encounter = $PokemonEncounters.choose_wild_pokemon($PokemonEncounters.encounter_type) - end - if encounter[0] == $game_temp.poke_radar_data[0] && encounter[1] == $game_temp.poke_radar_data[1] - # Chain couldn't be broken somehow; continue it after all +EventHandlers.add(:on_wild_species_chosen, :poke_radar_chain, + proc { |encounter| + if GameData::EncounterType.get($game_temp.encounter_type).type != :land || + $PokemonGlobal.bicycle || $PokemonGlobal.partner + pbPokeRadarCancel + next + end + ring = pbPokeRadarGetShakingGrass + if ring >= 0 # Encounter triggered by stepping into rustling grass + # Get rarity of shaking grass + rarity = 0 # 0 = rustle, 1 = vigorous rustle, 2 = shiny rustle + $game_temp.poke_radar_data[3].each { |g| rarity = g[3] if g[2] == ring } + if $game_temp.poke_radar_data[2] > 0 # Chain count, i.e. is chaining + chain_chance = 58 + (ring * 10) + chain_chance += [$game_temp.poke_radar_data[2], 40].min / 4 # Chain length + chain_chance += 10 if $game_temp.poke_radar_data[4] # Previous in chain was caught + if rarity == 2 || rand(100) < chain_chance + # Continue the chain + encounter[0] = $game_temp.poke_radar_data[0] # Species + encounter[1] = $game_temp.poke_radar_data[1] # Level $game_temp.force_single_battle = true else - pbPokeRadarCancel + # Break the chain, force an encounter with a different species + 100.times do + break if encounter && encounter[0] != $game_temp.poke_radar_data[0] + new_encounter = $PokemonEncounters.choose_wild_pokemon($PokemonEncounters.encounter_type) + encounter[0] = new_encounter[0] + encounter[1] = new_encounter[1] + end + if encounter[0] == $game_temp.poke_radar_data[0] && encounter[1] == $game_temp.poke_radar_data[1] + # Chain couldn't be broken somehow; continue it after all + $game_temp.force_single_battle = true + else + pbPokeRadarCancel + end end + else # Not chaining; will start one + # Force random wild encounter, vigorous shaking means rarer species + new_encounter = pbPokeRadarGetEncounter(rarity) + encounter[0] = new_encounter[0] + encounter[1] = new_encounter[1] + $game_temp.force_single_battle = true end - else # Not chaining; will start one - # Force random wild encounter, vigorous shaking means rarer species - encounter = pbPokeRadarGetEncounter(rarity) - $game_temp.force_single_battle = true + elsif encounter # Encounter triggered by stepping in non-rustling grass + pbPokeRadarCancel end - elsif encounter # Encounter triggered by stepping in non-rustling grass + } +) + +EventHandlers.add(:on_wild_pokemon_created, :poke_radar_shiny, + proc { |pkmn| + next if !$game_temp.poke_radar_data + grasses = $game_temp.poke_radar_data[3] + next if !grasses + grasses.each do |grass| + next if $game_player.x != grass[0] || $game_player.y != grass[1] + pkmn.shiny = true if grass[3] == 2 + break + end + } +) + +EventHandlers.add(:on_wild_battle_end, :poke_radar_continue_chain, + proc { |species, level, decision| + if $game_temp.poke_radar_data && [1, 4].include?(decision) # Defeated/caught + $game_temp.poke_radar_data[0] = species + $game_temp.poke_radar_data[1] = level + $game_temp.poke_radar_data[2] += 1 + $stats.poke_radar_longest_chain = [$game_temp.poke_radar_data[2], $stats.poke_radar_longest_chain].max + # Catching makes the next Radar encounter more likely to continue the chain + $game_temp.poke_radar_data[4] = (decision == 4) + pbPokeRadarHighlightGrass(false) + else + pbPokeRadarCancel + end + } +) + +EventHandlers.add(:on_player_step_taken, :poke_radar, + proc { + if $PokemonGlobal.pokeradarBattery && $PokemonGlobal.pokeradarBattery > 0 && + !$game_temp.poke_radar_data + $PokemonGlobal.pokeradarBattery -= 1 + end + terrain = $game_map.terrain_tag($game_player.x, $game_player.y) + if !terrain.land_wild_encounters || !terrain.shows_grass_rustle + pbPokeRadarCancel + end + } +) + +EventHandlers.add(:on_enter_map, :cancel_poke_radar, + proc { |_old_map_id| pbPokeRadarCancel - end - next encounter -}) - -Events.onWildPokemonCreate += proc { |_sender, e| - pokemon = e[0] - next if !$game_temp.poke_radar_data - grasses = $game_temp.poke_radar_data[3] - next if !grasses - grasses.each do |grass| - next if $game_player.x != grass[0] || $game_player.y != grass[1] - pokemon.shiny = true if grass[3] == 2 - break - end -} - -Events.onWildBattleEnd += proc { |_sender, e| - species = e[0] - level = e[1] - decision = e[2] - if $game_temp.poke_radar_data && [1, 4].include?(decision) # Defeated/caught - $game_temp.poke_radar_data[0] = species - $game_temp.poke_radar_data[1] = level - $game_temp.poke_radar_data[2] += 1 - $stats.poke_radar_longest_chain = [$game_temp.poke_radar_data[2], $stats.poke_radar_longest_chain].max - # Catching makes the next Radar encounter more likely to continue the chain - $game_temp.poke_radar_data[4] = (decision == 4) - pbPokeRadarHighlightGrass(false) - else - pbPokeRadarCancel - end -} - -Events.onStepTaken += proc { |_sender, _e| - if $PokemonGlobal.pokeradarBattery && $PokemonGlobal.pokeradarBattery > 0 && - !$game_temp.poke_radar_data - $PokemonGlobal.pokeradarBattery -= 1 - end - terrain = $game_map.terrain_tag($game_player.x, $game_player.y) - if !terrain.land_wild_encounters || !terrain.shows_grass_rustle - pbPokeRadarCancel - end -} - -Events.onMapChange += proc { |_sender, _e| - pbPokeRadarCancel -} + } +) ################################################################################ # Item handlers diff --git a/Data/Scripts/014_Pokemon/001_Pokemon-related/002_ShadowPokemon_Other.rb b/Data/Scripts/014_Pokemon/001_Pokemon-related/002_ShadowPokemon_Other.rb index f92ffc558..a6adb1480 100644 --- a/Data/Scripts/014_Pokemon/001_Pokemon-related/002_ShadowPokemon_Other.rb +++ b/Data/Scripts/014_Pokemon/001_Pokemon-related/002_ShadowPokemon_Other.rb @@ -396,39 +396,43 @@ end # Record current heart gauges of Pokémon in party, to see if they drop to zero # during battle and need to say they're ready to be purified afterwards -Events.onStartBattle += proc { |_sender| - $game_temp.party_heart_gauges_before_battle = [] - $player.party.each_with_index do |pkmn, i| - $game_temp.party_heart_gauges_before_battle[i] = pkmn.heart_gauge - end -} - -Events.onEndBattle += proc { |_sender, _e| - $game_temp.party_heart_gauges_before_battle.each_with_index do |value, i| - pkmn = $player.party[i] - next if !pkmn || !value || value == 0 - pkmn.check_ready_to_purify if pkmn.heart_gauge == 0 - end -} - -Events.onStepTaken += proc { - $player.able_party.each do |pkmn| - next if pkmn.heart_gauge == 0 - pkmn.heart_gauge_step_counter = 0 if !pkmn.heart_gauge_step_counter - pkmn.heart_gauge_step_counter += 1 - if pkmn.heart_gauge_step_counter >= 256 - old_stage = pkmn.heartStage - pkmn.change_heart_gauge("walking") - new_stage = pkmn.heartStage - if new_stage == 0 - pkmn.check_ready_to_purify - elsif new_stage != old_stage - pkmn.update_shadow_moves - end - pkmn.heart_gauge_step_counter = 0 +EventHandlers.add(:on_start_battle, :record_party_heart_gauges, + proc { + $game_temp.party_heart_gauges_before_battle = [] + $player.party.each_with_index do |pkmn, i| + $game_temp.party_heart_gauges_before_battle[i] = pkmn.heart_gauge end - end - if ($PokemonGlobal.purifyChamber rescue nil) - $PokemonGlobal.purifyChamber.update - end -} + } +) + +EventHandlers.add(:on_end_battle, :check_ready_to_purify, + proc { |_decision, _canLose| + $game_temp.party_heart_gauges_before_battle.each_with_index do |value, i| + pkmn = $player.party[i] + next if !pkmn || !value || value == 0 + pkmn.check_ready_to_purify if pkmn.heart_gauge == 0 + end + } +) + +EventHandlers.add(:on_player_step_taken, :lower_heart_gauges, + proc { + $player.able_party.each do |pkmn| + next if pkmn.heart_gauge == 0 + pkmn.heart_gauge_step_counter = 0 if !pkmn.heart_gauge_step_counter + pkmn.heart_gauge_step_counter += 1 + if pkmn.heart_gauge_step_counter >= 256 + old_stage = pkmn.heartStage + pkmn.change_heart_gauge("walking") + new_stage = pkmn.heartStage + if new_stage == 0 + pkmn.check_ready_to_purify + elsif new_stage != old_stage + pkmn.update_shadow_moves + end + pkmn.heart_gauge_step_counter = 0 + end + end + $PokemonGlobal.purifyChamber&.update + } +) diff --git a/Data/Scripts/016_UI/001_Non-interactive UI/003_UI_EggHatching.rb b/Data/Scripts/016_UI/001_Non-interactive UI/003_UI_EggHatching.rb index cbbede2e5..68eef5dec 100644 --- a/Data/Scripts/016_UI/001_Non-interactive UI/003_UI_EggHatching.rb +++ b/Data/Scripts/016_UI/001_Non-interactive UI/003_UI_EggHatching.rb @@ -217,18 +217,20 @@ def pbHatch(pokemon) end end -Events.onStepTaken += proc { |_sender, _e| - $player.party.each do |egg| - next if egg.steps_to_hatch <= 0 - egg.steps_to_hatch -= 1 - $player.pokemon_party.each do |pkmn| - next if !pkmn.ability&.has_flag?("FasterEggHatching") +EventHandlers.add(:on_player_step_taken, :hatch_eggs, + proc { + $player.party.each do |egg| + next if egg.steps_to_hatch <= 0 egg.steps_to_hatch -= 1 - break + $player.pokemon_party.each do |pkmn| + next if !pkmn.ability&.has_flag?("FasterEggHatching") + egg.steps_to_hatch -= 1 + break + end + if egg.steps_to_hatch <= 0 + egg.steps_to_hatch = 0 + pbHatch(egg) + end end - if egg.steps_to_hatch <= 0 - egg.steps_to_hatch = 0 - pbHatch(egg) - end - end -} + } +) diff --git a/Data/Scripts/018_Alternate battle modes/001_SafariZone.rb b/Data/Scripts/018_Alternate battle modes/001_SafariZone.rb index 3e7f35a7f..058f67c2c 100644 --- a/Data/Scripts/018_Alternate battle modes/001_SafariZone.rb +++ b/Data/Scripts/018_Alternate battle modes/001_SafariZone.rb @@ -55,9 +55,11 @@ end -Events.onMapChange += proc { |_sender, *args| - pbSafariState.pbEnd if !pbInSafari? -} +EventHandlers.add(:on_enter_map, :end_safari_game, + proc { |_old_map_id| + pbSafariState.pbEnd if !pbInSafari? + } +) def pbInSafari? if pbSafariState.inProgress? @@ -75,29 +77,32 @@ def pbSafariState return $PokemonGlobal.safariState end -Events.onStepTakenTransferPossible += proc { |_sender, e| - handled = e[0] - next if handled[0] - if pbInSafari? && pbSafariState.decision == 0 && Settings::SAFARI_STEPS > 0 +EventHandlers.add(:on_player_step_taken_can_transfer, :safari_game_counter, + proc { |handled| + # handled is an array: [nil]. If [true], a message has already been shown + # because of this step, so don't do anything that might show another one + next if handled[0] + next if Settings::SAFARI_STEPS == 0 || !pbInSafari? || pbSafariState.decision != 0 pbSafariState.steps -= 1 - if pbSafariState.steps <= 0 - pbMessage(_INTL("PA: Ding-dong!\1")) - pbMessage(_INTL("PA: Your safari game is over!")) - pbSafariState.decision = 1 - pbSafariState.pbGoToStart - handled[0] = true - end - end -} + next if pbSafariState.steps > 0 + pbMessage(_INTL("PA: Ding-dong!\1")) + pbMessage(_INTL("PA: Your safari game is over!")) + pbSafariState.decision = 1 + pbSafariState.pbGoToStart + handled[0] = true + } +) -Events.onWildBattleOverride += proc { |_sender, e| - species = e[0] - level = e[1] - handled = e[2] - next if handled[0] != nil - next if !pbInSafari? - handled[0] = pbSafariBattle(species, level) -} +EventHandlers.add(:on_calling_wild_battle, :safari_battle, + proc { |species, level, handled| + # handled is an array: [nil]. If [true] or [false], the battle has already + # been overridden (the boolean is its outcome), so don't do anything that + # would override it again + next if !handled[0].nil? + next if !pbInSafari? + handled[0] = pbSafariBattle(species, level) + } +) def pbSafariBattle(species, level) # Generate a wild Pokémon based on the species and level @@ -140,7 +145,7 @@ def pbSafariBattle(species, level) end pbSet(1, decision) # Used by the Poké Radar to update/break the chain - Events.onWildBattleEnd.trigger(nil, species, level, decision) + EventHandlers.trigger(:on_wild_battle_end, species, level, decision) # Return the outcome of the battle return decision end diff --git a/Data/Scripts/018_Alternate battle modes/002_BugContest.rb b/Data/Scripts/018_Alternate battle modes/002_BugContest.rb index e843f0286..2c7a1b002 100644 --- a/Data/Scripts/018_Alternate battle modes/002_BugContest.rb +++ b/Data/Scripts/018_Alternate battle modes/002_BugContest.rb @@ -286,36 +286,40 @@ def pbBugContestDecided? return pbBugContestState.decided? end -Events.onMapChange += proc { |_sender, _e| - pbBugContestState.pbClearIfEnded -} +EventHandlers.add(:on_enter_map, :end_bug_contest, + proc { |_old_map_id| + pbBugContestState.pbClearIfEnded + } +) -Events.onMapSceneChange += proc { |_sender, e| - scene = e[0] - if pbInBugContest? && pbBugContestState.decision == 0 && BugContestState::TIME_ALLOWED > 0 +EventHandlers.add(:on_map_or_spriteset_change, :show_bug_contest_timer, + proc { |scene, _map_changed| + next if !pbInBugContest? || pbBugContestState.decision != 0 || BugContestState::TIME_ALLOWED == 0 scene.spriteset.addUserSprite( TimerDisplay.new(pbBugContestState.timer, BugContestState::TIME_ALLOWED * Graphics.frame_rate) ) - end -} + } +) -Events.onMapUpdate += proc { |_sender, _e| - if !$game_player.move_route_forcing && !pbMapInterpreterRunning? && - !$game_temp.message_window_showing && pbBugContestState.expired? - pbMessage(_INTL("ANNOUNCER: BEEEEEP!")) +EventHandlers.add(:on_frame_update, :bug_contest_counter, + proc { + next if !pbBugContestState.expired? + next if $game_player.move_route_forcing || pbMapInterpreterRunning? || + $game_temp.message_window_showing + pbMessage(_INTL("ANNOUNCER: BEEEEEP!")) pbMessage(_INTL("Time's up!")) pbBugContestState.pbStartJudging - end -} + } +) -Events.onMapChanging += proc { |_sender, e| - newmapID = e[0] - if pbInBugContest? && pbBugContestState.pbOffLimits?(newmapID) +EventHandlers.add(:on_leave_map, :end_bug_contest, + proc { |new_map_id, new_map| + next if !pbInBugContest? || !pbBugContestState.pbOffLimits?(new_map_id) # Clear bug contest if player flies/warps/teleports out of the contest pbBugContestState.pbEnd(true) - end -} + } +) def pbBugContestStartOver $player.party.each do |pkmn| @@ -326,19 +330,21 @@ def pbBugContestStartOver pbBugContestState.pbStartJudging end -Events.onWildBattleOverride += proc { |_sender, e| - species = e[0] - level = e[1] - handled = e[2] - next if handled[0] != nil - next if !pbInBugContest? - handled[0] = pbBugContestBattle(species, level) -} +EventHandlers.add(:on_calling_wild_battle, :bug_contest_battle, + proc { |species, level, handled| + # handled is an array: [nil]. If [true] or [false], the battle has already + # been overridden (the boolean is its outcome), so don't do anything that + # would override it again + next if !handled[0].nil? + next if !pbInBugContest? + handled[0] = pbBugContestBattle(species, level) + } +) def pbBugContestBattle(species, level) # Record information about party Pokémon to be used at the end of battle (e.g. # comparing levels for an evolution check) - Events.onStartBattle.trigger(nil) + EventHandlers.trigger(:on_start_battle) # Generate a wild Pokémon based on the species and level pkmn = pbGenerateWildPokemon(species, level) foeParty = [pkmn] @@ -387,7 +393,7 @@ def pbBugContestBattle(species, level) end pbSet(1, decision) # Used by the Poké Radar to update/break the chain - Events.onWildBattleEnd.trigger(nil, species, level, decision) + EventHandlers.trigger(:on_wild_battle_end, species, level, decision) # Return false if the player lost or drew the battle, and true if any other result return (decision != 2 && decision != 5) end