MT1.3b87.06 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! :)
Dorn
Cave Troll
Posts: 55
Joined: Sat Mar 30, 2013 8:59 am

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by Dorn »

smartsoldier wrote:Alright, I made a new macro with that rage code and it works great! However, what do you mean "editing the mod under con"? I assume this has something to do with the fact that the new macro I made doesn't actually change my stats yet?
As a GM, click the red campaign macro that says "Edit Mods". Then choose rage from the list, and make the changes.

smartsoldier
Cave Troll
Posts: 45
Joined: Sat Aug 10, 2013 10:03 pm

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by smartsoldier »

When I rage and my CON increases, only my maximum HP increases, my current HP does not increase to compensate. There is not a "HP" option in the category of STRMOD, CONMOD, etc. How would I go about adding eg. 9hp when I rage inside the macro?

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

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by aliasmask »

smartsoldier wrote:When I rage and my CON increases, only my maximum HP increases, my current HP does not increase to compensate.
I recall an older version use to do that, but I'm still using B87 02 and the hp increases and decreases with the mod.

Try this. Heal to Full HP, apply rage, use HP change for 1 dmg. Check hp total. Maybe the hp recalc isn't taking place when it should, so you don't see the change. This takes place in subModToggle and the part that adjusts the HP after changing the CON looks like this:

Code: Select all

...

[H: tDamage = HPmax - HP]

[H, FOREACH( m, json.fields( tjMods ) ), CODE: {
   [ isModField = if( listContains( modList, m ) > 0, 1, 0 ) ]
   [ isArmor = if( listContains( modArmorFieldList, m ) > 0, 1, 0 ) ]
   [ isSpeed = if( listContains( modSpeedFieldList, m ) > 0, 1, 0 ) ]
   [ isStatCheckMod = if( listContains( modStatCheckFieldList, m ) > 0, 1, 0 ) ]
   [ isDRERMod = if( listContains( modDRERFieldList, m ) > 0, 1, 0 ) ]
   [ tm = eval( "" + m ) ]
   [MACRO( "subCalcMod@this" ): json.set( "{}", "tokenID", tToken, "setID", tmID, "param", m, "active", active, "presetVars", presetVars, "casterlevel", tclvl ) ]
   [ newMSTotal = json.get( macro.return, "newMSTotal" ) ]
   [ oldMSTotal = json.get( macro.return, "oldMSTotal" ) ]
   [IF( isModField ): setProperty( m, tm - oldMSTotal + newMSTotal ) ]
   [IF( isArmor ): ArmorClass =  setStrProp( ArmorClass, m, if( listContains( modAddStackList, m ) > 0 || matches( m, ".*Mod" ),
      tm - oldMSTotal + newMSTotal,
	  newMSTotal ) )
   ]
   [IF( isSpeed ): SpeedMod =  json.set( SpeedMod, lower( m ), ( tm - oldMSTotal + newMSTotal ) ) ]
   [IF( isStatCheckMod ): StatCheckMod =  json.set( StatCheckMod, m, ( tm - oldMSTotal + newMSTotal ) ) ]
   [IF( isDRERMod ): DRERMod =  json.set( DRERMod, m, ( tm - oldMSTotal + newMSTotal ) ) ]
}]

[H: tACP = 0 ]
[H: tmaxdex = 50 ]
[H: tencumbered = 0 ]
[H: tdesc = "" ]
[H, IF( tmType == 1 ), FOREACH( i, aItems ), CODE: {
   [ jI = json.get( BonusTypedItems, i ) ]
   [ tACP = tACP + json.get( jI, "acp" ) ]
   [ tmaxdex = min( tmaxdex, json.get( jI, "maxdex" ) ) ]
   [ tencumbered = max( tencumbered, json.get( jI, "encumbered" ) ) ]
   [ tnote = json.get( jI, "note" ) ]
   [ armorDesc = if( json.contains( json.get( jI, "mods" ), "Armor" ) || json.contains( json.get( jI, "mods" ), "Shield" ), 1, 0 ) ]
   [IF( tnote != "" && armorDesc ): tdesc = listAppend( tdesc, tnote ) ]
}]
[H, IF( tmType == 1 ): ArmorClass = setStrProp( ArmorClass, "ArmorACP", tACP ) ]
[H, IF( tmType == 1 ): ArmorClass = setStrProp( ArmorClass, "MaxDex", tmaxdex ) ]
[H, IF( tmType == 1 ): ArmorClass = setStrProp( ArmorClass, "Description", tdesc ) ]
[H, IF( tmType == 1 ): SpeedMod = json.set( SpeedMod, "encumbered", tencumbered ) ]

