Module: Lich::Common::CreatureBase::InstanceMethods
- Defined in:
- documented/common/creature/creature_base.rb
Overview
Per-instance transient status and classification tracking driven by the
<crtrStatus> feed. The host class must call
#initialize_status_tracking from its own initialize and expose
@name/@id (used only for debug headers).
Instance Method Summary collapse
-
#add_status(status, duration = nil) ⇒ void
Adds a status to the creature.
-
#cleanup_expired_statuses ⇒ void
Drops any timed statuses whose expiry has passed.
-
#crtr_flag?(key) ⇒ Boolean
Checks a classification flag captured from
<crtrStatus>. -
#crtr_flags? ⇒ Boolean
Whether any
<crtrStatus>classification has been seen for this creature yet. -
#flag_active?(key) ⇒ Boolean
Checks whether a status or classification flag is active.
-
#has_status?(status) ⇒ Boolean
Checks whether a specific status is active (after expiring stale ones).
-
#initialize_status_tracking ⇒ void
Initializes the tracking ivars.
-
#remove_status(status) ⇒ void
Removes a status from the creature.
-
#statuses ⇒ Array<String>
Returns a copy of the currently-active statuses (after expiry).
-
#sync_crtr_status(attrs) ⇒ void
Reconciles status and classification from a
<crtrStatus>tag.
Instance Method Details
#add_status(status, duration = nil) ⇒ void
This method returns an undefined value.
Adds a status to the creature.
Normalizes to String so callers can pass symbols from message-based
status parsing or strings from <crtrStatus>; both sources then land
in the same status entries and match #has_status?.
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'documented/common/creature/creature_base.rb', line 452 def add_status(status, duration = nil) # Canonicalize case at the boundary, not per producer: the crit # tables report position as "PRONE"/"KNEELING"/"SITTING" while # messaging and <crtrStatus> use lowercase, and @status membership # is exact - an uppercase add could never be removed or matched. status = status.to_s.downcase if @status.include?(status) # Re-adding with an explicit duration extends the lock: without # this, a 3s roundtime followed by an overlapping 20s one kept # the 3s expiry and reported the creature free ~19s early. # Never shorten - the longest known source wins. if duration expires = Time.now + duration current = @status_timestamps[status] @status_timestamps[status] = expires if current.nil? || expires > current end return end @status << status duration ||= STATUS_DURATIONS[status] if duration @status_timestamps[status] = Time.now + duration debug_log("+status: #{status} (expires in #{duration}s)") else debug_log("+status: #{status} (no auto-expiry)") end end |
#cleanup_expired_statuses ⇒ void
This method returns an undefined value.
Drops any timed statuses whose expiry has passed.
500 501 502 503 504 505 506 507 508 509 |
# File 'documented/common/creature/creature_base.rb', line 500 def cleanup_expired_statuses return unless @status_timestamps && !@status_timestamps.empty? now = Time.now @status_timestamps.select { |_status, expires_at| expires_at <= now }.keys.each do |expired_status| @status.delete(expired_status) @status_timestamps.delete(expired_status) debug_log("~status: #{expired_status} (auto-expired)") end end |
#crtr_flag?(key) ⇒ Boolean
Checks a classification flag captured from <crtrStatus>.
Unlike template tri-state facts, live XML flags are always-sent booleans, so an unknown or unseen flag is false, not nil.
569 570 571 |
# File 'documented/common/creature/creature_base.rb', line 569 def crtr_flag?(key) @crtr_flags[key.to_sym] || false end |
#crtr_flags? ⇒ Boolean
Whether any <crtrStatus> classification has been seen for this
creature yet.
Callers filtering on a flag need to tell "the feed said this is not
hostile" apart from "the feed has not told us anything" - an absent
flag is unknown, not false. A ridden mount, for instance, carries a
bold creature link but never a <crtrStatus> of its own.
582 583 584 |
# File 'documented/common/creature/creature_base.rb', line 582 def crtr_flags? !@crtr_flags.empty? end |
#flag_active?(key) ⇒ Boolean
Checks whether a status or classification flag is active.
The two vocabularies are intentionally disjoint, so callers can filter on any known flag name without caring which bucket stores it.
593 594 595 |
# File 'documented/common/creature/creature_base.rb', line 593 def flag_active?(key) has_status?(key) || crtr_flag?(key) end |
#has_status?(status) ⇒ Boolean
Checks whether a specific status is active (after expiring stale ones).
515 516 517 518 |
# File 'documented/common/creature/creature_base.rb', line 515 def has_status?(status) cleanup_expired_statuses @status.include?(status.to_s.downcase) end |
#initialize_status_tracking ⇒ void
This method returns an undefined value.
Initializes the tracking ivars. Call from the host class initialize.
436 437 438 439 440 |
# File 'documented/common/creature/creature_base.rb', line 436 def initialize_status_tracking @status = [] @status_timestamps = {} @crtr_flags = {} end |
#remove_status(status) ⇒ void
This method returns an undefined value.
Removes a status from the creature.
486 487 488 489 490 491 492 493 494 495 |
# File 'documented/common/creature/creature_base.rb', line 486 def remove_status(status) status = status.to_s.downcase @status.delete(status) @status_timestamps.delete(status) # A stun removal (message or <crtrStatus> snapshot) is authoritative # and retires any crit-table duration estimate with it, however much # time that estimate had left. GemStone-only hook. clear_stun_estimate if status == 'stunned' && respond_to?(:clear_stun_estimate) debug_log("-status: #{status}") end |
#statuses ⇒ Array<String>
Returns a copy of the currently-active statuses (after expiry).
523 524 525 526 |
# File 'documented/common/creature/creature_base.rb', line 523 def statuses cleanup_expired_statuses @status.dup end |
#sync_crtr_status(attrs) ⇒ void
This method returns an undefined value.
Reconciles status and classification from a <crtrStatus> tag.
The tag is a full snapshot of what is currently active, not a delta. A missing flag, or a flag set to "0", means inactive even if it was active a moment ago, so absent known flags are cleared rather than ignored.
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 |
# File 'documented/common/creature/creature_base.rb', line 537 def sync_crtr_status(attrs) # Scoped to CRTR_STATUS_FLAGS on purpose: @status has two writers, # this feed and the combat parser reading messaging. The feed is a # full snapshot only of the states it reports, so it owns removal # for exactly those - and must not touch the rest. blind, # poisoned, natures_decay and the other message-only effects never # appear in the tag; reconciling them here would clear them on the # next one and make them impossible to model. CRTR_STATUS_FLAGS.each do |xml_name, status| if attrs[xml_name] == '1' add_status(status) elsif @status.include?(status) remove_status(status) end end CRTR_CLASSIFICATION_FLAGS.each do |xml_name, key| new_value = (attrs[xml_name] == '1') debug_log("~flag: #{key}=#{new_value}") if debug_level == :changes && @crtr_flags[key] != new_value @crtr_flags[key] = new_value end report_crtr_snapshot(attrs) if %i[all active].include?(debug_level) end |