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

Token Mod- Deduct x HP for tokens with a red dot?

November 14 (8 years ago)
Looking for a solution to dealing with AoE damage. Currently using group check to resolve the saves and token mod to deal with the HP. Had a thought it might be nice to mark the tokens who failed their save with a red marker and use token mod to give half damage to those marked red and full damage to the remainder? Is this possible? 
November 14 (8 years ago)
The Aaron
Pro
API Scripter
There is no support for it in current TokenMod. I can't think of a way to support that as a general purpose option. 

However, I could write you a one-off pretty easily that would do that. 
November 14 (8 years ago)
If you don't mind, and wouldn't go to great trouble, that would be awesome. 
November 14 (8 years ago)
The Aaron
Pro
API Scripter
Ok, give this a shot...

Commands
  • !apply-change --<argument>[param]|[value] ... ::= Applies a change to the selected or specified tokens.
    • --bar ::= This specified which bar to apply the change to. ex: --bar|1
    • --amount ::= This is an amount to change by.  --amount|-10.  You can supply tags to an amount like by appending a comma separated list in brackets
      • --amount[fire]|-10
      • --amount[force,piercing]|-3
    • --damage  ::= This is just like amount, but multiplied by -1.  --amount|-10 is the same as --damage|10
    • --mod ::= This is a modifier rule.  It takes the form --mod[<rule>[,<rule>,...]]|<operation><number>
      • <rule> can be is a <type>:<value> where <type> is one of the following strings.  It can optionally be prefaced by a ! to negate the meaning.
        • status ::= the <value> will be one of the status marker names (same ones used by TokenMod)
        • tag ::= the <value> will be one of the tags you supplied to a --amount or --damage argument 
      • <operation> must be one of the following characters.  It can optionally be followed by a number in brackets to denote the number of decimal places to retain (defaults to floor of the value).
        • * -- multiple the amount by the <number>
        • - -- subtract the <number> from the a amount
        • + -- add the <number> to the amount
        • / -- divide the amount by the <number>
        • = -- replace the amount with the <number>
        • % -- replace the amount with the modules by <number>
    • --ids ::= a list of ids like TokenMod takes.  --ids <id1> <id2> <id3>

Ok.  That probably sounds complicated.  I'll give some examples that should make this easier:

Simplest use, applying damage to all selected tokens:
!apply-change --bar|3 --damage|[[3d6]]
Half damage if they saved, denoted by a red status marker:
!apply-change {{
  --bar|3
  --damage|[[6d6]]
  --mod[status:red]|*.5
}}
Using a tag, if they creatures with brown mark are resistant to fire:
!apply-change {{
  --bar|3
  --damage[fire]|[[6d6]]
  --mod[tag:fire,status:brown]|*.5
}}
Resistant and saved:
!apply-change {{
  --bar|3
  --damage[fire]|[[6d6]]
  --mod[tag:brown,status:brown]|*.5
  --mod[status:red]|*.5
}}
How about more than one damage type:
!apply-change {{
  --bar|3
  --damage[acid]|[[2d4]]
  --damage[fire]|[[6d6]]
  --mod[tag:brown,status:brown]|*.5
  --mod[status:red]|*.5
}}
And maybe a green status demarks immunity to acid:
!apply-change {{
  --bar|3
  --damage[acid]|[[2d4]]
  --damage[fire]|[[6d6]]
  --mod[tag:brown,status:brown]|*.5
  --mod[status:red]|*.5
  --mod[status:green]|=0
}}
And possibly the half damage save doesn't apply to acid:
!apply-change {{
  --bar|3
  --damage[acid]|[[2d4]]
  --damage[fire]|[[6d6]]
  --mod[tag:brown,status:brown]|*.5
  --mod[!tag:acid,status:red]|*.5
  --mod[status:green]|=0
}}
For completeness, maybe you count HP to 2 decimal places:
!apply-change {{
  --bar|3
  --damage[acid]|[[2d4]]
  --damage[fire]|[[6d6]]
  --mod[tag:brown,status:brown]|*[2].5
  --mod[!tag:acid,status:red]|*[2].5
  --mod[status:green]|=0
}}
Or possibly on a save, the acid damage heals:
!apply-change {{
  --bar|3
  --damage[acid]|[[2d4]]
  --damage[fire]|[[6d6]]
  --mod[tag:brown,status:brown]|*[2].5
  --mod[!tag:acid,status:red]|*[2].5
  --mod[status:green,!status:red]|=0
  --mod[status:red,status:red]|*-1
}}
Rules are evaluated in order, and all rules are evaluated, so you might find yourself using ! and the parts from prior rules to get an or sort of case.

