I have a player that has recently picked up the Book of Nine Swords Warblade ability to add Int bonus to confirm critical hits.
I see that critical focus has been added, so this seems like it would be easy to add but i'm not sure where to dig for the code for that or where it would hit.
Is there any chance someone could add it that is more familiar then me?
Thanks!
Feat added to the core stats?
Moderators: dorpond, trevor, Azhrei, giliath, Gamerdude, jay, Mr.Ice, lmarkus001
Forum rules
Discussion regarding lmarkus001's framework only. Other posts deleted without notice!
Discussion regarding lmarkus001's framework only. Other posts deleted without notice!
Re: Feat added to the core stats?
I can do this, but the more feats that are squeezed into the Attack and LibAttack macros, the harder it becomes to understand what is going on.
@Lindsay: Any chance of adding crit to the JSON like CMD/INIT/AbilityBonuses and such? If so, this could be easy to fix.
@Lindsay: Any chance of adding crit to the JSON like CMD/INIT/AbilityBonuses and such? If so, this could be easy to fix.
Re: Feat added to the core stats?
I started a rewrite of the attack macro awhile back, but for it to cover all possibilities, it started turning in to a very large project. My plan was to define certain aspects of the attack and then create generic mods for each so custom feats could be easily added. I was adding things like firstStrikeAttack, firstStrikeDamage for things like smite.
This was my code so far:
But I'm going to revisit this code and see if I can finish it up. I'll have to look at the most recent version to make sure I don't forget anything new that was added. One main thing I want to accomplish is cleaning up the attack input screen and output for attack. One of the cool things will be the unlimited number of adders for weapon damage and the ability to uncheck them before applying damage (ie my flaming sword may not be flaming at the moment).
This was my code so far:
||| Attack |||
Code: Select all
[H, IF( json.type( macro.args ) == "UNKNOWN" ), CODE: {
[ varsFromStrProp(eval(macro.args))]
[ if(!Primary): abort(0)]
[ fullRound = 1 ]
[ flanking = 0 ]
[ higherGround = 0 ]
[ rangeIncrement = 0 ]
[ isPointBlank = 0 ]
[ fireIntoMelee = 0 ]
[ sneak = "0d6" ]
[ isSneak = 0 ]
[ sneakDMG = 0 ]
[ favEnemy = 0 ]
[ cleave = 0 ]
[ flurryRapid = 1 ]
[ target1Name = "" ]
[ target1ID = "" ]
[ target2Name = "" ]
[ target2ID = "" ]
};{
[ tWeapon = json.get( macro.args, "weapon" ) ]
[ varsFromStrProp(eval(tWeapon))]
[ if(!Primary): abort(0)]
[ fullRound = json.get( macro.args, "fullRound" ) ]
[IF( json.isEmpty( fullRound ) ): fullRound = 1 ]
[ flanking = json.get( macro.args, "flanking" ) ]
[IF( json.isEmpty( flanking ) ): flanking = 0; flanking = flanking * 2 ]
[ 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 ]
[ isCleave = json.get( macro.args, "cleave" ) ]
[IF( json.isEmpty( isCleave ) ): isCleave = 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 = "" ]
}]
[H: gTok = "Lib:GlobalsSRDPF" ]
[H: system = getLibProperty("System", gTok)]
<!-- Get Active Temp Mod Sets -->
[H: aTMS = json.get( PrivateJSON, "ActiveTempModSets" ) ]
[H, IF( json.type( aTMS ) == "UNKNOWN" ), CODE: {
[ PrivateJSON = json.set( PrivateJSON, "ActiveTempModSets", "[]" ) ]
[ aTMS = "[]" ]
}]
<!-- Active Mod Setters -->
<!-- Note: Active mod set will have defined name, attack bonus, damage bonus, 1stAttack, ... where values/formulas will be pulled from -->
[H, if(system == "Pathfinder"): padaID = "Power Attack/Deadly Aim"; padaID = "Power Attack"]
[H, if(json.contains(aTMS,padaID)): hasPowerAttack = 1; hasPowerAttack = 0]
<!-- I'll add this to feats and attack macro as option to activate eventually -->
[H, if(json.contains(aTMS,"Smite")): hasSmite = 1; hasSmite = 0]
<!-- Check for Cleave option -->
[H, if(isCleave), code: {
[H: tGreatCleave = getStrProp(Feats, "GreatCleave")]
[H: tGreatCleave = if(tGreatCleave == "", 0, tGreatCleave)]
[H, if(tGreatCleave): tCleave = 1; tCleave = 0]
};{
[H: tCleave = getStrProp(Feats, "Cleave")]
[H: tCleave = if(tCleave == "", 0, tCleave)]
}]
<!-- Calc number of attacks -->
[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: 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, if(!fullRound || Primary == 2 || isCleave): numAttacks = 1; numAttacks = if(Manufactured,FAN,Quantity) + tHaste + isFlurryRapid]
<!-- Special Attacks -->
[H, if(tHaste): extraAttack = json.append("","Haste"); extraAttack = ""]
[H, if(isFlurryRapid): extraAttack = json.append(attackSpecial,"Rapid")]
<!-- GET ATTACK MODS -->
[H: attackMod = ""]
[H: attackModName = ""]
[H, if(AtkBonus == "*"): autoHit = 1; autoHit = 0]
[H: rangeMod = 0]
[H, if(!autoHit), code: {
<!-- Get Stat Mod -->
[H: tWeaponFinesse = getStrProp(Feats, "WeaponFinesse")]
[H: tWeaponFinesse = if(tWeaponFinesse == "", 0, tWeaponFinesse)]
[H, if(Ranged): statAttackMod = DexB; statAttackMod = if(tWeaponFinesse && Finesse, max(StrB, DexB), StrB)]
[H: attackMod = json.append(attackMod,statAttackMod)]
[H: attackModName = json.append(attackModName,"Stat Bonus")]
<!-- Get Multiple Weapon attack mod -->
[H, if( OHLight != 2 && fullRound), code: {
[H: tTwoWeaponFighting = getStrProp(Feats, "TwoWeaponFighting")]
[H: tTwoWeaponFighting = if(tTwoWeaponFighting == "", 0, tTwoWeaponFighting)]
[H: tMultiAttack = getStrProp(Feats, "MultiAttack")]
[H: tMultiAttack = if(tMultiAttack == "", 0, tMultiAttack)]
[H: MultAtkMP = if(Manufactured == 1, -6 + (tTwoWeaponFighting * 2), 0)]
[H: MultAtkM = if(Manufactured == 1, -10 + (tTwoWeaponFighting * 6), -5 + (tMultiAttack * 3))]
[H: atkMult = if(Primary == 1, min(0, max(MultAtkMP, MultAtkMP+(OHLight*2))), min(0, max(MultAtkM, MultAtkM+(OHLight*2))))]
[H: attackMod = json.append(attackMod,atkMult)]
[H: attackModName = json.append(attackModName,"Multi Attack")]
};{}]
<!-- Get Range Mod -->
[H, if(Ranged), code: {
[H: tPointBlankShot = getStrProp(Feats, "PointBlankShot")]
[H: tPointBlankShot = if(tPointBlankShot == "", 0, tPointBlankShot)]
[H: rangeMod = if( rangeIncrement == 0, if( tPointBlankShot && isPointBlank, 1, 0 ), -2 * ( rangeIncrement ) ) ]
[H: attackMod = json.append(attackMod,rangeMod)]
[H: attackModName = json.append(attackModName,"Range")]
};{}]
<!-- Get Size Mod -->
[H, if(SizeM), code: {
[H: attackMod = json.append(attackMod,SizeM)]
[H: attackModName = json.append(attackModName,"Size")]
};{}]
<!-- Get Misc Attack Mod -->
<!-- All the Misc attack mods will be replaced with the respective feat/ability name -->
[H, if(MiscATK), code: {
[H: attackMod = json.append(attackMod,MiscATK)]
[H: attackModName = json.append(attackModName,"Misc")]
};{}]
<!-- Get Aiming Attack Mod -->
[H, if(fireIntoMelee), code: {
[H: attackMod = json.append(attackMod,fireIntoMelee)]
[H: attackModName = json.append(attackModName,"Aiming")]
};{}]
<!-- Get Flanking Attack Mod -->
[H, if(flanking), code: {
[H: attackMod = json.append(attackMod,flanking)]
[H: attackModName = json.append(attackModName,"Flanking")]
};{}]
<!-- Get Weapon Attack Mod -->
[H, if(AtkBonus), code: {
[H: attackMod = json.append(attackMod,AtkBonus)]
[H: attackModName = json.append(attackModName,"Weapon")]
};{}]
};{}]
<!-- GET DAMAGE MODS - Damage done independant of target's defenses -->
[H: damageMod = "{}"]
<!-- Get Power Attack Damage -->
[H, if( hasPowerAttack && !autoHit), code: {
[H: powerAttackBAB = json.get( json.get( json.get( json.get( json.get( PrivateJSON, "CustomModSetValues" ), padaID ), "mods" ), "globalMod" ), "v" )]
[H, if(system == "Pathfinder"), code: {
[H: pa2H = 1.5 ]
[H: paMultiplier = 2 ]
[H: paOffhand = 0.5 ]
[H, if(Ranged): padaID = "Deadly Aim"; padaID = "Power Attack"]
};{
[H: tImprovedPA = getStrProp(Feats, "ImprovedPA")]
[H: tImprovedPA = if(tImprovedPA == "", 0, tImprovedPA)]
[H: tSupremePA = getStrProp(Feats, "SupremePA")]
[H: tSupremePA = if(tSupremePA == "", 0, tSupremePA)]
[H: paMultiplier = max(1,tImprovedPA * 1.5,tSupremePA * 2)]
[H: pa2H = 2 ]
[H: paOffhand = 0 ]
}]
[H, if(TwoHanded): paDMG = floor( paMultiplier * powerAttackBAB * pa2H); paDMG = floor( paMultiplier * powerAttackBAB )]
<!-- Note: Weapon should have type defined (unarmed,light,natural?(for creatures and monks - this effects power attack),oneHand,twoHand,Range,Thrown) -->
[H, if(OHLight == 1 || (system == "Pathfinder" && Ranged)): paDMG = paDMG * paOffhand]
[H, if(paDMG), code {
[H: damageMod = json.set(damageMod,padaID,paDMG)]
};{}]
};{}]
<!-- Get Stat Damage Mod -->
[H, if(!autoHit), code: {
[H, if(Ranged), code: {
<!-- two handed is a bow, other is thrown weapon -->
[H, if(TwoHanded): damageStatMod = min(DmgBonusCap,StrB); damageStatMod = StrB]
};{
<!-- A monk's flurry of blows is always StrB despite weapon type -->
[H, if(TwoHanded && !isFlurryRapid): damageStatMod = Str2hB; damageStatMod = StrB]
[H, if(Primary == 2 && !isFlurryRapid): damageStatMod = min(StrB,StrSecB)]
}]
[H, if(damageStatMod), code: {
[H: damageMod = json.set(damageMod,"Stat Bonus",damageStatMod)]
};{}]
<!-- Point Blank damage mod -->
[H, if(Ranged && rangeMod > 0), code {
[H: damageMod = json.set(damageMod,"Point Blank",rangeMod)]
};{}]
};{}]
<!-- GET EXTRA DAMAGE MODS - Optional damage based on target's defenses -->
<!-- ( Sneak, Skirmish, Good, Evil, Law, Chaos, Bane, Effect(DC check) ) -->
<!-- Some of these will need to be activated in the attack window -->
[H: xDamageMod = "{}"]
<!-- The extra damage and extra damage name can be a list of values separated by a comma and evaluated -->
<!-- Because of Comma Separated List, put note for user to use "," for a comma in output -->
[H: xDamageList = json.fromList(DmgExtra)]
[H: xDamageNameList = json.fromList(DmgExtraName)]
[H, if(isSneak), code: {
[h: xDamageList = json.append(xDamageList,sneak)]
[H: xDamageNameList = json.append(xDamageNameList,"Sneak")]
};{}]
[H: hasXDamage = 0]
[H, if(json.length(xDamageList) > 0), code: {
[H: firstDamage = json.get(xDamageList,0)]
[H, if(firstDamage != "0" && firstDamage != "0d6"): hasXDamage = 1]
};{}]
<!-- Lets validate the xDamage fields -->
[H, if(hasXDamage), code: {
[H: xDamageNameListLen = json.length(xDamageNameList)]
[H: xDamageListLen = json.length(xDamageList)]
[H, c(xDamageListLen), code: {
[H, if(xDamageListLen > xDamageNameListLen):
xDamageMod = json.set(xDamageMod,"xDamage" + roll.count,strformat("{%s}",json.get(xDamageList,roll.count)));
xDamageMod = json.set(xDamageMod,json.get(xDamageNameList,roll.count),strformat("{%s}",json.get(xDamageList,roll.count)))
]
}]
};{}]
<!-- GET EXTRA CRIT DAMAGE MODS - Optional damage based on target's defenses with a critical -->
[H: xCritDamageMod = "{}"]
<!-- The extra damage and extra damage name can be a list of values separated by a comma and evaluated -->
[H: xCritDamageList = json.fromList(DmgExtraCrit)]
[H: xCritDamgeNameList = json.fromList(DmgExtraCritName)]
[H: hasXCritDamage = 0]
[H, if(json.length(xCritDamageList) > 0), code: {
[H: firstDamage = json.get(xCritDamageList,0)]
[H, if(firstDamage != "0" && firstDamage != "0d6"): hasXCritDamage = 1]
};{}]
<!-- Validate the xCritDamage fields -->
[H, if(hasXCritDamage), code: {
[H: xCritDamageNameListLen = json.length(xCritDamageNameList)]
[H: xCritDamageListLen = json.length(xCritDamageList)]
[H, c(xCritDamageListLen), code: {
[H, if(xCritDamageListLen > xCritDamageNameListLen):
xCritDamageMod = json.set(xCritDamageMod,"xCritDamage" + roll.count,json.get(xCritDamageList,roll.count));
xCritDamageMod = json.set(xCritDamageMod,json.get(xCritDamageNameList,roll.count)
]
}]
};{}]
<!-- LETS MAKE SOME ROLLS and see what Criticals -->
[H, C(numAttacks), code: {
[H: rollResult = 1d20]
[H, if(rollResult >= CritRange): critRoll = 1d20; critRoll = 0]
<!-- Build data struct to pass -->
[H: damageRecord = "{}"]
[H: weaponDamage = val(Damage)]
[H, if(!weaponDamage && Damage != "" && Damage != "0d6"): weaponDamage = 1]
[H, if(weaponDamage): damageRecord = json.set(damageRecord,"Weapon",weaponDamage)]
[H: modDamage = 0]
[H, if(weaponDamage && !json.isEmpty(damageMod)), code: {
[H: damageRecord = json.set(damageRecord,"Weapon Mods",damageMod)]
[H: damageModList = json.fields(damageMod)]
[H, foreach(dMod,damageMod): modDamage = modDamage + json.get(damageMod,dMod)]
};{}]
[H, if(weaponDamage && critRoll), code: {
[H: critWeaponDamage = 0]
[H, C(CritMult-1): critWeaponDamage = critWeaponDamage + max(1,val(Damage)) + modDamage]
[H: damageRecord = json.set(damageRecord,"Crit",critWeaponDamage)]
};{}]
[H: xDamageModList = json.fields(xDamageMod)]
[H, if(hasXDamage): eXDamageMod = json.evaluate(xDamageMod)]
[H, foreach(xDMod,xDamageModList): damageRecord = json.set(damageRecord,xDMod,json.get(eXDamageMod,xDMod))]
...
Downloads:
- Notepad++ MapTool addon
- RPEdit details (v1.3)
- Coding Tips: Modularity and Design
- Videos: Macro Writing Tools
- lmarkus001
- Great Wyrm
- Posts: 1867
- Joined: Sat Mar 29, 2008 12:30 am
- Location: Layfayette Hill, PA
Re: Feat added to the core stats?
I just added this feat tree in. So it will be available next update!
Re: Feat added to the core stats?
Thanks!!!