Class: Lich::Gemstone::CreatureInstance

Inherits:
Object
  • Object
show all
Includes:
Common::CreatureBase
Defined in:
documented/gemstone/creature.rb

Overview

Individual GemStone creature instance (runtime tracking with ID).

Shares its id-keyed registry, room roster and <crtrStatus> status/flag handling with DragonRealms via the Common::CreatureBase mixin; the GemStone-specific layer here adds bestiary templates, UCS (Unarmed Combat System) tracking, HP/injury modelling and the GemStone valid_target? exclusions.

Constant Summary collapse

BODY_PARTS =

Valid GemStone body parts for injury tracking.

Used by #add_injury to validate injury locations. Keys correspond to the body part names used in the bestiary and combat parsing.

See Also:

  • #injured?, #injured_locations
%w[abdomen back chest head leftArm leftEye leftFoot leftHand leftLeg neck nerves rightArm rightEye rightFoot rightHand rightLeg]
UCS_TTL =

UCS data expires after 2 minutes

120
UCS_SMITE_TTL =

Smite effect expires after 15 seconds

15

Constants included from Common::CreatureBase

Common::CreatureBase::ALL_CRTR_FLAGS, Common::CreatureBase::CRTR_CLASSIFICATION_FLAGS, Common::CreatureBase::CRTR_STATUS_FLAGS, Common::CreatureBase::KNOWN_FLAG_NAMES, Common::CreatureBase::STATUS_DURATIONS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Common::CreatureBase

included

Constructor Details

#initialize(id, noun, name) ⇒ void

Initializes a creature instance for runtime tracking.

Sets up the creature's identity, injury log, HP tracking, and UCS (Unarmed Combat System) state. Status tracking is delegated to the shared Common::CreatureBase mixin.

Parameters:

  • id (Integer)

    the creature's unique id in the room

  • noun (String)

    the creature noun (e.g. "orc", "spider")

  • name (String)

    the display name, may include boon adjectives



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'documented/gemstone/creature.rb', line 268

def initialize(id, noun, name)
  @id = id.to_i
  @noun = noun
  @name = name
  initialize_status_tracking
  @injuries = Hash.new(0)
  @health = nil
  @damage_taken = 0
  @created_at = Time.now
  @fatal_crit = false
  @ucs_position = nil
  @ucs_tierup = nil
  @ucs_smote = nil
  @ucs_updated = nil
end

Instance Attribute Details

#created_atObject

Returns the value of attribute created_at.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def created_at
  @created_at
end

#damage_takenObject

Returns the value of attribute damage_taken.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def damage_taken
  @damage_taken
end

#fatal_critObject

Returns the value of attribute fatal_crit.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def fatal_crit
  @fatal_crit
end

#healthObject

Returns the value of attribute health.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def health
  @health
end

#idObject

Returns the value of attribute id.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def id
  @id
end

#injuriesObject

Returns the value of attribute injuries.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def injuries
  @injuries
end

#nameObject

Returns the value of attribute name.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def name
  @name
end

#nounObject

Returns the value of attribute noun.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def noun
  @noun
end

#statusObject

Returns the value of attribute status.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def status
  @status
end

#status_timestampsObject

Returns the value of attribute status_timestamps.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def status_timestamps
  @status_timestamps
end

#ucs_positionObject

Get UCS position tier (1-3, or nil if expired)



365
366
367
368
# File 'documented/gemstone/creature.rb', line 365

def ucs_position
  return nil if ucs_expired?
  @ucs_position
end

#ucs_smoteObject

Returns the value of attribute ucs_smote.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def ucs_smote
  @ucs_smote
end

#ucs_tierupObject

Get UCS tierup vulnerability (or nil if expired)



371
372
373
374
# File 'documented/gemstone/creature.rb', line 371

def ucs_tierup
  return nil if ucs_expired?
  @ucs_tierup
end

#ucs_updatedObject

Returns the value of attribute ucs_updated.



243
244
245
# File 'documented/gemstone/creature.rb', line 243

def ucs_updated
  @ucs_updated
end

Instance Method Details

#add_damage(amount) ⇒ Object

Add damage to creature



405
406
407
# File 'documented/gemstone/creature.rb', line 405

