Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Help getting false result from my Defence script [D&D 4e]

I'm currently writing a script to auto read ac and decide if the attacker has hit. It was going okay until I tried to read the property "ac-ability" this returns saying it is "ac-highest" this then returned as null. For my test "ac-ability" should be 1 I'm not sure if it is a personal error or a bug, has anyone else encountered this?
1419822556
The Aaron
Pro
API Scripter
Hmm. If you can post some code, we can try to help you debug it.
1419823292

Edited 1419828607
Lithl
Pro
Sheet Author
API Scripter
On the 4e sheet, @{ac-ability} is an autocalc field with the value "@{ac-highest}". @{ac-highest} is a select dropdown to choose which ability calculates AC, and might be "@{strength-mod}", "@{constitution-mod}", etc. which are in turn autocalc fields with the value "floor((@{strength}-10)/2)" etc. The API does not attempt to resolve the values of attributes automatically. Therefore, your options are either to figure out which attribute is set to @{ac-highest}, get the value of that ability and perform the appropriate calculations on it, or else use sendChat to perform the calculation for you. The former would look something like this: var character = ... var acAbilityAttribute = getAttrByName(character.id, 'ac-highest').get('current'); // "@{strength-mod}" acAbilityAttribute = acAbility.substring(2, acAbility.length - 5); // "strength" var ability = parseInt(getAttrByName(character.id, acAbilityAttribute).get('current')); // 16 var acAbility = Math.floor((ability - 10) / 2); // 3 The latter would look something like this: var character = ... sendChat('', '/roll @{' + character.get('name') + '|ac-ability}', function(ops) { var acAbility = JSON.parse(ops[0].content).total; }); Note that because sendChat is asynchronous, you need to either implement some kind of lock to wait until the sendChat is complete (such as a semaphore), or else perform the rest of your logic within the sendChat callback function.
1419889120

Edited 1419889251
I've got it working now the problem is returning to formula for for ac-ability the co getAttrByName(character.id, 'ac-highest').get('current'); this isn't the correct syntax I thing it should be: getAttrByName(character.id, 'ac-highest', 'current'; Although this still return null or to be precise '' My solution what to put in a condition to just use a preset formula to find ac-abulity and then changed it for fort, will and ref. If anyone wants the code just say, I'll probably post it at some point in the future anyway. Thanks for your help.
1419892000
Lithl
Pro
Sheet Author
API Scripter
Right, for some reason I was thinking that getAttrByName was returning the attribute object, but it's actually returning the value of the attribute. You should actually be able to omit the third parameter and still get the current value if you like; it's mostly there to specify that you want to retrieve the max value.
ye you're correct the third parameter defaults to current, and you where correct in thinking getAttrByName by name will return the attribute object. For example ac-ten (this is the ac for 10 + 1/2 lvl) it will return "10+@{halfleval}", halfleval will return "floor(@{level}/2)" and level will return level. From this information you can find ac-ten, however this information is not returned when asking for ac-highest which leads me to believe it may be a bug, the same is true for will,fort and ref.
1419908524
Lithl
Pro
Sheet Author
API Scripter
ac-highest should be one of the ability mods. Is something else being returned?
1419935485

Edited 1419935535
if you run it through the roll20 engine it uses the formula but when runing throught the api it just returns null
1419955166

Edited 1419955173
Lithl
Pro
Sheet Author
API Scripter
Could you share your code that's getting the bad result?
Ye sure I haven't quite finished it, theres a few tweaks needed but it works for the most part. I will add that I only a started javascript last week befor that I have only done c properly so sorry for the bad syntax. //commands for GM to attack character and announce damage //--------------------------------------------------------// //For the !attackfunctionn to work 4variabless need to be passed in this order // 1. Defender Token_id // 2. Defence type used (ac/fort/ref/will) // 3. The modifier to hit // 4. The attack roll (xdx+mod : 2d8+5) //This is the macro I use: // !ATTACK @{target|token_id} ?{Defence|ac} ?{mod|0} ?{Attack|xdx+mod} //--------------------------------------------------------// on("chat:message", function(msg) { // Exit if not an api command if (msg.type != "api") return; // Get the API Chat Command var command = msg.content.split(" "); if(command[0] == '!ATTACK') { log(command); //target character var targetToken = getObj("graphic", command[2]); var targetCharacter = targetToken.get("represents"); //algarithem to find targes defence var targetFullDefence = 0; var targetDefence = getAttrByName(targetCharacter, command[3]); targetDefence = targetDefence.split("+"); do { //buffer is used to store remaning callculations var buffer = ""; var i = 0; targetDefence.forEach(function(opts) { //eseption to find half level if(targetDefence[i].search("@{halflevel}") != -1) { targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "level"))/2); } //eseption to find def-highest ((dex/con/char/dex) - 10)/2 else if(targetDefence[i].search("highest}") != -1) { if(targetDefence[i].search("ac") != -1) targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "dexterity") - 10)/2); else if(targetDefence[i].search("fort") != -1) targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "constitution") - 10)/2); else if(targetDefence[i].search("will") != -1) targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "charisma") - 10)/2); else if(targetDefence[i].search("ref") != -1) targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "dexterity") - 10)/2); else log("unusual value for 'highest'} :"+targetDefence[i]); //catchs invaled input } //check if an attribute needs to be found and find it else if(targetDefence[i].search("@{") != -1) { targetDefence[i] = targetDefence[i].replace("@{", ""); targetDefence[i] = targetDefence[i].replace("}", ""); var temp = getAttrByName(targetCharacter, targetDefence[i]); //if temp is another attrabut store it in buffer if(temp.search("@{") != -1) { buffer += temp; buffer += " "; } else // if temp is a value add it to defence { //only add it to defence if the valse is grater then 0 this also cathes null values if(temp > 0) { targetFullDefence += Number(temp); } } } else //if the target is anything else it must be a number so add it to defence { targetFullDefence += Number(targetDefence[i]); } i++; }); //seperate buffer into an array then save it the defence buffer = buffer.replace("+", " "); buffer = buffer.split(" "); targetDefence = buffer; } while(buffer.length > 1); //if buffer is grater then 1 it must have more values to find (there is pertental bug) log("Target Def = "+targetFullDefence); //roll fot attack var attack = randomInteger(20) + Number(command[4]); //if attack if higher then defence attack hit log(attack+">"+targetFullDefence+"(AC)") if(attack > targetFullDefence) { sendChat("AS:","/w GM Target Hit"); var damage = command[5]; var damageTotal = 0; damage = damage.split("+"); var i = 0; log(damage) damage.forEach(function(opts) { if(damage[i].search("d") != -1) { var buffer = damage[i].split("d"); for(i = 0; i < buffer[0]; i++) damageTotal = randomInteger(Number(buffer[1])); } else { damageTotal += Number(damage[i]); } }); sendChat("","/w GM "+damageTotal+" Damage Delt"); } else //else miss { sendChat("(AttckScript)","/w GM Attacker Missed"); } } }) This is the whole command in the while loop I use to translate the command into the numbers I put this exeption in to avoind the error: else if(targetDefence[i].search("highest}") != -1) { if(targetDefence[i].search("ac") != -1) targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "dexterity") - 10)/2); else if(targetDefence[i].search("fort") != -1) targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "constitution") - 10)/2); else if(targetDefence[i].search("will") != -1) targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "charisma") - 10)/2); else if(targetDefence[i].search("ref") != -1) targetFullDefence += Math.floor(Number(getAttrByName(targetCharacter, "dexterity") - 10)/2); else log("unusual value for 'highest'} :"+targetDefence[i]); //catchs invaled input } This find the defence used then calculates the ability modifier this avoids having to directly look at "ac-highest"
This is an example of the specific code i use to look at the attributes var test = getAttrByName(targetCharacter, "ac"); log(test); //"@{ac-ten}+@{ac-ability}+@{ac-armor}+@{ac-class}+@{ac-feat}+@{ac-enh}+@{ac-misc}+@{ac-misc2}" test = getAttrByName(targetCharacter, "ac-ability"); og(test); //"@{ac-highest}" test = getAttrByName(targetCharacter, "ac-highest"); log(test); //"" test = getAttrByName(targetCharacter, "ac-ten"); log(test); //"10+@{halflevel}" test = getAttrByName(targetCharacter, "halflevel"); log(test); //"floor(@{level}/2)" test = getAttrByName(targetCharacter, "level"); log(test); //"5" As you can see "ac-highest" is the only one thing that retuns a null value irelevent of its cotent
1419960924
Lithl
Pro
Sheet Author
API Scripter
Hmm, that's odd. If you change the selection for ac-highest, does it still return an empty string? I suspect this is an issue with select attributes having their defaults handled differently from input attributes.
Either max or current it still return null, and its the same for all defences.
1419974584
Lithl
Pro
Sheet Author
API Scripter
I don't mean changing between max and current (max should be an empty string regardless, that's expected), I mean changing the selection of the dropdown within the character sheet and trying again.
oh right well I can't force it to a value directly but I can change the associated attribute and still returns "". I've also tried other characters and it still returned a null value.
1419977421
Lithl
Pro
Sheet Author
API Scripter
Okay, that's strange. Even if there was an issue with select dropdowns and default values, you should be getting a result after changing the value on the sheet.