Module: PFM::Text

Included in:
Battle::Message
Defined in:
scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb

Overview

The text parser of PSDK (retrieve text from Studio::Text)

Author:

  • Nuri Yuri

Constant Summary collapse

PKNICK =

Pokemon Nickname var catcher

Array.new(7) { |i| "[VAR PKNICK(000#{i})]" }
PKNAME =

Pokemon name var catcher

Array.new(7) { |i| "[VAR PKNAME(000#{i})]" }
TRNAME =

Trainer name var catcher

Array.new(7) { |i| "[VAR TRNAME(000#{i})]" }
ITEM2 =

Item var catcher

['[VAR ITEM2(0000)]', '[VAR ITEM2(0001)]', '[VAR ITEM2(0002)]', '[VAR ITEM2(0003)]']
ITEMPLUR1 =

Definite article catcher

['[VAR ITEMPLUR1]']
MOVE =

Move var catcher

['[VAR MOVE(0000)]', '[VAR MOVE(0001)]', '[VAR MOVE(0002)]']
NUMB =

Number var catcher

[nil.to_s, '[VAR NUM1(0000)]', '[VAR NUM1(0001)]']
NUM3 =

Number 3 var catcher

['[VAR NUM3(0000)]', '[VAR NUM3(0001)]', '[VAR NUM3(0002)]']
NUM2 =

Number 2 var catcher

['[VAR NUM2(0000)]', '[VAR NUM2(0001)]', '[VAR NUM2(0002)]', '[VAR NUM2(0003)]']
NUM7R =

Number 7 var catcher regexp

/\[VAR NUM7[^\]]*\]/
NUMXR =

Number x var catcher regexp

/\[VAR NUM.[^\]]*\]/
BERRY =

Berry var catcher

[nil.to_s, nil.to_s, nil.to_s, nil.to_s, nil.to_s, nil.to_s, nil.to_s, '[VAR BERRY(0007)]']
COLOR =

Color var catcher

['[VAR COLOR(0000)]', '[VAR COLOR(0001)]', '[VAR COLOR(0002)]', '[VAR COLOR(0003)]']
LOCATION =

Location var catcher

[
  '[VAR LOCATION(0000)]', '[VAR LOCATION(0001)]', '[VAR LOCATION(0002)]',
  '[VAR LOCATION(0003)]', '[VAR LOCATION(0004)]'
]
ABILITY =

Ability var catcher

['[VAR ABILITY(0002)]', '[VAR ABILITY(0001)]', '[VAR ABILITY(0002)]']
KAPHOTICS_Clean =

Kaphotics decoded var clean regexp

/\[VAR [^\]]+\]/
NUMBRNCH_Reg =

Nummeric branch regexp catcher

