Last active
January 26, 2017 21:30
-
-
Save BaldarSilveraxe/8e987828e2969684c59d2c7337dfced1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var DungeonDraw = DungeonDraw || (function(){ | |
'use strict'; | |
//settings | |
var defaultTexture = 'Old School|#18769c', | |
cssButtonAnchor = ' style="border: 1px solid AliceBlue; background-color: SteelBlue; color: white;" ', | |
cssButtonSpan = ' style="color: white; font-weight: normal; display: block; width: 150px;" ', | |
cssButtonAnchorImg = ' style="border: 1px solid Black; background-color: White; color: white;" ', | |
cssButtonImg = ' style="padding: 0px 0px 0px 0px; outline: none; border: none;" ', | |
deferred={ | |
batchSize: 30, | |
initialDefer: 10, | |
batchDefer: 10 | |
}, | |
//version | |
version = 3.1, | |
lastUpdate = 1430236079, //Unix timestamp | |
schemaVersion = 3.1, | |
//system | |
currentTextureName, | |
currentPageId, | |
installedTextures = [], | |
currentTiles = [], | |
allTexturesTiles = [], | |
bitTiles = [], | |
pathUndo = [], | |
placementTiles = [], | |
placeSeek = [], | |
featurePathArray = [], | |
objExtractKeys = ['id','pageid','stroke','rotation','layer','width','height','top','left','controlledby'], | |
seq = (function(seed) { | |
var count = seed; | |
return function(){ | |
return ++seed; | |
}; | |
}(0)), | |
createLoadedMap = function(message) { | |
var args = message.replace('!DungeonDrawCreateLoadedMap ', '').split('^|'), | |
mapName = args[0], confirmed = args[1].toLowerCase(), | |
data = DungeonDrawShared[mapName].split(']'), | |
mapTags = data[0] + ']', | |
mapStringy = Base64.decode(data[1]), | |
mapData = JSON.parse(mapStringy), | |
playerPages = Campaign().get('playerspecificpages'), | |
ownerPage = playerPages[state.DungeonDraw.owner], | |
loadPageId, loadPage, | |
mapArray1, mapArray2, | |
installedTexturesObject = [], | |
textureToUse = defaultTexture, | |
tempTexture, tileNumber; | |
if( 'y' !== confirmed ){return; } | |
if( undefined === ownerPage ){ | |
loadPageId = Campaign().get('playerpageid'); | |
}else{ | |
loadPageId = ownerPage; | |
} | |
loadPage = getObj('page', loadPageId); | |
switch(mapData.schemaVersion){ | |
case 1: | |
loadPage.set('width', mapData.width); | |
loadPage.set('height', mapData.height); | |
loadPage.set('background_color', mapData.background_color); | |
loadPage.set('gridcolor', mapData.gridcolor); | |
mapArray1 = _.map(mapData.standardTiles.match(/\d+[A-Z]\d[A-Z]{1,3}\d+/g),function(m){ | |
return _.object(['row','tile','set','rotation','hflip','vflip','column'], | |
_.rest(m.match(/^(\d+)([A-Z])(\d)([A-Z])([A-Z]?)([A-Z]?)(\d+)$/))); | |
}); | |
mapArray2 = _.map(mapData.specialTiles.match(/\d+[A-Z]\d[A-Z]{1,3}\d+/g),function(m){ | |
return _.object(['row','tile','set','rotation','hflip','vflip','column'], | |
_.rest(m.match(/^(\d+)([A-Z])(\d)([A-Z])([A-Z]?)([A-Z]?)(\d+)$/))); | |
}); | |
_.each(installedTextures, function(eachTexture) { | |
installedTexturesObject[eachTexture.split('|')[0]] = eachTexture; | |
}); | |
_.each(mapArray1, function(obj) { | |
if ( undefined === installedTexturesObject[mapData.standardPacks[obj.set]] ) { | |
textureToUse = defaultTexture; | |
}else{ | |
textureToUse = installedTexturesObject[mapData.standardPacks[obj.set]]; | |
} | |
tempTexture = _.clone(DungeonDrawTiles[textureToUse]); | |
tileNumber = obj.tile.charCodeAt(0) - 65; | |
if ( tileNumber >= 16 ){tileNumber = tileNumber + 2; } | |
deferredCreateObj('graphic', { | |
subtype: 'token', | |
pageid: loadPageId, | |
layer: 'map', | |
width: 70, | |
height: 70, | |
left: (parseInt(obj.column,10) * 70) + 35, | |
top: (parseInt(obj.row,10) * 70) + 35, | |
rotation: (obj.rotation.charCodeAt(0) - 65) * 90, | |
flipv: obj.vflip, | |
fliph: obj.hflip, | |
imgsrc: tempTexture[tileNumber].url, | |
name: tempTexture[tileNumber].key, | |
controlledby: 'DungeonDrawGraphic' | |
}); | |
}); | |
_.each(mapArray2, function(obj) { | |
if ( undefined === installedTexturesObject[mapData.specialPacks[obj.set]] ) { | |
textureToUse = defaultTexture; | |
}else{ | |
textureToUse = installedTexturesObject[mapData.specialPacks[obj.set]]; | |
} | |
tempTexture = _.clone(DungeonDrawTiles[textureToUse]); | |
tileNumber = obj.tile.charCodeAt(0) - 43; | |
deferredCreateObj('graphic', { | |
subtype: 'token', | |
pageid: loadPageId, | |
layer: 'map', | |
width: 70, | |
height: 70, | |
left: (parseInt(obj.column,10) * 35), | |
top: (parseInt(obj.row,10) * 35), | |
rotation: (obj.rotation.charCodeAt(0) - 65) * 90, | |
imgsrc: tempTexture[tileNumber].url, | |
name: tempTexture[tileNumber].key, | |
controlledby: 'DungeonDrawGraphic' | |
}); | |
}); | |
break; | |
} | |
sendChat('Main Menu', '/w ' + state.DungeonDraw.who + ' <a href="!DungeonDrawMenu"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>Dungeon Draw Menu</span></a>'); | |
}, | |
setMap = function(message) { | |
var playerPages = Campaign().get('playerspecificpages'), | |
ownerPage = playerPages[state.DungeonDraw.owner], | |
savePageId, savePage, | |
mapName = message.replace('!DungeonDrawSetMap ', '');; | |
if( undefined === ownerPage ){ | |
savePageId = Campaign().get('playerpageid'); | |
}else{ | |
savePageId = ownerPage; | |
} | |
savePage = getObj('page', savePageId); | |
if( (undefined === savePage.get('name')) || ('' === savePage.get('name')) || ('Untitled' === savePage.get('name')) ){ | |
sendChat('Dungeon Draw', '/w ' + state.DungeonDraw.who + ' ' | |
+'<div style="padding:1px 3px;border: 1px solid #9F6000; background: #FEEFB3; color: #9F6000; font-size: 80%;">' | |
+'<img src="https://s3.amazonaws.com/files.d20.io/images/6422879/M-oWEvMt1bhC2M-bdi28tA/thumb.png?1416499678" style="vertical-align: text-bottom; width:20px; height:20px; padding: 0px 5px;" />' | |
+'<b>Target map</b> must have a <b>Name</b> (and/or cannot be named "Untitled).' | |
); | |
return; | |
} | |
sendChat('Share', '/w ' + state.DungeonDraw.who + ' ' | |
+ '<a href="!DungeonDrawCreateLoadedMap ' + mapName + '^|?{Are You Sure|N}" >' | |
+ 'Create map on page: ' + savePage.get('name') + '</a>'); | |
}, | |
getMapData = function(id) { | |
var savePage = getObj("page", id), images = findObjs({pageid: id, type: "graphic"}), | |
mapData, foundTile, mapTiles = [], spcTiles =[], rot, otherTiles = [], | |
standardTiles = '', specialTiles = '', | |
codeString = "DungeonShare['" + savePage.get("name") + "'] = '[tag1,tag2,tagn]'", | |
mapValues = { | |
schemaVersion: 1.0, | |
width: savePage.get("width"), | |
height: savePage.get("height"), | |
background_color: savePage.get("background_color"), | |
gridcolor: savePage.get("gridcolor"), | |
standardPacks: 'none', | |
standardTiles: 'none', | |
specialPacks: 'none', | |
specialTiles: 'none' | |
}, | |
standardPacks, spcTilePacks, | |
mapStringy, | |
parts, | |
i; | |
_.each(images, function(obj) { | |
foundTile = _.where(allTexturesTiles, {url: obj.get('imgsrc')}); | |
if( 0 !== foundTile.length) { | |
rot = (Math.round(obj.get('rotation')/90)*90)%360 + (obj.get('rotation')<0 ? 360 : 0); | |
if( 21 > foundTile[0].key.split('_')[1] ) { | |
mapTiles.push({ | |
pack: foundTile[0].pack.split('|')[0], | |
top: (parseInt(obj.get('top'),10) - 35 ) / 70, | |
left: (parseInt(obj.get('left'),10) - 35 ) / 70, | |
tile: String.fromCharCode(parseInt(foundTile[0].key.split('_')[1],10) + 64), | |
rot: String.fromCharCode((rot/90) + 65) | |
}); | |
}else{ | |
spcTiles.push({ | |
pack: foundTile[0].pack.split('|')[0], | |
top: (parseInt(obj.get('top'),10) / 35 ), | |
left: (parseInt(obj.get('left'),10) / 35 ), | |
flip: (obj.get('flipv') === false ? 'F' : 'T') + (obj.get('fliph') === false ? 'F' : 'T'), | |
tile: String.fromCharCode(parseInt(foundTile[0].key.split('_')[1],10) + 44), | |
rot: String.fromCharCode((rot/90) + 65) | |
}); | |
} | |
} | |
}); | |
mapTiles = _.sortBy(mapTiles, 'pack'); | |
mapValues.standardPacks = _.chain(mapTiles).map(function(item) { return item.pack }).uniq().value(); | |
spcTiles = _.sortBy(spcTiles, 'pack'); | |
mapValues.specialPacks = _.chain(spcTiles).map(function(item) { return item.pack }).uniq().value(); | |
_.each(mapTiles, function(obj) { | |
i = mapValues.standardPacks.indexOf(obj.pack); | |
standardTiles += obj.top + obj.tile + i + obj.rot + obj.left + ' '; | |
}); | |
standardTiles = standardTiles.substring(0, standardTiles.length - 1); | |
mapValues.standardTiles = standardTiles; | |
_.each(spcTiles, function(obj) { | |
i = mapValues.specialPacks.indexOf(obj.pack); | |
specialTiles += obj.top + obj.tile + i + obj.rot + obj.flip + obj.left + ' '; | |
}); | |
specialTiles = specialTiles.substring(0, specialTiles.length - 1); | |
mapValues.specialTiles = specialTiles; | |
mapStringy = JSON.stringify(mapValues); | |
mapData = Base64.encode(mapStringy); | |
parts = mapData.match(/[\s\S]{1,70}/g) || []; | |
_.each(parts, function(obj) { | |
codeString = codeString + "<br> +'" + obj + "'" | |
}); | |
codeString = codeString.substring(0, codeString.length - 1) + "';"; | |
sendChat("Copy/Paste", "/direct <pre>" + codeString + "</pre>"); | |
sendChat('Main Menu', '/w ' + state.DungeonDraw.who + ' <a href="!DungeonDrawMenu"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>Dungeon Draw Menu</span></a>'); | |
}, | |
help = function(href,aStyle,url,imgStyle) { | |
sendChat('Help', '/w ' + state.DungeonDraw.who + ' ' | |
+'<div style="border: 1px solid black; background-color: white; padding: 3px 3px;">' | |
+'<div style="font-weight: bold; border-bottom: 1px solid black; font-size: 100%;">' | |
+'Dungeon Draw v'+version | |
+'</div>' | |
+'<b style="font-size: 90%;">Overview</b>' | |
+'<div style="padding-left:10px;margin:3px; font-size: 90%;">' | |
+'<p>This script leverages the Rectangle and Polygon/Line Tools to create dungeon maps based on a selected set of tiles in the API.</p>' | |
+'<p>Complete help information can be found here:<ul><li><a href="https://wiki.roll20.net/Dungeon_Draw_API"><span style="color: blue;" ><u>Wiki Dungeon Draw</u></span></a>.</li></ul>' | |
+'</div>' | |
+'<b style="font-size: 90%;">Commands</b>' | |
+'<div style="padding-left:10px;margin:3px; font-size: 90%;">' | |
+'<p>This script uses whisper chat pane commands with the exception of:</p>' | |
+'<hr><p>Call menu to chat pane.</p>' | |
+'<pre style="white-space:normal;word-break:normal;word-wrap:normal;">' | |
+'!DungeonDrawMenu' | |
+'</pre>' | |
+'<hr><p>Take control of script.</p>' | |
+'<pre style="white-space:normal;word-break:normal;word-wrap:normal;">' | |
+'!DungeonDrawControl' | |
+'</pre>' | |
+'</div>' | |
+'</div>' | |
); | |
sendChat('Main Menu', '/w ' + state.DungeonDraw.who + ' <a href="!DungeonDrawMenu"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>Dungeon Draw Menu</span></a>'); | |
}, | |
cellhtml = function(href,aStyle,url,imgStyle) { | |
var html = '<div style="display: table-cell; border-collapse: collapse; padding-left: 0px; padding-right: 0px;" >' | |
+'<a href="' + href + '"' + aStyle + '>' | |
+'<img src="' + url + '" height="50" width="50" border="0"' + imgStyle + '>' | |
+'</a>' | |
+'</div>'; | |
return html; | |
}, | |
loadMap = function() { | |
var text = '/w ' + state.DungeonDraw.who + ' ', | |
sharedList = [], | |
args; | |
Object.keys(DungeonDrawShared).forEach(function(key) { | |
sharedList.push(key); | |
}); | |
if( 0 === sharedList.length) {return; } | |
_.each(sharedList, function(eachMap) { | |
text += '<br><a href="!DungeonDrawSetMap ' + eachMap + '"><span style="color: white; font-weight: normal; display: block; width: 150px;" >▹ ' + eachMap + '</span></a>'; | |
}); | |
sendChat('Share', text); | |
}, | |
saveMap = function() { | |
var playerPages = Campaign().get('playerspecificpages'), | |
ownerPage = playerPages[state.DungeonDraw.owner], | |
savePageId, savePage; | |
if( undefined === ownerPage ){ | |
savePageId = Campaign().get('playerpageid'); | |
}else{ | |
savePageId = ownerPage; | |
} | |
savePage = getObj('page', savePageId); | |
if( (undefined === savePage.get('name')) || ('' === savePage.get('name')) || ('Untitled' === savePage.get('name')) ){ | |
sendChat('Dungeon Draw', '/w ' + state.DungeonDraw.who + ' ' | |
+'<div style="padding:1px 3px;border: 1px solid #9F6000; background: #FEEFB3; color: #9F6000; font-size: 80%;">' | |
+'<img src="https://s3.amazonaws.com/files.d20.io/images/6422879/M-oWEvMt1bhC2M-bdi28tA/thumb.png?1416499678" style="vertical-align: text-bottom; width:20px; height:20px; padding: 0px 5px;" />' | |
+'<b>Target map</b> must have a <b>Name</b> (and/or cannot be named "Untitled).' | |
); | |
return; | |
} | |
sendChat('Share', '/w ' + state.DungeonDraw.who + ' ' | |
+'<a href="!DungeonDrawConfirm ' + savePageId + '"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>' | |
+'Save Map named "' + savePage.get('name') + '".</span></a>'); | |
}, | |
DungeonDrawMenu = function(menu) { | |
var tilesDataUniq, tableText, i = 0, menuText; | |
tilesDataUniq = _.chain(currentTiles) | |
.reduce(function(m,e){ | |
m[e.key+e.url.split(/\?/)[0]]={key: e.key, url: e.url}; | |
return m; | |
},{}) | |
.values() | |
.value(); | |
sendChat('Dungeon Draw Tools', '/w ' + state.DungeonDraw.who + ' '); | |
tableText = '/w ' + state.DungeonDraw.who + ' ' | |
+ '<div style="display: table;" >' | |
+ '<div style="display: table-row;" >' | |
+ cellhtml('!DungeonAddToolFlatten', cssButtonAnchorImg,'https://s3.amazonaws.com/files.d20.io/images/8907984/mi2Vl6tWu8JsGM0LpCmYNg/thumb.png?1429400030',cssButtonImg) | |
+ cellhtml('!DungeonAddToolRaise', cssButtonAnchorImg,'https://s3.amazonaws.com/files.d20.io/images/8908018/CX3Y6F5LJmI84N5dJP7CUg/thumb.png?1429400112',cssButtonImg) | |
+ cellhtml('!TAKENOACTION', cssButtonAnchorImg,'https://s3.amazonaws.com/files.d20.io/images/8838664/r-3M8jzLatXgeb88GnKy_g/thumb.jpg?1429048748',cssButtonImg) | |
+ cellhtml('!TAKENOACTION', cssButtonAnchorImg,'https://s3.amazonaws.com/files.d20.io/images/8838664/r-3M8jzLatXgeb88GnKy_g/thumb.jpg?1429048748',cssButtonImg) | |
+ '</div>'; | |
while (i < tilesDataUniq.length) { | |
tableText += '<div style="display: table-row;" >' | |
+ cellhtml('!DungeonDrawNumber ' + tilesDataUniq[i].key, cssButtonAnchorImg,tilesDataUniq[i].url,cssButtonImg) | |
+ cellhtml('!DungeonDrawNumber ' + tilesDataUniq[i + 1].key, cssButtonAnchorImg,tilesDataUniq[i + 1].url,cssButtonImg) | |
+ cellhtml('!DungeonDrawNumber ' + tilesDataUniq[i + 2].key, cssButtonAnchorImg,tilesDataUniq[i + 2].url,cssButtonImg) | |
+ cellhtml('!DungeonDrawNumber ' + tilesDataUniq[i + 3].key, cssButtonAnchorImg,tilesDataUniq[i + 3].url,cssButtonImg) | |
+ '</div>'; | |
i = i + 4; | |
} | |
sendChat('Current Tiles', tableText); | |
if( 'more' !== menu ) { | |
menuText = '/w ' + state.DungeonDraw.who + ' ' | |
+ '<br><a href="!DungeonDrawUndo"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>↻-Undo-Path</span></a>' | |
+ '<br><a href="!DungeonDrawClear ?{Are You Sure|N}"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>⊠-Clear-Map</span></a>' | |
+ '<br><a href="!DungeonDrawMap"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>╔╣-Rol20Draw</span></a>' | |
+ '<br><a href="!DungeonDrawColor"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>▓-Set-Map-Color</span></a>' | |
+ '<br><a href="!DungeonDrawChange"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>⊞-Change-Texture</span></a>' | |
+ '<br><a href="!DungeonDrawMore"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>⇓-More Commands</span></a>'; | |
}else{ | |
menuText = '/w ' + state.DungeonDraw.who + ' ' | |
+ '<br><a href="!DungeonDrawHelp"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>?-Help</span></a>' | |
+ '<br><a href="!DungeonSave"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>▓>>░-Save Map</span></a>' | |
+ '<br><a href="!DungeonLoad"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>░<<▓-Load Map</span></a>' | |
+ '<br><a href="!DungeonDrawMenu"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>⇓-More Commands</span></a>'; | |
} | |
if( true === state.DungeonDraw.drawMode ){ | |
menuText += '<br><a href="!DungeonDrawMode" style="border: 1px solid Black; background-color: PaleGreen; color: Black;" ><span style="color: white; font-weight: normal; display: block; width: 150px;" >◯-Draw-Is-<b>ON</b></span>'; | |
}else{ | |
menuText += '<br><a href="!DungeonDrawMode" style="border: 1px solid DarkGray; background-color: DarkGray; color: white;" ><span style="color: white; font-weight: normal; display: block; width: 150px;" >◯-Draw-Is-<b>OFF</b></span>'; | |
} | |
sendChat('Main Menu', menuText); | |
}, | |
directTokenAdd = function (key) { | |
var page, | |
pageId, | |
thisTile, | |
center, | |
middle, | |
keyArguments, | |
newObj, | |
widthHeight = 70; | |
pageId = currentPageId; | |
page = getObj('page', pageId); | |
center = page.get('width') * 35; | |
middle = page.get('height') * 35; | |
thisTile = _.where(currentTiles, {key: key}); | |
if( _.isEmpty(thisTile) ) { | |
keyArguments = key.split('_'); | |
if(-1 !== 'GM,Label,Level'.indexOf(keyArguments[0])){ | |
thisTile = _.where(gmSpecial, {key: key}); | |
newObj = createObj('graphic', { | |
type: 'graphic', | |
subtype: 'token', | |
pageid: pageId, | |
layer: 'map', | |
width: 70, | |
height: 70, | |
left: center, | |
top: middle, | |
imgsrc: thisTile[0].url, | |
name: key, | |
controlledby: 'DungeonDrawGraphic' | |
}); | |
setTimeout(function() {toFront(newObj); }, 500); | |
} | |
return; | |
} | |
if ( (255 === thisTile[0].value) && (0 === thisTile[0].mask) ) { | |
widthHeight = 140; | |
if( ('DD_017' === thisTile[0].key) || ('DD_018' === thisTile[0].key) || ('DD_019' === thisTile[0].key) || ('DD_020' === thisTile[0].key) ) { | |
widthHeight = 70; | |
} | |
} | |
newObj = createObj('graphic', { | |
type: 'graphic', | |
subtype: 'token', | |
pageid: pageId, | |
layer: 'map', | |
width: widthHeight, | |
height: widthHeight, | |
left: widthHeight === 140 ? (center + 35) : center, | |
top: widthHeight === 140 ? (middle + 35) : middle, | |
imgsrc: thisTile[0].url, | |
name: key, | |
controlledby: 'DungeonDrawGraphic' | |
}); | |
setTimeout(function() {toFront(newObj); }, 500); | |
newObj.set('gmnotes', newObj.get('id')); | |
}, | |
colorMap = function() { | |
var page = getObj('page', currentPageId), | |
args = state.DungeonDraw.currentTextureName.split('|'); | |
if( _.isEmpty(page) ){return; } | |
if( (false === /^#[0-9A-F]{6}$/.test(args[1])) && (2 !== args.length) ){return; } | |
page.set('background_color', args[1]); | |
}, | |
pathingRotation = function(angle, point,width,height) { | |
var pointX = point[0], pointY = point[1], originX = (width/2), originY = (height/2); | |
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 | |
]; | |
}, | |
placeRotatedFlipPaths = function(givenPathData) { | |
var temp, i, newX, newY, inputPath, angle, Xoffset, Yoffset, PathArray, maxX, minX, maxY, minY, objectWidth, objectHeight, | |
objectTop, objectLeft, pathString, graphicID; | |
_.each(givenPathData, function(given) { | |
temp = []; | |
for(i = 0; i < given.path.length; i = i + 1) { | |
newX = given.path[i][0]; | |
newY = given.path[i][1]; | |
if(given.fliph){newX = given.width - given.path[i][0]; } | |
if(given.flipv){newY = given.height - given.path[i][1]; } | |
temp.push([newX, newY]); | |
} | |
given.path = temp; | |
graphicID = given.forID; | |
inputPath = given.path; | |
angle = given.rotation; | |
Xoffset = given.left - (given.width/2); | |
Yoffset = given.top - (given.height/2); | |
PathArray = []; | |
if(!angle) {angle = 0; } | |
if(!Xoffset) {Xoffset = 0; } | |
if(!Yoffset) {Yoffset = 0; } | |
maxX = 0; | |
minX = false; | |
maxY = 0; | |
minY = false; | |
for(i = 0; i < inputPath.length; i = i + 1) { | |
PathArray.push([inputPath[i][0], inputPath[i][1]]); | |
PathArray[i] = pathingRotation(angle, PathArray[i],given.width,given.height); | |
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]; } | |
} | |
objectWidth = maxX - minX; | |
objectHeight = maxY - minY; | |
objectTop = minY + (objectHeight/2); | |
objectLeft = minX + (objectWidth/2); | |
for(i = 0; i < PathArray.length; i = i + 1) { | |
PathArray[i][0] = PathArray[i][0] - minX; | |
PathArray[i][1] = PathArray[i][1] - minY; | |
} | |
pathString = ""; | |
for(i = 0; i < PathArray.length; i = i + 1) { | |
if(i !== 0) { | |
pathString += ",[\"L\"," + PathArray[i][0] + "," + PathArray[i][1] + "]"; | |
} else { | |
pathString = "[\[\"M\"," + PathArray[i][0] + "," + PathArray[i][1] + "]"; | |
} | |
} | |
pathString += "\]"; | |
objectTop = objectTop + Yoffset; | |
objectLeft = objectLeft + Xoffset; | |
given.path = pathString; | |
given.left = objectLeft; | |
given.top = objectTop; | |
createObj('path',{ | |
pageid: currentPageId, | |
layer: 'walls', | |
path: given.path, | |
left: given.left, | |
top: given.top, | |
width: objectWidth, | |
height: objectHeight, | |
rotation: 0, | |
fliph: false, | |
flipv: false, | |
stroke: given.stroke, | |
stroke_width: given.strokewidth, | |
controlledby: graphicID | |
}); | |
}); | |
}, | |
forceProperPlacementAddDL = function(obj,left,top,rotation,id,foundTile) { | |
var newTop = (Math.round((top - 35)/70)*70) + 35, | |
newLeft = (Math.round((left - 35)/70)*70) + 35, | |
newRotation = (Math.round(rotation/90)*90)%360 + (rotation<0 ? 360 : 0), | |
bitCount, | |
pathValue; | |
obj.set({ | |
rotation: newRotation, | |
flipv: false, | |
fliph: false, | |
width: 70, | |
height: 70, | |
top: newTop, | |
left: newLeft | |
}); | |
_.each( findObjs({_type: 'path', controlledby: id}), function(eachPath) { | |
eachPath.remove(); | |
}); | |
featurePathArray = []; | |
for (bitCount = 0; bitCount < 8; bitCount = bitCount + 1) { | |
if (!(foundTile.dlBits & (1<<bitCount))) { | |
switch(bitCount + 1) { | |
case 1: pathValue = [[0,-1],[0,71]]; break; | |
case 2: pathValue = [[0,68],[0,70],[2,70]]; break; | |
case 3: pathValue = [[-1,70],[71,70]]; break; | |
case 4: pathValue = [[70,68],[70,70],[68,70]]; break; | |
case 5: pathValue = [[70,-1],[70,71]]; break; | |
case 6: pathValue = [[70,2],[70,0],[68,0]]; break; | |
case 7: pathValue = [[-1,0],[71,0]]; break; | |
case 8: pathValue = [[0,2],[0,0],[2,0]]; break; | |
} | |
if(pathValue){ | |
if( false === foundTile.diag ) { | |
featurePathArray.push({ | |
width: 70, | |
height: 70, | |
top: newTop, | |
left: newLeft, | |
rotation: newRotation, | |
fliph: false, | |
flipv: false, | |
path: pathValue, | |
stroke: '#FF0000', | |
strokewidth: 3, | |
forID: id | |
}); | |
} | |
} | |
} | |
} | |
if( true === foundTile.diag ) { | |
featurePathArray.push({ | |
width: 70, | |
height: 70, | |
top: newTop, | |
left: newLeft, | |
rotation: newRotation, | |
fliph: false, | |
flipv: false, | |
path: [[0,0],[-1,4],[66,71],[70,70]], | |
stroke: '#FF0000', | |
strokewidth: 3, | |
forID: id | |
}); | |
} | |
placeRotatedFlipPaths(featurePathArray); | |
setTimeout(function() {toFront(obj); }, 500); | |
}, | |
deferredCreateObj = (function(){ | |
var queue = [], | |
creator, | |
doCreates = function(){ | |
var done = 0, | |
request; | |
while(queue.length && ++done < deferred.batchSize ){ | |
request = queue.shift(); | |
createObj(request.type,request.properties); | |
} | |
if( queue.length ){ | |
creator = setTimeout(doCreates, deferred.batchDefer ); | |
} else { | |
creator = false; | |
} | |
}; | |
return function(type,properties){ | |
queue.push({type: type, properties: properties}); | |
if(!creator){ | |
creator = setTimeout(doCreates, deferred.initialDefer ); | |
} | |
}; | |
}()), | |
setTexture = function(message) { | |
var pack = message.replace('!DungeonDrawSetTexture ', ''), | |
switchPack = defaultTexture, | |
messageArguments; | |
_.each(installedTextures, function(eachTextures) { | |
messageArguments = eachTextures.split('|'); | |
if( messageArguments[0] === pack ) {switchPack = eachTextures; } | |
}); | |
state.DungeonDraw.currentTextureName = switchPack; | |
currentTiles = _.clone(DungeonDrawTiles[state.DungeonDraw.currentTextureName]); | |
currentTextureName = state.DungeonDraw.currentTextureName; | |
DungeonDrawMenu(); | |
}, | |
selectTexture = function() { | |
var text = '/w ' + state.DungeonDraw.who + ' ', | |
args; | |
if( 0 === installedTextures.length) {return; } | |
_.each(installedTextures, function(eachTextures) { | |
args = eachTextures.split('|'); | |
if( 2 !== args.length){return; } | |
}); | |
_.each(installedTextures, function(eachTextures) { | |
args = eachTextures.split('|'); | |
text += '<br><a href="!DungeonDrawSetTexture ' + args[0] + '"><span style="color: white; font-weight: normal; display: block; width: 150px;" >▹ ' + args[0] + '</span></a>'; | |
}); | |
sendChat('Select Texture', text); | |
}, | |
eigthBitClockwise = function(value, degree) { | |
var shift = (degree/90) * 2; | |
return (((value | (value << 8)) >> shift) & 255); | |
}, | |
getObjValue = function(obj, keys) { | |
return _.reduce( keys || objExtractKeys, function(m,prop){ | |
m[prop] = obj.get(prop); | |
return m; | |
}, {}); | |
}, | |
pathChecker = function (obj){ | |
var ObjValues = getObjValue(obj, ['layer', 'path']), | |
check = true, | |
firstX = false, | |
firstY = false, | |
lastX, lastY; | |
_.each(JSON.parse(ObjValues.path), function(eachPoint) { | |
if( false === firstX ) { | |
firstX = eachPoint[1]; | |
firstY = eachPoint[2]; | |
} | |
lastX = eachPoint[1]; | |
lastY = eachPoint[2]; | |
if( 3 !== eachPoint.length ) { | |
check = false; | |
return false; | |
} | |
}); | |
if ( (lastX !== firstX) || (lastY !== firstY) ) { | |
check = false; | |
} | |
if ( ('map' !== ObjValues.layer) ) { | |
check = false; | |
} | |
return check; | |
}, | |
clearMap = function(y) { | |
if( 'Y' !== y.toUpperCase() ){return; } | |
_.each(findObjs({_pageid: currentPageId, _type: 'graphic', layer: 'map', controlledby: 'DungeonDrawGraphic'}), function(eachPath) { | |
getObj('graphic', eachPath.id).remove(); | |
}); | |
_.each(findObjs({_pageid: currentPageId, _type: 'path', layer: 'map', controlledby: 'DungeonDrawPath'}), function(eachPath) { | |
getObj('path', eachPath.id).remove(); | |
}); | |
pathUndo = []; | |
}, | |
drawUndo = function() { | |
var lastPathSequence, | |
undoThisPath; | |
if( _.isEmpty(pathUndo) ){ | |
return; | |
} | |
lastPathSequence = Math.max.apply(Math,pathUndo.map(function(o){return o.sequence;})); | |
undoThisPath = _.where(pathUndo, {sequence: lastPathSequence}); | |
pathUndo = _.reject(pathUndo,function(o){ | |
return undoThisPath[0].id === o.id; | |
}); | |
getObj('path', undoThisPath[0].id).remove(); | |
}, | |
snapPathing = function(obj) { | |
var ObjValues = getObjValue(obj, ['pageid','layer','path','width','height','top','left']), | |
pathResult = '[', | |
atX, | |
atY, | |
largestX = 0, | |
largestY = 0, | |
top, | |
left, | |
width, | |
height, | |
middle, | |
center, | |
newPathData; | |
_.each(JSON.parse(ObjValues.path), function(eachPoint) { | |
atX = Math.round(eachPoint[1] /70) * 70; | |
atY = Math.round(eachPoint[2] /70) * 70; | |
if( atX > largestX ) { largestX = atX; } | |
if( atY > largestY ) { largestY = atY; } | |
pathResult = pathResult + '["' + eachPoint[0] + '",' + atX + ',' + atY + '],'; | |
}); | |
pathResult = pathResult.substring(0, pathResult.length - 1); | |
pathResult = pathResult + ']'; | |
width = largestX; | |
height = largestY; | |
top = Math.ceil(ObjValues.top/35) * 35; | |
left = Math.ceil(ObjValues.left/35) * 35; | |
middle = (Math.round((top - (height / 2))/35) * 35) / 70; | |
middle = middle - Math.floor(middle); | |
if( 0.5 === middle ) { | |
top = top - 35; | |
} | |
center = (Math.round((left - (width / 2))/35) * 35) / 70; | |
center = center - Math.floor(center); | |
if( 0.5 === center ) { | |
left = left - 35; | |
} | |
newPathData = { | |
width: width, | |
height: height, | |
top: top, | |
left: left, | |
path: pathResult | |
}; | |
return newPathData; | |
}, | |
macrosInstall = function() { | |
var controller = findObjs({ _type: 'character', name: 'Dungeon-Draw-Connection'})[0] || | |
createObj('character', {name: 'Dungeon-Draw-Connection', avatar: 'https://s3.amazonaws.com/files.d20.io/images/8821111/fBVwB1f2_t7U3k8XrmbKxw/thumb.png?1428953603'}), | |
ability = findObjs({_type: 'ability', name: '⇗▀⇘▄-Remove-Replace', characterid: controller.get('id')})[0] || | |
createObj('ability', {name: '⇗▀⇘▄-Remove-Replace', characterid: controller.get('id'), action: '!DungeonRemoveReplace', istokenaction: true}); | |
return controller.get('id'); | |
}, | |
getUnderRaise = function(token) { | |
var squares = [], | |
foundSuqare, | |
foundBits, | |
theseTiles = [], | |
thisPageId = token.get('pageid'), | |
tile1, | |
tile2, | |
tile3, | |
tile4, | |
currentTileBits, | |
seekBits, | |
seekPack = 'none', | |
seekDegree, | |
checkTiles, | |
i, | |
maskedMapSquare, | |
changeTarget; | |
bitTiles = []; | |
getAllBitTiles(); | |
//AND Logic | |
squares = [ | |
{sqr: 1, left: -70, top: -70, outer: false, mask: 247}, | |
{sqr: 2, left: 0, top: -70, outer: false, mask: 251}, | |
{sqr: 3, left: +70, top: -70, outer: false, mask: 253}, | |
{sqr: 4, left: +70, top: 0, outer: false, mask: 254}, | |
{sqr: 5, left: +70, top: +70, outer: false, mask: 127}, | |
{sqr: 6, left: 0, top: +70, outer: false, mask: 191}, | |
{sqr: 7, left: -70, top: +70, outer: false, mask: 223}, | |
{sqr: 8, left: -70, top: 0, outer: false, mask: 239}, | |
{sqr: 9, left: 0, top: 0, outer: false, mask: 0 } | |
]; | |
_.each(squares, function(atSquares) { | |
foundSuqare = findObjs({ | |
_pageid: thisPageId, | |
_type: 'graphic', | |
layer: 'map', | |
width: 70, | |
height: 70, | |
left: parseInt(token.get('left')) + parseInt(atSquares.left), | |
top: parseInt(token.get('top')) + parseInt(atSquares.top) | |
}); | |
foundBits = _.where(bitTiles, { | |
url: foundSuqare.length ? foundSuqare[0].get('imgsrc') : 'none', | |
degree: foundSuqare.length ? foundSuqare[0].get('rotation') : 'none' | |
}); | |
theseTiles.push({ | |
sqr: atSquares.sqr, | |
sqrMask: atSquares.mask, | |
updateId: foundSuqare.length ? foundSuqare[0].get('id') : 'none', | |
UpdateName: foundSuqare.length ? foundSuqare[0].get('name') : 'none', | |
updateRotation: foundSuqare.length ? foundSuqare[0].get('rotation') : 'none', | |
updateImgsrc: foundSuqare.length ? foundSuqare[0].get('imgsrc') : 'none', | |
updateLeft: foundSuqare.length ? (parseInt(token.get('left')) + atSquares.left) : 'none', | |
updateTop: foundSuqare.length ? (parseInt(token.get('top')) + atSquares.top) : 'none', | |
value: foundBits.length ? foundBits[0].value : 'none', | |
mask: foundBits.length ? foundBits[0].mask : 'none', | |
pack: foundBits.length ? foundBits[0].pack : 'none' | |
}); | |
}); | |
_.each(theseTiles, function(eachTileFlatten) { | |
if( 'none' !== eachTileFlatten.UpdateName) { | |
currentTileBits = eachTileFlatten.value & eachTileFlatten.mask; | |
seekBits = currentTileBits & eachTileFlatten.sqrMask; | |
seekPack = eachTileFlatten.pack; | |
seekDegree = eachTileFlatten.updateRotation; | |
checkTiles = _.where(bitTiles, {pack: seekPack}); | |
i=0; | |
while (i < checkTiles.length) { | |
maskedMapSquare = seekBits & checkTiles[i].mask; | |
if(checkTiles[i].value === maskedMapSquare){ | |
getObj('graphic', eachTileFlatten.updateId).remove(); | |
changeTarget = createObj('graphic', { | |
_type: 'graphic', | |
subtype: 'token', | |
pageid: thisPageId, | |
layer: 'map', | |
width: 70, | |
height: 70, | |
left: eachTileFlatten.updateLeft, | |
top: eachTileFlatten.updateTop, | |
rotation: checkTiles[i].degree, | |
imgsrc: checkTiles[i].url, | |
name: checkTiles[i].key, | |
controlledby: 'DungeonDrawGraphic' | |
}); | |
setTimeout(function() {toBack(changeTarget); }, 500); | |
break; | |
} | |
i = i + 1; | |
} | |
} | |
}); | |
}, | |
getUnderFlatten = function(token) { | |
var squares = [], | |
foundSuqare, | |
foundBits, | |
theseTiles = [], | |
thisPageId = token.get('pageid'), | |
tile1, | |
tile2, | |
tile3, | |
tile4, | |
currentTileBits, | |
seekBits, | |
seekPack = 'none', | |
seekDegree, | |
checkTiles, | |
i, | |
maskedMapSquare, | |
changeTarget; | |
bitTiles = []; | |
getAllBitTiles(); | |
//OR Logic | |
squares = [ | |
{sqr: 1, left: -35, top: -35, outer: false, mask: 28}, | |
{sqr: 2, left: +35, top: -35, outer: false, mask: 7}, | |
{sqr: 3, left: +35, top: +35, outer: false, mask: 193}, | |
{sqr: 4, left: -35, top: +35, outer: false, mask: 112} | |
]; | |
_.each(squares, function(atSquares) { | |
foundSuqare = findObjs({ | |
_pageid: thisPageId, | |
_type: 'graphic', | |
layer: 'map', | |
width: 70, | |
height: 70, | |
left: parseInt(token.get('left')) + parseInt(atSquares.left), | |
top: parseInt(token.get('top')) + parseInt(atSquares.top) | |
}); | |
foundBits = _.where(bitTiles, { | |
url: foundSuqare.length ? foundSuqare[0].get('imgsrc') : 'none', | |
degree: foundSuqare.length ? foundSuqare[0].get('rotation') : 'none' | |
}); | |
theseTiles.push({ | |
sqr: atSquares.sqr, | |
sqrMask: atSquares.mask, | |
updateId: foundSuqare.length ? foundSuqare[0].get('id') : 'none', | |
UpdateName: foundSuqare.length ? foundSuqare[0].get('name') : 'none', | |
updateRotation: foundSuqare.length ? foundSuqare[0].get('rotation') : 'none', | |
updateImgsrc: foundSuqare.length ? foundSuqare[0].get('imgsrc') : 'none', | |
updateLeft: foundSuqare.length ? (parseInt(token.get('left')) + atSquares.left) : 'none', | |
updateTop: foundSuqare.length ? (parseInt(token.get('top')) + atSquares.top) : 'none', | |
value: foundBits.length ? foundBits[0].value : 'none', | |
mask: foundBits.length ? foundBits[0].mask : 'none', | |
pack: foundBits.length ? foundBits[0].pack : 'none' | |
}); | |
}); | |
_.each(theseTiles, function(eachTileFlatten) { | |
if( 'none' !== eachTileFlatten.UpdateName) { | |
currentTileBits = eachTileFlatten.value & eachTileFlatten.mask; | |
seekBits = currentTileBits | eachTileFlatten.sqrMask; | |
seekPack = eachTileFlatten.pack; | |
seekDegree = eachTileFlatten.updateRotation; | |
checkTiles = _.where(bitTiles, {pack: seekPack}); | |
i=0; | |
while (i < checkTiles.length) { | |
maskedMapSquare = seekBits & checkTiles[i].mask; | |
if(checkTiles[i].value === maskedMapSquare){ | |
getObj('graphic', eachTileFlatten.updateId).remove(); | |
changeTarget = createObj('graphic', { | |
_type: 'graphic', | |
subtype: 'token', | |
pageid: thisPageId, | |
layer: 'map', | |
width: 70, | |
height: 70, | |
left: eachTileFlatten.updateLeft, | |
top: eachTileFlatten.updateTop, | |
rotation: checkTiles[i].degree, | |
imgsrc: checkTiles[i].url, | |
name: checkTiles[i].key, | |
controlledby: 'DungeonDrawGraphic' | |
}); | |
setTimeout(function() {toBack(changeTarget); }, 500); | |
break; | |
} | |
i = i + 1; | |
} | |
} | |
}); | |
}, | |
useRemoveReplace = function(message) { | |
var token = getObj('graphic', message.selected[0]._id); | |
if( 'flatten' === token.get('name') ) { | |
getUnderFlatten(token); | |
}else{ | |
getUnderRaise(token); | |
} | |
}, | |
fixFlattenRaiseTool = function(obj) { | |
if( 'flatten' === obj.get('name') ) { | |
obj.set({ | |
rotation: 0, | |
width: 140, | |
height: 140, | |
left: Math.floor(obj.get('left') / 70) * 70, | |
top: Math.floor(obj.get('top') / 70) * 70 | |
}); | |
}else{ | |
obj.set({ | |
rotation: 0, | |
width: 210, | |
height: 210, | |
left: (Math.floor(obj.get('left') / 70) * 70) + 35, | |
top: (Math.floor(obj.get('top') / 70) * 70) + 35 | |
}); | |
} | |
}, | |
addToolRaise = function() { | |
var pageId, | |
page, | |
center, | |
middle, | |
whichTool, | |
newTool; | |
pageId = currentPageId; | |
page = getObj('page', pageId); | |
center = (Math.floor(page.get('width') / 2) * 70) - 35; | |
middle = (Math.floor(page.get('height') / 2) * 70) - 35; | |
newTool = createObj('graphic', { | |
type: 'graphic', | |
subtype: 'token', | |
pageid: pageId, | |
layer: 'map', | |
width: 210, | |
height: 210, | |
left: center, | |
top: middle, | |
imgsrc: 'https://s3.amazonaws.com/files.d20.io/images/8908018/CX3Y6F5LJmI84N5dJP7CUg/thumb.png?1429400112', | |
represents: macrosInstall(), | |
name: 'raise' | |
}); | |
setTimeout(function() {toFront(newTool); }, 500); | |
}, | |
addToolFlatten = function() { | |
var pageId, | |
page, | |
center, | |
middle, | |
whichTool, | |
newTool; | |
pageId = currentPageId; | |
page = getObj('page', pageId); | |
center = Math.floor(page.get('width') / 2) * 70; | |
middle = Math.floor(page.get('height') / 2) * 70; | |
newTool = createObj('graphic', { | |
type: 'graphic', | |
subtype: 'token', | |
pageid: pageId, | |
layer: 'map', | |
width: 140, | |
height: 140, | |
left: center, | |
top: middle, | |
imgsrc: 'https://s3.amazonaws.com/files.d20.io/images/8907984/mi2Vl6tWu8JsGM0LpCmYNg/thumb.png?1429400030', | |
represents: macrosInstall(), | |
name: 'flatten' | |
}); | |
setTimeout(function() {toFront(newTool); }, 500); | |
}, | |
getBits = function(left,top) { | |
var i, | |
checkTiles, | |
maskedMapSquare, | |
seekBits = 0, | |
bit1 = _.isEmpty(placementTiles[ (parseInt(left,10) - 70).toString() + ':' + top.toString() ]) ? 0 : 1, | |
bit2 = _.isEmpty(placementTiles[ (parseInt(left,10) - 70).toString() + ':' + (parseInt(top,10) + 70).toString() ]) ? 0 : 2, | |
bit3 = _.isEmpty(placementTiles[ left.toString() + ':' + (parseInt(top,10) + 70).toString() ]) ? 0 : 4, | |
bit4 = _.isEmpty(placementTiles[ (parseInt(left,10) + 70).toString() + ':' + (parseInt(top,10) + 70).toString() ]) ? 0 : 8, | |
bit5 = _.isEmpty(placementTiles[ (parseInt(left,10) + 70).toString() + ':' + top.toString() ]) ? 0 : 16, | |
bit6 = _.isEmpty(placementTiles[ (parseInt(left,10) + 70).toString() + ':' + (parseInt(top,10) - 70).toString() ]) ? 0 : 32, | |
bit7 = _.isEmpty(placementTiles[ left.toString() + ':' + (parseInt(top,10) - 70).toString() ]) ? 0 : 64, | |
bit8 = _.isEmpty(placementTiles[ (parseInt(left,10) - 70).toString() + ':' + (parseInt(top,10) - 70).toString() ]) ? 0 : 128; | |
seekBits = bit1 | bit2 | bit3 | bit4 | bit5 | bit6 | bit7 | bit8; | |
checkTiles = _.where(bitTiles, {pack: currentTextureName}); | |
i=0; | |
while (i < checkTiles.length) { | |
maskedMapSquare = seekBits & checkTiles[i].mask; | |
if(checkTiles[i].value === maskedMapSquare){ | |
deferredCreateObj('graphic', { | |
subtype: 'token', | |
pageid: currentPageId, | |
layer: 'map', | |
width: 70, | |
height: 70, | |
left: left, | |
top: top, | |
rotation: checkTiles[i].degree, | |
imgsrc: checkTiles[i].url, | |
name: checkTiles[i].key, | |
controlledby: 'DungeonDrawGraphic' | |
}); | |
break; | |
} | |
i = i + 1; | |
} | |
}, | |
evelauateTiles = function() { | |
var left_top, | |
bitValue; | |
placeSeek = []; | |
Object.keys(placementTiles).forEach(function(key) { | |
left_top = key.split(':'); | |
bitValue = getBits(parseInt(left_top[0]),parseInt(left_top[1])); | |
placeSeek.push({ | |
left: parseInt(left_top[0]), | |
top: parseInt(left_top[1]), | |
bits: bitValue | |
}); | |
}); | |
}, | |
isPointInPoly = function (poly, pt){ | |
var c = false, i = -1, l = poly.length, j; | |
for(j = l - 1; ++i < l; j = i) { | |
((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) | |
&& (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) && (c = !c); | |
} | |
return c; | |
}, | |
getStepsInBoxBound = function(getBoxBound) { | |
var rowStart, | |
rowEnd = getBoxBound.yMaxBoxBound, | |
colStart, | |
colEnd = getBoxBound.xMaxBoxBound, | |
point, | |
inPoly; | |
for(rowStart = getBoxBound.yMinBoxBound; rowStart < rowEnd; rowStart = rowStart + 70) { | |
for(colStart = getBoxBound.xMinBoxBound; colStart < colEnd; colStart = colStart + 70) { | |
point = [{x: colStart, y: rowStart}]; | |
inPoly = isPointInPoly(getBoxBound.checkerPoints, point[0]); | |
if(inPoly){ | |
placementTiles[parseInt(colStart) + ':' + parseInt(rowStart)] = {x: colStart, y: rowStart}; | |
} | |
} | |
} | |
}, | |
getBoxBoundPath = function(pathObject) { | |
var width = Math.ceil((pathObject.get('width') + 140)/70) * 70, | |
height = Math.ceil((pathObject.get('height') + 140)/70) * 70, | |
top = Math.ceil(pathObject.get('top')/35) * 35, | |
left = Math.ceil(pathObject.get('left')/35) * 35, | |
center, | |
middle, | |
newPath, | |
newPathData, | |
points = []; | |
middle = (Math.round((top - (height / 2))/35) * 35) / 70; | |
middle = middle - Math.floor(middle); | |
if( 0.5 === middle ) { | |
top = top - 35; | |
} | |
center = (Math.round((left - (width / 2))/35) * 35) / 70; | |
center = center - Math.floor(center); | |
if( 0.5 === center ) { | |
left = left - 35; | |
} | |
newPath = '[["M",0,0],["L",' + width + ',0],["L",' + width + ',' + height + '],["L",0,' + height + '],["L",0,0]]'; | |
//get poly points | |
_.each(JSON.parse(pathObject.get('path')), function(eachPoint) { | |
points.push({ | |
x: parseInt(eachPoint[1] + (pathObject.get('left') - (pathObject.get('width') / 2))), | |
y: parseInt(eachPoint[2] + (pathObject.get('top') - (pathObject.get('height') / 2))) | |
}); | |
}); | |
//get poly points | |
newPathData = { | |
id: pathObject.get('id'), | |
pageid: pathObject.get('pageid'), | |
objWidth: pathObject.get('width'), | |
objHeight: pathObject.get('height'), | |
objTop: pathObject.get('top'), | |
ObjLeft: pathObject.get('left'), | |
ObjPath: pathObject.get('path'), | |
widthBoxBound: width, | |
heightBoxBound: height, | |
topBoxBound: top, | |
leftBoxBound: left, | |
pathBoxBound: newPath, | |
xMinBoxBound: left - (width / 2) + 35, | |
xMaxBoxBound: (left + (width / 2) - 35) + 70, | |
yMinBoxBound: top - (height / 2) + 35, | |
yMaxBoxBound: (top + (height / 2) - 35) + 70, | |
checkerPoints: points | |
}; | |
return newPathData; | |
}, | |
drawMap = function() { | |
var boxBound, | |
pageid = currentPageId, | |
eachExistingTile = [], | |
existTiles; //newcode | |
//newcode | |
existTiles = filterObjs(function(obj) { | |
switch(obj.get('name')) { | |
case 'DD_001': | |
case 'DD_002': | |
case 'DD_003': | |
case 'DD_004': | |
case 'DD_005': | |
case 'DD_006': | |
case 'DD_007': | |
case 'DD_008': | |
case 'DD_009': | |
case 'DD_010': | |
case 'DD_011': | |
case 'DD_012': | |
case 'DD_013': | |
case 'DD_014': | |
case 'DD_015': | |
case 'DD_016': | |
if(pageid === obj.get('pageid')){ | |
return true; | |
} | |
} | |
return false; | |
}); | |
_.each(existTiles, function(eachTile) { | |
eachExistingTile.push(parseInt(eachTile.get('left')) + ':' + parseInt(eachTile.get('top'))); | |
}); | |
//newCode | |
//Create box bounding | |
_.each(pathUndo, function(eachPath) { | |
boxBound = getBoxBoundPath(getObj('path', eachPath.id)); | |
getStepsInBoxBound(boxBound); | |
pathUndo = _.reject(pathUndo,function(o){ | |
return eachPath.id === o.id; | |
}); | |
}); | |
//newcode | |
Object.keys(placementTiles).forEach(function(key) { | |
if( -1 !== eachExistingTile.indexOf(key) ) { | |
delete placementTiles[key]; | |
} | |
}); | |
//newcode | |
evelauateTiles(); | |
_.each(findObjs({_type: 'path', controlledby: 'DungeonDrawPath'}), function(eachPath) { | |
getObj('path', eachPath.id).remove(); | |
}); | |
pathUndo = []; | |
placementTiles = []; | |
placeSeek = []; | |
}, | |
checkOwnerName = function(players,ownerId) { | |
var whoToTest = _.where(players, {id: ownerId})[0].get('displayname').split(' ')[0]; | |
return _.chain(players) | |
.map(function(p){ | |
return p.get('displayname').split(' ')[0]; | |
}) | |
.filter(function(n){ | |
return n === whoToTest; | |
}) | |
.value() | |
.length>0; | |
}, | |
getAllBitTiles = function() { | |
var newValue, newMask; | |
bitTiles = []; | |
_.each(allTexturesTiles, function(eachTile) { | |
if( 0 !== eachTile.mask ){ | |
bitTiles.push({ | |
degree: 0, | |
value: eachTile.value, | |
mask: eachTile.mask, | |
url: eachTile.url, | |
key: eachTile.key, | |
pack: eachTile.pack | |
}); | |
newValue = eigthBitClockwise(eachTile.value, 90); | |
newMask = eigthBitClockwise(eachTile.mask, 90); | |
bitTiles.push({ | |
degree: 90, | |
value: newValue, | |
mask: newMask, | |
url: eachTile.url, | |
key: eachTile.key, | |
pack: eachTile.pack | |
}); | |
newValue = eigthBitClockwise(eachTile.value, 180); | |
newMask = eigthBitClockwise(eachTile.mask, 180); | |
bitTiles.push({ | |
degree: 180, | |
value: newValue, | |
mask: newMask, | |
url: eachTile.url, | |
key: eachTile.key, | |
pack: eachTile.pack | |
}); | |
newValue = eigthBitClockwise(eachTile.value, 270); | |
newMask = eigthBitClockwise(eachTile.mask, 270); | |
bitTiles.push({ | |
degree: 270, | |
value: newValue, | |
mask: newMask, | |
url: eachTile.url, | |
key: eachTile.key, | |
pack: eachTile.pack | |
}); | |
} | |
}); | |
}, | |
refreshData = function(){ | |
var playerPages = Campaign().get('playerspecificpages'), | |
ownerPage = playerPages[state.DungeonDraw.owner], | |
tempPack, | |
i; | |
if( undefined === ownerPage ){ | |
currentPageId = Campaign().get('playerpageid'); | |
if( state.DungeonDraw.drawMode === true ){ | |
sendChat('Dungeon Draw', '/w ' + state.DungeonDraw.who + ' ' | |
+'<div style="padding:1px 3px;border: 1px solid #9F6000; background: #FEEFB3; color: #9F6000; font-size: 80%;">' | |
+'<img src="https://s3.amazonaws.com/files.d20.io/images/6422879/M-oWEvMt1bhC2M-bdi28tA/thumb.png?1416499678" style="vertical-align: text-bottom; width:20px; height:20px; padding: 0px 5px;" />' | |
+'Current page is the player book mark page. Recommend using the party split feature to select the page you wish to edit.' | |
); | |
} | |
}else{ | |
currentPageId = ownerPage; | |
} | |
installedTextures = []; | |
Object.keys(DungeonDrawTiles).forEach(function(key) { | |
installedTextures.push(key); | |
}); | |
currentTiles = _.clone(DungeonDrawTiles[state.DungeonDraw.currentTextureName]); | |
allTexturesTiles = []; | |
for (i = 0; i < installedTextures.length; i = i + 1) { | |
tempPack = _.clone(DungeonDrawTiles[installedTextures[i]]); | |
_.each(tempPack, function(eachTile) { | |
allTexturesTiles.push({ | |
url: eachTile.url, | |
key: eachTile.key, | |
value: eachTile.value, | |
mask: eachTile.mask, | |
dlBits: eachTile.dlBits, | |
diag: eachTile.diag, | |
pack: installedTextures[i] | |
}); | |
}); | |
} | |
currentTextureName = state.DungeonDraw.currentTextureName; | |
getAllBitTiles(); | |
state.DungeonDraw.processing = false; | |
state.DungeonDraw.drawMode = true; | |
}, | |
initializeResetState = function(action) { | |
var players, ownerId, nameTruncated; | |
switch(action){ | |
case 'initialize': | |
players = findObjs({type: 'player'}); | |
ownerId = _.find(_.pluck(players,'id'),playerIsGM); | |
if( !ownerId || !checkOwnerName(players,ownerId)) {return; } | |
log('DungeonDraw: Initialize State'); | |
state.DungeonDraw = { | |
version: schemaVersion, | |
currentTextureName: defaultTexture, | |
drawMode: false, | |
processing: false, | |
owner: ownerId, | |
who: getObj('player',ownerId).get('_displayname').split(' ')[0] | |
}; | |
return; | |
case 'reset': | |
log('DungeonDraw: Resetting State'); | |
state.DungeonDraw.version = schemaVersion; | |
state.DungeonDraw.currentTextureName = defaultTexture; | |
state.DungeonDraw.drawMode = false; | |
state.DungeonDraw.processing = false; | |
return; | |
} | |
}, | |
checkInstall = function() { | |
if( ! _.has(state,'DungeonDraw') ) { | |
initializeResetState('initialize'); | |
} | |
if( ! _.has(state,'DungeonDraw') ) { | |
sendChat('Dungeon Draw','/direct ' | |
+'<div style="padding:1px 3px;border: 1px solid #FF0000; background: #FFBABA; color: #D8000C; font-size: 80%;">' | |
+'<img src="https://s3.amazonaws.com/files.d20.io/images/6422880/SIjBHWJNC8f9a73Rg_VkOQ/thumb.png?14164996807" style="vertical-align: text-bottom; width:20px; height:20px; padding: 0px 5px;" />' | |
+'<b>Script Halted.</b> Script halted. State failed to initialize. Likely due to no GM being found or GMs do not having unique names.' | |
); | |
return; | |
} | |
if( state.DungeonDraw.version !== schemaVersion ) { | |
initializeResetState('reset') | |
} | |
refreshData(); | |
macrosInstall(); | |
sendChat('Main Menu', '/w ' + state.DungeonDraw.who + ' <a href="!DungeonDrawMenu"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>Dungeon Draw Menu</span></a>'); | |
}, | |
control = function(id) { | |
var players = findObjs({type: 'player'}); | |
if( !checkOwnerName(players,id) ) { | |
sendChat('Dungeon Draw', '/direct ' | |
+'<div style="padding:1px 3px;border: 1px solid #9F6000; background: #FEEFB3; color: #9F6000; font-size: 80%;">' | |
+'<img src="https://s3.amazonaws.com/files.d20.io/images/6422879/M-oWEvMt1bhC2M-bdi28tA/thumb.png?1416499678" style="vertical-align: text-bottom; width:20px; height:20px; padding: 0px 5px;" />' | |
+'Transfer of control failed. Name conflict.' | |
); | |
return; | |
} | |
state.DungeonDraw.owner = id; | |
state.DungeonDraw.who = getObj('player',id).get('_displayname').split(' ')[0]; | |
refreshData(); | |
sendChat('Main Menu', '/w ' + state.DungeonDraw.who + ' <a href="!DungeonDrawMenu"' + cssButtonAnchor + ' ><span' + cssButtonSpan + '>Dungeon Draw Menu</span></a>'); | |
}, | |
handleInput = function(msg) { | |
var message = _.clone(msg), messageArguments = msg.content.split(/\s+/); | |
if ( ('api' !== message.type) || (true === state.DungeonDraw.processing) || (false === playerIsGM(message.playerid)) ) { | |
return; | |
} | |
if ( messageArguments[0] === '!DungeonDrawMode') { | |
state.DungeonDraw.drawMode = (state.DungeonDraw.drawMode === true ? false : true); | |
} | |
if( (messageArguments[0] === '!DungeonDrawMenu') || (messageArguments[0] === '!DungeonDrawMode') ){ | |
DungeonDrawMenu(); | |
return; | |
} | |
state.DungeonDraw.processing = true; | |
switch(messageArguments[0]) { | |
case '!DungeonDrawClear': clearMap(messageArguments[1]); break; | |
case '!DungeonDrawMap': drawMap(); break; | |
case '!DungeonDrawUndo': drawUndo(); break; | |
case '!DungeonDrawChange': selectTexture(); break; | |
case '!DungeonDrawSetTexture': setTexture(message.content); break; | |
case '!DungeonDrawColor': colorMap(); break; | |
case '!DungeonDrawNumber': directTokenAdd(messageArguments[1]); break; | |
case '!DungeonAddToolFlatten': addToolFlatten(); break; | |
case '!DungeonAddToolRaise': addToolRaise(); break; | |
case '!DungeonRemoveReplace': useRemoveReplace(message); break; | |
case '!DungeonDrawHelp': help(); break; | |
case '!DungeonDrawControl': control(message.playerid); break; | |
case '!DungeonDrawMore': DungeonDrawMenu('more'); break; | |
case '!DungeonSave': saveMap(); break; | |
case '!DungeonDrawConfirm': getMapData(messageArguments[1]); break; | |
case '!DungeonLoad': loadMap(); break; | |
case '!DungeonDrawSetMap': setMap(message.content); break; | |
case '!DungeonDrawCreateLoadedMap': createLoadedMap(message.content); break; | |
} | |
state.DungeonDraw.processing = false; | |
}, | |
handleGraphicChange = function(obj) { | |
var ObjValues = getObjValue(obj,['name','pageid','rotation','left','top','flipv','fliph','id','imgsrc']), | |
foundTile = _.where(allTexturesTiles, {url: ObjValues.imgsrc}), | |
newLeft, | |
newTop, | |
newRotation; | |
if( ('flatten' === ObjValues.name) || ('raise' === ObjValues.name) ) { | |
fixFlattenRaiseTool(obj); | |
return; | |
} | |
if( !_.isEmpty(foundTile) ){ | |
if ( (255 === foundTile[0].value) && (0 === foundTile[0].mask) ){ | |
return; | |
} | |
//force proper tile placement and update dynamic lighting | |
forceProperPlacementAddDL(obj,ObjValues.left,ObjValues.top,ObjValues.rotation,ObjValues.id,foundTile[0]); | |
} | |
}, | |
handleGraphicDestroy = function(obj) { | |
var foundTiles = _.where(currentTiles, {key: obj.get('name')}); | |
if( 0 === foundTiles.length) {return; } | |
if ( (255 === foundTiles[0].value) && (0 === foundTiles[0].mask) ){ | |
return; | |
} | |
_.each(findObjs({_type: 'path', controlledby: obj.get('_id') }), function(eachPath) { | |
eachPath.remove(); | |
}); | |
}, | |
handlePathAdd = function(obj) { | |
var goodPath = pathChecker(obj), | |
ObjValues = getObjValue(obj, ['pageid','layer','path','width','height','top','left']), | |
newPath, | |
snappedPath; | |
if( (false === state.DungeonDraw.drawMode) || (currentPageId !== ObjValues.pageid) ){ | |
return; | |
} | |
if( (70 > (Math.round(ObjValues.width/70) * 70)) || (70 > (Math.round(ObjValues.height/70) * 70)) ) { | |
obj.remove(); | |
return; | |
} | |
if(goodPath){ | |
snappedPath = snapPathing(obj); | |
newPath = createObj('path', { | |
type: 'path', | |
pageid: ObjValues.pageid, | |
path: snappedPath.path, | |
fill: '#00CC99', | |
stroke: '#00CC99', | |
layer: 'map', | |
stroke_width: 1, | |
width: snappedPath.width, | |
height: snappedPath.height, | |
top: snappedPath.top, | |
left: snappedPath.left, | |
controlledby: 'DungeonDrawPath' | |
}); | |
pathUndo.push({ | |
id: newPath.get('id'), | |
pageid: ObjValues.pageid, | |
layer: 'map', | |
path: snappedPath.path, | |
width: snappedPath.width, | |
height: snappedPath.height, | |
top: snappedPath.top, | |
left: snappedPath.left, | |
fill: '#00CC99', | |
stroke: '#00CC99', | |
stroke_width: 1, | |
controlledby: 'DungeonDrawPath', | |
sequence: seq() | |
}); | |
} | |
if( 'map' === ObjValues.layer ) { | |
//obj.remove(); | |
_.defer(()=>obj.remove()); | |
} | |
}, | |
handlePageChange = function(obj) { | |
refreshData(); | |
}, | |
registerEventHandlers = function() { | |
on('change:campaign:playerpageid', handlePageChange); | |
on('change:campaign:playerspecificpages', handlePageChange); | |
on('chat:message', handleInput); | |
on('change:graphic', handleGraphicChange); | |
on('add:path', handlePathAdd); | |
on('destroy:graphic', handleGraphicDestroy); | |
checkInstall(); | |
}; | |
return { | |
CheckInstall: checkInstall, | |
RegisterEventHandlers: registerEventHandlers | |
}; | |
}()); | |
on('ready',function(){ | |
'use strict'; | |
DungeonDraw.RegisterEventHandlers(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment