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

TokenMod: function to add & remove character in plate name?

May 25 (5 years ago)

Edited May 25 (5 years ago)

Hi!

I use scripts with TokenMod to toggle whether name plates are shown to me, or players or not. But often I don't know if the players can the see the plate for a certain token.

Can I use TokenMod to add an asterix in front of any given name (indicating to me it's "privacy status"), and on the next toggle the asterix is removed again by TokenMod?

May 26 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

Not automatically. I'm assuming you're toggling the visibility with --flip. If you have a separate one for --on and --off you could add the * with the --on and reset it to without when you do the off. 

Sorry, RL was interfering heavily ....

Yes, you're assumption is right. But how can I reset it? Do I have to store the name in a newly created variable (AKA attribute) in the sheet?

June 03 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

The token name is separate from the character name. You can reset it by just setting it back to the character name:

!token-mod --set name|"@{selected|character_name}"

I used to do this for marking my Mystic character with her active focus.


Oh, so easy .... thanks for that advice! :-)

June 04 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

No problem!

So, I eventually managed to find spare time to spent in Roll20 again :-) The next challenge (at least for me) arises since I use TokenNameNumber, also.

To hide the names I use

!token-mod --off showplayers_name --set name|"(@{selected|token_name})"

(setting the name within parentheses). By the way: First, I tried it with a preceding asterix (*) but it didn't work, it must have a special meaning here :-)

If I use your suggestion for resetting the name

!token-mod --set name|"@{selected|character_name}"

the original name will be used. But TokenNameNumber already changed that TokenName, so if I use character_name the 'numbered name' will be lost (or the script will add a different name, but I think it runs only, when a new token is added, right?).

I don't think that this issue can be solved, because Tokens don't have that many variables stored to them, do they?



June 06 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

It might not be solvable easily in the general case, but it can probably be specifically solved for your case with a one-off script.  Scripts like TokenMod are large and complex because they need to support as much capability as possible.  One-offs can be really small and simple since they only need to do one specific thing.  Here's one for your need:

on('ready',()=>{

  const toggleName = (t) => {
    let nameShown = t.get('showplayers_name');
    if(nameShown){
      t.set({
        showplayers_name: false,
        name: `(${t.get('name')})`
      });
    } else {
      t.set({
        showplayers_name: true,
        name: t.get('name').replace(/\((.*)\)/,(f,p)=>p)
      });
    }
  };

  on('chat:message',msg=>{
    if('api'===msg.type && /^!toggle-name-hidden(\b\s|$)/i.test(msg.content) && playerIsGM(msg.playerid)){
      (msg.selected || [])
        .map(o=>getObj('graphic',o._id))
        .filter(g=>undefined !== g)
        .forEach(toggleName)
        ;
    }
  });
});

Just select one or more tokens and run:

!toggle-name-hidden

and it will hide and wrap them in a ( ), or unhide and unwrap them.  It will preserve whatever numbering there is on the token since it literally just wraps and unwraps the existing name with parenthesis.

Oh, great! So easy! I very appreciate your help!



I not yet really into this programming, so might I ask you some newbie questions?


1. What does the

(\b\s|$)

term in the regular expression do? Especially the |$ part ... does this just catch spaces OR the end of line?


2. Which other types of msg.type do exist? (I remember to have read one page about it, but I didn't cared for it at that time)


3.  What about

(msg.selected || [])

    ? Is it just to exit the routine if there is no message?


4. Last question:

.filter(g=>undefined !== g)

   I am utterly lost at this line.

June 08 (5 years ago)
The Aaron
Roll20 Production Team
API Scripter

No worries. 

1) \b is the word boundary matcher, \s is the white space matcher. $ is the end of line matcher. | (pipe) is an or. So (\b\s|$) matches "the end of a word or the end of a line". Since \b only catches the transition from \w (word characters) to \W (non-word characters) in either direction, it's insufficient for finding a break in the command line as I'm using it. \b would match the location between "foo" and "-bar" in "foo-bar" because - is not a word character. Similarly, there's no tradition after foo in "foo" because the end is reached and there isn't another character to transition to. 

2) There are:  "general", "rollresult", "gmrollresult", "emote", "whisper", "desc", or "api".

Read about them all here: https://wiki.roll20.net/API:Chat

3) msg.selected is only present if there are selected things. In javascript, since all things have a "truthiness", the logic operators return the things compared, rather than a Boolean.  That means an operation with || (logical or) will result in the first "truthy" argument, so it can be used to provide a default value for an expression that might otherwise be missing.  So this is "use the msg.selected array if it exists, otherwise use this empty array []". This is an idiomatic way in javascript to deal with missing data. In the case that nothing is selected, this chain of operations will not be executed because the length is 0 on the array.

4) => us the "fat arrow" syntax for defining functions.  This is passing a function to the .filter() operation on the array that's being worked on in that chain of commands. The .filter() on an array will return a new array containing all the elements of the source array for which the predicate function passed to it returns true.  The predicate function in this case is g=>undefined !== g  A function that takes g and compares it to undefined.  So this line removes anything that was selected but wasn't a graphic (drawings, text, etc).  That predicate function could be written more traditionally as function(g){return undefined !==g;}


Hope that helps!  Ask more questions if you like!