2024-06-01 00:17:39 +02:00
import { ChatVente } from "../achat-vente/chat-vente.js" ;
2023-01-01 22:10:03 +01:00
import { ChatUtility } from "../chat-utility.js" ;
2022-12-28 23:36:48 +01:00
import { SYSTEM _SOCKET _ID } from "../constants.js" ;
2023-11-04 03:42:39 +01:00
import { Grammar } from "../grammar.js" ;
2022-12-28 23:36:48 +01:00
import { Monnaie } from "../item-monnaie.js" ;
2024-09-25 22:56:24 +02:00
import { ITEM _TYPES } from "../item.js" ;
2022-12-28 23:36:48 +01:00
import { Misc } from "../misc.js" ;
2023-01-01 22:10:03 +01:00
import { RdDAudio } from "../rdd-audio.js" ;
2023-06-05 20:18:05 +02:00
import { RdDConfirm } from "../rdd-confirm.js" ;
2022-12-29 02:25:45 +01:00
import { RdDUtility } from "../rdd-utility.js" ;
2022-12-28 23:36:48 +01:00
import { SystemCompendiums } from "../settings/system-compendiums.js" ;
export class RdDBaseActor extends Actor {
2023-11-04 03:42:39 +01:00
2023-12-10 22:13:05 +01:00
static _findCaracNode ( carac , name ) {
return Object . entries ( carac )
. filter ( it => Grammar . equalsInsensitive ( it [ 1 ] . label , name ) )
. map ( it => it [ 0 ] )
2024-05-26 22:13:47 +02:00
. find ( it => it )
2023-12-10 22:13:05 +01:00
}
static $findCaracByName ( carac , name ) {
2023-11-04 03:42:39 +01:00
const caracList = Object . entries ( carac ) ;
let entry = Misc . findFirstLike ( name , caracList , { mapper : it => it [ 0 ] , description : 'caractéristique' } ) ;
if ( ! entry || entry . length == 0 ) {
entry = Misc . findFirstLike ( name , caracList , { mapper : it => it [ 1 ] . label , description : 'caractéristique' } ) ;
}
return entry && entry . length > 0 ? carac [ entry [ 0 ] ] : undefined ;
}
2022-12-28 23:36:48 +01:00
static getDefaultImg ( itemType ) {
return game . system . rdd . actorClasses [ itemType ] ? . defaultIcon ? ? defaultItemImg [ itemType ] ;
}
static init ( ) {
2024-06-11 02:48:37 +02:00
Hooks . on ( "preUpdateItem" , ( item , change , options , id ) => Misc . documentIfResponsible ( item . parent ) ? . onPreUpdateItem ( item , change , options , id ) )
Hooks . on ( "createItem" , ( item , options , id ) => Misc . documentIfResponsible ( item . parent ) ? . onCreateItem ( item , options , id ) )
Hooks . on ( "deleteItem" , ( item , options , id ) => Misc . documentIfResponsible ( item . parent ) ? . onDeleteItem ( item , options , id ) )
Hooks . on ( "updateActor" , ( actor , change , options , actorId ) => Misc . documentIfResponsible ( actor ) ? . onUpdateActor ( change , options , actorId ) )
2022-12-28 23:36:48 +01:00
}
static onSocketMessage ( sockmsg ) {
switch ( sockmsg . msg ) {
case "msg_remote_actor_call" :
return RdDBaseActor . onRemoteActorCall ( sockmsg . data , sockmsg . userId ) ;
2023-04-21 22:23:40 +02:00
}
2022-12-28 23:36:48 +01:00
}
static remoteActorCall ( callData , userId = undefined ) {
userId = userId ? ? Misc . firstConnectedGMId ( ) ;
if ( userId == game . user . id ) {
RdDBaseActor . onRemoteActorCall ( callData , userId ) ;
return false ;
}
else {
game . socket . emit ( SYSTEM _SOCKET _ID , { msg : "msg_remote_actor_call" , data : callData , userId : userId } ) ;
return true ;
}
}
static onRemoteActorCall ( callData , userId ) {
if ( userId == game . user . id ) {
2023-11-23 01:45:03 +01:00
const actor = RdDBaseActor . getRealActor ( callData ? . actorId , callData ? . tokenId ) ;
2022-12-28 23:36:48 +01:00
if ( Misc . isOwnerPlayerOrUniqueConnectedGM ( actor ) ) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
const args = callData . args ;
console . info ( ` RdDBaseActor.onRemoteActorCall: pour l'Actor ${ callData . actorId } , appel de RdDBaseActor. ${ callData . method } ( ` , ... args , ')' ) ;
actor [ callData . method ] ( ... args ) ;
}
}
}
2023-11-23 01:45:03 +01:00
static getRealActor ( actorId , tokenId ) {
if ( tokenId ) {
let token = canvas . tokens . get ( tokenId )
if ( token ) {
return token . actor
}
}
return game . actors . get ( actorId )
}
2024-11-15 00:01:55 +01:00
getAlias ( ) {
if ( this . token ? . name != null && this . token != this . prototypeToken ) {
return this . token . name
}
return this . name
}
2024-03-09 23:12:13 +01:00
isPersonnageJoueur ( ) { return false }
2023-11-21 16:03:26 +01:00
static extractActorMin = ( actor ) => { return { id : actor ? . id , type : actor ? . type , name : actor ? . name , img : actor ? . img } ; } ;
2022-12-28 23:36:48 +01:00
/ * *
2023-11-21 16:03:26 +01:00
* Cette methode surcharge Actor . create ( ) pour ajouter si besoin des Items par défaut :
2022-12-28 23:36:48 +01:00
* compétences et monnaies .
2023-11-21 16:03:26 +01:00
*
* @ param { Object } actorData template d ' acteur auquel ajouter des informations .
* @ param { Object } options optionspour customiser la création
* /
2022-12-28 23:36:48 +01:00
static async create ( actorData , options ) {
// import depuis un compendium
if ( actorData instanceof Array ) {
return super . create ( actorData , options ) ;
}
// Création d'un acteur avec des items (uniquement en cas de duplication): pas besoin d'ajouter d'items
if ( actorData . items ) {
return await super . create ( actorData , options ) ;
}
2023-01-01 22:10:03 +01:00
actorData . items = [ ] ;
2022-12-28 23:36:48 +01:00
if ( actorData . type == "personnage" ) {
const competences = await SystemCompendiums . getCompetences ( actorData . type ) ;
2023-01-01 22:10:03 +01:00
actorData . items = actorData . items . concat ( competences . map ( i => i . toObject ( ) ) )
2022-12-28 23:36:48 +01:00
. concat ( Monnaie . monnaiesStandard ( ) ) ;
}
2023-01-01 22:10:03 +01:00
else if ( actorData . type == "commerce" ) {
actorData . items = actorData . items . concat ( Monnaie . monnaiesStandard ( ) ) ;
2022-12-28 23:36:48 +01:00
}
return super . create ( actorData , options ) ;
}
constructor ( docData , context = { } ) {
if ( ! context . rdd ? . ready ) {
2024-05-01 09:13:21 +02:00
foundry . utils . mergeObject ( context , { rdd : { ready : true } } ) ;
2022-12-28 23:36:48 +01:00
const ActorConstructor = game . system . rdd . actorClasses [ docData . type ] ;
if ( ActorConstructor ) {
if ( ! docData . img ) {
docData . img = ActorConstructor . defaultIcon ;
}
return new ActorConstructor ( docData , context ) ;
}
}
2024-06-29 00:03:38 +02:00
context . rdd = undefined
2022-12-28 23:36:48 +01:00
super ( docData , context ) ;
}
2023-12-10 22:13:05 +01:00
findCaracByName ( name ) {
name = Grammar . toLowerCaseNoAccent ( name )
switch ( name ) {
case 'reve-actuel' : case 'reve actuel' :
return this . system . carac . reve
case 'chance-actuelle' : case 'chance actuelle' :
return this . system . carac . chance
case 'vie' :
return this . system . sante . vie
}
const carac = this . system . carac ;
return RdDBaseActor . $findCaracByName ( carac , name ) ;
}
2023-11-21 16:03:26 +01:00
getCaracByName ( name ) {
switch ( Grammar . toLowerCaseNoAccent ( name ) ) {
case 'reve-actuel' : case 'reve actuel' :
return this . getCaracReveActuel ( ) ;
case 'chance-actuelle' : case 'chance-actuelle' :
return this . getCaracChanceActuelle ( ) ;
}
2023-12-10 22:13:05 +01:00
return this . findCaracByName ( name ) ;
2023-11-21 16:03:26 +01:00
}
2023-11-04 17:48:59 +01:00
/* -------------------------------------------- */
async _preCreate ( data , options , user ) {
await super . _preCreate ( data , options , user ) ;
// Configure prototype token settings
const prototypeToken = { } ;
if ( this . type === "personnage" ) Object . assign ( prototypeToken , {
sight : { enabled : true } , actorLink : true , disposition : CONST . TOKEN _DISPOSITIONS . FRIENDLY
} ) ;
this . updateSource ( { prototypeToken } ) ;
}
/* -------------------------------------------- */
2023-11-04 03:42:39 +01:00
prepareData ( ) {
super . prepareData ( )
this . prepareActorData ( )
this . cleanupConteneurs ( )
this . computeEtatGeneral ( )
this . computeEncTotal ( )
}
async prepareActorData ( ) { }
async computeEtatGeneral ( ) { }
/* -------------------------------------------- */
2023-11-04 17:48:50 +01:00
findPlayer ( ) {
return game . users . players . find ( player => player . active && player . character ? . id == this . id ) ;
}
2023-11-04 03:42:39 +01:00
2023-11-04 17:48:50 +01:00
isCreatureEntite ( ) { return this . isCreature ( ) || this . isEntite ( ) }
isCreature ( ) { return false }
2023-11-04 03:42:39 +01:00
isEntite ( typeentite = [ ] ) { return false }
2023-11-04 18:14:10 +01:00
isVehicule ( ) { return false }
2023-11-04 17:48:50 +01:00
isPersonnage ( ) { return false }
2022-12-28 23:36:48 +01:00
getItem ( id , type = undefined ) {
const item = this . items . get ( id ) ;
if ( type == undefined || ( item ? . type == type ) ) {
return item ;
}
return undefined ;
}
2023-11-21 21:07:37 +01:00
2023-11-21 16:03:26 +01:00
listeSuivants ( filter = suivant => true ) { return [ ] }
2023-12-10 22:13:05 +01:00
listeSuivants ( filter = suivant => true ) { return [ ] }
2022-12-28 23:36:48 +01:00
listItems ( type = undefined ) { return ( type ? this . itemTypes [ type ] : this . items ) ; }
2023-06-24 00:44:50 +02:00
filterItems ( filter , type = undefined ) { return ( type ? this . itemTypes [ type ] : this . items ) ? . filter ( filter ) ? ? [ ] ; }
2022-12-28 23:36:48 +01:00
findItemLike ( idOrName , type ) {
return this . getItem ( idOrName , type )
? ? Misc . findFirstLike ( idOrName , this . listItems ( type ) , { description : Misc . typeName ( 'Item' , type ) } ) ;
}
2023-01-01 22:10:03 +01:00
getMonnaie ( id ) { return this . findItemLike ( id , 'monnaie' ) ; }
2023-11-03 20:21:17 +01:00
getEncombrementMax ( ) { return 0 }
2023-01-01 22:10:03 +01:00
2022-12-28 23:36:48 +01:00
/* -------------------------------------------- */
async onPreUpdateItem ( item , change , options , id ) { }
async onCreateItem ( item , options , id ) { }
async onUpdateActor ( update , options , actorId ) { }
2024-11-29 22:11:24 +01:00
async onDeleteItem ( item , options , id ) {
if ( item . isInventaire ( ) ) {
this . _removeItemFromConteneur ( item )
}
}
_removeItemFromConteneur ( item ) {
this . items . filter ( it => it . isConteneur ( ) && it . system . contenu . includes ( item . id ) )
. forEach ( conteneur => {
const nouveauContenu = conteneur . system . contenu . filter ( id => id != item . id ) ;
conteneur . update ( { 'system.contenu' : nouveauContenu } ) ;
} ) ;
}
2022-12-28 23:36:48 +01:00
2023-01-07 23:28:30 +01:00
async onTimeChanging ( oldTimestamp , newTimestamp ) {
this . items . filter ( it => it . isFinPeriode ( oldTimestamp , newTimestamp ) )
. forEach ( async it => await it . onFinPeriodeTemporel ( oldTimestamp , newTimestamp ) )
}
2023-07-29 23:42:05 +02:00
async creerObjetParMJ ( object ) {
2024-10-23 23:42:38 +02:00
if ( ! Misc . isFirstConnectedGM ( ) ) {
2023-06-14 22:25:11 +02:00
RdDBaseActor . remoteActorCall ( {
2023-08-13 20:42:54 +02:00
tokenId : this . token ? . id ,
2023-06-14 22:25:11 +02:00
actorId : this . id ,
method : 'creerObjetParMJ' ,
args : [ object ]
} ) ;
return ;
}
await this . createEmbeddedDocuments ( 'Item' , [ object ] )
}
2023-11-04 03:42:39 +01:00
/* -------------------------------------------- */
async cleanupConteneurs ( ) {
2024-07-04 20:49:57 +02:00
if ( Misc . isOwnerPlayerOrUniqueConnectedGM ( this ) ) {
let updates = this . itemTypes [ 'conteneur' ]
. filter ( c => c . system . contenu . filter ( id => this . getItem ( id ) == undefined ) . length > 0 )
. map ( c => { return { _id : c . _id , 'system.contenu' : c . system . contenu . filter ( id => this . getItem ( id ) != undefined ) } } ) ;
if ( updates . length > 0 ) {
await this . updateEmbeddedDocuments ( "Item" , updates )
}
2023-11-04 03:42:39 +01:00
}
}
2023-01-01 22:10:03 +01:00
/* -------------------------------------------- */
2022-12-28 23:36:48 +01:00
getFortune ( ) {
return Monnaie . getFortune ( this . itemTypes [ 'monnaie' ] ) ;
}
2023-01-01 22:10:03 +01:00
/* -------------------------------------------- */
2023-03-30 02:56:06 +02:00
async itemQuantiteIncDec ( id , value ) {
let item = this . getItem ( id ) ;
if ( item && item . isInventaire ( ) ) {
const quantite = Math . max ( 0 , item . system . quantite + value ) ;
2023-11-21 16:03:26 +01:00
await item . update ( { 'system.quantite' : quantite } ) ;
2023-01-01 22:10:03 +01:00
}
}
computePrixTotalEquipement ( ) {
return this . items . filter ( it => it . isInventaire ( ) )
. filter ( it => ! it . isMonnaie ( ) )
. map ( it => it . valeurTotale ( ) )
. reduce ( Misc . sum ( ) , 0 ) ;
}
async payerSols ( depense ) {
depense = Number ( depense ) ;
if ( depense == 0 ) {
return ;
}
let fortune = this . getFortune ( ) ;
console . log ( "payer" , game . user . character , depense , fortune ) ;
2024-10-16 23:18:15 +02:00
// TODO: passer en handlebars
2023-01-01 22:10:03 +01:00
let msg = "" ;
if ( fortune >= depense ) {
await Monnaie . optimiserFortune ( this , fortune - depense ) ;
msg = ` Vous avez payé <strong> ${ depense } Sols</strong>, qui ont été soustraits de votre argent. ` ;
RdDAudio . PlayContextAudio ( "argent" ) ; // Petit son
} else {
msg = "Vous n'avez pas assez d'argent pour payer cette somme !" ;
}
2024-10-16 23:18:15 +02:00
ChatMessage . create ( {
whisper : ChatUtility . getOwners ( this ) ,
2023-01-01 22:10:03 +01:00
content : msg
2024-10-16 23:18:15 +02:00
} )
2023-01-01 22:10:03 +01:00
}
async depenserSols ( sols ) {
let reste = this . getFortune ( ) - Number ( sols ) ;
if ( reste >= 0 ) {
await Monnaie . optimiserFortune ( this , reste ) ;
}
return reste ;
}
async ajouterSols ( sols , fromActorId = undefined ) {
sols = Number ( sols ) ;
if ( sols == 0 ) {
return ;
}
if ( sols < 0 ) {
ui . notifications . error ( ` Impossible d'ajouter un gain de ${ sols } <0 ` ) ;
return ;
}
if ( fromActorId && ! game . user . isGM ) {
RdDBaseActor . remoteActorCall ( {
userId : Misc . connectedGMOrUser ( ) ,
2023-08-15 17:24:01 +02:00
tokenId : this . token ? . id ,
2023-01-01 22:10:03 +01:00
actorId : this . id ,
method : 'ajouterSols' , args : [ sols , fromActorId ]
} ) ;
}
else {
const fromActor = game . actors . get ( fromActorId )
await Monnaie . optimiserFortune ( this , sols + this . getFortune ( ) ) ;
RdDAudio . PlayContextAudio ( "argent" ) ; // Petit son
ChatMessage . create ( {
2024-11-03 21:29:18 +01:00
whisper : ChatUtility . getOwners ( this ) ,
2023-01-01 22:10:03 +01:00
content : ` Vous avez reçu <strong> ${ sols } Sols</strong> ${ fromActor ? " de " + fromActor . name : '' } , qui ont été ajoutés à votre argent. `
} ) ;
}
}
/* -------------------------------------------- */
getQuantiteDisponible ( item ) {
2023-01-03 13:38:04 +01:00
return item ? . isService ( ) ? undefined : item ? . getQuantite ( ) ;
2023-01-01 22:10:03 +01:00
}
/* -------------------------------------------- */
async achatVente ( achat ) {
if ( achat . vendeurId == achat . acheteurId ) {
ui . notifications . info ( "Inutile de se vendre à soi-même" ) ;
return ;
}
2024-10-23 23:42:38 +02:00
if ( ! Misc . isFirstConnectedGM ( ) ) {
2023-01-01 22:10:03 +01:00
RdDBaseActor . remoteActorCall ( {
actorId : achat . vendeurId ? ? achat . acheteurId ,
method : 'achatVente' ,
args : [ achat ]
} ) ;
return ;
}
const cout = Number ( achat . prixTotal ? ? 0 ) ;
const vendeur = achat . vendeurId ? game . actors . get ( achat . vendeurId ) : undefined ;
const acheteur = achat . acheteurId ? game . actors . get ( achat . acheteurId ) : undefined ;
2023-04-07 00:33:29 +02:00
const quantite = ( achat . choix . nombreLots ? ? 1 ) * ( achat . vente . tailleLot ) ;
2023-06-12 23:04:32 +02:00
const itemVendu = vendeur ? . getItem ( achat . vente . item . _id ) ? ? game . items . get ( achat . vente . item . _id ) ;
2023-04-18 22:59:15 +02:00
if ( ! itemVendu ) {
2023-07-29 23:42:05 +02:00
ChatUtility . notifyUser ( achat . userId , 'warn' , vendeur ? ` Le vendeur n'a pas plus de ${ achat . vente . item . name } ! ` : ` Impossible de retrouver: ${ achat . vente . item . name } ! ` ) ;
2023-04-18 22:59:15 +02:00
return ;
}
2023-07-27 19:16:59 +02:00
if ( vendeur && ! vendeur . verifierQuantite ( itemVendu , quantite ) ) {
2023-01-01 22:10:03 +01:00
ChatUtility . notifyUser ( achat . userId , 'warn' , ` Le vendeur n'a pas assez de ${ itemVendu . name } ! ` ) ;
return
}
if ( acheteur && ! acheteur . verifierFortune ( cout ) ) {
ChatUtility . notifyUser ( achat . userId , 'warn' , ` Vous n'avez pas assez d'argent pour payer ${ Math . ceil ( cout / 100 ) } sols ! ` ) ;
return ;
}
2024-06-01 00:17:39 +02:00
await vendeur ? . vendre ( itemVendu , quantite , cout ) ;
await acheteur ? . acheter ( itemVendu , quantite , cout , achat )
2023-01-01 22:10:03 +01:00
if ( cout > 0 ) {
RdDAudio . PlayContextAudio ( "argent" ) ;
}
2024-05-02 14:08:02 +02:00
const chatAchatItem = foundry . utils . duplicate ( achat . vente ) ;
2023-01-01 22:10:03 +01:00
chatAchatItem . quantiteTotal = quantite ;
ChatMessage . create ( {
user : achat . userId ,
2024-11-15 00:01:55 +01:00
speaker : { alias : ( acheteur ? ? vendeur ) . getAlias ( ) } ,
2024-10-16 23:18:15 +02:00
whisper : ChatUtility . getOwners ( this ) ,
2023-01-01 22:10:03 +01:00
content : await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html' , chatAchatItem )
} ) ;
2023-04-07 00:33:29 +02:00
if ( ! achat . vente . quantiteIllimite ) {
2024-06-01 00:17:39 +02:00
if ( achat . vente . nbLots <= achat . choix . nombreLots ) {
2023-01-01 22:10:03 +01:00
ChatUtility . removeChatMessageId ( achat . chatMessageIdVente ) ;
}
else if ( achat . chatMessageIdVente ) {
2024-06-11 02:48:37 +02:00
await ChatVente . diminuerQuantiteAchatVente ( achat . chatMessageIdVente , achat . choix . nombreLots )
2023-01-01 22:10:03 +01:00
}
}
}
2024-06-01 00:17:39 +02:00
async vendre ( item , quantite , cout ) {
await this . ajouterSols ( cout ) ;
await this . decrementerQuantiteItem ( item , quantite ) ;
}
async acheter ( item , quantite , cout , achat ) {
await this . depenserSols ( cout )
const createdItemId = await this . creerQuantiteItem ( item , quantite )
if ( achat . choix . consommer && item . type == 'nourritureboisson' && createdItemId != undefined ) {
achat . choix . doses = achat . choix . nombreLots ;
await this . consommerNourritureboisson ( createdItemId , achat . choix , achat . vente . actingUserId ) ;
2023-01-01 22:10:03 +01:00
}
}
verifierFortune ( cout ) {
return this . getFortune ( ) >= cout ;
}
2023-06-12 23:04:32 +02:00
verifierQuantite ( item , quantiteDemande ) {
2023-07-27 19:16:59 +02:00
const disponible = this . getQuantiteDisponible ( item ) ;
2023-06-12 23:04:32 +02:00
return disponible == undefined || disponible >= quantiteDemande ;
2023-01-01 22:10:03 +01:00
}
2024-06-01 00:17:39 +02:00
async consommerNourritureboisson ( itemId , choix , userId ) { }
2023-01-01 22:10:03 +01:00
2023-01-03 00:31:32 +01:00
async decrementerQuantiteItem ( item , quantite , options = { supprimerSiZero : true } ) {
2023-01-05 14:32:35 +01:00
if ( item . isService ( ) ) {
2023-01-03 13:38:04 +01:00
return ;
}
2024-06-01 00:17:39 +02:00
const itemId = item . id ;
2023-01-01 22:10:03 +01:00
let resteQuantite = ( item . system . quantite ? ? 1 ) - quantite ;
if ( resteQuantite <= 0 ) {
if ( options . supprimerSiZero ) {
await this . deleteEmbeddedDocuments ( "Item" , [ item . id ] ) ;
}
2023-01-03 00:31:32 +01:00
else {
2024-06-01 00:17:39 +02:00
await this . updateEmbeddedDocuments ( "Item" , [ { _id : itemId , 'system.quantite' : 0 } ] ) ;
2023-01-01 22:10:03 +01:00
}
if ( resteQuantite < 0 ) {
ui . notifications . warn ( ` La quantité de ${ item . name } était insuffisante, l'objet a donc été supprimé ` )
}
}
else if ( resteQuantite > 0 ) {
2024-06-01 00:17:39 +02:00
const realItem = this . getItem ( item . id )
realItem . update ( { 'system.quantite' : resteQuantite } ) ;
2023-01-01 22:10:03 +01:00
await this . updateEmbeddedDocuments ( "Item" , [ { _id : item . id , 'system.quantite' : resteQuantite } ] ) ;
}
}
async creerQuantiteItem ( item , quantite ) {
2023-01-03 00:31:32 +01:00
if ( this . canReceive ( item ) ) {
const isItemEmpilable = "quantite" in item . system ;
const baseItem = {
type : item . type ,
img : item . img ,
name : item . name ,
2024-06-01 00:17:39 +02:00
system : foundry . utils . mergeObject ( item . system , { quantite : isItemEmpilable ? quantite : undefined } , { inplace : false } )
2023-01-03 00:31:32 +01:00
} ;
const newItems = isItemEmpilable ? [ baseItem ] : Array . from ( { length : quantite } , ( _ , i ) => baseItem ) ;
const items = await this . createEmbeddedDocuments ( "Item" , newItems ) ;
return items . length > 0 ? items [ 0 ] . id : undefined ;
}
2023-01-01 22:10:03 +01:00
}
/* -------------------------------------------- */
async computeEncTotal ( ) {
if ( ! this . pack ) {
this . encTotal = this . items . map ( it => it . getEncTotal ( ) ) . reduce ( Misc . sum ( ) , 0 ) ;
return this . encTotal ;
}
return 0 ;
}
2023-11-04 03:42:39 +01:00
getEncTotal ( ) {
return Math . floor ( this . encTotal ? ? 0 ) ;
}
2022-12-28 23:36:48 +01:00
async createItem ( type , name = undefined ) {
if ( ! name ) {
name = 'Nouveau ' + Misc . typeName ( 'Item' , type ) ;
}
await this . createEmbeddedDocuments ( 'Item' , [ { name : name , type : type } ] , { renderSheet : true } ) ;
}
canReceive ( item ) {
return false ;
}
2022-12-29 02:25:45 +01:00
2023-01-01 22:10:03 +01:00
async processDropItem ( params ) {
2023-11-23 01:45:03 +01:00
const targetActorId = this . id
const sourceActorId = params . sourceActorId
const sourceTokenId = params . sourceTokenId
const itemId = params . itemId
const destId = params . destId
const srcId = params . srcId
2023-01-01 22:10:03 +01:00
if ( sourceActorId && sourceActorId != targetActorId ) {
2023-11-23 01:45:03 +01:00
console . log ( "Moving objects" , sourceActorId , sourceTokenId , targetActorId , itemId ) ;
this . moveItemsBetweenActors ( itemId , sourceActorId , sourceTokenId ) ;
2023-01-01 22:10:03 +01:00
return false ;
}
let result = true ;
const item = this . getItem ( itemId ) ;
2023-01-03 00:31:32 +01:00
if ( item ? . isInventaire ( 'all' ) && sourceActorId == targetActorId ) {
2023-01-01 22:10:03 +01:00
// rangement
if ( srcId != destId && itemId != destId ) { // déplacement de l'objet
const src = this . getItem ( srcId ) ;
const dest = this . getItem ( destId ) ;
const cible = this . getContenantOrParent ( dest ) ;
const [ empilable , message ] = item . isInventaireEmpilable ( dest ) ;
if ( empilable ) {
await dest . empiler ( item )
result = false ;
}
// changer de conteneur
else if ( ! cible || this . conteneurPeutContenir ( cible , item ) ) {
await this . enleverDeConteneur ( item , src , params . onEnleverConteneur ) ;
await this . ajouterDansConteneur ( item , cible , params . onAjouterDansConteneur ) ;
if ( message && ! dest . isConteneur ( ) ) {
ui . notifications . info ( cible
? ` ${ message } <br> ${ item . name } a été déplacé dans: ${ cible . name } `
: ` ${ message } <br> ${ item . name } a été sorti du conteneur ` ) ;
}
}
}
}
await this . computeEncTotal ( ) ;
return result ;
}
getContenantOrParent ( dest ) {
if ( ! dest || dest . isConteneur ( ) ) {
return dest ;
}
return this . getContenant ( dest ) ;
}
getContenant ( item ) {
return this . itemTypes [ 'conteneur' ] . find ( it => it . system . contenu . includes ( item . id ) ) ;
}
/* -------------------------------------------- */
2023-07-29 23:42:05 +02:00
conteneurPeutContenir ( dest , moved ) {
2023-01-01 22:10:03 +01:00
if ( ! dest ) {
return true ;
}
if ( ! dest . isConteneur ( ) ) {
return false ;
}
2023-07-29 23:42:05 +02:00
if ( moved . isConteneurContenu ( dest ) ) {
ui . notifications . warn ( ` Impossible de déplacer un conteneur parent ( ${ moved . name } ) dans un de ses contenus ${ dest . name } ! ` ) ;
return false ;
2023-01-01 22:10:03 +01:00
}
// Calculer le total actuel des contenus
2023-07-29 23:42:05 +02:00
const encContenu = dest . getEncContenu ( ) ;
const newEnc = moved . getEncTotal ( ) ; // Calculer le total actuel du nouvel objet
2024-09-27 02:30:48 +02:00
const placeDisponible = Misc . keepDecimals ( dest . system . capacite - encContenu - newEnc , 4 )
2023-01-01 22:10:03 +01:00
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
2023-07-29 23:42:05 +02:00
if ( placeDisponible < 0 ) {
2023-01-01 22:10:03 +01:00
ui . notifications . warn (
2023-07-29 23:42:05 +02:00
` Le conteneur ${ dest . name } a une capacité de ${ dest . system . capacite } , et contient déjà ${ encContenu } .
Impossible d 'y ranger: ${moved.name} d' encombrement $ { newEnc } ! ` );
2023-01-01 22:10:03 +01:00
return false ;
}
return true ;
}
/* -------------------------------------------- */
2023-11-21 16:03:26 +01:00
/** Ajoute un item dans un conteneur, sur la base de leurs ID */
2023-01-01 22:10:03 +01:00
async ajouterDansConteneur ( item , conteneur , onAjouterDansConteneur ) {
2024-08-01 01:05:00 +02:00
if ( conteneur ? . isConteneur ( ) ) {
2023-01-01 22:10:03 +01:00
item . estContenu = true ;
2023-11-21 16:03:26 +01:00
const nouveauContenu = [ ... conteneur . system . contenu , item . id ] ;
await conteneur . update ( { 'system.contenu' : nouveauContenu } ) ;
2024-08-01 01:05:00 +02:00
onAjouterDansConteneur ( item . id , conteneur . id )
}
else {
item . estContenu = false ;
await conteneur ? . update ( { 'system.-=contenu' : undefined } )
2023-01-01 22:10:03 +01:00
}
}
/* -------------------------------------------- */
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
async nettoyerConteneurs ( ) {
RdDConfirm . confirmer ( {
settingConfirmer : "confirmation-vider" ,
content : ` <p>Etes vous certain de vouloir vider tous les conteneurs ?</p> ` ,
title : 'Vider les conteneurs' ,
buttonLabel : 'Vider' ,
onAction : async ( ) => {
const corrections = [ ] ;
for ( let item of this . items ) {
if ( item . estContenu ) {
item . estContenu = undefined ;
}
2024-08-01 01:05:00 +02:00
if ( item . system . contenu != undefined ) {
if ( item . type == 'conteneur' ) {
corrections . push ( { _id : item . id , 'system.contenu' : [ ] } ) ;
}
else {
corrections . push ( { _id : item . id , 'system.-=contenu' : undefined } ) ;
}
2023-01-01 22:10:03 +01:00
}
}
if ( corrections . length > 0 ) {
await this . updateEmbeddedDocuments ( 'Item' , corrections ) ;
}
}
} ) ;
}
/* -------------------------------------------- */
buildSubConteneurObjetList ( conteneurId , deleteList ) {
let conteneur = this . getItem ( conteneurId ) ;
if ( conteneur ? . type == 'conteneur' ) { // Si c'est un conteneur
for ( let subId of conteneur . system . contenu ) {
let subObj = this . getItem ( subId ) ;
if ( subObj ) {
if ( subObj . type == 'conteneur' ) {
this . buildSubConteneurObjetList ( subId , deleteList ) ;
}
deleteList . push ( { id : subId , conteneurId : conteneurId } ) ;
}
}
}
}
/* -------------------------------------------- */
async deleteAllConteneur ( itemId , options ) {
let list = [ ] ;
list . push ( { id : itemId , conteneurId : undefined } ) ; // Init list
this . buildSubConteneurObjetList ( itemId , list ) ;
await this . deleteEmbeddedDocuments ( 'Item' , list . map ( it => it . id ) , options ) ;
}
/* -------------------------------------------- */
2024-08-01 01:05:00 +02:00
/ * *
* Supprime un item d ' un conteneur , sur la base de leurs ID
* /
2023-01-01 22:10:03 +01:00
async enleverDeConteneur ( item , conteneur , onEnleverDeConteneur ) {
2024-08-01 01:05:00 +02:00
if ( conteneur ) {
if ( conteneur . isConteneur ( ) ) {
const contenu = conteneur . system . contenu . filter ( id => id != item . id ) ;
await conteneur . update ( { 'system.contenu' : contenu } ) ;
onEnleverDeConteneur ( ) ;
}
else {
await conteneur . update ( { 'system.-=contenu' : undefined } )
}
2023-01-01 22:10:03 +01:00
}
2024-08-01 01:05:00 +02:00
item . estContenu = false ;
2023-01-01 22:10:03 +01:00
}
/* -------------------------------------------- */
2023-11-23 01:45:03 +01:00
async moveItemsBetweenActors ( itemId , sourceActorId , sourceTokenId ) {
let sourceActor = RdDBaseActor . getRealActor ( sourceActorId , sourceTokenId )
let itemsList = [ { id : itemId , conteneurId : undefined } ]
2023-01-01 22:10:03 +01:00
sourceActor . buildSubConteneurObjetList ( itemId , itemsList ) ; // Get itemId list
const itemsDataToCreate = itemsList . map ( it => sourceActor . getItem ( it . id ) )
2024-05-02 14:08:02 +02:00
. map ( it => foundry . utils . duplicate ( it ) )
2023-01-01 22:10:03 +01:00
. map ( it => { it . system . contenu = [ ] ; return it ; } ) ;
let newItems = await this . createEmbeddedDocuments ( 'Item' , itemsDataToCreate ) ;
let itemMap = this . _buildMapOldNewId ( itemsList , newItems ) ;
for ( let item of itemsList ) { // Second boucle pour traiter la remise en conteneurs
// gestion conteneur/contenu
if ( item . conteneurId ) { // l'Objet était dans un conteneur
2023-11-21 16:03:26 +01:00
const newConteneurId = itemMap [ item . conteneurId ] ;
const newConteneur = this . getItem ( newConteneurId ) ;
const newItemId = itemMap [ item . id ] ; // Get newItem
2023-01-01 22:10:03 +01:00
console . log ( 'New conteneur filling!' , newConteneur , newItemId , item ) ;
2023-11-21 16:03:26 +01:00
const nouveauContenu = [ ... newConteneur . system . contenu , newItemId ]
await newConteneur . update ( { 'system.contenu' : nouveauContenu } )
2023-01-01 22:10:03 +01:00
}
}
2023-11-21 16:03:26 +01:00
const deletedItemIds = itemsList . map ( it => it . id )
await sourceActor . deleteEmbeddedDocuments ( 'Item' , deletedItemIds ) ;
2023-01-01 22:10:03 +01:00
}
_buildMapOldNewId ( itemsList , newItems ) {
let itemMap = { } ;
for ( let i = 0 ; i < itemsList . length ; i ++ ) {
itemMap [ itemsList [ i ] . id ] = newItems [ i ] . id ; // Pour garder le lien ancien / nouveau
}
return itemMap ;
}
2022-12-29 02:25:45 +01:00
/* -------------------------------------------- */
async postActorToChat ( modeOverride ) {
let chatData = {
doctype : 'Actor' ,
id : this . id ,
type : this . type ,
img : this . img ,
pack : this . pack ,
2024-11-15 00:01:55 +01:00
name : this . getAlias ( ) ,
2022-12-29 02:25:45 +01:00
system : { description : this . system . description }
}
renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/post-actor.html' , chatData )
. then ( html => ChatMessage . create ( RdDUtility . chatDataSetup ( html , modeOverride ) ) ) ;
}
2023-11-04 03:42:39 +01:00
actionImpossible ( action ) {
2024-11-15 00:01:55 +01:00
ui . notifications . info ( ` ${ this . getAlias ( ) } ne peut pas faire cette action: ${ action } ` )
2022-12-29 02:25:45 +01:00
2023-11-04 03:42:39 +01:00
}
2024-11-15 00:01:55 +01:00
2023-11-04 03:42:39 +01:00
async jetEthylisme ( ) { this . actionImpossible ( "jet d'éthylisme" ) }
async rollAppelChance ( ) { this . actionImpossible ( "appel à la chance" ) }
async jetDeMoral ( ) { this . actionImpossible ( "jet de moral" ) }
2023-11-06 23:03:44 +01:00
2023-11-21 16:03:26 +01:00
async actionPrincipale ( item , onActionItem = async ( ) => { } ) {
2023-11-06 23:03:44 +01:00
switch ( item . type ) {
2024-09-25 22:56:24 +02:00
case ITEM _TYPES . conteneur : return await item . sheet . render ( true ) ;
2023-11-06 23:03:44 +01:00
}
return undefined
}
2024-11-03 23:31:56 +01:00
async resetItemUse ( ) { }
async incDecItemUse ( itemId , inc = 1 ) { }
getItemUse ( itemId ) { return 0 ; }
async finDeRound ( options = { terminer : false } ) { }
isActorCombat ( ) { return false }
2024-11-06 23:24:53 +01:00
getCaracInit ( competence ) { return 0 }
listActionsCombat ( ) { return [ ] }
listActionsPossessions ( ) {
return this . itemTypes [ ITEM _TYPES . possession ]
. map ( p => {
return {
name : p . name ,
action : 'possession' ,
system : {
competence : p . name ,
possessionid : p . system . possessionid ,
}
}
} )
}
2022-12-28 23:36:48 +01:00
}