Added pre-commit scripts and README with development instructions.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
node_modules/
|
||||
coverage/
|
||||
.idea
|
||||
.idea
|
||||
output/
|
||||
@@ -762,120 +762,122 @@
|
||||
</div>
|
||||
|
||||
<script type="text/worker">
|
||||
const sheetOpened = () => {
|
||||
sheetMigration()
|
||||
'use strict';
|
||||
|
||||
getAttrs(["btatow_sheet_version", ], ({
|
||||
btatow_sheet_version
|
||||
}) => {
|
||||
if (btatow_sheet_version >= 3) {
|
||||
recalculateSkills()
|
||||
}
|
||||
})
|
||||
}
|
||||
const STRENGTH_XP = "strength_xp";
|
||||
const BODY_XP = "body_xp";
|
||||
const REFLEX_XP = "reflex_xp";
|
||||
const DEXTERITY_XP = "dexterity_xp";
|
||||
const INTELLIGENCE_XP = "intelligence_xp";
|
||||
const WILL_XP = "will_xp";
|
||||
const CHARISMA_XP = "charisma_xp";
|
||||
const EDGE_XP = "edge_xp";
|
||||
|
||||
// run any data migrations
|
||||
on("sheet:opened", sheetOpened)
|
||||
const STRENGTH_LINK = "strength_link";
|
||||
const BODY_LINK = "body_link";
|
||||
const REFLEX_LINK = "reflex_link";
|
||||
const DEXTERITY_LINK = "dexterity_link";
|
||||
const INTELLIGENCE_LINK = "intelligence_link";
|
||||
const WILL_LINK = "will_link";
|
||||
const CHARISMA_LINK = "charisma_link";
|
||||
const EDGE_LINK = "edge_link";
|
||||
|
||||
const recalculateSkills = () => {
|
||||
getSectionIDs("skills", ids =>
|
||||
ids.forEach(
|
||||
id => getAttrs(["repeating_skills_" + id + "_skill_xp", ],
|
||||
values =>
|
||||
skillXPChanged({
|
||||
newValue: values["repeating_skills_" + id + "_skill_xp"],
|
||||
id,
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const STRENGTH_XP = "strength_xp"
|
||||
const BODY_XP = "body_xp"
|
||||
const REFLEX_XP = "reflex_xp"
|
||||
const DEXTERITY_XP = "dexterity_xp"
|
||||
const INTELLIGENCE_XP = "intelligence_xp"
|
||||
const WILL_XP = "will_xp"
|
||||
const CHARISMA_XP = "charisma_xp"
|
||||
const EDGE_XP = "edge_xp"
|
||||
|
||||
const STRENGTH_LINK = "strength_link"
|
||||
const BODY_LINK = "body_link"
|
||||
const REFLEX_LINK = "reflex_link"
|
||||
const DEXTERITY_LINK = "dexterity_link"
|
||||
const INTELLIGENCE_LINK = "intelligence_link"
|
||||
const WILL_LINK = "will_link"
|
||||
const CHARISMA_LINK = "charisma_link"
|
||||
const EDGE_LINK = "edge_link"
|
||||
const linkedAttributeDisplayNames = {
|
||||
STRENGTH_LINK: "STR",
|
||||
BODY_LINK: "BOD",
|
||||
REFLEX_LINK: "RFL",
|
||||
DEXTERITY_LINK: "DEX",
|
||||
INTELLIGENCE_LINK: "INT",
|
||||
WILL_LINK: "WIL",
|
||||
CHARISMA_LINK: "CHA",
|
||||
EDGE_LINK: "EDG",
|
||||
};
|
||||
|
||||
const calculateAbilityScore = ({
|
||||
sourceAttribute,
|
||||
newValue
|
||||
}) => {
|
||||
const attributeValue = Math.floor(newValue / 100)
|
||||
const attributeLinkedValue = calculateLinkedAttributeValue(attributeValue)
|
||||
if (typeof newValue !== "number") {
|
||||
console.error("Expected numerical value for attribute [ " + sourceAttribute + " ] but got [ " + newValue + " ]");
|
||||
return undefined
|
||||
}
|
||||
|
||||
let attributesToSet = {}
|
||||
const attributeValue = Math.floor(newValue / 100);
|
||||
const attributeLinkedValue = calculateLinkedAttributeValue(attributeValue);
|
||||
|
||||
let attribute;
|
||||
|
||||
switch (sourceAttribute) {
|
||||
case STRENGTH_XP:
|
||||
attributesToSet = {
|
||||
strength: attributeValue,
|
||||
strength_link: attributeLinkedValue,
|
||||
}
|
||||
attribute = {
|
||||
name: "strength",
|
||||
value: attributeValue,
|
||||
linkName: STRENGTH_LINK,
|
||||
linkValue: attributeLinkedValue,
|
||||
};
|
||||
break
|
||||
case BODY_XP:
|
||||
attributesToSet = {
|
||||
body: attributeValue,
|
||||
body_link: attributeLinkedValue,
|
||||
}
|
||||
attribute = {
|
||||
name: "body",
|
||||
value: attributeValue,
|
||||
linkName: BODY_LINK,
|
||||
linkValue: attributeLinkedValue,
|
||||
};
|
||||
break
|
||||
case REFLEX_XP:
|
||||
attributesToSet = {
|
||||
reflex: attributeValue,
|
||||
reflex_link: attributeLinkedValue,
|
||||
}
|
||||
attribute = {
|
||||
name: "reflex",
|
||||
value: attributeValue,
|
||||
linkName: REFLEX_LINK,
|
||||
linkValue: attributeLinkedValue,
|
||||
};
|
||||
break
|
||||
case DEXTERITY_XP:
|
||||
attributesToSet = {
|
||||
dexterity: attributeValue,
|
||||
dexterity_link: attributeLinkedValue,
|
||||
}
|
||||
attribute = {
|
||||
name: "dexterity",
|
||||
value: attributeValue,
|
||||
linkName: DEXTERITY_LINK,
|
||||
linkValue: attributeLinkedValue,
|
||||
};
|
||||
break
|
||||
case INTELLIGENCE_XP:
|
||||
attributesToSet = {
|
||||
intelligence: attributeValue,
|
||||
intelligence_link: attributeLinkedValue,
|
||||
}
|
||||
attribute = {
|
||||
name: "intelligence",
|
||||
value: attributeValue,
|
||||
linkName: INTELLIGENCE_LINK,
|
||||
linkValue: attributeLinkedValue,
|
||||
};
|
||||
break
|
||||
case WILL_XP:
|
||||
attributesToSet = {
|
||||
will: attributeValue,
|
||||
will_link: attributeLinkedValue,
|
||||
}
|
||||
attribute = {
|
||||
name: "will",
|
||||
value: attributeValue,
|
||||
linkName: WILL_LINK,
|
||||
linkValue: attributeLinkedValue,
|
||||
};
|
||||
break
|
||||
case CHARISMA_XP:
|
||||
attributesToSet = {
|
||||
charisma: attributeValue,
|
||||
charisma_link: attributeLinkedValue,
|
||||
}
|
||||
attribute = {
|
||||
name: "charisma",
|
||||
value: attributeValue,
|
||||
linkName: CHARISMA_LINK,
|
||||
linkValue: attributeLinkedValue,
|
||||
};
|
||||
break
|
||||
case EDGE_XP:
|
||||
attributesToSet = {
|
||||
edge: attributeValue,
|
||||
edge_link: attributeLinkedValue,
|
||||
}
|
||||
attribute = {
|
||||
name: "edge",
|
||||
value: attributeValue,
|
||||
linkName: EDGE_LINK,
|
||||
linkValue: attributeLinkedValue,
|
||||
};
|
||||
break
|
||||
default:
|
||||
console.error("unknown attribute type passed in to basic attribute on change function")
|
||||
console.error("unknown attribute type passed in to basic attribute on change function");
|
||||
}
|
||||
|
||||
setAttrs(attributesToSet, {}, recalculateSkills)
|
||||
}
|
||||
|
||||
// calculate stat values when XP amount changes
|
||||
on("change:strength_xp change:body_xp change:reflex_xp change:dexterity_xp change:intelligence_xp change:will_xp change:charisma_xp change:edge_xp", calculateAbilityScore)
|
||||
return attribute
|
||||
};
|
||||
|
||||
const calculateLinkedAttributeValue = attribute => {
|
||||
if (attribute > 10) {
|
||||
@@ -894,117 +896,7 @@ const calculateLinkedAttributeValue = attribute => {
|
||||
else
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
on("change:repeating_skills:skill change:repeating_skills:sub_skill", _ => {
|
||||
getAttrs(["repeating_skills_skill_xp", ], ({
|
||||
repeating_skills_skill_xp
|
||||
}) => {
|
||||
skillXPChanged({
|
||||
newValue: repeating_skills_skill_xp,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const skillXPChanged = ({
|
||||
id,
|
||||
newValue
|
||||
}) => {
|
||||
const tieredSkills = [
|
||||
"art",
|
||||
"computers",
|
||||
"interest",
|
||||
"martial",
|
||||
"melee",
|
||||
"prestidigitation",
|
||||
]
|
||||
|
||||
// When the sheet is opened, or data migrations are run, the skills are retrieved via ID, and thus must have their
|
||||
// ID included in the attribute name when setting attributes.
|
||||
const skillId = id !== undefined ? id + "_" : ""
|
||||
|
||||
const skill = "repeating_skills_" + skillId + "skill"
|
||||
const skillLevel = "repeating_skills_" + skillId + "skill_level"
|
||||
const subSkillAttrName = "repeating_skills_" + skillId + "sub_skill"
|
||||
|
||||
getAttrs([skill, subSkillAttrName, "learning_speed", ], values => {
|
||||
const skillName = values[skill]
|
||||
const skillNameLookupKey = skillName.split("_")[0]
|
||||
const subSkill = values[subSkillAttrName]
|
||||
|
||||
let skillAttributesToSet = {}
|
||||
|
||||
skillAttributesToSet[skillLevel] = calculateSkillLevel(Number(newValue), values.learning_speed)
|
||||
|
||||
const skillData = getSkill(
|
||||
skillNameLookupKey,
|
||||
skillAttributesToSet[skillLevel],
|
||||
tieredSkills.includes(skillNameLookupKey)
|
||||
)
|
||||
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_tnc"] = skillData.targetNumber + "/" + skillData.complexity
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "target_number"] = skillData.targetNumber
|
||||
|
||||
getAttrs(skillData.linkedAttributes, values => {
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_modifier"] = Object.values(values)
|
||||
.reduce((total, num) => Number(total) + Number(num)) + Number(skillAttributesToSet[skillLevel])
|
||||
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_linked_attributes"] = skillData.linkedAttributes
|
||||
.map(linkAtr => getLinkedAttributeDisplayName(linkAtr) + " (" + values[linkAtr] + ")")
|
||||
.join(" + ")
|
||||
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_roll_value"] =
|
||||
getSkillDisplayName(skillData, skillName, subSkill) + " Skill Check:\n" +
|
||||
"Margin of Success: [[2d6 + @{skill_modifier}[MOD] - @{target_number}[TN]]]"
|
||||
|
||||
setAttrs(skillAttributesToSet, {}, () => {})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// calculate skill modifiers when skill xp changes
|
||||
on("change:repeating_skills:skill_xp", skillXPChanged)
|
||||
|
||||
// recalculate all skills when learning speed modifier changes
|
||||
on("change:learning_speed", recalculateSkills)
|
||||
|
||||
const calculateSkillLevel = (skillXP, learningSpeedModifier) => {
|
||||
skillXP = Number(skillXP)
|
||||
learningSpeedModifier = Number(learningSpeedModifier)
|
||||
|
||||
if (skillXP < 30 + learningSpeedModifier * 3) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (skillXP >= 570 + learningSpeedModifier * 57) {
|
||||
return 10
|
||||
}
|
||||
|
||||
let currentSkillXP = skillXP - (20 + learningSpeedModifier * 2)
|
||||
|
||||
for (let i = 1; i < 11; i++) {
|
||||
if (currentSkillXP < i * (10 + learningSpeedModifier)) {
|
||||
return i - 1
|
||||
}
|
||||
|
||||
currentSkillXP -= i * (10 + learningSpeedModifier)
|
||||
}
|
||||
|
||||
console.error("should never hit this line, this means the skill XP is not less than level 1, not greater than level 10, but also not within a level range.")
|
||||
return undefined
|
||||
}
|
||||
|
||||
const getSkillDisplayName = (skill, skillDisplayNameKey, subSkill) => {
|
||||
if (skill.subSkills === true) {
|
||||
return skill.displayName[skillDisplayNameKey] + "/" + subSkill
|
||||
}
|
||||
|
||||
if (typeof subSkill === "string" && subSkill != "") {
|
||||
return skill.displayName[skillDisplayNameKey] + " (" + subSkill + ")"
|
||||
}
|
||||
|
||||
return skill.displayName[skillDisplayNameKey]
|
||||
}
|
||||
};
|
||||
|
||||
const skillsList = {
|
||||
"acrobatics": {
|
||||
@@ -1455,7 +1347,7 @@ const skillsList = {
|
||||
"zero_g_operations": "Zero-G Operations",
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const tieredSkillsBasic = {
|
||||
"art": {
|
||||
@@ -1514,7 +1406,7 @@ const tieredSkillsBasic = {
|
||||
"prestidigitation_sleight_of_hand": "Prestidigitation/Sleight of Hand",
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const tieredSkillsAdvanced = {
|
||||
"art": {
|
||||
@@ -1573,12 +1465,56 @@ const tieredSkillsAdvanced = {
|
||||
"prestidigitation_sleight_of_hand": "Prestidigitation/Sleight of Hand",
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const tieredSkills = [
|
||||
"art",
|
||||
"computers",
|
||||
"interest",
|
||||
"martial",
|
||||
"melee",
|
||||
"prestidigitation",
|
||||
];
|
||||
|
||||
const calculateSkillLevel = (skillXP, learningSpeedModifier) => {
|
||||
const learningSpeedPercentageModifier = 1 + 0.2 * learningSpeedModifier;
|
||||
|
||||
if (skillXP < 20 * learningSpeedPercentageModifier) {
|
||||
return -1
|
||||
}
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (skillXP < getXPForLevel(i + 1) * learningSpeedPercentageModifier)
|
||||
return i
|
||||
}
|
||||
|
||||
return 10
|
||||
};
|
||||
|
||||
const getXPForLevel = level => {
|
||||
let total = 0;
|
||||
|
||||
while (level > 0) {
|
||||
total += level * 10;
|
||||
level--;
|
||||
}
|
||||
|
||||
return total + 20
|
||||
};
|
||||
|
||||
const getSkillDisplayName = (skill, skillDisplayNameKey, subSkill) => {
|
||||
if (skill.subSkills === true) {
|
||||
return skill.displayName[skillDisplayNameKey] + "/" + subSkill
|
||||
}
|
||||
|
||||
if (typeof subSkill === "string" && subSkill != "") {
|
||||
return skill.displayName[skillDisplayNameKey] + " (" + subSkill + ")"
|
||||
}
|
||||
|
||||
return skill.displayName[skillDisplayNameKey]
|
||||
};
|
||||
|
||||
const getSkill = (skillName, skillLevel, tieredSkill) => {
|
||||
skillName = String(skillName)
|
||||
skillLevel = Number(skillLevel)
|
||||
|
||||
if (tieredSkill) {
|
||||
if (skillLevel <= 3) {
|
||||
return tieredSkillsBasic[skillName]
|
||||
@@ -1588,53 +1524,132 @@ const getSkill = (skillName, skillLevel, tieredSkill) => {
|
||||
} else {
|
||||
return skillsList[skillName]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getLinkedAttributeDisplayName = linkedAttributeName => {
|
||||
const linkedAttributeDisplayNames = {}
|
||||
linkedAttributeDisplayNames[STRENGTH_LINK] = "STR"
|
||||
linkedAttributeDisplayNames[BODY_LINK] = "BOD"
|
||||
linkedAttributeDisplayNames[REFLEX_LINK] = "RFL"
|
||||
linkedAttributeDisplayNames[DEXTERITY_LINK] = "DEX"
|
||||
linkedAttributeDisplayNames[INTELLIGENCE_LINK] = "INT"
|
||||
linkedAttributeDisplayNames[WILL_LINK] = "WIL"
|
||||
linkedAttributeDisplayNames[CHARISMA_LINK] = "CHA"
|
||||
linkedAttributeDisplayNames[EDGE_LINK] = "EDG"
|
||||
const sheetOpened = () => {
|
||||
sheetMigration();
|
||||
|
||||
return linkedAttributeDisplayNames[linkedAttributeName]
|
||||
}
|
||||
getAttrs(["btatow_sheet_version", ], ({
|
||||
btatow_sheet_version
|
||||
}) => {
|
||||
if (btatow_sheet_version >= 3) {
|
||||
recalculateSkills();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// run any data migrations
|
||||
on("sheet:opened", sheetOpened);
|
||||
|
||||
const recalculateSkills = () => {
|
||||
getSectionIDs("skills", ids =>
|
||||
ids.forEach(
|
||||
id => getAttrs(["repeating_skills_" + id + "_skill_xp", ],
|
||||
values =>
|
||||
skillXPChanged({
|
||||
newValue: values["repeating_skills_" + id + "_skill_xp"],
|
||||
id,
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
// calculate stat values when XP amount changes
|
||||
on("change:strength_xp change:body_xp change:reflex_xp change:dexterity_xp change:intelligence_xp change:will_xp change:charisma_xp change:edge_xp", calculateAbilityScore);
|
||||
|
||||
on("change:repeating_skills:skill change:repeating_skills:sub_skill", _ => {
|
||||
getAttrs(["repeating_skills_skill_xp", ], ({
|
||||
repeating_skills_skill_xp
|
||||
}) => {
|
||||
skillXPChanged({
|
||||
newValue: repeating_skills_skill_xp,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const skillXPChanged = ({
|
||||
id,
|
||||
newValue
|
||||
}) => {
|
||||
// When the sheet is opened, or data migrations are run, the skills are retrieved via ID, and thus must have their
|
||||
// ID included in the attribute name when setting attributes.
|
||||
const skillId = id !== undefined ? id + "_" : "";
|
||||
|
||||
const skill = "repeating_skills_" + skillId + "skill";
|
||||
const skillLevel = "repeating_skills_" + skillId + "skill_level";
|
||||
const subSkillAttrName = "repeating_skills_" + skillId + "sub_skill";
|
||||
|
||||
getAttrs([skill, subSkillAttrName, "learning_speed", ], values => {
|
||||
const skillName = values[skill];
|
||||
const skillNameLookupKey = skillName.split("_")[0];
|
||||
const subSkill = values[subSkillAttrName];
|
||||
|
||||
let skillAttributesToSet = {};
|
||||
|
||||
skillAttributesToSet[skillLevel] = calculateSkillLevel(Number(newValue), values.learning_speed);
|
||||
|
||||
const skillData = getSkill(
|
||||
skillNameLookupKey,
|
||||
skillAttributesToSet[skillLevel],
|
||||
tieredSkills.includes(skillNameLookupKey)
|
||||
);
|
||||
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_tnc"] = skillData.targetNumber + "/" + skillData.complexity;
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "target_number"] = skillData.targetNumber;
|
||||
|
||||
getAttrs(skillData.linkedAttributes, values => {
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_modifier"] = Object.values(values)
|
||||
.reduce((total, num) => Number(total) + Number(num)) + Number(skillAttributesToSet[skillLevel]);
|
||||
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_linked_attributes"] = skillData.linkedAttributes
|
||||
.map(linkAtr => linkedAttributeDisplayNames[linkAtr] + " (" + values[linkAtr] + ")")
|
||||
.join(" + ");
|
||||
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_roll_value"] =
|
||||
getSkillDisplayName(skillData, skillName, subSkill) + " Skill Check:\n" +
|
||||
"Margin of Success: [[2d6 + @{skill_modifier}[MOD] - @{target_number}[TN]]]";
|
||||
|
||||
setAttrs(skillAttributesToSet, {}, () => {});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// calculate skill modifiers when skill xp changes
|
||||
on("change:repeating_skills:skill_xp", skillXPChanged);
|
||||
|
||||
// recalculate all skills when learning speed modifier changes
|
||||
on("change:learning_speed", recalculateSkills);
|
||||
|
||||
const sheetMigration = () => {
|
||||
console.log("Running sheet data migration")
|
||||
console.log("Running sheet data migration");
|
||||
|
||||
let sheetVersionAttributeName = "btatow_sheet_version"
|
||||
let currentVersion = 3
|
||||
let sheetVersionAttributeName = "btatow_sheet_version";
|
||||
let currentVersion = 3;
|
||||
|
||||
getAttrs([sheetVersionAttributeName, ], sheetVersionAttribute => {
|
||||
let sheetVersion = Number(sheetVersionAttribute[sheetVersionAttributeName])
|
||||
let sheetVersion = Number(sheetVersionAttribute[sheetVersionAttributeName]);
|
||||
// Check if we should do the migration
|
||||
if (isNaN(sheetVersion)) {
|
||||
console.error("No sheet version defined, unable to determine if sheet data needs to be migrated.")
|
||||
console.error("No sheet version defined, unable to determine if sheet data needs to be migrated.");
|
||||
return
|
||||
}
|
||||
|
||||
if (sheetVersion === currentVersion) {
|
||||
console.log("No migration needed")
|
||||
console.log("No migration needed");
|
||||
return
|
||||
}
|
||||
|
||||
switch (sheetVersion) {
|
||||
case 1:
|
||||
migrateFrom1To2()
|
||||
migrateFrom1To2();
|
||||
break
|
||||
case 2:
|
||||
migrateFrom2To3()
|
||||
break
|
||||
default:
|
||||
migrateFrom2To3();
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Migrate attribute data from version 1 to version 2
|
||||
const migrateFrom1To2 = () => {
|
||||
@@ -1647,7 +1662,7 @@ const migrateFrom1To2 = () => {
|
||||
"WILXP",
|
||||
"CHAXP",
|
||||
"EDGXP",
|
||||
]
|
||||
];
|
||||
const newAttributeNames = [
|
||||
"strength_xp",
|
||||
"body_xp",
|
||||
@@ -1657,93 +1672,93 @@ const migrateFrom1To2 = () => {
|
||||
"will_xp",
|
||||
"charisma_xp",
|
||||
"edge_xp",
|
||||
]
|
||||
];
|
||||
|
||||
let newAttributes = {}
|
||||
let newAttributes = {};
|
||||
|
||||
console.log("Starting migration from version 1 to version 2.")
|
||||
console.log("Starting migration from version 1 to version 2.");
|
||||
|
||||
getAttrs(oldAttributeNames, attributes => {
|
||||
console.debug("Attributes fetched: " + JSON.stringify(attributes))
|
||||
console.debug("Attributes fetched: " + JSON.stringify(attributes));
|
||||
for (let i = 0; i < oldAttributeNames.length; i++) {
|
||||
if (attributes[oldAttributeNames[i]] !== undefined) {
|
||||
console.debug("Attributes[" + oldAttributeNames[i] + "]: " + attributes[oldAttributeNames[i]])
|
||||
newAttributes[newAttributeNames[i]] = attributes[oldAttributeNames[i]]
|
||||
console.debug("Attributes[" + oldAttributeNames[i] + "]: " + attributes[oldAttributeNames[i]]);
|
||||
newAttributes[newAttributeNames[i]] = attributes[oldAttributeNames[i]];
|
||||
}
|
||||
}
|
||||
|
||||
console.debug("New attributes: " + JSON.stringify(newAttributes))
|
||||
console.debug("New attributes: " + JSON.stringify(newAttributes));
|
||||
|
||||
setAttrs(newAttributes, {}, () => {
|
||||
setAttrs({
|
||||
btatow_sheet_version: "2",
|
||||
}, {}, () => {
|
||||
console.log("Sheet data migration completed")
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
console.log("Sheet data migration completed");
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Migrate skills data from version 2 to version 3
|
||||
const migrateFrom2To3 = () => {
|
||||
console.log("Starting migration from version 2 to version 3.")
|
||||
console.log("Starting migration from version 2 to version 3.");
|
||||
|
||||
getSectionIDs("skills", ids => {
|
||||
let skillsUpdated = 0
|
||||
let skillsUpdated = 0;
|
||||
|
||||
ids.forEach(id => {
|
||||
const oldSkillDataNames = {
|
||||
skill: "repeating_skills_" + id + "_skill",
|
||||
subSkill: "repeating_skills_" + id + "_skillNotes",
|
||||
xp: "repeating_skills_" + id + "_skillXP",
|
||||
}
|
||||
};
|
||||
const newSkillDataNames = {
|
||||
skill: "repeating_skills_" + id + "_skill",
|
||||
subSkill: "repeating_skills_" + id + "_sub_skill",
|
||||
xp: "repeating_skills_" + id + "_skill_xp",
|
||||
}
|
||||
};
|
||||
getAttrs(Object.values(oldSkillDataNames), oldSkillValues => {
|
||||
const oldSkillName = oldSkillValues[oldSkillDataNames.skill]
|
||||
const oldSkillSubSkillName = oldSkillValues[oldSkillDataNames.subSkill]
|
||||
const oldSkillName = oldSkillValues[oldSkillDataNames.skill];
|
||||
const oldSkillSubSkillName = oldSkillValues[oldSkillDataNames.subSkill];
|
||||
|
||||
if (oldSkillName === undefined || oldSkillValues[oldSkillDataNames.xp] === undefined) {
|
||||
console.error("Old skill data is missing values, unable to migrate.\n" + JSON.stringify(oldSkillValues))
|
||||
skillsUpdated++
|
||||
console.error("Old skill data is missing values, unable to migrate.\n" + JSON.stringify(oldSkillValues));
|
||||
skillsUpdated++;
|
||||
return
|
||||
}
|
||||
|
||||
let parsedSkillName = oldSkillName.toLowerCase()
|
||||
.replace(" ", "_")
|
||||
.replace("-", "_")
|
||||
.replace("-", "_");
|
||||
|
||||
const skillFirstName = parsedSkillName.split("_")[0]
|
||||
const skillFirstName = parsedSkillName.split("_")[0];
|
||||
|
||||
let skillData = {}
|
||||
const newSkillValues = {}
|
||||
let skillData = {};
|
||||
const newSkillValues = {};
|
||||
|
||||
if (skillFirstName in skillsList) {
|
||||
skillData = skillsList[skillFirstName]
|
||||
skillData = skillsList[skillFirstName];
|
||||
} else if (skillFirstName in tieredSkillsBasic) {
|
||||
skillData = tieredSkillsBasic[skillFirstName]
|
||||
skillData = tieredSkillsBasic[skillFirstName];
|
||||
} else if (skillFirstName.substring(0, skillFirstName.length - 1) in tieredSkillsBasic) {
|
||||
skillData = tieredSkillsBasic[skillFirstName.substring(0, skillFirstName.length - 1)]
|
||||
parsedSkillName = parsedSkillName.substring(0, parsedSkillName.length - 1)
|
||||
skillData = tieredSkillsBasic[skillFirstName.substring(0, skillFirstName.length - 1)];
|
||||
parsedSkillName = parsedSkillName.substring(0, parsedSkillName.length - 1);
|
||||
} else {
|
||||
console.error("Unable to migrate skill data. Old values are: " + JSON.stringify(oldSkillValues))
|
||||
skillsUpdated++
|
||||
console.error("Unable to migrate skill data. Old values are: " + JSON.stringify(oldSkillValues));
|
||||
skillsUpdated++;
|
||||
return
|
||||
}
|
||||
|
||||
let skillName = ""
|
||||
let displaySubSkill = true
|
||||
let skillName = "";
|
||||
let displaySubSkill = true;
|
||||
|
||||
if (parsedSkillName in skillData.displayName) {
|
||||
skillName = parsedSkillName
|
||||
skillName = parsedSkillName;
|
||||
} else if (parsedSkillName.substring(0, parsedSkillName.length - 1) in skillData.displayName) {
|
||||
skillName = parsedSkillName.substring(0, parsedSkillName.length - 1)
|
||||
skillName = parsedSkillName.substring(0, parsedSkillName.length - 1);
|
||||
} else if (oldSkillSubSkillName === undefined) {
|
||||
console.error("Unable to identify skill. Old skill name: " + oldSkillName)
|
||||
skillsUpdated++
|
||||
console.error("Unable to identify skill. Old skill name: " + oldSkillName);
|
||||
skillsUpdated++;
|
||||
return
|
||||
} else {
|
||||
const parsedSubSkillName = oldSkillSubSkillName.trim()
|
||||
@@ -1751,45 +1766,41 @@ const migrateFrom2To3 = () => {
|
||||
.replace("`", "")
|
||||
.replace("-", "_")
|
||||
.replace("/", "_")
|
||||
.toLowerCase()
|
||||
.toLowerCase();
|
||||
|
||||
const skillWithSubSkill = parsedSkillName + "_" + parsedSubSkillName
|
||||
const skillWithSubSkill = parsedSkillName + "_" + parsedSubSkillName;
|
||||
|
||||
if (skillWithSubSkill in skillData.displayName) {
|
||||
skillName = skillWithSubSkill
|
||||
displaySubSkill = false
|
||||
skillName = skillWithSubSkill;
|
||||
displaySubSkill = false;
|
||||
} else {
|
||||
console.error("Unable to identify skill. Old skill name and notes: " + oldSkillName + " " + oldSkillSubSkillName)
|
||||
skillsUpdated++
|
||||
console.error("Unable to identify skill. Old skill name and notes: " + oldSkillName + " " + oldSkillSubSkillName);
|
||||
skillsUpdated++;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
newSkillValues[newSkillDataNames.skill] = skillName
|
||||
newSkillValues[newSkillDataNames.skill] = skillName;
|
||||
if (displaySubSkill && oldSkillSubSkillName !== undefined) {
|
||||
newSkillValues[newSkillDataNames.subSkill] = oldSkillSubSkillName
|
||||
newSkillValues[newSkillDataNames.subSkill] = oldSkillSubSkillName;
|
||||
}
|
||||
newSkillValues[newSkillDataNames.xp] = oldSkillValues[oldSkillDataNames.xp]
|
||||
newSkillValues[newSkillDataNames.xp] = oldSkillValues[oldSkillDataNames.xp];
|
||||
|
||||
setAttrs(newSkillValues, {}, () => {
|
||||
skillsUpdated++
|
||||
skillsUpdated++;
|
||||
|
||||
if (skillsUpdated === ids.length) {
|
||||
setAttrs({
|
||||
btatow_sheet_version: 3,
|
||||
}, {}, () => {
|
||||
console.log("Sheet migrated from version 2 to version 3.")
|
||||
recalculateSkills()
|
||||
})
|
||||
console.log("Sheet migrated from version 2 to version 3.");
|
||||
recalculateSkills();
|
||||
});
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// exports for testing
|
||||
// export {
|
||||
// calculateLinkedAttributeValue
|
||||
// }
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# BattleTech - A Time of War Character Sheet
|
||||
|
||||
## Development Notes
|
||||
|
||||
The character sheet for BattleTech - A Time of War is not as straightforward as other character sheets. However, it is hopefully easier to develop.
|
||||
|
||||
Since the majority of IDEs recognise a file based on its file extension, having the sheet worker JavaScript in the same HTML file as the character sheet results in the IDE not being able to give you any help with your JavaScript code. To rectify this problem, the sheet worker code has been pulled out into multiple separate JavaScript files. The main file is the [sheet-worker.js](https://github.com/Roll20/roll20-character-sheets/blob/master/BattleTech-A-Time-of-War/development/src/sheet-worker.js) file, with other separate files for the different pieces of functionality. All changes to the sheet worker code should be made to these files.
|
||||
|
||||
Once your changes have been made, there are two steps you need to do before committing. You'll need a few programs as well.
|
||||
|
||||
1. [npm](https://www.npmjs.com/get-npm)
|
||||
2. [Python](https://www.python.org/downloads/)
|
||||
|
||||
Once npm is installed, run `npm -i` in the development directory to install the libraries needed.
|
||||
|
||||
After making your code changes:
|
||||
1. Run `npm test` in the development directory to automatically run the unit tests. If any of the tests fail, check your changes; you must have made a mistake in your code.
|
||||
2. Run `python3 main.py` in the pre-commit-script directory. This will combine all the JavaScript into a single file, then insert the JavaScript into the character sheet HTML file.
|
||||
+87
-6
@@ -1571,6 +1571,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-babel": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.2.tgz",
|
||||
"integrity": "sha512-MjmH7GvFT4TW8xFdIeFS3wqIX646y5tACdxkTO+khbHvS3ZcVJL6vkAHLw2wqPmkhwCfWHoNsp15VYNwW6JEJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.10.4",
|
||||
"@rollup/pluginutils": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"@rollup/pluginutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
|
||||
"integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/estree": "0.0.39",
|
||||
"estree-walker": "^1.0.1",
|
||||
"picomatch": "^2.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"estree-walker": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
|
||||
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@sinonjs/commons": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz",
|
||||
@@ -1630,6 +1659,12 @@
|
||||
"@babel/types": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"@types/estree": {
|
||||
"version": "0.0.39",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
|
||||
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/graceful-fs": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.4.tgz",
|
||||
@@ -1887,12 +1922,6 @@
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"dev": true
|
||||
},
|
||||
"babel": {
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
|
||||
"integrity": "sha1-0NHn2APpdHZb7qMjLU4VPA77kPQ=",
|
||||
"dev": true
|
||||
},
|
||||
"babel-jest": {
|
||||
"version": "26.6.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz",
|
||||
@@ -1973,6 +2002,15 @@
|
||||
"babel-preset-current-node-syntax": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"babelrc-rollup": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babelrc-rollup/-/babelrc-rollup-3.0.0.tgz",
|
||||
"integrity": "sha1-/Ozb4+tkAM9OdpIzwXhqL6/otWw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"resolve": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
@@ -2905,6 +2943,12 @@
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||
"dev": true
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
|
||||
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
|
||||
"dev": true
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
@@ -5474,6 +5518,43 @@
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.35.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.35.1.tgz",
|
||||
"integrity": "sha512-q5KxEyWpprAIcainhVy6HfRttD9kutQpHbeqDTWnqAFNJotiojetK6uqmcydNMymBEtC4I8bCYR+J3mTMqeaUA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"fsevents": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
||||
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"rollup-plugin-babel": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz",
|
||||
"integrity": "sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"rollup-pluginutils": "^2.8.1"
|
||||
}
|
||||
},
|
||||
"rollup-pluginutils": {
|
||||
"version": "2.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
|
||||
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"estree-walker": "^0.6.1"
|
||||
}
|
||||
},
|
||||
"rsvp": {
|
||||
"version": "4.8.5",
|
||||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
"name": "battletech-a-time-of-war",
|
||||
"version": "1.0.0",
|
||||
"description": "Character sheet for Roll20 for the A Time of War TTRPG system.",
|
||||
"main": "index.js",
|
||||
"main": "sheet-worker.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "jest --silent --coverage"
|
||||
"test": "jest --silent --coverage",
|
||||
"compile": "npx rollup src/sheet-worker.js --file output/sheet-worker.js --format cjs"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
@@ -14,7 +15,10 @@
|
||||
"@babel/core": "^7.12.9",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.12.7",
|
||||
"@rollup/plugin-babel": "^5.2.2",
|
||||
"babelrc-rollup": "^3.0.0",
|
||||
"eslint": "^7.15.0",
|
||||
"jest": "^26.6.3"
|
||||
"jest": "^26.6.3",
|
||||
"rollup": "^2.35.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import {
|
||||
STRENGTH_LINK,
|
||||
BODY_LINK,
|
||||
REFLEX_LINK,
|
||||
DEXTERITY_LINK,
|
||||
INTELLIGENCE_LINK,
|
||||
WILL_LINK,
|
||||
CHARISMA_LINK,
|
||||
calculateAbilityScore,
|
||||
linkedAttributeDisplayNames
|
||||
} from './domain/attribute'
|
||||
} from './attributes'
|
||||
import {
|
||||
calculateSkillLevel,
|
||||
getSkill,
|
||||
getSkillDisplayName
|
||||
} from './skills'
|
||||
import {
|
||||
skillsList,
|
||||
tieredSkillsBasic,
|
||||
tieredSkills
|
||||
} from './domain/skills/skills-list'
|
||||
|
||||
const sheetOpened = () => {
|
||||
sheetMigration()
|
||||
@@ -56,15 +59,6 @@ const skillXPChanged = ({
|
||||
id,
|
||||
newValue
|
||||
}) => {
|
||||
const tieredSkills = [
|
||||
"art",
|
||||
"computers",
|
||||
"interest",
|
||||
"martial",
|
||||
"melee",
|
||||
"prestidigitation",
|
||||
]
|
||||
|
||||
// When the sheet is opened, or data migrations are run, the skills are retrieved via ID, and thus must have their
|
||||
// ID included in the attribute name when setting attributes.
|
||||
const skillId = id !== undefined ? id + "_" : ""
|
||||
@@ -114,628 +108,6 @@ on("change:repeating_skills:skill_xp", skillXPChanged)
|
||||
// recalculate all skills when learning speed modifier changes
|
||||
on("change:learning_speed", recalculateSkills)
|
||||
|
||||
const calculateSkillLevel = (skillXP, learningSpeedModifier) => {
|
||||
skillXP = Number(skillXP)
|
||||
learningSpeedModifier = Number(learningSpeedModifier)
|
||||
|
||||
if (skillXP < 30 + learningSpeedModifier * 3) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (skillXP >= 570 + learningSpeedModifier * 57) {
|
||||
return 10
|
||||
}
|
||||
|
||||
let currentSkillXP = skillXP - (20 + learningSpeedModifier * 2)
|
||||
|
||||
for (let i = 1; i < 11; i++) {
|
||||
if (currentSkillXP < i * (10 + learningSpeedModifier)) {
|
||||
return i - 1
|
||||
}
|
||||
|
||||
currentSkillXP -= i * (10 + learningSpeedModifier)
|
||||
}
|
||||
|
||||
console.error("should never hit this line, this means the skill XP is not less than level 1, not greater than level 10, but also not within a level range.")
|
||||
return undefined
|
||||
}
|
||||
|
||||
const getSkillDisplayName = (skill, skillDisplayNameKey, subSkill) => {
|
||||
if (skill.subSkills === true) {
|
||||
return skill.displayName[skillDisplayNameKey] + "/" + subSkill
|
||||
}
|
||||
|
||||
if (typeof subSkill === "string" && subSkill != "") {
|
||||
return skill.displayName[skillDisplayNameKey] + " (" + subSkill + ")"
|
||||
}
|
||||
|
||||
return skill.displayName[skillDisplayNameKey]
|
||||
}
|
||||
|
||||
const skillsList = {
|
||||
"acrobatics": {
|
||||
"linkedAttributes": [REFLEX_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"acrobatics_free_fall": "Acrobatics/Free-Fall",
|
||||
"acrobatics_gymnastics": "Acrobatics/Gymnastics",
|
||||
},
|
||||
},
|
||||
"acting": {
|
||||
"linkedAttributes": [CHARISMA_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "CB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"acting": "Acting",
|
||||
},
|
||||
},
|
||||
"administration": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"administration": "Administration",
|
||||
},
|
||||
},
|
||||
"animal": {
|
||||
"linkedAttributes": [WILL_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"animal_handling_herding": "Animal Handling/Herding",
|
||||
"animal_handling_riding": "Animal Handling/Riding",
|
||||
"animal_handling_training": "Animal Handling/Training",
|
||||
},
|
||||
},
|
||||
"appraisal": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "CB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"appraisal": "Appraisal",
|
||||
},
|
||||
},
|
||||
"archery": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"archery": "Archery",
|
||||
},
|
||||
},
|
||||
"artillery": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"artillery": "Artillery",
|
||||
},
|
||||
},
|
||||
"career": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"career": "Career",
|
||||
},
|
||||
},
|
||||
"climbing": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"climbing": "Climbing",
|
||||
},
|
||||
},
|
||||
"communications": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"communications_black_box": "Communications/Black Box",
|
||||
"communications_conventional_em": "Communications/Conventional (EM)",
|
||||
"communications_hyperpulse_generator": "Communications/Hyperpulse Generator",
|
||||
},
|
||||
},
|
||||
"cryptography": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"cryptography": "Cryptography",
|
||||
},
|
||||
},
|
||||
"demolitions": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"demolitions": "Demolitions",
|
||||
},
|
||||
},
|
||||
"disguise": {
|
||||
"linkedAttributes": [CHARISMA_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"disguise": "Disguise",
|
||||
},
|
||||
},
|
||||
"driving": {
|
||||
"linkedAttributes": [REFLEX_LINK, DEXTERITY_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"driving_ground_vehicles": "Driving/Ground Vehicles",
|
||||
"driving_rail_vehicles": "Driving/Rail Vehicles",
|
||||
"driving_sea_vehicles": "Driving/Sea Vehicles",
|
||||
},
|
||||
},
|
||||
"escape": {
|
||||
"linkedAttributes": [STRENGTH_LINK, DEXTERITY_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"escape_artist": "Escape Artist",
|
||||
},
|
||||
},
|
||||
"forgery": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"forgery": "Forgery",
|
||||
},
|
||||
},
|
||||
"gunnery": {
|
||||
"linkedAttributes": [REFLEX_LINK, DEXTERITY_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"gunnery_aerospace": "Gunnery/Aerospace",
|
||||
"gunnery_air_vehicle": "Gunnery/Air Vehicle",
|
||||
"gunnery_battlesuit": "Gunnery/Battlesuit",
|
||||
"gunnery_ground_vehicle": "Gunnery/Ground Vehicle",
|
||||
"gunnery_mech": "Gunnery/'Mech",
|
||||
"gunnery_protomech": "Gunnery/ProtoMech",
|
||||
"gunnery_sea_vehicle": "Gunnery/Sea Vehicle",
|
||||
"gunnery_spacecraft": "Gunnery/Spacecraft",
|
||||
"gunnery_turret": "Gunnery/Turret",
|
||||
},
|
||||
},
|
||||
"interrogation": {
|
||||
"linkedAttributes": [WILL_LINK, CHARISMA_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"interrogation": "Interrogation",
|
||||
},
|
||||
},
|
||||
"investigation": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"investigation": "Investigation",
|
||||
},
|
||||
},
|
||||
"language": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, CHARISMA_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"language": "Language",
|
||||
},
|
||||
},
|
||||
"leadership": {
|
||||
"linkedAttributes": [WILL_LINK, CHARISMA_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"leadership": "Leadership",
|
||||
},
|
||||
},
|
||||
"medtech": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"medtech_general": "MedTech/General",
|
||||
"medtech_veterinary": "MedTech/Veterinary",
|
||||
},
|
||||
},
|
||||
"navigation": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"navigation_air": "Navigation/Air",
|
||||
"navigation_ground": "Navigation/Ground",
|
||||
"navigation_kf_jump": "Navigation/K-F Jump",
|
||||
"navigation_sea": "Navigation/Sea",
|
||||
"navigation_space": "Navigation/Space",
|
||||
},
|
||||
},
|
||||
"negotiation": {
|
||||
"linkedAttributes": [CHARISMA_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "CB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"negotiation": "Negotiation",
|
||||
},
|
||||
},
|
||||
"perception": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"perception": "Perception",
|
||||
},
|
||||
},
|
||||
"piloting": {
|
||||
"linkedAttributes": [REFLEX_LINK, DEXTERITY_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"piloting_aerospace": "Piloting/Aerospace",
|
||||
"piloting_air_vehicle": "Piloting/Air Vehicle",
|
||||
"piloting_battlesuit": "Piloting/Battlesuit",
|
||||
"piloting_ground_vehicle": "Piloting/Ground Vehicle",
|
||||
"piloting_mech": "Piloting/'Mech",
|
||||
"piloting_protomech": "Piloting/ProtoMech",
|
||||
"piloting_rail_vehicle": "Piloting/Rail Vehicle",
|
||||
"piloting_sea_vehicle": "Piloting/Sea Vehicle",
|
||||
"piloting_spacecraft": "Piloting/Spacecraft",
|
||||
},
|
||||
},
|
||||
"protocol": {
|
||||
"linkedAttributes": [WILL_LINK, CHARISMA_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"protocol": "Protocol",
|
||||
},
|
||||
},
|
||||
"running": {
|
||||
"linkedAttributes": [REFLEX_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"running": "Running",
|
||||
},
|
||||
},
|
||||
"science": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"science": "Science",
|
||||
},
|
||||
},
|
||||
"security": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"security_systems_electronic": "Security Systems/Electronic",
|
||||
"security_systems_mechanical": "Security Systems/Mechanical",
|
||||
},
|
||||
},
|
||||
"sensor": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"sensor_operations": "Sensor Operations",
|
||||
},
|
||||
},
|
||||
"small": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"small_arms": "Small Arms",
|
||||
},
|
||||
},
|
||||
"stealth": {
|
||||
"linkedAttributes": [REFLEX_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"stealth": "Stealth",
|
||||
},
|
||||
},
|
||||
"strategy": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"strategy": "Strategy",
|
||||
},
|
||||
},
|
||||
"streetwise": {
|
||||
"linkedAttributes": [CHARISMA_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "CB",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"streetwise": "Streetwise",
|
||||
},
|
||||
},
|
||||
"support": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"support_weapons": "Support Weapons",
|
||||
},
|
||||
},
|
||||
"surgery": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"surgery_general": "Surgery/General",
|
||||
"surgery_veterinary": "Surgery/Veterinary",
|
||||
},
|
||||
},
|
||||
"survival": {
|
||||
"linkedAttributes": [BODY_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"survival": "Survival",
|
||||
},
|
||||
},
|
||||
"swimming": {
|
||||
"linkedAttributes": [STRENGTH_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"swimming": "Swimming",
|
||||
},
|
||||
},
|
||||
"tactics": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"tactics_air": "Tactics/Air",
|
||||
"tactics_infantry": "Tactics/Infantry",
|
||||
"tactics_land": "Tactics/Land",
|
||||
"tactics_sea": "Tactics/Sea",
|
||||
"tactics_space": "Tactics/Space",
|
||||
},
|
||||
},
|
||||
"technician": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"technician_aeronautics": "Technician/Aeronautics",
|
||||
"technician_cybernetics": "Technician/Cybernetics",
|
||||
"technician_electronic": "Technician/Electronic",
|
||||
"technician_jets": "Technician/Jets",
|
||||
"technician_mechanical": "Technician/Mechanical",
|
||||
"technician_myomer": "Technician/Myomer",
|
||||
"technician_nuclear": "Technician/Nuclear",
|
||||
"technician_weapons": "Technician/Weapons",
|
||||
},
|
||||
},
|
||||
"thrown": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"thrown_weapons_blades": "Thrown Weapons/Blades",
|
||||
"thrown_weapons_blunt_weapons": "Thrown Weapons/Blunt Weapons",
|
||||
},
|
||||
},
|
||||
"tracking": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"tracking_urban": "Tracking/Urban",
|
||||
"tracking_wilds": "Tracking/Wilds",
|
||||
},
|
||||
},
|
||||
"training": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, CHARISMA_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"training": "Training",
|
||||
},
|
||||
},
|
||||
"zero": {
|
||||
"linkedAttributes": [REFLEX_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"zero_g_operations": "Zero-G Operations",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const tieredSkillsBasic = {
|
||||
"art": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "CB",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"art": "Art",
|
||||
},
|
||||
},
|
||||
"computers": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "CB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"computers": "Computers",
|
||||
},
|
||||
},
|
||||
"interest": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "CB",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"interest": "Interest",
|
||||
},
|
||||
},
|
||||
"martial": {
|
||||
"linkedAttributes": [REFLEX_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"martial_arts": "Martial Arts",
|
||||
},
|
||||
},
|
||||
"melee": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"melee_weapons": "Melee Weapons",
|
||||
},
|
||||
},
|
||||
"prestidigitation": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, ],
|
||||
"targetNumber": 7,
|
||||
"complexity": "SB",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"prestidigitation_pick_pocket": "Prestidigitation/Pick Pocket",
|
||||
"prestidigitation_quickdraw": "Prestidigitation/Quickdraw",
|
||||
"prestidigitation_sleight_of_hand": "Prestidigitation/Sleight of Hand",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const tieredSkillsAdvanced = {
|
||||
"art": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"art": "Art",
|
||||
},
|
||||
},
|
||||
"computers": {
|
||||
"linkedAttributes": [DEXTERITY_LINK, INTELLIGENCE_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"computers": "Computers",
|
||||
},
|
||||
},
|
||||
"interest": {
|
||||
"linkedAttributes": [INTELLIGENCE_LINK, WILL_LINK, ],
|
||||
"targetNumber": 9,
|
||||
"complexity": "CA",
|
||||
"subSkills": true,
|
||||
"displayName": {
|
||||
"interest": "Interest",
|
||||
},
|
||||
},
|
||||
"martial": {
|
||||
"linkedAttributes": [REFLEX_LINK, DEXTERITY_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"martial_arts": "Martial Arts",
|
||||
},
|
||||
},
|
||||
"melee": {
|
||||
"linkedAttributes": [REFLEX_LINK, DEXTERITY_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"melee_weapons": "Melee Weapons",
|
||||
},
|
||||
},
|
||||
"prestidigitation": {
|
||||
"linkedAttributes": [REFLEX_LINK, DEXTERITY_LINK, ],
|
||||
"targetNumber": 8,
|
||||
"complexity": "SA",
|
||||
"subSkills": false,
|
||||
"displayName": {
|
||||
"prestidigitation_pick_pocket": "Prestidigitation/Pick Pocket",
|
||||
"prestidigitation_quickdraw": "Prestidigitation/Quickdraw",
|
||||
"prestidigitation_sleight_of_hand": "Prestidigitation/Sleight of Hand",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const getSkill = (skillName, skillLevel, tieredSkill) => {
|
||||
skillName = String(skillName)
|
||||
skillLevel = Number(skillLevel)
|
||||
|
||||
if (tieredSkill) {
|
||||
if (skillLevel <= 3) {
|
||||
return tieredSkillsBasic[skillName]
|
||||
} else {
|
||||
return tieredSkillsAdvanced[skillName]
|
||||
}
|
||||
} else {
|
||||
return skillsList[skillName]
|
||||
}
|
||||
}
|
||||
|
||||
const sheetMigration = () => {
|
||||
console.log("Running sheet data migration")
|
||||
|
||||
@@ -918,9 +290,4 @@ const migrateFrom2To3 = () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// exports for testing
|
||||
// export {
|
||||
// calculateLinkedAttributeValue
|
||||
// }
|
||||
}
|
||||
@@ -8,76 +8,52 @@ import {
|
||||
tieredSkillsAdvanced
|
||||
} from './domain/skills/skills-list'
|
||||
|
||||
// const recalculateSkills = () => {
|
||||
// getSectionIDs("skills", ids =>
|
||||
// ids.forEach(
|
||||
// id => getAttrs(["repeating_skills_" + id + "_skill_xp", ],
|
||||
// values =>
|
||||
// skillXPChanged({
|
||||
// newValue: values["repeating_skills_" + id + "_skill_xp"],
|
||||
// id,
|
||||
// })
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
const skillXPChanged = ({
|
||||
id,
|
||||
newValue
|
||||
}) => {
|
||||
// When the sheet is opened, or data migrations are run, the skills are retrieved via ID, and thus must have their
|
||||
// ID included in the attribute name when setting attributes.
|
||||
const skillId = id !== undefined ? id + "_" : ""
|
||||
|
||||
// on("change:repeating_skills:skill change:repeating_skills:sub_skill", _ => {
|
||||
// getAttrs(["repeating_skills_skill_xp", ], ({
|
||||
// repeating_skills_skill_xp
|
||||
// }) => {
|
||||
// skillXPChanged({
|
||||
// newValue: repeating_skills_skill_xp,
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
const skill = "repeating_skills_" + skillId + "skill"
|
||||
const skillLevel = "repeating_skills_" + skillId + "skill_level"
|
||||
const subSkillAttrName = "repeating_skills_" + skillId + "sub_skill"
|
||||
|
||||
// const skillXPChanged = ({
|
||||
// id,
|
||||
// newValue
|
||||
// }) => {
|
||||
// // When the sheet is opened, or data migrations are run, the skills are retrieved via ID, and thus must have their
|
||||
// // ID included in the attribute name when setting attributes.
|
||||
// const skillId = id !== undefined ? id + "_" : ""
|
||||
getAttrs([skill, subSkillAttrName, "learning_speed", ], values => {
|
||||
const skillName = values[skill]
|
||||
const skillNameLookupKey = skillName.split("_")[0]
|
||||
const subSkill = values[subSkillAttrName]
|
||||
|
||||
// const skill = "repeating_skills_" + skillId + "skill"
|
||||
// const skillLevel = "repeating_skills_" + skillId + "skill_level"
|
||||
// const subSkillAttrName = "repeating_skills_" + skillId + "sub_skill"
|
||||
let skillAttributesToSet = {}
|
||||
|
||||
// getAttrs([skill, subSkillAttrName, "learning_speed", ], values => {
|
||||
// const skillName = values[skill]
|
||||
// const skillNameLookupKey = skillName.split("_")[0]
|
||||
// const subSkill = values[subSkillAttrName]
|
||||
skillAttributesToSet[skillLevel] = calculateSkillLevel(Number(newValue), values.learning_speed)
|
||||
|
||||
// let skillAttributesToSet = {}
|
||||
const skillData = getSkill(
|
||||
skillNameLookupKey,
|
||||
skillAttributesToSet[skillLevel],
|
||||
tieredSkills.includes(skillNameLookupKey)
|
||||
)
|
||||
|
||||
// skillAttributesToSet[skillLevel] = calculateSkillLevel(Number(newValue), values.learning_speed)
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_tnc"] = skillData.targetNumber + "/" + skillData.complexity
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "target_number"] = skillData.targetNumber
|
||||
|
||||
// const skillData = getSkill(
|
||||
// skillNameLookupKey,
|
||||
// skillAttributesToSet[skillLevel],
|
||||
// tieredSkills.includes(skillNameLookupKey)
|
||||
// )
|
||||
getAttrs(skillData.linkedAttributes, values => {
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_modifier"] = Object.values(values)
|
||||
.reduce((total, num) => Number(total) + Number(num)) + Number(skillAttributesToSet[skillLevel])
|
||||
|
||||
// skillAttributesToSet["repeating_skills_" + skillId + "skill_tnc"] = skillData.targetNumber + "/" + skillData.complexity
|
||||
// skillAttributesToSet["repeating_skills_" + skillId + "target_number"] = skillData.targetNumber
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_linked_attributes"] = skillData.linkedAttributes
|
||||
.map(linkAtr => linkedAttributeDisplayNames[linkAtr] + " (" + values[linkAtr] + ")")
|
||||
.join(" + ")
|
||||
|
||||
// getAttrs(skillData.linkedAttributes, values => {
|
||||
// skillAttributesToSet["repeating_skills_" + skillId + "skill_modifier"] = Object.values(values)
|
||||
// .reduce((total, num) => Number(total) + Number(num)) + Number(skillAttributesToSet[skillLevel])
|
||||
skillAttributesToSet["repeating_skills_" + skillId + "skill_roll_value"] =
|
||||
getSkillDisplayName(skillData, skillName, subSkill) + " Skill Check:\n" +
|
||||
"Margin of Success: [[2d6 + @{skill_modifier}[MOD] - @{target_number}[TN]]]"
|
||||
|
||||
// skillAttributesToSet["repeating_skills_" + skillId + "skill_linked_attributes"] = skillData.linkedAttributes
|
||||
// .map(linkAtr => linkedAttributeDisplayNames[linkAtr] + " (" + values[linkAtr] + ")")
|
||||
// .join(" + ")
|
||||
|
||||
// skillAttributesToSet["repeating_skills_" + skillId + "skill_roll_value"] =
|
||||
// getSkillDisplayName(skillData, skillName, subSkill) + " Skill Check:\n" +
|
||||
// "Margin of Success: [[2d6 + @{skill_modifier}[MOD] - @{target_number}[TN]]]"
|
||||
|
||||
// setAttrs(skillAttributesToSet, {}, () => {})
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
setAttrs(skillAttributesToSet, {}, () => {})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const calculateSkillLevel = (skillXP, learningSpeedModifier) => {
|
||||
const learningSpeedPercentageModifier = 1 + 0.2 * learningSpeedModifier
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import os
|
||||
from typing import List
|
||||
|
||||
|
||||
def main():
|
||||
os.system("npm --prefix ../development/ run compile")
|
||||
|
||||
output: List[str] = []
|
||||
|
||||
with open('../BattleTech-A-Time-of-War.html', 'r') as character_sheet:
|
||||
@@ -10,7 +13,7 @@ def main():
|
||||
if line == '<script type="text/worker">\n':
|
||||
break
|
||||
|
||||
with open('../development/sheet-worker.js') as sheet_worker:
|
||||
with open('../development/output/sheet-worker.js') as sheet_worker:
|
||||
output.append(sheet_worker.read())
|
||||
output.append("\n</script>\n")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user