Module: Lich::Gemstone::Combat::Tracker
- Defined in:
- documented/gemstone/combat/tracker.rb
Overview
Combat tracking system
Main interface for the combat tracking system. Integrates with Lich's downstream hooks to process game output and track combat events.
Features:
- Damage tracking and HP estimation
- Wound/injury tracking by body part
- Status effect tracking with auto-expiration
- UCS (Unarmed Combat System) support
- Async processing for performance
- Automatic creature registry cleanup
Constant Summary collapse
- DEFAULT_SETTINGS =
Default settings for combat tracking
{ enabled: false, # Disabled by default, user must enable track_damage: true, track_wounds: true, track_statuses: true, track_ucs: true, # Track UCS (position, tierup, smite) emit_attacks: false, # Emit whole parsed events (:attack blob) for recorder-class subscribers max_threads: 2, # Keep threading for performance debug: false, buffer_size: 200, # Increase for large combat chunks fallback_max_hp: 350, # Default max HP when template unavailable cleanup_interval: 100, # Cleanup creature registry every N chunks cleanup_max_age: 600 # Remove creatures older than N seconds (10 minutes) }.freeze
- DEBUG_LEVELS =
Debug levels, in the order they were introduced.
trueis kept as an alias for :verbose so settings saved before levels existed still resolve. %i[summary verbose].freeze
- COMBAT_RELEVANT_PATTERN =
Single compiled filter for combat-relevant content. One regex scan replaces ~11 include? calls plus a regex per line; alternation of literals compiles to an efficient multi-substring search.
Regexp.union( 'points of damage', ' damage!', # roll-based short form ("... 6 damage!") # has no "points of" - chunks holding # only these were dropped entirely '<pushBold/>', # Creatures '**', # Flares 'AS:', # Attack rolls 'swing', 'thrust', 'cast', 'gesture', 'positioning against', # UCS position 'vulnerable to a followup', # UCS tierup 'crimson mist' # UCS smite ).freeze
- COMBAT_RESOLUTION_PATTERN =
Pattern matching combat resolution outcomes: hit, miss, parry, block, or dodge.
Case-insensitive word-boundary match used to detect attack resolution lines in game output when the full COMBAT_RELEVANT_PATTERN is too broad.
/\b(?:hit|miss|parr|block|dodge)\b/i.freeze
Class Attribute Summary collapse
-
.buffer ⇒ Object
readonly
Returns the value of attribute buffer.
-
.settings ⇒ Object
readonly
Returns the value of attribute settings.
Class Method Summary collapse
-
.combat_relevant?(line) ⇒ Boolean
Check if line contains combat-relevant content.
-
.configure(new_settings = {}) ⇒ void
Update tracker settings.
-
.debug?(level = nil) ⇒ Symbol, ...
Check if debug mode is enabled, or whether a specific level is.
-
.disable! ⇒ void
Disable combat tracking.
-
.disable_debug! ⇒ void
Disable debug logging.
-
.enable! ⇒ void
Enable combat tracking.
-
.enable_debug!(level = :verbose) ⇒ void
Enable debug logging.
-
.enabled? ⇒ Boolean
Check if combat tracking is enabled.
-
.fallback_hp ⇒ Integer
Returns the configured fallback max HP for creatures without templates.
-
.off(handler_or_name) ⇒ Object
Unsubscribe a handler returned by Tracker.on, or by its name:.
-
.on(*types, name: nil, &block) ⇒ Proc
Subscribe to parsed combat events (see Combat::Observers for event types, payloads, and the subscriber contract - callbacks may run on worker threads; never send game commands from one).
-
.process(chunk) ⇒ void
Process a chunk of game lines.
-
.set_fallback_hp(hp_value) ⇒ void
Set fallback HP value for creatures without templates.
-
.stats ⇒ Hash
Get processing statistics.
Class Attribute Details
.buffer ⇒ Object (readonly)
Returns the value of attribute buffer.
68 69 70 |
# File 'documented/gemstone/combat/tracker.rb', line 68 def buffer @buffer end |
.settings ⇒ Object (readonly)
Returns the value of attribute settings.
68 69 70 |
# File 'documented/gemstone/combat/tracker.rb', line 68 def settings @settings end |
Class Method Details
.combat_relevant?(line) ⇒ Boolean
Check if line contains combat-relevant content
Quick filter to avoid processing non-combat lines.
277 278 279 |
# File 'documented/gemstone/combat/tracker.rb', line 277 def combat_relevant?(line) COMBAT_RELEVANT_PATTERN.match?(line) || COMBAT_RESOLUTION_PATTERN.match?(line) end |
.configure(new_settings = {}) ⇒ void
This method returns an undefined value.
Update tracker settings
Merges new settings with existing ones and persists to Lich settings. Reinitializes processor if thread count changes.
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'documented/gemstone/combat/tracker.rb', line 295 def configure(new_settings = {}) initialize! unless @initialized @settings.merge!(new_settings) # Save to Lich settings system for persistence save_settings # Reinitialize processor if thread count changed if new_settings.key?(:max_threads) shutdown_processor initialize_processor end respond "[Combat] Settings updated: #{@settings}" if debug? end |
.debug?(level = nil) ⇒ Symbol, ...
Check if debug mode is enabled, or whether a specific level is.
Called bare it returns the active level (truthy), which keeps every
existing if Tracker.debug? guard working unchanged.
151 152 153 154 155 156 157 |
# File 'documented/gemstone/combat/tracker.rb', line 151 def debug?(level = nil) current = @settings[:debug] || $combat_debug current = :verbose if current == true return current unless level current == level end |
.disable! ⇒ void
This method returns an undefined value.
Disable combat tracking
Shuts down the processor, removes hooks, and persists disabled state.
126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'documented/gemstone/combat/tracker.rb', line 126 def disable! return unless @enabled initialize! unless @initialized @enabled = false @settings[:enabled] = false save_settings # Persist disabled state remove_downstream_hook shutdown_processor respond "[Combat] Combat tracking disabled" if debug? end |
.disable_debug! ⇒ void
This method returns an undefined value.
Disable debug logging
Restores the thread count debug mode took over.
189 190 191 192 193 194 195 |
# File 'documented/gemstone/combat/tracker.rb', line 189 def disable_debug! initialize! unless @initialized restore = @pre_debug_threads || DEFAULT_SETTINGS[:max_threads] @pre_debug_threads = nil configure(debug: false, max_threads: restore) respond "[Combat] Debug mode disabled (max_threads: #{restore})" end |
.enable! ⇒ void
This method returns an undefined value.
Enable combat tracking
Initializes the processor, loads settings, and adds downstream hook. Persists enabled state to DB.
108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'documented/gemstone/combat/tracker.rb', line 108 def enable! return if @enabled initialize! unless @initialized @enabled = true @settings[:enabled] = true # Force enabled in settings save_settings # Persist enabled state initialize_processor add_downstream_hook respond "[Combat] Combat tracking enabled" if debug? end |
.enable_debug!(level = :verbose) ⇒ void
This method returns an undefined value.
Enable debug logging
Forces inline processing (max_threads: 0) for the duration, so debug output appears in true order relative to the game text instead of interleaving from the async worker.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'documented/gemstone/combat/tracker.rb', line 168 def enable_debug!(level = :verbose) level = :verbose if level == true unless DEBUG_LEVELS.include?(level) respond "[Combat] Unknown debug level #{level.inspect} (expected #{DEBUG_LEVELS.map(&:inspect).join(' or ')})" return end initialize! unless @initialized # Only capture on the first enable - a second call while already # in debug would otherwise record the forced 0 as the value to # restore, stranding the character inline. @pre_debug_threads = @settings[:max_threads] unless debug? configure(debug: level, enabled: true, max_threads: 0) respond "[Combat] Debug mode enabled (#{level}, inline processing)" end |
.enabled? ⇒ Boolean
Check if combat tracking is enabled
Lazily initializes on first check if not already initialized.
92 93 94 95 96 97 98 99 100 |
# File 'documented/gemstone/combat/tracker.rb', line 92 def enabled? # Before login data is available we can't load per-character # settings; report disabled instead of sleeping on the caller's # thread (the background init thread completes setup once ready). return false unless @initialized || xmldata_ready? initialize! unless @initialized @enabled && @settings[:enabled] end |
.fallback_hp ⇒ Integer
Returns the configured fallback max HP for creatures without templates.
209 210 211 212 |
# File 'documented/gemstone/combat/tracker.rb', line 209 def fallback_hp initialize! unless @initialized @settings[:fallback_max_hp] end |
.off(handler_or_name) ⇒ Object
Unsubscribe a handler returned by on, or by its name:.
83 84 85 |
# File 'documented/gemstone/combat/tracker.rb', line 83 def off(handler_or_name) Observers.off(handler_or_name) end |
.on(*types, name: nil, &block) ⇒ Proc
Subscribe to parsed combat events (see Combat::Observers for event types, payloads, and the subscriber contract - callbacks may run on worker threads; never send game commands from one).
78 79 80 |
# File 'documented/gemstone/combat/tracker.rb', line 78 def on(*types, name: nil, &block) Observers.on(*types, name: name, &block) end |
.process(chunk) ⇒ void
This method returns an undefined value.
Process a chunk of game lines
Filters for combat-relevant lines and processes them. Triggers periodic cleanup of old creature instances.
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'documented/gemstone/combat/tracker.rb', line 221 def process(chunk) return unless enabled? return if chunk.empty? # Quick filter - only process if combat-related content present return unless chunk.any? { |line| combat_relevant?(line) } if @async_processor @async_processor.process_async(chunk) else Processor.process(chunk) end # Periodic cleanup of old creature instances @chunks_processed += 1 if @chunks_processed >= @settings[:cleanup_interval] cleanup_creatures @chunks_processed = 0 end end |
.set_fallback_hp(hp_value) ⇒ void
This method returns an undefined value.
Set fallback HP value for creatures without templates
201 202 203 204 |
# File 'documented/gemstone/combat/tracker.rb', line 201 def set_fallback_hp(hp_value) configure(fallback_max_hp: hp_value.to_i) respond "[Combat] Fallback max HP set to #{hp_value}" end |
.stats ⇒ Hash
Get processing statistics
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'documented/gemstone/combat/tracker.rb', line 314 def stats return { enabled: false } unless enabled? base_stats = { enabled: true, buffer_size: @buffer.size, settings: @settings } if @async_processor base_stats.merge(@async_processor.stats) else base_stats.merge(active: 0, total: 0) end end |