ENH: Initiative and licensing
parent
83a1c7b717
commit
f8265fc4ed
11
README.md
11
README.md
|
@ -1,11 +1,16 @@
|
|||
# Old School Essentials System for Foundry VTT
|
||||
|
||||
## Installation
|
||||
You can now find this Foundry VTT game system within Foundry VTT in the system browser.
|
||||
|
||||
## License
|
||||
Old-School Essentials is a trademark of Necrotic Gnome.
|
||||
This Foundry VTT system requires Old-School Essentials Core Rules and does not contain any copyrighted material.
|
||||
This Foundry VTT system requires Old-School Essentials Core Rules that you can find here [here](https://necroticgnome.com).
|
||||
|
||||
This third party product is not affiliated with or approved by Necrotic Gnome.
|
||||
Old-School Essentials is a trademark of Necrotic Gnome.The trademark and Old-School Essentials logo are used with permission of Necrotic Gnome, under license
|
||||
|
||||
## Contributions
|
||||
This system is currently under heavy development.
|
||||
This system is currently in Beta.
|
||||
Feel free to grab a TO DO issue from the gitlab board. You can then do a merge request on the `development` branch.
|
||||
|
||||
[](https://ko-fi.com/H2H21WMKA)
|
|
@ -72,6 +72,7 @@
|
|||
"OSE.HitDice": "Hit Dice",
|
||||
"OSE.HitDiceShort": "HD",
|
||||
"OSE.Movement": "Movement Rate",
|
||||
"OSE.MovementDetails": "Movement Details",
|
||||
"OSE.MovementEncounter": "Encounter Movement Rate",
|
||||
"OSE.MovementEncounterShort": "En",
|
||||
"OSE.MovementOverland": "Overland Movement Rate",
|
||||
|
@ -197,5 +198,13 @@
|
|||
"OSE.messages.AttackFailure": "<b>Attack fails</b> ({bonus})",
|
||||
"OSE.messages.InflictsDamage": "Inflicts damage!",
|
||||
"OSE.ChatContextDamage": "Apply Damage",
|
||||
"OSE.ChatContextHealing": "Apply Healing"
|
||||
"OSE.ChatContextHealing": "Apply Healing",
|
||||
|
||||
"OSE.colors.green": "Green",
|
||||
"OSE.colors.red": "Red",
|
||||
"OSE.colors.yellow": "Yellow",
|
||||
"OSE.colors.purple": "Purple",
|
||||
"OSE.colors.blue": "Blue",
|
||||
"OSE.colors.orange": "Orange",
|
||||
"OSE.colors.white": "White"
|
||||
}
|
|
@ -110,7 +110,9 @@ export class OseActorSheetCharacter extends OseActorSheet {
|
|||
|
||||
_calculateMovement(data, weight) {
|
||||
if (data.config.encumbrance == "detailed") {
|
||||
if (weight > 800) {
|
||||
if (weight > data.encumbrance.max) {
|
||||
data.data.movement.base = 0;
|
||||
} else if (weight > 800) {
|
||||
data.data.movement.base = 30;
|
||||
} else if (weight > 600) {
|
||||
data.data.movement.base = 60;
|
||||
|
|
|
@ -80,7 +80,6 @@ export class OseActorSheetMonster extends OseActorSheet {
|
|||
}
|
||||
|
||||
async _onCountChange(event) {
|
||||
console.log("CHANGE", event);
|
||||
event.preventDefault();
|
||||
const itemId = event.currentTarget.closest(".item").dataset.itemId;
|
||||
const item = this.actor.getOwnedItem(itemId);
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
import { OseDice } from "./dice.js";
|
||||
|
||||
export class OseCombat {
|
||||
static rollInitiative(combat, data, diff, id) {
|
||||
// Check groups
|
||||
data.combatants = [];
|
||||
let groups = {};
|
||||
combat.data.combatants.forEach((cbt) => {
|
||||
groups[cbt.flags.ose.group] = {present: true};
|
||||
data.combatants.push(cbt);
|
||||
});
|
||||
|
||||
// Roll init
|
||||
Object.keys(groups).forEach((group) => {
|
||||
let roll = new Roll("1d6").roll();
|
||||
roll.toMessage({flavor: `${CONFIG.OSE.colors[group]} group rolls initiative`});
|
||||
groups[group].initiative = roll.total;
|
||||
})
|
||||
|
||||
// Set init
|
||||
for (let i = 0; i < data.combatants.length; ++i) {
|
||||
data.combatants[i].initiative = groups[data.combatants[i].flags.ose.group].initiative;
|
||||
}
|
||||
}
|
||||
|
||||
static format(object, html, user) {
|
||||
html.find('.combat-control[data-control="rollNPC"]').remove();
|
||||
html.find('.combat-control[data-control="rollAll"]').remove();
|
||||
html.find(".combatant").each((_, ct) => {
|
||||
// Can't roll individual inits
|
||||
$(ct).find(".roll").remove();
|
||||
|
||||
// Get group color
|
||||
let cmbtant = object.combat.getCombatant(ct.dataset.combatantId);
|
||||
let color = cmbtant.flags.ose.group;
|
||||
|
||||
// Append colored flag
|
||||
let controls = $(ct).find(".combatant-controls");
|
||||
controls.prepend(
|
||||
`<a class='combatant-control flag' style='color:${color}' title="${CONFIG.OSE.colors[color]}"><i class='fas fa-flag'></i></a>`
|
||||
);
|
||||
});
|
||||
OseCombat.addListeners(html);
|
||||
}
|
||||
|
||||
static addListeners(html) {
|
||||
// Cycle through colors
|
||||
html.find(".combatant-control.flag").click((ev) => {
|
||||
let currentColor = ev.currentTarget.style.color;
|
||||
let colors = Object.keys(CONFIG.OSE.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: { ose: { group: colors[index] } },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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 = {
|
||||
ose: {
|
||||
group: color,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -26,5 +26,14 @@ export const OSE = {
|
|||
light: "OSE.armor.light",
|
||||
heavy: "OSE.armor.heavy",
|
||||
shield: "OSE.armor.shield",
|
||||
},
|
||||
colors: {
|
||||
green: "OSE.colors.green",
|
||||
red: "OSE.colors.red",
|
||||
yellow: "OSE.colors.yellow",
|
||||
purple: "OSE.colors.purple",
|
||||
blue: "OSE.colors.blue",
|
||||
orange: "OSE.colors.orange",
|
||||
white: "OSE.colors.white"
|
||||
}
|
||||
};
|
||||
|
|
41
src/ose.js
41
src/ose.js
|
@ -10,6 +10,7 @@ import { registerSettings } from "./module/settings.js";
|
|||
import { registerHelpers } from "./module/helpers.js";
|
||||
import * as chat from "./module/chat.js";
|
||||
import * as macros from "./module/macros.js";
|
||||
import { OseCombat } from "./module/combat.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
|
@ -61,7 +62,7 @@ Hooks.once("init", async function () {
|
|||
*/
|
||||
Hooks.once("setup", function () {
|
||||
// Localize CONFIG objects once up-front
|
||||
const toLocalize = ["saves_short", "saves_long", "scores", "armor"];
|
||||
const toLocalize = ["saves_short", "saves_long", "scores", "armor", "colors"];
|
||||
for (let o of toLocalize) {
|
||||
CONFIG.OSE[o] = Object.entries(CONFIG.OSE[o]).reduce((obj, e) => {
|
||||
obj[e[0]] = game.i18n.localize(e[1]);
|
||||
|
@ -74,21 +75,37 @@ Hooks.once("ready", async () => {
|
|||
Hooks.on("hotbarDrop", (bar, data, slot) =>
|
||||
macros.createOseMacro(data, slot)
|
||||
);
|
||||
const template = 'systems/ose/templates/chat/license.html';
|
||||
const template = "systems/ose/templates/chat/license.html";
|
||||
const html = await renderTemplate(template);
|
||||
$('#settings .game-system').append(html);
|
||||
$("#settings .game-system").append(html);
|
||||
});
|
||||
|
||||
Hooks.on(
|
||||
"preUpdateCombat",
|
||||
async (combat, updateData, options, userId) => {
|
||||
if (!updateData.round) {
|
||||
return;
|
||||
}
|
||||
if (game.settings.get('ose', 'individualInit')) {
|
||||
}
|
||||
Hooks.on("preCreateCombatant", (combat, data, options, id) => {
|
||||
OseCombat.addCombatant(combat, data, options, id);
|
||||
});
|
||||
|
||||
Hooks.on("preUpdateCombatant", (combat, combatant, data, diff, id) => {
|
||||
if (data.initiative) {
|
||||
let groupInit = data.initiative;
|
||||
combat.combatants.forEach((ct) => {
|
||||
if (ct.initiative && ct._id != data._id && ct.flags.ose.group == combatant.flags.ose.group) {
|
||||
groupInit = ct.initiative;
|
||||
data.initiative = parseInt(groupInit);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Hooks.on("renderCombatTracker", (object, html, data) => {
|
||||
OseCombat.format(object, html, data);
|
||||
});
|
||||
|
||||
Hooks.on("preUpdateCombat", async (combat, data, diff, id) => {
|
||||
if (!data.round) {
|
||||
return;
|
||||
}
|
||||
OseCombat.rollInitiative(combat, data, diff, id);
|
||||
});
|
||||
|
||||
Hooks.on("renderChatLog", (app, html, data) => OseItem.chatListeners(html));
|
||||
Hooks.on("getChatLogEntryContext", chat.addChatMessageContextOptions);
|
||||
|
|
|
@ -46,7 +46,8 @@
|
|||
}
|
||||
},
|
||||
"movement": {
|
||||
"base": 120
|
||||
"base": 120,
|
||||
"value": ""
|
||||
},
|
||||
"initiative": {
|
||||
"value": 0,
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Movement'}}">{{ localize "OSE.MovementShort" }}
|
||||
</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.movement.value" type="text" value="{{data.movement.value}}" placeholder="0"
|
||||
<input name="data.movement.base" type="text" value="{{data.movement.base}}" placeholder="0"
|
||||
data-dtype="Number" />
|
||||
</div>
|
||||
</li>
|
||||
|
@ -138,8 +138,8 @@
|
|||
{{!-- Saving throws --}}
|
||||
<div class="attribute-group">
|
||||
<div class="attacks-description">
|
||||
<label>{{ localize "OSE.Attacks" }}</label>
|
||||
<input name="data.att" type="text" value="{{data.att}}" data-dtype="String" />
|
||||
<label>{{ localize "OSE.MovementDetails" }}</label>
|
||||
<input name="data.movement.value" type="text" value="{{data.movement.value}}" data-dtype="String" />
|
||||
</div>
|
||||
<ul class="attributes">
|
||||
<li class="attribute saving-throw" data-save="death">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="ose game-license">
|
||||
<p class="ose game-license">
|
||||
This fan-made system requires requires Old-School Essentials Core Rules that
|
||||
This fan-made system requires Old-School Essentials Core Rules that
|
||||
you can find <a href="https://necroticgnome.com">here</a>.
|
||||
</p>
|
||||
<p>
|
||||
|
|
Loading…
Reference in New Issue