mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
159 - Companion (#224)
* Initial datamodel * Fixed attack * Temp * Fixed normal levelup * Fixed showing summary of new experiences * Touchups * level sync fixes * Reworked Action storage * Companions now take stress when damaged * Fixed Feature flow * Removed retroactive companion levelup * Restored delevel on partner removal * PR fixes * Added a check for card duplicates on character
This commit is contained in:
parent
6f1529fefe
commit
b7e4169079
57 changed files with 1682 additions and 1012 deletions
|
|
@ -1,6 +1,8 @@
|
|||
import DamageSelectionDialog from '../applications/damageSelectionDialog.mjs';
|
||||
import { GMUpdateEvent, socketEvent } from '../helpers/socket.mjs';
|
||||
import DamageReductionDialog from '../applications/damageReductionDialog.mjs';
|
||||
import { LevelOptionType } from '../data/levelTier.mjs';
|
||||
import DHFeature from '../data/item/feature.mjs';
|
||||
|
||||
export default class DhpActor extends Actor {
|
||||
async _preCreate(data, options, user) {
|
||||
|
|
@ -8,7 +10,7 @@ export default class DhpActor extends Actor {
|
|||
|
||||
// Configure prototype token settings
|
||||
const prototypeToken = {};
|
||||
if (this.type === 'character')
|
||||
if (['character', 'companion'].includes(this.type))
|
||||
Object.assign(prototypeToken, {
|
||||
sight: { enabled: true },
|
||||
actorLink: true,
|
||||
|
|
@ -18,7 +20,7 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
|
||||
async updateLevel(newLevel) {
|
||||
if (this.type !== 'character' || newLevel === this.system.levelData.level.changed) return;
|
||||
if (!['character', 'companion'].includes(this.type) || newLevel === this.system.levelData.level.changed) return;
|
||||
|
||||
if (newLevel > this.system.levelData.level.current) {
|
||||
const maxLevel = Object.values(
|
||||
|
|
@ -41,6 +43,7 @@ export default class DhpActor extends Actor {
|
|||
return acc;
|
||||
}, {});
|
||||
|
||||
const featureIds = [];
|
||||
const domainCards = [];
|
||||
const experiences = [];
|
||||
const subclassFeatureState = { class: null, multiclass: null };
|
||||
|
|
@ -53,6 +56,7 @@ export default class DhpActor extends Actor {
|
|||
const advancementCards = level.selections.filter(x => x.type === 'domainCard').map(x => x.itemUuid);
|
||||
domainCards.push(...achievementCards, ...advancementCards);
|
||||
experiences.push(...Object.keys(level.achievements.experiences));
|
||||
featureIds.push(...level.selections.flatMap(x => x.featureIds));
|
||||
|
||||
const subclass = level.selections.find(x => x.type === 'subclass');
|
||||
if (subclass) {
|
||||
|
|
@ -66,13 +70,21 @@ export default class DhpActor extends Actor {
|
|||
multiclass = level.selections.find(x => x.type === 'multiclass');
|
||||
});
|
||||
|
||||
for (let featureId of featureIds) {
|
||||
this.items.get(featureId).delete();
|
||||
}
|
||||
|
||||
if (experiences.length > 0) {
|
||||
this.update({
|
||||
const getUpdate = () => ({
|
||||
'system.experiences': experiences.reduce((acc, key) => {
|
||||
acc[`-=${key}`] = null;
|
||||
return acc;
|
||||
}, {})
|
||||
});
|
||||
this.update(getUpdate());
|
||||
if (this.system.companion) {
|
||||
this.system.companion.update(getUpdate());
|
||||
}
|
||||
}
|
||||
|
||||
if (subclassFeatureState.class) {
|
||||
|
|
@ -114,10 +126,15 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.system.companion) {
|
||||
this.system.companion.updateLevel(newLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async levelUp(levelupData) {
|
||||
const actions = [];
|
||||
const levelups = {};
|
||||
for (var levelKey of Object.keys(levelupData)) {
|
||||
const level = levelupData[levelKey];
|
||||
|
|
@ -126,13 +143,23 @@ export default class DhpActor extends Actor {
|
|||
const experience = level.achievements.experiences[experienceKey];
|
||||
await this.update({
|
||||
[`system.experiences.${experienceKey}`]: {
|
||||
description: experience.name,
|
||||
name: experience.name,
|
||||
value: experience.modifier
|
||||
}
|
||||
});
|
||||
|
||||
if (this.system.companion) {
|
||||
await this.system.companion.update({
|
||||
[`system.experiences.${experienceKey}`]: {
|
||||
name: '',
|
||||
value: experience.modifier
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let multiclass = null;
|
||||
const featureAdditions = [];
|
||||
const domainCards = [];
|
||||
const subclassFeatureState = { class: null, multiclass: null };
|
||||
const selections = [];
|
||||
|
|
@ -141,7 +168,18 @@ export default class DhpActor extends Actor {
|
|||
for (var checkboxNr of Object.keys(selection)) {
|
||||
const checkbox = selection[checkboxNr];
|
||||
|
||||
if (checkbox.type === 'multiclass') {
|
||||
const tierOption = LevelOptionType[checkbox.type];
|
||||
if (tierOption.features?.length > 0) {
|
||||
featureAdditions.push({
|
||||
checkbox: {
|
||||
...checkbox,
|
||||
level: Number(levelKey),
|
||||
optionKey: optionKey,
|
||||
checkboxNr: Number(checkboxNr)
|
||||
},
|
||||
features: tierOption.features
|
||||
});
|
||||
} else if (checkbox.type === 'multiclass') {
|
||||
multiclass = {
|
||||
...checkbox,
|
||||
level: Number(levelKey),
|
||||
|
|
@ -174,6 +212,28 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
}
|
||||
|
||||
for (var addition of featureAdditions) {
|
||||
for (var featureData of addition.features) {
|
||||
const feature = new DHFeature({
|
||||
...featureData,
|
||||
description: game.i18n.localize(featureData.description)
|
||||
});
|
||||
const embeddedItem = await this.createEmbeddedDocuments('Item', [
|
||||
{
|
||||
...featureData,
|
||||
name: game.i18n.localize(featureData.name),
|
||||
type: 'feature',
|
||||
system: feature
|
||||
}
|
||||
]);
|
||||
addition.checkbox.featureIds = !addition.checkbox.featureIds
|
||||
? [embeddedItem[0].id]
|
||||
: [...addition.checkbox.featureIds, embeddedItem[0].id];
|
||||
}
|
||||
|
||||
selections.push(addition.checkbox);
|
||||
}
|
||||
|
||||
if (multiclass) {
|
||||
const subclassItem = await foundry.utils.fromUuid(multiclass.secondaryData.subclass);
|
||||
const subclassData = subclassItem.toObject();
|
||||
|
|
@ -238,6 +298,7 @@ export default class DhpActor extends Actor {
|
|||
|
||||
await this.update({
|
||||
system: {
|
||||
actions: [...this.system.actions, ...actions],
|
||||
levelData: {
|
||||
level: {
|
||||
current: this.system.levelData.level.changed
|
||||
|
|
@ -246,6 +307,10 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.system.companion) {
|
||||
this.system.companion.updateLevel(this.system.levelData.level.changed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -266,7 +331,7 @@ export default class DhpActor extends Actor {
|
|||
* @param {object} [config.costs]
|
||||
*/
|
||||
async diceRoll(config) {
|
||||
config.source = {...(config.source ?? {}), actor: this.uuid};
|
||||
config.source = { ...(config.source ?? {}), actor: this.uuid };
|
||||
config.data = this.getRollData();
|
||||
const rollClass = config.roll.lite ? CONFIG.Dice.daggerheart['DHRoll'] : this.rollClass;
|
||||
return await rollClass.build(config);
|
||||
|
|
@ -364,6 +429,11 @@ export default class DhpActor extends Actor {
|
|||
}
|
||||
|
||||
async takeDamage(damage, type) {
|
||||
if (this.type === 'companion') {
|
||||
await this.modifyResource([{ value: 1, type: 'stress' }]);
|
||||
return;
|
||||
}
|
||||
|
||||
const hpDamage =
|
||||
damage >= this.system.damageThresholds.severe
|
||||
? 3
|
||||
|
|
@ -422,14 +492,17 @@ export default class DhpActor extends Actor {
|
|||
break;
|
||||
default:
|
||||
updates.actor.resources[`system.resources.${r.type}.value`] = Math.max(
|
||||
Math.min(this.system.resources[r.type].value + r.value, (this.system.resources[r.type].maxTotal ?? this.system.resources[r.type].max)),
|
||||
Math.min(
|
||||
this.system.resources[r.type].value + r.value,
|
||||
this.system.resources[r.type].maxTotal ?? this.system.resources[r.type].max
|
||||
),
|
||||
0
|
||||
);
|
||||
break;
|
||||
}
|
||||
});
|
||||
Object.values(updates).forEach(async u => {
|
||||
console.log(updates, u)
|
||||
console.log(updates, u);
|
||||
if (Object.keys(u.resources).length > 0) {
|
||||
if (game.user.isGM) {
|
||||
await u.target.update(u.resources);
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ export default class DHItem extends foundry.documents.Item {
|
|||
isInventoryItem === true
|
||||
? 'Inventory Items'
|
||||
: isInventoryItem === false
|
||||
? 'Character Items'
|
||||
: 'Other';
|
||||
? 'Character Items'
|
||||
: 'Other';
|
||||
|
||||
return { value: type, label, group };
|
||||
}
|
||||
|
|
@ -83,13 +83,14 @@ export default class DHItem extends foundry.documents.Item {
|
|||
{ actions: this.system.actions }
|
||||
),
|
||||
title = 'Select Action';
|
||||
|
||||
|
||||
return foundry.applications.api.DialogV2.prompt({
|
||||
window: { title },
|
||||
content,
|
||||
ok: {
|
||||
label: title,
|
||||
callback: (event, button, dialog) => this.system.actions.find(a => a._id === button.form.elements.actionId.value)
|
||||
callback: (event, button, dialog) =>
|
||||
this.system.actions.find(a => a._id === button.form.elements.actionId.value)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -115,7 +116,9 @@ export default class DHItem extends foundry.documents.Item {
|
|||
this.type === 'ancestry'
|
||||
? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.AncestryTitle')
|
||||
: this.type === 'community'
|
||||
? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.CommunityTitle')
|
||||
? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.CommunityTitle')
|
||||
: this.type === 'feature'
|
||||
? game.i18n.localize('TYPES.Item.feature')
|
||||
: game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'),
|
||||
origin: origin,
|
||||
img: this.img,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue