@@ -3,6 +3,7 @@ import ABFFoundryRoll from '../rolls/ABFFoundryRoll';
33import { splitAsActorAndItemChanges } from './utils/splitAsActorAndItemChanges' ;
44import { unflat } from './utils/unflat' ;
55import { ALL_ITEM_CONFIGURATIONS } from './utils/prepareItems/constants' ;
6+ import { INITIAL_EFFECT_DATA } from '../types/effects/EffectItemConfig' ;
67import { getFieldValueFromPath } from './utils/prepareItems/util/getFieldValueFromPath' ;
78import { getUpdateObjectFromPath } from './utils/prepareItems/util/getUpdateObjectFromPath' ;
89import { ABFItems } from '../items/ABFItems' ;
@@ -98,18 +99,27 @@ export default class ABFActorSheet extends ActorSheet {
9899 async getData ( options ) {
99100 const sheet = await super . getData ( options ) ;
100101
101- if ( this . actor . type === 'character' ) {
102- await sheet . actor . prepareDerivedData ( ) ;
103- sheet . system = sheet . actor . system ;
102+ const actor = this . actor ; // use the real Document, not sheet.actor
103+
104+ if ( actor ?. type === 'character' ) {
105+ await actor . prepareDerivedData ( ) ;
106+ sheet . system = actor . system ;
104107 }
105108
106109 sheet . config = CONFIG . config ;
110+
107111 const permissions = game . settings . get (
108112 game . animabf . id ,
109113 ABFSettingsKeys . MODIFY_DICE_FORMULAS_PERMISSION
110114 ) ;
111115 sheet . canModifyDice = permissions ?. [ game . user . role ] === true ;
112- sheet . effects = this . actor . effects ?. contents ?? [ ] ;
116+
117+ // Use embedded item collection directly
118+ const effectItems = actor . items . filter ( i => i && i . type === ABFItems . EFFECT ) ;
119+ sheet . effects = effectItems ;
120+
121+ console . log ( 'EFFECT ITEMS EN SHEET' , sheet . effects ) ;
122+
113123 return sheet ;
114124 }
115125
@@ -175,31 +185,74 @@ export default class ABFActorSheet extends ActorSheet {
175185 const a = event . currentTarget ;
176186 const action = a . dataset . action ;
177187 const li = a . closest ( '.effect' ) ;
178- const effectId = li ?. dataset . effectId ;
188+ const itemId = li ?. dataset . itemId ;
189+ const item = itemId ? this . actor . items . get ( itemId ) : null ;
179190
180191 switch ( action ) {
181- case 'create' :
192+ case 'create' : {
182193 const name = game . i18n . localize ( 'anima.effects.newEffect' ) ?? 'New Effect' ;
183- return this . actor . createEmbeddedDocuments ( 'ActiveEffect ' , [
194+ const [ created ] = await this . actor . createEmbeddedDocuments ( 'Item ' , [
184195 {
196+ type : ABFItems . EFFECT ,
185197 name,
186- icon : 'icons/svg/aura.svg'
198+ system : INITIAL_EFFECT_DATA
187199 }
188200 ] ) ;
201+ if ( created ?. sheet ) created . sheet . render ( true ) ;
202+ return ;
203+ }
189204
190205 case 'edit' : {
191- const effect = this . actor . effects . get ( effectId ) ;
192- return effect ?. sheet ?. render ( true ) ;
206+ if ( ! item ) return ;
207+
208+ // Asegura que exista un AE vinculado a este item
209+ const effect = await this . _ensureEffectForItem ( item ) ;
210+ if ( ! effect ) return ;
211+
212+ // Configura la sincronización item <-> AE
213+ this . _setupEffectSync ( item , effect ) ;
214+
215+ return effect . sheet ?. render ( true ) ;
193216 }
194217
195- case 'delete' :
196- return this . actor . deleteEmbeddedDocuments ( 'ActiveEffect' , [ effectId ] ) ;
218+ case 'delete' : {
219+ if ( ! itemId ) return ;
220+
221+ const item = this . actor . items . get ( itemId ) ;
222+ if ( ! item ) return ;
223+
224+ // get linked AE
225+ const effect = this . _getLinkedEffect ( item ) ;
226+
227+ const deletions = [ ] ;
228+
229+ // delete item
230+ deletions . push ( this . actor . deleteEmbeddedDocuments ( 'Item' , [ itemId ] ) ) ;
231+
232+ // delete linked AE
233+ if ( effect ) {
234+ deletions . push ( this . actor . deleteEmbeddedDocuments ( 'ActiveEffect' , [ effect . id ] ) ) ;
235+ }
236+
237+ return Promise . all ( deletions ) ;
238+ }
197239
198240 case 'toggle' : {
199- const effect = this . actor . effects . get ( effectId ) ;
200- if ( ! effect ) return ;
201- return effect . update ( { disabled : ! effect . disabled } ) ;
241+ if ( ! item ) return ;
242+
243+ const newActive = ! item . system . active ;
244+ await item . update ( { 'system.active' : newActive } ) ;
245+
246+ const effect = this . _getLinkedEffect ( item ) ;
247+ if ( effect ) {
248+ await effect . update ( { disabled : ! newActive } ) ;
249+ }
250+
251+ return ;
202252 }
253+
254+ default :
255+ return ;
203256 }
204257 }
205258
@@ -356,4 +409,80 @@ export default class ABFActorSheet extends ActorSheet {
356409 ...otherItems
357410 ] ) ;
358411 } ;
412+
413+ _getLinkedEffect ( item ) {
414+ if ( ! item ) return null ;
415+ return this . actor . effects . find ( e => e . origin === item . uuid ) ?? null ;
416+ }
417+
418+ async _linkItemToEffect ( item , effect ) {
419+ if ( ! item || ! effect ) return ;
420+ await item . setFlag ( 'animabf' , 'linkedEffectId' , effect . id ) ;
421+ }
422+
423+ async _ensureEffectForItem ( item ) {
424+ if ( ! item ) return null ;
425+
426+ let effect = this . _getLinkedEffect ( item ) ;
427+ if ( effect ) return effect ;
428+
429+ const rawBaseData = item . system ?. effectData ?? { } ;
430+ // Ignore old origin if it exists in stored data
431+ const { origin, ...baseData } = rawBaseData ;
432+
433+ const data = foundry . utils . mergeObject (
434+ {
435+ name : item . name ,
436+ icon : item . img || 'icons/svg/aura.svg' ,
437+ disabled : ! item . system ?. active ,
438+ origin : item . uuid // always the current item
439+ } ,
440+ baseData ,
441+ { inplace : false }
442+ ) ;
443+
444+ const [ created ] = await this . actor . createEmbeddedDocuments ( 'ActiveEffect' , [ data ] ) ;
445+ return created ?? null ;
446+ }
447+
448+ async _onDropItem ( event , data ) {
449+ const created = await super . _onDropItem ( event , data ) ;
450+
451+ const items = Array . isArray ( created ) ? created : created ? [ created ] : [ ] ;
452+
453+ for ( const item of items ) {
454+ if ( item . type !== ABFItems . EFFECT ) continue ;
455+
456+ await item . update ( {
457+ 'system.active' : false ,
458+ 'system.effectData.disabled' : true
459+ } ) ;
460+
461+ await this . _ensureEffectForItem ( item ) ;
462+ }
463+
464+ return created ;
465+ }
466+
467+ _setupEffectSync ( item , effect ) {
468+ const handler = async ( doc , diff , options , userId ) => {
469+ if ( doc . id !== effect . id ) return ;
470+ if ( userId !== game . user . id ) return ;
471+
472+ if ( doc . transfer === true ) {
473+ await doc . update ( { transfer : false } ) ;
474+ return ;
475+ }
476+
477+ const obj = doc . toObject ( ) ;
478+ const { _id, _key, parent, ...clean } = obj ;
479+
480+ await item . update ( { 'system.effectData' : clean } ) ;
481+ await item . update ( { 'system.active' : ! doc . disabled } ) ;
482+
483+ Hooks . off ( 'updateActiveEffect' , handler ) ;
484+ } ;
485+
486+ Hooks . on ( 'updateActiveEffect' , handler ) ;
487+ }
359488}
0 commit comments