Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: feat: add active effects to items #762

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
85788cb
feat: traits are now active effects
jonepatr Dec 26, 2021
d700a68
updates based on feedback
jonepatr Jan 3, 2022
cbe0428
added short description to traits
jonepatr Jan 4, 2022
c6b1ded
adjust column styles for trait list on actor sheet
marvin9257 Jan 4, 2022
cb9a9d6
address missing localization, tint and name for new effects
marvin9257 Jan 4, 2022
1e54708
add missing effects values on drag and drop trait
marvin9257 Jan 4, 2022
9534b62
fix deepScan issues
marvin9257 Jan 4, 2022
b0356ff
updated migration
jonepatr Jan 7, 2022
0239cc4
fix deepscan issue
jonepatr Jan 7, 2022
b042714
update migration name
jonepatr Jan 7, 2022
c19b8c9
cleanup
jonepatr Jan 9, 2022
bcb649a
use new function for applying migrations to all actors
jonepatr Jan 9, 2022
ec786b4
refactored trait active effect creation
jonepatr Jan 9, 2022
480cfd0
fix migration
jonepatr Jan 9, 2022
e0bdc86
Add possibility to add advantage/disadvantage to skill rolls through …
jonepatr Jan 9, 2022
ecdf350
type fix
jonepatr Jan 10, 2022
ace7257
work in progress
jonepatr Jan 13, 2022
530989a
fixed
jonepatr Jan 13, 2022
efef653
deepscan fix
jonepatr Jan 13, 2022
5b5c1ee
make lint happy
jonepatr Jan 13, 2022
3c8dc39
takes into consideration equipped
jonepatr Jan 13, 2022
ab01b1a
allow for using active effects on armor/radiation/encumbrance
jonepatr Jan 20, 2022
bcb5e09
remove circular dependency on twodsixitem
jonepatr Jan 21, 2022
84e8530
fixed bug with item containers
jonepatr Jan 21, 2022
369b468
Fixed bug with editing effects
jonepatr Jan 21, 2022
50c499b
fixed carrying item bug
jonepatr Jan 21, 2022
27ece90
Fix bug related to ids of active effects not updating when dragging o…
jonepatr Jan 21, 2022
8921642
typing fixes
jonepatr Jan 21, 2022
cca7da2
formatting
jonepatr Jan 21, 2022
fb0523f
style tweaks
marvin9257 Jan 23, 2022
b49d260
fix missing label
marvin9257 Jan 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions src/module/entities/TwodsixActor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import { calcModFor, getKeyByValue } from "../utils/sheetUtils";
import { TWODSIX } from "../config";
import { TwodsixRollSettings } from "../utils/TwodsixRollSettings";
import { TwodsixDiceRoll } from "../utils/TwodsixDiceRoll";
import TwodsixItem from "./TwodsixItem";
import type TwodsixItem from "./TwodsixItem";
import { Stats } from "../utils/actorDamage";
import {Characteristic, Component, Gear, Skills, Traveller, Weapon} from "../../types/template";
import { Characteristic, Component, Gear, Skills, Traveller, Weapon } from "../../types/template";
import { simplifySkillName } from "../utils/utils";
import { DocumentModificationOptions } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/abstract/document.mjs";

export default class TwodsixActor extends Actor {
/**
Expand Down Expand Up @@ -49,7 +51,7 @@ export default class TwodsixActor extends Actor {
const actorSkills = actorData.items.filter(
(item:TwodsixItem) => item.type === "skills"
).map(
(skill:TwodsixItem) => [TwodsixItem.simplifySkillName(skill.name ?? ""), (skill.data.data as Skills).value]
(skill:TwodsixItem) => [simplifySkillName(skill.name ?? ""), (skill.data.data as Skills).value]
);

const handler = {
Expand All @@ -69,6 +71,7 @@ export default class TwodsixActor extends Actor {
data.skills = new Proxy(Object.fromEntries(actorSkills), handler);
}


_prepareShipData(actorData): void {

let calcPowerMax = 0;
Expand Down Expand Up @@ -133,7 +136,34 @@ export default class TwodsixActor extends Actor {
return 0;
}

protected async _onCreate() {
protected override _onUpdateEmbeddedDocuments(embeddedName:string, documents:foundry.abstract.Document<any, any>[], result:Record<string, unknown>[], options: DocumentModificationOptions, userId: string): void {
super._onUpdateEmbeddedDocuments(embeddedName, documents, result, options, userId);
if (embeddedName === "ActiveEffect") {
documents.forEach(async (element:ActiveEffect, i) => {
const activeEffectId = element.getFlag("twodsix", "sourceId");
if (activeEffectId) {
const match = element.data.origin?.match(/Item\.(.+)/);
if (match) {
const item = (<TwodsixActor>element.parent)?.items.get(match[1]);
delete result[i]._id;
const newEffects = item?.effects.map(effect => {
if (effect.id === activeEffectId) {
return foundry.utils.mergeObject(effect.toObject(), result[i]);
} else {
return effect.toObject();
}
});
// @ts-ignore
item?.update({"effects": newEffects}, {recursive: true});
}
}
});
}
this.render();
}


protected async _onCreate(): Promise<void> {
switch (this.data.type) {
case "traveller":
if (game.settings.get("twodsix", "defaultTokenSettings")) {
Expand Down
47 changes: 31 additions & 16 deletions src/module/entities/TwodsixItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,39 @@ import { TwodsixDiceRoll } from "../utils/TwodsixDiceRoll";
import { TwodsixRollSettings } from "../utils/TwodsixRollSettings";
import TwodsixActor from "./TwodsixActor";
import { DICE_ROLL_MODES } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/constants.mjs";
import {Consumable, Gear, Skills, UsesConsumables, Weapon} from "../../types/template";
import { Consumable, Gear, Skills, UsesConsumables, Weapon } from "../../types/template";
import { ItemDataConstructorData } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs/itemData";


export default class TwodsixItem extends Item {
public static async create(data, options?): Promise<TwodsixItem> {

public static async create(data: ItemDataConstructorData, options?: DocumentModificationContext): Promise<TwodsixItem> {
const item = await super.create(data, options) as unknown as TwodsixItem;
item?.setFlag('twodsix', 'newItem', true);
if (item?.data.type === 'weapon' && (item.data.img === "" || item.data.img === foundry.data.ItemData.DEFAULT_ICON)) {
await item.update({'img': 'systems/twodsix/assets/icons/default_weapon.png'});
await item.update({ 'img': 'systems/twodsix/assets/icons/default_weapon.png' });
}

return item;
}


protected override async _onCreate(data): Promise<void> {
if (data.effects) {
const newEffects = data.effects.map((effect:Record<string, any>) => {
effect._id = randomID();
if (effect.flags.twodsix === undefined) {
effect.flags.twodsix = {};
}
effect.flags.twodsix.sourceId = effect._id
effect.origin = "";
return effect;
});
this.update({ "effects": newEffects });
}
}


/**
* Augment the basic Item data model with additional dynamic data.
*/
Expand Down Expand Up @@ -48,7 +67,7 @@ export default class TwodsixItem extends Item {
if (gear.consumables.includes(consumableId)) {
console.error(`Twodsix | Consumable already exists for item ${this.id}`);
} else {
await this.update({"data.consumables": gear.consumables.concat(consumableId)}, {});
await this.update({ "data.consumables": gear.consumables.concat(consumableId) }, {});
}
} else {
ui.notifications.error(`Twodsix | Consumable can't be added to item ${this.id}`);
Expand All @@ -59,7 +78,7 @@ export default class TwodsixItem extends Item {
const updatedConsumables = gear.consumables.filter((cId: string) => {
return (cId !== consumableId && cId !== null && this.actor?.items.get(cId) !== undefined);
});
const updateData = {"data.consumables": updatedConsumables};
const updateData = { "data.consumables": updatedConsumables };
if (gear.useConsumableForAttack === consumableId) {
updateData["data.useConsumableForAttack"] = "";
}
Expand Down Expand Up @@ -90,7 +109,7 @@ export default class TwodsixItem extends Item {
diceModifier: undefined
};
if (skill) {
tmpSettings = {characteristic: (<Skills>skill.data.data).characteristic || 'NONE'};
tmpSettings = { characteristic: (<Skills>skill.data.data).characteristic || 'NONE' };
}

let usedAmmo = 1;
Expand Down Expand Up @@ -211,7 +230,7 @@ export default class TwodsixItem extends Item {

const damageFormula = weapon.damage + (bonusDamage ? "+" + bonusDamage : "");
const damageRoll = new Roll(damageFormula, this.actor?.data.data);
const damage: Roll = await damageRoll.evaluate({async: true}); // async: true will be default in foundry 0.10
const damage: Roll = await damageRoll.evaluate({ async: true }); // async: true will be default in foundry 0.10
if (showInChat) {
const results = damage.terms[0]["results"];
const contentData = {
Expand All @@ -229,13 +248,13 @@ export default class TwodsixItem extends Item {
}
);
await damage.toMessage({
speaker: this.actor ? ChatMessage.getSpeaker({actor: this.actor}) : "???",
speaker: this.actor ? ChatMessage.getSpeaker({ actor: this.actor }) : "???",
content: html,
flags: {
"core.canPopout": true,
"transfer": transfer
}
}, {rollMode: rollMode});
}, { rollMode: rollMode });
}
return damage;
}
Expand Down Expand Up @@ -276,17 +295,13 @@ export default class TwodsixItem extends Item {
}
}

