Skip to content

Instantly share code, notes, and snippets.

@Bastlifa
Last active July 23, 2023 08:22
Show Gist options
  • Save Bastlifa/5a8eaa6f7259c2e9ed4f43180c55d984 to your computer and use it in GitHub Desktop.
Save Bastlifa/5a8eaa6f7259c2e9ed4f43180c55d984 to your computer and use it in GitHub Desktop.
Rooftops plus dynamic lighting
// a script to remove rooftops if a player enters a building
// move the player flag to the page you want to use this on
// draw your dynamic lighting lines on your building
// use a roof token, best if it's rotation is an integer multiple of 90 degrees (0, 90, 180, 270)
// name the roof token "roof", without the quotes. Preferable put it on map layer
// drag in player tokens. That is, tokens either assigned to players, or representing characters assigned to player
// type !RoofReady into chat, or better yet, use it from a macro. Alternatively, dragging the player flag to the page does this.
// should be good to go. Let me know if there are errors please :)
// other feature: !RoofDLOff and !RoofDLOn will now turn off or on the dynamic lighting interaction of the script. Default is 'on'.
// if you want default to be off, change the declaration on line 21 to read: var dlInteraction = false;
// finally, the default is to turn off the roof when characters are under it. You can change this by editing the
// interactionRange variable on line 22. 0 Is when they're under the roof, 1 is within 5 feet, 2 10 ft, etc.
// Alternatively, you can type !RooftopRange x, where x is the number of 5 foot squares away from which it will interact.
on("ready", function() {
"use strict";
var allPlayerTokens = [];
var allRoofTokens = [];
var allPaths = [];
var dlInteraction = true;
var interactionRange = 0;
function getPlayerTokens()
{
var campaign = findObjs({type: "campaign"})[0];
var allTokens = findObjs({type: 'graphic', pageid: campaign.get("playerpageid"), layer: "objects"});
allPlayerTokens = [];
for (var i = 0; i<allTokens.length; i++)
{
if (allTokens[i].get("controlledby") != "" || allTokens[i].get("represents"))
{
if (allTokens[i].get("represents"))
{
if (getObj('character', allTokens[i].get("represents")).get("controlledby"))
{
allPlayerTokens.push(allTokens[i]);
}
}
else
{
allPlayerTokens.push(allTokens[i]);
}
}
}
}
function getRoofTokens()
{
var campaign = findObjs({type: "campaign"})[0];
var allMapTokens = findObjs({type: 'graphic', pageid: campaign.get("playerpageid")});
allRoofTokens = [];
for (var i = 0; i<allMapTokens.length; i++)
{
if (allMapTokens[i].get("name") == "roof")
{
allRoofTokens.push(allMapTokens[i]);
}
}
}
function getPaths()
{
var campaign = findObjs({type: "campaign"})[0];
allPaths = [];
allPaths = findObjs({type: 'path', pageid: campaign.get("playerpageid")});
}
function roofInsideCheck(roofToken)
{
var anyoneInside = false;
for (var i = 0; i < allPlayerTokens.length; i++)
{
if (roofToken.get("rotation") == 0 || roofToken.get("rotation") == 180)
{
if (roofToken.get("left") - (roofToken.get("width")/2 + 70*interactionRange) < allPlayerTokens[i].get("left") &&
roofToken.get("left") + (roofToken.get("width")/2 + 70*interactionRange) > allPlayerTokens[i].get("left") &&
roofToken.get("top") - (roofToken.get("height")/2 + 70*interactionRange) < allPlayerTokens[i].get("top") &&
roofToken.get("top") + (roofToken.get("height")/2 + 70*interactionRange) > allPlayerTokens[i].get("top"))
{
anyoneInside = true;
}
}
else if (roofToken.get("rotation") == 90 || roofToken.get("rotation") == 270)
{
if (roofToken.get("left") - (roofToken.get("height")/2 + 70*interactionRange) < allPlayerTokens[i].get("left") &&
roofToken.get("left") + (roofToken.get("height")/2 + 70*interactionRange) > allPlayerTokens[i].get("left") &&
roofToken.get("top") - (roofToken.get("width")/2 + 70*interactionRange) < allPlayerTokens[i].get("top") &&
roofToken.get("top") + (roofToken.get("width")/2 + 70*interactionRange) > allPlayerTokens[i].get("top"))
{
anyoneInside = true;
}
}
else
{
//default for odd rotation, won't be perfect.
if (roofToken.get("left") - (roofToken.get("width")/2 + 70*interactionRange) < allPlayerTokens[i].get("left") &&
roofToken.get("left") + (roofToken.get("width")/2 + 70*interactionRange) > allPlayerTokens[i].get("left") &&
roofToken.get("top") - (roofToken.get("height")/2 + 70*interactionRange) < allPlayerTokens[i].get("top") &&
roofToken.get("top") + (roofToken.get("height")/2 + 70*interactionRange) > allPlayerTokens[i].get("top"))
{
anyoneInside = true;
}
}
}
return anyoneInside;
}
function removeRoof(roofID)
{
getObj('graphic', roofID).set("layer", "walls");
if(dlInteraction) { restorePath(roofID); }
}
function restoreRoof(roofID)
{
getObj('graphic', roofID).set("layer", "map");
if(dlInteraction) { removePath(roofID); }
}
function removePath(roofID)
{
var roofToken = getObj('graphic', roofID);
if (!roofToken) {return;}
for (var i = 0; i < allPaths.length; i++)
{
if (roofToken.get("rotation") == 0 || roofToken.get("rotation") == 180)
{
if (roofToken.get("left") - (roofToken.get("width")/2 + 70*interactionRange) < allPaths[i].get("left") &&
roofToken.get("left") + (roofToken.get("width")/2 + 70*interactionRange) > allPaths[i].get("left") &&
roofToken.get("top") - (roofToken.get("height")/2 + 70*interactionRange) < allPaths[i].get("top") &&
roofToken.get("top") + (roofToken.get("height")/2 + 70*interactionRange) > allPaths[i].get("top"))
{
allPaths[i].set("layer", "gmlayer");
}
}
else if (roofToken.get("rotation") == 90 || roofToken.get("rotation") == 270)
{
if (roofToken.get("left") - (roofToken.get("height")/2 + 70*interactionRange) < allPaths[i].get("left") &&
roofToken.get("left") + (roofToken.get("height")/2 + 70*interactionRange) > allPaths[i].get("left") &&
roofToken.get("top") - (roofToken.get("width")/2 + 70*interactionRange) < allPaths[i].get("top") &&
roofToken.get("top") + (roofToken.get("width")/2 + 70*interactionRange) > allPaths[i].get("top"))
{
allPaths[i].set("layer", "gmlayer");
}
}
else
{
if (roofToken.get("left") - (roofToken.get("width")/2 + 70*interactionRange) < allPaths[i].get("left") &&
roofToken.get("left") + (roofToken.get("width")/2 + 70*interactionRange) > allPaths[i].get("left") &&
roofToken.get("top") - (roofToken.get("height")/2 + 70*interactionRange) < allPaths[i].get("top") &&
roofToken.get("top") + (roofToken.get("height")/2 + 70*interactionRange) > allPaths[i].get("top"))
{
allPaths[i].set("layer", "gmlayer");
}
}
}
}
function restorePath (roofID)
{
var roofToken = getObj('graphic', roofID);
if (!roofToken) {return;}
for (var i = 0; i < allPaths.length; i++)
{
if (roofToken.get("rotation") == 0 || roofToken.get("rotation") == 180)
{
if (roofToken.get("left") - (roofToken.get("width")/2 + 70*interactionRange) < allPaths[i].get("left") &&
roofToken.get("left") + (roofToken.get("width")/2 + 70*interactionRange) > allPaths[i].get("left") &&
roofToken.get("top") - (roofToken.get("height")/2 + 70*interactionRange) < allPaths[i].get("top") &&
roofToken.get("top") + (roofToken.get("height")/2 + 70*interactionRange) > allPaths[i].get("top"))
{
allPaths[i].set("layer", "walls");
}
}
else if (roofToken.get("rotation") == 90 || roofToken.get("rotation") == 270)
{
if (roofToken.get("left") - (roofToken.get("height")/2 + 70*interactionRange) < allPaths[i].get("left") &&
roofToken.get("left") + (roofToken.get("height")/2 + 70*interactionRange) > allPaths[i].get("left") &&
roofToken.get("top") - (roofToken.get("width")/2 + 70*interactionRange) < allPaths[i].get("top") &&
roofToken.get("top") + (roofToken.get("width")/2 + 70*interactionRange) > allPaths[i].get("top"))
{
allPaths[i].set("layer", "walls");
}
}
else
{
if (roofToken.get("left") - (roofToken.get("width")/2 + 70*interactionRange) < allPaths[i].get("left") &&
roofToken.get("left") + (roofToken.get("width")/2 + 70*interactionRange) > allPaths[i].get("left") &&
roofToken.get("top") - (roofToken.get("height")/2 + 70*interactionRange) < allPaths[i].get("top") &&
roofToken.get("top") + (roofToken.get("height")/2 + 70*interactionRange) > allPaths[i].get("top"))
{
allPaths[i].set("layer", "walls");
}
}
}
}
on("change:campaign:playerpageid", function() {
getPlayerTokens();
getRoofTokens();
getPaths();
sendChat("", "/w gm &{template:default} {{name=Rooftops Ready}} {{Player Tokens=" + allPlayerTokens.length +
"}} {{Roof Tokens=" + allRoofTokens.length + "}}")
});
on("chat:message", function (msg) {
if (msg.type === 'api' && msg.content === "!RoofReady"){
getPlayerTokens();
getRoofTokens();
getPaths();
sendChat("", "/w gm &{template:default} {{name=Rooftops Ready}} {{Player Tokens=" + allPlayerTokens.length +
"}} {{Roof Tokens=" + allRoofTokens.length + "}}")
}
});
on("chat:message", function (msg) {
if (msg.type === 'api' && msg.content === "!RoofDLOn"){
dlInteraction = true;
sendChat("", "/w gm &{template:default} {{name=Rooftops DL Interaction}} {{Now set to On}}");
}
});
on("chat:message", function (msg) {
if (msg.type === 'api' && msg.content === "!RoofDLOff"){
dlInteraction = false;
sendChat("", "/w gm &{template:default} {{name=Rooftops DL Interaction}} {{Now set to Off}}");
}
});
on("change:graphic", function(obj){
if (allPlayerTokens.includes(obj))
{
for (var i = 0; i < allRoofTokens.length; i++)
{
if (roofInsideCheck(allRoofTokens[i])) { removeRoof(allRoofTokens[i].id); }
else { restoreRoof(allRoofTokens[i].id); }
}
}
});
on("chat:message", function (msg) {
var args = msg.content.split(" ");
if (msg.type === 'api' && args[0] === "!RooftopRange"){
if (args[1]) { interactionRange = parseInt(args[1]); }
else { interactionRange = 0; }
sendChat("", "/w gm &{template:default} {{name=Rooftops Range}} {{Now set to " + interactionRange*5 + "}}");
}
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment