[MOD] LibAttack and Attack (MT1.3b82 r01)

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
User avatar
aliasmask
RPTools Team
Posts: 9024
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

[MOD] LibAttack and Attack (MT1.3b82 r01)

Post by aliasmask »

I'm not sure what has been modified since the first release, but this mod assumes no other modifications to LibAttack and Attack. So, if you have done changes already, then this will remove those in place of the ones I have done. If you want me integrate your changes just post the file and give me a small description of what you have done. I actually plan to reformat the output sometime in the near future, but this is a quick update.
  • Concealment Miss Chance - This adds the option to display text to confirm a miss against a target with concealment. This will also suppress the option to confirm a critical hit, as per concealment rules.
    HIT: 24, 42, 30, 24, 34 #1! (50%: 93) . . . FUMBLE! (swing# 1) #2! (50%: 95) MISS #3! (50%: 3) MISS #4! (50%: 42) . . . FUMBLE! (swing# 4) #5! (50%: 80) ( Shock )
    DMG: 7, 8, 1, 6, 6
I will update the original post as I apply more mods to the attack system. I use RPedit formatting for use with Notepad++. You can cut/paste selected text and remove top 2 lines and bottom line and apply directly to macro.
||| LibAttack |||

Code: Select all

@@ @LibAttack
@PROPS@ fontColor=black;autoExecute=true;fontSize=1.00em;sortBy=5;color=darkgray;playerEditable=false;applyToSelected=true;group=Combat;tooltip=;minWidth=94
[H, IF( json.type( macro.args ) == "UNKNOWN" ), CODE: {
   [ varsFromStrProp(eval(macro.args))]
   [ fullRound = 1 ]
   [ flanking = 0 ]
   [ higherGround = 0 ]
   [ rangeIncrement = 0 ]
   [ isPointBlank = 0 ]
   [ fireIntoMelee = 0 ]
   [ sneak = "0d6" ]
   [ isSneak = 0 ]
   [ sneakDMG = 0 ]
   [ favEnemy = 0 ]
   [ flurryRapid = 1 ]
   [ target1Name = "" ]
   [ target1ID = "" ]
   [ target2Name = "" ]
   [ target2ID = "" ]
   [ flagSecret = 0 ]
   [ tempATK = 0 ]
   [ tempDMG = 0 ]
   [ concealMiss = 0]
};{
   [ tWeapon = json.get( macro.args, "weapon" ) ]
   [ varsFromStrProp(eval(tWeapon))]
   [ fullRound = json.get( macro.args, "fullRound" ) ]
   [IF( json.isEmpty( fullRound ) ): fullRound = 1 ]
   [ flanking = json.get( macro.args, "flanking" ) ]
   [IF( json.isEmpty( flanking ) ): flanking = 0 ]
   [ higherGround = json.get( macro.args, "higherGround" ) ]
   [IF( json.isEmpty( higherGround ) ): higherGround = 0 ]
   [ rangeIncrement = json.get( macro.args, "rangeIncrement" ) ]
   [IF( json.isEmpty( rangeIncrement ) ): rangeIncrement = 0 ]
   [ isPointBlank = json.get( macro.args, "pointBlank" ) ]
   [IF( json.isEmpty( isPointBlank ) ): isPointBlank = 0 ]
   [ fireIntoMelee = json.get( macro.args, "fireIntoMelee" ) ]
   [IF( json.isEmpty( fireIntoMelee ) ): fireIntoMelee = 0; fireIntoMelee = -4 * fireIntoMelee ]
   [ sneak = json.get( macro.args, "sneak" ) ]
   [IF( json.isEmpty( sneak ) ): sneak = "0d6" ]
   [ isSneak = if( sneak == "0d6" || sneak == 0, 0, 1 ) ]
   [ favEnemy = json.get( macro.args, "favEnemy" ) ]
   [IF( json.isEmpty( favEnemy ) ): favEnemy = 0 ]
   [ flurryRapid = json.get( macro.args, "flurryRapid" ) ]
   [IF( json.isEmpty( flurryRapid ) ): flurryRapid = 1 ]
   [ target1Name = json.get( macro.args, "target1Name" ) ]
   [IF( json.isEmpty( target1Name ) ): target1Name = "" ]
   [ target1ID = json.get( macro.args, "target1ID" ) ]
   [IF( json.isEmpty( target1ID ) ): target1ID = "" ]
   [ target2Name = json.get( macro.args, "target2Name" ) ]
   [IF( json.isEmpty( target2Name ) ): target2Name = "" ]
   [ target2ID = json.get( macro.args, "target2ID" ) ]
   [IF( json.isEmpty( target2ID ) ): target2ID = "" ]
   [ flagSecret = json.get( macro.args, "flagSecret" ) ]
   [IF( json.isEmpty( flagSecret ) ): flagSecret = 0 ]
   [ tempATK = json.get( macro.args, "tempATK" ) ]
   [IF( json.isEmpty( tempATK ) ): tempATK = 0 ]
   [ tempDMG = json.get( macro.args, "tempDMG" ) ]
   [IF( json.isEmpty( tempDMG ) ): tempDMG = 0 ]
   [ concealMiss = json.get( macro.args, "concealMiss" ) ]
   [IF( json.isEmpty( concealMiss ) ): concealMiss = 0 ]
}]

[H: gTok = "Lib:GlobalsSRDPF" ]
[H: system = getLibProperty("System", gTok)]
[H, SWITCH(system), CODE:
   case "Pathfinder": {
      [ padaID = "Power Attack/Deadly Aim" ]
      [ pa2H = 1.5 ]
      [ paMultiplier = 2 ]
      [ paOffhand = 0.5 ]
   };
   case "D&D3.5": {
      [ padaID = "Power Attack" ]
      [ pa2H = 2 ]
      [ paMultiplier = 1 ]
      [ paOffhand = 0 ]      
   };
   default: {
      [ padaID = "Power Attack" ]
      [ pa2H = 2 ]
      [ paMultiplier = 1 ]
      [ paOffhand = 0 ] 
   }
]

[H: aTMS = json.get( PrivateJSON, "ActiveTempModSets" ) ]
[H, IF( json.type( aTMS ) == "UNKNOWN" ), CODE: {
   [ PrivateJSON = json.set( PrivateJSON, "ActiveTempModSets", "[]" ) ]
   [ aTMS = "[]" ]
}]
[H: paON = if( json.contains( aTMS, padaID ) > 0, 1, 0 ) ]
[H, IF( paON ): paDMG = floor( paMultiplier * json.get( json.get( json.get( json.get( json.get( PrivateJSON, "CustomModSetValues" ), padaID ), "mods" ), "globalMod" ), "v" ) ); paDMG = 0 ]

[H: tWeaponFinesse = getStrProp(Feats, "WeaponFinesse")]
[H: tWeaponFinesse = if(tWeaponFinesse == "", 0, tWeaponFinesse)]
[H: tTwoWeaponFighting = getStrProp(Feats, "TwoWeaponFighting")]
[H: tTwoWeaponFighting = if(tTwoWeaponFighting == "", 0, tTwoWeaponFighting)]
[H: tImprovedTwoWeaponFighting = getStrProp(Feats, "ImprovedTwoWeaponFighting")]
[H: tImprovedTwoWeaponFighting = if(tImprovedTwoWeaponFighting == "", 0, tImprovedTwoWeaponFighting)]
[H: tGreaterTwoWeaponFighting = getStrProp(Feats, "GreaterTwoWeaponFighting")]
[H: tGreaterTwoWeaponFighting = if(tGreaterTwoWeaponFighting == "", 0, tGreaterTwoWeaponFighting)]
[H: tMultiAttack = getStrProp(Feats, "MultiAttack")]
[H: tMultiAttack = if(tMultiAttack == "", 0, tMultiAttack)]
[H: tPointBlankShot = getStrProp(Feats, "PointBlankShot")]
[H: tPointBlankShot = if(tPointBlankShot == "", 0, tPointBlankShot)]
[H: tManyShot = getStrProp(Feats, "ManyShot")]
[H: tManyShot = if(tManyShot == "", 0, tManyShot)]
[H: tCriticalFocus = getStrProp(Feats, "CriticalFocus")]
[H: tCriticalFocus = if(tCriticalFocus == "", 0, tCriticalFocus)]
[H: jCombat = json.get(PrivateJSON, "Combat")]
[H, IF( json.isEmpty( jCombat ) ): tMagicExtraAttack = 0; tMagicExtraAttack = json.get( jCombat, "magicExtraAttack" ) ]
[H, IF( !isNumber( tMagicExtraAttack ) ): tMagicExtraAttack = 0 ]

[H: rangeMod = if( rangeIncrement == 0, if( tPointBlankShot && isPointBlank, 1, 0 ), -2 * ( rangeIncrement ) ) ]

[H: FAN = max( 1, floor((BAB - 1) / 5) + 1 ) ]
[H: tHaste = if((Primary == 1) && (state.Haste || tMagicExtraAttack == 1 ), 1, 0)]
[H: isFlurryRapid = if( flurryRapid <= 0 && Manufactured == 1, 1, 0 ) ]

[H: MultAtkMP = if(Manufactured == 1, -6 + (tTwoWeaponFighting * 2), 0)]
[H: MultAtkM = if(Manufactured == 1, -10 + (tTwoWeaponFighting * 6), -5 + (tMultiAttack * 3))]

[H: temp1 = ""]
[H: temp2 = ""]
[H: temp3 = ""]
[H: temp4 = ""]
[H: temp5 = ""]
[H: atkDecay = if((Primary == 1 || ( Primary == 2 && ( tImprovedTwoWeaponFighting || tGreaterTwoWeaponFighting))) && (Manufactured == 1) && fullRound, 1, 0)]
[H: numAtk = if(atkDecay && fullRound, FAN + tHaste + isFlurryRapid, if( !fullRound, 1, Quantity + tHaste + isFlurryRapid ) )]
[H, IF( Primary == 2 && atkDecay ): numAtk = min( FAN, if( tGreaterTwoWeaponFighting, 3, 2 ) ) ]
[H: atkMult = if(OHLight == 2, 0, If(Primary == 1, min(0, max(MultAtkMP, MultAtkMP+(OHLight*2))), min(0, max(MultAtkM, MultAtkM+(OHLight*2)))))]
[H: atkMult = if( fullRound, atkMult, 0 ) ]
[H: atkStatB = if(Ranged == 1, DexB, if(tWeaponFinesse == 1 && Finesse == 1, max(StrB, DexB), StrB))]
[H: dmgStatB = min(DmgBonusCap, if(TwoHanded == 1, Str2hB + if( Ranged == 1, 0, floor(paDMG*pa2H)), if(Primary == 2,floor(StrSecB + if( Ranged == 1, 0,(paDMG*paOffhand))),StrB + if( Ranged == 1, 0, paDMG))))]
[H, C(numAtk, ""): eval("result1" + roll.count + "= 1d20")]
[H, C(numAtk, ""): eval("result1c" + roll.count + "= 1d20")]
[H, C(numAtk, ""): eval("damage1" + roll.count + "= " + Damage)]
[H, C(numAtk, ""): eval("damage1c" + roll.count + "= " + Damage)]
[H, C(numAtk, ""): eval("damage2c" + roll.count + "= " + Damage)]
[H, C(numAtk, ""): eval("damage3c" + roll.count + "= " + Damage)]

[H, C(numAtk, ""): temp1 = temp1 
   + eval("eval('result1' + roll.count) + BAB -(atkDecay*5*max(0,(roll.count - if(tHaste && fullRound,1,0) - if(isFlurryRapid && fullRound, 1, 0)))) + atkMult + SizeM + atkStatB + eval('0 + ' + AtkBonus) + MiscATK + tempATK + if( Ranged, rangeMod + fireIntoMelee, 0 ) + if( isflurryRapid && fullRound, flurryRapid, 0 ) + if( system == 'Pathfinder', favEnemy, 0 ) + higherGround + ( flanking * 2 )") 
   + if(tHaste && fullRound && roll.count == 0," <i><font color='red'>(Haste)</font></i>","")
   + if(isFlurryRapid && fullRound && ((tHaste && roll.count == 1) || (!tHaste && roll.count == 0)), if( Ranged, " <i><font color=black>(Rapid Shot)</font></i>", " <i><font color=black>(Flurry of Blows)</font></i>" ), "") 
   + if(numAtk != roll.count + 1, ", ", "")
]
[H, C(numAtk, ""), code: {
   [H: missCheck = 1d100]
   [H: concealMissText = ""]
   [H, if(concealMiss && concealMiss >= missCheck): concealMissText = strformat(" <b>MISS #%s! (%s%: <font color=red>%s</font>)</b>",roll.count+1,concealMiss,missCheck)]
   [H, if(concealMiss && concealMiss < missCheck): concealMissText = strformat(" <b>#%s! (%s%: <font color=blue>%s</font>)</b>",roll.count+1,concealMiss,missCheck)]
   [H: rollResult = eval("result1" + roll.count)]
   [H: temp2 = temp2 + concealMissText + if( AtkBonus != "*" && rollResult >= CritRange && !concealMiss, 
      "  <i>. . .  CRIT! " + if( numAtk > 1, "(swing# " + (roll.count + 1) + ") ", "") + "-> </i>" + eval("eval('result1c' + roll.count)+BAB-(atkDecay*5*max(0,(roll.count - if(tHaste && fullRound,1,0) - if(isFlurryRapid && fullRound, 1, 0))))+atkMult+SizeM+atkStatB+ eval('0 + ' + AtkBonus) +MiscATK + tempATK + if( Ranged, rangeMod + fireIntoMelee, 0 ) + if( isflurryRapid && fullRound, flurryRapid, 0 ) + if( system == 'Pathfinder', favEnemy, 0 ) + higherGround + ( flanking * 2 ) + if( tCriticalFocus, tCriticalFocus*4, 0 )"), 
      if(rollResult == 1, "  <i>. . .  FUMBLE! " + if(numAtk > 1, "(swing# " + (roll.count + 1) + ") ", "") + "</i>", "")))
   ]
}]
 
[H, C(numAtk, ""): temp3 = temp3
   + eval("max(1, eval('damage1' + roll.count) + dmgStatB + MiscDMG + tempDMG + if( Ranged, max( 0, rangeMod ) + if( system == 'Pathfinder', paDMG, 0 ), 0 ))")
   + if( DmgExtra == "0d6" || DmgExtra == "" || DmgExtra == "0", "", " + " + eval("0 + " + DmgExtra) + " <i>" + DmgExtraName + "</i>")
   + if( favEnemy > 0, " + " + favEnemy + " <font size=2>Favored Enemy</font>", "" )
   + if( isSneak && ( ( Ranged && isPointBlank ) || !Ranged ), " + " + eval( "" + sneak ) + " <font size=2>Sneak (" + sneak + ")</font>", "" )
   + if( numAtk != roll.count+1, ", ", "")
]
[H, C(numAtk, ""): temp4 = temp4 
   + if( AtkBonus != "*" && eval("result1" + roll.count) >= CritRange && !concealMiss, "  <i>. . .  CRIT! " + if(numAtk > 1, "(swing# " + (roll.count + 1) + ") ", "") + "-> </i>" 
   + eval("eval('damage1c' + roll.count) + dmgStatB + MiscDMG + tempDMG + if( Ranged, max( 0, rangeMod ) + if( system == 'Pathfinder', paDMG, 0 ), 0 )") 
   + if(CritMult > 2,  " + " + eval("eval('damage2c' + roll.count) + dmgStatB + MiscDMG"),"")  
   + if(CritMult > 3,  " + " + eval("eval('damage3c' + roll.count) + dmgStatB + MiscDMG"),"")  
   + if(DmgExtraCrit == "0d10" || DmgExtraCrit == "" || DmgExtraCrit == "0", "", " + " + eval("0 + " + DmgExtraCrit) * (CritMult - 1) + " <i>" + DmgExtraName + "</i>")
, "")]
[H, C(1, ""): temp5 = temp5 
   + if( tManyShot, "  <b>Many Shot DMG: </b>" 
   + eval("eval(Damage) + dmgStatB + MiscDMG + tempDMG + if( Ranged, max( 0, rangeMod ) + if( system == 'Pathfinder', paDMG, 0 ), 0 )")
   + if( favEnemy > 0, " + " + favEnemy + " <font size=2>Favored Enemy</font>", "" )
, "")]

[H: AtkString1 = "<b>HIT:</b> "+ if(AtkBonus == "*","",temp1 + temp2 + " ") + "  (<i> " + Name + " </i>)<br/><b>DMG:</b>  " + temp3 + temp4 + "<br />" + temp5]

[H: atkList = ""]
[H,C(numAtk, ""): atkList = atkList + if(roll.count != 0, ",", "") + eval("result1" + roll.count)]
[H: critList = ""]
[H,C(numAtk, ""): critList = critList + if(roll.count != 0, ",", "") + eval("result1c" + roll.count)]
[H: atkList = "<font size= 3>ATK Rolls:<b> " + atkList + " </b>BAB:<b> " + BAB + " </b>MultiAtk:<b> " + atkMult + " </b>Size:<b> " + SizeM + " </b>StatBonus:<b> " + atkStatB + " </b>AtkBonus:<b> " + AtkBonus + " </b>CritThreat:<b> " + CritRange + " </b>Misc:<b> " + MiscATK + " </b>Temp:<b> " + tempATK + if( Ranged, " </b>RangeMod:<b> " + rangeMod + if( fireIntoMelee != 0, " </b>ShootIntoMelee:<b> " + fireIntoMelee, ""), "" ) + if( isFlurryRapid && fullRound, " </b>" + if(Ranged, "Rapid Shot", "Flurry of Blows") + ":<b> " + flurryRapid, "" ) + if( flanking, " </b>Flanking:<b> 2", "" ) + if( higherGround, " </b>Higher Ground:<b> 1", "" ) + if( system == 'Pathfinder' && favEnemy > 0, " </b>FavoredEnemy:<b> " + favEnemy, "" ) + "</b></font><br />"]
[H: atkList = atkList + "<font size= 3>CritRolls:<b> " + critList + "</b></font><br />" ]

[H: dmgList = ""]
[H,C(numAtk, ""): dmgList = dmgList + if(roll.count != 0, ",", "") + eval("damage1" + roll.count)]
[H: dmgList = "<font size= 3>DMG Rolls:<b> " + dmgList + " </b>DamageDice:<b> " + Damage 
   + " </b>StatBonus" + if( Ranged != 1 && paON, '<i><font color="red">+PowerAttack</font></i>', "" ) + ":<b> " + dmgStatB 
   + if( Ranged && paON && system == "Pathfinder", ' <i><font color="red">DeadlyAim</font>:</i> ' + paDMG, "" )
   + " </b>MiscDMG:<b> " + MiscDMG + " </b>TempDMG:<b> " + tempDMG 
   + if(DmgExtra == "0d6" || DmgExtra == "" || DmgExtra == "0", "", " </b>ExtraDMG:<b> " + DmgExtra + " </b>ExtraDMGType: <b>" + DmgExtraName )
   + if(DmgExtraCrit == "0d10" || DmgExtraCrit == "" || DmgExtraCrit == "0", "", " </b>CritDMG:<b> " + DmgExtraCrit )
   + " </b>CritMultiplier:<b> " + CritMult 
   + if( Ranged, " </b>RangeMod:<b> " + max( 0, rangeMod ), "" ) 
   + "</b></font><br />"
]

[H: targString = "" ]
[H: targString = if( target1Name == "", "", "<b>Primary Target: </b>" + target1Name ) ]
[H: targString = targString + if( target2Name == "", "", " -- <b>Secondary Target: </b>" + target2Name ) ]
[H: targString = targString + if( target1Name == "", "", "<br>" ) ]

