Skip to content

Instantly share code, notes, and snippets.

@sandersch
Last active September 21, 2018 03:22
Show Gist options
  • Save sandersch/2e04a83b3b299dab5c59bb43bca8a28c to your computer and use it in GitHub Desktop.
Save sandersch/2e04a83b3b299dab5c59bb43bca8a28c to your computer and use it in GitHub Desktop.
UAC module with qstrike cost calculation
class UAC
class << self
@@best_move_against ||= {}
@@max_tiered ||= []
def best_move_against
@@best_move_against
end
ATTACK_REGEX = Regexp.union(
/You have excellent positioning against/,
/leaves foe vulnerable to a followup (\w+) attack/,
/Roundtime/,
)
def attack(target, aimed=false)
ensure_proper_stance
ensure_hands_are_ready
if aimed
Ranged.autoaim target, "uac"
else
Ranged.aim "random"
end
waitrt?
attack_move = determine_attack_move_against(target)
if ["jab", max_tier_attack].include?(attack_move) && should_mstrike?
echo "DEBUG: seems ok to mstrike" if $debug_fite
attack_move = "mstrike #{max_tier_attack}"
end
if should_qstrike?(attack_move)
if Spell[506].active?
attack_move = "quickstrike 1 #{attack_move}"
else
secs = determine_qstrike_amount(attack_move)
attack_move = "quickstrike #{secs} #{attack_move}"
end
end
attack_result = dothistimeout "#{attack_move} ##{target.id}", 3, ATTACK_REGEX
if attack_result =~ /You have excellent positioning against/
@@max_tiered << target.id
set_followup_attack_to(target, max_tier_attack)
elsif attack_result =~ /leaves foe vulnerable to a followup (\w+) attack/
echo "DEBUG: Should follow up with: #{$1}" if $debug_fite
@@max_tiered.delete(target.id)
set_followup_attack_to(target, $1)
elsif attack_result =~ /Roundtime/
@@max_tiered.delete(target.id)
echo "DEBUG: Matched roundtime" if $debug_fite
clear_vuln_on target
else
echo "ERROR: didn't detect an unarmed attack"
end
attack_result
end
def clear_vuln_on(target)
best_move_against.delete(target.id)
end
def set_followup_attack_to(target, move)
echo "DEBUG: setting next move against ##{target.id} to #{move}" if $debug_fite
best_move_against[target.id] = move
end
def determine_attack_move_against(target)
best_move = if @@max_tiered.include? target.id
max_tier_attack
else
best_move_against[target.id] || default_attack_move
end
echo "DEBUG: best move against ##{target.id} is #{best_move}" if $debug_fite
best_move
end
def default_attack_move
"jab".tap do |move|
echo "DEBUG: falling back to default attack move of #{move}" if $debug_fite
end
end
def max_tier_attack
"kick".tap do |move|
echo "DEBUG: using max tier attack of: #{move}" if $debug_fite
end
end
def ensure_proper_stance
fput "stance #{proper_stance}" unless checkstance == proper_stance
end
def proper_stance
"offensive"
end
def ensure_hands_are_ready
ensure_ammo_is_stowed
end
def ensure_ammo_is_stowed
if defined?(Ranged) && have_ammo_in_hands?
Ranged.stow_ammo
end
end
def have_ammo_in_hands?
[GameObj.right_hand, GameObj.left_hand].find do |hand|
hand.type.inclde?("ammo") || hand.name.end_with?("arrow")
end
end
def know_how_to_mstrike?
Skills.multiopponentcombat >= 30
end
MINIMUM_MSTRIKE_ON_COOLDOWN_STAMINA = 50
def have_enough_stamina_to_mstrike?
!mstrike_on_cooldown? || # Mstrike Cooldown
checkstamina(MINIMUM_MSTRIKE_ON_COOLDOWN_STAMINA)
end
def no_spell_or_effect_prevents_mstrike?
!haste_active? && !muscles_popped?
end
def haste_active?
Spell[506].active?
end
def mstrike_on_cooldown?
Spell[9005].active?
end
def muscles_popped?
Spell[9699].active?
end
def should_mstrike?
know_how_to_mstrike? &&
no_spell_or_effect_prevents_mstrike? &&
have_enough_stamina_to_mstrike?
end
def mstrike
ensure_proper_stance
ensure_hands_are_ready
waitrt?
attack_move = "mstrike #{mstrike_move}"
if should_qstrike?
attack_move = "quickstrike -1 #{attack_move}"
end
attack_result = dothistimeout attackmove, 3, ATTACK_REGEX
if attack_result
echo "DEBUG: mstrike successful"
attack_result
else
echo "ERROR: failed to mstrike"
nil
end
end
def mstrike_move
"punch"
end
def no_spell_or_effect_prevents_qstrike?
!muscles_popped?
end
MINIMUM_QSTRIKE_STAMINA = 50
# jab = 12
# punch = 13
# grapple = 13
# kick = 14
# mstrike = 100?
QSTRIKE_STAMINA_COST_FOR = {
"jab" => 12,
"punch" => 13,
"grapple" => 13,
"kick" => 14,
"mstrike" => 75, # TODO: maybe figure this out?
}
def stamina_cost_for_move(attack_move)
m = attack_move.split.first
cost = QSTRIKE_STAMINA_COST_FOR.fetch(m)
if attack_move =~ /mstrike/ && mstrike_on_cooldown?
cost += MINIMUM_MSTRIKE_ON_COOLDOWN_STAMINA if mstrike_on_cooldown?
end
echo "DEBUG: estimated stamina cost for #{attack_move} = #{cost}"
cost
end
def determine_qstrike_amount(attack_move)
case (m = attack_move.split.first)
when /mstrike/
-2
when /jab/
-1
when /punch/, /grapple/, /kick/
max_possible = (checkstamina - BUFFER_STAMINA) / stamina_cost_for_move(attack_move)
if max_possible <= 0
echo "ERROR: not enough stamina to qstrike"
0
else
limit = if m =~ /kick/
3
else
2
end
-[limit, max_possible].min
end
end
end
BUFFER_STAMINA = 15
def have_enough_stamina_to_qstrike?(attack_move)
haste_active? ||
checkstamina(
BUFFER_STAMINA + stamina_cost_for_move(attack_move)
)
end
def should_qstrike?(attack_move="mstrike")
no_spell_or_effect_prevents_qstrike? &&
have_enough_stamina_to_qstrike?(attack_move)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment