Skip to content

Commit

Permalink
feature: traits are now active effects
Browse files Browse the repository at this point in the history
Previsouly adding a trait did not affect the actor. This change makes
it so that a trait is an active effect and can change the
actor.

Fix #272
  • Loading branch information
jonepatr committed Dec 29, 2021
1 parent b871164 commit 745c3ae
Show file tree
Hide file tree
Showing 20 changed files with 245 additions and 48 deletions.
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module.exports = {
plugins: [
nodeResolve(),
commonjs(),
esbuild({
esbuild.default({
include: /\.[jt]sx?$/, // TODO Might have to include d.ts here
sourceMap: true,
minify: process.env.NODE_ENV === 'production',
Expand Down
25 changes: 25 additions & 0 deletions src/migrations/2021_12_29_05_08_25_active-effects-for-traits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
async function applyActiveEffects(p, actor) {
await p;
return Promise.all(actor.items.filter(item => item.type === "trait").map(async item => {
if (!item.data.data.effectId) {
//@ts-ignore
const effects = await actor.createEmbeddedDocuments("ActiveEffect", [{
origin: item.uuid,
icon: "systems/twodsix/assets/icons/science.svg"
}]);
await item.update({ "data.effectId": effects[0].id });
}
return Promise.resolve();
}));
}

export async function migrate(): Promise<void> {
const tokenActor = game.scenes
//@ts-ignore
.reduce((memo, scene) => memo.concat(scene.tokens.contents), [])
.filter(s => s.actor.type === "traveller" && !s.data.actorLink)
.map(token => token._actor);
//@ts-ignore
await game.actors.filter(actor => actor.type === "traveller").reduce(applyActiveEffects, Promise.resolve());
await tokenActor.reduce(applyActiveEffects, Promise.resolve());
}
10 changes: 10 additions & 0 deletions src/module/entities/TwodsixActor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ export default class TwodsixActor extends Actor {
}
}

_onUpdateEmbeddedDocuments(embeddedName, documents, result, options, userId) {
if (embeddedName === "ActiveEffect") {
documents.forEach(element => {
const item = element.parent.items.find(itm => itm.data.data.effectId === element.id);
item.update({"data.changes": element.data.changes});
});
}
this.render();
}

protected async _onCreate(data, options, user) {
switch (this.data.type) {
case "traveller":
Expand Down
5 changes: 5 additions & 0 deletions src/module/entities/TwodsixItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export default class TwodsixItem extends Item {
if (this.getFlag("twodsix", "untrainedSkill")) {
this.data.name = game.i18n.localize("TWODSIX.Actor.Skills.Untrained");
}

if (this.data.data.effectId && this.actor?.data) {
const effect = this.actor.effects.get(this.data.data.effectId);
this.data.data.effect = effect;
}
}

prepareConsumable(): void {
Expand Down
4 changes: 2 additions & 2 deletions src/module/handlebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ 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, array, options) => {
const sortedArray = array?.slice(0).sort((a:TwodsixItem, b:TwodsixItem) => {
const aName = a.name.toLowerCase(), bName = b.name.toLowerCase();
const aName = a[property].toLowerCase(), bName = b[property].toLowerCase();
return (aName > bName) ? 1 : ((bName > aName) ? -1 : 0);
});
return Handlebars.helpers.each(sortedArray, options);
Expand Down
27 changes: 23 additions & 4 deletions src/module/sheets/AbstractTwodsixActorSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,21 @@ export abstract class AbstractTwodsixActorSheet extends ActorSheet {
type,
data
};

// Remove the type from the dataset since it's in the itemData.type prop.
// delete itemData.data.type;
this.updateWithItemSpecificValues(itemData, type);

// Finally, create the item!
// @ts-ignore
await this.actor.createEmbeddedDocuments("Item", [itemData]);
const items = await this.actor.createEmbeddedDocuments("Item", [itemData]);

if (type === "trait") {
// @ts-ignore
const effects = await this.actor.createEmbeddedDocuments("ActiveEffect", [{
origin: items[0].uuid,
icon: "systems/twodsix/assets/icons/science.svg"
}]);
items[0].update({"data.effectId": effects[0].id});
}
}


Expand Down Expand Up @@ -258,7 +265,19 @@ export abstract class AbstractTwodsixActorSheet extends ActorSheet {
// 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
return this._onDropItemCreate(itemData);
const items = await this._onDropItemCreate(itemData);

if (items[0].type === "trait") {
// @ts-ignore
const effects = await actor.createEmbeddedDocuments("ActiveEffect", [{
origin: items[0].uuid,
icon: "systems/twodsix/assets/icons/science.svg",
changes: items[0].data.data.changes
}]);
await items[0].update({"data.effectId": effects[0].id});
actor.render();
}
return items;
}

private static _getWeight(item): number{
Expand Down
12 changes: 12 additions & 0 deletions src/module/sheets/TwodsixActorSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,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 @@ -93,8 +99,14 @@ export class TwodsixActorSheet extends AbstractTwodsixActorSheet {
html.find(".item-value-edit").on("click", (event) => {
$(event.currentTarget).trigger("select");
});

html.find(".effect-edit").on("click", this._onTraitEdit.bind(this));
}

private _onTraitEdit(event) {
const effect = this.actor.effects.get($(event.currentTarget).data('effectId'));
effect.sheet.render(true);
}

private getItem(event:Event):TwodsixItem {
const itemId = $(event.currentTarget).parents('.item').data('item-id');
Expand Down
40 changes: 38 additions & 2 deletions src/module/sheets/TwodsixItemSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ export class TwodsixItemSheet extends AbstractTwodsixItemSheet {
// @ts-ignore
getData():ItemSheetData {
const data = super.getData();
const actorData = data.data;
data.actor = actorData;
data.actor = this.item.actor;

// @ts-ignore
this.item.prepareConsumable();
Expand All @@ -51,6 +50,12 @@ export class TwodsixItemSheet extends AbstractTwodsixItemSheet {
};
data.data.config = TWODSIX;
data.data.isOwned = this.item.isOwned;

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

Expand Down Expand Up @@ -81,9 +86,40 @@ export class TwodsixItemSheet extends AbstractTwodsixItemSheet {
html.find('.consumable-edit').on('click', this._onEditConsumable.bind(this));
html.find('.consumable-delete').on('click', this._onDeleteConsumable.bind(this));
html.find('.consumable-use-consumable-for-attack').on('change', this._onChangeUseConsumableForAttack.bind(this));

//change-row
html.find('.change-row input, .change-row select').on('change', this._onEditChange.bind(this));
html.find('.change-create').on('click', this._onCreateChange.bind(this));
html.find('.change-delete').on('click', this._onDeleteChange.bind(this));

html.find(".effect-edit").on("click", this._onEditEffect.bind(this));

this.handleContentEditable(html);
}

private _onEditEffect(event) {
const effect = this.actor.effects.get($(event.currentTarget).data('effectId'));
effect.sheet.render(true);
}

private _onDeleteChange(event:Event) {
const idx = parseInt($(event.currentTarget).data("index"), 10);
const changes = this.item.data.data.changes.filter((_, i) => i !== idx);
this.item.update({"data.changes": changes});
}

private _onEditChange(event:Event) {
const idx = $(event.currentTarget).parents(".change-row").data("change-index");
const changes = this.item.data.data.changes;
changes[parseInt(idx, 10)][$(event.currentTarget).data("type")] = $(event.currentTarget).val();
this.item.update({"data.changes": changes});
}

private _onCreateChange(event:Event) {
const changes = this.item.data.data.changes ?? [];
this.item.update({"data.changes": changes.concat({key: "", value: "", mode: 0})});
}

private getConsumable(event:Event):TwodsixItem {
const li = $(event.currentTarget).parents(".consumable");
// @ts-ignore
Expand Down
5 changes: 3 additions & 2 deletions src/scripts/create_migration.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from 'fs';
/* eslint-disable @typescript-eslint/no-var-requires */
const fs = require("fs");

const migrationName = process.argv[2];
if (!migrationName) {
Expand All @@ -7,7 +8,7 @@ if (!migrationName) {
}

const tmpDate = new Date();
const date = (new Date(tmpDate.toUTCString())).toISOString().replaceAll(/-|:|T/ig, "_").split(".")[0];
const date = (new Date(tmpDate.toUTCString())).toISOString().replace(/-|:|T/ig, "_").split(".")[0];

const templateString = "export async function migrate():Promise<void> {\n\n}";

Expand Down
12 changes: 11 additions & 1 deletion static/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,17 @@
},
"Traits": {
"Prerequisite": "Prerequisite",
"TraitName": "Trait Name"
"TraitName": "Trait Name",
"AttributeKey": "Attribute Key",
"ChangeMode": "Change Mode",
"EffectValue": "Effect Value",
"CreateEffect": "Create Effect",
"DeleteEffect": "Delete Effect",
"EditEffects": "Edit Effects",
"EditEffect": "Edit Effect",
"Effects": "Effects",
"CreateTrait": "Create Trait",
"DeleteTrait": "Delete Trait"
},
"Tool": {
"Bonus": "Bonus"
Expand Down
13 changes: 11 additions & 2 deletions static/styles/twodsix.css
Original file line number Diff line number Diff line change
Expand Up @@ -757,9 +757,18 @@ a.notes-tab.active {

.items-traits {
display: grid;
grid-template-columns: 14em 2em 14em 3em;
grid-template-columns: 7em 22em 4em;
gap: 1px 1px;
grid-template-areas: '. . . .';
grid-template-areas: '. . .';
}

.trait-name {
display: inline-flex;
align-items: center;
}

.effect-edit {
width: 150%;
}

.items-consumable {
Expand Down
14 changes: 12 additions & 2 deletions static/styles/twodsix_basic.css
Original file line number Diff line number Diff line change
Expand Up @@ -512,9 +512,18 @@ a.skill-tab.active, a.item-tab.active, a.finances-tab.active, a.info-tab.active,

.items-traits {
display: grid;
grid-template-columns: 14em 2em 14em 3em;
grid-template-columns: 7em 22em 4em;
gap: 1px 1px;
grid-template-areas: '. . . .';
grid-template-areas: '. . .';
}

.trait-name {
display: inline-flex;
align-items: center;
}

.effect-edit {
width: 150%;
}

.items-consumable {
Expand Down Expand Up @@ -1453,6 +1462,7 @@ button.flexrow.flex-group-center.toggle-skills {
text-shadow: 0 0 5px /*var(--default-color);
}*/


.item-type {
position: relative;
float: right;
Expand Down
3 changes: 2 additions & 1 deletion static/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@
"shortdescr": "",
"subtype": "",
"reference": "",
"key": "key"
"effectId": "",
"changes": []
},
"consumable": {
"templates": ["gearTemplate"],
Expand Down
41 changes: 26 additions & 15 deletions static/templates/actors/parts/actor/actor-info.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,43 @@
<div><span class="pusher"></span>
<span class="item-title">{{localize "TWODSIX.Actor.Items.TRAITS"}}</span>
<div class="items-traits gear-header">
<span class="item-name">{{localize "TWODSIX.Actor.Items.Name"}}</span>
<span class="item-name">{{localize "TWODSIX.Actor.Skills.Level"}}</span>
<span class="item-name centre">{{localize "TWODSIX.Actor.Items.ShortDescr"}}</span>
<span class="item-name centre"><a class="item-control item-create"
title='{{localize "TWODSIX.Actor.Items.CreateItem"}}' data-type="trait"><i class="fas fa-plus"></i></a></span>
<span class="item-name">{{localize "TWODSIX.Items.Traits.TraitName"}}</span>
<span class="item-name">{{localize "TWODSIX.Items.Traits.Effects"}}</span>
<span class="item-name centre">
<a class="item-control item-create" title='{{localize "TWODSIX.Items.Traits.CreateTrait"}}' data-type="trait">
<i class="fas fa-plus"></i>
</a>
</span>
</div>

{{#each_sort_by_name data.traits as |item id|}}
{{#each_sort_by_property "name" data.traits as |item|}}
<div class="item gear">
<ol class="ol-no-indent">
<li class="item flexrow" data-item-id="{{item.id}}">
<span class="items-traits">
<span class="item-name">{{item.name}}</span>
<span class="item-name centre">{{item.data.data.value}}</span>
<span class="item-name centre">{{item.data.data.shortdescr}}</span>
<span class="item-name trait-name">{{item.name}}</span>
<span class="item-name">
<ul>
{{#each item.data.data.effect.data.changes as |change|}}
<li>{{change.key}} {{lookup @root.ACTIVE_EFFECT_MODES change.mode}} {{change.value}}</li>
{{/each}}
</ul>
</span>
<span class="item-controls centre">
<a class="item-control item-edit" title='{{localize "TWODSIX.Actor.Items.EditItem"}}'><i
class="fas fa-edit"></i></a>
<a class="item-control item-delete" title='{{localize "TWODSIX.Actor.Items.DeleteItem"}}'><i
class="fas fa-trash"></i></a>
<a class="item-control item-edit" title='{{localize "TWODSIX.Actor.Items.EditItem"}}'>
<i class="fas fa-edit"></i>
</a>
<a class="item-control effect-edit" data-effect-id="{{item.data.data.effect.data._id}}" title='{{localize "TWODSIX.Items.Traits.EditEffect"}}'>
<i class="fas fa-sliders-h"></i>
</a>
<a class="item-control item-delete" title='{{localize "TWODSIX.Items.Traits.DeleteTrait"}}'>
<i class="fas fa-trash"></i>
</a>
</span>
</span>
</li>
</ol>
</div>
{{/each_sort_by_name}}
{{/each_sort_by_property}}
</div>

<div class="info-container">
Expand Down
Loading

0 comments on commit 745c3ae

Please sign in to comment.