diff --git a/GURPS/gurps.css b/GURPS/gurps.css
index c67e81a9ca..c44f3e7e99 100644
--- a/GURPS/gurps.css
+++ b/GURPS/gurps.css
@@ -3178,7 +3178,8 @@ input[name="attr_toggle_melee_mod_tool"][value="1"] ~ .sheet-attack-modifiers-no
width: 50px;
}
-.sheet-reset input[name="attr_resync_state"][value="clicked"] ~ button.sheet-reset {
+.sheet-reset input[name="attr_resync_state"][value="clicked"] ~ button.sheet-reset,
+.sheet-reset input[name="attr_import_json_state"][value="clicked"] ~ button.sheet-reset {
background-color: gray;
}
@@ -3746,7 +3747,7 @@ input[name="attr_inventory_item_carried"][value="1"] ~ span.sheet-item-weight-to
}
.sheet-spells .sheet-text-college-width {
- width: 185px;
+ width: 184px;
}
/* -- if edit mode, hide toggle notes -- */
@@ -4888,7 +4889,8 @@ input[name="attr_combat_tabs"][value="ranged"] ~ .sheet-tabs .sheet-tabbed-heade
/* Options Tab > sub tabs */
input[name="attr_options_tabs"][value="sheet"] ~ .sheet-tabs.sheet-options > div:nth-of-type(1),
input[name="attr_options_tabs"][value="rules"] ~ .sheet-tabs.sheet-options > div:nth-of-type(2),
-input[name="attr_options_tabs"][value="import"] ~ .sheet-tabs.sheet-options > div:nth-of-type(3) {
+input[name="attr_options_tabs"][value="import"] ~ .sheet-tabs.sheet-options > div:nth-of-type(3),
+input[name="attr_options_tabs"][value="import-json"] ~ .sheet-tabs.sheet-options > div:nth-of-type(4) {
display: block;
}
diff --git a/GURPS/gurps.html b/GURPS/gurps.html
index 1bd92f48a5..94d13030b3 100644
--- a/GURPS/gurps.html
+++ b/GURPS/gurps.html
@@ -4358,12 +4358,25 @@
-
+
@@ -4791,7 +4804,7 @@ Roll at the end of your turn after Do Nothing
@@ -4886,7 +4899,7 @@ Fit +1 to Death Check . Very Fit +2 to Death Check
@@ -7086,13 +7099,13 @@ PU2:126 = Power-Ups 2. Page 126
-
Import Tool [BETA]
+
Import Tool [DEPRACATED]
- Initial version is designed for a one time import. Future iterations will allow re-import and adding GURPS Character Sheet (GCS).
+ Initial version is designed for a one time import.
+ This import is being replaced by a generic json formatted import.
+ See the Import tab.
GCA4 Import
@@ -15611,7 +15662,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
- Reset
+ Reset
@@ -15663,6 +15714,88 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
+
+
+
+
+
Import Tool
+
+
+ Imports a file using data based on a standard json shema for use with the GURPS Roll20 Charactersheet.
+ Exporter tools can be developed for a character generator in this format, instead of
+ creating a special import for each character generator.
+
+
+ Initial version is designed to allow you to re-import your character. Be aware, this will overwrite general notes.
+ Future iterations will check for deleted items and remove them and import notes checkbox. This checkbox will
+ prevent overwriting any notes you may have written on the character sheet.
+
+
+
GCA5
+
+
How to Install
+
+
+ Open GCA5
+ Update GCA5
+
+ Click on Help -> Check for Updates
+ Click on Optional Packages tab
+ Look for Export to Roll20 and check This package is installed
+ Press the OK button to install the plugin.
+
+
+ Enable the Plugin
+
+ Click on Tools -> Plugins...
+ Find the section titled Export Character to Roll20
+ Enable this plugin
+
+
+
+
+
How to export
+
+
+ Open GCA5 and a character
+ Click on File -> Export...
+ Save the character and note where you saved it.
+ Open the file in a text editor, NOT a web browser.
+ Copy the content and paste it into the box to the right.
+
+
+
+
+
+
+
+
JSON DATA
+
+
+
+
+
+
+
+ Reset
+
+
+
+
+ Import
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -17280,9 +17413,9 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
const noop = function () { }; // do nothing callback function.
- const version = "2.8.4";
+ const version = "2.9.0";
- const latestChangesDate = "9/6/2022";
+ const latestChangesDate = "10/12/2022";
let modCascade = true;
@@ -18118,6 +18251,105 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
]);
let rawDefenseNotes = {};
+
+
+ /* -------- async functions -------- */
+ /* see: https://github.com/onyxring/Roll20Async */
+
+ function setActiveCharacterId(charId) {
+ var oldAcid = getActiveCharacterId();
+ var ev = new CustomEvent("message");
+ ev.data = { "id": "0", "type": "setActiveCharacter", "data": charId };
+ self.dispatchEvent(ev);
+ return oldAcid;
+ }
+ var _sIn = setInterval;
+ setInterval = function (callback, timeout) {
+ var acid = getActiveCharacterId();
+ _sIn(
+ function () {
+ var prevAcid = setActiveCharacterId(acid);
+ callback();
+ setActiveCharacterId(prevAcid);
+ }
+ , timeout);
+ }
+ var _sto = setTimeout
+ setTimeout = function (callback, timeout) {
+ var acid = getActiveCharacterId();
+ _sto(
+ function () {
+ var prevAcid = setActiveCharacterId(acid);
+ callback();
+ setActiveCharacterId(prevAcid);
+ }
+ , timeout);
+ }
+ function getAttrsAsync(props) {
+ var acid = getActiveCharacterId(); //save the current activeCharacterID in case it has changed when the promise runs
+ var prevAcid = null; //local variable defined here, because it needs to be shared across the promise callbacks defined below
+ return new Promise((resolve, reject) => {
+ prevAcid = setActiveCharacterId(acid); //in case the activeCharacterId has changed, restore it to what we were expecting and save the current value to restore later
+ try {
+ getAttrs(props, (values) => { resolve(values); });
+ }
+ catch { reject(); }
+ }).finally(() => {
+ setActiveCharacterId(prevAcid); //restore activeCharcterId to what it was when the promise first ran
+ });
+ }
+ //use the same pattern for each of the following...
+ function setAttrsAsync(propObj, options) {
+ var acid = getActiveCharacterId();
+ var prevAcid = null;
+ return new Promise((resolve, reject) => {
+ prevAcid = setActiveCharacterId(acid);
+ try {
+ setAttrs(propObj, options, (values) => { resolve(values); });
+ }
+ catch { reject(); }
+ }).finally(() => {
+ setActiveCharacterId(prevAcid);
+ });
+ }
+
+ function getSectionIDsAsync(sectionName) {
+ var acid = getActiveCharacterId();
+ var prevAcid = null;
+ return new Promise((resolve, reject) => {
+ prevAcid = setActiveCharacterId(acid);
+ try {
+ getSectionIDs(sectionName, (values) => { resolve(values); });
+ }
+ catch { reject(); }
+ }).finally(() => {
+ setActiveCharacterId(prevAcid);
+ });
+ }
+ function getSingleAttrAsync(prop) {
+ var acid = getActiveCharacterId();
+ var prevAcid = null;
+ return new Promise((resolve, reject) => {
+ prevAcid = setActiveCharacterId(acid);
+ try {
+ getAttrs([prop], (values) => { resolve(values[prop]); });
+ }
+ catch { reject(); }
+ }).finally(() => {
+ setActiveCharacterId(prevAcid);
+ });
+ }
+
+ /**
+ * Async foreach.
+ * see: https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404
+ */
+ async function asyncForEach(array, callback) {
+ for (let index = 0; index < array.length; index++) {
+ await callback(array[index], index, array);
+ }
+ }
+ /*------------------*/
const styleCount = 9; // THIS NUMBER MUST BE EQUAL TO THE NUMBER OF COLOR SETTINGS
on("change:sheetstyle sheet:opened", function (event) {
@@ -19246,7 +19478,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
});
- updateRepeatingSkillValues = () => {
+ let updateRepeatingSkillValues = () => {
let fieldValues = [
"repeating_skills_name", //for debugging
@@ -19379,7 +19611,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
});
- updateRepeatingSpellValues = () => {
+ let updateRepeatingSpellValues = () => {
let fieldValues = [
"repeating_spells_base",
@@ -21518,7 +21750,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
* Function to make sure the repeating_ranged_{id}_mal_max_value is set
* during a new version load or possible future reset button
*/
- setRangedMaxMalfunctionValues = () => {
+ let setRangedMaxMalfunctionValues = () => {
getSectionIDs("repeating_ranged", (ids) => {
@@ -29121,14 +29353,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
let uniqueKeys = {};
importCharacterSheetWithGCA(uniqueKeys, jsonData, importNotes);
-
- // uniqueKeys is passed by reference. Gets updated while reading each repeating table.
- // getUniqueKeysForSheet(uniqueKeys, () => {
- //
- // importCharacterSheetWithGCA(uniqueKeys, jsonData, importNotes);
-
- // });
-
+
} else {
@@ -29189,144 +29414,6 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
return true;
}
- /**
- * Get all the unique keys and associated row ids.
- * This allows us to update existing rows instead of inserting new ones
- *
- * @param {object} uniqueKeys Key values pairs for unique idkey and associated row id. Passed by reference
- * @param {() => void} callback Function to run after we're done getting data
- */
- function getUniqueKeysForSheet(uniqueKeys, callback) {
-
- // make sure we have a valid function
- callback = callback || noop;
-
- // sorry about this
- getUniqueKeysForTable("repeating_languages", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_cultures", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_traits", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_perks", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_quirks", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_disadvantages", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_racial", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_skills", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_techniquesrevised", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_defense", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_melee", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_ranged", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_item", uniqueKeys, () => {
-
- getUniqueKeysForTable("repeating_spells", uniqueKeys, () => {
-
- // finally return! Sorry1
- callback();
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- });
-
- }
-
- /**
- * Get unique idkey and associated row id for a table
- *
- * @param {string} table Name of repeating table
- * @param {object} uniqueKeys Key values pairs for unique idkey and associated row id. Passed by reference
- * @param {() => void} callback Function to run after we're done getting data
- */
- function getUniqueKeysForTable(table, uniqueKeys, callback) {
-
- // make sure we have a valid function
- callback = callback || noop;
-
- getSectionIDs(table, (ids) => {
-
- if (ids.length === 0) {
- callback();
- return;
- }
-
- // get the idkey for each row.
- let fields = [];
-
- for (let i = 0; i < ids.length; i++) {
-
- fields.push(`${table}_${ids[i]}_idkey`);
-
- }
-
- getAttrs(fields, values => {
-
- // loop through each row
- for (let key in values) {
-
- let idkey;
-
- let rowId;
-
- if (values.hasOwnProperty(key)) {
-
- idkey = values[key];
-
- // get row id from the key name
- // example: repeating_melee_KEYHERE_idkey
- rowId = getRowIdFromRowFieldKey(key, table);
-
- if (idkey && rowId) {
-
- // add new key/value pair!
- uniqueKeys[idkey] = rowId;
-
- }
-
- }
-
- }
-
- });
-
- });
-
- callback();
-
- }
-
/**
* Start processing GCA json data and update character sheet
*
@@ -33710,7 +33797,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
});
- resetResyncButtonSate = () => {
+ let resetResyncButtonSate = () => {
setTimeout(() => {
@@ -33724,7 +33811,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
* Loop through each skill, set sync field = 1 (true)
* this forces the skill to recalculate the value.
*/
- resyncRepeatingSkills = () => {
+ let resyncRepeatingSkills = () => {
getSectionIDs("repeating_skills", ids => {
@@ -33757,7 +33844,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
* Loop through each technique, set sync field = 1 (true)
* this forces the technique to recalculate the value.
*/
- resyncRepeatingTechniques = () => {
+ let resyncRepeatingTechniques = () => {
getSectionIDs("repeating_techniquesrevised", ids => {
@@ -33788,7 +33875,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
* Recalculate the weight and value of all items.
* Should NOT be run silent, so the totals can be calculated
*/
- resyncRepeatingItems = () => {
+ let resyncRepeatingItems = () => {
getSectionIDs("repeating_item", ids => {
@@ -33841,7 +33928,7 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
* Loop through each spell, set sync field = 1 (true)
* this forces the spell to recalculate the value.
*/
- resyncRepeatingSpells = () => {
+ let resyncRepeatingSpells = () => {
getSectionIDs("repeating_spells", ids => {
@@ -33869,91 +33956,889 @@ Diffuse: Max 2HP (Exception: Area-effect, cone, and explosion attacks cause norm
}
- /* async functions */
- /* see: https://github.com/onyxring/Roll20Async */
+ // close roll modifiers, no updates
+ on("clicked:import_json", async (event) => {
+
+ let attribs = {
+ import_json_state: "clicked",
+ import_json_message: "Processing..."
+ };
- function setActiveCharacterId(charId) {
- var oldAcid = getActiveCharacterId();
- var ev = new CustomEvent("message");
- ev.data = { "id": "0", "type": "setActiveCharacter", "data": charId };
- self.dispatchEvent(ev);
- return oldAcid;
- }
- var _sIn = setInterval;
- setInterval = function (callback, timeout) {
- var acid = getActiveCharacterId();
- _sIn(
- function () {
- var prevAcid = setActiveCharacterId(acid);
- callback();
- setActiveCharacterId(prevAcid);
- }
- , timeout);
- }
- var _sto = setTimeout
- setTimeout = function (callback, timeout) {
- var acid = getActiveCharacterId();
- _sto(
- function () {
- var prevAcid = setActiveCharacterId(acid);
- callback();
- setActiveCharacterId(prevAcid);
- }
- , timeout);
- }
- function getAttrsAsync(props) {
- var acid = getActiveCharacterId(); //save the current activeCharacterID in case it has changed when the promise runs
- var prevAcid = null; //local variable defined here, because it needs to be shared across the promise callbacks defined below
- return new Promise((resolve, reject) => {
- prevAcid = setActiveCharacterId(acid); //in case the activeCharacterId has changed, restore it to what we were expecting and save the current value to restore later
- try {
- getAttrs(props, (values) => { resolve(values); });
- }
- catch { reject(); }
- }).finally(() => {
- setActiveCharacterId(prevAcid); //restore activeCharcterId to what it was when the promise first ran
- });
- }
- //use the same pattern for each of the following...
- function setAttrsAsync(propObj, options) {
- var acid = getActiveCharacterId();
- var prevAcid = null;
- return new Promise((resolve, reject) => {
- prevAcid = setActiveCharacterId(acid);
- try {
- setAttrs(propObj, options, (values) => { resolve(values); });
- }
- catch { reject(); }
- }).finally(() => {
- setActiveCharacterId(prevAcid);
- });
- }
+ await setAttrsAsync(attribs);
- function getSectionIDsAsync(sectionName) {
- var acid = getActiveCharacterId();
- var prevAcid = null;
- return new Promise((resolve, reject) => {
- prevAcid = setActiveCharacterId(acid);
- try {
- getSectionIDs(sectionName, (values) => { resolve(values); });
- }
- catch { reject(); }
- }).finally(() => {
- setActiveCharacterId(prevAcid);
- });
- }
- function getSingleAttrAsync(prop) {
- var acid = getActiveCharacterId();
- var prevAcid = null;
- return new Promise((resolve, reject) => {
- prevAcid = setActiveCharacterId(acid);
- try {
- getAttrs([prop], (values) => { resolve(values[prop]); });
- }
- catch { reject(); }
- }).finally(() => {
- setActiveCharacterId(prevAcid);
- });
- }
+ await importCharacterJson();
+
+
+ });
+
+ on("clicked:import_json_reset", (event) => {
+
+ setAttrs({
+ import_json_state: "normal",
+ import_json_message: "Start Import",
+ character_json_data: ""
+ });
+
+ });
+
+ let importCharacterJson = async () => {
+
+ let values = await getAttrsAsync(["character_json_data"]);
+
+ let data = String(values.character_json_data).trim();
+
+ let success = true;
+
+ let message = "";
+
+ // schema file
+ let character;
+
+ if (data) {
+
+ try {
+
+ character = JSON.parse(data);
+
+ } catch (ex) {
+
+ success = false;
+
+ message = "Invalid JSON Data. " + ex.message;
+
+ }
+ } else {
+
+ success = false;
+
+ message = "Please copy/paste JSON Data into text area.";
+
+ }
+
+ if (success) {
+
+ // TODO: figure out async/await
+ let uniqueKeys = await getUniqueKeysForCharacter();
+
+ await importAttributes(character);
+
+ await importRepeatingLanguages(character, uniqueKeys);
+
+ await importRepeatingCultures(character, uniqueKeys);
+
+ await importRepeatingTraits(character, uniqueKeys);
+
+ await importRepeatingPerks(character, uniqueKeys);
+
+ await importRepeatingQuirks(character, uniqueKeys);
+
+ await importRepeatingDisadvantages(character, uniqueKeys);
+
+ await importRepeatingRacial(character, uniqueKeys);
+
+ await importRepeatingSkills(character, uniqueKeys);
+
+ await importRepeatingTechniquesrevised(character, uniqueKeys);
+
+ await importRepeatingDefense(character, uniqueKeys);
+
+ await importRepeatingMelee(character, uniqueKeys);
+
+ await importRepeatingRanged(character, uniqueKeys);
+
+ await importRepeatingItem(character, uniqueKeys);
+
+ await importRepeatingSpells(character, uniqueKeys);
+
+ // very last attribute to get updated
+ const applyCombatReflexes = character.CombatReflexes ? "1" : "0";
+
+ await setAttrsAsync({combat_reflexes: applyCombatReflexes});
+
+ setAttrs({
+ import_json_state: "normal",
+ import_json_message: "Import has completed!",
+ character_json_data: ""
+ });
+
+ } else {
+
+ setAttrs({ "import_json_message": message });
+
+ }
+
+ }
+
+ let getUniqueKeysForCharacter = async () => {
+
+ let uniqueKeys = {};
+
+ await getUniqueKeysByTableAsync("repeating_languages", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_cultures", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_traits", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_perks", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_quirks", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_disadvantages", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_racial", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_skills", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_techniquesrevised", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_defense", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_melee", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_ranged", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_item", uniqueKeys);
+
+ await getUniqueKeysByTableAsync("repeating_spells", uniqueKeys);
+
+ return uniqueKeys;
+
+ }
+
+ let getUniqueKeysByTableAsync = async (table, uniqueKeys) => {
+
+ let ids = await getSectionIDsAsync(table);
+
+ if (ids.length === 0) {
+ return;
+ }
+
+ // get the idkey for each row.
+ let fields = [];
+
+ for (let i = 0; i < ids.length; i++) {
+
+ fields.push(`${table}_${ids[i]}_idkey`);
+
+ }
+
+ let values = await getAttrsAsync(fields);
+
+ // loop through each row
+ for (let key in values) {
+
+ let idkey;
+
+ let rowId;
+
+ if (values.hasOwnProperty(key)) {
+
+ idkey = values[key];
+
+ // get row id from the key name
+ // example: repeating_melee_KEYHERE_idkey
+ rowId = getRowIdFromRowFieldKey(key, table);
+
+ if (idkey && rowId) {
+
+ // add new key/value pair!
+ uniqueKeys[idkey] = rowId;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ let importAttributes = async (character) => {
+
+ const applySizeModifier = character.ApplySizeModifier ? "1" : "0";
+ const flightChecked = character.FlightChecked ? "1" : "0";
+ const amphibiousChecked = character.AmphibiousChecked ? "1" : "0";
+
+ const baseAttributes = {
+ fullname: character.CharacterName,
+ playername: character.Playername,
+ nickname: character.Nickname,
+ race: character.Race,
+ gender: character.Gender,
+ size: parseInt(character.Size),
+ apply_size_modifier: applySizeModifier,
+ reactions: character.Reactions,
+ campaign_tl: parseInt(character.CampaignTl),
+ tl: parseInt(character.Tl),
+ tl_pts: parseInt(character.TlPts),
+ status: character.Status,
+ wealth: character.Wealth,
+ income: character.Income,
+ cost_of_living: character.CostOfLiving,
+ stash: character.Stash,
+ age: character.Age,
+ height: character.Height,
+ weight: parseFloat(character.Weight),
+ appearance: parseInt(character.Appearance),
+ general_appearance: character.GeneralAppearance,
+ strength_points: parseInt(character.StrengthPoints),
+ dexterity_points: parseInt(character.DexterityPoints),
+ intelligence_points: parseInt(character.IntelligencePoints),
+ health_points: parseInt(character.HealthPoints)
+ };
+
+ const baseAttributeMods = {
+ strength_mod: parseInt(character.StrengthMod),
+ dexterity_mod: parseInt(character.DexterityMod),
+ intelligence_mod: parseInt(character.IntelligenceMod),
+ health_mod: parseInt(character.HealthMod),
+ };
+
+ const secondaryAttributesPoints = {
+ perception_points: parseInt(character.PerceptionPoints),
+ vision_points: parseInt(character.VisionPoints),
+ hearing_points: parseInt(character.HearingPoints),
+ taste_smell_points: parseInt(character.TasteSmellPoints),
+ touch_points: parseInt(character.TouchPoints),
+ willpower_points: parseInt(character.WillpowerPoints),
+ fear_check_points: parseInt(character.FearCheckPoints),
+ unconscious_check_points: parseInt(character.UnconsciousCheckPoints),
+ death_check_points: parseInt(character.death_check_points),
+ basic_speed_points: parseInt(character.BasicSpeedPoints),
+ basic_move_points: parseInt(character.BasicMovePoints),
+ enhanced_ground_move_points: parseInt(character.EnhancedGroundMovePoints),
+ lift_st_points: parseInt(character.LiftStPoints),
+ striking_st_points: parseInt(character.StrikingStPoints),
+ hit_points_points: parseInt(character.HitPointsPoints),
+ hit_points: parseInt(character.HitPoints),
+ fatigue_points_points: parseInt(character.FatiguePointsPoints),
+ fatigue_points: parseInt(character.FatiguePoints),
+ flight_checked: flightChecked,
+ flight_points: parseInt(character.FlightPoints),
+ basic_air_move_points: parseInt(character.BasicAirMovePoints),
+ enhanced_air_move_points: parseInt(character.EnhancedAirMovePoints),
+ amphibious_checked: amphibiousChecked,
+ amphibious_points: parseInt(character.AmphibiousPoints),
+ basic_water_move_points: parseInt(character.BasicWaterMovePoints),
+ enhanced_water_move_points: parseInt(character.EnhancedWaterMovePoints),
+ super_jump_points: parseInt(character.SuperJumpPoints)
+ };
+
+ const secondaryAttributesMods = {
+ perception_mod: parseInt(character.PerceptionMod),
+ vision_mod: parseInt(character.VisionMod),
+ hearing_mod: parseInt(character.HearingMod),
+ taste_smell_mod: parseInt(character.TasteSmellMod),
+ touch_mod: parseInt(character.TouchMod),
+ willpower_mod: parseInt(character.WillpowerMod),
+ fear_check_mod: parseInt(character.FearCheckMod),
+ stun_check_mod: parseInt(character.StunCheckMod),
+ knockdown_check_mod: parseInt(character.KnockdownCheckMod),
+ unconscious_check_mod: parseInt(character.UnconsciousCheckMod),
+ death_check_mod: parseInt(character.DeathCheckMod),
+ basic_speed_mod: Number(character.BasicSpeedMod),
+ basic_move_mod: parseInt(character.BasicMoveMod),
+ enhanced_ground_move_mod: Number(character.EnhancedGroundMoveMod),
+ dodge_mod: parseInt(character.DodgeMod),
+ lift_st_mod: parseInt(character.LiftStMod),
+ striking_st_mod: parseInt(character.StrikingStMod),
+ hit_points_mod: parseInt(character.HitPointsMod),
+ fatigue_points_mod: parseInt(character.FatiguePointsMod),
+ basic_air_move_mod: parseInt(character.BasicAirMoveMod),
+ enhanced_air_level: Number(character.EnhancedAirLevel),
+ basic_water_move_mod: parseInt(character.BasicWaterMoveMod),
+ enhanced_water_level: Number(character.EnhancedWaterLevel),
+ super_jump_entered_level: parseInt(character.SuperJumpEnteredLevel),
+ spell_bonus: parseInt(character.SpellBonus)
+ };
+
+ await setAttrsAsync(baseAttributes);
+
+ await setAttrsAsync(baseAttributeMods);
+
+ await setAttrsAsync(secondaryAttributesPoints);
+
+ await setAttrsAsync(secondaryAttributesMods);
+
+ }
+
+ let importRepeatingLanguages = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingLanguages, async (language) => {
+
+ let attributes = {};
+
+ if (language.IsNative) {
+
+ // use the non-repeating native language
+ attributes["native_language_idkey"] = language.Idkey;
+
+ attributes["name_native_language"] = language.Name;
+
+ attributes["native_language_spoken"] = parseInt(language.Spoken);
+
+ attributes["native_language_written"] = parseInt(language.Written);
+
+ } else {
+
+ let rowId = generateOrGetRowId(uniqueKeys, language.Idkey);
+
+ let baseFieldName = `repeating_languages_${rowId}`;
+
+ attributes[`${baseFieldName}_idkey`] = language.Idkey;
+
+ attributes[`${baseFieldName}_name`] = language.Name;
+
+ attributes[`${baseFieldName}_spoken`] = parseInt(language.Spoken);
+
+ attributes[`${baseFieldName}_written`] = parseInt(language.Written);
+
+ }
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingCultures = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingCultures, async (culture) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, culture.Idkey);
+
+ let baseFieldName = `repeating_cultures_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = culture.Idkey;
+
+ attributes[`${baseFieldName}_name`] = culture.Name;
+
+ attributes[`${baseFieldName}_points`] = parseInt(culture.Points);
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingTraits = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingTraits, async (trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_traits_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_trait_level`] = trait.TraitLevel;
+
+ attributes[`${baseFieldName}_foa`] = trait.Foa;
+
+ attributes[`${baseFieldName}_points`] = parseInt(trait.Points);
+
+ attributes[`${baseFieldName}_ref`] = trait.Ref;
+
+ attributes[`${baseFieldName}_notes`] = trait.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingPerks = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingPerks, async (trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_perks_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_foa`] = trait.Foa;
+
+ attributes[`${baseFieldName}_points`] = parseInt(trait.Points);
+
+ attributes[`${baseFieldName}_ref`] = trait.Ref;
+
+ attributes[`${baseFieldName}_notes`] = trait.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingQuirks = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingQuirks, async (trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_quirks_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_control_rating`] = trait.ControlRating;
+
+ attributes[`${baseFieldName}_points`] = parseInt(trait.Points);
+
+ attributes[`${baseFieldName}_ref`] = trait.Ref;
+
+ attributes[`${baseFieldName}_notes`] = trait.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingDisadvantages = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingDisadvantages, async(trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_disadvantages_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_trait_level`] = trait.TraitLevel;
+
+ attributes[`${baseFieldName}_control_rating`] = trait.ControlRating;
+
+ attributes[`${baseFieldName}_points`] = parseInt(trait.Points);
+
+ attributes[`${baseFieldName}_ref`] = trait.Ref;
+
+ attributes[`${baseFieldName}_notes`] = trait.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingRacial = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingRacial, async (trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_racial_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_trait_level`] = trait.TraitLevel;
+
+ attributes[`${baseFieldName}_control_rating`] = trait.ControlRating;
+
+ attributes[`${baseFieldName}_points`] = parseInt(trait.Points);
+
+ attributes[`${baseFieldName}_ref`] = trait.Ref;
+
+ attributes[`${baseFieldName}_notes`] = trait.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingSkills = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingSkills, async (skill) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, skill.Idkey);
+
+ let baseFieldName = `repeating_skills_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = skill.Idkey;
+
+ attributes[`${baseFieldName}_name`] = skill.Name;
+
+ attributes[`${baseFieldName}_tl`] = skill.Tl;
+
+ attributes[`${baseFieldName}_base`] = skill.Base;
+
+ attributes[`${baseFieldName}_difficulty`] = getSKillDifficultyValue(skill.Difficulty);
+
+ attributes[`${baseFieldName}_bonus`] = parseInt(skill.Bonus);
+
+ attributes[`${baseFieldName}_points`] = parseInt(skill.Points);
+
+ attributes[`${baseFieldName}_ref`] = skill.Ref;
+
+ attributes[`${baseFieldName}_skill_mod_notes`] = skill.SkillModNotes;
+
+ attributes[`${baseFieldName}_notes`] = skill.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ /**
+ * Converts difficulty name to a number
+ * TODO: checks for wildcard!
+ */
+ let getSKillDifficultyValue = difficulty => {
+
+ let difficultyValue = "-1";
+
+ switch (difficulty) {
+
+ case "A":
+ difficultyValue = "-2";
+ break;
+
+ case "H":
+ difficultyValue = "-3";
+ break;
+
+ case "VH":
+ difficultyValue = "-4";
+ break;
+
+ case "WC":
+ difficultyValue = "-5 + 1";
+ break;
+
+ case "E":
+ default:
+ difficultyValue = "-1";
+ break;
+ }
+
+ return difficultyValue;
+
+ }
+
+ let importRepeatingTechniquesrevised = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingTechniquesrevised, async (skill) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, skill.Idkey);
+
+ let baseFieldName = `repeating_techniquesrevised_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = skill.Idkey;
+
+ attributes[`${baseFieldName}_name`] = skill.Name;
+
+ attributes[`${baseFieldName}_parent`] = skill.Parent;
+
+ attributes[`${baseFieldName}_base_level`] = skill.BaseLevel;
+
+ attributes[`${baseFieldName}_default`] = parseInt(skill.Default);
+
+ attributes[`${baseFieldName}_max_modifier`] = parseInt(skill.MaxModifier);
+
+ attributes[`${baseFieldName}_difficulty`] = getTechniqueDifficultyValue(skill.Difficulty);
+
+ attributes[`${baseFieldName}_skill_modifier`] = parseInt(skill.SkillModifier);
+
+ attributes[`${baseFieldName}_points`] = parseInt(skill.Points);
+
+ attributes[`${baseFieldName}_ref`] = skill.Ref;
+
+ attributes[`${baseFieldName}_skill_mod_notes`] = skill.SkillModNotes;
+
+ attributes[`${baseFieldName}_notes`] = skill.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let getTechniqueDifficultyValue = difficulty => {
+
+ let difficultyValue = "Average";
+
+ switch (difficulty) {
+
+ case "H":
+ difficultyValue = "Hard";
+ break;
+
+ case "A":
+ default:
+ difficultyValue = "Average";
+ break;
+ }
+
+ return difficultyValue;
+
+ }
+
+ let importRepeatingDefense = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingDefense, async (trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_defense_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_type`] = trait.Type;
+
+ attributes[`${baseFieldName}_info`] = trait.Info;
+
+ attributes[`${baseFieldName}_skill`] = parseInt(trait.Skill);
+
+ attributes[`${baseFieldName}_skill_mod`] = parseInt(trait.SkillMod);
+
+ attributes[`${baseFieldName}_defense_mod_reason`] = trait.DefenseModReason;
+
+ attributes[`${baseFieldName}_info_description`] = trait.InfoDescription;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ /**
+ * Will convert variable die rolls to Roll20 macro prompt
+ * if it starts with ~, then add macro to allow user to enter number of dice to roll
+ */
+ let getDamageDieMacro = (damageDie) => {
+
+ let dieRoll = damageDie;
+
+ if (damageDie && damageDie.includes("~")) {
+
+ // example: ~1d+1
+ // remove ~
+ damageDie = damageDie.replace("~", "");
+
+ // array = [1, +1]
+ let arrDamageDie = damageDie.split("d");
+
+ let baseDie = 1;
+
+ let dieModifier = "0";
+
+ if (arrDamageDie.length === 1) {
+
+ baseDie = arrDamageDie[0];
+
+ } else if (arrDamageDie.length === 2) {
+
+ baseDie = arrDamageDie[0];
+
+ dieModifier = arrDamageDie[0];
+
+ }
+
+ dieRoll = getNumberOfDicePrompt(baseDie, Number(dieModifier), 12);
+
+ }
+
+ return dieRoll;
+
+ }
+
+ let importRepeatingMelee = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingMelee, async (trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_melee_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_damage`] = getDamageDieMacro(trait.Damage);
+
+ attributes[`${baseFieldName}_type`] = getDamageTypeFromGca(trait.Type);
+
+ attributes[`${baseFieldName}_reach`] = trait.Reach;
+
+ attributes[`${baseFieldName}_skill`] = parseInt(trait.Skill);
+
+ attributes[`${baseFieldName}_armor_divisor`] = Number(trait.ArmorDivisor);
+
+ attributes[`${baseFieldName}_notes`] = trait.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingRanged = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingRanged, async (trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_ranged_${rowId}`;
+
+ const malfunctionVerify = trait.MalfunctionVerify ? "1" : "0";
+
+ const malfunctionVeryReliable = trait.MalfunctionVeryReliable ? "1" : "0";
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_damage`] = getDamageDieMacro(trait.Damage);
+
+ attributes[`${baseFieldName}_type`] = getDamageTypeFromGca(trait.Type);
+
+ attributes[`${baseFieldName}_acc`] = trait.Acc;
+
+ attributes[`${baseFieldName}_range`] = trait.Range;
+
+ attributes[`${baseFieldName}_rof`] = trait.Rof;
+
+ attributes[`${baseFieldName}_shots`] = trait.Shots;
+
+ attributes[`${baseFieldName}_bulk`] = trait.Bulk;
+
+ attributes[`${baseFieldName}_recoil`] = trait.Recoil;
+
+ attributes[`${baseFieldName}_skill`] = parseInt(trait.Skill);
+
+ attributes[`${baseFieldName}_malfunction`] = trait.Malfunction;
+
+ attributes[`${baseFieldName}_malfunction_verify`] = malfunctionVerify;
+
+ attributes[`${baseFieldName}_malfunction_very_reliable`] = malfunctionVeryReliable;
+
+ attributes[`${baseFieldName}_armor_divisor`] = Number(trait.ArmorDivisor);
+
+ attributes[`${baseFieldName}_notes`] = trait.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingItem = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingItem, async (trait) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, trait.Idkey);
+
+ let baseFieldName = `repeating_item_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = trait.Idkey;
+
+ attributes[`${baseFieldName}_name`] = trait.Name;
+
+ attributes[`${baseFieldName}_tl`] = trait.Tl;
+
+ attributes[`${baseFieldName}_legality_class`] = trait.LegalityClass;
+
+ attributes[`${baseFieldName}_ref`] = trait.Ref;
+
+ attributes[`${baseFieldName}_count`] = parseInt(trait.Count);
+
+ attributes[`${baseFieldName}_cost`] = Number(trait.Cost);
+
+ attributes[`${baseFieldName}_weight`] = Number(trait.Weight);
+
+ attributes[`${baseFieldName}_notes`] = trait.Notes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
+
+ let importRepeatingSpells = async (character, uniqueKeys) => {
+
+ await asyncForEach(character.RepeatingSpells, async (skill) => {
+
+ let rowId = generateOrGetRowId(uniqueKeys, skill.Idkey);
+
+ let baseFieldName = `repeating_spells_${rowId}`;
+
+ let attributes = {};
+
+ attributes[`${baseFieldName}_idkey`] = skill.Idkey;
+
+ attributes[`${baseFieldName}_name`] = skill.Name;
+
+ attributes[`${baseFieldName}_difficulty`] = getSKillDifficultyValue(skill.Difficulty);
+
+ attributes[`${baseFieldName}_spell_modifier`] = parseInt(skill.SpellModifier);
+
+ attributes[`${baseFieldName}_points`] = parseInt(skill.Points);
+
+ attributes[`${baseFieldName}_spell_resisted_by`] = skill.SpellResistedBy;
+
+ attributes[`${baseFieldName}_duration`] = skill.Duration;
+
+ attributes[`${baseFieldName}_cost`] = skill.Cost;
+
+ attributes[`${baseFieldName}_ref`] = skill.Ref;
+
+ attributes[`${baseFieldName}_ref`] = skill.Ref;
+
+ attributes[`${baseFieldName}_casttime`] = skill.Casttime;
+
+ attributes[`${baseFieldName}_maintain`] = skill.Maintain;
+
+ attributes[`${baseFieldName}_spell_class`] = skill.SpellClass;
+
+ attributes[`${baseFieldName}_spell_college`] = skill.SpellCollege;
+
+ attributes[`${baseFieldName}_spell_college_secondary`] = skill.SpellCollegeSecondary;
+
+ attributes[`${baseFieldName}_spell_mod_notes`] = skill.SpellModNotes;
+
+ attributes[`${baseFieldName}_notes`] = skill.SpellNotes;
+
+ await setAttrsAsync(attributes);
+
+ });
+
+ }
diff --git a/GURPS/readme/assets/Artillery Mage (NPC) export.json b/GURPS/readme/assets/Artillery Mage (NPC) export.json
new file mode 100644
index 0000000000..c927e64e93
--- /dev/null
+++ b/GURPS/readme/assets/Artillery Mage (NPC) export.json
@@ -0,0 +1,1077 @@
+{
+ "CharacterName": "Artillery Mage",
+ "Fullname": "Artillery Mage (NPC)",
+ "Playername": "NPC",
+ "Nickname": "",
+ "Race": "Human",
+ "RaceRef": "",
+ "TemplateNames": "",
+ "Gender": "",
+ "Size": 0.0,
+ "ApplySizeModifier": false,
+ "Reactions": "",
+ "CampaignTl": 3.0,
+ "TotalPoints": 250.0,
+ "Tl": 3.0,
+ "TlPts": 0.0,
+ "Status": "1",
+ "Wealth": "Comfortable",
+ "Income": 1400.0,
+ "CostOfLiving": 1200.0,
+ "Stash": 1135.0,
+ "Age": "",
+ "Height": "",
+ "Weight": 0.0,
+ "Appearance": 0.0,
+ "GeneralAppearance": "",
+ "StrengthMod": 0.0,
+ "StrengthPoints": -10.0,
+ "DexterityMod": 0.0,
+ "DexterityPoints": 0.0,
+ "IntelligenceMod": 0.0,
+ "IntelligencePoints": 60.0,
+ "HealthMod": 0.0,
+ "HealthPoints": 0.0,
+ "PerceptionMod": 0.0,
+ "PerceptionPoints": 0.0,
+ "VisionMod": 0.0,
+ "VisionPoints": 0.0,
+ "HearingMod": 0.0,
+ "HearingPoints": 0.0,
+ "TasteSmellMod": 0.0,
+ "TasteSmellPoints": 0.0,
+ "TouchMod": 0.0,
+ "TouchPoints": 0.0,
+ "WillpowerMod": 0.0,
+ "WillpowerPoints": 0.0,
+ "FearCheckMod": 0.0,
+ "FearCheckPoints": 0.0,
+ "StunCheckMod": 0.0,
+ "KnockdownCheckMod": 0.0,
+ "UnconsciousCheckMod": 0.0,
+ "UnconsciousCheckPoints": 0.0,
+ "DeathCheckMod": 0.0,
+ "DeathCheckPoints": 0.0,
+ "BasicSpeedMod": 0.0,
+ "BasicSpeedPoints": 0.0,
+ "BasicMoveMod": 0.0,
+ "BasicMovePoints": 0.0,
+ "EnhancedGroundMoveMod": 0.0,
+ "EnhancedGroundMovePoints": 0.0,
+ "DodgeMod": 0.0,
+ "LiftStMod": 0.0,
+ "LiftStPoints": 0.0,
+ "StrikingStMod": 0.0,
+ "StrikingStPoints": 0.0,
+ "HitPointsMod": 0.0,
+ "HitPointsPoints": 0.0,
+ "HitPoints": 9.0,
+ "FatiguePointsMod": 0.0,
+ "FatiguePointsPoints": 0.0,
+ "FatiguePoints": 10.0,
+ "FlightChecked": false,
+ "FlightPoints": 0.0,
+ "BasicAirMoveMod": 0.0,
+ "BasicAirMovePoints": 0.0,
+ "EnhancedAirLevel": 0.0,
+ "EnhancedAirMovePoints": 0.0,
+ "AmphibiousChecked": false,
+ "AmphibiousPoints": 0.0,
+ "BasicWaterMoveMod": 0.0,
+ "BasicWaterMovePoints": 0.0,
+ "EnhancedWaterLevel": 0.0,
+ "EnhancedWaterMovePoints": 0.0,
+ "SuperJumpEnteredLevel": 0.0,
+ "SuperJumpPoints": 0.0,
+ "SpellBonus": 3.0,
+ "CombatReflexes": false,
+ "RepeatingLanguages": [
+ {
+ "Idkey": "13362",
+ "Name": "Common",
+ "Spoken": 0.0,
+ "Written": 0.0,
+ "IsNative": true
+ }
+ ],
+ "RepeatingCultures": [
+ {
+ "Idkey": "13364",
+ "Name": "Western",
+ "Points": 1.0
+ }
+ ],
+ "RepeatingTraits": [
+ {
+ "Idkey": "186",
+ "Name": "Energy Reserve (Magical)",
+ "TraitLevel": "3",
+ "Foa": "",
+ "Points": 9.0,
+ "Ref": "P119",
+ "Notes": "Magical"
+ },
+ {
+ "Idkey": "184",
+ "Name": "Magery",
+ "TraitLevel": "3",
+ "Foa": "",
+ "Points": 30.0,
+ "Ref": "B66",
+ "Notes": "WARNING: Always use the Magery modifiers with Magery and the Magery 0 modifiers with Magery 0. Using the Magery modifiers with any other trait can cause your spells to be miscalculated. For standard magic use Magery, for Ritual Magic use Ritual Magery, for Wildcard! magic use Wildcard Magery!, for Clerical Magic use Power Investiture, for Syntactic magic use Syntactic Magery, For standard magic use Magery; for Ritual Magic use Ritual Magery; for Wildcard! Magic use Wildcard Magery!; for Clerical Magic use Power Investiture."
+ },
+ {
+ "Idkey": "185",
+ "Name": "Magery 0",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B66",
+ "Notes": "Magery 0 is included as a separate item from the normal Magery advantage, due to the fact that many kinds of enhancements and limitations are meant to only affect the levels above 0, not the base 5 points from Magery 0. The Magery advantage is set to have Magery 0 as a pre-req. WARNING: Always use the Magery modifiers with Magery and the Magery 0 modifiers with Magery 0. Using the Magery modifiers with any other item can cause your spells to be miscalculated."
+ },
+ {
+ "Idkey": "231",
+ "Name": "Status",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B28",
+ "Notes": "+1"
+ },
+ {
+ "Idkey": "232",
+ "Name": "Wealth",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 10.0,
+ "Ref": "B25",
+ "Notes": "Comfortable"
+ }
+ ],
+ "RepeatingPerks": [],
+ "RepeatingQuirks": [],
+ "RepeatingDisadvantages": [
+ {
+ "Idkey": "233",
+ "Name": "Loner",
+ "TraitLevel": "1",
+ "ControlRating": "12",
+ "Points": -5.0,
+ "Ref": "B142",
+ "Notes": "12 or less, *1"
+ }
+ ],
+ "RepeatingRacial": [],
+ "RepeatingSkills": [
+ {
+ "Idkey": "187",
+ "Name": "Innate Attack (Projectile)",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 8.0,
+ "Skill": 13.0,
+ "Ref": "B201",
+ "SkillModNotes": "",
+ "Notes": "Projectile"
+ },
+ {
+ "Idkey": "188",
+ "Name": "Staff",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 4.0,
+ "Skill": 11.0,
+ "Ref": "B208",
+ "SkillModNotes": "",
+ "Notes": ""
+ }
+ ],
+ "RepeatingTechniquesrevised": [],
+ "RepeatingDefense": [
+ {
+ "Idkey": "128_unarmed_parry",
+ "Name": "Punch",
+ "Type": "Unarmed Parry",
+ "Info": "",
+ "Skill": 8.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "189_parry",
+ "Name": "Quarterstaff (Staff Swing)",
+ "Type": "Parry",
+ "Info": "",
+ "Skill": 10.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "189_parry",
+ "Name": "Quarterstaff (Staff Thrust)",
+ "Type": "Parry",
+ "Info": "",
+ "Skill": 10.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "189_parry",
+ "Name": "Quarterstaff (2H Sword Swing)",
+ "Type": "Parry",
+ "Info": "",
+ "Skill": 5.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "189_parry",
+ "Name": "Quarterstaff (2H Sword Thrust)",
+ "Type": "Parry",
+ "Info": "",
+ "Skill": 5.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ }
+ ],
+ "RepeatingMelee": [
+ {
+ "Idkey": "226_airjet_",
+ "Name": "Air Jet",
+ "Damage": "~2d6",
+ "Type": "knock",
+ "Reach": "~2",
+ "Skill": 11.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{~1-3 energy. Multiply spell effect based on enegy spent.}"
+ },
+ {
+ "Idkey": "14_bite_bite",
+ "Name": "Bite",
+ "Damage": "1d6-3",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 10.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ },
+ {
+ "Idkey": "13350_breathefire_",
+ "Name": "Breathe Fire",
+ "Damage": "~1d6+1",
+ "Type": "burn",
+ "Reach": "~1",
+ "Skill": 11.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{~1-4 energy. Multiply spell effect based on enegy spent.}"
+ },
+ {
+ "Idkey": "13351_flamejet_",
+ "Name": "Flame Jet",
+ "Damage": "~1d6",
+ "Type": "burn",
+ "Reach": "~1",
+ "Skill": 11.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{~1-3 energy. Multiply spell effect based on enegy spent.}"
+ },
+ {
+ "Idkey": "69_kick_kick",
+ "Name": "Kick",
+ "Damage": "1d6-2",
+ "Type": "cr",
+ "Reach": "C,1",
+ "Skill": 8.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ },
+ {
+ "Idkey": "128_punch_punch",
+ "Name": "Punch",
+ "Damage": "1d6-3",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 10.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ },
+ {
+ "Idkey": "189_quarterstaff_staffswing",
+ "Name": "Quarterstaff (Staff Swing)",
+ "Damage": "1d6+1",
+ "Type": "cr",
+ "Reach": "1,2",
+ "Skill": 11.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "189_quarterstaff_staffthrust",
+ "Name": "Quarterstaff (Staff Thrust)",
+ "Damage": "1d6",
+ "Type": "cr",
+ "Reach": "1,2",
+ "Skill": 11.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "189_quarterstaff_2hswordswing",
+ "Name": "Quarterstaff (2H Sword Swing)",
+ "Damage": "1d6+1",
+ "Type": "cr",
+ "Reach": "1,2",
+ "Skill": 5.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "189_quarterstaff_2hswordthrust",
+ "Name": "Quarterstaff (2H Sword Thrust)",
+ "Damage": "1d6-1",
+ "Type": "cr",
+ "Reach": "2",
+ "Skill": 5.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ }
+ ],
+ "RepeatingRanged": [
+ {
+ "Idkey": "216_fireball_",
+ "Name": "Fireball",
+ "Damage": "~1d6",
+ "Type": "burn",
+ "Acc": "1",
+ "Range": "25/50",
+ "Rof": "",
+ "Shots": "",
+ "Bulk": "",
+ "Recoil": "",
+ "Skill": 13.0,
+ "Malfunction": "",
+ "MalfunctionVerify": false,
+ "MalfunctionVeryReliable": false,
+ "ArmorDivisor": 1.0,
+ "Notes": "{~1-3 energy. Multiply spell effect based on enegy spent.}"
+ },
+ {
+ "Idkey": "222_icedagger_",
+ "Name": "Ice Dagger",
+ "Damage": "~1d6-1",
+ "Type": "imp",
+ "Acc": "3",
+ "Range": "30/60",
+ "Rof": "",
+ "Shots": "",
+ "Bulk": "",
+ "Recoil": "",
+ "Skill": 13.0,
+ "Malfunction": "",
+ "MalfunctionVerify": false,
+ "MalfunctionVeryReliable": false,
+ "ArmorDivisor": 1.0,
+ "Notes": "{~1-3 energy. Multiply spell effect based on enegy spent.}"
+ },
+ {
+ "Idkey": "223_icesphere_",
+ "Name": "Ice Sphere",
+ "Damage": "~1d6",
+ "Type": "cr",
+ "Acc": "2",
+ "Range": "40/80",
+ "Rof": "",
+ "Shots": "",
+ "Bulk": "",
+ "Recoil": "",
+ "Skill": 13.0,
+ "Malfunction": "",
+ "MalfunctionVerify": false,
+ "MalfunctionVeryReliable": false,
+ "ArmorDivisor": 1.0,
+ "Notes": "{~1-3 energy. Multiply spell effect based on enegy spent.}"
+ },
+ {
+ "Idkey": "225_pistolcrossbow_barbed-head",
+ "Name": "Pistol Crossbow (ST 10) (Barbed-head)",
+ "Damage": "1d6-4",
+ "Type": "imp",
+ "Acc": "1",
+ "Range": "0",
+ "Rof": "1",
+ "Shots": "1(4)",
+ "Bulk": "-4",
+ "Recoil": "-",
+ "Skill": 6.0,
+ "Malfunction": "",
+ "MalfunctionVerify": false,
+ "MalfunctionVeryReliable": false,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Requires two hands to ready, but only one hand to attack.}"
+ },
+ {
+ "Idkey": "201_stonemissile_",
+ "Name": "Stone Missile",
+ "Damage": "~1d6+1",
+ "Type": "cr",
+ "Acc": "2",
+ "Range": "40/80",
+ "Rof": "",
+ "Shots": "",
+ "Bulk": "",
+ "Recoil": "",
+ "Skill": 13.0,
+ "Malfunction": "",
+ "MalfunctionVerify": false,
+ "MalfunctionVeryReliable": false,
+ "ArmorDivisor": 1.0,
+ "Notes": "{~1-3 energy. Multiply spell effect based on enegy spent.}"
+ }
+ ],
+ "RepeatingItem": [
+ {
+ "Idkey": "191",
+ "Name": "Cloth Armor Suit",
+ "Tl": "1",
+ "LegalityClass": "",
+ "Ref": "L18",
+ "Count": 1.0,
+ "Cost": 250.0,
+ "Weight": 12.0,
+ "Notes": "Deflect, +1, +100\nTL:1 LC:-- DR:1* Locations: all Notes:This is a full suit of armor from GURPS Lite. It includes an article of light, common clothing to wear underneath - or padding, if this is usual for the armor. The statistics already reflect this; you do not have to buy clothing or padding seperately, or account for its DR and weight."
+ },
+ {
+ "Idkey": "225",
+ "Name": "Pistol Crossbow (ST 10)",
+ "Tl": "3",
+ "LegalityClass": "4",
+ "Ref": "LT75",
+ "Count": 1.0,
+ "Cost": 150.0,
+ "Weight": 4.0,
+ "Notes": "ST 10\nTL:3 LC:4, Dam:thr+2 imp ACC:1 Range:ST*15/ST*20 ROF:1 Shots:1(4) ST:7 Bulk:-4 Rcl:- Skill:Crossbow, DX-4 Notes: [2, 3]"
+ },
+ {
+ "Idkey": "193",
+ "Name": "Powerstone (Energy 4)",
+ "Tl": "",
+ "LegalityClass": "",
+ "Ref": "M20",
+ "Count": 1.0,
+ "Cost": 425.0,
+ "Weight": 0.0,
+ "Notes": "Energy 4"
+ },
+ {
+ "Idkey": "189",
+ "Name": "Quarterstaff",
+ "Tl": "0",
+ "LegalityClass": "4",
+ "Ref": "LT69",
+ "Count": 1.0,
+ "Cost": 40.0,
+ "Weight": 4.0,
+ "Notes": "Staff, +30\nTL:0 LC:4 \\par [Dam:sw+2 cr Reach:1, 2 Parry:2 ST:7 Skill:Staff, DX-5, Polearm-4, Spear-2] \\par [Dam:thr+2 cr Reach:1, 2 Parry:2 ST:7 Skill:Staff, DX-5, Polearm-4, Spear-2] \\par [Dam:sw+2 cr Reach:1, 2 Parry:0 ST:9 Skill:Two-Handed Sword, DX-5, Broadsword-4, Force Sword-4] \\par [Dam:thr+1 cr Reach:2 Parry:0 ST:9 Skill:Two-Handed Sword, DX-5, Broadsword-4, Force Sword-4]"
+ }
+ ],
+ "RepeatingSpells": [
+ {
+ "Idkey": "226",
+ "Name": "Air Jet",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "1 sec.",
+ "Cost": "1 to 3/S",
+ "Skill": 15.0,
+ "Ref": "M24",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Air",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 3 Prerequisites: Shape Air"
+ },
+ {
+ "Idkey": "13349",
+ "Name": "Body of Flames",
+ "Difficulty": "VH",
+ "SpellModifier": 0.0,
+ "Points": 1.0,
+ "SpellResistedBy": "R-HT",
+ "Duration": "1 min.",
+ "Cost": "12/4",
+ "Skill": 13.0,
+ "Ref": "M76",
+ "Casttime": "5 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 8 Prerequisites: Magery 1, Breathe Fire"
+ },
+ {
+ "Idkey": "13350",
+ "Name": "Breathe Fire",
+ "Difficulty": "VH",
+ "SpellModifier": 0.0,
+ "Points": 1.0,
+ "SpellResistedBy": "",
+ "Duration": "1 sec.",
+ "Cost": "1 to 4",
+ "Skill": 13.0,
+ "Ref": "M76",
+ "Casttime": "2 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 7 Prerequisites: Magery 1, Flame Jet, Resist Fire"
+ },
+ {
+ "Idkey": "210",
+ "Name": "Create Air",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "5 sec.#",
+ "Cost": "1",
+ "Skill": 15.0,
+ "Ref": "M23, B243",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Area",
+ "SpellCollege": "Air",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 1 Prerequisites: Purify Air or Seek Air"
+ },
+ {
+ "Idkey": "197",
+ "Name": "Create Earth",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Perm.",
+ "Cost": "2/cu. yd.",
+ "Skill": 15.0,
+ "Ref": "M51, B246",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Earth",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 3 Prerequisites: Magery 1, Earth to Stone"
+ },
+ {
+ "Idkey": "212",
+ "Name": "Create Fire",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "1 min.",
+ "Cost": "2/H",
+ "Skill": 15.0,
+ "Ref": "M72, B246",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Area",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 1 Prerequisites: Ignite Fire or Seek Fire"
+ },
+ {
+ "Idkey": "219",
+ "Name": "Create Water",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Perm.",
+ "Cost": "2/gal.",
+ "Skill": 15.0,
+ "Ref": "M184, B253",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Water",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 2 Prerequisites: Purify Water"
+ },
+ {
+ "Idkey": "198",
+ "Name": "Earth to Stone",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Perm.",
+ "Cost": "3/cu. yd.#",
+ "Skill": 15.0,
+ "Ref": "M51, B245",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Earth",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 2 Prerequisites: Magery 1, Shape Earth"
+ },
+ {
+ "Idkey": "13354",
+ "Name": "Extinguish Fire",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 1.0,
+ "SpellResistedBy": "",
+ "Duration": "Perm.",
+ "Cost": "3",
+ "Skill": 14.0,
+ "Ref": "M72, B247",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Area",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 1 Prerequisites: Ignite Fire"
+ },
+ {
+ "Idkey": "214",
+ "Name": "Fire Cloud",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "10 sec.",
+ "Cost": "1 to 5/S",
+ "Skill": 15.0,
+ "Ref": "M75",
+ "Casttime": "1 to 5 sec.",
+ "Maintain": "",
+ "SpellClass": "Area",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 7 Prerequisites: Magery 1, Shape Air, Fireball"
+ },
+ {
+ "Idkey": "216",
+ "Name": "Fireball",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Instant",
+ "Cost": "1 to Magery#",
+ "Skill": 15.0,
+ "Ref": "M74, B247",
+ "Casttime": "1 to 3 sec.",
+ "Maintain": "",
+ "SpellClass": "Missile",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 3 Prerequisites: Magery 1, Create Fire, Shape Fire"
+ },
+ {
+ "Idkey": "13353",
+ "Name": "Fireproof",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 1.0,
+ "SpellResistedBy": "",
+ "Duration": "1 day",
+ "Cost": "3#",
+ "Skill": 14.0,
+ "Ref": "M73",
+ "Casttime": "5 min.",
+ "Maintain": "",
+ "SpellClass": "Area",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 2 Prerequisites: Extinguish Fire"
+ },
+ {
+ "Idkey": "13351",
+ "Name": "Flame Jet",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 1.0,
+ "SpellResistedBy": "",
+ "Duration": "1 sec.",
+ "Cost": "1 to 3/S",
+ "Skill": 14.0,
+ "Ref": "M73",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 3 Prerequisites: Create Fire, Shape Fire"
+ },
+ {
+ "Idkey": "222",
+ "Name": "Ice Dagger",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Instant",
+ "Cost": "1 to Magery#",
+ "Skill": 15.0,
+ "Ref": "M188",
+ "Casttime": "1 to 3 sec.",
+ "Maintain": "",
+ "SpellClass": "Missile",
+ "SpellCollege": "Water",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 5 Prerequisites: Ice Sphere or Water Jet"
+ },
+ {
+ "Idkey": "223",
+ "Name": "Ice Sphere",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Instant",
+ "Cost": "1 to Magery#",
+ "Skill": 15.0,
+ "Ref": "M186",
+ "Casttime": "1 to 3 sec.",
+ "Maintain": "",
+ "SpellClass": "Missile",
+ "SpellCollege": "Water",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 4 Prerequisites: Shape Water"
+ },
+ {
+ "Idkey": "213",
+ "Name": "Ignite Fire",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "1 sec.",
+ "Cost": "1 to 4/S",
+ "Skill": 15.0,
+ "Ref": "M72, B246",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 0"
+ },
+ {
+ "Idkey": "229",
+ "Name": "Itch",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "R-HT",
+ "Duration": "Scratch#",
+ "Cost": "2",
+ "Skill": 15.0,
+ "Ref": "M35, B244",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Body Control",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 0"
+ },
+ {
+ "Idkey": "195",
+ "Name": "Lend Energy",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Perm.",
+ "Cost": "Varies",
+ "Skill": 15.0,
+ "Ref": "M89, B248",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Healing",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 0 Prerequisites: Magery 1 or Empathy"
+ },
+ {
+ "Idkey": "230",
+ "Name": "Light",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "1 min.",
+ "Cost": "1/1",
+ "Skill": 15.0,
+ "Ref": "M110, B249",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Light & Darkness",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 0"
+ },
+ {
+ "Idkey": "211",
+ "Name": "Purify Air",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Instant",
+ "Cost": "1",
+ "Skill": 15.0,
+ "Ref": "M23, B243",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Area",
+ "SpellCollege": "Air",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 0"
+ },
+ {
+ "Idkey": "220",
+ "Name": "Purify Water",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Perm.",
+ "Cost": "1/gal.",
+ "Skill": 15.0,
+ "Ref": "M184, B253",
+ "Casttime": "5-10 sec/gal#",
+ "Maintain": "",
+ "SpellClass": "Special",
+ "SpellCollege": "Water",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 1 Prerequisites: Seek Water"
+ },
+ {
+ "Idkey": "196",
+ "Name": "Recover Energy",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Special",
+ "Cost": "none",
+ "Skill": 15.0,
+ "Ref": "M89, B248",
+ "Casttime": "Special",
+ "Maintain": "",
+ "SpellClass": "Special",
+ "SpellCollege": "Healing",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 1 Prerequisites: Magery 1, Lend Energy"
+ },
+ {
+ "Idkey": "13352",
+ "Name": "Resist Fire",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 1.0,
+ "SpellResistedBy": "",
+ "Duration": "1 min.",
+ "Cost": "2/1#",
+ "Skill": 14.0,
+ "Ref": "M74, B247",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 3 Prerequisites: Fireproof or Extinguish Fire, Cold"
+ },
+ {
+ "Idkey": "218",
+ "Name": "Seek Air",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Instant",
+ "Cost": "1",
+ "Skill": 15.0,
+ "Ref": "M23",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Information",
+ "SpellCollege": "Air",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 0"
+ },
+ {
+ "Idkey": "200",
+ "Name": "Seek Earth",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Instant",
+ "Cost": "3",
+ "Skill": 15.0,
+ "Ref": "M50, B245",
+ "Casttime": "10 sec.",
+ "Maintain": "",
+ "SpellClass": "Information",
+ "SpellCollege": "Earth",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 0"
+ },
+ {
+ "Idkey": "221",
+ "Name": "Seek Water",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Instant",
+ "Cost": "2",
+ "Skill": 15.0,
+ "Ref": "M184, B253",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Information",
+ "SpellCollege": "Water",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 0"
+ },
+ {
+ "Idkey": "215",
+ "Name": "Shape Air",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "1 min.",
+ "Cost": "1 to 10#",
+ "Skill": 15.0,
+ "Ref": "M24, B243",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Air",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 2 Prerequisites: Create Air"
+ },
+ {
+ "Idkey": "199",
+ "Name": "Shape Earth",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "1 min.",
+ "Cost": "1/cu. yd./h",
+ "Skill": 15.0,
+ "Ref": "M50, B245",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Earth",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 1 Prerequisites: Seek Earth"
+ },
+ {
+ "Idkey": "217",
+ "Name": "Shape Fire",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "1 min.",
+ "Cost": "2/H",
+ "Skill": 15.0,
+ "Ref": "M72, B246",
+ "Casttime": "1 sec.",
+ "Maintain": "",
+ "SpellClass": "Area",
+ "SpellCollege": "Fire",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 1 Prerequisites: Ignite Fire"
+ },
+ {
+ "Idkey": "224",
+ "Name": "Shape Water",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "1 min.",
+ "Cost": "1/1#",
+ "Skill": 15.0,
+ "Ref": "M185, B253",
+ "Casttime": "2 sec.",
+ "Maintain": "",
+ "SpellClass": "Regular",
+ "SpellCollege": "Water",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 3 Prerequisites: Create Water"
+ },
+ {
+ "Idkey": "201",
+ "Name": "Stone Missile",
+ "Difficulty": "H",
+ "SpellModifier": 0.0,
+ "Points": 2.0,
+ "SpellResistedBy": "",
+ "Duration": "Instant",
+ "Cost": "1 to Magery",
+ "Skill": 15.0,
+ "Ref": "M52",
+ "Casttime": "1 to 3 sec.",
+ "Maintain": "",
+ "SpellClass": "Missile",
+ "SpellCollege": "Earth",
+ "SpellCollegeSecondary": "",
+ "SpellModNotes": "",
+ "SpellNotes": "Prereq Count: 4 Prerequisites: Magery 1, Create Earth"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/GURPS/readme/assets/Rampage (NPC) export.json b/GURPS/readme/assets/Rampage (NPC) export.json
new file mode 100644
index 0000000000..a5c724aa1e
--- /dev/null
+++ b/GURPS/readme/assets/Rampage (NPC) export.json
@@ -0,0 +1,982 @@
+{
+ "CharacterName": "Rampage",
+ "Fullname": "Rampage (NPC)",
+ "Playername": "NPC",
+ "Nickname": "",
+ "Race": "Human",
+ "RaceRef": "",
+ "TemplateNames": "",
+ "Gender": "",
+ "Size": 0.0,
+ "ApplySizeModifier": false,
+ "Reactions": "+2 from 'Charisma 2'\nConditional:\n-2 from 'Reputation 2 (Gang Leader; 7 or less, +1, *1/3; Large class, +1, *1/2)'",
+ "CampaignTl": 8.0,
+ "TotalPoints": 150.0,
+ "Tl": 8.0,
+ "TlPts": 0.0,
+ "Status": "0",
+ "Wealth": "Comfortable",
+ "Income": 5200.0,
+ "CostOfLiving": 600.0,
+ "Stash": 5169.6,
+ "Age": "27",
+ "Height": "6'",
+ "Weight": 210.0,
+ "Appearance": 0.0,
+ "GeneralAppearance": "Short mohawk, painted face, likes to wear chains, like something out of Road Warrior.",
+ "StrengthMod": 1.0,
+ "StrengthPoints": 60.0,
+ "DexterityMod": 0.0,
+ "DexterityPoints": 40.0,
+ "IntelligenceMod": 0.0,
+ "IntelligencePoints": 0.0,
+ "HealthMod": 0.0,
+ "HealthPoints": 20.0,
+ "PerceptionMod": 0.0,
+ "PerceptionPoints": 10.0,
+ "VisionMod": 0.0,
+ "VisionPoints": 0.0,
+ "HearingMod": 0.0,
+ "HearingPoints": 0.0,
+ "TasteSmellMod": 0.0,
+ "TasteSmellPoints": 0.0,
+ "TouchMod": 0.0,
+ "TouchPoints": 0.0,
+ "WillpowerMod": 0.0,
+ "WillpowerPoints": 10.0,
+ "FearCheckMod": 2.0,
+ "FearCheckPoints": 0.0,
+ "StunCheckMod": 0.0,
+ "KnockdownCheckMod": 0.0,
+ "UnconsciousCheckMod": 1.0,
+ "UnconsciousCheckPoints": 0.0,
+ "DeathCheckMod": 1.0,
+ "DeathCheckPoints": 0.0,
+ "BasicSpeedMod": 0.0,
+ "BasicSpeedPoints": 0.0,
+ "BasicMoveMod": 0.0,
+ "BasicMovePoints": 0.0,
+ "EnhancedGroundMoveMod": 0.5,
+ "EnhancedGroundMovePoints": 0.0,
+ "DodgeMod": 2.0,
+ "LiftStMod": 7.0,
+ "LiftStPoints": 15.0,
+ "StrikingStMod": 4.0,
+ "StrikingStPoints": 0.0,
+ "HitPointsMod": 0.0,
+ "HitPointsPoints": 8.0,
+ "HitPoints": 21.0,
+ "FatiguePointsMod": 0.0,
+ "FatiguePointsPoints": 0.0,
+ "FatiguePoints": 12.0,
+ "FlightChecked": false,
+ "FlightPoints": 0.0,
+ "BasicAirMoveMod": 0.0,
+ "BasicAirMovePoints": 0.0,
+ "EnhancedAirLevel": 0.0,
+ "EnhancedAirMovePoints": 0.0,
+ "AmphibiousChecked": false,
+ "AmphibiousPoints": 0.0,
+ "BasicWaterMoveMod": 0.0,
+ "BasicWaterMovePoints": 0.0,
+ "EnhancedWaterLevel": 0.0,
+ "EnhancedWaterMovePoints": 0.0,
+ "SuperJumpEnteredLevel": 0.0,
+ "SuperJumpPoints": 0.0,
+ "SpellBonus": 0.0,
+ "CombatReflexes": true,
+ "RepeatingLanguages": [
+ {
+ "Idkey": "10663",
+ "Name": "English",
+ "Spoken": 0.0,
+ "Written": 0.0,
+ "IsNative": true
+ },
+ {
+ "Idkey": "12985",
+ "Name": "French",
+ "Spoken": 2.0,
+ "Written": 1.0,
+ "IsNative": false
+ },
+ {
+ "Idkey": "12984",
+ "Name": "German",
+ "Spoken": 2.0,
+ "Written": 2.0,
+ "IsNative": false
+ }
+ ],
+ "RepeatingCultures": [
+ {
+ "Idkey": "12982",
+ "Name": "European (Native)",
+ "Points": 0.0
+ },
+ {
+ "Idkey": "12983",
+ "Name": "Western",
+ "Points": 1.0
+ }
+ ],
+ "RepeatingTraits": [
+ {
+ "Idkey": "10717",
+ "Name": "Ambidexterity",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B39",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10800",
+ "Name": "Appearance",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 4.0,
+ "Ref": "B21",
+ "Notes": "Attractive"
+ },
+ {
+ "Idkey": "10704",
+ "Name": "Body Control Talent",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "P121,P167-169",
+ "Notes": "Innate Attack (Projectile), +0"
+ },
+ {
+ "Idkey": "10799",
+ "Name": "Charisma",
+ "TraitLevel": "2",
+ "Foa": "",
+ "Points": 10.0,
+ "Ref": "B41",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10698",
+ "Name": "Combat Reflexes",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 14.0,
+ "Ref": "B43",
+ "Notes": "Biological, -10%"
+ },
+ {
+ "Idkey": "12986",
+ "Name": "Contact (Rival Gang)",
+ "TraitLevel": "1",
+ "Foa": "9",
+ "Points": 1.0,
+ "Ref": "B44",
+ "Notes": "My notes here\nEffective Skill 12\nRival Gang\n9 or less, *1\nSomewhat Reliable, *1\nMy notes here\nUgly dude with twisted lips"
+ },
+ {
+ "Idkey": "10720",
+ "Name": "Crossbow (Armor Piercing)",
+ "TraitLevel": "3",
+ "Foa": "",
+ "Points": 38.0,
+ "Ref": "B61, P53",
+ "Notes": "Armor Piercing\nArmor Divisor, 2, +50%\nGadget/Breakable: DR 3-5, -15%\nGadget/Breakable: Size -3 or -4, -15%\nGadget/Can Be Stolen: Must be forcefully removed, -10%\nInaccurate, -1, -5%\nIncreased Range, x2, +10%\nIncreased Range, 1/2D Range only, x5, +10%\nNo Signature, +20%\nRicochet, +10%"
+ },
+ {
+ "Idkey": "10730",
+ "Name": "Crossbow (Explosive)",
+ "TraitLevel": "3",
+ "Foa": "",
+ "Points": 7.0,
+ "Ref": "B61, P53",
+ "Notes": "Explosive\nAlternative Attack, *1/5\nDouble Knockback, +20%\nExplosive, Damage / 2xYards, +100%\nGadget/Breakable: DR 3-5, -15%\nGadget/Breakable: Size -3 or -4, -15%\nGadget/Can Be Stolen: Must be forcefully removed, -10%\nInaccurate, -1, -5%\nIncreased Range, x2, +10%\nIncreased Range, 1/2D Range only, x10, +15%\nNo Signature, +20%"
+ },
+ {
+ "Idkey": "10741",
+ "Name": "Crossbow (Smoke Arrow)",
+ "TraitLevel": "6",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B72, P64",
+ "Notes": "Smoke Arrow\nAlternative Ability, *1/5\nArea Effect, 4 yd, +50%\nGadget/Breakable: DR 3-5, -15%\nGadget/Breakable: Size -3 or -4, -15%\nGadget/Can Be Stolen: Must be forcefully removed, -10%\nInaccurate, -1, -5%\nIncreased Range, x2, +10%\nIncreased Range, 1/2D Range Only, x5, +10%\nNo Signature, +20%\nRanged, +50%"
+ },
+ {
+ "Idkey": "10666",
+ "Name": "Damage Resistance",
+ "TraitLevel": "2",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B46, P45",
+ "Notes": "Biological, -10%\nTough Skin, -40%"
+ },
+ {
+ "Idkey": "10700",
+ "Name": "Enhanced Dodge",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 14.0,
+ "Ref": "B51",
+ "Notes": "Biological, -10%"
+ },
+ {
+ "Idkey": "10715",
+ "Name": "Enhanced Move (Ground)",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 9.0,
+ "Ref": "B52, P49",
+ "Notes": "#list(LevelName Step 0.5)\nGround\nBiological, -10%"
+ },
+ {
+ "Idkey": "10702",
+ "Name": "Enhanced Muscle",
+ "TraitLevel": "4",
+ "Foa": "",
+ "Points": 29.0,
+ "Ref": "Bio213",
+ "Notes": "Biological, -10%"
+ },
+ {
+ "Idkey": "10718",
+ "Name": "Extra Attack",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 23.0,
+ "Ref": "B54, P49",
+ "Notes": "Biological, -10%"
+ },
+ {
+ "Idkey": "11893",
+ "Name": "Extra ST",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 10.0,
+ "Ref": "B14",
+ "Notes": "Affects ST, +0%\nSize, +0%\nThe Extra ST advantage allows you to take extra levels of the attribute which you can then apply enhancements and limitations to. The \"Affects displayed score\" modifier causes the Extra ST advantage to affect the displayed attribute score. If you don't wish this advantage to affect the displayed score remove that modifier."
+ },
+ {
+ "Idkey": "10712",
+ "Name": "Fit",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B55",
+ "Notes": ""
+ },
+ {
+ "Idkey": "11891",
+ "Name": "Lifting ST",
+ "TraitLevel": "3",
+ "Foa": "",
+ "Points": 9.0,
+ "Ref": "B65, P58",
+ "Notes": "Size, +0%"
+ },
+ {
+ "Idkey": "10709",
+ "Name": "Protected Vision",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B78, P69",
+ "Notes": "Biological, -10%"
+ },
+ {
+ "Idkey": "10714",
+ "Name": "Rapid Healing",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B79",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10711",
+ "Name": "Resilience",
+ "TraitLevel": "20",
+ "Foa": "",
+ "Points": 18.0,
+ "Ref": "",
+ "Notes": "Biological, -10%"
+ },
+ {
+ "Idkey": "10705",
+ "Name": "Resistant (Metabolic Hazards)",
+ "TraitLevel": "4",
+ "Foa": "",
+ "Points": 9.0,
+ "Ref": "B80, P71",
+ "Notes": "Very Common\nMetabolic Hazards\nBiological, -10%\n+3, *1/3"
+ },
+ {
+ "Idkey": "10835",
+ "Name": "Signature Gear (Advanced Body Armor)",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 1.0,
+ "Ref": "B85",
+ "Notes": "%SigGearAliasList%\nAdvanced Body Armor"
+ },
+ {
+ "Idkey": "11890",
+ "Name": "Wealth",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 10.0,
+ "Ref": "B25",
+ "Notes": "Comfortable"
+ }
+ ],
+ "RepeatingPerks": [
+ {
+ "Idkey": "10756",
+ "Name": "Alcohol Tolerance",
+ "Foa": "",
+ "Points": 1.0,
+ "Ref": "B100, B100,PU2:13",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10757",
+ "Name": "Base (Bar)",
+ "Foa": "",
+ "Points": 1.0,
+ "Ref": "PU2:17",
+ "Notes": "Bar"
+ },
+ {
+ "Idkey": "10794",
+ "Name": "Teamwork (Concrete Savages)",
+ "Foa": "",
+ "Points": 1.0,
+ "Ref": "MA52, PU2:6",
+ "Notes": "Concrete Savages"
+ }
+ ],
+ "RepeatingQuirks": [
+ {
+ "Idkey": "10774",
+ "Name": "Chauvinistic",
+ "ControlRating": "",
+ "Points": -1.0,
+ "Ref": "B164",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10773",
+ "Name": "wears chains",
+ "ControlRating": "",
+ "Points": -1.0,
+ "Ref": "",
+ "Notes": ""
+ }
+ ],
+ "RepeatingDisadvantages": [
+ {
+ "Idkey": "10758",
+ "Name": "Bad Temper",
+ "TraitLevel": "1",
+ "ControlRating": "12",
+ "Points": -10.0,
+ "Ref": "B124",
+ "Notes": "12 or less, *1"
+ },
+ {
+ "Idkey": "10769",
+ "Name": "Enemy (Police)",
+ "TraitLevel": "1",
+ "ControlRating": "",
+ "Points": -10.0,
+ "Ref": "B135",
+ "Notes": "Small group (3-5 people)\nPolice\n9 or less, *1\nHunter, *1"
+ },
+ {
+ "Idkey": "10760",
+ "Name": "Greed",
+ "TraitLevel": "1",
+ "ControlRating": "12",
+ "Points": -15.0,
+ "Ref": "B137",
+ "Notes": "12 or less, *1"
+ },
+ {
+ "Idkey": "10762",
+ "Name": "Reputation (Gang Leader)",
+ "TraitLevel": "2",
+ "ControlRating": "",
+ "Points": -1.0,
+ "Ref": "B27",
+ "Notes": "Gang Leader\n7 or less, *1/3\nLarge class, *1/2"
+ }
+ ],
+ "RepeatingRacial": [],
+ "RepeatingSkills": [
+ {
+ "Idkey": "10784",
+ "Name": "Area Knowledge (local)",
+ "Tl": "",
+ "Base": "@{intelligence}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 11.0,
+ "Ref": "B176",
+ "SkillModNotes": "",
+ "Notes": "local"
+ },
+ {
+ "Idkey": "10753",
+ "Name": "Brawling",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 4.0,
+ "Skill": 14.0,
+ "Ref": "B182",
+ "SkillModNotes": "",
+ "Notes": "Notes: Calculated damage takes into account bonuses from Teeth, Weak Bite, Claws, and skill level. You may add the modifier \"Has Gauntlets/Brass Knuckles\" or \"Has Boots\" to apply the +1 damage to Punch or Kick, as appropriate."
+ },
+ {
+ "Idkey": "10780",
+ "Name": "Carousing",
+ "Tl": "",
+ "Base": "@{health}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 13.0,
+ "Ref": "B183",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10776",
+ "Name": "Connoisseur (Music)",
+ "Tl": "",
+ "Base": "@{intelligence}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 3.0,
+ "Skill": 11.0,
+ "Ref": "B185",
+ "SkillModNotes": "",
+ "Notes": "Music"
+ },
+ {
+ "Idkey": "10777",
+ "Name": "Dancing",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 1.0,
+ "Skill": 11.0,
+ "Ref": "B187",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10781",
+ "Name": "Forced Entry",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 13.0,
+ "Ref": "B196",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10775",
+ "Name": "Guns (Pistol)",
+ "Tl": "8",
+ "Base": "@{dexterity}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 4.0,
+ "Skill": 14.0,
+ "Ref": "B198",
+ "SkillModNotes": "",
+ "Notes": "uns/TL8 (Pistol"
+ },
+ {
+ "Idkey": "10752",
+ "Name": "Innate Attack (Projectile)",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "E",
+ "Bonus": 1.0,
+ "Points": 12.0,
+ "Skill": 17.0,
+ "Ref": "B201",
+ "SkillModNotes": "+1 from 'Body Control Talent 1 (Innate Attack (Projectile), +0)'",
+ "Notes": "Projectile"
+ },
+ {
+ "Idkey": "10782",
+ "Name": "Intimidation",
+ "Tl": "",
+ "Base": "10",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 4.0,
+ "Skill": 13.0,
+ "Ref": "B202",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10798",
+ "Name": "Leadership",
+ "Tl": "",
+ "Base": "@{intelligence}",
+ "Difficulty": "A",
+ "Bonus": 2.0,
+ "Points": 4.0,
+ "Skill": 13.0,
+ "Ref": "B204",
+ "SkillModNotes": "+2 from 'Charisma 2'",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10778",
+ "Name": "Musical Instrument (Guitar)",
+ "Tl": "",
+ "Base": "@{intelligence}",
+ "Difficulty": "H",
+ "Bonus": 0.0,
+ "Points": 12.0,
+ "Skill": 12.0,
+ "Ref": "B211",
+ "SkillModNotes": "",
+ "Notes": "Guitar"
+ },
+ {
+ "Idkey": "13357",
+ "Name": "Navigation (Land)",
+ "Tl": "8",
+ "Base": "@{intelligence}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 10.0,
+ "Ref": "B211",
+ "SkillModNotes": "",
+ "Notes": "avigation/TL8 (Land"
+ },
+ {
+ "Idkey": "13175",
+ "Name": "Shield (Force)",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 13.0,
+ "Ref": "B220",
+ "SkillModNotes": "",
+ "Notes": "Force"
+ },
+ {
+ "Idkey": "10779",
+ "Name": "Singing",
+ "Tl": "",
+ "Base": "@{health}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 13.0,
+ "Ref": "B220",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "10783",
+ "Name": "Streetwise",
+ "Tl": "",
+ "Base": "@{intelligence}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 8.0,
+ "Skill": 12.0,
+ "Ref": "B223",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "13361",
+ "Name": "Thief!",
+ "Tl": "",
+ "Base": "@{intelligence}",
+ "Difficulty": "WC",
+ "Bonus": 0.0,
+ "Points": 24.0,
+ "Skill": 10.0,
+ "Ref": "SU37",
+ "SkillModNotes": "",
+ "Notes": "Replaces Climbing, Escape, Filch, Forced Entry, Pickpocket, and Stealth. Make an IQ-based roll for Electronics Operation (Security), Lockpicking, Traps, or Streetwise; for Shadowing to follow an intended victim; and for Merchant to sell stolen goods.\nReplaces Climbing, Escape, Filch, Forced Entry, Pickpocket, and Stealth. Make an IQ-based roll for Electronics Operation (Security), Lockpicking, Traps, or Streetwise; for Shadowing to follow an intended victim; and for Merchant to sell stolen goods.\nReplaces Climbing, Escape, Filch, Forced Entry, Pickpocket, and Stealth. Make an IQ-based roll for Electronics Operation (Security), Lockpicking, Traps, or Streetwise; for Shadowing to follow an intended victim; and for Merchant to sell stolen goods."
+ },
+ {
+ "Idkey": "13174",
+ "Name": "Wrestling",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 1.0,
+ "Skill": 11.0,
+ "Ref": "B228",
+ "SkillModNotes": "",
+ "Notes": ""
+ }
+ ],
+ "RepeatingTechniquesrevised": [
+ {
+ "Idkey": "13172",
+ "Name": "Aggressive Parry (Brawling)",
+ "Parent": "Brawling",
+ "BaseLevel": "10",
+ "Default": -1.0,
+ "MaxModifier": 0.0,
+ "Difficulty": "H",
+ "SkillModifier": 0.0,
+ "Points": 2.0,
+ "Skill": 11.0,
+ "Ref": "MA65",
+ "SkillModNotes": "",
+ "Notes": "Brawling"
+ },
+ {
+ "Idkey": "13173",
+ "Name": "Arm Lock (Wrestling)",
+ "Parent": "Wrestling",
+ "BaseLevel": "11",
+ "Default": 0.0,
+ "MaxModifier": 4.0,
+ "Difficulty": "A",
+ "SkillModifier": 0.0,
+ "Points": 2.0,
+ "Skill": 13.0,
+ "Ref": "MA65, B230",
+ "SkillModNotes": "",
+ "Notes": "Wrestling"
+ }
+ ],
+ "RepeatingDefense": [
+ {
+ "Idkey": "10704_power_dodge",
+ "Name": "Body Control Talent (Power Dodge)",
+ "Type": "Power Dodge",
+ "Info": "",
+ "Skill": 9.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "10704_power_block",
+ "Name": "Body Control Talent (Power Block/Physical)",
+ "Type": "Power Block",
+ "Info": "",
+ "Skill": 9.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "10704_power_block_mental",
+ "Name": "Body Control Talent (Power Block/Mental)",
+ "Type": "Power Block Mental",
+ "Info": "",
+ "Skill": 9.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "10753_unarmed_parry",
+ "Name": "Brawling (Punch)",
+ "Type": "Unarmed Parry",
+ "Info": "",
+ "Skill": 11.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "10613_unarmed_parry",
+ "Name": "Punch",
+ "Type": "Unarmed Parry",
+ "Info": "",
+ "Skill": 11.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "13175_block",
+ "Name": "Shield (Force)",
+ "Type": "Block",
+ "Info": "",
+ "Skill": 10.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ }
+ ],
+ "RepeatingMelee": [
+ {
+ "Idkey": "13172_aggressiveparry_",
+ "Name": "Aggressive Parry (Brawling)",
+ "Damage": "2d6-2",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 11.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "10525_bite_bite",
+ "Name": "Bite",
+ "Damage": "2d6+1",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 14.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ },
+ {
+ "Idkey": "10753_brawling_punch",
+ "Name": "Brawling (Punch)",
+ "Damage": "2d6+1",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 14.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "10753_brawling_bite",
+ "Name": "Brawling (Bite)",
+ "Damage": "2d6+1",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 14.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "10753_brawling_kick",
+ "Name": "Brawling (Kick)",
+ "Damage": "2d6+2",
+ "Type": "cr",
+ "Reach": "C,1",
+ "Skill": 12.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{If you miss with a kick, roll vs. DX to avoid falling.}"
+ },
+ {
+ "Idkey": "13176_forceshield_bash",
+ "Name": "Force Shield (Bash)",
+ "Damage": "2d6",
+ "Type": "cr",
+ "Reach": "1",
+ "Skill": 13.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Worn on the wrist, leaving the hand free.}"
+ },
+ {
+ "Idkey": "13176_forceshield_rush",
+ "Name": "Force Shield (Rush)",
+ "Damage": "slam+3",
+ "Type": "cr",
+ "Reach": "1",
+ "Skill": 13.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Worn on the wrist, leaving the hand free.}"
+ },
+ {
+ "Idkey": "10558_kick_kick",
+ "Name": "Kick",
+ "Damage": "2d6+2",
+ "Type": "cr",
+ "Reach": "C,1",
+ "Skill": 12.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ },
+ {
+ "Idkey": "10613_punch_punch",
+ "Name": "Punch",
+ "Damage": "2d6+1",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 14.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ }
+ ],
+ "RepeatingRanged": [
+ {
+ "Idkey": "10720_crossbow_primary",
+ "Name": "Crossbow (Armor Piercing) (Primary)",
+ "Damage": "3d6",
+ "Type": "imp",
+ "Acc": "2",
+ "Range": "100/200",
+ "Rof": "1",
+ "Shots": "",
+ "Bulk": "",
+ "Recoil": "1",
+ "Skill": 17.0,
+ "Malfunction": "",
+ "MalfunctionVerify": false,
+ "MalfunctionVeryReliable": false,
+ "ArmorDivisor": 2.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "10730_crossbow_primary",
+ "Name": "Crossbow (Explosive) (Primary)",
+ "Damage": "3d6",
+ "Type": "cr dkb ex/2",
+ "Acc": "2",
+ "Range": "200",
+ "Rof": "1",
+ "Shots": "n/a",
+ "Bulk": "",
+ "Recoil": "1",
+ "Skill": 17.0,
+ "Malfunction": "",
+ "MalfunctionVerify": false,
+ "MalfunctionVeryReliable": false,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "10786_revolver357m_",
+ "Name": "Revolver, .357M",
+ "Damage": "3d6-1",
+ "Type": "pi",
+ "Acc": "2",
+ "Range": "185/2000",
+ "Rof": "3",
+ "Shots": "6(3i)",
+ "Bulk": "-2",
+ "Recoil": "3",
+ "Skill": 15.0,
+ "Malfunction": "17",
+ "MalfunctionVerify": false,
+ "MalfunctionVeryReliable": false,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ }
+ ],
+ "RepeatingItem": [
+ {
+ "Idkey": "10833",
+ "Name": "Advanced Body Armor",
+ "Tl": "8",
+ "LegalityClass": "2",
+ "Ref": "HT66",
+ "Count": 1.0,
+ "Cost": 4600.0,
+ "Weight": 17.0,
+ "Notes": "Signature Gear, +0\nTL:8 LC:2 DR:35/5* Location:torso Notes:[1] Concealable as or under clothing. [5] Use the lower DR versus crushing attacks only."
+ },
+ {
+ "Idkey": "10790",
+ "Name": "Boots, Steel-Toed",
+ "Tl": "6",
+ "LegalityClass": "4",
+ "Ref": "HT68",
+ "Count": 1.0,
+ "Cost": 100.0,
+ "Weight": 4.0,
+ "Notes": "TL:6 LC:4 DR:6/2 Location:feet Notes:[1] Concealable as or under clothing. [2] Give +1 to kicking damage (p. B271). [4] Split DR: use the first, higher DR when - in the GM's opinion - the boot's steel toe box would protect (e. g. , dropping an item on the foot or crushing the toes in heavy machinery) or when an attack on the foot hits the toe (2/6 protection); use the second, lower DR against all other attacks."
+ },
+ {
+ "Idkey": "13358",
+ "Name": "Compass",
+ "Tl": "6",
+ "LegalityClass": "",
+ "Ref": "B288",
+ "Count": 1.0,
+ "Cost": 50.0,
+ "Weight": 0.0,
+ "Notes": "TL:6 Notes: +1 to Navigation skill"
+ },
+ {
+ "Idkey": "13176",
+ "Name": "Force Shield",
+ "Tl": "^",
+ "LegalityClass": "3",
+ "Ref": "B273, B287",
+ "Count": 1.0,
+ "Cost": 1500.0,
+ "Weight": 0.5,
+ "Notes": "TL:^ LC:3 DB:3 Dam:thr cr Reach:1 Parry:No ST:-- DR:100 HP:-- Skill:Shield (Force) Notes: [3,5] Also available as a buckler. You can ready a buckler in one turn and drop it as a free action, just like a weapon - but it always occupies one hand, and it does not allow a shield rush. Use Shield (Buckler) instead of regular shield skill. No effect on statistics. Worn on the wrist, leaving the hand free. DR is hardened (treat as Hardened enhancement, p. B47)."
+ },
+ {
+ "Idkey": "13355",
+ "Name": "Holster, Belt",
+ "Tl": "5",
+ "LegalityClass": "",
+ "Ref": "B289",
+ "Count": 1.0,
+ "Cost": 1180.4,
+ "Weight": 7.62,
+ "Notes": "TL:5 Notes: Fits most pistols."
+ },
+ {
+ "Idkey": "10788",
+ "Name": "Laser Sight",
+ "Tl": "8",
+ "LegalityClass": "",
+ "Ref": "B289",
+ "Count": 1.0,
+ "Cost": 100.0,
+ "Weight": 0.0,
+ "Notes": "TL:8 Notes: +1 to skill, see Laser Sights (p. B412)"
+ },
+ {
+ "Idkey": "10792",
+ "Name": "Personal Basics",
+ "Tl": "0",
+ "LegalityClass": "",
+ "Ref": "B288",
+ "Count": 1.0,
+ "Cost": 5.0,
+ "Weight": 1.0,
+ "Notes": "TL:0 Notes: Minimum gear for camping: -2 to any Survival roll without it. Includes utensils, tinderbox or flint and steel, towel, etc., as TL permits."
+ },
+ {
+ "Idkey": "10786",
+ "Name": "Revolver, .357M",
+ "Tl": "7",
+ "LegalityClass": "3",
+ "Ref": "B278",
+ "Count": 1.0,
+ "Cost": 1100.0,
+ "Weight": 3.6,
+ "Notes": "Rugged, *2\nReceives Skill Bonus, +1, +0\nTL:7 LC:3 Damage:3d-1 pi Acc:2 Range:185/2000 RoF:3 Shots:6(3i) ST:10 Bulk:-2 Rcl:3 Skill:Guns (Pistol)"
+ },
+ {
+ "Idkey": "13356",
+ "Name": "Revolver, .357M (Ammunition)",
+ "Tl": "7",
+ "LegalityClass": "3",
+ "Ref": "",
+ "Count": 12.0,
+ "Cost": 50.4,
+ "Weight": 2.52,
+ "Notes": "Ammunition"
+ }
+ ],
+ "RepeatingSpells": []
+}
\ No newline at end of file
diff --git a/GURPS/readme/assets/gargoyle export.json b/GURPS/readme/assets/gargoyle export.json
new file mode 100644
index 0000000000..2e5634696a
--- /dev/null
+++ b/GURPS/readme/assets/gargoyle export.json
@@ -0,0 +1,516 @@
+{
+ "CharacterName": "Gargoyle",
+ "Fullname": "Gargoyle (Test)",
+ "Playername": "Test",
+ "Nickname": "",
+ "Race": "Gargoyle",
+ "RaceRef": "",
+ "TemplateNames": "Gargoyle (Dungeon Fantasy)",
+ "Gender": "",
+ "Size": 0.0,
+ "ApplySizeModifier": false,
+ "Reactions": "Conditional:\n-1 from 'Callous' when past victim, or has Empathy\n-1 from 'Odious Racial Habit (Dirty)' when people notice your problem",
+ "CampaignTl": 3.0,
+ "TotalPoints": 150.0,
+ "Tl": 3.0,
+ "TlPts": 0.0,
+ "Status": "0",
+ "Wealth": "Average",
+ "Income": 700.0,
+ "CostOfLiving": 600.0,
+ "Stash": 180.0,
+ "Age": "14",
+ "Height": "5'6\"",
+ "Weight": 130.0,
+ "Appearance": 0.0,
+ "GeneralAppearance": "",
+ "StrengthMod": 0.0,
+ "StrengthPoints": 20.0,
+ "DexterityMod": 0.0,
+ "DexterityPoints": 60.0,
+ "IntelligenceMod": -1.0,
+ "IntelligencePoints": 0.0,
+ "HealthMod": 1.0,
+ "HealthPoints": 0.0,
+ "PerceptionMod": 0.0,
+ "PerceptionPoints": 10.0,
+ "VisionMod": 2.0,
+ "VisionPoints": 0.0,
+ "HearingMod": 2.0,
+ "HearingPoints": 0.0,
+ "TasteSmellMod": 0.0,
+ "TasteSmellPoints": 0.0,
+ "TouchMod": 0.0,
+ "TouchPoints": 0.0,
+ "WillpowerMod": 0.0,
+ "WillpowerPoints": 0.0,
+ "FearCheckMod": 0.0,
+ "FearCheckPoints": 0.0,
+ "StunCheckMod": 0.0,
+ "KnockdownCheckMod": 0.0,
+ "UnconsciousCheckMod": 0.0,
+ "UnconsciousCheckPoints": 0.0,
+ "DeathCheckMod": 0.0,
+ "DeathCheckPoints": 0.0,
+ "BasicSpeedMod": -0.25,
+ "BasicSpeedPoints": 5.0,
+ "BasicMoveMod": 0.0,
+ "BasicMovePoints": 5.0,
+ "EnhancedGroundMoveMod": 0.0,
+ "EnhancedGroundMovePoints": 0.0,
+ "DodgeMod": 0.0,
+ "LiftStMod": 0.0,
+ "LiftStPoints": 0.0,
+ "StrikingStMod": 0.0,
+ "StrikingStPoints": 0.0,
+ "HitPointsMod": 2.0,
+ "HitPointsPoints": 0.0,
+ "HitPoints": 14.0,
+ "FatiguePointsMod": 0.0,
+ "FatiguePointsPoints": 3.0,
+ "FatiguePoints": 12.0,
+ "FlightChecked": false,
+ "FlightPoints": 0.0,
+ "BasicAirMoveMod": 2.0,
+ "BasicAirMovePoints": 0.0,
+ "EnhancedAirLevel": 0.5,
+ "EnhancedAirMovePoints": 0.0,
+ "AmphibiousChecked": false,
+ "AmphibiousPoints": 0.0,
+ "BasicWaterMoveMod": 0.0,
+ "BasicWaterMovePoints": 0.0,
+ "EnhancedWaterLevel": 0.0,
+ "EnhancedWaterMovePoints": 0.0,
+ "SuperJumpEnteredLevel": 1.0,
+ "SuperJumpPoints": 0.0,
+ "SpellBonus": 0.0,
+ "CombatReflexes": false,
+ "RepeatingLanguages": [
+ {
+ "Idkey": "12360",
+ "Name": "Common",
+ "Spoken": 0.0,
+ "Written": 0.0,
+ "IsNative": true
+ }
+ ],
+ "RepeatingCultures": [
+ {
+ "Idkey": "12362",
+ "Name": "Gargoyle (Native)",
+ "Points": 0.0
+ }
+ ],
+ "RepeatingTraits": [
+ {
+ "Idkey": "12371",
+ "Name": "Absolute Direction",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 5.0,
+ "Ref": "B34",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12363",
+ "Name": "Acute Hearing",
+ "TraitLevel": "2",
+ "Foa": "",
+ "Points": 4.0,
+ "Ref": "B35",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12364",
+ "Name": "Acute Vision",
+ "TraitLevel": "2",
+ "Foa": "",
+ "Points": 4.0,
+ "Ref": "B35",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12379",
+ "Name": "Enhanced Move (Air)",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 10.0,
+ "Ref": "B52",
+ "Notes": "#list(LevelName Step 0.5)\nAir"
+ },
+ {
+ "Idkey": "12382",
+ "Name": "Extra Air Move",
+ "TraitLevel": "2",
+ "Foa": "",
+ "Points": 4.0,
+ "Ref": "B18",
+ "Notes": "Affects Air Move, +0%\nThe Extra Air Move advantage allows you to take extra levels of the attribute which you can then apply enhancements and limitations to. The \"Affects displayed score\" modifier causes the Extra Air Move advantage to affect the displayed attribute score. If you don't wish this advantage to affect the displayed score remove that modifier."
+ },
+ {
+ "Idkey": "12372",
+ "Name": "Night Vision",
+ "TraitLevel": "3",
+ "Foa": "",
+ "Points": 3.0,
+ "Ref": "B71",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12378",
+ "Name": "Super Jump",
+ "TraitLevel": "1",
+ "Foa": "",
+ "Points": 10.0,
+ "Ref": "B89",
+ "Notes": ""
+ }
+ ],
+ "RepeatingPerks": [],
+ "RepeatingQuirks": [],
+ "RepeatingDisadvantages": [
+ {
+ "Idkey": "12365",
+ "Name": "Callous",
+ "TraitLevel": "1",
+ "ControlRating": "",
+ "Points": -5.0,
+ "Ref": "B125",
+ "Notes": ""
+ }
+ ],
+ "RepeatingRacial": [
+ {
+ "Idkey": "12346",
+ "Name": "Gargoyle (Dungeon Fantasy)",
+ "TraitLevel": "",
+ "ControlRating": "",
+ "Points": 0.0,
+ "Ref": "",
+ "Notes": "Dungeon Fantasy\nA gargoyle resembles nothing so much as an ugly stone man with wings."
+ },
+ {
+ "Idkey": "12347",
+ "Name": "Stony",
+ "TraitLevel": "1",
+ "ControlRating": "",
+ "Points": 1.0,
+ "Ref": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12348",
+ "Name": "Claws (Blunt Claws)",
+ "TraitLevel": "1",
+ "ControlRating": "",
+ "Points": 3.0,
+ "Ref": "",
+ "Notes": "Blunt Claws"
+ },
+ {
+ "Idkey": "12349",
+ "Name": "Gargoyle Flight",
+ "TraitLevel": "1",
+ "ControlRating": "",
+ "Points": 30.0,
+ "Ref": "",
+ "Notes": "Winged, -25%"
+ },
+ {
+ "Idkey": "12351",
+ "Name": "Gargoyle Damage Resistance",
+ "TraitLevel": "2",
+ "ControlRating": "",
+ "Points": 10.0,
+ "Ref": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12352",
+ "Name": "Night Vision",
+ "TraitLevel": "5",
+ "ControlRating": "",
+ "Points": 5.0,
+ "Ref": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12353",
+ "Name": "Striker (Impaling; Gargoyle Tail)",
+ "TraitLevel": "1",
+ "ControlRating": "",
+ "Points": 5.0,
+ "Ref": "",
+ "Notes": "Impaling\nGargoyle Tail\nClumsy, -2, -40%"
+ },
+ {
+ "Idkey": "12355",
+ "Name": "Appearance",
+ "TraitLevel": "2",
+ "ControlRating": "",
+ "Points": -8.0,
+ "Ref": "",
+ "Notes": "Ugly"
+ },
+ {
+ "Idkey": "12356",
+ "Name": "Gluttony",
+ "TraitLevel": "1",
+ "ControlRating": "12",
+ "Points": -5.0,
+ "Ref": "",
+ "Notes": "12 or less, *1"
+ },
+ {
+ "Idkey": "12358",
+ "Name": "Odious Racial Habit (Dirty)",
+ "TraitLevel": "1",
+ "ControlRating": "",
+ "Points": -5.0,
+ "Ref": "",
+ "Notes": "Dirty"
+ },
+ {
+ "Idkey": "12359",
+ "Name": "Torso armor isn't interchangeable with human torso armor.",
+ "TraitLevel": "1",
+ "ControlRating": "",
+ "Points": 0.0,
+ "Ref": "",
+ "Notes": ""
+ }
+ ],
+ "RepeatingSkills": [
+ {
+ "Idkey": "12366",
+ "Name": "Aerobatics",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "H",
+ "Bonus": 0.0,
+ "Points": 4.0,
+ "Skill": 13.0,
+ "Ref": "B174",
+ "SkillModNotes": "+0 from 'Absolute Direction'",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12369",
+ "Name": "Area Knowledge (local)",
+ "Tl": "",
+ "Base": "@{intelligence}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 10.0,
+ "Ref": "B176",
+ "SkillModNotes": "",
+ "Notes": "local"
+ },
+ {
+ "Idkey": "12377",
+ "Name": "Axe/Mace",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 1.0,
+ "Skill": 12.0,
+ "Ref": "B208",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12373",
+ "Name": "Brawling",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "E",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 14.0,
+ "Ref": "B182",
+ "SkillModNotes": "",
+ "Notes": "Notes: Calculated damage takes into account bonuses from Teeth, Weak Bite, Claws, and skill level. You may add the modifier \"Has Gauntlets/Brass Knuckles\" or \"Has Boots\" to apply the +1 damage to Punch or Kick, as appropriate."
+ },
+ {
+ "Idkey": "12374",
+ "Name": "Dropping",
+ "Tl": "",
+ "Base": "@{dexterity}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 2.0,
+ "Skill": 13.0,
+ "Ref": "B189",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12367",
+ "Name": "Flight",
+ "Tl": "",
+ "Base": "@{health}",
+ "Difficulty": "A",
+ "Bonus": 0.0,
+ "Points": 8.0,
+ "Skill": 13.0,
+ "Ref": "B195",
+ "SkillModNotes": "",
+ "Notes": ""
+ },
+ {
+ "Idkey": "12370",
+ "Name": "Navigation (Air)",
+ "Tl": "3",
+ "Base": "@{intelligence}",
+ "Difficulty": "A",
+ "Bonus": 3.0,
+ "Points": 4.0,
+ "Skill": 13.0,
+ "Ref": "B211",
+ "SkillModNotes": "+3 from 'Absolute Direction'",
+ "Notes": "avigation/TL3 (Air"
+ }
+ ],
+ "RepeatingTechniquesrevised": [],
+ "RepeatingDefense": [
+ {
+ "Idkey": "12373_mode_219",
+ "Name": "Brawling (Punch)",
+ "Type": "Unarmed Parry",
+ "Info": "",
+ "Skill": 10.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "12376_mode_228",
+ "Name": "Knobbed Club (Swing)",
+ "Type": "Parry",
+ "Info": "",
+ "Skill": 9.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "12296_mode_117",
+ "Name": "Punch",
+ "Type": "Unarmed Parry",
+ "Info": "",
+ "Skill": 10.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ },
+ {
+ "Idkey": "12353_mode_195",
+ "Name": "Striker (Impaling; Gargoyle Tail) ([Description])",
+ "Type": "Parry",
+ "Info": "",
+ "Skill": 9.0,
+ "SkillMod": 0.0,
+ "DefenseModReason": "",
+ "InfoDescription": ""
+ }
+ ],
+ "RepeatingMelee": [
+ {
+ "Idkey": "12208_mode_12",
+ "Name": "Bite",
+ "Damage": "1d6-2",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 14.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ },
+ {
+ "Idkey": "12373_mode_219",
+ "Name": "Brawling (Punch)",
+ "Damage": "1d6-1",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 14.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "12373_mode_220",
+ "Name": "Brawling (Bite)",
+ "Damage": "1d6-2",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 14.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "12373_mode_221",
+ "Name": "Brawling (Kick)",
+ "Damage": "1d6",
+ "Type": "cr",
+ "Reach": "C,1",
+ "Skill": 12.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{If you miss with a kick, roll vs. DX to avoid falling.}"
+ },
+ {
+ "Idkey": "12241_mode_57",
+ "Name": "Kick",
+ "Damage": "1d6",
+ "Type": "cr",
+ "Reach": "C,1",
+ "Skill": 12.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ },
+ {
+ "Idkey": "12376_mode_228",
+ "Name": "Knobbed Club (Swing)",
+ "Damage": "1d6+3",
+ "Type": "cr",
+ "Reach": "1",
+ "Skill": 12.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ },
+ {
+ "Idkey": "12296_mode_117",
+ "Name": "Punch",
+ "Damage": "1d6-1",
+ "Type": "cr",
+ "Reach": "C",
+ "Skill": 14.0,
+ "ArmorDivisor": 1.0,
+ "Notes": "{Brawling (p. B182) increases all unarmed damage; Claws (p. B42) and Karate (p. B203) improve damage with punches and kicks (Claws don't affect damage with brass knuckles or boots); and Boxing (p. B182) improves punching damage.}"
+ },
+ {
+ "Idkey": "12353_mode_195",
+ "Name": "Striker (Impaling; Gargoyle Tail) ([Description])",
+ "Damage": "1d6",
+ "Type": "imp",
+ "Reach": "C",
+ "Skill": 12.0,
+ "ArmorDivisor": 1.0,
+ "Notes": ""
+ }
+ ],
+ "RepeatingRanged": [],
+ "RepeatingItem": [
+ {
+ "Idkey": "12376",
+ "Name": "Knobbed Club",
+ "Tl": "0",
+ "LegalityClass": "4",
+ "Ref": "LT65",
+ "Count": 1.0,
+ "Cost": 20.0,
+ "Weight": 2.0,
+ "Notes": "TL:0 LC:4, Dam:sw+1 cr Reach:1 Parry:0 ST:8 Skill:Axe/Mace, DX-5, Flail-4, Two-Handed Axe/Mace-3"
+ }
+ ],
+ "RepeatingSpells": []
+}
\ No newline at end of file
diff --git a/GURPS/translation.json b/GURPS/translation.json
index b03b5b83bb..205366da68 100644
--- a/GURPS/translation.json
+++ b/GURPS/translation.json
@@ -436,14 +436,14 @@
"attribute-will": "Will",
"attribute-will-tooltip": "Willpower
Based on Intelligence
5pts/level
Unmodified:
",
"attribute-fright": "Fright",
- "attribute-fright-tooltip": "Fright Check (B360)
Based on Willpower
2pts/level
Unmodified:
See extensive list of Modifiers B360 & GURPS Horror p139-142.",
+ "attribute-fright-tooltip": "Fright Check (B360)
Based on Willpower
2pts/level
Unmodified:
See extensive list of Modifiers B360 & GURPS Horror p139-142.
If manually creating and/or maintaining this sheet, Combat Reflexes adds +2 to Fright (Enter as a MOD with a value of 2)",
"abbreviation-threshold": "Thresh",
"attribute-fright-check-threshold-tooltip": "Fright Check Threshold - Uses
Rule of 14 (B360). By default this value is 13.
This means that a roll of 14 or more is automatically a failure.
This Threshold can be modifier by the Perks of Brave (Dungeon Fantasy 11, p11) or Rule of 15
(Power Ups 2, p13).
Will and/or Fright plus bonuses (like Fearlessness or Combat Reflexes) must total 14+ for this
to be useful, of course!
Note: A Fright Check can be used for Awe and Confusion. (Powers p84 under Terror) and the Awe and
Confusion Check Table for failures. (Powers p85).",
"fright-check-label": "Fright Check",
"attribute-unstun": "Unstun",
"attribute-unstun-tooltip": "Recover from physical stun, based on Health.
Roll at the end of your turn after Do Nothing ",
"abbreviation-knock-down": "K Down",
- "attribute-knock-down-tooltip": "Knockdown and Stunning check (B420), based on HT (Health).
Roll
immediately whenever the following happens:
You suffer a Major Wound (B420) - This is any single injury that inflicts a wound in excess of ½ your HP. You suffer any Crippling Injury (B420-421). Whenever you are struck in the Head (Skull, Face, or Eye) or Vitals for enough injury to cause a Shock (B419) penalty. Modifiers: - 5 for a Major Wound (B420) to the Face or Vitals (or to the Groin on a humanoid male). - 10 for a Major Wound (B420) to the Skull or Eye. ",
+ "attribute-knock-down-tooltip": "Knockdown and Stunning check (B420), based on HT (Health).
Roll
immediately whenever the following happens:
You suffer a Major Wound (B420) - This is any single injury that inflicts a wound in excess of ½ your HP. You suffer any Crippling Injury (B420-421). Whenever you are struck in the Head (Skull, Face, or Eye) or Vitals for enough injury to cause a Shock (B419) penalty. Modifiers: - 5 for a Major Wound (B420) to the Face or Vitals (or to the Groin on a humanoid male). - 10 for a Major Wound (B420) to the Skull or Eye. If manually creating and/or maintaining this sheet, High Pain Threshold adds +3 to Knockdown (Enter as a MOD with a value of 3) ",
"abbreviation-unconscious": "Unc.",
"attribute-unconscious-check-tooltip": "Unconscious Check, based on Health
If HP zero or less, roll per turn to take an Active Action.
-1 per full multiple of HP below zero.
Hard/Easy to Subdue: Gives +/- per level to Unconscious Check
Fit +1 to Unc. Check . Very Fit +2 to Unc. Check",
"abbreviation-death-check": "Death",
@@ -870,6 +870,7 @@
"option-basic-speed": "Basic Speed",
"option-current-dodge": "Current Dodge",
"talent-level-label": "Talent Level:",
+ "talent-level-tooltip": "For use with Power Dodge, Power Parry, and Power Blocks formulas. See P167",
"formula-level-label": "Formula Level:",
"abbreviation-information-notes": "INFO Notes",
"fencing-unbalanced-tooltip": "If you enter F or U under the
INFO column, the notes
below will be
replaced with appropriate notes.
Any other value, and the text box will get
cleared out.
",
@@ -887,7 +888,7 @@
"melee-attacks-label": "Melee Attacks",
"attacks-label": "Attacks",
"targets-label": "Targets",
- "melee-attack-damage-tooltip": "For an
Armor Divisor : A number in parenthesis after
the damage - eg. (2) - is an armor divisor.
Enter this number in the
Damage Notes as AD(#) or as
Armor Divisor(#).
ex : indicates the attack causes an explosion.
See B269. Enter in the
Damage Notes ",
+ "melee-attack-damage-tooltip": "For an
Armor Divisor : A number in parenthesis after
the damage - eg. (2) - is an armor divisor.
Enter this number in the
Damage Notes as AD(#) or as
Armor Divisor(#).
ex : indicates the attack causes an explosion.
See B269. Enter in the
Damage Notes Macros You can also use @{thrust} and @{swing} for Melee Damage value, which is based on the values entered on the General page. You can even add additional modifiers such as @{thrust}+3.",
"damage-type-tooltip": "
Abbr Name aff Affliction burn Burning cor Corrosion cr Crushing cut Cutting fat Fatigue imp Impaling pi- Small Piercing pi Piercing pi+ Large Piercing pi++ Huge Piercing spec Special tox Toxic
",
"reach-label": "Reach",
"melee-reach-tooltip": "The distance in yards that the weapon can reach.
C : this weapon can be used in close combat.
* : the weapon is awkward, and requires a Ready
maneuver to switch between different reaches.",
@@ -930,7 +931,7 @@
"ranged-fail-notes-tooltip": "Any standard notes entered here will appear in the Roll Template in chat.
Hint: Enter inline rolls for additional results.
Example: Does an additional [[1d6]] fire damage.",
"ranged-critical-fail-notes-tooltip": "Any standard notes entered here will appear in the Roll Template in chat.
Hint: Enter inline rolls for additional results.
Example: Does an additional [[1d6]] fire damage.",
"ranged-attacks-label": "Ranged Attacks",
- "ranged-damage-tooltip": "For an
Armor Divisor : A number in parenthesis after
the damage - eg. (2) - is an armor divisor.
Enter this number in the
Damage Notes as AD(#) or as
Armor Divisor(#).
ex : indicates the attack causes an explosion.
[#d] : indicates the attack causes fragmentation.
See B269. Enter in the
Damage Notes ",
+ "ranged-damage-tooltip": "For an
Armor Divisor : A number in parenthesis after
the damage - eg. (2) - is an armor divisor.
Enter this number in the
Damage Notes as AD(#) or as
Armor Divisor(#).
ex : indicates the attack causes an explosion.
[#d] : indicates the attack causes fragmentation.
See B269. Enter in the
Damage Notes .
Macros You can also use @{thrust} and @{swing} for Ranged Damage value, which is based on the values entered on the General page. You can even add additional modifiers such as @{thrust}+3.",
"abbreviation-range-label": "RNG",
"range-tooltip": "Range. See B269.",
"shots-label": "Shots",
@@ -1072,7 +1073,8 @@
"latest-changes-updated-label": "Latest Changes: Updated",
"sheet-options-label": "Sheet Options",
"rules-label": "Rules",
- "import-label": "Import",
+ "import-label": "Import GCA4",
+ "import-json-label": "Import",
"critical-roll-options-label": "Critical Roll Options",
"user-rules-as-written-label": "Use rules as written",
"critical-miss-notes": "Roll on the appropriate Critical Miss Table (B556).",