Looking for input on 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

Post Reply
Guardian
Kobold
Posts: 8
Joined: Wed Dec 14, 2016 1:30 pm

Looking for input on macro

Post by Guardian »

I know this code is super sloppy, and I personally want to get better/more organized in my approach. I feel like knowing how to write advanced macros would really help me on this front. I need someone to help me out with this project and give me advice on where I could be better. Thank you!




Code: Select all

[h:EnemyList = getSelectedNames()]
[h:Attacker = getImpersonated()]


<!--- Weapon Special Stack Effects --->
[h:AssignedStackNumber = 1]
[h:HasStackEffect = 0]
[h:MaxStackEffect = 4]
[h:StackExtraDamage = 0]
[h:StackExtraPercentDamage = 0]
[h:StackExtraHealing = 0]
[h:StackExtraPercentHealing = 0]
[h:StackEffectDiscription = "Insert a unique description or status effect here"]
[h:StackStrDamage = 0]
[h:StackDexDamage = 0]
[h:StackConDamage = 0]
[h:StackWisDamage = 0]
[h:StackIntDamage = 0]
[h:StackChaDamage = 0]
[h:StackResourceDrain = 0]
[h:StackResourceAbsorb = 0]
[h:StackArmorPiercing = 0]
[h:StackACReduction = 0]


<!--- Get Attacker Stats --->
[h:AttackerStrBonus = getProperty("StrMOD", Attacker)]
[h:AttackerDexBonus = getProperty("DexMOD", Attacker)]
[h:AttackerBAB = getProperty("BAB", Attacker)]
[h:AttackerCriticalTrue = getProperty("CriticalTrue", Attacker)]
[h:AttackerCriticalMult = getProperty("CriticalMult", Attacker)]
[h:AttackerCriticalAdd = getProperty("CriticalAdd", Attacker)]
[h:AttackerAP = getProperty("AP", Attacker)]
[h:AttackerResource = getProperty("Resource", Attacker)]
[h:AttackerResourceOnHit = getProperty("ResourceOnHit", Attacker)]
[h:AttackerMaxResource = getProperty("MaxResource", Attacker)]
[h:AttackerMinResource = getProperty("MinResource", Attacker)]
[h:AttackerResourceOnAttack = getProperty("ResourceOnAttack", Attacker)]
[h:AttackerStackCounter = getProperty("StackCounter"+AssignedStackNumber, Attacker)]
[h:AttackerHP = getProperty("HP", Attacker)]
[h:AttackerMaxHP = getProperty("MaxHP", Attacker)]
[h:AttackerMinHP = getProperty("MinHP", Attacker)]
[h:AttackerName = getImpersonatedName()]
[h:AttackerResourceName = getProperty("ResourceName", Attacker)]


<!--- Weapon Statistics --->
[h:WeaponDamage = 1d4]
[h:WeaponBonusAttackRoll = 0]
[h:WeaponAPCost = 0]
[h:WeaponElement = "Physical"]
[h:GravityPercentDamage = 0]
[h:FinesseWeapon = 0]
[h:WeaponCriticalRangeLow = 20 - AttackerCriticalAdd]
[h:WeaponCriticalMultiplier = 2 + AttackerCriticalMult]
[h:TwoHandedWeapon = 0]
[h:TrueDamageWeapon = 0]


<!--- Weapon Special Attacks and On-Hit effects --->
[h:SpecialAttackDamage = 0]
[h:OnHitEffectDamage = 0]
[h:WeaponEnchantmentDamage = 0]
[h:SneakAttackDamage = 0]
[h:ArmorPiercing = 0]
[h:ACReduction = 0]
[h:CriticalSpecialDamage = 0]
[h:CreateVulnurability = 0]
[h:VulnurabilityPercent = 0]
[h:VulnurabilityExtraDamage = 0]


<!--- Weapon Stat Damage --->
[h:StrDamage = 0]
[h:DexDamage = 0]
[h:ConDamage = 0]
[h:WisDamage = 0]
[h:IntDamage = 0]
[h:ChaDamage = 0]


<!--- Resource Draining and Lifesteal --->
[h:ResourceDrain = 0]
[h:ResourceAbsorb = 0]
[h:OnHitHealing = 0]
[h:OnHitHealingPercent = 0]



<!--- Weapon Finesse Feat Check --->
[h:AttackerWeaponFinesse = getProperty("WeaponFinesse", Attacker)]

<!--- Weapon Basic Calculation Properties --->
[h:Base1 = 1d20]
[h:Base2 = 1d20]


<!--- Weapon Basic Damage Calculation --->
[h, if(AttackerWeaponFinesse == 1), CODE: {
	[h:TotalWeaponDamage = WeaponDamage + DexMOD] }]

[h, if(TwoHandedWeapon == 1), CODE: {
	[h:TotalWeaponDamage = WeaponDamage + AttackerStrBonus*1.5] }]

[h, if(TwoHandedWeapon == 0 && AttackerWeaponFinesse == 0), CODE: {
	[h:TotalWeaponDamage = WeaponDamage + AttackerStrBonus] }]

[h:TotalWeaponDamage = TotalWeaponDamage + SpecialAttackDamage]
[h:TotalWeaponDamage = TotalWeaponDamage + OnHitEffectDamage]
[h:TotalWeaponDamage = TotalWeaponDamage + WeaponEnchantmentDamage]


<!--- Stack Weapon Check --->
[h, if(HasStackEffect == 1 && AttackerStackCounter == MaxStackEffect), CODE: {
	[h:TotalWeaponDamage = TotalWeaponDamage + StackExtraDamage]
	[h:GravityPercentDamage = GravityPercentDamage + StackExtraPercentDamage]
	[h: OnHitHealing = OnHitHealing + StackExtraHealing]
	[h: OnHitHealingPercent = OnHitHealingPercent + StackExtraPercentHealing]
	[h: StrDamage = StrDamage + StackStrDamage]
	[h: DexDamage = DexDamage + StackDexDamage]
	[h: ConDamage = ConDamage + StackConDamage]
	[h: WisDamage = WisDamage + StackWisDamage]
	[h: IntDamage = IntDamage + StackIntDamage]
	[h: ChaDamage = ChaDamage + StackChaDamage]
	[h: ResourceDrain = ResourceDrain + StackResourceDrain]
	[h: ResourceAbsorb = ResourceAbsorb + StackResourceAbsorb]
	[h: ArmorPiercing = ArmorPiercing + StackArmorPiercing]
	[h: ACReduction = ACReduction + StackACReduction]
	[h:setProperty("StackCounter"+AssignedStackNumber, 0, Attacker)]
}]
[h, if(HasStackEffect == 1 && AttackerStackCounter < MaxStackEffect), CODE: {
	[h:setProperty("StackCounter"+AssignedStackNumber, AttackerStackCounter + 1, Attacker)]
}]


<!--- Sneak Attack and Bonus Calculations --->
[h: ResourceDrainCheck = if(ResourceDrain != 0, "Resource Drained: " + ResourceDrain + "<br>", "")]
[h: ResourceAbsorbCheck = if(ResourceAbsorb != 0, "Resource Absorbed: " + ResourceAbsorb + "<br>", "")]
[h: VulnurabilityCheck = if(CreateVulnurability == 1 && VulnurabilityExtraDamage != 0, "Vulurability Created For: " + VulnurabilityExtraDamage + "<br>", "")]
[h: VulnurabilityCheck2 = if(CreateVulnurability == 1 && VulnurabilityPercent != 0, "Vulnurability Created For: " + VulnurabilityPercent + 100 + "%<br>", "")]
[h: APCheck = if(WeaponAPCost > AttackerAP, 0, 1)]
[h:StrDamageCheck = if(StrDamage != 0, "Str Damage: " + StrDamage + "<br>","")]
[h:DexDamageCheck = if(DexDamage != 0, "Dex Damage: " + DexDamage + "<br>","")]
[h:ConDamageCheck = if(ConDamage != 0, "Con Damage: " + ConDamage + "<br>","")]
[h:WisDamageCheck = if(WisDamage != 0, "Wis Damage: " + WisDamage + "<br>","")]
[h:IntDamageCheck = if(IntDamage != 0, "Int Damage: " + IntDamage + "<br>","")]
[h:ChaDamageCheck = if(ChaDamage != 0, "Cha Damage: " + ChaDamage + "<br>","")]
[h:ArmorPiercingCheck = if(ArmorPiercing != 0, "DR reduced by: " +ArmorPiercing + "<br>","")]
[h:ACReductionCheck = if(ACReduction != 0, "AC reduced by: " + ACReduction + "<br>","")]
[h, if(TrueDamageWeapon == 1), CODE: {
[h:FinalDamage = (TotalWeaponDamage)]
};{
[h:FinalDamage = (TotalWeaponDamage)]
}]
[h:ResourceOnHitCheck = if(AttackerResourceOnHit != 0, AttackerName + " gains " + AttackerResourceOnHit + " " + AttackerResourceName + ".<br>", "")] 
[h:ResourceOnAttackCheck = if(AttackerResourceOnAttack != 0, AttackerName + " gains " + AttackerResourceOnAttack + " " + AttackerResourceName + ".<br>", "")]


<!--- Attack Roll Calculation--->
[h, if(FinesseWeapon == 0), CODE: {
	[h: AttackRoll = Base1 + AttackerBAB + AttackerStrBonus + WeaponBonusAttackRoll]
	[h:ConfirmationRoll = Base2 + AttackerBAB + AttackerStrBonus + WeaponBonusAttackRoll]
};{
	[h:AttackRoll = Base1 + AttackerBAB + AttackerDexBonus + WeaponBonusAttackRoll]
	[h:ConfirmationRoll = Base2 + AttackerBAB + AttackerDexBonus + WeaponBonusAttackRoll]
}]



<!--- Individual Token Mathematical Calculations --->
[r,foreach(enemy, EnemyList, "<br>"),CODE: {

	[h:switchToken(enemy)]
	<b>[r:token.name]</b><br>
	
	[r, if(ConfirmationRoll >= AC && Base1 >= WeaponCriticalRangeLow || CriticalTrue == 1), CODE: {
	Confirmed Critical ([r:Base1], [r:ConfirmationRoll]).<br>
	[h:HP_OLD = HP]
	[h:FinalDamage2 = round(max(1, ((FinalDamage*WeaponCriticalMultiplier) + CriticalSpecialDamage + SneakAttackDamage)*(1 + (DTakenPercent+getProperty("DMeleePercent", Attacker) + getProperty("DAllPercent", Attacker))/100) + (HP_OLD*(GravityPercentDamage/100))) - DamageReduction))]
	Damage: [r:FinalDamage2] // Healing: [r:round(OnHitHealing + (AttackerMaxHP*(OnHitHealingPercent/100)))]<br>
	[r:ResourceDrainCheck]
	[r:ResourceAbsorbCheck]
	[h:Resource = max(MinResource, min(MaxResource, Resource - ResourceAbsorb - ResourceDrain + ResourceOnDamage))]
	[r:VulnurabilityCheck]
	[r:VulnurabilityCheck2]
	[h:ExtraDamage = VulnurabilityExtraDamage]
	[h:DTakenPercent = VulnurabilityPercent]
	[r:ArmorPiercingCheck]
	[h:DamageReduction = DamageReduction - ArmorPiercing]
	[h:NaturalAC = NaturalAC - ACReduction]
	[r:ACReductionCheck]
	[r:StrDamageCheck]
	[h:Strength = Strength - StrDamage]
	[r:DexDamageCheck]
	[h:Dexterity = Dexterity - DexDamage]
	[r:ConDamageCheck]
	[h:Constitution = Constitution - ConDamage]
	[r:WisDamageCheck]
	[h:Wisdom = Wisdom - WisDamage]
	[r:IntDamageCheck]
	[h:Intelligence = Intelligence - IntDamage]
	[r:ChaDamageCheck]
	[h:Charisma = Charisma - ChaDamage]
	[h:HP = max(MinHP, min(MaxHP, HP - FinalDamage2))]
	[r:ResourceOnHitCheck]
	[r:ResourceOnAttackCheck]
	[h:Hit=1]
	[h:setProperty("HP", min(AttackerMaxHP, round(max(AttackerMinHP, (getProperty("HP", Attacker) + OnHitHealing + (AttackerMaxHP*(OnHitHealingPercent/100)))))), Attacker)]
	};{}]

	[r, if(ConfirmationRoll < AC && Base1 >= WeaponCriticalRangeLow), CODE: {
	Automatic Hit: ([r:Base1], [r:ConfirmationRoll]).<br>
	[h:HP_OLD = HP]
	[h:FinalDamage2 = round(max(1, ((FinalDamage + SneakAttackDamage)*(1 + (DTakenPercent+getProperty("DMeleePercent", Attacker) + getProperty("DAllPercent", Attacker))/100) + (HP_OLD*(GravityPercentDamage/100))) - DamageReduction))]
	Damage: [r:FinalDamage2] // Healing: [r:round(OnHitHealing + (AttackerMaxHP*(OnHitHealingPercent/100)))]<br>
	[r:ResourceDrainCheck]
	[r:ResourceAbsorbCheck]
	[h:Resource = max(MinResource, min(MaxResource, Resource - ResourceAbsorb - ResourceDrain + ResourceOnDamage))]
	[r:VulnurabilityCheck]
	[r:VulnurabilityCheck2]
	[h:ExtraDamage = VulnurabilityExtraDamage]
	[h:DTakenPercent = VulnurabilityPercent]
	[h:DamageReduction = DamageReduction - ArmorPiercing]
	[h:NaturalAC = NaturalAC - ACReduction]
	[r:ArmorPiercingCheck]
	[r:ACReductionCheck]
	[r:StrDamageCheck]
	[h:Strength = Strength - StrDamage]
	[r:DexDamageCheck]
	[h:Dexterity = Dexterity - DexDamage]
	[r:ConDamageCheck]
	[h:Constitution = Constitution - ConDamage]
	[r:WisDamageCheck]
	[h:Wisdom = Wisdom - WisDamage]
	[r:IntDamageCheck]
	[h:Intelligence = Intelligence - IntDamage]
	[r:ChaDamageCheck]
	[h:Charisma = Charisma - ChaDamage]
	[h:HP = max(MinHP, min(MaxHP, HP - FinalDamage2))]
	[r:ResourceOnHitCheck]
	[r:ResourceOnAttackCheck]
	[h:setProperty("HP", min(AttackerMaxHP, round(max(AttackerMinHP, (getProperty("HP", Attacker) + OnHitHealing + (AttackerMaxHP*(OnHitHealingPercent/100)))))), Attacker)]
	[h:Hit=1]
	};{}]

	[r, if(AttackRoll >= AC && Base1 < WeaponCriticalRangeLow), CODE: {
	Hit: ([r:AttackRoll]).<br>
	[h:HP_OLD = HP]
	[h:FinalDamage2 = round(max(1, (FinalDamage + SneakAttackDamage)*(1 + (DTakenPercent+getProperty("DMeleePercent", Attacker) + getProperty("DAllPercent", Attacker))/100) + (HP_OLD*(GravityPercentDamage/100)) - DamageReduction))]
	Damage: [r:FinalDamage2] // Healing: [r:round(OnHitHealing + (AttackerMaxHP*(OnHitHealingPercent/100)))]<br>
	[r:ResourceDrainCheck]
	[r:ResourceAbsorbCheck]
	[h:Resource = max(MinResource, min(MaxResource, Resource - ResourceAbsorb - ResourceDrain + ResourceOnDamage))]
	[r:VulnurabilityCheck]
	[r:VulnurabilityCheck2]
	[h:ExtraDamage = VulnurabilityExtraDamage]
	[h:DTakenPercent = VulnurabilityPercent]
	[h:DamageReduction = DamageReduction - ArmorPiercing]
	[h:NaturalAC = NaturalAC - ACReduction]
	[r:ArmorPiercingCheck]
	[r:ACReductionCheck]
	[r:StrDamageCheck]
	[h:Strength = Strength - StrDamage]
	[r:DexDamageCheck]
	[h:Dexterity = Dexterity - DexDamage]
	[r:ConDamageCheck]
	[h:Constitution = Constitution - ConDamage]
	[r:WisDamageCheck]
	[h:Wisdom = Wisdom - WisDamage]
	[r:IntDamageCheck]
	[h:Intelligence = Intelligence - IntDamage]
	[r:ChaDamageCheck]
	[h:Charisma = Charisma - ChaDamage]
	[h:HP = max(MinHP, min(MaxHP, HP - FinalDamage2))]
	[r:ResourceOnHitCheck]
	[r:ResourceOnAttackCheck]
	[h:setProperty("HP", min(AttackerMaxHP, round(max(AttackerMinHP, (getProperty("HP", Attacker) + OnHitHealing + (AttackerMaxHP*(OnHitHealingPercent/100)))))), Attacker)]
	[h:Hit=1]
	};{}]

	[r, if(AttackRoll < AC), CODE: {
	Miss! ([r:AttackRoll]).<br>
	[r:ResourceOnAttackCheck]
	[h:Hit=0]
	};{}]
	
	<!--- Resource Generation Check --->
	[h, if(Hit ==1 && SpecialAttackDamage == 0), CODE: {
	[h:setProperty("Resource", Max(AttackerMinResource, Min(AttackerMaxResource, AttackerResource + AttackerResourceOnAttack + AttackerResourceOnHit + ResourceAbsorb)), Attacker)]
	}]
	[h, if(Hit == 0 && SpecialAttackDamage == 0), CODE: {
	[h:setProperty("Resource", Max(AttackerMinResource, Min(AttackerMaxResource, AttackerResource + AttackerResourceOnAttack)), Attacker)]
	}]

}]
Last edited by aliasmask on Thu Jan 19, 2017 4:06 pm, edited 1 time in total.
Reason: added code tag

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

Re: Looking for input on macro

Post by wolph42 »

I had a quick look and its quite some code, but from what I saw I can give you some general advice that should help you get your code more structured:

core structuring of code (roughly) goes in 4 parts (or less if one is not required):

initialization
here you retrieve passed on parameters (arg(0),arg(1), etc), retrieve variables from tokens (getTokenProperty()) and do pre calculations required for input

input
here you ask the user for input, no more, no less

calculation/processing
here you do ALL processing, so the stuff you got from the initialization, combined with the processing, here you also (if required) create the output text:

Code: Select all

[outputText = ""]
stuf 
[outputText = outputText + "Confirmed Critical" + Base1 + ", " + ConfirmationRoll + ").<br>"]
more stuf
output
Here you actually send stuff to the chat either with [r:outputText] or (my preference) [h:broadcast(outputText)]
so yes this is often one single line, sometimes with a couple of if's in there to get the syntax right (like he/she, or multiples).

This form of code structuring helps you a lot later on, and also if you post long pieces like hereabove 'we' can at least have a look per section to see if anything can be optimized.

one tiny optimization I noticed: next to [if:] there's also the Wiki: if(). This can help cleaning up this:

Code: Select all

<!--- Attack Roll Calculation--->
[h, if(FinesseWeapon == 0), CODE: {
   [h:AttackRoll = Base1 + AttackerBAB + AttackerStrBonus + WeaponBonusAttackRoll]
   [h:ConfirmationRoll = Base2 + AttackerBAB + AttackerStrBonus + WeaponBonusAttackRoll]
};{
   [h:AttackRoll = Base1 + AttackerBAB + AttackerDexBonus + WeaponBonusAttackRoll]
   [h:ConfirmationRoll = Base2 + AttackerBAB + AttackerDexBonus + WeaponBonusAttackRoll]
}] 
into this

Code: Select all

<!--- Attack Roll Calculation--->
[h:AttackRoll = Base1 + AttackerBAB + if(FinesseWeapon == 0, AttackerStrBonus,AttackerDexBonus) + WeaponBonusAttackRoll]
[h:ConfirmationRoll = Base2 + AttackerBAB + if(FinesseWeapon == 0, AttackerStrBonus, AttackerDexBonus) + WeaponBonusAttackRoll] 

Guardian
Kobold
Posts: 8
Joined: Wed Dec 14, 2016 1:30 pm

Re: Looking for input on macro

Post by Guardian »

This was awesome. Thanks for the rundown. I especially enjoyed the last portion with the if() statements. I didn't think to use the code that way. That's so much easier.

One of the problems I am currently having is that Maptool will not allow me to drag the macro to any token, and when I try to copy/paste the code, I get an error message.

Another thing, is that I want to be able to understand macro argument and how to pass information back and forth between macros. This would help immensely when i need to call upon certain statuses or special damage cases. I don't really understand the advanced stuff all that much even though i've read every tutorial a ton of times.

One other problem is that macros like these (I wrote a far less complicated version of this awhile back), have to be recreated whenever a character gets a new equipment or equipment changes. Is there a better solution to this?

Thank you for the help btw. The system I'm using is fairly complicated. It involves individual character resources (Think like diablo 3), and an AP system, which is a measurement of how much a character can do in one round. Not sure how to make this system less complex than it is, because it involves a ton of different token property manipulations.

I need to get on the right track of thinking so that I can make better macros and improve the smoothness of my campaigns.
If anyone wants to help develop this or is open to giving me any advice on these subjects please let me know.
Thanks again.

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

Re: Looking for input on macro

Post by aliasmask »

Guardian wrote:One of the problems I am currently having is that Maptool will not allow me to drag the macro to any token, and when I try to copy/paste the code, I get an error message.
If you're the gm, this shouldn't be a problem. Also, if there is a macro that can be run on many tokens it's probably best to put the macro on a lib token and the call to the macro in the Campaign Macros.

Guardian
Kobold
Posts: 8
Joined: Wed Dec 14, 2016 1:30 pm

Re: Looking for input on macro

Post by Guardian »

aliasmask wrote:
Guardian wrote:One of the problems I am currently having is that Maptool will not allow me to drag the macro to any token, and when I try to copy/paste the code, I get an error message.
If you're the gm, this shouldn't be a problem. Also, if there is a macro that can be run on many tokens it's probably best to put the macro on a lib token and the call to the macro in the Campaign Macros.
Never understood how that could ever be helpful though when people have multiple pieces of equipment. Do you have an example that could help clarify what I am missing?

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

Re: Looking for input on macro

Post by aliasmask »

You need to define the equipment in to it's constituents parts (stat boost, damage, ...) and then all it is is changing the numbers with a new item and saving it in to a variable. Right now, it looks like you just hard code the changes in the macro.

A good example would be the 3.5/pathfinder framework by Lindsay. You edit your equipment and then equip it. I would look at some of his code.

Guardian
Kobold
Posts: 8
Joined: Wed Dec 14, 2016 1:30 pm

Re: Looking for input on macro

Post by Guardian »

A useful idea.
Does the framework support automated combat? If so, I can take inspiration from that as well.

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

Re: Looking for input on macro

Post by wolph42 »

if you want to see automated combat through the roof you should take a look at my w40k framework :D (note that if I need to dig into that code I start crying...) I've automated the combat as far as maptools allows me to and the warhammer battle is insanely complex with user interactions and A LOT of exceptions, notwithstanding skills, talents and traits that influence the outcome....but you can have a look. I think though that AMs suggestion is better, lindsays framework is a little bit less complex

Guardian
Kobold
Posts: 8
Joined: Wed Dec 14, 2016 1:30 pm

Re: Looking for input on macro

Post by Guardian »

wolph42 wrote:if you want to see automated combat through the roof you should take a look at my w40k framework :D (note that if I need to dig into that code I start crying...) I've automated the combat as far as maptools allows me to and the warhammer battle is insanely complex with user interactions and A LOT of exceptions, notwithstanding skills, talents and traits that influence the outcome....but you can have a look. I think though that AMs suggestion is better, lindsays framework is a little bit less complex
Is there any way to modify the w40k framework to support a system like mine? E.G. resources, ap, custom made feats, etc?


Guardian
Kobold
Posts: 8
Joined: Wed Dec 14, 2016 1:30 pm

Re: Looking for input on macro

Post by Guardian »

I mean, I already have some things in place. The macro that I presented does its intended job.

I need someone to teach me about the more advanced pieces of macro programming that I am failing to understand myself.

Ideally, I would like to build this framework myself or with the help of others.

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

