Page 2 of 14

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Fri Aug 19, 2016 7:48 am
by lmarkus001
tohavetobe wrote:Is there any tutorials or manuals of this framework?
From this forum category:
http://forums.rptools.net/viewtopic.php?f=53&t=25374

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Thu Aug 25, 2016 3:37 pm
by Oryan77
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!

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Thu Aug 25, 2016 7:20 pm
by Oryan77
Sorry, I have another question that maybe you can help me with.

I just to port over the "Lib:libDnD35Pathfinder" token to my own campaign. I am trying to use the "Elevation" macro from that token.

I think I created all of the proper states needed for that macro. I am able to set an elevation and choose the Elevation Type. The states appear on the token as they should.

The problem is that when I use the macro again to change the elevation, the "numbers" (states) do not get removed like they do in your campaign file. On mine, they stay and the new numbers (states) appear over them. I can keep doing this and the new numbers (states) keep stacking on the old ones. For example:

I set Current Elevation to "100". "100" appears on the token.
I set Current Elevation to "250". The tens and hundredths number (1 and 0) stay on the token, and 2 and 5 appear over them.

Any idea what I have not done correctly to make this work right?

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Thu Aug 25, 2016 10:23 pm
by aliasmask
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.

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Thu Aug 25, 2016 11:04 pm
by Oryan77
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.
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!

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Thu Aug 25, 2016 11:55 pm
by aliasmask
When setting the group name of a state it creates that group if not already there. It's under Campaign Properties, States Tab and field on the right named Group. My original code uses the "Elevations" group.

Here's the code I use.
||| CODE |||

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]

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Fri Aug 26, 2016 12:05 am
by Oryan77
I am not sure what to change in the code since I see the word elevation appearing over and over and I'm not sure which text in the code refers to the state group name and which refers to other important features of the code using the same word elevation.

Is it simply that any line in the code with quotations around the word Elevation the only bit of code referring to the state group named Elevation? So changing just "Elevation" in the code to something like "My States" will work if my states are located in the My States group?

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Fri Aug 26, 2016 5:46 am
by aliasmask
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)]

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Fri Aug 26, 2016 5:06 pm
by Oryan77
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)]
That worked. Easy fix. Thank you.

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Tue Aug 30, 2016 8:38 am
by lmarkus001
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!
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).

The active-mod resizing actually changes weapon damage as well and is more sophisticated.

Given all that, if you still just want to swap the two choices, the campaign macro code would need to change to:

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 + ";"] 

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Tue Aug 30, 2016 4:18 pm
by Oryan77
lmarkus001 wrote: Given all that, if you still just want to swap the two choices, the campaign macro code would need to change to:
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!

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Tue Aug 30, 2016 7:54 pm
by lmarkus001
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.

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Thu Sep 01, 2016 1:31 pm
by Oryan77
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.
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. :P Thank you!

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Wed Sep 07, 2016 10:27 am
by jsharen
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

Re: 91.08 Pathfinder + D&D3.5 Framework NEW!

Posted: Wed Sep 07, 2016 2:46 pm
by aliasmask
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
There's an option in Edit Char that will remove all mods.