Module: Lich::Gemstone::Weapon

Defined in:
documented/gemstone/psms/weapon.rb

Overview

Provides weapon techniques and their management.

See Also:

Constant Summary collapse

@@weapon_techniques =
{
  "barrage"          => {
    :short_name => "barrage",
    :type       => :assault,
    :cost       => { stamina: 15 },
    :regex      => /Drawing several (?:arrows|bolts) from your .+, you grip them loosely between your fingers in preparation for a rapid barrage\./,
    :assault_rx => /Your satisfying display of dexterity bolsters you and inspires those around you\!/,
    :buff       => "Enh. Dexterity (+10)"
  },
  "charge"           => {
    :short_name => "charge",
    :type       => :setup,
    :cost       => { stamina: 14 },
    :regex      => /You rush forward at .+ with your .+ and attempt a charge\!/
  },
  "clash"            => {
    :short_name => "clash",
    :type       => :area_of_effect,
    :cost       => { stamina: 20 },
    :regex      => /Steeling yourself for a brawl, you plunge into the fray\!/
  },
  "clobber"          => {
    :short_name => "clobber",
    :type       => :reaction,
    :cost       => { stamina: 0 },
    :regex      => /You redirect the momentum of your parry, hauling your .+ around to clobber .+\!/
  },
  "cripple"          => {
    :short_name => "cripple",
    :type       => :setup,
    :cost       => { stamina: 7 },
    :regex      => /You reverse your grip on your .+ and dart toward .+ at an angle\!/
  },
  "cyclone"          => {
    :short_name => "cyclone",
    :type       => :area_of_effect,
    :cost       => { stamina: 20 },
    :regex      => /You weave your .+ in an under arm spin, swiftly picking up speed until it becomes a blurred cyclone of .+\!/
  },
  "dizzying_swing"   => {
    :short_name => "dizzyingswing",
    :type       => :setup,
    :cost       => { stamina: 7 },
    :regex      => /You heft your .+ and, looping it once to build momentum, lash out in a strike at .+ head\!/,
    :usage      => "dizzyingswing"
  },
  "flurry"           => {
    :short_name => "flurry",
    :type       => :assault,
    :cost       => { stamina: 15 },
    :regex      => /You rotate your wrist, your .+ executing a casual spin to establish your flow as you advance upon .+\!/,
    :assault_rx => /The mesmerizing sway of body and blade glides to its inevitable end with one final twirl of your .+\!/,
    :buff       => "Slashing Strikes"
  },
  "fury"             => {
    :short_name => "fury",
    :type       => :assault,
    :cost       => { stamina: 15 },
    :regex      => /With a percussive snap, you shake out your arms in quick succession and bear down on .+ in a fury\!/,
    :assault_rx => /Your furious assault bolsters you and inspires those around you\!/,
    :buff       => "Enh. Constitution (+10)"
  },
  "guardant_thrusts" => {
    :short_name => "gthrusts",
    :type       => :assault,
    :cost       => { stamina: 15 },
    :regex      => /Retaining a defensive profile, you raise your .+ in a hanging guard and prepare to unleash a barrage of guardant thrusts upon .+\!/,
    :usage      => "gthrusts"
  },
  "overpower"        => {
    :short_name => "overpower",
    :type       => :reaction,
    :cost       => { stamina: 0 },
    :regex      => /On the heels of .+ parry, you erupt into motion, determined to overpower .+ defenses\!/
  },
  "pin_down"         => {
    :short_name => "pindown",
    :type       => :area_of_effect,
    :cost       => { stamina: 14 },
    :regex      => /You take quick assessment and raise your .+, several (?:arrows|bolts) nocked to your string in parallel\./,
    :usage      => "pindown"
  },
  "pulverize"        => {
    :short_name => "pulverize",
    :type       => :area_of_effect,
    :cost       => { stamina: 20 },
    :regex      => /You wheel your .+ overhead before slamming it around in a wide arc to pulverize your foes\!/
  },
  "pummel"           => {
    :short_name => "pummel",
    :type       => :assault,
    :cost       => { stamina: 15 },
    :regex      => /You take a menacing step toward .+, sweeping your .+ out low to your side in your advance\./,
    :assault_rx => /With a final snap of your wrist, you sweep your .+ back to the ready, your assault complete\./,
    :buff       => "Concussive Blows"
  },
  "radial_sweep"     => {
    :short_name => "radialsweep",
    :type       => :reaction,
    :cost       => { stamina: 0 },
    :regex      => /Crouching low, you sweep your .+ in a broad arc\!/,
    :usage      => "radialsweep"
  },
  "reactive_shot"    => {
    :short_name => "reactiveshot",
    :type       => :reaction,
    :cost       => { stamina: 0 },
    :regex      => /You fire off a quick shot at the .+, then make a hasty retreat\!/,
    :usage      => "reactiveshot"
  },
  "reverse_strike"   => {
    :short_name => "reversestrike",
    :type       => :reaction,
    :cost       => { stamina: 0 },
    :regex      => /Spotting an opening in .+ defenses, you quickly reverse the direction of your .+ and strike from a different angle\!/,
    :usage      => "reversestrike"
  },
  "riposte"          => {
    :short_name => "riposte",
    :type       => :reaction,
    :cost       => { stamina: 0 },
    :regex      => /Before .+ can recover, you smoothly segue from parry to riposte\!/
  },
  "spin_kick"        => {
    :short_name => "spinkick",
    :type       => :reaction,
    :cost       => { stamina: 0 },
    :regex      => /Stepping with deliberation, you wheel into a leaping spin\!/,
    :usage      => "spinkick"
  },
  "thrash"           => {
    :short_name => "thrash",
    :type       => :assault,
    :cost       => { stamina: 15 },
    :regex      => /You rush .+, raising your .+ high to deliver a sound thrashing\!/
  },
  "twin_hammerfists" => {
    :short_name => "twinhammer",
    :type       => :setup,
    :cost       => { stamina: 7 },
    :regex      => /You raise your hands high, lace them together and bring them crashing down towards the .+\!/,
    :usage      => "twinhammer"
  },
  "volley"           => {
    :short_name => "volley",
    :type       => :area_of_effect,
    :cost       => { stamina: 20 },
    :regex      => /Raising your .+ high, you loose (?:arrow|bolt) after (?:arrow|bolt) as fast as you can, filling the sky with a volley of deadly projectiles\!/
  },
  "whirling_blade"   => {
    :short_name => "wblade",
    :type       => :area_of_effect,
    :cost       => { stamina: 20 },
    :regex      => /With a broad flourish, you sweep your .+ into a whirling display of keen-edged menace\!/,
    :usage      => "wblade"
  },
  "whirlwind"        => {
    :short_name => "whirlwind",
    :type       => :area_of_effect,
    :cost       => { stamina: 20 },
    :regex      => /Twisting and spinning among your foes, you lash out again and again with the force of a reaping whirlwind\!/
  }
}

