Skip to content

Commit

Permalink
feat(combat): token visibility
Browse files Browse the repository at this point in the history
* handle CSS issues with the "active" class not being properly set
* handle confusion around which actor is active
* localize strings for hidden slots
* remove slot names for hidden slots (only applies for non-GMs)
* correct image "has gone" state not being reset at the start of a new round
* handle removing combatants confusing the claimed slot state

#1343
#1340
  • Loading branch information
wrycu committed Feb 21, 2024
1 parent 208356e commit 99d04b2
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 12 deletions.
1 change: 1 addition & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@
"SWFFG.Combats.Actors.Friendly": "Friendly Actors",
"SWFFG.Combats.Actors.Enemy": "Enemy Actors",
"SWFFG.Combats.Actors.Neutral": "Neutral Actors",
"SWFFG.Combats.Actors.Hidden": "Hidden Actor",
"SWFFG.Settings.UseGenericSlots.Name": "Use Generic Slots",
"SWFFG.Settings.UseGenericSlots.Hint": "Replaces named slots in the combat tracker with generic, claimable slots"
}
51 changes: 46 additions & 5 deletions modules/combat-ffg.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,40 @@ export class CombatFFG extends Combat {
return [];
}

/**
* Check if a given combatant has any claims in the current combat round
* @param combatantId - STRING - the combatant ID (NOT token ID, NOT actor ID)
* @returns {boolean|string} - false if no claims, otherwise the round of the claimant
*/
hasClaims(combatantId) {
const claims = this.getClaims(this.round);
if (!claims) {
return false;
}
if (Object.values(claims).includes(combatantId)) {
return Object.keys(claims).find(key => claims[key] === combatantId);
} else {
return false;
}
}

async handleCombatantRemoval(combatant, options, combatantId) {
CONFIG.logger.debug(`Handling combatant removal of ${combatant?.name}`);
const claims = this.hasClaims(combatant.id);
if (!claims) {
CONFIG.logger.debug("No claimed slots found, nothing to do!");
return;
}
CONFIG.logger.debug("Claimed slots found, unclaiming...");
await this.unclaimSlot(this.round, claims);
CONFIG.logger.debug("...Done!");
}

async handleCombatantAddition(combatant, context, options, combatantI) {
// there may be cases when this is needed, but for now, we don't need to do anything
// (leaving as a placeholder until we know for sure)
}

