Hi everyone, I wrote a quick script this morning to utilize the Roll20AM script's global variable and generate an inline-link chat menu macro for the 5e OGL Character Sheet. I wanted the chat menu to list all of my playlists along with each track I have imported for traps and spells . This handles that and can be customized to build any other type of Roll20AM menu. Additionally, with a bit more customization, you can build any type of chat menu you wanted. I know other API scripts exist out there that can do this, but I needed a bit of customization and it was a nice morning challenge. Hope someone finds it useful! var roll20AMMenuGenerator = roll20AMMenuGenerator || {
menuStr: '/w gm&{template:npcaction} {{rname=Roll20AM Menu}} {{description=',
trackDetails: state.Roll20AM.trackDetails,
playlistDetails: state.Roll20AM.playLists,
r20AMStopCommand: '!roll20AM --audio,stop',
makeBold: (str) => { return '**'+str+'**' },
makeChatCommand: (title, command) => { return '['+title+']('+command+')' },
r20AMPlayCommand: (objName) => { return '!roll20AM --audio,play|'+ encodeURIComponent(objName) },
inputHandler: function(msg_original) {
if(msg_original.content.indexOf('!r20AMMenuGenerator') !== 0){
return;
} else {
this.generateMenu(msg_original.playerid);
}
},
generatePlaylistStr: function(playlistNameArr) {
var playListStr = this.makeBold('Playlists')+'\n';
let playListNames = playlistNameArr.filter( name => !name.toLowerCase().match(/tag[0-9]/) ).sort();
_.each(playListNames, (plName) => playListStr += this.makeChatCommand(plName, this.r20AMPlayCommand(plName))+'\n');
return playListStr;
},
generateTrapTracks: function(tracksNameArr) {
var trapTrackStr = this.makeBold('Trap Sounds')+'\n';
let trapTrackNames = tracksNameArr.filter( name => name.toLowerCase().includes('trap') ).sort();
_.each(trapTrackNames, (ttName) => trapTrackStr += this.makeChatCommand(ttName.split(' by')[0].replace('Trap',''), this.r20AMPlayCommand(ttName))+' | ');
return trapTrackStr;
},
generateSpellSoundEffects: function(tracksNameArr) {
var spellTrackStr = this.makeBold('Spell Sounds')+'\n';
let spellTrackNames = _.filter(tracksNameArr, name => name.toLowerCase().includes('spell') ).sort();
_.each(spellTrackNames, (stName) => spellTrackStr += this.makeChatCommand(stName.split(' by')[0].replace('Spell',''), this.r20AMPlayCommand(stName))+' | ');
return spellTrackStr
},
generateMenu: function(playerId){
let playListStr = this.generatePlaylistStr(Object.keys(this.playlistDetails));
let trackNames = _.map(this.trackDetails, (track) => track['title']);
let trapTrackStr = this.generateTrapTracks(trackNames);
let spellTrackStr = this.generateSpellSoundEffects(trackNames);
let stopAudioButton = this.makeChatCommand('STOP ALL AUDIO', this.r20AMStopCommand);
// Finalize menu string
this.menuStr += playListStr + '\n'
+ trapTrackStr + '\n\n'
+ spellTrackStr + '\n'
+ '\n\n' + stopAudioButton
+ '}}';
// send chat for test
// sendChat('yaBoi', this.menuStr);
createObj('macro', {
name: 'roll20AM-Audio-Menu',
action: this.menuStr,
playerid: playerId
});
}
};
on('chat:message', function(msg){
'use strict';
roll20AMMenuGenerator.inputHandler(msg);
});