public static simplifySkillName(skillName:string): string {
return skillName.replace(/\W/g, "");
}

//////// CONSUMABLE ////////
public async consume(quantity: number): Promise<void> {
const consumableLeft = (<Consumable>this.data.data).currentCount - quantity;
if (consumableLeft >= 0) {
await this.update({"data.currentCount": consumableLeft}, {});
await this.update({ "data.currentCount": consumableLeft }, {});
} else {
throw {name: 'NoAmmoError'};
throw { name: 'NoAmmoError' };
}
}

Expand All @@ -298,7 +313,7 @@ export default class TwodsixItem extends Item {
"data.currentCount": consumable.max
}, {});
} else {
throw {name: 'TooLowQuantityError'};
throw { name: 'TooLowQuantityError' };
}
}
}
16 changes: 8 additions & 8 deletions src/module/handlebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { advantageDisadvantageTerm } from "./i18n";
import { calcModFor, getKeyByValue } from "./utils/sheetUtils";
import { TWODSIX } from "./config";
import TwodsixItem from "./entities/TwodsixItem";
import { getCharShortName } from "./utils/utils";
import { getCharShortName, simplifySkillName } from "./utils/utils";
import {Skills} from "../types/template";

export default function registerHandlebarsHelpers(): void {
Expand Down Expand Up @@ -143,7 +143,7 @@ export default function registerHandlebarsHelpers(): void {
});

Handlebars.registerHelper('skillName', (skillName) => {
return TwodsixItem.simplifySkillName(skillName);
return simplifySkillName(skillName);
});

Handlebars.registerHelper('replace', (text, key, value) => {
Expand Down Expand Up @@ -223,20 +223,20 @@ export default function registerHandlebarsHelpers(): void {

Handlebars.registerHelper("concat", (...args) => args.slice(0, args.length - 1).join(''));

Handlebars.registerHelper('each_sort_by_name', (array, options) => {
Handlebars.registerHelper('each_sort_by_property', (property:string, array:TwodsixItem[], options) => {
let sortedArray: TwodsixItem[] = [];
const slice: TwodsixItem[] = <TwodsixItem[]>array?.slice(0);
const slice = array?.slice(0);
if (slice) {
sortedArray = slice.sort((a, b) => {
if (a.name == null) {
if (a[property] == null) {
return 1;
} else {
if (b.name == null) {
if (b[property] == null) {
return -1;
} else if (a.name === b.name) {
} else if (a[property] === b[property]) {
return 0;
} else {
return a.name?.toLocaleLowerCase().localeCompare(b.name?.toLocaleLowerCase());
return a[property].toLocaleLowerCase().localeCompare(b[property].toLocaleLowerCase());
}
}
});
Expand Down
18 changes: 8 additions & 10 deletions src/module/sheets/AbstractTwodsixActorSheet.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import TwodsixItem from "../entities/TwodsixItem";
import {getDataFromDropEvent, getItemDataFromDropData} from "../utils/sheetUtils";
import { getDataFromDropEvent, getItemDataFromDropData } from "../utils/sheetUtils";
import TwodsixActor from "../entities/TwodsixActor";
import {Armor, Skills, UsesConsumables, Component} from "../../types/template";
import { TwodsixShipSheetData } from "../../types/twodsix";
Expand Down Expand Up @@ -158,7 +158,7 @@ export abstract class AbstractTwodsixActorSheet extends ActorSheet {
event.preventDefault();

const data = getDataFromDropEvent(event);
const actor = this.actor;
const actor = <TwodsixActor>this.actor;

if (!data) {
console.log(`Twodsix | Dragging something that can't be dragged`);
Expand Down Expand Up @@ -225,7 +225,7 @@ export abstract class AbstractTwodsixActorSheet extends ActorSheet {
console.log(`Twodsix | Added Skill ${itemData.name} to character`);
}

private async handleDroppedItem(actor:Actor, itemData, data:Record<string, any>, event:DragEvent) {
private async handleDroppedItem(actor:TwodsixActor, itemData, data:Record<string, any>, event:DragEvent) {
// Handle item sorting within the same Actor
const sameActor = (data.actorId === actor.id) || (actor.isToken && (data.tokenId === actor.token?.id));
if (sameActor) {
Expand All @@ -244,9 +244,7 @@ export abstract class AbstractTwodsixActorSheet extends ActorSheet {
itemData.data.skill = actor.items.getName(itemData.data.associatedSkillName)?.data._id;
}

// Create the owned item (TODO Add to type and remove the two lines below...)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// Create the owned item
return this._onDropItemCreate(itemData);
}

Expand Down Expand Up @@ -280,10 +278,10 @@ export abstract class AbstractTwodsixActorSheet extends ActorSheet {
const traits:Item[] = [];
const consumable:Item[] = [];
const component = {};
let encumbrance = 0;
let primaryArmor = 0;
let secondaryArmor = 0;
let radiationProtection = 0;
let encumbrance = sheetData.data.encumbrance?.value;
let primaryArmor = sheetData.data.primaryArmor?.value;
let secondaryArmor = sheetData.data.secondaryArmor?.value;
let radiationProtection = sheetData.data.radiationProtection?.value;

// Iterate through items, allocating to containers
items.forEach((item:TwodsixItem) => {
Expand Down
54 changes: 38 additions & 16 deletions src/module/sheets/TwodsixActorSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TWODSIX } from "../config";
import TwodsixItem from "../entities/TwodsixItem";
import TwodsixActor from "../entities/TwodsixActor";
import { DICE_ROLL_MODES } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/constants.mjs";
import {Consumable, Skills} from "../../types/template";
import {Consumable, Gear, Skills} from "../../types/template";

export class TwodsixActorSheet extends AbstractTwodsixActorSheet {

Expand Down Expand Up @@ -45,6 +45,12 @@ export class TwodsixActorSheet extends AbstractTwodsixActorSheet {
showLifebloodStamina: game.settings.get("twodsix", "showLifebloodStamina"),
showHeroPoints: game.settings.get("twodsix", "showHeroPoints")
};

data.ACTIVE_EFFECT_MODES = Object.entries(CONST.ACTIVE_EFFECT_MODES).reduce((ret, entry) => {
const [ key, value ] = entry;
ret[ value ] = key;
return ret;
}, {});
data.config = TWODSIX;

return data;
Expand Down Expand Up @@ -264,21 +270,37 @@ export class TwodsixActorSheet extends AbstractTwodsixActorSheet {
* @param {Event} event The originating click event.
* @private
*/
private async _onToggleItem(event): Promise<void> {
const li = $(event.currentTarget).parents(".item");
const itemSelected: any = this.actor.items.get(li.data("itemId"));

switch (itemSelected.data.data.equipped) {
case "equipped":
await itemSelected.update({["data.equipped"]: "ship"});
break;
case "ship":
await itemSelected.update({["data.equipped"]: "backpack"});
break;
case "backpack":
default:
await itemSelected.update({["data.equipped"]: "equipped"});
break;
private async _onToggleItem(event:Event): Promise<void> {
if (event.currentTarget) {
const li = $(event.currentTarget).parents(".item");
const itemSelected = <TwodsixItem>this.actor.items.get(li.data("itemId"));

let disableEffect: boolean;
switch ((<Gear>itemSelected.data.data).equipped) {
case "equipped":
await itemSelected.update({["data.equipped"]: "ship"});
disableEffect = true;
break;
case "ship":
await itemSelected.update({["data.equipped"]: "backpack"});
disableEffect = true;
break;
case "backpack":
default:
await itemSelected.update({["data.equipped"]: "equipped"});
disableEffect = false;
break;
}

if (itemSelected.effects.size > 0) {
const effect = this.actor.effects.find(e => e.getFlag("twodsix", "sourceId") === itemSelected.effects.contents[0].id);
if (effect) {
if (effect.getFlag("twodsix", "lastSetDisable") === undefined || effect.getFlag("twodsix", "lastSetDisable") === effect.data.disabled) {
await effect.update({disabled: disableEffect});
effect.setFlag("twodsix", "lastSetDisable", disableEffect);
}
}
}
}
}

Expand Down
Loading