[H, IF( target1ID != "" ), TOKEN( target1ID ): targ1Image = '<img src="' + getTokenImage() + '" width="50" height="50">'; targ1Image = "" ]
[H, IF( target2ID != "" ), TOKEN( target2ID ): targ2Image = '<img src="' + getTokenImage() + '" width="50" height="50">'; targ2Image = "" ]

[H: output = if( Primary != 0, targString + AtkString1, "" ) ]
[H: outputwTip = "<span title='<html>" + targ1Image +  targ2Image + if(  target1ID != "" || target2ID != "" , "<br> ", " " ) + atkList + " " + dmgList + " </html>'>" + output + "</span>"]

[H, MACRO( "subGetAllOtherPCPlayers@this" ): "" ]
[H: allOtherPC = macro.return ]

[IF( flagSecret && isGM() ), CODE: 
  {
      [R, G: outputwTip ]
  };{}
]
[IF( flagSecret && !isGM() ), CODE: {
      [R, S, G: outputwTip ]
    };{}
]
[IF( !flagSecret ), CODE: {
      [R, W( allOtherPC ): output ]
      [R, S, G: outputwTip ]
   };{}
]

!!
||| Attack |||

Code: Select all

@@ @Attack
@PROPS@ fontColor=black;autoExecute=true;fontSize=1.00em;sortBy=7;color=gray;playerEditable=false;applyToSelected=true;group=Combat;tooltip=;minWidth=40
[H, IF( json.type( macro.args ) == "UNKNOWN" ), CODE: { 
   [ weaponID = macro.args ]
   [ flagSecret = 0 ]
};{
   [ weaponID = json.get( macro.args, "weaponID" ) ]
   [ flagSecret = json.get( macro.args, "flagSecret" ) ]
   [IF( json.isEmpty( flagSecret ) ): flagSecret = 0 ]
   [ numWeapChoice = json.get( macro.args, "numWeapChoice" ) ]
   [IF( json.isEmpty( numWeapChoice ) ): numWeapChoice = 10 ]
} ]
[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" ) ) ]
   };
   case "D&D3.5": {
      [ meleeMods = table( "SysVars", json.get( table( "SysVars", 0 ), "meleeModsSRD" ) ) ]
   };
   default: {
   }
]

[H: tToken = currentToken() ]

[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  ) ]
   [ PrivateJSON = json.set( PrivateJSON, "CombatConfig", jCC ) ]
}] 
[H: inCC = 
   "fullRound|Single, Full Round|Attack|RADIO|ORIENT=H SELECT=1 ##"
   + "concealMiss|0,20,50|Concealment Miss Chance|RADIO|ORIENT=H VALUE=STRING ##"
   + "flagSecret|" + flagSecret + "|<html><font color=red>Secret</font>?</html>|CHECK| ##"
   + "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| ##"
   + "flurryRapid|-2, -1, 0, Normal Attack|Flurry of Blows/Rapid Shot Attack *|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" ) + "|Shoot/Throw into Melee (-4)?|CHECK| ##"
   + "favEnemy|" + json.get( jCC, "favEnemy" ) + "|Favorite Enemy Bonus|TEXT|WIDTH=10" + "##"
   + "sneak|" + json.get( jCC, "sneak" ) + "|Sneak Attack Damage|TEXT|WIDTH=10"
]

[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(20, ""): 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 ): visTokens = json.append( visTokens, json.set( "{}", "name", getName(i), "id", i, "range", getDistance(i) ) ) ]
[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: PrivateJSON = json.set( PrivateJSON, "CombatConfig", json.set( "{}", "fullRound", fullRound, "rangeIncrement", rangeIncrement, "pointBlank", pointBlank, "flurryRapid", flurryRapid, "favEnemy", favEnemy, "sneak", sneak, "fireIntoMelee", fireIntoMelee ) ) ]

[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, FOREACH( n, json.fields( jMM, "json" ) ), 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 ) ]
   };{}]
}]
   