/**
* Claim a slot for a given combatant
* @param round - INT - the round
Expand Down Expand Up @@ -381,7 +415,7 @@ export class CombatTrackerFFG extends CombatTracker {
const turns = this.viewed.turns.map((turn_initial, index) => {
let turn = data.turns.find(i => i.id === turn_initial.id);
if (turn === undefined) {
CONFIG.logger.warn("Turn not found, using initial data");
CONFIG.logger.debug("Turn not found, using initial data (this is expected for non-GMs if there are hidden units");
turn = turn_initial;
}
const combatant = combat.combatants.get(turn.id);
Expand Down Expand Up @@ -416,8 +450,6 @@ export class CombatTrackerFFG extends CombatTracker {
}
}

// propagate this to the overall turn data, so we can gray out claimed slots
this.viewed.turns.find(i => i.id === claimant.id).claimed = true;
const hidden = this._getTokenHidden(claimant.tokenId);

if (!hidden && turn.css) {
Expand All @@ -435,15 +467,21 @@ export class CombatTrackerFFG extends CombatTracker {
effects,
};
turn.hidden = hidden;
turn.tokenId = claimant.tokenId;
} else {
CONFIG.logger.debug(`slot ${index} is unclaimed`);
combatant.hidden = this._getTokenHidden(combatant.tokenId);
turn.tokenId = combatant.tokenId;
// sync the turn state to the token state
turn.hidden = combatant.hidden;
}

if (combatant.css === undefined) {
combatant.css = "";
}
if (combat.turn === index) {
combatant.active = true;
combatant.css += "active";
combatant.css += " active";
} else {
combatant.active = false;
combatant.css = "";
Expand Down Expand Up @@ -490,12 +528,15 @@ export class CombatTrackerFFG extends CombatTracker {
// update visibility state for each token
for (const turn of turnData['Friendly']) {
turn.hidden = this._getTokenHidden(turn.tokenId);
turn.claimed = combat.hasClaims(combat.combatants.find(i => i.tokenId === turn.tokenId).id);
}
for (const turn of turnData['Enemy']) {
turn.hidden = this._getTokenHidden(turn.tokenId);
turn.claimed = combat.hasClaims(combat.combatants.find(i => i.tokenId === turn.tokenId).id);
}
for (const turn of turnData['Neutral']) {
turn.hidden = this._getTokenHidden(turn.tokenId);
turn.claimed = combat.hasClaims(combat.combatants.find(i => i.tokenId === turn.tokenId).id);
}

return {
Expand Down Expand Up @@ -573,7 +614,7 @@ export class CombatTrackerFFG extends CombatTracker {
if (token) {
hidden = token.hidden;
}
CONFIG.logger.debug(`looking up hidden state for ${token.name}/${tokenId} on scene ${scene.id}: ${hidden}`);
CONFIG.logger.debug(`looking up hidden state for ${token?.name}/${tokenId} on scene ${scene.id}: ${hidden}`);
return hidden;
}
}
Expand Down
9 changes: 9 additions & 0 deletions modules/swffg-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,15 @@ Hooks.once("init", async function () {
updateCombatTracker();
}
});

Hooks.on("preCreateCombatant", async (combatant, context, options, combatantId) => {
console.log("caught create combatant")
await game.combat.handleCombatantAddition(combatant, context, options, combatantId);
});
Hooks.on("preDeleteCombatant", async (combatant, options, unknownId) => {
console.log("caught delete combatant")
await game.combat.handleCombatantRemoval(combatant, options, unknownId);
});
}

await gameSkillsList();
Expand Down
14 changes: 7 additions & 7 deletions templates/dialogs/combat-tracker.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ <h3 class="encounter-title noborder">{{localize "COMBAT.None"}}</h3>
<div class="encounter-controls flexrow flex-center{{#if hasCombat}} combat{{/if}}">
{{#each turnData.Friendly }}
{{#if ../user.isGM }}
<img class="token-image actor-header friendly{{#if claimed}} slot-claimed{{/if}}" src="{{img}}" alt="{{name}} data-combatant-id="{{id}}""/>
<img class="combatant token-image actor-header friendly{{#if claimed}} slot-claimed{{/if}}" src="{{img}}" alt="{{name}}" data-combatant-id="{{id}}"/>
{{else}}
{{#if hidden}}
<img class="combatant token-image actor-header enemy{{#if claimed}} slot-claimed{{/if}}" src="systems/starwarsffg/images/combat/hidden.png" alt="{{name}}"/>
<img class="combatant token-image actor-header enemy{{#if claimed}} slot-claimed{{/if}}" src="systems/starwarsffg/images/combat/hidden.png" alt="{{localize "SWFFG.Combats.Actors.Hidden"}}"/>
{{else}}
<img class="token-image actor-header friendly{{#if claimed}} slot-claimed{{/if}}" src="{{img}}" alt="{{name}} data-combatant-id="{{id}}""/>
<img class="combatant token-image actor-header friendly{{#if claimed}} slot-claimed{{/if}}" src="{{img}}" alt="{{name}}" data-combatant-id="{{id}}"/>
{{/if}}
{{/if}}
{{/each}}
Expand All @@ -89,7 +89,7 @@ <h3 class="encounter-title noborder">{{localize "COMBAT.None"}}</h3>
<img class="combatant token-image actor-header enemy{{#if claimed}} slot-claimed{{/if}}" src="{{img}}" alt="{{name}}" data-combatant-id="{{id}}"/>
{{else}}
{{#if hidden}}
<img class="combatant token-image actor-header enemy{{#if claimed}} slot-claimed{{/if}}" src="systems/starwarsffg/images/combat/hidden.png" alt="{{name}}"/>
<img class="combatant token-image actor-header enemy{{#if claimed}} slot-claimed{{/if}}" src="systems/starwarsffg/images/combat/hidden.png" alt="{{localize "SWFFG.Combats.Actors.Hidden"}}"/>
{{else}}
<img class="combatant token-image actor-header enemy{{#if claimed}} slot-claimed{{/if}}" src="{{img}}" alt="{{name}}" data-combatant-id="{{id}}"/>
{{/if}}
Expand All @@ -107,7 +107,7 @@ <h3 class="encounter-title noborder">{{localize "COMBAT.None"}}</h3>
<img class="combatant token-image actor-header neutral{{#if claimed}} slot-claimed{{/if}}" src="{{img}}" alt="{{name}}" data-combatant-id="{{id}}"/>
{{else}}
{{#if hidden}}
<img class="combatant token-image actor-header neutral{{#if claimed}} slot-claimed{{/if}}" src="systems/starwarsffg/images/combat/hidden.png" alt="{{name}}"/>
<img class="combatant token-image actor-header neutral{{#if claimed}} slot-claimed{{/if}}" src="systems/starwarsffg/images/combat/hidden.png" alt="{{localize "SWFFG.Combats.Actors.Hidden"}}"/>
{{else}}
<img class="combatant token-image actor-header neutral{{#if claimed}} slot-claimed{{/if}}" src="{{img}}" alt="{{name}}" data-combatant-id="{{id}}"/>
{{/if}}
Expand All @@ -122,7 +122,7 @@ <h3 class="encounter-title noborder">{{localize "COMBAT.None"}}</h3>
<img class="token-image" data-src="{{img}}" alt="{{name}}"/>
{{else}}
{{#if hidden }}
<img class="token-image" data-src="systems/starwarsffg/images/combat/hidden.png" alt="{{name}}"/>
<img class="token-image" data-src="systems/starwarsffg/images/combat/hidden.png" alt="{{localize "SWFFG.Combats.Actors.Hidden"}}"/>
{{else}}
<img class="token-image" data-src="{{img}}" alt="{{name}}"/>
{{/if}}
Expand All @@ -132,7 +132,7 @@ <h3 class="encounter-title noborder">{{localize "COMBAT.None"}}</h3>
<h4>{{name}}</h4>
{{else}}
{{#if hidden }}
<h4>Unknown</h4>
<h4>{{localize "SWFFG.Combats.Actors.Hidden"}}</h4>
{{else}}
<h4>{{name}}</h4>
{{/if}}
Expand Down

0 comments on commit 99d04b2

Please sign in to comment.