Manage luck with Edge
This commit is contained in:
		| @@ -136,6 +136,10 @@ export class SoSActorSheet extends ActorSheet { | ||||
|       this.actor.resetDeck(); | ||||
|       this.render(true); | ||||
|     }); | ||||
|     html.find('.discard-card').click((event) => { | ||||
|       const cardName = $(event.currentTarget).data("discard"); | ||||
|       this.actor.discardEdge( cardName ); | ||||
|     }); | ||||
|     html.find('.consequence-severity').click((event) => { | ||||
|       const li = $(event.currentTarget).parents(".item"); | ||||
|       const item = this.actor.getOwnedItem(li.data("item-id")); | ||||
|   | ||||
| @@ -85,6 +85,12 @@ export class SoSActor extends Actor { | ||||
|     this.saveDeck(); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   discardEdge( cardName ) {   | ||||
|     this.cardDeck.discardEdge( cardName  ); | ||||
|     this.saveDeck(); | ||||
|   } | ||||
|    | ||||
|   /* -------------------------------------------- */ | ||||
|   resetDeck( ) { | ||||
|     this.cardDeck.resetDeck(); | ||||
| @@ -221,7 +227,8 @@ export class SoSActor extends Actor { | ||||
|       modifierList: SoSUtility.fillRange(-10, +10), | ||||
|       tnList: SoSUtility.fillRange(6, 20), | ||||
|       consequencesList: duplicate( this.getApplicableConsequences() ), | ||||
|       malusConsequence: 0 | ||||
|       malusConsequence: 0, | ||||
|       bonusConsequence: 0 | ||||
|     } | ||||
|     let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/dialog-flip.html', flipData); | ||||
|     new SoSFlipDialog(flipData, html).render(true); | ||||
| @@ -238,7 +245,8 @@ export class SoSActor extends Actor { | ||||
|       actor: this, | ||||
|       modifierList: SoSUtility.fillRange(-10, +10), | ||||
|       tnList: SoSUtility.fillRange(6, 20), | ||||
|       malusConsequence: 0 | ||||
|       malusConsequence: 0, | ||||
|       bonusConsequence: 0 | ||||
|     } | ||||
|     flipData.statList['nostat'] = { label: "No stat (ie defaulting skills)", value: 0, cardsuit: "none" } | ||||
|     let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/dialog-flip.html', flipData); | ||||
|   | ||||
| @@ -76,6 +76,13 @@ export class SoSCardDeck  { | ||||
|     } | ||||
|   } | ||||
|    | ||||
|   /* -------------------------------------------- */ | ||||
|   discardEdge( cardName ) { | ||||
|     let newEdge = this.data.cardEdge.filter( card => card.cardName != cardName); | ||||
|     this.data.cardEdge = newEdge; // New edge list | ||||
|     this.data.discard.push( { cardName: cardName }); // And push in the discard pile | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   drawEdge( edgeNumber = 1 ) { | ||||
|     for (let i=0; i<edgeNumber; i++) { | ||||
| @@ -159,6 +166,10 @@ export class SoSCardDeck  { | ||||
|     flipData.isJoker = false; | ||||
|     flipData.fullTrump = false; | ||||
|  | ||||
|     if ( flipData.edgeLuck ) {  | ||||
|       flipData.cardOrigin == "Deck"; // Force Deck | ||||
|     } | ||||
|  | ||||
|     // Select card origin | ||||
|     if ( flipData.cardOrigin == "Deck") { | ||||
|       flipData.cardSlot[0].card1 = this.drawFromDeck(); | ||||
| @@ -190,7 +201,7 @@ export class SoSCardDeck  { | ||||
|  | ||||
|       // Trump check | ||||
|       flipData.cardSlot[0].cardsuit  = cardsuit; | ||||
|       if ( ! flipData.isJoker && cardsuit == flipData.stat.cardsuit ) { | ||||
|       if ( !flipData.isJoker && ( cardsuit == flipData.stat.cardsuit || flipData.edgeLuck) ) { | ||||
|         // This is a trump ! | ||||
|         flipData.cardSlot[1] = { total: 0 }; | ||||
|         flipData.isTrump = true; | ||||
| @@ -293,6 +304,15 @@ export class SoSCardDeck  { | ||||
|     return html; | ||||
|   } | ||||
|  | ||||
|     /* -------------------------------------------- */ | ||||
|     getEdgeHTMLForFlip( ) { | ||||
|       let html = ""; | ||||
|       for (let edge of this.data.cardEdge) { | ||||
|         html += `<a class='view-edge'><img class='flip-card edge-card' data-edge-card='${edge.cardName}' src='systems/foundryvtt-shadows-over-sol/img/cards/${edge.cardName}.webp' /></a>` | ||||
|       } | ||||
|       return html; | ||||
|     } | ||||
|    | ||||
|   /* -------------------------------------------- */ | ||||
|   getDiscardTopHTML( ) { | ||||
|     let html = ""; | ||||
|   | ||||
| @@ -36,6 +36,7 @@ export class SoSFlipDialog extends Dialog { | ||||
|       scoreBase = this.flipData.stat.value; | ||||
|     } | ||||
|     scoreBase += this.flipData.malusConsequence; | ||||
|     scoreBase += this.flipData.bonusConsequence; | ||||
|     $('#score-base').text( scoreBase); | ||||
|   } | ||||
|  | ||||
| @@ -46,7 +47,7 @@ export class SoSFlipDialog extends Dialog { | ||||
|     $("#view-deck").append(await flipData.actor.cardDeck.getDeckHTML()); | ||||
|  | ||||
|     $('.view-edge').remove(); | ||||
|     $("#view-edge").append(await flipData.actor.cardDeck.getEdgeHTML()); | ||||
|     $("#view-edge").append(await flipData.actor.cardDeck.getEdgeHTMLForFlip()); | ||||
|  | ||||
|     this.updateScoreBase(); | ||||
|  | ||||
| @@ -55,6 +56,7 @@ export class SoSFlipDialog extends Dialog { | ||||
|       flipData.modifier = $('#modifier').val(); | ||||
|       flipData.tn = (flipData.target) ? flipData.target.actor.data.data.scores.defense.value : $('#tn').val(); | ||||
|       flipData.edgeName = event.currentTarget.attributes['data-edge-card'].value; | ||||
|       flipData.edgeLuck = $('#edge-luck').is(":checked"); | ||||
|       flipData.cardOrigin = "Edge"; | ||||
|       if ( flipData.mode == 'skill' || flipData.mode == 'weapon') { | ||||
|         flipData.stat = duplicate( flipData.statList[ $('#statSelect').val() ] ); | ||||
| @@ -67,8 +69,8 @@ export class SoSFlipDialog extends Dialog { | ||||
|   } | ||||
|    | ||||
|   /* -------------------------------------------- */ | ||||
|   updateConsequence(event) { | ||||
|     this.flipData.consequencesSelected = $('#consequenceSelect').val(); | ||||
|   updateConsequenceMalus(event) { | ||||
|     this.flipData.consequencesSelected = $('#consequenceSelectMalus').val(); | ||||
|     let malusConsequence = 0; | ||||
|     for (let consequenceId of this.flipData.consequencesSelected) { | ||||
|       let consequence = this.flipData.consequencesList.find( item => item._id == consequenceId); | ||||
| @@ -80,6 +82,20 @@ export class SoSFlipDialog extends Dialog { | ||||
|     this.updateScoreBase(); | ||||
|   } | ||||
|  | ||||
|     /* -------------------------------------------- */ | ||||
|     updateConsequenceBonus(event) { | ||||
|       this.flipData.consequencesSelected = $('#consequenceSelectBonus').val(); | ||||
|       let bonusConsequence = 0; | ||||
|       for (let consequenceId of this.flipData.consequencesSelected) { | ||||
|         let consequence = this.flipData.consequencesList.find( item => item._id == consequenceId); | ||||
|         console.log(consequence, consequenceId); | ||||
|         bonusConsequence += SoSUtility.getConsequenceBonus( consequence.data.severity );       | ||||
|       } | ||||
|       $('#consequence-bonus').text(bonusConsequence); | ||||
|       this.flipData.bonusConsequence = bonusConsequence; | ||||
|       this.updateScoreBase(); | ||||
|     } | ||||
|    | ||||
|   /* -------------------------------------------- */ | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html); | ||||
| @@ -90,9 +106,6 @@ export class SoSFlipDialog extends Dialog { | ||||
|        | ||||
|     function onLoad() { | ||||
|       let flipData = dialog.flipData; | ||||
|       //RdDItemSort.setCoutReveReel(rollData.selectedSort); | ||||
|       //$("#diffLibre").val(Misc.toInt(rollData.diffLibre)); | ||||
|       //$("#diffConditions").val(Misc.toInt(rollData.diffConditions)); | ||||
|       dialog.updateFlip(flipData); | ||||
|     } | ||||
|    | ||||
| @@ -103,8 +116,11 @@ export class SoSFlipDialog extends Dialog { | ||||
|       this.updateFlip(dialog.flipData ); | ||||
|     } ); | ||||
|  | ||||
|     html.find('#consequenceSelect').change((event) => { | ||||
|       this.updateConsequence( event ); | ||||
|     html.find('#consequenceSelectMalus').change((event) => { | ||||
|       this.updateConsequenceMalus( event ); | ||||
|     } ); | ||||
|     html.find('#consequenceSelectBonus').change((event) => { | ||||
|       this.updateConsequenceBonus( event ); | ||||
|     } ); | ||||
|  | ||||
|     html.find('.class-view-deck').click((event) => { | ||||
|   | ||||
| @@ -4,6 +4,8 @@ import { SoSDialogCombatActions } from "./sos-dialog-combat-actions.js"; | ||||
|  | ||||
| /* -------------------------------------------- */   | ||||
| const severity2malus = { "none": 0, "light": -1, "moderate": -2, "severe": -3, "critical": -4}; | ||||
| /* -------------------------------------------- */   | ||||
| const severity2bonus = { "none": 0, "light": 1, "moderate": 2, "severe": 3, "critical": 4}; | ||||
|  | ||||
| /* -------------------------------------------- */   | ||||
| export class SoSUtility extends Entity { | ||||
| @@ -98,6 +100,10 @@ export class SoSUtility extends Entity { | ||||
|   static getConsequenceMalus(severity) { | ||||
|     return severity2malus[severity] ?? 0; | ||||
|   } | ||||
|   /* -------------------------------------------- */ | ||||
|   static getConsequenceBonus(severity) { | ||||
|     return severity2bonus[severity] ?? 0; | ||||
|   } | ||||
|    | ||||
|   /* -------------------------------------------- */ | ||||
|   static computeEncumbrance( items) { | ||||
|   | ||||
| @@ -1022,6 +1022,24 @@ ul, li { | ||||
|   font-weight: bold; | ||||
| } | ||||
|  | ||||
| .card-button { | ||||
|   box-shadow: inset 0px 1px 0px 0px #a6827e; | ||||
|   background: linear-gradient(to bottom, #21374afc 5%, #152833ab 100%); | ||||
|   background-color: #7d5d3b00; | ||||
|   border-radius: 3px; | ||||
|   border: 2px ridge #846109; | ||||
|   display: inline-block; | ||||
|   cursor: pointer; | ||||
|   color: #ffffff; | ||||
|   font-family: Neuropol; | ||||
|   font-size: 0.7rem; | ||||
|   padding: 4px 12px 0px 12px; | ||||
|   text-decoration: none; | ||||
|   text-shadow: 0px 1px 0px #4d3534; | ||||
|   position: relative; | ||||
|   margin:2px; | ||||
| } | ||||
|  | ||||
| .chat-card-button { | ||||
|   box-shadow: inset 0px 1px 0px 0px #a6827e; | ||||
|   background: linear-gradient(to bottom, #21374afc 5%, #152833ab 100%); | ||||
| @@ -1032,7 +1050,7 @@ ul, li { | ||||
|   cursor: pointer; | ||||
|   color: #ffffff; | ||||
|   font-family: Neuropol; | ||||
|   font-size: 0.9rem; | ||||
|   font-size: 0.8rem; | ||||
|   padding: 4px 12px 0px 12px; | ||||
|   text-decoration: none; | ||||
|   text-shadow: 0px 1px 0px #4d3534; | ||||
| @@ -1040,10 +1058,12 @@ ul, li { | ||||
|   margin:5px; | ||||
| } | ||||
|  | ||||
| .card-button:hover, | ||||
| .chat-card-button:hover { | ||||
|   background: linear-gradient(to bottom, #800000 5%, #3e0101 100%); | ||||
|   background-color: red; | ||||
| } | ||||
| .card-button:active, | ||||
| .chat-card-button:active { | ||||
|   position:relative; | ||||
|   top:1px; | ||||
|   | ||||
| @@ -71,18 +71,23 @@ | ||||
|             </div> | ||||
|           </div> | ||||
|            | ||||
|           <div class="flexrow"> | ||||
|             <span class="flexcol"> | ||||
|           <div class="flexcol"> | ||||
|             <h3 class="edge-name">Current deck size : {{data.deckSize}} cards</h3> | ||||
|               <span class="edge-name"><a class="reset-deck-full">Reset full deck and edges</a></span> | ||||
|               <span class="edge-name"><a class="draw-new-edge">Draw a new Edge card</a></span> | ||||
|               <span class="edge-name"><a class="reset-deck">Reset deck only (ie after a Joker)</a></span> | ||||
|             </span> | ||||
|             <div class="flexrow"> | ||||
|               <span class="edge-name"><a class="card-button reset-deck-full">Reset full deck and edges</a></span> | ||||
|               <span class="edge-name"><a class="card-button draw-new-edge">Draw a new Edge card</a></span> | ||||
|               <span class="edge-name"><a class="card-button reset-deck">Reset deck only (ie after a Joker)</a></span> | ||||
|             </div> | ||||
|             <span class="edge-name"> | ||||
|               <h3 class="edge-name">Edge cards : </h3> | ||||
|               <div class="flexrow"> | ||||
|                 {{#each data.edgecard as |card key|}} | ||||
|                 <div class="flexcol"> | ||||
|                   <img class="card-img" src="{{card.path}}" data-edit="img" title="{{card.cardName}}" /> | ||||
|                   <span class="edge-name"><a class="card-button discard-card" data-discard="{{card.cardName}}">Discard</a></span> | ||||
|                 </div> | ||||
|                 {{/each}} | ||||
|               </div> | ||||
|             </span> | ||||
|           </div> | ||||
|  | ||||
|   | ||||
| @@ -2,9 +2,8 @@ | ||||
|    | ||||
|   <h2 class="compdialog" id="statSkillFlip">Flip Dialog !</h2> | ||||
|    | ||||
|   <div class="grid grid-2col"> | ||||
|  | ||||
|     <div class="flex-group-left flexcol skill-column"> | ||||
|     <div class="flexrow"> | ||||
|       <div class="flexcol"> | ||||
|         {{#if (eq mode 'stat')}} | ||||
|         <h3 class="skill-label" id="flipSubTitle"> | ||||
|           Stat Only Flip : {{localize stat.label}} : {{stat.value}} - <img class="cardsuit-img" src="systems/foundryvtt-shadows-over-sol/img/cards/{{stat.cardsuit}}.webp"/> | ||||
| @@ -13,8 +12,7 @@ | ||||
|           <h3 class="skill-label" id="flipSubTitle">Final Score : <span id='score-base'>0</span> </h3> | ||||
|         </span> | ||||
|         {{else}} | ||||
|       <h3 class="skill-label" id="flipSubTitle"> | ||||
|         Select Stat   | ||||
|         <h3 class="skill-label" id="flipSubTitle">Select Stat</h3> | ||||
|         <select name="stat" id="statSelect" data-dtype="String"> | ||||
|           {{#select statList}} | ||||
|           {{#each statList as |stat key|}} | ||||
| @@ -22,27 +20,39 @@ | ||||
|           {{/each}} | ||||
|           {{/select}} | ||||
|         </select>         | ||||
|       </h3> | ||||
|         <span> | ||||
|           <h3 class="skill-label" id="flipSubTitle">Skill Flip : {{skill.name}} ({{skill.data.value}}) </h3> | ||||
|           <h3 class="skill-label" id="flipSubTitle">Final Score : <span id='score-base'>0</span> </h3> | ||||
|         </span> | ||||
|         {{/if}} | ||||
|       </div> | ||||
|     <div class="flex-group-left flexcol skill-column"> | ||||
|       <div class="flexcol"> | ||||
|         <div class="tab" data-group="primary"> | ||||
|         <select name="consequenceSelect" id="consequenceSelect" data-dtype="String" multiple size="5" width="200"> | ||||
|           <select name="consequenceSelect" id="consequenceSelectMalus" data-dtype="String" multiple size="5" width="200"> | ||||
|             {{#select consequencesList}} | ||||
|             {{#each consequencesList as |consequence key|}} | ||||
|             <option value={{consequence._id}}>{{localize consequence.name}} - {{consequence.data.severity}}</option> | ||||
|             {{/each}} | ||||
|             {{/select}} | ||||
|           </select>   | ||||
|         <h3 class="skill-label" id="flipConsequenceMalus">Consequences malus : <span id='consequence-malus'>0</span> </h3> | ||||
|           <h3 class="skill-label" id="flipConsequenceMalus">Consequences Malus : <span id='consequence-malus'>0</span> </h3> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="flexcol"> | ||||
|         <div class="tab" data-group="primary"> | ||||
|           <select name="consequenceSelect" id="consequenceSelectBonus" data-dtype="String" multiple size="5" width="200"> | ||||
|             {{#select consequencesList}} | ||||
|             {{#each consequencesList as |consequence key|}} | ||||
|             <option value={{consequence._id}}>{{localize consequence.name}} - {{consequence.data.severity}}</option> | ||||
|             {{/each}} | ||||
|             {{/select}} | ||||
|           </select>   | ||||
|           <h3 class="skill-label" id="flipConsequenceMalus">Consequences Bonus : <span id='consequence-bonus'>0</span> </h3> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|  | ||||
|   </div> | ||||
|   <hr> | ||||
|   {{#if target}} | ||||
|   <div> | ||||
|     <h4>Target : {{target.actor.name}} - Defense : {{target.actor.data.data.scores.defense.value}}/{{target.actor.data.data.scores.defense.critical}}</h4> | ||||
| @@ -64,9 +74,7 @@ | ||||
|           {{/select}} | ||||
|         </select> | ||||
|         {{/if}} | ||||
|       </div> | ||||
|       <div class="flexrow"> | ||||
|         <label for="categorie" class="generic-label">Flip Modifier</label> | ||||
|         <label for="categorie" class="generic-label"> Flip Modifier (GM bonus/malus)</label> | ||||
|         <select name="modifier" id="modifier" data-dtype="number"> | ||||
|           {{#select modifier}} | ||||
|           {{#each modifierList as |key|}} | ||||
| @@ -76,14 +84,19 @@ | ||||
|         </select> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div id="flexrow"> | ||||
|     <hr> | ||||
|     <div class="flexcol"> | ||||
|       <label class="generic-label">Click on deck to flip from deck, or click on the relevant Edge card to flip from it!</label> | ||||
|  | ||||
|       <label class="generic-label flexrow">Discard Edge for Luck (ie force Trump) when clicking :  | ||||
|           <span class="attribute-value checkbox"><input type="checkbox" name="edge-luck" id="edge-luck"/></span> | ||||
|       </label> | ||||
|     </div> | ||||
|     <div id="flexrow"> | ||||
|     <div class="flexrow"> | ||||
|       <span class="class-view-deck" id="view-deck"></span> | ||||
|       <span class="class-view-edge" id="view-edge"></span> | ||||
|     </div> | ||||
|     <div id="flexrow">   | ||||
|     <div class="flexrow">   | ||||
|       <label class="generic-label"></label> | ||||
|     </div> | ||||
|   </section> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user