[IF(weaponID == ""), CODE: {
   [C(numWeapChoice,""), IF( eval("Weap" + roll.count) == "" || eval("Weap" + roll.count) == 0), CODE: {
   };{
      [MACRO("LibAttack@this"): json.set("{}", "weapon", ("Weapon" +(eval("Weap" + roll.count) - 1)), "fullRound", fullRound, "flanking", flanking, "higherGround", higherGround, "favEnemy", favEnemy, "rangeIncrement", rangeIncrement, "pointBlank", pointBlank, "fireIntoMelee", fireIntoMelee, "sneak", sneak, "flurryRapid", flurryRapid, "target1Name", target1Name, "target1ID", target1ID, "target2Name", target2Name, "target2ID", target2ID, "flagSecret", flagSecret, "tempATK", tempATK, "tempDMG", tempDMG, "concealMiss", concealMiss ) ]
   }]
};{
   [MACRO("LibAttack@this"): json.set("{}", "weapon", weaponID, "fullRound", fullRound, "flanking", flanking, "higherGround", higherGround, "favEnemy", favEnemy, "rangeIncrement", rangeIncrement, "pointBlank", pointBlank, "fireIntoMelee", fireIntoMelee, "sneak", sneak, "flurryRapid", flurryRapid, "target1Name", target1Name, "target1ID", target1ID, "target2Name", target2Name, "target2ID", target2ID, "flagSecret", flagSecret, "tempATK", tempATK, "tempDMG", tempDMG, "concealMiss", concealMiss ) ]
}]

!!
PS. Anyone know what LibAttackW is used for?

jsharen
Giant
Posts: 196
Joined: Tue Feb 05, 2008 3:39 pm

Re: [MOD] LibAttack and Attack (MT1.3b82 r01)

Post by jsharen »

Aliasmask,
Is it easy for you to modify the field for miss chance to be a number?

If 0 (default) there is no miss chance, otherwise the number is the % to miss?

I am starting to come across a LOT of different miss % numbers, I originally thought there were only a few in my experience.

Cheers!

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

Re: [MOD] LibAttack and Attack (MT1.3b82 r01)

Post by aliasmask »

Well, since the results don't really have any in game results, just putting any percentage will give the result and you can determine from there if it's a hit or miss. I think having a text box instead of a radio button would accomplish what you need though.

Change this part of this line in the "Attack" macro:

Code: Select all

+ "concealMiss|0,20,50|Concealment Miss Chance|RADIO|ORIENT=H VALUE=STRING ##"
to

Code: Select all

+ "concealMiss|0|Concealment Miss Chance|TEXT ##"
to have a textbox instead. For 3.5, I think there are some classes or special rules that have different percentages, but 99% of the time, 20% or 50% should be enough. I think it would be a pain to actually type the percent out, so I'm going to leave my code alone in that respect. I had a hard enough time getting my players to remember to click it when needed.

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

Re: [MOD] LibAttack and Attack (MT1.3b82 r01)

Post by neofax »

@Aliasmask: Does this change the original output & outputwTip format by only adding in the miss chance? The reason I ask, is I like the original output but would like to incorporate the miss chance now that I am starting to DM higher level play.

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

Re: [MOD] LibAttack and Attack (MT1.3b82 r01)

Post by aliasmask »

neofax wrote:@Aliasmask: Does this change the original output & outputwTip format by only adding in the miss chance? The reason I ask, is I like the original output but would like to incorporate the miss chance now that I am starting to DM higher level play.
The above only adds the miss chance info. Everything else is the same.

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

Re: [MOD] LibAttack and Attack (MT1.3b82 r01)

Post by lmarkus001 »

aliasmask wrote: PS. Anyone know what LibAttackW is used for?
Heh... any macro with a W on the end was an older Working version of the code that I can quickly roll back too. I am not always good at cleaning up my old W's...

I will incorporate this nice miss chance output for the next update, thanks!

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

Re: [MOD] LibAttack and Attack (MT1.3b82 r01)

Post by lmarkus001 »

Well hell, now I need to incorporate a second miss chance roll for those folks with Blind Fighting and the like :-)

http://www.d20srd.org/srd/feats.htm#blindFight
http://www.d20pfsrd.com/feats/combat-fe ... ght-combat

Post Reply

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