Help with a macro

If you have searched the other User Creations subforums and an answer to your question has not been found, please post here!

Moderators: dorpond, trevor, Azhrei, Gamerdude

raazorfiend
Kobold
Posts: 17
Joined: Thu Sep 19, 2013 12:40 pm

Help with a macro

Post by raazorfiend »

Hey Im working on a simple Macro, I want it to damage or heal a selected token, and set stage to Wounded, Dying or dead.

Using HP and MaxHP
So far it looks like this:

Code: Select all

[h:switchToken(getSelected())]
[h:status = input(
"hpAmount|0|Points",
"hpType|Damage,Healing|Damage or heal?|RADIO|SELECT=0")]
[h:abort(status)]

[if(hpType == 0),CODE: {
	[h:diff = max(0, hpAmount - PD)]
        [h:HP = max(-10, HP - diff)]
        [h:bar.Health = HP / MaxHP]
        [r:token.name] takes [r:diff] damage.
        [h, if(HP >= -MaxHP): state.Dead = 1]
        [h, if(HP == -MaxHP): state.Dying = 1]
        [h, if(HP >= -1): setAllStates(0)]
        [h, if(HP >= (MaxHP/2)): state.Wounded = 1]
       };
{
        [h:diff = MaxHP - HP]
        [h:HP = min(HP+hpAmount, MaxHP)]
        [h:bar.Health = HP / MaxHP]
        [r:token.name] gains [r:min(diff,hpAmount)] HP. 
	[H, if(HP >= (-MaxHP/2)): setAllStates(0)]};]
        
Now I cant make it set state.Dying on 0HP
The Dead state works, the wounded state applies on first hit no matter the damage, but applying more damage, but not enough to reach 0 removes wounded state..
Ech
Any great ideas?

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Help with a macro

Post by wolph42 »

given that its completely unclear when ' dying ' and 'dead' apply I've assumed that <0 is dying and -10 is dead. made some minor and major changes, didn't look at healing part.

Code: Select all

[h:switchToken(getSelected())]
[h:abort(input(
	"hpAmount|0|Points",
	"healing|Damage,Healing|Damage or heal?|RADIO|SELECT=0"
))]

[if(!healing),CODE: {
	[h:diff = max(0, hpAmount - PD)] <!-- no clue what pd is -->
	[h:HP = max(-10, HP - diff)]
	[h:bar.Health = HP / MaxHP]
	[r:token.name] takes [r:diff] damage.
};{
	[h:diff = MaxHP - HP]
	[h:HP = min(HP+hpAmount, MaxHP)]
	[h:bar.Health = HP / MaxHP]
	[r:token.name] gains [r:min(diff,hpAmount)] HP. 
	[H:' , if(HP >= (-MaxHP/2)): setAllStates(0)' ]<!-- i would be a bit careful with ALL states. e.g. prone, flying, sick, dizzy, sleeping, etc. will also be turned off-->
}]

[h: state.Dying = if(HP < 0 && HP > -10, 1, 0)]
[h: state.Dead = if(HP <= -10, 1, 0)]
[h: state.Wounded = if(HP < MaxHP && !state.Dead, 1, 0)]

        

raazorfiend
Kobold
Posts: 17
Joined: Thu Sep 19, 2013 12:40 pm

Re: Help with a macro

Post by raazorfiend »

Dying is indeed between 0 and -10
PD is Passive defence, the sum of armor and magic trinkets that reduce direkt damage.

Thanks a lot, Ill give it a try right away :)

- - -
Edit.
So I see your point with set all states, and removed that bit.
Seems Wounded stage pops on at any damage, so modified that to [h: state.Wounded = if(HP < MaxHP/2 && !state.Dead, 1, 0)]

In the system we play, being on half Hp reduces move and attacks by ½ (being half dead)

Never the less its awesome! Thank you mate! - cant wrap my head around the "&& !" type funktion.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Help with a macro

Post by wolph42 »

! means 'not' and inverts a true/false. Note that
true=a number not zero and
false=0
so !34=0 and !0=1
You can make nifty use of that function in case e.g. for your list where the 'damage' choice results in 0 (false) and 'healing' choice results in 1 (true).

&& is 'AND' just as || is 'OR'
where AND means that BOTH conditions must be met and OR means only ONE condition needs to be met.

