Get most of the custom Initiative sorting stuff through the door
This commit is contained in:
parent
ed93e9f927
commit
e302b56a4e
10 changed files with 142 additions and 14 deletions
|
|
@ -16,6 +16,7 @@ export default [
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
globals: {
|
globals: {
|
||||||
CONFIG: `writable`,
|
CONFIG: `writable`,
|
||||||
|
CONST: `readonly`,
|
||||||
game: `readonly`,
|
game: `readonly`,
|
||||||
Handlebars: `readonly`,
|
Handlebars: `readonly`,
|
||||||
Hooks: `readonly`,
|
Hooks: `readonly`,
|
||||||
|
|
@ -32,6 +33,7 @@ export default [
|
||||||
TextEditor: `readonly`,
|
TextEditor: `readonly`,
|
||||||
fromUuid: `readonly`,
|
fromUuid: `readonly`,
|
||||||
Combat: `readonly`,
|
Combat: `readonly`,
|
||||||
|
Combatant: `readonly`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixi
|
||||||
ctx.fate.selected = ctx.actor.system.fate;
|
ctx.fate.selected = ctx.actor.system.fate;
|
||||||
ctx.fate.options = [
|
ctx.fate.options = [
|
||||||
{ label: `RipCrypt.common.empty`, v: `` },
|
{ label: `RipCrypt.common.empty`, v: `` },
|
||||||
...gameTerms.FatePath
|
...Object.values(gameTerms.FatePath)
|
||||||
.map(v => ({ label: `RipCrypt.common.path.${v}`, value: v })),
|
.map(v => ({ label: `RipCrypt.common.path.${v}`, value: v })),
|
||||||
];
|
];
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Logger } from "../../utils/Logger.mjs";
|
||||||
|
|
||||||
|
const { CombatTracker } = foundry.applications.sidebar.tabs;
|
||||||
|
|
||||||
|
export class RipCryptCombatTracker extends CombatTracker {
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
async _prepareTurnContext(combat, combatant, index) {
|
||||||
|
Logger.debug(`_prepareTurnContext`);
|
||||||
|
const turn = await super._prepareTurnContext(combat, combatant, index);
|
||||||
|
|
||||||
|
// if ( !this.viewed ) return;
|
||||||
|
|
||||||
|
// ! TODO: This is causing an error while the combat is not active, but is fine when it's active, this needs to be fixed
|
||||||
|
Logger.debug(turn, combatant);
|
||||||
|
const groupKey = combatant.groupKey;
|
||||||
|
if (groupKey) {
|
||||||
|
turn.active ||= combat.combatant.groupKey === groupKey;
|
||||||
|
if (turn.active && !turn.css.includes(`active`)) {
|
||||||
|
turn.css += `active`;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return turn;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -90,7 +90,7 @@ export class HeroData extends foundry.abstract.TypeDataModel {
|
||||||
trim: true,
|
trim: true,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
choices: () => {
|
choices: () => {
|
||||||
return gameTerms.FatePath.concat(``);
|
return Object.values(gameTerms.FatePath).concat(``);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
level: new fields.SchemaField({
|
level: new fields.SchemaField({
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,24 @@ Resources:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class RipCryptCombat extends Combat {
|
export class RipCryptCombat extends Combat {
|
||||||
|
|
||||||
|
get groups() {
|
||||||
|
let groups = new Map();
|
||||||
|
|
||||||
|
for (const combatant of this.combatants) {
|
||||||
|
const groupKey = combatant.groupKey;
|
||||||
|
if (!groupKey) { continue };
|
||||||
|
|
||||||
|
if (groups.has(groupKey)) {
|
||||||
|
groups.get(groupKey).push(combatant);
|
||||||
|
} else {
|
||||||
|
groups.set(groupKey, [combatant]);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
* Sorts combatants for the combat tracker in the following way:
|
* Sorts combatants for the combat tracker in the following way:
|
||||||
|
|
@ -14,13 +32,14 @@ export class RipCryptCombat extends Combat {
|
||||||
*/
|
*/
|
||||||
_sortCombatants(a, b) {
|
_sortCombatants(a, b) {
|
||||||
// The distance from fate
|
// The distance from fate
|
||||||
|
return super._sortCombatants(a, b) * -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
nextTurn() {
|
// nextTurn() {
|
||||||
// Make it skip all combatants with the same initiative value
|
// // Make it skip all combatants with the same initiative value
|
||||||
};
|
// };
|
||||||
|
|
||||||
previousTurn() {
|
// previousTurn() {
|
||||||
// Go back a step
|
// // Go back a step
|
||||||
};
|
// };
|
||||||
};
|
};
|
||||||
|
|
|
||||||
37
module/documents/combatant.mjs
Normal file
37
module/documents/combatant.mjs
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { distanceBetweenFates } from "../utils/distanceBetweenFates.mjs";
|
||||||
|
|
||||||
|
export class RipCryptCombatant extends Combatant {
|
||||||
|
|
||||||
|
async _preCreate(data, options, user) {
|
||||||
|
const allowed = await super._preCreate(data, options, user);
|
||||||
|
if (allowed === false) { return false };
|
||||||
|
|
||||||
|
const start = game.settings.get(`ripcrypt`, `currentFate`);
|
||||||
|
const end = this.actor?.system?.fate || this.baseActor?.system?.fate;
|
||||||
|
const fateDistance = distanceBetweenFates(start, end);
|
||||||
|
|
||||||
|
this.updateSource({
|
||||||
|
initiative: fateDistance,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
get groupKey() {
|
||||||
|
const path = this.token?.actor?.system?.fate;
|
||||||
|
|
||||||
|
// Disallow grouping things that don't have a fate path
|
||||||
|
if (!path) { return null };
|
||||||
|
|
||||||
|
// Token Disposition (group into: friendlies, unknown, hostiles)
|
||||||
|
let disposition = `unknown`;
|
||||||
|
switch (this.token.disposition) {
|
||||||
|
case CONST.TOKEN_DISPOSITIONS.HOSTILE:
|
||||||
|
disposition = `hostile`;
|
||||||
|
break;
|
||||||
|
case CONST.TOKEN_DISPOSITIONS.FRIENDLY:
|
||||||
|
disposition = `friendly`;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
return `${path}:${disposition}`;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -11,12 +11,12 @@ export const gameTerms = Object.preventExtensions({
|
||||||
FLECT: `flect`,
|
FLECT: `flect`,
|
||||||
FRACT: `fract`,
|
FRACT: `fract`,
|
||||||
}),
|
}),
|
||||||
FatePath: [
|
FatePath: Object.freeze({
|
||||||
`North`,
|
NORTH: `North`,
|
||||||
`East`,
|
EAST: `East`,
|
||||||
`South`,
|
SOUTH: `South`,
|
||||||
`West`,
|
WEST: `West`,
|
||||||
],
|
}),
|
||||||
Access: [
|
Access: [
|
||||||
`Common`,
|
`Common`,
|
||||||
`Uncommon`,
|
`Uncommon`,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ import { registerDevSettings } from "../settings/devSettings.mjs";
|
||||||
import { registerMetaSettings } from "../settings/metaSettings.mjs";
|
import { registerMetaSettings } from "../settings/metaSettings.mjs";
|
||||||
import { registerUserSettings } from "../settings/userSettings.mjs";
|
import { registerUserSettings } from "../settings/userSettings.mjs";
|
||||||
import { registerWorldSettings } from "../settings/worldSettings.mjs";
|
import { registerWorldSettings } from "../settings/worldSettings.mjs";
|
||||||
|
import { RipCryptCombat } from "../documents/combat.mjs";
|
||||||
|
import { RipCryptCombatant } from "../documents/combatant.mjs";
|
||||||
|
import { RipCryptCombatTracker } from "../Apps/sidebar/CombatTracker.mjs";
|
||||||
|
|
||||||
Hooks.once(`init`, () => {
|
Hooks.once(`init`, () => {
|
||||||
Logger.log(`Initializing`);
|
Logger.log(`Initializing`);
|
||||||
|
|
@ -53,6 +56,9 @@ Hooks.once(`init`, () => {
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region Class Changes
|
// #region Class Changes
|
||||||
|
CONFIG.ui.combat = RipCryptCombatTracker;
|
||||||
|
CONFIG.Combat.documentClass = RipCryptCombat;
|
||||||
|
CONFIG.Combatant.documentClass = RipCryptCombatant;
|
||||||
CONFIG.Item.documentClass = RipCryptItem;
|
CONFIG.Item.documentClass = RipCryptItem;
|
||||||
CONFIG.Dice.terms.d = CryptDie;
|
CONFIG.Dice.terms.d = CryptDie;
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,14 @@ export function registerMetaSettings() {
|
||||||
ui.crypt.render({ parts: [ `delveConditions` ]});
|
ui.crypt.render({ parts: [ `delveConditions` ]});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.settings.register(`ripcrypt`, `currentFate`, {
|
||||||
|
scope: `world`,
|
||||||
|
type: String,
|
||||||
|
config: false,
|
||||||
|
requiresReload: false,
|
||||||
|
onChange: () => {
|
||||||
|
ui.crypt.render({ parts: [ `fate` ] });
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
27
module/utils/distanceBetweenFates.mjs
Normal file
27
module/utils/distanceBetweenFates.mjs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { gameTerms } from "../gameTerms.mjs";
|
||||||
|
import { Logger } from "./Logger.mjs";
|
||||||
|
|
||||||
|
const { FatePath } = gameTerms;
|
||||||
|
|
||||||
|
export function isOppositeFates(a, b) {
|
||||||
|
return a === FatePath.NORTH && b === FatePath.SOUTH
|
||||||
|
|| a === FatePath.EAST && FatePath.WEST;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function distanceBetweenFates(start, end) {
|
||||||
|
if (!start || !end) {
|
||||||
|
Logger.error(`Start and End must both have a defined value, given`, {start, end});
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isOppositeFates(start, end)) {
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
let isForward = start === FatePath.SOUTH && end === FatePath.WEST;
|
||||||
|
isForward ||= start === FatePath.NORTH && end === FatePath.EAST;
|
||||||
|
if (isForward) {
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
return 3;
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue