Knight Limb Counter

I haven't really been playing much at all recently, but figured I'd stop being lazy and strip down my target tracker/limb counter to release. I'm not charging for it, I'll just stick the link below and if people want to try it out they're more than welcome to do so. It's probablydefinitely not the nicest code in the world, there was probably a better way to achieve some of the things I wanted to achieve, but it works (for me, it's possible I missed a bug or two in the fresh profile I tried it on).

What does it do?

- Tracks for multiple targets.

Each target is essentially an object (I think the correct Lua term is a dictionary?) with a number of properties. It tracks their name, the number of individual slashes necessary to break, then the actual counts for each of their limbs: head, torso, left leg, right leg, left arm, right arm. It also tracks - via the in-game targetting and the SETTARGET command (plus a trigger) - whether or not the target is an adventurer; I use this for determining whether I want to add venoms to the doubleslash syntax on my attack alias.

- Rough estimates from limb probe (Sawbones trait).

This currently only works one way. If you think you haven't hit their limb at all, and limb probe says it's "Heavily damaged", it's going to adjust the current count for that limb upwards to roughly the percentage I think that term corresponds to (it's around 80% from my testing). Similarly, if it says "Heavily damaged" and the number of hits is non-zero but below 80%, it will also adjust the count upwards. However, if you think you've got it fully prepped, and it says "Lightly damaged", it won't adjust down. The one exception to this is "Perfect health", which will set the count back to 0.

- Three second warnings after the last salve application

Will tell you when three seconds has passed since the person last applied, and what they applied the salve to. Doesn't have any checks on it, and isn't limited to your current target. It will pick up literally every application that you see (I will probably change this at some point).

- Resets the count for a limb four seconds after a salve is applied to the necessary bodypart, and only if the counter thinks you've actually broken one of those limbs.

So if they apply restoration to their legs, and you think their left leg is broken, four seconds after that application the count for their left leg will reset to 0. If, however, they apply to their legs before it thinks

- Integrates with Svo's custom prompt

It sets up a couple of custom prompt tags that you can use if you want to. The most important one is @limbhits which will provide a colour-coded readout of the current status of their bodyparts plus the number it takes to actually break. White means it's not prepped, orange means it's prepped (two hits/one doubleslash away from break), red means it's broken. The order is left leg/right leg/left arm/right arm/head/torso - if you want a different order there's a function called antonius.targetting.prompt_hits which you'll need to modify.

- Colour codes prepped/broken attack messages.

Much the same as the Svo custom prompt, the attack line is coloured orange when the limb is prepped, red for an attack that actually breaks it. I'm not entirely sure how that's going to work if you already have colours applied to those messages (I don't, personally).

What doesn't it do?

- Estimate number of hits to break for you.

The trigger for ASSESS is there, it just always sets the number of hits to 10. I have a formula that works for (unruned) Soulpiercers about 99% of the time, but I haven't included that. You'll need to get a formula from somewhere else, or do your own testing, to determine those values for you based on your own weapons.

- Have anti-illusion

This is probably the biggest drawback. I had an idea of how I'd implement it, but I never got around to it since it would be a fairly big structural change to the way the entire thing works. Maybe when I start playing again, maybe I'll throw out another release of this at some point that includes this. Absolutely no promises.

- Handle any other attacks.

Strictly your own (double)slashes with regular rapiers (change the trigger lines if you have customised weapons). It won't recognise weapon attacks from another person, it won't recognise any other attack that deals limb damage.


lleg/ll - sets the currently targetted bodypart (antonius.targetting.bodypart) to "left leg"

rleg/rl - sets the currently targetted bodypart (antonius.targetting.bodypart) to "right leg"

larm/la - sets the currently targetted bodypart (antonius.targetting.bodypart) to "left arm"

rarm/ra - sets the currently targetted bodypart (antonius.targetting.bodypart) to "right arm"

head/h - sets the currently targetted bodypart (antonius.targetting.bodypart) to "head"

torso/t - sets the currently targetted bodypart (antonius.targetting.bodypart) to "torso"

nothing - sets the currently targetted bodypart (antonius.targetting.bodypart) to "nothing" (untargetted attacks)

hits <number> - manually overrides the number of hits to break a limb of the current target

hit [limb ]<number> - manually sets the number of hits on the currently targetted limb (if not specified) or the limb specified. Example usage: hit 10 - sets the number of hits on the currently targetted bodypart to 10 for the current target; hit lleg 10 - sets the number of hits for the left leg of the current target to 10.

reset [limb] - resets the count for the specified limb or the currently targetted limb. Example usage: reset - resets the count for the currently targetted limb; reset lleg - resets the count for the left leg of the current target

limbreset - resets the count for every limb of the current target

lp [name] - limbprobes either the current target or the person specified

What do you need to do?

Add a call to the function to your current targetting alias. Should look something like this:[2]). If you use a variable called 'target' currently, that function will also set that for you so you could replace the 'target = matches[2]' line with the function call rather than having both.

Add @limbhits to your Svo custom prompt if you want to, otherwise set up some other way to display the state of your current target. If you want to use the counts elsewhere, the variables to use would be["head"],["torso"],["left arm"], etc. Then for the actual number to break.


Send me a message on the forums with anything like that. I'm happy to try to resolve any issues people are having, consider requests for changes/improvements/additions, etc.


  • Haven't really looked at this for a while. Mostly a combination of extreme laziness and not really having been playing the game.

    However, new version with a couple of changes since somebody asked me about it.

    Should no longer break the Svo prompt if you don't have anything targetted! Sorry, @Platonus, you PM'd me about this ages ago letting me know, and I never got back to you (because you seemed to be the only person using it and figured out the issue yourself).

    Added support for WunderSys' custom prompt in addition to Svo's. It will allow you to use the @target and @limbhits prompt tags, which show the name of the person you're targetting and the current status of their limb hits, respectively. You'll need to restart Mudlet after installing (or call the targetprompts() function) to set up the new tags correctly.
  • After spending ages with Krux trying to figure this out...

    Apparently there's been a change to the message received in Mudlet when you successfully log in to Achaea. As a result, WunderSys is no longer recognising login and not raising its "logged in" event that I'm using to set up the prompt tags for the limb counter. I've messaged @Nemutaur in game about this - didn't have WunderSys installed on the profile I was logged in with at the time so couldn't use your bug reporting alias, sorry!

    Until an official fix is released, changing the pattern for the "Logged in" trigger in WunderSys to "What is your password? Password correct.
    Welcome to Achaea.", still using the Exact match pattern type, should fix it.

  • For any heathen using anything but a Mac maybe, its still its own line for me. I changed it to a substring trigger (why oh why...the horror) for now. Just being lazy with releasing this update.
  • It's something about wether you have compression on, the line is the same but the compression setting in musket decides wether or not it's 1 line, or 2 lines.
  • @Antonius not sure if it is just me or what, but I can't get the SVO prompt to work properly for me. Another issue I'm having is trying to change the targets limb hits. Any ideas as to how I can fix this?
  • @Taurnil:

    Svo prompt: There's a couple of things this could be. What's your custom prompt currently configured as? (You can do vconfig2 then click on the (show) link next to "Custom prompt is in use" to see that - not sure if there's an alias for it.) What exactly are you seeing on your prompt? Is it disappearing entirely (older problem that the newer version should have fixed) or is it not recognising the prompt tag so it just displays @limbhits rather than the text it's supposed to?

    Change the targets limb hits: Do you mean the specific hits for individual limbs or the total number required to break for a target? If it's the latter, you'll need to figure out the number of hits required to break a limb for various amounts of max health for the weapons you have, and update the 'Hit calculation' trigger to set that data; alternatively, you can use the 'hits' alias to manually set that value once you've worked it out in a fight.

    If you have the numbers already and just aren't sure on how to do the coding, shoot me a PM or post here and I'll help you out. I'll probably modify that trigger slightly to have an example (commented out) of how you might go about doing it for people who aren't quite as coding savvy.


    More generally, I'm hoping to have another version to release soon (possibly tomorrow) that adds anti-illusion to the attack and assess triggers. Just want to do some further testing when I get time to make sure server side queueing isn't going to mess things up with the way it's coded.
  • The prompt issue is the latter one, just showing the @limbhits when I add it to my prompt. The other issue works when I do say HITS 14, and then assess again it resets it back to 10. Is there anyway to make it not do that so that I keep the number set until I change it again or something of the like?
  • @Taurnil Ok, I'm at a loss on the custom prompt issue. I created a new Mudlet profile, installed Svo and my limb counter script, and it seems to work okay for me. I'm going to need to see what your custom prompt is currently set to. Enter the 'vconfig2' alias, click on 'view' next to 'Custom prompt is in use', then paste the text that it brings up in the main window here or in a PM, please.

    On the other issue, that's because the Hit calculation (Assess) trigger just sets the hitsneeded value for the assessed target to 10. Probably not necessary since it defaults to 10 when a new target is recognised anyway. I'll try to get a new version up in a couple of hours that no longer does that so you can override it with the 'hits' alias and not revert back on assess. For now, you can just edit the 'Hit calculation' trigger and delete the line that reads "target.hits = hitsneeded".
  • New version with two changes.

    Anti-illusion! Now checks that you've actually used the associated balance before processing an attack against a target or assessing somebody. If you want to add this to your own triggers for other things, you can use antonius.bals.balance_used("bal") and antonius.bals.balance_used("eq") to check whether balance or equilibrium has been used when processing a trigger.

    The Hit calculation trigger no longer sets the number of hits, since it was just always setting it to 10 and that's the default on a newly recognised target anyway. It also has a commented out example of how you might go about writing the code to set the actual number of hits based on the target's maximum health, part of which looks like this:
            local maxhp = tonumber(multimatches[2][3])
    	local hitsneeded = 10 -- default to 10?
    	if maxhp >= 6000 then
    		hitsneeded = 14
    	else if maxhp >= 5000 then
    		hitsneeded = 13
    	else if maxhp >= 4000 then
    		hitsneeded = 12

    That assumes fictional brackets of 6000 or more is 14 hits, 5000 to 5999 is 13, 4000 to 4999 is 12, everything below 4000 would still get set to 10.
  • edited December 2014
    I've just put another new version on Dropbox to fix/improve a couple of things. If you run into any problems just give me a shout; post here, PM me on the forums, or message me in game. I tested this as much as I could, but it's possible there are some things I've missed.

    Change 1: The illusion checks should now work correctly when using the server side balance/equilibrium queues.

    Change 2: I've changed the way that hit calculation in the ASSESS trigger is done. It now calls a function - antonius.targetting.calculate_hits - which takes a single argument, the person's maximum health. The default implementation of this function returns nil, which means that it won't override whatever value is set for that target (or the default of 10).

    This also allows people to provide their own implementation of that function in a separate script object so that custom logic to determine break values won't be removed whenever I put out new versions. In order to do that you'll need to create an event handler for the "antonius targetting loaded" event that creates a new function referenced by antonius.targetting.calculate_hits.

    Note: If you provide a custom implementation to calculate hits it will use that value every time you ASSESS. If you've manually set the number of hits to a different value, it will be changed back when you ASSESS. I'm still thinking about the best way to solve that problem, there may be another release in the next few days with something in that regard.

    If that's something you're going to need to do, and you're not familiar with any of the steps involved, here's how you'd do it:

    Step 1. Open the Scripts window and click on Add Item to create a new script object.

    Step 2. Give your new script object a name (I called mine AntoniusTargettingLoaded).

    Step 3. Enter code that looks similar to this as the body of the script object:
    <pre>function [name_of_script_object]() antonius.targetting.calculate_hits = function(maxhp) if maxhp >= 6000 then return 14 elseif maxhp >= 5000 then return 13 elseif maxhp >= 4000 then return 12 elseif maxhp >= 3000 then return 11 else return 10 end end end </pre> Note: The name of the script object and the name of the function must be exactly the same. If you called your script object AntoniusTargettingLoaded, the first line should be function AntoniusTargettingLoaded().

    Replace the body of the inner function (the if - elseif - ... - end part) with your own logic to calculate the correct values.

    Should look something like this:

    Step 4. Enter "antonius targetting loaded" in the Add User Defined Event Handler: box.

    Step 5. Click on the + button next to that box to add it to the Registered Event Handlers list.

    Step 6. Save your profile and then restart Mudlet.
  • edited March 2015
    Been spending a bit of time trying to set this up. Looks like the last update came before t he big change (scimitars, euphorbia, etc)

    I've swapped out rapiers for scimitar/battleaxe, but it doesn't seem to track my attacks:

    if antonius.bals.balance_used("bal") then
    local target = antonius.targetting.get_target(matches[2])
    target.attacked = matches[3]
    if matches[4] == "a Scimitar of Hawks" then antonius.targetting.add_hit(matches[3], 1,
    elseif matches[4] == "a dwarven battleaxe" then antonius.targetting.add_hit(matches[3], 2,
    if antonius.targetting.is_broken(matches[3], then
    setFgColor(255, 0, 0)
    elseif antonius.targetting.is_prepped(matches[3], then
    setFgColor(255, 170, 0)
    setTriggerStayOpen("Attacking", 0)

    I've set up pretty solid health ranges, but still need to plug them in. Any reason you could think why it won't track my attack lines?

    ^Lightning-quick, you jab (\w+)'s (.*) with (?:a Scimitar of Hawks|a dwarven battleaxe)\.$
    ^You viciously jab (?:a Scimitar of Hawks|a dwarven battleaxe) into (\w+)'s (.*)\.$
    ^You slash into (\w+)'s (.*) with a (?:a Scimitar of Hawks|a dwarven battleaxe)\.$

    then a different trigger for swing, since target/limb positioning are different.

    ^You swing (?:a Scimitar of Hawks|a dwarven battleaxe) at (\w+)'s (.*) with all your might.$

    Got prompt tags set up in WunderSys, but not properly tracking attacks.

  • KlendathuKlendathu Eye of the Storm
    By putting ?: before A Scimitar of Hawks|a dwarven battleaxe, you're telling Mudlet to not capture which weapon. Not sure if that's an issue.

    Tharos, the Announcer of Delos shouts, "It's near the end of the egghunt and I still haven't figured out how to pronounce Clean-dat-hoo."
  • Ah, I didn't know what that did. Knocked it out so it can know to +1 on Scims +2 on Battleaxe. Still, it's not counting on slashes. It does update when I limbprobe. Any ideas @Antonius
  • edited March 2015
    You have a double "a" on the slash line so it won't match, one before the weapons and one inside your grouping for each weapon. can be handy for debugging regex, as it breaks down the pattern for you and shows where it stops matching.
    ^You slash into (\w+)'s (.*) with a (?:a Scimitar of Hawks|a dwarven battleaxe)\.$
  • Thanks, Lideron! Slash seems to be working correctly now. I think the anti illusion bit of it is messing up any queued lines. So like if I wield/slash it won't count that slash, or if a Runeblade fires it won't count that slash. I assume curare.

    Swing doesn't work at all:

    ^You swing (a Scimitar of Hawks|a dwarven battleaxe) at (\w+)'s (.*) with all your might\.$

    if antonius.bals.balance_used("bal") then
    local target = antonius.targetting.get_target(matches[3])
    target.attacked = matches[4]
    if matches[2] == "a Scimitar of Hawks" then antonius.targetting.add_hit(matches[4], 1,
    elseif matches[2] == "a dwarven battleaxe" then antonius.targetting.add_hit(matches[4], 2,
    if antonius.targetting.is_broken(matches[3], then
    setFgColor(255, 0, 0)
    elseif antonius.targetting.is_prepped(matches[4], then
    setFgColor(255, 170, 0)
    setTriggerStayOpen("Attacking", 0)
    I tried playing with Regex101, but I'm not sure what it's telling me. I just get that my pattern does not match subject string for everything.

  • edited March 2015
    You forgot the ?: before the weapons

    ^You swing (?:a Scimitar of Hawks|a dwarven battleaxe) at (\w+)'s (.*) with all your might\.$

  • God damn it.
  • NimNim
    edited March 2015
    He's using that in the lua, though. ?: means to not create a match.

    If you show me what string it's not matching, I can help~
  • Aedin said:
    You forgot the ?: before the weapons

    ^You swing (?:a Scimitar of Hawks|a dwarven battleaxe) at (\w+)'s (.*) with all your might\.$

    Nah, I had updated it. Just can't get it to track.
  • @Mizik: I've noticed some issues with the anti-illusion part, where it won't always correctly identify that balance was used. I suspect it's an issue with the order in which things happen: the trigger lines are occasionally processed prior to the gmcp tables being updated, so both my tracking and GMCP think you're on balance (when in reality you're not). I've got a few ideas on how I might go about fixing that, I've just been slacking on working on my counter since the Knight changes, especially in the last month or so where I haven't been logging in much at all.

    Not related to your actual problem, but something you'll need to consider: if you're adding 1 for scimitars and 2 for battleaxes, you'll need to track that somehow so you know whether to subtract 1 or 2 again on a parried/dodged/rebounded hit. Also make sure that for each of these triggers, you update this bit of code:
    setTriggerStayOpen("Attacking", 0)
    so that the name of the trigger being passed in ("Attacking" in this case) matches the name of the trigger it's being called in.

    The code looks mostly correct. There's one minor issue (probably caused by a typo or being missed when you were making the changes) that shouldn't cause the tracking itself to fail:
    if antonius.targetting.is_broken(matches[3], then
    should be using matches[4] instead.

    Other than that, let's do some basic debugging:

    Stick this at the very start of the code for that trigger: echo(string.format("Local: %s, GMCP: %s", antonius.bals.bal and "1" or "0", gmcp.Char.Vitals.bal))
    Is there anything displayed in the Errors view in Mudlet just after that trigger should fire?

    That will tell you 1. whether or not the trigger is firing at all (if you don't see an echo, there's an issue with the trigger) and 2. what values it has for its internal balance tracking (Local) and GMCP's balance variable. If that's all okay, the Errors view will tell you if there's an issue occurring when the code executes.

Sign In or Register to comment.