Problem with a loop

Discuss macro implementations, ask for macro help (to share your creations, see User Creations, probably either Campaign Frameworks or Drop-in Resources).

Moderators: dorpond, trevor, Azhrei, giliath, jay, Mr.Ice

Post Reply
User avatar
TheIneffableCheese
Cave Troll
Posts: 64
Joined: Sun Mar 22, 2015 3:57 pm

Problem with a loop

Post by TheIneffableCheese »

I'm, apparently, not understanding looping.

I'm trying to up my macro game a bit. I have a fairly basic healing macro that works exactly as intended. It pulls the HP property from the token, applies the healing, adjusts some states dealing with the health of the character, then writes the new HP total back to the token and publishes a message to the GM about the relative health of the character. See code here:
Working Healing Macro

Code: Select all


[h: Input("Healing | 0 | Input amount healed")]

<!--- Set variables from token --->
[h: hpCurrent = getProperty("HP")]
[h: hpMax = getProperty("MaxHP")]
[h: nlCurrent = getProperty("Nonlethal")]

<!--- do math to find post-healing values --->
[h, if (hpCurrent + healing > hpMax): hpCurrent = hpMax; hpCurrent = hpCurrent + healing]
[h, if (nlCurrent > 0): nlCurrent = nlCurrent - healing]
[h, if (nlCurrent < 0): nlCurrent = 0]

<!--- Set states based on new HP totals --->
[h, if (hpCurrent == nlCurrent): setState("Staggered", 1); setState("Staggered", 0)]
[h, if (hpCurrent < nlCurrent): setState("Unconscious", 1); setState("Unconscious", 0)]
[h, if (hpCurrent >= hpMax * 0.25): setState("Wounded3", 0)]
[h, if (hpCurrent >= hpMax * 0.5): setState("Wounded2", 0)]
[h, if (hpCurrent >= hpMax * 0.75): setState("Wounded1", 0)]

<!--- set Properties on token to new HP values --->
[h: setProperty("HP", hpCurrent)]
[h: setProperty("Nonlethal", nlCurrent)]

<!--- display HP status to GM --->
[h: output = "Has "+getProperty("HP")+" of "+getProperty("MaxHP")+" HP currently."]
[g,r: output]

I want to have the macro apply the same amount of healing to all selected tokens. The idea would be I could grab a bunch of tokens who all receive a mass healing spell or the like. The other idea is using this as a prototype for doing the same thing with my (much more complicated) Damage macro. My thought was to put my working healing macro inside a foreach loop.

However, it's not working as anticipated. It prompts for the damage IDing the first selected token in the title bar at the top of the Input dialog box, then it prompts for damage IDing the second token, and so on for each selected token. Then it is applying all the prompted healing values to all the tokens. It is also not publishing the GM message at the end of the code block.

Here is the code that isn't working as expected.
Broken Looping Healing Macro

Code: Select all


[h: ids = getSelected()]
[h: Input("healing | 0 | Input amount healed")]

[h, foreach(id, ids), code:{

	<!--- Set variables from token --->
	[h: hpCurrent = getProperty("HP", id)]
	[h: hpMax = getProperty("MaxHP", id)]
	[h: nlCurrent = getProperty("Nonlethal", id)]
	
	<!--- do math to find post-healing values --->
	[h, if (hpCurrent + healing > hpMax): hpCurrent = hpMax; hpCurrent = hpCurrent + healing]
	[h, if (nlCurrent > 0): nlCurrent = nlCurrent - healing]
	[h, if (nlCurrent < 0): nlCurrent = 0]
	
	<!--- Set states based on new HP totals --->
	[h, if (hpCurrent == nlCurrent): setState("Staggered", 1, id); setState("Staggered", 0, id)]
	[h, if (hpCurrent < nlCurrent): setState("Unconscious", 1, id); setState("Unconscious", 0, id)]
	[h, if (hpCurrent >= hpMax * 0.25): setState("Wounded3", 0, id)]
	[h, if (hpCurrent >= hpMax * 0.5): setState("Wounded2", 0, id)]
	[h, if (hpCurrent >= hpMax * 0.75): setState("Wounded1", 0, id)]
	
	<!--- set Properties on token to new HP values --->
	[h: setProperty("HP", hpCurrent, id)]
	[h: setProperty("Nonlethal", nlCurrent, id)]
	
	<!--- display HP status to GM --->
	[h: output = "Has "+getProperty("HP")+" of "+getProperty("MaxHP")+" HP currently."]
	[g,r: output]
}]

I have been over this and over this. I revisited the wiki article on looping. I just can't seem to figure out what's up.

So, my last thought was to write a super simple looping macro from scratch and slowly build up from there. I decided to make something that damages the tokens by a set amount - pull the HP property, subtract 10, write it back to the token.

However, with this one I'm getting a similar behavior - the 10 points is subtracted once for each token selected. So, if I select two they each take 20 points, selecting three results in 30 points of damage to each token, etc.
Weird Damage Loop

Code: Select all


[h: ids = getSelected()]