Here's the code.  Once you (and anyone else) has played with it a bit, I'll see about adding some other things.  It probably needs a way to bound to the bar max and zero, round instead of floor, specify more complicated rules, maybe a stop rule syntax or some and/or syntax for rules.

//ApplyChange
on('ready',function(){
    'use strict';

    var modifiers = {
        places: function(places){ return (number)=>parseFloat((parseInt(number,10)||0).toFixed(places)); },
        '*': function(amount){ return (number)=>number*amount;},
        '+': function(amount){ return (number)=>number+amount;},
        '/': function(amount){ return (number)=>number/amount;},
        '-': function(amount){ return (number)=>number/amount;},
        '=': function(amount){ return (number)=>amount;},
        '%': function(amount){ return (number)=>number%amount;}
    },
    matchers = {
        'status': function(status){
            return (token,amount,context)=>{
                let sm=_.reduce(
                    token.get('statusmarkers').split(/,/),
                    (m,o)=>{let p=o.split(/@/); m[p[0]]=(p[1]||0); return m; },
                    {}
                );
                return _.has(sm,status);
            };
        },
        'negate': function(fn){ return (token,amount,context)=>!fn(context,token); },
        'tag': function(tag){ return (token,amount,context)=>_.contains(amount.tags,tag); }
    },

    buildMatcher = function(params){
        return (function(matchers){
            return function(token,amount,context){
                return !_.find(matchers,(m)=>!m(token,amount,context));
            };
        }(_.chain(params)
            .reduce((m,o)=>{
                let p=_.rest(o.match(/^(!)?([^:]*):(.*)$/));
                p[0]=!!p[0];
                m.push({
                    negate: p[0],
                    type: p[1],
                    value: p[2]
                });
                return m;
            }, [])
            .map((o)=>{
                if('negate'===o.type || !_.has(matchers,o.type)){
                    return _.constant(true);
                }
                return (o.negate ?
                    matchers.negate(matchers[o.type](o.value)) :
                    matchers[o.type](o.value) );
            })
            .value()));
    },
    buildModifier = function(op,amount,places){
        return (_.isUndefined(places) ?
            modifiers[op](amount) :
            _.compose(modifiers.places(amount) , modifiers[op](amount)) );
    };

    on('chat:message',function(msg){
        if('api' === msg.type && msg.content.match(/^!apply-change/) && playerIsGM(msg.playerid) ){

            if(_.has(msg,'inlinerolls')){
                msg.content = _.chain(msg.inlinerolls)
                    .reduce(function(m,v,k){
                        var ti=_.reduce(v.results.rolls,function(m2,v2){
                            if(_.has(v2,'table')){
                                m2.push(_.reduce(v2.results,function(m3,v3){
                                    m3.push(v3.tableItem.name);
                                    return m3;
                                },[]).join(', '));
                            }
                            return m2;
                        },[]).join(', ');
                        m['$[['+k+']]']= (ti.length && ti) || v.results.total || 0;
                        return m;
                    },{})
                    .reduce(function(m,v,k){
                        return m.replace(k,v);
                    },msg.content)
                    .value();
            }

            let args = _.rest(msg.content
                    .replace(/<br\/>\n/g, ' ')
                    .replace(/(\{\{(.*?)\}\})/g," $2 ")
                    .split(/\s+--/)),
                ids = _.pluck(msg.selected,'_id'),
                context = {
                    bar: 1,
                    amount: [],
                    mods: []
                };

                // !apply-change --bar|1 --amount|-[[xdy]] --mod[status:red,!status:green,tag:fire]|*.5 --ids @{target|token_id}
                // !apply-change --bar|1 --damage|[[xdy]] --mod[status:green]|*.5 --ids @{target|token_id}

            _.map(args,function(arg){
                let cmds=((arg.match(/([^\s]+[\|#]'[^']+'|[^\s]+[\|#]"[^"]+"|[^\s]+)/)||[])[0]||'').split(/[\|#]/),
                    mult=1,
                    cmdparts=cmds.shift().match(/^([^\[]*)(?:\[([^\]]*)\])?$/),
                    cmd=cmdparts[1],
                    params=((cmdparts[2]||'').length ? cmdparts[2].trim.split(/\s*,\s*/) : []);
                switch(cmd){
                    case 'ids':
                        ids=_.union(_.rest(arg.split(/\s+/)),ids);
                        break;

                    case 'bar':
                        context.bar = (parseInt(cmds[0])||1);
                        break;

                    case 'damage':
                        mult=-1;
                        /* falls through */

                    case 'amount':
                        context.amount.push({
                            amount: mult*parseInt(cmds[0]||0),
                            tags: params
                        });
                        mult=1;
                        break;

                    case 'mod':
                        let parts=cmds[0].match(/^([\*\+\-\/=%](?:\[\d\])?)?([\d\.]*)/),
                            amount=parseFloat(parts[2]),
                            opParts=parts[1].match(/^(.)(?:\[(\d*)\])?$/),
                            op=opParts[1],
                            places=opParts[2]||0;
                        context.mods.push({
                            matcher: buildMatcher(params),
                            modifier: buildModifier(op,amount,places)
                        });
                        break;
                }
            });

            // get tokens
            if(ids.length){
                _.chain(ids)
                    .uniq()
                    .map(function(t){
                        return getObj('graphic',t);
                    })
                    .reject(_.isUndefined)
                    .each(function(token) {
                        let bar=`bar${context.bar}_value`,
                            change=0;
                        _.map(context.amount, (amount)=>{
                            let value=amount.amount;
                            
                            if(context.mods.length){
                                _.each(context.mods,(mod)=>{
                                    if(mod.matcher(token,amount,context)){
                                        value=mod.modifier(value);
                                    }
                                });
                            }
                            change+=value;
                        });
                        token.set(bar,parseFloat(token.get(bar))+change);
                    });
            }
        }
    });
});

Cheers!
November 15 (8 years ago)

Edited November 15 (8 years ago)
The Aaron
Pro
API Scripter
Here's how you might use tags to adjust the damage based on a formula:
!apply-change {{
  --bar|1
  --damage[success:[[(1d20+5)>@{target|foe|defense)]] ]|[[3d6]]
  --mod[tag:success:1]|=0
}}

See below...
November 15 (8 years ago)

Edited November 15 (8 years ago)

The Aaron said:

Here's how you might use tags to adjust the damage based on a formula:
!apply-change {{
  --bar|1
  --damage[success:[[(1d20+5)>@{target|foe|defense)]] ]|[[3d6]]
  --mod[tag:success:1]|=0
}}


Yayy, you used the method i was asking you about lol
coincidence probably but it seems nice ;D
November 15 (8 years ago)
Aaron that is awesome. I had thought bout the resistances and such and figured it was asking too much. As always, awesome. 
November 15 (8 years ago)
In a year, I predict there will be a script that calculates saves and processes damage for an AoE spell. In two years Aaron will probably have a script that replaces the game master :)
November 15 (8 years ago)
The Aaron
Pro
API Scripter
I think I have a few corrections coming on this and some extra options.. testing a --mod{formula:[[something]]}|=0 sort of thing right now.
November 15 (8 years ago)

Edited November 15 (8 years ago)
The Aaron
Pro
API Scripter
Ok.  Here's a new version: https://gist.github.com/shdwjk/cebd253564511c8d8e0...

I made some robustness changes, set the default for non existing mod types to be non-matching, and added:
  • --mod[formula:<value>]|<operation><number>  ::=  if <value> is greater than 0, the mod is applied.  Prepending a ! will mean if it's 0 or less, it applies.  
  • Alternate syntax --mod{<type>:<value>}|<operation><number> ::=  To play nice with inline rolls, you can use { } around the mod rules (or tags).
  • --ignore-selected ::= causes it to ignore any selected tokens and only change tokens whose ids are passed to --ids
Some examples:

Zero out the damage if an attack was a miss:
!apply-change {{
  --bar|1
  --damage|[[3d6]]
  --mod{!formula:[[(1d20+5)>@{target|foe|defense}]]}|=0
  --ignore-selected
  --ids @{target|foe|token_id}
}}
and the alternate syntax applied to tags:
!apply-change {{
  --bar|1
  --damage{chance[[1d4]]}|10
  --mod[tag:chance1]|*3
  --mod[tag:chance2]|/2
}}

Let me know what you think!
November 15 (8 years ago)
I'm certain to use this script!

Now for a question that you're probably anticipating: should we get our hopes up for an --attribute|attribute_name argument as an alternative to --bar? :D
November 15 (8 years ago)
vÍnce
Pro
Sheet Author

Silvyre said:

I'm certain to use this script!

Now for a question that you're probably anticipating: should we get our hopes up for an --attribute|attribute_name argument as an alternative to --bar? :D
And maybe call it...
oh I don't know,
how about,
" CharMod "?

;-P

November 15 (8 years ago)
The Aaron
Pro
API Scripter
You guys!  =D~

I could definitely add one. 
November 15 (8 years ago)
This really could be a one stop solution to hits, saves, and damage. Far more than I hoped for, so my next question is rather like asking for seconds on desert. Is it possible to integrate this with the Shaped Sheet? So that the numbers pull directly from the character sheet? And is it possible to include an override button in case the target does something like shield or cutting words? 

November 15 (8 years ago)
Kiyomi N.
Sheet Author
Seriously Aaron. This is incredible. You've really outdone yourself so far :)
November 15 (8 years ago)
The Aaron
Pro
API Scripter

Gary W. said:

Is it possible to integrate this with the Shaped Sheet? So that the numbers pull directly from the character sheet? 
Can you give some examples of how you see this working, I'm not sure I completely get what you're talking about.


Gary W. said:
 And is it possible to include an override button in case the target does something like shield or cutting words? 
Definitely possible.  Reporting was the next thing I was going to add.  I'll move this over to a proper script format first, in the repo and with help and configs and such.


November 15 (8 years ago)
The Aaron
Pro
API Scripter

Kiyomi N. said:

Seriously Aaron. This is incredible. You've really outdone yourself so far :)

Thanks!  I have a feeling that Gary's first suggestion on working directly with the character sheet will play well with what you're needing.  Definitely jump in on that discussion as well. =D  Changing --mod{formula:...} to work against individual token details would go a long way. =D
November 15 (8 years ago)
The more the script works without the user seeing it the better. Once reason I am such a fan of the Shaped Sheet is that it will create macros for every weapon and trait on the character sheet. The ideal solution would resolve individual melee and spell attacks as well as dealing with area of effect spells. One individual attack rolls the shaped sheet will make a roll to hit and determine damage. Could we append your script to the macro so that those to hit and damage rolls and deduct them from the token hit points. 

Area of effect spells are probably going to be more tricky. I have recently started using Jakob's group check script- which makes a save or ability check for every token selected. I then use token mod to deduct the damage. Ideally the scrip would have each token roll a save using the shaped sheet modifiers (like Jakobs), and apply the damage to the token based on the result of the save. 

Perhaps somewhere down the line a script could account for heavy armor mastery, the shield spell cast as a reaction, cutting words as a reaction etc, but in the meantime the script would need some way of being rolled back on individual tokens that have these features and use them.

Does this make sense? I wish I could speak programmers lingo but I don't :) 
November 15 (8 years ago)
Kiyomi N.
Sheet Author
As for resistances... Is there any way to, instead of checking for a status icon, checking the value of an attribute to determine whether or not it has one? For example, right now I just have a box where players right in what elements they are weak, resistant or immune to but I doubt it can check a text box for specific text so maybe if I created separate attributes for each element and weak/resist and if the box is checked, the value becomes 1 and if the script looks for that... Just a thought.
November 15 (8 years ago)
Kiyomi N.
Sheet Author
So for people who use macros that use target for the target and selected for the user... Would that be a simple adjustment?
November 15 (8 years ago)
The Aaron
Pro
API Scripter

Gary W. said:

The more the script works without the user seeing it the better. Once reason I am such a fan of the Shaped Sheet is that it will create macros for every weapon and trait on the character sheet. The ideal solution would resolve individual melee and spell attacks as well as dealing with area of effect spells. One individual attack rolls the shaped sheet will make a roll to hit and determine damage. Could we append your script to the macro so that those to hit and damage rolls and deduct them from the token hit points. 
Maybe.  I've not played with that, it kind of depends on how we would get the damage into the script. I'll have to experiment.


Gary W. said:
Area of effect spells are probably going to be more tricky. I have recently started using Jakob's group check script- which makes a save or ability check for every token selected. I then use token mod to deduct the damage. Ideally the scrip would have each token roll a save using the shaped sheet modifiers (like Jakobs), and apply the damage to the token based on the result of the save. 
Checking against a particular individual formula is something I'd like to add, so that part should be possible. Selecting who to target might be harder as you'd either have to have selected them before hitting the macro (and that might cause other problems) or you'd need to pass a sufficient number of @{target|T#|token_id} arguments to --ids.  Probably outputting an API Command Button to click once they've been selected would be easier on all sides.


Gary W. said:
Perhaps somewhere down the line a script could account for heavy armor mastery, the shield spell cast as a reaction, cutting words as a reaction etc, but in the meantime the script would need some way of being rolled back on individual tokens that have these features and use them.
Probably these could be handled by providing some sort of adjustment interface via the chat.  Maybe have a collection of possible adjustments to apply and a button to negate each rule that was applied (and maybe to force ones that weren't).


Gary W. said:
Does this make sense? I wish I could speak programmers lingo but I don't :) 
No worries.  Most people don't speak programmer lingo, so I'm like a left handed fencer--used to it more than you are!


Kiyomi N. said:
As for resistances... Is there any way to, instead of checking for a status icon, checking the value of an attribute to determine whether or not it has one? For example, right now I just have a box where players right in what elements they are weak, resistant or immune to but I doubt it can check a text box for specific text so maybe if I created separate attributes for each element and weak/resist and if the box is checked, the value becomes 1 and if the script looks for that... Just a thought.
Yeah, I'd like to add that.  It actually wouldn't be hard to pull them all from a text box provided they are in a sensible format (comma delimited, all on individual lines, etc).  The biggest thing would be to have each of the individual types of qualities separated: weak in one box, resistant in another, immune in a third, etc.





November 15 (8 years ago)
The Aaron
Pro
API Scripter

Kiyomi N. said:

So for people who use macros that use target for the target and selected for the user... Would that be a simple adjustment?
Something like is what I had in mind for that (--ignore-selected to not adjust the selected user, --ids to specify who to affect with @{target}, etc) :
!apply-change {{
  --bar|1
  --damage|[[3d6]]
  --mod{!formula:[[(1d20+5)>@{target|foe|defense}]]}|=0
  --ignore-selected
  --ids @{target|foe|token_id}
}}


November 15 (8 years ago)

Edited November 15 (8 years ago)
Kiyomi N.
Sheet Author
Yeah, I'd like to add that. It actually wouldn't be hard to pull them all from a text box provided they are in a sensible format (comma delimited, all on individual lines, etc). The biggest thing would be to have each of the individual types of qualities separated: weak in one box, resistant in another, immune in a third, etc.

Yes this is how my sheet is designed. That would be wonderful! Also the targeting seems like it would work just fine. My thoughts on AOE... Is there any way to affect all squares within so many squares of the user, or within so many of the target token? Failing that, is there a way to target multiple enemies are once using 'target' rather than 'selected'?
November 15 (8 years ago)

The Aaron said:

Gary W. said:

The more the script works without the user seeing it the better. Once reason I am such a fan of the Shaped Sheet is that it will create macros for every weapon and trait on the character sheet. The ideal solution would resolve individual melee and spell attacks as well as dealing with area of effect spells. One individual attack rolls the shaped sheet will make a roll to hit and determine damage. Could we append your script to the macro so that those to hit and damage rolls and deduct them from the token hit points. 
Maybe.  I've not played with that, it kind of depends on how we would get the damage into the script. I'll have to experiment.


One thing I have found really useful is the ability to "add" to the sheets macros by through the freeform section. https://docs.google.com/document/d/1yPcIZ_bIc3JlnW...

The Aaron said:

Gary W. said:

Area of effect spells are probably going to be more tricky. I have recently started using Jakob's group check script- which makes a save or ability check for every token selected. I then use token mod to deduct the damage. Ideally the scrip would have each token roll a save using the shaped sheet modifiers (like Jakobs), and apply the damage to the token based on the result of the save. 
Checking against a particular individual formula is something I'd like to add, so that part should be possible. Selecting who to target might be harder as you'd either have to have selected them before hitting the macro (and that might cause other problems) or you'd need to pass a sufficient number of @{target|T#|token_id} arguments to --ids.  Probably outputting an API Command Button to click once they've been selected would be easier on all sides.
I envision this working the same way your group initiative operates- using the mouse to draw a big box around the tokens being selected. 
November 15 (8 years ago)

Edited November 15 (8 years ago)
The Aaron
Pro
API Scripter
Kiyomi N. said:
Yes this is how my sheet is designed. That would be wonderful! Also the targeting seems like it would work just fine. My thoughts on AOE... Is there any way to affect all squares within so many squares of the user, or within so many of the target token? Failing that, is there a way to target multiple enemies are once using 'target' rather than 'selected'?

Specifying multiple targets can be done by adding multiple target arguments for --ids:
!apply-change {{
  --bar|1
  --damage|[[3d6]]
  --ignore-selected
  --ids @{target|foe1|token_id} @{target|foe2|token_id} @{target|foe3|token_id} @{target|foe4|token_id}
}}
Where that gets complicated is with the --mod argument.  Since the formula is (currently) calculated on the client side, there isn't a way to individually consider each target's defense.  I'll try to find a good way to handle that.  I'd like to support as many scenarios as possible:
  • single rolled number vs. target attribute
  • single rolled number vs. target rolled number
  • individually rolled number vs target attribute
  • individually rolled number vs target rolled number 
Thoughts?
November 15 (8 years ago)
The Aaron
Pro
API Scripter

Gary W. said:

I envision this working the same way your group initiative operates- using the mouse to draw a big box around the tokens being selected. 
Right, the complicated part comes when you consider when you're doing that selection, and who is doing it.  Players can't select tokens they don't control, for example.

November 15 (8 years ago)
Kiyomi N.
Sheet Author
Sounds like that would cover every situation I can think of...
November 15 (8 years ago)

Edited November 15 (8 years ago)
Even a simple click would be acceptable in my opinion. Below is a screen shot of how the macros I set up for a paladin using divine favor and divine smite look.



The macro (as it stands today) gives me a visual of the to hit roll, another roll that would apply if advantage or disadvantage is in play, and the rolled damage. The player then clicks the the pink text to roll divine favor damage. Same with rolling divine smite damage. 

Would it be easier to let the information to continue to computed on the client side and add a button the dm can click to assess the damage to a token?
November 15 (8 years ago)
The Aaron
Pro
API Scripter
I think that would be easier. =D
November 15 (8 years ago)
Kiyomi N.
Sheet Author
Certainly seems easier.
November 15 (8 years ago)

Edited November 15 (8 years ago)
Jakob
Sheet Author
API Scripter
Wow, this is becoming a major undertaking. Looking quite nice so far. I was thinking about some kind of script intercommunication with GroupCheck, but that may be hard to implement, as GroupCheck doesn't know the results of the roll, only the formula.
November 15 (8 years ago)

The Aaron said:

Kiyomi N. said:
Yes this is how my sheet is designed. That would be wonderful! Also the targeting seems like it would work just fine. My thoughts on AOE... Is there any way to affect all squares within so many squares of the user, or within so many of the target token? Failing that, is there a way to target multiple enemies are once using 'target' rather than 'selected'?

Specifying multiple targets can be done by adding multiple target arguments for --ids:
!apply-change {{
  --bar|1
  --damage|[[3d6]]
  --ignore-selected
  --ids @{target|foe1|token_id} @{target|foe2|token_id} @{target|foe3|token_id} @{target|foe4|token_id}
}}
Where that gets complicated is with the --mod argument.  Since the formula is (currently) calculated on the client side, there isn't a way to individually consider each target's defense.  I'll try to find a good way to handle that.  I'd like to support as many scenarios as possible:
  • single rolled number vs. target attribute
  • single rolled number vs. target rolled number
  • individually rolled number vs target attribute
  • individually rolled number vs target rolled number 
Thoughts?

I am attempting to use this in my macro but it doesn't seem to be recognizing my inline roll as a value? I have it setup to see what i roll, and I roll a 6 but it doesn't subtract anything from the token? But if I put a 6 in the damage manually it takes it away fine :/
November 15 (8 years ago)
The Aaron
Pro
API Scripter
Can you post your macro?
November 15 (8 years ago)

Jakob said:

Wow, this is becoming a major undertaking. Looking quite nice so far. I was thinking about some kind of script intercommunication with GroupCheck, but that may be hard to implement, as GroupCheck doesn't know the results of the roll, only the formula.

Ok- so in the same line as adding a button to resolve the damage to single target attacks couldn't we do something similar with AoE attacks?



We let the DM visually compare the save result with the spell DC. Ideally- all the bells and whistles Aaron was discussing would apply to the check. Did the mob save or fail (full/half/no damage) and a means of applying the resistance and such. It wouldn't be as awesome as a script that did all of the above on its own, but it would speed up large encounters exponentially. 
November 15 (8 years ago)
The Aaron
Pro
API Scripter
Probably we can work something out for communication between the scripts, or GroupCheck could output some buttons, or the functionality might get subsumed with the addition of attributes to the mod rules.
November 15 (8 years ago)
This conversation has me very excited- jumping around like a kid the night before Christmas :)
November 15 (8 years ago)

Edited November 15 (8 years ago)
Jakob
Sheet Author
API Scripter

The Aaron said:

Probably we can work something out for communication between the scripts, or GroupCheck could output some buttons, or the functionality might get subsumed with the addition of attributes to the mod rules.

In simple cases (1 roll per token) I could certainly try to output a button with all the results and token/character ids inserted in the right places, using the sendChat callback. Just need to think of a way of passing along all the options to apply-change.
November 15 (8 years ago)

Edited November 15 (8 years ago)
Kiyomi N.
Sheet Author
Same here Gary. Speaking of Christmas... If I wanted to reward you for all your hard work Aaron, do you have like a wishlist or anything? :D
November 15 (8 years ago)
The Aaron
Pro
API Scripter
Ha!  Nah.. don't worry about it.  I do it because I enjoy it.  =D
November 15 (8 years ago)
Kiyomi N.
Sheet Author
If you say so! That's the same way I feel about creating and maintaining my final fantasy rpg sheet.
November 15 (8 years ago)
The Aaron
Pro
API Scripter
(My eldest daughter is named Aeris. =D )
November 15 (8 years ago)
Kiyomi N.
Sheet Author
Don't you mean Aerith? Just kidding, that's adorable :3
November 15 (8 years ago)
The Aaron
Pro
API Scripter
Hahahah, I figured I'd hear that. =D
November 15 (8 years ago)

Edited November 16 (8 years ago)

The Aaron said:

Can you post your macro?


For some reason it didn't show this as a reply :/

!extend `(1d20+@{selected|repeating_weapon_$0_total-attack})[tohit]` `(${tohit}>@{target|AC})[hit]` `(${toconf}==20 | ${toconf}>@{target|AC})[cconf]` `(${dieroll} ==1 | ${tohit}<=@{target|AC})[miss]` `(${dieroll} ==20 | ${dieroll}>=@{selected|repeating_weapon_$0_crit-target})[crit]` `(${miss} ? "Miss" : "Hit")[horm]` `(@{selected|repeating_weapon_$0_damage-dice-num}d@{selected|repeating_weapon_$0_damage-die})[dmg]` `(${dmg}*@{selected|repeating_weapon_$0_crit-multiplier}))[critdmg]` `(${dmg}*0)[missdmg]` `(${hit} & ${crit} & ${cconf} ? ${critdmg} : ${damage})[finaldmg]` `(${hit} & ${crit} & ${cconf} ? "Crit" : ${horm})[result]` `(1d20+@{selected|repeating_weapon_$0_total-attack}+@{selected|repeating_weapon_$0_crit_confirm})[toconf]` `(${hit} ? ${dmg} : ${missdmg})[damage]` &{template:pf_attack} {{character_name=@{selected|token_name}}} {{subtitle= attacks @{target|token_name} with @{selected|repeating_weapon_$0_name}}} {{D20 Roll= `(${tohit}-@{selected|repeating_weapon_$0_total-attack})[dieroll]` Hitting AC: `(${tohit})`}} {{Crit D20 Roll= `(${toconf}-(@{selected|repeating_weapon_$0_total-attack}+@{selected|repeating_weapon_$0_crit_confirm}))` To Confirm: `(${toconf})`}} {{Result= `(${result})`}} {{Damage=  `(${finaldmg})`}}

It a little lengthy right now, but then again it is 95% done. Works 100% as it currently is, uses variables to pre-determine rolls and just calls them when needed. Template output is fairly compact and nice as well. The only problem I am having is when i use
!apply-change--bar|1 --damage|`(${finaldmg})` --ignore-selected --ids @{target|foe1|token_id} 
it doesn't subtract the damage from the token's hp bar but if i change it to
!apply-change--bar|1 --damage|6 --ignore-selected --ids @{target|foe1|token_id} 
while still inside the macro it will take 6 hp away

Also if we can get this final part working Kiyomi N. should be able to extrapolate from my macro and be able to automate what they're doing as well. And that way we can all live happily ever after with automated attack macros :D

Its taken me around 10 hrs of coding my macro to get it to work right 0.o
November 16 (8 years ago)
Kiyomi N.
Sheet Author
That looks like the most complex but amazing macro.
November 16 (8 years ago)

Edited November 16 (8 years ago)
To show you a couple of examples of its output.



The first is just a normal hit because it didn't breach the crit threshold of 18 but the hit roll beat the target's AC of 15
The second is a miss because the hit roll well... didn't beat the target's AC
The Third Crit because both the D20 roll was a crit and the To Confirm roll was greater than the Target's AC
And the Forth was a crit but it did not beat the Target's AC on the confrim roll so it didn't Crit.

Also it is of note that
Silvyre said:
This won't work because `(${finaldmg})` is not recognized by the ApplyChange script as meaningful syntax.
so thats why it won't work in conjunction with ApplyChange, if The Aaron can maybe add the syntax in we can combine/make them work together??
November 16 (8 years ago)
The Aaron
Pro
API Scripter
That `(${finaldmg))` is only going to work inside !extend commands.  Even if I added something to accept that syntax, nothing on my end would be filling finaldmg with the same thing as in the !extend call.
November 16 (8 years ago)

The Aaron said:

That `(${finaldmg))` is only going to work inside !extend commands.  Even if I added something to accept that syntax, nothing on my end would be filling finaldmg with the same thing as in the !extend call.


I figured as much, is it possible to "combine" the two api scripts to get it to function the same as if they were independent but if they happen to be grouped together they would be able to interact correctly?
November 16 (8 years ago)
The Aaron
Pro
API Scripter
I've heard that one script can call another by sending the command to chat, but I've never actually messed with it before. 
November 16 (8 years ago)

Edited November 16 (8 years ago)
Do you think the result would warrant the work? Cause I noticed a lot of people want a automated attack macro like the one I've made with the added benefit of your scripts.

I personally am not that great at writing the api scripts (as you know) but I am decent at writing macros that do great things with logic :D
November 16 (8 years ago)

B14d3r11 said:

Do you think the result would warrant the work? Cause I noticed a lot of people want a automated attack macro like the one I've made with the added benefit of your scripts.

The result would be revolutionary for Roll20. At least IMO.