/\[VAR NUMBRNCH\(....,....\)\][^\[]+/
GENDBR_Reg =

Gender branch regexp catcher

/\[VAR GENDBR\(....,....\)\][^\[]+/
BELL_Reg =

Bell detector

/\[VAR BE05\(([0-9]+)\)\]/
S_Empty =

Empty string (remove stuff)

nil.to_s
NBSP_B =

Non breaking space '!' detector

/ !/
NBSP_R =

Non breaking space '!' remplacement

' !'
Dot =

Automatic replacement of … with the correct char

['...', '']
Money =

Automatic replacement of the $ with a non breaking space $

[' $', ' $']
S_000 =

The \ temporary replacement

"\x00"
GameKeys =

The InGame key name to their key value association

{
  0 => 'KeyError', 'a' => :A, 'b' => :B, 'x' => :X, 'y' => :Y,
  'l' => :L, 'r' => :R, 'l2' => :L2, 'r2' => :R2, 'select' => :SELECT, 'start' => :START,
  'l3' => :L3, 'r3' => :R3, 'down' => :DOWN, 'left' => :LEFT,
  'right' => :RIGHT, 'up' => :UP, 'home' => :HOME
}

Class Method Summary collapse

Class Method Details

.define_const(obj)

Define generic constants adder to an object (Get var catcher easier)

Parameters:

  • obj (Class)

    the object that will receive constants



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 63

def define_const(obj)
  obj.const_set(:PKNICK, PKNICK)
  obj.const_set(:PKNAME, PKNAME)
  obj.const_set(:TRNAME, TRNAME)
  obj.const_set(:ITEM2, ITEM2)
  obj.const_set(:ITEMPLUR1, ITEMPLUR1)
  obj.const_set(:MOVE, MOVE)
  obj.const_set(:NUMB, NUMB)
  obj.const_set(:NUM3, NUM3)
  obj.const_set(:NUM2, NUM2)
  obj.const_set(:COLOR, COLOR)
  obj.const_set(:LOCATION, LOCATION)
  obj.const_set(:ABILITY, ABILITY)
  obj.const_set(:NUM7R, NUM7R)
  obj.const_set(:NUMXR, NUMXR)
end

.detect_dialog(text)

Detect a dialog text from message and return it instead of text

Parameters:



284
285
286
287
288
289
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 284

def detect_dialog(text)
  if (match = text.match(/^([0-9]+),( |)([0-9]+)/))
    text = Studio::Text.get_dialog_message(match[1].to_i, match[3].to_i)
  end
  return text
end

.enemy_pokemon?(pokemon) ⇒ Boolean

Detect if a Pokemon is an enemy Pokemon

Parameters:

Returns:

  • (Boolean)


113
114
115
116
117
118
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 113

def enemy_pokemon?(pokemon)
  return false unless pokemon
  return pokemon.bank != 0 if pokemon.is_a?(PFM::PokemonBattler)

  return pokemon.position.nil? || pokemon.position < 0
end

.get_key_name(name) ⇒ String

Return the real keyboard key name

Parameters:

  • name (String)

    the InGame key name

Returns:

  • (String)

    the keyboard key name



301
302
303
304
305
306
307
308
309
310
311
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 301

def get_key_name(name)
  key_id = GameKeys[name.downcase]
  return GameKeys[0] unless key_id
  key_value = Input::Keys[key_id][0]
  return "J#{-(key_value + 1) / 32 + 1}K#{(-key_value - 1) % 32}" if key_value < 0
  keybd = Input::Keyboard
  keybd.constants.each do |key_name|
    return key_name.to_s if keybd.const_get(key_name) == key_value
  end
  return GameKeys[0]
end

.parse(file_id, text_id, additionnal_var = nil) ⇒ String

Parse a text from the text database with specific informations

Parameters:

  • file_id (Integer)

    ID of the text file

  • text_id (Integer)

    ID of the text in the file

  • additionnal_var (nil, Hash{String => String}) (defaults to: nil)

    additional remplacements in the text

Returns:

  • (String)

    the text parsed and ready to be displayed



85
86
87
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 85

def parse(file_id, text_id, additionnal_var = nil)
  parse_with_pokemon(file_id, text_id, nil, additionnal_var)
end

.parse_gendbr(text)

Note:

Sorry for the code, when I did that I wasn't in the “clear” period ^^'

Parse the GENDBR (gender of the player, I didn't see other case)

Parameters:

  • text (String)

    text that will be parsed



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 199

def parse_gendbr(text)
  text.gsub!(GENDBR_Reg) do |s|
    quant = s.split(',')[1].to_i(16)
    ret = s.split(']')[1]
    if $trainer.playing_girl
      beg = quant & 0xFF
      len = quant >> 8
      end_position = beg + len
    else
      beg = 0
      len = quant & 0xFF
      end_position = len + (quant >> 8)
    end
    len2 = ret.size - end_position
    next(ret[beg, len] + ret[end_position, len2].to_s)
  end
end

.parse_numbrnch(text)

Note:

Sorry for the code, when I did that I wasn't in the “clear” period ^^'

Parse the NUMBRNCH (pural)

Parameters:

  • text (String)

    text that will be parsed



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 178

def parse_numbrnch(text)
  text.gsub!(NUMBRNCH_Reg) do |s|
    index, quant = s.split(',').collect { |element| element.to_i(16) }
    ret = s.split(']')[1]
    if @plural[index]
      beg = quant & 0xFF
      len = quant >> 8
      end_position = beg + len
    else
      beg = 0
      len = quant & 0xFF
      end_position = len + (quant >> 8)
    end
    len2 = ret.size - end_position
    next(ret[beg, len] + ret[end_position, len2].to_s)
  end
end

.parse_rest_of_thing(text)

Perform the rest of the automatic parse (factorization)

Parameters:

  • text (String)

    text that will be parsed



219
220
221
222
223
224
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 219

def parse_rest_of_thing(text)
  parse_numbrnch(text)
  parse_gendbr(text)
  text.gsub!(KAPHOTICS_Clean, S_Empty)
  text.gsub!(NBSP_B, NBSP_R)
end

.parse_string_for_messages(text) ⇒ String

Parse a string for a message

Parameters:

  • text (String)

    the message

Returns:

  • (String)

    the parsed message



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 260

def parse_string_for_messages(text)
  return text.dup if text.empty? # or text.frozen?

  # Detect dialog
  text = detect_dialog(text).dup
  # Gsub text
  text.gsub!(/\\\\/, S_000)
  text.gsub!(/\\v\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
  text.gsub!(/\\n\[([0-9]+)\]/i) { $game_actors[$1.to_i]&.name }
  text.gsub!(/\\p\[([0-9]+)\]/i) { $actors[$1.to_i - 1]&.name }
  text.gsub!(/\\k\[([^\]]+)\]/i) { get_key_name($1) }
  text.gsub!('\E') { $game_switches[Yuki::Sw::Gender] ? 'e' : nil }
  text.gsub!(/\\f\[([^\]]+)\]/i) { $1.split('§')[$game_switches[Yuki::Sw::Gender] ? 0 : 1] }
  text.gsub!(/\\t\[([0-9]+), *([0-9]+)\]/i) { ::PFM::Text.parse($1.to_i, $2.to_i) }
  # text.gsub!(NBSP_B, NBSP_R)
  text.gsub!(*Dot)
  text.gsub!(*Money)
  @variables.each { |expr, value| text.gsub!(expr, value) }
  text.gsub!(KAPHOTICS_Clean, S_Empty)
  return text
end

.parse_with_2pokemon(file_id, text_id, pokemon1, pokemon2, additionnal_var) ⇒ String

Parse a text from the text database with 2 pokemon & specific information

Parameters:

  • file_id (Integer)

    ID of the text file

  • text_id (Integer)

    ID of the text in the file

  • pokemon1 (PFM::Pokemon)

    pokemon we're talking about

  • pokemon2 (PFM::Pokemon)

    pokemon who originated the “problem” (eg. bind)

  • additionnal_var (nil, Hash{String => String})

    additional remplacements in the text

Returns:

  • (String)

    the text parsed and ready to be displayed



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 127

def parse_with_2pokemon(file_id, text_id, pokemon1, pokemon2, additionnal_var)
  if enemy_pokemon?(pokemon1)
    text_id += $game_temp.trainer_battle ? 5 : 3
    text_id += 1 if enemy_pokemon?(pokemon2)
  elsif enemy_pokemon?(pokemon2)
    text_id += ($game_temp.trainer_battle ? 2 : 1)
  end
  # Get text
  text = Studio::Text.get(file_id, text_id).clone
  # Parse all the variables
  additionnal_var&.each { |expr, value| text.gsub!(expr, value || '<nil>') }
  @variables.each { |expr, value| text.gsub!(expr, value) }
  # Set the Pokemon nickname
  text.gsub!(PKNICK[0], pokemon1.given_name)
  text.gsub!(PKNICK[1], pokemon2.given_name)
  # Parse the branches & clean the text
  parse_rest_of_thing(text)
  return text
end

.parse_with_pokemon(file_id, text_id, pokemon, additionnal_var = nil) ⇒ String

Parse a text from the text database with specific informations and a pokemon

Parameters:

  • file_id (Integer)

    ID of the text file

  • text_id (Integer)

    ID of the text in the file

  • pokemon (PFM::Pokemon)

    pokemon that will introduce an offset on text_id (its name is also used)

  • additionnal_var (nil, Hash{String => String}) (defaults to: nil)

    additional remplacements in the text

Returns:

  • (String)

    the text parsed and ready to be displayed



95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 95

def parse_with_pokemon(file_id, text_id, pokemon, additionnal_var = nil)
  # Text id adjustment
  text_id += ($game_temp.trainer_battle ? 2 : 1) if enemy_pokemon?(pokemon)
  # Get text
  text = Studio::Text.get(file_id, text_id).clone
  # Parse all the variables
  additionnal_var&.each { |expr, value| text.gsub!(expr, value || '<nil>') }
  @variables.each { |expr, value| text.gsub!(expr, value) }
  # Set the Pokemon nickname
  text.gsub!(PKNICK[0], pokemon.given_name) if pokemon
  # Parse the branches & clean the text
  parse_rest_of_thing(text)
  return text
end

.parse_with_pokemons(file_id, text_id, pokemon, pokemon2, additionnal_var = nil) ⇒ String

Parse a text from the text database with specific informations and two Pokemon

Parameters:

  • file_id (Integer)

    ID of the text file

  • text_id (Integer)

    ID of the text in the file

  • pokemon (PFM::Pokemon)

    pokemon that will introduce an offset on text_id (its name is also used)

  • pokemon2 (PFM::Pokemon)

    second pokemon that will introduce an offset on text_id (its name is also used)

  • additionnal_var (nil, Hash{String => String}) (defaults to: nil)

    additional remplacements in the text

Returns:

  • (String)

    the text parsed and ready to be displayed



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 154

def parse_with_pokemons(file_id, text_id, pokemon, pokemon2, additionnal_var = nil)
  # Text id adjustment
  if enemy_pokemon?(pokemon)
    text_id += ($game_temp.trainer_battle ? 5 : 3)
    text_id += 1 if enemy_pokemon?(pokemon2)
  elsif enemy_pokemon?(pokemon2)
    text_id += ($game_temp.trainer_battle ? 2 : 1)
  end
  # Get text
  text = ::Studio::Text.get(file_id, text_id).clone
  # Parse all the variables
  additionnal_var&.each { |expr, value| text.gsub!(expr, value || '<nil>') }
  @variables.each { |expr, value| text.gsub!(expr, value) }
  # Set the Pokemon nickname
  text.gsub!(PKNICK[0], pokemon.given_name) if pokemon
  text.gsub!(PKNICK[1], pokemon2.given_name) if pokemon2
  # Parse the branches & clean the text
  parse_rest_of_thing(text)
  return text
end

.reset_variables

Remove every automatic var catcher defined



240
241
242
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 240

def reset_variables
  @variables.clear
end

.set_ability_name(value, index = 0)

Set the ability name variable

Parameters:



348
349
350
351
352
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 348

def set_ability_name(value, index = 0)
  value = data_ability(value).name if value.is_a?(Symbol) || value.is_a?(Integer)
  value = value.ability_name if value.is_a?(PFM::Pokemon)
  set_variable(ABILITY[index].to_s, value.to_s)
end

.set_item_name(value, index = 0)

Set the item name variable

Parameters:



332
333
334
335
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 332

def set_item_name(value, index = 0)
  value = data_item(value).name if value.is_a?(Integer) || value.is_a?(Symbol)
  set_variable(ITEM2[index].to_s, value.to_s)
end

.set_move_name(value, index = 0)

Set the move name variable

Parameters:



340
341
342
343
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 340

def set_move_name(value, index = 0)
  value = data_move(value).name if value.is_a?(Integer) || value.is_a?(Symbol)
  set_variable(MOVE[index].to_s, value.to_s)
end

.set_num1(value, index = 1)

Set the number1 variable

Parameters:



357
358
359
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 357

def set_num1(value, index = 1)
  set_variable(NUMB[index].to_s, value.to_s)
end

.set_num2(value, index = 0)

Set the number2 variable

Parameters:



364
365
366
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 364

def set_num2(value, index = 0)
  set_variable(NUM2[index].to_s, value.to_s)
end

.set_num3(value, index = 0)

Set the number2 variable

Parameters:



371
372
373
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 371

def set_num3(value, index = 0)
  set_variable(NUM3[index].to_s, value.to_s)
end

.set_pkname(value, index = 0)

Set the Pokemon Name variable

Parameters:



316
317
318
319
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 316

def set_pkname(value, index = 0)
  value = value.name if value.is_a?(PFM::Pokemon)
  set_variable(PKNAME[index].to_s, value.to_s)
end

.set_pknick(value, index = 0)

Set the Pokemon Nickname variable

Parameters:



324
325
326
327
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 324

def set_pknick(value, index = 0)
  value = value.given_name if value.is_a?(PFM::Pokemon)
  set_variable(PKNICK[index].to_s, value.to_s)
end

.set_plural(value_or_index = true, value = true)

Set the numbranches to plural state

Parameters:

  • value_or_index (Integer, Boolean) (defaults to: true)

    the value for all branch or the index you want to set in pural

  • value (Boolean) (defaults to: true)

    the value when you choosed an index



247
248
249
250
251
252
253
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 247

def set_plural(value_or_index = true, value = true)
  if value_or_index.is_a?(Integer)
    @plural[value_or_index] = value
  else
    @plural.collect! { value_or_index }
  end
end

.set_variable(expr, value)

Define an automatic var catcher with its value

Parameters:

  • expr (String, Regexp)

    the var catcher that is replaced by the value

  • value (String)

    the value that replace the expr



229
230
231
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 229

def set_variable(expr, value)
  @variables[expr] = value.to_s.force_encoding(Encoding::UTF_8)
end

.unset_variable(expr)

Remove an automatic var catcher with its value

Parameters:

  • expr (String, Regexp)

    the var catcher that is replaced by a value



235
236
237
# File 'scripts/01450 Systems/00000 General/00001 PFM/00200 Helpers/00100 Text.rb', line 235

def unset_variable(expr)
  @variables.delete(expr)
end