292 lines
9.5 KiB
JavaScript
292 lines
9.5 KiB
JavaScript
import { ITEM_TYPES } from "../constants.js";
|
||
import { RdDItem } from "../item.js";
|
||
import { BASE_CORPS_A_CORPS } from "./base-items.js";
|
||
import { Grammar } from "../grammar.js";
|
||
import { RdDInitiative } from "../initiative.mjs";
|
||
import { MappingCreatureArme } from "./mapping-creature-arme.mjs";
|
||
|
||
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 const ATTAQUE_TYPE = {
|
||
UNE_MAIN: '(1 main)',
|
||
DEUX_MAINS: '(2 mains)',
|
||
CORPS_A_CORPS: '(corps à corps)',
|
||
COMPETENCE: 'competence',
|
||
TIR: '(tir)',
|
||
LANCER: '(lancer)'
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
export class RdDItemArme extends RdDItem {
|
||
|
||
static get ITEM_TYPE() { return ITEM_TYPES.arme }
|
||
|
||
static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp" }
|
||
|
||
penetration() { return parseInt(this.system.penetration ?? 0) }
|
||
|
||
isParade() { return this.system.resistance > 0 && this.system.categorie_parade }
|
||
isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') }
|
||
|
||
/* -------------------------------------------- */
|
||
static valeurMain(valeurs, main) {
|
||
valeurs = valeurs?.toString() ?? ""
|
||
const table = valeurs.includes("/") ? valeurs.split("/") : [valeurs, valeurs]
|
||
return parseInt(main == ATTAQUE_TYPE.DEUX_MAINS ? table[1] : table[0])
|
||
}
|
||
|
||
static getMainAttaque(competence) {
|
||
switch (competence.system.categorie) {
|
||
case 'tir': return ATTAQUE_TYPE.TIR
|
||
case 'lancer': return ATTAQUE_TYPE.LANCER
|
||
}
|
||
if (competence.name.includes('2 main')) {
|
||
return ATTAQUE_TYPE.DEUX_MAINS
|
||
}
|
||
return ATTAQUE_TYPE.UNE_MAIN
|
||
}
|
||
|
||
static getArme(arme) {
|
||
switch (arme ? arme.type : '') {
|
||
case ITEM_TYPES.arme: return arme;
|
||
case ITEM_TYPES.competencecreature:
|
||
return MappingCreatureArme.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 ATTAQUE_TYPE.COMPETENCE: return arme.system.competence;
|
||
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
|
||
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
|
||
case ATTAQUE_TYPE.TIR: case 'tir': return arme.system.tir
|
||
case ATTAQUE_TYPE.LANCER: 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 (![ITEM_TYPES.arme, ITEM_TYPES.competencecreature].includes(armeData.type)) {
|
||
return ''
|
||
}
|
||
if (armeData.system.categorie_parade) {
|
||
return armeData.system.categorie_parade
|
||
}
|
||
// pour compatibilité avec des personnages existants
|
||
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 == ATTAQUE_TYPE.UNE_MAIN ? 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 ? ATTAQUE_TYPE.UNE_MAIN : ATTAQUE_TYPE.DEUX_MAINS)
|
||
}
|
||
return arme;
|
||
}
|
||
|
||
competence1Mains() {
|
||
return this.system.competence.replace(" 2 mains", " 1 main");
|
||
}
|
||
|
||
competence2Mains() {
|
||
return this.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
|
||
}
|
||
|
||
isAttaque() {
|
||
return this.system.resistance > 0 || (this.system.tir != '' && this.system.portee_courte > 0)
|
||
}
|
||
|
||
static corpsACorps(actor) {
|
||
let competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS
|
||
let melee = actor ? actor.system.carac['melee'].value : 0
|
||
return new RdDItemArme({
|
||
_id: competence.id,
|
||
name: 'Corps à corps',
|
||
type: ITEM_TYPES.arme,
|
||
img: competence.img,
|
||
system: {
|
||
initiative: RdDInitiative.getRollInitiative(melee, competence.system.niveau),
|
||
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 pugilat(actor) {
|
||
const pugilat = RdDItemArme.corpsACorps(actor)
|
||
pugilat.name = 'Mains nues'
|
||
return pugilat;
|
||
}
|
||
|
||
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
|
||
}
|
||
}
|