Class Method Summary collapse

Class Method Details

.[](name) ⇒ Hash?

Retrieves a weapon technique by its name.

Examples:

technique = Weapon["barrage"]
puts technique[:short_name] if technique

Parameters:

  • name (String) —

    the name of the weapon technique

Returns:

  • (Hash, nil) —

    the weapon technique details or nil if not found



196
197
198
# File 'documented/gemstone/psms/weapon.rb', line 196

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

.active?(name) ⇒ Boolean

Deprecated.

Use #buff_active? instead

Checks if a weapon technique is currently active.

Parameters:

  • name (String) —

    the name of the weapon technique

Returns:

  • (Boolean) —

    true if active, false otherwise



246
247
248
249
250
# File 'documented/gemstone/psms/weapon.rb', line 246

def self.active?(name)
  ## DEPRECATED ##
  Lich.deprecated("Weapon.active?", "Weapon.buff_active?", caller[0], fe_log: false)
  buff_active?(name)
end

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

Determines if a weapon technique can be afforded based on the current conditions.

Examples:

puts Weapon.affordable?("charge")

Parameters:

  • name (String) —

    the name of the weapon technique

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

    the number of forcerts available

Returns:

  • (Boolean) —

    true if affordable, false otherwise



217
218
219
220
# File 'documented/gemstone/psms/weapon.rb', line 217

def self.affordable?(name, forcert_count: 0)
  return true if @@weapon_techniques.fetch(PSMS.find_name(name, "Weapon")[:long_name])[:type] == :area_of_effect && Effects::Buffs.active?("Glorious Momentum")
  return PSMS.assess(name, 'Weapon', true, forcert_count: forcert_count)
end

.available?(name, min_rank: 1, forcert_count: 0) ⇒ Boolean

Checks if a weapon technique is available for use based on known status, affordability, and buffs.

Examples:

puts Weapon.available?("flurry")

Parameters:

  • name (String) —

    the name of the weapon technique

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

    the minimum rank required

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

    the number of forcerts available

Returns:

  • (Boolean) —

    true if available, false otherwise



229
230
231
232
233
234
235
236
237
238
239
240
# File 'documented/gemstone/psms/weapon.rb', line 229

def self.available?(name, min_rank: 1, forcert_count: 0)
  return false unless Weapon.known?(name, min_rank: min_rank)
  return false unless Weapon.affordable?(name, forcert_count: forcert_count)
  if @@weapon_techniques.fetch(PSMS.find_name(name, "Weapon")[:long_name])[:type] == :area_of_effect && Effects::Buffs.active?("Glorious Momentum")
    return false unless PSMS.available?(name, true)
  elsif @@weapon_techniques.fetch(PSMS.find_name(name, "Weapon")[:long_name])[:type] == :assault && Effects::Buffs.active?("Ardor of the Scourge")
    return false unless PSMS.available?(name, true)
  else
    return false unless PSMS.available?(name)
  end
  return true
end

.buff_active?(name) ⇒ Boolean

Checks if the buff associated with a weapon technique is currently active.

Examples:

puts Weapon.buff_active?("fury")

Parameters:

  • name (String) —

    the name of the weapon technique

Returns:

  • (Boolean) —

    true if the buff is active, false otherwise



257
258
259
260
261
# File 'documented/gemstone/psms/weapon.rb', line 257

def self.buff_active?(name)
  buff = @@weapon_techniques.fetch(PSMS.find_name(name, "Weapon")[:long_name])[:buff]
  return false if buff.nil?
  Effects::Buffs.active?(@@weapon_techniques.fetch(PSMS.find_name(name, "Weapon")[:long_name])[:buff])
end

.known?(name, min_rank: 1) ⇒ Boolean

Checks if a weapon technique is known and meets the minimum rank requirement.

Examples:

puts Weapon.known?("barrage", 1)

Parameters:

  • name (String) —

    the name of the weapon technique

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

    the minimum rank to check against

Returns:

  • (Boolean) —

    true if known and meets rank, false otherwise



206
207
208
209
# File 'documented/gemstone/psms/weapon.rb', line 206

def self.known?(name, min_rank: 1)
  min_rank = 1 unless min_rank >= 1 # in case a 0 or below is passed
  Weapon[name] >= min_rank
end

.regexp(name) ⇒ Regexp

Retrieves the regex pattern associated with a weapon technique.

Examples:

pattern = Weapon.regexp("charge")

Parameters:

  • name (String) —

    the name of the weapon technique

Returns:

  • (Regexp) —

    the regex pattern for the weapon technique



340
341
342
# File 'documented/gemstone/psms/weapon.rb', line 340

def self.regexp(name)
  @@weapon_techniques.fetch(PSMS.find_name(name, "Weapon")[:long_name])[:regex]
end

.use(name, target = "", results_of_interest: nil, forcert_count: 0) ⇒ String?

Uses a weapon technique against a target, processing the results.

Examples:

result = Weapon.use("barrage", "enemy")

Parameters:

  • name (String) —

    the name of the weapon technique

  • target (String) (defaults to: "") —

    the target of the weapon technique

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

    additional regex patterns to match results

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

    the number of forcerts available

Returns:

  • (String, nil) —

    the result of the weapon use or nil if not applicable



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'documented/gemstone/psms/weapon.rb', line 271

def self.use(name, target = "", results_of_interest: nil, forcert_count: 0)
  return unless Weapon.available?(name, forcert_count: forcert_count)

  name_normalized = PSMS.name_normal(name)
  technique = @@weapon_techniques.fetch(PSMS.find_name(name_normalized, "Weapon")[:long_name])
  usage = technique.key?(:usage) ? technique[:usage] : name_normalized
  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
  )

  results_regex = Regexp.union(results_regex, results_of_interest) if results_of_interest

  usage_cmd = "weapon #{usage}"
  if target.is_a?(GameObj)
    usage_cmd += " ##{target.id}"
  elsif target.is_a?(Integer)
    usage_cmd += " ##{target}"
  elsif target != ""
    usage_cmd += " #{target}"
  end

  usage_result = nil
  if (technique.key?(:assault_rx))
    results_regex = Regexp.union(results_regex, technique[:assault_rx])
    break_out = Time.now() + 12
    loop {
      usage_result = dothistimeout(usage_cmd, 10, results_regex)
      if usage_result =~ /\.\.\.wait/i
        waitrt?
        next
      end
      break if usage_result.eql?(false)
      break if usage_result =~ technique[:assault_rx]
      break if usage_result =~ /^#{name} what\?$/i
      break if usage_result =~ in_cooldown_regex
      break if Time.now() > break_out
      sleep 0.25
    }
  else
    results_regex = Regexp.union(results_regex, technique[:regex], /^Roundtime: [0-9]+ sec\.$/)

    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
  end

  usage_result
end

.weapon_lookups ⇒ Array<Hash>

Returns a list of weapon techniques with their long and short names and costs.

Examples:

Weapon.weapon_lookups.each do |weapon|
  puts weapon[:long_name]
end

Returns:

  • (Array<Hash>) —

    list of weapon techniques with details



180
181
182
183
184
185
186
187
188
# File 'documented/gemstone/psms/weapon.rb', line 180

def self.weapon_lookups
  @@weapon_techniques.map do |long_name, psm|
    {
      long_name: long_name,
      short_name: psm[:short_name],
      cost: psm[:cost]
    }
  end
end