/*global sendChat, createObj, getObj, toFront, toBack, state, _, log, on, filterObjs, setTimeout, playerIsGM*/ /*jslint white: true */ var AOEDrawer = AOEDrawer || (function(){ 'use strict'; //breakcode = breakcode var version = 0.81, lastUpdate = 1440326236, schemaVersion = 0.81, //Default Settings slideMenuDefaultOn = false, strokeDefault = '#ff0000', stroke = '#ff0000', strokeWidth = 2, controlWidth = 25, ControlHeight = 25, iconIndex = [], keyIndex = [], controlIndex = {}, menuIndex = {}, subMenuIndex = {}, //sliderIndex = {}, icons = [ {key: '000', url: 'https://s3.amazonaws.com/files.d20.io/images/11586803/h8osf5_LzhhLnd2b-xQ14w/thumb.png?1439740906'}, {key: '001', url: 'https://s3.amazonaws.com/files.d20.io/images/11599767/axQ_j6iVfMiyR-GH4XOICw/thumb.png?1439772721'}, {key: '002', url: 'https://s3.amazonaws.com/files.d20.io/images/11599764/Ypi69de9_TysWnzr0DCn6Q/thumb.png?1439772710'}, {key: '003', url: 'https://s3.amazonaws.com/files.d20.io/images/11695574/i9svmUrm5eFqVpKEKsRRDg/thumb.png?1440161024'}, {key: '004', url: 'https://s3.amazonaws.com/files.d20.io/images/11695573/MB1fcqoCGVYhQ3Z-I0UjRQ/thumb.png?1440161021'}, {key: '005', url: 'https://s3.amazonaws.com/files.d20.io/images/11655199/Gcr7m87Mt2AMOrhAUuF-uw/thumb.png?1440000088'}, {key: '006', url: 'https://s3.amazonaws.com/files.d20.io/images/11655198/IbMLzahdaGzmsZhm30g8BQ/thumb.png?1440000084'}, {key: '007', url: 'https://s3.amazonaws.com/files.d20.io/images/11695570/oMjSBI1TP8aakBdFhZb5kg/thumb.png?1440161017'}, {key: '008', url: 'https://s3.amazonaws.com/files.d20.io/images/11695569/eBn3dtLC2RLS6Mfvwji65A/thumb.png?1440161014'}, {key: '009', url: 'https://s3.amazonaws.com/files.d20.io/images/11759786/Iv3U3YdFpmRLc7xEm3HziQ/thumb.png?1440346196'}, {key: '010', url: 'https://s3.amazonaws.com/files.d20.io/images/11759790/JyH9Vush0peWGbFEci9kag/thumb.png?1440346201'} ], objectNodeIc = 'https://s3.amazonaws.com/files.d20.io/images/11955642/VtboJWMnboar1U3Ytq23EQ/thumb.png?1441053682', objectCenter = 'https://s3.amazonaws.com/files.d20.io/images/11955640/Hfb6XR-8jfJOry5i8d7j-Q/thumb.png?1441053678', // ~~~> Cahnge Settings <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ changeSettings = (function(){ var toggleOnDefault = function() { if( true === state.AOEdrawer.config.defaultOn ) { state.AOEdrawer.config.defaultOn = false; }else{ state.AOEdrawer.config.defaultOn = true; } }, getInput = function(input) { switch(input){ case 'toggleOnDefault': toggleOnDefault(); break; } }; return { Input: getInput }; }()), // ~~~> Cahnge Settings <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~> Chat Output <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ chatOutput = (function(){ var slideSwitch = function(href,onOff,options) { var color = onOff ? '#393' : '#933', float = onOff ? 'left' : 'right', html = '' +'' +'
 
' +'
'; return html; }, button = function(href,text,options) { var html = '' + '' +text+''; return html; }, tableRowSwitch = function(value) { var html = '' + '' + '' + value.text + '' + slideSwitch(value.command,value.onOff,value.options) + ''; return html; }, tableRowButton = function(value) { var html = '' + '' + '' + button(value.command,value.text,value.options) + ''; return html; }, help = function(toTarget) { var content = toTarget + '
Beta Script. Read more here
' + '' + tableRowButton({ text: 'Main Menu.', command: '!aoedrawer menu', options: {} }) + '
'; sendChat('API', content); }, menu = function(toTarget,gm) { var content = toTarget + '
' + ''; if(gm){ content = content + tableRowSwitch({ text: state.AOEdrawer.config.defaultOn ? 'Drawing Control "Off" by default.' : 'Drawing Control "On" by default.', command: '!aoedrawer toggleOnDefault', onOff: state.AOEdrawer.config.defaultOn, options: {} }); } content = content + tableRowButton({ text: 'Toggle On/Off for selected.', command: '!aoedrawer toggleMenu', options: {} }) + tableRowButton({ text: 'Help With this Script.', command: '!aoedrawer help', options: {} }) + '
'; sendChat('AOE Drawer', content); }, getInput = function(input) { var toTarget = '/w "' + (getObj('player', input.who) || {get: function() {return '';}}).get('displayname') + '" '; switch(input.action){ case 'help': help(toTarget,input.gm); break; case 'menu': menu(toTarget,input.gm); break; } }; return { Input: getInput }; }()), // ~~~> Chat Output <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~> Place Spel Effect <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ placeEffect = (function(){ var checkAngle = function(ax,ay,bx,by) { var ty = by - ay, tx = bx - ax, theta = Math.atan2(ty, tx); theta *= 180 / Math.PI; return theta + 180; }, measurementValue = function (page,shape,distance1,distance2) { var displayValue,w,h; switch(shape){ case 'circle': displayValue = (((distance1 / 2) / 70) * page.get('scale_number')); displayValue = 'R:' + displayValue.toFixed(2) + ' ' + page.get('scale_units'); break; case 'rectangle': w = ((distance1 / 70) * page.get('scale_number')) * 2; h = ((distance2 / 70) * page.get('scale_number')) * 2; w = 'W:' + w.toFixed(1) + ' ' + page.get('scale_units'); h = 'H:' + h.toFixed(1) + ' ' + page.get('scale_units'); displayValue = w + ' ' + h; break; case 'cone': displayValue = (((distance1) / 70) * page.get('scale_number')); displayValue = 'L:' + displayValue.toFixed(2) + ' ' + page.get('scale_units') + ' ' + distance2 + '°'; break; case 'ray': displayValue = (((distance1) / 70) * page.get('scale_number')); displayValue = 'L:' + displayValue.toFixed(2) + ' ' + page.get('scale_units'); break; } return displayValue; }, lineDistance = function (point1, point2) { return Math.sqrt( (point2.x - point1.x) * (point2.x - point1.x) + (point2.y - point1.y) * (point2.y - point1.y) ); }, createShape = function (value) { //(token,c,l,t,w,h,p) var path = createObj('path', { layer: 'objects', pageid: value.token.get('_pageid'), controlledby: value.controlledby, left: value.left, top: value.top, width: value.width, height: value.height, path: value.path, stroke: stroke, stroke_width: strokeWidth, rotation: value.rotation || 0 }); return path; }, createControl = function (values) { var control = createObj('graphic', { imgsrc: objectNodeIc, pageid: values.obj.get('pageid'), layer: values.obj.get('layer'), controlledby: 'NEW,' + values.controlList, isdrawing: true, width: controlWidth, height: ControlHeight, left: values.left, top: values.top, showname: true, showplayers_name: true, name: '', lastmove: values.left + ',' + values.top, tint_color: stroke, light_hassight: true, light_losangle: 0, light_radius: 1 }); return control; }, createCenter = function (values) { var control = createObj('graphic', { imgsrc: objectCenter, pageid: values.obj.get('pageid'), layer: values.obj.get('layer'), controlledby: 'NEW,' + values.controlList, isdrawing: true, width: controlWidth, height: ControlHeight, left: values.obj.get('left') + values.offsetLeft, top: values.obj.get('top') + values.offsetTop, showname: true, showplayers_name: true, name: '', lastmove: values.obj.get('left') + values.offsetLeft + ',' + values.obj.get('top') + values.offsetTop, tint_color: stroke, light_hassight: true, light_losangle: 0, light_radius: 1 }); return control; }, getCircle = function (diameter) { var pts = _.map([0,0.22382,0.5,0.77614,1],function(f){ return f*diameter; }); return { path: '[["M",'+pts[0]+','+pts[2]+'],'+ '["C", '+pts[0]+', '+pts[1]+', '+pts[1]+', '+pts[0]+', '+pts[2]+', '+pts[0]+'],'+ '["C", '+pts[3]+', '+pts[0]+', '+pts[4]+', '+pts[1]+', '+pts[4]+', '+pts[2]+'],'+ '["C", '+pts[4]+', '+pts[3]+', '+pts[3]+', '+pts[4]+', '+pts[2]+', '+pts[4]+'],'+ '["C", '+pts[1]+', '+pts[4]+', '+pts[0]+', '+pts[3]+', '+pts[0]+', '+pts[2]+']]', center: {x: pts[2], y: pts[2]}, box: {width: pts[4],height: pts[4]} }; }, getSquare = function (w,h) { return { path: '[["M",'+ 0 +','+ 0 +'],'+ '["L", '+ w +', '+ 0 +'],'+ '["L", '+ w +', '+ h +'],'+ '["L", '+ 0 +', '+ h +'],'+ '["L", '+ 0 +', '+ 0 +']]', center: {x: w/2, y: h/2}, box: {width: w, height: h} }; }, rotate_point = function (pointX, pointY, originX, originY, angle) { angle = angle * Math.PI / 180.0; return { x: Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX, y: Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY }; }, getCone = function (distance,angle,spin) { var opposite = distance * Math.tan((angle / 2) * (Math.PI / 180)), x0 = opposite, y0 = 0, x1 = opposite * 2, y1 = distance, x2 = 0, y2 = distance, x3 = opposite, y3 = 0, w = opposite * 2, h = distance, spunPoints; spunPoints = rotate_point(x0,y0,opposite,0, spin); x0 = spunPoints.x; y0 = spunPoints.y; spunPoints = rotate_point(x1,y1,opposite,0, spin); x1 = spunPoints.x; y1 = spunPoints.y; spunPoints = rotate_point(x2,y2,opposite,0, spin); x2 = spunPoints.x; y2 = spunPoints.y; spunPoints = rotate_point(x3,y3,opposite,0, spin); x3 = spunPoints.x; y3 = spunPoints.y; w = Math.max(x0,x1,x2,x3) - Math.min(x0,x1,x2,x3); h = Math.max(y0,y1,y2,y3) - Math.min(y0,y1,y2,y3); return { path: '[["M",'+ x0 +','+ y0 +'],'+ '["L", '+ x1 +', '+ y1 +'],'+ '["L", '+ x2 +', '+ y2 +'],'+ '["L", '+ x3 +', '+ y3 +']]', center: {x: Math.min(x0,x1,x2,x3) + (w/2) - x0, y: Math.min(y0,y1,y2,y3) + (h/2) - y0}, box: {width: w, height: h} }; }, getRay = function (distance,spin) { var x0 = 0, y0 = 0, x1 = 0, y1 = distance, w = strokeWidth, h = distance; return { path: '[["M",'+ x0 +','+ y0 +'],["L", '+ x1 +', '+ y1 +']]', center: {x: strokeWidth / 2, y: distance / 2}, box: {width: w, height: h} }; }, createNewShape = function (token,key,type) { var controlList,page,shape,tokenOffsetLeft,tokenOffsetTop,contrlOffsetLeft,contrlOffsetTop,distance,control,measurement,playercolor; if( undefined === token ) {return; } page = getObj('page', token.get('pageid')); if( undefined === page ) {return; } controlList = getObj('character', token.get('represents')); if( undefined !== controlList ) {controlList = controlList.get('controlledby'); }else{controlList = ''; } playercolor = getObj('player', _.first(controlList.split(','))); if( undefined !== playercolor ) { stroke = playercolor.get('color'); }else{ stroke = strokeDefault; } switch(type){ case 'CircleToken': case 'CircleContr': shape = getCircle(140); break; case 'RctnglToken': case 'RctnglContr': case 'SquareToken': case 'SquareContr': shape = getSquare(140,140); break; case 'ConeslToken': case 'ConeslContr': shape = getCone(140,30,0); break; case 'DthRayToken': case 'DthRayContr': shape = getRay(140,0); break; } tokenOffsetLeft = 70; tokenOffsetTop = 70; switch(type){ case 'CircleContr': case 'RctnglContr': case 'SquareContr': case 'ConeslContr': case 'DthRayContr': token = createCenter({ obj: token, offsetLeft: tokenOffsetLeft, offsetTop: tokenOffsetTop, controlList: controlList }); break; } switch(type){ case 'CircleToken': case 'CircleContr': contrlOffsetLeft = token.get('left'); contrlOffsetTop = token.get('top') - (shape.box.height / 2); distance = lineDistance( {x: contrlOffsetLeft, y: contrlOffsetTop}, {x: tokenOffsetLeft, y: tokenOffsetTop} ); measurement = measurementValue(page,'circle',distance * 2); break; case 'RctnglToken': case 'RctnglContr': case 'SquareToken': case 'SquareContr': contrlOffsetLeft = token.get('left') - (shape.box.width / 2); contrlOffsetTop = token.get('top') + (shape.box.height / 2); measurement = measurementValue(page,'rectangle',shape.box.width,shape.box.height); break; case 'ConeslToken': case 'ConeslContr': contrlOffsetLeft = token.get('left'); contrlOffsetTop = token.get('top') + 140; measurement = measurementValue(page,'cone',140,30); break; case 'DthRayToken': case 'DthRayContr': contrlOffsetLeft = token.get('left'); contrlOffsetTop = token.get('top') + 140; measurement = measurementValue(page,'ray',140); break; } control = createControl({ obj: token, left: contrlOffsetLeft, top: contrlOffsetTop, controlList: controlList }); switch(type){ case 'CircleToken': case 'CircleContr': case 'RctnglToken': case 'RctnglContr': case 'SquareToken': case 'SquareContr': control.set({ name: measurement }); shape = createShape({ token: token, controlledby: control.get('id') + ',' + token.get('id'), left: token.get('left'), top: token.get('top'), width: shape.box.width, height: shape.box.height, path: shape.path }); break; case 'ConeslToken': case 'ConeslContr': control.set({ name: measurement, rotation: 30 }); shape = createShape({ token: token, controlledby: control.get('id') + ',' + token.get('id'), left: token.get('left') + shape.center.x, top: token.get('top') + shape.center.y, width: shape.box.width, height: shape.box.height, path: shape.path }); break; case 'DthRayToken': case 'DthRayContr': control.set({ name: measurement }); shape = createShape({ token: token, controlledby: control.get('id') + ',' + token.get('id'), left: token.get('left') + shape.center.x, top: token.get('top') + shape.center.y, width: shape.box.width, height: shape.box.height, path: shape.path }); break; } state.AOEdrawer.pathData[control.get('id')] = { type: type, token: token.get('id'), control: control.get('id'), path: shape.get('id'), color: stroke }; //TEMP state.AOEdrawer.preLeftTop[token.get('id')] = token.get('left') + ',' + token.get('top'); //TEMP controlIndex[control.get('id')] = control.get('id'); controlIndex[shape.get('id')] = control.get('id'); state.AOEdrawer.controlPointMiddl[token.get('id')] = state.AOEdrawer.controlPointMiddl[token.get('id')] || {}; state.AOEdrawer.controlPointMiddl[token.get('id')][control.get('id')] = [control.get('id')]; setTimeout(function() {toBack(shape); }, 300); }, updateShape = function(action,obj,key,type,centerMove) { var token,control,shape,path,distance,page = getObj('page', obj.get('pageid')), measurement,spin,angle,lastx,lasty,controlList; control = getObj('graphic', key.control); if( undefined === control ) {return; } token = getObj('graphic', key.token); lastx = parseInt(state.AOEdrawer.preLeftTop[token.get('id')].split(',')[0]); lasty = parseInt(state.AOEdrawer.preLeftTop[token.get('id')].split(',')[1]); if( undefined === token ) {return; } path = getObj('path', key.path); if( undefined === path ) {return; } stroke = path.get('stroke'); switch(type){ case 'ConeslToken': case 'ConeslContr': spin = (Math.round(control.get('rotation')/5)*5)%360 + (control.get('rotation')<0 ? 360 : 0); if( spin < 5 ){spin = 5; } if( spin > 175 ){spin = 175; } if( true === centerMove ){ control.set({ left: control.get('left') + token.get('left') - lastx, top: control.get('top') + token.get('top') - lasty, width: controlWidth, height: ControlHeight, rotation: spin }); }else{ control.set({ left: control.get('left'), top: control.get('top'), width: controlWidth, height: ControlHeight, rotation: spin }); } break; case 'DthRayToken': case 'DthRayContr': if( true === centerMove ){ control.set({ left: control.get('left') + token.get('left') - lastx, top: control.get('top') + token.get('top') - lasty, width: controlWidth, height: ControlHeight }); }else{ control.set({ left: control.get('left'), top: control.get('top'), width: controlWidth, height: ControlHeight }); } break; case 'CircleToken': case 'RctnglToken': case 'SquareToken': case 'CircleContr': case 'RctnglContr': case 'SquareContr': control.set({ left: control.get('left') + token.get('left') - path.get('left'), top: control.get('top') + token.get('top') - path.get('top'), rotation: 0, width: controlWidth, height: ControlHeight }); break; } switch(type){ case 'CircleToken': case 'CircleContr': distance = lineDistance( {x: control.get('left'), y: control.get('top')}, {x: token.get('left'), y: token.get('top')} ); measurement = measurementValue(page,'circle',distance * 2); break; case 'RctnglToken': case 'RctnglContr': measurement = measurementValue(page,'rectangle', Math.abs(control.get('left') - token.get('left')), Math.abs(control.get('top') - token.get('top')) ); break; case 'SquareToken': case 'SquareContr': measurement = measurementValue(page,'rectangle', Math.max(Math.abs(control.get('left') - token.get('left')),Math.abs(control.get('top') - token.get('top'))), Math.max(Math.abs(control.get('left') - token.get('left')),Math.abs(control.get('top') - token.get('top'))) ); break; case 'ConeslToken': case 'ConeslContr': angle = checkAngle(token.get('left'),token.get('top'),control.get('left'),control.get('top')); distance = lineDistance( {x: control.get('left'), y: control.get('top')}, {x: token.get('left'), y: token.get('top')} ); measurement = measurementValue(page,'cone',distance,spin); break; case 'DthRayToken': case 'DthRayContr': angle = checkAngle(token.get('left'),token.get('top'),control.get('left'),control.get('top')); distance = lineDistance( {x: control.get('left'), y: control.get('top')}, {x: token.get('left'), y: token.get('top')} ); measurement = measurementValue(page,'ray',distance); break; } control.set('name', measurement); delete controlIndex[path.get('id')]; path.remove(); switch(type){ case 'CircleToken': case 'CircleContr': shape = getCircle(distance * 2); break; case 'RctnglToken': case 'RctnglContr': shape = getSquare(Math.abs(control.get('left') - token.get('left')) * 2, Math.abs(control.get('top') - token.get('top')) * 2 ); break; case 'SquareToken': case 'SquareContr': shape = getSquare( Math.max(Math.abs(control.get('left') - token.get('left')) * 2,Math.abs(control.get('top') - token.get('top')) * 2), Math.max(Math.abs(control.get('left') - token.get('left')) * 2,Math.abs(control.get('top') - token.get('top')) * 2) ); break; case 'ConeslToken': case 'ConeslContr': shape = getCone(distance,spin,angle + 90); break; case 'DthRayToken': case 'DthRayContr': shape = getRay(distance,spin); break; } switch(type){ case 'ConeslToken': case 'ConeslContr': shape = createShape({ token: token, controlledby: control.get('id') + ',' + token.get('id'), left: token.get('left') + shape.center.x, top: token.get('top') + shape.center.y, width: shape.box.width, height: shape.box.height, path: shape.path }); break; case 'CircleToken': case 'CircleContr': case 'RctnglToken': case 'RctnglContr': case 'SquareToken': case 'SquareContr': shape = createShape({ token: token, controlledby: control.get('id') + ',' + token.get('id'), left: token.get('left'), top: token.get('top'), width: shape.box.width, height: shape.box.height, path: shape.path }); break; case 'DthRayToken': case 'DthRayContr': shape = createShape({ token: token, controlledby: control.get('id') + ',' + token.get('id'), left: ((token.get('left') + control.get('left'))/2), top: ((token.get('top') + control.get('top'))/2), width: shape.box.width, height: shape.box.height, path: shape.path, rotation: angle + 90 }); break; } //TEMP state.AOEdrawer.preLeftTop[token.get('id')] = token.get('left') + ',' + token.get('top'); //TEMP controlIndex[shape.get('id')] = control.get('id'); state.AOEdrawer.pathData[control.get('id')].path = shape.get('id'); setTimeout(function() {toBack(shape); }, 300); }, deleteShape = function(obj,key,type) { var control = getObj('graphic', key.control), token = getObj('graphic', key.token), path = getObj('path', key.path); if ( undefined !== control ) { delete state.AOEdrawer.pathData[controlIndex[control.get('id')]]; delete controlIndex[control.get('id')]; control.remove(); } if ( undefined !== path ) { delete state.AOEdrawer.pathData[controlIndex[path.get('id')]]; delete controlIndex[path.get('id')]; path.remove(); } switch(type){ case 'CircleContr': case 'RctnglContr': case 'SquareContr': case 'ConeslContr': case 'DthRayContr': if ( undefined !== token ) { delete state.AOEdrawer.controlPointMiddl[token.get('id')]; token.remove(); } break; default: delete state.AOEdrawer.controlPointMiddl[token.get('id')][control.get('id')]; break; } delete controlIndex[control.get('id')]; }, getInput = function(value) { switch(value.icon){ case '001': createNewShape(value.token,value.icon,'CircleToken'); break; case '002': createNewShape(value.token,value.icon,'CircleContr'); break; case '003': createNewShape(value.token,value.icon,'RctnglToken'); break; case '004': createNewShape(value.token,value.icon,'RctnglContr'); break; case '005': createNewShape(value.token,value.icon,'SquareToken'); break; case '006': createNewShape(value.token,value.icon,'SquareContr'); break; case '007': createNewShape(value.token,value.icon,'ConeslToken'); break; case '008': createNewShape(value.token,value.icon,'ConeslContr'); break; case '009': createNewShape(value.token,value.icon,'DthRayToken'); break; case '010': createNewShape(value.token,value.icon,'DthRayContr'); break; } }, change = function(obj,centerMove) { var data; if ( undefined === controlIndex[obj.get('id')] ) {return; } data = state.AOEdrawer.pathData[controlIndex[obj.get('id')]]; switch(data.type){ case 'CircleToken': updateShape('change',obj,data,'CircleToken',centerMove); break; case 'CircleContr': updateShape('change',obj,data,'CircleContr',centerMove); break; case 'RctnglToken': updateShape('change',obj,data,'RctnglToken',centerMove); break; case 'RctnglContr': updateShape('change',obj,data,'RctnglContr',centerMove); break; case 'SquareToken': updateShape('change',obj,data,'SquareToken',centerMove); break; case 'SquareContr': updateShape('change',obj,data,'SquareContr',centerMove); break; case 'ConeslToken': updateShape('change',obj,data,'ConeslToken',centerMove); break; case 'ConeslContr': updateShape('change',obj,data,'ConeslContr',centerMove); break; case 'DthRayToken': updateShape('change',obj,data,'DthRayToken',centerMove); break; case 'DthRayContr': updateShape('change',obj,data,'DthRayContr',centerMove); break; } }, handleGraphicChangeLeftTopSpin = function(obj) { var control,hasControl = false; if( objectNodeIc === obj.get('imgsrc') ) { change(obj,false); setTimeout(function() {toFront(obj); }, 100); return; } _.each(state.AOEdrawer.controlPointMiddl[obj.get('id')], function(cId) { control = getObj('graphic', cId); if ( undefined !== control ){ change(control,true); hasControl = true; setTimeout(function() {toFront(control); }, 100); } }); if ( true === hasControl ){ if( objectCenter === obj.get('imgsrc') ) { obj.set({width: controlWidth, height: ControlHeight, rotation: 0 }); } setTimeout(function() {toFront(obj); }, 100); } }, handlePathChange = function(obj) { var control; control = getObj('graphic', controlIndex[obj.get('id')]); if ( undefined !== control ){change(control,false); } }, detroy = function(obj) { var data; if ( undefined === controlIndex[obj.get('id')] ) {return; } data = state.AOEdrawer.pathData[controlIndex[obj.get('id')]]; switch(data.type){ case 'CircleToken': deleteShape(obj,data,'CircleToken'); break; case 'CircleContr': deleteShape(obj,data,'CircleContr'); break; case 'RctnglToken': deleteShape(obj,data,'RctnglToken'); break; case 'RctnglContr': deleteShape(obj,data,'RctnglContr'); break; case 'SquareToken': deleteShape(obj,data,'SquareToken'); break; case 'SquareContr': deleteShape(obj,data,'SquareContr'); break; case 'ConeslToken': deleteShape(obj,data,'ConeslToken'); break; case 'ConeslContr': deleteShape(obj,data,'ConeslContr'); break; case 'DthRayToken': deleteShape(obj,data,'DthRayToken'); break; case 'DthRayContr': deleteShape(obj,data,'DthRayContr'); break; } delete state.AOEdrawer.pathData[controlIndex[obj.get('id')]]; }, handleGraphicDestroy = function(obj) { var control; if( objectNodeIc === obj.get('imgsrc') ) {detroy(obj); } _.each(state.AOEdrawer.controlPointMiddl[obj.get('id')], function(cId) { control = getObj('graphic', cId); if ( undefined !== control ){detroy(control); } }); delete state.AOEdrawer.controlPointMiddl[obj.get('id')]; }, handleGraphicChange = function(obj) { var controlledby = obj.get('controlledby').split(','); if( 'NEW' === controlledby[0] ) { controlledby.shift(); obj.set({ controlledby: controlledby.toString(), left: obj.get('left') + 0.1 }); setTimeout(function() {toFront(obj); }, 100); } }, registerEventHandlers = function(){ on('change:graphic', handleGraphicChange ); on("change:graphic:lastmove", handleGraphicChangeLeftTopSpin); on("change:graphic:rotation", handleGraphicChangeLeftTopSpin); on("change:path", handlePathChange); on("destroy:path", handlePathChange); on('destroy:graphic', handleGraphicDestroy); }; return { RegisterEventHandlers: registerEventHandlers, Input: getInput }; }()), // ~~~> Place Spel Effect <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~> Menu <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ menu = (function(){ var createNewMenuIcon = function(obj,character) { var menuIcon = createObj('graphic', { pageid: obj.get('pageid'), imgsrc: keyIndex['000'], left: obj.get('left') - (obj.get('width') / 2) + 10, top: obj.get('top') + (obj.get('height') / 2) - 10, width: controlWidth, height: ControlHeight, layer: obj.get('layer'), isdrawing: true, controlledby: 'NEW,' + character.get('controlledby'), light_hassight: true, light_losangle: 0, light_radius: 1 }); state.AOEdrawer.preLeftTop[menuIcon.get('id')] = menuIcon.get('left') + ',' + menuIcon.get('top'); menuIndex[menuIcon.get('id')] = obj.get('id'); state.AOEdrawer.tokenMenu[obj.get('id')] = [menuIcon.get('id')]; setTimeout(function() {toFront(menuIcon); }, 300); return menuIcon; }, setMenuIcon = function(menuItem,obj) { menuItem.set({ left: obj.get('left') - (obj.get('width') / 2) + 10, top: obj.get('top') + (obj.get('height') / 2) - 10, rotation: 0, width: controlWidth, height: ControlHeight, layer: obj.get('layer') }); state.AOEdrawer.preLeftTop[menuItem.get('id')] = menuItem.get('left') + ',' + menuItem.get('top'); setTimeout(function() {toFront(menuItem); }, 300); }, createNewSubMenu = function(token,imgsrc,left,top,controlledby) { var submenu = createObj('graphic', { pageid: token.get('pageid'), imgsrc: imgsrc, left: token.get('left')+(token.get('width')/2) + left, top: token.get('top')-(token.get('height')/2) + top, width: controlWidth, height: ControlHeight, layer: token.get('layer'), isdrawing: true, controlledby: controlledby, light_hassight: true, light_losangle: 0, light_radius: 1 }); setTimeout(function() {toFront(submenu); }, 300); return submenu; }, deleteSubMenu = function(token) { if( undefined === state.AOEdrawer.tokenSubMenu[token.get('id')] ) { return; } _.each(state.AOEdrawer.tokenSubMenu[token.get('id')], function(sm) { if( undefined !== getObj('graphic', sm) ){ delete subMenuIndex[sm]; getObj('graphic', sm).remove(); } }); delete state.AOEdrawer.tokenSubMenu[token.get('id')]; }, subMenu = function(token) { var submenu, character = getObj('character', token.get('represents')),subMenuArray = []; if( undefined === token) { return; } if( undefined === character ) { return; } character = 'NEW,' + character.get('controlledby'); submenu = createNewSubMenu(token,keyIndex['001'], 10,18,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['002'], 10,48,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['003'], 35,18,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['004'], 35,48,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['005'], 60,18,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['006'], 60,48,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['007'], 90,18,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['008'], 90,47,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['009'],110,18,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); submenu = createNewSubMenu(token,keyIndex['010'],110,48,character); subMenuArray.push(submenu.get('id')); subMenuIndex[submenu.get('id')] = token.get('id'); state.AOEdrawer.tokenSubMenu[token.get('id')] = subMenuArray; }, handleSubMenuDestroy = function(obj) { var token,key; key = iconIndex[obj.get('imgsrc')]; token = getObj('graphic', subMenuIndex[obj.get('id')]); if( undefined !== token ) { deleteSubMenu(token); } }, handleSubMenuChange = function(obj) { var controlledby = obj.get('controlledby').split(','),token; if( 'NEW' === controlledby[0] ) { controlledby.shift(); obj.set('controlledby', controlledby.toString()); return; } token = getObj('graphic', subMenuIndex[obj.get('id')]); if( undefined !== token ) { deleteSubMenu(token); } placeEffect.Input({ token: token, icon: iconIndex[obj.get('imgsrc')] }); }, handleTokenChange = function(obj) { var menuItem, character = getObj('character', obj.get('represents')); menuItem = getObj('graphic', state.AOEdrawer.tokenMenu[obj.get('id')]); if( undefined === menuItem ) { delete state.AOEdrawer.tokenMenu[obj.get('id')]; delete state.AOEdrawer.preLeftTop[obj.get('id')]; delete menuIndex[obj.get('id')]; }else{ if ( menuItem.get('imgsrc') === keyIndex['000'] ){ setMenuIcon(menuItem,obj); deleteSubMenu(obj); } return; } if( undefined !== menuItem ) { return; } if ( undefined === character ) { return; } createNewMenuIcon(obj,character); deleteSubMenu(obj); }, handleMenuChange = function(obj) { var controlledby = obj.get('controlledby').split(','),token; if( 'NEW' === controlledby[0] ) { controlledby.shift(); obj.set('controlledby', controlledby.toString()); return; } //deltaX = Math.abs(state.AOEdrawer.preLeftTop[obj.get('id')].split(',')[0] - obj.get('left')); //deltaY = Math.abs(state.AOEdrawer.preLeftTop[obj.get('id')].split(',')[1] - obj.get('top')); token = getObj('graphic', menuIndex[obj.get('id')] ); if( undefined === token ) { delete state.AOEdrawer.tokenMenu[menuIndex[obj.get('id')]]; delete menuIndex[obj.get('id')]; delete state.AOEdrawer.preLeftTop[obj.get('id')]; obj.remove(); return; } setMenuIcon(obj,token); if( undefined !== state.AOEdrawer.tokenSubMenu[token.get('id')] ) { deleteSubMenu(token); }else{ //if( (deltaX > 20 || deltaY > 20) ) { // return; //}else{ // if( (deltaX > 0 && deltaY > 0) ) { subMenu(token,obj); // } //} } }, handleMenuDestroy = function(obj) { var token, character; if ( undefined === menuIndex[obj.get('id')] ) { return; } token = getObj('graphic', menuIndex[obj.get('id')]); delete menuIndex[obj.get('id')]; delete state.AOEdrawer.preLeftTop[obj.get('id')]; if( undefined === token ) { return; } delete state.AOEdrawer.tokenMenu[token.get('id')]; character = getObj('character', token.get('represents')); if ( undefined === character ) { return; } if( undefined === state.AOEdrawer.onForCharacter[token.get('represents')] && false === state.AOEdrawer.config.defaultOn ) { return; } createNewMenuIcon(token,character); deleteSubMenu(token); }, handleTokenDestroy = function(obj) { var menuIcon = getObj('graphic', state.AOEdrawer.tokenMenu[obj.get('id')]); if( undefined !== menuIcon ){ delete menuIndex[menuIcon.get('id')]; delete state.AOEdrawer.preLeftTop[menuIcon.get('id')]; menuIcon.remove(); } delete state.AOEdrawer.tokenMenu[obj.get('id')]; delete state.AOEdrawer.preLeftTop[obj.get('id')]; delete menuIndex[obj.get('id')]; deleteSubMenu(obj); }, handleGraphicDestroy = function(obj) { if( obj.get('imgsrc') === keyIndex['000'] ) { handleMenuDestroy(obj); return; } if( undefined !== iconIndex[obj.get('imgsrc')] ) { handleSubMenuDestroy(obj); } if( undefined !== state.AOEdrawer.tokenMenu[obj.get('id')] ) { handleTokenDestroy(obj); return; } }, handleGraphicChange = function(obj) { var character = getObj('character', obj.get('represents')); if( obj.get('imgsrc') === keyIndex['000'] ) { handleMenuChange(obj); return; } if( undefined !== iconIndex[obj.get('imgsrc')] ) { handleSubMenuChange(obj); } if ( undefined === character ) { return; } if( undefined !== state.AOEdrawer.onForCharacter[character.get('id')] ) { handleTokenChange(obj); } if( true === state.AOEdrawer.config.defaultOn ) { handleTokenChange(obj); } }, toggleMenu = function(obj) { var token = state.AOEdrawer.tokenMenu[obj.get('id')], character = getObj('character', obj.get('represents')), menuIcon; if( undefined === token ) { if ( undefined === character ) { return; } state.AOEdrawer.onForCharacter[obj.get('represents')] = obj.get('represents'); createNewMenuIcon(obj,character); }else{ menuIcon = getObj('graphic',state.AOEdrawer.tokenMenu[obj.get('id')] ); if( undefined !== menuIcon ){ delete menuIndex[menuIcon.get('id')]; delete state.AOEdrawer.preLeftTop[menuIcon.get('id')]; menuIcon.remove(); } delete state.AOEdrawer.onForCharacter[obj.get('represents')]; delete state.AOEdrawer.tokenMenu[obj.get('id')]; } }, getInput = function(input) { switch(input.action){ case 'toggleMenu': if( undefined !== input.selected ) { toggleMenu(input.selected); } break; } }, registerEventHandlers = function(){ on('change:graphic', handleGraphicChange ); on('destroy:graphic', handleGraphicDestroy); }; return { RegisterEventHandlers: registerEventHandlers, Input: getInput }; }()), // ~~~> Menu <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~> inputManagement <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Checked inputManagement = (function() { var handleInput = function (msg) { var message = _.clone(msg); if ( 'api' !== message.type || '!aoedrawer' !== message.content.split(/\s+/)[0] ) { return; } switch(message.content.split(/\s+/)[1]) { case 'menu': chatOutput.Input({ action: 'menu', who: message.playerid, gm: playerIsGM(message.playerid) }); break; case 'toggleMenu': if( getObj('graphic', (_.first(message.selected)||{_id:0})._id ) ) { menu.Input({ action: 'toggleMenu', selected: getObj('graphic', (_.first(message.selected)||{_id:0})._id ) }); } break; case 'toggleOnDefault': changeSettings.Input('toggleOnDefault'); chatOutput.Input({ action: 'menu', who: message.playerid, gm: playerIsGM(message.playerid) }); break; //######################################REMOVE //case 'state': // SotSA.CheckState(); //break; //######################################REMOVE default: chatOutput.Input({ action: 'help', who: message.playerid, gm: playerIsGM(message.playerid) }); break; } }, registerEventHandlers = function(){ on('chat:message', handleInput); }; return { RegisterEventHandlers: registerEventHandlers }; }()), // ~~~> inputManagement <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~> On Start <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Checked setup = (function() { var onStart = function() { if( ! _.has(state,'AOEdrawer' ) || state.AOEdrawer.version !== schemaVersion ) { state.AOEdrawer = { version: schemaVersion, config: { defaultOn: slideMenuDefaultOn }, controlPointMiddl: {}, controlPointToken: {}, pathData: {}, charaterSettings: {}, tokenMenu: {}, tokenSubMenu: {}, onForCharacter: {}, preLeftTop: {} }; log('AOEDrawer: Initialize State'); }else{ Object.keys(state.AOEdrawer.tokenMenu).forEach(function(key) { if( undefined === getObj('graphic', key) ){ delete state.AOEdrawer.tokenMenu[key]; } }); Object.keys(state.AOEdrawer.controlPointMiddl).forEach(function(key) { Object.keys(state.AOEdrawer.controlPointMiddl[key]).forEach(function(subkey) { if( undefined === getObj('graphic', subkey) ){ delete state.AOEdrawer.controlPointMiddl[key]; } }); if( undefined === getObj('graphic', key) ){ delete state.AOEdrawer.controlPointMiddl[key]; } }); Object.keys(state.AOEdrawer.pathData).forEach(function(key) { if( undefined === getObj('graphic', key) ){ delete state.AOEdrawer.pathData[key]; } }); Object.keys(state.AOEdrawer.tokenMenu).forEach(function(key) { if( undefined === getObj('graphic', key) ){ delete state.AOEdrawer.tokenMenu[key]; } }); Object.keys(state.AOEdrawer.preLeftTop).forEach(function(key) { if( undefined === getObj('graphic', key) ){ delete state.AOEdrawer.preLeftTop[key]; } }); } _.each(icons, function(icon) { iconIndex[icon.url] = icon.key; keyIndex[icon.key] = icon.url; }); Object.keys(state.AOEdrawer.pathData).forEach(function(key) { controlIndex[state.AOEdrawer.pathData[key].control] = state.AOEdrawer.pathData[key].control; controlIndex[state.AOEdrawer.pathData[key].path] = state.AOEdrawer.pathData[key].control; }); Object.keys(state.AOEdrawer.tokenMenu).forEach(function(key) { menuIndex[state.AOEdrawer.tokenMenu[key]] = key; }); }; return { Start: onStart }; }()), // ~~~> On Start <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~> Register <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Checked registerEventHandlers = function() { setup.Start(); menu.RegisterEventHandlers(); placeEffect.RegisterEventHandlers(); inputManagement.RegisterEventHandlers(); log('AOEDrawer ' + new Date(lastUpdate * 1000) + ' version: ' + version + ' Schema Version: ' + schemaVersion); log('(!aoedrawer help)'); log('(!aoedrawer menu)'); }; // ~~~> Register <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ return { RegisterEventHandlers: registerEventHandlers }; }()); on('ready',function(){ 'use strict'; AOEDrawer.RegisterEventHandlers(); });