From 63e552cc6ab95b33b9a23fa5306483e05510eda7 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Thu, 4 Feb 2021 08:38:59 +0100 Subject: [PATCH] Initiative from PHASE OK --- module/sos-combat.js | 46 +++++++++++++++++++++++++---- module/sos-dialog-combat-actions.js | 32 +++++++++++++++----- module/sos-main.js | 15 +--------- module/sos-utility.js | 4 ++- packs/combat-actions.db | 2 +- system.json | 2 +- 6 files changed, 71 insertions(+), 30 deletions(-) diff --git a/module/sos-combat.js b/module/sos-combat.js index 9e08a9c..7de2083 100644 --- a/module/sos-combat.js +++ b/module/sos-combat.js @@ -10,21 +10,57 @@ export class SoSCombat extends Combat { async nextRound() { console.log("NEXT ROUND !!!!"); - if ( game.user.isGM ) { - ChatMessage.create( { content: `New round !! Click on the button below to declare your actions for round ${this.round} !
- Declare actions`, - whisper: game.users.map(user => user.data._id) } ); + if ( game.user.isGM ) { + for( let combatant of this.combatants) { + let uniq = randomID(16); + if ( combatant.players[0]) { + // A player controls this combatant -> message ! + ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${combatant.actor.data.name} for round ${this.round} !
+ Declare actions`, + whisper: [ combatant.players[0].data._id] } ); + } else { + ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${combatant.actor.data.name} for round ${this.round} !
+ Declare actions`, + whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); + } + } } super.nextRound(); } + /* -------------------------------------------- */ + getPhaseRank( actionConf) { + for (let i=2; i>=0; i--) { + let action = actionConf.phaseArray[i]; + if (action.name != "No Action") { + console.log("Init is : ", i+1); + return i+1; + } + } + return 0; + } + /* -------------------------------------------- */ setupActorActions(actionConf) { + console.log("Setting combat for phase : ", actionConf); + if ( !this.phaseSetup) this.phaseSetup = []; // Opportunistic init if ( !this.phaseSetup[this.round] ) this.phaseSetup[this.round] = {}; // Bis // Keep track - this.phaseSetup[this.round][actionConf.userId] = actionConf; + this.phaseSetup[this.round][actionConf.combatantId] = actionConf; + console.log( this.combatants); + let combatant = this.combatants.find( comb => comb._id == actionConf.combatantId); + this.setInitiative( actionConf.combatantId, this.getPhaseRank( actionConf ) ); + + let actionsDone = true + for( let combatant of this.combatants) { + if ( !combatant.initiative ) actionsDone = false; + } + if ( actionsDone ) { + ChatMessage.create( { content: `Action phase has been completed ! Now proceeding with actions.`, + whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); + } } } diff --git a/module/sos-dialog-combat-actions.js b/module/sos-dialog-combat-actions.js index 8fd9954..872b9ab 100644 --- a/module/sos-dialog-combat-actions.js +++ b/module/sos-dialog-combat-actions.js @@ -4,12 +4,14 @@ import { SoSUtility } from "./sos-utility.js"; export class SoSDialogCombatActions extends Dialog { /* -------------------------------------------- */ - static async create( combatId, round ) { + static async create( combatId, combatantId, round, uniqId ) { let combatActions = { actionsList: await SoSUtility.loadCompendium( 'foundryvtt-shadows-over-sol.combat-actions' ), actionPoints: SoSUtility.fillRange(0, 6), combatId: combatId, + combatantId: combatantId, + uniqId: uniqId, round: round } for ( let i=0; i it.data.content.includes( this.combatActions.uniqId )); + toDelete.forEach(it => it.delete()); } else { ui.notifications.warn("Action Points are below 0 ! Please check your phases !"); } @@ -68,6 +83,7 @@ export class SoSDialogCombatActions extends Dialog { /* -------------------------------------------- */ validateActions( html ) { + } /* -------------------------------------------- */ diff --git a/module/sos-main.js b/module/sos-main.js index eaf1a27..375ad32 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -18,16 +18,6 @@ import { SoSCombat } from "./sos-combat.js"; /* Foundry VTT Initialization */ /* -------------------------------------------- */ -/************************************************************************************/ -const _patch_initiative = () => { - Combat.prototype.rollInitiative = async function ( - ids, - formula = undefined, - messageOptions = {} - ) { - } -} - /************************************************************************************/ Hooks.once("init", async function () { console.log(`Initializing Shadows over Sol System`); @@ -40,7 +30,7 @@ Hooks.once("init", async function () { /* -------------------------------------------- */ // Set an initiative formula for the system CONFIG.Combat.initiative = { - formula: "1+(1d6/10)", + formula: "1d3", decimals: 2 }; @@ -68,9 +58,6 @@ Hooks.once("init", async function () { SoSUtility.registerChatCallbacks(html); }); - // Patch the initiative formula - _patch_initiative(); - }); /* -------------------------------------------- */ diff --git a/module/sos-utility.js b/module/sos-utility.js index 939b30a..c2dc6dd 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -64,8 +64,10 @@ import { SoSDialogCombatActions } from "./sos-dialog-combat-actions.js"; static async openDeclareActions( event) { event.preventDefault(); let round = event.currentTarget.attributes['data-round'].value; + let combatantId = event.currentTarget.attributes['data-combatant-id'].value; let combatId = event.currentTarget.attributes['data-combat-id'].value; - let d = await SoSDialogCombatActions.create( combatId, round ); + let uniqId = event.currentTarget.attributes['data-uniq-id'].value; + let d = await SoSDialogCombatActions.create( combatId, combatantId, round, uniqId ); d.render(true); } diff --git a/packs/combat-actions.db b/packs/combat-actions.db index 1702456..4f58098 100644 --- a/packs/combat-actions.db +++ b/packs/combat-actions.db @@ -10,6 +10,7 @@ {"name":"First Aid","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"interact","minap":1,"description":"

To apply first aid in combat, the healer should make a Dex/medic-10 flip. The action benefits from having the appropriate tools (see page 111). On a success, she may remove the patient’s Bleeding consequence. A medic may not remove Wound consequences in the span of a combat round unless she has gear specifically capable of this (healing wounds normally takes 10 minutes; see page 119).

\n

Performing first aid in combat requires at least 1 AP or at least 2 AP if performing it on oneself.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_health.svg","effects":[],"_id":"NVzQN62rV05WYKSD"} {"name":"Grapple","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"attack","minap":1,"description":"

Sometimes the best tactic is to grab one’s opponent with one’s bare hands and grapple with her. To do this, the attacker must have a free hand. Should she not have a free hand available, she may immediately drop whatever she is holding, thereby gaining one or more free hands to grapple with. 

\n

Characters in a grapple may not take move actions until the grapple is broken.  Breaking a grapple is free for the initiator of the grapple, but for other characters, it requires a successful Str/melee vs. Defense flip—an attack action. This attack does not deal damage and is made at a -4 penalty. 

\n

While in a grapple, all actions that do not solely target the grappling opponent are at a -4 penalty. Additionally, as an attack action, a grappler may make Str/melee vs. End flip to choke her target. On a success, this increases the target’s Fatigue consequence a severity. If she’s already at Fatigue (critical), it instead renders her unconscious.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_grapple.svg","effects":[],"_id":"Q8kTBgxjEV3jMCF4"} {"name":"Trick","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"interact","minap":1,"description":"

Sometime it’s possible to trick an enemy, granting an opening that can be exploited in combat. Such tricks are usually high risk, high  reward actions, and they always leave the foe all the wiser against similar future actions. Tricks will usually be opposed actions, although the exact stats and skills will vary depending on the nature of the trick. For example, spraying congealed blood in a foe’s face might be a Dex/athletics vs. Spd flip, while faking a punch to leave an opening might be a Chr/melee vs. Int flip. Regardless of the nature of the trick, on a success, the foe’s Dazed consequence increases a  severity. With Mag 5+ it increases by two severities. On the other hand, should the trick fail, the trickster increases her Dazed consequence a severity or two severities if she failed by Mag 5+.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_trick.svg","effects":[],"_id":"TBgzXqY7gMjCV6gm"} +{"name":"No Action","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"other","minap":0,"description":0},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_none.svg","effects":[],"_id":"bqSieyyOLSY8tU2U"} {"name":"Coordinate","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"interact","minap":1,"description":"

There’s a reason that small tactical units train together, have their own comm channels and have a clear command structure. Groups of people fight better when coordinated. In combat, a character may take an Int/persuade-10 flip to try to coordinate her allies.

\n

A character may coordinate up to a number of allies equal to her intelligence. This requires the ability to clearly communicate with the coordinated allies, and benefits  from appropriate tools, such as linked comms (see page 194). 

\n

A character may not coordinate herself. On a success, all coordinated allies increase their Bolstered consequence by a severity. With 5+ Mag, they increase it two severities.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_coordinate.svg","effects":[],"_id":"dES68v89c6rJuijs"} {"name":"Aim","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"concentrate","minap":1,"description":"

With an aim action, a character may take a moment to apply some extra focus and attention when lining up an attack. When this action is taken, the character must specify the target, who must be visible. Every AP spent on the aim provides a +2 bonus to her next attack on the target to a maximum bonus equal to the character’s Perception. This bonus can carry over round to round, but the character’s aim is broken if she takes any action other than to continue to aim at the target or if she takes a dodge or a zone of control reaction against a different target.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_aim.svg","effects":[],"_id":"ePuCC1vQfMFSnSlj"} {"name":"Disarm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"attack","minap":1,"description":"

Make an attack at a -4 penalty. This attack forces the target to drop her weapon, usually because the attack hit her arm or weapon. Once dropped, the weapon lands on the ground a meter or two away from the target. With a disarm, the attacker may choose not to deal the usual damage.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_disarm.svg","effects":[],"_id":"jtfMVasuf8c6B7pd"} @@ -17,4 +18,3 @@ {"name":"Taking Cover","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"move","minap":1,"description":"

Sometimes a basic move or a change in posture will be enough to gain a character the Cover or Concealment consequences. To make the most of these, however, the character will need to make a take cover action. There is a difference between “taking cover” and simply having cover. Think of it like this: if Monique is being fired upon and runs to where a stack of barrels is between her and her attacker, she has cover from the attacks. At the same time, if she wants to shoot back, the barrels are in her way as well. She has cover, but she hasn’t “taken cover” to make the most of it.

\n

When a character takes cover, she needs to have moved immediately next to the object providing her with the cover consequence. She then performs the take cover action, setting herself up so that the cover does not hinder her attacks but still provides her with protection against the attacks of others. Without this, the cover’s bonus to Defense applies both to incoming and outgoing attacks.

\n

 

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_cover.svg","effects":[],"_id":"pwq6CB24QhNkrt1s"} {"name":"Posture","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"move","minap":1,"description":"

By default, characters are assumed to be standing. There are times, however, when a character might want to kneel, crouch, sit or lay down. Changing between any of these postures is a move action, and one change in posture may be tacked on for free to another move action, such as a basic move or taking cover. If performed by itself, changing posture costs the usual amount of AP for the phase.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_posture.svg","effects":[],"_id":"tF8mIKv0zi2HLv9B"} {"name":"Drawing/Reloading","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"interact","minap":1,"description":"

Drawing a weapon or reloading one is a simple interact action that involves taking a weapon out or putting ammunition into one. This costs at least 1 AP if the weapon or magazine was in a holster or other easy-to-access position. It costs at least 2 AP if it was harder to reach, such as stowed at the top of a pack or tucked inside one’s boot. Some weapons may have longer reload times, requiring more AP. This will be noted in the weapon’s properties.

\n

 

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_reload.svg","effects":[],"_id":"uSQw858IiBrWkeSj"} -{"name":"No Action","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"action","data":{"type":"other","minap":0,"description":0},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/action_none.svg","effects":[],"_id":"bqSieyyOLSY8tU2U"} diff --git a/system.json b/system.json index da46eab..86024c4 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.0.12", + "version": "0.0.13", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9",