[H, IF( listContains( statesList, state ) > 0 ): setState( state, !active ) ]

[R,S,G, IF( tmacro != ""), MACRO( tmacro ): json.set( "{}", "token", tToken, "active", active, "casterlevel", tclvl ) ]

[H: HP = HPmax - tDamage]

...
Notice the first line and last line. All the stuff in between makes the changes. Now if the process is interrupted, it's possible to update CON but not the HP, but it would likely have to error to do that. Perhaps with a bad value in one of your fields.

smartsoldier
Cave Troll
Posts: 45
Joined: Sat Aug 10, 2013 10:03 pm

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by smartsoldier »

I am trying to make a macro to alter the ACMod, but ACMod isn't a property on its own; it seems to be single part of ArmorClass, which is a set of a bunch of all the different factors to AC. How can I modify AC via setProperty?

Edit: I can edit the ACMod with:
[H: ArmorClass = setStrProp( ArmorClass, "ACMod", 61 ) ]
but it does not update the AC on the tooltip. How can I manually update the tooltip? (little mini character sheet that pops up when I mouse over my token)

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

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by aliasmask »

You have to run "subRecalcAC" macro I believe.

Code: Select all

[H, MACRO("subRecalcAC@this"): "Token=" + tToken]

smartsoldier
Cave Troll
Posts: 45
Joined: Sat Aug 10, 2013 10:03 pm

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by smartsoldier »

Thanks a lot! I now have a macro that will toggle all the specific rage properties of my Bloodrager on and off at will!

aranginor
Giant
Posts: 131
Joined: Fri Dec 05, 2008 2:32 pm

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by aranginor »

The following code is in the Attack macro

Code: Select all

[H, IF( manyShot ), CODE: {
    [H: fullRound = 0 ]
    [H: tempATK = tempATK - 4 ]
    [H: flurryRapid = 1 ]
}]
Why a -4 penalty on attack rolls for using Manyshot? D20PFSRD says nothing about a -4 penalty.
http://www.d20pfsrd.com/feats/combat-fe ... at---final

Dorn
Cave Troll
Posts: 55
Joined: Sat Mar 30, 2013 8:59 am

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by Dorn »

aranginor wrote: Why a -4 penalty on attack rolls for using Manyshot? D20PFSRD says nothing about a -4 penalty.
http://www.d20pfsrd.com/feats/combat-fe ... at---final
I don't know... I don't have time to go through the code right now, but I did some test shots right now with multi-shot checked, and the -4 didn't show up anywhere. Are you seeing it as a penalty or counting against your attack rolls?

aranginor
Giant
Posts: 131
Joined: Fri Dec 05, 2008 2:32 pm

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by aranginor »

Not multi-shot. The option is "Using Many Shot Feat?". When I select that option, with a ranged weapon, I get a Temp: -4 attack modifier.
Dorn wrote:
aranginor wrote: Why a -4 penalty on attack rolls for using Manyshot? D20PFSRD says nothing about a -4 penalty.
http://www.d20pfsrd.com/feats/combat-fe ... at---final
I don't know... I don't have time to go through the code right now, but I did some test shots right now with multi-shot checked, and the -4 didn't show up anywhere. Are you seeing it as a penalty or counting against your attack rolls?

Dorn
Cave Troll
Posts: 55
Joined: Sat Mar 30, 2013 8:59 am

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by Dorn »

aranginor wrote:Not multi-shot. The option is "Using Many Shot Feat?". When I select that option, with a ranged weapon, I get a Temp: -4 attack modifier.
Sorry, I meant many shot, obviously, as multi-shot is not an option. Again, I don't have time to look through all the code at the moment, but I did notice that if you use the new attack frame (Under Character Sheet heading, "Attack (Frame)") you do not get the -4 from many shot. If you use the "Attack Dialog" under GM heading, you do get the -4. My suggestion would be to just change the -4 to 0 and be on your way.

