diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 1436aaf..eb03e6d 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -26,6 +26,8 @@ export class SoSActorSheet extends ActorSheet { let data = super.getData(); data.data.edgecard = this.actor.getEdgesCard(); + data.data.deckSize = this.actor.getDeckSize(); + data.data.skills = this.actor.data.items.filter( item => item.type == 'skill').sort( (a, b) => { if ( a.name > b.name ) return 1; return -1; diff --git a/module/actor.js b/module/actor.js index a39b582..64575c5 100644 --- a/module/actor.js +++ b/module/actor.js @@ -59,6 +59,12 @@ export class SoSActor extends Actor { } this.controlScores(); } + + /* -------------------------------------------- */ + getDeckSize() { + return this.cardDeck.getDeckSize(); + } + /* -------------------------------------------- */ getEdgesCard( ) { let edgesCard = duplicate(this.cardDeck.data.cardEdge); diff --git a/module/sos-card-deck.js b/module/sos-card-deck.js index 80ebbfd..8e0da25 100644 --- a/module/sos-card-deck.js +++ b/module/sos-card-deck.js @@ -94,6 +94,11 @@ export class SoSCardDeck { } } + /* -------------------------------------------- */ + getDeckSize() { + return this.data.deck.length; + } + /* -------------------------------------------- */ getCardSuit( cardName ) { if ( cardName[0] == 'c') return 'club'; diff --git a/module/sos-combat.js b/module/sos-combat.js index 3b4e0b1..0f4686a 100644 --- a/module/sos-combat.js +++ b/module/sos-combat.js @@ -139,6 +139,18 @@ export class SoSCombat extends Combat { return 0; } + /* -------------------------------------------- */ + decreaseAPFromActor( actorId ) { + for( let combatant of this.combatants) { + //console.log(combatant); + if ( combatant.actor.data._id == actorId ) { + let phase = this.phaseSetup[combatant._id]; + phase.remainingAP -= 1; + if ( phase.remainingAP < 0 ) phase.remainingAP = 0; + } + } + } + /* -------------------------------------------- */ async setupActorActions(actionConf) { console.log("Setting combat for phase : ", actionConf); diff --git a/module/sos-utility.js b/module/sos-utility.js index f3870be..cdad57b 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -35,19 +35,21 @@ export class SoSUtility { /* -------------------------------------------- */ onSocketMesssage( msg ) { + if( !game.user.isGM ) return; // Only GM + if (msg.name == 'msg_declare_actions' ) { - if (game.user.isGM) { - let combat = game.combats.get( msg.data.combatId); // Get the associated combat - combat.setupActorActions( msg.data ); - } + let combat = game.combats.get( msg.data.combatId); // Get the associated combat + combat.setupActorActions( msg.data ); } else if (msg.name == 'msg_close_action') { - if (game.user.isGM) { - game.combat.closeAction( msg.data.uniqId ); - } + game.combat.closeAction( msg.data.uniqId ); } else if (msg.name == 'msg_request_defense') { - if (game.user.isGM) { - SoSUtility.applyDamage( msg.data ); - } + SoSUtility.applyDamage( msg.data ); + } else if (msg.name == 'msg_reaction_cover') { + SoSUtility.reactionCover( msg.data.uniqId ); + } else if (msg.name == 'msg_reaction_melee') { + SoSUtility.reactionMelee( msg.data.uniqId ); + } else if (msg.name == 'msg_reaction_hit') { + SoSUtility.reactionHit( msg.data.uniqId ); } } @@ -119,7 +121,7 @@ export class SoSUtility { if ( game.user.isGM ) { game.combat.closeAction( uniqId ); } else { - game.socket.emit("system.foundryvtt-reve-de-dragon", { + game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_close_action", data: { uniqId: uniqId} } ); } } @@ -132,6 +134,32 @@ export class SoSUtility { html.on("click", '#button-end-action', event => { SoSUtility.closeAction( event ); }); + + html.on("click", '#button-reaction-cover', event => { + let uniqId = event.currentTarget.attributes['data-uniq-id'].value; + if ( game.user.isGM ) { + SoSUtility.reactionCover( uniqId ); + } else { + game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_cover", data: { uniqId: uniqId} } ); + } + }); + + html.on("click", '#button-reaction-melee', event => { + let uniqId = event.currentTarget.attributes['data-uniq-id'].value; + if ( game.user.isGM ) { + SoSUtility.reactionMelee( uniqId ); + } else { + game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_melee", data: { uniqId: uniqId} } ); + } + }); + html.on("click", '#button-reaction-hit', event => { + let uniqId = event.currentTarget.attributes['data-uniq-id'].value; + if ( game.user.isGM ) { + SoSUtility.reactionHit( uniqId ); + } else { + game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_hit", data: { uniqId: uniqId} } ); + } + }); } /* -------------------------------------------- */ @@ -144,14 +172,24 @@ export class SoSUtility { return undefined; } - /* -------------------------------------------- */ - static increaseConsequenceSeverity( severity ) { - if ( severity == 'none') return 'light'; - if ( severity == 'light') return 'moderate'; - if ( severity == 'moderate') return 'severe'; - if ( severity == 'severe') return 'critical'; - return 'critical'; - } + /* -------------------------------------------- */ + static increaseConsequenceSeverity( severity ) { + if ( severity == 'none') return 'light'; + if ( severity == 'light') return 'moderate'; + if ( severity == 'moderate') return 'severe'; + if ( severity == 'severe') return 'critical'; + return 'critical'; + } + + /* -------------------------------------------- */ + static getConsequenceSeverityLevel( severity) { + if ( severity == 'none') return 0; + if ( severity == 'light') return 1; + if ( severity == 'moderate') return 2; + if ( severity == 'severe') return 3; + if ( severity == 'critical') return 4; + return 0; + } /* -------------------------------------------- */ static increaseSeverity( severity ) { @@ -180,6 +218,17 @@ export class SoSUtility { /* -------------------------------------------- */ static async applyDamage( flipData ) { + if (!this.registry) this.registry = {}; + + if ( flipData.isReaction) { + flipData.magnitude = flipData.finalScore - flipData.tn; // Update magnitude + if ( flipData.magnitude < 0 ) { + let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-reaction-result.html', flipData ); + ChatMessage.create( { content: html }); + return; + } + } + let dr = flipData.target.actor.data.data.scores.dr.value; let shock = flipData.target.actor.data.data.scores.shock.value; let defenseCritical = flipData.target.actor.data.data.scores.defense.critical; @@ -228,22 +277,50 @@ export class SoSUtility { flipData.coverConsequence = defender.data.items.find( item => item.type == 'consequence' && item.name == 'Cover'); flipData.APavailable = game.combat.getAPFromActor( defender.data._id ); console.log("FLIPDATE : ", flipData); - if ( flipData.APavailable > 0) { + if ( !flipData.isReaction && flipData.APavailable > 0) { if ( (flipData.weapon.data.category == 'melee' ) || ( (flipData.weapon.data.category == 'laser' || flipData.weapon.data.category == 'ballistic') && flipData.coverConsequence.data.severity != 'none') ) { - flipData.coverSeverityLevel = this.getSeverityLevel( flipData.coverConsequence.data.severity ) * 2; + flipData.coverSeverityLevel = this.getConsequenceSeverityLevel( flipData.coverConsequence.data.severity ) * 2; flipData.coverSeverityFlag = (flipData.coverSeverityLevel > 0); flipData.isMelee = (flipData.weapon.data.category == 'melee' ); let melee = defender.data.items.find( item => item.type == 'skill' && item.name == 'Melee'); flipData.defenderMelee = melee.data.value; + flipData.uniqId = randomID(16); + this.registry[flipData.uniqId] = flipData; let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-request-dodge.html', flipData ); ChatMessage.create( { content: html, whisper: [ChatMessage.getWhisperRecipients(flipData.target.actor.name), ChatMessage.getWhisperRecipients("GM") ] } ); return; // Wait message response } } + flipData.isReaction = false; this.takeWounds( flipData); } + /* -------------------------------------------- */ + static reactionCover( uniqId) { + let flipData = this.registry[uniqId]; + flipData.tn += flipData.coverSeverityLevel; + flipData.isReaction = true; + game.combat.decreaseAPFromActor( flipData.target.actor._id ); + SoSUtility.applyDamage( flipData); + } + + /* -------------------------------------------- */ + static reactionMelee( uniqId) { + let flipData = this.registry[uniqId]; + flipData.tn += flipData.defenderMelee; + flipData.isReaction = true; + game.combat.decreaseAPFromActor( flipData.target.actor._id ); + SoSUtility.applyDamage( flipData); + } + + /* -------------------------------------------- */ + static reactionHit( uniqId) { + let flipData = this.registry[uniqId]; + flipData.isReaction = true; + SoSUtility.takeWounds( flipData); + } + /* -------------------------------------------- */ static takeWounds( flipData ) { let defender = game.actors.get( flipData.target.actor._id); diff --git a/styles/simple.css b/styles/simple.css index be4c310..6e2d732 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -1032,7 +1032,7 @@ ul, li { cursor: pointer; color: #ffffff; font-family: Neuropol; - font-size: 14px; + font-size: 0.9rem; padding: 4px 12px 0px 12px; text-decoration: none; text-shadow: 0px 1px 0px #4d3534; diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 0bdf159..7d414a7 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -73,12 +73,13 @@
-

Edge cards :

+

Current deck size : {{data.deckSize}} cards

Reset full deck and edges Draw a new Edge card Reset deck only (ie after a Joker)
+

Edge cards :

{{#each data.edgecard as |card key|}} {{/each}} diff --git a/templates/chat-damage-request-dodge.html b/templates/chat-damage-request-dodge.html index 0fa1c84..28bb914 100644 --- a/templates/chat-damage-request-dodge.html +++ b/templates/chat-damage-request-dodge.html @@ -1,10 +1,13 @@ -

{{target.actor.name}} has {{remainingAP}} AP and can react to the attack from {{actor.name}} !

+

{{target.actor.name}} has {{APavailable}} AP and can react to the attack from {{actor.name}} !

{{#if coverSeverityFlag}} - + + Add cover consequence bonus x 2 to your defense : {{coverSeverityLevel}}` {{/if}} {{#if isMelee}} - + + Add Melee level to your defense : {{defenderMelee}}` {{/if}} - + + Do not dodge and get the hit !`
diff --git a/templates/chat-reaction-result.html b/templates/chat-reaction-result.html new file mode 100644 index 0000000..4f55bc2 --- /dev/null +++ b/templates/chat-reaction-result.html @@ -0,0 +1,4 @@ +

{{target.actor.name}} reacted and has avoided damages !

+
+ +