Page 1 of 1

Fireball token + macro

Posted: Thu Aug 25, 2011 1:55 pm
by magnus_gallowglass
I've been working on a macro for executing fireball in our campaign to help out the GM and I thought I'd share it in the spirit of giving back for the existence of maptools, the framework, and all the help I got while putting it together.

To make it work fully you'll have to add two new properties "evasion" and "impevasion" default 0 and 1 would mean the token has the feat. Other than that it should just run off the standard framework.

It accounts for evasion, improved evasion, DR, ER, Widened, Maximized, empowered, Energy substitution, and whether the token is helpless for the ~4 states currently in the framework that result in a token being helpless.

I have it set to run off of a token with the intent that you would just slap it down over a 20'radius template the player draws.

It's not perfect but it seems to work pretty well from the testing I've done. The graphic is kind of lame but Tokentool and I aren't on speaking terms at the moment to come up with something better.

The 2nd attachment is a macro that can be used to mass add evasion and improved evasion to selected tokens also to make things easier once the properties are in place to update the tokens.

Re: Fireball token + macro

Posted: Thu Aug 25, 2011 5:58 pm
by Azhrei
This sounds cool! I particularly like how you have thought about conditions that could affect the Reflex save. I'm curious how you handle the Enlarged metamagic (seems like a second JSON array would be needed to identify the grid cells) so I'll definitely be looking at this code when I have some time.

Thanks for sharing!

Re: Fireball token + macro

Posted: Tue Sep 13, 2011 12:55 pm
by jsharen
I tried to make this work, however after I run the token update for evasion and such I drop it and click the button to explode and I get a pop up asking for CL if I don't overwrite the 5th level.

Also if I do type something in, I then get a damage pop up. If I leave it blank it moves along and outputs the rolls.

If I try to type in say 5d6 I get:
Illegal argument type java.lang.String, expecting java.math.BigDecimal

Awesome idea, this along with a lightening bolt type example would go a long way to making life easier :)

Re: Fireball token + macro

Posted: Sat Sep 17, 2011 2:29 pm
by magnus_gallowglass
So if I understand the situation...
You put down the fireball token and click on the macro and it pulls up the input box.
If you just click ok, leaving all the values at the default, it pops up a dialogue box asking for the value for "CL"

If you change the value for CL in the input box from the default of 5 to something else it does not pop up a dialogue box asking for CL but does for "DMG"?

I've not been able to re-create the error so far :?

The way I have the token setup is that no players have ownership, the macro has it set so that the "apply to selected tokens" is unchecked, and under options the checkbox for allowing users to edit the macro is unchecked as well. Is that how it's setup for you as well?

I'm not sure what would cause the macro to not use the default value for CL from the input box but work just fine if you type in a value.

If you get a popup for DMG it's asking for a number, such as 6, and then it uses that number to determine how many D6 to roll. so if you put in 5d6 I can see why it would error out in it, just put 5 instead.

Are you using the pathfinder framework?
What version of Maptools are you using?
Also if I do type something in, I then get a damage pop up. If I leave it blank it moves along and outputs the rolls.
what does it show for the output when this happens? It should list something like:
Image

I'm sorry I haven't been much help...
If it helps I edited the top post with a new fireball token which has an updated macro, it now has the ability to account for energy substitution and will hit tokens on the object layer which are not dead.

Here is a copy of the macro code, maybe it's getting messed up when I export the token and attach it to the post....?

Code: Select all

[h: input(
"CL | 5 | Caster Level | TEXT",
"DC | 14 | DC | TEXT",
"featdmg | None, Maximize, Empowered | MetaMagic Feat | RADIO | ORIENT=H SELECT=0",
"EnergyType | Fire, Acid, Cold, Sonic, Electricity | Select Energy Type | RADIO | ORIENT=H SELECT=0",
"featarea | 0 | Widened | CHECK"
)]

<!--- determine damage amount --->
[h: DMG = roll(CL,6)]
[h, if(featdmg==1): DMG=CL*6; DMG]
[h, if(featdmg==2): DMG=DMG*1.5; DMG]


<!------Get tokens ------>
[H,if(featarea==0), CODE:
{
<!-- 20 foot radius burst--->
[h: areaOffsets = '[
{x:2, y:-1},{x:3, y:-1},
{x:0, y:0},{x:1, y:0},{x:2, y:0},{x:3, y:0},{x:4, y:0},{x:5, y:0},
{x:0, y:1},{x:1, y:1},{x:2, y:1},{x:3, y:1},{x:4, y:1},{x:5, y:1},
{x:-1, y:2},{x:0, y:2},{x:1, y:2},{x:2, y:2},{x:3, y:2},{x:4, y:2},{x:5, y:2},{x:6, y:2},
{x:-1, y:3},{x:0, y:3},{x:1, y:3},{x:2, y:3},{x:3, y:3},{x:4, y:3},{x:5, y:3},{x:6, y:3},
{x:0, y:4},{x:1, y:4},{x:2, y:4},{x:3, y:4},{x:4, y:4},{x:5, y:4},
{x:0, y:5},{x:1, y:5},{x:2, y:5},{x:3, y:5},{x:4, y:5},{x:5, y:5},
{x:2, y:6},{x:3, y:6},
]']
};
{
<!-- 40 foot radius burst--->
[H: areaOffsets = '[
{x:2, y:-5},{x:3, y:-5},
{x:0, y:-4},{x:1, y:-4},{x:2, y:-4},{x:3, y:-4},{x:4, y:-4},{x:5, y:-4},
{x:-2, y:-3},{x:-1, y:-3},{x:0, y:-3},{x:1, y:-3},{x:2, y:-3},{x:3, y:-3},{x:4, y:-3},{x:5, y:-3},{x:6, y:-3},{x:7, y:-3},
{x:-3, y:-2},{x:-2, y:-2},{x:-1, y:-2},{x:0, y:-2},{x:1, y:-2},{x:2, y:-2},{x:3, y:-2},{x:4, y:-2},{x:5, y:-2},{x:6, y:-2},{x:7, y:-2},{x:8, y:-2},
{x:-3, y:-1},{x:-2, y:-1},{x:-1, y:-1},{x:0, y:-1},{x:1, y:-1},{x:2, y:-1},{x:3, y:-1},{x:4, y:-1},{x:5, y:-1},{x:6, y:-1},{x:7, y:-1},{x:8, y:-1},
{x:-4, y:0},{x:-3, y:0},{x:-2, y:0},{x:-1, y:0},{x:0, y:0},{x:1, y:0},{x:2, y:0},{x:3, y:0},{x:4, y:0},{x:5, y:0},{x:6, y:0},{x:7, y:0},{x:8, y:0},{x:9,y :0},
{x:-4, y:1},{x:-3, y:1},{x:-2, y:1},{x:-1, y:1},{x:0, y:1},{x:1, y:1},{x:2, y:1},{x:3, y:1},{x:4, y:1},{x:5, y:1},{x:6, y:1},{x:7, y:1},{x:8, y:1},{x:9, y:1},
{x:-5, y:2},{x:-4, y:2},{x:-3, y:2},{x:-2, y:2},{x:-1, y:2},{x:0, y:2},{x:1, y:2},{x:2, y:2},{x:3, y:2},{x:4, y:2},{x:5, y:2},{x:6, y:2},{x:7, y:2},{x:8, y:2},{x:9, y:2},{x:10, y:2},
{x:-5, y:3},{x:-4, y:3},{x:-3, y:3},{x:-2, y:3},{x:-1, y:3},{x:0, y:3},{x:1, y:3},{x:2, y:3},{x:3, y:3},{x:4, y:3},{x:5, y:3},{x:6, y:3},{x:7, y:3},{x:8, y:3},{x:9, y:3},{x:10, y:3},
{x:-4, y:4},{x:-3, y:4},{x:-2, y:4},{x:-1, y:4},{x:0, y:4},{x:1, y:4},{x:2, y:4},{x:3, y:4},{x:4, y:4},{x:5, y:4},{x:6, y:4},{x:7, y:4},{x:8, y:4},{x:9, y:4},
{x:-4, y:5},{x:-3, y:5},{x:-2, y:5},{x:-1, y:5},{x:0, y:5},{x:1, y:5},{x:2, y:5},{x:3, y:5},{x:4, y:5},{x:5, y:5},{x:6, y:5},{x:7, y:5},{x:8, y:5},{x:9, y:5},
{x:-3, y:6},{x:-2, y:6},{x:-1, y:6},{x:0, y:6},{x:1, y:6},{x:2, y:6},{x:3, y:6},{x:4, y:6},{x:5, y:6},{x:6, y:6},{x:7, y:6},{x:8, y:6},
{x:-3, y:7},{x:-2, y:7},{x:-1, y:7},{x:0, y:7},{x:1, y:7},{x:2, y:7},{x:3, y:7},{x:4, y:7},{x:5, y:7},{x:6, y:7},{x:7, y:7},{x:8, y:7},
{x:-2, y:8},{x:-1, y:8},{x:0, y:8},{x:1, y:8},{x:2, y:8},{x:3, y:8},{x:4, y:8},{x:5, y:8},{x:6, y:8},{x:7, y:8},
{x:0, y:9},{x:1, y:9},{x:2, y:9},{x:3, y:9},{x:4, y:9},{x:5, y:9},
{x:2, y:10},{x:3, y:10},
]']
}]
[H: area = json.set("{}", "offsets", areaOffsets)]
[H: cond = json.set("{}", "area", area, "Current", 0, "unsetStates",json.append("","Dead"), "layer", json.append("", "object", "hidden", "token"))]
[H: targets = getTokenNames("json", cond)]

