[MOD] Additional Conditions

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! :)
User avatar
aliasmask
RPTools Team
Posts: 9031
Joined: Tue Nov 10, 2009 6:11 pm
Location: California

Re: [MOD] Additional Conditions

Post by aliasmask »

neofax wrote:@Aliasmask: Have you defeated this dragon? If so, could you school Paradox and myself? Thanks!
I'm still massaging the data structures, but I think I can have something working very soon. My first intent was to write a generic data structure manager (which I did) but with large amounts of data and complex structures, it's just takes too long to write data. With my recent speed tests on another project, I learned a couple of speed optimizations I wasn't aware of. I stepped away from the generic and I'm just doing the data structures by need trying to keep the number of properties down and the json structures simple.

neofax
Great Wyrm
Posts: 1694
Joined: Tue May 26, 2009 8:51 pm
Location: Philadelphia, PA
Contact:

Re: [MOD] Additional Conditions

Post by neofax »

Thanks! Between you, Lindsay, Plothos, BioDude, CoveredInFish and others, I enjoy as easy way to run my campaigns! I salute you all.

User avatar
Paradox
Dragon
Posts: 724
Joined: Fri Feb 27, 2009 4:01 pm

Re: [MOD] Additional Conditions

Post by Paradox »

I was about to feel really dumb.. but...

Stoneskin is there. However it's just a blanket DR10/Adamantine, with no other functionality beyond that.

That is, it isn't asking for Caster Level to determine a total amount of hit points absorbed and keeping track of it, and then dropping when that total is achieved.


Really? You guys aren't familiar with stoneskin? My players use it all the time, and a lot of Rise of the Runelord villains from Chapter 4 on up have it as a standard stock spell. It works great, but requires some bookeeping, as it absorbs a predetermined amount of damage based on caster level.
I no longer believe that MapTools is usuable or intended just for programmers. MapTools is for everyone.

User avatar
aliasmask
RPTools Team
Posts: 9031
Joined: Tue Nov 10, 2009 6:11 pm
Location: California

Re: [MOD] Additional Conditions

Post by aliasmask »

I don't know what the current version uses but maybe you can hack together my code to take care of that... In the mod under custom macro I call tmStoneskin@this. Under global mod I call [MACRO("pStoneskin@this"):""]

Here are the 2 macros I use, via MacroIO export:

Code: Select all

@@tmStoneskin
[H: tmargs = macro.args ]
[H: tToken = json.get( macro.args, "token" ) ]
[H: active = json.get( macro.args, "active" ) ]
[H: switchToken( tToken ) ]

[H, IF( active ), CODE: {
   [ jOrigDR = json.get( PrivateJSON, "msStoneskin" ) ]
   [ baseDR = json.get( jOrigDR, "val" ) ]
   [ tDRtype = json.get( jOrigDR, "type" ) ]
   [ jDR = json.get( DRER, "Damage Reduction" ) ]
   [ DRER = json.set( DRER, "Damage Reduction", json.set( jDR, tDRtype, baseDR ) ) ]
   [ MACRO("subRecalcDR@this"): json.set( "{}", "Token", tToken ) ]
   [ PrivateJSON = json.remove( PrivateJSON, "msStoneskin") ]
};{
   [ jPMS = json.get( json.get( PrivateJSON, "CustomModSetValues" ), "Stoneskin" ) ]
   [ gmodv = json.get( json.get( json.get( jPMS, "mods" ), "globalMod" ), "v" ) ]
   [ Caster_Level = json.get( gmodv, "Caster_Level" ) ]
   [ abPoints = json.get( gmodv, "Absorption_Points" ) ]
   [ tDR = json.get( gmodv, "Max_Absorb" ) ]
   [ tDRtype = "Adamantine" ]

   [ jDR = json.get( DRER, "Damage Reduction" ) ]
   [ baseDR = json.get( jDR, tDRtype ) ]

   [ DRER = json.set( DRER, "Damage Reduction", json.set( jDR, tDRtype, tDR ) ) ]
   [ PrivateJSON = json.set( PrivateJSON, "msStoneskin", json.set( "{}", "val", baseDR, "type", tDRtype, "abPoints", abPoints, "maxAb", tDR ) ) ]

   [MACRO("subRecalcDR@this"): json.set( "{}", "Token", tToken ) ]
}]

@@pStoneskin
[H: cancel = input(
  "junk|Stoneskin||LABEL|SPAN=TRUE",
  "Caster_Level|" + Level + "|Caster Level|TEXT|WIDTH=2"
)]
[H: abort(cancel)]
[H, IF( !isNumber( Caster_Level ) ): Caster_Level = 7 ]
[H: abPoints = 10 * max(7,min(15,Caster_Level)) ]

[H: macro.return = json.set("{}","Caster_Level",Caster_Level,"Max_Absorb",10,"Absorption_Points",abPoints) ]
 
* For v05 you wouldn't need most of tmStoneskin. You would just need to only save Caster_Level, Max_Absorb and Absorption_Points in the macro. You won't have to fiddle with keeping track of the 10 DR.

And so I can account for reduction of points in stoneskin when taking damage I had to update the HPChange macro. I actually rewrote the whole macro for my own needs with new tooltip. There are some other components to this, like getting the GM name, but you can glean where the stoneskin part is. Also, I like the 2nd edition subdual rules so my nonlethal does 1/4 real damage. That can easily be removed by changing the 0.75 to 1 in the code below. Also, to set the GM name, put these lines in the onCampaignLoad at the beginning of token Lib:libDnD35Pathfinder:

Code: Select all

[h: gmNames = getLibProperty("gmNames")]
[h, if(json.isEmpty(gmNames)): gmNames = "[]"]
[h, if(isGM()), code: {
   [h: setLibProperty("gmNames",json.union(gmNames,json.fromList(getPlayerName())))]
};{
   [h: playerName = getPlayerName()]
   [h, if(json.contains(gmNames,playerName)): setLibProperty("gmNames",json.difference(gmNames,json.fromList(playerName)))]
}]
* As a side note, you should always save and have your startup page be the one with your lib files.
HPChange

Code: Select all

[H, if(json.isEmpty(macro.args)): mArgs = "{}"; mArgs = json.get(macro.args,0)]
[H: doinput = 0]
[H, if(json.type(mArgs) == "OBJECT"), code: {
   [H: page = json.get(mArgs,"Page")]
   [H, if(json.isEmpty(page)): page = "Main"]   
   [H: HPt = json.get(mArgs,"HPAmount")]
   [H, if(json.isEmpty(HPt)), code: {
      [H: doinput = 1]
      [H: HPt = -1]
   };{}]
   [H: HPtype = json.get(mArgs,"HPtype")]
   [H, if(json.isEmpty(HPtype)): HPtype = 1]
   [H, if(HPt == 0): HPtype = 4]
   [H: tToken = json.get(mArgs,"tToken")]
   [H, if(json.isEmpty(tToken)): tToken = currentToken(); switchToken( tToken ) ]
   [H: playerShow = json.get(mArgs,"playerShow")]
   [H, if(json.isEmpty(playerShow)): playerShow = 1]
};{
   [H: '<!-- Used for UDF call hpChange(HPAmount,HPtype,id,playerShow) -->' ]
   [H: page = "Main"]
   [H: numArgs = json.length(macro.args)]
   [H: HPt = json.get(macro.args,0)]
   [H, if(numArgs >= 2): HPtype = json.get(macro.args,1); HPtype = 1]
   [H, if(HPt == 0): HPtype = 4]
   [H, if(numArgs >= 3): tToken = json.get(macro.args,2); tToken = ""]
   [H, if(json.isEmpty(tToken)): tToken = currentToken(); switchToken( tToken ) ]
   [H, if(numArgs >= 4): playerShow = json.get(macro.args,3); playerShow = 1]
}]

[H, IF( doinput ), CODE: {
   [H: cancel = input(
      "HPt|0|# Hit Points| TEXT | WIDTH=4",
      "HPtype|Healing, Damage, Non-Lethal Damage, Non-Lethal Recovery|Change Type|RADIO|SELECT=1",
      "playerShow|Hide, Show, Detailed|Other Player Output|RADIO|ORIENT=H SELECT=" + playerShow
   )]
   [H: abort(cancel)]
   [H, if(HPt == 0): HPtype = 4]
}]
[H: spellData = "{}"]
[H: pJson = getProperty("PrivateJSON")]
[H: spellCheckList = "Stoneskin,Protection From Energy (Acid),Protection From Energy (Cold),Protection From Energy (Electricity),Protection From Energy (Fire),Protection From Energy (Sonic)"]
[H, foreach(spell,spellCheckList), code: {
   [H: tempData = json.get(pJson,"ms"+spell)]
   [H, if(!json.isEmpty(tempData)), code: {[H: spellData = json.set(spellData,spell,tempData)]};{}]
}]
[H: spellCheckList = json.fields(spellData)]

[H: '<!-- HP absorption only calculates against actual damage -->' ]
[H, IF( !json.isEmpty(spellData) && (HPtype == 1 || HPtype == 2)), CODE: {
   [H: inputParameters = json.append("",
      "junk|Enter the amount applied to absorptions below. Max Defaulted.||LABEL|SPAN=TRUE",
      "junk|*Note: Most spell absorptions do not stack.||LABEL|SPAN=TRUE")
   ]
   [H, foreach(spell,spellCheckList), code: {
      [H: spellAb = json.get(spellData,spell)]
      [H: maxAbsorb = min(HPt,json.get(spellAb,"maxAb"))]
      [H: curVal = json.get(spellAb,"abPoints")]
      [H, if(maxAbsorb < 0): maxAbsorb = curVal]
      [H: inputParameters = json.append(inputParameters,strformat("%s|%d|Damage absorbed by %s|TEXT|WIDTH=4",replace(spell,"[^a-zA-Z0-9]",""),maxAbsorb,spell))]
   }]
   [ inputParameters = json.toList(inputParameters,"##")]
   [ cancel = input( inputParameters  )]
   [H: abort(cancel)]
};{}]

