After finding Dreaven's scripting videos I have come up with a simple solution it seems.
Code:
=begin
Mechanical Crossbow Combat Script
V 1.1
author: Getho
tags: ranged crossbow combat
For use with a T2 mechanical crossbow (5 bolts).
Checks number of bolts loaded and fills magazine if less than 3.
Will kneel
Will cast 608 if able, will hide if not.
Cocks and fires crossbow.
=end
target = nil
ammo = nil
check_reload = proc{
fput "look in my crossbow"
while line = get
if line =~ /^In the mechanical crossbow you see (.*)\, (.*)\, (.*)\, (.*) and (.*)\.$/
ammo = 5
break
elsif line =~ /^In the mechanical crossbow you see (.*)\, (.*)\, (.*) and (.*)\.$/
ammo = 4
break
elsif line =~ /^In the mechanical crossbow you see (.*)\, (.*) and (.*)\.$/
ammo = 3
break
elsif line =~ /^In the mechanical crossbow you see (.*) and (.*)\.$/
ammo = 2
break
elsif line =~ /^In the mechanical crossbow you see (.*)\.$/
ammo = 1
break
elsif line =~ /^There is nothing in there\.$/
ammo = 0
break
end
end
echo ammo
if ammo <= 2
while ammo < 5
multifput "get 1 bolt from thigh", "load crossbow"
ammo += 1
end
end
}
get_target = proc{
if target == nil
target = GameObj.npcs.find { |npc| npc.name =~ // }
(target = nil) if (target.name =~ /grizzled|ancient/) && (checkbounty !~ /hunt down and kill a particularly dangerous/)
end
}
kneel_prep = proc{
if checkkneeling != true
fput "kneel" until kneeling?
else
end
}
hide_prep = proc{
if checkhidden != true && Spell[608].known? && Spell[608].affordable? && !Spell[608].active?
Spell[608].cast
elsif checkhidden != true
fput "hide" until hiding?
end
}
attack_target = proc{
waitrt?
fput "cock my crossbow"
pause 0.1
waitrt?
fput "stance offensive"
pause 0.1
fput "fire"
pause 0.1
waitrt?
fput "stance defensive"
}
check_reload.call
target = nil if (target.status =~ /dead|gone/)
get_target.call
while target != nil
kneel_prep.call
hide_prep.call until hiding?
attack_target.call if (target != nil) && (target.status !~ /dead|gone/)
sleep 0.1
if target.status =~ /dead|gone/
target = nil
end
end
The next step was to make a loot script that would reload the crossbow. So i made a script that called sloot, once sloot finished it would would pick up bolts one at a time and load them into the crossbow, adding any excess back to the bundle. I accomplished this by taking sloot's gather ammo portions and making a couple tiny modifications. So it's like an sloot inception I guess ... heh. Can't say I fiully understand too much of what's going on.
This will work until I can learn and make something cleaner. The bundle portion of it is really just there as a safety net for when I somehow end up shooting all 5 bolts and reloading without recovering ammo.
Code:
#
# Mechanical Crossbow Support for Sloot
# Author: Getho
#
#
# I blatantly ripped the ammo gather code from sloot and tweaked it a tiny bit to work with my mechanical crossbow.
# ALL PRIASE GOES TO SPIFFYJR
#
# Script will run sloot, when sloot is complete it will pick up each bolt one at a time and load them back into
# the mechanical crossbow. Once the crossbow is full, it should add remaining bolts to the bundle in your quiver.
# The bundle portion is untested and may not work properly.
#
#
#
#
#
#
#
#
# Gets bundle information for ammo
get_bundle_details = proc do |bundle|
details = {
:id => bundle.id
}
put "look at ##{bundle.id}"
while line = get
if line =~ /a strength of (\d+) and a durability of (\d+)/
details[:strength] = $1.to_i
details[:durability] = $2.to_i
elsif line =~ /Each individual projectile will be "([^"]+)"\./
details[:name] = $1.to_s
break
end
end
details
end
waitrt?
Script.start('sloot')
while( running?('sloot'))
pause 1.0
end
sleep 0.25
ammo_name = "bolt"
quiver = GameObj.inv.find { |obj| obj.name =~ /#{UserVars.ammosack}/ }
ammo_noun = nil
if ammo_name =~ /\b(bolt|arrow|dart)\b/
ammo_noun = $1.to_s
else
end
bundles = quiver.contents.find_all do |loot|
loot.type == 'ammo' and
loot.name =~ /bundle/i
end
$sloot_bundles ||= []
$sloot_bundles.delete_if { |sb| not quiver.contents.find { |item| item.id == sb[:id] } }
bundles.each do |bundle|
if $sloot_bundles.find { |sb| sb[:id] == bundle.id }
next
end
$sloot_bundles.push(get_bundle_details.call(bundle))
end
ammo = GameObj.loot.find_all do |loot|
loot.type == 'ammo' and
loot.name =~ /\b#{ammo_name}s?\b/
end
rounds = ammo.length
while rounds > 0
# get ammo first
res = dothistimeout "get #{ammo_noun}", 2, /The bolt is out of your reach\.|You gather|You pick up/
if res =~ /You pick up/
rounds -= 1
sleep 0.2 until GameObj.right_hand.id
fput "load my crossbow"
sleep 0.1
end
if checkright != false
if GameObj.right_hand.name =~ /#{ammo_noun}s/i
details = get_bundle_details.call(GameObj.right_hand)
bundle = $sloot_bundles.find { |bundle| bundle[:name] == details[:name] }
if bundle
fput "put ##{details[:id]} in ##{bundle[:id]}"
end
elsif GameObj.right_hand.name =~ /#{ammo_name}/i
bundle = $sloot_bundles.find { |bundle| bundle[:name] =~ /#{GameObj.right_hand.name}/i }
if bundle
fput "put ##{GameObj.right_hand.id} in ##{bundle[:id]}"
end
end
else
end
end