browser icon
You are using an insecure version of your web browser. Please update your browser!
Using an outdated browser makes your computer unsafe. For a safer, faster, more enjoyable user experience, please update your browser today or try a newer browser.

Adding an Attack to an Existing Weapon

Posted by on August 13, 2010

I made some modifications to the new weapon macro, based on the idea that labeling different attacks Attack1, Attack2, etc. is really stupid.  This was mostly so I could then write clean code for adding new attack types to the weapon.

New Create Melee Weapon codeblock:

<!– Add_New_Melee_Weapon –>

<!– Adding a new melee weapon to the library token. The property WeaponList on the token must be filled in to define an empty JSON object prior to running the first time. –>

[h: weaponList2 = getLibProperty(“WeaponList”, “Lib:Weapons”)]

<!– The property SkillsMelee on the library token must be defined as a JSON array containing all melee skill names to be used in the campaign. –>

[h: SkillList= json.toList(SkillsMelee)]

<!– Define the weapon’s basic parameters and the primary attack mode.  Additional modes to be added after weapon creation in a different macro. –>

[h: newWeapon =
input(
“wName|No Weapon|Weapon Name|TEXT”,
“wWeight||Weight|TEXT”,
“wDR||DR (for breakage)|TEXT”,
“wMaxHP||Maximum HP|TEXT”,

“wAttackLabel||Attack Label|TEXT”,
“wSkill1|”+SkillList+”|Skill Used|LIST|SELECT=0 VALUE=STRING”,
“wDamBase1|none,thrust,swing,static|Damage Base 1|LIST|SELECT=0 VALUE=STRING”,
“wDamMod1|0|Damage Modifier 1 (0/+#/-#/dice expression)|TEXT”,
“wDamType1|crushing,cutting,impaling,pi-,pi,pi+,pi++|Damage Type 1|LIST|SELECT=0 VALUE=STRING”,
“wReach1|0,0-1,1,1-2,1-3,1-4,1-7,2,2-3,4|Reaches (C = 0)|LIST|SELECT=0 VALUE=STRING”,
“wGripChange1|0|Ready Maneuver to Change Grip?|CHECK”,
“wParry1|0,0U,0F,-1,-2U,+2|Parry|LIST|SELECT=0 VALUE=STRING”,
“wMinST1||Minimum Strength|TEXT”,
“wHand1|1H,2H,2H Unready|Hands|RADIO|ORIENT=H SELECT=0 VALUE=STRING”,
“wStuck1|0|Can get stuck?|CHECK”

)]

<!– Create the new weapon JSON object and the first attack sub-object to store to the master WeaponList array.  If the OK button is clicked without changing the No Weapon default, do not execute. –>

[r, if (wName != “No Weapon”), code:
{
[h: weaponStats = “{}”]
[h: attackStats = “{}”]

[h: weaponStats = json.set(weaponStats, “Name”, wName)]
[h: weaponStats = json.set(weaponStats, “Weight”, wWeight)]
[h: weaponStats = json.set(weaponStats, “DR”, wDR)]
[h: weaponStats = json.set(weaponStats, “MaxHP”, wMaxHP)]

[h: attackStats = json.set(attackStats, “Label”, wAttackLabel)]
[h: attackStats = json.set(attackStats, “Skill”, wSkill1)]
[h: attackStats = json.set(attackStats, “DamBase”, wDamBase1)]
[h: attackStats = json.set(attackStats, “DamMod”, wDamMod1)]
[h: attackStats = json.set(attackStats, “DamType”, wDamType1)]
[h: attackStats = json.set(attackStats, “Reach”, wReach1)]
[h: attackStats = json.set(attackStats, “GripChange”, wGripChange1)]
[h: attackStats = json.set(attackStats, “Parry”, wParry1)]
[h: attackStats = json.set(attackStats, “MinST”, wMinST1)]
[h: attackStats = json.set(attackStats, “Hand”, wHand1)]
[h: attackStats = json.set(attackStats, “Stuck”, wStuck1)]

[h: weaponStats = json.set(weaponStats, wAttackLabel, attackStats)]

[h: weaponList2 = json.set(weaponList2, wName, weaponStats)]

[h: setLibProperty(“WeaponList”, weaponList2, “Lib:Weapons”)]

Weapon ‘[r: wName]’ added to WeaponList.
};
{ No weapon added. }]

I added a Thrusting Broadsword to a blank WeaponsList array as per GURPS Basic.  The base object looked like this:

{“Thrusting Broadsword”:{“Name”:”Thrusting Broadsword”, “Weight”:3, “DR”:6, “MaxHP”:12, “Swing”:{“Label”:”Swing”, “Skill”:”Broadsword”, “DamBase”:”swing”, “DamMod”:1, “DamType”:”cutting”, “Reach”:1, “GripChange”:0, “Parry”:0,”MinST”:10, “Hand”:”1H”, “Stuck”:0}}}

Properties like weapon quality, weapon bond modifiers, current hit points for damaged objects, etc. I figure will be added when the weapon is added onto the player token, to keep things simpler.  (I can also tie them to a new library token that holds a player’s inventory, but one step at a time here…)  As you can see, the one attack “Swing” is now a sub-object.  Now I need a macro that will cleanly add a thrust attack.  The macro will also be used to add attacks based on different weapon skills, such as Broadsword/Two-Handed Sword for a bastard sword.

One debate I was having before making up this structure is how to deal with different grips.  There are a lot of variables that go into determining how a weapon is being held in GURPS:

  • How many hands are used for variable hands weapons like spears, bastard swords, etc.
  • The reach grip used for awkward weapons like polearms, requiring either Grip Mastery or a Ready maneuver to switch
  • Optional grips like Reverse Grip, Defensive Grip, etc.

Right now I’m just going to have to leave the grip options to the character properties while the weapon is used.  When the weapon is armed, I will have to add additional properties to the object such as Grip (for defensive, reversed, etc.), ReachGrip (for long weapons), and Hands (for 1H/2H weapons).  Of course these variables also exist inside the attack sub-objects so it might get confusing… oh well, worry about it later.

The adding a melee attack macro I cooked up looks like this:

<!– Add_New_Melee_Attack –>

<!– Adding a new melee attack to a weapon in the library token. –>

[h: weaponList2 = getLibProperty(“WeaponList”, “Lib:Weapons”)]

<!– The property SkillsMelee on the library token must be defined as a JSON array containing all melee skill names to be used in the campaign. –>

[h: SkillList= json.toList(SkillsMelee)]

<!– Get the existing weapon names for a list with the first weapon being the null selection –>

[h: wWeaponListArray = “[]”]
[h: wWeaponListArray = json.append(wWeaponListArray, “No Weapon”, json.toList(json.fields(WeaponList, “json”)))]
[h: wWeaponNames = json.toList(wWeaponListArray)]

<!– Pick the existing weapon name and define the new attack’s characteristics.
NOTE:  No safeguards against duplicate attack names! –>

[h: newMeleeAttack =
input(
“wName|”+wWeaponNames+”|Weapon Name|LIST|SELECT=0 VALUE=STRING”,

“wAttackLabel||Attack Label|TEXT”,
“wSkill1|”+SkillList+”|Skill Used|LIST|SELECT=0 VALUE=STRING”,
“wDamBase1|none,thrust,swing,static|Damage Base 1|LIST|SELECT=0 VALUE=STRING”,
“wDamMod1|0|Damage Modifier 1 (0/+#/-#/dice expression)|TEXT”,
“wDamType1|crushing,cutting,impaling,pi-,pi,pi+,pi++|Damage Type 1|LIST|SELECT=0 VALUE=STRING”,
“wReach1|0,0-1,1,1-2,1-3,1-4,1-7,2,2-3,4|Reaches (C = 0)|LIST|SELECT=0 VALUE=STRING”,
“wGripChange1|0|Ready Maneuver to Change Grip?|CHECK”,
“wParry1|0,0U,0F,-1,-2U,+2|Parry|LIST|SELECT=0 VALUE=STRING”,
“wMinST1||Minimum Strength|TEXT”,
“wHand1|1H,2H,2H Unready|Hands|RADIO|ORIENT=H SELECT=0 VALUE=STRING”,
“wStuck1|0|Can get stuck?|CHECK”

)]

<!– Append the new attack type to the weapon object.  If No Weapon is selected, do not execute. –>

[r, if (wName != “No Weapon”), code:
{
[h: weaponStats = “{}”]
[h: attackStats = “{}”]

[h: attackStats = json.set(attackStats, “Label”, wAttackLabel)]
[h: attackStats = json.set(attackStats, “Skill”, wSkill1)]
[h: attackStats = json.set(attackStats, “DamBase”, wDamBase1)]
[h: attackStats = json.set(attackStats, “DamMod”, wDamMod1)]
[h: attackStats = json.set(attackStats, “DamType”, wDamType1)]
[h: attackStats = json.set(attackStats, “Reach”, wReach1)]
[h: attackStats = json.set(attackStats, “GripChange”, wGripChange1)]
[h: attackStats = json.set(attackStats, “Parry”, wParry1)]
[h: attackStats = json.set(attackStats, “MinST”, wMinST1)]
[h: attackStats = json.set(attackStats, “Hand”, wHand1)]
[h: attackStats = json.set(attackStats, “Stuck”, wStuck1)]

<!– Set the weaponStats string to the single weapon object from the weaponlist2 object –>

[h: weaponStats = json.get(weaponlist2, wName)]

<!– Set the new attack into the weapon object –>

[h: weaponStats = json.set(weaponStats, wAttackLabel, attackStats)]

<!– Write the weapon back into the array with the new attack –>

[h: weaponlist2 = json.set(weaponlist2, wName, weaponStats)]

[h: setLibProperty(“WeaponList”, weaponList2, “Lib:Weapons”)]

Attack ‘[r: wAttackLabel]’ added to ‘[r: wName]’.
};
{ No attack added. }]

Obviously I was able to recycle a lot of the Add New Weapon code.  The dialog box and my new attack look like this:

The resulting code for my thrusting broadsword is:

{“Thrusting Broadsword”:{“Name”:”Thrusting Broadsword”, “Weight”:3, “DR”:6, “MaxHP”:12, “Swing”:{“Label”:”Swing”, “Skill”:”Broadsword”, “DamBase”:”swing”, “DamMod”:1, “DamType”:”cutting”, “Reach”:1, “GripChange”:0, “Parry”:0, “MinST”:10, “Hand”:”1H”, “Stuck”:0}, “Thrust”:{“Label”:”Thrust”, “Skill”:”Broadsword”, “DamBase”:”thrust”, “DamMod”:2, “DamType”:”impaling”, “Reach”:1, “GripChange”:0, “Parry”:0, “MinST”:10, “Hand”:”1H”, “Stuck”:0}}}

Pretty schmott… except I just realized I’ve made a terrible mistake.  Random names like “Swing” and “Thrust” exist in the same hierarchy as unchanging properties like “Weight” so I have no way to cleanly grab all of the attacks out of a weapon when creating my attack macro later on!  I need to add a new object to contain all of the attack.  At this point I’m really glad I went with JSON objects instead of string lists.  So I blank out my WeaponList property (to {}) and add a new layer of stupidity to my create and add attack macros:

<!– Add_New_Melee_Weapon –>

<!– Adding a new melee weapon to the library token. The property WeaponList on the token must be filled in to define an empty JSON object prior to running the first time. –>

[h: weaponList2 = getLibProperty(“WeaponList”, “Lib:Weapons”)]

<!– The property SkillsMelee on the library token must be defined as a JSON array containing all melee skill names to be used in the campaign. –>

[h: SkillList= json.toList(SkillsMelee)]

<!– Define the weapon’s basic parameters and the primary attack mode.  Additional modes to be added after weapon creation in a different macro. –>

[h: newWeapon =
input(
“wName|No Weapon|Weapon Name|TEXT”,
“wWeight||Weight|TEXT”,
“wDR||DR (for breakage)|TEXT”,
“wMaxHP||Maximum HP|TEXT”,

“wAttackLabel||Attack Label|TEXT”,
“wSkill1|”+SkillList+”|Skill Used|LIST|SELECT=0 VALUE=STRING”,
“wDamBase1|none,thrust,swing,static|Damage Base 1|LIST|SELECT=0 VALUE=STRING”,
“wDamMod1|0|Damage Modifier 1 (0/+#/-#/dice expression)|TEXT”,
“wDamType1|crushing,cutting,impaling,pi-,pi,pi+,pi++|Damage Type 1|LIST|SELECT=0 VALUE=STRING”,
“wReach1|0,0-1,1,1-2,1-3,1-4,1-7,2,2-3,4|Reaches (C = 0)|LIST|SELECT=0 VALUE=STRING”,
“wGripChange1|0|Ready Maneuver to Change Grip?|CHECK”,
“wParry1|0,0U,0F,-1,-2U,+2|Parry|LIST|SELECT=0 VALUE=STRING”,
“wMinST1||Minimum Strength|TEXT”,
“wHand1|1H,2H,2H Unready|Hands|RADIO|ORIENT=H SELECT=0 VALUE=STRING”,
“wStuck1|0|Can get stuck?|CHECK”

)]

<!– Create the new weapon JSON object and the first attack sub-object to store to the master WeaponList array.  If the OK button is clicked without changing the No Weapon default, do not execute. –>

[r, if (wName != “No Weapon”), code:
{
[h: weaponStats = “{}”]
[h: attackStats = “{}”]
[h: attacks = “{}”]

[h: weaponStats = json.set(weaponStats, “Name”, wName)]
[h: weaponStats = json.set(weaponStats, “Weight”, wWeight)]
[h: weaponStats = json.set(weaponStats, “DR”, wDR)]
[h: weaponStats = json.set(weaponStats, “MaxHP”, wMaxHP)]

[h: attackStats = json.set(attackStats, “Label”, wAttackLabel)]
[h: attackStats = json.set(attackStats, “Skill”, wSkill1)]
[h: attackStats = json.set(attackStats, “DamBase”, wDamBase1)]
[h: attackStats = json.set(attackStats, “DamMod”, wDamMod1)]
[h: attackStats = json.set(attackStats, “DamType”, wDamType1)]
[h: attackStats = json.set(attackStats, “Reach”, wReach1)]
[h: attackStats = json.set(attackStats, “GripChange”, wGripChange1)]
[h: attackStats = json.set(attackStats, “Parry”, wParry1)]
[h: attackStats = json.set(attackStats, “MinST”, wMinST1)]
[h: attackStats = json.set(attackStats, “Hand”, wHand1)]
[h: attackStats = json.set(attackStats, “Stuck”, wStuck1)]

<!– Add the Attacks sub-object to hold all attacks for easy sorting –>

[h: attacks = json.set(attacks, wAttackLabel, attackStats)]
[h: weaponStats = json.set(weaponStats, “Attacks”, attacks)]

[h: weaponList2 = json.set(weaponList2, wName, weaponStats)]

[h: setLibProperty(“WeaponList”, weaponList2, “Lib:Weapons”)]

Weapon ‘[r: wName]’ added to WeaponList.
};
{ No weapon added. }]

———————————————————————-

<!– Add_New_Melee_Attack –>

<!– Adding a new melee attack to a weapon in the library token. –>

[h: weaponList2 = getLibProperty(“WeaponList”, “Lib:Weapons”)]

<!– The property SkillsMelee on the library token must be defined as a JSON array containing all melee skill names to be used in the campaign. –>

[h: SkillList= json.toList(SkillsMelee)]

<!– Get the existing weapon names for a list with the first weapon being the null selection –>

[h: wWeaponListArray = “[]”]
[h: wWeaponListArray = json.append(wWeaponListArray, “No Weapon”, json.toList(json.fields(WeaponList, “json”)))]
[h: wWeaponNames = json.toList(wWeaponListArray)]

<!– Pick the existing weapon name and define the new attack’s characteristics.
NOTE:  No safeguards against duplicate attack names! –>

[h: newMeleeAttack =
input(
“wName|”+wWeaponNames+”|Weapon Name|LIST|SELECT=0 VALUE=STRING”,

“wAttackLabel||Attack Label|TEXT”,
“wSkill1|”+SkillList+”|Skill Used|LIST|SELECT=0 VALUE=STRING”,
“wDamBase1|none,thrust,swing,static|Damage Base 1|LIST|SELECT=0 VALUE=STRING”,
“wDamMod1|0|Damage Modifier 1 (0/+#/-#/dice expression)|TEXT”,
“wDamType1|crushing,cutting,impaling,pi-,pi,pi+,pi++|Damage Type 1|LIST|SELECT=0 VALUE=STRING”,
“wReach1|0,0-1,1,1-2,1-3,1-4,1-7,2,2-3,4|Reaches (C = 0)|LIST|SELECT=0 VALUE=STRING”,
“wGripChange1|0|Ready Maneuver to Change Grip?|CHECK”,
“wParry1|0,0U,0F,-1,-2U,+2|Parry|LIST|SELECT=0 VALUE=STRING”,
“wMinST1||Minimum Strength|TEXT”,
“wHand1|1H,2H,2H Unready|Hands|RADIO|ORIENT=H SELECT=0 VALUE=STRING”,
“wStuck1|0|Can get stuck?|CHECK”

)]

<!– Append the new attack type to the weapon object.  If No Weapon is selected, do not execute. –>

[r, if (wName != “No Weapon”), code:
{
[h: attackStats = “{}”]

[h: attackStats = json.set(attackStats, “Label”, wAttackLabel)]
[h: attackStats = json.set(attackStats, “Skill”, wSkill1)]
[h: attackStats = json.set(attackStats, “DamBase”, wDamBase1)]
[h: attackStats = json.set(attackStats, “DamMod”, wDamMod1)]
[h: attackStats = json.set(attackStats, “DamType”, wDamType1)]
[h: attackStats = json.set(attackStats, “Reach”, wReach1)]
[h: attackStats = json.set(attackStats, “GripChange”, wGripChange1)]
[h: attackStats = json.set(attackStats, “Parry”, wParry1)]
[h: attackStats = json.set(attackStats, “MinST”, wMinST1)]
[h: attackStats = json.set(attackStats, “Hand”, wHand1)]
[h: attackStats = json.set(attackStats, “Stuck”, wStuck1)]

<!– Set the weaponStats string to the single weapon object from the weaponlist2 object –>

[h: weaponStats = json.get(weaponlist2, wName)]

<!– Set the attacks  to the current ones –>

[h: attacks = json.get(weaponStats, “Attacks”)]

<!– Add the Attacks sub-object –>

[h: attacks = json.set(attacks, wAttackLabel, attackStats)]
[h: weaponStats = json.set(weaponStats, “Attacks”, attacks)]

<!– Write the weapon back into the array with the new attack –>

[h: weaponlist2 = json.set(weaponlist2, wName, weaponStats)]
[h: setLibProperty(“WeaponList”, weaponList2, “Lib:Weapons”)]

Attack ‘[r: wAttackLabel]’ added to ‘[r: wName]’.
};
{ No attack added. }]

The new weapon object:

{“Thrusting Broadsword”:{“Name”:”Thrusting Broadsword”, “Weight”:3, “DR”:6, “MaxHP”:12, “Attacks”:{“Swing”:{“Label”:”Swing”, “Skill”:”Broadsword”, “DamBase”:”swing”, “DamMod”:1, “DamType”:”cutting”, “Reach”:1, “GripChange”:0, “Parry”:0, “MinST”:10, “Hand”:”1H”, “Stuck”:0}, “Thrust”:{“Label”:”Thrust”, “Skill”:”Broadsword”, “DamBase”:”thrust”, “DamMod”:2, “DamType”:”impaling”, “Reach”:1, “GripChange”:0, “Parry”:0, “MinST”:10, “Hand”:”1H”, “Stuck”:0}}}}

All pretty good.  Now to figure out what to do with it, and more importantly how to edit this array once it becomes unbelievably long.

<!– Adding a new melee attack to a weapon in the library token. –>

[h: weaponList2 = getLibProperty(“WeaponList”, “Lib:Weapons”)]

<!– The property SkillsMelee on the library token must be defined as a JSON array containing all melee skill names to be used in the campaign. –>

[h: SkillList= json.toList(SkillsMelee)]

<!– Get the existing weapon names for a list with the first weapon being the null selection –>

[h: wWeaponListArray = “[]”]
[h: wWeaponListArray = json.append(wWeaponListArray, “No Weapon”, json.toList(json.fields(WeaponList, “json”)))]
[h: wWeaponNames = json.toList(wWeaponListArray)]

<!– Pick the existing weapon name and define the new attack’s characteristics.
NOTE:  No safeguards against duplicate attack names! –>

[h: newMeleeAttack =
input(
“wName|”+wWeaponNames+”|Weapon Name|LIST|SELECT=0 VALUE=STRING”,

“wAttackLabel||Attack Label|TEXT”,
“wSkill1|”+SkillList+”|Skill Used|LIST|SELECT=0 VALUE=STRING”,
“wDamBase1|none,thrust,swing,static|Damage Base 1|LIST|SELECT=0 VALUE=STRING”,
“wDamMod1|0|Damage Modifier 1 (0/+#/-#/dice expression)|TEXT”,
“wDamType1|crushing,cutting,impaling,pi-,pi,pi+,pi++|Damage Type 1|LIST|SELECT=0 VALUE=STRING”,
“wReach1|0,0-1,1,1-2,1-3,1-4,1-7,2,2-3,4|Reaches (C = 0)|LIST|SELECT=0 VALUE=STRING”,
“wGripChange1|0|Ready Maneuver to Change Grip?|CHECK”,
“wParry1|0,0U,0F,-1,-2U,+2|Parry|LIST|SELECT=0 VALUE=STRING”,
“wMinST1||Minimum Strength|TEXT”,
“wHand1|1H,2H,2H Unready|Hands|RADIO|ORIENT=H SELECT=0 VALUE=STRING”,
“wStuck1|0|Can get stuck?|CHECK”

)]

<!– Append the new attack type to the weapon object.  If No Weapon is selected, do not execute. –>

[r, if (wName != “No Weapon”), code:
{
[h: weaponStats = “{}”]
[h: attackStats = “{}”]

[h: attackStats = json.set(attackStats, “Label”, wAttackLabel)]
[h: attackStats = json.set(attackStats, “Skill”, wSkill1)]
[h: attackStats = json.set(attackStats, “DamBase”, wDamBase1)]
[h: attackStats = json.set(attackStats, “DamMod”, wDamMod1)]
[h: attackStats = json.set(attackStats, “DamType”, wDamType1)]
[h: attackStats = json.set(attackStats, “Reach”, wReach1)]
[h: attackStats = json.set(attackStats, “GripChange”, wGripChange1)]
[h: attackStats = json.set(attackStats, “Parry”, wParry1)]
[h: attackStats = json.set(attackStats, “MinST”, wMinST1)]
[h: attackStats = json.set(attackStats, “Hand”, wHand1)]
[h: attackStats = json.set(attackStats, “Stuck”, wStuck1)]

[h: weaponStats = json.set(weaponStats, wAttackLabel, attackStats)]

[h: weaponList2 = json.set(weaponList2, wName, weaponStats)]

[h: setLibProperty(“WeaponList”, weaponList2, “Lib:Weapons”)]

Attack ‘[r: wAttackLabel]’ added to ‘[r: wName]’.
};
{ No attack added. }]

Leave a Reply

Your email address will not be published. Required fields are marked *