the lot are called 'operators', more on this: https://wiki.rptools.info/index.php/if_(roll_option)

raazorfiend
Kobold
Posts: 17
Joined: Thu Sep 19, 2013 12:40 pm

Re: Help with a macro

Post by raazorfiend »

Hello,

A new problem has arrised with a macro for wh40k.
Heres the macro I use to deal damage to enemies. Its only the Bolter on single and full auto:

Code: Select all

[h:switchToken(getSelected())]
[h:abort(input(
	"BSInput|0|BS",
	"Single|Single,Full Auto auto|Single or Full Auto|RADIO|SELECT=0"
))]
[h:Pen = 5]
[if(!Single),CODE: {
	[H: link = "https://ia601508.us.archive.org/29/items/Boltersinglefire/Boltersinglefire.mp3"]
        [H: execFunction("playClip",json.append("",link))]
	[H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[H:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage.
};{
	[H: link = "https://ia601501.us.archive.org/7/items/bolter-autofire/Bolter%20Autofire.mp3"]
	[H: execFunction("playClip",json.append("",link))]
	[H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[h:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage.. 
and	
	[H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[h:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage.
and
       [H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[h:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage
and
	[H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[h:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage.}]
	
	
[h: state.Critical_wound = if(Wounds < 0 && Wounds > -10, 1, 0)]
[h: state.Dead = if(Wounds <= -10, 1, 0)]
[h: state.Wounded = if(Wounds < MaxWounds/2 && !state.Dead, 1, 0)]
[h: state.Lightly_Wounded = if(Wounds < MaxWounds/3 && !state.Dead, 1, 0)]

Now I have 3 problems.
1, Id like to test ad100 roll against the entered and modified BS (Balistic skill) -and do a GOTO END or "You missed" on miss.
2, Pen (penetration) is currently just added, and armor deducted from damage, but the Pen dont actually deal more damage, so someone wearing no armor will currently take the added pen in damage, which is less then ideal.
3, It would be even smarter if I could select the shooter and target, and get their probaties for: Attacker -BS- Weapon, pen - Damage and sound
and for: Defender Dodge(ag+skill) test, Armor - penetration, with a floor/min funktion - and apply damage to target depending on the number of degrees of success (if you have BS 50% and roll 35, you hit with 1 degree) Degree basically 1 pr 10 you roll lower.

I have this hit or miss macro, but I cant figure how to incorperate it above, because the 2 IF() seems to mess up..

Code: Select all

[h:targetNumber = BS] <!--input-->

[h,if(attackRoll >= targetNumber), code:
{
  [attackResult = "hits"]
  [h: DamageRoll =  PrimaryDamage]
  };
{
  [attackResult = "miss"]
  [h: DamageRoll =  0]
  }]

Your attack [attackResult], and you do [DamageRoll] damage. 
Long Post, but I had a lot of luck with this community so far!

Finally my own failed attempt at merging the 2 macros :|

Code: Select all

[h:switchToken(getSelected())]
[h:abort(input(
	"BSInput|0|BS",
	"Single|Single,Full Auto auto|Single or Full Auto|RADIO|SELECT=0"
))]
[h:Pen = 5]
[h:targetNumber = BSInput]
[h:attackRoll = 1d100]
[h,if(attackRoll >= targetNumber), code:
{
  [attackResult = "hits"]
    };
{
  [attackResult = "miss"]
  [h: DamageRoll =  0]
  }] 
  
[if(!hits),CODE: {
	[H: link = "https://ia601508.us.archive.org/29/items/Boltersinglefire/Boltersinglefire.mp3"]
    [H: execFunction("playClip",json.append("",link))]
	[H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[H:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage.
};{
	[H: link = "https://ia601501.us.archive.org/7/items/bolter-autofire/Bolter%20Autofire.mp3"]
	[H: execFunction("playClip",json.append("",link))]
	[H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[h:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage.. 
and	
	[H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[h:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage.
and
    [H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[h:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage
and
	[H: hitLocation = tbl("HitLocation")]
	[R: strformat("Hit in the %{hitlocation}")]
	[h:diff = max(0, 2d10+5 + Pen - AP - Tb)] 
	[h:Wounds = max(-10, Wounds - diff)]
	[r:token.name] takes [r:diff] damage.}]
	
	
[h: state.Critical_wound = if(Wounds < 0 && Wounds > -10, 1, 0)]
[h: state.Dead = if(Wounds <= -10, 1, 0)]
[h: state.Wounded = if(Wounds < MaxWounds/2 && !state.Dead, 1, 0)]
[h: state.Lightly_Wounded = if(Wounds < MaxWounds/3 && !state.Dead, 1, 0)]


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

Re: Help with a macro

Post by aliasmask »

This may not be everything because too much info for me is missing, but this should help you along.

Code: Select all

[h:switchToken(getSelected())]
[h:abort(input(
	"BSInput|0|BS",
	"fullAuto|Single,Full Auto auto|Single or Full Auto|RADIO|SELECT=0"
))]

<!-- ag and skill should be properties of token (I would use better names though) -->
[H: defense = ag + skill]
[H: attackDiff = BS - defense]
[h: Pen = 5]
[H: armorDefense = getProperty("AP")]
[H: mysteryStat = getProperty("Tb")]
[H: weaponDamage = "2d10+5"]

<!-- test for 0, 1 hit and every +10 after that -->
[H, if(attackDiff >= 0): successes = if(fullAuto,1 + floor(attackDiff / 10),1); successes = 0]

<!-- generate basic attack info -->
[H, if(fullAuto && successes): attackOutput = strformat("%{token.name} is attacked with Bolter (%{weaponDamage}), full auto. Is hit %{successes} time(s).")]
[H, if(! fullAuto && successes): attackOutput = strformat("%{token.name} is attacked with Bolter (%{weaponDamage}), single shot. Is hit 1 time.")]
[H, if(! successes): attackOutput = strformat("%{token.name} is attacked with Bolter. Miss.")]

<!-- calc damage -->
[H: totalDamage = 0]
[H, c(successes), code: {
	[H: hitLocation = tbl("HitLocation")]
   [H: damage = max(0,eval(weaponDamage) - max(0,armorDefense - Pen) - mysteryStat)]
   <!-- add damage to attack output -->
   [H, if(damage): attackOutput = json.append(attackOutput,strformat("Shot %d: %{damage} to location %{hitLocation}",roll.count +1));
      attackOutput = json.append(attackOutput,strformat("Shot %d: Absorbed by armor."))
   ]
   [H: totalDamage = totalDamage + damage]
}]

<!-- update health and states -->
[H: Wounds = max(-10,Wounds - totalDamage)]

[h: state.Dead = if(Wounds <= -10, 1, 0)]
[h: state.Critical_wound = if(Wounds < 0 && Wounds > -10, 1, 0)]
[h: state.Wounded = if(Wounds < MaxWounds/2 && Wounds >= 0, 1, 0)]
[h: state.Lightly_Wounded = if(Wounds < MaxWounds/3 && Wounds >= MaxWounds/2, 1, 0)]

<!-- special effects at the end -->
[H, if(fullAuto): link = "https://ia601501.us.archive.org/7/items/bolter-autofire/Bolter%20Autofire.mp3";
   link = "https://ia601508.us.archive.org/29/items/Boltersinglefire/Boltersinglefire.mp3"
]
[H: execFunction("playClip",json.append("",link),1,"all")]

<!-- output -->
[R: json.toList(attackOutput,"<BR>")]


raazorfiend
Kobold
Posts: 17
Joined: Thu Sep 19, 2013 12:40 pm

Re: Help with a macro

Post by raazorfiend »

@Wolph42 thanks, something I wanted to do since 2013 xD, Im currently adding Las,Single, semi, autoo, Plasma single, semi, overcharged, Bolter, single, semi, auto, Heavy bolter auto, chain weapon, hit, miss and idle. Heres my archive: https://archive.org/details/@razorfiend

Hey thanks Aliasmask! First off, Im very grateful for your assistance, you clearly know this programming very well!

Ok I see I should explain a bit xD this is a D100 based system.

TB is Toughness bonus - the first digit of the Toughness stat - and is deducted from nearly ALL damage, so 50% Toughness = TB 5
Toughness is not affected by Penetration.

Ag is agility and the base Dodge chance - however skill dodge can be bought to+10 or +20, dodging completely negates damage.

AP = Armor points These are actually often different pr body part, so in its final form the macro should use the hitlocation to get
HeadAP:0
BodyAP:0
ArmLeftAP:0
ArmRightAP:0
LegLeftAP:0
LegRightAP:0 - at the moment I use just a AP stat because *Im just a script kitty*

Defence is a dodge, which in wh40k Deathwatch negates 1 hit pr success. Defined as if my Ag is 30 and I have Dodge +20 - I roll d100 ~ 30
-I succeeded with 2 degrees EG. I dodge 3 hits, one for succeeding plus 2 for the degrees.

The correct battle mechanic therefore would be
1-Test BS to hit (in Full auto this is +20 and a hit pr degree, in semi its +10 and a hit pr second degree.
So a semi auto attack is rol d100- test vs my imput BS (because its easier to enter BS by hand due to many many modifiers) calculate potential hits.
2-Test Ag+dodge vs d100 for defender and see if any hits are negated.
3-Apply and output results..

So with those denountions in mind Id change skill to Dodge, like so

Code: Select all

[h:switchToken(getSelected())]
[h:abort(input(
	"BSInput|0|BS",
	"fullAuto|Single,Full Auto auto|Single or Full Auto|RADIO|SELECT=0"
))]

<!-- ag and skill should be properties of token (I would use better names though) -->
[h:attackRoll = 1d100]
 (attackRoll >= BS)
<!--Calculate degrees and hits-->
[H: attackDiff = BS vs d100]
[H: defense = Ag + Dodge]
[H: defence roll = d100]
<!-- Magical comparison of number of degrees BS hits Vs Dodge-->
[H: armorDefense = getProperty("AP")]
[H: mysteryStat = getProperty("Tb")]
[H: weaponDamage = "2d10+5"]
[h: Pen = 5]
<!-- test for 0, 1 hit and every +10 after that -->
[H, if(attackDiff >= 0): successes = if(fullAuto,1 + floor(attackDiff / 10),1); successes = 0]

<!-- generate basic attack info -->
[H, if(fullAuto && successes): attackOutput = strformat("%{token.name} is attacked with Bolter (%{weaponDamage}), full auto. Is hit %{successes} time(s).")]
[H, if(! fullAuto && successes): attackOutput = strformat("%{token.name} is attacked with Bolter (%{weaponDamage}), single shot. Is hit 1 time.")]
[H, if(! successes): attackOutput = strformat("%{token.name} is attacked with Bolter. Miss.")]

<!-- calc damage -->
[H: totalDamage = 0]
[H, c(successes), code: {
	[H: hitLocation = tbl("HitLocation")]
   [H: damage = max(0,eval(weaponDamage) - max(0,armorDefense - Pen) - mysteryStat)]
   <!-- add damage to attack output -->
   [H, if(damage): attackOutput = json.append(attackOutput,strformat("Shot %d: %{damage} to location %{hitLocation}",roll.count +1));
      attackOutput = json.append(attackOutput,strformat("Shot %d: Absorbed by armor."))
   ]
   [H: totalDamage = totalDamage + damage]
}]

<!-- update health and states -->
[H: Wounds = max(-10,Wounds - totalDamage)]

[h: state.Dead = if(Wounds <= -10, 1, 0)]
[h: state.Critical_wound = if(Wounds < 0 && Wounds > -10, 1, 0)]
[h: state.Wounded = if(Wounds < MaxWounds/2 && Wounds >= 0, 1, 0)]
[h: state.Lightly_Wounded = if(Wounds < MaxWounds/3 && Wounds >= MaxWounds/2, 1, 0)]

<!-- special effects at the end -->
[H, if(fullAuto): link = "https://ia601501.us.archive.org/7/items/bolter-autofire/Bolter%20Autofire.mp3";
   link = "https://ia601508.us.archive.org/29/items/Boltersinglefire/Boltersinglefire.mp3"
]
[H: execFunction("playClip",json.append("",link),1,"all")]

<!-- output -->
[R: json.toList(attackOutput,"<BR>")]

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

Re: Help with a macro

Post by aliasmask »

Yeah, I figured the math calculations were off not knowing the system. I did change the state changes since I figured you only wanted one of them to be active at any one time. Also, breaking out the output from what is always included and the attacks would help clarify things.

But I think the macro has a big logic problem. You're mixing stats from target and attacker so it should be made clear what is coming from where. The macro should not have apply to selected on. Attacker will have their token impersonated in the chat and macro will be in the impersonated frame (or campaign window). Then you can do stuff like this.

Code: Select all

[H: attacker = getImpersonated()]
[H: target = getSelected()]

<!-- get target stats -->
[H: switchToken(target)}
... set needed values

<!-- get attacker stats -->
[H: switchToken(attacker)]
... set needed values

<!-- get additional inputs -->
[H: abort(input(...))]

... do the math
I personally don't like using the getImpersonated() method, but it's easier to use. Another method is to draw a frame where the attacker id is set so any attacks using button in frame has the needed info.

raazorfiend
Kobold
Posts: 17
Joined: Thu Sep 19, 2013 12:40 pm

Re: Help with a macro

Post by raazorfiend »

yea I noticed the problem with 2 token attributes.

Actually my states stack, wounded is 2 lines and "lightlywounded" is 1, but comes at 1/3 health left -and then the token has 3 wound lines ^^
but dead should replace dying of course xD

Thats why I made a macro for each weapon. Thus the "Input" BS is manually put by me (GM) because it will need modifiers anyway.
F.eks. Peter shoots a orc, he has 45 Bs, but; the range is short +10, he fires full auto +20, the orc is hulking +10 - so the test is really d100 vs 85.
The macros I made I wanted simply to input the shooter modified BS -because it changes all the time and is simply easier then interchanging 2 tokens.

So as you can see below, I'm really simply making a macro pr weapon. The only token I need to partain to is target. By entering the BS in ite modified and final form as the only input that can nicely test against a d100
Right now entering the BS just does nothing - and armor/tough/dam is not calculated correctly.

In your macro its calculated nice!, we are getting close.

My screen looks like this:
Image
Attachments
exsample2.gif
exsample2.gif (515.69 KiB) Viewed 3816 times
exsample.gif
exsample.gif (612.83 KiB) Viewed 3816 times

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Help with a macro

Post by wolph42 »

probably redundant, but I did create a full fledge framework for W40K over the past 8 years or so. Have you seen that? Link in sig.

raazorfiend
Kobold
Posts: 17
Joined: Thu Sep 19, 2013 12:40 pm

Re: Help with a macro

Post by raazorfiend »

Hey Wolph42

I indeed downloaded your framework with full intent on using it, but loading the campaign file dosent look right. There are no library tokens, macros and so on.

so I kinda just started working on it.

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Help with a macro

Post by wolph42 »

not sure what you mean, just downloaded the campaign file to check, its full with lib tokens a few 100 macros and close to 10.000 library items. They're still there. So what exactly do you mean?

raazorfiend
Kobold
Posts: 17
Joined: Thu Sep 19, 2013 12:40 pm

Re: Help with a macro

Post by raazorfiend »

Well my pc showed the camaping as a zip, renamed it, see tables but not tokens :/ odd enough

also trying to make a simple darn macro that advances initiative, and centers map on the new initiative holder (as as GM or campaign macro)

Code: Select all

[H: nextInitiative()]
[h:getCurrentInitiative(name)]
[H: allSelected = getSelected("json")]
[H, foreach(name,allSelected), code: {
   [H: switchToken(name)]
   [h: goto(name)]
}]
if I manually enter the "name" of the target it do switch to him... but then its faster to dobblelclick anyway

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Help with a macro

Post by wolph42 »

raazorfiend wrote:
Mon Feb 08, 2021 9:29 am
Well my pc showed the camaping as a zip, renamed it, see tables but not tokens :/ odd enough

also trying to make a simple darn macro that advances initiative, and centers map on the new initiative holder (as as GM or campaign macro)

Code: Select all

[H: nextInitiative()]
[h:goto(getInitiativeToken())]
if I manually enter the "name" of the target it do switch to him... but then its faster to dobblelclick anyway
just to be sure, we're talking about this ink right? https://www.dropbox.com/s/018c1rj7asazu ... cmpgn?dl=1
updated code above.

Post Reply

Return to “Requests for HELLLLP!”