User avatar
ssveter
Kobold
Posts: 13
Joined: Sat Jan 01, 2011 12:18 pm
Location: Texas
Contact:

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by ssveter »

Am I missing something but how do you turn off a disguise using this framework?

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

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by aliasmask »

ssveter wrote:Am I missing something but how do you turn off a disguise using this framework?
I recently ran in to something weird with disguise myself using b89 and I'm not sure of the cause. After changing something on the token, like hit points, the disguise would change to another image. This happened even after I removed the asset from the list. I think I may have caused this by naming two tokens the same. After changing the name, it stopped happening.

User avatar
ssveter
Kobold
Posts: 13
Joined: Sat Jan 01, 2011 12:18 pm
Location: Texas
Contact:

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by ssveter »

aliasmask wrote:
ssveter wrote:Am I missing something but how do you turn off a disguise using this framework?
I recently ran in to something weird with disguise myself using b89 and I'm not sure of the cause. After changing something on the token, like hit points, the disguise would change to another image. This happened even after I removed the asset from the list. I think I may have caused this by naming two tokens the same. After changing the name, it stopped happening.
The disguised token was changed to look like another one on the map. But its name remains the same. Are you saying then that I'll need to change the name of the disguised token or what exactly?

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

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by aliasmask »

ssveter wrote:
aliasmask wrote:
ssveter wrote:Am I missing something but how do you turn off a disguise using this framework?
I recently ran in to something weird with disguise myself using b89 and I'm not sure of the cause. After changing something on the token, like hit points, the disguise would change to another image. This happened even after I removed the asset from the list. I think I may have caused this by naming two tokens the same. After changing the name, it stopped happening.
The disguised token was changed to look like another one on the map. But its name remains the same. Are you saying then that I'll need to change the name of the disguised token or what exactly?
Yeah, try that. I also copy/pasted the disguised token. You can try that too.

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

Re: MT1.3b87.06 Pathfinder + D&D3.5 Framework (NEW! Latest V

Post by aliasmask »

I just added a couple of things that may be useful. All these changes are made to the Lib:libDnD35Pathfinder token.

First, auto-check rapid shot when doing flurry of blows with ranged weapon in pathfinder. This is so the Zen Archer or Monk throwing shuriken will have the right number of attacks with the correct modifier:

Code: Select all

...
[H, IF( vitalStrike ), CODE: {
    [H: fullRound = 0 ]
    [H: flurryRapid = 1 ]
};{}]

<!-- place this after vital strike check in "Attack" macro -->
[H, if(system == "Pathfinder"), code: {
   [H, if(Flurry_of_Blows), code: {
      [H: flurryRapid = -2]
      [H: fullRound = 1]
   };{}]
};{}]
...
Second, is a check for Point Blank shot. This requires you to select a target. I'm always forgetting to check this box, now I won't have to:

Code: Select all

...
[H: '<!-- Check point blank -->']
[H, if(Ranged && tPointBlankShot && ! json.isEmpty(target1ID) && ! isPointBlank), code: {
   [H: distance = getDistance(target1ID,1)]
   [H, if(distance <= 30): isPointBlank = 1]
};{}]

<!-- Place above code just before this line in "LibAttack" macro -->
[H: rangeMod = if( rangeIncrement == 0, if( tPointBlankShot && isPointBlank, 1, 0 ), -2 * ( rangeIncrement ) ) ]
...
Third and is far more complicated to add is a check for flanking. This also requires you to select a target when attacking and will only check immediately around target. So, if your ally has reach, the flanking checkbox will still need to be checked manually. Note that this doesn't check visibility, so an ally on the other side of VBL will still flank. This usually isn't a problem, but I'll program for this fringe case and using reach in the future:

Code: Select all

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

<!-- place this code just below the above code in "LibAttack" macro -->
[H: '<!-- Check flanking -->']
[H, if(! Ranged && ! json.isEmpty(target1ID) && ! flanking), code: {
   [H: attacker = currentToken()]
   [H: target = target1ID]
   [H, if(isPC()): allies = getTokens("json",json.set("{}","pc",1,"range",json.set("{}","token",target,"distancePerCell",1,"upto",5)));
      allies = getTokens("json",json.set("{}","npc",1,"range",json.set("{}","token",target,"distancePerCell",1,"upto",5)))]
   [H: flankers = am.getFlankers(attacker,target,allies)]
   [H, if(! json.isEmpty(flankers)): flanking = 1]
};{}]
...
For the above to work you need to add 4 new macros and edit the onCampaignLoad macro.
||| New Macros |||

Code: Select all

@@ @getFlankers
<!-- getFlankers(attacker,target,allies): flankers -->
[H: attackerId = arg(0)]
[H: targetId = arg(1)]
[H: allyIds = arg(2)]

[H: flankers = ""]
[H, if(json.type(allyIds) == "UNKNOWN" && ! json.isEmpty(allyIds)): allyIds = json.fromList(allyIds)]

[H, if(json.contains(allyIds,attackerId)): allyIds = json.difference(allyIds,json.append("",attackerId))]
[H, if(json.contains(allyIds,targetId)): allyIds = json.difference(allyIds,json.append("",targetId))]
[H, foreach(allyId,allyIds), code: {
   [H: isFlanking = am.isFlanking(attackerId,targetId,allyId)]
   [H, if(isFlanking): flankers = listAppend(flankers,allyId)]
}]
[H: macro.return = flankers]

!!
@@ @isFlanking
@PROPS@ fontColor=black ; autoExecute=true ; fontSize=11pt ; sortBy= ; color=default ; playerEditable=false ; applyToSelected=false ; group= ; tooltip= ; minWidth=94 ; 
[H: a.id = arg(0)]
[H: t.id = arg(1)]
[H: f.id = arg(2)]

<!-- Since we are dealing with grid squares, the distance to the center of grid is 0.5 -->
[H: offset = 0.5]
[H: infinity = 1000000000]

[H: a.strProps = am.defineTokenCoords.sub(a.id,0,0,"a")]
[H: t.strProps = am.defineTokenCoords.sub(t.id,0,0,"t")]
[H: f.strProps = am.defineTokenCoords.sub(f.id,0,0,"f")]

<!-- Check vertical and horizontal -->
[H: isFlanking = if((max(a.x1,t.x1,f.x1) <= min(a.x2,t.x2,f.x2)-1) && ((a.y1 > t.y1 && t.y1 > f.y1) || (a.y1 < t.y1 && t.y1 < f.y1)),1,0)]
[H, if(! isFlanking): isFlanking = if((max(a.y1,t.y1,f.y1) <= min(a.y2,t.y2,f.y2)-1) && ((a.x1 > t.x1 && t.x1 > f.x1) || (a.x1 < t.x1 && t.x1 < f.x1)),1,0)]

<!-- if attacker and ally is size 1, just check path through target -->
[H, if(! isFlanking && a.size == 1 && f.size == 1), code: {
   [H: slope = (f.cy - a.cy)/(f.cx - a.cx)]
   [H: b = a.cy - (a.cx * slope)]
   [H, if(slope > 1 || slope < -1), code: {
      [H, if((t.y1 - b)/slope >= t.x1 && (t.y1 - b)/slope <= t.x2 && (t.y2 - b)/slope >= t.x && (t.y2 - b)/slope <= t.x2): isFlanking = 1]
   };{
      [H, if(slope * t.x1 + b >= t.y1 && slope * t.x1 + b <= t.y2 && slope * t.x2 + b >= t.y1 && slope * t.x2 + b <= t.y2): isFlanking = 1]
   }]
};{}]

<!-- Do slope test: ULtoLR, LLtoUR, URtoLL and LRtoUL. I just redefine coords to ULtoLR to avoid duplicating formulas -->
[H, if(! isFlanking), code: {
   [H, if(a.x1_ <= t.cx && a.y1_ <= t.cy && f.x2_ >= t.cx && f.y2_ >= t.cy): isFlanking = am.slopeRangeCheck(a.strProps,t.strProps,f.strProps)]
   [H, if(! isFlanking && a.x1_ <= t.cx && a.y2_ >= t.cy && f.x2_ >= t.cx && f.y1_ <= t.cy): isFlanking = am.slopeRangeCheck(am.defineTokenCoords.sub(a.id,0,2*(t.cy-a.cy),"a",0),t.strProps,am.defineTokenCoords.sub(f.id,0,2*(t.cy-f.cy),"f",0))]
   [H, if(! isFlanking && a.x2_ >= t.cx && a.y1_ <= t.cy && f.x1_ <= t.cx && f.y2_ >= t.cy): isFlanking = am.slopeRangeCheck(am.defineTokenCoords.sub(a.id,2*(t.cx-a.cx),0,"a",0),t.strProps,am.defineTokenCoords.sub(f.id,2*(t.cx-f.cx),0,"f",0))]
   [H, if(! isFlanking && a.x2_ >= t.cx && a.y2_ >= t.cy && f.x1_ <= t.cx && f.y1_ <= t.cy): isFlanking = am.slopeRangeCheck(am.defineTokenCoords.sub(f.id,0,0,"a",0),t.strProps,am.defineTokenCoords.sub(a.id,0,0,"f",0))]
};{}]

[H: macro.return = isFlanking]

!!
@@ @defineTokenCoords.sub
[H: id.sub = arg(0)]
[H, if(argCount() >= 3), code: {
   [H: offsetX.sub = arg(1)]
   [H: offsetY.sub = arg(2)]
};{
   [H: offsetX.sub = 0]
   [H: offsetY.sub = 0]
}]
[H, if(argCount() >= 4): prefix.sub = arg(3); prefix.sub = strformat("t%{id.sub}")]
[H, if(argCount() >= 5): preDefine.sub = arg(4); preDefine.sub = 1]

[H: indent.sub = 0.5]
[H: x.sub = getTokenX(0,id.sub)]
[H: y.sub = getTokenY(0,id.sub)]
[H: size.sub = max(1,listFind("Medium,Large,Huge,Gargantuan,Empty,Colossal",getSize(id.sub))+1)]
[H: strProp.sub = strformat("%{prefix.sub}.x1=%s; %{prefix.sub}.y1=%s; %{prefix.sub}.x2=%s; %{prefix.sub}.y2=%s; %{prefix.sub}.size=%{size.sub}; %{prefix.sub}.cx=%s; %{prefix.sub}.cy=%s; %{prefix.sub}.x1_=%s; %{prefix.sub}.y1_=%s; %{prefix.sub}.x2_=%s; %{prefix.sub}.y2_=%s;", x.sub+offsetX.sub, y.sub+offsetY.sub, x.sub+size.sub+offsetX.sub, y.sub+size.sub+offsetY.sub, x.sub+(size.sub/2)+offsetX.sub, y.sub+(size.sub/2)+offsetY.sub, x.sub+offsetX.sub+indent.sub, y.sub+offsetY.sub+indent.sub, x.sub+size.sub+offsetX.sub-indent.sub, y.sub+size.sub+offsetY.sub-indent.sub)]
<!--
   x1 - left x
   x2 - right x
   y1 - up y
   y2 - down y
   size - token grid unit size
   cx - center x
   cy - center y
   x1_ - indented left x
   x2_ - indented right x
   y1_ - indented up y
   y2_ - indented down y
-->
[H, if(preDefine.sub): varsFromStrProp(strProp.sub)]
[H: macro.return = strProp.sub]

!!
@@ @slopeRangeCheck
<!-- slopeRangeCheck(attackerProps,targetProps,allyProps): isFlanking -->
[H: varsFromStrProp(arg(0))]
[H: varsFromStrProp(arg(1))]
[H: varsFromStrProp(arg(2))]

<!-- Since we are dealing with grid squares, the distance to the center of grid is 0.5 -->
[H: offset = 0.5]
[H: infinity = 1000000000]
[H: isFlanking = 0]

<!-- get slope1, left-most slope -->
[H, if(a.x2_ >= t.x1): slope1 = infinity; slope1 = (t.y1 - a.y1_)/(t.x1 - a.x2_)]

<!-- slope offset is used to determine best point of reference. Either UL or LR depending on slope relation to slope of 1 -->
[H, if(slope1 < 1), code: {
   [H: slope1.offset = t.size]
   [H: slope1 = ((t.y1 + slope1.offset) - a.y1_)/((t.x1 + slope1.offset) - a.x2_)]
};{
   [H: slope1.offset = 0]
}]

<!-- get slope2, right-most slope -->
[H, if(a.y2_ >= t.y1): slope2 = 0; slope2 = (t.y1 - a.y2_)/(t.x1 - a.x1_)]
[H, if(slope2 > 1), code: {
   [H: slope2.offset = t.size]
   [H: slope2 = ((t.y1 + slope2.offset) - a.y2_)/((t.x1 + slope2.offset) - a.x1_)]
};{
   [H: slope2.offset = 0]
}]

<!-- get max left and right values -->
[H, if(slope1 == infinity): isLeft = 1; isLeft = 0]
[H, if(slope2 == 0): isRight = 1; isRight = 0]

<!-- Check left slope for left of ally and border crossover -->
[H, if(! isLeft), code: {
   [H: slope1.b = t.y1 + slope1.offset - ((t.x1 + slope1.offset) * slope1)]
   [H: slope1.x1 = slope1 * f.x1_ + slope1.b]
   [H, if(slope1.x1 > f.y2_): isLeft = 1]
   [H, if(! isLeft), code: {
      <!-- also check to see if line intersects flanker wall -->
      [H: slope1.x2 = slope1 * f.x2_ + slope1.b]
      [H, if((slope1.x1 <= f.y2_ && slope1.x1 >= f.y1_) || (slope1.x2 <= f.y2_ && slope1.x2 >= f.y1_)): isFlanking = 1]
   };{}]
   [H, if(! isLeft && ! isFlanking), code: {
      [H: slope1.y1 = (f.y1_ - slope1.b)/slope1]
      [H: slope1.y2 = (f.y2_ - slope1.b)/slope1]
      [H, if((slope1.y1 <= f.x2_ && slope1.y1 >= f.x1_) || (slope1.y2 <= f.x2_ && slope1.y2 >= f.x1_)): isFlanking = 1]
   };{}]
};{}]
   
[H, if(! isRight && ! isFlanking), code: {
   [H: slope2.b = t.y1 + slope2.offset - ((t.x1 + slope2.offset) * slope2)]
   [H: slope2.y1 = (f.y1_ - slope2.b)/slope2]
   [H, if(slope2.y1 > f.x2_): isRight = 1]
   <!-- also check to see if line intersects flanker wall -->
   [H, if(! isRight), code: {
      [H: slope2.y2 = (f.y2_ - slope2.b)/slope2]
      [H, if((slope2.y1 <= f.x2_ && slope2.y1 >= f.x1_) || (slope2.y2 < f.x2_ && slope2.y2 >= f.x1_)): isFlanking = 1]
   };{}]   
   <!-- check through other flanker walls -->
   [H, if(! isRight && ! isFlanking), code: {
      [H: slope2.x1 = slope2 * f.x1_ + slope2.b]
      [H: slope2.x2 = slope2 * f.x2_ + slope2.b]
      [H, if((slope2.x1 <= f.y2_ && slope2.x1 >= f.y1_) || (slope2.x2 < f.y2_ && slope2.x2 >= f.y1_)): isFlanking = 1]
   };{}]
};{}]
   
<!-- The 2 slopes surround the flanker which means all points of flanker are flanking -->
[H, if(isLeft && isRight): isFlanking = 1]

[H: macro.return = isFlanking]

!!
Add these lines to onCampaignLoad:

Code: Select all

...
[H: defineFunction("am.defineTokenCoords.sub","defineTokenCoords.sub@"+thisLib,1,0)]
[H: defineFunction("am.getFlankers","getFlankers@"+thisLib,1)]
[H: defineFunction("am.isFlanking","isFlanking@"+thisLib,1)]
[H: defineFunction("am.slopeRangeCheck","slopeRangeCheck@"+thisLib,1)]
...
thisLib if not already defined is [H: thisLib = getMacroLocation()]. Once you are done editing onCampaignLoad, then you need to run it for the functions to be defined this session. As always, save your campaign before making these changes just in case something gets messed up. Once you're satisfied it's working, save campaign to new name.

Post Reply

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