
markus l. said:
Looks really cool but I tried it and nothing shows up except:
"API: GeomorphicMap has images on it."
Though no pictures are showing, the lighting script seems to work.
Jarrod . said:
The !geo function works perfectly.. and it is far more usable than previous iterations. Congrats!
I think I missed how to set up the lighting for now (despite the fact that it doesn't function properly). Is there something I need to place on line 866 where it has "obj.path"? Currently when I try to use !light, I get this:
readMap = function() { var campaignPagesGeo = findObjs({ name: mapName, _type: "page"}); geomorphicMapId = campaignPagesGeo[0].get("_id"); var currentPageGraphics = findObjs({ _pageid: geomorphicMapId, layer: "map" }); var lightArray = new Array(); _.each(currentPageGraphics, function(obj) { pathData = _.where(geomorphicTilesArray, {side: obj.get("currentSide")}); lightArray.push({ currentSide: obj.get("currentSide"), left: obj.get("left"), top: obj.get("top"), rotation: obj.get("rotation"), path: pathData[0].walls }); }); log(lightArray) /* _.each(lightArray, function(obj) { createObj("path",{ layer: "walls", _path: obj.path, width: 840, height: 840, top: obj.top, left: obj.left, rotation: obj.rotation, stroke: "#00ff00", pageid: geomorphicMapId }); }); */ };
To check all layers I mean this:markus l. said:
Thanks for the quick reply!
I went through all layers, drawing a doodle on each and selecting everything on the layer with ctrl+A and there doesn't seem to be anything off screen.
Doesn't work when I retry on a new map.
When you say "You need to to check all layers.", is that a toggle of some kind or just looking at each layer?
I redid everything on a fresh campaign and I can't make it work there either.
on("ready", function() { on("chat:message", function(msg) {if(msg.type == "api"){processMessage(msg)};}); }); processMessage = function(msg) { if(msg.type !== "api"){return}; var mapName = "GeomorphicMap";
var campaignPagesGeo = findObjs({ name: mapName, _type: "page"}); geomorphicMapId = campaignPagesGeo[0].get("_id"); var currentPageGraphics = findObjs({ _pageid: geomorphicMapId}); log(currentPageGraphics) };
mapCheck = function() { var campaignPagesGeo = findObjs({ name: mapName, _type: "page"}); if(campaignPagesGeo.length == 0){isError = true; errorType = mapName + " is missing."; return;}; if(campaignPagesGeo.length > 1){isError = true; errorType = "More than one " + mapName + "."; return;}; geomorphicMapId = campaignPagesGeo[0].get("_id"); var geomorphicMapGraphics = findObjs({_pageid: geomorphicMapId, _type: "graphic"}); if(geomorphicMapGraphics.length != 0){isError = true; errorType = mapName + " has images on it."; return;}; var geomorphicMapGraphics = findObjs({_pageid: geomorphicMapId, _type: "path"}); if(geomorphicMapGraphics.length != 0){isError = true; errorType = mapName + " has paths on it."; return;}; geomorphicMapWidth = campaignPagesGeo[0].get("width"); geomorphicMapHeight = campaignPagesGeo[0].get("height"); if(geomorphicMapWidth % 12 !== 0){isError = true; errorType = "Map width must be disible by 12."; return;}; if(geomorphicMapHeight % 12 !== 0){isError = true; errorType = "Map height must be disible by 12."; return;}; if(geomorphicMapWidth < 36 || geomorphicMapHeight < 36){isError = true; errorType = "Map height must be 36 or larger."; return;}; log(geomorphicMapGraphics) };
Jarrod . said:
ok, so... after re-entering the script (deleting it and copying and pasting the script again) both !geo and !light work.. and looking at how the lighting is set up, I'm wondering if the way the Lighting lines are listed in the array, if it's making smaller polygons on the map instead of setting the paths to be the barriers. Here's a shot of what I mean
"[\[\"M\",315,595],[\"L\",245,595],[\"L\",245,245],[\"L\",595,245],[\"L\",595,595],[\"L\",525,595],\[\"M\",315,0],[\"L\",315,35],[\"L\",525,35],[\"L\",525,0],\ [\"M\",840,105],[\"L\",805,105],[\"L\",805,35],[\"L\",735,35],[\"L\",735,0],\[\"M\",0,105],[\"L\",35,105],[\"L\",35,35],[\"L\",105,35],[\"L\",105,0],\ [\"M\",0,315],[\"L\",35,315],[\"L\",35,525],[\"L\",0,525],\ [\"M\",840,315],[\"L\",805,315],[\"L\",805,525],[\"L\",840,525],\ [\"M\",0,735],[\"L\",35,735],[\"L\",35,805],[\"L\",105,805],[\"L\",105,840],\ [\"M\",840,735],[\"L\",805,735],[\"L\",805,805],[\"L\",735,805],[\"L\",735,840],\ [\"M\",315,840],[\"L\",315,805],[\"L\",525,805],[\"L\",525,840]\]";Each start of "M" would be its own object with its own path... tricky part is you have to find the center of each path and relate it to the center of the tile and turn it around that point based on rotation.
geomorph = function() { mapCheck(); checkTileTable(); buildTileArray(); gridOutMap(); createSides(); if(isError == true){sendChat("API", errorType); isError = false; return;}; placeCorners(); placeEdge(); fillFrame(); setSpin(); stepThroughMap(); };The functions are pretty sequential... so you can comment out each one and step through it.
geomorph = function() { mapCheck(); /*Only functions above this will run checkTileTable(); buildTileArray(); gridOutMap(); createSides(); if(isError == true){sendChat("API", errorType); isError = false; return;}; placeCorners(); placeEdge(); fillFrame(); setSpin(); stepThroughMap(); */ };Get the MapCheck(); working without error and then the next.
markus l. said:
OK so when I allowed the last line "stepThroughMap();" that's when it starts saying that there already are images on the map and also "ERROR: You cannot set the imgsrc or avatar of an object unless you use an image that is in your Roll20 Library. See the API documentation for more info."
*Thanks :)
dynamicLighting = [ [315,595], [245,595], [245,245], [595,245], [595,595], [525,595] ]; function rot(angle, point) { var pointX = point[0], pointY = point[1], originX = 70*6, originY = 70*6; angle = angle * Math.PI / 180.0; return [ Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX, Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY ]; } //Put this somewhere, I use on ready. var h = 0; var l = false; var h2 = 0; var l2 = false; for(var i = 0; i < dynamicLighting.length; i++) { dynamicLighting[i] = rot(90, dynamicLighting[i]); } var p = "[\[\"M\"," + dynamicLighting[0][0] + "," + dynamicLighting[0][1] + "]"; for(var i = 0; i < dynamicLighting.length; i++) { if(i != 0) { p += ",[\"L\"," + dynamicLighting[i][0] + "," + dynamicLighting[i][1] + "]"; } if(dynamicLighting[i][0] > h) h = dynamicLighting[i][0]; if(!l || dynamicLighting[i][0] < l) l = dynamicLighting[i][0]; if(dynamicLighting[i][1] > h2) h2 = dynamicLighting[i][1]; if(!l2 || dynamicLighting[i][1] < l2) l2 = dynamicLighting[i][1]; } p += "\]"; var w = h - l; var hi = h2 - l2; var t = l2 + (hi/2); var le = l + (w/2); createObj("path",{ layer: "walls", _path: p, width: w, height: hi, top: t, left: le, rotation: 0, stroke: "#00ff00", pageid: Campaign().get("playerpageid") });
Alex L. said:
Code for Creating individual lines + rotation. You will need to add offsets to the Top and left to position them correctly (this only works for a single tile).dynamicLighting = [ [315,595], [245,595], [245,245], [595,245], [595,595], [525,595] ]; function rot(angle, point) { var pointX = point[0], pointY = point[1], originX = 70*6, originY = 70*6; angle = angle * Math.PI / 180.0; return [ Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX, Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY ]; } //Put this somewhere, I use on ready. var h = 0; var l = false; var h2 = 0; var l2 = false; for(var i = 0; i < dynamicLighting.length; i++) { dynamicLighting[i] = rot(90, dynamicLighting[i]); } var p = "[\[\"M\"," + dynamicLighting[0][0] + "," + dynamicLighting[0][1] + "]"; for(var i = 0; i < dynamicLighting.length; i++) { if(i != 0) { p += ",[\"L\"," + dynamicLighting[i][0] + "," + dynamicLighting[i][1] + "]"; } if(dynamicLighting[i][0] > h) h = dynamicLighting[i][0]; if(!l || dynamicLighting[i][0] < l) l = dynamicLighting[i][0]; if(dynamicLighting[i][1] > h2) h2 = dynamicLighting[i][1]; if(!l2 || dynamicLighting[i][1] < l2) l2 = dynamicLighting[i][1]; } p += "\]"; var w = h - l; var hi = h2 - l2; var t = l2 + (hi/2); var le = l + (w/2); createObj("path",{ layer: "walls", _path: p, width: w, height: hi, top: t, left: le, rotation: 0, stroke: "#00ff00", pageid: Campaign().get("playerpageid") });
Jarrod . said:
Just curious.. Are the random tiles to fill the center all defaulted as the normal orientation, or do they have a randomized rotation?
var geomorphicTilesInformation = [ ......
{tileName:"Geo_Type_A_0025", edge: false, corner: true, entrance: false, type: "d", rotation: 180, rarity: 100, blocked: false}, {tileName: "Geo_Type_A_0026", edge: true, corner: false, entrance: false, type: "d", rotation: 270, rarity: 100, blocked: false},
.....
Stephen S. said:
Alex L. said:
Code for Creating individual lines + rotation. You will need to add offsets to the Top and left to position them correctly (this only works for a single tile).
This is perfect.... and what is needed.
As you said... need the offset and the offset as it is rotated.
var dynamicLighting = [ [[315,595],[245,595],[245,245],[595,245],[595,595],[525,595]], [[315,0],[315,35],[525,35],[525,0]], [[840,105],[805,105],[805,35],[735,35],[735,0]], [[0,105],[35,105],[35,35],[105,35],[105,0]], [[0,315],[35,315],[35,525],[0,525]], [[840,315],[805,315],[805,525],[840,525]], [[0,735],[35,735],[35,805],[105,805],[105,840]], [[840,735],[805,735],[805,805],[735,805],[735,840]], [[315,840],[315,805],[525,805],[525,840]] ]; function rot(angle, point) { var pointX = point[0], pointY = point[1], originX = 70*6, originY = 70*6; // total tile size is 12^2 squares = (12^2)*70 pixels, origin is the point that we rotate around. angle = angle * Math.PI / 180.0; return [ Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX, Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY ]; } function createPath(inputPath, angle, Xoffset, Yoffset) { var PathArray = []; // use a god dam copy you n00b :P if(!angle) angle = 0; if(!Xoffset) Xoffset = 0; if(!Yoffset) Yoffset = 0; //use these to work our how big the path is. var maxX = 0; var minX = false; var maxY = 0; var minY = false; //find the min and max X and Y. for(var i = 0; i < inputPath.length; i++) { if(inputPath[i][0] > maxX) maxX = inputPath[i][0]; if(minX === false || Number(inputPath[i][0]) < Number(minX)) minX = inputPath[i][0]; if(inputPath[i][1] > maxY) maxY = inputPath[i][1]; if(minY === false || inputPath[i][1] < minY) minY = inputPath[i][1]; PathArray.push([inputPath[i][0], inputPath[i][1]]); } //work out the size and position the object within the 12^2 area. var objectWidth = maxX - minX; var objectHeight = maxY - minY; var objectTop = minY + (objectHeight/2); var objectLeft = minX + (objectWidth/2); //Rotate the cords in the array and fix array to remove positioning. for(var i = 0; i < PathArray.length; i++) { PathArray[i][0] = PathArray[i][0] - objectLeft + (objectWidth/2); PathArray[i][1] = PathArray[i][1] - objectTop + (objectHeight/2); PathArray[i] = rot(angle, PathArray[i]); } //Convert the array to a string. var pathString = ""; for(var i = 0; i < PathArray.length; i++) { if(i != 0) { pathString += ",[\"L\"," + PathArray[i][0] + "," + PathArray[i][1] + "]"; } else { pathString = "[\[\"M\"," + PathArray[i][0] + "," + PathArray[i][1] + "]"; } } pathString += "\]"; objectTop = objectTop + Yoffset; //offset should be the relative position from the top left in multiples of 840. objectLeft = objectLeft + Xoffset; createObj("path",{ layer: "walls", _path: pathString, width: objectWidth, height: objectHeight, top: objectTop, left: objectLeft, rotation: 0, stroke: "#00ff00", pageid: Campaign().get("playerpageid") }); //You may need to change the page id. } on("ready", function() { //Create a tile at 0,0 with no rotation. for(var i = 0; i < dynamicLighting.length; i++) { createPath(dynamicLighting[i]); } //create the same tile at 0,1 with 90 rotation. for(var i = 0; i < dynamicLighting.length; i++) { createPath(dynamicLighting[i], 90, 1*840, 0); } });
Jarrod . said:
@stephen-
thanks for that explanation. That makes a lot of sense. :)
@alex-
you and Stephen are a power team! I can't wait to see what kind of stuff you two are going to come up with next!
setPaths = function() {
readMap();
log(pathArray);
};
....{"left":420,"top":420,"rotation":180,"path":"[[840,735],[805,735],[805,805],[735,805],[735,840]]"},
{"left":420,"top":420,"rotation":180,"path":"[[0,105],[35,105],[35,35],[105,35],[105,0]]"},
{"left":420,"top":420,"rotation":180,"path":"[[0,315],[35,315],[35,385],[385,385],[385,35],[315,35],[315,0]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[840,735],[805,735],[805,805],[735,805],[735,840]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[315,840],[315,805],[385,805],[385,315]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[0,735],[35,735],[35,805],[105,805],[105,840]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[0,525],[35,525],[35,315]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[0,105],[35,105],[35,35],[105,35],[105,0]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[0,315],[35,315],[385,315],[385,35],[315,35],[315,0]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[805,420],[400,805]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[315,0],[315,35],[525,35],[525,0]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[840,105],[805,105],[805,35],[735,35],[735,0]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[0,105],[35,105],[35,35],[105,35],[105,0]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[0,315],[35,315],[35,525],[0,525]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[840,315],[805,315],[805,525],[840,525]]"}....
Stephen S. said:
Jarrod . said:
@stephen-
thanks for that explanation. That makes a lot of sense. :)
@alex-
you and Stephen are a power team! I can't wait to see what kind of stuff you two are going to come up with next!:P Alex is saving me from my reach exceeding my grasp!
Updated the script so the paths are their own object...
Will work Alex's stuff into the !light action which goes to this function:setPaths = function() {
readMap();
log(pathArray);
};
created pathArray for each random map now looks like this for a small random map... (in part, not posting the entire array)....{"left":420,"top":420,"rotation":180,"path":"[[840,735],[805,735],[805,805],[735,805],[735,840]]"},
{"left":420,"top":420,"rotation":180,"path":"[[0,105],[35,105],[35,35],[105,35],[105,0]]"},
{"left":420,"top":420,"rotation":180,"path":"[[0,315],[35,315],[35,385],[385,385],[385,35],[315,35],[315,0]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[840,735],[805,735],[805,805],[735,805],[735,840]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[315,840],[315,805],[385,805],[385,315]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[0,735],[35,735],[35,805],[105,805],[105,840]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[0,525],[35,525],[35,315]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[0,105],[35,105],[35,35],[105,35],[105,0]]"},
{"left":420,"top":1260,"rotation":180,"path":"[[0,315],[35,315],[385,315],[385,35],[315,35],[315,0]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[805,420],[400,805]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[315,0],[315,35],[525,35],[525,0]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[840,105],[805,105],[805,35],[735,35],[735,0]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[0,105],[35,105],[35,35],[105,35],[105,0]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[0,315],[35,315],[35,525],[0,525]]"},
{"left":420,"top":2100,"rotation":-90,"path":"[[840,315],[805,315],[805,525],[840,525]]"}....
Stephen S. said:
Here is the current code... I will delete this later so its only at the top:
Getting an error: Error: Firebase.set failed: First argument contains NaN in property 'width'
Alex L. said:
Stephen S. said:
Here is the current code... I will delete this later so its only at the top:
Getting an error: Error: Firebase.set failed: First argument contains NaN in property 'width'
Your paths shouldnt be strings this:
{tileName: "Geo_Type_A_0001", path:"[[0,105],[105,105],[105,0]]]"},
should be:
{tileName: "Geo_Type_A_0001", path:[[0,105],[105,105],[105,0]]]},
Stephen S. said:
Fixed the string issue a few posts up......ALEX!!!!!!!
You got me SOOOO CLOSE!
420px to the right and 420px down....
PLEASE PLEASE where do I fix it!!!!!!!!!!!!!!!!
_.each(pathArray, function(pathArrayEach) { var givenPath = pathArrayEach.path; var givenAngle = pathArrayEach.rotation; var givenX = pathArrayEach.left - 420; var givenY = pathArrayEach.top - 420; /* ------------------- createPath function was most helpfully provided by Alex L. https://app.roll20.net/users/71687/alex-l ------------------- */ createPath(givenPath, givenAngle, givenX, givenY); });
function createPath(inputPath, angle, Xoffset, Yoffset) { var PathArray = []; // use a god dam copy you n00b :P if(!angle) angle = 0; if(!Xoffset) Xoffset = 0; if(!Yoffset) Yoffset = 0; //use these to work our how big the path is. var maxX = 0; var minX = false; var maxY = 0; var minY = false; //find the min and max X and Y. Rotate the cords in the array. for(var i = 0; i < inputPath.length; i++) { PathArray.push([inputPath[i][0], inputPath[i][1]]); PathArray[i] = rot(angle, PathArray[i]); if(PathArray[i][0] > maxX) maxX = PathArray[i][0]; if(minX === false || Number(PathArray[i][0]) < Number(minX)) minX = PathArray[i][0]; if(PathArray[i][1] > maxY) maxY = PathArray[i][1]; if(minY === false || PathArray[i][1] < minY) minY = PathArray[i][1]; } //work out the size and position the object within the 12^2 area. var objectWidth = maxX - minX; var objectHeight = maxY - minY; var objectTop = minY + (objectHeight/2); var objectLeft = minX + (objectWidth/2); //fix array to remove positioning. for(var i = 0; i < PathArray.length; i++) { PathArray[i][0] = PathArray[i][0] - objectLeft + (objectWidth/2); PathArray[i][1] = PathArray[i][1] - objectTop + (objectHeight/2); } //Convert the array to a string. var pathString = ""; for(var i = 0; i < PathArray.length; i++) { if(i != 0) { pathString += ",[\"L\"," + PathArray[i][0] + "," + PathArray[i][1] + "]"; } else { pathString = "[\[\"M\"," + PathArray[i][0] + "," + PathArray[i][1] + "]"; } } pathString += "\]"; objectTop = objectTop + Yoffset; //offset should be the relative position from the top left in multiples of 840. objectLeft = objectLeft + Xoffset; createObj("path",{ layer: "walls", _path: pathString, width: objectWidth, height: objectHeight, top: objectTop, left: objectLeft, rotation: 0, stroke: "#00ff00", pageid: Campaign().get("playerpageid") }); //You may need to change the page id. }
Geo_Type_A_0031 and Geo_Type_A_0032 are used to "fill in" the offset area.
"Blocked" value turns off tiles that should not be randomly placed.
var geomorphicTilesInformation = [ {tileName: "Geo_Type_A_0031", edge: false, corner: false, entrance: false, type: "d", rotation: 0, rarity: 100, blocked: true }, {tileName: "Geo_Type_A_0032", edge: false, corner: false, entrance: false, type: "d", rotation: 0, rarity: 100, blocked: true },