diff --git a/modules/hero6-actor.js b/modules/hero6-actor.js
index 055c61e..efb6c92 100644
--- a/modules/hero6-actor.js
+++ b/modules/hero6-actor.js
@@ -3,12 +3,9 @@ import { Hero6Utility } from "./hero6-utility.js";
import { Hero6RollDialog } from "./hero6-roll-dialog.js";
/* -------------------------------------------- */
-const coverBonusTable = { "nocover": 0, "lightcover": 2, "heavycover": 4, "entrenchedcover": 6 };
-const statThreatLevel = ["agi", "str", "phy", "com", "def", "per"]
-const __subkey2title = {
- "melee-dmg": "Melee Damage", "melee-atk": "Melee Attack", "ranged-atk": "Ranged Attack",
- "ranged-dmg": "Ranged Damage", "dmg-res": "Damare Resistance"
-}
+const __speed2Segments = [[0], [7], [6, 12], [4, 8, 12], [3, 6, 9, 12], [3, 5, 8, 10, 12], [2, 4, 6, 8, 10, 12]
+ [2, 4, 6, 7, 9, 11, 12], [2, 3, 5, 6, 8, 9, 11, 12], [2, 3, 4, 6, 7, 8, 10, 11, 12], [2, 3, 4, 5, 6, 8, 9, 10, 11, 12],
+ [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
/* -------------------------------------------- */
/* -------------------------------------------- */
@@ -67,8 +64,8 @@ export class Hero6Actor extends Actor {
}
}
computeDicesValue() {
- this.system.biodata.presenceattack = Hero6Utility.getDerivatedDiceFormulas(this.system.characteristics.pre.value )
- this.system.characteristics.str.strdice = Hero6Utility.getDerivatedDiceFormulas(this.system.characteristics.str.value )
+ this.system.biodata.presenceattack = Hero6Utility.getDerivatedDiceFormulas(this.system.characteristics.pre.value)
+ this.system.characteristics.str.strdice = Hero6Utility.getDerivatedDiceFormulas(this.system.characteristics.str.value)
}
/* -------------------------------------------- */
prepareDerivedData() {
@@ -275,13 +272,13 @@ export class Hero6Actor extends Actor {
return 0;
}
getManeuvers() {
- let maneuvers = {
+ let maneuvers = {
general: this.items.filter(item => item.type == "maneuver" && item.system.maneuvertype == "general"),
offensive: this.items.filter(item => item.type == "maneuver" && item.system.maneuvertype == "offensive"),
defensive: this.items.filter(item => item.type == "maneuver" && item.system.maneuvertype == "defensive")
}
- Hero6Utility.sortArrayObjectsByName(maneuvers.general)
- Hero6Utility.sortArrayObjectsByName(maneuvers.offensive)
+ Hero6Utility.sortArrayObjectsByName(maneuvers.general)
+ Hero6Utility.sortArrayObjectsByName(maneuvers.offensive)
Hero6Utility.sortArrayObjectsByName(maneuvers.defensive)
return maneuvers
}
@@ -292,32 +289,32 @@ export class Hero6Actor extends Actor {
}
getEquipments() {
let list = this.items.filter(item => item.type == "equipment" && item.system.subtype == "equipment");
- Hero6Utility.sortArrayObjectsByName(list)
+ Hero6Utility.sortArrayObjectsByName(list)
return list
}
getWeapons() {
let list = this.items.filter(item => item.type == "equipment" && item.system.subtype == "weapon");
- Hero6Utility.sortArrayObjectsByName(list)
+ Hero6Utility.sortArrayObjectsByName(list)
return list
}
getArmors() {
let list = this.items.filter(item => item.type == "equipment" && item.system.subtype == "armor");
- Hero6Utility.sortArrayObjectsByName(list)
+ Hero6Utility.sortArrayObjectsByName(list)
return list
}
getShields() {
let list = this.items.filter(item => item.type == "equipment" && item.system.subtype == "shield");
- Hero6Utility.sortArrayObjectsByName(list)
+ Hero6Utility.sortArrayObjectsByName(list)
return list
}
getEquipmentsMoneys() {
let list = duplicate(this.items.filter(item => item.type == "equipment" && (item.system.subtype == "equipment" || item.system.subtype == "money")) || [])
- Hero6Utility.sortArrayObjectsByName(list)
+ Hero6Utility.sortArrayObjectsByName(list)
return list
}
getEquipmentsOnly() {
let list = duplicate(this.items.filter(item => item.type == "equipment" && item.system.subtype == "equipment") || [])
- Hero6Utility.sortArrayObjectsByName(list)
+ Hero6Utility.sortArrayObjectsByName(list)
return list
}
@@ -412,13 +409,23 @@ export class Hero6Actor extends Actor {
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
}
}
+
/* -------------------------------------------- */
- getInitiativeScore(combatId, combatantId) {
- if (this.type == 'character') {
- this.rollMR(true, combatId, combatantId)
- }
- console.log("Init required !!!!")
- return -1;
+ hasPhase( segmentNumber) {
+ let index = Math.min( Math.max(this.system.characteristics.spd.value, 1), 12) // Security bounds
+ let phases = __speed2Segments[index]
+ return phases.includes(segmentNumber)
+ }
+ /* -------------------------------------------- */
+ getSegments() {
+ let index = Math.min( Math.max(this.system.characteristics.spd.value, 1), 12) // Security bounds
+ return __speed2Segments[index]
+ }
+ /* -------------------------------------------- */
+ getBaseInit() {
+ let r = new Roll("1d6").roll({async: false})
+ let base = this.system.characteristics.dex.value + (r.total / 10)
+ return base
}
/* -------------------------------------------- */
diff --git a/modules/hero6-combat.js b/modules/hero6-combat.js
index 5874f1a..2c076aa 100644
--- a/modules/hero6-combat.js
+++ b/modules/hero6-combat.js
@@ -1,21 +1,141 @@
import { Hero6Utility } from "./hero6-utility.js";
/* -------------------------------------------- */
-export class Hero6Combat extends Combat {
-
+export class Hero6CombatTracker extends CombatTracker {
+
/* -------------------------------------------- */
- async rollInitiative(ids, formula = undefined, messageOptions = {} ) {
+ static get defaultOptions() {
+ var path = "systems/fvtt-hero-system-6/templates/apps/combat-tracker.hbs";
+ return foundry.utils.mergeObject(super.defaultOptions, {
+ template: path,
+ });
+ }
+}
+
+/* -------------------------------------------- */
+export class Hero6Combat extends Combat {
+
+ /* -------------------------------------------- */
+ static init() {
+ Hooks.on("getCombatTrackerEntryContext", (html, options) => { Hero6Combat.pushMenuOptions(html, options); });
+ }
+ /* -------------------------------------------- */
+ static pushMenuOptions(html, options) {
+ let newOpt
+ for (let i = 0; i < options.length; i++) {
+ let option = options[i];
+ if (option.name == 'COMBAT.CombatantReroll') { // Replace !
+ option.name = "Hold action";
+ option.condition = true;
+ option.icon = '';
+ option.callback = target => {
+ Hero6Combat.holdAction(target.data('combatant-id'));
+ }
+ newOpt = duplicate(option)
+ }
+ }
+ newOpt.name = "Abort action"
+ newOpt.callback = target => {
+ Hero6Combat.abortAction(target.data('combatant-id'));
+ }
+ options.push( newOpt)
+ }
+
+ /* -------------------------------------------- */
+ static holdAction(combatantId) {
+ console.log("Combatant HOLD : ", combatantId)
+ const combatant = game.combat.combatants.get(combatantId)
+ combatant.setFlag("world", "hero6-hold-action", true)
+ combatant.update({name: combatant.name + " (H)"})
+ console.log("HOLD", combatant)
+ }
+ /* -------------------------------------------- */
+ static abortAction(html, combatantId) {
+ console.log("Combatant ABORT : ", combatantId);
+ const combatant = game.combat.combatants.get(combatantId);
+ combatant.setFlag("world", "hero6-abort-action", true)
+ combatant.update({name: combatant.name + " (A)"})
+ console.log("ABORT", combatant)
+ }
+
+ /* -------------------------------------------- */
+ constructor(data, context) {
+ super(data, context);
+
+ this.turnNumber = 1;
+ this.segmentNumber = 12;
+ }
+
+ /* -------------------------------------------- */
+ async computeInitiative(c) {
+ let id = c._id || c.id
+ if (c.actor.hasPhase(this.segmentNumber)) {
+ let baseInit = c.actor ? c.actor.getBaseInit() : - 1;
+ await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: baseInit }]);
+ } else {
+ await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: -1, visible: false, active: false }]);
+ }
+ console.log("Combatant", c)
+ }
+ /* -------------------------------------------- */
+ async rollInitiative(ids, formula = undefined, messageOptions = {}) {
ids = typeof ids === "string" ? [ids] : ids;
for (let cId = 0; cId < ids.length; cId++) {
- const c = this.combatants.get(ids[cId]);
- let id = c._id || c.id;
- let initBonus = c.actor ? c.actor.getInitiativeScore( this.id, id ) : -1;
- await this.updateEmbeddedDocuments("Combatant", [ { _id: id, initiative: initBonus } ]);
+ const c = this.combatants.get(ids[cId])
+ await this.computeInitiative(c)
}
return this;
}
+ /* -------------------------------------------- */
+ nextRound() {
+ let turn = this.turn === null ? null : 0; // Preserve the fact that it's no-one's turn currently.
+ if (this.settings.skipDefeated && (turn !== null)) {
+ turn = this.turns.findIndex(t => !t.isDefeated);
+ if (turn === -1) {
+ ui.notifications.warn("COMBAT.NoneRemaining", { localize: true });
+ turn = 0;
+ }
+ }
+ let advanceTime = Math.max(this.turns.length - this.turn, 0) * CONFIG.time.turnTime;
+ advanceTime += CONFIG.time.roundTime;
+ let nextRound = this.round + 1;
+
+ let turnData = this.getFlag("world", "hero6-turn-data")
+ if (!turnData) {
+ turnData = { turnNumber: 1, segmentNumber: 12 }
+ this.setFlag("world", "hero6-turn-data", turnData)
+ }
+ turnData = duplicate(turnData)
+ turnData.segmentNumber -= 1
+ if (turnData.segmentNumber <= 0) {
+ turnData.segmentNumber = 12
+ turnData.turnNumber++
+ }
+ this.setFlag("world", "hero6-turn-data", turnData)
+ this.turnNumber = turnData.turnNumber;
+ this.segmentNumber = turnData.segmentNumber;
+
+ // Re-compute init of actors
+ for (let c of this.combatants) {
+ this.computeInitiative(c)
+ }
+
+ // Update the document, passing data through a hook first
+ const updateData = { round: nextRound, turn, segmentNumber: turnData.segmentNumber, turnNumber: turnData.turnNumber };
+ const updateOptions = { advanceTime, direction: 1 };
+ Hooks.callAll("combatRound", this, updateData, updateOptions);
+ return this.update(updateData, updateOptions);
+ }
+
+
+ /* -------------------------------------------- */
+ async _onCreateEmbeddedDocuments(type, documents, result, options, userId) {
+ console.log(">>>>", documents)
+ super._onCreateEmbeddedDocuments(type, documents, result, options, userId)
+ }
+
/* -------------------------------------------- */
_onUpdate(changed, options, userId) {
}
diff --git a/modules/hero6-config.js b/modules/hero6-config.js
index 7ba5b9b..421a617 100644
--- a/modules/hero6-config.js
+++ b/modules/hero6-config.js
@@ -48,5 +48,11 @@ export const Hero6_CONFIG = {
powerSenseAffecting: {
"none": "None",
"senseaffecting": "Sense-Affecting",
+ },
+ powerEffectRoll: {
+ "standard": "Standard",
+ "normal": "Normal",
+ "killing": "Killing",
+ "countbody": "Killing (Count BODY)"
}
}
\ No newline at end of file
diff --git a/modules/hero6-main.js b/modules/hero6-main.js
index bd49680..2bfa2ad 100644
--- a/modules/hero6-main.js
+++ b/modules/hero6-main.js
@@ -13,7 +13,7 @@ import { Hero6ItemSheet } from "./hero6-item-sheet.js";
import { Hero6ActorSheet } from "./hero6-actor-sheet.js";
import { Hero6NPCSheet } from "./hero6-npc-sheet.js";
import { Hero6Utility } from "./hero6-utility.js";
-import { Hero6Combat } from "./hero6-combat.js";
+import { Hero6Combat, Hero6CombatTracker } from "./hero6-combat.js";
import { Hero6Item } from "./hero6-item.js";
import { Hero6Hotbar } from "./hero6-hotbar.js"
import { Hero6Commands } from "./hero6-commands.js"
@@ -41,7 +41,7 @@ Hooks.once("init", async function () {
// Set an initiative formula for the system
CONFIG.Combat.initiative = {
formula: "1d6",
- decimals: 1
+ decimals: 3
};
/* -------------------------------------------- */
@@ -54,6 +54,8 @@ Hooks.once("init", async function () {
CONFIG.Combat.documentClass = Hero6Combat
CONFIG.Actor.documentClass = Hero6Actor
CONFIG.Item.documentClass = Hero6Item
+ CONFIG.ui.combat = Hero6CombatTracker;
+
/* -------------------------------------------- */
// Register sheet application classes
@@ -65,6 +67,7 @@ Hooks.once("init", async function () {
Items.registerSheet("fvtt-hero-system-6", Hero6ItemSheet, { makeDefault: true });
Hero6Utility.init()
+ Hero6Combat.init()
});
/* -------------------------------------------- */
diff --git a/modules/hero6-utility.js b/modules/hero6-utility.js
index 8bcaa2d..99ba541 100644
--- a/modules/hero6-utility.js
+++ b/modules/hero6-utility.js
@@ -179,7 +179,8 @@ export class Hero6Utility {
'systems/fvtt-hero-system-6/templates/partials/partial-power-equipment-cost.hbs',
'systems/fvtt-hero-system-6/templates/partials/partial-item-hasroll.hbs',
'systems/fvtt-hero-system-6/templates/partials/partial-actor-equipment.hbs',
- 'systems/fvtt-hero-system-6/templates/partials/partial-actor-equipment-section.hbs'
+ 'systems/fvtt-hero-system-6/templates/partials/partial-actor-equipment-section.hbs',
+ 'systems/fvtt-hero-system-6/templates/partials/partial-power-maneuver-effect.hbs'
]
return loadTemplates(templatePaths);
}
diff --git a/system.json b/system.json
index 0555c58..7444a90 100644
--- a/system.json
+++ b/system.json
@@ -91,7 +91,7 @@
"styles": [
"styles/simple.css"
],
- "version": "10.0.33",
+ "version": "10.0.34",
"compatibility": {
"minimum": "10",
"verified": "10",
@@ -99,7 +99,7 @@
},
"title": "Hero System v6 for FoundrtVTT (Official)",
"manifest": "https://www.uberwald.me/gitea/uberwald/fvtt-hero-system-6/raw/branch/main/system.json",
- "download": "https://www.uberwald.me/gitea/uberwald/fvtt-hero-system-6/archive/fvtt-hero-system-6-v10.0.33.zip",
+ "download": "https://www.uberwald.me/gitea/uberwald/fvtt-hero-system-6/archive/fvtt-hero-system-6-v10.0.34.zip",
"url": "https://www.uberwald.me/gitea/uberwald/",
"background": "images/ui/hro6_welcome_page.webp",
"id": "fvtt-hero-system-6"
diff --git a/template.json b/template.json
index 28d5d06..28b7955 100644
--- a/template.json
+++ b/template.json
@@ -346,6 +346,9 @@
"hasroll": false,
"roll": 0,
"computebody": false,
+ "haseffectroll": false,
+ "effectroll": "standard",
+ "effectrollformula": "",
"items": {}
}
},
diff --git a/templates/apps/combat-tracker.hbs b/templates/apps/combat-tracker.hbs
new file mode 100644
index 0000000..3f7e69e
--- /dev/null
+++ b/templates/apps/combat-tracker.hbs
@@ -0,0 +1,127 @@
+Turn {{combat.turnNumber}} Segment {{combat.segmentNumber}}
+ {{else}}
+ {{localize 'COMBAT.NotStarted'}}
+ {{/if}}
+ {{else}}
+ {{localize "COMBAT.None"}}
+ {{/if}}
+
+ {{#if user.isGM}}
+
+
+
+
+
+
+
+
+
+ {{/if}}
+
+ {{#each turns}}
+ {{#if (ne this.initiative "-1")}}
+
+
+
+{{this.name}} {{log this}} {{#if this.holdAction}}(H){{/if}}
+
+