Skip to content

Commit 90a464a

Browse files
authored
Merge pull request #2068 from Roll20/beacon/welcome-package
WelcomePackage | 1.4 | Adding Beacon Compatibility
2 parents fa934a0 + d45130c commit 90a464a

3 files changed

Lines changed: 236 additions & 37 deletions

File tree

WelcomePackage/1.4/script.js

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
const WelcomePackage = (() => {
2+
'use strict';
3+
4+
const CREATE_CHARACTER_CMD = '!welcomePackageCreateCharacter';
5+
6+
const observers = [];
7+
let isReady = false;
8+
9+
/**
10+
* Report an error to the GM and log its stack trace.
11+
* @param err The error.
12+
*/
13+
function _error(err) {
14+
log(`WelcomePackage ERROR: ${err.message}`);
15+
log(err.stack);
16+
sendChat('WelcomePackage API',
17+
`/w gm ERROR: ${err.message} --- See API console log for details.`);
18+
}
19+
20+
/**
21+
* Event handler for when a player logs into the game.
22+
* @private
23+
* @param {Player} player
24+
*/
25+
function _handlePlayerOnline(player) {
26+
if (player.get('_online') && !playerIsGM(player.get('_id')))
27+
createPlayerCharacter(player);
28+
}
29+
30+
/**
31+
* Registers a function to be notified when a character is created
32+
* @param {function} func
33+
*/
34+
function onAddCharacter(func){
35+
if('function' === typeof func){
36+
observers.push(func);
37+
}
38+
}
39+
40+
/**
41+
* Notifies all registered functions when a character is created
42+
* @param {Character} character
43+
*/
44+
function notifyAddCharacter(character){
45+
observers.forEach((f)=>f(character));
46+
}
47+
48+
/**
49+
* Creates a character creation macro for a player if they don't already
50+
* have the macro.
51+
* @param {Player} player
52+
*/
53+
function addCharacterCreateMacro() {
54+
const macroName = 'CreateACharacter';
55+
56+
let allPlayers = findObjs({
57+
_type: 'player'
58+
});
59+
_.each(allPlayers, player => {
60+
let playerId = player.get('_id');
61+
62+
let macro = findObjs({
63+
_type: 'macro',
64+
_playerid: playerId,
65+
name: macroName
66+
})[0];
67+
if(!macro) {
68+
log(`WelcomePackage: Creating "CreateACharacter" macro for player ` +
69+
`${player.get('_displayname')}`);
70+
createObj('macro', {
71+
_playerid: playerId,
72+
name: macroName,
73+
action: `${CREATE_CHARACTER_CMD} ?{Character Name:}`
74+
});
75+
}
76+
});
77+
}
78+
79+
/**
80+
* Creates a character for a player if they don't already have any characters.
81+
* @param {Player} player
82+
* @param {string} [name] The name of the character. If this is provided,
83+
* the character will be created regardless of whether
84+
* the player has a character already.
85+
*/
86+
function createPlayerCharacter(player, name) {
87+
let playerId = player.get('_id');
88+
let who = player.get('_displayname');
89+
90+
// Check if there are any characters already controlled by the player.
91+
let characters = findObjs({
92+
_type: 'character'
93+
}).filter(character => {
94+
return character.get('controlledby').includes(playerId);
95+
});
96+
97+
// Create the new character if there are none, or if a name has been
98+
// provided for a character being explicitly created through the macro.
99+
if(characters.length === 0 || name) {
100+
if(!name) {
101+
log(`WelcomePackage: Creating first-time character for player ` +
102+
`${player.get('_displayname')}`);
103+
name = `${who}'s character`;
104+
}
105+
106+
let character = createObj('character', {
107+
controlledby: playerId,
108+
inplayerjournals: 'all',
109+
name
110+
});
111+
112+
// Disable the Charactermancer for the new character by creating
113+
// the "version" attribute. This will be set to its correct value later
114+
// by the character sheet's worker.
115+
/*
116+
createObj('attribute', {
117+
name: 'mancer_confirm_flag',
118+
characterid: character.id,
119+
current: '1'
120+
});
121+
createObj('attribute', {
122+
name: 'l1mancer_status',
123+
characterid: character.id,
124+
current: 'completed'
125+
});
126+
*/
127+
128+
setTimeout(() => {
129+
notifyAddCharacter(character);
130+
showCharacterLink(who, character);
131+
}, 1000);
132+
}
133+
}
134+
135+
/**
136+
* Shows a player the link to their new character with a welcoming message.
137+
* @param {string} who The player's display name.
138+
* @param {Character} character
139+
*/
140+
function showCharacterLink(who, character) {
141+
const html = `
142+
<div class="menu" style="background: #fff; border: solid 1px #a88cd5; border-radius: 5px; font-weight: bold; margin-bottom: 1em; overflow: hidden;">
143+
<div class="menuHeader" style="background: #a88cd5 ; color: #fff ; text-align: center;">Welcome!</div>
144+
<div class="menuBody" style="padding: 5px; text-align: center">
145+
<div>A blank character has been created for you to start building: </div>
146+
<a href="http://journal.roll20.net/character/${character.get('_id')}" style="color: #a08;">${character.get('name')}
147+
</div>
148+
</div>
149+
`;
150+
sendChat('Welcome Package', '/w ' + who + ' ' + html);
151+
}
152+
153+
// When a player logs in, create a character for them if they don't have one.
154+
on('change:player:_online', player => {
155+
if(isReady)
156+
_handlePlayerOnline(player);
157+
});
158+
159+
on('ready', () => {
160+
try {
161+
// Create the global macro for the script (visible to all players)
162+
// if it doesn't already exist.
163+
addCharacterCreateMacro();
164+
165+
log('*** Initialized Welcome Package v1.3.3 ***');
166+
isReady = true;
167+
168+
// Wait some amount of time to give other scripts a chance to finish
169+
// loading. Then process any pending logged in players.
170+
setTimeout(() => {
171+
try {
172+
// Once we're loaded, create a character for any player that doesn't
173+
// have one.
174+
let players = findObjs({
175+
_type: 'player'
176+
});
177+
_.each(players, player => {
178+
_handlePlayerOnline(player);
179+
});
180+
}
181+
catch (err) {
182+
_error(err);
183+
}
184+
}, 5000);
185+
}
186+
catch (err) {
187+
_error(err);
188+
}
189+
});
190+
191+
/**
192+
* Process chat commands.
193+
*/
194+
on('chat:message', msg => {
195+
let playerId = msg.playerid;
196+
197+
if(msg.content.startsWith(CREATE_CHARACTER_CMD)) {
198+
let player = getObj('player', playerId);
199+
let argv = msg.content.split(' ');
200+
let name = argv.slice(1).join(' ');
201+
createPlayerCharacter(player, name);
202+
}
203+
});
204+
205+
return {
206+
OnAddCharacter: onAddCharacter,
207+
onAddCharacter
208+
};
209+
})();
210+
_.noop(WelcomePackage);

WelcomePackage/script.json

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
{
22
"name": "Welcome Package",
33
"script": "script.js",
4-
"version": "1.3.2",
5-
"previousversions": ["1.3.1", "1.3", "1.2", "1.1", "1.0"],
4+
"version": "1.4",
5+
"previousversions": [
6+
"1.3.2",
7+
"1.3.1",
8+
"1.3",
9+
"1.2",
10+
"1.1",
11+
"1.0"
12+
],
613
"description": "# Welcome Package\r\rThis script welcomes new players to your game and creates a blank new character\rfor them to begin building immediately.\r\rNormally, this would be a back and forth process with various steps depending the schedules of you and your players:\r* Player joins your campaign, can't do anything, and logs off.\r* You login, create a blank character for the player, and then log off.\r* The player eventually gets back on and builds their character.\r\rWith this script there is only one step:\r* Player joins your campaign and can immediately start building their character.\r\rThe script also installs a macro for each player named \"CreateACharacter\"\rwhich allows the players to create additional new characters with a\rspecified name.\r\r## Help\r\rMy scripts are provided 'as-is', without warranty of any kind, expressed or implied.\r\rThat said, if you experience any issues while using this script,\rneed help using it, or if you have a neat suggestion for a new feature,\rplease shoot me a PM:\rhttps://app.roll20.net/users/46544/ada-l\r\rWhen messaging me about an issue, please be sure to include any error messages that\rappear in your API Console Log, any configurations you've got set up for the\rscript in the VTT, and any options you've got set up for the script on your\rgame's API Scripts page. The more information you provide me, the better the\rchances I'll be able to help.\r\r## Show Support\r\rIf you would like to show your appreciation and support for the work I do in writing,\rupdating, maintaining, and providing tech support my API scripts,\rplease consider buying one of my art packs from the Roll20 marketplace:\r\rhttps://marketplace.roll20.net/browse/publisher/165/ada-lindberg\r",
714
"authors": "Ada Lindberg",
815
"roll20userid": 46544,
916
"useroptions": [],
10-
"dependencies": ["HTML Builder"],
17+
"dependencies": [
18+
"HTML Builder"
19+
],
1120
"modifies": {},
1221
"conflicts": []
13-
}
22+
}

