Welcome to the Achaea Forums! Please be sure to read the Forum Rules.

Bard Combat macro/script design

BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
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?


  • AntoniusAntonius Posts: 4,193Member @@ - Legendary Achaean
    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.
  • AntoniusAntonius Posts: 4,193Member @@ - Legendary Achaean

    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 antonius.target.shield or antonius.target.rebounding then
    		table.insert(commands, "raze " .. antonius.target.name)
    		if affstrack.score.deaf == 100 then
    			if antonius.voicecraft.balance() then
    				table.insert(commands, antonius.voicecraft.songcommands[affs.song] .. " " .. antonius.target.name)
    			elseif queue or antonius.queueing.anyqueued("class") then 
    				send("queue add class " .. antonius.voicecraft.songcommands[affs.song] .. " " .. antonius.target.name, false)
    		table.insert(commands, "jab " .. antonius.target.name .. " " .. 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[affs.song] .. " " .. antonius.target.name)
    		-- 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[affs.song] .. " " .. antonius.target.name, 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.

  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    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.

  • RouillierRouillier Posts: 39Member ✭✭ - Stalwart
    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?
  • AntoniusAntonius Posts: 4,193Member @@ - Legendary Achaean
    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.
  • AtalkezAtalkez Posts: 4,047Member, Secret Squirrel @@ - Legendary Achaean
    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!

    You hug Aurora compassionately.
  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    Alright, I think I have done something wrong. I pasted your scripts in. The alias works fine, but the 2 scripts both show buggy.

  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    It says it's attempting to index global 'antonius' a nil value.

  • AhmetAhmet Wherever I wanna bePosts: 3,302Member @@ - Legendary Achaean
    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.
  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    Thanks. Now to try it out.

  • AntoniusAntonius Posts: 4,193Member @@ - Legendary Achaean
    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 bePosts: 3,302Member @@ - Legendary Achaean
    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.
  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    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.

  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    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.

  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    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. 

  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    Won't be quite as elegant as yours, but it'll do for now.

  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    @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? 

  • AntoniusAntonius Posts: 4,193Member @@ - Legendary Achaean
    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.
  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    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.

  • DochithaDochitha Posts: 1,061Member ✭✭✭✭✭ - Grand Achaean
    @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.
  • BorranBorran Posts: 845Member ✭✭✭✭ - Eminent
    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 to Comment.