mirror of
https://github.com/Kornstalx/5etools-mirror-2.github.io.git
synced 2025-10-28 20:45:35 -05:00
285 lines
7.0 KiB
JavaScript
285 lines
7.0 KiB
JavaScript
import {
|
|
INITIATIVE_APPLICABILITY_NOT_APPLICABLE,
|
|
InitiativeTrackerStatColumnFactory,
|
|
} from "./dmscreen-initiativetracker-statcolumns.js";
|
|
import {DmScreenUtil} from "../dmscreen-util.js";
|
|
import {InitiativeTrackerSort} from "./dmscreen-initiativetracker-sort.js";
|
|
|
|
/** @abstract */
|
|
class _InitiativeTrackerRowStateBuilderBase {
|
|
constructor ({comp, roller}) {
|
|
this._comp = comp;
|
|
this._roller = roller;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* @param {?array} rows Existing/partial rows, for calculating ordinal.
|
|
* @param {?boolean} isActive
|
|
* @param {?boolean} isPlayerVisible
|
|
* @param {?string} name
|
|
* @param {?string} displayName
|
|
* @param {?number} scaledCr
|
|
* @param {?number} scaledSummonSpellLevel
|
|
* @param {?number} scaledSummonClassLevel
|
|
* @param {?string} customName
|
|
* @param {?string} source
|
|
* @param {?number} hpCurrent
|
|
* @param {?number} hpMax
|
|
* @param {?number} initiative
|
|
* @param {?number} ordinal
|
|
* @param {?array} rowStatColData
|
|
* @param {?array} conditions
|
|
*/
|
|
async pGetNewRowState (
|
|
{
|
|
rows = null,
|
|
|
|
isActive = null,
|
|
isPlayerVisible = null,
|
|
name = null,
|
|
displayName = null,
|
|
scaledCr = null,
|
|
scaledSummonSpellLevel = null,
|
|
scaledSummonClassLevel = null,
|
|
customName = null,
|
|
source = null,
|
|
hpCurrent = null,
|
|
hpMax = null,
|
|
initiative = null,
|
|
ordinal = null,
|
|
rowStatColData = null,
|
|
conditions = null,
|
|
} = {},
|
|
) {
|
|
if (rowStatColData == null) rowStatColData = this._getInitialRowStatColData();
|
|
|
|
return {
|
|
id: CryptUtil.uid(),
|
|
entity: {
|
|
isActive: !!isActive,
|
|
isPlayerVisible: !!isPlayerVisible,
|
|
name,
|
|
displayName,
|
|
scaledCr,
|
|
scaledSummonSpellLevel,
|
|
scaledSummonClassLevel,
|
|
customName,
|
|
source,
|
|
hpCurrent,
|
|
hpMax,
|
|
initiative,
|
|
ordinal,
|
|
rowStatColData: rowStatColData ?? [],
|
|
conditions: conditions ?? [],
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {?object} mon
|
|
* @param {?object} fluff
|
|
*/
|
|
_getInitialRowStatColData ({mon = null, fluff = null} = {}) {
|
|
return this._comp._state.statsCols
|
|
.map(data => {
|
|
return InitiativeTrackerStatColumnFactory.fromStateData({data})
|
|
.getInitialCellStateData({mon, fluff});
|
|
});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
async pGetRowInitiativeMeta ({row}) {
|
|
const out = {mon: null, initiativeModifier: null};
|
|
|
|
const {entity} = row;
|
|
|
|
const initiativeInfos = this._comp._state.statsCols
|
|
.map(data => {
|
|
const cell = entity.rowStatColData.find(cell => cell.id === data.id);
|
|
if (!cell) return null;
|
|
return {
|
|
id: cell.id,
|
|
...InitiativeTrackerStatColumnFactory.fromStateData({data})
|
|
.getInitiativeInfo({state: cell}),
|
|
};
|
|
})
|
|
.filter(Boolean)
|
|
.filter(info => info.applicability !== INITIATIVE_APPLICABILITY_NOT_APPLICABLE)
|
|
.sort(InitiativeTrackerSort.sortInitiativeInfos.bind(InitiativeTrackerSort));
|
|
|
|
const maxApplicability = Math.max(INITIATIVE_APPLICABILITY_NOT_APPLICABLE, ...initiativeInfos.map(info => info.applicability));
|
|
if (maxApplicability !== INITIATIVE_APPLICABILITY_NOT_APPLICABLE) {
|
|
const initiativeInfosApplicable = initiativeInfos.filter(info => info.applicability === maxApplicability);
|
|
out.initiativeModifier = Math.max(...initiativeInfosApplicable.map(info => info.initiative));
|
|
}
|
|
|
|
return out;
|
|
}
|
|
}
|
|
|
|
export class InitiativeTrackerRowStateBuilderActive extends _InitiativeTrackerRowStateBuilderBase {
|
|
_prop = "rows";
|
|
|
|
async pGetScaledCreature ({isMon, name, source, scaledCr, scaledSummonSpellLevel, scaledSummonClassLevel}) {
|
|
if (!isMon) return null;
|
|
return DmScreenUtil.pGetScaledCreature({name, source, scaledCr, scaledSummonSpellLevel, scaledSummonClassLevel});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
async pGetNewRowState (
|
|
{
|
|
rows = null,
|
|
|
|
isActive = null,
|
|
isPlayerVisible = null,
|
|
name = null,
|
|
displayName = null,
|
|
scaledCr = null,
|
|
scaledSummonSpellLevel = null,
|
|
scaledSummonClassLevel = null,
|
|
customName = null,
|
|
source = null,
|
|
hpCurrent = null,
|
|
hpMax = null,
|
|
initiative = null,
|
|
ordinal = null,
|
|
rowStatColData = null,
|
|
conditions = null,
|
|
} = {},
|
|
) {
|
|
const isMon = name && source;
|
|
const mon = await this.pGetScaledCreature({isMon, name, source, scaledCr, scaledSummonSpellLevel, scaledSummonClassLevel});
|
|
if (isMon && !mon) return null;
|
|
|
|
const fluff = mon ? await Renderer.monster.pGetFluff(mon) : null;
|
|
|
|
if (isMon) {
|
|
if (hpCurrent == null && hpMax == null) {
|
|
hpCurrent = hpMax = await this._roller.pGetOrRollHp(mon, {isRollHp: this._comp._state.isRollHp});
|
|
}
|
|
|
|
if (initiative == null && this._comp._state.isRollInit) {
|
|
initiative = await this._roller.pGetRollInitiative({mon});
|
|
}
|
|
|
|
if (ordinal == null) {
|
|
const existingCreatures = this.getSimilarRows({
|
|
rows,
|
|
rowEntity: {
|
|
name,
|
|
customName,
|
|
scaledCr,
|
|
scaledSummonSpellLevel,
|
|
scaledSummonClassLevel,
|
|
source,
|
|
},
|
|
});
|
|
|
|
ordinal = existingCreatures.length + 1;
|
|
}
|
|
|
|
if (isPlayerVisible == null) isPlayerVisible = !this._comp._state.playerInitHideNewMonster;
|
|
}
|
|
|
|
if (!isMon) {
|
|
if (isPlayerVisible == null) isPlayerVisible = true;
|
|
}
|
|
|
|
if (rowStatColData == null) rowStatColData = this._getInitialRowStatColData({mon, fluff});
|
|
|
|
return {
|
|
id: CryptUtil.uid(),
|
|
entity: {
|
|
isActive: !!isActive,
|
|
isPlayerVisible: !!isPlayerVisible,
|
|
name,
|
|
displayName,
|
|
scaledCr,
|
|
scaledSummonSpellLevel,
|
|
scaledSummonClassLevel,
|
|
customName,
|
|
source,
|
|
hpCurrent,
|
|
hpMax,
|
|
initiative,
|
|
ordinal,
|
|
rowStatColData: rowStatColData ?? [],
|
|
conditions: conditions ?? [],
|
|
},
|
|
};
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
async pGetRowInitiativeMeta ({row}) {
|
|
const out = await super.pGetRowInitiativeMeta({row});
|
|
|
|
const mon = await this.pGetScaledCreature(row.entity);
|
|
if (!mon) return out;
|
|
|
|
out.mon = mon;
|
|
out.initiativeModifier ||= Parser.getAbilityModifier(mon.dex);
|
|
|
|
return out;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
static _SIMILAR_ROW_PROPS = [
|
|
"name",
|
|
"customName",
|
|
"scaledCr",
|
|
"scaledSummonSpellLevel",
|
|
"scaledSummonClassLevel",
|
|
"source",
|
|
];
|
|
|
|
static getSimilarRowEntityHash ({rowEntity}) {
|
|
return this._SIMILAR_ROW_PROPS
|
|
.map(prop => JSON.stringify(rowEntity[prop] ?? null))
|
|
.join("__");
|
|
}
|
|
|
|
getSimilarRows (
|
|
{
|
|
rows = null,
|
|
|
|
rowEntity,
|
|
},
|
|
) {
|
|
const rowEntityHash = this.constructor.getSimilarRowEntityHash({rowEntity});
|
|
|
|
return (rows || this._comp._state[this._prop])
|
|
.filter(({entity}) => {
|
|
return this.constructor.getSimilarRowEntityHash({rowEntity: entity}) === rowEntityHash;
|
|
});
|
|
}
|
|
|
|
getSimilarRowCounts (
|
|
{
|
|
rows = null,
|
|
},
|
|
) {
|
|
return (rows || this._comp._state[this._prop])
|
|
.reduce(
|
|
(accum, {entity}) => {
|
|
const rowEntityHash = InitiativeTrackerRowStateBuilderActive.getSimilarRowEntityHash({rowEntity: entity});
|
|
accum[rowEntityHash] = (accum[rowEntityHash] || 0) + 1;
|
|
return accum;
|
|
},
|
|
{},
|
|
);
|
|
}
|
|
}
|
|
|
|
export class InitiativeTrackerRowStateBuilderDefaultParty extends _InitiativeTrackerRowStateBuilderBase {
|
|
_prop = "rowsDefaultParty";
|
|
}
|