Skip to content

Commit 2dd79c7

Browse files
author
Tyson
committed
Removed chat reporting of blocked commands, and fixed the issue where ClockTokens would report on commands sent to other scripts. Also corrected .readme file.
1 parent ac721d1 commit 2dd79c7

File tree

3 files changed

+262
-9
lines changed

3 files changed

+262
-9
lines changed

ClockTokens/1.2/ClockTokens.js

+239
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/*
2+
* ClockTokens.js
3+
* Current version: 1.2
4+
* Last updated: 2022-04-24 by Tyson Tiatia
5+
*
6+
* See README.md for full description
7+
*
8+
* Commands:
9+
* !clocktokens [next|prev|first|last]
10+
*
11+
* User Options:
12+
* [GM Only]
13+
* [Use Macros]
14+
*/
15+
var ClockTokens = ClockTokens || (function () {
16+
'use strict';
17+
18+
var version = "1.2",
19+
lastUpdate = "2022-04-24",
20+
listenerActive = false,
21+
userOptions = (globalconfig && globalconfig.ClockTokens) || {
22+
"GM Only": true,
23+
"Use Macros": true
24+
},
25+
26+
/** Prints script info to log */
27+
checkInstall = function () {
28+
log("ClockTokens v" + version + " installed.");
29+
},
30+
31+
/** Prints script user options to log */
32+
checkOptions = function () {
33+
log("-GM Only: " + userOptions["GM Only"] + "\n-Use Macros: " + userOptions["Use Macros"]);
34+
},
35+
36+
/** Adds the chat event handler */
37+
registerEventHandlers = function () {
38+
if (!listenerActive) {
39+
on('chat:message', handleInput);
40+
listenerActive = true;
41+
}
42+
},
43+
44+
/** Returns a usable string for imagesrc
45+
* @param {string} imgscr The raw source string
46+
*/
47+
getCleanImagesrc = function (imgsrc) {
48+
var parts = imgsrc.match(/(.*\/images\/.*)(thumb|med|original|max)([^?]*)(\?[^?]+)?$/);
49+
if (parts) {
50+
return parts[1] + 'thumb' + parts[3] + (parts[4] ? parts[4] : `?${Math.round(Math.random() * 9999999)}`);
51+
}
52+
return;
53+
},
54+
55+
/**
56+
* Processes input from the user
57+
* @param {*} msg - The Roll20 chat message object/
58+
*/
59+
handleInput = function (msg) {
60+
if (msg.type == "api") {
61+
var cmds = msg.content.trim().toLowerCase().split(/[ ]+/);
62+
63+
if (cmds[0] === "!clocktokens") {
64+
65+
// Based on user setting, ignore non-GM players' commands
66+
if (userOptions["GM Only"] && !playerIsGM(msg.playerid) && cmds[0] === "!clocktokens") {
67+
log("ClockTokens: Command from " + msg.who + " blocked due to GM-only mode being active");
68+
return;
69+
}
70+
71+
if (cmds.length !== 2) {
72+
sendChat("API", "Error with !clocktokens command.");
73+
}
74+
if (msg.selected && msg.selected.length > 0) {
75+
var tokens = msg.selected.flatMap(function (o) {
76+
return o._type == "graphic" ? getObj("graphic", o._id) : [];
77+
});
78+
79+
tokens.forEach(obj => {
80+
var allSides = getSides(obj);
81+
if (allSides.length <= 1) {
82+
// Nothing to change
83+
return;
84+
}
85+
86+
var currentSide = getCurrentSide(obj, allSides);
87+
switch (cmds[1]) {
88+
case "next":
89+
if (currentSide < allSides.length + 1) {
90+
setSide(obj, allSides, currentSide + 1);
91+
}
92+
break;
93+
case "prev":
94+
if (currentSide > 0) {
95+
setSide(obj, allSides, currentSide - 1);
96+
}
97+
break;
98+
case "first":
99+
setSide(obj, allSides, 0);
100+
break;
101+
case "last":
102+
setSide(obj, allSides, allSides.length - 1);
103+
break;
104+
}
105+
});
106+
}
107+
}
108+
}
109+
},
110+
111+
/**
112+
* Retrieves all data on token sides
113+
* @param {*} obj - the Roll20 graphic object
114+
*/
115+
getSides = function (obj) {
116+
return obj.get("sides").split("|");
117+
},
118+
119+
/**
120+
* Retrieves the index of the current token side
121+
* @param {*} obj - the Roll20 graphic object
122+
* @param {array} allSides - the array of image data for the token
123+
*/
124+
getCurrentSide = function (obj, allSides) {
125+
var side = obj.get("currentSide");
126+
return allSides.indexOf(side);
127+
},
128+
129+
/**
130+
* Changes the token's active side to the specified index
131+
* @param {*} obj - The Roll20 graphic object
132+
* @param {array} allSides - the array of image data for the token
133+
* @param {int} newIndex - the index of th
134+
*/
135+
setSide = function (obj, allSides, newIndex) {
136+
var nextURL = getCleanImagesrc(decodeURIComponent(allSides[newIndex]));
137+
if (nextURL) {
138+
obj.set({
139+
currentSide: allSides[newIndex],
140+
imgsrc: nextURL
141+
});
142+
}
143+
},
144+
145+
/** Adds the macros for this script */
146+
manageMacros = function () {
147+
if (userOptions["Use Macros"]) {
148+
var gmId = findObjs({ _type: 'player' })[0].id;
149+
var whoCanSee = !userOptions["GM Only"] ? "all" : getAllGmPlayerNames().join(",");
150+
addMacro("TokenNext", "!clocktokens next", gmId, whoCanSee);
151+
addMacro("TokenPrev", "!clocktokens prev", gmId, whoCanSee);
152+
addMacro("TokenFirst", "!clocktokens first", gmId, whoCanSee);
153+
addMacro("TokenLast", "!clocktokens last", gmId, whoCanSee);
154+
}
155+
else {
156+
removeMacro("TokenNext");
157+
removeMacro("TokenPrev");
158+
removeMacro("TokenFirst");
159+
removeMacro("TokenLast");
160+
}
161+
},
162+
163+
/**
164+
* Either creates a new macro or updates an existing one to match the specifications
165+
* @param {string} mName - The Name of the macro
166+
* @param {string} mAction - The contents of the macro (what it does when it runs)
167+
* @param {string} gmId - A playereId to be recorded as the creator
168+
* @param {string} visibleTo - Comma-delimited list of players who should be able to see the macro
169+
*/
170+
addMacro = function (mName, mAction, gmId, whoCanSee) {
171+
var macro = findObjs({ type: "macro", name: mName });
172+
if (macro.length == 0) {
173+
createObj("macro", {
174+
name: mName,
175+
action: mAction,
176+
playerid: gmId,
177+
istokenaction: true,
178+
visibleto: whoCanSee
179+
});
180+
}
181+
else {
182+
macro[0].set({
183+
action: mAction,
184+
istokenaction: true,
185+
visibleto: whoCanSee
186+
});
187+
if (macro.length > 1) {
188+
for (var i = 1; i < macro.length; i++) {
189+
macro[i].remove();
190+
}
191+
}
192+
}
193+
},
194+
195+
/**
196+
* Deletes the specified macro, if it exists
197+
* @param {string} mName - The Name of the macro
198+
*/
199+
removeMacro = function (mName) {
200+
var macro = findObjs({ type: "macro", name: mName });
201+
if (macro.length > 0) {
202+
macro.forEach(function (m) {
203+
m.remove();
204+
});
205+
}
206+
},
207+
208+
/**
209+
* Returns a list of GM names
210+
*/
211+
getAllGmPlayerNames = function () {
212+
var names = [];
213+
var currentPlayers = findObjs({
214+
_type: "player",
215+
});
216+
_.each(currentPlayers, function (obj) {
217+
if (playerIsGM(obj.get("_id"))) {
218+
log("GM found \"" + obj.get("_displayname") + "\"");
219+
names.push(obj.get("_id"));
220+
}
221+
});
222+
return names;
223+
};
224+
225+
return {
226+
CheckInstall: checkInstall,
227+
CheckOptions: checkOptions,
228+
ManageMacros: manageMacros,
229+
RegisterEventHandlers: registerEventHandlers
230+
};
231+
}());
232+
233+
on("ready", function () {
234+
'use strict';
235+
ClockTokens.CheckInstall();
236+
ClockTokens.CheckOptions();
237+
ClockTokens.ManageMacros();
238+
ClockTokens.RegisterEventHandlers();
239+
});
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,39 @@
11
# Clock Tokens
22

3-
##What is it?
3+
## What is it?
4+
45
This script gives you an easy way to manage multi-sided tokens which are being used to represent [progress clocks](http://bladesinthedark.com/progress-clocks), or any other kind of incrementing timer or countdown.
56

6-
##What does it do?
7+
## What does it do?
8+
79
The script changes the token image of currently selected tokens based on the command given:
10+
811
* ``!clocktokens next`` changes to the next 'side' of a multi-sided token. If already on the last side, no change.
912
* ``!clocktockens prev`` changes to the previous 'side' of a multi-sided token. If already on the first side, no change.
1013
* ``!clocktockens first`` changes to the first 'side' of a multi-sided token. If already on the first side, no change.
1114
* ``!clocktockens last`` changes to the last 'side' of a multi-sided token. If already on the last side, no change.
1215

13-
##User Options
16+
## User Options
17+
1418
* _GM Only_: (Default On) If enabled then only the GM can use the ``!clocktokens`` commands.
1519
* _Use Macros_: (Default On) If enabled then token macros will automatically be created an maintained, one for each of the four commands above.
1620

17-
##Why use this over other token scripts?
21+
## Why use this over other token scripts?
22+
1823
This script was designed specifically for handling the large number of _Forged In The Dark_ and _Powered By The Apocolpyse_ games that I run. Multi-sided tokens take far too many clicks to move between sides, and there is no way to change multiple at once.
1924

2025
There are other token scripts with far more functionality, and if you feel you'll benefit from them then I recommend using those instead. However if you only want to flip multi-sided tokens back and forth in sequence then there's no need to bloat your game with a larger, more complicated script.
2126

22-
##Changelist
23-
###_v1.0_ (2021-01-01)
27+
## Changelist
28+
29+
### _v1.0_ (2021-01-01)
30+
2431
* Script created
25-
###_v1.1_ (2021-05-09)
32+
33+
### _v1.1_ (2021-05-09)
34+
2635
* Changed logic to accomodate multi-GM games or games where the creator is not a GM.
36+
37+
### _v1.2_ (2022-04-24)
38+
39+
* Removed chat reporting of blocked commands, and fixed the issue where ClockTokens would report on commands sent to other scripts. Also corrected .readme file.

ClockTokens/script.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Clock Tokens",
33
"script": "ClockTokens.js",
4-
"version": "1.1",
4+
"version": "1.2",
55
"authors": "Tyson Tiatia",
66
"description": "A script for GMs utilising Multi-sided tokens to track 'clocks', a common mechanic for tracking progress in Power By The Apocolypse and Forged In The Dark games, among others. Accepts the command !clocktokens with one of the following parameters: 'next', 'prev', 'first', 'last', and changes any multi-sided tokens selected to the corresponding image. Automatically adds four token macros for these commands.",
77
"roll20userid": "514883",
@@ -22,6 +22,7 @@
2222
}
2323
],
2424
"previousversions": [
25-
"1.0"
25+
"1.0",
26+
"1.1"
2627
]
2728
}

0 commit comments

Comments
 (0)