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

Auto update journal permissions

July 17 (2 years ago)

So this wise person made a script that automatically updates character sheets "controlled by" when you swap character sheets from 1 server to another, but it doesn't update the "In players journal" part so no one can see their characters anyway. Is there a way to add to this script to also update the journal part?

July 17 (2 years ago)

https://app.roll20.net/forum/post/7688240/is-there-a-way-to-automatically-assign-permission-to-edit-and-view-a-character-sheet-someone-is-importing-to-my-game

July 17 (2 years ago)
The Aaron
Roll20 Production Team
API Scripter

Try this version:

/* global TokenMod */
on('ready',()=>{
    const OwnerAttrName = 'OwnerRoll20IDs';
    
    const assureOwnerID = (c, p, force = false) => {
        let cb = c.get('controlledby');

        if(cb.length && ! /\ball\b/i.test(cb)) {
            let shouldUpdate = force;
            let props = {
                type: 'attribute',
                characterid: c.id,
                name: OwnerAttrName
            };

            let attr = findObjs(props)[0];
            if(!attr) {
                attr = createObj('attribute', props);
                shouldUpdate = true;
            }

            if(shouldUpdate){
                attr.set({
                    current: c.get('controlledby')
                                .split(/,/)
                                .map( id => findObjs({ type: 'player', id })[0] )
                                .filter( p => undefined !== p )
                                .map( p => p.get('d20userid') )
                                .join(',')
                });
                return 1;
            }
        }
        return 0;
    };

    const restoreOwnersOnCharacter = (c) => {
        let props = {
            type: 'attribute',
            characterid: c.id,
            name: OwnerAttrName
        };
        let attr = findObjs(props)[0];
        if(attr){
            let controlList = attr.get('current')
                                .split(/,/)
                                .map( id => findObjs({ type: 'player', d20userid: id})[0] )
                                .filter( p => undefined !== p )
                                .map( p => p.id)
                                .join(',')
                                ;
            c.set({
                controlledby: controlList,
                inplayerjournals: controlList
            });
            return 1;
        }
        return 0;
    };


    const considerChangeOnToken = (t) => setTimeout( () => {
        let token = getObj('graphic',t.id);
        if(token){
            let c = getObj('character',token.get('represents'));
            if(c){
                assureOwnerID(c,null,true);
            }
        }
    }, 100);


    on('change:character:controlledby', assureOwnerID );
    on('add:character', restoreOwnersOnCharacter );

    if('undefined' !== typeof TokenMod && TokenMod.ObserveTokenChange){
        TokenMod.ObserveTokenChange(considerChangeOnToken);
    }

    on('chat:message', (msg)=>{
        if('api' === msg.type && /^!update-ownership\b/i.test(msg.content) && playerIsGM(msg.playerid) ){

            let chars = findObjs({type: 'character'});
            let updates = 0;

            sendChat('',`/w gm <div><b>Considering <code>${chars.length}</code> characters for update.</b></div>`);

            const burndown = ()=>{
                let c = chars.shift();
                if(c){
                    updates += assureOwnerID(c,null,true);
                    setTimeout(burndown,0);
                } else {
                    sendChat('',`/w gm <div><b>Updated ownership on <code>${updates}</code> characters.</b></div>`);
                }
            };

            burndown();

        }

        if('api' === msg.type && /^!update-controlledby\b/i.test(msg.content) && playerIsGM(msg.playerid) ){
            let chars = findObjs({type: 'attribute', name: OwnerAttrName})
                .map(a=>getObj('character',a.get('characterid')))
                .filter( c => undefined !== c);
            let updates = 0;

            sendChat('',`/w gm <div><b>Considering <code>${chars.length}</code> character owners for update.</b></div>`);

            const burndown = ()=>{
                let c = chars.shift();
                if(c){
                    updates += restoreOwnersOnCharacter(c);
                    setTimeout(burndown,0);
                } else {
                    sendChat('',`/w gm <div><b>Updated controlledby on <code>${updates}</code> characters.</b></div>`);
                }
            };

            burndown();

        }
    });
});

July 17 (2 years ago)
The Aaron
Roll20 Production Team
API Scripter

The original one didn't overwrite inplayerjournals assuming that player characters would be set to in all player's journals, but I could see doing it differently.  Probably it would be better to check if it does have `all` in there, and only overwrite it if it doesn't, but this version should work for you.

July 17 (2 years ago)

:O The Wiseman cometh!

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

Lol! =D

July 18 (2 years ago)

But also thankyou so much ,this works perfectly and has saved us so much stress having to assign 10+ sheets every day.

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

No problem! =D

July 22 (2 years ago)
GiGs
Pro
Sheet Author
API Scripter

This looks interesting. For clarification, when would you use this? After importing a character from the Character Vault, to update the visible player?

Is the controlledby preserveed when swapping via the vault?

July 22 (2 years ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

Vault imports come in without permissions. Unless you set up a custom attribute ahead of time for the API to read, that contains a player identifier, it would either have to be set for "All Players" or be left blank.

July 22 (2 years ago)
GiGs
Pro
Sheet Author
API Scripter

In that case, what's the use case for this script?

July 22 (2 years ago)
keithcurtis
Forum Champion
Marketplace Creator
API Scripter

I haven't looked at the code, but assumed it is installed in both games and ensures that the controller gets written to an attribute that can be read from in the new game. IIRC, that's what the original did.

The use case would be when vaulting a character into a new game, you don't have to wait for the GM to assign the controller before you can activate it. I think the primary application would be for West Marches style campaigns, where characters come and go a lot. The Aaron knows best what it's for, of course.

July 22 (2 years ago)

Edited July 22 (2 years ago)
GiGs
Pro
Sheet Author
API Scripter


keithcurtis said:

I haven't looked at the code, but assumed it is installed in both games and ensures that the controller gets written to an attribute that can be read from in the new game. IIRC, that's what the original did.

The use case would be when vaulting a character into a new game, you don't have to wait for the GM to assign the controller before you can activate it. I think the primary application would be for West Marches style campaigns, where characters come and go a lot. The Aaron knows best what it's for, of course.

Thanks. I hadnt looked at the thread lnked above - you're right, it must be installed in both campaigns, and there's a command to run before you vault characters out of that campaign.

I should have looked there - it explains everything :)

That handily fixes a frustrating part of using the character vault.

July 22 (2 years ago)
Aye this is for a 5e west march I help run. We have a server to store all the charatcers as there are 80+, then 2 servers where our GMs run games on. So we are constantly having to transfers sheets over to the playing servers.

This script has been a massive help being as our groups usually have 2-3 extra sheets each for wildshapes, familiars, summons etc
July 22 (2 years ago)

Edited July 22 (2 years ago)
GiGs
Pro
Sheet Author
API Scripter

I can see how it would be massively useful there.

But it sounds useful even for the occasional character vault use. I'm thinking of times I've had players import their characters, and then they've had to wait for em to get online to set the permissions so they could use them. It would have been so much more convenient for them to just import the character and start fiddling with them immediately.

It occurs to be me this is only useful if importing a character from a game where the creator also has a Pro account, but you won't often be transferring characters from one GM to another, so that's not much of a flaw. I know I thoroughly vet characters who've been played with anpther GM, so the delay on permissions there would be a good thing. Butr if its transferring a character from a game i run to another game I run (or just another campaign server for the same game), this script would be very useful.

July 22 (2 years ago)

Edited July 22 (2 years ago)
The Aaron
Roll20 Production Team
API Scripter

You're absolutely right, GiGs. This would require Pro on both sides. It stores the Roll20 User ID to an attribute on the character for each player that can control it in the source game, it then uses that ID to find the player ID in the new game and assign it. 

Player IDs are uniquely generated in the game, just like Token IDs. (I'm not sure, but it wouldn't surprise me if a player that leaves a game and returns gets a new one.). Roll20 User IDs are fixed at account creation and never change. The source player IDs are retained in the controlled by field, but don't show up as they don't match any players in the new game. 

The best your could do with a non-pro source game transfer is detect an unmatched player ID and provide an interface to claim those characters, which probably is not a bad idea.  I should add that to my PlayerCharacters script. 

July 22 (2 years ago)
GiGs
Pro
Sheet Author
API Scripter


The Aaron said:

Player IDs are uniquely generated in the game, just like Token IDs. (I'm not sure, but it wouldn't surprise me if a player that leaves a game and returns gets a new one.). Roll20 User IDs are fixed at account creation and never change. The source player IDs are retained in the controlled by field, but don't show up as they don't match any players in the new game.

I wondered about that. I didn't realise you could get the Roll20 User ID from a script. Looking at the script now, I see the d20userid - handy.

The best your could do with a non-pro source game transfer is detect an unmatched player ID and provide an interface to claim those characters, which probably is not a bad idea.  I should add that to my PlayerCharacters script.

That does sound useful.

July 23 (2 years ago)
The Aaron
Roll20 Production Team
API Scripter

Ok, I did that. =D  https://app.roll20.net/forum/permalink/10990928/

July 24 (2 years ago)
GiGs
Pro
Sheet Author
API Scripter

Nice :)