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
This post has been closed. You can still view previous posts, but you can't post any new replies.

CombatMaster Alpha

Victor B. said: Fabulous Chef, probably be best if you invited me to game and then promoted me to GM after I'm in (temporary).  I can take a look.  Send me a PM with game invite Thanks, Vic. I’ll see if I can do that sometime in the next day or two. Much appreciated. 
I have updated the script to the latest version, and the Concentration status does not apply to tokens, nor does a message trigger... do I need to add the spells to the API before that works? I'm a little lost on what I could be doing wrong...
1595780446
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Hi Inkcharm, I was having the same issues. Look towards the end of the previous page. Victor gives pretty good steps to help understand the procedure.
@Vic, thanks for reaching out in the midst of working on this update I have tried to call for Group Init to reroll at the beginning of the round using CM, but it simply ignores the command when the round starts and proceeds as normal.  I would prefer to use CM's built in Dynamic Initiative, but for a reason unknown to me, Roll20 just started declaring that it was a Possible Infinite Loop one day, even though it had previously been functioning just fine. And again, it does the infinite loop error even if there are only two tokens in the turn order (I've even made sure to clear out any duplicates of those tokens found across other pages, as I know, in the version I was using, going Unconscious would set that character's token as Unconscious on every page, and send a duplicate message per instance, and I thought that they might have been related issues)
1595813496
Victor B.
Pro
Sheet Author
API Scripter
Invite me to game?  PM me invite, let me take a look
I have some questions about auto-adding conditions that require a target. Let's say I have a class ability that I'd like my player to use on an enemy token. Currently, when you set the "spell" condition target setting to true, you're prompted with this whenever you activate it: "Select target tokens to assign this condition and hit the button above when ready." Could a player activate the spell and select a monster as a target, even though (obviously) they don't control the monster token? Or is this GM only? Also, is there a way to have that "select target tokens" thing show up but without auto-applying the spell status marker to the PC? I'm thinking specifically of the paladin's Oath of Vengeance feature, which lets him designate one enemy in a combat as his target. Currently, if I add the Oath of Vengeance condition I've created in CM, it adds the status marker to the paladin token, and prompts the user to select an enemy target. I'd rather not have the status marker on the paladin himself, since that's just clutter and unnecessary (it doesn't require concentration). 
@Victor Sent you an invite, I'll be on roll20 pretty much all day today since I have a session at 6:15 CST, but it will end around 10 CST. 
Victor B., belated thank you for your assistance last week.  After deleting StatusInfo and Combat Tracker, I uploaded CM 2.22 and all is well so far.  Thank you for your hard work on our behalf!
Okay, so currently (after Roll20 was down and came back), Combat Master's Dynamic Initiative is working for me. I turned Show Initiative On, and now, while my API Logs are definitely outputting more information, Roll20 isn't crashing it as an Infinite Loop. It might be a Roll20 issues more than a CM issue, and if it is, I'm afraid of that u.u If you could still give it a look and see what might be influencing these behaviors though, I would greatly appreciate it
1595950152

Edited 1595950218
Victor B.
Pro
Sheet Author
API Scripter
@Jay it's GM only to select targets in part because players don't have access to NPC tokens.  If you allow access, they can see the NPC stat block, which you probably don't want.   For Oath of Vengeance, you don't want that to be a concentration spell,  Make sure concentration is false.  For that one, you simply highlight the target and add the spell.  The caster shouldn't be touched.   And always if a box comes into chat, select target or select caster, simply ignore it if you don't need it.  
Victor B. said: @Jay it's GM only to select targets in part because players don't have access to NPC tokens.  If you allow access, they can see the NPC stat block, which you probably don't want.   For Oath of Vengeance, you don't want that to be a concentration spell,  Make sure concentration is false.  For that one, you simply highlight the target and add the spell.  The caster shouldn't be touched.   And always if a box comes into chat, select target or select caster, simply ignore it if you don't need it.   OK, that's good to know. Thanks, Victor.
Hai hai. After some fiddling with the settings, the sandbox keeps crashing every time I use the command !cmaster --config: TypeError: Cannot set property 'undefined' of undefined TypeError: Cannot set property 'undefined' of undefined at editCombatState (apiscript.js:2298:102) at commandHandler (apiscript.js:1773:13) at apiscript.js:1560:21 at Function.each (/home/node/d20-api-server/node_modules/underscore/underscore.js:188:9) at inputHandler (apiscript.js:1555:19) at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:154:1), <anonymous>:65:16) at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:154:1), <anonymous>:70:8) at /home/node/d20-api-server/api.js:1661:12 at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147)
1596075362
Victor B.
Pro
Sheet Author
API Scripter
use the menu.  !cmaster --main and then click the cog icon
1596223796
Victor B.
Pro
Sheet Author
API Scripter
Version 2.26 found here.&nbsp;&nbsp; <a href="https://github.com/vicberg/CombatMaster" rel="nofollow">https://github.com/vicberg/CombatMaster</a> .&nbsp; One click has been updated to v2.20.&nbsp;&nbsp; Fixed - Various small issues New Functionality - Pathfinder 2 support added for auto-spells.&nbsp; PF2 doesn't use concentration so I'm not checking for it and shouldn't be used.&nbsp;&nbsp;
1596228235
Victor B.
Pro
Sheet Author
API Scripter
v2.27 found here&nbsp; <a href="https://github.com/vicberg/CombatMaster" rel="nofollow">https://github.com/vicberg/CombatMaster</a> Fixed - I had a syntax error in the code I didn't notice before publishing.&nbsp; I've been a bit distracted
1596258301

Edited 1596265618
@Victor, I noticed that spell conditions placed on a target track duration based on the target's turn rather than the caster's. Shouldn't it be tracked on the caster's turn, the way normal targeted conditions work? If a player casts a spell on an NPC that lasts 1 round, that usually means it lasts until the caster's next turn? Currently, it's lasting until the target's next turn instead (so ending earlier than it should). EDIT: Wait, I see, if I set the spell to targeted I target the caster first, then it lets me select the target of the spell. In the gif you can see I'm able to set the spell to track on the caster as it should.
Forgive me for my ignorance if this is covered elsewhere, but I can't find how to add a new initiative using CM. Is this supported so that a new addition has initiative rolled for it?
Mark W. said: Forgive me for my ignorance if this is covered elsewhere, but I can't find how to add a new initiative using CM. Is this supported so that a new addition has initiative rolled for it? To start combat you use:&nbsp;&nbsp;!cmaster --turn,start --main To add more combatants just use it again.&nbsp; I start by drawing a big square around the fight and hitting the start command.&nbsp; When more people join the fight I draw a square around them and hit the start command again and it adds them to the order and sorts it.
Patrick said: Mark W. said: Forgive me for my ignorance if this is covered elsewhere, but I can't find how to add a new initiative using CM. Is this supported so that a new addition has initiative rolled for it? To start combat you use:&nbsp;&nbsp;!cmaster --turn,start --main To add more combatants just use it again.&nbsp; I start by drawing a big square around the fight and hitting the start command.&nbsp; When more people join the fight I draw a square around them and hit the start command again and it adds them to the order and sorts it. Thank you. So it won't change the initiatives in order already?
1596432003

Edited 1596470451
The safest bet for me has been to do as I mentioned above and only add new combatants at the start of a turn.&nbsp; I am not certain, but seem to remember no problems with the initiative order when doing it that way.&nbsp; Tonight we tried having combat master auto roll a new initiative each round to simulate the changing tides of battle and hands of fate.&nbsp; It worked pretty nice in my opinion, but when I added new combatants it did seem to re roll everyone, not that it mattered since it was a new round and they hadn't started on the new rolls yet.
1596434578

Edited 1596434657
Victor B.
Pro
Sheet Author
API Scripter
Group init.&nbsp; Use it to add diff groups of combatants.&nbsp; And always, add them at end of the combat round.&nbsp; Mid flight you'll have to manually adjust the turnorder.&nbsp; Don't expect magic.&nbsp; If you are mid combat round and want everything to magically sort out, won't happen.&nbsp; APIs can't do everything.&nbsp;
Like Patrick, I too find that it's safer to add new combatants at the start of a round. If they're hidden, it's not like the party will know what's going on anyway, and it avoids the possibility of your initiative order getting messed up by adding creatures mid-round.&nbsp;
@Victor, I just noticed that when using a targeted condition with a duration, the marker on the target is removed after the first round instead of remaining until the end of the duration.
1596507341

