Module: Lich::Gemstone::CritRanks
- Defined in:
- documented/gemstone/critranks.rb
Overview
Resolves critical hits from combat messages into their mechanical results.
Queries critical hit tables loaded from lib/crit_tables/*.rb files and provides methods to parse incoming damage text, look up critical effects by type/location/rank, and reload table data on demand.
Class Method Summary collapse
-
.clean_key(key) ⇒ Integer, ...
Normalizes a key for lookup: integers stay as-is; symbols and strings are downcased and whitespace/hyphens converted to underscores.
-
.create_indices ⇒ Object
Builds the pattern indices.
-
.fetch(type, location, rank) ⇒ Hash?
Looks up a critical hit record by type, location, and rank.
-
.init ⇒ void
private
Loads all critical hit table files from the critranks directory.
-
.locations ⇒ Array
Returns a list of all body locations in the loaded tables.
-
.parse(line) ⇒ Hash
Matches a damage line against all loaded critical patterns and returns matching records.
-
.ranks ⇒ Array
Returns a list of all critical severity ranks in the loaded tables.
-
.reload! ⇒ void
private
Clears all loaded critical hit tables and reloads them from disk.
-
.table ⇒ Hash
Returns the in-memory critical hit table hash.
-
.tables ⇒ Array<String>
Returns a list of loaded critical table names, with namespace separators removed.
-
.types ⇒ Array
Returns a list of all critical hit types in the loaded tables.
-
.validate(key, valid) ⇒ Integer, ...
Normalizes a key and checks it against a list of valid options.
Class Method Details
.clean_key(key) ⇒ Integer, ...
Normalizes a key for lookup: integers stay as-is; symbols and strings are downcased and whitespace/hyphens converted to underscores.
107 108 109 110 111 112 |
# File 'documented/gemstone/critranks.rb', line 107 def self.clean_key(key) return key.to_i if key.is_a?(Integer) || key =~ (/^\d+$/) return key.downcase if key.is_a?(Symbol) key.strip.downcase.gsub(/[ -]/, '_') end |
.create_indices ⇒ Object
Builds the pattern indices. Tolerates nil location/rank rows in the table data (some tables carry explicit nil placeholders); a nil row means that crit is simply unrecognized rather than a load failure.
Patterns are indexed by the leading literal word of their (anchored) regex, so parse only has to test the handful of patterns that could possibly match a given line instead of all ~2400. Patterns that are not ^-anchored to a literal word are kept in a small residual list that is always checked.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'documented/gemstone/critranks.rb', line 141 def self.create_indices @index_buckets = Hash.new { |hash, key| hash[key] = [] } @index_residual = [] @critical_table.each do |type, typedata| @types.append(type) typedata.each do |loc, locdata| @locations.append(loc) unless @locations.include?(loc) next if locdata.nil? locdata.each do |rank, record| @ranks.append(rank) unless @ranks.include?(rank) next if record.nil? || record[:regex].nil? source = record[:regex].source if source.start_with?('^') && (first_word = source[1..].match(/\A([A-Za-z']+)\b/)) @index_buckets[first_word[1].downcase].push(record) else @index_residual.push(record) end end end end @index_buckets.each_value(&:freeze) @index_buckets.default = nil # drop the auto-vivifying default proc @index_buckets.freeze @index_residual.freeze end |
.fetch(type, location, rank) ⇒ Hash?
Looks up a critical hit record by type, location, and rank.
Validates all three arguments, then digs into the critical table. On any error, logs the error and returns nil.
197 198 199 200 201 202 203 204 205 |
# File 'documented/gemstone/critranks.rb', line 197 def self.fetch(type, location, rank) table.dig( validate(type, types), validate(location, locations), validate(rank, ranks) ) rescue StandardError => e Lich::Messaging.msg('error', "Error! #{e}") end |
.init ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Loads all critical hit table files from the critranks directory.
This is a no-op if tables are already loaded. Automatically called at module
load time and may be called again after .reload!. Uses load instead of
require to ensure reload can re-run the table definitions.
37 38 39 40 41 42 43 44 45 |
# File 'documented/gemstone/critranks.rb', line 37 def self.init return unless @critical_table.empty? Dir.glob("#{File.join(LIB_DIR, "gemstone", "critranks", "*critical_table.rb")}").each do |file| # load, not require: require makes reload! a no-op (already-required # table files never re-run, leaving the emptied table empty forever) load file end create_indices end |
.locations ⇒ Array
Returns a list of all body locations in the loaded tables.
87 88 89 |
# File 'documented/gemstone/critranks.rb', line 87 def self.locations @locations end |
.parse(line) ⇒ Hash
Matches a damage line against all loaded critical patterns and returns matching records.
Extracts the leading word from the line to index into a bucket of candidate patterns, then tests all candidates (plus residual non-anchored patterns) for a match. Returns a hash mapping matching Regexp objects to their record definitions.
177 178 179 180 181 182 183 184 |
# File 'documented/gemstone/critranks.rb', line 177 def self.parse(line) stripped = line.strip # need to strip spaces to support anchored regex in tables first_word = stripped[/\A[A-Za-z']+/]&.downcase candidates = @index_buckets.fetch(first_word, nil) ? @index_buckets[first_word] + @index_residual : @index_residual candidates.each_with_object({}) do |record, matches| matches[record[:regex]] = record if record[:regex] =~ stripped end end |
.ranks ⇒ Array
Returns a list of all critical severity ranks in the loaded tables.
94 95 96 |
# File 'documented/gemstone/critranks.rb', line 94 def self.ranks @ranks end |
.reload! ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Clears all loaded critical hit tables and reloads them from disk.
58 59 60 61 62 63 64 |
# File 'documented/gemstone/critranks.rb', line 58 def self.reload! @critical_table = {} @types = [] @locations = [] @ranks = [] init end |
.table ⇒ Hash
Returns the in-memory critical hit table hash.
50 51 52 |
# File 'documented/gemstone/critranks.rb', line 50 def self.table @critical_table end |
.tables ⇒ Array<String>
Returns a list of loaded critical table names, with namespace separators removed.
69 70 71 72 73 74 75 |
# File 'documented/gemstone/critranks.rb', line 69 def self.tables @tables = [] @types.each do |type| @tables.push(type.to_s.gsub(':', '')) end @tables end |
.types ⇒ Array
Returns a list of all critical hit types in the loaded tables.
80 81 82 |
# File 'documented/gemstone/critranks.rb', line 80 def self.types @types end |
.validate(key, valid) ⇒ Integer, ...
Normalizes a key and checks it against a list of valid options.
Raises an exception if the cleaned key is not found in the valid list.
125 126 127 128 129 130 |
# File 'documented/gemstone/critranks.rb', line 125 def self.validate(key, valid) clean = clean_key(key) raise "Invalid key '#{key}', expecting one of #{valid.join(',')}" unless valid.include?(clean) clean end |