<!--- setting energy type for output --->
[h, if(EnergyType == 0): Energy = "<b>Fire</b>"]
[h, if(EnergyType == 1): Energy = "<b>Acid</b>"]
[h, if(EnergyType == 2): Energy = "<b>Cold</b>"]
[h, if(EnergyType == 3): Energy = "<b>Sonic</b>"]
[h, if(EnergyType == 4): Energy = "<b>Electricity</b>"]

<!-- applying damage-->
CL is <b>[r:CL]</b> and DC is <b>[r:DC] </b>for <b>[r:DMG]</b> of [r:Energy] dmg.
[H: output = "<table border=0><tr><th>Target  </th><th>" + "Save" + "  </th>" + "<th>" + "Damage" "</th></tr>"]
[h, foreach(id,targets, <br>), code:
{
<!-- Get token Hit point values -->
[h: HP = getProperty("HP", id)]
[h: HPtemp = getProperty("HPtemp", id)]

<!--- Determine Reflex save --->
[h: RefRoll = 1d20]
[h: reflex = getProperty("Reflex", id)]
[h: DexB = getProperty("DexB" , id)]
[h: RefBonus = getProperty("ReflexBonus" , id)]
[h: Ref = RefRoll+reflex+DexB+Refbonus]

<!---- Determine DR and ER values --->
[h: DRERMod = getProperty("DRERMod" ,id)]
[h, if(EnergyType == 0): ER = json.get(DRERMod, "ER_Fire")]
[h, if(EnergyType == 1): ER = json.get(DRERMod, "ER_Acid")]
[h, if(EnergyType == 2): ER = json.get(DRERMod, "ER_Cold")]
[h, if(EnergyType == 3): ER = json.get(DRERMod, "ER_Sonic")]
[h, if(EnergyType == 4): ER = json.get(DRERMod, "ER_Electricity")]
[h: DRER = getProperty("DRER" ,id)]
[h: DR = json.get(DRER, "Energy Resistance")]
[h, if(EnergyType == 0): DR = json.get(DR, "Fire")]
[h, if(EnergyType == 1): DR = json.get(DR, "Acid")]
[h, if(EnergyType == 2): DR = json.get(DR, "Cold")]
[h, if(EnergyType == 3): DR = json.get(DR, "Sonic")]
[h, if(EnergyType == 4): DR = json.get(DR, "Electricity")]
[h: DMGResist = max(DR, ER)]


<!--- get evasion values and modify DMG --->
[h: evasion = getProperty("evasion", id)]
[h: impevasion = getProperty("impevasion", id)]
[h, if(evasion == 1 && impevasion == 0 && Ref >= DC): DMG2 = 0]
[h, if(evasion == 1 && impevasion == 0 && Ref < DC): DMG2 = DMG]
[h, if(impevasion == 1 && evasion == 1 && ref >= DC): DMG2 = 0]
[h, if(impevasion == 1 && evasion == 1 && ref < DC): DMG2 = DMG/2]
[h, if(evasion == 0 && impevasion == 0 && ref >= DC): DMG2 = DMG/2]
[h, if(evasion == 0 && impevasion == 0 && ref < DC): DMG2 = DMG]
<!--- determine if helpless --->
[h: Dying = getState("Dying", id)]
[h: Incapacitated = getState("Incapacitated", id)]
[h: Unconscious = getState("Unconscious", id)]
[h: Paralyzed = getState("Paralyzed", id)]
[h,  if(Dying == 1 || Incapacitated == 1 || Unconscious == 1 || Paralyzed == 1): helpless = 1; helpless = 0)]
[h, if(helpless == 1): DMG2 = DMG)]


<!------------ update HPs------------------->
<!--- dealing with DR --->
[h: DMG2 = round(DMG2)]
[h, if(DMGResist > 0): DMG2 = DMG2-DMGResist]
[h, if(DMG2 < 0): dmg2 = 0]
<!--- dealing with temp hps --->
[h, if(HPtemp >= DMG2), code:
{
[h: HPtemp = HPtemp-DMG2]
[h: DMG2 =0]
[h: setProperty("HPtemp", HPtemp, id)]
}]
[h, if(HPtemp < DMG2), code:
{
[h: setProperty("HPtemp" , 0, id)]
[h: DMG2 = DMG2 - HPtemp]
}]

<!--- updating HP property --->
[h: setProperty("HP", HP-DMG2, id)]

<!--- update states and HP bars by calling to lib --->
[tToken= id]
[H, MACRO( "subUpdateHPStatesBars@Lib:libDnD35Pathfinder" ): "Token=" + tToken]

<!--- fill in individual stats into text list -->
[H: output = output + "<tr><td>" + id + "</td><td align=center bgcolor=" + if(Ref >= DC, "green", "red") + ">" + Ref + "</td>" + "<td align=center>" + DMG2 + "</td></tr>"]
}]

[H: output = output + "</table>"]
[R: output]

Re: Fireball token + macro

Posted: Sat Sep 17, 2011 2:39 pm
by lmarkus001
I ran into some intense performance issues using the Area parameter of Wiki: getTokens() (see this thread: http://forums.rptools.net/viewtopic.php?f=20&t=19849 ). I have not played with what you have here, but I see you are using the Area parameter. In that thread you will see Aliasmask convinced me that multiple Range getTokens() calls were faster than one Area call and so I have re-written my Black Tentacles macro (which dropped execution time from 4.5 minutes to 23 seconds). You may want to peruse that should you run into performance issues.

Another tid-bit... two people may not modify a single token at the same time. A player that has their token selected counts as a person modifying their token. So when you run your macro (or my Black Tentacles macros) make certain that it is run by the GM and no players have any tokens selected.

The workaround to this is to send the players macroLinks that they use to apply the damage themselves. This is less elegant, but more stable.

I like the idea of templates that can be summoned and dropped on the map and the player can run a macro that performs all saving throws for tokens in the area. That is safe to do and fast to code. I may extend that with an Apply-Damage macrolink to the owners of the tokens.

Re: Fireball token + macro

Posted: Mon Sep 19, 2011 11:20 am
by lmarkus001
You inspired me to make a generic spell targeting token!

So I grabbed yours to see what ideas it would spark (it is always good to leverage other peoples work and ideas :-) ).

One quick fix I would suggest for your code is a token property type filter. My first test was on a bed of Basic tokens with no data in them (they were on the Object layer, so this is actually a thing you could run in too). I would suggest removing from processing any token that is not a "Pathfinder" or "DnD35" token type... like thus (this presumes you are returning an array of token ids):

Code: Select all

[H, FOR(i, json.length(targets)-1, -1, -1), CODE: {
  [tID = json.get(targets, i)]
  [tType = getPropertyType(tID)]
  [IF(tType != "DnD35" && tType != "Pathfinder"): targets = json.remove(targets, i)]
}] 

Re: Fireball token + macro

Posted: Mon Sep 19, 2011 1:36 pm
by mfrizzell
lmarkus001 wrote:You inspired me to make a generic spell targeting token!

So I grabbed yours to see what ideas it would spark (it is always good to leverage other peoples work and ideas :-) ).

One quick fix I would suggest for your code is a token property type filter. My first test was on a bed of Basic tokens with no data in them (they were on the Object layer, so this is actually a thing you could run in too). I would suggest removing from processing any token that is not a "Pathfinder" or "DnD35" token type... like thus (this presumes you are returning an array of token ids):

Code: Select all

[H, FOR(i, json.length(targets)-1, -1, -1), CODE: {
  [tID = json.get(targets, i)]
  [tType = getPropertyType(tID)]
  [IF(tType != "DnD35" && tType != "Pathfinder"): targets = json.remove(targets, i)]
}] 
I don't play either pathfinder or 3.5 but always interested in discussions of new code. So I was wonder if you last line of code.

Code: Select all

[IF(tType != "DnD35" && tType != "Pathfinder"): targets = json.remove(targets, i)]
}]
Shouldn't actually be or'ed instead of and'ed as you state in your description. I believe your list will always be empty as no token can have 2 property types.

Re: Fireball token + macro

Posted: Mon Sep 19, 2011 2:30 pm
by lmarkus001
Nope it is correct as posted... it can be read as,

If the token id is not from a Pathfinder token, and the token id is not from a D&D3.5 token, then remove that id from the collection of ids to be processed.

Re: Fireball token + macro

Posted: Mon Sep 19, 2011 2:33 pm
by aliasmask
Another way it could be written is if token is not from current system token type.

Re: Fireball token + macro

Posted: Sun Sep 25, 2011 10:42 pm
by jsharen
Ok I am still getting an error message on the latest version. :(

I did notice that this line has lower case dmg2:

Code: Select all

<!------------ update HPs------------------->
<!--- dealing with DR --->
[h: DMG2 = round(DMG2)]
[h, if(DMGResist > 0): DMG2 = DMG2-DMGResist]
[h, if(DMG2 < 0): dmg2 = 0]
However I changed that, and now I get unknown json type error.

Untouched it pops up DMG2 is unknown, and asks me for a number. if I put that number in, then the damage is shown as whatever number I put in.

In the attached example I just left it at the default 0 for dmg2.