287 lines
9.0 KiB
JavaScript
287 lines
9.0 KiB
JavaScript
export class AcksCombat {
|
|
static rollInitiative(combat, data) {
|
|
// Check groups
|
|
data.combatants = [];
|
|
let groups = {};
|
|
combat.data.combatants.forEach((cbt) => {
|
|
groups[cbt.flags.acks.group] = { present: true };
|
|
data.combatants.push(cbt);
|
|
});
|
|
|
|
// Roll init
|
|
Object.keys(groups).forEach((group) => {
|
|
let roll = new Roll("1d6").roll();
|
|
roll.toMessage({
|
|
flavor: game.i18n.format('ACKS.roll.initiative', { group: CONFIG["ACKS"].colors[group] }),
|
|
});
|
|
groups[group].initiative = roll.total;
|
|
});
|
|
|
|
// Set init
|
|
for (let i = 0; i < data.combatants.length; ++i) {
|
|
if (!data.combatants[i].actor) {
|
|
return;
|
|
}
|
|
data.combatants[i].initiative =
|
|
groups[data.combatants[i].flags.acks.group].initiative;
|
|
if (data.combatants[i].actor.data.data.isSlow) {
|
|
data.combatants[i].initiative -= 1;
|
|
}
|
|
}
|
|
combat.setupTurns();
|
|
}
|
|
|
|
static async resetInitiative(combat, data) {
|
|
let reroll = game.settings.get("acks", "initiative");
|
|
if (!["reset", "reroll"].includes(reroll)) {
|
|
return;
|
|
}
|
|
combat.resetAll();
|
|
}
|
|
|
|
static async individualInitiative(combat, data) {
|
|
let updates = [];
|
|
let messages = [];
|
|
combat.data.combatants.forEach((c, i) => {
|
|
// This comes from foundry.js, had to remove the update turns thing
|
|
// Roll initiative
|
|
const cf = combat._getInitiativeFormula(c);
|
|
const roll = combat._getInitiativeRoll(c, cf);
|
|
let value = roll.total;
|
|
if (combat.settings.skipDefeated && c.defeated) {
|
|
value = -790;
|
|
}
|
|
updates.push({ _id: c._id, initiative: value });
|
|
|
|
// Determine the roll mode
|
|
let rollMode = game.settings.get("core", "rollMode");
|
|
if ((c.token.hidden || c.hidden) && (rollMode === "roll")) rollMode = "gmroll";
|
|
|
|
// Construct chat message data
|
|
let messageData = mergeObject({
|
|
speaker: {
|
|
scene: canvas.scene._id,
|
|
actor: c.actor ? c.actor._id : null,
|
|
token: c.token._id,
|
|
alias: c.token.name
|
|
},
|
|
flavor: game.i18n.format('ACKS.roll.individualInit', { name: c.token.name })
|
|
}, {});
|
|
const chatData = roll.toMessage(messageData, { rollMode, create: false });
|
|
|
|
if (i > 0) chatData.sound = null; // Only play 1 sound for the whole set
|
|
messages.push(chatData);
|
|
});
|
|
await combat.updateEmbeddedEntity("Combatant", updates);
|
|
await CONFIG.ChatMessage.entityClass.create(messages);
|
|
data.turn = 0;
|
|
}
|
|
|
|
static format(object, html, user) {
|
|
html.find(".initiative").each((_, span) => {
|
|
span.innerHTML =
|
|
span.innerHTML == "-789.00"
|
|
? '<i class="fas fa-weight-hanging"></i>'
|
|
: span.innerHTML;
|
|
span.innerHTML =
|
|
span.innerHTML == "-790.00"
|
|
? '<i class="fas fa-dizzy"></i>'
|
|
: span.innerHTML;
|
|
});
|
|
|
|
html.find(".combatant").each((_, ct) => {
|
|
// Append spellcast and retreat
|
|
const controls = $(ct).find(".combatant-controls .combatant-control");
|
|
const cmbtant = object.combat.getCombatant(ct.dataset.combatantId);
|
|
const moveActive = cmbtant.flags.acks && cmbtant.flags.acks.moveInCombat ? "active" : "";
|
|
controls.eq(1).after(
|
|
`<a class='combatant-control move-combat ${moveActive}'><i class='fas fa-running'></i></a>`
|
|
);
|
|
const spellActive = cmbtant.flags.acks && cmbtant.flags.acks.prepareSpell ? "active" : "";
|
|
controls.eq(1).after(
|
|
`<a class='combatant-control prepare-spell ${spellActive}'><i class='fas fa-magic'></i></a>`
|
|
);
|
|
const holdActive = cmbtant.flags.acks && cmbtant.flags.acks.holdTurn ? "active" : "";
|
|
controls.eq(1).after(
|
|
`<a class='combatant-control hold-turn ${holdActive}'><i class='fas fa-pause-circle'></i></a>`
|
|
);
|
|
});
|
|
AcksCombat.announceListener(html);
|
|
|
|
let init = game.settings.get("acks", "initiative") === "group";
|
|
if (!init) {
|
|
return;
|
|
}
|
|
|
|
html.find('.combat-control[data-control="rollNPC"]').remove();
|
|
html.find('.combat-control[data-control="rollAll"]').remove();
|
|
let trash = html.find(
|
|
'.encounters .combat-control[data-control="endCombat"]'
|
|
);
|
|
$(
|
|
'<a class="combat-control" data-control="reroll"><i class="fas fa-dice"></i></a>'
|
|
).insertBefore(trash);
|
|
|
|
html.find(".combatant").each((_, ct) => {
|
|
// Can't roll individual inits
|
|
$(ct).find(".roll").remove();
|
|
|
|
// Get group color
|
|
const cmbtant = object.combat.getCombatant(ct.dataset.combatantId);
|
|
let color = cmbtant.flags.acks.group;
|
|
|
|
// Append colored flag
|
|
let controls = $(ct).find(".combatant-controls");
|
|
controls.prepend(
|
|
`<a class='combatant-control flag' style='color:${color}' title="${CONFIG.ACKS.colors[color]}"><i class='fas fa-flag'></i></a>`
|
|
);
|
|
});
|
|
AcksCombat.addListeners(html);
|
|
}
|
|
|
|
static updateCombatant(combat, combatant, data) {
|
|
let init = game.settings.get("acks", "initiative");
|
|
// Why do you reroll ?
|
|
// Legacy Slowness code from OSE
|
|
// if (combatant.actor.data.data.isSlow) {
|
|
// data.initiative = -789;
|
|
// return;
|
|
// }
|
|
if (data.initiative && init == "group") {
|
|
let groupInit = data.initiative;
|
|
// Check if there are any members of the group with init
|
|
combat.combatants.forEach((ct) => {
|
|
if (
|
|
ct.initiative &&
|
|
ct.initiative != "-789.00" &&
|
|
ct._id != data._id &&
|
|
ct.flags.acks.group == combatant.flags.acks.group
|
|
) {
|
|
groupInit = ct.initiative;
|
|
// Set init
|
|
data.initiative = parseInt(groupInit);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
static announceListener(html) {
|
|
html.find(".combatant-control.hold-turn").click((ev) => {
|
|
ev.preventDefault();
|
|
// Toggle hold announcement
|
|
let id = $(ev.currentTarget).closest(".combatant")[0].dataset.combatantId;
|
|
let isActive = ev.currentTarget.classList.contains('active');
|
|
game.combat.updateCombatant({
|
|
_id: id,
|
|
flags: { acks: { holdTurn: !isActive } },
|
|
});
|
|
})
|
|
html.find(".combatant-control.prepare-spell").click((ev) => {
|
|
ev.preventDefault();
|
|
// Toggle spell announcement
|
|
let id = $(ev.currentTarget).closest(".combatant")[0].dataset.combatantId;
|
|
let isActive = ev.currentTarget.classList.contains('active');
|
|
game.combat.updateCombatant({
|
|
_id: id,
|
|
flags: { acks: { prepareSpell: !isActive } },
|
|
});
|
|
});
|
|
html.find(".combatant-control.move-combat").click((ev) => {
|
|
ev.preventDefault();
|
|
// Toggle retreat announcement
|
|
let id = $(ev.currentTarget).closest(".combatant")[0].dataset.combatantId;
|
|
let isActive = ev.currentTarget.classList.contains('active');
|
|
game.combat.updateCombatant({
|
|
_id: id,
|
|
flags: { acks: { moveInCombat: !isActive } },
|
|
});
|
|
});
|
|
}
|
|
|
|
static addListeners(html) {
|
|
// Cycle through colors
|
|
html.find(".combatant-control.flag").click((ev) => {
|
|
if (!game.user.isGM) {
|
|
return;
|
|
}
|
|
let currentColor = ev.currentTarget.style.color;
|
|
let colors = Object.keys(CONFIG.ACKS.colors);
|
|
let index = colors.indexOf(currentColor);
|
|
if (index + 1 == colors.length) {
|
|
index = 0;
|
|
} else {
|
|
index++;
|
|
}
|
|
let id = $(ev.currentTarget).closest(".combatant")[0].dataset.combatantId;
|
|
game.combat.updateCombatant({
|
|
_id: id,
|
|
flags: { acks: { group: colors[index] } },
|
|
});
|
|
});
|
|
|
|
html.find('.combat-control[data-control="reroll"]').click((ev) => {
|
|
if (!game.combat) {
|
|
return;
|
|
}
|
|
let data = {};
|
|
AcksCombat.rollInitiative(game.combat, data);
|
|
game.combat.update({ data: data }).then(() => {
|
|
game.combat.setupTurns();
|
|
});
|
|
});
|
|
}
|
|
|
|
static addCombatant(combat, data, options, id) {
|
|
let token = canvas.tokens.get(data.tokenId);
|
|
let color = "black";
|
|
switch (token.data.disposition) {
|
|
case -1:
|
|
color = "red";
|
|
break;
|
|
case 0:
|
|
color = "yellow";
|
|
break;
|
|
case 1:
|
|
color = "green";
|
|
break;
|
|
}
|
|
data.flags = {
|
|
acks: {
|
|
group: color,
|
|
},
|
|
};
|
|
}
|
|
static activateCombatant(li) {
|
|
const turn = game.combat.turns.findIndex(turn => turn._id === li.data('combatant-id'));
|
|
game.combat.update({turn: turn})
|
|
}
|
|
|
|
static addContextEntry(html, options) {
|
|
options.unshift({
|
|
name: "Set Active",
|
|
icon: '<i class="fas fa-star-of-life"></i>',
|
|
callback: AcksCombat.activateCombatant
|
|
});
|
|
}
|
|
|
|
static async preUpdateCombat(combat, data, diff, id) {
|
|
let init = game.settings.get("acks", "initiative");
|
|
let reroll = game.settings.get("acks", "initiative");
|
|
if (!data.round) {
|
|
return;
|
|
}
|
|
if (data.round !== 1) {
|
|
if (reroll === "reset") {
|
|
AcksCombat.resetInitiative(combat, data, diff, id);
|
|
return;
|
|
} else if (reroll === "keep") {
|
|
return;
|
|
}
|
|
}
|
|
if (init === "group") {
|
|
AcksCombat.rollInitiative(combat, data, diff, id);
|
|
} else if (init === "individual") {
|
|
AcksCombat.individualInitiative(combat, data, diff, id);
|
|
}
|
|
}
|
|
} |