forked from public/foundryvtt-reve-de-dragon
		
	
		
			
				
	
	
		
			280 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			280 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { Grammar } from "./grammar.js";
 | ||
| import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
 | ||
| import { ITEM_TYPES } from "./constants.js";
 | ||
| import { BASE_CORPS_A_CORPS } from "./item/base-items.js";
 | ||
| import { RdDCombatManager } from "./rdd-combat.js";
 | ||
| 
 | ||
| const nomCategorieParade = {
 | ||
|   "sans-armes": "Sans arme",
 | ||
|   "armes-naturelles": "Armes naturelles",
 | ||
|   "hast": "Armes d'hast",
 | ||
|   "batons": "Bâtons",
 | ||
|   "boucliers": "Boucliers",
 | ||
|   "dagues": "Dagues",
 | ||
|   "epees-courtes": "Epées courtes",
 | ||
|   "epees-longues": "Epées longues",
 | ||
|   "epees-lourdes": "Epées lourdes",
 | ||
|   "haches": "Haches",
 | ||
|   "lances": "Lances",
 | ||
| }
 | ||
| 
 | ||
| /* -------------------------------------------- */
 | ||
| export class RdDItemArme extends Item {
 | ||
| 
 | ||
|   static isArme(item) {
 | ||
|     return item.type == ITEM_TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item);
 | ||
|   }
 | ||
| 
 | ||
|   /* -------------------------------------------- */
 | ||
|   static getArme(arme) {
 | ||
|     switch (arme ? arme.type : '') {
 | ||
|       case ITEM_TYPES.arme: return arme;
 | ||
|       case ITEM_TYPES.competencecreature:
 | ||
|         return RdDItemCompetenceCreature.armeCreature(arme);
 | ||
|     }
 | ||
|     return RdDItemArme.corpsACorps();
 | ||
|   }
 | ||
| 
 | ||
|   static getCompetenceArme(arme, maniement) {
 | ||
|     switch (arme.type) {
 | ||
|       case ITEM_TYPES.competencecreature:
 | ||
|         return arme.name
 | ||
|       case ITEM_TYPES.arme:
 | ||
|         switch (maniement) {
 | ||
|           case 'competence': return arme.system.competence;
 | ||
|           case 'unemain': return RdDItemArme.competence1Mains(arme);
 | ||
|           case 'deuxmains': return RdDItemArme.competence2Mains(arme);
 | ||
|           case 'tir': return arme.system.tir;
 | ||
|           case 'lancer': return arme.system.lancer;
 | ||
|         }
 | ||
|     }
 | ||
|     return undefined
 | ||
|   }
 | ||
| 
 | ||
|   static computeNiveauArmes(armes, competences) {
 | ||
|     for (const arme of armes) {
 | ||
|       arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   static niveauCompetenceArme(arme, competences) {
 | ||
|     const compArme = competences.find(it => Grammar.equalsInsensitive(it.name, arme.system.competence))
 | ||
|     return compArme?.system.niveau ?? -8
 | ||
|   }
 | ||
| 
 | ||
|   /* -------------------------------------------- */
 | ||
|   static getNomCategorieParade(arme) {
 | ||
|     const categorie = arme?.system ? RdDItemArme.getCategorieParade(arme) : arme;
 | ||
|     return nomCategorieParade[categorie];
 | ||
|   }
 | ||
| 
 | ||
|   /* -------------------------------------------- */
 | ||
|   static needArmeResist(armeAttaque, armeParade) {
 | ||
|     if (!armeAttaque || !armeParade) {
 | ||
|       return false;
 | ||
|     }
 | ||
|     // Epées parant une arme de bois (cf. page 115 ), une résistance est nécessaire
 | ||
|     let attCategory = RdDItemArme.getCategorieParade(armeAttaque);
 | ||
|     let defCategory = RdDItemArme.getCategorieParade(armeParade);
 | ||
| 
 | ||
|     return attCategory.match(/epees-/) && defCategory.match(/(haches|lances)/);
 | ||
|   }
 | ||
| 
 | ||
|   /* -------------------------------------------- */
 | ||
|   static getCategorieParade(armeData) {
 | ||
|     if (armeData.system.categorie_parade) {
 | ||
|       return armeData.system.categorie_parade
 | ||
|     }
 | ||
|     // pour compatibilité avec des personnages existants
 | ||
|     if (armeData.type == ITEM_TYPES.competencecreature || armeData.system.categorie == 'creature') {
 | ||
|       return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '')
 | ||
|     }
 | ||
|     if (!armeData.type.match(/arme|competencecreature/)) {
 | ||
|       return ''
 | ||
|     }
 | ||
|     if (armeData.system.competence == undefined) {
 | ||
|       return ITEM_TYPES.competencecreature;
 | ||
|     }
 | ||
|     let compname = armeData.system.competence.toLowerCase();
 | ||
|     if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) {
 | ||
|       return ''
 | ||
|     }
 | ||
| 
 | ||
|     if (compname.match('hache')) return 'haches'
 | ||
|     if (compname.match('hast')) return 'hast'
 | ||
|     if (compname.match('lance')) return 'lances'
 | ||
|     if (compname.match('bouclier')) return 'boucliers'
 | ||
|     if (compname.match('masse')) return 'masses'
 | ||
|     if (compname.match('epée') || compname.match('épée')) {
 | ||
|       if (armeData.name.toLowerCase().match(/(gnome)/))
 | ||
|         return 'epees-courtes'
 | ||
|       if (armeData.name.toLowerCase().match(/((e|é)pée dragone|esparlongue|demi-dragonne)/))
 | ||
|         return 'epees-longues'
 | ||
|       return 'epees-lourdes'
 | ||
|     }
 | ||
|     if (compname.match('dague')) {
 | ||
|       return 'dagues'
 | ||
|     }
 | ||
|     return 'sans-armes'
 | ||
|   }
 | ||
