Help with weapon attack 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

User avatar
Full Bleed
Demigod
Posts: 4736
Joined: Sun Feb 25, 2007 11:53 am
Location: FL

Re: Help with weapon attack macro

Post by Full Bleed »

ralstad wrote:
Thu Jul 12, 2018 12:56 am
ok making a small addition to the macro and getting a little headache from it.
Here it is.

Code: Select all

[h: if(att1 == ""),CODE:
	{
	[h: assert(att1 == "", "No bonus entered!", 0)]
	[h: abort(0)]
	}
]
It is popping this error.

Error in body of roll.       
Statement options (if any): h       
Statement Body : if(att1 == ""),CODE: { [h: assert(att1 = "", "No bonus entered!", 0)] [h: abort(0)] }; { };

ralstad
You have two things wrong.

1) When using a Category:Roll_Option you need to put a comma after the H.
2) When using a CODE option you need to provide a section for a false option (even if it's blank.)

Code: Select all

[h, if(att1 == ""), CODE:
	{
		[h: assert(att1 == "", "No bonus entered!", 0)]
		[h: abort(0)]
	};
	{
	}
]
And, as a side note, Abort and Assert do the same thing. Assert just requires a condition and provides a message when executed.

That assert statement will never execute because it shares the same condition as the if statement (att1 == "") and both are run when the condition is True.
Maptool is the Millennium Falcon of VTT's -- "She may not look like much, but she's got it where it counts."

ralstad
Cave Troll
Posts: 54
Joined: Sat Nov 19, 2016 12:52 am

Re: Help with weapon attack macro

Post by ralstad »

Thanks Full Bleed,

I had copied and made adjustments to other if statements but this is the first that I tried writing completely and missed the ",".

I do have another question.

In the code I am checking to see if the variable of att1 is empty(not having a value) and if it is empty to abort the code. I made sure to remove the variable I had in there to test the rest of the code and when I run the code to see if it will abort out now it still runs the code as usual.

Code: Select all

[h: att1 = getProperty("Wpn 1 Att 1")]
[h, if(att1 == ""), CODE:
	{
		[h: assert(att1 == "", "No bonus entered!", 0)]
	};
	{
	}
]
Is there something wrong in my coding that is not seeing the empty variable?

ralstad

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

Re: Help with weapon attack macro

Post by aliasmask »

You'll run in to the problem of comparing mismatching types, ie an empty string with a json(?). I recommend using json.isEmpty. It works for everything and doesn't crash. You also don't need to make 2 checks for the same thing.

Code: Select all

[H: att1 = getProperty("Wpn 1 Att 1")]
[H: assert(! json.isEmpty(att1),"No bonus entered!", 0)]

ralstad
Cave Troll
Posts: 54
Joined: Sat Nov 19, 2016 12:52 am

Re: Help with weapon attack macro

Post by ralstad »

Thanks aliasmask,

Could you do me a favor and give me a quick explanation of what the difference is between what I had and using ! json.isEmpty is?

Oh and why will I have problems if I have spaces in my token properties names? I am using spaces and no problems.

ralstad

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

Re: Help with weapon attack macro

Post by aliasmask »

ralstad wrote:
Thu Jul 12, 2018 5:11 pm
Thanks aliasmask,

Could you do me a favor and give me a quick explanation of what the difference is between what I had and using ! json.isEmpty is?

ralstad
When doing comparisons between two "things" those things can potentially be of different types. A variable could have been null, a string, a number or a json. Although a json is represented as a string, it's stored internally as it's own thing. So, when you compare att1 == "" and att1 is a json the parser doesn't like that. Same if att1 was a number. If att1 can only be a string, then you're okay. Using json.isEmpty allows att1 to be null, empty string, empty array [] or empty object {} to give you a valid result.

doing att1 == "" and then followed by assert(att1 == "",...) is being redundant. You already know at that point the condition is true. You could have also done assert(0,...) to get the same result.

Also, the [if:] allows for a single statement without a code block.
[H, if(att1 == ""): assert(0,"...",0)] would also be another way to do things, assuming the att1 = "" passed.

Personally, I almost always put the code block after an if just in case I need to add more stuff to it, but when I get things working the way I like I go through the code and clean up. Maybe add some comments if something could be unclear or to explain what it does. I usually do that around formulas. The code should speak for itself so don't over comment something unless you're trying to get a non-coder to understand what's going on.

ralstad
Cave Troll
Posts: 54
Joined: Sat Nov 19, 2016 12:52 am

Re: Help with weapon attack macro

Post by ralstad »

Thank you Aliasmask,

So the ! json.isEmpty in essence gives the variable greater flexibility for the test to pass in essence.

I think I understand. I have done a bit of VB coding, but this is noticeably different and is taking me a little to understand the syntax.

Thank you for explaining it.

Now the coding is complete. As far as I can think of.

Code: Select all

[h: att1 = getProperty("Wpn 1 Att 1")]
[H: assert(! json.isEmpty(att1),"No bonus entered!", 0)]
[h: wpndmg1 = getProperty("Wpn 1 Dmg")]
[h: bns1 = getProperty("Wpn 1 Dmg Bns")]
[h: roll = 1d20]
[h: dmg1 = eval(wpndmg1)]
[h: att2 = getProperty("Wpn 1 Att 2")]
[h: dmg2 = eval(wpndmg1)]
[h: att3 = getProperty("Wpn 1 Att 3")]
[h: dmg3 = eval(wpndmg1)]
[h: att4 = getProperty("Wpn 1 Att 4")]
[h: dmg4 = eval(wpndmg1)]
[h: fum=0]
[h: err = getProperty("Wpn 1 Error")]
[h: thrt = getProperty("Wpn 1 Threat")]
[r, if(roll >= thrt),CODE:
	{
		<b>Attack:</b><b>CRIT!!!!!</b> [t: roll+att1]<br>
		<b>Damage:</b> [t: dmg1+dmg1+bns1]<br>
	};
	{
	};
]
[r, if(roll <= err),CODE:
	{
		<b>FUMBLE!!!!!</b><br>
		[h: fum=1]
	};
	{
	};
]
[r, if(roll > err && roll < thrt),CODE:
	{
		<b>Attack:</b> [t: roll+att1]<br>
		<b>Damage:</b> [t: dmg1+bns1]<br>
	};
	{
	};
]
[h: roll = 1d20]
[h: check=0]
[r, if(roll >= thrt),CODE:
	{
		[h: check=2]
	};
	{
	};
]
[r, if(roll <= err),CODE:
	{
		[h: check=1]
	};
	{
	};
]
[r, if(att2 > 0 && fum == 0),CODE:{
	[switch(roll), code:
		case 2: {
			<b>Attack:</b><b>CRIT!!!!!</b> [t: roll+att2]<br>
			<b>Damage:</b> [t: dmg2+dmg2+bns1]<br>
		};
		case 1: {
			<b>FUMBLE!!!!!</b><br>
			[h: fum=1]
		};
		default: {
			<b>Attack:</b> [t: roll+att2]<br>
			<b>Damage:</b> [t: dmg2+bns1]<br>
		}]
	};
	{
	};
]
[h: roll = 1d20]
[h: check=0]
[r, if(roll >= thrt),CODE:
	{
		[h: check=2]
	};
	{
	};
]
[r, if(roll <= err),CODE:
	{
		[h: check=1]
	};
	{
	};
]
[r, if(att3 > 0 && fum == 0),CODE:{
	[switch(check), code:
		case 2: {
			<b>Attack:</b><b>CRIT!!!!!</b> [t: roll+att3]<br>
			<b>Damage:</b> [t: dmg3+dmg3+bns1]<br>
  		};
		case 1: {
			<b>FUMBLE!!!!!</b><br>
			[h: fum=1]
 		 };
		default: {
			<b>Attack:</b> [t: roll+att3]<br>
			<b>Damage:</b> [t: dmg3+bns1]<br>
		}]
	};
	{
	};
]
[h: roll = 1d20]
[h: check=0]
[r, if(roll >= thrt),CODE:
	{
		[h: check=2]
	};
	{
	};
]
[r, if(roll <= err),CODE:
	{
		[h: check=1]
	};
	{
	};
]
[r, if(att4 > 0 && fum == 0),CODE:{
	[switch(check), code:
		case 2: {
			<b>Attack:</b><b>CRIT!!!!!</b> [t: roll+att4]<br>
			<b>Damage:</b> [t: dmg4+dmg4+bns1]<br>
  		};
		case 1: {
			<b>FUMBLE!!!!!</b><br>
  		};
		default: {
			<b>Attack:</b> [t: roll+att4]<br>
			<b>Damage:</b> [t: dmg4+bns1]<br>
		}]
	};
	{
	};
]
Any suggestions to make the code better? It works well but always looking to get better.

ralstad

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

Re: Help with weapon attack macro

Post by aliasmask »

Are you using notepad++? I recommend replacing tabs with spaces. I personally use 3.

I'll take a closer look, but off-hand I see you're doing the same thing over and over which tells me there should be a function and a loop in there. I also recommend using full names for variables. Abbreviating saves you very little time in coding since only 1/10th your time is done typing and 9/10ths in reading the code.

I also prefer to build my outputs to a variable and then output at the end, but since you're using the MT tooltips and not making your own that makes it difficult to do.

I have some coding tips and an example of an attack macro I rewrote for someone that you may glean some insight from: viewtopic.php?f=20&t=22886&p=233681&hil ... ck#p233681

ralstad
Cave Troll
Posts: 54
Joined: Sat Nov 19, 2016 12:52 am

Re: Help with weapon attack macro

Post by ralstad »

aliasmask wrote:
Thu Jul 12, 2018 5:53 pm
Are you using notepad++? I recommend replacing tabs with spaces. I personally use 3.
No just using Maptools macro editor.
aliasmask wrote:
Thu Jul 12, 2018 5:53 pm
I'll take a closer look, but off-hand I see you're doing the same thing over and over which tells me there should be a function and a loop in there. I also recommend using full names for variables. Abbreviating saves you very little time in coding since only 1/10th your time is done typing and 9/10ths in reading the code.
As far as repeating similar code I understand that there might be a better way but I'm not trying to make a full framework just trying to create some macros to speed up play also just starting to learn this code writing and trying to keep it simple at the moment. I might get more complex later but not now.

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

Re: Help with weapon attack macro

Post by aliasmask »

I understand the desire to do the quick and dirty way just to have a working model in place, but that's not what you're asking me to do with your code, "Any suggestions to make the code better? It works well but always looking to get better." I've been coding since 1985 with many languages and there are some core similarities and practices the teachers have told me to adhere to. Repeating code is one of those things you try to avoid to be better. For one, when you need to make a change you want to change it in one place. Using copied code requires to make those changes in several locations.

There are many ways to do one thing. Some of the ways are based on style and preference and some of the ways are just bad coding practices. I'm just trying to show you a better way.

Taking a look at your code I see you have these variables:

Code: Select all

att1,att2,att3,att4 - attack modifier for each weapon attack 1 to 4 (integer)
wpndmg1 - dice expression for weapon damage (string)
bns1 - bonus damage for weapon (integer)
dmg1,dmg2,dmg3,dmg4 - evaluated damage for each attack using dice expression for weapon
fum - fumble flag
err - fumble threshold for weapon
thrt - critical threat threshold for weapon
One thing I would suggest to get away from is having single properties for each variable. These are all related and should be grouped together. Old school we call them records, but a json is the way MT does it.

Code: Select all

[H: weaponType = json.set("{}",
   "baseAttackMod","[]",
   "damageDice","",
   "damageMod",0,
   "threatRange",20,
   "fumbleRange",1
)]
Your base attack mods can range from 1 to 4 (maybe more?) but it doesn't matter if you just set it as an array. The size of the array determines the number of attacks. The rest are just default values to represent the type of data for an unassigned weapon.

Right now, you're probably setting your weapon by opening the token properties and plugging in values. This still can be done but it's better to have a form to fill in to set the weapon values.

to be continued...

ralstad
Cave Troll
Posts: 54
Joined: Sat Nov 19, 2016 12:52 am

Re: Help with weapon attack macro

Post by ralstad »

aliasmask wrote:
Thu Jul 12, 2018 8:20 pm
I understand the desire to do the quick and dirty way just to have a working model in place, but that's not what you're asking me to do with your code, "Any suggestions to make the code better? It works well but always looking to get better." I've been coding since 1985 with many languages and there are some core similarities and practices the teachers have told me to adhere to. Repeating code is one of those things you try to avoid to be better. For one, when you need to make a change you want to change it in one place. Using copied code requires to make those changes in several locations.

There are many ways to do one thing. Some of the ways are based on style and preference and some of the ways are just bad coding practices. I'm just trying to show you a better way.
I guess you miss interpreted my last comment or it came out wrong. I am interested in how to make the coding better and welcome any input you have. I just wanted to point out that at the moment I am new to MT coding and may not understand what you are telling me. I am self taught in VB coding but it is basic knowledge by what would be your evaluation probably. Getting into complex things may be a little advanced for me right now.
aliasmask wrote:
Thu Jul 12, 2018 8:20 pm
Taking a look at your code I see you have these variables:

Code: Select all

att1,att2,att3,att4 - attack modifier for each weapon attack 1 to 4 (integer)
wpndmg1 - dice expression for weapon damage (string)
bns1 - bonus damage for weapon (integer)
dmg1,dmg2,dmg3,dmg4 - evaluated damage for each attack using dice expression for weapon
fum - fumble flag
err - fumble threshold for weapon
thrt - critical threat threshold for weapon
One thing I would suggest to get away from is having single properties for each variable. These are all related and should be grouped together. Old school we call them records, but a json is the way MT does it.

Code: Select all

[H: weaponType = json.set("{}",
   "baseAttackMod","[]",
   "damageDice","",
   "damageMod",0,
   "threatRange",20,
   "fumbleRange",1
)]
Your base attack mods can range from 1 to 4 (maybe more?) but it doesn't matter if you just set it as an array. The size of the array determines the number of attacks.
If you could please explain this, I see that you are creating variables and I know what an array is but not in MT or how to create one.
aliasmask wrote:
Thu Jul 12, 2018 8:20 pm
The rest are just default values to represent the type of data for an unassigned weapon.

Right now, you're probably setting your weapon by opening the token properties and plugging in values. This still can be done but it's better to have a form to fill in to set the weapon values.

to be continued...
Only at the moment as a gm I want to create a macro for the players to enter the info in on and have the macro set the specific property.

Thank you.
ralstad

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

Re: Help with weapon attack macro

Post by aliasmask »

Here's how I would do the setWeapon macro. Ideally, the macro will be saved on a lib token and then called from the campaign window, but you can also just put all the code in the campaign window:

Code: Select all

<!-- setWeapon() -->

{H: mainWeapon = getProperty("mainWeapon")]

[H: defaultWeapon = json.set("{}",
   "baseAttackMod","0",
   "damageDice","1d6",
   "damageMod",0,
   "threatRange",20,
   "fumbleRange",1
)]

[H, if(json.isEmpty(mainWeapon)): mainWeapon = defaultWeapon]

[H: abort(input(
   strformat("baseAttackMod|%{baseAttackMod}|Enter Base Attack List|TEXT"),
   strformat("damageDice|%{damageDice}|Weapon Damage Dice Expression|TEXT"),
   strformat("damageMod|%{damageMod}|Base Weapon Damage Mod|TEXT"),
   strformat("threatRange|%{threatRange}|Critical Threat|TEXT"),
   strformat("fumbleRange|%{fumbleRange}|Fumble Threshold|TEXT")
))]

<!-- Here is where you do your error checking, but I will skip that part -->

[H: mainWeapon = json.set(mainWeapon,
   "baseAttackMod",baseAttackMod,
   "damageDice",damageDice,
   "damageMod",damageMod,
   "threatRange",threatRange,
   "fumbleRange",fumbleRange
)]

[H: setProperty("mainWeapon",mainWeapon)]
Having a function sets up the process of having multiple weapons and gets away from editing MT token properties directly. It's much more convenient this way as well. I also decided to not use a json array for output reasons. Also, a comma separated list is easy to enter.

ralstad
Cave Troll
Posts: 54
Joined: Sat Nov 19, 2016 12:52 am

Re: Help with weapon attack macro

Post by ralstad »

alias,

I kinda get your macro, but not completely.

Here are the token properties I have set.

*@Vitality
*@MaxVitality
*@Wounds
*@MaxWounds
*@Defense
*@Speed
*@Initiative
*@Fortitude
*@Reflex
*@Will
*@Unarmed
*@Melee
*@Ranged
*@Inspiration
*@Education
*@Wpn 1
*@Wpn 1 Dmg
*@Wpn 1 Dmg Bns
*@Wpn 1 Att 1
*@Wpn 1 Att 2
*@Wpn 1 Att 3
*@Wpn 1 Att 4
*@Wpn 1 Error
*@Wpn 1 Threat
*@Wpn 1 Thrt Mult
*@Wpn 2
*@Wpn 2 Dmg
*@Wpn 2 Dmg Bns
*@Wpn 2 Att 1
*@Wpn 2 Att 2
*@Wpn 2 Att 3
*@Wpn 2 Att 4
*@Wpn 2 Error
*@Wpn 2 Threat
*@Wpn 2 Thrt Mult
*@Wpn 3
*@Wpn 3 Dmg
*@Wpn 3 Dmg Bns
*@Wpn 3 Att 1
*@Wpn 3 Att 2
*@Wpn 3 Att 3
*@Wpn 3 Att 4
*@Wpn 3 Error
*@Wpn 3 Threat
*@Wpn 3 Thrt Mult
*@Wpn 4
*@Wpn 4 Dmg
*@Wpn 4 Dmg Bns
*@Wpn 4 Att 1
*@Wpn 4 Att 2
*@Wpn 4 Att 3
*@Wpn 4 Att 4
*@Wpn 4 Error
*@Wpn 4 Threat
*@Wpn 4 Thrt Mult

Since I am just learning how would you set up token properties to work the best you could. Also could you place a few more notes in your code so I can understand what it is doing?

Also, what is json I have seen it alot but don't understand what it is?

A little background also my group uses a customized excel sheet for Stargate SG1 but basically 3.5 stuff.

ralstad

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

Re: Help with weapon attack macro

Post by aliasmask »

For your generic questions you should bookmark this page: viewtopic.php?f=3&t=25077&p=252549#p252549

I also bookmark this page for MT functions which I use all the time: http://lmwcs.com/rptools/wiki/Category:Macro_Function

The MT wiki on jsons is here which is linked in the first bookmark: http://www.lmwcs.com/rptools/wiki/Intro ... _Datatypes

edit: One thing I would note about the JSON wiki page is they reference the json type and structure in a pseudo-code fashion, so it's not actual code. You should build json objects with Wiki: json.set() and json arrays with Wiki: json.append() functions.

There are 2 kinds of token properties. There are the ones that are a part of the token type (what you listed) and there are hidden properties which are created with Wiki: setProperty(). All the token type properties are global which means if you make reference to them from anywhere in relation to the token it will contain a value. So, for example, if you have "Will" as a property you don't need to have code like this:

Code: Select all

[H: Will = getProperty("Will")]
Will is already defined for a macro on that token. You have to be careful of global variables because you can accidentally change them. Often I'll see beginners change a variable with a prefix or suffix so it becomes a different variable, ie "tWill" when they don't want to deal with the variable directly, say when recalculating the value. This is where good naming practices come in. A better name would be save.Will. If you still want it as a token type you may show it like this:

Code: Select all

*@save.Will(Will):0
It's also good practice to have default values. In this case, save.Will is the variable name and "Will" is the token stat sheet name. I like to keep my token type variables to a minimum. Mostly I just put variables in there that will be displayed on the stat sheet either directly or indirectly like in a formula or formatted output. For example:
Spoiler

Code: Select all

*@sheet.physical (Body):[R: strformat("Str:%s(%+d) Dex:%s(%+d) Con:%s(%+d)",Strength+StrMod,StrB,Dexterity+DexMod,DexB,Constitution+ConMod,ConB)]
*@sheet.mental (Mind):[R: strformat("Int:%s(%+d) Wis:%s(%+d) Chr:%s(%+d)",Intelligence+IntMod,IntB,Wisdom+WisMod,WisB,Charisma+ChaMod,ChaB)]
*@AllSaves (Saves):[R: strformat("Fort:%+d Ref:%+d Will:%+d",Fort+ConB+FortBonus,Reflex+DexB+ReflexBonus,Will+WisB+WillBonus)]
Strength (Str):10
StrMod:0
Dexterity (Dex):10
DexMod:0
Constitution (Con):10
ConMod:0
Intelligence (Int):10
IntMod:0
Wisdom (Wis):10
WisMod:0
Charisma (Cha):10
ChaMod:0
Fort:0
FortBonus:0
Reflex:0
ReflexBonus:0
Will:0
WillBonus:0
StrB:[R: floor((Strength+StrMod-10)/2)]
Str2hB:[R: floor(floor((Strength+StrMod-10)/2)+(max(0,floor((Strength+StrMod-10)/4))))]
StrSecB:[R: floor((Strength+StrMod-10)/4)]
DexB:[R: floor((Dexterity+DexMod-10)/2)]
ConB:[R: floor((Constitution+ConMod-10)/2)]
IntB:[R: floor((Intelligence+IntMod-10)/2)]
WisB:[R: floor((Wisdom+WisMod-10)/2)]
ChaB:[R: floor((Charisma+ChaMod-10)/2)]
The top 3 lines are for the token stat sheet while the other values are used in calculations and output formatting and don't require the *@

This is based on someone else's work, so the naming conventions are a bit different than I would normally use.
Attachments
token stat sheet example.jpg
token stat sheet example.jpg (28.98 KiB) Viewed 4622 times

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

Re: Help with weapon attack macro

Post by aliasmask »

Fyi, I'm making a lib token for you. I have a game in about an hour but any updates I do will be to this token.
Attachments
sg1 logo.png
sg1 logo.png (182.23 KiB) Viewed 4611 times
lib_sg1.rptok
(383.57 KiB) Downloaded 57 times

ralstad
Cave Troll
Posts: 54
Joined: Sat Nov 19, 2016 12:52 am

Re: Help with weapon attack macro

Post by ralstad »

Alias,

That is cool. I looked through the macros and didn't understand hardly any of it. :)
Did you make the token?
I would be willing to help if you are willing to do the coding for it.
I have an excel spread sheet for SG1 my group uses to create characters.
I do have to warn you our SG1 is slightly modified from the standard rule set.

ralstad

Post Reply

Return to “Requests for HELLLLP!”