
This is just a little script I threw together for a new game I'm starting. It simplifies adding new characters for new players. I know there are a few others out there, this one just works the way I wanted. =D When a new player joins, it creates them a character and sends them a message:
Existing players that join get a list of their existing characters:
The Green + adds a new character.
Note that nothing shows up for players that are GMs.
Script:
on('ready',()=>{ const IN_PLAYER_JOURNALS = true; const TIME_TO_CHECK = 1000; const styles = { box: 'display: block; border: 1px solid #999; border-radius: .3em; padding: .3em; background-color: white; box-shadow: 0 0 25px 2px #999; margin: 1em 0 1em 0;', charRow: 'display: block; border-top: 1px solid #ccc; margin: .2em;', img: 'max-width: 2em; max-height: 3em;width:auto;height:auto;border:1px solid #999;float:left;margin: .1em; display: inline-block;', link: 'color: #07c; border: 1px solid #999; border-radius: .3em; padding: .3em 1em; background-color:#ccc;font-weight: bold;display: inline-block;float: right;margin: .1em;', addBtn: 'color: #fff; border: 1px solid #9f9; border-radius: .3em; padding: .3em 1em; background-color:#3c3;font-weight: bold;display: inline-block;float: right;margin: .1em;' }; const defaultImg = 'https://app.roll20.net/images/character.png'; const clear = ()=>`<div style="clear:both"></div>`; const GetCharImage = (c) => c.get('avatar')||defaultImg; const GetShowCharacter = (c) => `<div style="${styles.charRow}"><a style="${styles.link}" href="http://journal.roll20.net/character/${c.id}">Open</a><img style="${styles.img}" src="${GetCharImage(c)}"/>${c.get('name')}${clear()}</div>`; const AddButton = () => `<a style="${styles.addBtn}" href="!add-player-character">+</a>`; const AddPlayerCharacter = (player) => { let c = createObj('character',{ controlledby: player.id, name: `${player.get('displayname')}'s New Character`, inplayerjournals: (IN_PLAYER_JOURNALS ? 'all' : '') }); return c; }; const ShowPlayerCharacters = (player,chars)=>{ chars = chars||findObjs({ type: 'character', archived: false }).filter(c=>c.get('controlledby').split(/\s*,\s*/).includes(player.id)); sendChat('',`/w "${player.get('displayname')}" <div style="${styles.box}"><div>${AddButton()}Your Characters:${clear()}</div>${chars.map(GetShowCharacter).join('')}</div>`); }; const CheckPlayerCharacters = (player) => { if(playerIsGM(player.id)){ return; } let chars = findObjs({ type: 'character', archived: false }).filter(c=>c.get('controlledby').split(/\s*,\s*/).includes(player.id)); if( ! chars.length){ chars.push(AddPlayerCharacter(player)); } ShowPlayerCharacters(player,chars); }; on('chat:message', (msg) => { if('api' === msg.type && /^!add-player-character\b/i.test(msg.content)){ let player = getObj('player',msg.playerid); if(player){ AddPlayerCharacter(player); ShowPlayerCharacters(player); } } }); const checkAll = () => { findObjs({ type: 'player' }).forEach(CheckPlayerCharacters); }; setTimeout(()=>{ checkAll(); on('change:player:_online',(obj)=>{ if(true === obj.get('online')){ setTimeout(()=>CheckPlayerCharacters(obj),TIME_TO_CHECK); } }); }, TIME_TO_CHECK ); });