|
|
|
@ -32,6 +32,7 @@ export class RdDActor extends Actor {
|
|
|
|
|
static init() {
|
|
|
|
|
Hooks.on("deleteActiveEffect", (actor, effect, options) => actor.onDeleteActiveEffect(effect, options));
|
|
|
|
|
Hooks.on("createActiveEffect", (actor, effect, options) => actor.onCreateActiveEffect(effect, options));
|
|
|
|
|
Hooks.on("updateActor", (actor, update, options, actorId) => actor.onUpdateActor(update, options, actorId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
@ -99,18 +100,18 @@ export class RdDActor extends Actor {
|
|
|
|
|
// Make separate methods for each Actor type (character, npc, etc.) to keep
|
|
|
|
|
// things organized.
|
|
|
|
|
if (actorData.type === 'personnage') this._prepareCharacterData(actorData);
|
|
|
|
|
if (actorData.type === 'creature') this.prepareCreatureData(actorData);
|
|
|
|
|
if (actorData.type === 'vehicule') this.prepareVehiculeData(actorData);
|
|
|
|
|
if (actorData.type === 'creature') this._prepareCreatureData(actorData);
|
|
|
|
|
if (actorData.type === 'vehicule') this._prepareVehiculeData(actorData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
prepareCreatureData(actorData) {
|
|
|
|
|
_prepareCreatureData(actorData) {
|
|
|
|
|
this.computeEncombrementTotalEtMalusArmure();
|
|
|
|
|
this.computeEtatGeneral();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
prepareVehiculeData( actorData ) {
|
|
|
|
|
_prepareVehiculeData( actorData ) {
|
|
|
|
|
this.computeEncombrementTotalEtMalusArmure();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1105,7 +1106,7 @@ export class RdDActor extends Actor {
|
|
|
|
|
if (this.isEntiteCauchemar()) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return this.data.data.attributs?.sconst?.value ?? 0;
|
|
|
|
|
return RdDUtility.calculSConst(this.data.data.carac.constitution.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
@ -1177,18 +1178,14 @@ export class RdDActor extends Actor {
|
|
|
|
|
sonne: false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let minValue = 0;
|
|
|
|
|
if (this.type == 'personnage') {
|
|
|
|
|
// TODO: les animaux/humanoïdes on théoriquement aussi un sconst, mais la SPA n'est pas passé par là
|
|
|
|
|
minValue = name == "vie" ? -Number(this.data.data.attributs.sconst.value) : 0;
|
|
|
|
|
}
|
|
|
|
|
let minValue = name == "vie" ? -this.getSConst()-1 : 0;
|
|
|
|
|
|
|
|
|
|
result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max));
|
|
|
|
|
//console.log("New value ", inc, minValue, result.newValue);
|
|
|
|
|
let fatigue = 0;
|
|
|
|
|
if (name == "endurance" && this.data.type != 'entite') {
|
|
|
|
|
if (!isCritique && result.newValue == 0 && inc < 0) { // perte endurance et endurance devient 0 -> -1 vie sauf si coup critique
|
|
|
|
|
sante.vie.value = sante.vie.value - 1;
|
|
|
|
|
if (name == "endurance" && !this.isEntiteCauchemar()) {
|
|
|
|
|
if (result.newValue == 0 && inc < 0 && !isCritique) { // perte endurance et endurance devient 0 (sauf critique) -> -1 vie
|
|
|
|
|
sante.vie.value --;
|
|
|
|
|
}
|
|
|
|
|
result.newValue = Math.max(0, result.newValue);
|
|
|
|
|
if (inc > 0) { // le max d'endurance s'applique seulement à la récupération
|
|
|
|
@ -1202,6 +1199,7 @@ export class RdDActor extends Actor {
|
|
|
|
|
result.jetEndurance = testIsSonne.roll.total;
|
|
|
|
|
} else if (inc > 0) {
|
|
|
|
|
await this.setSonne(false);
|
|
|
|
|
sante.sonne.value = false;
|
|
|
|
|
}
|
|
|
|
|
if (sante.fatigue && inc < 0) { // Each endurance lost -> fatigue lost
|
|
|
|
|
fatigue = perte;
|
|
|
|
@ -1213,6 +1211,9 @@ export class RdDActor extends Actor {
|
|
|
|
|
if (sante.fatigue && fatigue > 0) {
|
|
|
|
|
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this._computeFatigueMin());
|
|
|
|
|
}
|
|
|
|
|
if (!this.isEntiteCauchemar() && sante.vie.value<-this.getSConst()) {
|
|
|
|
|
await this.addStatusEffectById('dead');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await this.update({ "data.sante": sante });
|
|
|
|
|
return result;
|
|
|
|
@ -2366,8 +2367,11 @@ export class RdDActor extends Actor {
|
|
|
|
|
count--;
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: status effect dead
|
|
|
|
|
ChatMessage.create({ content: `<strong>${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !</strong>` });
|
|
|
|
|
this.addStatusEffectById('dead');
|
|
|
|
|
ChatMessage.create({ content: `<img class="chat-icon" src="icons/svg/skull.svg" alt="charge" height="32" width="32" />
|
|
|
|
|
<strong>${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !</strong>` });
|
|
|
|
|
encaissement.critiques -= count;
|
|
|
|
|
encaissement.mort = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2639,6 +2643,13 @@ export class RdDActor extends Actor {
|
|
|
|
|
await this.update( { 'data.subacteurs.montures': newMontures });
|
|
|
|
|
}
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
async onUpdateActor(update, options, actorId) {
|
|
|
|
|
const updatedEndurance = update?.data?.sante?.endurance;
|
|
|
|
|
if (updatedEndurance && options.diff) {
|
|
|
|
|
this.forceStatusEffectId('unconscious', updatedEndurance.value == 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
async onCreateActiveEffect(effect, options) {
|
|
|
|
|
switch (StatusEffects.statusId(effect)) {
|
|
|
|
|
case 'sonne':
|
|
|
|
@ -2646,7 +2657,7 @@ export class RdDActor extends Actor {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
async onDeleteActiveEffect(effect, options) {
|
|
|
|
|
switch (StatusEffects.statusId(effect)) {
|
|
|
|
@ -2655,80 +2666,81 @@ export class RdDActor extends Actor {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
enleverTousLesEffets() {
|
|
|
|
|
this.deleteEmbeddedEntity('ActiveEffect', Array.from(this.effects?.keys() ?? []));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
listeEffets(matching = it => true) {
|
|
|
|
|
const all = Array.from(this.effects?.values() ?? []);
|
|
|
|
|
const filtered = all.filter(it => matching(it.data));
|
|
|
|
|
return filtered;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
async setStatusDemiReve(status) {
|
|
|
|
|
const options = { renderSheet: true/*, noHook: from == 'hook' */ };
|
|
|
|
|
if (status) {
|
|
|
|
|
await this.addEffect(StatusEffects.demiReve(), options)
|
|
|
|
|
await this.addStatusEffect(StatusEffects.demiReve())
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
this.deleteEffect(StatusEffects.demiReve(), options)
|
|
|
|
|
this.deleteStatusEffect(StatusEffects.demiReve())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
async setStatusSonne(sonne) {
|
|
|
|
|
if (this.isEntiteCauchemar()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const id = 'sonne';
|
|
|
|
|
const options = { renderSheet: true/*, noHook: from == 'hook' */ };
|
|
|
|
|
|
|
|
|
|
await this.forceStatusEffectId('sonne', sonne);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
async forceStatusEffectId(statusId, sonne) {
|
|
|
|
|
if (sonne) {
|
|
|
|
|
await this.addById(id, options);
|
|
|
|
|
await this.addStatusEffectById(statusId);
|
|
|
|
|
}
|
|
|
|
|
else /* if (!sonne)*/ {
|
|
|
|
|
this.deleteById(id, options)
|
|
|
|
|
else {
|
|
|
|
|
this.deleteStatusEffectById(statusId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
deleteById(id, options) {
|
|
|
|
|
deleteStatusEffectById(id, options = { renderSheet: true}) {
|
|
|
|
|
const effects = Array.from(this.effects?.values())
|
|
|
|
|
.filter(it => it.data.flags.core?.statusId == id);
|
|
|
|
|
this._deleteAll(effects, options);
|
|
|
|
|
this._deleteStatusEffects(effects, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
deleteEffect(effect, options) {
|
|
|
|
|
deleteStatusEffect(effect, options = { renderSheet: true}) {
|
|
|
|
|
const toDelete = Array.from(this.effects?.values())
|
|
|
|
|
.filter(it => StatusEffects.statusId(it.data) == StatusEffects.statusId(effect));
|
|
|
|
|
this._deleteAll(toDelete, options);
|
|
|
|
|
this._deleteStatusEffects(toDelete, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
_deleteAll(effects, options) {
|
|
|
|
|
this._deleteAllIds(effects.map(it => it.id), options);
|
|
|
|
|
_deleteStatusEffects(effects, options) {
|
|
|
|
|
this._deleteStatusEffectsByIds(effects.map(it => it.id), options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
_deleteAllIds(effectIds, options) {
|
|
|
|
|
_deleteStatusEffectsByIds(effectIds, options) {
|
|
|
|
|
this.deleteEmbeddedEntity('ActiveEffect', effectIds, options);
|
|
|
|
|
this.applyActiveEffects();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
async addById(id, options) {
|
|
|
|
|
async addStatusEffectById(id, options = { renderSheet: true}) {
|
|
|
|
|
const statusEffect = CONFIG.statusEffects.find(it => it.id == id);
|
|
|
|
|
await this.addEffect(statusEffect, options);
|
|
|
|
|
await this.addStatusEffect(statusEffect, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
|
async addEffect(statusEffect, options) {
|
|
|
|
|
this.deleteById(statusEffect.id, options);
|
|
|
|
|
async addStatusEffect(statusEffect, options = { renderSheet: true}) {
|
|
|
|
|
this.deleteStatusEffectById(statusEffect.id, options);
|
|
|
|
|
const effet = duplicate(statusEffect);
|
|
|
|
|
effet["flags.core.statusId"] = effet.id;
|
|
|
|
|
await this.createEmbeddedEntity('ActiveEffect', effet, options);
|
|
|
|
|