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

Having trouble with API & macro to reset the initiative tracker

I imagine I'm making this more complex then it is.  I want to have a macro reset the tracker by ascending after each person takes their turn.  I know I have to use an API to do this.  I tried to get it to work with combat tracker, combat master and group initiative.  The reasoning is, I'm adding action points (what they do) to a persons initiative each time they take their turn.  The initiative will keep growing and depending on what the person did will determine when they come up next.  Any help would be appreciated.

July 16 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

Can you give an example of how the turn order should change and look for a few rounds, I'm having trouble visualizing what you're after. I don't think it will be a problem to get a solution, I just need to understand it better first. 

If three people are in a fight; A, B & C, they roll initiative.  A has a 5, B has a 7 and C has 9.  This will go ascending, lowest to highest so A goes first.  He moves and shoots which add up to 7 action points.  I have a macro set up for "end of turn" to input the action points to his initiative,  A initiative is now 12.  I know I can hit the next button now but here is where the question is.  B is next and she moves and takes cover for 3 action points.  She hits "EoT" and her initiative is now 10.  I can hit next on the tracker again but when C is done with their turn I need to redo the ascending order.  There will not be a strict order of actions, depending on what one does will effect when they go next.  I hope that helped and didn't make it more confusing.

July 18 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

OK, so the basic order of operations will be:


1) Initial values for all tokens

2) Sort ascending

3) Top person takes their turn

4) Add some value to top person's turn

5) got to 2)

Does that sound right?

Yes, that is correct.  It's somewhat similar to Hackmaster to the point of your adding seconds to your initiative but in this case its action points.

July 18 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

Ok.  As GM, you can do that with Group Initiative by configuring it to sort Ascending:

!group-init-config --sort-option|Ascending

Then for handling a player's turn, you can use:

!group-init --adjust-current ?{Add how much}
!group-init --sort

That will only work for the GM though, so if you want players to be able to adjust their own turns, you'll need a custom script...



...like this!

Just set up a macro with:

!forward-init ?{Adjustment}

For players, it will let them adjust the turn for the first token if they can control it.  For the GM, you can adjust anyone's turn, or even custom turn entries.  It also supports inline rolls, if that's something you need:

!forward-init [[@{selected|base}+1d3]]


Here's the code:

on('ready',()=>{

    const playerCanControl = (obj, playerid='any') => {
        const playerInControlledByList = (list, playerid) => list.includes('all') || list.includes(playerid) || ('any'===playerid && list.length);
        let players = obj.get('controlledby')
            .split(/,/)
            .filter(s=>s.length);

        if(playerInControlledByList(players,playerid)){
            return true;
        }

        if('' !== obj.get('represents') ) {
            players = (getObj('character',obj.get('represents')) || {get: function(){return '';} } )
                .get('controlledby').split(/,/)
                .filter(s=>s.length);
            return  playerInControlledByList(players,playerid);
        }
        return false;
    };


    const processInlinerolls = (msg) => {
        if(_.has(msg,'inlinerolls')){
            return _.chain(msg.inlinerolls)
                .reduce(function(m,v,k){
                    let 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();
        } else {
            return msg.content;
        }
    };

/* eslint-disable no-unused-vars */
	const getTurnArray = () => ( '' === Campaign().get('turnorder') ? [] : JSON.parse(Campaign().get('turnorder')));
	const setTurnArray = (ta) => Campaign().set({turnorder: JSON.stringify(ta)});
	const addTokenTurn = (id, pr) => Campaign().set({ turnorder: JSON.stringify( [...getTurnArray(), {id,pr}]) });
	const addCustomTurn = (custom, pr) => Campaign().set({ turnorder: JSON.stringify( [...getTurnArray(), {id:-1,custom,pr}]) });
	const removeTokenTurn = (tid) => Campaign().set({ turnorder: JSON.stringify( getTurnArray().filter( (to) => to.id !== tid)) });
	const clearTurnOrder = () => Campaign().set({turnorder:'[]'});
	const sorter_asc = (a, b) => a.pr - b.pr;
	const sorter_desc = (a, b) => b.pr - a.pr;
	const sortTurnOrder = (sortBy = sorter_desc) => Campaign().set({turnorder: JSON.stringify(getTurnArray().sort(sortBy))});
/* eslint-enable no-unused-vars */

	on('chat:message',msg=>{
		if('api'===msg.type && /^!forward-init(\b\s|$)/i.test(msg.content)){
			//let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');

            let args = processInlinerolls(msg).split(/\s+/);

            let to = getTurnArray();
            let token = getObj('graphic',(to[0]||{}).id);
            if( playerIsGM(msg.playerid) || (token && playerCanControl(token,msg.playerid)) ){
                let adjust = parseFloat(args[1])||0;
                to[0].pr = parseFloat(to[0].pr)+(adjust);
                setTurnArray(to.sort(sorter_asc));
            }
		}
	});
});


Wow, that is awesome.  Thanks so much for the quick script write up.  Is works great and helps me out a lot.

July 19 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

No problem!