Class: Lich::Gemstone::CreatureTemplate

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

Overview

Static creature template data (ID-less reference information)

Manages creature templates loaded from data files. Templates contain static information about creature types (level, HP, abilities, etc.) and are shared across all instances of that creature type.

Examples:

Load and lookup a template

CreatureTemplate.load_all
template = CreatureTemplate['troll']
puts template.level  # => 14

Handle boon adjectives

template = CreatureTemplate['radiant troll']  # Same as 'troll'

Constant Summary collapse

BOON_ADJECTIVES =
%w[
  adroit afflicted apt barbed belligerent blurry canny combative dazzling deft diseased drab
  dreary ethereal flashy flexile flickering flinty frenzied ghastly ghostly gleaming glittering
  glorious glowing grotesque hardy illustrious indistinct keen lanky luminous lustrous muculent
  nebulous oozing pestilent radiant raging ready resolute robust rune-covered shadowy shifting
  shimmering shining sickly green sinuous slimy sparkling spindly spiny stalwart steadfast stout
  tattoed tenebrous tough twinkling unflinching unyielding wavering wispy
]
BOON_REGEX =

Clean creature name by removing boon adjectives Optimized to use single compiled regex instead of 50+ sequential matches

/^(#{BOON_ADJECTIVES.join('|')})\s+/i.freeze
@@templates =
{}
@@loaded =
false
@@max_templates =

Prevent unbounded template cache growth

500

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ CreatureTemplate

Returns a new instance of CreatureTemplate.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'documented/gemstone/creature.rb', line 40

def initialize(data)
  @name = data[:name]
  @url = data[:url]
  @picture = data[:picture]
  @level = data[:level].to_i
  @family = data[:family]
  @type = data[:type]
  @undead = data[:undead]
  @otherclass = data[:otherclass] || []
  @areas = data[:areas] || []
  @bcs = data[:bcs]
  @max_hp = data[:max_hp]&.to_i || data[:hitpoints]&.to_i
  @speed = data[:speed]
  @height = data[:height].to_i
  @size = data[:size]

  atk = data[:attack_attributes] || {}
  @attack_attributes = OpenStruct.new(
    physical_attacks: atk[:physical_attacks] || [],
    bolt_spells: atk[:bolt_spells] || [],
    warding_spells: normalize_spells(atk[:warding_spells]),
    offensive_spells: normalize_spells(atk[:offensive_spells]),
    maneuvers: atk[:maneuvers] || [],
    special_abilities: (atk[:special_abilities] || []).map { |s| SpecialAbility.new(s) }
  )

  @defense_attributes = DefenseAttributes.new(data[:defense_attributes] || {})
  @treasure = Treasure.new(data[:treasure] || {})
  @messaging = Messaging.new(data[:messaging] || {})
  @special_other = data[:special_other]
  @abilities = data[:abilities] || []
  @alchemy = data[:alchemy] || []
end

Instance Attribute Details

#abilitiesObject (readonly)

Returns the value of attribute abilities.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def abilities
  @abilities
end

#alchemyObject (readonly)

Returns the value of attribute alchemy.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def alchemy
  @alchemy
end

#areasObject (readonly)

Returns the value of attribute areas.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def areas
  @areas
end

#attack_attributesObject (readonly)

Returns the value of attribute attack_attributes.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def attack_attributes
  @attack_attributes
end

#bcsObject (readonly)

Returns the value of attribute bcs.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def bcs
  @bcs
end

#defense_attributesObject (readonly)

Returns the value of attribute defense_attributes.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def defense_attributes
  @defense_attributes
end

#familyObject (readonly)

Returns the value of attribute family.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def family
  @family
end

#heightObject (readonly)

Returns the value of attribute height.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def height
  @height
end

#levelObject (readonly)

Returns the value of attribute level.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def level
  @level
end

#max_hpObject (readonly)

Returns the value of attribute max_hp.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def max_hp
  @max_hp
end

#messagingObject (readonly)

Returns the value of attribute messaging.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def messaging
  @messaging
end

#nameObject (readonly)

Returns the value of attribute name.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def name
  @name
end

#otherclassObject (readonly)

Returns the value of attribute otherclass.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def otherclass
  @otherclass
end

#pictureObject (readonly)

Returns the value of attribute picture.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def picture
  @picture
end

#sizeObject (readonly)

Returns the value of attribute size.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def size
  @size
end

#special_otherObject (readonly)

Returns the value of attribute special_other.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def special_other
  @special_other
end

#speedObject (readonly)

Returns the value of attribute speed.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def speed
  @speed
end

#treasureObject (readonly)

Returns the value of attribute treasure.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def treasure
  @treasure
end

#typeObject (readonly)

Returns the value of attribute type.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def type
  @type
end

#undeadObject (readonly)

Returns the value of attribute undead.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def undead
  @undead
end

#urlObject (readonly)

Returns the value of attribute url.



25
26
27
# File 'documented/gemstone/creature.rb', line 25

def url
  @url
end

Class Method Details

.[](name) ⇒ CreatureTemplate?

Lookup template by creature name

Attempts exact match first, then tries with boon adjectives removed. Automatically loads templates if not yet loaded.

Examples:

template = CreatureTemplate['troll']
template = CreatureTemplate['radiant troll']  # Same result

Parameters:

  • name (String)

    Creature name to look up

Returns:



163
164
165
166
167
168
169
170
171
172
173
174
# File 'documented/gemstone/creature.rb', line 163

def self.[](name)
  load_all unless @@loaded
  return nil unless name

  # Try exact match first
  template = @@templates[name.downcase]
  return template if template

  # Try with boon adjectives removed
  normalized_name = fix_template_name(name)
  @@templates[normalized_name]
end

.allObject

Get all loaded templates



177
178
179
180
# File 'documented/gemstone/creature.rb', line 177

def self.all
  load_all unless @@loaded
  @@templates.values.uniq
end

.fix_template_name(template_name) ⇒ String

Remove boon adjectives from creature names for template matching

Boon adjectives like “radiant”, “ghostly”, “shadowy” are temporary modifiers and should be stripped for template lookup.

Examples:

fix_template_name("radiant troll")  # => "troll"

Parameters:

  • template_name (String)

    The creature name to normalize

Returns:

  • (String)

    Normalized name without boon adjectives



133
134
135
136
137
# File 'documented/gemstone/creature.rb', line 133

def self.fix_template_name(template_name)
  name = template_name.dup.downcase
  name.sub!(BOON_REGEX, '')
  name.strip
end

.load_allvoid

Note:

Only loads once; subsequent calls are no-ops

This method returns an undefined value.

Load all creature templates from the creatures directory

Scans for .rb files in lib/gemstone/creatures and loads them as templates. Implements a safety limit (@@max_templates) to prevent memory exhaustion. Templates are cached in @@templates for fast lookup.



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'documented/gemstone/creature.rb', line 82

def self.load_all
  return if @@loaded

  templates_dir = File.join(File.dirname(__FILE__), 'creatures')
  return unless File.directory?(templates_dir)

  template_count = 0
  Dir[File.join(templates_dir, '*.rb')].each do |path|
    next if File.basename(path) == '_creature_template.rb'

    # Check template limit
    if template_count >= @@max_templates
      puts "--- warning: Template cache limit (#{@@max_templates}) reached, skipping remaining templates" if $creature_debug
      break
    end

    template_name = File.basename(path, '.rb').tr('_', ' ')
    normalized_name = fix_template_name(template_name)

    begin
      # Safer loading with validation
      file_content = File.read(path)
      data = load_template_data(file_content, path)
      next unless data.is_a?(Hash)

      data[:name] = template_name
      template = new(data)
      @@templates[normalized_name] = template
      template_count += 1
    rescue => e
      puts "--- error loading template #{template_name}: #{e.message}" if $creature_debug
    end
  end

  @@loaded = true
  puts "--- loaded #{template_count} creature templates" if $creature_debug
end