Re: Looking for input on macro

Post by wolph42 »

well, thats what this forum is for... post pieces of code, ask questions! What you coded doesn't look bad, just a bit unorganised and not very optimal, but that's what my framework looked like in the beginning...
The most important part is that you start (which you did) and along the way you will learn new tricks and rewrite parts of your code to be more efficient (which I did many many times).

edit: seeing the below post, concerning documentation: check the first link in my sig. And another thing make sure you have notepad++ with alias' plugin installed, its linked in his sig. Without it, coding is hell!

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

Re: Looking for input on macro

Post by aliasmask »

Framework is just a name for an idea. Generally speaking you have 1 or more lib tokens holding all the macros, put macros that call the lib token macros in the Campaign Window for global access. You'll have special token properties, states and visions that are relevant to your game.

I have a starter token here: http://forums.rptools.net/viewtopic.php ... 58#p265358

The notes in the macros will explain what they do. Also, in my signature is reference to RPEdit and notepad++. RPEdit is a token drop-in to help you edit your lib token macros. The notepad++ stuff you can download and then copy the files I created to aid in the MapTool macroscript with highlighting and tooltips. Also, the ctrl-shift-c to copy a macro block is useful.

The starter token includes 3 debugging macros and onCampaignLoad which will make all your macros in to user defined functions (UDFs) with a prefix. All these UDFs have the output suppressed so I also included a generic output macro.

I also have a generic best practices for programming in MapTool here: http://forums.rptools.net/viewtopic.php ... 81#p233681

I'm sure wolph42 has some other documentation as well to help out.

Guardian
Kobold
Posts: 8
Joined: Wed Dec 14, 2016 1:30 pm

Re: Looking for input on macro

Post by Guardian »

Took some advice on your guy's statements. Can't figure this one out though. Says Error in body of roll.

Code: Select all

<!--- Initialization --->
[h: EnemyList = getSelectedNames()]
[h: SaveCheck = json.get(macro.args, "SaveCheck")]
[h: FortCheck = json.get(macro.args, "FortCheck")]
[h: RefCheck = json.get(macro.args, "RefCheck")]
[h: WillCheck = json.get(macro.args, "WillCheck")]
[h: HalfCheck = json.get(macro.args, "HalfCheck")]
[h: NegateCheck = json.get(macro.args, "NegateCheck")]
[h: Unsavable = json.get(macro.args, "Unsavable")]
[h: Vulnurabilty = json.get(macro.args, "Vulnurabilty")]
[h: RayAbility = json.get(macro.args, "RayAbility")]
[h: SlowingAbility = json.get(macro.args, "SlowingAbility")]
[h: HealingAbility = json.get(macro.args, "HealingAbility")]
[h: StatDamage = json.get(macro.args, "StatDamage")]
[h: NoPower = json.get(macro.args, "NoPower")]
[h: NoDamage = json.get(macro.args, "NoDamage")]
[h: Damage = json.get(macro.args, "Damage")]
[h: PercentDamage = json.get(macro.args, "PercentDamage")]
[h: TrueDamage = json.get(macro.args, "TrueDamage")]
[h: AttackBonus = json.get(macro.args, "AttackBonus")]
[h: Healing = json.get(macro.args, "Healing")]
[h: PercentHealing = json.get(macro.args, "PercentHealing")]
[h: ResourceCost = json.get(macro.args, "ResourceCost")]
[h: ResourceGain = json.get(macro.args, "ResourceGain")]
[h: VulnurabilityAmount = json.get(macro.args, "VulnurabilityAmount")]
[h: SlowingAmount = json.get(macro.args, "SlowingAmount")]
[h: StrDamage = json.get(macro.args, "StrDamage")]
[h: DexDamage = json.get(macro.args, "DexDamage")]
[h: ConDamage = json.get(macro.args, "ConDamage")]
[h: WisDamage = json.get(macro.args, "WisDamage")]
[h: IntDamage = json.get(macro.args, "IntDamage")]
[h: ChaDamage = json.get(macro.args, "ChaDamage")]

[r, if(RayAbility == 1), CODE: {
[MACRO("TouchAttackCalc@Lib:Combat"):SendData]
};{}]

[r,foreach(enemy, EnemyList, "<br>"),CODE: {

	[h:switchToken(enemy)]
	<b>[r:token.name]</b><br>
	[h:enemy = token.name]

	[h: SendData = json.set("{}", "Damage", Damage, "SaveCheck", SaveCheck, "Healing", Healing, "PercentHealing", PercentHealing, "ResourceCost", ResourceCost, "ResourceGain", ResourceGain, "APCost", APCost, "FortCheck", FortCheck, "RefCheck", RefCheck, "WillCheck", WillCheck, "HalfCheck", HalfCheck, "NegateCheck", NegateCheck, "Unsavable", Unsavable, "Vulnurabilty", Vulnurability, "VulnurabilityAmount", VulnurabilityAmount, "RayAbility", RayAbility, "AttackBonus", AttackBonus, "SlowingAbility", SlowingAbility, "SlowingAmount", SlowingAmount, "HealingAbility", HealingAbility, "StatDamage", StatDamage, "StrDamage", StrDamage, "DexDamage", DexDamage, "ConDamage", ConDamage, "WisDamage", WisDamage, "IntDamage", IntDamage, "ChaDamage", ChaDamage, "AttackType", AttackType, "NoPower", NoPower, "NoDamage", NoDamage, "CritThreat", CritThreat, "CriticalMultiplier", CriticalMultiplier, "PercentDamage", PercentDamage, "BasicDamage", BasicDamage, "TrueDamage", TrueDamage, "enemy", enemy)]


	[r, if(Unsavable == 1 && NoDamage == 0 && RayAbility == 0), CODE: {
	[MACRO("AttackDamageCalc@Lib:Combat"):SendData]
	};{}]

	[r, if(Unsavable == 1 && StatDamage == 0 && RayAbility == 0), CODE: {
	[MACRO("StatDamageCalc@Lib:Combat"):SendData]
	};{}]

	[r, if(SlowingAbility == 1 && Unsavable == 1), CODE: {
	[MACRO("SlowCalc@Lib:Combat"):SendData]
	};{}]
	
	[r, if(Vulnurabilty == 1 && Unsavable == 1), CODE: {
	[MACRO("VulnCalc@Lib:Combat"):SendData]
	};{}]
	
	[r, if(HealingAbility == 1), CODE: {
	[MACRO("HealCalc@Lib:Combat"):SendData]
	};{}]

	[r, if(HalfCheck == 1 && RefCheck == 1), CODE: {
	[MACRO("ReflexHalfCheck@Lib:Combat"):SendData]
	};{}]

	[r, if(HalfCheck == 1 && FortCheck == 1), CODE: {
	[MACRO("FortitudeHalfCheck@Lib:Combat"):SendData]
	};{}]

	[r, if(HalfCheck == 1 && WillCheck == 1), CODE: {
	[MACRO("WillHalfCheck@Lib:Combat"):SendData]
	};{}]

	[r, if(NegateCheck == 1 && RefCheck == 1), CODE: {
	[MACRO("ReflexNegateCheck@Lib:Combat"):SendData]
	};{}]

	[r, if(NegateCheck == 1 && FortCheck == 1), CODE: {
	[MACRO("FortitudeNegateCheck@Lib:Combat"):SendData]
	};{}]

	[r, if(NegateCheck == 1 && WillCheck == 1), CODE: {
	[MACRO("WillNegateCheck@Lib:Combat"):SendData]
	};{}]

};{}]
Any advice is appreciated

Edit: Found the spelling error in vulnurability. Things still dont work.

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

Re: Looking for input on macro

Post by aliasmask »

I notice in your first macro call you refer to SendData but it's not defined by that point. Also, if all your data you're defining is in macro.args you may be able to use this shortcut.

Code: Select all

[H: props = json.toStrProp(macro.args)]
[H: varsFromStrProp(props)]
Btw, this is only good if you don't have any ; in your data.

I also recommend using

Code: Select all

[h: EnemyList = getSelectedNames("json")]
I counted the variables in sendData and I count 36, but there are fewer variables defined above, so that could be something.

Post Reply

Return to “Requests for HELLLLP!”