Growlly's Totally Noob Questions about Macros

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

User avatar
growlly
Cave Troll
Posts: 32
Joined: Fri Jul 10, 2015 11:35 am
Location: United States

Re: Growlly's Totally Noob Questions about Macros

Post by growlly »

Ah, that's cool. I'll have to find out whether that's faster than Excel. Fortunately I don't imagine updating the data often after it's stored.

New question:
I'm setting up my macros to get/drop weapons. To drop a weapon, I open my dialog to pick the token and pick the weapon slot (a group of properties that share a prefix). The weapon properties I need to update are called:
Weap1Name
Weap1Type
etc...

So, I would need the code to look like this to drop the weapon in slot 1.

Code: Select all

[h: Weap1Name = "Slot Empty"]
Now I just need to get Weap1Name when the slot selected is slot 1. The slots are named Weap1, Weap2, etc. so I have the macro concatenate the selected slot with weapon property type to construct the name of the property:

Code: Select all

[r: NameString = slot+"Name"]
Returns: Weap1Name

Great, so now the value of NameString is the property that I need to update based on the slot selected. Except, stuff like this won't work:

Code: Select all

[h: NameString = "Slot Empty"]
Obviously, because it's trying to change the value of NameString rather than the property named by the value of NameString. What's the best way out of this? Is there a way to put a r: inside another function? Like [h: [r: MyProperty] = newvalue] or something similar? I haven't figured it out--I usually try to code around it when it comes up, but I don't think I can this time.

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

Re: Growlly's Totally Noob Questions about Macros

Post by aliasmask »

I would do it an entirely different way, but you can just simply check the string with an if before doing anything with the variable (which wouldn't exist).

Again, jsons are the way to go for database like structures. For example, limiting yourself to defined token properties of Weap1Name, Weapon2Name when you could just have 1 property called, weapons. So, if the variable is empty, then you have no weapons.

Here's an example of me building weapon data in to a json.
||| initWeaponData

Code: Select all

[H: rawData = json.append("",
   "Aklys	Exotic	Light	Melee	5	1d8	20x2	20	2	Blunt	Performance,Trip	UC",
   "Ammentum	Martial	Ranged	Ranged	0	1d6	20x2	50	1	Pierce	Performance	UC",
   "Axe, Boarding	Martial	Light	Melee	6	1d6	20x3	0	3	Pierce,Slash		PoIS",
   "Axe, Hooked	Exotic	OneHand	Melee	20	1d8	20x3	0	7	Slash	Disarm,Performance,Trip	UC",
   "Axe, Knuckle	Exotic	Light	Melee	9	1d6	20x3	0	2	Slash	Monk,Performance	UC",
   "Axe, Orc Double	Exotic	TwoHand	Melee	60	1d8/1d8	20x3/20x3	0	15	Slash/Slash	Double	CRB",
   "Axe, Throwing	Martial	Light	Melee	8	1d6	20x2	10	2	Slash		CRB",
   "Battle Ladder	Exotic	TwoHand	Melee	20	1d6/1d6	20x2/20x2	0	8	Blunt/Blunt	Trip	GoG",
   "Battleaxe	Martial	OneHand	Melee	10	1d8	20x3	0	6	Slash		CRB",
   "Bayonet	Simple	TwoHand	Melee	5	1d6	20x2	0	1	Pierce		APG",
   "Blowgun	Simple	Ranged	Ranged	2	1d2	20x2	20	1	Pierce		CRB",
   "Boarding Gaff	Exotic	TwoHand	Melee	8	1d6/1d6	20x2/20x2	0	8	Slash/Slash	Double,Reach,Trip	PoIS",
   "Boarding Pike	Simple	TwoHand	Melee	8	1d8	20x3	0	9	Pierce	Brace,Reach	PoIS",
   "Bola	Exotic	Ranged	Thrown	5	1d4	20x2	10	2	Blunt	Nonlethal,Trip	CRB",
   "Bola, Brutal	Exotic	Ranged	Thrown	15	1d4	20x2	10	2	Blunt,Pierce	Trip	ISWG",
   "Boomerang	Exotic	Ranged	Thrown	3	1d6	20x2	30	3	Blunt		APG",
   "Bow, Thorn	Exotic	Ranged	Ranged	50	1d6	20x3	40	2	Pierce		AA",
   "Brass Knife	Simple	Light	Melee	2	1d4	19x2	10	1	Pierce,Slash	Fragile	PoIS",
   "Brass Knuckles	Simple	Light	Melee	1	1d3	20x2	0	1	Blunt	Monk	AA,APG",
   "Cat-O'-Nine-Tails	Martial	Light	Melee	1	1d4	20x2	0	1	Slash	Disarm,Nonlethal	PoIS",
   "Cestus	Simple	Light	Melee	5	1d4	19x2	0	1	Blunt,Pierce	Monk	APG",
   "Chain, Spiked	Exotic	TwoHand	Melee	25	2d4	20x2	0	10	Pierce	Disarm,Trip	CRB",
   "Chakram	Martial	Ranged	Ranged	1	1d8	20x2	30	1	Slash		APG",
   "Club	Simple	OneHand	Melee	0	1d6	20x2	10	3	Blunt		CRB",
   "Club, Mere	Simple	OneHand	Melee	2	1d4	20x2	0	2	Blunt,Pierce	Fragile	AA",
   "Crossbow, Double	Exotic	Ranged	Ranged	300	1d8	19x2	80	18	Pierce		APG",
   "Crossbow, Hand	Exotic	Ranged	Ranged	100	1d4	19x2	30	2	Pierce		CRB",
   "Crossbow, Heavy	Simple	Ranged	Ranged	50	1d10	19x2	120	8	Pierce		CRB",
   "Crossbow, Heavy (Underwater)	Simple	Ranged	Ranged	100	1d10	19x2	120	8	Pierce		ARG",
   "Crossbow, Light	Simple	Ranged	Ranged	35	1d8	19x2	80	4	Pierce		CRB",
   "Crossbow, Light (Underwater)	Simple	Ranged	Ranged	70	1d8	19x2	80	4	Pierce		ARG",
   "Crossbow, Repeating	Exotic	Ranged	Ranged	250	1d8	19x2	80	6	Pierce		CRB",
   "Crossbow, Repeating Heavy	Exotic	Ranged	Ranged	400	1d10	19x2	120	12	Pierce		CRB",
   "Curve Blade, Elven	Exotic	TwoHand	Melee	80	1d10	18x2	0	7	Slash		CRB",
   "Cutlass	Martial	OneHand	Melee	15	1d6	18x2	0	4	Slash		PoIS",
   "Dagger	Simple	Light	Melee	2	1d4	19x2	10	1	Pierce,Slash		CRB",
   "Dagger, Punching	Simple	Light	Melee	2	1d4	20x3	0	1	Pierce		CRB",
   "Dagger, Swordbreaker	Exotic	Light	Melee	10	1d4	20x2	0	3	Slash	Disarm,Sunder	APG",
   "Dart	Simple	Ranged	Thrown	0.5	1d4	20x2	20	0.5	Pierce		CRB",
   "Dogslicer	Martial	Light	Melee	8	1d6	19x2	0	1	Slash	Fragile	ARG",
   "Dorn Dergar, Dwarven	Exotic	TwoHand	Melee	50	1d10	20x2	0	15	Blunt	Reach	DoG",
   "Earth Breaker	Martial	TwoHand	Melee	40	2d6	20x3	0	14	Blunt		ISWG",
   "Falcata	Exotic	OneHand	Melee	18	1d8	19x3	0	4	Slash		APG",
   "Falchion	Martial	TwoHand	Melee	75	2d4	18x2	0	8	Slash		CRB",
   "Fauchard	Exotic	TwoHand	Melee	14	1d10	18x2	0	10	Slash	Reach,Trip	CHR",
   "Flail	Martial	OneHand	Melee	8	1d8	20x2	0	5	Blunt	Disarm,Trip	CRB",
   "Flail, Dire	Exotic	TwoHand	Melee	90	1d8/1d8	20x2/20x2	0	10	Blunt/Blunt	Disarm,Double,Trip	CRB",
   "Flail, Heavy	Martial	TwoHand	Melee	15	1d10	19x2	0	10	Blunt	Disarm,Trip	CRB",
   "Flailpole	Exotic	TwoHand	Melee	15	1d8	20x2	0	10	Slash	Reach,Trip	GoG",
   "Flambard	Exotic	TwoHand	Melee	50	1d10	19x2	0	6	Slash	Sunder	AA",
   "Flindbar	Exotic	OneHand	Melee	30	2d4	19x2	0	2	Blunt	Disarm	CMR",
   "Flying Blade	Exotic	TwoHand	Melee	40	1d12	20x3	0	12	Slash	Performance,Reach	UC",
   "Flying Talon	Exotic	Light	Melee	15	1d4	20x2	10	5	Pierce	Disarm,Trip	D1",
   "Gauntlet	Simple	Unarmed	Melee	2	1d3	20x2	0	1	Blunt		CRB",
   "Gauntlet, Spiked	Simple	Light	Melee	5	1d4	20x2	0	1	Pierce		CRB",
   "Gladius	Martial	Light	Melee	15	1d6	19x2	0	3	Pierce,Slash	Performance	UC",
   "Glaive	Martial	TwoHand	Melee	8	1d10	20x3	0	10	Slash	Reach	CRB",
   "Grappling Hook	Exotic	Ranged	Thrown	6	1d6	20x2	10	14	Pierce	Grapple	PoIS",
   "Greataxe	Martial	TwoHand	Melee	20	1d12	20x3	0	12	Slash		CRB",
   "Greatclub	Martial	TwoHand	Melee	5	1d10	20x2	0	8	Blunt		CRB",
   "Greatsword	Martial	TwoHand	Melee	50	2d6	19x2	0	8	Slash		CRB",
   "Guisarme	Martial	TwoHand	Melee	9	2d4	20x3	0	12	Slash	Reach,Trip	CRB",
   "Halberd	Martial	TwoHand	Melee	10	1d10	20x3	0	12	Pierce,Slash	Brace,Trip	CRB",
   "Hammer, Gnome Hooked	Exotic	TwoHand	Melee	20	1d8/1d6	20x3/20x4	0	6	Blunt/Pierce	Double,Trip	CRB",
   "Hammer, Light	Martial	Light	Melee	1	1d4	20x2	20	2	Blunt		CRB",
   "Handaxe	Martial	Light	Melee	6	1d6	20x3	0	3	Slash		CRB",
   "Harpoon	Exotic	TwoHand	Melee	5	1d8	20x3	10	16	Pierce	Grapple	PoIS",
   "Hook Hand	Simple	Light	Melee	10	1d4	20x2	0	1	Slash	Disarm	PoIS",
   "Horsechopper	Martial	TwoHand	Melee	10	1d10	20x3	0	12	Pierce,Slash	Reach,Trip	ARG",
   "Hunga Munga	Martial	Ranged	Melee	4	1d6	20x2	15	3	Pierce		AA",
   "Javelin	Simple	Ranged	Thrown	1	1d6	20x2	30	2	Pierce		CRB",
   "Kama	Exotic	Light	Melee	2	1d6	20x2	0	2	Slash	Monk,Trip	CRB",
   "Katar, Tri-Bladed	Exotic	Light	Melee	6	1d4	20x4	0	2	Pierce		PCS",
   "Khopesh	Exotic	OneHand	Melee	20	1d8	19x2	0	8	Slash	Trip	APG",
   "Klar	Martial	OneHand	Melee	12	1d6	20x2	0	6	Slash		ISWG",
   "Knife, Butterfly	Exotic	Light	Melee	5	1d4	19x2	0	1	Pierce,Slash		AA",
   "Knife, Switchblade	Martial	Light	Melee	5	1d4	19x2	10	1	Pierce		AA",
   "Kobold Tail Attachment, Long Lash	Martial	Light	Melee	15	1d6	20x2	0	1	Slash	Reach	ARG",
   "Kobold Tail Attachment, Pounder	Martial	Light	Melee	1	1d8	20x2	0	4	Blunt		ARG",
   "Kobold Tail Attachment, Razored	Martial	Light	Melee	3	1d8	19x2	0	2	Slash		ARG",
   "Kobold Tail Attachment, Spiked	Martial	Light	Melee	3	1d8	20x3	0	2	Pierce		ARG",
   "Kobold Tail Attachment, Sweeper	Martial	Light	Melee	7	1d6	20x2	0	3	Blunt	Trip	ARG",
   "Kukri	Martial	Light	Melee	8	1d4	18x2	0	2	Slash		CRB",
   "Lance	Martial	TwoHand	Melee	10	1d8	20x3	0	10	Pierce	Reach	CRB",
   "Longaxe, Dwarven	Exotic	TwoHand	Melee	50	1d12	20x3	0	14	Slash	Reach	ARG",
   "Longbow	Martial	Ranged	Ranged	75	1d8	20x3	100	3	Pierce		CRB",
   "Longbow, Composite	Martial	Ranged	Ranged	100	1d8	20x3	110	3	Pierce		CRB",
   "Longhammer, Dwarven	Exotic	TwoHand	Melee	70	2d6	20x3	0	20	Blunt	Reach	ARG",
   "Longspear	Simple	TwoHand	Melee	5	1d8	20x3	0	9	Pierce	Brace,Reach	CRB",
   "Longsword	Martial	OneHand	Melee	15	1d8	19x2	0	4	Slash		CRB",
   "Mace, Heavy	Simple	OneHand	Melee	12	1d8	20x2	0	8	Blunt		CRB",
   "Mace, Light	Simple	Light	Melee	5	1d6	20x2	0	4	Blunt		CRB",
   "Maulaxe, Dwarven	Exotic	Light	Melee	25	1d6	20x3	10	5	Blunt,Slash		AA",
   "Morningstar	Simple	OneHand	Melee	8	1d8	20x2	0	6	Blunt,Pierce		CRB",
   "Nunchaku	Exotic	Light	Melee	2	1d6	20x2	0	2	Blunt	Disarm,Monk	CRB",
   "Ogre Hook	Martial	TwoHand	Melee	24	1d10	20x3	0	10	Pierce	Trip	ISWG",
   "Pick, Heavy	Martial	OneHand	Melee	8	1d6	20x4	0	6	Pierce		CRB",
   "Pick, Light	Martial	Light	Melee	4	1d4	20x4	0	3	Pierce		CRB",
   "Pickaxe	Martial	TwoHand	Melee	14	1d8	20x4	0	12	Pierce		AP14",
   "Quadrens	Exotic	Light	Melee	8	1d6	19x2	0	2	Pierce	Performance	UC",
   "Quarterstaff	Simple	TwoHand	Melee	0	1d6/1d6	20x2/20x2	0	4	Blunt/Blunt	Double,Monk	CRB",
   "Ranseur	Martial	TwoHand	Melee	10	2d4	20x3	0	12	Pierce	Disarm,Reach	CRB",
   "Rapier	Martial	OneHand	Melee	20	1d6	18x2	0	2	Pierce		CRB",
   "Ratfolk Tailblade	Martial	Light	Melee	11	1d3	20x2	0	0.5	Slash		ARG",
   "Rhoka	Exotic	OneHand	Melee	5	1d8	18x2	0	6	Slash		AA",
   "Rope Gauntlet	Exotic	Light	Melee	0.2	1d4	20x2	0	2	Blunt,Slash		AA",
   "Sabre, Sawtooth	Exotic	OneHand	Melee	35	1d8	19x2	0	2	Slash		ISWG",
   "Sai	Exotic	Light	Melee	1	1d4	20x2	0	1	Blunt	Disarm,Monk	CRB",
   "Sap	Martial	Light	Melee	1	1d6	20x2	0	2	Blunt	Nonlethal	CRB",
   "Scarf, Bladed	Exotic	TwoHand	Melee	12	1d6	20x2	0	2	Slash	Disarm,Trip	ISWG",
   "Scimitar	Martial	OneHand	Melee	15	1d6	18x2	0	4	Slash		CRB",
   "Scizore	Martial	OneHand	Melee	20	1d10	20x2	0	3	Pierce		UC",
   "Scythe	Martial	TwoHand	Melee	18	2d4	20x4	0	10	Pierce,Slash	Trip	CRB",
   "Sea-Knife	Martial	Light	Melee	8	1d4	19x2	0	1	Slash		ARG",
   "Shield, Heavy Steel	Martial	OneHand	Melee	20	1d4	20x2	0	15	Blunt		CRB",
   "Shield, Light Steel	Martial	Light	Melee	9	1d3	20x2	0	6	Blunt		CRB",
   "Shortbow	Martial	Ranged	Ranged	30	1d6	20x3	60	2	Pierce		CRB",
   "Shortbow, Composite	Martial	Ranged	Ranged	75	1d6	20x3	70	2	Pierce		CRB",
   "Shortspear	Simple	OneHand	Melee	1	1d6	20x2	20	3	Pierce		CRB",
   "Shotel	Exotic	OneHand	Melee	30	1d8	20x3	0	3	Pierce	Performance	UC",
   "Shuriken	Exotic	Ranged	Thrown	0.2	1d2	20x2	10	0.1	Pierce	Monk	CRB",
   "Siangham	Exotic	Light	Melee	3	1d6	20x2	0	1	Pierce	Monk	CRB",
   "Sica	Exotic	Light	Melee	10	1d6	20x2	0	2	Slash	Performance	UC",
   "Sickle	Simple	Light	Melee	6	1d6	20x2	0	2	Slash	Trip	CRB",
   "Sling	Simple	Ranged	Thrown	0	1d4	20x2	50	0	Blunt		CRB",
   "Sling Glove	Exotic	Ranged	Thrown	5	1d4	20x2	50	2	Blunt		AA",
   "Sling Staff, Halfling	Exotic	Ranged	Thrown	20	1d8	20x3	80	3	Blunt		CRB",
   "Sling, Stitched	Exotic	Ranged	Thrown	0	1d6	20x2	0	1	Blunt	Disarm,Trip	HoG",
   "Spear	Simple	TwoHand	Melee	2	1d8	20x3	20	6	Pierce	Brace	CRB",
   "Starknife	Martial	Light	Melee	24	1d4	20x3	20	3	Pierce		CRB",
   "Sword, Bastard	Exotic	OneHand	Melee	35	1d10	19x2	0	6	Slash		CRB",
   "Sword, Dueling	Exotic	OneHand	Melee	20	1d8	19x2	0	3	Slash		ISWG",
   "Sword, Short	Martial	Light	Melee	10	1d6	19x2	0	2	Pierce		CRB",
   "Sword, Two-Bladed	Exotic	TwoHand	Melee	100	1d8/1d8	19x2/19x2	0	10	Slash/Slash	Double	CRB",
   "Terbutje	Martial	OneHand	Melee	5	1d8	19x2	0	2	Slash	Fragile	AA",
   "Terbutje, Steel	Martial	OneHand	Melee	20	1d8	19x2	0	4	Slash		AA",
   "Thorn Bracer	Exotic	Light	Melee	30	1d6	20x2	0	3	Pierce		PCS",
   "Trident	Martial	OneHand	Melee	15	1d8	20x2	10	4	Pierce	Brace	CRB",
   "Unarmed Strike	Simple	Unarmed	Melee	0	1d3	20x2	0	0	Blunt	Nonlethal	CRB",
   "Urgrosh, Dwarven	Exotic	TwoHand	Melee	50	1d8/1d6	20x3/20x3	0	12	Slash/Pierce	Brace,Double	CRB",
   "War Razor	Martial	Light	Melee	8	1d4	19x2	0	1	Slash		ISWG",
   "Waraxe, Dwarven	Exotic	OneHand	Melee	30	1d10	20x3	0	8	Slash		CRB",
   "Warhammer	Martial	OneHand	Melee	12	1d8	20x3	0	5	Blunt		CRB",
   "Whip	Exotic	OneHand	Melee	1	1d3	20x2	0	2	Slash	Disarm,Nonlethal,Reach,Trip	CRB",
   "Whip, Scorpion	Exotic	Light	Melee	5	1d4	20x2	0	3	Slash	Disarm,Performance,Reach,Trip	UC",
   "Wooden Stake	Simple	Light	Melee	0	1d4	20x2	10	1	Pierce		APG"
)]
[H: keyList = "weapon.name,weapon.category,weapon.encumbrance,weapon.threat,weapon.cost,weapon.damage,weapon.crit,weapon.range,weapon.weight,weapon.type,weapon.special,weapon.source"]
[H: TAB = decode("%09")]
[H: weaponList = "{}"]
[H: inputTemplate = "<html><table><td width=350><b>%{input.name}</b> %{input.categories}</td><td width=50><b color=blue>%{input.damage}</b></td><td width=75><b color=red>%{input.critical}</b></td><td width=50><b>%{input.range}</b></td><td width=100><b><i>%{input.special}</i></b></td></table></html>"]
[H: weaponInputList = json.set("{}","<html><table><td width=350><b>Name (Categories)</b></td><td width=50><b>Damage</b></td><td width=75><b>Critical</b></td><td width=50><b>Range</b></td><td width=125><b>Special</b></td></table></html>","")]
[H, foreach(data,rawData), code: {
   [H: weaponName = listGet(data,0,TAB)]
   [H: propName = "weapon." + am.pf.cleanProp(weaponName)]
   [H: obj = "{}"]
   [H, foreach(prop,keyList): obj = json.set(obj,prop,listGet(data,roll.count,TAB))]
   [H: setLibProperty(propName,obj)]
   [H: weaponList = json.set(weaponList,weaponName,propName)]
   
   [H: input.name = replace(weaponName,",","&#44")]
   [H: input.categories = strformat("(%s/%s/%s/%s)",listGet(data,1,TAB),listGet(data,2,TAB),listGet(data,3,TAB),replace(listGet(data,9,TAB),",","&#44"))]
   [H: input.damage = listGet(data,5,TAB)]
   [H: input.critical = listGet(data,6,TAB)]
   [H: input.range = listGet(data,7,TAB)]
   [H, if(! input.range): input.range = " "]
   [H: input.special = trim(replace(listGet(data,10,TAB),",","&#44"))]
   [H, if(json.isEmpty(input.special)): input.special = " "]
   [H: inputListName = strformat(inputTemplate)]
   [H: weaponInputList = json.set(weaponInputList,inputListName,propName)]
}]
[H: setLibProperty("weaponList",weaponList)]
[H: setLibProperty("weaponList.input",weaponInputList)]
||| listWeapons |||

Code: Select all

<!-- addWeapon() -->
[H: weaponList = getLibProperty("weaponList.input")]
[H: weaponNameList = json.fields(weaponList)]
[H: abort(input("tip|<html><font size=6><b><center>Pick Base Weapon</center></b></font></html>|Pick Base Weapon|LABEL|SPAN=TRUE",
   strformat("select|%{weaponNameList}||LIST|SPAN=TRUE")))]
[R: json.get(weaponList,listGet(weaponNameList,select))]
Running initWeaponData first saves the data to the token and then listWeapons shows the list of weapons. The variable weaponList has all the data and weaponList.input is just the hmtl I use for input(). Also, weaponList is just a list of prop names on the token that represent the weapon. For example, "weapon.longsword" is the name of a variable on the lib token. weaponList has it as "Longsword":"weapon.longsword". You could do something similar. I'm not sure how you want to organize your data but you could have "weapon.mainhand","weapon.offhand","weapon.1","weapon.2",...

It's easier to store object data as it's own property rather than making an array of objects or objects of obects, which you can also do.

Code: Select all

[H: weapons = json.set("{}",
   "weapon1",json.set("{}",
      "name","Longsword",
      "type","slashing",
      "damage","1d8"),
   "weapon2",json.set("{}",
      "name","Shortsword",
      "type","slashing,piercing",
      "damage","1d6")
   )
]

<!-- get weapon 1 data -->
[H: weaponData = json.get(weapons,"weapon1")]

<!-- get weapon 1 damage -->
[H: damage = json.get(weaponData,"damage")]

<!-- get weapon data not there -->
[H: weaponData = json.get(weapons,"weapon3")]

<!-- check to see if it has data -->
[H: emptySlot = json.isEmtpy(weaponData)]
[R, if(emptySlot): "Empty Slot"]

User avatar
growlly
Cave Troll
Posts: 32
Joined: Fri Jul 10, 2015 11:35 am
Location: United States

Re: Growlly's Totally Noob Questions about Macros

Post by growlly »

aliasmask wrote:I would do it an entirely different way, but you can just simply check the string with an if before doing anything with the variable (which wouldn't exist).

Again, jsons are the way to go for database like structures. For example, limiting yourself to defined token properties of Weap1Name, Weapon2Name when you could just have 1 property called, weapons. So, if the variable is empty, then you have no weapons.
Wow, that is awesome. I feel like I'm at the end of building a project car, and I have to decide whether to finish it as planned or take it all apart again and use what I've learned. I'll have to figure that out soon.

New question: how can we populate an input field with the current value of the field? I'm trying to set up a quick input box so players can edit notes. It looks like this so far:

Code: Select all

[h: status = input(
"NewNotes|[r: getNotes()]|Edit Notes"
)]
[h: abort(status)]
[h: setNotes(NewNotes)]
Notes edited.
Except that the area for the default value displays the actual text "[r: getNotes()]" rather than the value. Actually, in that sense, it's kind of similar to the previous problem. Any thoughts?

EDIT: I also tried doing it with HTML, and I got it to display the current notes this way. However, I don't know how to get it to replace the notes with what is typed in.

Code: Select all

[dialog("Edit Notes"):{
<html>
<body>
<input type="text" name="NewNotes" value="[r: getNotes()]">
</input>
<br>
<input id="saveButton" type="submit" name="Save" value="Save">
</input>
</body>
</html>
}]
Notes edited.
The issue this way is that the form doesn't know that the field being submitted is the notes field.

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

Re: Growlly's Totally Noob Questions about Macros

Post by aliasmask »

Here's the basics for writing to a textarea: http://forums.rptools.net/viewtopic.php ... 80#p258527

The main thing there are certain characters you need to change because they have special meaning.

Input is a little more straight forward. The one thing you will need to do is change &#59 to ; like this:

Code: Select all

[H, if(!json.isEmpty(taText)): taText = replace(taText,"&#"+59,";")]
Depending on your in put source, you may need to filter more characters like unicode. You will need to wrap your input with a <form> tag as well.

Code: Select all

<form method="json" action="[r: macroLinkText("processForm@"+getMacroLocation(),"none","",id)]">
The above calls the macro processForm on the current lib token and passes form inputs as a json. So, in your case you get the data by:

Code: Select all

<!-- processForm() -->
[H: args = macro.args]
[H: notes = json.get(args,"NewNotes")]

User avatar
growlly
Cave Troll
Posts: 32
Joined: Fri Jul 10, 2015 11:35 am
Location: United States

Re: Growlly's Totally Noob Questions about Macros

Post by growlly »

Ok, so I read over everything you wrote and linked to... and comprehended about 40% of it. Sorry. Basically I understood that some characters have to be converted in order for HTML to produce the intended characters instead of interpreting them as syntax, and you provided some code to search through the text and replace them. Excellent.

But before I even get to that problem, I still don't know how to actually update the notes. This opens a dialog that displays the current notes and lets you type over them, but I need it to actually save what you type in to update the notes.

Code: Select all

[dialog("Edit Notes"):{
<html>
<body>
<input type="text" name="NewNotes" value="[r: getNotes()]">
</input>
<br>
<input id="saveButton" type="submit" name="Save" value="Save">
</input>
</body>
</html>
}]
Notes edited.
I tried setNotes(NewNotes) but it's still acting like it doesn't know what NewNotes is. I need to tell it that what is being typed in or saved is NewNotes.

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

Re: Growlly's Totally Noob Questions about Macros

Post by aliasmask »

That's why I said you need to add a form tag. That's how the data is sent to the macro for processing. <input> by itself does nothing.

http://www.w3schools.com/html/html_forms.asp

User avatar
growlly
Cave Troll
Posts: 32
Joined: Fri Jul 10, 2015 11:35 am
Location: United States

Re: Growlly's Totally Noob Questions about Macros

Post by growlly »

Do you mean like this?

Code: Select all

[dialog("Edit Notes"):{
<html>
<body>
<form>
<input type="text" name="NewNotes" value="[r: getNotes()]">
</input>
<br>
<input id="saveButton" type="submit" name="Save" value="Save">
</input>
</form>
</body>
</html>
}]
Notes edited.
I didn't notice any change. I also tried the [h: setNotes(NewNotes)] at the end, but it's still acting like NewNotes is a brand new variable, not one holding the value of the text that was entered.

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

Re: Growlly's Totally Noob Questions about Macros

Post by aliasmask »

Look at my post above:

Code: Select all

<form method="json" action="[r: macroLinkText("processForm@"+getMacroLocation(),"none","",id)]">
There's a forms tutorial somewhere in the wiki, but the above is the core of it.

<form> does nothing if you don't tell it where to process the form. The inputs names and values are sent to the macro where you can do what you want to the data.

User avatar
growlly
Cave Troll
Posts: 32
Joined: Fri Jul 10, 2015 11:35 am
Location: United States

Re: Growlly's Totally Noob Questions about Macros

Post by growlly »

Ok, I got it sorted out now. This was way more complicated than I thought. I just didn't understand enough to see what you were doing. I used the Forms tutorial, but I also had to fill in some gaps because the tutorial doesn't actually show you how to use the output to do stuff with it. It also says it assumes you know about lib tokens and "simple" macros but ends up requiring JSON knowledge if you actually want to do anything with the output you get from it.

Anyway, here's what I ended up doing it, in case future n00bs come along:
I have a token called Lib:Char that has all my character/character sheet-related stuff on it. To edit a token's notes with a pop-up frame, I added 3 macros to it:

EditNotes

Code: Select all

[frame("Edit Notes"): {
[r, macro("DisplayNotes@Lib:Char"): ""]
}]
DisplayNotes

Code: Select all

[h: processorLink = macroLinkText("ProcessNotes@Lib:Char", "all")]
<form action="[r:processorLink]" method="json">
Notes: <textarea name="NewNotes" cols="50" rows="7">[r: getNotes()]</textarea>
<input type="submit" name="myForm_btn" value="Save Changes">
<input type="reset" value="Undo Changes">
</form>
ProcessNotes

Code: Select all

[h: myNotes = json.indent(macro.args,2)]
[h: NewNotes = json.get(myNotes, "NewNotes")]
[h: setNotes(NewNotes)]
When a token (or in my case, a token's character sheet) calls up EditNotes, it opens a frame that displays the current notes. You can type over them and click "save changes" to save or "undo changes" to reset back to when you opened the frame. I know it's not the slickest way to do this, but it's simple and it does work.

The only special character that has caused strangeness is semicolon. It shows up as &#59 in the actual Notes tab when you edit a token, but shows up normally everywhere else. No problems with ()[]{}, etc.

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

Re: Growlly's Totally Noob Questions about Macros

Post by aliasmask »

Here's my take one what you're doing:
/// CODE \\\

Code: Select all

@@ @editNotes
<!-- editNotes(tokenId,notes)

This function will allow you to edit token notes
-->

<!-- allow to set initial notes -->
[H, if(argCount() >= 1): id = arg(0); id = currentToken()]
[H, if(argCount() >= 2): notes = arg(1); notes = getNotes()]

[H: assert(! json.isEmpty(id),"Token not on current map.",0)]
[H: switchToken(id)]

<!-- do some character conversions to display notes in textarea -->
[H, if(! json.isEmpty(notes)), code: {
   [H: notes = replace(notes,"&","&")]
   [H: notes = replace(notes,"\\\\","\")]
   [H: notes = replace(notes,"<","<")]
   [H: notes = replace(notes,"/","/")]
   [H: notes = replace(notes,"[\$]","$")]
};{}]

<!-- set some form variables -->
[H: processLink = macroLinkText("processForm@"+getMacroLocation(),"none","",currentToken())]
[H: formWidth = 80]
[H: formHeight = 10]

<!-- generate output for form -->
[H: taOutput = strformat('
   <form method="json" action="%{processLink}">
   <table width="100%">
      <tr style="text-align:right">
         <td><input type="submit" name="submit" value="Reload" /></td>
      </tr>
      <tr>
         <td><textarea name="notes" cols="%{formWidth}" rows="%{formHeight}">%{notes}</textArea></td>
      </tr>
      <tr style="text-align:right">
         <td><input type="submit" name="submit" value="Save" /></td>
      </tr>
   </table>
   </form>
')]

<!-- display form -->
[dialog("Edit Notes","width=700;height=350;temporary=1;"): { [r: taOutput] }]

!!
@@ @processForm
<!-- processForm(formObj)

This function will process form data from edit notes.
--->
[H: args = macro.args]
[H: notes = json.get(args,"notes")]
[H: action = json.get(args,"submit")]

<!-- check for reload and confirm -->
[H, if(action == "Reload"), code: {
   [H: confirm = input("tip|<html>All note changes will be lost and current notes reloaded<br><br>Click <b>OK</b> to Confirm.</html>||LABEL|SPAN=TRUE")]
   <!-- callback to form -->
   [H, if(confirm): am.note.editNotes(); am.note.editNotes(currentToken(),notes)]
};{}]

<!-- save changes -->
[H, if(action == "Save"), code: {
   [H: setNotes(notes)]
   <!-- callback to form -->
   [H: am.note.editNotes()]
};{}]

!!
 
I've also included a token. It includes the 2 functions above as well as my starter kit macros for lib tokens. The only thing required is the onCampaignLoad to make the macros in to functions.

keywords: amsave notes form
Attachments
lib notes 8-1-15.rptok
(35.62 KiB) Downloaded 60 times

User avatar
growlly
Cave Troll
Posts: 32
Joined: Fri Jul 10, 2015 11:35 am
Location: United States

Re: Growlly's Totally Noob Questions about Macros

Post by growlly »

Thanks, I did eventually get the notes editing process down.

New topic: How do I reference images in the resource library? I have some weapon images ready to go in the library, but I need to be able to display them on inventory sheets, etc. What's the best way to do that? I'm assuming there's some kind of file path, but I don't know where to find it.

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

Re: Growlly's Totally Noob Questions about Macros

Post by aliasmask »

The reference library? Any image you want to reference needs to be in your campaign. You can build a table of images, but I like using findImage(tokenName). It returns the image asset from any token in the campaign.

User avatar
growlly
Cave Troll
Posts: 32
Joined: Fri Jul 10, 2015 11:35 am
Location: United States

Re: Growlly's Totally Noob Questions about Macros

Post by growlly »

Hmm... maybe I should back up. I've got weapon images saved on my computer, and I would like to call them up as properties (alongside accuracy and damage, etc.) so they can display on the inventory frame. So if I have "gun.jpg" on my computer, I assumed that I would add the directory that gun.jpg is in to the resource library and then reference it (resources\guns\gun.jpg or whatever) as the property's value.

What you're saying is that the image has to be in the campaign file somewhere, which makes a bit of sense because if I send the campaign to players, they need the images too. If I understand what you mean about using tokens to reference the images, it sounds like I would have to make a token for every image (200+ in my case). A table sounds better in my case, and I assume you mean the following: column 1 = index number, column 2 = image. But how do I get the image into column 2?

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

Re: Growlly's Totally Noob Questions about Macros

Post by aliasmask »

There's a little plus sign you click to add an image when editing a table.

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

Re: Growlly's Totally Noob Questions about Macros

Post by Full Bleed »

aliasmask wrote:Input is a little more straight forward. The one thing you will need to do is change &#59 to ; like this:

Code: Select all

[H, if(!json.isEmpty(taText)): taText = replace(taText,"&#"+59,";")]
I can't get the semi-colon replace example you provided above to work with your notes code:

Code: Select all

[H, if(! json.isEmpty(notes)), code: {
   [H: notes = replace(notes,"&","&")]
   [H: notes = replace(notes,"\\\\","\")]
   [H: notes = replace(notes,"<","<")]
   [H: notes = replace(notes,"/","/")]
   [H: notes = replace(notes,"[\$]","$")]
};{}]
Do you have code to properly display a semi-colon?
Maptool is the Millennium Falcon of VTT's -- "She may not look like much, but she's got it where it counts."

Post Reply

Return to “Macros”