def add_damage(amount)
  @damage_taken += amount.to_i
end

#add_injury(body_part, amount = 1) ⇒ Object

Add injury to body part



377
378
379
380
381
382
# File 'documented/gemstone/creature.rb', line 377

def add_injury(body_part, amount = 1)
  unless BODY_PARTS.include?(body_part.to_s)
    raise ArgumentError, "Invalid body part: #{body_part}"
  end
  @injuries[body_part.to_sym] += amount
end

#clear_smoteObject

Clear smote status



352
353
354
355
356
# File 'documented/gemstone/creature.rb', line 352

def clear_smote
  @ucs_smote = nil
  @ucs_updated = Time.now
  debug_log("UCS: smote cleared")
end

#current_hpObject

Calculate current HP (max_hp - damage_taken)



431
432
433
434
# File 'documented/gemstone/creature.rb', line 431

def current_hp
  return nil unless max_hp
  [max_hp - @damage_taken, 0].max
end

#dead?Boolean

Check if creature is dead (0 HP)

Returns:

  • (Boolean)


449
450
451
# File 'documented/gemstone/creature.rb', line 449

def dead?
  current_hp == 0
end

#essential_dataObject

Essential data for this instance



487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
# File 'documented/gemstone/creature.rb', line 487

def essential_data
  {
    id: @id,
    noun: @noun,
    name: @name,
    status: @status,
    injuries: @injuries,
    health: @health,
    damage_taken: @damage_taken,
    max_hp: max_hp,
    current_hp: current_hp,
    hp_percent: hp_percent,
    has_template: has_template?,
    created_at: @created_at,
    ucs_position: ucs_position,
    ucs_tierup: ucs_tierup,
    ucs_smote: smote?
  }
end

#fatal_crit?Boolean

Check if creature died from fatal crit

Returns:

  • (Boolean)


395
396
397
# File 'documented/gemstone/creature.rb', line 395

def fatal_crit?
  @fatal_crit
end

#has_template?Boolean

Check if creature has template data

Returns:

  • (Boolean)


295
296
297
# File 'documented/gemstone/creature.rb', line 295

def has_template?
  !template.nil?
end

#hp_percentObject

Calculate HP percentage (0-100)



437
438
439
440
# File 'documented/gemstone/creature.rb', line 437

def hp_percent
  return nil unless max_hp && max_hp > 0
  ((current_hp.to_f / max_hp) * 100).round(1)
end

#injured?(location, threshold = 1) ⇒ Boolean

Check if injured at location

Returns:

  • (Boolean)


385
386
387
# File 'documented/gemstone/creature.rb', line 385

def injured?(location, threshold = 1)
  @injuries[location.to_sym] >= threshold
end

#injured_locations(threshold = 1) ⇒ Object

Get all injured locations



400
401
402
# File 'documented/gemstone/creature.rb', line 400

def injured_locations(threshold = 1)
  @injuries.select { |_, value| value >= threshold }.keys
end

#low_hp?(threshold = 25) ⇒ Boolean

Check if creature is below HP threshold

Returns:

  • (Boolean)


443
444
445
446
# File 'documented/gemstone/creature.rb', line 443

def low_hp?(threshold = 25)
  return false unless hp_percent
  hp_percent <= threshold
end

#mark_fatal_crit!Object

Mark creature as killed by fatal critical hit



390
391
392
# File 'documented/gemstone/creature.rb', line 390

def mark_fatal_crit!
  @fatal_crit = true
end

#max_hpObject

Get maximum HP from template, with fallback



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
# File 'documented/gemstone/creature.rb', line 410

def max_hp
  # Try template first
  hp = template&.max_hp
  return hp if hp && hp > 0

  # Fall back to combat tracker setting if available
  begin
    if defined?(Lich::Gemstone::Combat::Tracker) &&
       Lich::Gemstone::Combat::Tracker.respond_to?(:fallback_hp)
      fallback = Lich::Gemstone::Combat::Tracker.fallback_hp
      return fallback if fallback && fallback > 0
    end
  rescue
    # Ignore errors accessing tracker
  end

  # Last resort: hardcoded fallback
  400
end

#muckled?Boolean

