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

Issue with SWITCH function not working properly

Ok, so what I mean is, it seems to work at random.  It always works right after restarting the sandbox, but while it stays on, it seems to randomly not respect the tested value, and always default to the first item in the list.  The script below is the whole script, normally wouldn't post the whole thing, but something is making this act wonky.  I can change out to three separate if/then statements if I have to... I am calling the API from a macro that is -  !cncAttackV2 @{selected|token_ID} 1 ?{Enter Advantage/Disadvantage/Standard|Standard,S|Advantage,A|Disadvantage,D} @{target|token_id} Here is the script -  on('ready',()=>{ on('chat:message', async function(msg) {//the async keyword denotes this function as an asynchronous function. This is necessary to use the await keyword later // Syntax: !cncAttackV2 <attacker> <weapon #> <advantage> <target> // // <attacker> - The token id of the attacking character // <weapon #> - Number of the weapon slot // <advntage> - // S - Standard attack // A - Advantage attack // D - Disadvantage attack // // Example: !cncAttackV2 @{selected|token_id} 1 S @{target|token_id} var args = msg.content.split(' '); if('!cncAttackV2' !== args.shift() ) { return; } let attackerTokenID = args[0]; let attackerWeaponNumber = args[1]; let attackerAdvantage = args[2]; let attackerTokenObj = getObj("graphic", attackerTokenID); let attackerObj = getObj('character',(attackerTokenObj||{get:()=>{}}).get('represents')); let attackerName = getAttrByName(attackerObj.id,'CharacterName','current'); let attackerWeaponName = getAttrByName(attackerObj.id,'WeaponName_' + attackerWeaponNumber); let attackerWeaponDamage = getAttrByName(attackerObj.id,'WeaponDmg_' + attackerWeaponNumber); let attackerTHBth = parseInt(getAttrByName(attackerObj.id,'WeaponBth_' + attackerWeaponNumber),10); let attackerTHMod = parseInt(getAttrByName(attackerObj.id,'WeaponHitMod_' + attackerWeaponNumber),10); let attackerTHMagic = parseInt(getAttrByName(attackerObj.id,'WeaponHitMagic_' + attackerWeaponNumber),10); let attackerTHMisc = parseInt(getAttrByName(attackerObj.id,'WeaponHitMisc_' + attackerWeaponNumber),10); let attackerDamMod = parseInt(getAttrByName(attackerObj.id,'WeaponDmgMod_' + attackerWeaponNumber),10); let attackerDamMagic = parseInt(getAttrByName(attackerObj.id,'WeaponDmgMagic_' + attackerWeaponNumber),10); let attackerDamMisc = parseInt(getAttrByName(attackerObj.id,'WeaponDmgMisc_' + attackerWeaponNumber),10); let attackerToHitBonus = attackerTHBth + " + " + attackerTHMod + " +" + attackerTHMisc + " + " + attackerTHMagic; let attackerToHitBonusTotal = attackerTHBth + attackerTHMod + attackerTHMagic + attackerTHMisc; let attackerDamageBonus = attackerDamMod + " + " + attackerDamMisc + " + " + attackerDamMagic; let toHitRoll = 0; let dieResult1 = await new Promise((resolve,reject)=>{ sendChat(msg.who, '/roll 1d20', function(ops) { let rollResult = JSON.parse(ops[0].content); resolve(rollResult.total); }); }); let dieResult2 = await new Promise((resolve,reject)=>{ sendChat(msg.who, '/roll 1d20', function(ops) { let rollResult = JSON.parse(ops[0].content); resolve(rollResult.total); }); }); sendChat("Combat Computer", "Ad - " + attackerAdvantage) switch(attackerAdvantage) { case 'S': toHitRoll = dieResult1; break; case 'A': if (dieResult1 >= dieResult2) { toHitRoll = dieResult1; sendChat("Combat Computer","Advantage Die Roll: " + dieResult1 + " / " + dieResult2); } else { toHitRoll = dieResult2; } break; case 'D': if (dieResult1 <= dieResult2) { toHitRoll = dieResult1; sendChat("Combat Computer","Disadvantage Die Roll: " + dieResult1 + " / " + dieResult2); } else { toHitRoll = dieResult2; }         break; }; let toHitTotal = toHitRoll + attackerToHitBonusTotal; let ToHitResult = attackerName + " is attacking with a " + attackerWeaponName + ". To hit roll: " + toHitRoll + " + " + attackerToHitBonus + " Total: " + toHitTotal; sendChat("Combat Computer", ToHitResult); let targetTokenID = args[3]; let targetTokenObj = getObj("graphic", targetTokenID); let targetObj = getObj('character',(targetTokenObj||{get:()=>{}}).get('represents')); let targetArmorAC = parseInt(getAttrByName(targetObj.id,'ArmorAC','current'),10); let targetShieldAC = parseInt(getAttrByName(targetObj.id,'ShieldAC','current'),10); let targetModAC = parseInt(getAttrByName(targetObj.id,'ModAC','current'),10); let targetMagicAC = parseInt(getAttrByName(targetObj.id,'MagicAC','current'),10); let targetMiscAC = parseInt(getAttrByName(targetObj.id,'MiscAC','current'),10); let targetAC = 10 + (targetArmorAC + targetShieldAC + targetModAC + targetMagicAC + targetMiscAC); let targetHP = parseInt(targetTokenObj.get("bar1_value")); let tokenAC = parseInt(targetTokenObj.get("bar2_value")); //toHitRoll = 20; if (toHitRoll == 20) { sendChat("Combat Computer", attackerName + " scored a critical hit!"); let baseDamage = await new Promise((resolve,reject)=>{ sendChat(msg.who, '/roll ' + attackerWeaponDamage, function(ops) { let rollResult = JSON.parse(ops[0].content); resolve(rollResult.total); }); }); let criticalDamage = await new Promise((resolve,reject)=>{ sendChat(msg.who, '/roll ' + attackerWeaponDamage, function(ops) { let rollResult = JSON.parse(ops[0].content); resolve(rollResult.total); }); });     baseDamage += attackerDamMod + attackerDamMagic + attackerDamMisc     criticalDamage += attackerDamMagic     let totalDamage = baseDamage + criticalDamage     sendChat("Combat Computer","Damage - Base: " + baseDamage + " Critical: " + criticalDamage + " Total: " + totalDamage)             let targetHP = parseInt(targetTokenObj.get("bar1_value"))     targetTokenObj.set("bar1_value", targetHP - totalDamage) } else { if (toHitTotal >= tokenAC){ sendChat(msg.who, "/roll "+attackerWeaponDamage, function(ops) { let rollResult = JSON.parse(ops[0].content); let dieResult = rollResult.total sendChat("Combat Computer", attackerName + " scored a hit!!") let totalDamage = dieResult + attackerDamMod + attackerDamMagic + attackerDamMisc sendChat("Combat Computer", "Base Damage: " + dieResult + " + " + attackerDamageBonus + " Total: " + totalDamage) let targetHP = parseInt(targetTokenObj.get("bar1_value")) targetTokenObj.set("bar1_value", targetHP - totalDamage) }); } else { sendChat("Combat Computer", attackerName + " failed to score a hit.") }         } }); });
oh, and you can see I put in a sendChat function to show what the value of the attackerAdvantage variable is, and it show properly as either S, A, or D
1597973860
GiGs
Pro
Sheet Author
API Scripter
After this line var args = msg.content.split(' '); put something like this line log(args.map((a, i) => `arg ${i}: ${a}`).join('; ')); This will show what the actual args are - thats the first thing to check. You want to make sure args[2] has the correct value, among other things.
1597977874
GiGs
Pro
Sheet Author
API Scripter
This is a complex script with lots of variables. Do you actually need to grab all of them? For instance you are building an attack bonus from several different attributes-  but doesn't the character sheet already have a calculated attack bonus? Likewise damage and defence attributes. If you can simplify the number of sheet calls it will make it easier to track down the problem's cause.
1597978315

Edited 1597978359
this doesn't pertain to your question and it doesn't really matter much here since the array size is so small, but i'd advise in general against using Array.shift().  it has a linear time complexity.  if you want that functionality either use a circular buffer or linkedlist implementation.
Did some testing and I put a log inside each switch statement and it seems to be hitting it.  For obv. reasons I did delete big chunk of your code and just left the switch statement in tact along with the die rolls needed.  Can you clarify what makes you think it's not hitting the correct case block?  Maybe the error is elsewhere in your code.
1598024968
David M.
Pro
API Scripter
Looks like you might be running into an issue with too many rapid fire sendChats. I added the following log (bold text):                         case 'A':      log("Advantage Die Roll: " + dieResult1 + " / " + dieResult2);     if (dieResult1 >= dieResult2) { toHitRoll = dieResult1; sendChat("Combat Computer","Advantage Die Roll: " + dieResult1 + " / " + dieResult2);     } else { toHitRoll = dieResult2;     }     break; For the cases where advantage is "seemingly" not being used (that line not appearing in the chat window), the log is showing that the highest of two dice is actually being calculated properly, and toHitRoll is displaying the highest value in the subsequent sendChat. It is likely that the last sendChat is often still processing when you make the call to show the advantage/disadvantage dice, and the latter is being ignored. I'd try building your output string completely and then making a single call to sendChat at the end.  
I got it, and boy do I feel dumb.  It was randomly displaying in the chat window because...  When testing to see which die was higher, I was sending chat, but on the else statement I was not!!!  LOL  Sometimes you just have to walk away and when you come back it is plainly obvious!
So, yes, in the end I will be crafting a single message either using /direct with HTML or using a roll template.  Was doing it this way for now during the initial script creation. David M. said: Looks like you might be running into an issue with too many rapid fire sendChats. I added the following log (bold text):                         case 'A':      log("Advantage Die Roll: " + dieResult1 + " / " + dieResult2);     if (dieResult1 >= dieResult2) { toHitRoll = dieResult1; sendChat("Combat Computer","Advantage Die Roll: " + dieResult1 + " / " + dieResult2);     } else { toHitRoll = dieResult2;     }     break; For the cases where advantage is "seemingly" not being used (that line not appearing in the chat window), the log is showing that the highest of two dice is actually being calculated properly, and toHitRoll is displaying the highest value in the subsequent sendChat. It is likely that the last sendChat is often still processing when you make the call to show the advantage/disadvantage dice, and the latter is being ignored. I'd try building your output string completely and then making a single call to sendChat at the end.  
The sheet does have a calculated field, but when trying to use it, it isn't found.  I am using the existing C&C sheet right now, but am also working on one of my own.  That is slow going, I am much better at JavaScript than HTML/CSS.  But getting there...  One of the things I haven't gotten to, but have looked ahead at are the repeating fields, and, not sure I quite have that figured out yet.  One thing though, I want to display the bonuses/penalties along side the die roll result.  If I use HTML with /direct, I think I can emulate the way Roll20 displays the result, as a tool tip, or whatever they call that today.   GiGs said: This is a complex script with lots of variables. Do you actually need to grab all of them? For instance you are building an attack bonus from several different attributes-  but doesn't the character sheet already have a calculated attack bonus? Likewise damage and defence attributes. If you can simplify the number of sheet calls it will make it easier to track down the problem's cause.