Module: Lich::Gemstone::Enhancive

Defined in:
documented/attributes/enhancive.rb

Constant Summary collapse

STATS =

Stats - all 10 stats including influence Stats - all 10 stats including influence.

Examples:

Lich::Gemstone::Enhancive::STATS
# => [:strength, :constitution, :dexterity, :agility, :discipline, :aura, :logic, :intuition, :wisdom, :influence]
%i[strength constitution dexterity agility discipline aura logic intuition wisdom influence].freeze
STAT_ABBREV =
{
  'STR' => :strength, 'CON' => :constitution, 'DEX' => :dexterity,
  'AGI' => :agility, 'DIS' => :discipline, 'AUR' => :aura,
  'LOG' => :logic, 'INT' => :intuition, 'WIS' => :wisdom,
  'INF' => :influence
}.freeze
STAT_CAP =
40
BONUS_SKILLS =

Skills that appear as "Bonus" in output (same as Skills module list)

%i[
  two_weapon_combat armor_use shield_use combat_maneuvers edged_weapons
  blunt_weapons two_handed_weapons ranged_weapons thrown_weapons polearm_weapons
  brawling ambush multi_opponent_combat physical_fitness dodging arcane_symbols
  magic_item_use spell_aiming harness_power elemental_mana_control mental_mana_control
  spirit_mana_control elemental_lore_air elemental_lore_earth elemental_lore_fire
  elemental_lore_water spiritual_lore_blessings spiritual_lore_religion
  spiritual_lore_summoning sorcerous_lore_demonology sorcerous_lore_necromancy
  mental_lore_divination mental_lore_manipulation mental_lore_telepathy
  mental_lore_transference mental_lore_transformation survival disarming_traps
  picking_locks stalking_and_hiding perception climbing swimming first_aid
  trading pickpocketing
].freeze
SKILL_CAP =
50
RESOURCES =

Resources Resources available in the game.

Examples:

Lich::Gemstone::Enhancive::RESOURCES
# => [:max_mana, :max_health, :max_stamina, :mana_recovery, :stamina_recovery]
%i[max_mana max_health max_stamina mana_recovery stamina_recovery].freeze
RESOURCE_CAPS =
{
  max_mana: 600, max_health: 300, max_stamina: 300,
  mana_recovery: 50, stamina_recovery: 50
}.freeze
SKILL_NAME_MAP =

Mapping from game output names to internal names Mapping from game output names to internal names.

Examples:

Lich::Gemstone::Enhancive::SKILL_NAME_MAP['Two Weapon Combat']
# => :two_weapon_combat
{
  'Two Weapon Combat'            => :two_weapon_combat,
  'Armor Use'                    => :armor_use,
  'Shield Use'                   => :shield_use,
  'Combat Maneuvers'             => :combat_maneuvers,
  'Edged Weapons'                => :edged_weapons,
  'Blunt Weapons'                => :blunt_weapons,
  'Two-Handed Weapons'           => :two_handed_weapons,
  'Ranged Weapons'               => :ranged_weapons,
  'Thrown Weapons'               => :thrown_weapons,
  'Polearm Weapons'              => :polearm_weapons,
  'Brawling'                     => :brawling,
  'Ambush'                       => :ambush,
  'Multi Opponent Combat'        => :multi_opponent_combat,
  'Physical Fitness'             => :physical_fitness,
  'Dodging'                      => :dodging,
  'Arcane Symbols'               => :arcane_symbols,
  'Magic Item Use'               => :magic_item_use,
  'Spell Aiming'                 => :spell_aiming,
  'Harness Power'                => :harness_power,
  'Elemental Mana Control'       => :elemental_mana_control,
  'Mental Mana Control'          => :mental_mana_control,
  'Spirit Mana Control'          => :spirit_mana_control,
  'Elemental Lore - Air'         => :elemental_lore_air,
  'Elemental Lore - Earth'       => :elemental_lore_earth,
  'Elemental Lore - Fire'        => :elemental_lore_fire,
  'Elemental Lore - Water'       => :elemental_lore_water,
  'Spiritual Lore - Blessings'   => :spiritual_lore_blessings,
  'Spiritual Lore - Religion'    => :spiritual_lore_religion,
  'Spiritual Lore - Summoning'   => :spiritual_lore_summoning,
  'Sorcerous Lore - Demonology'  => :sorcerous_lore_demonology,
  'Sorcerous Lore - Necromancy'  => :sorcerous_lore_necromancy,
  'Mental Lore - Divination'     => :mental_lore_divination,
  'Mental Lore - Manipulation'   => :mental_lore_manipulation,
  'Mental Lore - Telepathy'      => :mental_lore_telepathy,
  'Mental Lore - Transference'   => :mental_lore_transference,
  'Mental Lore - Transformation' => :mental_lore_transformation,
  'Survival'                     => :survival,
  'Disarming Traps'              => :disarming_traps,
  'Picking Locks'                => :picking_locks,
  'Stalking and Hiding'          => :stalking_and_hiding,
  'Perception'                   => :perception,
  'Climbing'                     => :climbing,
  'Swimming'                     => :swimming,
  'First Aid'                    => :first_aid,
  'Trading'                      => :trading,
  'Pickpocketing'                => :pickpocketing
}.freeze
RESOURCE_NAME_MAP =