WelcomePackage/src/script.js

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,6 @@ const WelcomePackage = (() => {
33

44
const CREATE_CHARACTER_CMD = '!welcomePackageCreateCharacter';
55

6-
const CSS = {
7-
'menu': {
8-
'background': '#fff',
9-
'border': 'solid 1px #a88cd5',
10-
'border-radius': '5px',
11-
'font-weight': 'bold',
12-
'margin-bottom': '1em',
13-
'overflow': 'hidden'
14-
},
15-
'menuBody': {
16-
'padding': '5px',
17-
'text-align': 'center'
18-
},
19-
'menuHeader': {
20-
'background': '#a88cd5',
21-
'color': '#fff',
22-
'text-align': 'center'
23-
}
24-
};
25-
266
const observers = [];
277
let isReady = false;
288

@@ -132,6 +112,7 @@ const WelcomePackage = (() => {
132112
// Disable the Charactermancer for the new character by creating
133113
// the "version" attribute. This will be set to its correct value later
134114
// by the character sheet's worker.
115+
/*
135116
createObj('attribute', {
136117
name: 'mancer_confirm_flag',
137118
characterid: character.id,
@@ -142,6 +123,7 @@ const WelcomePackage = (() => {
142123
characterid: character.id,
143124
current: 'completed'
144125
});
126+
*/
145127

146128
setTimeout(() => {
147129
notifyAddCharacter(character);
@@ -156,17 +138,15 @@ const WelcomePackage = (() => {
156138
* @param {Character} character
157139
*/
158140
function showCharacterLink(who, character) {
159-
let menu = new HtmlBuilder('.menu');
160-
menu.append('.menuHeader', 'Welcome!');
161-
let content = menu.append('.menuBody');
162-
content.append('div', 'A blank character has been created for you to start building: ');
163-
content.append('a', character.get('name'), {
164-
href: 'http://journal.roll20.net/character/' + character.get('_id'),
165-
style: {
166-
color: '#a08'
167-
}
168-
});
169-
let html = menu.toString(CSS);
141+
const html = `
142+
<div class="menu" style="background: #fff; border: solid 1px #a88cd5; border-radius: 5px; font-weight: bold; margin-bottom: 1em; overflow: hidden;">
143+
<div class="menuHeader" style="background: #a88cd5 ; color: #fff ; text-align: center;">Welcome!</div>
144+
<div class="menuBody" style="padding: 5px; text-align: center">
145+
<div>A blank character has been created for you to start building: </div>
146+
<a href="http://journal.roll20.net/character/${character.get('_id')}" style="color: #a08;">${character.get('name')}
147+
</div>
148+
</div>
149+
`;
170150
sendChat('Welcome Package', '/w ' + who + ' ' + html);
171151
}
172152

@@ -182,7 +162,7 @@ const WelcomePackage = (() => {
182162
// if it doesn't already exist.
183163
addCharacterCreateMacro();
184164

185-
log('*** Initialized Welcome Package vSCRIPT_VERSION ***');
165+
log('*** Initialized Welcome Package v1.3.3 ***');
186166
isReady = true;
187167

188168
// Wait some amount of time to give other scripts a chance to finish
@@ -227,4 +207,4 @@ const WelcomePackage = (() => {
227207
onAddCharacter
228208
};
229209
})();
230-
_.noop(WelcomePackage);
210+
_.noop(WelcomePackage);

0 commit comments

Comments
 (0)