@@ -4,6 +4,7 @@ import { FUItem } from '../documents/items/item.mjs';
44import { Flags } from './flags.mjs' ;
55import { FU , SYSTEM } from './config.mjs' ;
66import { FUActiveEffect } from '../documents/effects/active-effect.mjs' ;
7+ import { toggleStatusEffect } from './effects.mjs' ;
78
89const INLINE_EFFECT = 'InlineEffect' ;
910const INLINE_EFFECT_CLASS = 'inline-effect' ;
@@ -16,46 +17,61 @@ const enricher = {
1617 enricher : inlineEffectEnricher ,
1718} ;
1819
20+ function createEffectAnchor ( effect ) {
21+ const anchor = document . createElement ( 'a' ) ;
22+ anchor . draggable = true ;
23+ anchor . dataset . effect = toBase64 ( effect ) ;
24+ anchor . classList . add ( 'inline' , INLINE_EFFECT_CLASS , 'disable-how-to' ) ;
25+ const icon = document . createElement ( 'i' ) ;
26+ icon . classList . add ( 'fun' , 'fu-aura' ) ;
27+ anchor . append ( icon ) ;
28+ anchor . append ( effect . name ) ;
29+ return anchor ;
30+ }
31+
32+ function createBrokenAnchor ( ) {
33+ const anchor = document . createElement ( 'a' ) ;
34+ anchor . classList . add ( 'inline' , 'broken' ) ;
35+ const icon = document . createElement ( 'i' ) ;
36+ icon . classList . add ( 'fas' , 'fa-chain-broken' ) ;
37+ anchor . append ( icon ) ;
38+ anchor . append ( game . i18n . localize ( 'FU.InlineEffectInvalid' ) ) ;
39+ return anchor ;
40+ }
41+
42+ function createStatusAnchor ( effectValue , status ) {
43+ const anchor = document . createElement ( 'a' ) ;
44+ anchor . draggable = true ;
45+ anchor . dataset . status = effectValue ;
46+ anchor . classList . add ( 'inline' , INLINE_EFFECT_CLASS , 'disable-how-to' ) ;
47+ const icon = document . createElement ( 'i' ) ;
48+ icon . classList . add ( 'fun' , 'fu-aura' ) ;
49+ anchor . append ( icon ) ;
50+ anchor . append ( game . i18n . localize ( status . name ) ) ;
51+ return anchor ;
52+ }
53+
1954/**
2055 * @param text
2156 * @param options
2257 */
2358function inlineEffectEnricher ( text , options ) {
2459 /** @type string */
2560 const effectValue = text [ 1 ] ;
26- let effect ;
61+
2762 if ( SUPPORTED_STATUSES . includes ( effectValue ) || BOONS_AND_BANES . includes ( effectValue ) ) {
2863 const status = statusEffects . find ( ( value ) => value . id === effectValue ) ;
2964 if ( status ) {
30- status . name = game . i18n . localize ( status . name ) ;
31- effect = status ;
65+ return createStatusAnchor ( effectValue , status ) ;
3266 }
3367 } else {
3468 const decodedEffect = fromBase64 ( effectValue ) ;
3569 if ( decodedEffect && decodedEffect . name && decodedEffect . changes ) {
36- effect = decodedEffect ;
70+ return createEffectAnchor ( decodedEffect ) ;
3771 }
3872 }
3973
40- if ( effect ) {
41- const anchor = document . createElement ( 'a' ) ;
42- anchor . draggable = true ;
43- anchor . dataset . effect = toBase64 ( effect ) ;
44- anchor . classList . add ( 'inline' , INLINE_EFFECT_CLASS , 'disable-how-to' ) ;
45- const icon = document . createElement ( 'i' ) ;
46- icon . classList . add ( 'fun' , 'fu-aura' ) ;
47- anchor . append ( icon ) ;
48- anchor . append ( effect . name ) ;
49- return anchor ;
50- } else {
51- const anchor = document . createElement ( 'a' ) ;
52- anchor . classList . add ( 'inline' , 'broken' ) ;
53- const icon = document . createElement ( 'i' ) ;
54- icon . classList . add ( 'fas' , 'fa-chain-broken' ) ;
55- anchor . append ( icon ) ;
56- anchor . append ( game . i18n . localize ( 'FU.InlineEffectInvalid' ) ) ;
57- return anchor ;
58- }
74+ return createBrokenAnchor ( ) ;
5975}
6076
6177/**
@@ -71,14 +87,14 @@ function determineSource(document, element) {
7187 return document . uuid ;
7288 } else if ( document instanceof ChatMessage ) {
7389 const speakerActor = ChatMessage . getSpeakerActor ( document . speaker ) ;
74- if ( speakerActor ) {
75- return speakerActor . uuid ;
76- }
7790 const flagItem = document . getFlag ( SYSTEM , Flags . ChatMessage . Item ) ;
7891 if ( flagItem && speakerActor ) {
7992 const item = speakerActor . items . get ( flagItem . _id ) ;
8093 return item ? item . uuid : null ;
8194 }
95+ if ( speakerActor ) {
96+ return speakerActor . uuid ;
97+ }
8298 }
8399 return null ;
84100}
@@ -96,6 +112,7 @@ function activateListeners(document, html) {
96112 . on ( 'click' , function ( ) {
97113 const source = determineSource ( document , this ) ;
98114 const effectData = fromBase64 ( this . dataset . effect ) ;
115+ const status = this . dataset . status ;
99116 const controlledTokens = canvas . tokens . controlled ;
100117 let actors = [ ] ;
101118
@@ -110,7 +127,15 @@ function activateListeners(document, html) {
110127 }
111128
112129 if ( actors . length > 0 ) {
113- actors . forEach ( ( actor ) => onApplyEffectToActor ( actor , source , effectData ) ) ;
130+ if ( effectData ) {
131+ actors . forEach ( ( actor ) => onApplyEffectToActor ( actor , source , effectData ) ) ;
132+ } else if ( status ) {
133+ actors . forEach ( ( actor ) => {
134+ if ( ! actor . statuses . has ( status ) ) {
135+ toggleStatusEffect ( actor , status , source ) ;
136+ }
137+ } ) ;
138+ }
114139 } else {
115140 ui . notifications . warn ( game . i18n . localize ( 'FU.ChatApplyEffectNoActorsSelected' ) ) ;
116141 }
@@ -127,26 +152,39 @@ function activateListeners(document, html) {
127152 type : INLINE_EFFECT ,
128153 source : source ,
129154 effect : fromBase64 ( this . dataset . effect ) ,
155+ status : this . dataset . status ,
130156 } ;
131157 event . dataTransfer . setData ( 'text/plain' , JSON . stringify ( data ) ) ;
132158 event . stopPropagation ( ) ;
133159 } )
134160 . on ( 'contextmenu' , function ( event ) {
135161 event . preventDefault ( ) ;
136162 event . stopPropagation ( ) ;
137- const effectData = fromBase64 ( this . dataset . effect ) ;
138- const cls = getDocumentClass ( 'ActiveEffect' ) ;
139- delete effectData . id ;
140- cls . migrateDataSafe ( effectData ) ;
141- cls . cleanData ( effectData ) ;
142- Actor . create ( { name : 'Temp Actor' , type : 'character' } , { temporary : true } )
143- . then ( ( value ) => {
144- return cls . create ( effectData , { temporary : true , render : true , parent : value } ) ;
145- } )
146- . then ( ( value ) => {
147- const activeEffectConfig = new ActiveEffectConfig ( value ) ;
148- activeEffectConfig . render ( true , { editable : false } ) ;
149- } ) ;
163+ let effectData ;
164+ if ( this . dataset . status ) {
165+ const status = this . dataset . status ;
166+ const statusEffect = CONFIG . statusEffects . find ( ( value ) => value . id === status ) ;
167+ if ( statusEffect ) {
168+ effectData = { ...statusEffect , statuses : [ status ] } ;
169+ }
170+ } else {
171+ effectData = fromBase64 ( this . dataset . effect ) ;
172+ }
173+ if ( effectData ) {
174+ effectData . origin = determineSource ( document , this ) ;
175+ const cls = getDocumentClass ( 'ActiveEffect' ) ;
176+ delete effectData . id ;
177+ cls . migrateDataSafe ( effectData ) ;
178+ cls . cleanData ( effectData ) ;
179+ Actor . create ( { name : 'Temp Actor' , type : 'character' } , { temporary : true } )
180+ . then ( ( value ) => {
181+ return cls . create ( effectData , { temporary : true , render : true , parent : value } ) ;
182+ } )
183+ . then ( ( value ) => {
184+ const activeEffectConfig = new ActiveEffectConfig ( value ) ;
185+ activeEffectConfig . render ( true , { editable : false } ) ;
186+ } ) ;
187+ }
150188 } ) ;
151189}
152190
@@ -163,16 +201,22 @@ function onApplyEffectToActor(actor, source, effect) {
163201 }
164202}
165203
166- function onDropActor ( actor , sheet , { type, source, effect } ) {
204+ function onDropActor ( actor , sheet , { type, source, effect, status } ) {
167205 if ( type === INLINE_EFFECT ) {
168- ActiveEffect . create (
169- {
170- ...effect ,
171- origin : source ,
172- flags : foundry . utils . mergeObject ( effect . flags ?? { } , { [ SYSTEM ] : { [ FUActiveEffect . TEMPORARY_FLAG ] : true } } ) ,
173- } ,
174- { parent : actor } ,
175- ) ;
206+ if ( status ) {
207+ if ( ! actor . statuses . has ( status ) ) {
208+ toggleStatusEffect ( actor , status , source ) ;
209+ }
210+ } else if ( effect ) {
211+ ActiveEffect . create (
212+ {
213+ ...effect ,
214+ origin : source ,
215+ flags : foundry . utils . mergeObject ( effect . flags ?? { } , { [ SYSTEM ] : { [ FUActiveEffect . TEMPORARY_FLAG ] : true } } ) ,
216+ } ,
217+ { parent : actor } ,
218+ ) ;
219+ }
176220 return false ;
177221 }
178222}
@@ -520,7 +564,14 @@ class InlineEffectConfiguration extends FormApplication {
520564 if ( this . object . type === 'custom' ) {
521565 const cls = getDocumentClass ( 'ActiveEffect' ) ;
522566 const tempActor = await Actor . create ( { name : 'Temp Actor' , type : 'character' } , { temporary : true } ) ;
523- const tempEffect = await cls . create ( { _id : foundry . utils . randomID ( ) , name : game . i18n . localize ( this . #defaultName) , icon : this . #defaultIcon } , { temporary : true , parent : tempActor } ) ;
567+ const tempEffect = await cls . create (
568+ {
569+ _id : foundry . utils . randomID ( ) ,
570+ name : game . i18n . localize ( this . #defaultName) ,
571+ icon : this . #defaultIcon,
572+ } ,
573+ { temporary : true , parent : tempActor } ,
574+ ) ;
524575 const activeEffectConfig = new TempActiveEffectConfig ( tempEffect ) ;
525576 activeEffectConfig . render ( true ) ;
526577 const dispatch = this . #dispatch;
0 commit comments