Skip to content

Commit

Permalink
Merge pull request dmdorman#1483 from aeauseth/main
Browse files Browse the repository at this point in the history
Conditional Defenses, Darkness cost, stack size fix, NaN when uploading. Removed old determineDefense code
  • Loading branch information
aeauseth authored Nov 19, 2024
2 parents d2626db + 79e9e95 commit 81f363b
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 696 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Version 4.0.7 (So far...) [Hero System 6e (Unofficial) v2](https://github.com/dmdorman/hero6e-foundryvtt)

- Conditional DAMAGEREDUCTION and DAMAGENEGATION defenses now prompt for applicability. [#1478](https://github.com/dmdorman/hero6e-foundryvtt/issues/1478)
- Conditional defenses with special effects will attempt to automatically determine if it applies. GM still has to confirm conditional effects.

## Version 4.0.6

- Migrations are no longer supported from versions before 3.0.76. Migrate through any version prior to 4.0.6 if you find your world in this situation.
Expand Down
14 changes: 2 additions & 12 deletions module/actor/actor-sheet.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { HeroSystem6eActor } from "./actor.mjs";
import { HeroSystem6eItem } from "../item/item.mjs";
import { userInteractiveVerifyOptionallyPromptThenSpendResources } from "../item/item-attack.mjs";

import { determineDefense, getActorDefensesVsAttack } from "../utility/defense.mjs";
import { getActorDefensesVsAttack } from "../utility/defense.mjs";
import { presenceAttackPopOut } from "../utility/presence-attack.mjs";
import { onManageActiveEffect } from "../utility/effects.mjs";
import { getPowerInfo, getCharacteristicInfoArrayForActor, whisperUserTargetsForActor } from "../utility/util.mjs";
Expand Down Expand Up @@ -54,7 +54,7 @@ export class HeroSystemActorSheet extends ActorSheet {
}

// Items returned by the super have been neutered, we want the full class so we can use parentItem and childItem getters.
data.items = Array.from(data.items).sort((a, b) => (a.sort || 0) - (b.sort || 0));
data.items = Array.from(data.actor.items).sort((a, b) => (a.sort || 0) - (b.sort || 0));

// const equipmentWeightPercentage =
// parseInt(game.settings.get(game.system.id, "equipmentWeightPercentage")) / 100.0;
Expand Down Expand Up @@ -383,22 +383,12 @@ export class HeroSystemActorSheet extends ActorSheet {
);
await drainAttack._postUpload();

let {
defenseValue: _defenseValuePOWD,
// resistantValue:
// _resistantValuePOWD /*impenetrableValuePOWD*/ /*damageReductionValuePOWD*/ /*damageNegationValuePOWD*/ /*knockbackResistancePOWD*/,
// defenseTags: defenseTagsPOWD,
} = determineDefense(this.actor, drainAttack, { suppressDeprecationWarn: true });

// New POWERDEFENSE
const {
defenseValue: defenseValuePOWD,
resistantValue: resistantValuePOWD,
defenseTags: defenseTagsPOWD,
} = getActorDefensesVsAttack(this.actor, drainAttack);
if (_defenseValuePOWD != defenseValuePOWD) {
console.warn("POWERDEFENSE Defense mismatch", _defenseValuePOWD, defenseValuePOWD);
}
defense.POWD = defenseValuePOWD;
for (const tag of defenseTagsPOWD.filter((o) => o.operation === "add" && !o.options?.resistant)) {
defense.POWDtags = `${defense.POWDtags || ""}${tag.value.signedString()} ${tag.name} ${
Expand Down
3 changes: 2 additions & 1 deletion module/actor/actor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2136,7 +2136,7 @@ export class HeroSystem6eActor extends Actor {
// Characteristics
for (const key of Object.keys(this.system.characteristics)) {
let newValue = parseInt(this.system?.[key.toUpperCase()]?.LEVELS || 0);
newValue += this.getCharacteristicBase(key);
newValue += this.getCharacteristicBase(key) || 0; // 5e will have empty base for ocv/dcv and other figured characteristics
if (this.system.is5e && key === "spd") {
// SPD is always an integer, but in 5e due to figured characteristics, the base can be fractional.
newValue = Math.floor(newValue);
Expand All @@ -2156,6 +2156,7 @@ export class HeroSystem6eActor extends Actor {
}
if (
this.system.characteristics[key].value !== this.system.characteristics[key.toLowerCase()].max &&
this.system.characteristics[key.toLowerCase()].max !== null &&
overrideValues
) {
if (this.id) {
Expand Down
14 changes: 13 additions & 1 deletion module/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4685,7 +4685,19 @@ function addPower(powerDescription6e, powerOverrideFor5e) {
key: "DARKNESS",
type: ["sense-affecting", "attack", "standard"],
behaviors: ["attack"],
costPerLevel: costPerLevelFixedValue(0),
costPerLevel: function (item) {
switch (item?.system?.OPTIONID) {
case "SIGHTGROUP":
return 5; // Targeting sense gruop
case "HEARINGGROUP":
case "MENTALGROUP":
case "RADIOGROUP":
case "SMELLGROUP":
case "TOUCHGROUP":
return 3; // Non-targeting sense group
}
return 0;
},
duration: "constant",
range: HERO.RANGE_TYPES.STANDARD,
costEnd: true,
Expand Down
31 changes: 4 additions & 27 deletions module/item/item-attack.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HEROSYS } from "../herosystem6e.mjs";
import { getPowerInfo, getCharacteristicInfoArrayForActor, whisperUserTargetsForActor } from "../utility/util.mjs";
import { determineDefense, getActorDefensesVsAttack } from "../utility/defense.mjs";
import { getActorDefensesVsAttack, defenseConditionalCheckedByDefault } from "../utility/defense.mjs";
import { HeroSystem6eActorActiveEffects } from "../actor/actor-active-effects.mjs";
import { RoundFavorPlayerDown, RoundFavorPlayerUp } from "../utility/round.mjs";
import {
Expand Down Expand Up @@ -1269,16 +1269,6 @@ async function _rollApplyKnockback(token, knockbackDice) {
let ignoreDefenseIds = [];

let defense = "";
// Old Defense Stuff
let {
defenseValue: _defenseValue,
// resistantValue: _resistantValue,
// impenetrableValue: _impenetrableValue,
// damageReductionValue: _damageReductionValue,
damageNegationValue: _damageNegationValue,
knockbackResistanceValue: _knockbackResistanceValue,
//defenseTags: _defenseTags,
} = determineDefense(token.actor, pdAttack, { ignoreDefenseIds });

// New Defense Stuff
let {
Expand All @@ -1291,16 +1281,6 @@ async function _rollApplyKnockback(token, knockbackDice) {
defenseTags,
} = getActorDefensesVsAttack(token.actor, pdAttack, { ignoreDefenseIds });

if (damageNegationValue != _damageNegationValue) {
console.warn("damageNegationValue mismatch", damageNegationValue, _damageNegationValue);
}
if (defenseValue != _defenseValue) {
console.warn("defenseValue mismatch", defenseValue, _defenseValue);
}
if (knockbackResistanceValue != _knockbackResistanceValue) {
console.warn("knockbackResistanceValue mismatch", knockbackResistanceValue, _knockbackResistanceValue);
}

if (damageNegationValue > 0) {
defense += "Damage Negation " + damageNegationValue + "DC(s); ";
}
Expand Down Expand Up @@ -1758,7 +1738,7 @@ export async function _onRollMindScanEffectRoll(event) {
damageNegationValue,
knockbackResistanceValue,
defenseTags,
} = determineDefense(token.actor, item, { ignoreDefenseIds });
} = getActorDefensesVsAttack(token.actor, item, { ignoreDefenseIds });
if (damageNegationValue > 0) {
defense += "Damage Negation " + damageNegationValue + "DC(s); ";
}
Expand Down Expand Up @@ -1970,7 +1950,6 @@ export async function _onApplyDamageToSpecificToken(event, tokenId) {
}

// Check for conditional defenses

let ignoreDefenseIds = [];
let conditionalDefenses = token.actor.items.filter(
(o) =>
Expand All @@ -1982,9 +1961,7 @@ export async function _onApplyDamageToSpecificToken(event, tokenId) {

// Remove conditional defenses that provide no defense
if (!game.settings.get(HEROSYS.module, "ShowAllConditionalDefenses")) {
conditionalDefenses = conditionalDefenses.filter(
(defense) => defense.getDefense(token.actor, item).defenseTotalValue > 0,
);
conditionalDefenses = conditionalDefenses.filter((defense) => defense.getDefense(token.actor, item));
}

// AVAD Life Support
Expand Down Expand Up @@ -2031,7 +2008,7 @@ export async function _onApplyDamageToSpecificToken(event, tokenId) {
const option = {
id: defense.id,
name: defense.name,
checked: !avad && defense.getDefense(token.actor, item).defenseTotalValue > 0,
checked: !avad && defenseConditionalCheckedByDefault(defense, item),
conditions: "",
};

Expand Down
16 changes: 14 additions & 2 deletions module/item/item.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { HeroRoller } from "../utility/dice.mjs";
import { HeroSystem6eActorActiveEffects } from "../actor/actor-active-effects.mjs";
import { Attack } from "../utility/attack.mjs";
import { activateSpecialVision, removeSpecialVisions } from "../utility/vision.mjs";
import { determineDefense } from "../utility/defense.mjs";
import { getItemDefenseVsAttack } from "../utility/defense.mjs";
import { overrideCanAct } from "../settings/settings-helpers.mjs";

export function initializeItemHandlebarsHelpers() {
Expand Down Expand Up @@ -433,6 +433,9 @@ export class HeroSystem6eItem extends Item {
}
}

// Perceivability
content += ` ${this.perceivability}.`;

if (this.system.end) {
content += ` Estimated End: ${this.system.end}.`;
}
Expand Down Expand Up @@ -2221,6 +2224,7 @@ export class HeroSystem6eItem extends Item {
get parentItem() {
const parentId = this.system?.PARENTID;
if (!parentId) return null;
if (!this.system?.ID) return null;

const items = this.actor?.items || game.items;
return items.find((item) => item.system?.ID === parentId) || null;
Expand All @@ -2241,6 +2245,9 @@ export class HeroSystem6eItem extends Item {
// }
// game.packs.get(this.pack).index.contents

// Super old items may not have an ID
if (!this.system?.ID) return [];

const items = this.actor?.items || (this.pack ? [] : game.items);

const children = items
Expand Down Expand Up @@ -4838,7 +4845,8 @@ export class HeroSystem6eItem extends Item {
}

getDefense(targetActor, attackItem) {
return determineDefense(targetActor, attackItem, { only: this });
//return determineDefense(targetActor, attackItem, { only: this });
return getItemDefenseVsAttack(this, attackItem);
}

get attackDefenseVs() {
Expand Down Expand Up @@ -4942,6 +4950,10 @@ export class HeroSystem6eItem extends Item {
return false;
}

get perceivability() {
return this.baseInfo.perceivability;
}

get weightKg() {
const equipmentWeightPercentage =
parseInt(game.settings.get(game.system.id, "equipmentWeightPercentage")) / 100.0;
Expand Down
10 changes: 5 additions & 5 deletions module/testing/testing-defense.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HeroSystem6eActor } from "../actor/actor.mjs";
import { HeroSystem6eItem } from "../item/item.mjs";
import { determineDefense } from "../utility/defense.mjs";
import { getActorDefensesVsAttack } from "../utility/defense.mjs";

export function registerDefenseTests(quench) {
quench.registerBatch(
Expand Down Expand Up @@ -38,7 +38,7 @@ export function registerDefenseTests(quench) {
});
await itemAttack._postUpload();

const defense = determineDefense(actor, itemAttack);
const defense = getActorDefensesVsAttack(actor, itemAttack);
assert.equal(defense.resistantValue, 1);
});

Expand Down Expand Up @@ -71,7 +71,7 @@ export function registerDefenseTests(quench) {
});
await itemAttack._postUpload();

const defense = determineDefense(actor, itemAttack);
const defense = getActorDefensesVsAttack(actor, itemAttack);
assert.equal(defense.resistantValue, 2);
});

Expand Down Expand Up @@ -105,7 +105,7 @@ export function registerDefenseTests(quench) {
});
await itemAttack._postUpload();

const defense = determineDefense(actor, itemAttack);
const defense = getActorDefensesVsAttack(actor, itemAttack);
assert.equal(defense.resistantValue, 3);
});

Expand Down Expand Up @@ -140,7 +140,7 @@ export function registerDefenseTests(quench) {

await itemAttack._postUpload();

const defense = determineDefense(actor, itemAttack);
const defense = getActorDefensesVsAttack(actor, itemAttack);
assert.equal(defense.resistantValue, 4);
});
});
Expand Down
Loading

0 comments on commit 81f363b

Please sign in to comment.