[H: '<!-- Adjust absorption point totals and deactivate mod when reduced to 0 -->' ]
[H: tHPChange = HPt]
[H: totalAbsorbed = 0]
[H: tModReport = ""]
[H, if( HPType == 1 || HPType == 2 ): tempCheckList = spellCheckList; tempCheckList = "" ]
[H, foreach(spell,tempCheckList), code: {
   [H: spellAb = json.get(spellData,spell)]
   [H: maxAbsorb = min(tHPChange,json.get(spellAb,"maxAb"))]
   [H: curVal = json.get(spellAb,"abPoints")]
   [H, if(maxAbsorb == 0): maxAbsorb = min(curVal,tHPChange)]
   [H: inputName = replace(spell,"[^\\w]","")]
   [H: spellAbsorbed = max(0,min(maxAbsorb,eval(inputName)))]
   [H: curVal = curVal - spellAbsorbed]
   [H: totalAbsorbed = totalAbsorbed + spellAbsorbed]
   [H, IF(curVal > 0), code: {
      [H: '<!-- Update point totals locally -->' ]
      [H: spellAb = json.set(spellAb,"abPoints",curVal)]
      [H: spellData = json.set(spellData,spell,spellAb)]
   };{
      [H: spellData = json.remove(spellData,spell)]
      [H: spellCheckList = listDelete(spellCheckList,listFind(spellChecklist,spell))]
      [H: '<!-- Remove mod -->' ]
      [H, MACRO("subModToggle@Lib:libDnD35Pathfinder"): json.set( "{}", "tokenID", tToken, "setID", spell , "setType", 0 ) ]
      [H: tModReport = macro.return]
   }]
}]
[R, if(tModReport != ""): tModReport]
[H: '<!-- Finalize local changes globally for spell absorption -->' ]
[H: '<!-- Getting PrivateJSON again because data may have changed when removing mods -->' ]
[H: pJson = getProperty("PrivateJSON")]
[H, foreach(spell,spellCheckList), code: {
   [H: tempData = json.get(spellData,spell)]
   [H: pJson = json.set(pJson,"ms"+spell,tempData)]
}]
[H: setProperty("PrivateJSON",pJson)]
[H: '<!-- Update Hitpoint Totals -->' ]
[H, if(HPtype == 1 || HPtype == 2): tHPChange = tHPChange - totalAbsorbed]
[H: '<!-- Damage Reduction / Energy Resistance check -->' ]
[H: reduceDMG = 0 ]
[H, IF( tHPChange > 0 && DR != "" && (HPtype == 1 || HPType == 2)), CODE: {
   [H: inputParameters = json.append("",
      "junk|Damage Reduction / Energy Resistance exists!|drerx|LABEL|SPAN=TRUE",
      "junk|*Note: Most DR/ER does not stack with spell absorptions.|drerx|LABEL|SPAN=TRUE",
      "junk|" + HPt + "|Damage being Dealt|LABEL",      
      "junk|" + totalAbsorbed + "|Damage Absorbed by spell|LABEL",      
      "reduceDMG|0|Total Damage deflected by all DR/ER, not absorbed by spell|TEXT|WIDTH=4",
      "junk|DR/ER: " + DR + "|DR/ER|LABEL|SPAN=TRUE")
   ]
   [H: inputParameters = json.toList(inputParameters,"##")]
   [H: cancel = input( inputParameters  )]
   [H: abort(cancel)]
   [H: reduceDMG = min(tHPChange,abs( reduceDMG )) ]
};{}]
[H: '<!-- Update Hit point Totals from DR/ER -->' ]
[H, if(HPtype == 1 || HPtype == 2): tHPChange = tHPChange - reduceDMG]
[H: '<!-- Get current HP values to adjust -->' ]
[H: tHitPoints = getProperty("HP")]
[H: tHPmax = getProperty("HPmax")]
[H: tHPtemp = getProperty("HPtemp")]
[H: tHPNonLethalDMG = getProperty("HPNonLethalDMG")]
[H: tHPLethalChange = 0]
[H: tHPtempChange = 0]
[H: tNonLethalChange = 0]
[H: tHealingChange = 0]
[H: tNonLethalHealingChange = 0]
[H: '<!-- Update damage-->' ]
[H, if((HPtype == 1 || HPtype == 2) && tHPtemp > 0): tHPtempChange = min(tHPtemp,tHPChange)]
[H: tHPChange = tHPChange - tHPtempChange]
[H: tHPtemp = tHPtemp - tHPtempChange]
[H, if(HPtype == 1 || HPtype == 2), if(HPtype == 1): tHitPoints = tHitPoints - tHPChange; tHitPoints = tHitPoints - tHPChange + round(tHPChange * 0.75)]
[H: '<!-- Update non-lethal damage -->' ]
[H, if(HPtype == 2): tNonLethalChange = round(tHPChange * 0.75)]
[H: tHPChange = tHPChange - tNonLethalChange]
[H: tHPNonLethalDMG = tHPNonLethalDMG + tNonLethalChange]
[H: '<!-- Update healing -->' ]
[H, if(HPtype == 0): tHealingChange = min(tHPmax - tHitPoints, tHPChange)]
[H: tHitPoints = tHitPoints + tHealingChange]
[H, if(HPtype == 3 || HPtype == 0): tNonLethalHealingChange = min(tHPChange,tHPNonLethalDMG)]
[H: tNonLethalHealingChange = max(min(tHealingChange,tHPNonLethalDMG),tNonLethalHealingChange)]
[H: tHPNonLethalDMG = tHPNonLethalDMG - tNonLethalHealingChange]
[H: '<!-- tHPChange was used as a pool for hp change, in the end represents lethal damage remaining -->' ]
[H, if(HPtype != 1 && HPtype != 2): tHPChange = 0]
[H: '<!-- Finalize Changes on Token -->' ]
[H: setProperty("HP",tHitPoints)]
[H: setProperty("HPtemp",tHPtemp)]
[H: setProperty("HPNonLethalDMG",tHPNonLethalDMG)]
[H: 
'<!-- Summary of Formulas -->'
'<!-- HPt(damage) = Lethal(totalAbsorbed + reduceDMG + tHPtempChange + tHPChange) and Non-Lethal(reduceDMG + tHPtempChange + tNonLethalChange) -->'
'<!-- HPt(healing) ~ Lethal(tHealingChange) and Non-Lethal(tNonLethalHealingChange), extra healing is lost. -->'
'<!-- Update token states based on current change in hit points -->'
]
[H: tDieHard = val(getStrProp(Feats, "DieHard"))]
[H: effectiveHP = tHitPoints + tHPtemp ]
[H: sHPChange = max(tHealingChange,tNonLethalHealingChange) - tHPChange - tNonLethalChange ]
[H: tDeathPoint = eval(string(getLibProperty("DeathPoint","Lib:GlobalsSRDPF"))) ]
[H: oldConditionMatrix = (state.Dead * -1) + state.Staggered + (2 * state.Unconscious) + (4 * state.StableHP) + (8 * state.Disabled) + (16 * state.Dying) + (32*state.Prone) ]
[H: '<!-- Dead -->' ]
[H, if( effectiveHP <= tDeathPoint || state.Dead): t.Dead = 1; t.Dead = 0 ]
[H, if( !t.Dead ), code: {
   [H: '<!-- Staggered  -->' ]
   [H, if( (effectiveHP == tHPNonLethalDMG) && tHPNonLethalDMG > 0 ): state.Staggered = 1; state.Staggered = 0 ]
   [H: '<!-- Unconscious -->' ]
   [H, if( effectiveHP - tHPNonLethalDMG < 0): t.Unconscious = 1; t.Unconscious = 0 ]
   [H, if( effectiveHP < 0 && tDieHard && !state.Unconscious): state.Unconscious = 0; state.Unconscious = t.Unconscious ]
   [H: '<!-- StableHP -->' ]
   [H, if( (sHPChange > 0 || tDieHard) && effectiveHP < 0): state.StableHP = 1; state.StableHP = 0 ]
   [H: '<!-- Disabled -->' ]
   [H, if( (effectiveHP == 0 && !state.Unconscious) || (effectiveHP < 0 && !state.Unconscious && state.StableHP) ): state.Disabled = 1; state.Disabled = 0 ]
   [H: '<!-- Dying -->' ]
   [H, if( effectiveHP < 0 && !state.StableHP && effectiveHP > tDeathPoint ): state.Dying = 1; state.Dying = 0 ]
   [H: '<!-- Prone -->' ]
   [H, if( state.Unconscious ): state.Prone = 1 ]
};{
   [H: setAllStates(0)]
   [H: state.Dead = 1]
   [H: setLayer("OBJECT",currentToken())]
   [H: link = macroLinkText("deferSentToBack@this","none",currentToken())] 
   [H: execLink(link,1)]
}]
[H: '<!-- Set Hit Point Bars -->' ]
[H: tMaxEffectiveHP = tHPmax + tHPtemp]
[H: '<!-- Turn of unused bars -->' ]
[H: setBarVisible("HP",0)]
[H: setBarVisible("HPM",0)]
[H: setBarVisible("HPNonLethalDMG",0)]
[H: setBarVisible("HPMNonLethalDMG",0)]
[H: setBarVisible("HP",0)]
[H: setBarVisible("HPM",0)]
[H, if( state.Dead ), code: {
   [H: setBarVisible("HPdamage",0)]
   [H: setBarVisible("EmptyHP",0)]
};{
   [H, if( effectiveHP >= 0 ), code: {
      [H: bar.HPdamage = (tMaxEffectiveHP - effectiveHP) / tMaxEffectiveHP]
      [H: setBarVisible("EmptyHP",0)]
   };{
      [H: bar.HPdamage = max(0,(tDeathPoint - effectiveHP) / tDeathPoint) ]
      [H: bar.EmptyHP = 1]
   }]   
}]
[H, if( effectiveHP < 0 || state.Dead), code: { 
   [H: setBarVisible("NLD_HP",0) ]
   [H: setBarVisible("TempHP",0) ]
};{
   [H: bar.TempHP = bar.HPdamage + (tHPtemp / tMaxEffectiveHP) ]
   [H: bar.NLD_HP = tHPNonLethalDMG / tMaxEffectiveHP ]
}]

