diff --git a/lang/en.json b/lang/en.json index fc9579d..323113d 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1,27 +1,32 @@ { "TYPES": { + "Actor": { + "character": "Character", + "npc": "NPC", + "vehicle": "Vehicle" + }, "Item": { - "Race": "Race", - "Role": "Role", - "Ability": "Ability", - "Specialisation": "Specialisation", - "Perk": "Perk", - "Power": "Power", - "Armor": "Armor", - "Shield": "Shield", - "Equipment": "Equipment", - "Weapon": "Weapon", - "Effect": "Effect", - "Money": "Money", - "Virtue": "Virtue", - "Vice": "Vice", - "Vehiclehull": "Vehicule Hull", - "Powercoremodule": "Power Core Module", - "Mobilitymodule": "Mobility Module", - "Combatmodule": "Combat Module", - "Vehiclemodule": "Vehicle Module", - "Vehicleweaponmodule" : "Vehicle Weapon Module", - "Propulsionmodule": "Propulsion module" + "race": "Race", + "role": "Role", + "ability": "Ability", + "specialisation": "Specialisation", + "perk": "Perk", + "power": "Power", + "armor": "Armor", + "shield": "Shield", + "equipment": "Equipment", + "weapon": "Weapon", + "effect": "Effect", + "money": "Money", + "virtue": "Virtue", + "vice": "Vice", + "vehiclehull": "Vehicule Hull", + "powercoremodule": "Power Core Module", + "mobilitymodule": "Mobility Module", + "combatmodule": "Combat Module", + "vehiclemodule": "Vehicle Module", + "vehicleweaponmodule" : "Vehicle Weapon Module", + "propulsionmodule": "Propulsion module" } } diff --git a/modules/pegasus-actor.js b/modules/pegasus-actor.js index c5a8b0e..a3ad121 100644 --- a/modules/pegasus-actor.js +++ b/modules/pegasus-actor.js @@ -92,9 +92,7 @@ export class PegasusActor extends Actor { return actor; } - if (data.type == 'character') { - } - if (data.type == 'npc') { + if (data.type == 'character'|| this.type == 'npc') { } @@ -124,7 +122,7 @@ export class PegasusActor extends Actor { this.traumaState = "none" } - if (this.type == 'character') { + if (this.type == 'character' || this.type == 'npc') { this.computeNRGHealth(); this.system.encCapacity = this.getEncumbranceCapacity() this.buildContainerTree() @@ -965,7 +963,7 @@ export class PegasusActor extends Actor { } /* -------------------------------------------- */ getInitiativeScore(combatId, combatantId) { - if (this.type == 'character') { + if (this.type == 'character' || this.type == 'npc') { this.rollMR(true, combatId, combatantId) } if (this.type == 'vehicle') { @@ -1016,7 +1014,7 @@ export class PegasusActor extends Actor { /* -------------------------------------------- */ getStat(statKey) { let stat - if (this.type == "character" && statKey == 'mr') { + if ((this.type == "character" || this.type == 'npc') && statKey == 'mr') { stat = duplicate(this.system.mr) } else { stat = duplicate(this.system.statistics[statKey]) @@ -1193,7 +1191,7 @@ export class PegasusActor extends Actor { /* -------------------------------------------- */ incDecNRG(value) { - if (this.type == "character") { + if (this.type == "character" || this.type == 'npc') { let nrg = duplicate(this.system.nrg) nrg.value += value if (nrg.value >= 0 && nrg.value <= nrg.max) { @@ -1345,7 +1343,7 @@ export class PegasusActor extends Actor { /* -------------------------------------------- */ getTraumaState() { this.traumaState = "none" - if (this.type == "character") { + if (this.type == "character"|| this.type == 'npc') { if (this.system.secondary.delirium.status == "trauma") { this.traumaState = "trauma" } @@ -1918,7 +1916,7 @@ export class PegasusActor extends Actor { /* -------------------------------------------- */ computeCurrentHindrances() { let hindrancesDices = 0 - if (this.type == "character") { + if (this.type == "character" || this.type == 'npc') { if (this.system.combat.stunlevel > 0) { hindrancesDices += 2 @@ -1960,7 +1958,7 @@ export class PegasusActor extends Actor { /* -------------------------------------------- */ addHindrancesList(effectsList) { - if (this.type == "character") { + if (this.type == "character"|| this.type == 'npc') { if (this.system.combat.stunlevel > 0) { effectsList.push({ label: "Stun Hindrance", type: "hindrance", foreign: true, actorId: this.id, applied: false, value: 2 }) } @@ -2137,6 +2135,7 @@ export class PegasusActor extends Actor { let rollData = PegasusUtility.getBasicRollData(isInit) rollData.alias = this.name rollData.actorImg = this.img + rollData.actorType = this.type rollData.tokenId = this.token?.id rollData.actorId = (this.token) ? this.token.actor.id : this.id rollData.img = this.img @@ -2147,6 +2146,8 @@ export class PegasusActor extends Actor { rollData.noBonusDice = this.checkNoBonusDice() rollData.dicePool = [] rollData.subKey = subKey + rollData.tic1 = "NONE" + rollData.tic2 = "NONE" if (subKey == "melee-dmg" || subKey == "ranged-dmg" || subKey == "power-dmg") { rollData.isDamage = true @@ -2209,7 +2210,7 @@ export class PegasusActor extends Actor { } if (statKey == "mr") { - if (this.type == "character") { + if (this.type == "character"|| this.type == 'npc') { rollData.mrVehicle = PegasusUtility.checkIsVehicleCrew(this.id) if (rollData.mrVehicle) { rollData.effectsList.push({ @@ -2249,7 +2250,7 @@ export class PegasusActor extends Actor { processSizeBonus(rollData) { if (rollData.defenderTokenId) { let diffSize = 0 - if (this.type == "character") { + if (this.type == "character"|| this.type == 'npc') { this.system.biodata.sizenum = this.system.biodata?.sizenum ?? 0 this.system.biodata.sizebonus = this.system.biodata?.sizebonus ?? 0 diffSize = rollData.defenderSize - this.system.biodata.sizenum + this.system.biodata.sizebonus diff --git a/modules/pegasus-combat.js b/modules/pegasus-combat.js index fed4ca7..392f8c1 100644 --- a/modules/pegasus-combat.js +++ b/modules/pegasus-combat.js @@ -1,21 +1,98 @@ import { PegasusUtility } from "./pegasus-utility.js"; /* -------------------------------------------- */ -export class PegasusCombat extends Combat { - +export class PegasusCombatTracker extends CombatTracker { + /* -------------------------------------------- */ - async rollInitiative(ids, formula = undefined, messageOptions = {} ) { + static get defaultOptions() { + let path = "systems/fvtt-pegasus-rpg/templates/pegasus-combat-tracker.html"; + return foundry.utils.mergeObject(super.defaultOptions, { + template: path, + }); + } + /* -------------------------------------------- */ + activateListeners(html) { + super.activateListeners(html) + + html.find('.combat-tracker-tic').click(ev => { + let ticNum = $(ev.currentTarget).data("tic-num") + let combatantId = $(ev.currentTarget).data("combatant-id") + game.combat.revealTIC(ticNum, combatantId) + }) + } + +} + +/* -------------------------------------------- */ +export class PegasusCombat extends Combat { + + /* -------------------------------------------- */ + 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 } ]); + let initBonus = c.actor ? c.actor.getInitiativeScore(this.id, id) : -1; + await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: initBonus }]); } return this; } + /* -------------------------------------------- */ + isCharacter(combatantId) { + const combatant = game.combat.combatants.get(combatantId) + if (combatant) { + return combatant.actor.type == "character" + } + return false + } + + /* -------------------------------------------- */ + async setTic(combatantId, rollData) { + if ( !combatantId) { + return + } + const combatant = game.combat.combatants.get(combatantId) + if (combatant) { + await combatant.setFlag("world", "tic1", { revealed: false, text: rollData.tic1 }) + await combatant.setFlag("world", "tic2", { revealed: false, text: rollData.tic2 }) + } + } + + /* -------------------------------------------- */ + getTIC(num, combatantId) { + if ( !combatantId) { + return "" + } + const combatant = game.combat.combatants.get(combatantId) + if (combatant) { + let ticData = combatant.getFlag("world", "tic" + num) + if (ticData) { + let ticText = "TIC" + num + ":" + ticData.text + /* returns if revealed or if GM and NPC or if player and owner */ + if (ticData.revealed || (game.user.isGM && combatant.isNPC) || (!game.user.isGM && combatant.isOwner)) { + return ticText + } + } + } + return "TIC" + num + ":???" + } + /* -------------------------------------------- */ + async revealTIC(num, combatantId) { + if ( !num || !combatantId) { + return + } + const combatant = game.combat.combatants.get(combatantId) + if (combatant) { + let ticData = combatant.getFlag("world", "tic" + num) + if (ticData) { + ticData.revealed = true + await combatant.setFlag("world", "tic" + num, ticData) + } + } + } + /* -------------------------------------------- */ _onUpdate(changed, options, userId) { } @@ -28,11 +105,11 @@ export class PegasusCombat extends Combat { } /* -------------------------------------------- */ - static async decInitBy10( combatantId, value) { + static async decInitBy10(combatantId, value) { const combatant = game.combat.combatants.get(combatantId) let initValue = combatant.initiative + value await game.combat.setInitiative(combatantId, initValue) - setTimeout( this.checkTurnPosition, 400) // The setInitiative is no more blocking for unknown reason + setTimeout(this.checkTurnPosition, 400) // The setInitiative is no more blocking for unknown reason } } diff --git a/modules/pegasus-create-char.js b/modules/pegasus-create-char.js index ceb5640..e467b73 100644 --- a/modules/pegasus-create-char.js +++ b/modules/pegasus-create-char.js @@ -92,9 +92,11 @@ export class PegasusActorCreate { if (step == 'select-race-optionnal') { let ability = this.raceOptionnalAbilities.optionnalabilities.find(item => item._id == itemId); - let update = [] + let update = {} await this.actor.applyAbility(ability, update); - this.actor.update(update) + if (!jQuery.isEmptyObject(update)) { + this.actor.update(update) + } this.actor.createEmbeddedDocuments('Item', [ability]); PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); this.raceOptionnalAbilities.optionnalabilities = this.raceOptionnalAbilities.optionnalabilities.filter(item => item._id != itemId); diff --git a/modules/pegasus-main.js b/modules/pegasus-main.js index 51d80b4..a528adb 100644 --- a/modules/pegasus-main.js +++ b/modules/pegasus-main.js @@ -12,11 +12,9 @@ import { PegasusActor } from "./pegasus-actor.js"; import { PegasusItemSheet } from "./pegasus-item-sheet.js"; import { PegasusActorSheet } from "./pegasus-actor-sheet.js"; import { PegasusVehicleSheet } from "./pegasus-vehicle-sheet.js"; -import { PegasusNPCSheet } from "./pegasus-npc-sheet.js"; import { PegasusUtility } from "./pegasus-utility.js"; -import { PegasusCombat } from "./pegasus-combat.js"; +import { PegasusCombatTracker,PegasusCombat } from "./pegasus-combat.js"; import { PegasusItem } from "./pegasus-item.js"; -import { PegasusToken } from "./pegasus-token.js"; import { PEGASUS_CONFIG } from "./pegasus-config.js" /* -------------------------------------------- */ @@ -58,6 +56,7 @@ Hooks.once("init", async function () { CONFIG.Combat.documentClass = PegasusCombat CONFIG.Actor.documentClass = PegasusActor CONFIG.Item.documentClass = PegasusItem + CONFIG.ui.combat = PegasusCombatTracker game.system.pegasus = { utility: PegasusUtility, config: PEGASUS_CONFIG @@ -67,6 +66,7 @@ Hooks.once("init", async function () { // Register sheet application classes Actors.unregisterSheet("core", ActorSheet); Actors.registerSheet("fvtt-pegasus", PegasusActorSheet, { types: ["character"], makeDefault: true }) + Actors.registerSheet("fvtt-pegasus", PegasusActorSheet, { types: ["npc"], makeDefault: true }) Actors.registerSheet("fvtt-pegasus", PegasusVehicleSheet, { types: ["vehicle"], makeDefault: false }) Items.unregisterSheet("core", ItemSheet); diff --git a/modules/pegasus-roll-dialog.js b/modules/pegasus-roll-dialog.js index 9e422ec..a8883f9 100644 --- a/modules/pegasus-roll-dialog.js +++ b/modules/pegasus-roll-dialog.js @@ -39,6 +39,8 @@ export class PegasusRollDialog extends Dialog { /* -------------------------------------------- */ roll() { + this.rollData.tic1 = $('#roll-input-tic1').val() + this.rollData.tic2 = $('#roll-input-tic2').val() PegasusUtility.rollPegasus(this.rollData) } diff --git a/modules/pegasus-utility.js b/modules/pegasus-utility.js index 04923d8..375bb98 100644 --- a/modules/pegasus-utility.js +++ b/modules/pegasus-utility.js @@ -23,9 +23,9 @@ export class PegasusUtility { Hooks.on('renderChatLog', (log, html, data) => PegasusUtility.chatListeners(html)) Hooks.on('targetToken', (user, token, flag) => PegasusUtility.targetToken(user, token, flag)) Hooks.on('renderSidebarTab', (app, html, data) => PegasusUtility.addDiceRollButton(app, html, data)) - Hooks.on("getCombatTrackerEntryContext", (html, options) => { + /* Deprecated, no more used in rules Hooks.on("getCombatTrackerEntryContext", (html, options) => { PegasusUtility.pushInitiativeOptions(html, options); - }); + });*/ Hooks.on("dropCanvasData", (canvas, data) => { PegasusUtility.dropItemOnToken(canvas, data) }); @@ -87,7 +87,12 @@ export class PegasusUtility { Handlebars.registerHelper('isGM', function () { return game.user.isGM }) - + Handlebars.registerHelper('getTIC', function (num, id) { + return game.combat.getTIC(num, id) + }) + Handlebars.registerHelper('isCharacter', function (id) { + return game.combat.isCharacter(id) + }) } @@ -847,13 +852,14 @@ export class PegasusUtility { for (let res of rollData.hindranceRoll.terms[0].results) { if (res.result == 6) { rollData.hindranceFailure = true + rollData.img = `systems/fvtt-pegasus-rpg/images/dice/hindrance-dice.png` } } } await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode")) // Final score and keep data - rollData.finalScore = myRoll.total + rollData.finalScore = (rollData.hindranceFailure) ? 0 : myRoll.total if (rollData.damages) { let dmgFormula = this.getFoundryDiceFromLevel(rollData.damages.value) @@ -869,7 +875,8 @@ export class PegasusUtility { // Init stuf if (rollData.isInit) { let combat = game.combats.get(rollData.combatId) - combat.updateEmbeddedDocuments("Combatant", [{ _id: rollData.combatantId, initiative: rollData.finalScore }]) + await combat.setTic(rollData.combatantId, rollData) + combat.updateEmbeddedDocuments("Combatant", [{ _id: rollData.combatantId, initiative: rollData.finalScore }]) } // Stun specific -> Suffer a stun level when dmg-res for character diff --git a/system.json b/system.json index 835cfe5..acdafb2 100644 --- a/system.json +++ b/system.json @@ -252,7 +252,7 @@ ], "title": "Pegasus RPG", "url": "https://www.uberwald.me/data/files/fvtt-pegasus-rpg", - "version": "11.0.4", - "download": "https://www.uberwald.me/gitea/uberwald/fvtt-pegasus-rpg/archive/fvtt-pegasus-rpg-v11.0.4.zip", + "version": "11.0.5", + "download": "https://www.uberwald.me/gitea/uberwald/fvtt-pegasus-rpg/archive/fvtt-pegasus-rpg-v11.0.5.zip", "background": "systems/fvtt-pegasus-rpg/images/ui/pegasus_welcome_page.webp" } \ No newline at end of file diff --git a/template.json b/template.json index 2565c58..282bd0f 100644 --- a/template.json +++ b/template.json @@ -2,6 +2,7 @@ "Actor": { "types": [ "character", + "npc", "vehicle" ], "templates": { @@ -372,6 +373,12 @@ "core" ] }, + "npc": { + "templates": [ + "biodata", + "core" + ] + }, "vehicle": { "templates": [ "vehicle" diff --git a/templates/chat-generic-result.html b/templates/chat-generic-result.html index f26db6b..ad79bea 100644 --- a/templates/chat-generic-result.html +++ b/templates/chat-generic-result.html @@ -57,7 +57,7 @@ {{/if}} {{#if hindranceFailure}} -
  • Failed due to Hindrance Dice(s) !! +
  • Failed due to Hindrance Dice !! {{else}} {{#if isResistance}}
  • Defense Result : {{finalScore}} diff --git a/templates/pegasus-combat-tracker.html b/templates/pegasus-combat-tracker.html new file mode 100644 index 0000000..8ca2326 --- /dev/null +++ b/templates/pegasus-combat-tracker.html @@ -0,0 +1,132 @@ +
    +
    + {{#if user.isGM}} + + {{/if}} + +
    + {{#if user.isGM}} + + + + + + + {{/if}} + + {{#if combatCount}} + {{#if combat.round}} +

    {{localize 'COMBAT.Round'}} {{combat.round}}

    + {{else}} +

    {{localize 'COMBAT.NotStarted'}}

    + {{/if}} + {{else}} +

    {{localize "COMBAT.None"}}

    + {{/if}} + + {{#if user.isGM}} + + + + + + + {{/if}} + + + +
    +
    + +
      + {{#each turns}} +
    1. + {{this.name}} +
      +

      {{this.name}}

      +
      + {{#if ../user.isGM}} + + + + + + + {{/if}} + {{#if this.canPing}} + + + + {{/if}} +
      + {{#each this.effects}} + + {{/each}} +
      +
      +
      + + {{#if this.hasResource}} +
      + {{this.resource}} +
      + {{/if}} + +
      + {{getTIC 1 this.id}} + {{#if (isCharacter this.id)}} + {{getTIC 2 this.id}} + {{/if}} +
      + +
      + {{#if this.hasRolled}} + {{this.initiative}} + {{else if this.owner}} + + {{/if}} +
      +
    2. + {{/each}} +
    + + +
    diff --git a/templates/roll-dialog-generic.html b/templates/roll-dialog-generic.html index e975f08..3ae91ce 100644 --- a/templates/roll-dialog-generic.html +++ b/templates/roll-dialog-generic.html @@ -64,21 +64,6 @@ {{/if}} {{/if}} - -
    @@ -108,7 +93,7 @@ {{#if hindranceDices}}
    -

    Hindrance Dices

    +

    Hindrance Dice

    {{#for 1 hindranceDices 1}} @@ -170,6 +155,19 @@ {{> systems/fvtt-pegasus-rpg/templates/partial-roll-select-effects.html}} {{/if}} + {{#if isInit}} +
    + TIC 1: + +
    + {{#if (eq actorType "character")}} +
    + TIC 2: + +
    + {{/if}} + {{/if}} +