Skip to content

Commit 5591cd4

Browse files
committed
Add aziz light! script.
1 parent 7d529dc commit 5591cd4

File tree

4 files changed

+378
-0
lines changed

4 files changed

+378
-0
lines changed

Aziz Light!/1.0.0/aziz-light.js

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/**
2+
* Aziz Light!
3+
* This script allows you to quickly set and move the daylight brightness using dynamic lighting to different levels,
4+
* making it easy to macro light levels and mimic time passing.
5+
*
6+
* Orbotik's Roll20 Scripts & Macros
7+
* https://orbotik.com
8+
* This script is © Christopher Eaton (aka @orbotik) and is licensed under CC BY-SA 4.0.
9+
* To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/4.0/
10+
*
11+
* ## API Commands:
12+
* You can add exclamation points `!` to the end of any of the commands to animate the brightness change.
13+
* The more exclamation points, the faster the change! By default 1 exclamation point is a 1% change every 2seconds,
14+
* and each subsequent exclamation divides the time. So 4 exclamation points would make a 1% increase every 1/2second
15+
* (2seconds / 4).
16+
* ### GM Only:
17+
* !aziz light 90% daytime light.
18+
* !aziz eve 20% daytime light.
19+
* !aziz dark daytime light off.
20+
* !aziz exactly [number] +5% daytime light.
21+
* !aziz more +5% daytime light.
22+
* !aziz less -5% daytime light.
23+
*/
24+
25+
class AzizLightScript {
26+
27+
static VERSION = '1.0.0';
28+
29+
interval = null;
30+
31+
intervalTarget = null;
32+
33+
intervalStep = 1;
34+
35+
intervalCounter = 0;
36+
37+
constructor() {
38+
on('chat:message', this.onMessage.bind(this));
39+
}
40+
41+
/**
42+
* Stops and cleans up the animation.
43+
*/
44+
resetAnimation() {
45+
clearInterval(this.interval);
46+
this.intervalCounter = 0;
47+
this.intervalStep = 1;
48+
}
49+
50+
/**
51+
* Sets the page's brightness.
52+
* @param {Object} page
53+
* @param {Number} brightness
54+
* @param {Boolean} animate
55+
*/
56+
lightTo(page, brightness, animate) {
57+
if (animate) {
58+
let currentLevel = (page.get('daylightModeOpacity') ?? 0) * 100;
59+
let time = 2000 / Math.max(Math.min(100, animate), 1);
60+
this.resetAnimation();
61+
this.intervalTarget = brightness;
62+
this.intervalStep = 1;
63+
if (Math.abs(currentLevel - brightness) > 50 && animate > 5) {
64+
this.intervalStep = 2; //with wide time gaps, if there is an imperative to go fast, then boost the step.
65+
}
66+
if (currentLevel === brightness) {
67+
return; //already there!
68+
} else if (currentLevel > brightness) {
69+
this.intervalStep *= -1; //reduce brightness instead of increase
70+
}
71+
this.interval = setInterval(() => {
72+
let level = (page.get('daylightModeOpacity') ?? 0) * 100;
73+
if (Math.abs(currentLevel - brightness) <= 3 && Math.abs(this.intervalStep) > 1) {
74+
//ensure we don't overshoot when boosted.
75+
this.intervalStep = (this.intervalStep > 0 ? 1 : -1);
76+
}
77+
this.lightTo(page, level + this.intervalStep);
78+
this.intervalCounter++;
79+
if (this.intervalCounter > 100 || Math.round(level + this.intervalStep) === Math.round(this.intervalTarget)) {
80+
this.resetAnimation();
81+
}
82+
}, time);
83+
return;
84+
}
85+
if (brightness >= 5) {
86+
page.set({
87+
showlighting: true,
88+
daylight_mode_enabled: true,
89+
daylightModeOpacity: Math.max(0.05, Math.min(1, brightness / 100))
90+
});
91+
} else {
92+
page.set({
93+
showlighting: true,
94+
daylight_mode_enabled: false,
95+
daylightModeOpacity: 0.05
96+
});
97+
}
98+
}
99+
100+
onMessage(msg) {
101+
if (msg.type === 'api' && !msg.rolltemplate && msg.playerid) {
102+
let args;
103+
if (msg.content.indexOf('"') > -1 || msg.content.indexOf('\'') > -1) {
104+
let matches = msg.content.substring(1).matchAll(/[^\s"']+|["']([^"']*)["']/gi);
105+
args = [];
106+
for (let m of matches) {
107+
if (m[0]) {
108+
args.push(m.length > 1 && !!m[1] ? m[1] : m[0])
109+
}
110+
}
111+
} else {
112+
args = msg.content.substring(1).split(' ');
113+
}
114+
let command = args[0].toLowerCase();
115+
args.splice(0, 1);
116+
args = args.map(v => v.replaceAll(/[^a-zA-Z0-9 \._=@\-()&+!]/g, ''));
117+
if (command === 'aziz') {
118+
let currentPlayer = getObj('player', msg.playerid);
119+
if (currentPlayer) {
120+
let gm = playerIsGM(currentPlayer.id);
121+
if (gm) {
122+
let page = getObj('page', currentPlayer.get('lastpage'));
123+
let animate = false;
124+
let hasAnimate = args[args.length - 1].match(/(!+)$/g);
125+
if (hasAnimate?.length) {
126+
animate = hasAnimate[0].length;
127+
args[args.length - 1] = args[args.length - 1].replaceAll(/!+$/g, '');
128+
}
129+
let subCommand = (args[0] ?? '');
130+
log(`subCommand=${subCommand}; animate=${animate}`);
131+
this.resetAnimation();
132+
switch (subCommand) {
133+
case 'light': {
134+
this.lightTo(page, 90, animate);
135+
break;
136+
}
137+
case 'eve': {
138+
this.lightTo(page, 20, animate);
139+
break;
140+
}
141+
case 'dark': {
142+
this.lightTo(page, 0, animate);
143+
break;
144+
}
145+
case 'exactly': {
146+
let level = parseInt(args[1] || 0);
147+
if (isFinite(level) && level >= 0 && level <= 100) {
148+
this.lightTo(page, Math.round(level), animate);
149+
}
150+
break;
151+
}
152+
case 'less':
153+
case 'more': {
154+
let level = page.get('daylightModeOpacity');
155+
level += subCommand === 'more' ? 0.05 : -0.05;
156+
this.lightTo(page, level * 100, animate);
157+
break;
158+
}
159+
}
160+
}
161+
}
162+
}
163+
}
164+
}
165+
166+
}
167+
168+
on('ready', () => {
169+
log(`Aziz Light! script v${AzizLightScript.VERSION} initializing.`);
170+
new AzizLightScript();
171+
log(`Aziz Light! script initialized.`);
172+
});

Aziz Light!/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# [Orbotik's Aziz Light!](https://github.com/orbotik/roll20-scripts)
2+
`v1.0.0` `CC BY-SA 4.0`
3+
4+
This script allows you to quickly set and move the daylight brightness using dynamic lighting to different levels, making it easy to macro light levels and mimic time passing.
5+
*You can add an exclamation point `!` to the end of any of the commands to animate the brightness change.*
6+
7+
## Commands:
8+
| Cmd | Description |
9+
|:-|:-|
10+
| `!aziz light` | **GM-only.** Returns the daylight brightness to the default 90%. |
11+
| `!aziz eve` | **GM-only.** Moves the daylight brightness to the minimum of 20%. |
12+
| `!aziz dark` | **GM-only.** Turns daylight to 0% (off). |
13+
| `!aziz more` | **GM-only.** Increases the daylight brightness by 5%. |
14+
| `!aziz less` | **GM-only.** Decreases the daylight brightness by 5%. |
15+
| `!aziz exactly [number]` | **GM-only.** Sets the daylight brightness to a specific percentage (5-100). |
16+
> *Inspired from the scene from the Fifth Element.*
17+
> ![Aziz Light!](https://raw.githubusercontent.com/orbotik/roll20-scripts/refs/heads/master/.repo/aziz-light1.gif) ![Aziz Light Tally](https://raw.githubusercontent.com/orbotik/roll20-scripts/refs/heads/master/.repo/aziz-light2.gif)

Aziz Light!/aziz-light.js

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/**
2+
* Aziz Light!
3+
* This script allows you to quickly set and move the daylight brightness using dynamic lighting to different levels,
4+
* making it easy to macro light levels and mimic time passing.
5+
*
6+
* Orbotik's Roll20 Scripts & Macros
7+
* https://orbotik.com
8+
* This script is © Christopher Eaton (aka @orbotik) and is licensed under CC BY-SA 4.0.
9+
* To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/4.0/
10+
*
11+
* ## API Commands:
12+
* You can add exclamation points `!` to the end of any of the commands to animate the brightness change.
13+
* The more exclamation points, the faster the change! By default 1 exclamation point is a 1% change every 2seconds,
14+
* and each subsequent exclamation divides the time. So 4 exclamation points would make a 1% increase every 1/2second
15+
* (2seconds / 4).
16+
* ### GM Only:
17+
* !aziz light 90% daytime light.
18+
* !aziz eve 20% daytime light.
19+
* !aziz dark daytime light off.
20+
* !aziz exactly [number] +5% daytime light.
21+
* !aziz more +5% daytime light.
22+
* !aziz less -5% daytime light.
23+
*/
24+
25+
class AzizLightScript {
26+
27+
static VERSION = '1.0.0';
28+
29+
interval = null;
30+
31+
intervalTarget = null;
32+
33+
intervalStep = 1;
34+
35+
intervalCounter = 0;
36+
37+
constructor() {
38+
on('chat:message', this.onMessage.bind(this));
39+
}
40+
41+
/**
42+
* Stops and cleans up the animation.
43+
*/
44+
resetAnimation() {
45+
clearInterval(this.interval);
46+
this.intervalCounter = 0;
47+
this.intervalStep = 1;
48+
}
49+
50+
/**
51+
* Sets the page's brightness.
52+
* @param {Object} page
53+
* @param {Number} brightness
54+
* @param {Boolean} animate
55+
*/
56+
lightTo(page, brightness, animate) {
57+
if (animate) {
58+
let currentLevel = (page.get('daylightModeOpacity') ?? 0) * 100;
59+
let time = 2000 / Math.max(Math.min(100, animate), 1);
60+
this.resetAnimation();
61+
this.intervalTarget = brightness;
62+
this.intervalStep = 1;
63+
if (Math.abs(currentLevel - brightness) > 50 && animate > 5) {
64+
this.intervalStep = 2; //with wide time gaps, if there is an imperative to go fast, then boost the step.
65+
}
66+
if (currentLevel === brightness) {
67+
return; //already there!
68+
} else if (currentLevel > brightness) {
69+
this.intervalStep *= -1; //reduce brightness instead of increase
70+
}
71+
this.interval = setInterval(() => {
72+
let level = (page.get('daylightModeOpacity') ?? 0) * 100;
73+
if (Math.abs(currentLevel - brightness) <= 3 && Math.abs(this.intervalStep) > 1) {
74+
//ensure we don't overshoot when boosted.
75+
this.intervalStep = (this.intervalStep > 0 ? 1 : -1);
76+
}
77+
this.lightTo(page, level + this.intervalStep);
78+
this.intervalCounter++;
79+
if (this.intervalCounter > 100 || Math.round(level + this.intervalStep) === Math.round(this.intervalTarget)) {
80+
this.resetAnimation();
81+
}
82+
}, time);
83+
return;
84+
}
85+
if (brightness >= 5) {
86+
page.set({
87+
showlighting: true,
88+
daylight_mode_enabled: true,
89+
daylightModeOpacity: Math.max(0.05, Math.min(1, brightness / 100))
90+
});
91+
} else {
92+
page.set({
93+
showlighting: true,
94+
daylight_mode_enabled: false,
95+
daylightModeOpacity: 0.05
96+
});
97+
}
98+
}
99+
100+
onMessage(msg) {
101+
if (msg.type === 'api' && !msg.rolltemplate && msg.playerid) {
102+
let args;
103+
if (msg.content.indexOf('"') > -1 || msg.content.indexOf('\'') > -1) {
104+
let matches = msg.content.substring(1).matchAll(/[^\s"']+|["']([^"']*)["']/gi);
105+
args = [];
106+
for (let m of matches) {
107+
if (m[0]) {
108+
args.push(m.length > 1 && !!m[1] ? m[1] : m[0])
109+
}
110+
}
111+
} else {
112+
args = msg.content.substring(1).split(' ');
113+
}
114+
let command = args[0].toLowerCase();
115+
args.splice(0, 1);
116+
args = args.map(v => v.replaceAll(/[^a-zA-Z0-9 \._=@\-()&+!]/g, ''));
117+
if (command === 'aziz') {
118+
let currentPlayer = getObj('player', msg.playerid);
119+
if (currentPlayer) {
120+
let gm = playerIsGM(currentPlayer.id);
121+
if (gm) {
122+
let page = getObj('page', currentPlayer.get('lastpage'));
123+
let animate = false;
124+
let hasAnimate = args[args.length - 1].match(/(!+)$/g);
125+
if (hasAnimate?.length) {
126+
animate = hasAnimate[0].length;
127+
args[args.length - 1] = args[args.length - 1].replaceAll(/!+$/g, '');
128+
}
129+
let subCommand = (args[0] ?? '');
130+
log(`subCommand=${subCommand}; animate=${animate}`);
131+
this.resetAnimation();
132+
switch (subCommand) {
133+
case 'light': {
134+
this.lightTo(page, 90, animate);
135+
break;
136+
}
137+
case 'eve': {
138+
this.lightTo(page, 20, animate);
139+
break;
140+
}
141+
case 'dark': {
142+
this.lightTo(page, 0, animate);
143+
break;
144+
}
145+
case 'exactly': {
146+
let level = parseInt(args[1] || 0);
147+
if (isFinite(level) && level >= 0 && level <= 100) {
148+
this.lightTo(page, Math.round(level), animate);
149+
}
150+
break;
151+
}
152+
case 'less':
153+
case 'more': {
154+
let level = page.get('daylightModeOpacity');
155+
level += subCommand === 'more' ? 0.05 : -0.05;
156+
this.lightTo(page, level * 100, animate);
157+
break;
158+
}
159+
}
160+
}
161+
}
162+
}
163+
}
164+
}
165+
166+
}
167+
168+
on('ready', () => {
169+
log(`Aziz Light! script v${AzizLightScript.VERSION} initializing.`);
170+
new AzizLightScript();
171+
log(`Aziz Light! script initialized.`);
172+
});

Aziz Light!/script.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "Aziz Light",
3+
"script": "aziz-light.js",
4+
"version": "1.0.0",
5+
"description": "This script allows you to quickly set and move the daylight brightness using dynamic lighting to different levels, making it easy to macro light levels and mimic time passing.",
6+
"authors": "orbotik",
7+
"roll20userid": "12231884",
8+
"useroptions": [],
9+
"dependencies": [],
10+
"modifies": {
11+
"page.daylightModeOpacity": "read,write",
12+
"page.showlighting": "read,write",
13+
"page.daylight_mode_enabled": "read,write"
14+
},
15+
"conflicts": [],
16+
"previousversions": []
17+
}

0 commit comments

Comments
 (0)