From 22f0c8627a56b3d893618a38039e07ce652830e5 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 15 May 2022 20:28:06 +0100 Subject: [PATCH] Refactored battle-starting methods into WildBattle.start and TrainerBattle.start, etc. --- .../001_SafariBattle.rb | 2 + Data/Scripts/012_Overworld/001_Overworld.rb | 4 +- .../001_Overworld_BattleStarting.rb | 952 ++++++++++-------- .../003_Overworld_WildEncounters.rb | 4 +- .../005_Overworld_RoamingPokemon.rb | 2 +- .../004_Challenge_Battles.rb | 6 +- .../001_SafariZone.rb | 4 +- .../002_BugContest.rb | 20 +- .../003_Debug menus/002_Debug_MenuCommands.rb | 12 +- .../004_Compiler_MapsAndEvents.rb | 164 ++- 10 files changed, 700 insertions(+), 470 deletions(-) diff --git a/Data/Scripts/011_Battle/007_Other battle types/001_SafariBattle.rb b/Data/Scripts/011_Battle/007_Other battle types/001_SafariBattle.rb index 03000d664..1f3998f43 100644 --- a/Data/Scripts/011_Battle/007_Other battle types/001_SafariBattle.rb +++ b/Data/Scripts/011_Battle/007_Other battle types/001_SafariBattle.rb @@ -330,6 +330,8 @@ class SafariBattle @ballCount = 0 end + def disablePokeBalls=(value); end + def sendToBoxes=(value); end def defaultWeather=(value); @weather = value; end def defaultTerrain=(value); end diff --git a/Data/Scripts/012_Overworld/001_Overworld.rb b/Data/Scripts/012_Overworld/001_Overworld.rb index 8de30f668..0fab28480 100644 --- a/Data/Scripts/012_Overworld/001_Overworld.rb +++ b/Data/Scripts/012_Overworld/001_Overworld.rb @@ -210,9 +210,9 @@ def pbBattleOnStepTaken(repel_active) if $PokemonEncounters.have_double_wild_battle? encounter2 = $PokemonEncounters.choose_wild_pokemon(encounter_type) EventHandlers.trigger(:on_wild_species_chosen, encounter2) - pbDoubleWildBattle(encounter[0], encounter[1], encounter2[0], encounter2[1]) + WildBattle.start(encounter, encounter2, can_override: true) else - pbWildBattle(encounter[0], encounter[1]) + WildBattle.start(encounter, can_override: true) end $game_temp.encounter_type = nil $game_temp.encounter_triggered = true 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 cf708b68d..ea25b989a 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 @@ -82,104 +82,6 @@ def setBattleRule(*args) raise _INTL("Argument {1} expected a variable after it but didn't have one.", r) if r end -def pbNewBattleScene - return Battle::Scene.new -end - -# Sets up various battle parameters and applies special rules. -def pbPrepareBattle(battle) - battleRules = $game_temp.battle_rules - # The size of the battle, i.e. how many Pokémon on each side (default: "single") - battle.setBattleMode(battleRules["size"]) if !battleRules["size"].nil? - # Whether the game won't black out even if the player loses (default: false) - battle.canLose = battleRules["canLose"] if !battleRules["canLose"].nil? - # Whether the player can choose to run from the battle (default: true) - battle.canRun = battleRules["canRun"] if !battleRules["canRun"].nil? - # Whether wild Pokémon always try to run from battle (default: nil) - battle.rules["alwaysflee"] = battleRules["roamerFlees"] - # Whether Pokémon gain Exp/EVs from defeating/catching a Pokémon (default: true) - battle.expGain = battleRules["expGain"] if !battleRules["expGain"].nil? - # Whether the player gains/loses money at the end of the battle (default: true) - battle.moneyGain = battleRules["moneyGain"] if !battleRules["moneyGain"].nil? - # Whether Poké Balls cannot be thrown at all - battle.disablePokeBalls = battleRules["disablePokeBalls"] if !battleRules["disablePokeBalls"].nil? - # Whether the player is asked what to do with a new Pokémon when their party is full - battle.sendToBoxes = $PokemonSystem.sendtoboxes if Settings::NEW_CAPTURE_CAN_REPLACE_PARTY_MEMBER - battle.sendToBoxes = 2 if battleRules["forceCatchIntoParty"] - # Whether the player is able to switch when an opponent's Pokémon faints - battle.switchStyle = ($PokemonSystem.battlestyle == 0) - battle.switchStyle = battleRules["switchStyle"] if !battleRules["switchStyle"].nil? - # Whether battle animations are shown - battle.showAnims = ($PokemonSystem.battlescene == 0) - battle.showAnims = battleRules["battleAnims"] if !battleRules["battleAnims"].nil? - # Terrain - if battleRules["defaultTerrain"].nil? && Settings::OVERWORLD_WEATHER_SETS_BATTLE_TERRAIN - case $game_screen.weather_type - when :Storm - battle.defaultTerrain = :Electric - when :Fog - battle.defaultTerrain = :Misty - end - else - battle.defaultTerrain = battleRules["defaultTerrain"] - end - # Weather - if battleRules["defaultWeather"].nil? - case GameData::Weather.get($game_screen.weather_type).category - when :Rain, :Storm - battle.defaultWeather = :Rain - when :Hail - battle.defaultWeather = :Hail - when :Sandstorm - battle.defaultWeather = :Sandstorm - when :Sun - battle.defaultWeather = :Sun - end - else - battle.defaultWeather = battleRules["defaultWeather"] - end - # Environment - if battleRules["environment"].nil? - battle.environment = pbGetEnvironment - else - battle.environment = battleRules["environment"] - end - # Backdrop graphic filename - if !battleRules["backdrop"].nil? - backdrop = battleRules["backdrop"] - elsif $PokemonGlobal.nextBattleBack - backdrop = $PokemonGlobal.nextBattleBack - elsif $PokemonGlobal.surfing - backdrop = "water" # This applies wherever you are, including in caves - elsif $game_map.metadata - back = $game_map.metadata.battle_background - backdrop = back if back && back != "" - end - backdrop = "indoor1" if !backdrop - battle.backdrop = backdrop - # Choose a name for bases depending on environment - if battleRules["base"].nil? - environment_data = GameData::Environment.try_get(battle.environment) - base = environment_data.battle_base if environment_data - else - base = battleRules["base"] - end - battle.backdropBase = base if base - # Time of day - if $game_map.metadata&.battle_environment == :Cave - battle.time = 2 # This makes Dusk Balls work properly in caves - elsif Settings::TIME_SHADING - timeNow = pbGetTimeNow - if PBDayNight.isNight?(timeNow) - battle.time = 2 - elsif PBDayNight.isEvening?(timeNow) - battle.time = 1 - else - battle.time = 0 - end - end -end - # Used to determine the environment in battle, and also the form of Burmy/ # Wormadam. def pbGetEnvironment @@ -217,7 +119,8 @@ EventHandlers.add(:on_start_battle, :record_party_status, ) def pbCanDoubleBattle? - return $PokemonGlobal.partner || $player.able_pokemon_count >= 2 + return true if $player.able_pokemon_count >= 2 + return $PokemonGlobal.partner && $player.able_pokemon_count >= 1 end def pbCanTripleBattle? @@ -226,83 +129,186 @@ def pbCanTripleBattle? end #=============================================================================== -# Start a wild battle +# Helper methods for setting up and closing down battles #=============================================================================== -def pbWildBattleCore(*args) - outcomeVar = $game_temp.battle_rules["outcomeVar"] || 1 - canLose = $game_temp.battle_rules["canLose"] || false +module BattleCreationHelperMethods + module_function + # Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode - if $player.able_pokemon_count == 0 || ($DEBUG && Input.press?(Input::CTRL)) - pbMessage(_INTL("SKIPPING BATTLE...")) if $player.pokemon_count > 0 - pbSet(outcomeVar, 1) # Treat it as a win + def skip_battle? + return true if $player.able_pokemon_count == 0 + return true if $DEBUG && Input.press?(Input::CTRL) + return false + end + + def skip_battle(outcome_variable, trainer_battle = false) + pbMessage(_INTL("SKIPPING BATTLE...")) if !trainer_battle && $player.pokemon_count > 0 + pbMessage(_INTL("SKIPPING BATTLE...")) if trainer_battle && $DEBUG + pbMessage(_INTL("AFTER WINNING...")) if trainer_battle && $player.able_pokemon_count > 0 $game_temp.clear_battle_rules $PokemonGlobal.nextBattleBGM = nil $PokemonGlobal.nextBattleVictoryBGM = nil $PokemonGlobal.nextBattleCaptureME = nil $PokemonGlobal.nextBattleBack = nil pbMEStop - return 1 # Treat it as a win + outcome = 1 # Win + outcome = 0 if trainer_battle && $player.able_pokemon_count == 0 # Undecided + pbSet(outcome_variable, outcome) + return outcome end - # Record information about party Pokémon to be used at the end of battle (e.g. - # comparing levels for an evolution check) - EventHandlers.trigger(:on_start_battle) - # Generate wild Pokémon based on the species and level - foeParty = [] - sp = nil - args.each do |arg| - if arg.is_a?(Pokemon) - foeParty.push(arg) - elsif arg.is_a?(Array) - species = GameData::Species.get(arg[0]).id - pkmn = pbGenerateWildPokemon(species, arg[1]) - foeParty.push(pkmn) - elsif sp - species = GameData::Species.get(sp).id - pkmn = pbGenerateWildPokemon(species, arg) - foeParty.push(pkmn) - sp = nil + + def partner_can_participate?(foe_party) + return false if !$PokemonGlobal.partner || $game_temp.battle_rules["noPartner"] + return true if foe_party.length > 1 + if $game_temp.battle_rules["size"] + return false if $game_temp.battle_rules["size"] == "single" || + $game_temp.battle_rules["size"][/^1v/i] # "1v1", "1v2", "1v3", etc. + return true + end + return false + end + + # Generate information for the player and partner trainer(s) + def set_up_player_trainers(foe_party) + trainer_array = [$player] + ally_items = [] + pokemon_array = $player.party + party_starts = [0] + if partner_can_participate?(foe_party) + ally = NPCTrainer.new($PokemonGlobal.partner[1], $PokemonGlobal.partner[0]) + ally.id = $PokemonGlobal.partner[2] + ally.party = $PokemonGlobal.partner[3] + ally_items[1] = ally.items.clone + trainer_array.push(ally) + pokemon_array = [] + $player.party.each { |pkmn| pokemon_array.push(pkmn) } + party_starts.push(pokemon_array.length) + ally.party.each { |pkmn| pokemon_array.push(pkmn) } + setBattleRule("double") if $game_temp.battle_rules["size"].nil? + end + return trainer_array, ally_items, pokemon_array, party_starts + end + + def create_battle_scene + return Battle::Scene.new + end + + # Sets up various battle parameters and applies special rules. + def prepare_battle(battle) + battleRules = $game_temp.battle_rules + # The size of the battle, i.e. how many Pokémon on each side (default: "single") + battle.setBattleMode(battleRules["size"]) if !battleRules["size"].nil? + # Whether the game won't black out even if the player loses (default: false) + battle.canLose = battleRules["canLose"] if !battleRules["canLose"].nil? + # Whether the player can choose to run from the battle (default: true) + battle.canRun = battleRules["canRun"] if !battleRules["canRun"].nil? + # Whether wild Pokémon always try to run from battle (default: nil) + battle.rules["alwaysflee"] = battleRules["roamerFlees"] + # Whether Pokémon gain Exp/EVs from defeating/catching a Pokémon (default: true) + battle.expGain = battleRules["expGain"] if !battleRules["expGain"].nil? + # Whether the player gains/loses money at the end of the battle (default: true) + battle.moneyGain = battleRules["moneyGain"] if !battleRules["moneyGain"].nil? + # Whether Poké Balls cannot be thrown at all + battle.disablePokeBalls = battleRules["disablePokeBalls"] if !battleRules["disablePokeBalls"].nil? + # Whether the player is asked what to do with a new Pokémon when their party is full + battle.sendToBoxes = $PokemonSystem.sendtoboxes if Settings::NEW_CAPTURE_CAN_REPLACE_PARTY_MEMBER + battle.sendToBoxes = 2 if battleRules["forceCatchIntoParty"] + # Whether the player is able to switch when an opponent's Pokémon faints + battle.switchStyle = ($PokemonSystem.battlestyle == 0) + battle.switchStyle = battleRules["switchStyle"] if !battleRules["switchStyle"].nil? + # Whether battle animations are shown + battle.showAnims = ($PokemonSystem.battlescene == 0) + battle.showAnims = battleRules["battleAnims"] if !battleRules["battleAnims"].nil? + # Terrain + if battleRules["defaultTerrain"].nil? && Settings::OVERWORLD_WEATHER_SETS_BATTLE_TERRAIN + case $game_screen.weather_type + when :Storm + battle.defaultTerrain = :Electric + when :Fog + battle.defaultTerrain = :Misty + end else - sp = arg + battle.defaultTerrain = battleRules["defaultTerrain"] + end + # Weather + if battleRules["defaultWeather"].nil? + case GameData::Weather.get($game_screen.weather_type).category + when :Rain, :Storm + battle.defaultWeather = :Rain + when :Hail + battle.defaultWeather = :Hail + when :Sandstorm + battle.defaultWeather = :Sandstorm + when :Sun + battle.defaultWeather = :Sun + end + else + battle.defaultWeather = battleRules["defaultWeather"] + end + # Environment + if battleRules["environment"].nil? + battle.environment = pbGetEnvironment + else + battle.environment = battleRules["environment"] + end + # Backdrop graphic filename + if !battleRules["backdrop"].nil? + backdrop = battleRules["backdrop"] + elsif $PokemonGlobal.nextBattleBack + backdrop = $PokemonGlobal.nextBattleBack + elsif $PokemonGlobal.surfing + backdrop = "water" # This applies wherever you are, including in caves + elsif $game_map.metadata + back = $game_map.metadata.battle_background + backdrop = back if back && back != "" + end + backdrop = "indoor1" if !backdrop + battle.backdrop = backdrop + # Choose a name for bases depending on environment + if battleRules["base"].nil? + environment_data = GameData::Environment.try_get(battle.environment) + base = environment_data.battle_base if environment_data + else + base = battleRules["base"] + end + battle.backdropBase = base if base + # Time of day + if $game_map.metadata&.battle_environment == :Cave + battle.time = 2 # This makes Dusk Balls work properly in caves + elsif Settings::TIME_SHADING + timeNow = pbGetTimeNow + if PBDayNight.isNight?(timeNow) + battle.time = 2 + elsif PBDayNight.isEvening?(timeNow) + battle.time = 1 + else + battle.time = 0 + end end end - raise _INTL("Expected a level after being given {1}, but one wasn't found.", sp) if sp - # Calculate who the trainers and their party are - playerTrainers = [$player] - playerParty = $player.party - playerPartyStarts = [0] - room_for_partner = (foeParty.length > 1) - if !room_for_partner && $game_temp.battle_rules["size"] && - !["single", "1v1", "1v2", "1v3"].include?($game_temp.battle_rules["size"]) - room_for_partner = true + + def after_battle(outcome, can_lose) + $player.party.each do |pkmn| + pkmn.statusCount = 0 if pkmn.status == :POISON # Bad poison becomes regular + pkmn.makeUnmega + pkmn.makeUnprimal + end + if $PokemonGlobal.partner + $player.heal_party + $PokemonGlobal.partner[3].each do |pkmn| + pkmn.heal + pkmn.makeUnmega + pkmn.makeUnprimal + end + end + if [2, 5].include?(outcome) && can_lose # if loss or draw + $player.party.each { |pkmn| pkmn.heal } + (Graphics.frame_rate / 4).times { Graphics.update } + end + EventHandlers.trigger(:on_end_battle, outcome, can_lose) + $game_player.straighten end - if $PokemonGlobal.partner && !$game_temp.battle_rules["noPartner"] && room_for_partner - ally = NPCTrainer.new($PokemonGlobal.partner[1], $PokemonGlobal.partner[0]) - ally.id = $PokemonGlobal.partner[2] - ally.party = $PokemonGlobal.partner[3] - playerTrainers.push(ally) - playerParty = [] - $player.party.each { |pkmn| playerParty.push(pkmn) } - playerPartyStarts.push(playerParty.length) - ally.party.each { |pkmn| playerParty.push(pkmn) } - setBattleRule("double") if !$game_temp.battle_rules["size"] - end - # Create the battle scene (the visual side of it) - scene = pbNewBattleScene - # Create the battle class (the mechanics side of it) - battle = Battle.new(scene, playerParty, foeParty, playerTrainers, nil) - battle.party1starts = playerPartyStarts - # Set various other properties in the battle class - pbPrepareBattle(battle) - $game_temp.clear_battle_rules - # Perform the battle itself - decision = 0 - pbBattleAnimation(pbGetWildBattleBGM(foeParty), (foeParty.length == 1) ? 0 : 2, foeParty) { - pbSceneStandby { - decision = battle.pbStartBattle - } - pbAfterBattle(decision, canLose) - } - Input.update + # Save the result of the battle in a Game Variable (1 by default) # 0 - Undecided or aborted # 1 - Player won @@ -310,293 +316,285 @@ def pbWildBattleCore(*args) # 3 - Player or wild Pokémon ran from battle, or player forfeited the match # 4 - Wild Pokémon was caught # 5 - Draw - case decision - when 1, 4 # Won, caught - $stats.wild_battles_won += 1 - when 2, 3, 5 # Lost, fled, draw - $stats.wild_battles_lost += 1 + def set_outcome(outcome, outcome_variable = 1, trainer_battle = false) + case outcome + when 1, 4 # Won, caught + $stats.wild_battles_won += 1 if !trainer_battle + $stats.trainer_battles_won += 1 if trainer_battle + when 2, 3, 5 # Lost, fled, draw + $stats.wild_battles_lost += 1 if !trainer_battle + $stats.trainer_battles_lost += 1 if trainer_battle + end + pbSet(outcome_variable, outcome) end - pbSet(outcomeVar, decision) - return decision end #=============================================================================== -# Standard methods that start a wild battle of various sizes +# Wild battles #=============================================================================== -# Used when walking in tall grass, hence the additional code. -def pbWildBattle(species, level, outcomeVar = 1, canRun = true, canLose = false) - species = GameData::Species.get(species).id - # Potentially call a different pbWildBattle-type method instead (for roaming - # Pokémon, Safari battles, Bug Contest battles) - handled = [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 - setBattleRule("canLose") if canLose - # Perform the battle - decision = pbWildBattleCore(species, level) - # Used by the Poké Radar to update/break the chain - 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 +class WildBattle + # Used when walking in tall grass, hence the additional code. + def self.start(*args, can_override: false) + foe_party = WildBattle.generate_foes(*args) + # Potentially call a different WildBattle.start-type method instead (for + # roaming Pokémon, Safari battles, Bug Contest battles) + if foe_party.length == 1 && can_override + handled = [nil] + EventHandlers.trigger(:on_calling_wild_battle, foe_party[0].species, foe_party[0].level, handled) + return handled[0] if !handled[0].nil? + end + # Perform the battle + outcome = WildBattle.start_core(*foe_party) + # Used by the Poké Radar to update/break the chain + if foe_party.length == 1 && can_override + EventHandlers.trigger(:on_wild_battle_end, foe_party[0].species, foe_party[0].level, outcome) + end + # Return false if the player lost or drew the battle, and true if any other result + return outcome != 2 && outcome != 5 + end -def pbDoubleWildBattle(species1, level1, species2, level2, - outcomeVar = 1, canRun = true, canLose = false) - # Set some battle rules - setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 - setBattleRule("cannotRun") if !canRun - setBattleRule("canLose") if canLose - setBattleRule("double") - # Perform the battle - decision = pbWildBattleCore(species1, level1, species2, level2) - # Return false if the player lost or drew the battle, and true if any other result - return (decision != 2 && decision != 5) -end - -def pbTripleWildBattle(species1, level1, species2, level2, species3, level3, - outcomeVar = 1, canRun = true, canLose = false) - # Set some battle rules - setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 - setBattleRule("cannotRun") if !canRun - setBattleRule("canLose") if canLose - setBattleRule("triple") - # Perform the battle - decision = pbWildBattleCore(species1, level1, species2, level2, species3, level3) - # Return false if the player lost or drew the battle, and true if any other result - return (decision != 2 && decision != 5) -end - -#=============================================================================== -# Start a trainer battle -#=============================================================================== -def pbTrainerBattleCore(*args) - outcomeVar = $game_temp.battle_rules["outcomeVar"] || 1 - canLose = $game_temp.battle_rules["canLose"] || false - # Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode - if $player.able_pokemon_count == 0 || ($DEBUG && Input.press?(Input::CTRL)) - pbMessage(_INTL("SKIPPING BATTLE...")) if $DEBUG - pbMessage(_INTL("AFTER WINNING...")) if $DEBUG && $player.able_pokemon_count > 0 - pbSet(outcomeVar, ($player.able_pokemon_count == 0) ? 0 : 1) # Treat it as undecided/a win + def self.start_core(*args) + outcome_variable = $game_temp.battle_rules["outcomeVar"] || 1 + can_lose = $game_temp.battle_rules["canLose"] || false + # Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode + if BattleCreationHelperMethods.skip_battle? + return BattleCreationHelperMethods.skip_battle(outcome_variable) + end + # Record information about party Pokémon to be used at the end of battle + # (e.g. comparing levels for an evolution check) + EventHandlers.trigger(:on_start_battle) + # Generate array of foes + foe_party = WildBattle.generate_foes(*args) + # Generate information for the player and partner trainer(s) + player_trainers, ally_items, player_party, player_party_starts = BattleCreationHelperMethods.set_up_player_trainers(foe_party) + # Create the battle scene (the visual side of it) + scene = BattleCreationHelperMethods.create_battle_scene + # Create the battle class (the mechanics side of it) + battle = Battle.new(scene, player_party, foe_party, player_trainers, nil) + battle.party1starts = player_party_starts + battle.ally_items = ally_items + # Set various other properties in the battle class + setBattleRule("#{foe_party.length}v#{foe_party.length}") if $game_temp.battle_rules["size"].nil? + BattleCreationHelperMethods.prepare_battle(battle) $game_temp.clear_battle_rules - $PokemonGlobal.nextBattleBGM = nil - $PokemonGlobal.nextBattleVictoryBGM = nil - $PokemonGlobal.nextBattleCaptureME = nil - $PokemonGlobal.nextBattleBack = nil - pbMEStop - return ($player.able_pokemon_count == 0) ? 0 : 1 # Treat it as undecided/a win - end - # Record information about party Pokémon to be used at the end of battle (e.g. - # comparing levels for an evolution check) - EventHandlers.trigger(:on_start_battle) - # Generate trainers and their parties based on the arguments given - foeTrainers = [] - foeItems = [] - foeEndSpeeches = [] - foeParty = [] - foePartyStarts = [] - args.each do |arg| - case arg - when NPCTrainer - foeTrainers.push(arg) - foePartyStarts.push(foeParty.length) - arg.party.each { |pkmn| foeParty.push(pkmn) } - foeEndSpeeches.push(arg.lose_text) - foeItems.push(arg.items) - when Array # [trainer type, trainer name, ID, speech (optional)] - trainer = pbLoadTrainer(arg[0], arg[1], arg[2]) - pbMissingTrainer(arg[0], arg[1], arg[2]) if !trainer - return 0 if !trainer - EventHandlers.trigger(:on_trainer_load, trainer) - foeTrainers.push(trainer) - foePartyStarts.push(foeParty.length) - trainer.party.each { |pkmn| foeParty.push(pkmn) } - foeEndSpeeches.push(arg[3] || trainer.lose_text) - foeItems.push(trainer.items) - else - raise _INTL("Expected NPCTrainer or array of trainer data, got {1}.", arg) - end - end - # Calculate who the player trainer(s) and their party are - playerTrainers = [$player] - allyItems = [] - playerParty = $player.party - playerPartyStarts = [0] - room_for_partner = (foeParty.length > 1) - if !room_for_partner && $game_temp.battle_rules["size"] && - !["single", "1v1", "1v2", "1v3"].include?($game_temp.battle_rules["size"]) - room_for_partner = true - end - if $PokemonGlobal.partner && !$game_temp.battle_rules["noPartner"] && room_for_partner - ally = NPCTrainer.new($PokemonGlobal.partner[1], $PokemonGlobal.partner[0]) - ally.id = $PokemonGlobal.partner[2] - ally.party = $PokemonGlobal.partner[3] - allyItems[1] = ally.items.clone - playerTrainers.push(ally) - playerParty = [] - $player.party.each { |pkmn| playerParty.push(pkmn) } - playerPartyStarts.push(playerParty.length) - ally.party.each { |pkmn| playerParty.push(pkmn) } - setBattleRule("double") if !$game_temp.battle_rules["size"] - end - # Create the battle scene (the visual side of it) - scene = pbNewBattleScene - # Create the battle class (the mechanics side of it) - battle = Battle.new(scene, playerParty, foeParty, playerTrainers, foeTrainers) - battle.party1starts = playerPartyStarts - battle.party2starts = foePartyStarts - battle.items = foeItems - battle.ally_items = allyItems - battle.endSpeeches = foeEndSpeeches - # Set various other properties in the battle class - pbPrepareBattle(battle) - $game_temp.clear_battle_rules - # Perform the battle itself - decision = 0 - pbBattleAnimation(pbGetTrainerBattleBGM(foeTrainers), (battle.singleBattle?) ? 1 : 3, foeTrainers) { - pbSceneStandby { - decision = battle.pbStartBattle + # Perform the battle itself + outcome = 0 + pbBattleAnimation(pbGetWildBattleBGM(foe_party), (foe_party.length == 1) ? 0 : 2, foe_party) { + pbSceneStandby { + outcome = battle.pbStartBattle + } + BattleCreationHelperMethods.after_battle(outcome, can_lose) } - pbAfterBattle(decision, canLose) - } - Input.update - # Save the result of the battle in a Game Variable (1 by default) - # 0 - Undecided or aborted - # 1 - Player won - # 2 - Player lost - # 3 - Player or wild Pokémon ran from battle, or player forfeited the match - # 5 - Draw - case decision - when 1 # Won - $stats.trainer_battles_won += 1 - when 2, 3, 5 # Lost, fled, draw - $stats.trainer_battles_lost += 1 + Input.update + # Save the result of the battle in a Game Variable (1 by default) + BattleCreationHelperMethods.set_outcome(outcome, outcome_variable) + return outcome + end + + def self.generate_foes(*args) + ret = [] + species_id = nil + args.each do |arg| + case arg + when Pokemon + raise _INTL("Species {1} was given but not a level.", species_id) if species_id + ret.push(arg) + when Array + raise _INTL("Species {1} was given but not a level.", species_id) if species_id + species = GameData::Species.get(arg[0]).id + pkmn = pbGenerateWildPokemon(species, arg[1]) + ret.push(pkmn) + else + if species_id # Expecting level + if !arg.is_a?(Integer) || !(1..GameData::GrowthRate.max_level).include?(arg) + raise _INTL("Expected a level (1..{1}) but {2} is not a number or not a valid level.", GameData::GrowthRate.max_level, arg) + end + ret.push(pbGenerateWildPokemon(species_id, arg)) + species_id = nil + else # Expecting species ID + if !GameData::Species.exists?(arg) + raise _INTL("Species {1} does not exist.", arg) + end + species_id = arg + end + end + end + raise _INTL("Species {1} was given but not a level.", species_id) if species_id + return ret end - pbSet(outcomeVar, decision) - return decision end #=============================================================================== -# Standard methods that start a trainer battle of various sizes +# Trainer battles #=============================================================================== -# Used by most trainer events, which can be positioned in such a way that -# multiple trainer events spot the player at once. The extra code in this method -# deals with that case and can cause a double trainer battle instead. -def pbTrainerBattle(trainerID, trainerName, endSpeech = nil, - doubleBattle = false, trainerPartyID = 0, canLose = false, outcomeVar = 1) - # If there is another NPC trainer who spotted the player at the same time, and - # it is possible to have a double battle (the player has 2+ able Pokémon or - # has a partner trainer), then record this first NPC trainer into - # $game_temp.waiting_trainer and end this method. That second NPC event will - # then trigger and cause the battle to happen against this first trainer and - # themselves. - if !$game_temp.waiting_trainer && pbMapInterpreterRunning? && - ($player.able_pokemon_count > 1 || - ($player.able_pokemon_count > 0 && $PokemonGlobal.partner)) - thisEvent = pbMapInterpreter.get_self - # Find all other triggered trainer events - triggeredEvents = $game_player.pbTriggeredTrainerEvents([2], false) - otherEvent = [] - triggeredEvents.each do |i| - next if i.id == thisEvent.id - next if $game_self_switches[[$game_map.map_id, i.id, "A"]] - otherEvent.push(i) +class TrainerBattle + # Used by most trainer events, which can be positioned in such a way that + # multiple trainer events spot the player at once. The extra code in this + # method deals with that case and can cause a double trainer battle instead. + def self.start(*args) + # If there is another NPC trainer who spotted the player at the same time, + # and it is possible to have a double battle (the player has 2+ able Pokémon + # or has a partner trainer), then record this first NPC trainer into + # $game_temp.waiting_trainer and end this method. That second NPC event will + # then trigger and cause the battle to happen against this first trainer and + # themselves. + if !$game_temp.waiting_trainer && pbMapInterpreterRunning? && pbCanDoubleBattle? + thisEvent = pbMapInterpreter.get_self + # Find all other triggered trainer events + triggeredEvents = $game_player.pbTriggeredTrainerEvents([2], false) + otherEvent = [] + triggeredEvents.each do |i| + next if i.id == thisEvent.id + next if $game_self_switches[[$game_map.map_id, i.id, "A"]] + otherEvent.push(i) + end + # If there is exactly 1 other triggered trainer event, this trainer can be + # stored up to battle with that one + if otherEvent.length == 1 + trainers, _items, _end_speeches, _party, _party_starts = TrainerBattle.generate_foes(*args) + # If this is just 1 trainer with 6 or fewer Pokémon, it can be stored up + # to battle alongside the other trainer + if trainers.length == 1 && trainers[0].party.length <= Settings::MAX_PARTY_SIZE + $game_temp.waiting_trainer = [trainers[0], thisEvent.id] + return false + end + end end - # Load the trainer's data, and call an event which might modify it - trainer = pbLoadTrainer(trainerID, trainerName, trainerPartyID) - pbMissingTrainer(trainerID, trainerName, trainerPartyID) if !trainer - return false if !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 - if otherEvent.length == 1 && trainer.party.length <= Settings::MAX_PARTY_SIZE - trainer.lose_text = endSpeech if endSpeech && !endSpeech.empty? - $game_temp.waiting_trainer = [trainer, thisEvent.id] - return false + # Perform the battle + if $game_temp.waiting_trainer + new_args = args + [$game_temp.waiting_trainer[0]] + outcome = TrainerBattle.start_core(*new_args) + pbMapInterpreter.pbSetSelfSwitch($game_temp.waiting_trainer[1], "A", true) if outcome == 1 + $game_temp.waiting_trainer = nil + else + outcome = TrainerBattle.start_core(*args) end + # Return true if the player won the battle, and false if any other result + return outcome == 1 end - # Set some battle rules - setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 - setBattleRule("canLose") if canLose - setBattleRule("double") if doubleBattle || $game_temp.waiting_trainer - # Perform the battle - if $game_temp.waiting_trainer - decision = pbTrainerBattleCore($game_temp.waiting_trainer[0], - [trainerID, trainerName, trainerPartyID, endSpeech]) - else - decision = pbTrainerBattleCore([trainerID, trainerName, trainerPartyID, endSpeech]) - end - # Finish off the recorded waiting trainer, because they have now been battled - if decision == 1 && $game_temp.waiting_trainer # Win - pbMapInterpreter.pbSetSelfSwitch($game_temp.waiting_trainer[1], "A", true) - end - $game_temp.waiting_trainer = nil - # Return true if the player won the battle, and false if any other result - return (decision == 1) -end -def pbDoubleTrainerBattle(trainerID1, trainerName1, trainerPartyID1, endSpeech1, - trainerID2, trainerName2, trainerPartyID2 = 0, endSpeech2 = nil, - canLose = false, outcomeVar = 1) - # Set some battle rules - setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 - setBattleRule("canLose") if canLose - setBattleRule("double") - # Perform the battle - decision = pbTrainerBattleCore( - [trainerID1, trainerName1, trainerPartyID1, endSpeech1], - [trainerID2, trainerName2, trainerPartyID2, endSpeech2] - ) - # Return true if the player won the battle, and false if any other result - return (decision == 1) -end + def self.start_core(*args) + outcome_variable = $game_temp.battle_rules["outcomeVar"] || 1 + can_lose = $game_temp.battle_rules["canLose"] || false + # Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode + if BattleCreationHelperMethods.skip_battle? + return BattleCreationHelperMethods.skip_battle(outcome_variable, true) + end + # Record information about party Pokémon to be used at the end of battle (e.g. + # comparing levels for an evolution check) + EventHandlers.trigger(:on_start_battle) + # Generate information for the foes + foe_trainers, foe_items, end_speeches, foe_party, foe_party_starts = TrainerBattle.generate_foes(*args) + # Generate information for the player and partner trainer(s) + player_trainers, ally_items, player_party, player_party_starts = BattleCreationHelperMethods.set_up_player_trainers(foe_party) + # Create the battle scene (the visual side of it) + scene = BattleCreationHelperMethods.create_battle_scene + # Create the battle class (the mechanics side of it) + battle = Battle.new(scene, player_party, foe_party, player_trainers, foe_trainers) + battle.party1starts = player_party_starts + battle.party2starts = foe_party_starts + battle.ally_items = ally_items + battle.items = foe_items + battle.endSpeeches = end_speeches + # Set various other properties in the battle class + setBattleRule("#{foe_trainers.length}v#{foe_trainers.length}") if $game_temp.battle_rules["size"].nil? + BattleCreationHelperMethods.prepare_battle(battle) + $game_temp.clear_battle_rules + # Perform the battle itself + outcome = 0 + pbBattleAnimation(pbGetTrainerBattleBGM(foe_trainers), (battle.singleBattle?) ? 1 : 3, foe_trainers) { + pbSceneStandby { + outcome = battle.pbStartBattle + } + BattleCreationHelperMethods.after_battle(outcome, can_lose) + } + Input.update + # Save the result of the battle in a Game Variable (1 by default) + BattleCreationHelperMethods.set_outcome(outcome, outcome_variable, true) + return outcome + end -def pbTripleTrainerBattle(trainerID1, trainerName1, trainerPartyID1, endSpeech1, - trainerID2, trainerName2, trainerPartyID2, endSpeech2, - trainerID3, trainerName3, trainerPartyID3 = 0, endSpeech3 = nil, - canLose = false, outcomeVar = 1) - # Set some battle rules - setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 - setBattleRule("canLose") if canLose - setBattleRule("triple") - # Perform the battle - decision = pbTrainerBattleCore( - [trainerID1, trainerName1, trainerPartyID1, endSpeech1], - [trainerID2, trainerName2, trainerPartyID2, endSpeech2], - [trainerID3, trainerName3, trainerPartyID3, endSpeech3] - ) - # Return true if the player won the battle, and false if any other result - return (decision == 1) + def self.generate_foes(*args) + trainer_array = [] + foe_items = [] + end_speeches = [] + pokemon_array = [] + party_starts = [] + trainer_type = nil + trainer_name = nil + args.each_with_index do |arg, i| + case arg + when NPCTrainer + raise _INTL("Trainer type {1} was given but not a trainer name.", trainer_type) if trainer_type + trainer_array.push(arg) + foe_items.push(arg.items) + end_speeches.push(arg.lose_text) + party_starts.push(pokemon_array.length) + arg.party.each { |pkmn| pokemon_array.push(pkmn) } + when Array # [trainer type, trainer name, version number, speech (optional)] + raise _INTL("Trainer type {1} was given but not a trainer name.", trainer_type) if trainer_type + trainer = pbLoadTrainer(arg[0], arg[1], arg[2]) + pbMissingTrainer(arg[0], arg[1], arg[2]) if !trainer + trainer = pbLoadTrainer(arg[0], arg[1], arg[2]) if !trainer # Try again + raise _INTL("Trainer for data '{1}' is not defined.", arg) if !trainer + EventHandlers.trigger(:on_trainer_load, trainer) + trainer_array.push(trainer) + foe_items.push(trainer.items) + end_speeches.push(arg[3] || trainer.lose_text) + party_starts.push(pokemon_array.length) + trainer.party.each { |pkmn| pokemon_array.push(pkmn) } + else + if trainer_name # Expecting version number + if !arg.is_a?(Integer) || arg < 0 + raise _INTL("Expected a trainer version number (0 or higher) but {1} is not a number or not a valid value.", arg) + end + trainer = pbLoadTrainer(trainer_type, trainer_name, arg) + pbMissingTrainer(trainer_type, trainer_name, arg) if !trainer + trainer = pbLoadTrainer(trainer_type, trainer_name, arg) if !trainer # Try again + raise _INTL("Trainer for data '{1}, {2}, {3}' is not defined.", trainer_type, trainer_name, arg) if !trainer + EventHandlers.trigger(:on_trainer_load, trainer) + trainer_array.push(trainer) + foe_items.push(trainer.items) + end_speeches.push(trainer.lose_text) + party_starts.push(pokemon_array.length) + trainer.party.each { |pkmn| pokemon_array.push(pkmn) } + trainer_type = nil + trainer_name = nil + elsif trainer_type # Expecting trainer name + if !arg.is_a?(String) || arg.strip.empty? + raise _INTL("Expected a trainer name but '{1}' is not a valid name.", arg) + end + if args[i + 1].is_a?(Integer) # Version number is next + trainer_name = arg.strip + else + trainer = pbLoadTrainer(trainer_type, arg) + pbMissingTrainer(trainer_type, arg, 0) if !trainer + trainer = pbLoadTrainer(trainer_type, arg) if !trainer # Try again + raise _INTL("Trainer for data '{1}, {2}' is not defined.", trainer_type, arg) if !trainer + EventHandlers.trigger(:on_trainer_load, trainer) + trainer_array.push(trainer) + foe_items.push(trainer.items) + end_speeches.push(trainer.lose_text) + party_starts.push(pokemon_array.length) + trainer.party.each { |pkmn| pokemon_array.push(pkmn) } + trainer_type = nil + end + else # Expecting trainer type + if !GameData::TrainerType.exists?(arg) + raise _INTL("Trainer type {1} does not exist.", arg) + end + trainer_type = arg + end + end + end + raise _INTL("Trainer type {1} was given but not a trainer name.", trainer_type) if trainer_type + return trainer_array, foe_items, end_speeches, pokemon_array, party_starts + end end #=============================================================================== # After battles #=============================================================================== -def pbAfterBattle(decision, canLose) - $player.party.each do |pkmn| - pkmn.statusCount = 0 if pkmn.status == :POISON # Bad poison becomes regular - pkmn.makeUnmega - pkmn.makeUnprimal - end - if $PokemonGlobal.partner - $player.heal_party - $PokemonGlobal.partner[3].each do |pkmn| - pkmn.heal - pkmn.makeUnmega - pkmn.makeUnprimal - end - end - if [2, 5].include?(decision) && canLose # if loss or draw - $player.party.each { |pkmn| pkmn.heal } - (Graphics.frame_rate / 4).times { Graphics.update } - end - EventHandlers.trigger(:on_end_battle, decision, canLose) - $game_player.straighten -end - EventHandlers.add(:on_end_battle, :evolve_and_black_out, proc { |decision, canLose| # Check for evolutions @@ -739,3 +737,103 @@ def pbHoneyGather(pkmn) return unless rand(100) < chance pkmn.item = :HONEY end + +#=============================================================================== +# Deprecated methods +#=============================================================================== +# @deprecated This method is slated to be removed in v21. +def pbNewBattleScene + Deprecation.warn_method("pbNewBattleScene", "v21", "BattleCreationHelperMethods.create_battle_scene") + return BattleCreationHelperMethods.create_battle_scene +end + +# @deprecated This method is slated to be removed in v21. +def pbPrepareBattle(battle) + Deprecation.warn_method("pbPrepareBattle", "v21", "BattleCreationHelperMethods.prepare_battle(battle)") + BattleCreationHelperMethods.prepare_battle(battle) +end + +# @deprecated This method is slated to be removed in v21. +def pbWildBattleCore(*args) + Deprecation.warn_method("pbWildBattleCore", "v21", "WildBattle.start_core(species, level)") + return WildBattle.start_core(*args) +end + +# @deprecated This method is slated to be removed in v21. +def pbWildBattle(species, level, outcomeVar = 1, canRun = true, canLose = false) + Deprecation.warn_method("pbWildBattle", "v21", "WildBattle.start(species, level)") + setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 + setBattleRule("cannotRun") if !canRun + setBattleRule("canLose") if canLose + return WildBattle.start(species, level) +end + +# @deprecated This method is slated to be removed in v21. +def pbDoubleWildBattle(species1, level1, species2, level2, + outcomeVar = 1, canRun = true, canLose = false) + Deprecation.warn_method("pbDoubleWildBattle", "v21", "WildBattle.start(pkmn1, pkmn2)") + setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 + setBattleRule("cannotRun") if !canRun + setBattleRule("canLose") if canLose + setBattleRule("double") + return WildBattle.start(species1, level1, species2, level2) +end + +# @deprecated This method is slated to be removed in v21. +def pbTripleWildBattle(species1, level1, species2, level2, species3, level3, + outcomeVar = 1, canRun = true, canLose = false) + Deprecation.warn_method("pbTripleWildBattle", "v21", "WildBattle.start(pkmn1, pkmn2, pkmn3)") + setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 + setBattleRule("cannotRun") if !canRun + setBattleRule("canLose") if canLose + setBattleRule("triple") + return WildBattle.start(species1, level1, species2, level2, species3, level3) +end + +# @deprecated This method is slated to be removed in v21. +def pbTrainerBattleCore(*args) + Deprecation.warn_method("pbTrainerBattleCore", "v21", "TrainerBattle.start_core(trainer_type, trainer_name, trainer_version)") + return TrainerBattle.start_core(*args) +end + +# @deprecated This method is slated to be removed in v21. +def pbTrainerBattle(trainerID, trainerName, endSpeech = nil, + doubleBattle = false, trainerPartyID = 0, canLose = false, outcomeVar = 1) + Deprecation.warn_method("pbTrainerBattle", "v21", "TrainerBattle.start(trainer_type, trainer_name, trainer_version)") + setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 + setBattleRule("canLose") if canLose + setBattleRule("double") if doubleBattle + return TrainerBattle.start(trainerID, trainerName, trainerPartyID) +end + +# @deprecated This method is slated to be removed in v21. +def pbDoubleTrainerBattle(trainerID1, trainerName1, trainerPartyID1, endSpeech1, + trainerID2, trainerName2, trainerPartyID2 = 0, endSpeech2 = nil, + canLose = false, outcomeVar = 1) + Deprecation.warn_method("pbDoubleTrainerBattle", "v21", "TrainerBattle.start(trainer1, trainer2)") + setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 + setBattleRule("canLose") if canLose + setBattleRule("double") + return TrainerBattle.start(trainerID1, trainerName1, trainerPartyID1, + trainerID2, trainerName2, trainerPartyID2) +end + +# @deprecated This method is slated to be removed in v21. +def pbTripleTrainerBattle(trainerID1, trainerName1, trainerPartyID1, endSpeech1, + trainerID2, trainerName2, trainerPartyID2, endSpeech2, + trainerID3, trainerName3, trainerPartyID3 = 0, endSpeech3 = nil, + canLose = false, outcomeVar = 1) + Deprecation.warn_method("pbTripleTrainerBattle", "v21", "TrainerBattle.start(trainer1, trainer2, trainer3)") + setBattleRule("outcomeVar", outcomeVar) if outcomeVar != 1 + setBattleRule("canLose") if canLose + setBattleRule("triple") + return TrainerBattle.start(trainerID1, trainerName1, trainerPartyID1, + trainerID2, trainerName2, trainerPartyID2, + trainerID3, trainerName3, trainerPartyID3) +end + +# @deprecated This method is slated to be removed in v21. +def pbAfterBattle(outcome, can_lose) + Deprecation.warn_method("pbAfterBattle", "v21", "BattleCreationHelperMethods.after_battle(outcome, can_lose)") + BattleCreationHelperMethods.after_battle(outcome, can_lose) +end 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 1dee64b93..a23f263ee 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 @@ -461,9 +461,9 @@ def pbEncounter(enc_type, only_single = true) encounter2 = $PokemonEncounters.choose_wild_pokemon(enc_type) EventHandlers.trigger(:on_wild_species_chosen, encounter2) return false if !encounter2 - pbDoubleWildBattle(encounter1[0], encounter1[1], encounter2[0], encounter2[1]) + WildBattle.start(encounter1, encounter2, can_override: true) else - pbWildBattle(encounter1[0], encounter1[1]) + WildBattle.start(encounter1, can_override: true) end $game_temp.encounter_type = nil $game_temp.force_single_battle = false 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 3b2f26463..8992996a5 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 @@ -212,7 +212,7 @@ def pbRoamingPokemonBattle(species, level) setBattleRule("single") setBattleRule("roamerFlees") # Perform the battle - decision = pbWildBattleCore($PokemonGlobal.roamPokemon[idxRoamer]) + decision = WildBattle.start_core($PokemonGlobal.roamPokemon[idxRoamer]) # Update Roaming Pokémon data based on result of battle if [1, 4].include?(decision) # Defeated or caught $PokemonGlobal.roamPokemon[idxRoamer] = true diff --git a/Data/Scripts/018_Alternate battle modes/001_Battle Frontier/004_Challenge_Battles.rb b/Data/Scripts/018_Alternate battle modes/001_Battle Frontier/004_Challenge_Battles.rb index 1dafbeab8..04f73b08a 100644 --- a/Data/Scripts/018_Alternate battle modes/001_Battle Frontier/004_Challenge_Battles.rb +++ b/Data/Scripts/018_Alternate battle modes/001_Battle Frontier/004_Challenge_Battles.rb @@ -54,14 +54,14 @@ def pbOrganizedBattleEx(opponent, challengedata, endspeech, endspeechwin) olditems = $player.party.transform { |p| p.item_id } olditems2 = opponent.party.transform { |p| p.item_id } # Create the battle scene (the visual side of it) - scene = pbNewBattleScene + scene = BattleCreationHelperMethods.create_battle_scene # Create the battle class (the mechanics side of it) battle = challengedata.createBattle(scene, $player, opponent) battle.internalBattle = false battle.endSpeeches = [endspeech] battle.endSpeechesWin = [endspeechwin] # Set various other properties in the battle class - pbPrepareBattle(battle) + BattleCreationHelperMethods.prepare_battle(battle) # Perform the battle itself decision = 0 pbBattleAnimation(pbGetTrainerBattleBGM(opponent)) { @@ -114,7 +114,7 @@ end def pbPlayBattle(battledata) return if !battledata - scene = pbNewBattleScene + scene = BattleCreationHelperMethods.create_battle_scene scene.abortable = true lastbattle = Marshal.restore(battledata) case lastbattle[0] diff --git a/Data/Scripts/018_Alternate battle modes/001_SafariZone.rb b/Data/Scripts/018_Alternate battle modes/001_SafariZone.rb index f92d15110..26d8830ec 100644 --- a/Data/Scripts/018_Alternate battle modes/001_SafariZone.rb +++ b/Data/Scripts/018_Alternate battle modes/001_SafariZone.rb @@ -121,11 +121,11 @@ def pbSafariBattle(species, level) # Calculate who the trainer is playerTrainer = $player # Create the battle scene (the visual side of it) - scene = pbNewBattleScene + scene = BattleCreationHelperMethods.create_battle_scene # Create the battle class (the mechanics side of it) battle = SafariBattle.new(scene, playerTrainer, foeParty) battle.ballCount = pbSafariState.ballcount - pbPrepareBattle(battle) + BattleCreationHelperMethods.prepare_battle(battle) # Perform the battle itself decision = 0 pbBattleAnimation(pbGetWildBattleBGM(foeParty), 0, foeParty) { diff --git a/Data/Scripts/018_Alternate battle modes/002_BugContest.rb b/Data/Scripts/018_Alternate battle modes/002_BugContest.rb index 61fa77fe6..3e197c834 100644 --- a/Data/Scripts/018_Alternate battle modes/002_BugContest.rb +++ b/Data/Scripts/018_Alternate battle modes/002_BugContest.rb @@ -364,18 +364,18 @@ def pbBugContestBattle(species, level) playerParty = $player.party playerPartyStarts = [0] # Create the battle scene (the visual side of it) - scene = pbNewBattleScene + scene = BattleCreationHelperMethods.create_battle_scene # Create the battle class (the mechanics side of it) battle = BugContestBattle.new(scene, playerParty, foeParty, playerTrainer, nil) battle.party1starts = playerPartyStarts battle.ballCount = pbBugContestState.ballcount setBattleRule("single") - pbPrepareBattle(battle) + BattleCreationHelperMethods.prepare_battle(battle) # Perform the battle itself decision = 0 pbBattleAnimation(pbGetWildBattleBGM(foeParty), 0, foeParty) { decision = battle.pbStartBattle - pbAfterBattle(decision, true) + BattleCreationHelperMethods.after_battle(decision, true) if [2, 5].include?(decision) # Lost or drew $game_system.bgm_unpause $game_system.bgs_unpause @@ -390,19 +390,7 @@ def pbBugContestBattle(species, level) pbBugContestState.pbStartJudging end # Save the result of the battle in Game Variable 1 - # 0 - Undecided or aborted - # 1 - Player won - # 2 - Player lost - # 3 - Player or wild Pokémon ran from battle, or player forfeited the match - # 4 - Wild Pokémon was caught - # 5 - Draw - case decision - when 1, 4 # Won, caught - $stats.wild_battles_won += 1 - when 2, 3, 5 # Lost, fled, draw - $stats.wild_battles_lost += 1 - end - pbSet(1, decision) + BattleCreationHelperMethods(decision, 1) # Used by the Poké Radar to update/break the chain 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 diff --git a/Data/Scripts/020_Debug/003_Debug menus/002_Debug_MenuCommands.rb b/Data/Scripts/020_Debug/003_Debug menus/002_Debug_MenuCommands.rb index 98c7c651e..66aabdaf0 100644 --- a/Data/Scripts/020_Debug/003_Debug menus/002_Debug_MenuCommands.rb +++ b/Data/Scripts/020_Debug/003_Debug menus/002_Debug_MenuCommands.rb @@ -176,7 +176,8 @@ MenuHandlers.add(:debug_menu, :test_wild_battle, { GameData::Species.get(species).name), params) if level > 0 $game_temp.encounter_type = nil - pbWildBattle(species, level) + setBattleRule("canLose") + WildBattle.start(species, level) end end next false @@ -205,8 +206,9 @@ MenuHandlers.add(:debug_menu, :test_wild_battle_advanced, { next end setBattleRule(sprintf("%dv%d", size0, pkmn.length)) + setBattleRule("canLose") $game_temp.encounter_type = nil - pbWildBattleCore(*pkmn) + WildBattle.start(*pkmn) break elsif pkmnCmd == pkmnCmds.length - 2 # Set player side size if !pbCanDoubleBattle? @@ -254,7 +256,8 @@ MenuHandlers.add(:debug_menu, :test_trainer_battle, { "effect" => proc { trainerdata = pbListScreen(_INTL("SINGLE TRAINER"), TrainerBattleLister.new(0, false)) if trainerdata - pbTrainerBattle(trainerdata[0], trainerdata[1], nil, false, trainerdata[2], true) + setBattleRule("canLose") + TrainerBattle.start(trainerdata[0], trainerdata[1], trainerdata[2]) end next false } @@ -293,9 +296,10 @@ MenuHandlers.add(:debug_menu, :test_trainer_battle_advanced, { next end setBattleRule(sprintf("%dv%d", size0, size1)) + setBattleRule("canLose") battleArgs = [] trainers.each { |t| battleArgs.push(t[1]) } - pbTrainerBattleCore(*battleArgs) + TrainerBattle.start(*battleArgs) break elsif trainerCmd == trainerCmds.length - 2 # Set opponent side size if trainers.length == 0 || (trainers.length == 1 && trainers[0][1].party_count == 1) diff --git a/Data/Scripts/021_Compiler/004_Compiler_MapsAndEvents.rb b/Data/Scripts/021_Compiler/004_Compiler_MapsAndEvents.rb index 0c0ef2f77..a9d16b8bb 100644 --- a/Data/Scripts/021_Compiler/004_Compiler_MapsAndEvents.rb +++ b/Data/Scripts/021_Compiler/004_Compiler_MapsAndEvents.rb @@ -523,7 +523,7 @@ module Compiler backdrop = $~[1].gsub(/^\s+/, "").gsub(/\s+$/, "") push_comment(firstpage.list, command) if rewriteComments elsif command[/^EndSpeech\:\s*([\s\S]+)$/i] - endspeeches.push($~[1].gsub(/^\s+/, "").gsub(/\s+$/, "")) + endspeeches.push(command) push_comment(firstpage.list, command) if rewriteComments elsif command[/^Outcome\:\s*(\d+)$/i] outcome = $~[1].to_i @@ -562,6 +562,7 @@ module Compiler safetrcombo = sprintf(":%s,\"%s\"", trtype, safequote(trname)) # :YOUNGSTER,"Joey" introplay = sprintf("pbTrainerIntro(:%s)", trtype) # Write first page + push_comment(firstpage.list, endspeeches[0]) if endspeeches[0] # Just so it isn't lost push_script(firstpage.list, introplay) # pbTrainerIntro push_script(firstpage.list, "pbNoticePlayer(get_self)") push_text(firstpage.list, battles[0]) @@ -572,13 +573,10 @@ module Compiler push_script(firstpage.list, sprintf("setBattleRule(\"backdrop\",\"%s\")", safequote(backdrop))) if backdrop push_script(firstpage.list, sprintf("setBattleRule(\"outcomeVar\",%d)", outcome)) if outcome > 1 push_script(firstpage.list, "setBattleRule(\"canLose\")") if continue - espeech = (endspeeches[0]) ? sprintf("_I(\"%s\")", safequote2(endspeeches[0])) : "nil" if battleid > 0 - battleString = sprintf("pbTrainerBattle(%s,%s,nil,%d)", safetrcombo, espeech, battleid) - elsif endspeeches[0] - battleString = sprintf("pbTrainerBattle(%s,%s)", safetrcombo, espeech) + battleString = sprintf("TrainerBattle.start(%s,%d)", safetrcombo, battleid) else - battleString = sprintf("pbTrainerBattle(%s)", safetrcombo) + battleString = sprintf("TrainerBattle.start(%s)", safetrcombo) end push_branch(firstpage.list, battleString) if battles.length > 1 # Has rematches @@ -621,12 +619,7 @@ module Compiler push_script(rematchpage.list, sprintf("setBattleRule(\"backdrop\",%s)", safequote(backdrop)), 1) if backdrop push_script(rematchpage.list, sprintf("setBattleRule(\"outcomeVar\",%d)", outcome), 1) if outcome > 1 push_script(rematchpage.list, "setBattleRule(\"canLose\")", 1) if continue - espeech = nil - if endspeeches.length > 0 - espeech = (endspeeches[i]) ? endspeeches[i] : endspeeches[endspeeches.length - 1] - end - espeech = (espeech) ? sprintf("_I(\"%s\")", safequote2(espeech)) : "nil" - battleString = sprintf("pbTrainerBattle(%s,%s,nil,%d)", safetrcombo, espeech, battleid + i) + battleString = sprintf("TrainerBattle.start(%s,%d)", safetrcombo, battleid + i) push_branch(rematchpage.list, battleString, 1) push_script(rematchpage.list, sprintf("pbPhoneIncrement(%s,%d)", safetrcombo, battles.length), 2) push_self_switch(rematchpage.list, "A", true, 2) @@ -912,6 +905,150 @@ module Compiler return ret end + def replace_old_battle_scripts(event, list, index) + changed = false + script = list[index].parameters[1] + if script[/^\s*pbWildBattle\((.+)\)\s*$/] + battle_params = $1.split(",") + list[index].parameters[1] = sprintf("WildBattle.start(#{battle_params[0].strip}, #{battle_params[1].strip})") + old_indent = list[index].indent + new_events = [] + if battle_params[3] && battle_params[3][/false/] + push_script(new_events, "setBattleRule(\"cannotRun\")", old_indent) + end + if battle_params[4] && battle_params[4][/true/] + push_script(new_events, "setBattleRule(\"canLose\")", old_indent) + end + if battle_params[2] && battle_params[2].strip != "1" + push_script(new_events, "setBattleRule(\"outcome\", #{battle_params[2].strip})", old_indent) + end + list[index, 0] = new_events if new_events.length > 0 + changed = true + elsif script[/^\s*pbDoubleWildBattle\((.+)\)\s*$/] + battle_params = $1.split(",") + pkmn1 = "#{battle_params[0].strip}, #{battle_params[1].strip}" + pkmn2 = "#{battle_params[2].strip}, #{battle_params[3].strip}" + list[index].parameters[1] = sprintf("WildBattle.start(#{pkmn1}, #{pkmn2})") + old_indent = list[index].indent + new_events = [] + if battle_params[3] && battle_params[5][/false/] + push_script(new_events, "setBattleRule(\"cannotRun\")", old_indent) + end + if battle_params[4] && battle_params[6][/true/] + push_script(new_events, "setBattleRule(\"canLose\")", old_indent) + end + if battle_params[2] && battle_params[4].strip != "1" + push_script(new_events, "setBattleRule(\"outcome\", #{battle_params[4].strip})", old_indent) + end + list[index, 0] = new_events if new_events.length > 0 + changed = true + elsif script[/^\s*pbTripleWildBattle\((.+)\)\s*$/] + battle_params = $1.split(",") + pkmn1 = "#{battle_params[0].strip}, #{battle_params[1].strip}" + pkmn2 = "#{battle_params[2].strip}, #{battle_params[3].strip}" + pkmn3 = "#{battle_params[4].strip}, #{battle_params[5].strip}" + list[index].parameters[1] = sprintf("WildBattle.start(#{pkmn1}, #{pkmn2}, #{pkmn3})") + old_indent = list[index].indent + new_events = [] + if battle_params[3] && battle_params[7][/false/] + push_script(new_events, "setBattleRule(\"cannotRun\")", old_indent) + end + if battle_params[4] && battle_params[8][/true/] + push_script(new_events, "setBattleRule(\"canLose\")", old_indent) + end + if battle_params[2] && battle_params[6].strip != "1" + push_script(new_events, "setBattleRule(\"outcome\", #{battle_params[6].strip})", old_indent) + end + list[index, 0] = new_events if new_events.length > 0 + changed = true + elsif script[/^\s*pbTrainerBattle\((.+)\)\s*$/] + battle_params = $1.split(",") + trainer1 = "#{battle_params[0].strip}, #{battle_params[1].strip}" + trainer1 += ", #{battle_params[4].strip}" if battle_params[4].strip != "nil" + list[index].parameters[1] = "TrainerBattle.start(#{trainer1})" + old_indent = list[index].indent + new_events = [] + if battle_params[2] && !battle_params[2].strip.empty? && battle_params[2].strip != "nil" + speech = battle_params[2].gsub(/^\s*_I\(\s*"\s*/, "") + speech.gsub!(/\"\s*\)\s*$/, "").strip + push_comment(new_events, "EndSpeech: #{speech}", old_indent) + end + if battle_params[3] && battle_params[3][/true/] + push_script(new_events, "setBattleRule(\"double\")", old_indent) + end + if battle_params[5] && battle_params[5][/true/] + push_script(new_events, "setBattleRule(\"canLose\")", old_indent) + end + if battle_params[6] && battle_params[6].strip != "1" + push_script(new_events, "setBattleRule(\"outcome\", #{battle_params[6].strip})", old_indent) + end + list[index, 0] = new_events if new_events.length > 0 + changed = true + elsif script[/^\s*pbDoubleTrainerBattle\((.+)\)\s*$/] + battle_params = $1.split(",") + trainer1 = "#{battle_params[0].strip}, #{battle_params[1].strip}" + trainer1 += ", #{battle_params[2].strip}" if battle_params[2].strip != "nil" + trainer2 = "#{battle_params[4].strip}, #{battle_params[5].strip}" + trainer2 += ", #{battle_params[6].strip}" if battle_params[6] && battle_params[6].strip != "nil" + list[index].parameters[1] = "TrainerBattle.start(#{trainer1}, #{trainer2})" + old_indent = list[index].indent + new_events = [] + if battle_params[3] && !battle_params[3].strip.empty? && battle_params[3].strip != "nil" + speech = battle_params[3].gsub(/^\s*_I\(\s*"\s*/, "") + speech.gsub!(/\"\s*\)\s*$/, "").strip + push_comment(new_events, "EndSpeech1: #{speech}", old_indent) + end + if battle_params[7] && !battle_params[7].strip.empty? && battle_params[7].strip != "nil" + speech = battle_params[7].gsub(/^\s*_I\(\s*"\s*/, "") + speech.gsub!(/\"\s*\)\s*$/, "").strip + push_comment(new_events, "EndSpeech2: #{speech}", old_indent) + end + if battle_params[8] && battle_params[8][/true/] + push_script(new_events, "setBattleRule(\"canLose\")", old_indent) + end + if battle_params[9] && battle_params[9].strip != "1" + push_script(new_events, "setBattleRule(\"outcome\", #{battle_params[9].strip})", old_indent) + end + list[index, 0] = new_events if new_events.length > 0 + changed = true + elsif script[/^\s*pbTripleTrainerBattle\((.+)\)\s*$/] + battle_params = $1.split(",") + trainer1 = "#{battle_params[0].strip}, #{battle_params[1].strip}" + trainer1 += ", #{battle_params[2].strip}" if battle_params[2].strip != "nil" + trainer2 = "#{battle_params[4].strip}, #{battle_params[5].strip}" + trainer2 += ", #{battle_params[6].strip}" if battle_params[6] && battle_params[6].strip != "nil" + trainer3 = "#{battle_params[8].strip}, #{battle_params[9].strip}" + trainer3 += ", #{battle_params[10].strip}" if battle_params[10] && battle_params[10].strip != "nil" + list[index].parameters[1] = "TrainerBattle.start(#{trainer1}, #{trainer2}, #{trainer3})" + old_indent = list[index].indent + new_events = [] + if battle_params[3] && !battle_params[3].strip.empty? && battle_params[3].strip != "nil" + speech = battle_params[3].gsub(/^\s*_I\(\s*"\s*/, "") + speech.gsub!(/\"\s*\)\s*$/, "").strip + push_comment(new_events, "EndSpeech1: #{speech}", old_indent) + end + if battle_params[7] && !battle_params[7].strip.empty? && battle_params[7].strip != "nil" + speech = battle_params[7].gsub(/^\s*_I\(\s*"\s*/, "") + speech.gsub!(/\"\s*\)\s*$/, "").strip + push_comment(new_events, "EndSpeech2: #{speech}", old_indent) + end + if battle_params[7] && !battle_params[7].strip.empty? && battle_params[11].strip != "nil" + speech = battle_params[11].gsub(/^\s*_I\(\s*"\s*/, "") + speech.gsub!(/\"\s*\)\s*$/, "").strip + push_comment(new_events, "EndSpeech3: #{speech}", old_indent) + end + if battle_params[12] && battle_params[12][/true/] + push_script(new_events, "setBattleRule(\"canLose\")", old_indent) + end + if battle_params[13] && battle_params[13].strip != "1" + push_script(new_events, "setBattleRule(\"outcome\", #{battle_params[13].strip})", old_indent) + end + list[index, 0] = new_events if new_events.length > 0 + changed = true + end + return changed + end + def fix_event_use(event, _mapID, mapData) return nil if event_is_empty?(event) changed = false @@ -1283,6 +1420,7 @@ module Compiler when 111 # Conditional Branch if list[i].parameters[0] == 12 # script script = list[i].parameters[1] + changed = true if replace_old_battle_scripts(event, list, i) if script[trainerMoneyRE] # Compares $player.money with a value # Checking money directly operator = $1 @@ -1313,7 +1451,7 @@ module Compiler # Using pbItemBall on non-item events, change it list[i].parameters[1] = script.sub(/pbItemBall/, "pbReceiveItem") changed = true - elsif script[/^\s*(Kernel\.)?(pbTrainerBattle|pbDoubleTrainerBattle)/] + elsif script[/^\s*(TrainerBattle.start)/] # Check if trainer battle conditional branch is empty j = i + 1 isempty = true