825 lines
30 KiB
JavaScript
825 lines
30 KiB
JavaScript
/* -------------------------------------------- */
|
||
import { HawkmoonUtility } from "./hawkmoon-utility.js";
|
||
import { HawkmoonRollDialog } from "./applications/hawkmoon-roll-dialog.mjs";
|
||
|
||
/* -------------------------------------------- */
|
||
const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10]
|
||
const __vitesseBonus = [-2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8]
|
||
|
||
/* -------------------------------------------- */
|
||
/**
|
||
* Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system.
|
||
* @extends {Actor}
|
||
*/
|
||
export class HawkmoonActor extends Actor {
|
||
|
||
/* -------------------------------------------- */
|
||
/**
|
||
* Override the create() function to provide additional SoS functionality.
|
||
*
|
||
* This overrided create() function adds initial items
|
||
* Namely: Basic skills, money,
|
||
*
|
||
* @param {Object} data Barebones actor data which this function adds onto.
|
||
* @param {Object} options (Unused) Additional options which customize the creation workflow.
|
||
*
|
||
*/
|
||
|
||
static async create(data, options) {
|
||
|
||
// Case of compendium global import
|
||
if (data instanceof Array) {
|
||
return super.create(data, options);
|
||
}
|
||
// If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic
|
||
if (data.items) {
|
||
let actor = super.create(data, options);
|
||
return actor;
|
||
}
|
||
|
||
if (data.type == 'personnage') {
|
||
const skills = await HawkmoonUtility.loadCompendium("fvtt-hawkmoon-cyd.skills")
|
||
data.items = skills.map(i => i.toObject())
|
||
}
|
||
if (data.type == 'creature') {
|
||
const skills = await HawkmoonUtility.loadCompendium("fvtt-hawkmoon-cyd.skills-creatures")
|
||
data.items = skills.map(i => i.toObject())
|
||
data.items.push({ name: "Arme naturelle 1", type: 'arme', img: "systems/fvtt-hawkmoon-cyd/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } })
|
||
data.items.push({ name: "Arme naturelle 2", type: 'arme', img: "systems/fvtt-hawkmoon-cyd/assets/icons/melee.webp", system: { typearme: "contact", bonusmaniementoff: 0, seuildefense: 0, degats: "0" } })
|
||
}
|
||
|
||
return super.create(data, options);
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getBonusDefenseFromTalents() {
|
||
let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated)
|
||
let bonus = 0
|
||
for (let talent of talents) {
|
||
for (let auto of talent.system.automations) {
|
||
if (auto.eventtype == "bonus-permanent" && auto.bonusname == "bonus-defensif") {
|
||
bonus += Number(auto.bonus || 0)
|
||
}
|
||
}
|
||
}
|
||
return bonus
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
prepareArme(arme) {
|
||
if (this.type == "cellule") {
|
||
return arme
|
||
}
|
||
|
||
arme = foundry.utils.duplicate(arme)
|
||
let combat = this.getCombatValues()
|
||
if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") {
|
||
let bonusDefense = this.getBonusDefenseFromTalents()
|
||
arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "mêlée") ?? { system: { niveau: 0 } })
|
||
arme.system.attrKey = "pui"
|
||
arme.system.totalDegats = arme.system.degats + "+" + combat.bonusDegatsTotal
|
||
arme.system.totalOffensif = this.system.attributs.pui.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff + (this.system.combat.monte ? 3 : 0)
|
||
arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense + bonusDefense + (this.system.combat.monte ? 3 : 0)
|
||
console.log("Arme", arme.system.totalDefensif, combat, arme.system.competence.system.niveau, arme.system.seuildefense, bonusDefense)
|
||
arme.system.isdefense = true
|
||
arme.system.isMelee = true
|
||
arme.system.isDistance = false
|
||
}
|
||
if (arme.system.typearme == "jet" || arme.system.typearme == "tir") {
|
||
arme.system.competence = foundry.utils.duplicate(this.items.find(item => item.type == "competence" && item.name.toLowerCase() == "armes à distance") ?? { system: { niveau: 0 } })
|
||
arme.system.attrKey = "adr"
|
||
arme.system.totalOffensif = this.system.attributs.adr.value + arme.system.competence.system.niveau + arme.system.bonusmaniementoff
|
||
arme.system.totalDegats = arme.system.degats
|
||
arme.system.isMelee = false
|
||
arme.system.isDistance = true
|
||
if (arme.system.isdefense) {
|
||
arme.system.totalDefensif = combat.defenseTotal + arme.system.competence.system.niveau + arme.system.seuildefense
|
||
}
|
||
}
|
||
return arme
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getItemSorted(types) {
|
||
let items = this.items.filter(item => types.includes(item.type)) || []
|
||
HawkmoonUtility.sortArrayObjectsByName(items)
|
||
return items
|
||
}
|
||
getWeapons() {
|
||
let armes = []
|
||
for (let arme of this.items) {
|
||
if (arme.type == "arme") {
|
||
armes.push(this.prepareArme(arme))
|
||
}
|
||
}
|
||
HawkmoonUtility.sortArrayObjectsByName(armes)
|
||
return armes
|
||
}
|
||
getMonnaies() {
|
||
return this.getItemSorted(["monnaie"])
|
||
}
|
||
getEquipments() {
|
||
return this.getItemSorted(["equipement"])
|
||
}
|
||
getArtefacts() {
|
||
return this.getItemSorted(["artefact"])
|
||
}
|
||
getArmors() {
|
||
return this.getItemSorted(["protection"])
|
||
}
|
||
getHistoriques() {
|
||
return this.getItemSorted(["historique"])
|
||
}
|
||
getProfils() {
|
||
return this.getItemSorted(["profil"])
|
||
}
|
||
getTalents() {
|
||
return this.getItemSorted(["talent"])
|
||
}
|
||
getRessources() {
|
||
return this.getItemSorted(["ressource"])
|
||
}
|
||
getContacts() {
|
||
return this.getItemSorted(["contact"])
|
||
}
|
||
getMutations() {
|
||
return this.getItemSorted(["mutation"])
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getSkills() {
|
||
// Utiliser filter et map pour éviter les duplications inutiles
|
||
const comp = this.items
|
||
.filter(item => item.type === "competence")
|
||
.map(item => {
|
||
const itemCopy = foundry.utils.duplicate(item);
|
||
const attrs = this.system.attributs;
|
||
|
||
itemCopy.system.attribut1total = itemCopy.system.niveau + (attrs[itemCopy.system.attribut1]?.value || 0);
|
||
itemCopy.system.attribut2total = itemCopy.system.niveau + (attrs[itemCopy.system.attribut2]?.value || 0);
|
||
itemCopy.system.attribut3total = itemCopy.system.niveau + (attrs[itemCopy.system.attribut3]?.value || 0);
|
||
|
||
if (itemCopy.system.niveau === 0) {
|
||
itemCopy.system.attribut1total -= 3;
|
||
itemCopy.system.attribut2total -= 3;
|
||
itemCopy.system.attribut3total -= 3;
|
||
}
|
||
|
||
itemCopy.system.attribut1label = attrs[itemCopy.system.attribut1]?.label || "";
|
||
itemCopy.system.attribut2label = attrs[itemCopy.system.attribut2]?.label || "";
|
||
itemCopy.system.attribut3label = attrs[itemCopy.system.attribut3]?.label || "";
|
||
|
||
return itemCopy;
|
||
});
|
||
|
||
HawkmoonUtility.sortArrayObjectsByName(comp);
|
||
return comp;
|
||
}
|
||
|
||
/* ----------------------- --------------------- */
|
||
addMember(actorId) {
|
||
let members = foundry.utils.duplicate(this.system.members)
|
||
members.push({ id: actorId })
|
||
this.update({ 'system.members': members })
|
||
}
|
||
async removeMember(actorId) {
|
||
let members = this.system.members.filter(it => it.id != actorId)
|
||
this.update({ 'system.members': members })
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getDefenseBase() {
|
||
return Math.max(this.system.attributs.tre.value, this.system.attributs.adr.value)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getVitesseBase() {
|
||
const idx = Math.min(this.system.attributs.adr.value, __vitesseBonus.length - 1)
|
||
return 5 + (__vitesseBonus[idx] ?? 0)
|
||
}
|
||
/* -------------------------------------------- */
|
||
getProtection() {
|
||
let equipProtection = 0
|
||
for (let armor of this.items) {
|
||
if (armor.type == "protection" && armor.system.equipped) {
|
||
equipProtection += Number(armor.system.protection)
|
||
}
|
||
}
|
||
if (equipProtection < 4) {
|
||
return 4 + equipProtection // Cas des boucliers + sans armure
|
||
}
|
||
return equipProtection // Uniquement la protection des armures + boucliers
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getCombatValues() {
|
||
if (this.type == "cellule") {
|
||
return {
|
||
initBase: 0,
|
||
initTotal: 0,
|
||
bonusDegats: 0,
|
||
bonusDegatsTotal: 0,
|
||
vitesseBase: 0,
|
||
vitesseTotal: 0,
|
||
defenseBase: 0,
|
||
protection: 0,
|
||
defenseTotal: 0
|
||
}
|
||
}
|
||
|
||
let combat = {
|
||
initBase: this.system.attributs.adr.value,
|
||
initTotal: this.system.attributs.adr.value + this.system.combat.initbonus,
|
||
bonusDegats: this.getBonusDegats(),
|
||
bonusDegatsTotal: this.getBonusDegats() + this.system.combat.bonusdegats,
|
||
vitesseBase: this.getVitesseBase(),
|
||
vitesseTotal: this.getVitesseBase() + this.system.combat.vitessebonus,
|
||
defenseBase: this.getDefenseBase(),
|
||
protection: this.getProtection(),
|
||
defenseTotal: this.getDefenseBase() + this.system.combat.defensebonus + this.getProtection() - this.getTotalAdversite() + (this.system.combat.defensetotale ? 3 : 0)
|
||
}
|
||
return combat
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
prepareBaseData() {
|
||
if (game.release.generation >= 14) {
|
||
super.prepareBaseData();
|
||
}
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async prepareData() {
|
||
super.prepareData();
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
prepareDerivedData() {
|
||
|
||
if (this.type == 'personnage') {
|
||
let talentBonus = this.getVigueurBonus()
|
||
let vigueur = Math.floor((this.system.attributs.pui.value + this.system.attributs.tre.value) / 2) + talentBonus + this.system.sante.vigueurmodifier
|
||
if (vigueur != this.system.sante.vigueur) {
|
||
this.update({ 'system.sante.vigueur': vigueur })
|
||
}
|
||
}
|
||
super.prepareDerivedData()
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
_preUpdate(changed, options, user) {
|
||
if (changed?.system?.sante?.etat && changed?.system?.sante?.etat != this.system.sante.etat) {
|
||
setTimeout(() => {
|
||
this.processCombativite(changed.system.sante)
|
||
}, 800)
|
||
}
|
||
super._preUpdate(changed, options, user);
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
_onUpdate(data, options, user) {
|
||
super._onUpdate(data, options, user);
|
||
}
|
||
/* -------------------------------------------- */
|
||
getItemById(id) {
|
||
let item = this.items.find(item => item.id == id);
|
||
if (item) {
|
||
item = foundry.utils.duplicate(item)
|
||
}
|
||
return item;
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async equipItem(itemId) {
|
||
let item = this.items.find(item => item.id == itemId)
|
||
if (item && item.system) {
|
||
let update = { _id: item.id, "system.equipped": !item.system.equipped }
|
||
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
|
||
}
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
editItemField(itemId, itemType, itemField, dataType, value) {
|
||
let item = this.items.find(item => item.id == itemId)
|
||
if (item) {
|
||
console.log("Item ", item, itemField, dataType, value)
|
||
if (dataType.toLowerCase() == "number") {
|
||
value = Number(value)
|
||
} else {
|
||
value = String(value)
|
||
}
|
||
let update = { _id: item.id, [`system.${itemField}`]: value };
|
||
this.updateEmbeddedDocuments("Item", [update])
|
||
}
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
checkAttribut(attribut, minLevel) {
|
||
let attr = Object.values(this.system.attributs).find(at => at.labelnorm == attribut.toLowerCase())
|
||
if (attr && attr.value >= minLevel) {
|
||
return { isValid: true, attr: foundry.utils.duplicate(attr) }
|
||
}
|
||
return { isValid: false }
|
||
}
|
||
/* -------------------------------------------- */
|
||
checkAttributOrCompetenceLevel(compName, minLevel) {
|
||
let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase() && i.system.niveau >= minLevel)
|
||
if (comp) {
|
||
return { isValid: true, item: foundry.utils.duplicate(comp) }
|
||
} else {
|
||
for (let attrKey in this.system.attributs) {
|
||
if (this.system.attributs[attrKey].label.toLowerCase() == compName.toLowerCase() && this.system.attributs[attrKey].value >= minLevel) {
|
||
return { isValid: true, item: foundry.utils.duplicate(this.system.attributs[attrKey]) }
|
||
}
|
||
}
|
||
}
|
||
return { isValid: false, warningMessage: `Prérequis insuffisant : la compétence/attribut ${compName} doit être de niveau ${minLevel} au minimum` }
|
||
}
|
||
/* -------------------------------------------- */
|
||
addCompetenceBonus(compName, bonus, baCost) {
|
||
let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase())
|
||
if (comp) {
|
||
comp = foundry.utils.duplicate(comp)
|
||
comp.system.bonus = bonus
|
||
comp.system.baCost = baCost
|
||
return { isValid: true, item: comp }
|
||
}
|
||
return { isValid: false, warningMessage: `Compétence ${compName} non trouvée` }
|
||
}
|
||
/* -------------------------------------------- */
|
||
checkIfCompetence(compName) {
|
||
let comp = this.items.find(i => i.type == "competence" && i.name.toLowerCase() == compName.toLowerCase())
|
||
if (comp) {
|
||
return { isValid: true, item: comp }
|
||
}
|
||
return { isValid: false }
|
||
}
|
||
/* -------------------------------------------- */
|
||
getVigueur() {
|
||
return this.system.sante.vigueur
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getVigueurBonus() {
|
||
let talents = this.items.filter(item => item.type == "talent" && item.system.isautomated)
|
||
let bonus = 0
|
||
for (let talent of talents) {
|
||
for (let auto of talent.system.automations) {
|
||
if (auto.eventtype == "bonus-permanent" && auto.bonusname == "vigueur") {
|
||
bonus += Number(auto.bonus || 0)
|
||
}
|
||
}
|
||
}
|
||
return bonus
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getBonneAventure() {
|
||
return this.system.bonneaventure.actuelle
|
||
}
|
||
/* -------------------------------------------- */
|
||
checkBonneAventure(cost) {
|
||
return (this.system.bonneaventure.actuelle >= cost)
|
||
}
|
||
/* -------------------------------------------- */
|
||
changeBonneAventure(value) {
|
||
let newBA = this.system.bonneaventure.actuelle
|
||
newBA += value
|
||
this.update({ 'system.bonneaventure.actuelle': newBA })
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getEclat() {
|
||
return this.system.eclat.value
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
changeEclat(value) {
|
||
let newE = this.system.eclat.value
|
||
newE += value
|
||
this.update({ 'system.eclat.value': newE })
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
compareName(a, b) {
|
||
if (a.name < b.name) {
|
||
return -1;
|
||
}
|
||
if (a.name > b.name) {
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getAttribute(attrKey) {
|
||
return this.system.attributs[attrKey]
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getBonusDegats() {
|
||
return 0;
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
changeEtatCombativite(value) {
|
||
if (value === "vaincu") {
|
||
value = 200
|
||
}
|
||
let sante = foundry.utils.duplicate(this.system.sante)
|
||
sante.etat += Number(value)
|
||
sante.etat = Math.max(sante.etat, 0)
|
||
sante.etat = Math.min(sante.etat, this.system.sante.nbcombativite)
|
||
this.update({ 'system.sante': sante })
|
||
if (sante.etat == this.system.sante.nbcombativite) {
|
||
ChatMessage.create({ content: `<strong>${this.name} est vaincu !</strong>` })
|
||
}
|
||
// Duplicated ! this.processCombativite(sante)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
processCombativite(sante) {
|
||
sante = sante || foundry.utils.duplicate(this.system.sante)
|
||
// Gestion des états affaibli et très affaibli
|
||
if (sante.etat == this.system.sante.nbcombativite - 2 || sante.etat == this.system.sante.nbcombativite - 1) {
|
||
if (sante.etat == this.system.sante.nbcombativite - 2 && this.items.find(item => item.type == "talent" && item.name.toLowerCase() == "encaissement")) {
|
||
ChatMessage.create({ content: `<strong>${this.name} ne subit pas les 2 adversités rouge grâce à Encaissement. Pensez à les ajouter à la fin de la scène !</strong>` })
|
||
} else if (sante.etat == this.system.sante.nbcombativite - 1 && this.items.find(item => item.type == "talent" && item.name.toLowerCase().includes("vaillant"))) {
|
||
ChatMessage.create({ content: `<strong>${this.name} ne subit pas les 2 adversités rouge grâce à Vaillant. Pensez à les ajouter à la fin de la scène !</strong>` })
|
||
} else {
|
||
ChatMessage.create({ content: `<strong>${this.name} subit 2 adversités rouge !</strong>` })
|
||
this.incDecAdversite("rouge", 2)
|
||
}
|
||
}
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async equipGear(equipmentId) {
|
||
let item = this.items.find(item => item.id == equipmentId);
|
||
if (item?.system?.data) {
|
||
let update = { _id: item.id, "system.equipped": !item.system.equipped };
|
||
await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity
|
||
}
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getSubActors() {
|
||
let subActors = [];
|
||
for (let id of this.system.subactors) {
|
||
subActors.push(foundry.utils.duplicate(game.actors.get(id)));
|
||
}
|
||
return subActors;
|
||
}
|
||
/* -------------------------------------------- */
|
||
async addSubActor(subActorId) {
|
||
let subActors = foundry.utils.duplicate(this.system.subactors);
|
||
subActors.push(subActorId);
|
||
await this.update({ 'system.subactors': subActors });
|
||
}
|
||
/* -------------------------------------------- */
|
||
async delSubActor(subActorId) {
|
||
let newArray = [];
|
||
for (let id of this.system.subactors) {
|
||
if (id != subActorId) {
|
||
newArray.push(id);
|
||
}
|
||
}
|
||
await this.update({ 'system.subactors': newArray });
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getTotalAdversite() {
|
||
return this.system.adversite.bleue + this.system.adversite.rouge + this.system.adversite.noire
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async incDecAdversite(adv, incDec = 0) {
|
||
let adversite = foundry.utils.duplicate(this.system.adversite)
|
||
adversite[adv] += Number(incDec)
|
||
adversite[adv] = Math.max(adversite[adv], 0)
|
||
adversite[adv] = Math.min(adversite[adv], 20)
|
||
this.update({ 'system.adversite': adversite })
|
||
}
|
||
/* -------------------------------------------- */
|
||
async incDecQuantity(objetId, incDec = 0) {
|
||
let objetQ = this.items.get(objetId)
|
||
if (objetQ) {
|
||
let newQ = objetQ.system.quantite + incDec
|
||
newQ = Math.max(newQ, 0)
|
||
await this.updateEmbeddedDocuments('Item', [{ _id: objetQ.id, 'system.quantite': newQ }]); // pdates one EmbeddedEntity
|
||
}
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
computeRichesse() {
|
||
let valueSC = 0
|
||
for (let monnaie of this.items) {
|
||
if (monnaie.type == "monnaie") {
|
||
valueSC += Number(monnaie.system.prixsc) * Number(monnaie.system.quantite)
|
||
}
|
||
}
|
||
return HawkmoonUtility.computeMonnaieDetails(valueSC)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
computeValeurEquipement() {
|
||
let valueSC = 0
|
||
for (let equip of this.items) {
|
||
if (equip.type == "equipement" || equip.type == "arme" || equip.type == "protection") {
|
||
valueSC += Number(equip.system.prixsc) * Number(equip.system.quantite ?? 1)
|
||
valueSC += (Number(equip.system.prixca) * Number(equip.system.quantite ?? 1)) * 20
|
||
valueSC += (Number(equip.system.prixpo) * Number(equip.system.quantite ?? 1)) * 400
|
||
}
|
||
}
|
||
return HawkmoonUtility.computeMonnaieDetails(valueSC)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getCompetence(compId) {
|
||
return this.items.get(compId)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async setPredilectionUsed(compId, predIdx) {
|
||
let comp = this.items.get(compId)
|
||
let pred = foundry.utils.duplicate(comp.system.predilections)
|
||
pred[predIdx].used = true
|
||
await this.updateEmbeddedDocuments('Item', [{ _id: compId, 'system.predilections': pred }])
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getInitiativeScore() {
|
||
let init = this.getFlag("world", "last-initiative")
|
||
return init || -1
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getBestAttackValue() {
|
||
let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped)
|
||
let maxOff = 0
|
||
let bestArme
|
||
for (let arme of attackList) {
|
||
if (arme.type == "arme") {
|
||
arme = this.prepareArme(arme)
|
||
}
|
||
if (arme.system.totalOffensif > maxOff) {
|
||
maxOff = arme.system.totalOffensif
|
||
bestArme = foundry.utils.duplicate(arme)
|
||
}
|
||
}
|
||
return bestArme
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getBestDefenseValue() {
|
||
let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped)
|
||
let maxDef = 0
|
||
let bestArme
|
||
for (let arme of defenseList) {
|
||
if (arme.type == "arme") {
|
||
arme = this.prepareArme(arme)
|
||
}
|
||
if (arme.system.totalDefensif > maxDef) {
|
||
maxDef = arme.system.totalDefensif
|
||
bestArme = foundry.utils.duplicate(arme)
|
||
}
|
||
}
|
||
return bestArme
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
searchRelevantTalents(competence) {
|
||
let talents = []
|
||
|
||
for (let talent of this.items) {
|
||
if (talent.type == "talent" && talent.system.isautomated && talent.system.automations.length > 0) {
|
||
for (let auto of talent.system.automations) {
|
||
if (auto.eventtype === "prepare-roll") {
|
||
if (auto.competence.toLowerCase() == competence.name.toLowerCase()) {
|
||
talent = foundry.utils.duplicate(talent)
|
||
talent.system.bonus = auto.bonus
|
||
talent.system.baCost = auto.baCost
|
||
talents.push(talent)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return talents
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
buildListeAdversites() {
|
||
return []
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
getCommonRollData(attrKey = undefined, compId = undefined, compName = undefined) {
|
||
let rollData = HawkmoonUtility.getBasicRollData()
|
||
rollData.alias = this.name
|
||
rollData.actorImg = this.img
|
||
rollData.actorId = this.id
|
||
rollData.tokenId = this.token?.id
|
||
rollData.img = this.img
|
||
rollData.attributs = HawkmoonUtility.getAttributs()
|
||
rollData.maitriseId = "none"
|
||
rollData.nbEclat = this.system.eclat.value
|
||
rollData.nbBA = this.system.bonneaventure.actuelle
|
||
rollData.nbAdversites = this.getTotalAdversite()
|
||
rollData.talents = []
|
||
rollData.attrKey2 = "none"
|
||
rollData.coupDevastateur = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup dévastateur" && !it.system.used)
|
||
rollData.hasAmbidextre = this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "ambidextre")
|
||
rollData.hasFeinte = this.system.bonneaventure.actuelle > 0 && this.items.find(it => it.type == "talent" && it.name.toLowerCase() == "feinte")
|
||
rollData.isMonte = this.system.combat.monte
|
||
rollData.config = game.system.hawkmoon.config
|
||
|
||
if (attrKey) {
|
||
rollData.attrKey = attrKey
|
||
if (attrKey != "tochoose") {
|
||
rollData.actionImg = "systems/fvtt-hawkmoon-cyd/assets/icons/" + this.system.attributs[attrKey].labelnorm + ".webp"
|
||
rollData.attr = foundry.utils.duplicate(this.system.attributs[attrKey])
|
||
}
|
||
}
|
||
if (compId) {
|
||
rollData.competence = foundry.utils.duplicate(this.items.get(compId) || {})
|
||
let maitrises = [{ key: "none", label: "Aucune" }]
|
||
rollData.competence.system.predilections.forEach(function (item) {
|
||
if (item.maitrise) {
|
||
maitrises.push({ key: item.id, label: item.name });
|
||
}
|
||
})
|
||
rollData.maitrises = maitrises // rollData.competence.system.predilections.filter(p => p.maitrise)
|
||
rollData.actionImg = rollData.competence?.img
|
||
rollData.talents = this.searchRelevantTalents(rollData.competence)
|
||
}
|
||
if (compName) {
|
||
rollData.competence = foundry.utils.duplicate(this.items.find(item => item.name.toLowerCase() == compName.toLowerCase()) || {})
|
||
rollData.actionImg = rollData.competence?.img
|
||
}
|
||
return rollData
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async rollAttribut(attrKey, isInit = false) {
|
||
let rollData = this.getCommonRollData(attrKey)
|
||
rollData.isInit = isInit
|
||
if (isInit) {
|
||
rollData.multiplier = 1
|
||
rollData.initbonus = this.system.combat.initbonus ?? 0
|
||
} else {
|
||
rollData.multiplier = 2 // fallback si attrKey2 vaut l'attribut principal
|
||
rollData.hasAttr2 = true
|
||
rollData.attrKey2 = attrKey // même attribut par défaut = ×2
|
||
rollData.selectableAttributes = this.system.attributs
|
||
}
|
||
await HawkmoonRollDialog.create(this, rollData)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async rollCompetence(attrKey, compId) {
|
||
let rollData = this.getCommonRollData(attrKey, compId)
|
||
rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode
|
||
console.log("RollDatra", rollData)
|
||
await HawkmoonRollDialog.create(this, rollData)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async rollArmeOffensif(armeId) {
|
||
let arme = this.items.get(armeId)
|
||
if (!arme.system.equipped) {
|
||
ui.notifications.warn("Cette arme doit être équipée pour pouvoir attaquer !")
|
||
return
|
||
}
|
||
if (arme.type == "arme") {
|
||
arme = this.prepareArme(arme)
|
||
}
|
||
if (!arme.system.competence) {
|
||
ui.notifications.warn("Aucune compétence trouvée pour cette arme !")
|
||
return
|
||
}
|
||
let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id)
|
||
rollData.arme = arme
|
||
rollData.isCombat = true
|
||
rollData.isTir = arme.system.isDistance || false
|
||
HawkmoonUtility.updateWithTarget(rollData)
|
||
console.log("ARME!", rollData)
|
||
await HawkmoonRollDialog.create(this, rollData)
|
||
}
|
||
/* -------------------------------------------- */
|
||
async rollAssommer() {
|
||
let rollData = this.getCommonRollData("pui", undefined, "Filouterie")
|
||
rollData.assomer = true
|
||
rollData.conditionsCommunes = true
|
||
HawkmoonUtility.updateWithTarget(rollData)
|
||
await HawkmoonRollDialog.create(this, rollData)
|
||
}
|
||
/* -------------------------------------------- */
|
||
async rollCoupBas() {
|
||
let rollData = this.getCommonRollData("pui", undefined, "Mêlée")
|
||
rollData.coupBas = true
|
||
rollData.conditionsCommunes = true
|
||
HawkmoonUtility.updateWithTarget(rollData)
|
||
await HawkmoonRollDialog.create(this, rollData)
|
||
}
|
||
/* -------------------------------------------- */
|
||
async rollImmobiliser() {
|
||
let rollData = this.getCommonRollData("pui", undefined, "Mêlée")
|
||
rollData.immobiliser = true
|
||
rollData.conditionsCommunes = true
|
||
rollData.cibleconsciente = true
|
||
HawkmoonUtility.updateWithTarget(rollData)
|
||
await HawkmoonRollDialog.create(this, rollData)
|
||
}
|
||
/* -------------------------------------------- */
|
||
async rollRepousser() {
|
||
let rollData = this.getCommonRollData("pui", undefined, "Mêlée")
|
||
rollData.repousser = true
|
||
rollData.conditionsCommunes = true
|
||
rollData.cibleconsciente = true
|
||
HawkmoonUtility.updateWithTarget(rollData)
|
||
await HawkmoonRollDialog.create(this, rollData)
|
||
}
|
||
/* -------------------------------------------- */
|
||
async rollDesengager() {
|
||
let rollData = this.getCommonRollData("adr", undefined, "Mouvements")
|
||
rollData.desengager = true
|
||
rollData.conditionsCommunes = true
|
||
HawkmoonUtility.updateWithTarget(rollData)
|
||
await HawkmoonRollDialog.create(this, rollData)
|
||
}
|
||
|
||
/* -------------------------------------------- */
|
||
async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) {
|
||
const arme = this.items.get(armeId);
|
||
if (!arme) {
|
||
ui.notifications.warn("Arme non trouvée !");
|
||
return;
|
||
}
|
||
|
||
if (!arme.system?.equipped) {
|
||
ui.notifications.warn("Cette arme doit être équipée pour pouvoir infliger des dégâts !");
|
||
return;
|
||
}
|
||
|
||
const preparedArme = arme.type === "arme" ? this.prepareArme(arme) : arme;
|
||
console.log("DEGATS", preparedArme, targetVigueur, rollDataInput);
|
||
|
||
let roll;
|
||
let bonus = 0;
|
||
let bonus2 = 0;
|
||
|
||
if (rollDataInput?.applyCoupDevastateur) {
|
||
bonus2 = Math.floor(this.system.attributs.pui.value / 2);
|
||
const talent = this.items.find(item => item.type === "talent" && item.name.toLowerCase() === "coup dévastateur");
|
||
if (talent) {
|
||
await this.updateEmbeddedDocuments('Item', [{ _id: talent.id, 'system.used': true }]);
|
||
}
|
||
}
|
||
|
||
if (rollDataInput?.isHeroique) {
|
||
if (rollDataInput?.attaqueCharge) {
|
||
bonus = 5;
|
||
}
|
||
if (rollDataInput?.chargeCavalerie) {
|
||
bonus = 6;
|
||
}
|
||
roll = await new Roll("2d10rr10+" + preparedArme.system.totalDegats + "+" + bonus + "+" + bonus2).roll();
|
||
} else {
|
||
if (rollDataInput?.attaqueCharge) {
|
||
bonus = 3;
|
||
}
|
||
if (rollDataInput?.chargeCavalerie) {
|
||
bonus = 4;
|
||
}
|
||
roll = await new Roll("1d10+" + preparedArme.system.totalDegats + "+" + bonus + "+" + bonus2).roll();
|
||
}
|
||
await HawkmoonUtility.showDiceSoNice(roll, game.settings.get("core", "rollMode"));
|
||
let nbEtatPerdus = 0
|
||
if (targetVigueur) {
|
||
nbEtatPerdus = Math.floor(roll.total / targetVigueur)
|
||
}
|
||
//console.log(roll)
|
||
let rollData = {
|
||
arme: preparedArme,
|
||
finalResult: roll.total,
|
||
formula: roll.formula,
|
||
alias: this.name,
|
||
actorImg: this.img,
|
||
actorId: this.id,
|
||
defenderTokenId: rollDataInput?.defenderTokenId,
|
||
actionImg: preparedArme.img,
|
||
targetVigueur: targetVigueur,
|
||
nbEtatPerdus: nbEtatPerdus
|
||
};
|
||
HawkmoonUtility.createChatWithRollMode(rollData.alias, {
|
||
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-hawkmoon-cyd/templates/chat-degats-result.hbs`, rollData)
|
||
})
|
||
|
||
if (rollDataInput?.defenderTokenId && nbEtatPerdus) {
|
||
HawkmoonUtility.applyCombativite(rollDataInput, nbEtatPerdus)
|
||
}
|
||
|
||
}
|
||
}
|