[h, foreach(id, ids), code:{
	[h: hpNow = getProperty("HP")]
	[h: hpNow = hpNow - 10]
	[h: setProperty("HP", hpNow)]
}]

Any thoughts on what I'm doing wrong?

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

Re: Problem with a loop

Post by aliasmask »

Try this. I didn't dissect everything. I just took your good code, put it into a loop with switchToken and altered the output process. Also, very important, make sure the macro does not have Apply to Selected Token checked, otherwise it'll run on all the tokens for each tokens selected. This macro needs to be on a lib token or campaign window with allow players to edit unchecked because of permissions.

Code: Select all

[h: ids = getSelected()]
[h: Input("healing | 0 | Input amount healed")]

[H: output = "[]"]
[h, foreach(id, ids), code: {
   [H: switchToken(id)]

   <!--- Set variables from token --->
   [h: hpCurrent = getProperty("HP")]
   [h: hpMax = getProperty("MaxHP")]
   [h: nlCurrent = getProperty("Nonlethal")]

   <!--- do math to find post-healing values --->
   [h, if (hpCurrent + healing > hpMax): hpCurrent = hpMax; hpCurrent = hpCurrent + healing]
   [h, if (nlCurrent > 0): nlCurrent = nlCurrent - healing]
   [h, if (nlCurrent < 0): nlCurrent = 0]

   <!--- Set states based on new HP totals --->
   [h, if (hpCurrent == nlCurrent): setState("Staggered", 1); setState("Staggered", 0)]
   [h, if (hpCurrent < nlCurrent): setState("Unconscious", 1); setState("Unconscious", 0)]
   [h, if (hpCurrent >= hpMax * 0.25): setState("Wounded3", 0)]
   [h, if (hpCurrent >= hpMax * 0.5): setState("Wounded2", 0)]
   [h, if (hpCurrent >= hpMax * 0.75): setState("Wounded1", 0)]

   <!--- set Properties on token to new HP values --->
   [h: setProperty("HP", hpCurrent)]
   [h: setProperty("Nonlethal", nlCurrent)]

   <!--- save HP status to GM --->
   [h: output = json.append(output,strformat("%{token.name} has %{HP} of %{MaxHP} HP currently."))]
}]

[R,G: json.toList(output,"<BR>")] 
edit: added ) to fix code.

User avatar
TheIneffableCheese
Cave Troll
Posts: 64
Joined: Sun Mar 22, 2015 3:57 pm

Re: Problem with a loop

Post by TheIneffableCheese »

Well, clearly part of my problem was the fact I had Apply to Selected Token checked.

I unchecked that, and used Aliasmask's code with the switchToken call. Now I'm getting the following error message in the chat, and no healing is being applied:

"Invalid number of parameters 1, expected exactly 2 parameter(s)"

Any idea what that means? I've never run across that error.

including updated code for ease of reference:
Updated Code

Code: Select all

[h: ids = getSelected()]
[h: Input("healing | 0 | Input amount healed")]

[H: output = "[]"]

[h, foreach(id, ids), code: {
   [H: switchToken(id)]

   <!--- Set variables from token --->
   [h: hpCurrent = getProperty("HP", id)]
   [h: hpMax = getProperty("MaxHP", id)]
   [h: nlCurrent = getProperty("Nonlethal", id)]

   <!--- do math to find post-healing values --->
   [h, if (hpCurrent + healing > hpMax): hpCurrent = hpMax; hpCurrent = hpCurrent + healing]
   [h, if (nlCurrent > 0): nlCurrent = nlCurrent - healing]
   [h, if (nlCurrent < 0): nlCurrent = 0]

   <!--- Set states based on new HP totals --->
   [h, if (hpCurrent == nlCurrent): setState("Staggered", 1, id); setState("Staggered", 0, id)]
   [h, if (hpCurrent < nlCurrent): setState("Unconscious", 1, id); setState("Unconscious", 0, id)]
   [h, if (hpCurrent >= hpMax * 0.25): setState("Wounded3", 0, id)]
   [h, if (hpCurrent >= hpMax * 0.5): setState("Wounded2", 0, id)]
   [h, if (hpCurrent >= hpMax * 0.75): setState("Wounded1", 0, id)]

   <!--- set Properties on token to new HP values --->
   [h: setProperty("HP", hpCurrent, id)]
   [h: setProperty("Nonlethal", nlCurrent, id)]

   <!--- save HP status to GM --->
   [h: output = json.append(output,strformat("%{token.name} has %{hpCurrent} of %{hpMax} HP currently.")]
}]

[R,G: json.toList(output,"<BR>")] 

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

Re: Problem with a loop

Post by aliasmask »

I left off a ) at the end of my code:

Code: Select all

   [h: output = json.append(output,strformat("%{token.name} has %{HP} of %{MaxHP} HP currently."))]

User avatar
TheIneffableCheese
Cave Troll
Posts: 64
Joined: Sun Mar 22, 2015 3:57 pm

Re: Problem with a loop

Post by TheIneffableCheese »

That did it! Thanks again for your help.

Post Reply

Return to “Macros”