91.08 Pathfinder + D&D3.5 Framework

Discussion concerning lmarkus' campaign framework for D&D3.x and Pathfinder.

Moderators: dorpond, trevor, Azhrei, giliath, Gamerdude, jay, Mr.Ice, lmarkus001

Forum rules
Discussion regarding lmarkus001's framework only. Other posts deleted without notice! :)
Post Reply
Elorebaen
Dragon
Posts: 365
Joined: Sat Dec 22, 2007 5:37 pm

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

Post by Elorebaen »

Thank you LM!!!

Kharnacier
Kobold
Posts: 12
Joined: Thu Aug 17, 2017 7:28 pm

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

Post by Kharnacier »

First of all, great work and thank you !
I just have a problem: when I select D&D3.5 in Global Settings and try to use the Attack Frame macro, I get this error
Illegal argument type net.sf.json.JSONArray, expecting java.math.BigDecimal or java.lang.String
But if I select Pathfinder, the macro works fine :x :shock: :(
Any idea would be much appreciated.

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

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

Post by aliasmask »

Somewhere there is a variable with a json in it and the code is expecting a number or string. This usually happens with an [if:] statement like

Code: Select all

 [H, if(variable == "string"): "true thing"; "false thing"]
To track it down, you'll need to restart the launcher and go to the Advanced tab and check the macro handling box. You can then start the campaign, do what you do to get the error and then go to the .maptool folder under user profiles and look at the log.txt file for the exact line where the error occurs (near bottom of file). I recommend maybe deleting this file before restarting the campaign for a fresh file.

You can then copy/paste the error lines and a couple of lines before the error here and someone can take a look at it.

Kharnacier
Kobold
Posts: 12
Joined: Thu Aug 17, 2017 7:28 pm

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

Post by Kharnacier »

aliasmask wrote:
To track it down, you'll need to restart the launcher and go to the Advanced tab and check the macro handling box. You can then start the campaign, do what you do to get the error and then go to the .maptool folder under user profiles and look at the log.txt file for the exact line where the error occurs (near bottom of file). I recommend maybe deleting this file before restarting the campaign for a fresh file.

You can then copy/paste the error lines and a couple of lines before the error here and someone can take a look at it.
Thx for the quick answer :)
I tryed what you told but nothing appears in
log.txt:
2017-08-18 12:07:02,113 [model.AssetLoader:130] ERROR - I/O error retrieving/saving index for 'http://dl.dropbox.com/u/9052014/W42-BoT ... Y/index.gz
java.util.zip.ZipException: Not in GZIP format
at java.util.zip.GZIPInputStream.readHeader(Unknown Source)
at java.util.zip.GZIPInputStream.<init>(Unknown Source)
at java.util.zip.GZIPInputStream.<init>(Unknown Source)
at net.rptools.maptool.model.AssetLoader.decode(AssetLoader.java:142)
at net.rptools.maptool.model.AssetLoader.getIndexMap(AssetLoader.java:125)
at net.rptools.maptool.model.AssetLoader.addRepository(AssetLoader.java:59)
at net.rptools.maptool.model.AssetManager.updateRepositoryList(AssetManager.java:87)
at net.rptools.maptool.client.MapTool.setCampaign(MapTool.java:871)
at net.rptools.maptool.client.AppActionsrun(AppActions.java:2125)
Last edited by wolph42 on Fri Aug 18, 2017 7:01 am, edited 1 time in total.
Reason: added spoiler tag

Kharnacier
Kobold
Posts: 12
Joined: Thu Aug 17, 2017 7:28 pm

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

Post by Kharnacier »

I tryed again, checking all the boxes from "logging type" and got
that :
2017-08-18 12:19:39,738 [client.MapToolLineParser:1265] DEBUG - margs = macro.args
2017-08-18 12:19:39,741 [client.MapToolLineParser:1265] DEBUG - gLib = "Lib:GlobalsSRDPF"
2017-08-18 12:19:39,748 [client.MapToolLineParser:1265] DEBUG - submitAction = replace(json.get(margs, "processAttack"),"<[^>]*?>","")
2017-08-18 12:19:39,753 [client.MapToolLineParser:1265] DEBUG - numWeapChoice = json.get( margs, "numWeapChoice" )
2017-08-18 12:19:39,756 [client.MapToolLineParser:1265] DEBUG - if(json.isEmpty( numWeapChoice ), 1, 0)
2017-08-18 12:19:39,758 [client.MapToolLineParser:1265] DEBUG - ''
2017-08-18 12:19:39,759 [client.MapToolLineParser:1265] DEBUG - tToken = json.get(margs, "id")
2017-08-18 12:19:39,760 [client.MapToolLineParser:1265] DEBUG - isTokHere = findToken( tToken)
2017-08-18 12:19:39,762 [client.MapToolLineParser:1265] DEBUG - tcmap = getCurrentMapName()
2017-08-18 12:19:39,763 [client.MapToolLineParser:1265] DEBUG - ttmap = json.get(margs,"tmap")
2017-08-18 12:19:39,768 [client.MapToolLineParser:1265] DEBUG - if(isTokHere == "", 1, 0)
2017-08-18 12:19:39,769 [client.MapToolLineParser:1265] DEBUG - ""
2017-08-18 12:19:39,771 [client.MapToolLineParser:1265] DEBUG - if(isTokHere == "", 1, 0)
2017-08-18 12:19:39,772 [client.MapToolLineParser:1265] DEBUG - isTokHere2 = 1
2017-08-18 12:19:39,773 [client.MapToolLineParser:1265] DEBUG - if(isTokHere2 == "", 1, 0)
2017-08-18 12:19:39,774 [client.MapToolLineParser:1265] DEBUG - ""
2017-08-18 12:19:39,774 [client.MapToolLineParser:1265] DEBUG - assert( isTokHere2 != "", "Attack Frame: Token not found. Move to the map containing your token and try again.")
2017-08-18 12:19:39,776 [client.MapToolLineParser:1265] DEBUG - if(isTokHere != "" && tcmap != ttmap, 1, 0)
2017-08-18 12:19:39,776 [client.MapToolLineParser:1265] DEBUG - ""
2017-08-18 12:19:39,777 [client.MapToolLineParser:1265] DEBUG - target1ID = json.get(margs, "target1ID")
2017-08-18 12:19:39,778 [client.MapToolLineParser:1265] DEBUG - if(target1ID == "", 1, 0)
2017-08-18 12:19:39,779 [client.MapToolLineParser:1265] DEBUG - tid1name = ""
2017-08-18 12:19:39,780 [client.MapToolLineParser:1265] DEBUG - target2ID = json.get(margs, "target2ID")
2017-08-18 12:19:39,781 [client.MapToolLineParser:1265] DEBUG - if(target2ID == "", 1, 0)
2017-08-18 12:19:39,783 [client.MapToolLineParser:1265] DEBUG - tid2name = ""
2017-08-18 12:19:39,784 [client.MapToolLineParser:1265] DEBUG - tSelected = getSelected()
2017-08-18 12:19:39,785 [client.MapToolLineParser:1265] DEBUG - if(submitAction == "Set 1st", 1, 0)
2017-08-18 12:19:39,786 [client.MapToolLineParser:1265] DEBUG - if(submitAction == "Set 2nd", 1, 0)
2017-08-18 12:19:39,787 [client.MapToolLineParser:1265] DEBUG - system = getLibProperty("System", gLib)
2017-08-18 12:19:39,788 [client.MapToolLineParser:1265] DEBUG - system
2017-08-18 12:19:39,788 [client.MapToolLineParser:1265] DEBUG - meleeMods = table( "SysVars", json.get( table( "SysVars", 0 ), "meleeModsSRD" ) )
2017-08-18 12:19:39,789 [client.MapToolLineParser:1265] DEBUG - tPF= "PF"
2017-08-18 12:19:39,790 [client.MapToolLineParser:1265] DEBUG - tTable = "SRDSpecialATK"
2017-08-18 12:19:39,790 [client.MapToolLineParser:1265] DEBUG - sachoices = "None, Disarm, Grapple, Sunder, Trip"
2017-08-18 12:19:39,791 [client.MapToolLineParser:1265] DEBUG - tPF = if( "Pathfinder" == getPropertyType(tToken), "PF", tPF)
2017-08-18 12:19:39,793 [client.MapToolLineParser:1265] DEBUG - tToken
2017-08-18 12:19:39,794 [client.MapToolLineParser:1265] DEBUG - aTMS = json.get( PrivateJSON, "ActiveTempModSets" )
2017-08-18 12:19:39,800 [client.MapToolLineParser:1265] DEBUG - if(json.type( aTMS ) == "UNKNOWN", 1, 0)
2017-08-18 12:19:39,802 [client.MapToolLineParser:1265] DEBUG - tToken
2017-08-18 12:19:39,803 [client.MapToolLineParser:1265] DEBUG - jPTM = json.get( PrivateJSON, "CustomModSetValues" )
2017-08-18 12:19:39,809 [client.MapToolLineParser:1265] DEBUG - jMMFields = json.sort( json.fields( meleeMods, "json" ) )
2017-08-18 12:19:39,810 [client.MapToolLineParser:1265] DEBUG - hasChanged = 0
2017-08-18 12:19:39,811 [client.MapToolLineParser:1265] DEBUG - jMMFields
2017-08-18 12:19:39,811 [client.MapToolLineParser:1265] DEBUG - changed = 0
2017-08-18 12:19:39,812 [client.MapToolLineParser:1265] DEBUG - disable = 1
2017-08-18 12:19:39,813 [client.MapToolLineParser:1265] DEBUG - active = if( json.contains( aTMS, m ), 1, 0 )
2017-08-18 12:19:39,813 [client.MapToolLineParser:1265] DEBUG - jMM = json.get( meleeMods, m )
2017-08-18 12:19:39,814 [client.MapToolLineParser:1265] DEBUG - presetVars = ""
2017-08-18 12:19:39,816 [client.MapToolLineParser:1265] DEBUG - tjfjMM = json.fields( jMM, "json")
2017-08-18 12:19:39,816 [client.MapToolLineParser:1265] DEBUG - tjfjMM = if(tjfjMM == "", 0, tjfjMM)
2017-08-18 12:19:39,817 [client.MapToolLineParser:1265] DEBUG - tjfjMM
2017-08-18 12:19:39,819 [client.MapToolLineParser:1265] DEBUG - isJObj = if( json.type( jMM ) == "OBJECT", 1, 0 )
2017-08-18 12:19:39,821 [client.MapToolLineParser:1265] DEBUG - if(isJObj && active, 1, 0)
2017-08-18 12:19:39,822 [client.MapToolLineParser:1265] DEBUG - v = 0
2017-08-18 12:19:39,822 [client.MapToolLineParser:1265] DEBUG - if(isJObj, 1, 0)
2017-08-18 12:19:39,823 [client.MapToolLineParser:1265] DEBUG - tmv = json.get(margs, m)
2017-08-18 12:19:39,824 [client.MapToolLineParser:1265] DEBUG - if(isJObj, 1, 0)
2017-08-18 12:19:39,825 [client.MapToolLineParser:1265] DEBUG - tmv = if(tmv == "", 0, tmv)
2017-08-18 12:19:39,825 [client.MapToolLineParser:1265] DEBUG - if(isJObj, 1, 0)
2017-08-18 12:19:39,826 [client.MapToolLineParser:1265] DEBUG - disable = 1
2017-08-18 12:19:39,827 [client.MapToolLineParser:1265] DEBUG - if(isJObj, 1, 0)
2017-08-18 12:19:39,827 [client.MapToolLineParser:1265] DEBUG - changed = if( active != tmv, 1, changed )
2017-08-18 12:19:39,828 [client.MapToolLineParser:1265] DEBUG - if(changed && isJObj, 1, 0)
2017-08-18 12:19:39,829 [client.MapToolLineParser:1265] DEBUG - ""
2017-08-18 12:19:39,829 [client.MapToolLineParser:1265] DEBUG - if(changed && active, 1, 0)
2017-08-18 12:19:39,830 [client.MapToolLineParser:1265] DEBUG - if(changed && ( !disable || !active ), 1, 0)
2017-08-18 12:19:39,831 [client.MapToolLineParser:1265] DEBUG - hasChanged = if( hasChanged || changed, 1, 0 )
2017-08-18 12:19:39,833 [client.MapToolLineParser:1265] DEBUG - changed = 0
2017-08-18 12:19:39,833 [client.MapToolLineParser:1265] DEBUG - disable = 1
2017-08-18 12:19:39,834 [client.MapToolLineParser:1265] DEBUG - active = if( json.contains( aTMS, m ), 1, 0 )
2017-08-18 12:19:39,834 [client.MapToolLineParser:1265] DEBUG - jMM = json.get( meleeMods, m )
2017-08-18 12:19:39,835 [client.MapToolLineParser:1265] DEBUG - presetVars = ""
2017-08-18 12:19:39,836 [client.MapToolLineParser:1265] DEBUG - tjfjMM = json.fields( jMM, "json")
2017-08-18 12:19:39,836 [client.MapToolLineParser:1265] DEBUG - tjfjMM = if(tjfjMM == "", 0, tjfjMM)
2017-08-18 12:19:39,837 [client.MapToolLineParser:1280] DEBUG - net.rptools.parser.function.ParameterException: Illegal argument type net.sf.json.JSONArray, expecting java.math.BigDecimal or java.lang.String
I think that's the source of the error, but unfortunatly, I don't know how to fix it :(
Last edited by wolph42 on Fri Aug 18, 2017 7:02 am, edited 1 time in total.
Reason: added spoiler tag

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

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

Post by wolph42 »

its a coding error, this:

Code: Select all

tjfjMM = json.fields( jMM, "json")
tjfjMM = if(tjfjMM == "", 0, tjfjMM)
can never work. it should have been

Code: Select all

tjfjMM = json.fields( jMM)
tjfjMM = if(tjfjMM == "", 0, tjfjMM)
or

Code: Select all

tjfjMM = json.fields( jMM, "json")
tjfjMM = if(json.isEmpty(tjfjMM) == 1, 0, tjfjMM)
<!-- although it appears this is the intention, its bad coding as the end result is either numeric OR an array which can lead to all sorts of bugs -->
code remains weird though, by adding the "json" param. it seems that an array is required, but if the json is empty then '0' will do as well. This makes little sense.

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

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

Post by aliasmask »

I loaded the framework and was able to duplicate the error. The best solution is to just delete that line from the code. It appears in 2 places. For simplicity, I've provided an easy way for you to do this.

In the campaign window near the bottom of the macros is a macro called "Edit Macros". You want do go to the Libraries and Utils maps and you'll see a blue token named "Lib:libDnD35Pathfinder". Select this token and run that macro. A frame will popup and you copy/paste this code in to it and click the "Save" button. It should now work.
||| CODE |||

Code: Select all

@@ @Attack
@PROPS@ fontColor=black ; autoExecute=true ; fontSize=1.00em ; sortBy=1 ; color=gray ; playerEditable=false ; applyToSelected=true ; group=Combat ; tooltip= ; minWidth= ; 
<!-- ATTACK -->
[H: fGMSecret = getLibProperty("fGMSecret", "Lib:GlobalsSRDPF")]
[H, IF( json.type( macro.args ) == "UNKNOWN" ), CODE: {
   [ weaponID = macro.args ]
   [ flagSecret = fGMSecret ]
};{
   [ weaponID = json.get( macro.args, "weaponID" ) ]
   [ flagSecret = json.get( macro.args, "flagSecret" ) ]
   [IF( json.isEmpty( flagSecret ) ): flagSecret = fGMSecret ]
   [ numWeapChoice = json.get( macro.args, "numWeapChoice" ) ]
   [IF( json.isEmpty( numWeapChoice ) ): numWeapChoice = 10 ]
} ]

[H: tToken = currentToken() ]
[H, TOKEN( tToken ): assert( isOwner() || isGM(), getMacroName() + ": Not your token!" ) ]

[H: weaponID = if( isNumber(weaponID), "Weapon" + weaponID, weaponID ) ]

[H: gTok = "Lib:GlobalsSRDPF" ]
[H: system = getLibProperty("System", gTok)]
[H, SWITCH(system), CODE:
   case "Pathfinder": {
      [ meleeMods = table( "SysVars", json.get( table( "SysVars", 0 ), "meleeModsPF" ) ) ]
      [ pRapid = "Rapid Shot Attack *" ]
      [H: tPF= "PF"]
      [H: tTable = "PFSpecialATK" ]
      [H: sachoices = "None, Disarm, Grapple, Sunder, Trip"]
   };
   case "D&D3.5": {
      [ meleeMods = table( "SysVars", json.get( table( "SysVars", 0 ), "meleeModsSRD" ) ) ]
      [ pRapid = "Flurry of Blows/Rapid Shot Attack *" ]
      [H: tPF= "PF"]
      [H: tTable = "SRDSpecialATK" ]
      [H: sachoices = "None, Disarm, Grapple, Sunder, Trip"]
   };
   default: {
   }
]
[H: tPF = if( "Pathfinder" == getPropertyType(), "PF", tPF)]

[H: tPointBlankShot = getStrProp(Feats, "PointBlankShot")]
[H: tPointBlankShot = if(tPointBlankShot == "", 0, tPointBlankShot)]
[H: tManyShot = getStrProp(Feats, "ManyShot")]
[H: tManyShot = if(tManyShot == "", 0, tManyShot)]
[H: manyShot = 0 ]
[H: optManyShot = IF(tManyShot, "manyShot|0|Using Many Shot Feat?|CHECK| ##", "" ) ]

[H: tVitalStrike = getStrProp(Feats, "VitalStrike")]
[H: tVitalStrike = if(tVitalStrike == "", 0, tVitalStrike)]
[H: tImpVitalStrike = getStrProp(Feats, "ImprovedVitalStrike")]
[H: tImpVitalStrike = if(tImpVitalStrike == "", 0, tImpVitalStrike)]
[H: tGrVitalStrike = getStrProp(Feats, "GreaterVitalStrike")]
[H: tGrVitalStrike = if(tGrVitalStrike == "", 0, tGrVitalStrike)]
[H: tVitalStrike = if( tGrVitalStrike || tImpVitalStrike || tVitalStrike, 1, 0 ) ]
[H: vitalStrike = 0 ]
[H: optVitalStrike = IF(tVitalStrike, "vitalStrike|0|Use Vital Strike Feat?|CHECK| ##", "" ) ]

[H: jCC = json.get( PrivateJSON, "CombatConfig" ) ]
[H, IF( json.type( jCC ) == "UNKNOWN" ), CODE: {
   [ jCC = json.set( "{}", "fullRound", 1, "rangeIncrement", 1, "flurryRapid", 1, "favEnemy", 0, "sneak", "0d6", "fireIntoMelee", 0, "manyShot", manyShot, "critConfirm", 0, "modCritRange", 0, "sizeVariant", 0, "rollTwice", 0  ) ]
   [ PrivateJSON = json.set( PrivateJSON, "CombatConfig", jCC ) ]
}]
[H: sizeVariant = json.get( jCC, "sizeVariant" ) ]
[H, IF( sizeVariant == "" ): sizeVariant = 0; "" ]
[H: rollTwice = json.get( jCC, "rollTwice" ) ]
[H, IF( rollTwice == "" ): rollTwice = 0; "" ]

[H: tCriticalFocus = getStrProp(Feats, "CriticalFocus")]
[H: tCriticalFocus = if(tCriticalFocus == "", 0, tCriticalFocus)]
[H: critConfirm = json.get( jCC, "critConfirm" ) ]
[H: critConfirm = if( critConfirm == 0 && tCriticalFocus, tCriticalFocus*4, critConfirm ) ]

[H: sizeList = table( "SysVars", json.get( table( "SysVars", 0 ), "sizeList" ) ) ]

[H: inCC =
   "fullRound|Single, Full Round|Attack|RADIO|ORIENT=H SELECT=1 ##"
   + "concealMiss|0,1,2|Roll How Many Miss Chances?|RADIO|ORIENT=H VALUE=STRING ##"
   + "flagSecret|" + flagSecret + "|<html><font color=red>Secret</font>?</html>|CHECK| ##"
   + "specialATKChoice|" + sachoices + "|Follow-on Special Attack?|LIST|SELECT=0 ##"
   + "tempATK|0|Temporary Attack Bonus|TEXT|WIDTH=10 ##"
   + "tempDMG|0|Temporary Damage Bonus|TEXT|WIDTH=10 ##"
   + "flanking|0|Flanking?|CHECK| ##"
   + "higherGround|0|Attacking from Higher Ground?|CHECK| ##"
   + "cover|0|<html><span title='Use for Melee attacking around a hard corner or Range attacks with impediments (like an ally) in the way (-4 to Attack).'>Target has Cover?</span></html>|CHECK| ##"
   + optManyShot + optVitalStrike
   + "flurryRapid|-2, -1, 0, Normal Attack|"+pRapid+"|RADIO|ORIENT=H SELECT=3 ##"
   + "seperator|<html>   * Gives an additional attack if <i>Full Round</i> and weapon is <i>Manufactured</i>.</html>||LABEL|SPAN=TRUE ##"
   + "rangeIncrement|1,2,3,4,5,6,7,8,9,10|Range Increment|RADIO|ORIENT=H SELECT=0 ##"
   + "pointBlank|0|<html>Point Blank Range (<font color=red>30 feet</font>)?</html>|CHECK| ##"
   + "seperator|<html>     ------  </i>Persistent</i>  ------</html>||LABEL|SPAN=TRUE ##"
   + "fireIntoMelee|" + json.get( jCC, "fireIntoMelee" ) + "|<html><span title='Use for Shooting/Throwing into Melee (-4 to Attack).'>Fire into Melee?</span></html>|CHECK| ##"
   + "modCritRange|" + json.get( jCC, "modCritRange" ) + "|Mod to Crit Range|TEXT|WIDTH=10 ##"
   + "critConfirm|" + critConfirm + "|Bonus to Confirm Critical Hit|TEXT|WIDTH=10 ##"
   + "favEnemy|" + json.get( jCC, "favEnemy" ) + "|Favorite Enemy Bonus|TEXT|WIDTH=10 ##"
   + "sneak|" + json.get( jCC, "sneak" ) + "|Sneak Attack Damage|TEXT|WIDTH=10 ##"
   + "sizeVariant| NA," + sizeList + "|<html><span title='Use when Enlarged or Reduced to change the base damage dice.'>Variant Size</span></html>|RADIO| ORIENT=H SELECT=" + sizeVariant + " ##"
   + "rollTwice| NA, Use Highest, Use Lowest|Roll Attack Twice Variant|RADIO| ORIENT=H SELECT=" + rollTwice
]

[H: aTMS = json.get( PrivateJSON, "ActiveTempModSets" ) ]
[H, IF( json.type( aTMS ) == "UNKNOWN" ), CODE: {
   [ PrivateJSON = json.set( PrivateJSON, "ActiveTempModSets", "[]" ) ]
   [ aTMS = "[]" ]
}]
[H: jPTM = json.get( PrivateJSON, "CustomModSetValues" ) ]

[H: jMMFields = json.sort( json.fields( meleeMods, "json" ) ) ]

[H: inMods = "" ]
[H: modString = "%{p} | %{v} | %{n} | %{t} | %{o}" ]

[H, FOREACH( m, jMMFields ), CODE: {
   [ active = if( json.contains( aTMS, m ), 1, 0 ) ]
   [ jMM = json.get( meleeMods, m ) ]

   [IF( isNumber( jMM ) ), CODE: {
      [ p = replace( replace( m, " ", "_" ), "/", "." ) ]
      [ v = active ]
      [ n = "<html><b>" + m + "</b></html>" ]
      [ t = "CHECK" ]
      [ o = "" ]
      [ inMods = listAppend( inMods, strformat( modString ), "##" ) ]
   };{
      [ p = m ]
      [ v = "<html><b>" + m + "</b></html>" ]
      [ n = m ]
      [ t = "LABEL" ]
      [ o = "SPAN=TRUE" ]
      [ inMods = listAppend( inMods, strformat( modString ), "##" ) ]
   
      [MACRO( "pAttack@this" ): json.set( "{}", "tokenID", tToken, "mod", m, "variables", jMM, "active", active ) ]
      [ tinMods = json.get( macro.return, "inMods" ) ]
   
      [ inMods = listAppend( inMods, tinMods, "##" ) ]
   }]
}]

[H: inWeap = "" ]
[H, IF(weaponID == ""), CODE: {
   [H: weaponNames=""]
   [H, C(31, ""): weaponNames = weaponNames + ", " + getStrProp(eval("Weapon" + roll.count), "Name")]
   [H: inWeapString = 'Weap%{roll.count}|' + weaponNames + '|Select Attack%{roll.count}| LIST | SELECT=%{tSelect}' ]
   [H, C(numWeapChoice, ""), CODE: {
      [ tSelect = getStrProp( Private, "LastWeap" + roll.count ) ]
      [ inWeap = listAppend( inWeap, strformat( inWeapString ), '##' ) ]
   }]
};{
   [ weaponNames = getStrProp(eval("" + weaponID), "Name")]
   [ inWeap = 'junk|' + weaponNames + '|Weapon| LABEL |' ]
}]

[H: visTokens = "[]" ]
[H: visTokenIDs = getVisibleTokens("json") ]
[H, FOREACH( i, visTokenIDs ),CODE: {
   [IF(isNumber(i)): ""; visTokens = json.append( visTokens, json.set( "{}", "name", getName(i), "id", i, "range", lgm.getDistanceElev(i,tToken) ) ) ]
}]
[H: visTokens = json.sort( visTokens, "ascend", "range", "name" ) ]
[H: visTokenNames = "[]" ]
[H, FOREACH( i, visTokens ), CODE: {
   [ visTokenRange = json.get( i, "range" ) ]
   [ visTokenNames = json.append( visTokenNames, "(" + if( visTokenRange <= 30, "<font color=red>", "" ) + visTokenRange + " ft." + if( visTokenRange <= 30, "</font>", "" ) + ") " + json.get( i, "name" ) ) ]
}]

[H: visTokenNameList = "Not Specified" ]
[H, FOREACH( i, visTokenNames, "" ): visTokenNameList = listAppend( visTokenNameList,   "<html>" + replace( i, ",", "_" ) +  "</html>" ) ]

[H: cancel = input(
   "tab0 | Config Attack | | TAB",
   inWeap,
   inCC,
   "seperator|<html>     ---vvvv---  </i>Mod-Sets</i>  ---vvvv---</html>||LABEL|SPAN=TRUE",
   inMods,
   "tab1 | Primary Target | | TAB",
   "tTarget1 | " + visTokenNameList + " |Target|RADIO|",
   "tab1 | Secondary Target | | TAB",
   "tTarget2 | " + visTokenNameList + " |Target|RADIO|"
)]
[H: abort(cancel)]

[H: flurryRapid = flurryRapid - 2 ]

[H, IF( tTarget1 == 0 ): target1ID = ""; target1ID = json.get( json.get( visTokens, tTarget1-1 ), "id" ) ]
[H, IF( tTarget2 == 0 ): target2ID = ""; target2ID = json.get( json.get( visTokens, tTarget2-1 ), "id" ) ]
[H, IF( tTarget1 == 0 ): target1Name = ""; target1Name = json.get( json.get( visTokens, tTarget1-1 ), "name" ) ]
[H, IF( tTarget2 == 0 ): target2Name = ""; target2Name = json.get( json.get( visTokens, tTarget2-1 ), "name" ) ]
[H, IF( target1ID != "" ), CODE: {
   [H, IF( am.hasHighGround( tToken, target1ID ) ): higherGround = 1; ""]
   [H: tdist = lgm.getDistanceElev(target1ID,tToken)]
   [H, IF(tdist <= 30 && tPointBlankShot): pointBlank = 1; pointBlank = 0]
};{}]

[H, IF(weaponID == ""), CODE: {
   [H: Private = setStrProp(Private, "LastWeap0", Weap0)]
   [H, IF(numWeapChoice >= 2): Private = setStrProp(Private, "LastWeap1", Weap1)]
   [H, IF(numWeapChoice >= 3): Private = setStrProp(Private, "LastWeap2", Weap2)]
   [H, IF(numWeapChoice >= 4): Private = setStrProp(Private, "LastWeap3", Weap3)]
   [H, IF(numWeapChoice >= 5): Private = setStrProp(Private, "LastWeap4", Weap4)]
   [H, IF(numWeapChoice >= 6): Private = setStrProp(Private, "LastWeap5", Weap5)]
   [H, IF(numWeapChoice >= 7): Private = setStrProp(Private, "LastWeap6", Weap6)]
   [H, IF(numWeapChoice >= 8): Private = setStrProp(Private, "LastWeap7", Weap7)]
   [H, IF(numWeapChoice >= 9): Private = setStrProp(Private, "LastWeap8", Weap8)]
   [H, IF(numWeapChoice >= 10): Private = setStrProp(Private, "LastWeap9", Weap9)]
};
{}]

[FOREACH( m, jMMFields, "" ), CODE: {
   [H: changed = 0 ]
   [H: disable = 1 ]
   [H: active = if( json.contains( aTMS, m ), 1, 0 ) ]
   [H: jMM = json.get( meleeMods, m ) ]
   [H: presetVars = "" ]

   [H: tjfjMM = json.fields( jMM, "json")]

   [H, FOREACH( n, tjfjMM ), CODE: {
      [ isJObj = if( json.type( jMM ) == "OBJECT", 1, 0 ) ]
      [IF( isJObj && active ): v = json.get( json.get( json.get( json.get( jPTM, m ), "mods" ), "globalMod" ), "v" ); v = 0  ]
      [IF( isJObj ): tmv = eval( "" + json.get( jMM, n ) ); tmv = eval( "" + replace( replace( m, " ", "_" ), "/", "." ) ) ]     
     
      [IF( isJObj ): disable = if( tmv != 0, 0, disable ); disable = 1 ]
      [IF( isJObj ): changed = if( v != tmv, 1, changed ); changed = if( active != tmv, 1, changed ) ]
      [IF( changed && isJObj ): presetVars = json.set( presetVars, json.get( jMM, n ), tmv ) ]
   }]

   
   [IF( changed && active ), CODE: {
      [MACRO( "subModToggle@this" ): json.set( "{}", "tokenID", tToken, "setID", m, "setType", 0 ) ]
   };{}]
   [IF( changed && ( !disable || !active ) ), CODE: {
      [MACRO( "subModToggle@this" ): json.set( "{}", "tokenID", tToken, "setID", m, "setType", 0, "presetVars", presetVars ) ]
   };{}]
}]
   
[H,IF(weaponID == ""), CODE: {
   [C(numWeapChoice,""), IF( eval("Weap" + roll.count) == "" || eval("Weap" + roll.count) == 0), CODE: {
   };{
      [H: ti = eval("Weap" + roll.count) - 1]
      [H: tWeap = "Weapon" + ti]
      [H, IF( target1ID != "" ): lgm.getWeaponset(ti);""]
      [H, IF( target1ID != "" ): rangeIncrement = floor((tdist-0.01)/WpnRangeInc);""]
      [MACRO("LibAttack@this"): json.set("{}", "weapon", tWeap, "fullRound", fullRound, "flanking", flanking, "higherGround", higherGround, "favEnemy", favEnemy, "rangeIncrement", rangeIncrement, "pointBlank", pointBlank, "cover", cover, "fireIntoMelee", fireIntoMelee, "sneak", sneak, "flurryRapid", flurryRapid, "target1Name", target1Name, "target1ID", target1ID, "target2Name", target2Name, "target2ID", target2ID, "flagSecret", flagSecret, "tempATK", tempATK, "tempDMG", tempDMG, "concealMiss", concealMiss, "manyShot", manyShot, "critConfirm", eval(""+critConfirm), "modCritRange", eval(""+modCritRange), "vitalStrike", vitalStrike, "sizeVariant", sizeVariant, "rollTwice", rollTwice ) ]
   }]
};{
      [H: ti = replace(lower(weaponID),"weapon","")]
      [H, IF( target1ID != "" ): lgm.getWeaponset(ti);""]
      [H, IF( target1ID != "" ): rangeIncrement = floor((tdist-0.01)/WpnRangeInc);""]
      [MACRO("LibAttack@this"): json.set("{}", "weapon", weaponID, "fullRound", fullRound, "flanking", flanking, "higherGround", higherGround, "favEnemy", favEnemy, "rangeIncrement", rangeIncrement, "pointBlank", pointBlank, "cover", cover, "fireIntoMelee", fireIntoMelee, "sneak", sneak, "flurryRapid", flurryRapid, "target1Name", target1Name, "target1ID", target1ID, "target2Name", target2Name, "target2ID", target2ID, "flagSecret", flagSecret, "tempATK", tempATK, "tempDMG", tempDMG, "concealMiss", concealMiss, "manyShot", manyShot, "critConfirm", eval(""+critConfirm), "modCritRange", eval(""+modCritRange), "vitalStrike", vitalStrike, "sizeVariant", sizeVariant, "rollTwice", rollTwice ) ]
}]

[H: PrivateJSON = json.set( PrivateJSON, "CombatConfig", json.set( "{}", "fullRound", fullRound, "rangeIncrement", rangeIncrement, "pointBlank", pointBlank, "flurryRapid", flurryRapid, "favEnemy", favEnemy, "sneak", sneak, "fireIntoMelee", fireIntoMelee, "manyShot", manyShot, "critConfirm", critConfirm, "modCritRange", modCritRange, "sizeVariant", sizeVariant, "rollTwice", rollTwice ) ) ]

[H: tType = listGet( sachoices, specialATKChoice ) ]
[H: cntAll = table( tTable, 0 )]
[H: ref = ""]
[H: i = 1 ]

[H, WHILE( ref == "" && i <= cntAll ), CODE: {
  [H: jType = table( tTable, i )]
  [R: cType = json.get( jType, "name" )]
  [H, IF(tType == cType): ref = ref + json.get( jType, "ref" )]
  [H: i = i + 1 ]
}]

[H: out1 = "<b>" +  macroLink( tType, "dispSATKrules@" + getMacroLocation(), "none", json.set( "", "name", tType, "system", system)) + "</b> (" + ref + ")<br />" ]

[H,IF(flagSecret && (specialATKChoice != 0)),CODE:{
    [H: broadcast(out1,json.union(lgm.getAllGMs(),getOwners("json",tToken)),"json") ]
};{}]
[H,IF(!flagSecret && (specialATKChoice != 0)),CODE:{
    [H: broadcast(out1) ]
};{}]

[H,SWITCH(system), CODE:
  case "Pathfinder": {
   
[SWITCH(specialATKChoice), CODE:
   case 0: {  };
   case 1: { [MACRO("subDisarm"+tPF+"@this"):  ""] };
   case 2: { [MACRO("subGrapple"+tPF+"@this"):  ""] };
   case 3: { [MACRO("subSunder"+tPF+"@this"):  ""] };
   case 4: { [MACRO("subTrip"+tPF+"@this"):  ""] };

]
    };
  case "D&D3.5": {

[SWITCH(specialATKChoice), CODE:
   case 0: {  };
   case 1: { [MACRO("subDisarm"+tPF+"@this"):  ""] };
   case 2: { [MACRO("subGrapple"+tPF+"@this"):  ""] };
   case 3: { [MACRO("subSunder"+tPF+"@this"):  ""] };
   case 4: { [MACRO("subTrip"+tPF+"@this"):  ""] };
]
    };
  default: {}

]

!!
@@ @processAttack
@PROPS@ fontColor=black ; autoExecute=true ; fontSize=1.00em ; sortBy=1 ; color=cyan ; playerEditable=true ; applyToSelected=false ; group=CombatDialog ; tooltip= ; minWidth= ; 
[H: margs = macro.args ]

[H: gLib = "Lib:GlobalsSRDPF" ]

[H: submitAction = replace(json.get(margs, "processAttack"),"<[^>]*?>","") ]
[H: numWeapChoice = json.get( margs, "numWeapChoice" ) ]
[H,IF( json.isEmpty( numWeapChoice ) ): numWeapChoice = 4 ]

[H: tToken = json.get(margs, "id") ]
[H: isTokHere = findToken( tToken) ]
[H: tcmap = getCurrentMapName() ]

[H: ttmap = json.get(margs,"tmap") ]
[H, IF( isTokHere == "" ):  setCurrentMap( ttmap ); "" ]
[H, IF( isTokHere == "" ): isTokHere2 = findToken( tToken); isTokHere2 = 1 ]
[H, IF( isTokHere2 == "" ): execLink( macroLinkText("subReturnToMap@" + getMacroLocation(), "none", tcmap), 1); "" ]
[H: assert( isTokHere2 != "", "Attack Frame: Token not found.  Move to the map containing your token and try again.")]

[H, IF( isTokHere != "" && tcmap != ttmap):  margs = json.set(margs,"tmap",tcmap); "" ]

[H: target1ID = json.get(margs, "target1ID") ]
[H, IF(target1ID == ""): tid1name = ""; tid1name = getName(target1ID) ]
[H: target2ID = json.get(margs, "target2ID") ]
[H, IF(target2ID == ""): tid2name = ""; tid2name = getName(target2ID) ]

[H: tSelected = getSelected() ]

[H, IF(submitAction == "Set 1st"), CODE: {
   [H: margs = json.set(margs, "target1ID", if( listCount(tSelected) > 1, listGet(tSelected,0), tSelected )) ]
   [MACRO("attackFrame@this"): margs ]
   [H, IF( isTokHere == "" ): execLink( macroLinkText("subReturnToMap@" + getMacroLocation(), "none", tcmap), 1); "" ]
   [H: abort(0)]
};{}]
[H, IF(submitAction == "Set 2nd"), CODE: {
   [H: margs = json.set(margs, "target2ID", if( listCount(tSelected) > 1, listGet(tSelected,0), tSelected )) ]
   [MACRO("attackFrame@this"): margs ]
   [H, IF( isTokHere == "" ): execLink( macroLinkText("subReturnToMap@" + getMacroLocation(), "none", tcmap), 1); "" ]
   [H: abort(0)]
};{}]

[H: system = getLibProperty("System", gLib)]
[H, SWITCH(system), CODE:
   case "Pathfinder": {
      [ meleeMods = table( "SysVars", json.get( table( "SysVars", 0 ), "meleeModsPF" ) ) ]
      [H: tPF= "PF"]
      [H: tTable = "PFSpecialATK" ]
      [H: sachoices = "None, Disarm, Grapple, Sunder, Trip"]
   };
   case "D&D3.5": {
      [ meleeMods = table( "SysVars", json.get( table( "SysVars", 0 ), "meleeModsSRD" ) ) ]
      [H: tPF= "PF"]
      [H: tTable = "SRDSpecialATK" ]
      [H: sachoices = "None, Disarm, Grapple, Sunder, Trip"]
   };
   default: {
   }
]
[H: tPF = if( "Pathfinder" == getPropertyType(tToken), "PF", tPF)]

[H,TOKEN(tToken): aTMS = json.get( PrivateJSON, "ActiveTempModSets" ) ]
[H, IF( json.type( aTMS ) == "UNKNOWN" ), CODE: {
   [TOKEN(tToken): PrivateJSON = json.set( PrivateJSON, "ActiveTempModSets", "[]" ) ]
   [ aTMS = "[]" ]
};{}]
[H,TOKEN(tToken): jPTM = json.get( PrivateJSON, "CustomModSetValues" ) ]
[H: jMMFields = json.sort( json.fields( meleeMods, "json" ) ) ]

[H: hasChanged = 0 ]
[H,FOREACH( m, jMMFields, "" ), CODE: {
   [H: changed = 0 ]
   [H: disable = 1 ]
   [H: active = if( json.contains( aTMS, m ), 1, 0 ) ]
   [H: jMM = json.get( meleeMods, m ) ]
   [H: presetVars = "" ]

   [H: tjfjMM = json.fields( jMM, "json")]

   [H, FOREACH( n, tjfjMM ), CODE: {
      [ isJObj = if( json.type( jMM ) == "OBJECT", 1, 0 ) ]
      [IF( isJObj && active ): v = json.get( json.get( json.get( json.get( jPTM, m ), "mods" ), "globalMod" ), "v" ); v = 0  ]
      [IF( isJObj ): tmv = eval( "" + json.get( margs,json.get( jMM, n ) ) ); tmv = json.get(margs, m) ]     
      [IF( isJObj ): ""; tmv = if(tmv == "", 0, tmv) ]
  
      [IF( isJObj ): disable = if( tmv != 0, 0, disable ); disable = 1 ]
      [IF( isJObj ): changed = if( v != tmv, 1, changed ); changed = if( active != tmv, 1, changed ) ]
      [IF( changed && isJObj ): presetVars = json.set( presetVars, json.get( jMM, n ), tmv ); "" ]
   }]

   
   [IF( changed && active ), CODE: {
      [MACRO( "subModToggle@this" ): json.set( "{}", "tokenID", tToken, "setID", m, "setType", 0 ) ]
      [ broadcast(macro.return)]
   };{}]
   [IF( changed && ( !disable || !active ) ), CODE: {
      [MACRO( "subModToggle@this" ): json.set( "{}", "tokenID", tToken, "setID", m, "setType", 0, "presetVars", presetVars ) ]
      [ broadcast(macro.return)]
   };{}]
   [ hasChanged = if( hasChanged || changed, 1, 0 ) ]
}]

[IF(submitAction == "ATTACK"), CODE: {
   [H: ttempATK = json.get(margs,"tempATK") ]
   [H: ttempDMG = json.get(margs,"tempDMG") ]
   [H: tflanking = json.get(margs,"flanking") ]
   [H: thigherGround = json.get(margs,"higherGround") ]
   [H: tcover = json.get(margs,"cover") ]
   [H: tflurryRapid = json.get(margs,"flurryRapid") ]
   [H: trangeIncrement = json.get(margs,"rangeIncrement") ]
   [H: tpointBlank = json.get(margs,"pointBlank") ]
   [H: '<!-- Check point blank -->']
   [H: tPointBlankShot = getStrProp(getProperty("Feats", tToken), "PointBlankShot")]
   [H: tPointBlankShot = if(tPointBlankShot == "", 0, tPointBlankShot)]
   [H, IF( ! json.isEmpty(target1ID) ), CODE: {
      [H: tdist = lgm.getDistanceElev(tToken,target1ID)]
      [H, IF(tdist <= 30 && tPointBlankShot): tpointBlank = 1; tpointBlank = 0]
      [H, IF( am.hasHighGround( tToken, target1ID ) ): thigherGround = 1; thigherGround = 0]
      [H: margs = json.set(margs, "pointBlank", tpointBlank, "higherGround", thigherGround)]
   };{}]

   [H: tfireIntoMelee = json.get(margs,"fireIntoMelee") ]
   [H: tmodCritRange = json.get(margs,"modCritRange") ]
   [H: tcritConfirm = json.get(margs,"critConfirm") ]
   [H: tsneak = json.get(margs,"sneak") ]
   [H: tfavEnemy = json.get(margs,"favEnemy") ]
   [H: tfullRound = json.get(margs,"fullRound") ]
   [H: flagSecret = json.get(margs,"flagSecret") ]
   [H: tflagSecret = if( flagSecret == "" || flagSecret ==0, 2, flagSecret)]
   [H: tconcealMiss = json.get(margs,"concealMiss") ]
   [H: tmanyShot = json.get(margs,"manyShot") ]
   [H: tvitalStrike = json.get(margs,"vitalStrike") ]
   [H: specialATKChoice = json.get(margs,"specialATKChoice") ]
   [H: rollTwice = json.get(margs,"rollTwice") ]
   [H: sizeVariant = json.get(margs,"sizeVariant") ]
   
   [H: tpass = json.set("{}", "weapon", "", "id", tToken, "target1Name", tid1name, "target1ID", target1ID, "target2Name", tid2name, "target2ID", target2ID,"fullRound", tfullRound, "flanking", tflanking, "higherGround", thigherGround, "favEnemy", tfavEnemy, "rangeIncrement", trangeIncrement, "pointBlank", tpointBlank, "fireIntoMelee", tfireIntoMelee, "cover", tcover, "sneak", tsneak, "flurryRapid", tflurryRapid, "flagSecret", flagSecret, "tempATK", ttempATK, "tempDMG", ttempDMG, "concealMiss", tconcealMiss, "critConfirm", eval(""+tcritConfirm), "modCritRange", eval(""+tmodCritRange), "manyShot", tmanyShot, "vitalStrike", tvitalStrike, "sizeVariant", sizeVariant, "rollTwice", rollTwice, "numWeapChoice", numWeapChoice )]

   [H, FOR(pAi,0,numWeapChoice,1), CODE: {
      [H: tweapset = json.get(margs,"weap"+pAi) ]
      [H, IF( target1ID != "" && tweapset != "" ): ti = replace(lower(tweapset),"weapon","")]
      [H, IF( target1ID != "" && tweapset != "" ): lgm.getWeaponset(ti,tToken);""]
      [H, IF( target1ID != "" && tweapset != "" ): trangeIncrement = floor((tdist-0.01)/WpnRangeInc);""]
      [H, IF(tweapset != ""): tpass = json.set(tpass, "weapon", tweapset, "rangeIncrement", trangeIncrement ); ""]
      [H, IF(tweapset != ""): lgm.LibAttack(tpass);""]
   }]

   [H: margs = json.set(margs, "rangeIncrement", trangeIncrement, "flagSecret", tflagSecret)]

  
   [H: idxSA = listFind( sachoices, specialATKChoice ) ]
   [H: cntAll = table( tTable, 0 )]
   [H: ref = ""]
   [H: i = 1 ]

   [H, WHILE( ref == "" && i <= cntAll ), CODE: {
     [H: jType = table( tTable, i )]
     [R: cType = json.get( jType, "name" )]
     [H, IF(specialATKChoice == cType): ref = ref + json.get( jType, "ref" ); ""]
     [H: i = i + 1 ]
   }]

   [H: out1 = "<b>" +  macroLink( specialATKChoice, "dispSATKrules@" + getMacroLocation(), "none", json.set( "", "name", specialATKChoice, "system", system)) + "</b> (" + ref + ")<br />" ]
   [H,IF(flagSecret && (idxSA != 0)),CODE:{
       [H: broadcast(out1,json.merge(lgm.getAllGMs(),getOwners("json",tToken))) ]
   };{}]
   [H,IF(!flagSecret && (idxSA != 0)),CODE:{
       [H: broadcast(out1) ]
   };{}]

   [H,SWITCH(idxSA), CODE:
      case 0: {  };
      case 1: { [MACRO("subDisarm"+tPF+"@this"):  json.set("","id",tToken)] };
      case 2: { [MACRO("subGrapple"+tPF+"@this"):  json.set("","id",tToken)] };
      case 3: { [MACRO("subSunder"+tPF+"@this"):  json.set("","id",tToken)] };
      case 4: { [MACRO("subTrip"+tPF+"@this"):  json.set("","id",tToken)] };
      default: {}
   ]
    
};{   [H: broadcast("<pre>"+json.indent(margs)+"</pre>")] }]

[H,MACRO("attackFrame@this"): margs ]

[H: tName = getName(tToken)]
[H, IF( isFrameVisible( tName ) && hasChanged ), CODE:
  {
    [H: link = macroLinkText( "CharSheet@"+getMacroLocation(), "self", "Page=Main ; Token=" + tToken ) ]
    [H: execLink( link, 1 ) ]
  };{}
]

[H, IF( isTokHere == "" ): execLink( macroLinkText("subReturnToMap@" + getMacroLocation(), "none", tcmap), 1); "" ]

!!

Kharnacier
Kobold
Posts: 12
Joined: Thu Aug 17, 2017 7:28 pm

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

Post by Kharnacier »

Thx for all the help !!! It works like a charm :)
By the way, @wolph42, I'm happy you decided to post new tutos on Youtube :!:


Kharnacier
Kobold
Posts: 12
Joined: Thu Aug 17, 2017 7:28 pm

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

Post by Kharnacier »

I don't want to be annoying, but I have another question. :oops:
When a player attack one of my monsters, he can see its info (see the screenshot).
http://imgur.com/a/LseF0
Would it be possible to hide AC and Tactical info from my players ?
Thx for your help and patience :)

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

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

Post by aliasmask »

In our games, the players have some clue on the defenses and movement of creature which is why I wrote that little bit. This is also seen on the tokens when mousing over it. This is a function called tokenImageLink. I added a line that will not show a tooltip anymore:
||| CODE |||

Code: Select all

@@ @tokenImageLink
@PROPS@ fontColor=silver ; autoExecute=true ; fontSize=11pt ; sortBy= ; color=purple ; playerEditable=false ; applyToSelected=false ; group=Utility ; tooltip= ; minWidth=94 ; 
[H: '<!-- 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, IF(argCount() == 2): targetId = arg(1); targetId = ""]
[H: current = currentToken()]
[H,IF(tokenId == current): ""; switchToken(tokenId)]

[H: t.image = getImage(tokenId,0)]

[H: isCreature = if(  getPropertyType(tokenId) == "Pathfinder" || getPropertyType(tokenId) == "DnD35", 1, 0 ) ]
[H, if(isCreature ), code: {
   [H: t.ac = getProperty("AC",tokenId)]
   [H: t.tactical = getProperty("sheet.moveReach",tokenId)]
   [H,IF(targetId != ""): t.distance = lgm.getDistanceElev(tokenId,targetId); t.distance = distanceStatSheet(tokenId)]
   <!-- Calc health without revealing hit points -->
   [H: effectiveHP = getProperty("HP",tokenId) + getProperty("HPtemp",tokenId) - getProperty("HPNonLethalDMG",tokenId)]
   [H: effectiveMaxHP = getProperty("HPmax",tokenId) + getProperty("HPtemp",tokenId)]
   [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: 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(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()]
	
   <!-- custom request to remove tooltip info -->
   [H: tooltip = ""]
	
   [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,IF(tokenId == current): ""; switchToken(current)]

[H: macro.return = imageLink]

!!
Just follow the directions from the last time to apply the change.

Dougal
Cave Troll
Posts: 58
Joined: Sat Sep 08, 2012 11:05 am

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

Post by Dougal »

Been using this framework on the game I am hosting over discord, I don't use everything but I love the added functionally of it. I have one question tho. Is there a way to let the players adjust their own damage taken with the macro so I don't have to do it?


Dougal.

User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

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

Post by aliasmask »

The damage listed in the attack is a link anyone can click on. So, if they select their token and click the link then it will be applied. If the damage needs adjusting like from DR then putting DR on the token will prompt for an option to adjust the damage.

Kharnacier
Kobold
Posts: 12
Joined: Thu Aug 17, 2017 7:28 pm

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

Post by Kharnacier »

aliasmask wrote:In our games, the players have some clue on the defenses and movement of creature which is why I wrote that little bit. This is also seen on the tokens when mousing over it. This is a function called tokenImageLink. I added a line that will not show a tooltip anymore:

Just follow the directions from the last time to apply the change.
Thx alot ! :)

Kharnacier
Kobold
Posts: 12
Joined: Thu Aug 17, 2017 7:28 pm

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

Post by Kharnacier »

It's me, again :P Don't hesitate to tell me if I'm getting annoying/too much asking :)
I noticed 2 problems in the Wrathgon spell macro:
1) No description for Cure Minor Wound (it's missing in the spell library too).
2) 0-spell number doesn't decrease when you cast one of them (it works fine with 1-level spells).
Any way to correct these ?

Post Reply

Return to “D&D 3.5/Pathfinder 1e Campaign Macros”