import { Grammar } from "./grammar.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js" import { ITEM_TYPES } from "./item.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.mainsNues(); } 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 == 'bouclier') { 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 ajoutCorpsACorps(armes, actor) { armes.push(RdDItemArme.mainsNues(actor)); armes.push(RdDItemArme.empoignade(actor)); } static corpsACorps(actor) { let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } }; let melee = actor ? actor.system.carac['melee'].value : 0 return { _id: competence?.id, name: 'Corps à corps', type: ITEM_TYPES.arme, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp', 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, deuxmains: true, categorie_parade: 'sans-armes' } } } static mainsNues(actor) { const mainsNues = RdDItemArme.corpsACorps(actor) mainsNues.name = 'Mains nues' mainsNues.system.cac = 'pugilat' mainsNues.system.baseInit = 4 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 } }