Module: Lich::Gemstone::Armor
- Defined in:
- documented/gemstone/psms/armor.rb
Overview
Provides logic for detecting, checking, and using PSM3 armor techniques in GemStone IV.
This module defines a registry of available armor-related abilities and wraps common queries like whether a technique is known, affordable, or currently usable. It also provides the ‘use` method to execute the appropriate command in-game, handling roundtime and feedback matching.
Techniques are stored in a constant hash, and dynamic methods are defined for both long and short names of each technique.
Constant Summary collapse
- @@armor_techniques =
Mapping of armor technique identifiers to their associated data, including:
-
short name
-
usage command
-
regex to match expected in-game output
-
cost to use
-
type of technique (buff, passive, etc.)
-
{ "armor_blessing" => { :short_name => "blessing", :type => :buff, :cost => { stamina: 0 }, :regex => /As \w+ prays? over \w+(?:'s)? [\w\s]+, you sense that (?:the Arkati's|a) blessing will be granted against magical attacks\./i, :usage => "blessing" }, "armor_reinforcement" => { :short_name => "reinforcement", :type => :buff, :cost => { stamina: 0 }, :regex => /\w+ adjusts? \w+(?:'s)? [\w\s]+, reinforcing weak spots\./i, :usage => "reinforcement" }, "armor_spike_mastery" => { :short_name => "spikemastery", :type => :passive, :cost => { stamina: 0 }, :regex => /Armor Spike Mastery is passive and always active once learned\./i, :usage => "spikemastery" }, "armor_support" => { :short_name => "support", :type => :buff, :cost => { stamina: 0 }, :regex => /\w+ adjusts? \w+(?:'s)? [\w\s]+, improving its ability to support the weight of \w+ gear\./i, :usage => "support" }, "armored_casting" => { :short_name => "casting", :type => :buff, :cost => { stamina: 0 }, :regex => /\w+ adjusts? \w+(?:'s)? [\w\s]+, making it easier for \w+ to recover from failed spell casting\./i, :usage => "casting" }, "armored_evasion" => { :short_name => "evasion", :type => :buff, :cost => { stamina: 0 }, :regex => /\w+ adjusts? \w+(?:'s)? [\w\s]+, improving its comfort and maneuverability\./i, :usage => "evasion" }, "armored_fluidity" => { :short_name => "fluidity", :type => :buff, :cost => { stamina: 0 }, :regex => /\w+ adjusts? \w+(?:'s)? [\w\s]+, making it easier for \w+ to cast spells\./i, :usage => "fluidity" }, "armored_stealth" => { :short_name => "stealth", :type => :buff, :cost => { stamina: 0 }, :regex => /\w+ adjusts? \w+(?:'s)? [\w\s]+ to cushion \w+ movements\./i, :usage => "stealth" }, "crush_protection" => { :short_name => "crush", :type => :passive, :cost => { stamina: 0 }, :regex => Regexp.union( /You adjust \w+(?:'s)? [\w\s]+ with your (?:cloth|leather|scale|chain|plate|accessory) armor fittings, rearranging and reinforcing the armor to better protect against crushing damage\./i, /You must specify an armor slot\./, /You don't seem to have the necessary armor fittings in hand\./ ), :usage => "crush" }, "puncture_protection" => { :short_name => "puncture", :type => :passive, :cost => { stamina: 0 }, :regex => Regexp.union( /You adjust \w+(?:'s)? [\w\s]+ with your (?:cloth|leather|scale|chain|plate|accessory) armor fittings, rearranging and reinforcing the armor to better protect against puncturing damage\./i, /You must specify an armor slot\./, /You don't seem to have the necessary armor fittings in hand\./ ), :usage => "puncture" }, "slash_protection" => { :short_name => "slash", :type => :passive, :cost => { stamina: 0 }, :regex => Regexp.union( /You adjust \w+(?:'s)? [\w\s]+ with your (?:cloth|leather|scale|chain|plate|accessory) armor fittings, rearranging and reinforcing the armor to better protect against slashing damage\./i, /You must specify an armor slot\./, /You don't seem to have the necessary armor fittings in hand\./ ), :usage => "slash" } }
Class Method Summary collapse
-
.[](name) ⇒ Integer
Looks up the rank known of an armor technique.
-
.affordable?(name, forcert_count: 0) ⇒ Boolean
Determines if an armor technique is affordable, and optionally tests affordability with a given number of FORCERTs having been used (including the current one).
-
.armor_lookups ⇒ Array<Hash>
Returns a simplified array, for lookup purposes, of armor technique hashes with long name, short name, and cost.
-
.available?(name, min_rank: 1, forcert_count: 0) ⇒ Boolean
Determines if an armor technique is available to use right now by testing: - if the technique is known - if the technique is affordable - if the technique is not on cooldown - if the character is not overexerted - if the character is capable of performing the number of FORCERTs specified.
-
.buff_active?(name) ⇒ Boolean
Checks whether the technique’s buff is currently active.
-
.known?(name, min_rank: 1) ⇒ Boolean
Determines if the character knows an armor technique at all, and optionally if the character knows it at the specified rank.
-
.regexp(name) ⇒ Regexp
Returns the “success” regex associated with a given armor technique name.
-
.use(name, target = "", results_of_interest: nil, forcert_count: 0) ⇒ String?
Attempts to use an armor technique, optionally on a target.
Class Method Details
.[](name) ⇒ Integer
Looks up the rank known of an armor technique.
140 141 142 |
# File 'documented/gemstone/psms/armor.rb', line 140 def Armor.[](name) return PSMS.assess(name, 'Armor') end |
.affordable?(name, forcert_count: 0) ⇒ Boolean
Determines if an armor technique is affordable, and optionally tests affordability with a given number of FORCERTs having been used (including the current one).
167 168 169 |
# File 'documented/gemstone/psms/armor.rb', line 167 def Armor.affordable?(name, forcert_count: 0) return PSMS.assess(name, 'Armor', true, forcert_count: forcert_count) end |
.armor_lookups ⇒ Array<Hash>
Returns a simplified array, for lookup purposes, of armor technique hashes with long name, short name, and cost.
123 124 125 126 127 128 129 130 131 |
# File 'documented/gemstone/psms/armor.rb', line 123 def self.armor_lookups @@armor_techniques.map do |long_name, psm| { long_name: long_name, short_name: psm[:short_name], cost: psm[:cost] } end end |
.available?(name, min_rank: 1, forcert_count: 0) ⇒ Boolean
Determines if an armor technique is available to use right now by testing:
-
if the technique is known
-
if the technique is affordable
-
if the technique is not on cooldown
-
if the character is not overexerted
-
if the character is capable of performing the number of FORCERTs specified
blocked by overexertion
185 186 187 188 189 |
# File 'documented/gemstone/psms/armor.rb', line 185 def Armor.available?(name, min_rank: 1, forcert_count: 0) Armor.known?(name, min_rank: min_rank) && Armor.affordable?(name, forcert_count: forcert_count) && PSMS.available?(name) end |
.buff_active?(name) ⇒ Boolean
Checks whether the technique’s buff is currently active.
195 196 197 198 |
# File 'documented/gemstone/psms/armor.rb', line 195 def Armor.buff_active?(name) return unless @@armor_techniques.fetch(PSMS.find_name(name, "Armor")[:long_name]).key?(:buff) Effects::Buffs.active?(@@armor_techniques.fetch(PSMS.find_name(name, "Armor")[:long_name])[:buff]) end |
.known?(name, min_rank: 1) ⇒ Boolean
Determines if the character knows an armor technique at all, and optionally if the character knows it at the specified rank.
153 154 155 156 |
# File 'documented/gemstone/psms/armor.rb', line 153 def Armor.known?(name, min_rank: 1) min_rank = 1 unless min_rank >= 1 # in case a 0 or below is passed Armor[name] >= min_rank end |
.regexp(name) ⇒ Regexp
Returns the “success” regex associated with a given armor technique name. This regex is used to match the expected output when the technique is successfully attempted. It does not necessarily indicate that the technique was successful in its effect, or even that the technique was executed at all.
264 265 266 |
# File 'documented/gemstone/psms/armor.rb', line 264 def Armor.regexp(name) @@armor_techniques.fetch(PSMS.find_name(name, "Armor")[:long_name])[:regex] end |
.use(name, target = "", results_of_interest: nil, forcert_count: 0) ⇒ String?
Attempts to use an armor technique, optionally on a target.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'documented/gemstone/psms/armor.rb', line 210 def Armor.use(name, target = "", results_of_interest: nil, forcert_count: 0) return unless Armor.available?(name, forcert_count: forcert_count) name_normalized = PSMS.name_normal(name) technique = @@armor_techniques.fetch(PSMS.find_name(name_normalized, "Armor")[:long_name]) usage = technique[:usage] return if usage.nil? in_cooldown_regex = /^#{name} is still in cooldown\./i results_regex = Regexp.union( PSMS::FAILURES_REGEXES, /^#{name} what\?$/i, in_cooldown_regex, technique[:regex], /^Roundtime: [0-9]+ sec\.$/, /^\w+ [a-z]+ not wearing any armor that you can work with\.$/ ) results_regex = Regexp.union(results_regex, results_of_interest) if results_of_interest.is_a?(Regexp) usage_cmd = "armor #{usage}" if target.is_a?(GameObj) usage_cmd += " ##{target.id}" elsif target.is_a?(Integer) usage_cmd += " ##{target}" elsif target != "" usage_cmd += " #{target}" end if forcert_count > 0 usage_cmd += " forcert" else # if we're using forcert, we don't want to wait for rt, but we need to otherwise waitrt? waitcastrt? end usage_result = dothistimeout usage_cmd, 5, results_regex if usage_result == "You don't seem to be able to move to do that." 100.times { break if clear.any? { |line| line =~ /^You regain control of your senses!$/ }; sleep 0.1 } usage_result = dothistimeout usage_cmd, 5, results_regex end usage_result end |