Skip to content

Instantly share code, notes, and snippets.

@BaldarSilveraxe
Created October 3, 2014 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BaldarSilveraxe/746534f5d906f2dc8377 to your computer and use it in GitHub Desktop.
Save BaldarSilveraxe/746534f5d906f2dc8377 to your computer and use it in GitHub Desktop.
Roll20 API
on("ready", function() {
on("chat:message", function (msg) {
if (msg.type != "api") return;
msg.who = msg.who.replace(" (GM)", "");
msg.content = msg.content.replace("(GM) ", "");
var command = msg.content.split(" ", 1);
if(command == "!createMap") {createMap();};
});
});
var mapName = "DungeonDepth";
var DungeonDepthMapId = "Unknown";
var DungeonDepthTableId = "Unknown";
var isError = false;
var errorType = "None";
var tileMissing = true;
var DungeonDepthMapWidth;
var DungeonDepthMapHeight;
var DungeonDepthMapArray = new Array;
var emptySpotFound = false;
var pathToTake = [];
//Holder can be removed later
var DungeonDepthArray = [
{tileName: "Start", type: "Start"},
{tileName: "End", type: "End"},
{tileName: "Hall", type: "Hall"},
{tileName: "Corner", type: "Corner"},
{tileName: "Room", type: "Room"},
{tileName: "Quarter", type: "Quarter"},
{tileName: "Holder", type: "Holder"},
];
createMap = function() {
var DungeonDepthMapArray = new Array;
var pathToTake = new Array;
setupCheck();
if(isError == true){sendChat("API", errorType); isError = false; return;};
buildMapArray();
placeStartEnd();
if(isError == true){sendChat("API", errorType); isError = false; return;};
criticalPath();
swapPathTiles();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Need to add critical path doors here
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fillInMap();
buildMapBaseLayer();
//Used as an aid for code building
logMap();
sendChat("AP", "Let's make map");
};
/**
* @desc Performs basic setup check and finds set needed variables
* var DungeonDepthMapId (Object ID)
* var DungeonDepthMapWidth (Object Property)
* var DungeonDepthMapHeight (Object Property)
* var DungeonDepthTableId (Object ID)
* var DungeonDepthTiles (Objects)
* var isError
* var errorType
*/
setupCheck = function() {
var DungeonDepthPages = findObjs({ name: mapName, _type: "page"});
if(DungeonDepthPages.length == 0){isError = true; errorType = mapName + " map is missing."; return;};
if(DungeonDepthPages.length > 1){isError = true; errorType = "More than one " + mapName + " map."; return;};
DungeonDepthMapId = DungeonDepthPages[0].get("_id");
var DungeonDepthMapGraphics = findObjs({_pageid: DungeonDepthMapId, _type: "graphic"});
if(DungeonDepthMapGraphics.length != 0){isError = true; errorType = mapName + " has images on it."; return;};
var DungeonDepthMapGraphics = findObjs({_pageid: DungeonDepthMapId, _type: "path"});
if(DungeonDepthMapGraphics.length != 0){isError = true; errorType = mapName + " has paths on it."; return;};
DungeonDepthMapWidth = DungeonDepthPages[0].get("width");
DungeonDepthMapHeight = DungeonDepthPages[0].get("height");
if(DungeonDepthMapWidth % 14 !== 0){isError = true; errorType = "Map width must be divisible by 14."; return;};
if(DungeonDepthMapHeight % 14 !== 0){isError = true; errorType = "Map height must be divisible by 14."; return;};
if(DungeonDepthMapWidth < 42 || DungeonDepthMapHeight < 42){isError = true; errorType = "Map height must be 42 or larger."; return;};
var DungeonDepthTable = findObjs({ name: mapName, _type: "rollabletable"});
if(DungeonDepthTable.length == 0){isError = true; errorType = mapName + " table is missing."; return;};
DungeonDepthTableId = DungeonDepthTable[0].get("_id");
var DungeonDepthTiles = findObjs({ _rollabletableid: DungeonDepthTableId, _type: "tableitem"});
_.each(DungeonDepthArray, function(tileArray) {
tileMissing = false;
_.each(DungeonDepthTiles, function(tileTable) {
if(tileTable.get("name") == tileArray.tileName){tileMissing = true;};
});
if(tileMissing == false){isError = true; errorType = tileArray.tileName + " is missing from the table (might have extra space.)"; return;};
});
};
/**
* @desc Creates an array to be used to hold all tile information
* var DungeonDepthMapArray[i][j] (where i is based on map height and j is based on map width)
* -name, url, x, y, spin (rotation), flip v, flip H, and walls represented by 1 and 0
* -starting at the upper left of the tile wrap around.
* -0|1
* -1|1
* Would be an "L" shaped tile ("0111")
* Walls = "9999" has not been set to any tile.
*/
buildMapArray = function() {
for (i = 1; i < Math.floor((DungeonDepthMapHeight/14) + 1); i++) {
DungeonDepthMapArray[i] = new Array(Math.floor(DungeonDepthMapWidth/14))
for (j = 1; j < Math.floor((DungeonDepthMapWidth/14) + 1); j++) {
DungeonDepthMapArray[i][j] = {};
DungeonDepthMapArray[i][j] = {
name: "none",
tileURL: "",
xValue: Math.floor(((j - 1) * 980) + 490),
yValue: Math.floor(((i - 1) * 980) + 490),
spin: 0,
flipv: false,
fliph: false,
walls: "9999",
};
};
};
};
/**
* @desc Tries to add start and end locations.
* Attempts to ensure the distance between them is greater than 1/2 of the maps longest side.
*/
placeStartEnd = function() {
emptySpotFound = false;
var tries = Math.floor((DungeonDepthMapWidth/14)) * Math.floor((DungeonDepthMapHeight/14))
var dungeonX = Math.floor((DungeonDepthMapWidth/14));
var dungeonY = Math.floor((DungeonDepthMapHeight/14));
if(dungeonX >= dungeonY){
var dungeonSize = Math.floor(dungeonX * .5);
}else{
var dungeonSize = Math.floor(dungeonY * .5);
};
for (i = 1; i < tries + 1; i++) {
findEmptySpot("Start",0,false,false,"1111");
if(emptySpotFound == false){isError = true; errorType = "No open spot found! (Can you believe it?)"; return;};
findEmptySpot("End",0,false,false,"1111");
if(emptySpotFound == false){isError = true; errorType = "No open spot found! (Can you believe it?)"; return;};
for (i = 1; i < Math.floor(DungeonDepthMapHeight/14) + 1; i++) {
for (j = 1; j < Math.floor(DungeonDepthMapWidth/14) + 1; j++) {
if(DungeonDepthMapArray[i][j].name == "Start"){
var startXis = j
var startYis = i
};
if(DungeonDepthMapArray[i][j].name == "End"){
var endXis = j
var endYis = i
};
};
};
Xs = Math.abs(startXis - endXis) * Math.abs(startXis - endXis)
Ys = Math.abs(startYis - endYis) * Math.abs(startYis - endYis)
dungeonDistance = Math.sqrt(Xs + Ys);
if(dungeonSize < dungeonDistance){
return;
};
DungeonDepthMapArray = new Array;
buildMapArray();
};
};
/**
* @desc Tries to find a spot for start and end.
*/
findEmptySpot = function(givenName, givenSpin, givenFlipV, givenFlipH, givenWalls) {
emptySpotFound = false;
var tries = Math.floor((DungeonDepthMapWidth/14)) * Math.floor((DungeonDepthMapHeight/14))
for (i = 1; i < tries + 1; i++) {
var tryX = Math.floor(Math.random() * DungeonDepthMapWidth/14) + 1
var tryY = Math.floor(Math.random() * DungeonDepthMapHeight/14) + 1
if(DungeonDepthMapArray[tryY][tryX].name == "none"){
DungeonDepthMapArray[tryY][tryX].name = givenName;
DungeonDepthMapArray[tryY][tryX].tileURL = findObjs({ _rollabletableid: DungeonDepthTableId, _type: "tableitem", name: givenName})[0].get("avatar").replace("med.jpg?","thumb.jpg?");
DungeonDepthMapArray[tryY][tryX].spin = givenSpin;
DungeonDepthMapArray[tryY][tryX].flipv = givenFlipV;
DungeonDepthMapArray[tryY][tryX].fliph = givenFlipH;
DungeonDepthMapArray[tryY][tryX].walls = givenWalls
emptySpotFound = true;
return;
};
};
};
/**
* @desc Find the path between start and end and populates pathToTake = [];
*/
criticalPath = function() {
pathToTake = [];
for (i = 1; i < Math.floor(DungeonDepthMapHeight/14) + 1; i++) {
for (j = 1; j < Math.floor(DungeonDepthMapWidth/14) + 1; j++) {
if(DungeonDepthMapArray[i][j].name == "Start"){
var startRoomData = {
name: DungeonDepthMapArray[i][j].name,
xGrid: j,
yGrid: i,
tileURL: DungeonDepthMapArray[i][j].tileURL,
xValue: DungeonDepthMapArray[i][j].xValue,
yValue: DungeonDepthMapArray[i][j].yValue,
spin: DungeonDepthMapArray[i][j].spin,
flipv: DungeonDepthMapArray[i][j].flipv,
fliph: DungeonDepthMapArray[i][j].fliph,
walls: DungeonDepthMapArray[i][j].walls
};
};
if(DungeonDepthMapArray[i][j].name == "End"){
var endRoomData = {
name: DungeonDepthMapArray[i][j].name,
xGrid: j,
yGrid: i,
tileURL: DungeonDepthMapArray[i][j].tileURL,
xValue: DungeonDepthMapArray[i][j].xValue,
yValue: DungeonDepthMapArray[i][j].yValue,
spin: DungeonDepthMapArray[i][j].spin,
flipv: DungeonDepthMapArray[i][j].flipv,
fliph: DungeonDepthMapArray[i][j].fliph,
walls: DungeonDepthMapArray[i][j].walls
};
};
};
};
var xCurrent = startRoomData.xGrid;
var yCurrent = startRoomData.yGrid;
var xWasAt = startRoomData.xGrid;
var yWasAt = startRoomData.yGrid;
xDelta = startRoomData.xGrid - endRoomData.xGrid;
yDelta = startRoomData.yGrid - endRoomData.yGrid;
var xChanged;
while ((xCurrent != endRoomData.xGrid) || (yCurrent != endRoomData.yGrid)) {
xChanged = false;
if (xCurrent != endRoomData.xGrid) {
if (xCurrent > endRoomData.xGrid) {
xCurrent--;
}else{
xCurrent++;
};
xChanged = true;
};
if (yCurrent != endRoomData.yGrid && xChanged == false) {
if (yCurrent > endRoomData.yGrid) {
yCurrent--;
}else{
yCurrent++;
};
};
if((xCurrent != endRoomData.xGrid) || (yCurrent != endRoomData.yGrid)) {
placePathTile(xCurrent,yCurrent,xWasAt,yWasAt)
xWasAt = xCurrent;
yWasAt = yCurrent;
};
};
if(endRoomData.xGrid < xWasAt){stepDirection = "Left";};
if(endRoomData.xGrid > xWasAt){stepDirection = "Right";};
if(endRoomData.yGrid < yWasAt){stepDirection = "Up";};
if(endRoomData.yGrid > yWasAt){stepDirection = "Down";};
pathToTake.push({direction: stepDirection, xPath: endRoomData.xGrid, yPath: endRoomData.yGrid})
};
/**
* @desc Places placeholder tiles on the crtical path
* These are never seen but useful for testing the code (construction or editting.)
*/
placePathTile = function(xCurrent,yCurrent,xWasAt,yWasAt) {
DungeonDepthMapArray[yCurrent][xCurrent].name = "Holder";
DungeonDepthMapArray[yCurrent][xCurrent].tileURL = findObjs({ _rollabletableid: DungeonDepthTableId, _type: "tableitem", name: "Holder"})[0].get("avatar").replace("med.jpg?","thumb.jpg?");
DungeonDepthMapArray[yCurrent][xCurrent].spin = 0;
var stepDirection;
if(xCurrent < xWasAt){stepDirection = "Left";};
if(xCurrent > xWasAt){stepDirection = "Right";};
if(yCurrent < yWasAt){stepDirection = "Up";};
if(yCurrent > yWasAt){stepDirection = "Down";};
pathToTake.push({direction: stepDirection, xPath: xCurrent, yPath: yCurrent})
};
swapPathTiles = function() {
var LastWalls = "1111";
var sideWalls = "0000";
var lastSideWalls = "0000";
for (var i = 0; i < pathToTake.length - 1; i++) {
sideWalls = "0000"
var moveType = pathToTake[i].direction + "|" + pathToTake[i + 1].direction;
var stepX = pathToTake[i].xPath
var stepY = pathToTake[i].yPath
if(i != 0){
if(pathToTake[i].direction == "Right"){
LastWalls = DungeonDepthMapArray[stepY][stepX - 1].walls
};
if(pathToTake[i].direction == "Left"){
LastWalls = DungeonDepthMapArray[stepY][stepX + 1].walls
};
if(pathToTake[i].direction == "Up"){
LastWalls = DungeonDepthMapArray[stepY + 1][stepX].walls
};
if(pathToTake[i].direction == "Down"){
LastWalls = DungeonDepthMapArray[stepY - 1][stepX].walls
};
}
switch (moveType) {
case "Left|Left":
case "Right|Right":
case "Up|Up":
case "Down|Down":
DungeonDepthMapArray[stepY][stepX].name = "Room";
DungeonDepthMapArray[stepY][stepX].tileURL = findObjs({ _rollabletableid: DungeonDepthTableId, _type: "tableitem", name: "Room"})[0].get("avatar").replace("med.jpg?","thumb.jpg?")
DungeonDepthMapArray[stepY][stepX].walls = "1111";
var rndTile = Math.random()
if (rndTile < .7){
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].name = "Hall";
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].tileURL = findObjs({ _rollabletableid: DungeonDepthTableId, _type: "tableitem", name: "Hall"})[0].get("avatar").replace("med.jpg?","thumb.jpg?");
DungeonDepthMapArray[stepY][stepX].walls = "1001";
if(moveType == "Right|Right" || moveType == "Left|Left"){
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].spin = 90
DungeonDepthMapArray[stepY][stepX].walls = "1100";
};
if(Math.random() < .5 ){
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].fliph = true;
var tempWalls1 = DungeonDepthMapArray[stepY][stepX].walls.substring(2,4);
var tempWalls2 = DungeonDepthMapArray[stepY][stepX].walls.substring(0,2);
DungeonDepthMapArray[stepY][stepX].walls = tempWalls1 + tempWalls2
};
if(pathToTake[i].direction == "Right" || pathToTake[i].direction == "Left"){
sideWalls = DungeonDepthMapArray[stepY][stepX].walls.substring(1,3);
if(pathToTake[i].direction == "Right"){
lastSideWalls = LastWalls.charAt(1) + LastWalls.charAt(2)
}else{
lastSideWalls = LastWalls.charAt(0) + LastWalls.charAt(LastWalls.length-1)
};
}else{
sideWalls = DungeonDepthMapArray[stepY][stepX].walls.substring(0,2);
if(pathToTake[i].direction == "Up"){
lastSideWalls = LastWalls.charAt(0) + LastWalls.charAt(1)
}else{
lastSideWalls = LastWalls.charAt(LastWalls.length-1) + LastWalls.charAt(LastWalls.length-2)
};
};
var compareWalls1 = parseInt(sideWalls.charAt(0)) * parseInt(lastSideWalls.charAt(0));
var compareWalls2 = parseInt(sideWalls.charAt(1)) * parseInt(lastSideWalls.charAt(1));
var compareWalls = Math.floor(compareWalls1 + compareWalls2)
if(parseInt(compareWalls) == 0){
if(DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].fliph == true){
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].fliph = false;
}else{
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].fliph = true;
};
var tempWalls1 = DungeonDepthMapArray[stepY][stepX].walls.substring(2,4);
var tempWalls2 = DungeonDepthMapArray[stepY][stepX].walls.substring(0,2);
DungeonDepthMapArray[stepY][stepX].walls = tempWalls1 + tempWalls2
};
};
if (rndTile > .8){
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].name = "Corner";
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].tileURL = findObjs({ _rollabletableid: DungeonDepthTableId, _type: "tableitem", name: "Corner"})[0].get("avatar").replace("med.jpg?","thumb.jpg?");
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].fliph = true;
DungeonDepthMapArray[stepY][stepX].walls = "1011";
if(moveType == "Right|Right" || moveType == "Left|Left"){
DungeonDepthMapArray[pathToTake[i].yPath][pathToTake[i].xPath].flipv = true;
DungeonDepthMapArray[stepY][stepX].walls = "1101";
};
};
break;
default:
DungeonDepthMapArray[stepY][stepX].name = "Room";
DungeonDepthMapArray[stepY][stepX].tileURL = findObjs({ _rollabletableid: DungeonDepthTableId, _type: "tableitem", name: "Room"})[0].get("avatar").replace("med.jpg?","thumb.jpg?")
DungeonDepthMapArray[stepY][stepX].walls = "1111";
break;
};
};
};
fillInMap = function() {
//log(DungeonDepthMapArray.length)
//log(DungeonDepthMapArray[0].length)
for (i = 1; i < Math.floor(DungeonDepthMapHeight/14) + 1; i++) {
for (j = 1; j < Math.floor(DungeonDepthMapWidth/14) + 1; j++) {
if(DungeonDepthMapArray[i][j].name == "none"){
DungeonDepthMapArray[i][j].name = "Question";
DungeonDepthMapArray[i][j].tileURL = findObjs({ _rollabletableid: DungeonDepthTableId, _type: "tableitem", name: "Question"})[0].get("avatar").replace("med.jpg?","thumb.jpg?")
DungeonDepthMapArray[i][j].walls = "9999";
};
};
};
};
buildMapBaseLayer = function() {
for (i = 1; i < Math.floor(DungeonDepthMapHeight/14) + 1; i++) {
for (j = 1; j < Math.floor(DungeonDepthMapWidth/14) + 1; j++) {
if(DungeonDepthMapArray[i][j].name != "none"){
createObj("graphic", {_type: "graphic", _subtype: "token", _pageid: DungeonDepthMapId,
imgsrc: DungeonDepthMapArray[i][j].tileURL,
left: DungeonDepthMapArray[i][j].xValue + 0,
top: DungeonDepthMapArray[i][j].yValue + 0,
rotation: DungeonDepthMapArray[i][j].spin,
flipv: DungeonDepthMapArray[i][j].flipv,
fliph: DungeonDepthMapArray[i][j].fliph,
layer: "map", width: 980, height: 980,
});
};
};
};
};
//CAN DELETE
logMap = function(givenName) {
for (i = 1; i < Math.floor(DungeonDepthMapHeight/14) + 1; i++) {
var logText = "";
for (j = 1; j < Math.floor(DungeonDepthMapWidth/14) + 1; j++) {
logText += DungeonDepthMapArray[i][j].walls
};
//log(logText)
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment