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 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.

Constant Summary collapse

@@armor_techniques =
{
  "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

Class Method Details

.[](name) ⇒ Hash?

Retrieves the armor technique associated with the given name.

Parameters:

  • name (String) —

    the name of the armor technique to retrieve.

Returns:

  • (Hash, nil) —

    the armor technique details or nil if not found.



119
120
121
# File 'documented/gemstone/psms/armor.rb', line 119

def self.[](name)
  return PSMS.assess(name, 'Armor')
end

.affordable?(name, forcert_count: 0) ⇒ Boolean

Determines if the specified armor technique can be afforded based on the forcert count.

Parameters:

  • name (String) —

    the name of the armor technique to check affordability.

  • forcert_count (Integer) (defaults to: 0) —

    the number of forcerts available for the check.

Returns:

  • (Boolean) —

    true if the technique is affordable, false otherwise.



138
139
140
# File 'documented/gemstone/psms/armor.rb', line 138

def self.affordable?(name, forcert_count: 0)
  return PSMS.assess(name, 'Armor', true, forcert_count: forcert_count)
end

.armor_lookups ⇒ Array<Hash>

Returns an array of armor techniques with their long and short names and costs.

Returns:

  • (Array<Hash>) —

    an array of hashes containing armor technique details.



105
106
107
108
109
110
111
112
113
# File 'documented/gemstone/psms/armor.rb', line 105

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

Checks if the specified armor technique is known, affordable, and available for use.

Parameters:

  • name (String) —

    the name of the armor technique to check availability.

  • min_rank (Integer) (defaults to: 1) —

    the minimum rank required to consider the technique known.

  • forcert_count (Integer) (defaults to: 0) —

    the number of forcerts available for the check.

Returns:

  • (Boolean) —

    true if the technique is available, false otherwise.



148
149
150
151
152
# File 'documented/gemstone/psms/armor.rb', line 148

def self.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 if the specified armor technique's buff is currently active.

Parameters:

  • name (String) —

    the name of the armor technique to check.

Returns:

  • (Boolean, nil) —

    true if the buff is active, false if not, or nil if the technique does not have a buff.



158
159
160
161
# File 'documented/gemstone/psms/armor.rb', line 158

def self.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

Checks if the specified armor technique is known and meets the minimum rank requirement.

Parameters:

  • name (String) —

    the name of the armor technique to check.

  • min_rank (Integer) (defaults to: 1) —

    the minimum rank required to consider the technique known.

Returns:

  • (Boolean) —

    true if the technique is known and meets the rank requirement, false otherwise.



128
129
130
131
# File 'documented/gemstone/psms/armor.rb', line 128

def self.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

Retrieves the regex pattern associated with the specified armor technique.

Parameters:

  • name (String) —

    the name of the armor technique to retrieve the regex for.

Returns:

  • (Regexp) —

    the regex pattern for the armor technique.



219
220
221
# File 'documented/gemstone/psms/armor.rb', line 219

def self.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?

Uses the specified armor technique on a target, if available.

Parameters:

  • name (String) —

    the name of the armor technique to use.

  • target (String, Integer, GameObj) (defaults to: "") —

    the target of the armor technique.

  • results_of_interest (Regexp, nil) (defaults to: nil) —

    optional regex to match specific results.

  • forcert_count (Integer) (defaults to: 0) —

    the number of forcerts available for the use.

Returns:

  • (String, nil) —

    the result of the usage or nil if the technique cannot be used.



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'documented/gemstone/psms/armor.rb', line 170

def self.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