Mapping from game output resource names to internal names.

Examples:

Lich::Gemstone::Enhancive::RESOURCE_NAME_MAP['Max Mana']
# => :max_mana
{
  'Max Mana'         => :max_mana,
  'Max Health'       => :max_health,
  'Max Stamina'      => :max_stamina,
  'Mana Recovery'    => :mana_recovery,
  'Stamina Recovery' => :stamina_recovery
}.freeze
MARTIAL_SKILL_CAP =

Martial Knowledge Skills (CMan-based enhancives) These appear as "+X ranks" in the output rather than bonus format Derived dynamically from CMan module at runtime to stay DRY

5
MARTIAL_SPECIAL_NAMES =

Special display name mappings for CMan skills with apostrophes These can't be auto-generated from the symbol name

{
  :acrobats_leap       => "Acrobat's Leap",
  :executioners_stance => "Executioner's Stance",
  :griffins_voice      => "Griffin's Voice",
  :predators_eye       => "Predator's Eye"
}.freeze

Class Method Summary collapse

Class Method Details

.active?Boolean

Returns:

  • (Boolean)


310
311
312
# File 'documented/attributes/enhancive.rb', line 310

def self.active?
  Infomon.get("enhancive.active") == true
end

.active_last_updatedObject



314
315
316
317
# File 'documented/attributes/enhancive.rb', line 314

def self.active_last_updated
  timestamp = Infomon.get_updated_at("enhancive.active")
  timestamp ? Time.at(timestamp) : nil
end

.healthObject



279
280
281
# File 'documented/attributes/enhancive.rb', line 279

def self.health
  max_health
end

.item_countObject



298
299
300
# File 'documented/attributes/enhancive.rb', line 298

def self.item_count
  Infomon.get("enhancive.stats.item_count").to_i
end

.knows_spell?(spell_num) ⇒ Boolean

Returns:

  • (Boolean)


294
295
296
# File 'documented/attributes/enhancive.rb', line 294

def self.knows_spell?(spell_num)
  spells.include?(spell_num.to_i)
end

.last_updatedObject



323
324
325
326
# File 'documented/attributes/enhancive.rb', line 323

def self.last_updated
  timestamp = Infomon.get_updated_at("enhancive.stats.item_count")
  timestamp ? Time.at(timestamp) : nil
end

.manaObject



275
276
277
# File 'documented/attributes/enhancive.rb', line 275

def self.mana
  max_mana
end

.martial_display_to_symbol(display_name) ⇒ Symbol

Converts a martial skill display name to its symbol.

Examples:

Lich::Gemstone::Enhancive.martial_display_to_symbol("Acrobat's Leap")
# => :acrobats_leap

Parameters:

  • display_name (String)

    the display name of the martial skill.

Returns:

  • (Symbol)

    the corresponding martial skill symbol.



153
154
155
156
157
158
159
160
# File 'documented/attributes/enhancive.rb', line 153

