Skip to content

Commit e77c195

Browse files
author
Cazra
committed
Implemented useroptions for specifying terminal screen colors.
1 parent 14ba9f2 commit e77c195

File tree

3 files changed

+364
-89
lines changed

3 files changed

+364
-89
lines changed

Diff for: FalloutTerminal/1.1/terminal.js

+336
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
(function() {
2+
var ACTIVATE_TERMINAL_CMD = '!_activate_terminal';
3+
var PASSWORD_CMD = '!_guess_terminal_password';
4+
var PREV_SCREEN_CMD = '!_prev_terminal_screen';
5+
var SHOW_SCREEN_CMD = '!_show_terminal_screen';
6+
var VERSION = '1.1';
7+
8+
var ASCII_TABLE = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`{|}~';
9+
var DEFAULT_BG_COLOR = '#000';
10+
var DEFAULT_BUTTON_COLOR = '#114422';
11+
var DEFAULT_TEXT_COLOR = '#22ff88';
12+
13+
var curTerminal;
14+
var nextItemId;
15+
var history = [];
16+
var curScreenId;
17+
18+
/**
19+
* The FalloutTerminal state data.
20+
* @typedef {object} FalloutTerminalState
21+
*/
22+
state.FalloutTerminal = {}; //state.FalloutTerminal || {};
23+
_.defaults(state.FalloutTerminal, {
24+
userOptions: {}
25+
});
26+
var useroptions = globalconfig && globalconfig.falloutterminal;
27+
if(useroptions) {
28+
state.FalloutTerminal.userOptions = {
29+
bgColor: useroptions['bgColor'],
30+
buttonColor: useroptions['buttonColor'],
31+
textColor: useroptions['textColor']
32+
};
33+
}
34+
35+
/**
36+
* Activates a terminal by initializing its JSON and displaying the
37+
* first screen of the terminal.
38+
* @private
39+
* @param {string} id
40+
*/
41+
function _activateTerminal(id) {
42+
var json = _getTerminalJson(id);
43+
if(json) {
44+
_initTerminal(json);
45+
_displayScreen(curTerminal._startId);
46+
}
47+
}
48+
49+
/**
50+
* Displays a terminal screen in the chat.
51+
* @private
52+
* @param {(string|int)} id
53+
*/
54+
function _displayScreen(id) {
55+
var screen = curTerminal[id];
56+
curScreenId = id;
57+
58+
var html = '<table style="background-color: ' + getBgColor() + '; border: solid 1px ' + getBgColor() + '; border-collapse: separate; border-radius: 10px; font-family: monospace; overflow: hidden; width: 100%;">';
59+
html += '<thead><tr><th style="' +
60+
'background: ' + getTextColor() + ';' +
61+
'color: ' + getBgColor() + ';' +
62+
'padding: 0.5em 1em;' +
63+
'">' + curTerminal._terminalName + '</th></tr>';
64+
html += '</thead>';
65+
html += '<tbody>';
66+
html += '<tr><td style ="color: ' + getTextColor() + '; padding: 0.5em;">';
67+
if(screen)
68+
html += _displayScreenContent(screen);
69+
else
70+
html += _displayScreenContent('ERROR 0xFFFFF710\n"Data Corru:xsfkleg,, g364[735}3__' + id + '."');
71+
if(!curTerminal._locked)
72+
html += _displayScreenButtons(screen);
73+
html += '</td></tr></tbody></table>';
74+
sendChat('Fallout Terminal', html);
75+
}
76+
77+
/**
78+
* Displays a command button for the terminal screen.
79+
* @param {string} cmd
80+
* @param {string} label
81+
* @return {string}
82+
*/
83+
function _displayScreenButton(cmd, label) {
84+
return '<a href="' + cmd + '" style="background: ' + getButtonColor() + '; border: none; color: ' + getTextColor() + '; margin: 0.2em 0; width: 95%;">' + label + '</a>';
85+
}
86+
87+
/**
88+
* Displays the navigation buttons for the screen.
89+
* @param {TerminalScreen} screen
90+
*/
91+
function _displayScreenButtons(screen) {
92+
var prevScreenId = history[history.length-1];
93+
94+
var html = '<div style="padding-top: 1em;">';
95+
if(screen) {
96+
_.each(screen.screenIds, function(id) {
97+
var screen = curTerminal[id];
98+
if(screen)
99+
html += _displayScreenButton(SHOW_SCREEN_CMD + ' ' + id, screen.name);
100+
});
101+
}
102+
if(prevScreenId !== undefined)
103+
html += _displayScreenButton(PREV_SCREEN_CMD, '<div style="text-align:center;">BACK</div>');
104+
html += '</div>';
105+
return html;
106+
}
107+
108+
/**
109+
* Produce the HTML content for a terminal screen.
110+
* @private
111+
* @param {TerminalScreen} screen
112+
* @return {string}
113+
*/
114+
function _displayScreenContent(screen) {
115+
var html = '<div>';
116+
if(_.isString(screen))
117+
html += _htmlNewlines(screen);
118+
else if(curTerminal._locked) {
119+
if(!screen.attempts)
120+
html += _htmlNewlines('TERMINAL LOCKED\n\nPLEASE CONTACT AN ADMINISTRATOR');
121+
else
122+
html += _htmlNewlines(_displayScreenHacking());
123+
}
124+
else {
125+
html += _htmlNewlines(screen.name + '\n\n' + (screen.content || ''));
126+
}
127+
html += '</div>';
128+
return html;
129+
}
130+
131+
/**
132+
* Displays the terminal lockout screen.
133+
* @private
134+
* @return {string}
135+
*/
136+
function _displayScreenHacking() {
137+
var attempts = curTerminal._attempts;
138+
if(!attempts)
139+
return 'TERMINAL LOCKED\n\nPLEASE CONTACT AN ADMINISTRATOR';
140+
else {
141+
var html = attempts + ' ATTEMPT(S) LEFT: \n';
142+
_.each(_.range(attempts), function() {
143+
html += '&#9608; ';
144+
});
145+
html += '\n\n';
146+
147+
// Display a fake RAM dump.
148+
var startAddr = 0xf000 + Math.floor(Math.random()*0xf0f);
149+
var inc = 20;
150+
_.each(_.range(16), function(i) {
151+
var addr = startAddr + inc*i;
152+
html += '0x' + addr.toString(16).toUpperCase() + ' ';
153+
_.each(_.range(inc), function() {
154+
html += ASCII_TABLE[Math.floor(Math.random()*ASCII_TABLE.length)].replace('<','&lt;').replace('>', '&gt;');
155+
});
156+
html += '\n';
157+
});
158+
159+
// Display a button to guess the password.
160+
if(curTerminal._password) {
161+
html += '<div style="padding-top: 1em;">';
162+
html += _displayScreenButton(PASSWORD_CMD + ' ?{Password:}', 'GUESS PASSWORD');
163+
html += '</div>';
164+
}
165+
166+
return html;
167+
}
168+
}
169+
170+
/**
171+
* Gets the configured color for the terminal background.
172+
* @return {string}
173+
*/
174+
function getBgColor() {
175+
return state.FalloutTerminal.userOptions.bgColor || DEFAULT_BG_COLOR;
176+
}
177+
178+
/**
179+
* Gets the configured color for the terminal buttons.
180+
* @return {string}
181+
*/
182+
function getButtonColor() {
183+
return state.FalloutTerminal.userOptions.buttonColor || DEFAULT_BUTTON_COLOR;
184+
}
185+
186+
/**
187+
* Parses a terminal's raw JSON from its gmnotes.
188+
* @private
189+
* @param {string} id
190+
*/
191+
function _getTerminalJson(id) {
192+
var terminal = getObj('graphic', id);
193+
if(terminal && terminal.get('name').toLowerCase().indexOf('terminal') === 0) {
194+
var notes = unescape(terminal.get('gmnotes'));
195+
notes = notes.split(/<[/]?.+?>/g).join('');
196+
197+
return JSON.parse(notes);
198+
}
199+
}
200+
201+
/**
202+
* Gets the configured color for terminal text.
203+
* @return {string}
204+
*/
205+
function getTextColor() {
206+
return state.FalloutTerminal.userOptions.textColor || DEFAULT_TEXT_COLOR;
207+
}
208+
209+
/**
210+
* Guesses the password for the terminal.
211+
* @param {string} password
212+
*/
213+
function _guessPassword(password) {
214+
if(password === curTerminal._password)
215+
curTerminal._locked = false;
216+
else
217+
curTerminal._attempts--;
218+
_displayScreen(curTerminal._startId);
219+
}
220+
221+
/**
222+
* Replaces \n's with <br/>'s.
223+
* @param {string} str
224+
* @return {string}
225+
*/
226+
function _htmlNewlines(str) {
227+
return str.replace(/\n/g, '<br/>');
228+
}
229+
230+
/**
231+
* Initializes the internal JSON for the terminal. Optimized for use
232+
* by the Roll20 macro system.
233+
* @private
234+
* @param {Terminal} json
235+
*/
236+
function _initTerminal(json) {
237+
// Recursively create a map of each item in the terminal.
238+
curTerminal = {};
239+
nextItemId = 0;
240+
history = [];
241+
242+
_initTerminalScreens(json);
243+
_.extend(curTerminal, {
244+
_locked: json.locked,
245+
_password: json.password,
246+
_attempts: json.attempts,
247+
_startId: json.id,
248+
_terminalName: json.name
249+
});
250+
}
251+
252+
/**
253+
* Initializes the IDs for the terminal screens.
254+
* @private
255+
* @param {TerminalScreen} screen
256+
*/
257+
function _initTerminalScreens(screen) {
258+
// Assign the item an ID if it doesn't already have one.
259+
if(!screen.id) {
260+
screen.id = nextItemId;
261+
nextItemId++;
262+
}
263+
curTerminal[screen.id] = screen;
264+
265+
// Recursively create the child items' IDs.
266+
screen.screenIds = [];
267+
_.each(screen.screens, function(child) {
268+
if(_.isObject(child)) {
269+
_initTerminalScreens(child);
270+
screen.screenIds.push(child.id);
271+
}
272+
else
273+
screen.screenIds.push(child);
274+
});
275+
delete screen.screens;
276+
}
277+
278+
/**
279+
* Initialize the token macro for the terminals.
280+
*/
281+
on('ready', function() {
282+
var macro = findObjs({
283+
_type: 'macro',
284+
name: 'displayTerminal'
285+
})[0];
286+
287+
if(!macro) {
288+
var players = findObjs({
289+
_type: 'player'
290+
});
291+
var gms = _.filter(players, function(player) {
292+
return playerIsGM(player.get('_id'));
293+
});
294+
295+
_.each(gms, function(gm) {
296+
createObj('macro', {
297+
_playerid: gm.get('_id'),
298+
name: 'displayTerminal',
299+
action: ACTIVATE_TERMINAL_CMD,
300+
istokenaction: true
301+
});
302+
});
303+
}
304+
305+
log('=== Initialized Fallout Terminal v' + VERSION + ' ===');
306+
});
307+
308+
/**
309+
* Process the terminal chat commands.
310+
*/
311+
on('chat:message', function(msg) {
312+
try {
313+
if(msg.content === ACTIVATE_TERMINAL_CMD && msg.selected) {
314+
_activateTerminal(msg.selected[0]._id);
315+
}
316+
if(msg.content.indexOf(SHOW_SCREEN_CMD) === 0) {
317+
var args = msg.content.split(' ');
318+
var id = args[1];
319+
history.push(curScreenId);
320+
_displayScreen(args[1]);
321+
}
322+
if(msg.content.indexOf(PREV_SCREEN_CMD) === 0) {
323+
var id = history.pop();
324+
_displayScreen(id);
325+
}
326+
if(msg.content.indexOf(PASSWORD_CMD) === 0) {
327+
var args = msg.content.split(' ');
328+
var password = args.slice(1).join(' ');
329+
_guessPassword(password);
330+
}
331+
}
332+
catch(err) {
333+
log('FALLOT TERMINAL ERROR: ' + err.message);
334+
}
335+
});
336+
})();

0 commit comments

Comments
 (0)