2020-12-12 21:58:44 +01:00
import { ChatUtility } from "./chat-utility.js" ;
2022-07-22 21:38:15 +02:00
import { ENTITE _INCARNE , ENTITE _NONINCARNE , HIDE _DICE , SYSTEM _RDD , SYSTEM _SOCKET _ID } from "./constants.js" ;
2022-07-03 15:32:20 +02:00
import { Grammar } from "./grammar.js" ;
2020-12-12 21:58:44 +01:00
import { RdDItemArme } from "./item-arme.js" ;
import { RdDItemCompetence } from "./item-competence.js" ;
2021-01-13 23:47:12 +01:00
import { RdDItemCompetenceCreature } from "./item-competencecreature.js" ;
2020-12-12 21:58:44 +01:00
import { Misc } from "./misc.js" ;
2020-12-16 23:02:15 +01:00
import { RdDBonus } from "./rdd-bonus.js" ;
2020-12-12 21:58:44 +01:00
import { RdDResolutionTable } from "./rdd-resolution-table.js" ;
import { RdDRoll } from "./rdd-roll.js" ;
2020-12-17 12:29:54 +01:00
import { RdDRollTables } from "./rdd-rolltables.js" ;
2021-01-26 19:43:37 +01:00
import { ReglesOptionelles } from "./regles-optionelles.js" ;
2022-09-17 22:36:43 +02:00
import { STATUSES } from "./status-effects.js" ;
2020-12-12 21:58:44 +01:00
2021-02-27 22:59:10 +01:00
/* -------------------------------------------- */
const premierRoundInit = [
2021-06-28 16:08:45 +02:00
{ pattern : 'hast' , init : 5.90 } ,
{ pattern : 'lance' , init : 5.85 } ,
{ pattern : 'baton' , init : 5.80 } ,
{ pattern : 'doubledragonne' , init : 5.75 } ,
{ pattern : 'esparlongue' , init : 5.70 } ,
{ pattern : 'epeedragonne' , init : 5.65 } ,
{ pattern : 'epeebatarde' , init : 5.60 } ,
{ pattern : 'epeecyane' , init : 5.55 } ,
{ pattern : 'epeesorde' , init : 5.50 } ,
{ pattern : 'grandehache' , init : 5.45 } ,
{ pattern : 'bataille' , init : 5.40 } ,
{ pattern : 'epeegnome' , init : 5.35 } ,
{ pattern : 'masse' , init : 5.30 } ,
{ pattern : 'gourdin' , init : 5.25 } ,
2022-07-03 15:32:20 +02:00
{ pattern : 'fleau' , init : 5.20 } ,
2021-06-28 16:08:45 +02:00
{ pattern : 'dague' , init : 5.15 } ,
{ pattern : 'autre' , init : 5.10 } ,
2021-02-27 22:59:10 +01:00
] ;
2021-02-09 09:18:52 +01:00
/* -------------------------------------------- */
2021-02-25 02:13:39 +01:00
export class RdDCombatManager extends Combat {
static init ( ) {
/* -------------------------------------------- */
Hooks . on ( "getCombatTrackerEntryContext" , ( html , options ) => {
RdDCombatManager . pushInitiativeOptions ( html , options ) ;
} ) ;
2021-06-30 01:01:24 +02:00
Hooks . on ( "preDeleteCombat" , ( combat , html , id ) => {
combat . onPreDeleteCombat ( )
} ) ;
2021-02-25 02:13:39 +01:00
}
2021-02-09 09:18:52 +01:00
/* -------------------------------------------- */
cleanItemUse ( ) {
2021-02-25 02:13:39 +01:00
for ( let turn of this . turns ) {
2021-02-09 09:18:52 +01:00
turn . actor . resetItemUse ( )
}
}
2021-02-25 02:13:39 +01:00
2021-02-17 11:16:27 +01:00
/* -------------------------------------------- */
2021-06-30 01:01:24 +02:00
async nextRound ( ) {
this . cleanItemUse ( ) ;
await this . finDeRound ( ) ;
return await super . nextRound ( ) ;
}
/* -------------------------------------------- */
async onPreDeleteCombat ( ) {
await this . finDeRound ( { terminer : true } ) ;
}
/* -------------------------------------------- */
async finDeRound ( options = { terminer : false } ) {
2022-09-07 09:01:23 +02:00
for ( let combatant of this . combatants ) {
2021-03-14 19:04:35 +01:00
if ( combatant . actor ) {
2021-06-30 01:01:24 +02:00
await combatant . actor . finDeRound ( options ) ;
2021-03-14 14:22:25 +01:00
}
2021-03-14 19:04:35 +01:00
else {
2021-03-14 14:22:25 +01:00
ui . notifications . warn ( ` Le combatant ${ combatant . name } n'est pas associé à un acteur! ` )
}
2021-02-17 11:16:27 +01:00
}
}
2021-02-09 09:18:52 +01:00
2021-02-25 02:13:39 +01:00
/************************************************************************************/
async rollInitiative ( ids , formula = undefined , messageOptions = { } ) {
2022-09-07 09:01:23 +02:00
console . log ( ` ${ game . system . title } | Combat.rollInitiative() ` , ids , formula , messageOptions ) ;
2022-09-07 18:47:56 +02:00
2021-02-25 02:13:39 +01:00
ids = typeof ids === "string" ? [ ids ] : ids ;
const currentId = this . combatant . _id ;
// calculate initiative
for ( let cId = 0 ; cId < ids . length ; cId ++ ) {
2021-12-18 09:45:36 +01:00
const combatant = this . combatants . get ( ids [ cId ] ) ;
2022-07-03 15:32:20 +02:00
let rollFormula = formula ? ? RdDCombatManager . formuleInitiative ( 2 , 10 , 0 , 0 ) ;
if ( ! formula ) {
2022-07-14 22:32:57 +02:00
if ( combatant . actor . type == 'creature' || combatant . actor . type == 'entite' ) {
const competence = combatant . actor . items . find ( it => it . system . iscombat )
2022-07-03 15:32:20 +02:00
if ( competence ) {
2022-07-14 22:32:57 +02:00
rollFormula = RdDCombatManager . formuleInitiative ( 2 , competence . system . carac _value , competence . system . niveau , 0 ) ;
2021-02-25 02:13:39 +01:00
}
} else {
2022-09-07 18:47:56 +02:00
const armeCombat = combatant . actor . itemTypes [ 'arme' ] . find ( it => it . system . equipe )
2022-07-14 22:32:57 +02:00
const compName = ( armeCombat == undefined ) ? "Corps à corps" : armeCombat . system . competence ;
const competence = RdDItemCompetence . findCompetence ( combatant . actor . items , compName ) ;
2022-07-03 15:32:20 +02:00
if ( competence ) {
2022-07-14 22:32:57 +02:00
const carac = combatant . actor . system . carac [ competence . system . defaut _carac ] . value ;
const niveau = competence . system . niveau ;
2022-09-07 00:09:17 +02:00
const bonusEcaille = ( armeCombat ? . system . magique ) ? armeCombat . system . ecaille _efficacite : 0 ;
2022-07-03 15:32:20 +02:00
rollFormula = RdDCombatManager . formuleInitiative ( 2 , carac , niveau , bonusEcaille ) ;
2021-02-25 02:13:39 +01:00
}
}
}
//console.log("Combatat", c);
2021-04-16 22:18:36 +02:00
const roll = combatant . getInitiativeRoll ( rollFormula ) ;
2021-12-18 09:45:36 +01:00
if ( ! roll . total ) {
roll . evaluate ( { async : false } ) ;
}
2021-02-25 02:13:39 +01:00
if ( roll . total <= 0 ) roll . total = 0.00 ;
2021-12-18 09:45:36 +01:00
console . log ( "Compute init for" , rollFormula , roll . total , combatant ) ;
let id = combatant . _id || combatant . id ;
await this . updateEmbeddedDocuments ( "Combatant" , [ { _id : id , initiative : roll . total } ] ) ;
2021-02-25 02:13:39 +01:00
// Send a chat message
let rollMode = messageOptions . rollMode || game . settings . get ( "core" , "rollMode" ) ;
let messageData = mergeObject (
{
speaker : {
scene : canvas . scene . _id ,
2021-04-16 22:18:36 +02:00
actor : combatant . actor ? combatant . actor . _id : null ,
token : combatant . token . _id ,
alias : combatant . token . name ,
2021-02-25 02:13:39 +01:00
sound : CONFIG . sounds . dice ,
} ,
2021-04-16 22:18:36 +02:00
flavor : ` ${ combatant . token . name } a fait son jet d'Initiative ( ${ messageOptions . initInfo } )
2021-02-25 02:13:39 +01:00
< br >
` ,
} ,
messageOptions
) ;
roll . toMessage ( messageData , { rollMode , create : true } ) ;
RdDCombatManager . processPremierRoundInit ( ) ;
}
return this ;
} ;
2022-07-03 15:32:20 +02:00
static formuleInitiative ( rang , carac , niveau , bonusMalus ) {
return ` ${ rang } +( ( ${ RdDCombatManager . calculInitiative ( niveau , carac , bonusMalus ) } )/100) ` ;
}
2021-02-25 02:13:39 +01:00
/* -------------------------------------------- */
static calculInitiative ( niveau , caracValue , bonusEcaille = 0 ) {
let base = niveau + Math . floor ( caracValue / 2 ) ;
base += bonusEcaille ;
return "1d6" + ( base >= 0 ? "+" : "" ) + base ;
}
/* -------------------------------------------- */
2022-07-03 15:32:20 +02:00
/** Retourne une liste triée d'actions d'armes avec le split arme1 main / arme 2 main */
static listActionsArmes ( armes , competences , carac ) {
2021-02-25 02:13:39 +01:00
// Gestion des armes 1/2 mains
2022-07-03 15:32:20 +02:00
let actionsArme = [ ] ;
2022-06-12 08:17:59 +02:00
for ( const arme of armes ) {
2022-09-06 23:52:21 +02:00
let action = duplicate ( arme )
2022-07-14 22:32:57 +02:00
if ( action . system . equipe ) {
let compData = competences . find ( c => c . name == action . system . competence )
2021-05-22 02:19:22 +02:00
2022-07-03 15:32:20 +02:00
actionsArme . push ( action ) ;
action . action = 'attaque' ;
2022-07-14 22:32:57 +02:00
action . system . dommagesReels = Number ( action . system . dommages ) ;
2022-09-06 23:52:21 +02:00
action . system . niveau = compData . system . niveau ;
2022-07-14 22:32:57 +02:00
action . system . initiative = RdDCombatManager . calculInitiative ( compData . system . niveau , carac [ compData . system . defaut _carac ] . value ) ;
2021-02-25 02:13:39 +01:00
// Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence
2022-07-14 22:32:57 +02:00
if ( action . system . unemain && ! action . system . deuxmains ) {
action . system . mainInfo = "(1m)" ;
} else if ( ! action . system . unemain && action . system . deuxmains ) {
action . system . mainInfo = "(2m)" ;
} else if ( action . system . unemain && action . system . deuxmains ) {
action . system . mainInfo = "(1m)" ;
const comp2m = action . system . competence . replace ( " 1 main" , " 2 mains" ) ; // Replace !
const comp = competences . find ( c => c . name == comp2m )
2021-11-20 01:19:29 +01:00
2022-07-03 15:32:20 +02:00
const arme2main = duplicate ( action ) ;
2022-07-14 22:32:57 +02:00
arme2main . system . mainInfo = "(2m)" ;
arme2main . system . niveau = comp . system . niveau ;
arme2main . system . competence = comp2m ;
arme2main . system . initiative = RdDCombatManager . calculInitiative ( arme2main . system . niveau , carac [ comp . system . defaut _carac ] . value ) ;
2022-07-03 15:32:20 +02:00
actionsArme . push ( arme2main ) ;
2022-07-14 22:32:57 +02:00
const containsSlash = action . system . dommages . includes ( "/" ) ;
2021-11-20 01:19:29 +01:00
if ( containsSlash ) {
2022-07-14 22:32:57 +02:00
const tableauDegats = action . system . dommages . split ( "/" ) ;
action . system . dommagesReels = Number ( tableauDegats [ 0 ] ) ;
arme2main . system . dommagesReels = Number ( tableauDegats [ 1 ] ) ;
2021-11-20 01:19:29 +01:00
}
else {
2022-07-03 15:32:20 +02:00
ui . notifications . info ( "Les dommages de l'arme à 1/2 mains " + action . name + " ne sont pas corrects (ie sous la forme X/Y)" ) ;
2021-11-20 01:19:29 +01:00
}
2021-02-25 02:13:39 +01:00
}
}
}
2022-07-09 09:04:35 +02:00
return actionsArme . sort ( Misc . ascending ( armeData => armeData . name + ( armeData . system . mainInfo ? ? '' ) ) ) ;
2022-07-03 15:32:20 +02:00
}
2022-09-20 00:12:25 +02:00
static listActionsCreature ( competences ) {
return competences . filter ( it => RdDItemCompetenceCreature . isCompetenceAttaque ( it ) )
. map ( it => RdDItemCompetenceCreature . toActionArme ( it ) ) ;
}
2022-07-03 15:32:20 +02:00
static listActionsPossessions ( actor ) {
return RdDCombatManager . _indexActions ( actor . getPossessions ( ) . map ( p =>
{
return {
name : p . name ,
action : 'conjurer' ,
2022-09-07 18:47:56 +02:00
system : {
2022-07-03 15:32:20 +02:00
competence : p . name ,
2022-09-07 00:09:17 +02:00
possessionid : p . system . possessionid ,
2022-07-03 15:32:20 +02:00
}
}
} ) ) ;
2021-02-25 02:13:39 +01:00
}
/* -------------------------------------------- */
2022-07-03 15:32:20 +02:00
static listActionsCombat ( combatant ) {
const actor = combatant . actor ;
let actions = RdDCombatManager . listActionsPossessions ( actor ) ;
if ( actions . length > 0 ) {
return actions ;
2021-03-14 14:22:25 +01:00
}
2022-07-03 15:32:20 +02:00
if ( actor . isCreature ( ) ) {
2022-09-20 00:12:25 +02:00
actions = actions . concat ( RdDCombatManager . listActionsCreature ( actor . itemTypes [ 'competencecreature' ] ) ) ;
2021-02-25 02:13:39 +01:00
} else {
// Recupération des items 'arme'
2022-09-20 00:12:25 +02:00
const armes = actor . itemTypes [ 'arme' ] . filter ( it => RdDItemArme . isArmeUtilisable ( it ) )
2021-11-20 00:42:04 +01:00
//.concat(RdDItemArme.empoignade())
. concat ( RdDItemArme . mainsNues ( ) ) ;
2021-02-25 02:13:39 +01:00
2022-09-20 00:12:25 +02:00
const competences = actor . itemTypes [ 'competence' ] ;
2022-09-07 00:09:17 +02:00
actions = actions . concat ( RdDCombatManager . listActionsArmes ( armes , competences , actor . system . carac ) ) ;
2021-05-22 02:19:22 +02:00
2022-09-07 00:09:17 +02:00
if ( actor . system . attributs . hautrevant . value ) {
2022-09-07 18:47:56 +02:00
actions . push ( { name : "Draconic" , action : 'haut-reve' , system : { initOnly : true , competence : "Draconic" } } ) ;
2021-04-03 03:04:48 +02:00
}
2021-02-25 02:13:39 +01:00
}
2022-07-03 15:32:20 +02:00
return RdDCombatManager . _indexActions ( actions ) ;
}
static _indexActions ( actions ) {
2021-02-25 02:13:39 +01:00
for ( let index = 0 ; index < actions . length ; index ++ ) {
actions [ index ] . index = index ;
}
return actions ;
}
/* -------------------------------------------- */
static processPremierRoundInit ( ) {
// Check if we have the whole init !
2021-11-26 00:45:21 +01:00
if ( Misc . isUniqueConnectedGM ( ) && game . combat . current . round == 1 ) {
2022-09-07 09:01:23 +02:00
let initMissing = game . combat . combatants . find ( it => ! it . initiative ) ;
2021-02-25 02:13:39 +01:00
if ( ! initMissing ) { // Premier round !
2022-09-07 09:01:23 +02:00
for ( let combatant of game . combat . combatants ) {
2022-07-03 15:32:20 +02:00
let action = combatant . initiativeData ? . arme ;
2021-02-25 02:13:39 +01:00
//console.log("Parsed !!!", combatant, initDone, game.combat.current, arme);
2022-07-03 15:32:20 +02:00
if ( action && action . type == "arme" ) {
2021-02-25 02:13:39 +01:00
for ( let initData of premierRoundInit ) {
2022-09-07 00:09:17 +02:00
if ( Grammar . toLowerCaseNoAccentNoSpace ( action . system . initpremierround ) . includes ( initData . pattern ) ) {
2021-02-25 02:13:39 +01:00
let msg = ` <h4>L'initiative de ${ combatant . actor . name } a été modifiée !</h4>
< hr >
< div >
2022-07-03 15:32:20 +02:00
Etant donné son $ { action . name } , son initative pour ce premier round est désormais de $ { initData . init } .
2021-02-25 02:13:39 +01:00
< / d i v > `
ChatMessage . create ( { content : msg } ) ;
game . combat . setInitiative ( combatant . _id , initData . init ) ;
}
}
}
}
}
}
}
/* -------------------------------------------- */
static incDecInit ( combatantId , incDecValue ) {
2021-12-18 09:45:36 +01:00
const combatant = game . combat . combatants . get ( combatantId ) ;
2021-02-25 02:13:39 +01:00
let initValue = combatant . initiative + incDecValue ;
game . combat . setInitiative ( combatantId , initValue ) ;
}
/* -------------------------------------------- */
static pushInitiativeOptions ( html , options ) {
for ( let i = 0 ; i < options . length ; i ++ ) {
let option = options [ i ] ;
if ( option . name == 'COMBAT.CombatantReroll' ) { // Replace !
option . name = "Sélectionner l'initiative..." ;
option . condition = true ;
option . icon = '<i class="far fa-question-circle"></i>' ;
option . callback = target => {
RdDCombatManager . displayInitiativeMenu ( html , target . data ( 'combatant-id' ) ) ;
}
}
}
options = [
{ name : "Incrémenter initiative" , condition : true , icon : '<i class="fas fa-plus"></i>' , callback : target => { RdDCombatManager . incDecInit ( target . data ( 'combatant-id' ) , + 0.01 ) ; } } ,
{ name : "Décrémenter initiative" , condition : true , icon : '<i class="fas fa-minus"></i>' , callback : target => { RdDCombatManager . incDecInit ( target . data ( 'combatant-id' ) , - 0.01 ) ; } }
] . concat ( options ) ;
}
/* -------------------------------------------- */
2022-07-03 15:32:20 +02:00
static rollInitiativeAction ( combatantId , action ) {
2021-12-18 09:45:36 +01:00
const combatant = game . combat . combatants . get ( combatantId ) ;
2021-03-14 14:22:25 +01:00
if ( combatant . actor == undefined ) {
ui . notifications . warn ( ` Le combatant ${ combatant . name } n'est pas associé à un acteur, impossible de déterminer ses actions de combat! ` )
return [ ] ;
}
2021-02-25 02:13:39 +01:00
let initInfo = "" ;
let initOffset = 0 ;
let caracForInit = 0 ;
let compNiveau = 0 ;
2021-04-16 22:18:36 +02:00
let compData = { name : "Aucune" } ;
2021-03-14 14:22:25 +01:00
if ( combatant . actor . getSurprise ( ) == "totale" ) {
2021-02-25 02:13:39 +01:00
initOffset = - 1 ; // To force 0
initInfo = "Surprise Totale"
2021-03-14 14:22:25 +01:00
} else if ( combatant . actor . getSurprise ( ) == "demi" ) {
2021-02-25 02:13:39 +01:00
initOffset = 0 ;
initInfo = "Demi Surprise"
2022-07-03 15:32:20 +02:00
} else if ( action . action == 'conjurer' ) {
initOffset = 10 ;
caracForInit = combatant . actor . getReveActuel ( ) ;
initInfo = "Possession"
2022-07-22 00:36:16 +02:00
} else if ( action . action == 'autre' ) {
2021-02-25 02:13:39 +01:00
initOffset = 2 ;
initInfo = "Autre Action"
2022-07-03 15:32:20 +02:00
} else if ( action . action == 'haut-reve' ) {
2021-06-28 16:08:45 +02:00
initOffset = 9 ;
2021-02-25 02:13:39 +01:00
initInfo = "Draconic"
} else {
2022-09-20 00:09:45 +02:00
compData = RdDItemCompetence . findCompetence ( combatant . actor . items , action . system . competence ) ;
2022-06-12 09:46:58 +02:00
compNiveau = compData . system . niveau ;
2022-09-20 00:12:25 +02:00
initInfo = action . name + " / " + action . system . competence ;
if ( combatant . actor . type == 'creature' || combatant . actor . type == 'entite' ) {
caracForInit = compData . system . carac _value ;
} else {
caracForInit = combatant . actor . system . carac [ compData . system . defaut _carac ] . value ;
2021-02-25 02:13:39 +01:00
}
2022-09-20 00:12:25 +02:00
initOffset = RdDCombatManager . _baseInitOffset ( compData . system . categorie , action ) ;
2021-02-25 02:13:39 +01:00
}
2022-07-03 15:32:20 +02:00
2021-03-14 14:22:25 +01:00
let malus = combatant . actor . getEtatGeneral ( ) ; // Prise en compte état général
2021-02-25 02:13:39 +01:00
// Cas des créatures et entités vs personnages
2022-07-03 15:32:20 +02:00
let rollFormula = RdDCombatManager . formuleInitiative ( initOffset , caracForInit , compNiveau , malus ) ;
2021-02-25 02:13:39 +01:00
// Garder la trace de l'arme/compétence utilisée pour l'iniative
2022-07-03 15:32:20 +02:00
combatant . initiativeData = { arme : action } // pour reclasser l'init au round 0
2021-02-25 02:13:39 +01:00
game . combat . rollInitiative ( combatantId , rollFormula , { initInfo : initInfo } ) ;
}
2022-10-05 20:00:42 +02:00
/* -------------------------------------------- */
2021-06-28 16:08:45 +02:00
static _baseInitOffset ( categorie , arme ) {
if ( categorie == "tir" ) { // Offset de principe pour les armes de jet
return 8 ;
}
if ( categorie == "lancer" ) { // Offset de principe pour les armes de jet
return 7 ;
}
2022-09-07 00:09:17 +02:00
switch ( arme . system . cac ) {
2022-09-20 00:12:25 +02:00
case "empoignade" :
return 3 ;
case "pugilat" :
case "naturelle" :
return 4 ;
2021-06-28 16:08:45 +02:00
}
return 5 ;
}
2021-02-25 02:13:39 +01:00
/* -------------------------------------------- */
static displayInitiativeMenu ( html , combatantId ) {
2021-02-27 22:59:10 +01:00
console . log ( "Combatant ; " , combatantId ) ;
2021-12-18 09:45:36 +01:00
const combatant = game . combat . combatants . get ( combatantId ) ;
2022-07-03 15:32:20 +02:00
if ( ! ( combatant ? . actor ) ) {
ui . notifications . warn ( ` Le combatant ${ combatant . name ? ? combatantId } n'est pas associé à un acteur, impossible de déterminer ses actions de combat! ` )
return ;
}
let actions = RdDCombatManager . listActionsCombat ( combatant ) ;
2021-02-25 02:13:39 +01:00
// Build the relevant submenu
2022-07-03 15:32:20 +02:00
if ( actions ) {
2021-02-25 02:13:39 +01:00
let menuItems = [ ] ;
2022-07-03 15:32:20 +02:00
for ( let action of actions ) {
2021-02-25 02:13:39 +01:00
menuItems . push ( {
2022-09-07 00:09:17 +02:00
name : action . system . competence ,
2021-02-25 02:13:39 +01:00
icon : "<i class='fas fa-dice-d6'></i>" ,
2022-07-03 15:32:20 +02:00
callback : target => { RdDCombatManager . rollInitiativeAction ( combatantId , action ) }
2021-02-25 02:13:39 +01:00
} ) ;
}
new ContextMenu ( html , ".directory-list" , menuItems ) . render ( ) ;
}
2021-02-09 09:18:52 +01:00
}
2021-02-25 02:13:39 +01:00
2021-02-09 09:18:52 +01:00
}
2021-02-04 16:35:22 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
export class RdDCombat {
2021-01-10 00:30:37 +01:00
static init ( ) {
2021-03-29 23:41:08 +02:00
Hooks . on ( "updateCombat" , ( combat , change , options , userId ) => { RdDCombat . onUpdateCombat ( combat , change , options , userId ) } ) ;
Hooks . on ( "preDeleteCombat" , ( combat , options , userId ) => { RdDCombat . onPreDeleteCombat ( combat , options , userId ) ; } ) ;
2021-01-10 00:30:37 +01:00
}
/* -------------------------------------------- */
static onSocketMessage ( sockmsg ) {
switch ( sockmsg . msg ) {
case "msg_encaisser" :
2021-01-15 19:10:50 +01:00
return RdDCombat . onMsgEncaisser ( sockmsg . data ) ;
2021-01-10 00:30:37 +01:00
case "msg_defense" :
2021-01-15 19:10:50 +01:00
return RdDCombat . onMsgDefense ( sockmsg . data ) ;
2021-01-10 00:30:37 +01:00
}
}
/* -------------------------------------------- */
2021-03-29 23:41:08 +02:00
static onUpdateCombat ( combat , change , options , userId ) {
2022-09-07 09:01:23 +02:00
if ( combat . round != 0 && combat . turns && combat . active ) {
2021-02-09 09:18:52 +01:00
RdDCombat . combatNouveauTour ( combat ) ;
2021-01-10 00:30:37 +01:00
}
}
/* -------------------------------------------- */
2021-03-29 23:41:08 +02:00
static onPreDeleteCombat ( combat , options , userId ) {
2022-01-29 23:33:31 +01:00
if ( Misc . isUniqueConnectedGM ( ) ) {
2021-02-09 09:18:52 +01:00
combat . cleanItemUse ( ) ;
2021-01-20 00:44:19 +01:00
ChatUtility . removeChatMessageContaining ( ` <div data-combatid=" ${ combat . id } " data-combatmessage="actor-turn-summary"> ` )
2022-01-29 23:33:31 +01:00
game . messages . filter ( m => ChatUtility . getMessageData ( m , 'attacker-roll' ) != undefined && ChatUtility . getMessageData ( m , 'defender-roll' ) != undefined )
. forEach ( it => it . delete ( ) ) ;
2021-01-10 00:30:37 +01:00
}
}
/* -------------------------------------------- */
2021-02-09 09:18:52 +01:00
static combatNouveauTour ( combat ) {
2021-11-28 18:34:41 +01:00
if ( Misc . isUniqueConnectedGM ( ) ) {
2021-06-01 00:08:23 +02:00
let turn = combat . turns . find ( t => t . token ? . id == combat . current . tokenId ) ;
if ( turn ? . actor ) {
RdDCombat . displayActorCombatStatus ( combat , turn . actor ) ;
// TODO Playaudio for player??
}
2021-01-10 00:30:37 +01:00
}
}
2020-12-16 09:07:00 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
static isActive ( ) {
2020-12-15 23:54:05 +01:00
return true ;
2020-12-12 21:58:44 +01:00
}
/* -------------------------------------------- */
static createUsingTarget ( attacker ) {
2022-10-05 20:00:42 +02:00
const target = RdDCombat . getTarget ( )
2020-12-12 21:58:44 +01:00
if ( target == undefined ) {
2021-01-05 18:43:13 +01:00
ui . notifications . warn ( ( game . user . targets ? . size ? ? 0 ) > 1
2021-01-02 04:28:43 +01:00
? "Vous devez choisir <strong>une seule</strong> cible à attaquer!"
: "Vous devez choisir une cible à attaquer!" ) ;
2020-12-12 21:58:44 +01:00
}
2021-03-18 23:55:59 +01:00
else {
const defender = target ? . actor ;
2022-07-22 22:53:48 +02:00
const defenderTokenId = target ? . id ;
if ( defender . type == 'entite' && defender . system . definition . typeentite == ENTITE _NONINCARNE ) {
2021-11-08 14:58:06 +01:00
ui . notifications . warn ( "Vous ne pouvez pas cibler une entité non incarnée !!!!" ) ;
2021-06-28 18:31:46 +02:00
} else {
return this . create ( attacker , defender , defenderTokenId , target )
}
2021-03-18 23:55:59 +01:00
}
2020-12-12 21:58:44 +01:00
}
2020-12-16 09:07:00 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
static getTarget ( ) {
if ( game . user . targets && game . user . targets . size == 1 ) {
for ( let target of game . user . targets ) {
return target ;
}
}
return undefined ;
}
2020-12-16 09:07:00 +01:00
/* -------------------------------------------- */
2020-12-18 22:15:17 +01:00
static create ( attacker , defender , defenderTokenId , target = undefined ) {
return new RdDCombat ( attacker , defender , defenderTokenId , target )
2020-12-12 21:58:44 +01:00
}
2020-12-16 09:07:00 +01:00
/* -------------------------------------------- */
2021-01-19 22:31:32 +01:00
static createForAttackerAndDefender ( attackerId , defenderTokenId ) {
const attacker = game . actors . get ( attackerId ) ;
if ( defenderTokenId ) {
const defenderToken = canvas . tokens . get ( defenderTokenId ) ;
const defender = defenderToken . actor ;
2020-12-12 21:58:44 +01:00
2020-12-18 22:15:17 +01:00
return RdDCombat . create ( attacker , defender , defenderTokenId ) ;
2020-12-12 21:58:44 +01:00
}
2020-12-18 22:15:17 +01:00
return RdDCombat . createUsingTarget ( attacker )
2020-12-12 21:58:44 +01:00
}
2021-01-10 00:30:37 +01:00
/* -------------------------------------------- */
2022-06-12 08:17:59 +02:00
static onMsgEncaisser ( msg ) {
let defender = canvas . tokens . get ( msg . defenderTokenId ) . actor ;
2022-01-29 18:49:06 +01:00
if ( Misc . isOwnerPlayerOrUniqueConnectedGM ( ) ) {
2022-06-12 08:17:59 +02:00
let attackerRoll = msg . attackerRoll ;
let attacker = msg . attackerId ? game . actors . get ( msg . attackerId ) : null ;
2021-01-15 19:10:50 +01:00
defender . encaisserDommages ( attackerRoll , attacker ) ;
2022-06-12 08:17:59 +02:00
const rddCombat = RdDCombat . createForAttackerAndDefender ( msg . attackerId , msg . defenderTokenId ) ;
rddCombat ? . removeChatMessageActionsPasseArme ( attackerRoll . passeArme ) ;
2021-01-15 19:10:50 +01:00
}
}
/* -------------------------------------------- */
2021-01-19 22:31:32 +01:00
static onMsgDefense ( msg ) {
let defenderToken = canvas . tokens . get ( msg . defenderTokenId ) ;
2021-11-28 18:34:41 +01:00
if ( defenderToken && Misc . isUniqueConnectedGM ( ) ) {
2021-05-27 00:20:40 +02:00
const rddCombat = RdDCombat . createForAttackerAndDefender ( msg . attackerId , msg . defenderTokenId ) ;
2022-06-12 08:17:59 +02:00
rddCombat ? . removeChatMessageActionsPasseArme ( msg . defenderRoll . passeArme ) ;
rddCombat ? . _chatMessageDefense ( msg . paramChatDefense , msg . defenderRoll ) ;
2021-01-10 00:30:37 +01:00
}
}
2021-01-03 15:40:48 +01:00
/* -------------------------------------------- */
2021-01-05 18:43:13 +01:00
static _callJetDeVie ( event ) {
2021-01-03 15:40:48 +01:00
let actorId = event . currentTarget . attributes [ 'data-actorId' ] . value ;
let actor = game . actors . get ( actorId ) ;
actor . jetVie ( ) ;
}
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
static registerChatCallbacks ( html ) {
2021-01-07 00:32:22 +01:00
for ( let button of [
'#parer-button' ,
'#esquiver-button' ,
'#particuliere-attaque' ,
'#encaisser-button' ,
'#appel-chance-defense' ,
'#appel-destinee-defense' ,
2021-01-07 01:54:38 +01:00
'#appel-chance-attaque' ,
'#appel-destinee-attaque' ,
'#echec-total-attaque' ,
2021-01-07 00:32:22 +01:00
] ) {
2020-12-12 21:58:44 +01:00
html . on ( "click" , button , event => {
2021-01-19 22:31:32 +01:00
const rddCombat = RdDCombat . createForAttackerAndDefender (
event . currentTarget . attributes [ 'data-attackerId' ] ? . value ,
event . currentTarget . attributes [ 'data-defenderTokenId' ] ? . value ) ;
2021-03-18 23:55:59 +01:00
if ( rddCombat ) {
2021-01-19 22:31:32 +01:00
2021-03-18 23:55:59 +01:00
rddCombat . onEvent ( button , event ) ;
event . preventDefault ( ) ;
}
2020-12-12 21:58:44 +01:00
} ) ;
}
2021-01-03 15:40:48 +01:00
html . on ( "click" , '#chat-jet-vie' , event => {
event . preventDefault ( ) ;
RdDCombat . _callJetDeVie ( event ) ;
2021-01-05 18:43:13 +01:00
} ) ;
2021-01-03 15:40:48 +01:00
2020-12-12 21:58:44 +01:00
}
2020-12-18 22:15:17 +01:00
/* -------------------------------------------- */
constructor ( attacker , defender , defenderTokenId , target ) {
2022-10-05 20:00:42 +02:00
this . attacker = attacker
this . defender = defender
this . target = target
this . attackerId = this . attacker . id
this . defenderId = this . defender . id
this . defenderTokenId = defenderTokenId
2020-12-18 22:15:17 +01:00
}
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
async onEvent ( button , event ) {
2022-01-29 23:33:31 +01:00
const chatMessage = ChatUtility . getChatMessage ( event ) ;
const defenderRoll = ChatUtility . getMessageData ( chatMessage , 'defender-roll' ) ;
const attackerRoll = defenderRoll ? . attackerRoll ? ? ChatUtility . getMessageData ( chatMessage , 'attacker-roll' ) ;
console . log ( 'RdDCombat' , attackerRoll , defenderRoll ) ;
2021-01-13 03:11:03 +01:00
const defenderTokenId = event . currentTarget . attributes [ 'data-defenderTokenId' ] ? . value ;
2021-01-07 00:32:22 +01:00
2021-01-07 01:54:38 +01:00
const armeParadeId = event . currentTarget . attributes [ 'data-armeid' ] ? . value ;
2021-11-20 02:53:28 +01:00
const competence = event . currentTarget . attributes [ 'data-competence' ] ? . value ;
const compId = event . currentTarget . attributes [ 'data-compid' ] ? . value ;
2021-01-07 00:32:22 +01:00
2020-12-12 21:58:44 +01:00
switch ( button ) {
2021-01-07 00:32:22 +01:00
case '#particuliere-attaque' : return await this . choixParticuliere ( attackerRoll , event . currentTarget . attributes [ 'data-mode' ] . value ) ;
2021-12-08 23:22:37 +01:00
case '#parer-button' : return this . parade ( attackerRoll , armeParadeId ) ;
2021-11-20 02:53:28 +01:00
case '#esquiver-button' : return this . esquive ( attackerRoll , compId , competence ) ;
2022-01-29 23:33:31 +01:00
case '#encaisser-button' : return this . encaisser ( attackerRoll , defenderRoll , defenderTokenId ) ;
2021-01-07 01:54:38 +01:00
case '#echec-total-attaque' : return this . _onEchecTotal ( attackerRoll ) ;
2021-01-07 00:32:22 +01:00
2021-01-07 01:54:38 +01:00
case '#appel-chance-attaque' : return this . attacker . rollAppelChance (
( ) => this . attaqueChanceuse ( attackerRoll ) ,
( ) => this . _onEchecTotal ( attackerRoll ) ) ;
2021-01-07 00:32:22 +01:00
case '#appel-chance-defense' : return this . defender . rollAppelChance (
2021-01-15 19:10:50 +01:00
( ) => this . defenseChanceuse ( attackerRoll , defenderRoll ) ,
( ) => this . afficherOptionsDefense ( attackerRoll , defenderRoll , { defenseChance : true } ) ) ;
2021-01-07 01:54:38 +01:00
case '#appel-destinee-attaque' : return this . attacker . appelDestinee (
2021-01-09 19:33:19 +01:00
( ) => this . attaqueSignificative ( attackerRoll ) ,
2021-01-07 01:54:38 +01:00
( ) => { } ) ;
case '#appel-destinee-defense' : return this . defender . appelDestinee (
2022-01-29 23:33:31 +01:00
( ) => this . defenseDestinee ( defenderRoll ) ,
2021-01-07 01:54:38 +01:00
( ) => { } ) ;
2021-01-07 00:32:22 +01:00
}
}
2021-01-07 01:54:38 +01:00
/* -------------------------------------------- */
attaqueChanceuse ( attackerRoll ) {
ui . notifications . info ( "L'attaque est rejouée grâce à la chance" )
attackerRoll . essais . attaqueChance = true ;
this . attaque ( attackerRoll , attackerRoll . arme ) ;
}
2021-01-07 00:32:22 +01:00
2021-01-07 01:54:38 +01:00
/* -------------------------------------------- */
attaqueDestinee ( attackerRoll ) {
ui . notifications . info ( 'Attaque significative grâce à la destinée' )
2021-01-23 18:36:30 +01:00
RdDResolutionTable . significativeRequise ( attackerRoll . rolled ) ;
2021-01-07 01:54:38 +01:00
this . removeChatMessageActionsPasseArme ( attackerRoll . passeArme ) ;
this . _onAttaqueNormale ( attackerRoll ) ;
2021-01-07 00:32:22 +01:00
}
2021-01-07 01:54:38 +01:00
/* -------------------------------------------- */
2021-01-15 19:10:50 +01:00
defenseChanceuse ( attackerRoll , defenderRoll ) {
2021-01-07 01:54:38 +01:00
ui . notifications . info ( "La défense est rejouée grâce à la chance" )
attackerRoll . essais . defenseChance = true ;
attackerRoll . essais . defense = false ;
this . removeChatMessageActionsPasseArme ( attackerRoll . passeArme ) ;
2021-01-15 19:10:50 +01:00
this . _sendMessageDefense ( attackerRoll , defenderRoll , attackerRoll . essais ) ;
2021-01-07 00:32:22 +01:00
}
2021-01-07 01:54:38 +01:00
/* -------------------------------------------- */
2022-01-29 23:33:31 +01:00
defenseDestinee ( defenderRoll ) {
2021-01-08 22:55:00 +01:00
if ( defenderRoll ) {
ui . notifications . info ( 'Défense significative grâce à la destinée' )
2021-01-23 18:36:30 +01:00
RdDResolutionTable . significativeRequise ( defenderRoll . rolled ) ;
2021-01-08 22:55:00 +01:00
this . removeChatMessageActionsPasseArme ( defenderRoll . passeArme ) ;
if ( defenderRoll . arme ) {
this . _onParadeNormale ( defenderRoll ) ;
}
else {
this . _onEsquiveNormale ( defenderRoll ) ;
}
2021-01-07 00:32:22 +01:00
}
2021-01-07 01:54:38 +01:00
else {
2021-01-08 22:55:00 +01:00
ui . notifications . warn ( "Appel à la destinée impossible, la passe d'armes est déjà terminée!" )
2020-12-12 21:58:44 +01:00
}
}
2021-01-07 01:54:38 +01:00
/* -------------------------------------------- */
2021-01-15 19:10:50 +01:00
afficherOptionsDefense ( attackerRoll , defenderRoll , essais ) {
2021-01-07 01:54:38 +01:00
ui . notifications . info ( "La chance n'est pas avec vous" ) ;
2021-01-15 19:10:50 +01:00
this . _sendMessageDefense ( attackerRoll , defenderRoll , essais ) ;
2021-01-07 01:54:38 +01:00
}
2021-01-07 00:32:22 +01:00
/* -------------------------------------------- */
removeChatMessageActionsPasseArme ( passeArme ) {
2021-11-11 02:43:38 +01:00
if ( game . settings . get ( SYSTEM _RDD , "supprimer-dialogues-combat-chat" ) ) {
2021-01-20 00:44:19 +01:00
ChatUtility . removeChatMessageContaining ( ` <div data-passearme=" ${ passeArme } "> ` ) ;
2021-01-07 01:54:38 +01:00
}
2021-01-07 00:32:22 +01:00
}
2020-12-16 23:02:15 +01:00
/* -------------------------------------------- */
static isEchec ( rollData ) {
2021-01-13 03:11:03 +01:00
switch ( rollData . ajustements . surprise . used ) {
2020-12-16 23:02:15 +01:00
case 'totale' : return true ;
2021-03-14 19:19:37 +01:00
case 'demi' : return ! rollData . rolled . isSign ;
2020-12-16 23:02:15 +01:00
}
return rollData . rolled . isEchec ;
}
2020-12-17 12:29:54 +01:00
2020-12-16 23:02:15 +01:00
/* -------------------------------------------- */
static isEchecTotal ( rollData ) {
2021-01-13 03:11:03 +01:00
if ( ! rollData . attackerRoll && rollData . ajustements . surprise . used ) {
2021-04-03 23:59:29 +02:00
return rollData . rolled . isEchec && rollData . rolled . code != 'notSign' ;
2020-12-16 23:02:15 +01:00
}
return rollData . rolled . isETotal ;
}
2020-12-17 12:29:54 +01:00
2020-12-16 23:02:15 +01:00
/* -------------------------------------------- */
static isParticuliere ( rollData ) {
2021-01-13 03:11:03 +01:00
if ( ! rollData . attackerRoll && rollData . ajustements . surprise . used ) {
2020-12-16 23:02:15 +01:00
return false ;
}
return rollData . rolled . isPart ;
}
2020-12-17 12:29:54 +01:00
2020-12-16 23:02:15 +01:00
/* -------------------------------------------- */
static isReussite ( rollData ) {
2021-01-13 03:11:03 +01:00
switch ( rollData . ajustements . surprise . used ) {
2020-12-16 23:02:15 +01:00
case 'totale' : return false ;
2021-03-14 19:19:37 +01:00
case 'demi' : return rollData . rolled . isSign ;
2020-12-16 23:02:15 +01:00
}
return rollData . rolled . isSuccess ;
}
2022-10-05 20:00:42 +02:00
/* -------------------------------------------- */
2022-10-06 14:07:47 +02:00
verifierDistance ( rollData ) {
if ( rollData . competence . system . categorie == "tir" ||
rollData . competence . system . categorie == "lancer" ) {
const defenderToken = canvas . tokens . get ( this . defenderTokenId )
let dist = canvas . grid . measureDistances ( [ { ray : new Ray ( _token . center , defenderToken . center ) } ] , { gridSpaces : false } )
dist = Number ( dist ) . toPrecision ( 5 )
//let ray = new Ray( {x: _token.x, y: _token.y}, {x: defenderToken.x, y:defenderToken.y} )
let msgPortee = "portée est courte (0)"
if ( dist > rollData . arme . system . portee _courte && dist <= rollData . arme . system . portee _moyenne ) {
msgPortee = "portée est moyenne (-3)"
} else if ( dist > rollData . arme . system . portee _moyenne && dist <= rollData . arme . system . portee _extreme ) {
msgPortee = "portée est extrême (-5)"
} else if ( dist > rollData . arme . system . portee _extreme ) {
msgPortee = "cible est inateignable"
}
ChatMessage . create ( { content : ` <strong>Indication MJ</strong> : La cible est à une distance indicative de : ${ dist } mètres. Pour l'arme ${ rollData . arme . name } , la ${ msgPortee } . ` , whisper : ChatMessage . getWhisperRecipients ( "GM" ) } )
2022-10-05 20:00:42 +02:00
}
}
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
2021-06-28 16:08:45 +02:00
async attaque ( competence , arme ) {
2020-12-12 21:58:44 +01:00
if ( ! await this . accorderEntite ( 'avant-attaque' ) ) {
return ;
}
2022-06-12 12:14:55 +02:00
if ( arme . system . cac == 'empoignade' && this . attacker . isCombatTouche ( ) ) {
2021-06-28 16:08:45 +02:00
ChatMessage . create ( {
alias : this . attacker . name ,
whisper : ChatUtility . getWhisperRecipientsAndGMs ( this . attacker . name ) ,
content : await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-perte-empoignade.html' , {
attacker : this . attacker ,
competence : competence
} )
} ) ;
2022-06-12 08:17:59 +02:00
return ;
2021-06-28 16:08:45 +02:00
}
2020-12-12 21:58:44 +01:00
let rollData = this . _prepareAttaque ( competence , arme ) ;
console . log ( "RdDCombat.attaque >>>" , rollData ) ;
2021-03-12 23:19:34 +01:00
if ( arme ) {
this . attacker . verifierForceMin ( arme ) ;
}
2022-10-06 14:07:47 +02:00
this . verifierDistance ( rollData )
2020-12-12 21:58:44 +01:00
const dialog = await RdDRoll . create ( this . attacker , rollData ,
2020-12-17 12:29:54 +01:00
{
2021-10-30 01:34:57 +02:00
html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' ,
2020-12-17 12:29:54 +01:00
options : { height : 540 }
} , {
2020-12-12 21:58:44 +01:00
name : 'jet-attaque' ,
2021-01-04 14:10:21 +01:00
label : 'Attaque: ' + ( arme ? . name ? ? competence . name ) ,
2020-12-12 21:58:44 +01:00
callbacks : [
this . attacker . createCallbackExperience ( ) ,
2021-03-15 00:10:29 +01:00
this . attacker . createCallbackAppelAuMoral ( ) ,
2021-01-07 00:32:22 +01:00
{ action : r => this . removeChatMessageActionsPasseArme ( r . passeArme ) } ,
2021-03-14 19:04:35 +01:00
{ condition : r => arme && ! RdDCombat . isParticuliere ( r ) , action : r => this . attacker . incDecItemUse ( arme . _id ) } ,
2020-12-16 23:02:15 +01:00
{ condition : r => ( RdDCombat . isReussite ( r ) && ! RdDCombat . isParticuliere ( r ) ) , action : r => this . _onAttaqueNormale ( r ) } ,
2020-12-17 01:08:14 +01:00
{ condition : RdDCombat . isParticuliere , action : r => this . _onAttaqueParticuliere ( r ) } ,
{ condition : RdDCombat . isEchec , action : r => this . _onAttaqueEchec ( r ) } ,
2020-12-16 23:02:15 +01:00
{ condition : RdDCombat . isEchecTotal , action : r => this . _onAttaqueEchecTotal ( r ) } ,
2020-12-12 21:58:44 +01:00
]
2020-12-17 12:29:54 +01:00
} ) ;
2022-06-12 08:17:59 +02:00
dialog . render ( true ) ;
2020-12-12 21:58:44 +01:00
}
/* -------------------------------------------- */
_prepareAttaque ( competence , arme ) {
let rollData = {
2021-01-07 00:32:22 +01:00
passeArme : randomID ( 16 ) ,
2022-06-12 12:14:55 +02:00
mortalite : arme ? . system . mortalite ,
2020-12-12 21:58:44 +01:00
coupsNonMortels : false ,
competence : competence ,
2021-01-13 03:42:13 +01:00
surprise : this . attacker . getSurprise ( true ) ,
surpriseDefenseur : this . defender . getSurprise ( true ) ,
2021-01-09 19:33:19 +01:00
essais : { }
2020-12-12 21:58:44 +01:00
} ;
2021-06-28 16:08:45 +02:00
2020-12-12 21:58:44 +01:00
if ( this . attacker . isCreature ( ) ) {
2021-01-13 23:47:12 +01:00
RdDItemCompetenceCreature . setRollDataCreature ( rollData ) ;
2020-12-12 21:58:44 +01:00
}
2020-12-16 23:02:15 +01:00
else if ( arme ) {
2020-12-12 21:58:44 +01:00
// Usual competence
rollData . arme = RdDItemArme . armeUneOuDeuxMains ( arme , RdDItemCompetence . isArmeUneMain ( competence ) ) ;
}
2020-12-16 23:02:15 +01:00
else {
// sans armes: à mains nues
2022-06-12 12:14:55 +02:00
const niveau = competence . system . niveau ;
2022-06-12 09:46:58 +02:00
const init = RdDCombatManager . calculInitiative ( niveau , this . attacker . system . carac [ 'melee' ] . value ) ;
2021-06-28 16:08:45 +02:00
rollData . arme = RdDItemArme . mainsNues ( { niveau : niveau , initiative : init } ) ;
2020-12-16 23:02:15 +01:00
}
2020-12-12 21:58:44 +01:00
return rollData ;
}
/* -------------------------------------------- */
2021-01-07 01:54:38 +01:00
async _onAttaqueParticuliere ( rollData ) {
2022-01-29 23:33:31 +01:00
2021-03-14 19:06:43 +01:00
const isMeleeDiffNegative = ( rollData . competence . type == 'competencecreature' || rollData . selectedCarac . label == "Mêlée" ) && rollData . diffLibre < 0 ;
2021-06-28 16:08:45 +02:00
// force toujours, sauf empoignade
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
// rapidité seulement en mêlée, si l'arme le permet, et si la difficulté libre est de -1 minimum
2022-06-12 12:14:55 +02:00
const isForce = ! rollData . arme . system . empoignade ;
const isFinesse = rollData . arme . system . empoignade || isMeleeDiffNegative ;
const isRapide = ! rollData . arme . system . empoignade && isMeleeDiffNegative && rollData . arme . system . rapide ;
2021-06-28 16:08:45 +02:00
// si un seul choix possible, le prendre
if ( isForce && ! isFinesse && ! isRapide ) {
return await this . choixParticuliere ( rollData , "force" ) ;
}
else if ( ! isForce && isFinesse && ! isRapide ) {
return await this . choixParticuliere ( rollData , "finesse" ) ;
}
else if ( ! isForce && ! isFinesse && isRapide ) {
return await this . choixParticuliere ( rollData , "rapidite" ) ;
}
2022-01-29 23:33:31 +01:00
const choixParticuliere = await ChatMessage . create ( {
2021-01-15 19:10:50 +01:00
alias : this . attacker . name ,
whisper : ChatUtility . getWhisperRecipientsAndGMs ( this . attacker . name ) ,
2021-01-13 03:11:03 +01:00
content : await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html' , {
2021-01-15 19:10:50 +01:00
alias : this . attacker . name ,
2021-01-07 01:54:38 +01:00
attackerId : this . attackerId ,
defenderTokenId : this . defenderTokenId ,
2021-06-28 16:08:45 +02:00
isForce : isForce ,
isFinesse : isFinesse ,
isRapide : isRapide ,
2021-01-19 22:31:32 +01:00
passeArme : rollData . passeArme
2021-01-07 01:54:38 +01:00
} )
} ) ;
2022-01-29 23:33:31 +01:00
ChatUtility . setMessageData ( choixParticuliere , 'attacker-roll' , rollData ) ;
2020-12-12 21:58:44 +01:00
}
/* -------------------------------------------- */
2021-01-07 01:54:38 +01:00
async _onAttaqueNormale ( attackerRoll ) {
console . log ( "RdDCombat.onAttaqueNormale >>>" , attackerRoll ) ;
2021-01-01 03:25:48 +01:00
2022-07-22 21:38:15 +02:00
attackerRoll . dmg = RdDBonus . dmg ( attackerRoll , this . attacker . getBonusDegat ( ) , this . defender . isEntite ( ) ) ;
2021-01-19 22:31:32 +01:00
let defenderRoll = { attackerRoll : attackerRoll , passeArme : attackerRoll . passeArme , show : { } }
2021-01-07 01:54:38 +01:00
attackerRoll . show = {
2022-06-12 12:14:55 +02:00
cible : this . target ? this . defender . system . name : 'la cible' ,
2021-01-07 01:54:38 +01:00
isRecul : ( attackerRoll . particuliere == 'force' || attackerRoll . tactique == 'charge' )
2021-01-01 03:25:48 +01:00
}
2021-01-07 01:54:38 +01:00
await RdDResolutionTable . displayRollData ( attackerRoll , this . attacker , 'chat-resultat-attaque.html' ) ;
2021-01-01 03:25:48 +01:00
2020-12-19 18:02:05 +01:00
if ( ! await this . accorderEntite ( 'avant-defense' ) ) {
return ;
}
2021-01-01 03:25:48 +01:00
2020-12-12 21:58:44 +01:00
if ( this . target ) {
2021-01-19 22:31:32 +01:00
await this . _sendMessageDefense ( attackerRoll , defenderRoll ) ;
2020-12-12 21:58:44 +01:00
}
}
2021-11-20 02:53:28 +01:00
2021-11-08 14:58:06 +01:00
/* -------------------------------------------- */
isPossession ( attackerRoll ) {
return attackerRoll . selectedCarac . label . toLowerCase ( ) == 'possession' ;
}
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
2021-01-19 22:31:32 +01:00
async _sendMessageDefense ( attackerRoll , defenderRoll , essaisPrecedents = undefined ) {
2022-06-12 12:14:55 +02:00
console . log ( "RdDCombat._sendMessageDefense" , attackerRoll , defenderRoll , essaisPrecedents , " / " , this . attacker , this . target , this . attackerId , attackerRoll . competence . system . categorie ) ;
2020-12-18 22:15:17 +01:00
2021-01-07 00:32:22 +01:00
this . removeChatMessageActionsPasseArme ( attackerRoll . passeArme ) ;
2021-01-15 19:10:50 +01:00
if ( essaisPrecedents ) {
mergeObject ( attackerRoll . essais , essaisPrecedents , { overwrite : true } ) ;
}
2021-02-09 09:18:52 +01:00
// # utilisation esquive
2022-06-12 09:46:58 +02:00
const corpsACorps = this . defender . getCompetence ( "Corps à corps" , { onMessage : it => console . info ( it , this . defender ) } ) ;
const esquives = duplicate ( this . defender . getCompetences ( "esquive" , { onMessage : it => console . info ( it , this . defender ) } ) )
2022-09-21 14:13:43 +02:00
esquives . forEach ( e => e . system . nbUsage = e ? . _id ? this . defender . getItemUse ( e . _id ) : 0 ) ;
2021-02-09 09:18:52 +01:00
2021-01-19 22:31:32 +01:00
const paramChatDefense = {
2021-01-07 00:32:22 +01:00
passeArme : attackerRoll . passeArme ,
2021-01-07 01:54:38 +01:00
essais : attackerRoll . essais ,
2021-11-20 02:53:28 +01:00
isPossession : this . isPossession ( attackerRoll ) ,
2022-06-12 09:46:58 +02:00
defender : this . defender ,
attacker : this . attacker ,
2021-01-07 00:32:22 +01:00
attackerId : this . attackerId ,
2021-11-20 02:53:28 +01:00
esquives : esquives ,
2021-01-07 00:32:22 +01:00
defenderTokenId : this . defenderTokenId ,
2021-04-20 00:52:06 +02:00
mainsNues : attackerRoll . dmg . mortalite != 'mortel' && corpsACorps ,
2021-02-09 09:18:52 +01:00
armes : this . _filterArmesParade ( this . defender , attackerRoll . competence , attackerRoll . arme ) ,
2021-01-07 01:54:38 +01:00
diffLibre : attackerRoll . ajustements ? . diffLibre ? . value ? ? 0 ,
2021-01-15 19:09:44 +01:00
attaqueParticuliere : attackerRoll . particuliere ,
2022-06-12 12:14:55 +02:00
attaqueCategorie : attackerRoll . competence . system . categorie ,
2021-01-19 22:31:32 +01:00
attaqueArme : attackerRoll . arme ,
2021-01-20 09:19:16 +01:00
surprise : this . defender . getSurprise ( true ) ,
2021-01-19 22:31:32 +01:00
dmg : attackerRoll . dmg ,
2021-01-07 01:54:38 +01:00
} ;
2020-12-12 21:58:44 +01:00
2022-01-29 18:49:06 +01:00
if ( Misc . isUniqueConnectedGM ( ) ) {
2022-01-29 23:33:31 +01:00
await this . _chatMessageDefense ( paramChatDefense , defenderRoll ) ;
2021-01-19 22:31:32 +01:00
}
else {
2022-01-29 18:49:06 +01:00
this . _socketSendMessageDefense ( paramChatDefense , defenderRoll ) ;
2021-01-19 22:31:32 +01:00
}
}
2021-01-15 19:10:50 +01:00
2021-01-19 22:31:32 +01:00
/* -------------------------------------------- */
2022-01-29 23:33:31 +01:00
async _chatMessageDefense ( paramDemandeDefense , defenderRoll ) {
const choixDefense = await ChatMessage . create ( {
2021-01-19 22:31:32 +01:00
// message privé: du défenseur à lui même (et aux GMs)
speaker : ChatMessage . getSpeaker ( this . defender , canvas . tokens . get ( this . defenderTokenId ) ) ,
2021-01-15 19:10:50 +01:00
alias : this . attacker . name ,
whisper : ChatUtility . getWhisperRecipientsAndGMs ( this . defender . name ) ,
content : await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html' , paramDemandeDefense ) ,
2021-01-19 22:31:32 +01:00
} ) ;
2022-01-29 23:33:31 +01:00
// flag pour garder les jets d'attaque/defense
ChatUtility . setMessageData ( choixDefense , 'defender-roll' , defenderRoll ) ;
2020-12-18 22:15:17 +01:00
}
2020-12-12 21:58:44 +01:00
2021-01-15 19:10:50 +01:00
/* -------------------------------------------- */
2021-01-19 22:31:32 +01:00
_socketSendMessageDefense ( paramChatDefense , defenderRoll ) {
2021-01-15 19:10:50 +01:00
// envoyer le message au destinataire
2022-01-29 22:49:34 +01:00
game . socket . emit ( SYSTEM _SOCKET _ID , {
2021-01-19 22:31:32 +01:00
msg : "msg_defense" , data : {
2022-06-12 12:14:55 +02:00
attackerId : this . attacker ? . id ,
defenderId : this . defender ? . id ,
2021-01-19 22:31:32 +01:00
defenderTokenId : this . defenderTokenId ,
2021-03-29 18:08:18 +02:00
defenderRoll : defenderRoll ,
2021-01-19 22:31:32 +01:00
paramChatDefense : paramChatDefense ,
2021-01-15 19:10:50 +01:00
rollMode : true
2021-01-19 22:31:32 +01:00
}
} ) ;
2021-01-15 19:10:50 +01:00
}
2021-01-19 22:31:32 +01:00
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
2021-02-09 09:18:52 +01:00
_filterArmesParade ( defender , competence ) {
2022-09-07 18:47:56 +02:00
let items = defender . items . filter ( it => RdDItemArme . isArmeUtilisable ( it ) || RdDItemCompetenceCreature . isCompetenceParade ( it ) )
2021-02-25 02:13:39 +01:00
for ( let item of items ) {
2022-06-12 12:14:55 +02:00
item . system . nbUsage = defender . getItemUse ( item . id ) ; // Ajout du # d'utilisation ce round
2021-02-09 09:18:52 +01:00
}
2022-06-12 12:14:55 +02:00
switch ( competence . system . categorie ) {
2020-12-12 21:58:44 +01:00
case 'tir' :
case 'lancer' :
2021-01-03 16:56:25 +01:00
return items . filter ( item => RdDItemArme . getCategorieParade ( item ) == 'boucliers' )
2020-12-12 21:58:44 +01:00
default :
2021-01-02 04:28:43 +01:00
// Le fléau ne peut être paré qu’ au bouclier p115
2021-01-05 18:43:13 +01:00
if ( competence . name == "Fléau" ) {
2021-01-03 16:56:25 +01:00
return items . filter ( item => RdDItemArme . getCategorieParade ( item ) == 'boucliers' )
2021-01-02 04:28:43 +01:00
}
2021-01-03 16:56:25 +01:00
return items . filter ( item => RdDItemArme . getCategorieParade ( item ) ) ;
2020-12-12 21:58:44 +01:00
}
}
2020-12-16 09:07:00 +01:00
/* -------------------------------------------- */
2021-01-07 01:54:38 +01:00
async _onAttaqueEchecTotal ( attackerRoll ) {
2022-01-29 23:33:31 +01:00
const choixEchecTotal = await ChatMessage . create ( {
2021-02-25 02:13:39 +01:00
whisper : ChatUtility . getWhisperRecipientsAndGMs ( this . attacker . name ) ,
2021-01-07 01:54:38 +01:00
content : await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html' , {
attackerId : this . attackerId ,
2022-06-12 09:46:58 +02:00
attacker : this . attacker ,
2021-01-07 01:54:38 +01:00
defenderTokenId : this . defenderTokenId ,
essais : attackerRoll . essais
} )
} ) ;
2022-01-29 23:33:31 +01:00
ChatUtility . setMessageData ( choixEchecTotal , 'attacker-roll' , attackerRoll ) ;
2020-12-12 21:58:44 +01:00
}
2021-01-07 01:54:38 +01:00
/* -------------------------------------------- */
async _onEchecTotal ( rollData ) {
console . log ( "RdDCombat._onEchecTotal >>>" , rollData ) ;
const arme = rollData . arme ;
2022-06-12 12:14:55 +02:00
const avecArme = ! [ '' , 'sans-armes' , 'armes-naturelles' ] . includes ( arme ? . system . categorie _parade ? ? '' ) ;
2021-01-07 01:54:38 +01:00
const action = ( rollData . attackerRoll ? ( arme ? "la parade" : "l'esquive" ) : "l'attaque" ) ;
2021-01-09 19:36:19 +01:00
ChatUtility . createChatWithRollMode ( this . defender . name , {
2021-02-25 02:06:21 +01:00
content : ` <strong>Maladresse à ${ action } !</strong> ` + await RdDRollTables . getMaladresse ( { arme : avecArme } )
2021-01-09 19:36:19 +01:00
} ) ;
2021-01-07 01:54:38 +01:00
}
2021-01-02 04:28:43 +01:00
2020-12-16 09:07:00 +01:00
/* -------------------------------------------- */
2021-01-02 04:28:43 +01:00
async _onAttaqueEchec ( rollData ) {
2020-12-12 21:58:44 +01:00
console . log ( "RdDCombat.onAttaqueEchec >>>" , rollData ) ;
2021-01-05 18:43:13 +01:00
await RdDResolutionTable . displayRollData ( rollData , this . attacker , 'chat-resultat-attaque.html' ) ;
2020-12-12 21:58:44 +01:00
}
/* -------------------------------------------- */
async choixParticuliere ( rollData , choix ) {
console . log ( "RdDCombat.choixParticuliere >>>" , rollData , choix ) ;
2021-01-24 19:52:02 +01:00
2021-03-14 19:04:35 +01:00
if ( choix != "rapidite" ) {
2022-06-12 12:14:55 +02:00
this . attacker . incDecItemUse ( rollData . arme . id ) ;
2021-03-14 19:04:35 +01:00
}
2021-01-20 00:44:19 +01:00
this . removeChatMessageActionsPasseArme ( rollData . passeArme ) ;
2021-01-03 16:58:11 +01:00
rollData . particuliere = choix ;
2020-12-12 21:58:44 +01:00
await this . _onAttaqueNormale ( rollData ) ;
}
/* -------------------------------------------- */
2021-12-08 23:22:37 +01:00
async parade ( attackerRoll , armeParadeId ) {
const arme = this . defender . getArmeParade ( armeParadeId ) ;
2020-12-12 21:58:44 +01:00
console . log ( "RdDCombat.parade >>>" , attackerRoll , armeParadeId , arme ) ;
2022-09-07 18:47:56 +02:00
const competence = arme ? . system ? . competence ;
2021-12-08 23:22:37 +01:00
if ( competence == undefined )
{
2022-09-07 18:47:56 +02:00
console . error ( "Pas de compétence de parade associée à " , arme ? . name , armeParadeId ) ;
2021-12-08 23:22:37 +01:00
return ;
}
2020-12-12 21:58:44 +01:00
2021-11-20 02:53:28 +01:00
let rollData = this . _prepareParade ( attackerRoll , arme , competence ) ;
2020-12-12 21:58:44 +01:00
const dialog = await RdDRoll . create ( this . defender , rollData ,
2020-12-17 12:29:54 +01:00
{
2021-10-30 01:34:57 +02:00
html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' ,
2020-12-17 12:29:54 +01:00
options : { height : 540 }
} , {
2020-12-12 21:58:44 +01:00
name : 'jet-parade' ,
label : 'Parade: ' + ( arme ? arme . name : rollData . competence . name ) ,
callbacks : [
this . defender . createCallbackExperience ( ) ,
2021-03-15 00:10:29 +01:00
this . defender . createCallbackAppelAuMoral ( ) ,
2021-01-07 00:32:22 +01:00
{ action : r => this . removeChatMessageActionsPasseArme ( r . passeArme ) } ,
2021-03-14 19:04:35 +01:00
{ condition : r => ! RdDCombat . isParticuliere ( r ) , action : r => this . defender . incDecItemUse ( armeParadeId ) } ,
2020-12-16 23:02:15 +01:00
{ condition : RdDCombat . isReussite , action : r => this . _onParadeNormale ( r ) } ,
2020-12-17 01:08:14 +01:00
{ condition : RdDCombat . isParticuliere , action : r => this . _onParadeParticuliere ( r ) } ,
{ condition : RdDCombat . isEchec , action : r => this . _onParadeEchec ( r ) } ,
2020-12-12 21:58:44 +01:00
]
2020-12-17 12:29:54 +01:00
} ) ;
2020-12-12 21:58:44 +01:00
dialog . render ( true ) ;
}
2021-02-09 09:18:52 +01:00
/* -------------------------------------------- */
2021-11-20 02:53:28 +01:00
_prepareParade ( attackerRoll , armeParade , competenceParade ) {
2021-03-14 19:04:35 +01:00
let defenderRoll = {
2021-01-07 00:32:22 +01:00
passeArme : attackerRoll . passeArme ,
2020-12-12 21:58:44 +01:00
diffLibre : attackerRoll . diffLibre ,
attackerRoll : attackerRoll ,
2022-06-12 09:46:58 +02:00
competence : this . defender . getCompetence ( competenceParade ) ,
2020-12-17 00:23:40 +01:00
arme : armeParade ,
2021-01-13 03:42:13 +01:00
surprise : this . defender . getSurprise ( true ) ,
2021-12-08 23:22:37 +01:00
needParadeSignificative : ReglesOptionelles . isUsing ( 'categorieParade' ) && RdDItemArme . needParadeSignificative ( attackerRoll . arme , armeParade ) ,
2021-11-20 02:53:28 +01:00
needResist : RdDItemArme . needArmeResist ( attackerRoll . arme , armeParade ) ,
2022-06-12 09:46:58 +02:00
carac : this . defender . system . carac ,
2021-01-02 04:28:43 +01:00
show : { }
2020-12-12 21:58:44 +01:00
} ;
2021-01-13 03:42:13 +01:00
if ( this . defender . isCreature ( ) ) {
2021-03-14 19:04:35 +01:00
RdDItemCompetenceCreature . setRollDataCreature ( defenderRoll ) ;
2020-12-12 21:58:44 +01:00
}
2021-01-14 00:35:55 +01:00
2021-03-14 19:04:35 +01:00
return defenderRoll ;
2020-12-12 21:58:44 +01:00
}
2020-12-15 02:20:24 +01:00
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
_onParadeParticuliere ( defenderRoll ) {
console . log ( "RdDCombat._onParadeParticuliere >>>" , defenderRoll ) ;
if ( ! defenderRoll . attackerRoll . isPart ) {
2020-12-12 21:58:44 +01:00
// TODO: attaquant doit jouer résistance et peut être désarmé p132
2021-01-09 19:36:19 +01:00
ChatUtility . createChatWithRollMode ( this . defender . name , {
2021-01-07 00:32:22 +01:00
content : ` (à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132) `
2021-01-09 19:36:19 +01:00
} ) ;
2020-12-12 21:58:44 +01:00
}
}
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async _onParadeNormale ( defenderRoll ) {
console . log ( "RdDCombat._onParadeNormale >>>" , defenderRoll ) ;
2020-12-17 12:29:54 +01:00
2021-01-09 19:33:19 +01:00
await this . computeRecul ( defenderRoll ) ;
await this . computeDeteriorationArme ( defenderRoll ) ;
await RdDResolutionTable . displayRollData ( defenderRoll , this . defender , 'chat-resultat-parade.html' ) ;
2022-06-12 08:17:59 +02:00
this . removeChatMessageActionsPasseArme ( defenderRoll . passeArme ) ;
2020-12-12 21:58:44 +01:00
}
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async _onParadeEchec ( defenderRoll ) {
console . log ( "RdDCombat._onParadeEchec >>>" , defenderRoll ) ;
2020-12-12 21:58:44 +01:00
2021-01-09 19:33:19 +01:00
await RdDResolutionTable . displayRollData ( defenderRoll , this . defender , 'chat-resultat-parade.html' ) ;
2020-12-12 21:58:44 +01:00
2021-01-09 19:33:19 +01:00
this . removeChatMessageActionsPasseArme ( defenderRoll . passeArme ) ;
2021-01-15 19:10:50 +01:00
this . _sendMessageDefense ( defenderRoll . attackerRoll , defenderRoll , { defense : true } ) ;
2020-12-12 21:58:44 +01:00
}
/* -------------------------------------------- */
2021-11-20 02:53:28 +01:00
async esquive ( attackerRoll , compId , compName ) {
2022-06-12 09:46:58 +02:00
const esquive = this . defender . getCompetence ( compId ) ? ? this . defender . getCompetence ( compName )
2020-12-12 21:58:44 +01:00
if ( esquive == undefined ) {
2021-11-20 02:53:28 +01:00
ui . notifications . error ( this . defender . name + " n'a pas de compétence " + compName ) ;
2020-12-12 21:58:44 +01:00
return ;
}
console . log ( "RdDCombat.esquive >>>" , attackerRoll , esquive ) ;
let rollData = this . _prepareEsquive ( attackerRoll , esquive ) ;
const dialog = await RdDRoll . create ( this . defender , rollData ,
2021-10-30 01:34:57 +02:00
{ html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' } , {
2020-12-12 21:58:44 +01:00
name : 'jet-esquive' ,
label : 'Esquiver' ,
callbacks : [
this . defender . createCallbackExperience ( ) ,
2021-03-15 00:10:29 +01:00
this . defender . createCallbackAppelAuMoral ( ) ,
2021-03-14 19:04:35 +01:00
{ condition : r => ! RdDCombat . isParticuliere ( r ) , action : r => this . defender . incDecItemUse ( esquive . _id ) } ,
2021-01-07 00:32:22 +01:00
{ action : r => this . removeChatMessageActionsPasseArme ( r . passeArme ) } ,
2020-12-16 23:02:15 +01:00
{ condition : RdDCombat . isReussite , action : r => this . _onEsquiveNormale ( r ) } ,
2020-12-17 01:08:14 +01:00
{ condition : RdDCombat . isParticuliere , action : r => this . _onEsquiveParticuliere ( r ) } ,
2020-12-16 23:02:15 +01:00
{ condition : RdDCombat . isEchec , action : r => this . _onEsquiveEchec ( r ) } ,
2020-12-12 21:58:44 +01:00
]
} ) ;
dialog . render ( true ) ;
}
2020-12-26 18:29:03 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
_prepareEsquive ( attackerRoll , competence ) {
let rollData = {
2021-01-07 00:32:22 +01:00
passeArme : attackerRoll . passeArme ,
2020-12-12 21:58:44 +01:00
diffLibre : attackerRoll . diffLibre ,
attackerRoll : attackerRoll ,
competence : competence ,
2021-01-13 03:42:13 +01:00
surprise : this . defender . getSurprise ( true ) ,
surpriseDefenseur : this . defender . getSurprise ( true ) ,
2022-06-12 09:46:58 +02:00
carac : this . defender . system . carac ,
2021-01-02 04:28:43 +01:00
show : { }
2020-12-12 21:58:44 +01:00
} ;
if ( this . defender . isCreature ( ) ) {
2021-01-13 23:47:12 +01:00
RdDItemCompetenceCreature . setRollDataCreature ( rollData ) ;
2020-12-12 21:58:44 +01:00
}
return rollData ;
}
/* -------------------------------------------- */
_onEsquiveParticuliere ( rollData ) {
console . log ( "RdDCombat._onEsquiveParticuliere >>>" , rollData ) ;
2021-01-09 19:36:19 +01:00
ChatUtility . createChatWithRollMode ( this . defender . name , {
2021-01-20 00:44:40 +01:00
content : "<strong>Vous pouvez esquiver une deuxième fois!</strong>"
2021-01-09 19:36:19 +01:00
} ) ;
2020-12-12 21:58:44 +01:00
}
/* -------------------------------------------- */
2021-01-13 03:42:13 +01:00
async _onEsquiveNormale ( defenderRoll ) {
console . log ( "RdDCombat._onEsquiveNormal >>>" , defenderRoll ) ;
await RdDResolutionTable . displayRollData ( defenderRoll , this . defender , 'chat-resultat-esquive.html' ) ;
2022-06-12 08:17:59 +02:00
this . removeChatMessageActionsPasseArme ( defenderRoll . passeArme ) ;
2020-12-12 21:58:44 +01:00
}
2020-12-17 12:29:54 +01:00
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
2021-01-13 03:42:13 +01:00
async _onEsquiveEchec ( defenderRoll ) {
console . log ( "RdDCombat._onEsquiveEchec >>>" , defenderRoll ) ;
2020-12-12 21:58:44 +01:00
2021-01-13 03:42:13 +01:00
await RdDResolutionTable . displayRollData ( defenderRoll , this . defender , 'chat-resultat-esquive.html' ) ;
2020-12-12 21:58:44 +01:00
2021-01-13 03:42:13 +01:00
this . removeChatMessageActionsPasseArme ( defenderRoll . passeArme ) ;
2021-01-15 19:10:50 +01:00
this . _sendMessageDefense ( defenderRoll . attackerRoll , defenderRoll , { defense : true } )
2020-12-12 21:58:44 +01:00
}
2021-01-01 03:25:48 +01:00
2020-12-17 00:44:32 +01:00
/* -------------------------------------------- */
2021-01-28 00:27:44 +01:00
async computeDeteriorationArme ( defenderRoll ) {
2021-01-26 19:43:37 +01:00
if ( ! ReglesOptionelles . isUsing ( 'resistanceArmeParade' ) ) {
2021-01-25 08:48:03 +01:00
return ;
}
2021-01-28 00:27:44 +01:00
const attackerRoll = defenderRoll . attackerRoll ;
2021-01-02 04:28:43 +01:00
// Est-ce une parade normale?
2021-01-28 00:27:44 +01:00
if ( defenderRoll . arme && attackerRoll && ! defenderRoll . rolled . isPart ) {
2021-01-02 04:28:43 +01:00
// Est-ce que l'attaque est une particulière en force ou une charge
2021-01-28 00:27:44 +01:00
if ( defenderRoll . needResist || this . _isForceOuCharge ( attackerRoll ) ) {
2021-01-02 04:28:43 +01:00
2021-01-28 00:27:44 +01:00
defenderRoll . show = defenderRoll . show || { }
2021-01-02 04:28:43 +01:00
2020-12-17 00:44:32 +01:00
const dmg = attackerRoll . dmg . dmgArme + attackerRoll . dmg . dmgActor ;
2021-01-29 20:10:43 +01:00
let arme = defenderRoll . arme ;
2022-06-12 12:14:55 +02:00
let resistance = Misc . toInt ( arme . system . resistance ) ;
if ( arme . system . magique ) {
2021-01-29 20:10:43 +01:00
defenderRoll . show . deteriorationArme = 'resiste' ; // Par défaut
2022-06-12 12:14:55 +02:00
if ( arme . system . resistance _magique == undefined ) arme . system . resistance _magique = 0 ; // Quick fix
if ( dmg > arme . system . resistance _magique ) { // Jet uniquement si dommages supérieur à résistance magique (cf. 274)
2021-01-29 20:10:43 +01:00
// Jet de résistance de l'arme de parade (p.132)
let resistRoll = await RdDResolutionTable . rollData ( {
caracValue : resistance ,
finalLevel : - dmg ,
2021-12-03 22:53:38 +01:00
showDice : HIDE _DICE
2021-01-29 20:10:43 +01:00
} ) ;
2021-02-25 02:13:39 +01:00
if ( ! resistRoll . rolled . isSuccess ) {
2022-06-12 12:14:55 +02:00
let perteResistance = ( dmg - arme . system . resistance _magique )
2021-01-29 20:10:43 +01:00
resistance -= perteResistance ;
2021-02-25 02:13:39 +01:00
defenderRoll . show . deteriorationArme = resistance <= 0 ? 'brise' : 'perte' ;
2021-01-29 20:10:43 +01:00
defenderRoll . show . perteResistance = perteResistance ;
2022-09-07 18:47:56 +02:00
this . defender . updateEmbeddedDocuments ( 'Item' , [ { _id : defenderRoll . arme . _id , 'system.resistance' : resistance } ] ) ;
2021-01-29 20:10:43 +01:00
}
2021-02-25 02:13:39 +01:00
}
2020-12-17 00:44:32 +01:00
} else {
2021-01-29 20:10:43 +01:00
// Jet de résistance de l'arme de parade (p.132)
let resistRoll = await RdDResolutionTable . rollData ( {
caracValue : resistance ,
finalLevel : - dmg ,
2021-12-03 22:53:38 +01:00
showDice : HIDE _DICE
2021-01-29 20:10:43 +01:00
} ) ;
if ( resistRoll . rolled . isSuccess ) { // Perte de résistance
defenderRoll . show . deteriorationArme = 'resiste' ;
} else {
resistance -= dmg ;
2021-02-25 02:13:39 +01:00
defenderRoll . show . deteriorationArme = resistance <= 0 ? 'brise' : 'perte' ;
2021-01-29 20:10:43 +01:00
defenderRoll . show . perteResistance = dmg ;
2022-09-07 18:47:56 +02:00
this . defender . updateEmbeddedDocuments ( 'Item' , [ { _id : defenderRoll . arme . _id , 'system.resistance' : resistance } ] ) ;
2021-01-29 20:10:43 +01:00
}
2020-12-17 00:44:32 +01:00
}
2021-01-02 04:28:43 +01:00
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
2021-01-28 00:27:44 +01:00
if ( ReglesOptionelles . isUsing ( 'defenseurDesarme' ) && resistance > 0 && RdDItemArme . getCategorieParade ( defenderRoll . arme ) != 'boucliers' ) {
2020-12-17 00:44:32 +01:00
let desarme = await RdDResolutionTable . rollData ( {
2021-01-23 18:36:30 +01:00
caracValue : this . defender . getForce ( ) ,
2022-06-12 12:14:55 +02:00
finalLevel : Misc . toInt ( defenderRoll . competence . system . niveau ) - dmg ,
2021-12-03 22:53:38 +01:00
showDice : HIDE _DICE
2020-12-17 12:29:54 +01:00
} ) ;
2021-01-28 00:27:44 +01:00
defenderRoll . show . desarme = desarme . rolled . isEchec ;
2020-12-17 00:44:32 +01:00
}
}
}
}
2021-01-24 19:52:02 +01:00
2020-12-17 00:44:32 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async computeRecul ( defenderRoll ) { // Calcul du recul (p. 132)
const attackerRoll = defenderRoll . attackerRoll ;
2021-01-28 00:27:44 +01:00
if ( ReglesOptionelles . isUsing ( 'recul' ) && this . _isForceOuCharge ( attackerRoll ) ) {
2021-01-23 18:36:30 +01:00
const impact = this . _computeImpactRecul ( attackerRoll ) ;
const rollRecul = await RdDResolutionTable . rollData ( { caracValue : 10 , finalLevel : impact } ) ;
if ( rollRecul . rolled . isSuccess ) {
2021-01-09 19:33:19 +01:00
defenderRoll . show . recul = 'encaisse' ;
2021-01-24 19:52:02 +01:00
} else if ( rollRecul . rolled . isETotal || this . _isReculCauseChute ( impact ) ) {
2021-01-09 19:33:19 +01:00
defenderRoll . show . recul = 'chute' ;
2022-09-17 22:36:43 +02:00
await this . defender . setEffect ( STATUSES . StatusProne , true ) ;
2021-01-02 04:28:43 +01:00
}
else {
2021-01-24 19:52:02 +01:00
defenderRoll . show . recul = 'recul' ;
2020-12-17 00:44:32 +01:00
}
}
}
2021-01-24 19:52:02 +01:00
/* -------------------------------------------- */
async _isReculCauseChute ( impact ) {
const agilite = this . defender . getAgilite ( ) ;
const chute = await RdDResolutionTable . rollData ( { caracValue : agilite , finalLevel : impact } ) ;
return chute . rolled . isEchec ;
}
/* -------------------------------------------- */
2021-01-28 00:27:44 +01:00
_isForceOuCharge ( attaque ) {
2021-01-03 16:58:11 +01:00
return attaque . particuliere == 'force' || attaque . tactique == 'charge' ;
2021-01-02 04:28:43 +01:00
}
2021-01-24 19:52:02 +01:00
/* -------------------------------------------- */
2021-01-02 04:28:43 +01:00
_computeImpactRecul ( attaque ) {
2021-01-23 18:36:30 +01:00
const taille = this . defender . getTaille ( ) ;
const force = this . attacker . getForce ( ) ;
2022-06-12 12:14:55 +02:00
const dommages = attaque . arme . system . dommagesReels ? ? attaque . arme . system . dommages ;
2021-01-23 18:36:30 +01:00
return taille - ( force + dommages ) ;
2021-01-02 04:28:43 +01:00
}
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
2022-01-29 23:33:31 +01:00
async encaisser ( attackerRoll , defenderRoll , defenderTokenId ) {
2020-12-12 21:58:44 +01:00
defenderTokenId = defenderTokenId || this . defenderTokenId ;
console . log ( "RdDCombat.encaisser >>>" , attackerRoll , defenderTokenId ) ;
2021-01-15 19:10:50 +01:00
if ( defenderRoll ? . rolled && RdDCombat . isEchecTotal ( defenderRoll ) ) {
2021-01-07 01:54:38 +01:00
this . _onEchecTotal ( defenderRoll ) ;
}
2022-01-29 18:49:06 +01:00
if ( Misc . isOwnerPlayerOrUniqueConnectedGM ( this . defender ) ) {
2020-12-12 21:58:44 +01:00
attackerRoll . attackerId = this . attackerId ;
attackerRoll . defenderTokenId = defenderTokenId ;
2021-01-07 00:32:22 +01:00
await this . computeRecul ( defenderRoll ) ;
2021-01-23 18:36:30 +01:00
this . defender . encaisserDommages ( attackerRoll , this . attacker , defenderRoll ) ;
2021-05-22 02:19:22 +02:00
}
else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas
2022-01-29 22:49:34 +01:00
game . socket . emit ( SYSTEM _SOCKET _ID , {
2020-12-12 21:58:44 +01:00
msg : "msg_encaisser" ,
2021-01-15 19:10:50 +01:00
data : {
attackerId : this . attackerId ,
defenderTokenId : defenderTokenId ,
2021-05-22 14:48:51 +02:00
attackerRoll : attackerRoll
2021-01-15 19:10:50 +01:00
}
2020-12-12 21:58:44 +01:00
} ) ;
}
2021-01-19 22:31:32 +01:00
this . removeChatMessageActionsPasseArme ( attackerRoll . passeArme ) ;
2020-12-12 21:58:44 +01:00
}
/* -------------------------------------------- */
/* retourne true si on peut continuer, false si on ne peut pas continuer */
async accorderEntite ( when = 'avant-encaissement' ) {
2021-11-11 02:43:38 +01:00
if ( when != game . settings . get ( SYSTEM _RDD , "accorder-entite-cauchemar" )
2020-12-12 21:58:44 +01:00
|| this . defender == undefined
2022-07-22 21:38:15 +02:00
|| ! this . defender . isEntite ( [ ENTITE _INCARNE ] )
|| this . defender . isEntiteAccordee ( this . attacker ) ) {
2020-12-12 21:58:44 +01:00
return true ;
}
2022-06-12 09:46:58 +02:00
let rolled = await RdDResolutionTable . roll ( this . attacker . getReveActuel ( ) , - Number ( this . defender . system . carac . niveau . value ) ) ;
2020-12-12 21:58:44 +01:00
let message = {
content : "Jet de points actuels de rêve à " + rolled . finalLevel + RdDResolutionTable . explain ( rolled ) + "<br>" ,
whisper : ChatMessage . getWhisperRecipients ( this . attacker . name )
} ;
if ( rolled . isSuccess ) {
await this . defender . setEntiteReveAccordee ( this . attacker ) ;
message . content += this . attacker . name + " s'est accordé avec " + this . defender . name ;
}
else {
message . content += this . attacker . name + " n'est pas accordé avec " + this . defender . name ;
}
ChatMessage . create ( message ) ;
return rolled . isSuccess ;
}
2021-01-03 15:40:48 +01:00
/* -------------------------------------------- */
2021-01-10 00:30:37 +01:00
static async displayActorCombatStatus ( combat , actor ) {
2022-09-07 18:47:56 +02:00
let formData = {
2021-01-10 00:30:37 +01:00
combatId : combat . _id ,
2021-01-05 18:43:13 +01:00
alias : actor . name ,
2021-01-03 15:40:48 +01:00
etatGeneral : actor . getEtatGeneral ( ) ,
2021-01-05 18:43:13 +01:00
isSonne : actor . getSonne ( ) ,
2021-01-03 15:40:48 +01:00
blessuresStatus : actor . computeResumeBlessure ( ) ,
SConst : actor . getSConst ( ) ,
2022-06-12 12:14:55 +02:00
actorId : actor . id ,
2021-01-03 15:40:48 +01:00
isGrave : false ,
isCritique : false
}
2021-10-29 20:58:57 +02:00
if ( actor . countBlessuresNonSoigneeByName ( "critiques" ) > 0 ) { // Pour éviter le cumul grave + critique
2022-09-07 18:47:56 +02:00
formData . isCritique = true ;
2021-10-29 20:58:57 +02:00
} else if ( actor . countBlessuresNonSoigneeByName ( "graves" ) > 0 ) {
2022-09-07 18:47:56 +02:00
formData . isGrave = true ;
2021-01-03 15:40:48 +01:00
}
2021-01-10 00:30:37 +01:00
2021-01-09 19:36:19 +01:00
ChatUtility . createChatWithRollMode ( actor . name , {
2022-09-07 18:47:56 +02:00
content : await renderTemplate ( ` systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html ` , formData )
2021-01-09 19:36:19 +01:00
} ) ;
2021-01-03 15:40:48 +01:00
}
2021-01-25 08:48:03 +01:00
}