Module: Lich::Gemstone::Combat::Definitions::Resolutions

Defined in:
documented/gemstone/combat/defs/outcomes.rb

Overview

Parses combat resolution (roll) lines - the numeric line that decides an attack (AS/DS, CS/TD, UAF/UDF, SMR/SSR, and friends) - into a typed hash of its components.

Defined Under Namespace

Classes: ResolutionDef

Constant Summary collapse

RESOLUTION_DEFS =

All resolution definitions, in match-priority order.

Returns:

[
  ResolutionDef.new(:as_ds, [
    # optional "+ N +" term = True Strike bonus; the die is not
    # always d100 there either (d80, d40 at higher tiers)
    /AS: (?<as>[+\-\d]+) vs DS: (?<ds>[+\-\d]+) with AvD: (?<avd>[+\-\d]+) \+ (?:(?<bonus>\d+) \+ )?d\d+ roll: (?<roll>[+\-\d]+) = (?<result>[+\-\d]+)/
  ].freeze),
  ResolutionDef.new(:cs_td, [
    /CS: (?<cs>[+\-\d]+) - TD: (?<td>[+\-\d]+) \+ CvA: (?<cva>[+\-\d]+) \+ d\d+: (?<roll>[+\-\d]+) \+ Bonus: (?<bonus>[+\-\d]+) == (?<result>[+\-\d]+)/,
    # trailing "- N" modifier (Torment 718, Untrammel 209, Vertigo 1219)
    /CS: (?<cs>[+\-\d]+) - TD: (?<td>[+\-\d]+) \+ CvA: (?<cva>[+\-\d]+) \+ d\d+: (?<roll>[+\-\d]+)(?: - (?<penalty>[+\-\d]+))? == (?<result>[+\-\d]+)/
  ].freeze),
  ResolutionDef.new(:uaf_udf, [
    /UAF: (?<uaf>\d+) vs UDF: (?<udf>\d+) = (?<total>[.\d]+) \* MM: (?<mm>\d+) \+ d\d+: (?<roll>\d+) = (?<result>\d+)/
  ].freeze),
  ResolutionDef.new(:smr, [
    # Penalty term and negative results are both live (Rysk logs)
    /\[SMR result: (?<result>-?\d+) \(Open d100: (?<roll>[+\-\d]+)(?:, Bonus: (?<bonus>[+\-\d]+))?(?:, Penalt(?:y|ies): (?<penalty>[+\-\d]+))?\)\]/
  ].freeze),
  # Standard Save Roll - follows intimidation/terrorize checks
  ResolutionDef.new(:ssr, [
    /\[SSR result: (?<result>-?\d+) \(Open d100: (?<roll>[+\-\d]+)\)\]/
  ].freeze),
  # Imbed/crystal activation roll - sits between a wand wave and
  # its spell cast ("1d100: 30 + Modifiers: 375 == 405"); gives
  # the otherwise fact-less :wand event its roll (round-6, from
  # the fury/divine_fury real-feed capture)
  ResolutionDef.new(:activation, [
    /1d100: (?<roll>[+\-\d]+) \+ Modifiers: (?<mods>[+\-\d]+) == (?<result>[+\-\d]+)/
  ].freeze),
  # Legacy maneuver roll (lowercase "open", no SMR prefix). Most
  # cmans were converted to SMR but the old format is kept as a
  # fallback - it costs one gate literal and catches stragglers.
  ResolutionDef.new(:maneuver_roll, [
    /\[Roll result: (?<result>-?\d+) \(open d100: (?<roll>-?\d+)\)(?:,? (?:Bonus: (?<bonus>-?\d+)|Penalt(?:y|ies): (?<penalty>-?\d+)))?\]/
  ].freeze),
  # Fear resolution (Sheer fear) - its own roll grammar entirely
  ResolutionDef.new(:fear, [
    /FS: (?<fs>[+\-\d]+) - FD: (?<fd>[+\-\d]+) \+ FvP: (?<fvp>[+\-\d]+) \+ d100\(L\): (?<roll>[+\-\d]+) = (?<result>[+\-\d]+)/
  ].freeze)
].freeze
RESOLUTION_LOOKUP =

Flattened [pattern, type] pairs in definition order.

Returns:

  • (Array<Array(Regexp, Symbol)>)
RESOLUTION_DEFS.flat_map { |d| d.patterns.map { |rx| [rx, d.type] } }.freeze

Class Method Summary collapse

Class Method Details

.parse(line) ⇒ Hash?

Parses a single roll line into its numeric components.

Parameters:

  • line (String) —

    one line of game text

Returns:

  • (Hash, nil) —

    { type: :as_ds, as: 739, ds: 376, ..., result: 469 } with every named capture converted to Integer (total, which can be fractional in UCS, converts to Float when it contains a dot), or nil when the line is not a resolution line



392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# File 'documented/gemstone/combat/defs/outcomes.rb', line 392

def self.parse(line)
  return nil unless GATE.match?(line) || ALWAYS_SCAN.any? { |rx| rx.match?(line) }

  RESOLUTION_LOOKUP.each do |rx, type|
    next unless (match = rx.match(line))

    result = { type: type }
    match.names.each do |cap|
      next unless match[cap]

      result[cap.to_sym] = match[cap].include?('.') ? match[cap].to_f : match[cap].to_i
    end
    return result
  end
  nil
end