| 
 | ||
|   static defenseArmeParade(armeAttaque, armeParade) {
 | ||
|     const defCategory = RdDItemArme.getCategorieParade(armeParade)
 | ||
|     if (defCategory == 'boucliers') {
 | ||
|       return 'norm'
 | ||
|     }
 | ||
|     if (armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/)) {
 | ||
|       return ''
 | ||
|     }
 | ||
|     if (armeParade.system?.tir) {
 | ||
|       return ''
 | ||
|     }
 | ||
|     const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
 | ||
|     switch (attCategory) {
 | ||
|       case 'armes-naturelles': case 'sans-armes':
 | ||
|         return defCategory == 'sans-armes' ? 'norm' : ''
 | ||
|       default:
 | ||
|         return RdDItemArme.needParadeSignificative(armeAttaque, armeParade) ? 'sign' : 'norm'
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   /* -------------------------------------------- */
 | ||
|   static needParadeSignificative(armeAttaque, armeParade) {
 | ||
|     if (!armeAttaque || !armeParade) {
 | ||
|       return false;
 | ||
|     }
 | ||
|     // categories d'armes à la parade (cf. page 115 )
 | ||
|     const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
 | ||
|     const defCategory = RdDItemArme.getCategorieParade(armeParade)
 | ||
|     // bouclier et mêmes catégorie: peuvent se parer sans difficulté
 | ||
|     if (defCategory == 'boucliers') {
 | ||
|       return false;
 | ||
|     }
 | ||
|     // Parer avec une hache ou une arme d’hast exige toujours une significative
 | ||
|     if (defCategory.match(/(hast|haches)/)) {
 | ||
|       return true;
 | ||
|     }
 | ||
|     if (defCategory == attCategory) {
 | ||
|       return false;
 | ||
|     }
 | ||
|     // les épées se parent entre elles
 | ||
|     if (defCategory.match(/epees-/) && attCategory.match(/epees-/)) {
 | ||
|       return false;
 | ||
|     }
 | ||
|     // l'épée gnome pare la dague
 | ||
|     if (defCategory == 'epees-courtes' && attCategory == 'dagues') {
 | ||
|       return false;
 | ||
|     }
 | ||
|     // la dague pare les épées courtes et légères
 | ||
|     if (defCategory == 'dagues' && attCategory.match(/epees-(courtes|legeres)/)) {
 | ||
|       return false;
 | ||
|     }
 | ||
|     return true;
 | ||
|   }
 | ||
| 
 | ||
|   static dommagesReels(arme, maniement) {
 | ||
|     switch (maniement) {
 | ||
|       case 'tir':
 | ||
|       case 'lancer':
 | ||
|       case 'competence':
 | ||
|         return Number(arme.system.dommages)
 | ||
|     }
 | ||
|     if (arme.system.unemain && arme.system.deuxmains) {
 | ||
|       const containsSlash = !Number.isInteger(arme.system.dommages) && arme.system.dommages.includes("/")
 | ||
|       if (!containsSlash) {
 | ||
|         ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
 | ||
|         return Number(arme.system.dommages)
 | ||
|       }
 | ||
|       const tableauDegats = arme.system.dommages.split("/");
 | ||
|       return Number(tableauDegats[maniement == 'unemain' ? 0 : 1])
 | ||
|     }
 | ||
|     return Number(arme.system.dommages);
 | ||
|   }
 | ||
| 
 | ||
|   /* -------------------------------------------- */
 | ||
|   static armeUneOuDeuxMains(arme, aUneMain) {
 | ||
|     if (arme && !arme.system.cac) {
 | ||
|       arme = foundry.utils.duplicate(arme);
 | ||
|       arme.system.dommagesReels = RdDItemArme.dommagesReels(arme, aUneMain ? 'unemain' : 'deuxmains')
 | ||
|     }
 | ||
|     return arme;
 | ||
|   }
 | ||
| 
 | ||
|   static competence1Mains(arme) {
 | ||
|     return arme.system.competence.replace(" 2 mains", " 1 main");
 | ||
|   }
 | ||
| 
 | ||
|   static competence2Mains(arme) {
 | ||
|     return arme.system.competence.replace(" 1 main", " 2 mains");
 | ||
|   }
 | ||
| 
 | ||
|   static isUtilisable(arme) {
 | ||
|     switch (arme.type) {
 | ||
|       case ITEM_TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
 | ||
|       case ITEM_TYPES.competencecreature: return true
 | ||
|     }
 | ||
|     return false
 | ||
|   }
 | ||
| 
 | ||
|   static isAttaque(arme) {
 | ||
|     switch (arme.type) {
 | ||
|       case ITEM_TYPES.arme:
 | ||
|         return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
 | ||
|       case ITEM_TYPES.competencecreature:
 | ||
|         return arme.system.iscombat && RdDItemCompetenceCreature.isAttaque(item)
 | ||
|     }
 | ||
|     return false
 | ||
|   }
 | ||
| 
 | ||
|   static isParade(arme) {
 | ||
|     switch (arme.type) {
 | ||
|       case ITEM_TYPES.arme:
 | ||
|         return arme.system.equipe && arme.system.resistance > 0 && true/* TODO: regarder la categorie d'arme?*/
 | ||
|       case ITEM_TYPES.competencecreature:
 | ||
|         return arme.system.iscombat && RdDItemCompetenceCreature.isParade(arme)
 | ||
|     }
 | ||
|     return false
 | ||
|   }
 | ||
| 
 | ||
|   static corpsACorps(actor) {
 | ||
|     let competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS
 | ||
|     let melee = actor ? actor.system.carac['melee'].value : 0
 | ||
|     return {
 | ||
|       _id: competence.id,
 | ||
|       name: 'Corps à corps',
 | ||
|       type: ITEM_TYPES.arme,
 | ||
|       img: competence.img,
 | ||
|       system: {
 | ||
|         initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee),
 | ||
|         equipe: true,
 | ||
|         rapide: true,
 | ||
|         force: 0,
 | ||
|         dommages: "0",
 | ||
|         dommagesReels: 0,
 | ||
|         mortalite: 'non-mortel',
 | ||
|         competence: 'Corps à corps',
 | ||
|         resistance: 1,
 | ||
|         baseInit: 4,
 | ||
|         cac: 'pugilat',
 | ||
|         deuxmains: true,
 | ||
|         categorie_parade: 'sans-armes'
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   static mainsNues(actor) {
 | ||
|     const mainsNues = RdDItemArme.corpsACorps(actor)
 | ||
|     mainsNues.name = 'Mains nues'
 | ||
|     return mainsNues;
 | ||
|   }
 | ||
| 
 | ||
|   static empoignade(actor) {
 | ||
|     const empoignade = RdDItemArme.corpsACorps(actor)
 | ||
|     empoignade.name = 'Empoignade'
 | ||
|     empoignade.system.cac = 'empoignade'
 | ||
|     empoignade.system.baseInit = 3
 | ||
|     empoignade.system.mortalite = 'empoignade'
 | ||
|     return empoignade
 | ||
|   }
 | ||
| }
 |