Edited 1596507491
Victor B.
Pro
Sheet Author
API Scripter
ACK, I'll fix both issues with you
1596516595

Edited 1596516614
@Victor, I made a very small Git PR to change the Regexp from \content to \{{content to avoid an issue with the Hide-Content option for Shaped5e. This is for the autoaddspells function.
1596546150
AquaAlex
Sheet Author
Translator
API Scripter
Looks very cool, started playing with it so far all good
1596554155
Victor B.
Pro
Sheet Author
API Scripter
Juan post your change here and I'll incorporate.&nbsp;&nbsp;
1596569080

Edited 1596569127
Victor B. said: Juan post your change here and I'll incorporate.&nbsp;&nbsp; In line 2800: description = msg . content . match ( / { { content= ( [ ^ \n {} ] * [ ^" \n {} ] ) / ) As I said, this is to avoid hide_content=1 (Hide Content option) to mislead the CM Script (you could also just use a single bracket) With my limited JS knowledge I'll try to pull the level and duration values for the shaped 5e sheet (can't guarantee anything since all I do is follow other scripts by example and try to replicate).
Juan C. said: Victor B. said: Juan post your change here and I'll incorporate.&nbsp;&nbsp; In line 2800: description = msg . content . match ( / { { content= ( [ ^ \n {} ] * [ ^" \n {} ] ) / ) As I said, this is to avoid hide_content=1 (Hide Content option) to mislead the CM Script (you could also just use a single bracket) With my limited JS knowledge I'll try to pull the level and duration values for the shaped 5e sheet (can't guarantee anything since all I do is follow other scripts by example and try to replicate). I've given him access to a full Shaped 5e environment to play in.&nbsp; Your additions can easily be tested by him.
1596603232

Edited 1596604036
This is the most I could do. The values showed up in the debug log, but I couldn't manage to pass the duration or direction attribute to the new spells after being added. The added code is bolded (meh). handleSpellCast = function(msg) { if (debug) { log('Handle Spell Cast') log(msg) } let status = state[combatState].config.status; let concentration = state[combatState].config.concentration; let spellName let description let concentrate = false let spellLevel let duration let durationmult let direction if (status.sheet == 'OGL') { spellName = msg.content.match(/name=([^\n{}]*[^"\n{}])/); spellName = RegExp.$1; description = msg.content.match(/description=([^\n{}]*[^"\n{}])/) description = RegExp.$1; spellLevel = msg.content.match(/spelllevel=([^\n{}]*[^"\n{}])/) spellLevel = RegExp.$1; if (msg.content.includes("{{concentration=1}}")) { concentrate = true } if (!spellLevel &amp;&amp; !concentrate) { return; } } else if (status.sheet == 'Shaped') { spellName = msg.content.match(/title=([^\n{}]*[^"\n{}])/); spellName = RegExp.$1; description = msg.content.match(/{{content=([^\n{}]*[^"\n{}])/); description = RegExp.$1; duration = msg.content.match(/{{duration=.*([^\n{}]\d{1,2})_{1}([A-Z]*)[^"\n{}@][}$]/); duration = RegExp.$1; durationmult = RegExp.$2; if (durationmult.includes("ROUND")) { durationmult = 1 } else if (durationmult.includes("MINUTE")) { durationmult = 10 } else { durationmult = 0 //ONLY ACCOUNT FOR ROUND AND MINUTE DURATIONS, EVERYTHING ELSE IS 0 } if (durationmult == 0) { duration = 1 } else { duration = (duration * durationmult); } if (msg.content.includes("CONCENTRATION")) { concentrate = true } } else if (status.sheet == 'PF2') { spellName = msg.content.match(/header=([^\n{}]*[^"\n{}])/); spellName = RegExp.$1; description = msg.content.match(/desc=([^\n{}]*[^"\n{}])/) description = RegExp.$1; } if (!spellName) { return } if (debug) { log('Spell Name:'+spellName) log('Description:'+description) log('Concentrate:'+concentrate) log('Duration:'+duration) log('Duration Multiplier:'+durationmult) } if (!description) { description = 'None' } if (status.autoAddSpells) { let key = spellName.toLowerCase() let condition = getConditionByKey(key) if (duration &gt;= 1) { direction = -1 } else { direction = 0 } if (typeof condition == 'undefined' &amp;&amp; !getIgnoresByKey(key)) { state[combatState].spells[key] = { name: spellName, key: key, type: 'Spell', icon: 'red', iconType: 'Combat Master', description: description, duration: duration , direction: direction , message: 'None', targeted: false, favorite: false, concentration: concentrate, description: description, addAPI: 'None', addRoll20AM: 'None', addFX: 'None', addMacro: 'None', addPersistentMacro: false, remAPI: 'None', remRoll20AM: 'None', remFX: 'None', remMacro: 'None'
1596613762

Edited 1596613810
Victor B.
Pro
Sheet Author
API Scripter
Juan I'm not going down the path of setting duration/directon from the spells.&nbsp; That's a wildly slippery slope.&nbsp; Especially with OGL sheet which is all over the map in their design.&nbsp; So I'm not going to do it with shaped either for that reason.&nbsp; You are always welcome to your additions upon what I publish.&nbsp; I'll include the content part because that prevents hide content for coming into play.&nbsp;
1596628837

Edited 1596630583
Victor B. said: Juan I'm not going down the path of setting duration/directon from the spells.&nbsp; That's a wildly slippery slope.&nbsp; Especially with OGL sheet which is all over the map in their design.&nbsp; So I'm not going to do it with shaped either for that reason.&nbsp; You are always welcome to your additions upon what I publish.&nbsp; I'll include the content part because that prevents hide content for coming into play.&nbsp; Could you at least tell me what's wrong with the procedure I'm doing (namely if I need to add these values somewhere else?) I wouldn't need too much detail, just some general guidance. This is for personal use, as I understand the difficulties with the other sheets. Don't feel compelled to do so either, as you've already done enough by developing this amazing script as it is.
1596631443
Pantoufle
Pro
Sheet Author
Translator
Hello Victor, sorry if you have answered this in this thread (but 27 pages... wow this is huge :p) : can we use a 2d6 for initiative for non d20 games ? (currently I only see an option to change the d20 dice) Great work, great script! Cheers :)
1596638142

Edited 1596642103
Victor B.
Pro
Sheet Author
API Scripter
@juan, you have the code there and I'm going to assume that it's tested, so I'll incorporate as is.&nbsp; Shaped is a better designed char sheet.&nbsp; All spells have {{spell=1}} making it easy to identify a spell from something else.&nbsp; Duration/direction do not require parsing/fuzzy logic to figure out.&nbsp; OGL on the other hand was an effort done probably early in the life of Roll20, prior to serious APIs, and isn't structured nearly as well.&nbsp; There are some spells with absolutely nothing to identify it as a spell
1596638354
Victor B.
Pro
Sheet Author
API Scripter
@Pantoufle, I'd suggest using Group Initiative, by the Aaron.&nbsp; I was sorely tempted to remove CMs roll initiative functionality and integrate with Group Initiative solely.&nbsp; It does initiative overall much better than CM.&nbsp; You can download, set to 2d6 and then set CM to use group initiative when starting combat.&nbsp;&nbsp;
1596644175
Pantoufle
Pro
Sheet Author
Translator
Oh okay ! That makes sense, thx for the tip :)
Victor B. said: @juan, you have the code there and I'm going to assume that it's tested, so I'll incorporate as is.&nbsp; Shaped is a better designed char sheet.&nbsp; All spells have {{spell=1}} making it easy to identify a spell from something else.&nbsp; Duration/direction do not require parsing/fuzzy logic to figure out.&nbsp; OGL on the other hand was an effort done probably early in the life of Roll20, prior to serious APIs, and isn't structured nearly as well.&nbsp; There are some spells with absolutely nothing to identify it as a spell I second this.&nbsp; And reserve all rights to infinity if multiple voting is allowed.&nbsp; OGL is bone and stone knives.&nbsp; Shaped is a Laser Scalpel.
Victor B. said: @juan, you have the code there and I'm going to assume that it's tested, so I'll incorporate as is.&nbsp; Shaped is a better designed char sheet.&nbsp; All spells have {{spell=1}} making it easy to identify a spell from something else.&nbsp; Duration/direction do not require parsing/fuzzy logic to figure out.&nbsp; OGL on the other hand was an effort done probably early in the life of Roll20, prior to serious APIs, and isn't structured nearly as well.&nbsp; There are some spells with absolutely nothing to identify it as a spell Don't bother with the 'duration' thing, as I did some changes since it was not working before. Now it's working on my side without any issues. I really appreciate what you're doing!!
1596648295
Victor B.
Pro
Sheet Author
API Scripter
Version 2.29 can be found here&nbsp; <a href="https://github.com/vicberg/CombatMaster" rel="nofollow">https://github.com/vicberg/CombatMaster</a> &nbsp;and one click will be updated to it Fixed - Issue with targeted spells - issue with persistent macros&nbsp; New Functionality - Added Juan's changes (thanks!) for Shaped Sheet
1596650253
Victor B.
Pro
Sheet Author
API Scripter
Juan if you've got more changes, let me know and I'll incorporate.&nbsp;&nbsp;
Yeah, I've got some fixes (mostly) for the Regex's since I'm no expert on this kind of stuff (I'm trying though!!) Turns out it was pulling unintended underscores and cutting off the MINUTE/ROUND word by one off (my apologies!), and I didn't define the durationmult with the msg.orig.contents before applying the Regexp, so that's also my fault. Also added a nullcheck for duration and direction (just in case) to return it to default values! Learning from my mistakes though! My apologies! I'll post them in a brief while. 😐
1596655047

Edited 1596655134
Lines 2807 to 2810 (Replacement) duration = msg.content.match(/duration=.*(\d{1,2}[^_"\n{}]*)_{1}([A-Z]+[^"\n{}]*)/); duration = RegExp.$1; durationmult = msg.content.match(/duration=.*(\d{1,2}[^_"\n{}]*)_{1}([A-Z]+[^"\n{}]*)/); durationmult = RegExp.$2; After 2850 (after the description nullcheck): if (!duration) { duration = 1 } if (!direction) { direction = 0 } I was also trying to add the spellLevel, but since it actually has no use, I kinda prefer not to post it. Sorry for any inconveniences this may have caused you!!
1596739124
Victor B.
Pro
Sheet Author
API Scripter
Version 2.30 can be found here&nbsp; <a href="https://github.com/vicberg/CombatMaster" rel="nofollow">https://github.com/vicberg/CombatMaster</a> Fixed - A bug in the adding condition to token that would cause api failure - Updated Juan's shaped code
!cmaster --help gets the scripts disabled I also have issues with going through the turn order.. TypeError: Cannot convert undefined or null to object TypeError: Cannot convert undefined or null to object at Function.entries (&lt;anonymous&gt;) at doTurnCalls (apiscript.js:8623:20) at Timeout._onTimeout (apiscript.js:8039:18) at listOnTimeout (internal/timers.js:549:17) at processTimers (internal/timers.js:492:7)
There is a help icon to use at the top of each menu. In the right hand corner. So just try !cmaster --main and you will see the 1st one. LunaGore said: !cmaster --help gets the scripts disabled I also have issues with going through the turn order.. TypeError: Cannot convert undefined or null to object TypeError: Cannot convert undefined or null to object at Function.entries (&lt;anonymous&gt;) at doTurnCalls (apiscript.js:8623:20) at Timeout._onTimeout (apiscript.js:8039:18) at listOnTimeout (internal/timers.js:549:17) at processTimers (internal/timers.js:492:7)
1596819597
Victor B.
Pro
Sheet Author
API Scripter
!cmaster --help will cause a failure
@Juan_C - have you been able to use CM to set !shaped-at yet?&nbsp; ( <a href="https://bitbucket.org/mlenser/5eshapedscript/wiki/Home#markdown-header-shaped-at" rel="nofollow">https://bitbucket.org/mlenser/5eshapedscript/wiki/Home#markdown-header-shaped-at</a> ) Been trying to code the commands very specifically for Sentry Icon/ Advantage = !shaped-at&nbsp; --advantage Rolling Bomb Icon/ Disadvantage = !shaped-at&nbsp; --disadvantage Back To Normal when Condition is turned off = !shaped-at&nbsp; --normal
1596822499

Edited 1596822518
Yes the error I posted was from using !cmaster --main, I was clicking through turn order to test it out and after the first tokens turn ended it crashed. Sorry for not clarifying that. Kilter said: There is a help icon to use at the top of each menu. In the right hand corner. So just try !cmaster --main and you will see the 1st one. LunaGore said: !cmaster --help gets the scripts disabled I also have issues with going through the turn order.. TypeError: Cannot convert undefined or null to object TypeError: Cannot convert undefined or null to object at Function.entries (&lt;anonymous&gt;) at doTurnCalls (apiscript.js:8623:20) at Timeout._onTimeout (apiscript.js:8039:18) at listOnTimeout (internal/timers.js:549:17) at processTimers (internal/timers.js:492:7)
1596827805

Edited 1596828846
Wolf Thunderspirit said: @Juan_C - have you been able to use CM to set !shaped-at yet?&nbsp; ( <a href="https://bitbucket.org/mlenser/5eshapedscript/wiki/Home#markdown-header-shaped-at" rel="nofollow">https://bitbucket.org/mlenser/5eshapedscript/wiki/Home#markdown-header-shaped-at</a> ) Been trying to code the commands very specifically for Sentry Icon/ Advantage = !shaped-at&nbsp; --advantage Rolling Bomb Icon/ Disadvantage = !shaped-at&nbsp; --disadvantage Back To Normal when Condition is turned off = !shaped-at&nbsp; --normal This would be possible just by using the Add Condition and Remove Condition API to add the marker Shaped5e uses for advantage/disadvantage (green, red by default). You can trigger these additions through token-mod like I did for some other status'. I don't know if it would be possible directly from CM simply because I don't think there's an event observer for it. I haven't tried it. However, I believe the best practice would be to use the auto revert advantage feature, along with the Persistent Macro API for CM, to guarantee your players don't have unintended advantages or disadvantages after the cause-condition disappears.
Juan C. said: Wolf Thunderspirit said: @Juan_C - have you been able to use CM to set !shaped-at yet?&nbsp; ( <a href="https://bitbucket.org/mlenser/5eshapedscript/wiki/Home#markdown-header-shaped-at" rel="nofollow">https://bitbucket.org/mlenser/5eshapedscript/wiki/Home#markdown-header-shaped-at</a> ) Been trying to code the commands very specifically for Sentry Icon/ Advantage = !shaped-at&nbsp; --advantage Rolling Bomb Icon/ Disadvantage = !shaped-at&nbsp; --disadvantage Back To Normal when Condition is turned off = !shaped-at&nbsp; --normal This would be possible just by using the Add Condition and Remove Condition API to add the marker Shaped5e uses for advantage/disadvantage (green, red by default). You can trigger these additions through token-mod like I did for some other status'. I don't know if it would be possible directly from CM simply because I don't think there's an event observer for it. I haven't tried it. However, I believe the best practice would be to use the auto revert advantage feature, along with the Persistent Macro API for CM, to guarantee your players don't have unintended advantages or disadvantages after the cause-condition disappears. There is no observer in the Shaped Script to simply use a Status Icon as a toggle.&nbsp; When you use the API command (Ex: !shaped-at&nbsp; --advantage ), it puts the Icon up, but not vise versa, which is why I was trying to simplify with using CM.&nbsp; I just can't quite dial in the correct syntax for CM to operate it. It's useful for things like Reckless Attack and such.&nbsp; But using the auto-revert feature sometimes is annoying to your Barbarian, for example, when all of his attacks that round are at advantage.&nbsp; So Auto-revert will turn it off before his second attack.&nbsp; By using the CM Method, it won't turn off until the end of round (setting the round duration to 1, -1 timer), and keeps his Reckless Attack during the round better.&nbsp; On end effect, reverting to normal via CM rather than Shaped's built in option.