Here's a function I use to get seen tokens.
Code: Select all
<!-- getSeenTokens(options,source): json array or object
options (strprop or json object)
pc - 0 any token, 1 - PC only
npc - 0 any token, 1 - NPC only
range - upto this distance in grid units (ie feet, and not grid squares); 0 - any range
self - 0 do not include self, 1 include self
source = source token, defaults to currentToken
This function will get a list of tokenIds based on the current tokens vision
-->
[H, if(argCount()): options = lower(arg(0)); options = "{}"]
[H, if(argCount() >= 2): sourceToken = arg(1); sourceToken = currentToken()]
<!-- verify token is on current map -->
[H: sourceToken = findToken(sourceToken)]
[H: assert(! json.isEmpty(sourceToken),"<b>getSeenTokens(options,source):</b> Token not found on current map.",0)]
<!-- define options locally -->
[H: defaults = json.set("{}","pc",0,"npc",0,"range",0,"self",0)]
[H, if(json.type(options) == "UNKNOWN" && ! json.isEmpty(options)): options = json.fromStrProp(options)]
[H, if(json.isEmpty(options)): options = defaults; options = json.merge(defaults,options)]
[H: varsFromStrProp(json.toStrProp(options))]
<!-- get token ids -->
[H: conditions = "{}"]
[H, if(npc && ! pc): conditions = json.set(conditions,"npc",npc)]
[H, if(! npc && pc): conditions = json.set(conditions,"pc",pc)]
[H, if(range): conditions = json.set(conditions,"range",json.set("{}","token",sourceToken,"upto",range,"distancePerCell",1))]
[H, if(! json.isEmpty(conditions)): tokenIds = getTokens("json",conditions); tokenIds = getTokens("json")]
<!-- exclude self if set -->
[H, if(self), code: {
[H, if(! json.isEmpty(tokenIds)): tokenIds = json.union(tokenIds,json.append("",sourceToken)); tokenIds = json.append("",sourceToken)]
};{
[H, if(! json.isEmpty(tokenIds)): tokenIds = json.difference(tokenIds,json.append("",sourceToken)); tokenIds = "[]"]
}]
<!-- check each id for name and visible -->
[H: targets = "[]"]
[H: hasSight = hasSight()]
[H, if(! hasSight()): setHasSight(1)] <!-- this works for NPC tokens too -->
[H, foreach(tokenId,tokenIds), code: {
[H: canSee = ! json.isEmpty(canSeeToken(tokenId))]
[H, if(canSee): targets = json.append(targets,tokenId)]
}]
[H, if(hasSight != hasSight()): setHasSight(hasSight)]
[H: macro.return = targets]
Here is a macro I use to get distance. It accounts for elevation and token size as well.
Code: Select all
<!-- getRangedDistance(source,target): range -->
[H: source = arg(0)]
[H: target = arg(1)]
<!-- source and target must be defined -->
[H: assert(! json.isEmpty(source) && ! json.isEmpty(target),"<b>getRangedDistance(source,target): range</b> - Source or target not defined.",0)]
<!-- If elevation isnt set then set to 0 -->
[H: source.elevation = getProperty("Elevation",source)]
[H, if(! isNumber(source.elevation)): source.elevation = 0]
[H: target.elevation = getProperty("Elevation",target)]
[H, if(! isNumber(target.elevation)): target.elevation = 0]
<!-- get elevation difference and factor in size. Used big formula for processing speed -->
[H, if(source.elevation != target.elevation), code: {
[H, if(source.elevation < target.elevation): distance.vertical = max(0,target.elevation - (source.elevation + (listFind("Large,Huge,Gargantuan,NA,Colossal",getSize(source)) + 1)*5));
distance.vertical = max(0,source.elevation - (target.elevation + (listFind("Large,Huge,Gargantuan,NA,Colossal",getSize(target)) + 1)*5))]
};{
[H: distance.vertical = 0]
}]
[H, if(! distance.vertical), code: {
[H: totalDistance = getDistance(source,1,target,"ONE_TWO_ONE")]
};{
<!-- count squares, no metric in between -->
[H: distance.direct = getDistance(source,1,target,"ONE_ONE_ONE")]
<!-- get number of diagonal moves -->
[H: horizontal.diagonals = floor((getDistance(source,1,target,"NO_DIAGONALS") - distance.direct)/5)]
<!-- its assumed when changing elevation that you move in a diagonal fashion until at elevation -->
[H: vertical.diagonals = min(distance.direct,distance.vertical)]
<!-- subtract horizontal diags used from vertical diags needed because we can move diag in vert and horizontal direction for same cost -->
[H: extra.diagonals = floor((max(vertical.diagonals,horizontal.diagonals) - horizontal.diagonals)/5)]
<!-- manually calc distance based on number of diags moved (1-2-1) and add the leftover horizonal and vertical distances -->
[H: totalDistance = floor((horizontal.diagonals + extra.diagonals) * 0.5) * 5 + distance.direct + distance.vertical - vertical.diagonals]
}]
[H: macro.return = totalDistance]