From this forum category:tohavetobe wrote:Is there any tutorials or manuals of this framework?
http://forums.rptools.net/viewtopic.php?f=53&t=25374
Moderators: dorpond, trevor, Azhrei, giliath, Gamerdude, jay, Mr.Ice, lmarkus001
From this forum category:tohavetobe wrote:Is there any tutorials or manuals of this framework?
My ability and knowledge about code is extremely limited. What you said did not make much sense to me other than letting me know to check the name of the state group. I renamed the group my states were in to "Elevation" and that seemed to fix the problem. I'm not really sure how I can name the group to my own group name and still get the code to work. But thanks for getting me this far!aliasmask wrote:In my code, you should get the group the states appear in and loop through setting them to 0 removing them and then set the states needed.
Code: Select all
<!-- changeElevation(): output -->
[H: elevation.start = getProperty("Elevation")]
[H: elevation.states = getProperty("elevation.states")]
[H: elevation.type = getProperty("elevation.type")]
[H, if(! isNumber(elevation.start)): elevation.value = 0; elevation.value = elevation.start]
[H, if(! isNumber(elevation.states)): elevation.states = 0]
[H: elevationTypes = ",Fly,AirWalk,Levitate,Climb,Burrow,Swim,Above,Below"]
[H: type.index = max(0,listFind(elevationTypes,elevation.type))]
[H: abort(input(
strformat('elevation.input|%{elevation.value}|Set Elevation|TEXT'),
strformat('elevation.type|%{elevationTypes}|Set Elevation Type|LIST|VALUE=STRING SELECT=%{type.index}'),
"output.secret|0|Secret Output|CHECK"
))]
<!-- error checking -->
[H, if(! isNumber(elevation.input)): elevation.input = 0]
<!-- enforce 5ft increments -->
[H: elevation.new = floor(elevation.input/5)*5]
[H, if(elevation.type == ""): elevation.states = 0; elevation.states = 1]
[H, if(! elevation.states && elevation.new == 0): elevation.type = ""]
<!-- update elevation based on new elevation and elevation type, ie underground is negative -->
[H: limit = 0]
[H, if(listContains("Burrow,Below",elevation.type)): limit = -5]
[H, if(elevation.type == "Above"): limit = 5]
[H, if(listContains("Burrow,Swim,Below",elevation.type)): elevation.new = min(limit,elevation.new); elevation.new = max(limit,elevation.new)]
<!-- clear elevation states -->
[H: newStates = getTokenStates("json","Elevations")]
[H, foreach(state,newStates): setState(state,0)]
<!-- set states -->
[H, if(elevation.states), code: {
[H: setState("Elevation"+elevation.type,1)]
[H: setState("ElevationBG",1)]
<!-- convert elevation to state name -->
[H: elevation.string = max(-95,min(995,elevation.new))]
[H, if(elevation.string < 0): setState("negative",1)]
[H: elevation.string = abs(elevation.string)]
[H: elevation.100 = floor(elevation.string / 100)]
[H: elevation.10 = floor((elevation.string - elevation.100 * 100)/10)]
[H: elevation.1 = elevation.string - (elevation.100 * 100) - (elevation.10 * 10)]
[H, if(elevation.100), code: {
[H: setState("e"+elevation.100+"__",1)]
[H: setState("e_"+elevation.10+"_",1)]
[H: setState("e__"+elevation.1,1)]
};{
[H, if(elevation.10): setState("e_"+elevation.10+"_",1)]
[H: setState("e__"+elevation.1,1)]
}]
};{}]
[H, if(! elevation.states && elevation.new == 0): elevation.type = ""]
<!-- set elevation value -->
[H: setProperty("Elevation",elevation.new)]
[H: setProperty("elevation.states",elevation.states)]
[H: setProperty("elevation.type",elevation.type)]
<!-- output elevation changes -->
[H: tokenImage = am.tokenImageLink(currentToken())]
[H: output = strformat('
<table style="border-spacing:0px;border-style:solid;border-color:black;border-width:1pt;padding:0px">
<tr>
<td width="34" style="padding:0px">%{tokenImage}</td>
<td width="250" style="background-color:aqua;padding:0px 5px 2px 5px;">%{token.name} (<b>%{elevation.type}</b>): Elevation changed from %{elevation.start} to %{elevation.new}.</td>
</tr>
</table>
')]
[H, if(output.secret), code: {
[H: targets = am.getPlayerGroups("owner,gm")]
[H, if(json.isEmpty(targets)): targets = "all")]
[H: broadcast(output,targets)]
};{
[H: broadcast(output)]
}]
Code: Select all
<!-- tokenImageLink(tokenId): imageLink
tokenId - Can be id or name of token
imageLink - small image of token that displays info about token in tooltip.
Clicking link selects token. Clicking link of selected token moves view to token.
This function will create an image link with token info in tooltip and can select token or move to using link.
-->
[H: tokenId = arg(0)]
[H: current = currentToken()]
[H: switchToken(tokenId)]
[H: isOnMap = findToken(current)]
[H, if(json.isEmpty(isOnMap)): t.image = getImage(current); t.image = getTokenImage()]
[H, if(getPropertyType(current) == getPropertyType(tokenId) && getPropertyType(current) == "Pathfinder"), code: {
[H: t.ac = getProperty("AC")]
[H: t.tactical = getProperty("sheet.moveReach")]
[H: t.distance = distanceStatSheet(tokenId)]
<!-- Calc health without revealing hit points -->
[H: effectiveHP = getProperty("HP") + getProperty("HPtemp") - getProperty("HPNonLethalDMG")]
[H: effectiveMaxHP = getProperty("HPmax") + getProperty("HPtemp")]
[H, if(! json.isEmpty(effectiveHP)): percentHP = floor(effectiveHP/effectiveMaxHP*100); percentHP = 100]
[H: healthLevels = "-1,0,9,50,79,99,100"]
[H: healthNames = "Unconscious,Staggered,Frail,Wounded,Battered,Bruised,Unharmed"]
[H: healthNames = "Unconscious,Staggered,Frail (0-9%),Wounded (10-50%),Battered (51-80%),Bruised (81-100%),Unharmed"]
[H: healthStyles = "background-color:black;color:#FF4500;border-color:#FF4500;, background-color:gray;color:black;border-color:black;, background-color:red;color:white;border-color:black;, background-color:orange;color:black;border-color:black;, background-color:yellow;color:black;border-color:black;, background-color:#90EE90;color:black;border-color:black;, background-color:white;color:black;border-color:black;"]
<!-- Get current HP level -->
[H: index = 0]
[H: isHigher = if(percentHP > listGet(healthLevels,index) && listCount(healthLevels) > index +1,1,0)]
[H, while(isHigher), code: {
[H: index = index + 1]
[H: isHigher = if(percentHP > listGet(healthLevels,index) && listCount(healthLevels) > index +1,1,0)]
}]
[H: healthName = listGet(healthNames,index)]
[H: healthStyle = listGet(healthStyles,index)]
[H: col1 = "text-align:right;padding:0px 5px 0px 5px;font-weight:bold;"]
[H: col2 = "padding:0px 5px 0px 0px;"]
<!-- Create Tooltip text -->
[H: tokenData = json.append("",
strformat('
<table style="border-spacing:0px;padding:0px;">
<tr style="border-width:2px;border-style:solid;%{healthStyle}">
<td style="%{col1}">Status:</td>
<td style="%{col2}font-weight:bold;padding-bottom:2px;" NOWRAP>%{healthName}</td>
</tr>'),
strformat('
<tr>
<td style="%{col1}">Name:</td>
<td style="%{col2}">%{token.name}</td>
</tr>')
)]
[H, if(! json.isEmpty(t.ac)): tokenData = json.append(tokenData,strformat('<tr><td style="%{col1}">AC/TH/FF (CMD/FF):</td><td style="%{col2}">%{t.ac}</td></tr>'))]
[H, if(! json.isEmpty(t.tactical)): tokenData = json.append(tokenData,strformat('<tr><td style="%{col1}">Tactical:</td><td style="%{col2}">%{t.tactical}</td></tr>'))]
[H, if(! json.isEmpty(t.distance)): tokenData = json.append(tokenData,strformat('<tr><td style="%{col1}">Distance:</td><td style="%{col2}">%{t.distance}</td></tr>'))]
[H: tokenData = json.toList(tokenData,"")+"</table>"]
[H: tooltip = strformat('<html><body style="background-color:white;"><table style="font-size:14pt;"><tr valign="top"><td><img src="%{t.image}" width="100" height="100" /></td><td>%{tokenData}</td></tr></table></body></html>')]
[H: tooltip = replace(tooltip,'"',""")]
[H: thisLib = getMacroLocation()]
[H: imageLink = strformat('<a href="macro://gotoSelect@%{thisLib}/none/%{tokenId}?"><img border="0" src="%{t.image}" alt="%{tooltip}" width="30" height="30" /></a>')]
};{
[H: imageLink = strformat('<img src="%{t.image}" alt="%{token.name}" width="30" height="30" />')]
}]
[H: switchToken(current)]
[H: macro.return = imageLink]
Code: Select all
<!-- getPlayerGroups(targets,token)
targets - (default to all) A list or json of player names and/or groups who will see chatText.
* all - all players (keywords are case sensitive)
* owner - anyone who owns the token. token must be valid and on current map
* other - anyone who doesn't own token. token must be valid and on current map
* gm - only gm players
* -gm - anyone but the gm
* self - only displayed to self
* -self - display to all other players
(Note: when posting multiple versions of the same output, using owner and other is most common)
token - (default is currentToken) Specify owned token to post as. If currentToken is valid, but "" is passed, then chatText
is posted as the player.
Return players names based on target groups.
-->
[H, if(argCount() >= 1): targets = arg(0); targets = "all"]
[H, if(argCount() >= 2): token = arg(1); token = currentToken()]
<!-- validate token is on current map -->
[H: tokenId = findToken(token)]
[H, if(! json.isEmpty(tokenId)), code: {
[H: tokenName = getName(tokenId)]
[H: tokenImage = getImage(tokenId)]
};{}]
<!-- parse list of targets in to list of players names -->
[H, if(json.type(targets) == "UNKNOWN"): targets = json.fromList(targets)]
[H: players.all = getAllPlayerNames("json")]
[H: players.gm = json.get(getInfo("server"),"gm")]
[H: player.self = json.append("",getPlayerName())]
[H, if(json.isEmpty(tokenId)), code: {
[H: players.owner = json.union(players.gm,players.self)]
[H: players.other = json.difference(players.all,players.owner)]
};{
[H, if(isOwnedByAll(tokenId)), code: {
[H: players.owner = players.all]
[H: players.other = "[]"]
};{
[H: players.owner = getOwners("json",tokenId)]
[H: players.other = json.difference(players.all,players.owner)]
}]
}]
<!-- get player names based on groups -->
[H: targetNames = "[]"]
[H, if(json.isEmpty(targets)), code: {
[H: targetNames = players.all]
};{
[H, if(json.contains(targets,"all")): targetNames = json.union(targetNames,players.all)]
[H, if(json.contains(targets,"gm")): targetNames = json.union(targetNames,players.gm)]
[H, if(json.contains(targets,"self")): targetNames = json.union(targetNames,players.self)]
[H, if(json.contains(targets,"owner")): targetNames = json.union(targetNames,players.owner)]
[H, if(json.contains(targets,"other")): targetNames = json.union(targetNames,players.other)]
[H, if(json.contains(targets,"-gm")): targetNames = json.difference(targetNames,players.gm)]
[H, if(json.contains(targets,"-self")): targetNames = json.difference(targetNames,player.self)]
[H: targets = json.difference(targets,json.append("","all","gm","self","owner","other","-gm","-self"))]
[H, if(! json.isEmpty(targets)): targetNames = json.intersection(players.all,json.union(targetNames,targets))]
}]
[H: macro.return = targetNames]
Code: Select all
<!-- clear elevation states -->
[H: newStates = getTokenStates("json","Elevations")]
[H, foreach(state,newStates): setState(state,0)]
That worked. Easy fix. Thank you.aliasmask wrote:These are the relevant lines since your problem was with clearing the existing elevation states.:
Code: Select all
<!-- clear elevation states --> [H: newStates = getTokenStates("json","Elevations")] [H, foreach(state,newStates): setState(state,0)]
First of all, the Creature Size macro is to permanently resize a D&D3.5 creature. It is older code. I used it to scale a D&D3.5 creature as a GM as it permanently changes the Strength, Dexterity, Constitution of the creature (and changes the deprecated Natural Armor value).Oryan77 wrote:I have been trying to do this for hours now. I give up.
I have duplicated the "Creature Size" macro on the campaign window from this framework.
All I want to do is edit this duplicate macro and reverse the order of the radial buttons so that "Reduced" works on the left side and "Enlarged" works on the right side.
I don't want to mess with the "LibEnlargeReduce" macro on the lib token though because I still want to keep the original "Creature Size" macro working as-is.
All I seem to keep doing is making both radial buttons either "enlarge" the token or both will "reduce" the token. I can't seem to just flip them around.
Can you help me out here? Thanks!
Code: Select all
/gm
[H: success = input(
"pMod|Reduced,Enlarged|Size Change -- Selected targets are|Radio|ORIENT=H"
)]
[H: abort(success)]
[H: pMod = if(pMod, 0, 1)]
[H: modType = 1 ]
[MACRO("LibEnlargeReduce@Lib:libDnD35Pathfinder"): "Shrink=" + pMod +"; modType=" + modType + ";"]
That is exactly what I needed. Thanks. I am using it for my VTT campaign which does not use the robust character sheet and combat calculations. I just needed a convenient way to resize a token as if using the Enlarge/Reduce Person spells. This works perfectly for that. Thanks again!lmarkus001 wrote: Given all that, if you still just want to swap the two choices, the campaign macro code would need to change to:
Oh it works fine for what I am using it for. I just need the token to increase/decrease to the next size category, which this does. I don't know enough about coding to create it myself. I don't use the character sheet and stat adjustments in your framework. So this macro may be overkill, but the resizing works and I get no errors. So it seems good enough to me. Thank you!lmarkus001 wrote:Actually what it does NOT do is Enlarge/Reduce per the spells. The increase/decrease from these are much greater as they are the values used for scaling the size of a creature per the monster manual.
There's an option in Edit Char that will remove all mods.jsharen wrote:Lindsay,
How hard would it be to add a clear mod's button? That just simply removes all active mods.
We find ourselves doing this regularly, and a simple button would be a lot smoother than having to uncheck every mod individually. Usually when we end a combat, and go into resting.
Cheers,
Jared