[H: '<!-- Condition State Summary -->' ]
[H: conditionMatrix = (state.Dead * -1) + state.Staggered + (2 * state.Unconscious) + (4 * state.StableHP) + (8 * state.Disabled) + (16 * state.Dying) ]
[H, switch(conditionMatrix), code: 
   case -1: { [h: tCondition = "Dead"] [h: tColor1 = "#708090"] };
   case 0: { [h: tCondition = "Healthy"] [h: tColor1 = "#90EE90"] };
   case 1: { [h: tCondition = "Staggered"] [h: tColor1 = "#F0E68C"] };
   case 2: { [h: tCondition = "Unconscious"] [h: tColor1 = "#C0C0C0"] };
   case 4: { [h: tCondition = "Stable"] [h: tColor1 = "#FF8C00"] };
   case 6: { [h: tCondition = "Stable"] [h: tColor1 = "#FF8C00"] };
   case 8: { [h: tCondition = "Disabled"] [h: tColor1 = "#6495ED"] };
   case 12: { [h: tCondition = "Disabled,Stable"] [h: tColor1 = "#6495ED"] };
   case 18: { [h: tCondition = "Dying,Unconscious"] [h: tColor1 = "#ff4040"] };
   default: { [h: tCondition = "Healthy("+conditionMatrix+")?"] [h: tColor1 = "#90EE90"] }
]
[H: '<!-- ===== Output and toolitp ===== -->' ]

[H: '<!-- Core Chat display -->' ]
[H, switch(HPtype), code:
   case 0: { [H: output = strformat("<b><font color=green>Healed %d hitpoints!</font></b>",tHealingChange))] };
   case 1: { [H: output = strformat("<b><font color=red>Takes %d hitpoints of damage!</font></b>",tHPChange))] };
   case 2: { [H: output = strformat("<b><font color=#FF8C00>Takes %d hitpoints of non-lethal damage!</font></b>",tNonLethalChange)] };
   case 3: { [H: output = strformat("<b><font color=blue>Recovers %d hitpoints of non-lethal damage!</font></b>",tNonLethalHealingChange)] };
   default: { [H: output = "<b>Condition Updated</b>"] }
]
[H: '<!-- Tooltip when taking damage -->' ]
[H: oTooltip1 = "[]"]
[H, if(HPtype == 1 || HPtype == 2):
   oTooltip1 = json.append("",
      "<tr><td colspan=2><b>Damage Report</b></td></tr>",
      strformat("<tr><td>Damage Taken</td><td>%s%s</td></tr>",tHPChange,if(tNonLethalChange != 0," <font color=#FF8C00>("+tNonLethalChange+")</font>","")),
      strformat("<tr><td>Spell Absorbed</td><td>%d</td></tr>",totalAbsorbed),
      strformat("<tr><td>DR/ER Absorbed</td><td>%d</td></tr>",reduceDMG),
      strformat("<tr><td>Temp HP Absorbed</td><td>%d</td></tr>",tHPtempChange))
]
[H: '<!-- Tooltip when being healed -->' ]
[H, if(HPtype == 0 || HPtype == 3):
   oTooltip1 = json.append("",
      "<tr><td colspan=2><b>Healing Report</b></td></tr>",
      strformat("<tr><td>Damage Healed</td><td>%d</td></tr>",tHealingChange),
      strformat("<tr><td>Non-lethal Healed</td><td>%d</td></tr>",tNonLethalHealingChange))
]
[H: '<!-- Extra detailed info for owners -->' ]
[H: oTooltip2 = json.append("",
   "<tr><td colspan=2><b>Condition Report</b></td></tr>",
   strformat("<tr><td>Current Condition</td><td style='background-color:%s;text-align:center'>%s</td></tr>",tColor1,tCondition),
   strformat("<tr><td>Max Hit Points</td><td>%d</td></tr>",tHPmax),
   strformat("<tr><td>Real Hit Points</td><td>%d</td></tr>",tHitPoints),
   strformat("<tr><td>Remaining Temp HP</td><td>%d</td></tr>",tHPtemp),
   strformat("<tr><td>Non-lethal taken</td><td>%d</td></tr>",tHPNonLethalDMG),
   strformat("<tr><td>Real Damage taken</td><td>%d</td></tr>",tHPmax - tHitPoints),
   strformat("<tr bgcolor=%s><td><b><i>Effective HP Remaining</b></i></td><td><font size='+1'><b>%d</b></font></td></tr>",tColor1,effectiveHP - tHPNonLethalDMG))
]

[H: '<!-- Extra spell & DR/ER info for owners -->' ]
[H, if((spellCheckList != "" || DR != "")), code: {
   [H: oTooltip3 = json.append("","<tr><td colspan=2><b>Spell & DR/ER Report</b></td></tr>")]   
   [H, foreach(spell,spellCheckList), code: {
      [H: tempData = json.get(spellData,spell)]
      [H: oTooltip3 = json.append(oTooltip3,strformat("<tr><td>%s</td><td>%d</td></tr>",spell,json.get(tempData,"abPoints")))]
   }]
   [H: tDRER = getProperty("DRER")]
   [H: tDR = json.get(tDRER,"Damage Reduction")]
   [H: tDRList = json.fields(tDR)]
   [H, foreach(iDR,tDRList), code: {
      [H: tempData = json.get(tDR,iDR)]
      [H, if(iDR != "Note" && tempData != 0): oTooltip3 = json.append(oTooltip3,strformat("<tr><td>%s</td><td>%s</td></tr>",iDR,tempData+" DR"))]
   }]
   [H: tER = json.get(tDRER,"Energy Resistance")]
   [H: tERList = json.fields(tER)]
   [H, foreach(iER,tERList), code: {
      [H: tempData = json.get(tER,iER)]
      [H, if(iER != "Note" && tempData != 0): oTooltip3 = json.append(oTooltip3,strformat("<tr><td>%s</td><td>%s</td></tr>",iER,tempData+" ER"))]
   }]
};{
   [H: oTooltip3 = "[]"]
}]

[H: '<!-- Combine detailed and basic tooltips -->' ]
[H: tHead = json.append("",'<span title="<html><table>')]
[H, if(playerShow == 2): tHead = json.append(tHead,'<tr bgcolor=#FFA07A><td colspan=2 align=center><b>Player Detailed Report</b></td></tr>')]
[H: tFoot = json.append("",'</table></html>">',output,"</span>")]
[H: outputDetailed = json.merge(tHead,oTooltip1,oTooltip2,oTooltip3,tFoot)]
[H: outputDetailed = json.toList(outputDetailed,"")]
[H: outputBasic = json.merge(tHead,oTooltip1,tFoot)]
[H: outputBasic = json.toList(outputBasic,"")]
[H: '<!-- Display output to each player based on ownership -->' ]
[H: tGM = getLibProperty("gmNames")]
[H: tPlayers = getAllPlayerNames()]
[H, if(isOwnedByAll()): tOwners = tPlayers; tOwners = getOwners()]
[H, if(json.isEmpty(tOwners)): tOwners = tGM; tOwners = json.union(json.fromList(tOwners),tGM)]
[H: tPlayers = json.fromList(tPlayers)]
[H: tPlayers = json.difference(tPlayers,tOwners)]
[H, if(!token.visible): playerShow = 0]
[R,W(tOwners): outputDetailed]
[R, if(playerShow > 0 && !json.isEmpty(tPlayers) && !(HPtype == 4 && playerShow == 1)), code: {
   [R,W(tPlayers): if(playerShow == 2,outputDetailed,outputBasic)]
};{}]
[H: '<!-- Update Character if open -->' ]
[H, IF( isFrameVisible( token.name ) ), CODE: {
   [H: callback = "CharSheet@"+getMacroLocation()]
   [H: link = macroLinkText( callback, "self", "Page="+page + " ; Token=" + tToken ) ]
   [H: execLink( link, 1 ) ]
};{}]
If no one else ends up doing this I'll eventually get to it for v05, but probably not very soon.

User avatar
lmarkus001
Great Wyrm
Posts: 1867
Joined: Sat Mar 29, 2008 12:30 am
Location: Layfayette Hill, PA

Re: [MOD] Additional Conditions

Post by lmarkus001 »

Another caution with these mods is the Black Tentacles token/macros. They use the Grappled state. So they will apply/remove the state (but won't apply/remove the mod-set). They apply Grappled penalties internally, so if you apply the Grappled mod-set, then get hammered with a Black Tentacle, you will suffer double penalties! I don't think I want to add mod-set toggling into the EBT macros as they are quite slow enough already (they can take upwards of 2 minutes to run on a big crowd... which is still TONS faster than I have ever seen EBT processed in any live table game).

This is a specialty case, but I figured I should mention it.

Oh yeah, HPChange uses the states Staggered and Prone as well. So use them with mod-sets with caution.
Last edited by lmarkus001 on Thu Jan 06, 2011 2:36 pm, edited 1 time in total.

User avatar
lmarkus001
Great Wyrm
Posts: 1867
Joined: Sat Mar 29, 2008 12:30 am
Location: Layfayette Hill, PA

Re: [MOD] Additional Conditions

Post by lmarkus001 »

Dazzled.

Hummm... I have a vision type: Dazzled, that is basically 1/2 Normal. Now I can't remember where I found information that would make me create such a vision type. If I can find justification, I can make the Dazzled mod-set change the token's vision (like what I do with Blind).

User avatar
Paradox
Dragon
Posts: 724
Joined: Fri Feb 27, 2009 4:01 pm

Re: [MOD] Additional Conditions

Post by Paradox »

lmarkus001 wrote:Dazzled.

Hummm... I have a vision type: Dazzled, that is basically 1/2 Normal. Now I can't remember where I found information that would make me create such a vision type. If I can find justification, I can make the Dazzled mod-set change the token's vision (like what I do with Blind).

Lindsay,

AWESOME TO SEE YOU ACTIVE AGAIN. :)

In Pathfinder the Dazzled condition consists only of a -1 to attack rolls and a -1 to the Perception skill check.

Rule citation for conditions:

http://paizo.com/pathfinderRPG/prd/glos ... ml#dazzled

Just scroll down.
I no longer believe that MapTools is usuable or intended just for programmers. MapTools is for everyone.

User avatar
lmarkus001
Great Wyrm
Posts: 1867
Joined: Sat Mar 29, 2008 12:30 am
Location: Layfayette Hill, PA

Re: [MOD] Additional Conditions

Post by lmarkus001 »

Yeah 3.5 uses same Dazzled rules, but I thought I found somewhere that it could also be half vision distance... /shrug... maybe just a house rule I was using :-)

My wife is going to be running Pathfinder so I think we will finally see those Polymorph mods happen :-)

User avatar
Paradox
Dragon
Posts: 724
Joined: Fri Feb 27, 2009 4:01 pm

Re: [MOD] Additional Conditions

Post by Paradox »

Your wife is a goddess, and you are a gentleman!

Seriously, its a good update on 3.5. I've never wanted to cajole you into conversion, but I think you'd like it.

I may be a devoted fan, but Neo has done some great follow up work, as well as others... Who will forgive me if I don't list exhaustively.

(i.e. Azhrei's templates and many many others)
I no longer believe that MapTools is usuable or intended just for programmers. MapTools is for everyone.

neofax
Great Wyrm
Posts: 1694
Joined: Tue May 26, 2009 8:51 pm
Location: Philadelphia, PA
Contact:

Re: [MOD] Additional Conditions

Post by neofax »

I would love for a update to the mod-sets to include CMB/CMD and skills. Later, I wish it could handle attacks so that everything is basically a mod-set and can be manipulated via the mod-set macros. Also, I am glad to see you back!

Post Reply

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