Redesigned phone.txt (old format isn't supported), added support for contact-specific phone messages, added more phone message components

This commit is contained in:
Maruno17
2022-09-11 19:07:47 +01:00
parent 4fcd19e247
commit 2962944cab
9 changed files with 262 additions and 139 deletions

View File

@@ -240,5 +240,6 @@ module GameData
Metadata.load
PlayerMetadata.load
MapMetadata.load
PhoneMessage.load
end
end

View File

@@ -3,7 +3,6 @@
#===============================================================================
class Game_Temp
attr_accessor :town_map_data
attr_accessor :phone_messages_data
attr_accessor :regional_dexes_data
attr_accessor :battle_animations_data
attr_accessor :move_to_battle_animation_data
@@ -13,7 +12,6 @@ end
def pbClearData
if $game_temp
$game_temp.town_map_data = nil
$game_temp.phone_messages_data = nil
$game_temp.regional_dexes_data = nil
$game_temp.battle_animations_data = nil
$game_temp.move_to_battle_animation_data = nil
@@ -37,17 +35,6 @@ def pbLoadTownMapData
return $game_temp.town_map_data
end
#===============================================================================
# Method to get phone call data.
#===============================================================================
def pbLoadPhoneData
$game_temp = Game_Temp.new if !$game_temp
if !$game_temp.phone_messages_data && pbRgssExists?("Data/phone.dat")
$game_temp.phone_messages_data = load_data("Data/phone.dat")
end
return $game_temp.phone_messages_data
end
#===============================================================================
# Method to get Regional Dexes data.
#===============================================================================

View File

@@ -1,24 +0,0 @@
#===============================================================================
# Phone data
#===============================================================================
class PhoneDatabase
attr_accessor :generics
attr_accessor :greetings
attr_accessor :greetingsMorning
attr_accessor :greetingsEvening
attr_accessor :bodies1
attr_accessor :bodies2
attr_accessor :battleRequests
attr_accessor :trainers
def initialize
@generics = []
@greetings = []
@greetingsMorning = []
@greetingsEvening = []
@bodies1 = []
@bodies2 = []
@battleRequests = []
@trainers = []
end
end

View File

@@ -0,0 +1,96 @@
module GameData
class PhoneMessage
attr_reader :id
attr_reader :trainer_type, :real_name, :version
attr_reader :intro, :intro_morning, :intro_afternoon, :intro_evening
attr_reader :body, :body1, :body2
attr_reader :battle_request, :battle_remind
attr_reader :end
DATA = {}
DATA_FILENAME = "phone.dat"
SCHEMA = {
"Intro" => [:intro, "q"],
"IntroMorning" => [:intro_morning, "q"],
"IntroAfternoon" => [:intro_afternoon, "q"],
"IntroEvening" => [:intro_evening, "q"],
"Body" => [:body, "q"],
"Body1" => [:body1, "q"],
"Body2" => [:body2, "q"],
"BattleRequest" => [:battle_request, "q"],
"BattleRemind" => [:battle_remind, "q"],
"End" => [:end, "q"]
}
extend ClassMethodsSymbols
include InstanceMethods
# @param tr_type [Symbol, String]
# @param tr_name [String]
# @param tr_version [Integer, nil]
# @return [Boolean] whether the given other is defined as a self
def self.exists?(tr_type, tr_name, tr_version = 0)
validate tr_type => [Symbol, String]
validate tr_name => [String]
key = [tr_type.to_sym, tr_name, tr_version]
return !self::DATA[key].nil?
end
# @param tr_type [Symbol, String]
# @param tr_name [String]
# @param tr_version [Integer, nil]
# @return [self]
def self.get(tr_type, tr_name, tr_version = 0)
validate tr_type => [Symbol, String]
validate tr_name => [String]
key = [tr_type.to_sym, tr_name, tr_version]
raise "Phone messages not found for #{tr_type} #{tr_name} #{tr_version}." unless self::DATA.has_key?(key)
return self::DATA[key]
end
# @param tr_type [Symbol, String]
# @param tr_name [String]
# @param tr_version [Integer, nil]
# @return [self, nil]
def self.try_get(tr_type, tr_name, tr_version = 0)
validate tr_type => [Symbol, String]
validate tr_name => [String]
key = [tr_type.to_sym, tr_name, tr_version]
return (self::DATA.has_key?(key)) ? self::DATA[key] : nil
end
def initialize(hash)
@id = hash[:id]
@trainer_type = hash[:trainer_type]
@real_name = hash[:name]
@version = hash[:version] || 0
@intro = hash[:intro]
@intro_morning = hash[:intro_morning]
@intro_afternoon = hash[:intro_afternoon]
@intro_evening = hash[:intro_evening]
@body = hash[:body]
@body1 = hash[:body1]
@body2 = hash[:body2]
@battle_request = hash[:battle_request]
@battle_remind = hash[:battle_remind]
@end = hash[:end]
end
def property_from_string(str)
case str
when "Intro" then return @intro
when "IntroMorning" then return @intro_morning
when "IntroAfternoon" then return @intro_afternoon
when "IntroEvening" then return @intro_evening
when "Body" then return @body
when "Body1" then return @body1
when "Body2" then return @body2
when "BattleRequest" then return @battle_request
when "BattleRemind" then return @battle_remind
when "End" then return @end
end
return nil
end
end
end

View File

@@ -469,36 +469,59 @@ class Phone
def generate_trainer_dialogue(contact)
validate contact => Phone::Contact
# Get the set of messages to be used by the contact
messages = GameData::PhoneMessage.try_get(contact.trainer_type, contact.name, contact.version)
messages = GameData::PhoneMessage.try_get(contact.trainer_type, contact.name, contact.start_version) if !messages
messages = GameData::PhoneMessage::DATA["default"] if !messages
# Create lambda for choosing a random message and translating it
get_random_message = lambda do |messages|
return "" if !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)
ret = get_random_message.call(messages.intro)
time = pbGetTimeNow
if PBDayNight.isMorning?(time)
modcall = get_random_message.call(phone_data.greetingsMorning)
ret = modcall if !nil_or_empty?(modcall)
mod_call = get_random_message.call(messages.intro_morning)
ret = mod_call if !nil_or_empty?(mod_call)
elsif PBDayNight.isAfternoon?(time)
mod_call = get_random_message.call(messages.intro_afternoon)
ret = mod_call if !nil_or_empty?(mod_call)
elsif PBDayNight.isEvening?(time)
modcall = get_random_message.call(phone_data.greetingsEvening)
ret = modcall if !nil_or_empty?(modcall)
mod_call = get_random_message.call(messages.intro_evening)
ret = mod_call if !nil_or_empty?(mod_call)
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)
# Choose main message set
if Phone.rematches_enabled && contact.rematch_flag > 0
# Trainer is ready for a rematch, so tell/remind the player
if contact.rematch_flag == 1 # Tell the player
ret += get_random_message.call(messages.battle_request)
contact.rematch_flag = 2 # Ready for rematch and told player
elsif contact.rematch_flag == 2 # Remind the player
if messages.battle_remind
ret += get_random_message.call(messages.battle_remind)
else
ret += get_random_message.call(messages.battle_request)
end
end
else
# Choose random generic
ret += get_random_message.call(phone_data.generics)
# Standard messages
if messages.body1 && messages.body2 && (!messages.body || rand(100) < 75)
echoln messages.body2
# Choose random pair of body messages
ret += get_random_message.call(messages.body1)
ret += "\\m"
ret += get_random_message.call(messages.body2)
else
# Choose random full body message
ret += get_random_message.call(messages.body)
end
# Choose end message
mod_call = get_random_message.call(messages.end)
ret += "\\m" + mod_call if !nil_or_empty?(mod_call)
end
return ret
end

View File

@@ -757,7 +757,6 @@ module Compiler
modify_pbs_file_contents_before_compiling
compile_town_map
compile_connections
compile_phone
compile_types
compile_abilities
compile_moves # Depends on Type
@@ -775,6 +774,7 @@ module Compiler
compile_trainer_lists # Depends on TrainerType
compile_metadata # Depends on TrainerType
compile_map_metadata
compile_phone # Depends on TrainerType
end
def compile_all(mustCompile)

View File

@@ -102,37 +102,69 @@ module Compiler
def compile_phone(path = "PBS/phone.txt")
return if !safeExists?(path)
compile_pbs_file_message_start(path)
database = PhoneDatabase.new
sections = []
File.open(path, "rb") { |f|
pbEachSection(f) { |section, name|
case name
when "<Generics>"
database.generics = section
sections.concat(section)
when "<BattleRequests>"
database.battleRequests = section
sections.concat(section)
when "<GreetingsMorning>"
database.greetingsMorning = section
sections.concat(section)
when "<GreetingsEvening>"
database.greetingsEvening = section
sections.concat(section)
when "<Greetings>"
database.greetings = section
sections.concat(section)
when "<Bodies1>"
database.bodies1 = section
sections.concat(section)
when "<Bodies2>"
database.bodies2 = section
sections.concat(section)
GameData::PhoneMessage::DATA.clear
schema = GameData::PhoneMessage::SCHEMA
messages = []
contact_hash = nil
# Read each line of phone.txt at a time and compile it as a contact property
idx = 0
pbCompilerEachPreppedLine(path) { |line, line_no|
echo "." if idx % 50 == 0
idx += 1
Graphics.update if idx % 250 == 0
if line[/^\s*\[\s*(.+)\s*\]\s*$/]
# New section [trainer_type, name] or [trainer_type, name, version]
if contact_hash
# Add contact's data to records
if contact_hash[:trainer_type] == "default"
contact_hash[:id] = contact_hash[:trainer_type]
else
contact_hash[:id] = [contact_hash[:trainer_type], contact_hash[:name], contact_hash[:version]]
end
GameData::PhoneMessage.register(contact_hash)
end
}
# Construct contact hash
header = $~[1]
if header.strip.downcase == "default"
contact_hash = {
:trainer_type => "default"
}
else
line_data = pbGetCsvRecord($~[1], line_no, [0, "esU", :TrainerType])
contact_hash = {
:trainer_type => line_data[0],
:name => line_data[1],
:version => line_data[2] || 0
}
end
elsif line[/^\s*(\w+)\s*=\s*(.*)$/]
# XXX=YYY lines
if !contact_hash
raise _INTL("Expected a section at the beginning of the file.\r\n{1}", FileLineData.linereport)
end
property_name = $~[1]
line_schema = schema[property_name]
next if !line_schema
property_value = pbGetCsvRecord($~[2], line_no, line_schema)
# Record XXX=YYY setting
contact_hash[line_schema[0]] ||= []
contact_hash[line_schema[0]].push(property_value)
messages.push(property_value)
end
}
MessageTypes.setMessagesAsHash(MessageTypes::PhoneMessages, sections)
save_data(database, "Data/phone.dat")
# Add last contact's data to records
if contact_hash
# Add contact's data to records
if contact_hash[:trainer_type] == "default"
contact_hash[:id] = contact_hash[:trainer_type]
else
contact_hash[:id] = [contact_hash[:trainer_type], contact_hash[:name], contact_hash[:version]]
end
GameData::PhoneMessage.register(contact_hash)
end
# Save all data
GameData::PhoneMessage.save
MessageTypes.setMessagesAsHash(MessageTypes::PhoneMessages, messages)
process_pbs_file_message_end
end

View File

@@ -103,32 +103,26 @@ module Compiler
# Save phone messages to PBS file
#=============================================================================
def write_phone(path = "PBS/phone.txt")
data = load_data("Data/phone.dat") rescue nil
return if !data
write_pbs_file_message_start(path)
keys = GameData::PhoneMessage::SCHEMA.keys
File.open(path, "wb") { |f|
add_PBS_header_to_file(f)
f.write("\#-------------------------------\r\n")
f.write("[<Generics>]\r\n")
f.write(data.generics.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<BattleRequests>]\r\n")
f.write(data.battleRequests.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<GreetingsMorning>]\r\n")
f.write(data.greetingsMorning.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<GreetingsEvening>]\r\n")
f.write(data.greetingsEvening.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Greetings>]\r\n")
f.write(data.greetings.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Bodies1>]\r\n")
f.write(data.bodies1.join("\r\n") + "\r\n")
f.write("\#-------------------------------\r\n")
f.write("[<Bodies2>]\r\n")
f.write(data.bodies2.join("\r\n") + "\r\n")
# Write message sets
GameData::PhoneMessage.each do |contact|
f.write("\#-------------------------------\r\n")
if contact.id == "default"
f.write("[Default]\r\n")
elsif contact.version > 0
f.write(sprintf("[%s,%s,%d]\r\n", contact.trainer_type, contact.real_name, contact.version))
else
f.write(sprintf("[%s,%s]\r\n", contact.trainer_type, contact.real_name))
end
keys.each do |key|
msgs = contact.property_from_string(key)
next if !msgs || msgs.length == 0
msgs.each { |msg| f.write(key + " = " + msg + "\r\n") }
end
end
}
process_pbs_file_message_end
end
@@ -886,7 +880,6 @@ module Compiler
Console.echo_h1 _INTL("Writing all PBS files")
write_town_map
write_connections
write_phone
write_types
write_abilities
write_moves
@@ -904,6 +897,7 @@ module Compiler
write_trainer_lists
write_metadata
write_map_metadata
write_phone
echoln ""
Console.echo_h2("Successfully rewrote all PBS files", text: :green)
end

View File

@@ -1,34 +1,48 @@
# See the documentation on the wiki to learn how to edit this file.
#-------------------------------
[<Generics>]
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!
[Default]
Intro = Hello. This is \TN.
Intro = Good day, \PN! Hi. This is \TN.
Intro = How are you doing? \PN, howdy! This is \TN. Isn't it nice out?
Intro = \PN, good day! It's me, \TN. Got a minute?
Intro = Hello, \PN. This is \TN. How are things?
IntroMorning = Good morning, \PN. This is \TN. Did I wake you?
IntroAfternoon = Good afternoon, \PN! It's \TN here.
IntroEvening = \PN, good evening! Hi. This is \TN.
Body = 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.
Body = My \TP's looking really awesome. I wish I could show you.\mHey, listen! I almost caught a \TE the other day.\mOh, it was sooooooo close, too!
Body1 = How are your Pokémon doing?\mMy \TP's really energetic. It's a handful!
Body1 = How are your Pokémon doing?\mI always keep my \TP in top shape by going to Pokémon Centers.
Body1 = My \TP's looking really awesome. I wish I could show you.
Body1 = I dressed my \TP and it looks even cuter than before.
Body2 = Oh yeah, I managed to beat a tough \TE.\mI need to make my party stronger.
Body2 = You have to hear this! I battled \TE the other day.\mIt was easy! I had a type advantage.
Body2 = Hey, listen! I almost caught \TE the other day.\mOh, it was sooooooo close, too!
Body2 = Guess what happened the other day. I missed catching \TE again.\mMaybe I'm not very good at this.
BattleRequest = 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.
BattleRequest = 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.
#-------------------------------
[<BattleRequests>]
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.
[CAMPER,Jeff]
Intro = Hello. This is \TN...\mHow's it going, \PN?
Body1 = My \TP is looking more and more like me. It's getting cuter!
Body2 = And you know? Now we can KO \TE easily.\mI should challenge the Cedolan Gym.
Body2 = And you know? We just failed to beat \TE by a tiny margin.\mI'm guessing my Pokémon's levels aren't high enough yet...
BattleRequest = You must be a lot better now, huh?\mHow about showing me your technique in a real battle with me?\mI'll be waiting on \TM.
BattleReminder = Where are you? Lets have our battle soon!\mI'll be waiting on \TM.
End = See you later!
#-------------------------------
[<GreetingsMorning>]
Good morning, \PN.\mThis is \TN. Did I wake you?
#-------------------------------
[<GreetingsEvening>]
\PN, good evening! Hi.\mThis is \TN.
#-------------------------------
[<Greetings>]
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?
#-------------------------------
[<Bodies1>]
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.
I dressed my \TP and it looks even cuter than before.
#-------------------------------
[<Bodies2>]
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.
[PICNICKER,Susie]
Intro = This is \TN!
Intro = Hi, this is \TN!
IntroMorning = This is \TN! Good morning, \PN!
IntroMorning = Hi, this is \TN! Good morning, \PN!
IntroAfternoon = This is \TN! Good afternoon, \PN!
IntroAfternoon = Hi, this is \TN! Good afternoon, \PN!
IntroEvening = This is \TN! Good evening, \PN!
IntroEvening = Hi, this is \TN! Good evening, \PN!
Body1 = My \TP and I are getting more in sync with each other.
Body2 = We battled a wild \TE and managed to beat it in a close match.\mWere getting into the groove!
Body2 = But, you know what? I still havent caught \TE.\mIts getting beyond frustrating...
BattleRequest = Would you be my practice partner again sometime?\mI'll be waiting on \TM...\mCould you take it a little easier on me next time?
BattleReminder = How soon can I expect to see you?\mDon't forget, \TM!
End = Bye! Lets chat again!