forked from public/foundryvtt-reve-de-dragon
		
	
		
			
				
	
	
		
			394 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			394 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * Extend the base Dialog entity by defining a custom window to perform spell.
 | |
|  * @extends {Dialog}
 | |
|  */
 | |
| import { RdDUtility } from "./rdd-utility.js";
 | |
| import { TMRUtility } from "./tmr-utility.js";
 | |
| 
 | |
| /** Helper functions */
 | |
| export class RdDTMRDialog extends Dialog {
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   constructor( html, actor, tmrData) {
 | |
|        
 | |
|     // Common conf
 | |
|     let dialogConf = {          
 | |
|       content: html,
 | |
|       buttons:
 | |
|           {
 | |
|             closeButton:
 | |
|             {
 | |
|               label: "Fermer",
 | |
|               callback: html => this.close(html)
 | |
|             }
 | |
|           },
 | |
|           default: "closeButton"
 | |
|       }
 | |
|     let dialogOptions = { classes: [ "tmrdialog"] } 
 | |
|     
 | |
|     dialogConf.title = "Terres Médianes de Rêve",
 | |
|     dialogOptions.width =  920;
 | |
|     dialogOptions.height = 960;
 | |
|     dialogOptions['z-index'] = 20;
 | |
|     
 | |
|     super(dialogConf, dialogOptions);
 | |
|     
 | |
|     this.tmrdata = duplicate(tmrData);    
 | |
|     this.col1_y = 30;
 | |
|     this.col2_y = 55;
 | |
|     this.cellh  = 55;
 | |
|     this.cellw  = 55;
 | |
|     this.actor = actor;
 | |
|     this.nbFatigue = 1; // 1 premier point de fatigue du à la montée
 | |
|     this.rencontresExistantes = duplicate(this.actor.data.data.reve.rencontre.list);
 | |
|     this.sortReserves = duplicate(this.actor.data.data.reve.reserve.list);
 | |
| 
 | |
|     //console.log(this.rencontresExistantes);    
 | |
|     this.pixiApp = new PIXI.Application( {width: 720, height: 860 } );             
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   close() {
 | |
|     this.actor.santeIncDec("fatigue", this.nbFatigue).then( super.close() ); // moving 1 cell costs 1 fatigue
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   displaySortReserve() {
 | |
|     console.log(this.sortReserves);
 | |
|     for (let sortReserve of this.sortReserves) {
 | |
|       sortReserve.circle = new PIXI.Graphics();
 | |
|       sortReserve.circle.beginFill(0x767610, 0.6);
 | |
|       sortReserve.circle.drawCircle(0, 0, 6);
 | |
|       sortReserve.circle.endFill();
 | |
|       let coordXY = TMRUtility.convertToCellCoord( sortReserve.coord );    
 | |
|       let basey = (coordXY.x % 2 == 0) ? this.col1_y : this.col2_y;
 | |
|       let myx = 28+(coordXY.x * this.cellw); 
 | |
|       let myy = basey+28+(coordXY.y * this.cellh);
 | |
|       sortReserve.circle.x = myx - (this.cellw/2)+16;
 | |
|       sortReserve.circle.y = myy - (this.cellh/2)+16;
 | |
|       this.pixiApp.stage.addChild(sortReserve.circle);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   displayPreviousRencontres() {
 | |
|     for (let rencontre of this.rencontresExistantes) {
 | |
|       rencontre.circle = new PIXI.Graphics();
 | |
|       rencontre.circle.beginFill(0x101010, 0.8);
 | |
|       rencontre.circle.drawCircle(0, 0, 6);
 | |
|       rencontre.circle.endFill();
 | |
|       let coordXY = TMRUtility.convertToCellCoord( rencontre.coord );    
 | |
|       let basey = (coordXY.x % 2 == 0) ? this.col1_y : this.col2_y;
 | |
|       let myx = 28+(coordXY.x * this.cellw); 
 | |
|       let myy = basey+28+(coordXY.y * this.cellh);
 | |
|       rencontre.circle.x = myx - (this.cellw/2)+16;
 | |
|       rencontre.circle.y = myy - (this.cellh/2)+16;
 | |
|       this.pixiApp.stage.addChild(rencontre.circle);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   updatePreviousRencontres() {
 | |
|     for (let rencontre of this.rencontresExistantes) {
 | |
|       this.pixiApp.stage.removeChild( rencontre.circle );
 | |
|     }
 | |
|     this.rencontresExistantes = duplicate(this.actor.data.data.reve.rencontre.list); 
 | |
|     this.displayPreviousRencontres();   
 | |
|   }
 | |
| 
 | |
|   /* -------------------------------------------- */  
 | |
|   updateSortReserve() {
 | |
|     for (let sortReserve of this.sortReserves) { //cleanup pixi icons
 | |
|       this.pixiApp.stage.removeChild( sortReserve.circle );
 | |
|     }
 | |
|     this.sortReserves = duplicate(this.actor.data.data.reve.reserve.list); // Then do it again!
 | |
|     this.displaySortReserve();
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   async derober() {
 | |
|     await this.actor.addTMRRencontre( this.currentRencontre );
 | |
|     console.log("-> derober", this.currentRencontre);
 | |
|     ChatMessage.create( { title: "TMR", content: game.user.name + " s'est dérobé et quitte les TMR.", user: game.user._id, whisper: ChatMessage.getWhisperRecipients("GM") } );
 | |
|     this.close();
 | |
|   }
 | |
|   /* -------------------------------------------- */  
 | |
|   async refouler(data) {
 | |
|     ChatMessage.create( { title: "TMR", content: game.user.name + " a refoulé une rencontre.", user: game.user._id, whisper: ChatMessage.getWhisperRecipients("GM") } );
 | |
|     await this.actor.deleteTMRRencontreAtPosition(  ); // Remove the stored rencontre if necessary
 | |
|     let result = await this.actor.ajouterRefoulement(1);
 | |
|     this.updatePreviousRencontres();
 | |
|     if (result == "souffle") {
 | |
|       let souffle = TMRUtility.getSouffle();
 | |
|     }
 | |
|     console.log("-> refouler", this.currentRencontre)
 | |
|     this.updateValuesDisplay();
 | |
|   }
 | |
|   /* -------------------------------------------- */  
 | |
|   async matriser(data) {
 | |
|     this.actor.deleteTMRRencontreAtPosition(  ); // Remove the stored rencontre if necessary    
 | |
|     this.updatePreviousRencontres();
 | |
|     
 | |
|     let draconic = this.actor.getBestDraconic();
 | |
|     let carac = this.actor.getCurrentReve();
 | |
|     let level = draconic.data.niveau - this.currentRencontre.force;
 | |
|     console.log("Maitriser", carac, draconic.data.niveau, this.currentRencontre.force);
 | |
|     let scoreDef = CONFIG.RDD.resolutionTable[carac][level+10];
 | |
|     let result = new Roll("d100").roll().total;
 | |
|     if ( result > scoreDef.score ) {
 | |
|       TMRUtility.processRencontreEchec( this.actor, this.currentRencontre);
 | |
|       ChatMessage.create( { title: "TMR", content: "Vous avez <strong>échoué</strong> à votre maîtrise d'un " . this.currentRencontre.name + " de force " + 
 | |
|               this.currentRencontre.force + 
 | |
|               "<br>Vous quittez brutalement les Terres Médianes !", 
 | |
|               user: game.user._id, whisper: [ game.user ] } );
 | |
|       ChatMessage.create( { title: "TMR", content: game.user.name + " a perdu sa rencontre contre : " + this.currentRencontre.name + " de force " + this.currentRencontre.force, user: game.user._id, whisper: ChatMessage.getWhisperRecipients("GM") } );
 | |
|       this.close();      
 | |
|     } else {
 | |
|       TMRUtility.processRencontreReussite( this.actor, this.rencontre);      
 | |
|       ChatMessage.create( { title: "TMR", content: "Vous avez <strong>réussi</strong> votre maîtrise d'un " + this.currentRencontre.name + " de force " + this.currentRencontre.force, user: game.user._id, whisper: [ game.user ] } );
 | |
|       ChatMessage.create( { title: "TMR", content: game.user.name + " a gagné sa rencontre contre : " + this.currentRencontre.name + " de force " + this.currentRencontre.force, user: game.user._id, whisper: ChatMessage.getWhisperRecipients("GM") } );
 | |
|     }
 | |
|     console.log("-> matriser", this.currentRencontre);
 | |
|     this.updateValuesDisplay();
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   async manageRencontre(coordTMR, cellDescr)
 | |
|   {
 | |
|     // Roll until diffent than '8'
 | |
|     let rencontre
 | |
|     this.currentRencontre = undefined;
 | |
|     for (let previousRencontre of this.rencontresExistantes ) {
 | |
|       if ( previousRencontre.coord == coordTMR) 
 | |
|         rencontre = previousRencontre.rencontre;
 | |
|     }
 | |
|     if ( rencontre == undefined  ) {
 | |
|       let val = 8;
 | |
|       while (val == 8) {
 | |
|         let myroll = new Roll("d7");
 | |
|         myroll.roll();
 | |
|         val = myroll.total;
 | |
|         if ( val == 7 ) {
 | |
|           rencontre = TMRUtility.rencontreTMRRoll(coordTMR, cellDescr);
 | |
|           rencontre.force = new Roll(rencontre.data.force).roll().total;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     
 | |
|     if (rencontre) { // Manages it
 | |
|       this.currentRencontre = duplicate(rencontre);
 | |
|       let diag = new Dialog( { title: "Rencontre en TMR!", 
 | |
|                             content: "Vous recontrez un " + rencontre.name + " de force " + rencontre.force + "<br>",
 | |
|                             buttons: {
 | |
|                               derober: {
 | |
|                                  icon: '<i class="fas fa-check"></i>',
 | |
|                                  label: "Se dérober",
 | |
|                                  callback: () => this.derober() 
 | |
|                                 },
 | |
|                                 refouler: {
 | |
|                                  icon: '<i class="fas fa-check"></i>',
 | |
|                                  label: "Refouler",
 | |
|                                  callback: () => this.refouler()
 | |
|                                 },
 | |
|                                 maitiser: {
 | |
|                                  icon: '<i class="fas fa-check"></i>',
 | |
|                                  label: "Maîtriser",
 | |
|                                  callback: () => this.matriser()
 | |
|                                 }
 | |
|                               }
 | |
|                         } );
 | |
|       diag.render(true);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   performRoll (html) {
 | |
|     this.actor.performRoll( this.rollData );
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   updateValuesDisplay() {
 | |
|     let ptsreve = document.getElementById("pointsreve-value");
 | |
|     ptsreve.innerHTML = this.actor.data.data.reve.reve.value;
 | |
|     
 | |
|     let tmrpos = document.getElementById("tmr-pos");
 | |
|     let tmr = TMRUtility.getTMRDescription( this.actor.data.data.reve.tmrpos.coord );
 | |
|     tmrpos.innerHTML = this.actor.data.data.reve.tmrpos.coord + " (" + tmr.label + ")";   
 | |
|     
 | |
|     let etat = document.getElementById("etatgeneral-value");
 | |
|     etat.innerHTML = this.actor.data.data.compteurs.etat.value;
 | |
| 
 | |
|     let refoulement = document.getElementById("refoulement-value");
 | |
|     refoulement.innerHTML = this.actor.data.data.reve.refoulement.value;
 | |
|     
 | |
|     let fatigueItem = document.getElementById("fatigue-table");
 | |
|     fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix( this.actor.data.data.sante.fatigue.value,  this.actor.data.data.sante.endurance.max ).html() + "</table>";    
 | |
|   }
 | |
| 
 | |
|   /* -------------------------------------------- */  
 | |
|   manageCaseHumideResult() {
 | |
|     if ( this.toclose ) 
 | |
|       this.close();
 | |
|   }
 | |
| 
 | |
|   /* -------------------------------------------- */  
 | |
|   async manageCaseHumide( cellDescr ) {
 | |
|     if ( cellDescr.type == "lac" || cellDescr.type == "fleuve" || cellDescr.type == "marais" ) {
 | |
|       let draconic = this.actor.getBestDraconic();
 | |
|       let carac = this.actor.getCurrentReve();
 | |
|       let level = draconic.data.niveau - 7;
 | |
|       let scoreDef = CONFIG.RDD.resolutionTable[carac][level+10];
 | |
|       let result = new Roll("d100").roll().total;
 | |
|       let content = "";
 | |
|       let mycallback;
 | |
|       console.log(">>>>", scoreDef);
 | |
|       if ( result > scoreDef.score ) {
 | |
|         content =  "Vous êtes entré sur une case humide, et vous avez <strong>raté</strong> votre maîtrise !  Vous <strong>quittez les Terres Médianes</strong> ! ("+ draconic.name +") :" + carac + " / " + level + " -> " + result + " / " + scoreDef.score;
 | |
|         if ( result >= scoreDef.etotal ) {
 | |
|           let souffle = TMRUtility.getSouffle(true);
 | |
|           content += "<br>Vous avez fait un Echec Total. Vous subissez un Souffle de Dragon : " + souffle.name ;
 | |
|           this.actor.createOwnedItem( souffle );
 | |
|         }
 | |
|         this.toclose = true;
 | |
|       } else {
 | |
|         content = "Vous êtes entré sur une case humide, et vous avez <strong>réussi</strong> votre maîtrise ! ("+ draconic.name +") :" + carac + " / " + level + " -> " + result + " / " + scoreDef.score;
 | |
|         if ( result <= scoreDef.part ) {
 | |
|           content += "<br>Vous avez fait une Réussite Particulière";
 | |
|           if ( level < 0 ) {
 | |
|             let xpcarac = Math.floor( Math.abs(level) / 2);
 | |
|             let xpcomp  = (Math.abs(level) % 2 == 1) ? xpcarac+1 : xpcarac;
 | |
|             content += "<br>Points d'expérience gagné ! " + xpcarac + " - " + xpcomp;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       let humideDiag = new Dialog( {title: "Case humide", 
 | |
|                   content: content, 
 | |
|                   buttons: { 
 | |
|                     choice: { icon: '<i class="fas fa-check"></i>',
 | |
|                               label: "Fermer", 
 | |
|                               callback: () => this.manageCaseHumideResult()
 | |
|                             }
 | |
|                       }
 | |
|                  }
 | |
|               );
 | |
|       humideDiag.render(true);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
|   updateSprites( myself ) 
 | |
|   {    
 | |
|     let coordTMR = myself.actor.data.data.reve.tmrpos.coord;
 | |
|     let coordXY = TMRUtility.convertToCellCoord( coordTMR );    
 | |
|     let basey = (coordXY.x % 2 == 0) ? myself.col1_y : myself.col2_y;
 | |
|     let myx = 28+(coordXY.x * myself.cellw); 
 | |
|     let myy = basey+28+(coordXY.y * myself.cellh);
 | |
| 
 | |
|     myself.circle.x = myx;
 | |
|     myself.circle.y = myy;     
 | |
|   }
 | |
|     
 | |
|   /* -------------------------------------------- */  
 | |
|   async declencheSortEnReserve( coordTMR )
 | |
|   {
 | |
|     for (let sortReserve of this.sortReserves ) {
 | |
|       if ( sortReserve.coord == coordTMR) {        
 | |
|         await this.actor.deleteSortReserve(coordTMR);
 | |
|         this.updateSortReserve();
 | |
|         ChatMessage.create( { title: "Sort en réserve", content: "Vous avez déclenché le sort en réserve " + sortReserve.sort.name, user: game.user._id } );
 | |
|         this.close();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /* -------------------------------------------- */  
 | |
|   async getCursorPosition(event) {
 | |
|     let origEvent = event.data.originalEvent;
 | |
|     let myself = event.target.tmrObject;
 | |
|     
 | |
|     //console.log("EVENT:", event);
 | |
|     let canvasRect = origEvent.target.getBoundingClientRect();
 | |
|     let x = origEvent.clientX - canvasRect.left;
 | |
|     let y = origEvent.clientY - canvasRect.top;
 | |
|     let cellx = Math.floor( x / myself.cellw);//  [From 0 -> 12]
 | |
|     if (cellx % 2 == 0)
 | |
|       y -= myself.col1_y;
 | |
|     else
 | |
|       y -= myself.col2_y;
 | |
|     let celly = Math.floor( y / myself.cellh);//  [From 0 -> 14]
 | |
|     
 | |
|     console.log(">>>>", cellx, celly );
 | |
|     let currentPos = TMRUtility.convertToCellCoord(myself.actor.data.data.reve.tmrpos.coord);
 | |
|     if ( (Math.abs(cellx - currentPos.x) > 1 || Math.abs(celly - currentPos.y) > 1) || 
 | |
|          (currentPos.y == 0 && celly > currentPos.y && cellx != currentPos.x && currentPos.x % 2 == 0) || 
 | |
|          (celly == 0 && celly < currentPos.y && cellx != currentPos.x && currentPos.x % 2 == 1)  ) {
 | |
|       ui.notifications.error( "Vous ne pouvez vous déplacer que sur des cases adjacentes à votre position, et pas en diagonale" );
 | |
|     } else {
 | |
|       let coordTMR  = TMRUtility.convertToTMRCoord(cellx, celly);
 | |
|       let cellDescr = TMRUtility.getTMRDescription( coordTMR );    
 | |
|       console.log("TMR column is", coordTMR, cellx, celly, cellDescr, this);
 | |
|       let tmrPos = duplicate(myself.actor.data.data.reve.tmrpos);
 | |
|       tmrPos.coord = coordTMR;
 | |
|       await myself.actor.update( { "data.reve.tmrpos": tmrPos } );
 | |
|       myself.updateSprites(myself);
 | |
|       
 | |
|       myself.nbFatigue += 1;
 | |
|       myself.updateValuesDisplay();      
 | |
|       myself.manageRencontre(coordTMR, cellDescr);      
 | |
|       myself.manageCaseHumide( cellDescr );      
 | |
|       await myself.declencheSortEnReserve( coordTMR );
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   /* -------------------------------------------- */  
 | |
| 	async activateListeners(html) {
 | |
|     super.activateListeners(html);
 | |
|         
 | |
|     var row = document.getElementById("tmrrow1");
 | |
|     var cell1 = row.insertCell(1);
 | |
|     cell1.append( this.pixiApp.view );
 | |
|     
 | |
|     // Roll Sort
 | |
|     html.find('#lancer-sort').click((event) => {
 | |
|       this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord);
 | |
|     });
 | |
|           
 | |
|     // load the texture we need
 | |
|     await this.pixiApp.loader.add('tmr', 'systems/foundryvtt-reve-de-dragon/styles/ui/tmp_main_r1.webp').load((loader, resources) => {      
 | |
|       // This creates a texture from a 'bunny.png' image
 | |
|       const mytmr = new PIXI.Sprite(resources.tmr.texture);
 | |
|       // Setup the position of the bunny
 | |
|       mytmr.x = 0;
 | |
|       mytmr.y = 0;
 | |
|       mytmr.width  = 720;
 | |
|       mytmr.height = 860;
 | |
|       // Rotate around the center
 | |
|       mytmr.anchor.x = 0;
 | |
|       mytmr.anchor.y = 0;    
 | |
|       mytmr.interactive = true;
 | |
|       mytmr.buttonMode  = true;
 | |
|       mytmr.tmrObject   = this;
 | |
|       mytmr.on('pointerdown', this.getCursorPosition);
 | |
|       
 | |
|       this.circle = new PIXI.Graphics();
 | |
|       this.circle.beginFill(0x9966FF, 0.6);
 | |
|       this.circle.drawCircle(0, 0, 15);
 | |
|       this.circle.endFill();
 | |
|       this.updateSprites( this );
 | |
| 
 | |
|       // Add the bunny to the scene we are building
 | |
|       this.pixiApp.stage.addChild(mytmr);
 | |
|       this.pixiApp.stage.addChild(this.circle);
 | |
|       
 | |
|       this.displayPreviousRencontres();    
 | |
|       this.displaySortReserve();
 | |
|     } );
 | |
| 
 | |
|     await this.actor.updatePointsDeReve( (this.tmrdata.isRapide) ? -2 : -1); // 1 point defatigue
 | |
|     this.updateValuesDisplay();
 | |
|     let cellDescr = TMRUtility.getTMRDescription(this.actor.data.data.reve.tmrpos.coord);
 | |
|     this.manageRencontre( this.actor.data.data.reve.tmrpos.coord,cellDescr );
 | |
|     this.manageCaseHumide( cellDescr );    
 | |
|   }
 | |
| }
 |