Skip to content

Commit

Permalink
Merge pull request dmdorman#1564 from aeauseth/main
Browse files Browse the repository at this point in the history
Fix for SPD+1.  Combat Tracker improvement. Experimental Hidden Combatants.
  • Loading branch information
aeauseth authored Dec 1, 2024
2 parents 0bd58e8 + 16a1935 commit 11a7742
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 42 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Releases

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

- Fix for SPD purchased as a power not contributing to final values during upload. [#1439](https://github.com/dmdorman/hero6e-foundryvtt/issues/1439)
- Fix for combat tracker where sometimes it would skip combatants when new combatants were added/removed. [#1447](https://github.com/dmdorman/hero6e-foundryvtt/issues/1447)

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

- Correct 5e Elemental Control cost. [#1416](https://github.com/dmdorman/hero6e-foundryvtt/issues/1416)
Expand Down
5 changes: 5 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@
"Name": "Show all Conditional Defenses",
"Hint": "Conditional Defenses that provide no obvious defense are hidden by default. There may be some edge cases where these defenses should be applied. Enabling this setting will give the GM an opportunity to apply a conditional defense, even when the automation thinks it does not apply."
},
"ShowOnlyVisibleCombatants": {
"Name": "Show only visible combatants",
"Hint": "Show only the combatants that you can currently see. When a combatant goes around a corner or turns invisible, they will not show up on the combat tracker. Currently experimental."
},

"DefaultEdition" : {
"Name": "Default System Rules",
"Hint": "The system rules are typically determined by the edition defined within the HDC file you import for each actor. When there is no actor (or otherwise 5e/6e cannot be determined) we will use this choice for the rule system. Also used to create the HeroSystem compendium.",
Expand Down
6 changes: 6 additions & 0 deletions module/actor/actor-token.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,17 @@ export class HeroSystem6eToken extends Token {

_onControl(options) {
if (game.ready) game[HEROSYS.module].effectPanel.refresh();
if (game.ready && game.combat) {
game.combat.collection.render();
}
return super._onControl(options);
}

_onRelease(options) {
if (game.ready) game[HEROSYS.module].effectPanel.refresh();
if (game.ready && game.combat) {
game.combat.collection.render();
}
return super._onRelease(options);
}
}
9 changes: 6 additions & 3 deletions module/actor/actor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,12 @@ export class HeroSystem6eActor extends Actor {
uploadPerformance.actorPostUpload = new Date() - uploadPerformance._d;
uploadPerformance._d = new Date();

// For some unknown reason SPD with AE not working during upload.
// This kludge is a quick fix
// https://github.com/dmdorman/hero6e-foundryvtt/issues/1439
await this.update({ "system.characteristics.spd.max": this.system.characteristics.spd.core });
await this.update({ "system.characteristics.spd.value": this.system.characteristics.spd.max });

// Re-run _postUpload for CSL's or items that showAttacks so we can guess associated attacks (now that all attacks are loaded)
this.items
.filter((item) => item.system.csl || item.baseInfo?.editOptions?.showAttacks)
Expand Down Expand Up @@ -2173,9 +2179,6 @@ export class HeroSystem6eActor extends Actor {
//if (key.toLowerCase() === "spd") debugger;

let newValue = parseInt(this.system?.[key.toUpperCase()]?.LEVELS || 0); // uppercase? LEVELS? This probably hasn't worked in a long time!
if (newValue) {
console.log("newVALUE");
}
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.
Expand Down
44 changes: 5 additions & 39 deletions module/combat.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class HeroSystem6eCombat extends Combat {
// We could use rollAll() here, but rollInitiative is probably more efficient.
await this.rollInitiative(documents.map((o) => o.id));

// Get current combatant
// Get current combatant and try to maintain turn order to the best of our ability
const priorState = foundry.utils.deepClone(this.current);
this.setupTurns();
await this.assignSegments(priorState.tokenId);
Expand Down Expand Up @@ -185,11 +185,6 @@ export class HeroSystem6eCombat extends Combat {
for (let c = 0; c < tokenCombatantCount; c++) {
const _combatant = tokenCombatants[c];
const spd = clamp(parseInt(_combatant.actor?.system.characteristics.spd?.value || 0), 1, 12);
// const initiativeTooltip = `${
// _combatant.flags.initiative
// }${_combatant.flags.initiativeCharacteristic.toUpperCase()} ${spd}SPD ${
// lightningReflexes?.system.LEVELS ? `${lightningReflexes.system.LEVELS}LR` : ""
// }`;
if (spd) {
const segment = HeroSystem6eCombat.getSegment(spd, Math.floor(c * (lightningReflexes ? 0.5 : 1)));
let update = {
Expand Down Expand Up @@ -242,7 +237,7 @@ export class HeroSystem6eCombat extends Combat {
// Only 1 GM should do this
if (!game.users.activeGM?.isSelf) return;

const uniqueTokens = Array.from(new Set(this.combatants.map((o) => o.tokenId))); //this.combatants.filter((c, i, ar) => ar.indexOf(c) === i);
const uniqueTokens = Array.from(new Set(this.combatants.map((o) => o.tokenId)));
for (const _tokenId of uniqueTokens) {
const _combatant = this.combatants.find((o) => o.tokenId === _tokenId && o.actor);
if (!_combatant?.isOwner) continue;
Expand Down Expand Up @@ -278,37 +273,6 @@ export class HeroSystem6eCombat extends Combat {
// Add custom hero flags for segments and such
if (tokenCombatantCount === targetCombatantCount) {
await this.assignSegments(_tokenId);
// const updates = [];
// for (let c = 0; c < tokenCombatantCount; c++) {
// const _combatant = tokenCombatants[c];
// const spd = parseInt(_combatant.actor?.system.characteristics.spd.value);
// if (spd) {
// const segment = HeroSystem6eCombat.getSegment(
// spd,
// Math.floor(c * (lightningReflexes ? 0.5 : 1)),
// );
// let update = {
// _id: _combatant.id,
// initiative: _combatant.flags.initiative,
// "flags.segment": segment,
// "flags.spd": spd,
// };
// if (lightningReflexes && c % 2 === 0) {
// update = {
// ...update,
// initiative:
// _combatant.flags.initiative + parseInt(lightningReflexes?.system.LEVELS || 0),
// "flags.lightningReflexes.levels": parseInt(lightningReflexes.system.LEVELS),
// "flags.lightningReflexes.name":
// lightningReflexes.system.OPTION_ALIAS ||
// lightningReflexes.system.INPUT ||
// "All Actions",
// };
// }
// updates.push(update);
// }
// }
// await this.updateEmbeddedDocuments("Combatant", updates);
}
}
}
Expand Down Expand Up @@ -419,6 +383,8 @@ export class HeroSystem6eCombat extends Combat {
}

// We need a single combatant to store some flags. Like for DragRuler, end tracking, etc.
// getCombatantByToken seems to get the first combatant in combat.turns that is for our token.
// This likely causes issues when SPD/LightningReflexes changes.
const masterCombatant = this.getCombatantByToken(combatant.tokenId);

await super._onStartTurn(combatant);
Expand Down Expand Up @@ -911,7 +877,7 @@ export class HeroSystem6eCombat extends Combat {
// Find Exact match
let combatTurn = this.turns.findIndex(
(o) =>
o.id === priorState.combatantId &&
o.tokenId === priorState.tokenId &&
o.flags.segment === priorState.segment &&
o.initiative === priorState.initiative,
);
Expand Down
11 changes: 11 additions & 0 deletions module/combatTracker.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ export class HeroSystem6eCombatTracker extends CombatTracker {
for (let [i, combatant] of combat.turns.entries()) {
if (!combatant.visible) continue;

// Is this token visible by the player? Always show PC's
if (game.settings.get(HEROSYS.module, "ShowOnlyVisibleCombatants")) {
if (
!game.user.isGM &&
canvas.visibility?.testVisibility(combatant.token) === false &&
combatant.actor.type !== "pc"
) {
continue;
}
}

// Prepare turn data
const resource =
combatant.permission >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER ? combatant.resource : null;
Expand Down
11 changes: 11 additions & 0 deletions module/settings/settings-helpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,17 @@ export default class SettingsHelpers {
requiresReload: false,
});

game.settings.register(module, "ShowOnlyVisibleCombatants", {
name: game.i18n.localize("Settings.ShowOnlyVisibleCombatants.Name"),
hint: game.i18n.localize("Settings.ShowOnlyVisibleCombatants.Hint"),
scope: "world",
config: true,
type: Boolean,
default: false,
//onChange: () => ui.combat.render(),
requiresReload: false,
});

game.settings.register(module, "alphaTesting", {
name: game.i18n.localize("Settings.AlphaTesting.Name"),
hint: game.i18n.localize("Settings.AlphaTesting.Hint"),
Expand Down

0 comments on commit 11a7742

Please sign in to comment.