231 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* -------------------------------------------- */  
 | 
						|
import { VadentisCombat } from "./vadentis-combat.js";
 | 
						|
 | 
						|
/* -------------------------------------------- */  
 | 
						|
export class VadentisUtility extends Entity {
 | 
						|
  
 | 
						|
  /* -------------------------------------------- */  
 | 
						|
  static async preloadHandlebarsTemplates() {
 | 
						|
    
 | 
						|
    const templatePaths = [
 | 
						|
      'systems/foundryvtt-vadentis/templates/actor-sheet.html',
 | 
						|
      'systems/foundryvtt-vadentis/templates/item-sheet.html',
 | 
						|
      'systems/foundryvtt-vadentis/templates/editor-notes-gm.html'
 | 
						|
    ]
 | 
						|
    return loadTemplates(templatePaths);    
 | 
						|
  }
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static updateCombat( combat, round, diff, id ) {
 | 
						|
    if (game.user.isGM && combat.data.round != 0 && combat.turns && combat.data.active) {
 | 
						|
      let turn = combat.turns.find(t => t.tokenId == combat.current.tokenId);
 | 
						|
      ChatMessage.create( { content: `Round ${combat.data.round} : C'est au tour de ${turn.actor.name}<br>` } );
 | 
						|
 | 
						|
      canvas.tokens.get(turn.token._id).control();
 | 
						|
      canvas.tokens.cycleTokens(1, true);
 | 
						|
    }    
 | 
						|
  }
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static createOptionList( min, max) {
 | 
						|
    let options = ""
 | 
						|
    for(let i=min; i<=max; i++) {
 | 
						|
      options += `<option value="${i}">${i}</option>\n`;
 | 
						|
    }
 | 
						|
    return options;
 | 
						|
  }
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static createDirectOptionList( min, max) {
 | 
						|
    let options = {};
 | 
						|
    for(let i=min; i<=max; i++) {
 | 
						|
      options[`${i}`] = `${i}`;
 | 
						|
    }
 | 
						|
    return options;
 | 
						|
  }
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static createDirectReverseOptionList( min, max) {
 | 
						|
    let options = {};
 | 
						|
    for(let i=max; i>=min; i--) {
 | 
						|
      options[`${i}`] = `${i}`;
 | 
						|
    }
 | 
						|
    return options;
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static getTarget() {
 | 
						|
    if (game.user.targets && game.user.targets.size == 1) {
 | 
						|
    for (let target of game.user.targets) {
 | 
						|
      return target;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return undefined;
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static processDamageString( formula, actor ) {
 | 
						|
    let workFormula = formula.toLowerCase();
 | 
						|
    if ( workFormula.includes('bonus de force')) {
 | 
						|
      workFormula = workFormula.replace('bonus de force', actor.getForceScore());
 | 
						|
    }
 | 
						|
    return workFormula;
 | 
						|
  } 
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static async processRoll( formula, rollMode ) {
 | 
						|
    let myRoll = new Roll(formula);
 | 
						|
    myRoll.evaluate();
 | 
						|
    if (game.modules.get("dice-so-nice") && game.modules.get("dice-so-nice").active) {
 | 
						|
      await game.dice3d.showForRoll(myRoll, game.user, true);
 | 
						|
    }
 | 
						|
    return myRoll;
 | 
						|
  }
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static async performAttack( combatData) {
 | 
						|
    let attacker = game.actors.get(combatData.attackerActorId);
 | 
						|
    let defender = game.actors.get(combatData.targetActorId);
 | 
						|
    console.log("ATTACK !!", attacker, defender);
 | 
						|
    if( attacker && defender) {
 | 
						|
      let defense = defender.getDefenseScore();      
 | 
						|
      let attaque = attacker.getAttaqueScore();
 | 
						|
 | 
						|
      let msgData = {
 | 
						|
        alias: this.name, 
 | 
						|
        title: `${attacker.name} attaque ${defender.name}`
 | 
						|
      }
 | 
						|
  
 | 
						|
      let formulaTouche = "1d20+"+attaque;
 | 
						|
      let formulaFull = attacker.buildTexteFormula( attacker.data.data.combat.attaque );
 | 
						|
      let myRoll = await this.processRoll(formulaTouche);
 | 
						|
      if (myRoll.results[0] > 1 && myRoll.total >= defense) { // Success !
 | 
						|
        let degats = `normaux : ${combatData.arme.data.damage}`;
 | 
						|
        let formula = combatData.arme.data.damage.toLowerCase();
 | 
						|
        msgData.msg = `${attacker.name} a réussi son attaque sur ${defender.name} (${formulaFull} => ${myRoll.total} / ${defense}) !<br> Les dégâts sont ${degats}.`;
 | 
						|
        
 | 
						|
        if ( combatData.arme.type == 'tir') {
 | 
						|
          attacker.decrementeMunition(combatData.arme);
 | 
						|
          msgData.msg += `<br>C'est un tir, les munitions de l'attaquant ont été décrémentées`;
 | 
						|
        }
 | 
						|
 | 
						|
        if ( myRoll.results[0] >= combatData.arme.data.valuecritical ) {
 | 
						|
          degats = `critiques : ${combatData.arme.data.criticaldamage}`;
 | 
						|
          formula = combatData.arme.data.criticaldamage.toLowerCase();
 | 
						|
          msgData.msg += `<br>C'est une <strong>réussite critique</strong> !`;
 | 
						|
        }
 | 
						|
        msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_attaque_réussie.webp'
 | 
						|
        
 | 
						|
        formula = this.processDamageString( formula, attacker );        
 | 
						|
        let degatsRoll = await this.processRoll(formula);
 | 
						|
        msgData.msg +=`<br>Les dégats infligés sont de <strong>${degatsRoll.total}</strong> (${formula}).`;
 | 
						|
        defender.applyDamage( degatsRoll.total );
 | 
						|
      } else { //Echec
 | 
						|
        msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_attaque_échouée.webp';
 | 
						|
        if ( myRoll.results[0] == 1) {
 | 
						|
          msgData.msg = `${attacker.name} a fait un <strong>échec critique</strong> et a raté son attaque sur ${defender.name} (${myRoll.total} / ${defense}) !`;
 | 
						|
        } else {
 | 
						|
          msgData.msg = `${attacker.name} a raté son attaque sur ${defender.name} (${myRoll.total} / ${defense}) !`;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      ChatMessage.create({
 | 
						|
        //whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
 | 
						|
        content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
 | 
						|
      });  
 | 
						|
    } else {
 | 
						|
      ui.notifications.warn("Impossible de trouver l'attaquant et le défenseur.")
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static buildJetText( stat) {
 | 
						|
    let name = stat.label;
 | 
						|
    let title = `Jet de ${name}`;
 | 
						|
    if ( name.toLowerCase().substr(0,1).match(/[aeoiou]/g) ) {
 | 
						|
      title = `Jet d'${name}`;
 | 
						|
    } 
 | 
						|
    return title;
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static registerChatCallbacks( ) {
 | 
						|
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static fillRange (start, end) {
 | 
						|
    return Array(end - start + 1).fill().map((item, index) => start + index);
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static onSocketMesssage( msg ) {
 | 
						|
    if( !game.user.isGM ) return; // Only GM
 | 
						|
 | 
						|
    if (msg.name == 'msg_attack' ) {
 | 
						|
      this.performAttack( msg.data );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static async loadCompendiumNames(compendium) {
 | 
						|
    const pack = game.packs.get(compendium);
 | 
						|
    let competences;
 | 
						|
    await pack.getIndex().then(index => competences = index);
 | 
						|
    return competences;
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static async loadCompendium(compendium, filter = item => true) {
 | 
						|
    let compendiumItems = await SoSUtility.loadCompendiumNames(compendium);
 | 
						|
 | 
						|
    const pack = game.packs.get(compendium);
 | 
						|
    let list = [];
 | 
						|
    for (let compendiumItem of compendiumItems) {
 | 
						|
      await pack.getEntity(compendiumItem._id).then(it => {
 | 
						|
        const item = it.data;
 | 
						|
        if (filter(item)) {
 | 
						|
          list.push(item);
 | 
						|
        }
 | 
						|
      });
 | 
						|
    };
 | 
						|
    return list;
 | 
						|
  }
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static getDonnees( ) {
 | 
						|
    return this.loadCompendiumNames('foundryvtt-vadentis.donnees');
 | 
						|
  }
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static getEglises( ) {
 | 
						|
    return this.loadCompendiumNames('foundryvtt-vadentis.eglises');
 | 
						|
  }
 | 
						|
 | 
						|
  /* -------------------------------------------- */
 | 
						|
  static async confirmDelete(actorSheet, li) {
 | 
						|
    let itemId = li.data("item-id");
 | 
						|
    let objet = actorSheet.actor.items.find(item => item._id == itemId);
 | 
						|
    let msgTxt = "<p>Etes vous certain de souhaiter supprimer cet item ?";
 | 
						|
    let buttons = {
 | 
						|
      delete: {
 | 
						|
          icon: '<i class="fas fa-check"></i>',
 | 
						|
          label: "Oui, à supprimer",
 | 
						|
          callback: () => {
 | 
						|
            actorSheet.actor.deleteOwnedItem(itemId);
 | 
						|
            li.slideUp(200, () => actorSheet.render(false));
 | 
						|
          }
 | 
						|
        },
 | 
						|
        cancel: {
 | 
						|
          icon: '<i class="fas fa-times"></i>',
 | 
						|
          label: "Annuler"
 | 
						|
        }
 | 
						|
      }
 | 
						|
      msgTxt += "</p>";
 | 
						|
      let d = new Dialog({
 | 
						|
        title: "Confirmer la suppression",
 | 
						|
        content: msgTxt,
 | 
						|
        buttons: buttons,
 | 
						|
        default: "cancel"
 | 
						|
      });
 | 
						|
      d.render(true);
 | 
						|
  }
 | 
						|
 | 
						|
} |