def self.martial_display_to_symbol(display_name)
  # Check special names first (reverse lookup)
  special = MARTIAL_SPECIAL_NAMES.key(display_name)
  return special if special

  # Standard conversion: lowercase, replace spaces with underscores
  display_name.downcase.gsub(' ', '_').to_sym
end

.martial_skill(skill_symbol) ⇒ Object



263
264
265
266
267
268
# File 'documented/attributes/enhancive.rb', line 263

def self.martial_skill(skill_symbol)
  OpenStruct.new(
    ranks: Infomon.get("enhancive.martial.#{skill_symbol}").to_i,
    cap: MARTIAL_SKILL_CAP
  )
end

.martial_skillsObject



270
271
272
273
# File 'documented/attributes/enhancive.rb', line 270

def self.martial_skills
  martial_skills_list.select { |s| martial_skill(s).ranks > 0 }
                     .map { |s| { name: s, ranks: martial_skill(s).ranks } }
end

.martial_skills_listArray<Symbol>

Returns a list of martial skills defined in the CMan module.

Examples:

Lich::Gemstone::Enhancive.martial_skills_list
# => [:two_weapon_combat, :armor_use, ...]

Returns:

  • (Array<Symbol>)

    an array of martial skill symbols.



168
169
170
171
172
# File 'documented/attributes/enhancive.rb', line 168

def self.martial_skills_list
  return [] unless defined?(Lich::Gemstone::CMan)

  Lich::Gemstone::CMan.cman_lookups.map { |cman| cman[:long_name].to_sym }
end

.martial_symbol_to_display(symbol) ⇒ String

Converts a martial skill symbol to its display name.

Examples:

Lich::Gemstone::Enhancive.martial_symbol_to_display(:acrobats_leap)
# => "Acrobat's Leap"

Parameters:

  • symbol (Symbol)

    the martial skill symbol to convert.

Returns:

  • (String)

    the display name of the martial skill.



140
141
142
143
144
# File 'documented/attributes/enhancive.rb', line 140

def self.martial_symbol_to_display(symbol)
  return MARTIAL_SPECIAL_NAMES[symbol] if MARTIAL_SPECIAL_NAMES.key?(symbol)

  symbol.to_s.split('_').map(&:capitalize).join(' ')
end

.over_cap_skillsObject



355
356
357
# File 'documented/attributes/enhancive.rb', line 355

def self.over_cap_skills
  BONUS_SKILLS.select { |s| skill_over_cap?(s) rescue false }
end

.over_cap_statsObject



351
352
353
# File 'documented/attributes/enhancive.rb', line 351

def self.over_cap_stats
  STATS.select { |s| stat_over_cap?(s) }
end

.pausesObject



319
320
321
# File 'documented/attributes/enhancive.rb', line 319

def self.pauses
  Infomon.get("enhancive.pauses").to_i
end

.property_countObject



302
303
304
# File 'documented/attributes/enhancive.rb', line 302

def self.property_count
  Infomon.get("enhancive.stats.property_count").to_i
end

.refresh(silent: false, quiet: true) ⇒ void

This method returns an undefined value.

Refreshes the enhancive data from the game.

Examples:

Lich::Gemstone::Enhancive.refresh
# => Refreshes the data without output.

Parameters:

  • silent (Boolean) (defaults to: false)

    whether to suppress output messages (default: false).

  • quiet (Boolean) (defaults to: true)

    whether to suppress all output (default: true).



367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'documented/attributes/enhancive.rb', line 367

def self.refresh(silent: false, quiet: true)
  respond "Refreshing enhancive data..." unless quiet
  # First get status (active state + pauses)
  Lich::Util.issue_command(
    "invento enh",
    /^You are (?:currently|not currently|now|already|no longer)/,
    /<prompt/,
    include_end: true, timeout: 5, silent: silent, usexml: true, quiet: quiet
  )
  # Then get full totals
  # TODO: Update start pattern once GM adds proper start message to invento enhancive totals
  # Current pattern is fragile - if player has no stat enhancives, output starts with Skills/Resources
  Lich::Util.issue_command(
    "invento enhancive totals",
    /^<pushBold\/>(?:Stats:|Skills:|Resources:)|^No enhancive item bonuses found\./,
    /<prompt/,
    include_end: true, timeout: 5, silent: silent, usexml: true, quiet: quiet
  )
  respond "Enhancive data refreshed." unless quiet
end

.refresh_status(silent: false, quiet: true) ⇒ void

This method returns an undefined value.

Refreshes the current status of enhancive data.

Examples:

Lich::Gemstone::Enhancive.refresh_status
# => Refreshes the status without output.

Parameters:

  • silent (Boolean) (defaults to: false)

    whether to suppress output messages (default: false).

  • quiet (Boolean) (defaults to: true)

    whether to suppress all output (default: true).



396
397
398
399
400
401
402
403
# File 'documented/attributes/enhancive.rb', line 396

def self.refresh_status(silent: false, quiet: true)
  Lich::Util.issue_command(
    "invento enh",
    /^You are (?:currently|not currently|now|already|no longer)/,
    /<prompt/,
    include_end: true, timeout: 5, silent: silent, usexml: true, quiet: quiet
  )
end

.reset_allvoid

This method returns an undefined value.

Resets all stats, skills, resources, and spells to their initial values.

Examples:

Lich::Gemstone::Enhancive.reset_all
# => Resets all enhancive data.


411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
# File 'documented/attributes/enhancive.rb', line 411

def self.reset_all
  batch = []

  # Reset all stats to 0
  STATS.each do |stat|
    batch.push(["enhancive.stat.#{stat}", 0])
  end

  # Reset all skills to 0
  BONUS_SKILLS.each do |skill|
    batch.push(["enhancive.skill.#{skill}.ranks", 0])
    batch.push(["enhancive.skill.#{skill}.bonus", 0])
  end

  # Reset all resources to 0
  RESOURCES.each do |resource|
    batch.push(["enhancive.resource.#{resource}", 0])
  end

  # Reset all martial knowledge skills to 0
  # Uses CMan module to get full list of possible martial skills
  martial_skills_list.each do |skill|
    batch.push(["enhancive.martial.#{skill}", 0])
  end

  # Reset spells to empty array
  batch.push(["enhancive.spells", ""])

  # Reset statistics to 0
  batch.push(["enhancive.stats.item_count", 0])
  batch.push(["enhancive.stats.property_count", 0])
  batch.push(["enhancive.stats.total_amount", 0])

  Infomon.upsert_batch(batch)
end

.skill_over_cap?(skill) ⇒ Boolean

Checks if a given skill is over its cap.

Examples:

Lich::Gemstone::Enhancive.skill_over_cap?(:two_weapon_combat)
# => true or false

Parameters:

  • skill (Symbol)

    the skill to check.

Returns:

  • (Boolean)

    true if the skill is over cap, false otherwise.



346
347
348
349
# File 'documented/attributes/enhancive.rb', line 346

def self.skill_over_cap?(skill)
  s = send(skill)
  s.bonus > SKILL_CAP
end

.spellsObject



287
288
289
290
291
292
# File 'documented/attributes/enhancive.rb', line 287

def self.spells
  raw = Infomon.get("enhancive.spells")
  return [] if raw.nil? || raw.empty?

  raw.to_s.split(',').map(&:to_i)
end

.staminaObject



283
284
285
# File 'documented/attributes/enhancive.rb', line 283

def self.stamina
  max_stamina
end

.stat_over_cap?(stat) ⇒ Boolean

Checks if a given stat is over its cap.

Examples:

Lich::Gemstone::Enhancive.stat_over_cap?(:strength)
# => true or false

Parameters:

  • stat (Symbol)

    the stat to check.

Returns:

  • (Boolean)

    true if the stat is over cap, false otherwise.



335
336
337
# File 'documented/attributes/enhancive.rb', line 335

def self.stat_over_cap?(stat)
  send(stat).value > STAT_CAP
end

.total_amountObject



306
307
308
# File 'documented/attributes/enhancive.rb', line 306

def self.total_amount
  Infomon.get("enhancive.stats.total_amount").to_i
end