Skip to content

Commit

Permalink
Merge pull request #211 from SolarBear/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
SolarBear committed Aug 14, 2021
2 parents cdfa30e + aeca8eb commit 5f36fe4
Show file tree
Hide file tree
Showing 37 changed files with 1,703 additions and 185 deletions.
7 changes: 7 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"types": [
"@league-of-foundry-developers/foundry-vtt-types"
]
}
}
6 changes: 5 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
"NUMENERA.item.skill.tab.stat": "Stat",
"NUMENERA.item.skill.tab.instructions": "No skills yet. Create one by clicking the <a><i class=\"fas fa-plus\"></i></a> icon on the top right of the table or pick one from the Items Directory or a Compendium and drag it here.",
"NUMENERA.item.skill.newSkill": "New Skill",
"NUMENERA.skillLevels.label": "Level",
"NUMENERA.skillLevels.Inability": "Inability",
"NUMENERA.skillLevels.Untrained": "Untrained",
"NUMENERA.skillLevels.Trained": "Trained",
Expand Down Expand Up @@ -372,5 +373,8 @@
"NUMENERA.warnings.skillWithSameNameExists": "A Skill with the same name also exists",

"NUMENERA.macro.use.notActorsItem": "Your controlled Actor does not have such an item",
"NUMENERA.macro.create.onlyOwned": "You can only create macro buttons for owned Items"
"NUMENERA.macro.create.onlyOwned": "You can only create macro buttons for owned Items",

"NUMENERA.chat.sendToChat": "Send to chat"

}
5 changes: 4 additions & 1 deletion lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
"NUMENERA.item.skill.tab.stat": "Caractéristique",
"NUMENERA.item.skill.tab.instructions": "Pas de compétences. Créez-en une en cliquant sur l'icône <a><i class=\"fas fa-plus\"></i></a> en haut à droite du tableau ou sélectionnez-en une du ITEMS DIRECTORY ou d'un Compendium et DRAGGEZ-la jusque ici.",
"NUMENERA.item.skill.newSkill": "Nouvelle compétence",
"NUMENERA.skillLevels.label": "Niveau",
"NUMENERA.skillLevels.Inability": "Incompétence",
"NUMENERA.skillLevels.Untrained": "Non entraîné",
"NUMENERA.skillLevels.Trained": "Entraîné",
Expand Down Expand Up @@ -372,5 +373,7 @@
"NUMENERA.warnings.skillWithSameNameExists": "Une compétence portant le même nom existe déjà",

"NUMENERA.macro.use.notActorsItem": "L'acteur que vous contrôlez ne possède pas un tel item",
"NUMENERA.macro.create.onlyOwned": "Vous ne pouvez créer des boutons de macro que pour des items que vous possédez"
"NUMENERA.macro.create.onlyOwned": "Vous ne pouvez créer des boutons de macro que pour des items que vous possédez",

"NUMENERA.chat.sendToChat": "Envoyer dans le chat"
}
64 changes: 38 additions & 26 deletions module/actor/NumeneraPCActor.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,21 @@ export class NumeneraPCActor extends Actor {
//Default case: there is no specific ID
allFoci[Object.keys(allFoci)[0]] = value;

const data = {_id: this._id};
const data = {};
data["data.focus"] = {"": value};

this.update(data);
}

getInitiativeFormula() {
//Check for an initiative skill
let initSkill = this.items.find(i => i.type === "skill" && i.name.toLowerCase() === "initiative");
const setting = game.settings.get("numenera", "initiativeSkill");

let initSkill = this.items.find(i => i.type === "skill" && i.name === setting);

if (!initSkill) {
initSkill = new CONFIG.Item.documentClass(NumeneraSkillItem.object, {parent: this});
initSkill.data.data.name = "Initiative";
initSkill.data.data.name = setting;
}

const rollData = this.getSkillRollData(initSkill);
Expand All @@ -70,13 +73,14 @@ export class NumeneraPCActor extends Actor {
* @memberof NumeneraPCActor
*/
getSkillRollData(skill) {
//TODO this REALLY should be in the Skill class
const rollOptions = new RollData();

let data = skill.data;
if (data.hasOwnProperty("data"))
data = data.data;

rollOptions.skillLevel = data ? data.skillLevel : 0;
rollOptions.skillLevel = data ? parseInt(data.skillLevel) : 0;
rollOptions.isHindered = data ? data.inability : false;
rollOptions.damageTrackPenalty = this.data.data.damageTrack > 0;

Expand All @@ -88,10 +92,12 @@ export class NumeneraPCActor extends Actor {
*
* @param {String} skillId
* @param {RollData} rollData
* @param {NumeneraAbilityItem} ability
* @param {Number} enhancements
* @returns {Roll}
* @memberof NumeneraPCActor
*/
rollSkillById(skillId, rollData = null, ability = null) {
rollSkillById(skillId, rollData = null, ability = null, enhancements = 0) {
const skill = this.items.get(skillId);
return this.rollSkill(skill, rollData, ability);
}
Expand All @@ -102,10 +108,12 @@ export class NumeneraPCActor extends Actor {
*
* @param {NumeneraSkillItem} skill
* @param {RollData} rollData
* @param {NumeneraAbilityItem} ability
* @param {Number} enhancements
* @returns
* @memberof NumeneraPCActor
*/
rollSkill(skill, rollData = null, ability = null) {
rollSkill(skill, rollData = null, ability = null, enhancements = 0) {
switch (this.data.data.damageTrack) {
case 2:
ui.notifications.warn(game.i18n.localize("NUMENERA.pc.damageTrack.debilitated.warning"));
Expand All @@ -125,6 +133,7 @@ export class NumeneraPCActor extends Actor {
}

rollData.ability = ability;
rollData.enhancements = enhancements;

const roll = rollData.getRoll();
roll.roll();
Expand All @@ -133,11 +142,13 @@ export class NumeneraPCActor extends Actor {

const mods = []; //any roll modifier goes here: effort, skill level, etc.

if (skill.data.data.skillLevel == 2) {
mods.push("specialized");
}
else if (skill.data.data.skillLevel == 1) {
mods.push("trained");
switch (skill.data.data.skillLevel) {
case 2:
mods.push("specialized");
break;
case 1:
mods.push("trained");
break;
}

if (skill.data.data.inability)
Expand All @@ -146,6 +157,9 @@ export class NumeneraPCActor extends Actor {
if (rollData.effortLevel > 0)
mods.push(`${rollData.effortLevel} ${game.i18n.localize("NUMENERA.effort.title")}`);

if (enhancements > 0)
mods.push(`${enhancements} ${game.i18n.localize("NUMENERA.effort.other")}`);

if (mods.length > 0)
flavor += ` (${mods.join(", ")})`;

Expand Down Expand Up @@ -299,25 +313,23 @@ export class NumeneraPCActor extends Actor {
//TODO we're hitting the embedded collections twice... maybe cache the result?
//recompute whenever armor values change, are added or deleted

const heaviestArmor = this._getHeaviestArmor();
if (!heaviestArmor)
return 0;

let speedEffortPenalty = heaviestArmor.weightIndex;
let speedEffortPenalty = this.items.filter(i => i.type === NumeneraArmorItem.type)
.reduce((max, current) => Math.max(max, current.data.data.additionalSpeedEffortCost), 0);

//Local, utility function
const searchArmorSkill = name => {
// //Local, utility function
const searchArmorAbility = name => {
return !!this.getEmbeddedCollection("Item")
.some(i => i.type === NumeneraAbilityItem.type && i.name === name);
}

const trainingAbility = game.settings.get("numenera", "armorTrainingAbility");
const trainingSpecialization = game.settings.get("numenera", "armorSpecializationAbility");

//Look for any reducing skill(s)
if (searchArmorSkill("Mastery with Armor")) {
if (searchArmorAbility(trainingSpecialization))
speedEffortPenalty -= 2;
}
else if (searchArmorSkill("Trained in Armor")) {
else if (searchArmorAbility(trainingAbility))
speedEffortPenalty -= 1;
}

//Negative penalties are not allowed, for obvious reasons!
return Math.max(speedEffortPenalty, 0);
Expand Down Expand Up @@ -371,7 +383,7 @@ export class NumeneraPCActor extends Actor {
}

this.update({
_id: this._id,
_id: this._id, //TODO necessary?
"data.xp": xp,
});

Expand Down Expand Up @@ -509,7 +521,7 @@ export class NumeneraPCActor extends Actor {
const newPoolValue = stat.pool.value + stat.edge - cost.amount;
const poolProp = `data.stats.${cost.pool}.pool.value`;

const data = { _id: this._id };
const data = { _id: this._id }; //TODO necessary?
data[poolProp] = newPoolValue;

await this.update(data);
Expand Down Expand Up @@ -573,7 +585,7 @@ export class NumeneraPCActor extends Actor {
}

await this.updateEmbeddedDocuments("Item", [{
_id: newItem._id,
_id: newItem.id,
"data.level": itemData.level,
"data.form": itemData.form,
}]);
Expand Down Expand Up @@ -609,7 +621,7 @@ export class NumeneraPCActor extends Actor {
//Create a related skill if one does not already exist
const skillData = {
stat: actorAbility.data.data.cost.pool,
relatedAbilityId: actorAbility._id,
relatedAbilityId: actorAbility.id,
};

const itemData = {
Expand Down
14 changes: 8 additions & 6 deletions module/actor/sheets/NumeneraPCActorSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,18 +287,20 @@ export class NumeneraPCActorSheet extends ActorSheet {
sheetData.damageTrackData = NUMENERA.damageTrack;
sheetData.damageTrackDescription = NUMENERA.damageTrack[sheetData.data.damageTrack].description;

sheetData.displayMightCostPerHour = game.settings.get("numenera", "armorPenalty") === "old";
const armorPenaltySetting = game.settings.get("numenera", "armorPenalty");

sheetData.displayMightCostPerHour = armorPenaltySetting === "old";
if (sheetData.displayMightCostPerHour)
sheetData.armorMightCostPerHour = this.actor.mightCostPerHour;

sheetData.displaySpeedPoolReduction = game.settings.get("numenera", "armorPenalty") === "old";
sheetData.displaySpeedPoolReduction = armorPenaltySetting === "old";
if (sheetData.displaySpeedPoolReduction)
sheetData.armorSpeedPoolReduction = this.actor.speedPoolPenalty;

sheetData.displaySpeedEffortPenalty = ["none", "new"].some(s => s === game.settings.get("numenera", "armorPenalty"));
sheetData.displaySpeedEffortPenalty = ["none", "new"].indexOf(armorPenaltySetting) !== -1;

if (sheetData.displaySpeedEffortPenalty) {
if (game.settings.get("numenera", "armorPenalty") === "new") {
if (armorPenaltySetting === "new") {
sheetData.saveSpeedEffortPenalty = false;
sheetData.speedEffortPenalty = this.actor.extraSpeedEffortCost;
}
Expand Down Expand Up @@ -542,6 +544,7 @@ export class NumeneraPCActorSheet extends ActorSheet {
activateListeners(html) {
super.activateListeners(html);

//TODO yo wazzat
html.find("input.focus").on("change", this.actor.setFocusFromEvent.bind(this.actor));

html.find("div.stats").on("click", "a.rollable", this.onAttributeUse.bind(this));
Expand Down Expand Up @@ -643,7 +646,7 @@ export class NumeneraPCActorSheet extends ActorSheet {

const clickedItem = duplicate(
//TODO
this.actor.getEmbeddedEntity("OwnedItem", itemId)
this.actor.getEmbeddedDocument("Item", itemId)
);
clickedItem.data.stored = "";

Expand Down Expand Up @@ -727,7 +730,6 @@ export class NumeneraPCActorSheet extends ActorSheet {
if (!skillId)
return;

//this.actor.items.get(skillId).use();
this.actor.useItemById(skillId);
}

Expand Down
2 changes: 1 addition & 1 deletion module/actor/sheets/sheetUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function onItemDeleteGenerator(deleteType, callback = null) {
if (await confirmDeletion(deleteType)) {
const elem = event.currentTarget.closest("." + deleteType);
const itemId = elem.dataset.itemId;
const toDelete = this.actor.data.items.find(i => i._id === itemId);
const toDelete = this.actor.data.items.find(i => i.id === itemId);

await this.actor.deleteEmbeddedDocuments("Item", [itemId]);

Expand Down
57 changes: 21 additions & 36 deletions module/apps/EffortDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,10 @@ export class EffortDialog extends FormApplication {
* @param {Number} [assets=0]
* @param {Number} [taskLevel=null]
* @param {NumeneraPowerShiftItem} [powerShift=null]
* @param {RollData} [rollData=null]
* @memberof EffortDialog
*/
constructor(actor, {stat=null, skill=null, ability=null, assets=0, taskLevel=null, powerShift=null}) {
constructor(actor, {stat=null, skill=null, ability=null, assets=0, taskLevel=null, powerShift=null, rollData=null}) {
if (!stat) {
if (ability) {
stat = getShortStat(ability.data.data.cost.pool);
Expand Down Expand Up @@ -152,7 +153,8 @@ export class EffortDialog extends FormApplication {
armorSpeedEffortIncrease: actor.extraSpeedEffortCost,
powerShifts: [],
powerShift,
}, {});
rollData,
}, {});

this._isInitialized = false;
}
Expand All @@ -165,16 +167,9 @@ export class EffortDialog extends FormApplication {
* @memberof EffortDialog
*/
async init() {
this.object.skills = this.object.actor.getEmbeddedCollection("Item")
this.object.skills = (await this.object.actor.getEmbeddedCollection("Item"))
.filter(i => i.type === NumeneraSkillItem.type);

//TODO still required in 0.7?
//.map(NumeneraSkillItem.fromOwnedItem);

//TODO _might_ not be necessary. Isn't an object an auto-fulfilled Promise or something?
//0.8 returns Promise<Item>s instead of straight Items
this.object.skills = await Promise.all(this.object.skills);

this.object.skills = this.object.skills.map(sk => {
//Append an extra label to tell which skills are related to an ability
if (sk.data.relatedAbilityId)
Expand All @@ -185,14 +180,8 @@ export class EffortDialog extends FormApplication {

let powerShifts = null;
if (game.settings.get("numenera", "usePowerShifts")) {
powerShifts = this.object.actor.getEmbeddedCollection("Item")
.filter(i => i.type === "powerShift")
.map(NumeneraPowerShiftItem.fromOwnedItem);

//TODO _might_ not be necessary. Isn't an object an auto-fulfilled Promise or something?
powerShifts = await Promise.all(powerShifts);

this.object.powerShifts = powerShifts;
this.object.powerShifts = (await this.object.actor.getEmbeddedCollection("Item"))
.filter(i => i.type === "powerShift");
}

this._isInitialized = true;
Expand Down Expand Up @@ -424,7 +413,7 @@ export class EffortDialog extends FormApplication {
return;
}

const rollData = new RollData();
const rollData = this.object.rollData ? this.object.rollData : new RollData();

rollData.effortLevel = this.object.currentEffort;
rollData.taskLevel = this.finalLevel;
Expand All @@ -433,7 +422,7 @@ export class EffortDialog extends FormApplication {

if (this.object.skill) {
let skill = this.object.skill;

//Fetch the skill, might be one of these weird kind-of-Item objects
if (skill._id)
skill = this.object.actor.items.get(this.object.skill.id);
Expand All @@ -444,16 +433,15 @@ export class EffortDialog extends FormApplication {
await actor.rollAttribute(shortStat, rollData);
}

if (cost <= 0)
return;

const poolProp = `data.stats.${shortStat}.pool.value`;
if (cost > 0) {
const poolProp = `data.stats.${shortStat}.pool.value`;

const data = { _id: actor.id };
data[poolProp] = poolValue - cost;

//TIME TO PAY THE PRICE MWAHAHAHAHAHAHAH
actor.update(data);
const data = { _id: actor.id };
data[poolProp] = poolValue - cost;

//TIME TO PAY THE PRICE MWAHAHAHAHAHAHAH
actor.update(data);
}

this.close();
}
Expand Down Expand Up @@ -558,14 +546,11 @@ export class EffortDialog extends FormApplication {
this.object.current = actor.data.data.stats[shortStat].pool.value;
this.object.remaining = this.object.current - this.object.cost;

if (formData.powerShift) {
const powerShift = actor.getEmbeddedCollection("Item")
.find(i => i._id === formData.powerShift);
this.object.powerShift = NumeneraPowerShiftItem.fromOwnedItem(powerShift);
}
else {
if (formData.powerShift)
this.object.powerShift = actor.getEmbeddedCollection("Item")
.find(i => i._id === formData.powerShift);
else
this.object.powerShift = null;
}

//Re-render the form since it's not provided for free in FormApplications
this.render();
Expand Down
Loading

0 comments on commit 5f36fe4

Please sign in to comment.