Creature-side analog of Lich::Gemstone::Status.muckled? (the player's own "can't act right now" check). Deliberately narrower than everything tracked in @status: excludes penalty-only conditions (disoriented), positional ones (prone/kneeling/sitting/flying/ hovering), and calm (the player version excludes that too, tracking it separately) - this is only the statuses that actually prevent acting, not ones that merely penalize or reposition.

Returns:

  • (Boolean)


476
477
478
479
# File 'documented/gemstone/creature.rb', line 476

def muckled?
  has_status?('webbed') || crtr_flag?(:dead) || dead? || has_status?('stunned') ||
    has_status?('sleeping') || has_status?('immobilized') || has_status?('rooted')
end

#position_to_tier(pos) ⇒ Object

Convert position string/number to tier (1-3)



302
303
304
305
306
307
308
309
# File 'documented/gemstone/creature.rb', line 302

def position_to_tier(pos)
  case pos
  when "decent", 1, "1" then 1
  when "good", 2, "2" then 2
  when "excellent", 3, "3" then 3
  else nil
  end
end

#reset_damageObject

Reset damage (creature healed or respawned)



482
483
484
# File 'documented/gemstone/creature.rb', line 482

def reset_damage
  @damage_taken = 0
end

#set_ucs_position(position) ⇒ Object

Set UCS position tier



312
313
314
315
316
317
318
319
320
321
322
# File 'documented/gemstone/creature.rb', line 312

def set_ucs_position(position)
  new_tier = position_to_tier(position)
  return unless new_tier

  # Clear tierup if tier changed
  @ucs_tierup = nil if new_tier != @ucs_position

  @ucs_position = new_tier
  @ucs_updated = Time.now
  debug_log("UCS: position=#{new_tier}")
end

#set_ucs_tierup(attack_type) ⇒ Object

Set UCS tierup vulnerability



325
326
327
328
329
# File 'documented/gemstone/creature.rb', line 325

def set_ucs_tierup(attack_type)
  @ucs_tierup = attack_type
  @ucs_updated = Time.now
  debug_log("UCS: tierup=#{attack_type}")
end

#smite!Object

Mark creature as smote (crimson mist applied)



332
333
334
335
336
# File 'documented/gemstone/creature.rb', line 332

def smite!
  @ucs_smote = Time.now
  @ucs_updated = Time.now
  debug_log("UCS: smote!")
end

#smote?Boolean

Check if creature is currently smote

Returns:

  • (Boolean)


339
340
341
342
343
344
345
346
347
348
349
# File 'documented/gemstone/creature.rb', line 339

def smote?
  return false unless @ucs_smote

  # Check if smite effect has expired
  if Time.now - @ucs_smote > UCS_SMITE_TTL
    @ucs_smote = nil
    return false
  end

  true
end

#templateObject

Get the template for this creature. Sentinel-cached so a creature with no template doesn't redo the name lookup (downcase + boon regex) on every call the way ||= would.



287
288
289
290
291
292
# File 'documented/gemstone/creature.rb', line 287

def template
  return @template if defined?(@template_looked_up)

  @template_looked_up = true
  @template = CreatureTemplate[@name]
end

#ucs_expired?Boolean

Check if UCS data has expired

Returns:

  • (Boolean)


359
360
361
362
# File 'documented/gemstone/creature.rb', line 359

def ucs_expired?
  return true unless @ucs_updated
  (Time.now - @ucs_updated) > UCS_TTL
end

#valid_target?Boolean

Checks whether this creature should be considered attackable.

Uses the same decoy and appendage exclusions as GameObj.targets, but uses structured death data from and HP tracking instead of regex-matching a status string.

Returns:

  • (Boolean)


460
461
462
463
464
465
466
467
# File 'documented/gemstone/creature.rb', line 460

def valid_target?
  return false if crtr_flag?(:dead) || dead?
  return false if @name =~ /^animated\b/i && @name !~ /^animated slush/i
  return false if @noun =~ /^(?:arm|appendage|claw|limb|pincer|tentacle)s?$|^(?:palpus|palpi)$/i &&
                  @name !~ /(?:amaranthine|ghostly|grizzled|ancient) kraken tentacle/i

  true
end