Bard Combat macro/script design

edited February 2016 in Bard
I'm currently trying to setup aliases, keyboards, and macros so that I can get started on training for combat, but I've always guys that your initial alias setup sets the pace for your learning curve. But every time I think I have a working design, there is one aspect I'm missing. How do you setup your macros to handle venoms, voicecraft, targetting, and tunesmithing without having to do 4 things every standard balance?

 My most recent system incarnation has an alias to toggle for tunesmithing for all following jabs, a 3-letter alias to handle venom and voice at the same time, limb targetting with the numpad, and a click able menu to play harmonics (and display decay time). The issue with this is darting between the letter keys and the numpad every balance and the fact that I can't use jab and voice independent of one another if the balance times are different. Any suggestions?


  • I'll throw some actual code up when I get home (leaving work now!), but making use of queueing (eqbal for jab, class for songs) is going to be your best bet.
  • Ok, so this is the basis of my Bard offense:

    antonius.voicecraft = antonius.voicecraft or {
    	tunesmithing = "pesante"
    antonius.voicecraft.balance = function()
    	for _, v in ipairs(gmcp.Char.Vitals.charstats) do
    		if string.starts(v, "Voice:") then
    			return string.match(v, "Voice: (%a+)") == "Yes"
    	return false
    antonius.voicecraft.sing = function(song)
    	local song = antonius.voicecraft.afftosong[song] or song
    	antonius.queueing.queue("class", "add", "sing " .. song .. " at &tar", true)
    antonius.voicecraft.songcommands = {
    	epic = "recite epic at",
    	limerick = "sing limerick at",
    	maqam = "sing maqam at",
    	haiku = "recite haiku at ",
    	isorhythm = "sing isorhythm at",
    	fugue = "sing fugue at",
    	solo = "sing solo at",
    	poem = "recite poem at",
    	pastorale = "sing pastorale at",
    	noise = "sing noise at",
    	gimmegimme = "chant gimmegimme at",
    	ditty = "sing ditty at",
    	requiem = "sing requiem at",
    	ode = "recite ode at",
    	qasida = "sing qasida at",
    	passion = "sing passion at",
    	chant = "sing chant at",
    	tremolo = "sing tremolo",
    	vibrato = "sing vibrato",
    	cantata = "sing cantata at",
    	dwinnu = "chant dwinnu"
    antonius.voicecraft.afftosong = {
    	impatience = "limerick",
    	clumsiness = "maqam",
    	confusion = "haiku",
    	claustrophobia = "isorhythm",
    	nausea = "poem",
    	generosity = "gimmegimme",
    	epilepsy = "ditty",
    	paranoia = "requiem",
    	paralysis = "epic",
    	addiction = "ode",
    	anorexia = "qasida",
    	stupidity = "passion"
    antonius.voicecraft.modifiers = {
    	a = "accentato",
    	p = "pesante"
    antonius.voicecraft.attack = function(modifier, queue)
    	local queue = queue == nil and true or queue
    	local affs = antonius.voicecraft.affs()
    	-- if we've got a modifier on the alias, set tunesmithing accordingly (to be used for all subsequent jabs)
    	if modifier and antonius.voicecraft.modifiers[modifier] then
    		antonius.voicecraft.tunesmithing = antonius.voicecraft.modifiers[modifier]
    	local commands = antonius.wielding.wield(antonius.wielding.lookup.rapier, antonius.wielding.lookup.shield, nil, false)
    	table.insert(commands, "tunesmith " .. antonius.wielding.lookup.rapier .. " " .. antonius.voicecraft.tunesmithing)
    	if or then
    		table.insert(commands, "raze " ..
    		if affstrack.score.deaf == 100 then
    			if antonius.voicecraft.balance() then
    				table.insert(commands, antonius.voicecraft.songcommands[] .. " " ..
    			elseif queue or antonius.queueing.anyqueued("class") then 
    				send("queue add class " .. antonius.voicecraft.songcommands[] .. " " .., false)
    		table.insert(commands, "jab " .. .. " " .. antonius.targetting.bodypart .. " " .. affs.venom)
    		-- if we have both balances, we'll just send the song as part of the attack alias
    		if antonius.voicecraft.balance() and antonius.bals.bal then
    			table.insert(commands, antonius.voicecraft.songcommands[] .. " " ..
    		-- otherwise if we're queueing (i.e. not a state dependent update) or have a song already queued, queue on class balance
    		elseif queue or antonius.queueing.anyqueued("class") then 
    			antonius.queueing.queue("class", "add", antonius.voicecraft.songcommands[] .. " " .., true)
    	return commands
    antonius.voicecraft.affs = function()
    	local song = nil
    	local venom = nil
    	local leftaff = antonius.attacks.left
    	local rightaff = antonius.attacks.right
    	-- if we can use a song for the first affliction, do that, otherwise use a venom for it
    	if antonius.voicecraft.afftosong[leftaff] then
    		song = leftaff
    		venom = leftaff
    	-- if we can use a song for the second affliction, do so if: we aren't using a song yet, we can't use a venom for this affliction (e.g. impatience or confusion), or the first affliction is paralysis (jab for curare instead!)
    	if antonius.voicecraft.afftosong[rightaff] and (song == nil or antonius.envenom.afftovenom[rightaff] == nil or song == "paralysis") then
    		venom = leftaff
    		song = rightaff
    		venom = rightaff
    	if song == nil then
    		antonius.echo("Impossible venom and song combination. Song defaults to paralysis.")
    		song = "paralysis"
    	return {song = antonius.voicecraft.afftosong[song], venom = antonius.envenom.afftovenom[venom]}

    This is how I handle selecting afflictions:

    Alias pattern: ^(no|ac|cur|dar|del|dig|eps|ept|eup|eur|gec|kal|lar|monk|oc|pre|sli|var|ver|voy|xen|imp|con)(no|ac|cur|dar|del|dig|eps|ept|eup|eur|gec|kal|lar|monk|oc|pre|sli|var|ver|voy|xen|imp|i|con|c)?$
    Alias code: antonius.envenom.envenom(matches[2], matches[3])
    antonius.envenom = antonius.envenom or {}
    antonius.envenom.shortvenomtoaff = {
    	ac = "stupidity",
    	cur = "paralysis",
    	dar = "darkshade",
    	del = "sleep",
    	dig = "shyness",
    	eps = "crippledleg",
    	ept = "crippledarm",
    	eup = "nausea",
    	eur = "recklessness",
    	gec = "slickness",
    	kal = "asthma",
    	lar = "dizziness",
    	monk = "disloyalty",
    	oc = "blindness",
    	pre = "sensitivity",
    	sli = "anorexia",
    	var = "addiction",
    	ver = "weariness",
    	voy = "voyria",
    	xen = "clumsiness",
    	imp = "impatience",
    	i = "impatience",
    	no = "nothing",
    	con = "confusion",
    	c = "confusion"
    antonius.envenom.afftovenom = {
    	stupidity = "aconite",
    	paralysis = "curare",
    	darkshade = "darkshade",
    	sleep = "delphinium",
    	shyness = "digitalis",
    	crippledleg = "epseth",
    	crippledarm = "epteth",
    	nausea = "euphorbia",
    	recklessness = "eurypteria",
    	slickness = "gecko",
    	asthma = "kalmia",
    	dizziness = "larkspur",
    	disloyalty = "monkshood",
    	sensitivity = "prefarar",
    	deaf = "prefarar",
    	anorexia = "slike",
    	addiction = "vardrax",
    	weariness = "vernalius",
    	voyria = "voyria",
    	clumsiness = "xentio",
    	nothing = "nothing"
    antonius.envenom.envenom = function(left, right, report)
    	local leftaff = antonius.envenom.shortvenomtoaff[left]
    	local rightaff = antonius.envenom.shortvenomtoaff[right]
    	local report = report == nil and true or report
    	if ssc.isdragon() then
    		local leftvenom = antonius.envenom.afftovenom[leftaff]
    		local rightvenom = antonius.envenom.afftovenom[rightaff]
    		if(left_venom) then
    			send("envenom claws with " .. left_venom)
    		if(right_venom) then
    			send("envenom claws with " .. right_venom)
    	elseif ssc.inslowcuringmode() then
    		if left_venom ~= "nothing" then
    			send("envenom left with " .. left_venom)
    		if right_venom ~= "nothing" then
    			send("envenom right with " .. right_venom)
    		antonius.attacks.left = leftaff
    		antonius.attacks.right = rightaff
    		if report then
    			antonius.echo("Afflictions are now " .. leftaff .. " and " .. rightaff .. ".")
                    -- update anything that's already queued to use the new afflictions
    		antonius.attacks.attack(nil, false)

    I've been thinking for a while I could do with a better way of selecting afflictions, though; for the normal combinations six letter combos are just about okay, but sometimes my ability to type does fail me. Using all of that is just a case of entering my attack alias: 'atk', though I can add a modifier to that to do certain conditional things; for Bard, the current modifiers are a (for accentato) and p (for pesante), so I can do 'atka' when I want to switch to using accentato jabs (and it will use that on all future jabs until changed) or 'atkp' to switch to pesante.

  • Thank you. I'm going to start with what you have. I think I can abbreviate each affliction down to 1 letter/symbol, so I'll start modding there.  

    Eventually, I would like to build an affliction tracker menu that highlights red based on whether the target has an affliction, then goes yellow if it's possibly cured, and green if confirmed cured. And you could click the affliction on the menu and it will figure the best way to afflict based on balances, and deliver the affliction.. but as of now that is but a dream.

  • Is this:
    antonius.voicecraft.balance = function()
    	for _, v in ipairs(gmcp.Char.Vitals.charstats) do
    		if string.starts(v, "Voice:") then
    			return string.match(v, "Voice: (%a+)") == "Yes"
    	return false
    How you track your voice balance?
  • That's how I check if I currently have voice balance, though I don't track it in a persistent variable, mostly because I don't have balance tracking incorporated into my server side curing yet.
  • Yeah, you need to be able to use voice balance independently of jab. That's going to be the biggest thing to working towards a lock as a Bard.

    If you're tying your voice balance to your jab only, you're losing your afflicting speed!

    Penwize has cowardly forfeited the challenge to mortal combat issued by Atalkez.
  • Alright, I think I have done something wrong. I pasted your scripts in. The alias works fine, but the 2 scripts both show buggy.

  • It says it's attempting to index global 'antonius' a nil value.

  • AhmetAhmet Wherever I wanna be
    Borran said:
    It says it's attempting to index global 'antonius' a nil value.
    On the line before antonius.envenom = put

    antonius = antonius or {}
    Huh. Neat.
  • Thanks. Now to try it out.

  • Oh, yeah, that's a tiny part of my entire system. It was more to give you an idea of how you could do it (and borrow parts of the logic), not to just paste in and have it work. There's far far too much code for me to just dump on the forums and have it make sense for anybody, and for me to make sure there aren't any dependencies on other parts of my system.
  • AhmetAhmet Wherever I wanna be
    Ya there's probably other dependancies but that line should fix the base issue he was having, if he wants to adapt it all.
    Huh. Neat.
  • Alright.. I have the alias, but when I do the alias, it does nothing. And I know the trigger part is working because I added an echo that worked, but something else isn't.

  • I'll figure it out. It does have a lot of checks involved- check rapier, check shield, check rebounding.. While I would like to eventually have those, I don't have a real affliction tracker so it's probably looking at me like I'm retarded.

  • Sorry, didn't mean to assume- I pasted it, now I'm trying to reverse-engineer the parts that call for other parts of your system and gut them. I think I'll just throw raze/dwinnu as another affliction and have it called in the script. 

  • Won't be quite as elegant as yours, but it'll do for now.

  • @Antonius, I'm sorry to keep hounding you on this- you're being helpful and I just keep having more questions.

     I'm trying to simplify your antonius.envenom.envenom function by taking out the dragoncheck and the slowcuring check. This is what I have so far: 

    antonius.envenom.envenom = function(left, right)

    local leftaff = antonius.envenom.shortvenomtoaff[left]

    local rightaff = antonius.envenom.shortvenomtoaff[right]

    antonius.attacks.left = leftaff

    antonius.attacks.right = rightaff


    Does that look right to you, or have I gutted something I need? 

  • That code looks right, though it could be simplified a bit and it's probably going to error out when it actually runs. The antonius.attacks namespace is declared in an entirely different script that I haven't included (in this thread, though I did post some of it in another thread). Though you're probably better off just coming up with your own variable names, to be honest, rather than trying to keep my namespaced ones.
  • Thanks again for all your help. I'm going to try to setup a serpent script for this first and come back to this project after. It should be easy to add voicecraft afterwards.

  • @Borran you can try to simplify your system down to things that you actually use. No need to index all the venoms and possible jabs cos you likely only going to use a few of them in combat.
  • I've always preferred the train of thought that if you're prepared, you can adapt to any situation, so I'll keep all the afflictions, just in case.

Sign In or Register to comment.