Very nice. A few comments: Rather than Array.prototype.forEach, you have access to _.each. While _.each delegates the processing to Array.prototype.forEach if possible, not every browser has it (such as IE8). In that same vein, rather than collecting all of the tokens on the page with findObjs and then iterating over them with forEach or each, you could use filterObjs to do it all in one step. You should include a means to hit tokens which don't represent a character. Many GMs have NPCs which aren't represented by characters, and your targeting would ignore them. If you don't utilize the second point above, you can used Array.prototype.push to append things to an array, rather than i=arr.length;arr[i]=foo; (You can also initialize arrays with simply "[]" instead of "new Array()") An example of the second point (removing comments and debug): var result = filterObjs(function(obj) { if(obj.get('type') != 'graphic' || obj.get('subtype') != 'token' || obj.get('pageid') != pageID) return false; var tokenName = obj.get('name'); var representsID = obj.get('represents'); if (representsID == '' && representingCharactersOnly) return false; var correctDistance = false;
var correctAngle = false;
var correctWidth = false;
var correctCharType = false;
var d = distanceBetweenPoints(x, y, obj.get("left"), obj.get("top")); var thisCharType = 'monster';
var a = getAttrByName(representsID, 'Attitude');
if (a != null) {
thisCharType = a; }
if (d <= distPixels) { correctDistance = true; }
var point_dist = distanceOfPointFromLine(tok.get('left'), tok.get('top'), x, y, x2, y2);
if (point_dist <= (widthPixels / 2)) { correctWidth = true; }
var point_angle = angleFromPointToPointInDegrees(x, y, tok.get('left'), tok.get('top'));
if ((Math.abs(point_angle - direction) < 90 ) || (Math.abs((point_angle - 360) - direction) < 90 )) { correctAngle = true; }
if (charType == thisCharType) { correctCharType = true; }
else if (charType == 'all') { correctCharType = true; }
else if (charType == 'NPC') {
if ((thisCharType != 'PC') && (thisCharType != 'monster')) { correctCharType = true; } }
else if (charType == 'ally') {
if ((thisCharType == 'PC') || (thisCharType == 'helpful') || (thisCharType == 'friendly')) { correctCharType = true; } }
else if (charType == 'enemy') {
if ((thisCharType == 'unfriendly') || (thisCharType == 'hostile') || (thisCharType == 'monster')) { correctCharType = true; } }
return (correctDistance == true) && (correctCharType == true) && (correctAngle == true) && (correctWidth == true); }); The first three lines of the callback are the fail-fast to make the filter equivalent to the findObjs call you would have made -- if the rest of the callback were replaced with "return true", the results set would be the same as your findObjs call. The rest is the content of your iteration over the findObjs result set, except for the bit at the end which added the iteration item to the result array. This version, instead, returns true if the token should be in the result set, or false if it should not. Your functions would then be in the format: function example(...) { // initialize additional variables var result = filterObjs(function(obj) {...}); return result; }