From aa9b1a9e237d7b61ad1b69ce9c346c8fc77f8581 Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sat, 13 Aug 2022 16:52:42 +0100 Subject: [PATCH] Refactored phone/rematches code, added Phone.rematches_enabled/Phone.rematch_variant/map metadata flag "NoPhoneSignal", changed event layout, trainer contacts can use Common Events for their calls, etc. --- Data/Scripts/001_Settings.rb | 9 + .../002_Save data/005_Game_SaveConversions.rb | 32 + .../012_Overworld/002_Overworld_Metadata.rb | 8 +- Data/Scripts/013_Items/004_Item_Phone.rb | 890 +++++++++++++----- Data/Scripts/016_UI/008_UI_Pokegear.rb | 2 +- Data/Scripts/016_UI/010_UI_Phone.rb | 104 +- .../003_Debug menus/002_Debug_MenuCommands.rb | 10 +- .../004_Compiler_MapsAndEvents.rb | 176 ++-- PBS/phone.txt | 32 +- 9 files changed, 851 insertions(+), 412 deletions(-) diff --git a/Data/Scripts/001_Settings.rb b/Data/Scripts/001_Settings.rb index d5c3dde76..f688a9fba 100644 --- a/Data/Scripts/001_Settings.rb +++ b/Data/Scripts/001_Settings.rb @@ -132,6 +132,15 @@ module Settings # Whether overworld weather can set the default terrain effect in battle. # Storm weather sets Electric Terrain, and fog weather sets Misty Terrain. OVERWORLD_WEATHER_SETS_BATTLE_TERRAIN = (MECHANICS_GENERATION >= 8) + # The default setting for Phone.rematches_enabled, which determines whether + # trainers registered in the Phone can become ready for a rematch. If false, + # Phone.rematches_enabled = true will enable rematches at any point you want. + PHONE_REMATCHES_POSSIBLE_FROM_BEGINNING = false + # Whether the messages in a phone call with a trainer are colored blue or red + # depending on that trainer's gender. Note that this doesn't apply to contacts + # that are not trainers; they will need to be colored manually in their Common + # Events. + COLOR_PHONE_CALL_MESSAGES_BY_CONTACT_GENDER = true #============================================================================= diff --git a/Data/Scripts/002_Save data/005_Game_SaveConversions.rb b/Data/Scripts/002_Save data/005_Game_SaveConversions.rb index aa1c59f93..f2bb653cd 100644 --- a/Data/Scripts/002_Save data/005_Game_SaveConversions.rb +++ b/Data/Scripts/002_Save data/005_Game_SaveConversions.rb @@ -348,3 +348,35 @@ SaveData.register_conversion(:v20_convert_pokemon_markings) do end end end + +#=============================================================================== + +SaveData.register_conversion(:v21_replace_phone_data) do + essentials_version 21 + display_title "Updating Phone data format" + to_value :global_metadata do |global| + if !global.phone + global.instance_eval do + @phone = Phone.new + @phoneTime = nil # Don't bother using this + if @phoneNumbers + @phoneNumbers.each do |contact| + if contact.length > 4 + # Trainer + # TODO: Is there any way to ensure the versions count is accurate? + Phone.add_silent(contact[6], contact[7], contact[1], contact[2], 0, [contact[5], 3].max) + new_contact = Phone.get(contact[1], contact[2], 0) + new_contact.visible = contact[0] + new_contact.version = contact[5] + new_contact.rematch_flag = [contact[4] - 1, 0].max + else + # Non-trainer + Phone.add_silent(contact[3], contact[2], contact[1]) + end + end + @phoneNumbers = nil + end + end + end + end +end diff --git a/Data/Scripts/012_Overworld/002_Overworld_Metadata.rb b/Data/Scripts/012_Overworld/002_Overworld_Metadata.rb index 5a0077c45..69d64f050 100644 --- a/Data/Scripts/012_Overworld/002_Overworld_Metadata.rb +++ b/Data/Scripts/012_Overworld/002_Overworld_Metadata.rb @@ -14,8 +14,9 @@ class PokemonGlobalMetadata attr_accessor :stepcount attr_accessor :pcItemStorage attr_accessor :mailbox - attr_accessor :phoneNumbers - attr_accessor :phoneTime + attr_accessor :phoneNumbers # Deprecated + attr_accessor :phoneTime # Deprecated + attr_accessor :phone attr_accessor :partner attr_accessor :creditsPlayed # Pokédex @@ -64,8 +65,7 @@ class PokemonGlobalMetadata @stepcount = 0 @pcItemStorage = nil @mailbox = nil - @phoneNumbers = [] - @phoneTime = 0 + @phone = Phone.new @partner = nil @creditsPlayed = false # Pokédex diff --git a/Data/Scripts/013_Items/004_Item_Phone.rb b/Data/Scripts/013_Items/004_Item_Phone.rb index aca75a2f8..6c589effb 100644 --- a/Data/Scripts/013_Items/004_Item_Phone.rb +++ b/Data/Scripts/013_Items/004_Item_Phone.rb @@ -1,305 +1,677 @@ -#=============================================================================== -# Register contacts -#=============================================================================== -def pbPhoneRegisterNPC(ident, name, mapid, showmessage = true) - $PokemonGlobal.phoneNumbers = [] if !$PokemonGlobal.phoneNumbers - exists = pbFindPhoneTrainer(ident, name) - if exists - return if exists[0] # Already visible - exists[0] = true # Make visible - else - phonenum = [true, ident, name, mapid] - $PokemonGlobal.phoneNumbers.push(phonenum) - end - pbMessage(_INTL("\\me[Register phone]Registered {1} in the Pokégear.", name)) if showmessage -end +# TODO: Add an information window with details of the person in a phone call. +# Make this work with common event calls (create and dispose the info +# window in start_message and end_message). +# TODO: Rewrite the Phone UI. Have more than one method. Choosable icons/marks +# for each contact? Show an icon representing phone signal. -def pbPhoneRegister(event, trainertype, trainername) - $PokemonGlobal.phoneNumbers = [] if !$PokemonGlobal.phoneNumbers - return if pbFindPhoneTrainer(trainertype, trainername) - phonenum = [] - phonenum.push(true) - phonenum.push(trainertype) - phonenum.push(trainername) - phonenum.push(0) # time to next battle - phonenum.push(0) # can battle - phonenum.push(0) # battle count - if event - phonenum.push(event.map.map_id) - phonenum.push(event.id) - end - $PokemonGlobal.phoneNumbers.push(phonenum) -end +# TODO: Add a trainer comment for giving a trainer a common event ID. +# TODO: Add calling a contact at a particular time forcing rematch readiness. +# Add trainer comments for this. +# TODO: Allow individual trainers to never arrange a rematch by themself, thus +# requiring the player to call them at their particular time of day/week. +# TODO: Be able to put the Phone on silent mode (prevent all phone calls from +# trainers, but allow scripted calls as normal). -def pbPhoneDeleteContact(index) - $PokemonGlobal.phoneNumbers[index][0] = false # Remove from contact list - if $PokemonGlobal.phoneNumbers[index].length == 8 - $PokemonGlobal.phoneNumbers[index][3] = 0 # Reset countdown - $PokemonGlobal.phoneNumbers[index][4] = 0 # Reset countdown +# TODO: Better messages, more customisation of messages. +#=============================================================================== +# +#=============================================================================== +class Phone + attr_accessor :contacts + attr_accessor :rematch_variant, :rematches_enabled + attr_accessor :time_to_next_call, :last_refresh_time + + def initialize + @contacts = [] + @rematch_variant = 0 # Original variant is 0, first rematch variant is 1, etc. + @rematches_enabled = Settings::PHONE_REMATCHES_POSSIBLE_FROM_BEGINNING + @time_to_next_call = 0.0 + @last_refresh_time = 0 + end + + # Returns a visible contact only. + def get(trainer, *args) + @contacts.each do |contact| + next if !contact.visible? + next if contact.trainer? != trainer + if trainer + next if contact.trainer_type != args[0] || + contact.name != args[1] || contact.start_version != (args[2] || 0) + else + next if contact.name != args[0] + end + return contact + end + return nil + end + + def get_version(trainer_type, name, start_version = 0) + return 0 if !GameData::TrainerType.exists?(trainer_type) + trainer_type = GameData::TrainerType.get(trainer_type).id + contact = get(true, trainer_type, name, start_version) + return (contact) ? contact.version : 0 + end + + # Trainer type, name[, start_version] + # Name + def can_add?(*args) + return false if !$player.has_pokegear + if args.length == 1 + # Non-trainer (name only) + return false if get(false, args[0]) + else + # Trainer (has at least trainer type and name) + return false if !GameData::TrainerType.exists?(args[0]) + trainer_type = GameData::TrainerType.get(args[0]).id + return false if get(true, trainer_type, args[1], args[2] || 0) + end + return true + end + + # Event, trainer type, name, versions_count = 1, start_version = 0 + # Map ID, event ID, trainer type, name, versions_count = 1, start_version = 0 + # Map ID, name, common event ID + def add(*args) + if args[0].is_a?(Game_Event) + # Trainer + return false if !GameData::TrainerType.exists?(args[1]) + trainer_type = GameData::TrainerType.get(args[1]).id + name = args[2] + contact = get(true, trainer_type, name, args[3] || 0) + if contact + contact.visible = true + else + contact = Contact.new(true, args[0].map_id, args[0].id, + trainer_type, name, args[3] || 1, args[4] || 0) + contact.increment_version + @contacts.push(contact) + end + elsif args[1].is_a?(Numeric) + # Trainer + return false if !GameData::TrainerType.exists?(args[2]) + trainer_type = GameData::TrainerType.get(args[2]).id + name = args[3] + contact = get(true, trainer_type, name, args[4] || 0) + if contact + contact.visible = true + else + contact = Contact.new(true, args[0], args[1], + trainer_type, name, args[4] || 1, args[5] || 0) + contact.increment_version + @contacts.push(contact) + end + else + # Non-trainer + name = args[1] + contact = get(false, name) + if contact + contact.visible = true + else + contact = Contact.new(false, *args) + @contacts.push(contact) + end + end + return true + end + + #============================================================================= + + # Checks once every second. + def refresh_ready_trainers + return if !@rematches_enabled + time = pbGetTimeNow.to_i + return if @last_refresh_time == time + @last_refresh_time = time + @contacts.each do |contact| + next if !contact.trainer? || !contact.visible? + next if contact.rematch_flag > 0 # Already ready for rematch + if contact.time_to_ready <= 0 + contact.time_to_ready = rand(20...40) * 60 # 20-40 minutes + end + contact.time_to_ready -= 1 + next if contact.time_to_ready > 0 + contact.rematch_flag = 1 # Ready for rematch + contact.set_trainer_event_ready_for_rematch + end + end + + def reset_after_win(trainer_type, name, start_version = 0) + return if !GameData::TrainerType.exists?(trainer_type) + trainer_type = GameData::TrainerType.get(trainer_type).id + contact = get(true, trainer_type, name, start_version) + return if !contact + contact.variant_beaten = contact.version - contact.start_version + contact.increment_version + contact.rematch_flag = 0 + contact.time_to_ready = 0.0 + end + + #============================================================================= + + def self.rematch_variant + return $PokemonGlobal.phone.rematch_variant + end + + def self.rematch_variant=(value) + $PokemonGlobal.phone.rematch_variant = value + end + + def self.rematches_enabled + return $PokemonGlobal.phone.rematches_enabled + end + + def self.rematches_enabled=(value) + $PokemonGlobal.phone.rematches_enabled = value + end + + def self.get_trainer(*args) + return $PokemonGlobal.phone.get(true, *args) + end + + def self.can_add?(*args) + return $PokemonGlobal.phone.can_add?(*args) + end + + def self.add(*args) + ret = $PokemonGlobal.phone.add(*args) + if ret + if args[0].is_a?(Game_Event) + contact = $PokemonGlobal.phone.get(true, args[1], args[2], (args[4] || 0)) + elsif args[1].is_a?(Numeric) + contact = $PokemonGlobal.phone.get(true, args[2], args[3], (args[5] || 0)) + else + contact = $PokemonGlobal.phone.get(false, args[1]) + end + pbMessage(_INTL("\\me[Register phone]Registered {1} in the Pokégear!", contact.display_name)) + end + return ret + end + + def self.add_silent(*args) + return $PokemonGlobal.phone.add(*args) + end + + def self.increment_version(trainer_type, name, start_version = 0) + contact = $PokemonGlobal.phone.get(trainer_type, name, start_version) + contact.increment_version if contact + end + + # TODO: Rename this. + def self.variant(trainer_type, name, start_version = 0) + contact = $PokemonGlobal.phone.get(trainer_type, name, start_version) + return contact.version - contact.start_version if contact + return start_version + end + + def self.battle(trainer_type, name, start_version = 0) + contact = $PokemonGlobal.phone.get(true, trainer_type, name, start_version) + return false if !contact + contact.increment_version if contact.version == contact.start_version + contact.variant_beaten + return TrainerBattle.start(trainer_type, name, contact.version) + end + + def self.reset_after_win(trainer_type, name, start_version = 0) + $PokemonGlobal.phone.reset_after_win(trainer_type, name, start_version) + end + + def self.variant_beaten(trainer_type, name, start_version = 0) + contact = $PokemonGlobal.phone.get(true, trainer_type, name, start_version) + return 0 if !contact + return contact.variant_beaten end end -def pbPhoneRegisterBattle(message, event, trainertype, trainername, maxbattles) - return false if !$player.has_pokegear # Can't register without a Pokégear - return false if !GameData::TrainerType.exists?(trainertype) - trainertype = GameData::TrainerType.get(trainertype).id - contact = pbFindPhoneTrainer(trainertype, trainername) - return false if contact && contact[0] # Existing contact and is visible - message = _INTL("Let me register you.") if !message - return false if !pbConfirmMessage(message) - displayname = _INTL("{1} {2}", GameData::TrainerType.get(trainertype).name, - pbGetMessageFromHash(MessageTypes::TrainerNames, trainername)) - if contact # Previously registered, just make visible - contact[0] = true - else # Add new contact - pbPhoneRegister(event, trainertype, trainername) - pbPhoneIncrement(trainertype, trainername, maxbattles) +#=============================================================================== +# +#=============================================================================== +class Phone + class Contact + attr_accessor :map_id, :event_id + attr_accessor :name + attr_accessor :trainer_type, :start_version, :versions_count, :version + attr_accessor :time_to_ready, :rematch_flag, :variant_beaten + attr_accessor :common_event_id + attr_accessor :visible + + # Map ID, event ID, trainer type, name, versions count = 1, start version = 0 + # Map ID, name, common event ID + def initialize(trainer, *args) + @trainer = trainer + if @trainer + # Trainer + @map_id = args[0] + @event_id = args[1] + @trainer_type = args[2] + @name = args[3] + @versions_count = [args[4] || 1, 1].max # Includes the original version + @start_version = args[5] || 0 + @version = @start_version + @variant_beaten = 0 + @time_to_ready = 0 + @rematch_flag = 0 # 0=counting down, 1=ready for rematch, 2=ready and told player + @common_event_id = 0 + else + # Non-trainer + @map_id = args[0] + @name = args[1] + @common_event_id = args[2] || 0 + end + @visible = true + end + + def trainer? + return @trainer + end + + def visible? + return @visible + end + + def visible=(value) + return if @visible == value + @visible = value + if !value && trainer? + @time_to_ready = 0 + @rematch_flag = 0 + $game_self_switches[[@map_id, @event_id, "A"]] = true + $game_map.need_refresh = true + end + end + + def common_event_call? + return @common_event_id > 0 + end + + def can_rematch? + return trainer? && @rematch_flag >= 1 + end + + def display_name + if trainer? + return sprintf("%s %s", GameData::TrainerType.get(@trainer_type).name, + pbGetMessageFromHash(MessageTypes::TrainerNames, @name)) + end + return _INTL(@name) + end + + def increment_version + return if !trainer? + max_variant = [$PokemonGlobal.phone.rematch_variant, @versions_count - 1].min + return if @version - @start_version >= max_variant + @version += 1 + @time_to_ready = 0 + @rematch_flag = 0 + end + + def set_trainer_event_ready_for_rematch + return if !@trainer + $game_self_switches[[@map_id, @event_id, "A"]] = false + $game_self_switches[[@map_id, @event_id, "B"]] = true + $game_map.need_refresh = true + end end - pbMessage(_INTL("\\me[Register phone]Registered {1} in the Pokégear.", displayname)) - return true end #=============================================================================== -# Contact information +# #=============================================================================== -def pbRandomPhoneTrainer - $PokemonGlobal.phoneNumbers = [] if !$PokemonGlobal.phoneNumbers - temparray = [] - this_map_metadata = $game_map.metadata - return nil if !this_map_metadata || !this_map_metadata.town_map_position - currentRegion = this_map_metadata.town_map_position[0] - $PokemonGlobal.phoneNumbers.each do |num| - next if !num[0] || num.length != 8 # if not visible or not a trainer - next if $game_map.map_id == num[6] # Can't call if on same map - caller_map_metadata = GameData::MapMetadata.try_get(num[6]) - next if !caller_map_metadata || !caller_map_metadata.town_map_position - # Can't call if in different region - next if caller_map_metadata.town_map_position[0] != currentRegion - temparray.push(num) +class Phone + module Call + module_function + + def can_make? + return false if $game_map.metadata.has_flag?("NoPhoneSignal") + return true + end + + # For the player initiating the call. + def can_call_contact?(contact) + return false if !contact + if !can_make? + pbMessage(_INTL("There is no phone signal here...")) + return false + end + return true if !contact.trainer? + if contact.map_id == $game_map.map_id + pbMessage(_INTL("The Trainer is close by.\nTalk to the Trainer in person!")) + return false + end + caller_map_metadata = GameData::MapMetadata.try_get(contact.map_id) + this_map_metadata = $game_map.metadata + if !caller_map_metadata || !caller_map_metadata.town_map_position || + !this_map_metadata || !this_map_metadata.town_map_position || + caller_map_metadata.town_map_position[0] != this_map_metadata.town_map_position[0] + pbMessage(_INTL("The Trainer is out of range.")) + return false + end + return true + end + + # Get a random trainer contact from the region the player is currently in, + # but is not in the same map as the player. + def get_random_trainer_for_incoming_call + player_location = $game_map.metadata&.town_map_position + return nil if !player_location + player_region = player_location[0] + valid_contacts = [] + $PokemonGlobal.phone.contacts.each do |contact| + next if !contact.trainer? || !contact.visible? + next if contact.map_id == $game_map.map_id + # TODO: next if the contact's map name is the same as the current map's? + caller_map_metadata = GameData::MapMetadata.try_get(contact.map_id) + next if !caller_map_metadata || !caller_map_metadata.town_map_position + next if caller_map_metadata.town_map_position[0] != player_region + valid_contacts.push(contact) + end + return valid_contacts.sample + end + + #=========================================================================== + + def make_incoming + return if !can_make? + contact = get_random_trainer_for_incoming_call + if contact + call = generate_trainer_dialogue(contact) + play(call, contact) + end + end + + # Phone::Contact + # Trainer type, name[, start_version] + # Name (for non-trainers) + def make_outgoing(*args) + if args[0].is_a?(Phone::Contact) + contact = args[0] + elsif args.length > 1 + contact = Phone.get(true, args[0], args[1], args[2] || 0) # Trainer + else + contact = Phone.get(false, args[0]) # Non-trainer + end + raise _INTL("Couldn't find phone contact given: {1}.", args.inspect) if !contact + return if !can_call_contact?(contact) + if contact.common_event_call? + if !pbCommonEvent(contact.common_event_id) + pbMessage(_INTL("{1}'s messages not defined.\nCouldn't call common event {2}.", + contact.display_name, contact.common_event_id)) + end + else + call = generate_trainer_dialogue(contact) + play(call, contact) + end + end + + def start_message(contact) + pbMessage(_INTL("......\\wt[5] ......\\1")) + end + + def play(dialogue, contact) + start_message(contact) + contact_pokemon_species = get_random_contact_pokemon_species(contact) + random_encounter_species = get_random_encounter_species(contact) + contact_map_name = get_map_name(contact) + gender_colour_text = "" + if Settings::COLOR_PHONE_CALL_MESSAGES_BY_CONTACT_GENDER && contact.trainer? + data = GameData::TrainerType.try_get(contact.trainer_type) + if data + case data.gender + when 0 then gender_colour_text = "\\b" + when 1 then gender_colour_text = "\\r" + end + end + end + messages = dialogue.split("\\m") + messages.each_with_index do |message, i| + message.gsub!(/\\TN/, _INTL(contact.name)) + message.gsub!(/\\TP/, contact_pokemon_species) + message.gsub!(/\\TE/, random_encounter_species) + message.gsub!(/\\TM/, contact_map_name) + message += "\\1" if i < messages.length - 1 + pbMessage(gender_colour_text + message) + end + end_message(contact) + end + + def end_message(contact) + pbMessage(_INTL("Click!\\wt[10]\n......\\wt[5] ......\\1")) + end + + #=========================================================================== + + def generate_trainer_dialogue(contact) + validate contact => Phone::Contact + get_random_message = lambda do |messages| + msg = messages.sample + return "" if !msg + return pbGetMessageFromHash(MessageTypes::PhoneMessages, msg) + end + phone_data = pbLoadPhoneData + # Choose random greeting depending on time of day + ret = get_random_message.call(phone_data.greetings) + time = pbGetTimeNow + if PBDayNight.isMorning?(time) + modcall = get_random_message.call(phone_data.greetingsMorning) + ret = modcall if !nil_or_empty?(modcall) + elsif PBDayNight.isEvening?(time) + modcall = get_random_message.call(phone_data.greetingsEvening) + ret = modcall if !nil_or_empty?(modcall) + end + ret += "\\m" + if Phone.rematches_enabled && (contact.rematch_flag == 1 || + (contact.rematch_flag == 2 && rand(100) < 50)) + # If ready for rematch, tell the player (50% chance to remind the player) + ret += get_random_message.call(phone_data.battleRequests) + contact.rematch_flag = 2 # Ready for rematch and told player + elsif rand(100) < 75 + # Choose random body + ret += get_random_message.call(phone_data.bodies1) + ret += "\\m" + ret += get_random_message.call(phone_data.bodies2) + else + # Choose random generic + ret += get_random_message.call(phone_data.generics) + end + return ret + end + + def get_random_contact_pokemon_species(contact) + return "" if !contact.trainer? + version = [contact.version - 1, contact.start_version].max + trainer_data = GameData::Trainer.try_get(contact.trainer_type, contact.name, version) + return "" if !trainer_data + pkmn = trainer_data.pokemon.sample[:species] + return GameData::Species.get(pkmn).name + end + + def get_random_encounter_species(contact) + return "" if !contact.trainer? + encounter_data = GameData::Encounter.get(contact.map_id, $PokemonGlobal.encounter_version) + return "" if !encounter_data + get_species_from_table = lambda do |encounter_table| + return nil if !encounter_table || encounter_table.length == 0 + len = [encounter_table.length, 4].min # From first 4 slots only + return encounter_table[rand(len)][1] + end + enc_tables = encounter_data.types + species = get_species_from_table.call(enc_tables[:Land]) + if !species + species = get_species_from_table.call(enc_tables[:Cave]) + if !species + species = get_species_from_table.call(enc_tables[:Water]) + end + end + return "" if !species + return GameData::Species.get(species).name + end + + def get_map_name(contact) + return pbGetMapNameFromId(contact.map_id) + end end - return nil if temparray.length == 0 - return temparray[rand(temparray.length)] -end - -def pbFindPhoneTrainer(tr_type, tr_name) # Ignores whether visible or not - return nil if !$PokemonGlobal.phoneNumbers - $PokemonGlobal.phoneNumbers.each do |num| - return num if num[1] == tr_type && num[2] == tr_name # If a match - end - return nil -end - -def pbHasPhoneTrainer?(tr_type, tr_name) - return pbFindPhoneTrainer(tr_type, tr_name) != nil -end - -def pbPhoneBattleCount(tr_type, tr_name) - trainer = pbFindPhoneTrainer(tr_type, tr_name) - return (trainer) ? trainer[5] : 0 -end - -def pbPhoneReadyToBattle?(tr_type, tr_name) - trainer = pbFindPhoneTrainer(tr_type, tr_name) - return (trainer && trainer[4] >= 2) end #=============================================================================== -# Contact rematch data modifications -#=============================================================================== -def pbPhoneIncrement(tr_type, tr_name, maxbattles) - trainer = pbFindPhoneTrainer(tr_type, tr_name) - return if !trainer - trainer[5] += 1 if trainer[5] < maxbattles # Increment battle count - trainer[3] = 0 # reset time to can-battle - trainer[4] = 0 # reset can-battle flag -end - -def pbPhoneReset(tr_type, tr_name) - trainer = pbFindPhoneTrainer(tr_type, tr_name) - return false if !trainer - trainer[3] = 0 # reset time to can-battle - trainer[4] = 0 # reset can-battle flag - return true -end - -def pbSetReadyToBattle(num) - return if !num[6] || !num[7] - $game_self_switches[[num[6], num[7], "A"]] = false - $game_self_switches[[num[6], num[7], "B"]] = true - $game_map.need_refresh = true -end - -#=============================================================================== -# Phone-related counters +# #=============================================================================== 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 + $PokemonGlobal.phone.refresh_ready_trainers + # Count down time to next phone call + if $PokemonGlobal.phone.time_to_next_call <= 0 + $PokemonGlobal.phone.time_to_next_call = rand(20...40) * 60.0 # 20-40 minutes end + $PokemonGlobal.phone.time_to_next_call -= Graphics.delta_s + next if $PokemonGlobal.phone.time_to_next_call > 0 # 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 + Phone::Call.make_incoming } ) #=============================================================================== -# Player calls a contact +# Deprecated. #=============================================================================== -def pbCallTrainer(trtype, trname) - trainer = pbFindPhoneTrainer(trtype, trname) - return if !trainer - # Special NPC contacts - if trainer.length != 8 - if !pbCommonEvent(trtype) - pbMessage(_INTL("{1}'s messages not defined.\nCouldn't call common event {2}.", trainer[2], trtype)) - end - return - end - # Trainer contacts - if $game_map.map_id == trainer[6] - pbMessage(_INTL("The Trainer is close by.\nTalk to the Trainer in person!")) - return - end - caller_map_metadata = GameData::MapMetadata.try_get(trainer[6]) - this_map_metadata = $game_map.metadata - if !caller_map_metadata || !caller_map_metadata.town_map_position || - !this_map_metadata || !this_map_metadata.town_map_position || - caller_map_metadata.town_map_position[0] != this_map_metadata.town_map_position[0] - pbMessage(_INTL("The Trainer is out of range.")) - return # Can't call if in different region - end - call = pbPhoneGenerateCall(trainer) - pbPhoneCall(call, trainer) +# Called by events. +# @>Conditional Branch: Phone.can_add?(trainer_type, name, start_version) +# @>Text: Let me register you. +# @>Show Choices: Yes, No +# : When [Yes] +# @>Conditional Branch: Phone.add(get_self, trainer_type, name, start_version, versions_count) +# @>Text: Thanks! (optional) +# @> +# : Branch End +# : When [No] +# @>Text: Oh, okay then. (optional) +# @> +# : Branch End +# : Branch End +# @> +# @deprecated This method is slated to be removed in v21. +def pbPhoneRegisterBattle(message, event, trainer_type, name, versions_count) + Deprecation.warn_method("pbPhoneRegisterBattle", "v21", "several scripts and event commands; see def pbPhoneRegisterBattle") + return false if !Phone.can_add?(trainer_type, name, 0) + message = _INTL("Let me register you.") if !message + return false if !pbConfirmMessage(message) + return Phone.add(event, trainer_type, name, 0, versions_count) end -#=============================================================================== -# Generate phone message -#=============================================================================== -def pbPhoneGenerateCall(phonenum) - phoneData = pbLoadPhoneData - # Choose random greeting depending on time of day - call = pbRandomPhoneItem(phoneData.greetings) - time = pbGetTimeNow - if PBDayNight.isMorning?(time) - modcall = pbRandomPhoneItem(phoneData.greetingsMorning) - call = modcall if modcall && modcall != "" - elsif PBDayNight.isEvening?(time) - modcall = pbRandomPhoneItem(phoneData.greetingsEvening) - call = modcall if modcall && modcall != "" - end - call += "\\m" - if phonenum[4] == 2 || (rand(2) == 0 && phonenum[4] == 3) - # If "can battle" is set, make ready to battle - call += pbRandomPhoneItem(phoneData.battleRequests) - pbSetReadyToBattle(phonenum) - phonenum[4] = 3 - elsif rand(4) < 3 - # Choose random body - call += pbRandomPhoneItem(phoneData.bodies1) - call += "\\m" - call += pbRandomPhoneItem(phoneData.bodies2) +# @deprecated This method is slated to be removed in v21. +def pbPhoneRegister(event, trainer_type, name) + Deprecation.warn_method("pbPhoneRegister", "v21", "Phone.add_silent(event, trainer_type, name)") + Phone.add_silent(event, trainer_type, name) +end + +# Called by events. +# @deprecated This method is slated to be removed in v21. +def pbPhoneRegisterNPC(common_event_id, name, map_id, show_message = true) + Deprecation.warn_method("pbPhoneRegisterNPC", "v21", "Phone.add(map_id, name, common_event_id) or Phone.add_silent(map_id, name, common_event_id)") + if show_message + Phone.add(map_id, name, common_event_id) else - # Choose random generic - call += pbRandomPhoneItem(phoneData.generics) + Phone.add_silent(map_id, name, common_event_id) end - return call end -def pbRandomPhoneItem(array) - ret = array[rand(array.length)] - ret = "" if !ret - return pbGetMessageFromHash(MessageTypes::PhoneMessages, ret) +# @deprecated This method is slated to be removed in v21. +def pbPhoneDeleteContact(index) + Deprecation.warn_method("pbPhoneDeleteContact", "v21", "$PokemonGlobal.phone.contacts[index].visible = false") + $PokemonGlobal.phone.contacts[index].visible = false end -def pbRandomEncounterSpecies(enc_table) - return nil if !enc_table || enc_table.length == 0 - len = [enc_table.length, 4].min - return enc_table[rand(len)][1] +# @deprecated This method is slated to be removed in v21. +def pbFindPhoneTrainer(trainer_type, name) + Deprecation.warn_method("pbFindPhoneTrainer", "v21", "Phone.get(trainer_type, name)") + return Phone.get(trainer_type, name) end -def pbEncounterSpecies(phonenum) - return "" if !phonenum[6] || phonenum[6] == 0 - encounter_data = GameData::Encounter.get(phonenum[6], $PokemonGlobal.encounter_version) - return "" if !encounter_data - enc_tables = encounter_data.types - species = pbRandomEncounterSpecies(enc_tables[:Land]) - if !species - species = pbRandomEncounterSpecies(enc_tables[:Cave]) - if !species - species = pbRandomEncounterSpecies(enc_tables[:Water]) - end - end - return "" if !species - return GameData::Species.get(species).name +# @deprecated This method is slated to be removed in v21. +def pbHasPhoneTrainer?(trainer_type, name) + Deprecation.warn_method("pbHasPhoneTrainer", "v21", "Phone.get(trainer_type, name) != nil") + return Phone.get(trainer_type, name) != nil end -def pbTrainerSpecies(phonenum) - return "" if !phonenum[0] - partyid = [0, phonenum[5] - 1].max - trainer_data = GameData::Trainer.try_get(phonenum[1], phonenum[2], partyid) - return "" if !trainer_data - if trainer_data.pokemon.length == 1 - pkmn = trainer_data.pokemon[0][:species] - else - pkmn = trainer_data.pokemon[rand(trainer_data.pokemon.length)][:species] - end - return GameData::Species.get(pkmn).name +# @deprecated This method is slated to be removed in v21. +def pbPhoneReadyToBattle?(trainer_type, name) + Deprecation.warn_method("pbPhoneReadyToBattle", "v21", "Phone.get(trainer_type, name).can_rematch?") + contact = Phone.get(trainer_type, name) + return contact && contact.can_rematch? end -def pbTrainerMapName(phonenum) - return "" if !phonenum[6] || phonenum[6] == 0 - return pbGetMapNameFromId(phonenum[6]) +# @deprecated This method is slated to be removed in v21. +def pbPhoneReset(tr_type, tr_name) + Deprecation.warn_method("pbPhoneReadyToBattle", "v21", "Phone.get(trainer_type, name) and other things") + contact = Phone.get(trainer_type, name) + return false if !contact + contact.time_to_ready = 0 + contact.rematch_flag = 0 + $game_self_switches[[contact.map_id, contact.event_id, "A"]] = true + $game_map.need_refresh = true + return true end -#=============================================================================== -# The phone call itself -#=============================================================================== -def pbPhoneCall(call, phonenum) - pbMessage(_INTL("......\\wt[5] ......\\1")) - encspecies = pbEncounterSpecies(phonenum) - trainerspecies = pbTrainerSpecies(phonenum) - trainermap = pbTrainerMapName(phonenum) - messages = call.split("\\m") - messages.length.times do |i| - messages[i].gsub!(/\\TN/, phonenum[2]) - messages[i].gsub!(/\\TP/, trainerspecies) - messages[i].gsub!(/\\TE/, encspecies) - messages[i].gsub!(/\\TM/, trainermap) - messages[i] += "\\1" if i < messages.length - 1 - pbMessage(messages[i]) - end - pbMessage(_INTL("Click!\\wt[10]\n......\\wt[5] ......\\1")) +# Called by events. +# @deprecated This method is slated to be removed in v21. +def pbPhoneBattleCount(trainer_type, name) + Deprecation.warn_method("pbPhoneBattleCount", "v21", "Phone.variant(trainer_type, name)") + return Phone.variant(trainer_type, name) +end + +# Called by events. +# @deprecated This method is slated to be removed in v21. +def pbPhoneIncrement(trainer_type, name, versions_count) + Deprecation.warn_method("pbPhoneIncrement", "v21", "Phone.increment_version(trainer_type, name, start_version)") + Phone.increment_version(trainer_type, name, 0) +end + +# Used in phone calls that say they're ready for a rematch, used in Debug function. +# @deprecated This method is slated to be removed in v21. +def pbSetReadyToBattle(contact) + Deprecation.warn_method("pbSetReadyToBattle", "v21", "contact.set_trainer_event_ready_for_rematch") + contact.set_trainer_event_ready_for_rematch +end + +# @deprecated This method is slated to be removed in v21. +def pbRandomPhoneTrainer + Deprecation.warn_method("pbRandomPhoneTrainer", "v21", "Phone::Call.get_random_trainer_for_incoming_call") + return Phone::Call.get_random_trainer_for_incoming_call +end + +# @deprecated This method is slated to be removed in v21. +def pbCallTrainer(trainer_type, name) + Deprecation.warn_method("pbCallTrainer", "v21", "Phone::Call.make_outgoing(trainer_type, name)") + Phone::Call.make_outgoing(trainer_type, name) +end + +# @deprecated This method is slated to be removed in v21. +def pbPhoneGenerateCall(contact) + Deprecation.warn_method("pbPhoneGenerateCall", "v21", "Phone::Call.generate_trainer_dialogue(contact)") + return Phone::Call.generate_trainer_dialogue(contact) +end + +# @deprecated This method is slated to be removed in v21. +def pbPhoneCall(dialogue, contact) + Deprecation.warn_method("pbPhoneCall", "v21", "Phone::Call.play(dialogue, contact)") + Phone::Call.play(dialogue, contact) +end + +# @deprecated This method is slated to be removed in v21. +def pbEncounterSpecies(contact) + Deprecation.warn_method("pbEncounterSpecies", "v21", "Phone::Call.get_random_encounter_species(contact)") + return Phone::Call.get_random_encounter_species(contact) +end + +# @deprecated This method is slated to be removed in v21. +def pbTrainerSpecies(contact) + Deprecation.warn_method("pbTrainerSpecies", "v21", "Phone::Call.get_random_contact_pokemon_species(contact)") + return Phone::Call.get_random_contact_pokemon_species(contact) +end + +# @deprecated This method is slated to be removed in v21. +def pbTrainerMapName(contact) + Deprecation.warn_method("pbTrainerMapName", "v21", "Phone::Call.get_map_name(contact)") + return Phone::Call.get_map_name(contact) end diff --git a/Data/Scripts/016_UI/008_UI_Pokegear.rb b/Data/Scripts/016_UI/008_UI_Pokegear.rb index 78882499f..98c0adef7 100644 --- a/Data/Scripts/016_UI/008_UI_Pokegear.rb +++ b/Data/Scripts/016_UI/008_UI_Pokegear.rb @@ -180,7 +180,7 @@ MenuHandlers.add(:pokegear_menu, :phone, { "name" => _INTL("Phone"), "icon_name" => "phone", "order" => 20, - "condition" => proc { next $PokemonGlobal.phoneNumbers && $PokemonGlobal.phoneNumbers.length > 0 }, +# "condition" => proc { next $PokemonGlobal.phone && $PokemonGlobal.phone.contacts.length > 0 }, "effect" => proc { |menu| pbFadeOutIn { PokemonPhoneScene.new.start } next false diff --git a/Data/Scripts/016_UI/010_UI_Phone.rb b/Data/Scripts/016_UI/010_UI_Phone.rb index d027f3df6..7f6092c9e 100644 --- a/Data/Scripts/016_UI/010_UI_Phone.rb +++ b/Data/Scripts/016_UI/010_UI_Phone.rb @@ -5,7 +5,7 @@ class Window_PhoneList < Window_CommandPokemon def drawCursor(index, rect) selarrow = AnimatedBitmap.new("Graphics/Pictures/phoneSel") if self.index == index - pbCopyBitmap(self.contents, selarrow.bitmap, rect.x, rect.y) + pbCopyBitmap(self.contents, selarrow.bitmap, rect.x, rect.y + 2) end return Rect.new(rect.x + 28, rect.y + 8, rect.width - 16, rect.height) end @@ -22,44 +22,60 @@ end #=============================================================================== class PokemonPhoneScene def start - commands = [] - @trainers = [] - if $PokemonGlobal.phoneNumbers - $PokemonGlobal.phoneNumbers.each do |num| - if num[0] # if visible - if num.length == 8 # if trainer - @trainers.push([num[1], num[2], num[6], (num[4] >= 2)]) - else # if NPC - @trainers.push([num[1], num[2], num[3]]) - end - end - end + # Get list of contacts + @contacts = [] + $PokemonGlobal.phone.contacts.each do |contact| + @contacts.push(contact) if contact.visible? end - if @trainers.length == 0 + if @contacts.length == 0 pbMessage(_INTL("There are no phone numbers stored.")) return end + # Create list of commands (display names of contacts) and count rematches + commands = [] + rematch_count = 0 + @contacts.each do |contact| + commands.push(contact.display_name) + rematch_count += 1 if contact.can_rematch? + end + # Create viewport and sprites @sprites = {} @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @viewport.z = 99999 + addBackgroundPlane(@sprites, "bg", "phonebg", @viewport) @sprites["list"] = Window_PhoneList.newEmpty(152, 32, Graphics.width - 142, Graphics.height - 80, @viewport) + @sprites["list"].windowskin = nil + @sprites["list"].commands = commands + @sprites["list"].page_item_max.times do |i| + @sprites["rematch[#{i}]"] = IconSprite.new(468, 62 + (i * 32), @viewport) + j = i + @sprites["list"].top_item + if j < @contacts.length && @contacts[j].can_rematch? + @sprites["rematch[#{i}]"].setBitmap("Graphics/Pictures/phoneRematch") + end + end @sprites["header"] = Window_UnformattedTextPokemon.newWithSize( _INTL("Phone"), 2, -18, 128, 64, @viewport ) @sprites["header"].baseColor = Color.new(248, 248, 248) @sprites["header"].shadowColor = Color.new(0, 0, 0) - mapname = (@trainers[0][2]) ? pbGetMapNameFromId(@trainers[0][2]) : "" + @sprites["header"].windowskin = nil @sprites["bottom"] = Window_AdvancedTextPokemon.newWithSize( "", 162, Graphics.height - 64, Graphics.width - 158, 64, @viewport ) - @sprites["bottom"].text = "" + mapname + @sprites["bottom"].windowskin = nil + map_name = (@contacts[0].map_id > 0) ? pbGetMapNameFromId(@contacts[0].map_id) : "" + @sprites["bottom"].text = "" + map_name @sprites["info"] = Window_AdvancedTextPokemon.newWithSize("", -8, 224, 180, 160, @viewport) - addBackgroundPlane(@sprites, "bg", "phonebg", @viewport) + @sprites["info"].windowskin = nil + infotext = _INTL("Registered
") + infotext += _INTL(" {1}
", @sprites["list"].commands.length) + infotext += _INTL("Waiting for a rematch{1}", rematch_count) + @sprites["info"].text = infotext @sprites["icon"] = IconSprite.new(70, 102, @viewport) - if @trainers[0].length == 4 - filename = GameData::TrainerType.charset_filename(@trainers[0][0]) + if @contacts[0].trainer? + filename = GameData::TrainerType.charset_filename(@contacts[0].trainer_type) else - filename = sprintf("Graphics/Characters/phone%03d", @trainers[0][0]) + filename = sprintf("Graphics/Characters/phone%03d", @contacts[0].common_event_id) end @sprites["icon"].setBitmap(filename) charwidth = @sprites["icon"].bitmap.width @@ -67,33 +83,7 @@ class PokemonPhoneScene @sprites["icon"].x = 86 - (charwidth / 8) @sprites["icon"].y = 134 - (charheight / 8) @sprites["icon"].src_rect = Rect.new(0, 0, charwidth / 4, charheight / 4) - @trainers.each do |trainer| - if trainer.length == 4 - displayname = _INTL("{1} {2}", GameData::TrainerType.get(trainer[0]).name, - pbGetMessageFromHash(MessageTypes::TrainerNames, trainer[1])) - commands.push(displayname) # trainer's display name - else - commands.push(trainer[1]) # NPC's display name - end - end - @sprites["list"].commands = commands - @sprites["list"].page_item_max.times do |i| - @sprites["rematch[#{i}]"] = IconSprite.new(468, 62 + (i * 32), @viewport) - j = i + @sprites["list"].top_item - next if j >= commands.length - trainer = @trainers[j] - if trainer.length == 4 && trainer[3] - @sprites["rematch[#{i}]"].setBitmap("Graphics/Pictures/phoneRematch") - end - end - rematchcount = 0 - @trainers.each do |trainer| - rematchcount += 1 if trainer.length == 4 && trainer[3] - end - infotext = _INTL("Registered
") - infotext += _INTL(" {1}
", @sprites["list"].commands.length) - infotext += _INTL("Waiting for a rematch{1}", rematchcount) - @sprites["info"].text = infotext + # Start scene pbFadeInAndShow(@sprites) pbActivateWindow(@sprites, "list") { oldindex = -1 @@ -101,12 +91,13 @@ class PokemonPhoneScene Graphics.update Input.update pbUpdateSpriteHash(@sprites) + # Cursor moved, update display if @sprites["list"].index != oldindex - trainer = @trainers[@sprites["list"].index] - if trainer.length == 4 - filename = GameData::TrainerType.charset_filename(trainer[0]) + contact = @contacts[@sprites["list"].index] + if contact.trainer? + filename = GameData::TrainerType.charset_filename(contact.trainer_type) else - filename = sprintf("Graphics/Characters/phone%03d", trainer[0]) + filename = sprintf("Graphics/Characters/phone%03d", contact.common_event_id) end @sprites["icon"].setBitmap(filename) charwidth = @sprites["icon"].bitmap.width @@ -114,24 +105,23 @@ class PokemonPhoneScene @sprites["icon"].x = 86 - (charwidth / 8) @sprites["icon"].y = 134 - (charheight / 8) @sprites["icon"].src_rect = Rect.new(0, 0, charwidth / 4, charheight / 4) - mapname = (trainer[2]) ? pbGetMapNameFromId(trainer[2]) : "" - @sprites["bottom"].text = "" + mapname + map_name = (contact.map_id > 0) ? pbGetMapNameFromId(contact.map_id) : "" + @sprites["bottom"].text = "" + map_name @sprites["list"].page_item_max.times do |i| @sprites["rematch[#{i}]"].clearBitmaps j = i + @sprites["list"].top_item - next if j >= commands.length - trainer = @trainers[j] - if trainer.length == 4 && trainer[3] + if j < @contacts.length && @contacts[j].can_rematch? @sprites["rematch[#{i}]"].setBitmap("Graphics/Pictures/phoneRematch") end end end + # Get inputs if Input.trigger?(Input::BACK) pbPlayCloseMenuSE break elsif Input.trigger?(Input::USE) index = @sprites["list"].index - pbCallTrainer(@trainers[index][0], @trainers[index][1]) if index >= 0 + Phone::Call.make_outgoing(@contacts[index]) if index >= 0 end end } 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 befbbca1b..939d5fa42 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 @@ -391,13 +391,13 @@ MenuHandlers.add(:debug_menu, :ready_rematches, { "parent" => :battle_menu, "description" => _INTL("Make all trainers in the phone ready for rematches."), "effect" => proc { - if !$PokemonGlobal.phoneNumbers || $PokemonGlobal.phoneNumbers.length == 0 + if !$PokemonGlobal.phone || $PokemonGlobal.phone.contacts.length == 0 pbMessage(_INTL("There are no trainers in the Phone.")) else - $PokemonGlobal.phoneNumbers.each do |i| - next if i.length != 8 # Isn't a trainer with an event - i[4] = 2 - pbSetReadyToBattle(i) + $PokemonGlobal.phone.contacts.each do |contact| + next if !contact.trainer? + contact.rematch_flag = 1 + contact.set_trainer_event_ready_for_rematch end pbMessage(_INTL("All trainers in the Phone are now ready to rebattle.")) end diff --git a/Data/Scripts/021_Compiler/004_Compiler_MapsAndEvents.rb b/Data/Scripts/021_Compiler/004_Compiler_MapsAndEvents.rb index 5896f3cd1..348a7114c 100644 --- a/Data/Scripts/021_Compiler/004_Compiler_MapsAndEvents.rb +++ b/Data/Scripts/021_Compiler/004_Compiler_MapsAndEvents.rb @@ -198,6 +198,21 @@ module Compiler list.push(RPG::EventCommand.new(412, indent - 1, [])) end + # cancel is 1/2/3/4 for the options, 0 for disallow, 5 for branch + def push_choices(list, choices, cancel = 0, indent = 0) + list.push(RPG::EventCommand.new(102, indent, [choices, cancel, [0, 1, 2, 3]])) + end + + def push_choice(list, index, text, indent = 0) + list.push(RPG::EventCommand.new(0, indent, [])) if index > 0 + list.push(RPG::EventCommand.new(402, indent - 1, [index, text])) + end + + def push_choices_end(list, indent = 0) + list.push(RPG::EventCommand.new(0, indent, [])) + list.push(RPG::EventCommand.new(404, indent - 1, [])) + end + def push_self_switch(list, swtch, switchOn, indent = 0) list.push(RPG::EventCommand.new(123, indent, [swtch, switchOn ? 0 : 1])) end @@ -491,14 +506,13 @@ module Compiler end end # Compile the trainer comments - rewriteComments = false # You can change this + rewriteComments = true #false # You can change this battles = [] trtype = nil trname = nil battleid = 0 doublebattle = false backdrop = nil - endspeeches = [] outcome = 0 continue = false endbattles = [] @@ -522,34 +536,32 @@ module Compiler value = $~[1].gsub(/^\s+/, "").gsub(/\s+$/, "") doublebattle = true if value.upcase == "TRUE" || value.upcase == "YES" push_comment(firstpage.list, command) if rewriteComments - elsif command[/^Backdrop\:\s*([\s\S]+)$/i] - backdrop = $~[1].gsub(/^\s+/, "").gsub(/\s+$/, "") - push_comment(firstpage.list, command) if rewriteComments - elsif command[/^EndSpeech\:\s*([\s\S]+)$/i] - endspeeches.push(command) - push_comment(firstpage.list, command) if rewriteComments - elsif command[/^Outcome\:\s*(\d+)$/i] - outcome = $~[1].to_i - push_comment(firstpage.list, command) if rewriteComments elsif command[/^Continue\:\s*([\s\S]+)$/i] value = $~[1].gsub(/^\s+/, "").gsub(/\s+$/, "") continue = true if value.upcase == "TRUE" || value.upcase == "YES" push_comment(firstpage.list, command) if rewriteComments - elsif command[/^EndBattle\:\s*([\s\S]+)$/i] - endbattles.push($~[1].gsub(/^\s+/, "").gsub(/\s+$/, "")) - push_comment(firstpage.list, command) if rewriteComments elsif command[/^EndIfSwitch\:\s*([\s\S]+)$/i] endifswitch.push(($~[1].gsub(/^\s+/, "").gsub(/\s+$/, "")).to_i) push_comment(firstpage.list, command) if rewriteComments elsif command[/^VanishIfSwitch\:\s*([\s\S]+)$/i] vanishifswitch.push(($~[1].gsub(/^\s+/, "").gsub(/\s+$/, "")).to_i) push_comment(firstpage.list, command) if rewriteComments + elsif command[/^Backdrop\:\s*([\s\S]+)$/i] + backdrop = $~[1].gsub(/^\s+/, "").gsub(/\s+$/, "") + push_comment(firstpage.list, command) if rewriteComments + elsif command[/^Outcome\:\s*(\d+)$/i] + outcome = $~[1].to_i + push_comment(firstpage.list, command) if rewriteComments + elsif command[/^EndBattle\:\s*([\s\S]+)$/i] + endbattles.push($~[1].gsub(/^\s+/, "").gsub(/\s+$/, "")) + push_comment(firstpage.list, command) if rewriteComments elsif command[/^RegSpeech\:\s*([\s\S]+)$/i] regspeech = $~[1].gsub(/^\s+/, "").gsub(/\s+$/, "") push_comment(firstpage.list, command) if rewriteComments end end return nil if battles.length <= 0 + endbattles.push("...") if endbattles.length == 0 # Run trainer check now, except in editor trainerChecker.pbTrainerBattleCheck(trtype, trname, battleid) # Set the event's charset to one depending on the trainer type if the event @@ -562,32 +574,43 @@ module Compiler end end # Create strings that will be used repeatedly - safetrcombo = sprintf(":%s,\"%s\"", trtype, safequote(trname)) # :YOUNGSTER,"Joey" + safetrcombo = sprintf(":%s, \"%s\"", trtype, safequote(trname)) # :YOUNGSTER, "Joey" + brieftrcombo = safetrcombo + safetrcombo = sprintf("%s, %d", safetrcombo, battleid) if battleid > 0 # :YOUNGSTER, "Joey", 1 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]) if battles.length > 1 # Has rematches - push_script(firstpage.list, sprintf("pbTrainerCheck(%s,%d,%d)", safetrcombo, battles.length, battleid)) + if battleid > 0 + push_script(firstpage.list, sprintf("pbTrainerCheck(%s, %d, %d)", brieftrcombo, battles.length, battleid)) + else + push_script(firstpage.list, sprintf("pbTrainerCheck(%s, %d)", brieftrcombo, battles.length)) + end end push_script(firstpage.list, "setBattleRule(\"double\")") if doublebattle - 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, sprintf("setBattleRule(\n \"backdrop\", \"%s\"\n)", safequote(backdrop))) if backdrop + push_script(firstpage.list, sprintf("setBattleRule(\"outcomeVar\", %d)", outcome)) if outcome > 1 push_script(firstpage.list, "setBattleRule(\"canLose\")") if continue - if battleid > 0 - battleString = sprintf("TrainerBattle.start(%s,%d)", safetrcombo, battleid) - else - battleString = sprintf("TrainerBattle.start(%s)", safetrcombo) - end + battleString = sprintf("TrainerBattle.start(%s)", safetrcombo) push_branch(firstpage.list, battleString) if battles.length > 1 # Has rematches - push_script(firstpage.list, - sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_self,%s,%d)", - regspeech, safetrcombo, battles.length), 1) + push_branch(firstpage.list, sprintf("Phone.can_add?(%s)", safetrcombo), 1) + push_text(firstpage.list, regspeech, 2) + push_choices(firstpage.list, ["Yes", "No"], 2, 2) + push_choice(firstpage.list, 0, "Yes", 3) + if battleid > 0 + push_script(firstpage.list, sprintf("Phone.add(get_self,\n %s, %d, %d\n)", brieftrcombo, battles.length, battleid), 3) + else + push_script(firstpage.list, sprintf("Phone.add(get_self,\n %s, %d\n)", brieftrcombo, battles.length), 3) + end + push_choice(firstpage.list, 1, "No", 3) + push_choices_end(firstpage.list, 3) + push_branch_end(firstpage.list, 2) end push_self_switch(firstpage.list, "A", true, 1) + push_self_switch(firstpage.list, "B", true, 1) if battles.length > 1 push_branch_end(firstpage.list, 1) push_script(firstpage.list, "pbTrainerEnd", 0) push_end(firstpage.list) @@ -604,53 +627,66 @@ module Compiler rematchpage.condition = lastpage.condition.clone rematchpage.condition.self_switch_valid = true rematchpage.condition.self_switch_ch = "B" - # Write rematch and last pages - (1...battles.length).each do |i| - # Run trainer check now, except in editor - trainerChecker.pbTrainerBattleCheck(trtype, trname, battleid + i) - if i == battles.length - 1 - push_branch(rematchpage.list, sprintf("pbPhoneBattleCount(%s)>=%d", safetrcombo, i)) - push_branch(lastpage.list, sprintf("pbPhoneBattleCount(%s)>%d", safetrcombo, i)) - else - push_branch(rematchpage.list, sprintf("pbPhoneBattleCount(%s)==%d", safetrcombo, i)) - push_branch(lastpage.list, sprintf("pbPhoneBattleCount(%s)==%d", safetrcombo, i)) + # Write rematch page + push_script(rematchpage.list, introplay, 0) # pbTrainerIntro + if battles.length == 2 + push_text(rematchpage.list, battles[1], 0) + else + (1...battles.length).each do |i| + # Run trainer check now, except in editor + trainerChecker.pbTrainerBattleCheck(trtype, trname, battleid + i) + if i == 1 + push_branch(rematchpage.list, sprintf("Phone.variant(%s) <= %d", safetrcombo, i)) + elsif i == battles.length - 1 + push_branch(rematchpage.list, sprintf("Phone.variant(%s) >= %d", safetrcombo, i)) + else + push_branch(rematchpage.list, sprintf("Phone.variant(%s) == %d", safetrcombo, i)) + end + push_text(rematchpage.list, battles[i], 1) + push_branch_end(rematchpage.list, 1) end - # Rematch page - push_script(rematchpage.list, introplay, 1) # pbTrainerIntro - push_text(rematchpage.list, battles[i], 1) - push_script(rematchpage.list, "setBattleRule(\"double\")", 1) if doublebattle - 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 - 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) - push_self_switch(rematchpage.list, "B", false, 2) - push_script(rematchpage.list, "pbTrainerEnd", 2) - push_branch_end(rematchpage.list, 2) - push_exit(rematchpage.list, 1) # Exit Event Processing - push_branch_end(rematchpage.list, 1) - # Last page - if endbattles.length > 0 - ebattle = (endbattles[i]) ? endbattles[i] : endbattles[endbattles.length - 1] - push_text(lastpage.list, ebattle, 1) - end - push_script(lastpage.list, - sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_self,%s,%d)", - regspeech, safetrcombo, battles.length), 1) - push_exit(lastpage.list, 1) # Exit Event Processing - push_branch_end(lastpage.list, 1) end - # Finish writing rematch page + push_script(rematchpage.list, "setBattleRule(\"double\")", 1) if doublebattle + push_script(rematchpage.list, sprintf("setBattleRule(\n \"backdrop\", %s\n)", 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 + battleString = sprintf("Phone.battle(%s)", safetrcombo) + push_branch(rematchpage.list, battleString, 0) + push_script(rematchpage.list, sprintf("Phone.reset_after_win(\n %s\n)", safetrcombo), 1) + push_self_switch(rematchpage.list, "A", true, 1) + push_script(rematchpage.list, "pbTrainerEnd", 1) + push_branch_end(rematchpage.list, 1) push_end(rematchpage.list) - # Finish writing last page - ebattle = (endbattles[0]) ? endbattles[0] : "..." - push_text(lastpage.list, ebattle) + # Write last page + if endbattles.length > 0 + if battles.length == 1 + push_text(lastpage.list, endbattles[0], 0) + else + (0...battles.length).each do |i| + if i == battles.length - 1 + push_branch(lastpage.list, sprintf("Phone.variant_beaten(%s) >= %d", safetrcombo, i)) + else + push_branch(lastpage.list, sprintf("Phone.variant_beaten(%s) == %d", safetrcombo, i)) + end + ebattle = (endbattles[i]) ? endbattles[i] : endbattles[endbattles.length - 1] + push_text(lastpage.list, ebattle, 1) + push_branch_end(lastpage.list, 1) + end + end + end if battles.length > 1 - push_script(lastpage.list, - sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_self,%s,%d)", - regspeech, safetrcombo, battles.length)) + push_branch(lastpage.list, sprintf("Phone.can_add?(%s)", safetrcombo), 0) + push_text(lastpage.list, regspeech, 1) + push_choices(lastpage.list, ["Yes", "No"], 2, 1) + push_choice(lastpage.list, 0, "Yes", 2) + if battleid > 0 + push_script(lastpage.list, sprintf("Phone.add(get_self,\n %s, %d, %d\n)", brieftrcombo, battles.length, battleid), 2) + else + push_script(lastpage.list, sprintf("Phone.add(get_self,\n %s, %d\n)", brieftrcombo, battles.length), 2) + end + push_choice(lastpage.list, 1, "No", 2) + push_choices_end(lastpage.list, 2) + push_branch_end(lastpage.list, 1) end push_end(lastpage.list) # Add pages to the new event diff --git a/PBS/phone.txt b/PBS/phone.txt index 7270a5546..226a306f8 100644 --- a/PBS/phone.txt +++ b/PBS/phone.txt @@ -1,34 +1,34 @@ # See the documentation on the wiki to learn how to edit this file. #------------------------------- [] -How are your Pokémon doing?\mMy \TP's really energetic. It's a handful!\mOh yeah, I managed to beat a tough \TE.\mI need to make my party stronger. -My \TP's looking really awesome.\mI wish I could show you.\mHey, listen! I almost caught a \TE the other day.\mOh, it was sooooooo close, too! +How are your Pokémon doing?\mMy \TP's really energetic. It's a handful!\mOh yeah, I managed to beat a tough \TE.\mI need to make my party stronger. +My \TP's looking really awesome.\mI wish I could show you.\mHey, listen! I almost caught a \TE the other day.\mOh, it was sooooooo close, too! #------------------------------- [] -Want to battle? It's not going to be a repeat of the last time we met.\mI'll be waiting for you around \TM. -Do you want to battle? I'm going to win this time!\mI'll be waiting for you around \TM.\mLook for me, OK? My \TP will be expecting you. +Want to battle? It's not going to be a repeat of the last time we met.\mI'll be waiting for you around \TM. +Do you want to battle? I'm going to win this time!\mI'll be waiting for you around \TM.\mLook for me, OK? My \TP will be expecting you. #------------------------------- [] -Good morning, \PN.\mThis is \TN. Did I wake you? +Good morning, \PN.\mThis is \TN. Did I wake you? #------------------------------- [] -\PN, good evening! Hi.\mThis is \TN. +\PN, good evening! Hi.\mThis is \TN. #------------------------------- [] -Hello. This is \TN. -Good day, \PN! Hi. This is \TN. -How are you doing? \PN, howdy! This is \TN. Isn't it nice out? -\PN, good day! It's me, \TN. Got a minute? -Hello, \PN. This is \TN. How are things? +Hello. This is \TN. +Good day, \PN! Hi. This is \TN. +How are you doing? \PN, howdy! This is \TN. Isn't it nice out? +\PN, good day! It's me, \TN. Got a minute? +Hello, \PN. This is \TN. How are things? #------------------------------- [] -How are your Pokémon doing?\mMy \TP's really energetic. It's a handful! +How are your Pokémon doing?\mMy \TP's really energetic. It's a handful! How are your Pokémon doing?\mI always keep my \TP in top shape by going to Pokémon Centers. -My \TP's looking really awesome. I wish I could show you. +My \TP's looking really awesome. I wish I could show you. I dressed my \TP and it looks even cuter than before. #------------------------------- [] Oh yeah, I managed to beat a tough \TE.\mI need to make my party stronger. -You have to hear this! I battled \TE the other day.\mIt was easy! I had a type advantage. -Hey, listen! I almost caught \TE the other day.\mOh, it was sooooooo close, too! -Guess what happened the other day. I missed catching \TE again.\mMaybe I'm not very good at this. +You have to hear this! I battled \TE the other day.\mIt was easy! I had a type advantage. +Hey, listen! I almost caught \TE the other day.\mOh, it was sooooooo close, too! +Guess what happened the other day. I missed catching \TE again.\mMaybe I'm not very good at this.