11import type { ActorPF2e , CharacterPF2e } from "@actor" ;
22import { Coins } from "@item/physical/helpers.ts" ;
33import { ChatMessagePF2e } from "@module/chat-message/document.ts" ;
4- import appv1 = foundry . appv1 ;
54
6- interface PopupData extends appv1 . api . FormApplicationData < ActorPF2e > {
7- selection ?: string [ ] ;
8- actorInfo ?: {
9- id : string ;
10- name : string ;
11- checked : boolean ;
12- } [ ] ;
13- }
5+ /** Allows the distribution and split of coins to multiple players */
6+ export class DistributeCoinsDialog extends fa . api . HandlebarsApplicationMixin ( fa . api . ApplicationV2 ) {
7+ constructor (
8+ options : Partial < DistributeCoinsConfiguration > & Required < Pick < DistributeCoinsConfiguration , "actor" > > ,
9+ ) {
10+ super ( options ) ;
11+ this . actor = options . actor ;
12+ }
1413
15- interface PopupFormData extends FormData {
16- actorIds : string [ ] ;
17- breakCoins : boolean ;
18- }
14+ static override DEFAULT_OPTIONS : DeepPartial < DistributeCoinsConfiguration > = {
15+ id : "distribute-coins" ,
16+ tag : "form" ,
17+ window : {
18+ title : "Distribute Coins" ,
19+ contentClasses : [ "standard-form" ] ,
20+ } ,
21+ form : {
22+ closeOnSubmit : true ,
23+ handler : DistributeCoinsDialog . #onSubmit,
24+ } ,
25+ } ;
1926
20- /**
21- * @category Other
22- */
23- export class DistributeCoinsPopup extends appv1 . api . FormApplication < ActorPF2e , DistributeCoinsOptions > {
24- constructor ( actor : ActorPF2e , options : Partial < DistributeCoinsOptions > = { } ) {
25- super ( actor , options ) ;
26- }
27+ static override PARTS = {
28+ base : { template : "systems/pf2e/templates/actors/distribute-coins.hbs" , root : true } ,
29+ } ;
2730
28- static override get defaultOptions ( ) : appv1 . api . FormApplicationOptions {
29- const options = super . defaultOptions ;
30- options . id = "distribute-coins" ;
31- options . classes = [ ] ;
32- options . title = "Distribute Coins" ;
33- options . template = "systems/pf2e/templates/actors/distribute-coins.hbs" ;
34- options . width = "auto" ;
35- return options ;
36- }
31+ actor : ActorPF2e ;
32+ declare options : DistributeCoinsConfiguration ;
3733
38- override async getData ( options ?: Partial < DistributeCoinsOptions > ) : Promise < PopupData > {
39- const sheetData : PopupData = await super . getData ( options ) ;
40- const playerActors = ( options ? .recipients ?? game . actors . contents ) . filter (
34+ override async _prepareContext ( options : fa . ApplicationRenderOptions ) : Promise < DistributeCoinsContext > {
35+ const data = await super . _prepareContext ( options ) ;
36+ const playerActors = ( this . options . recipients ?? game . actors . contents ) . filter (
4137 ( a ) =>
4238 a . hasPlayerOwner &&
4339 a . isOfType ( "character" ) &&
4440 ! a . isToken &&
4541 ! a . system . traits . value . some ( ( t ) => [ "minion" , "eidolon" ] . includes ( t ) ) ,
4642 ) ;
47- sheetData . actorInfo = playerActors . map ( ( a ) => ( {
48- id : a . id ,
49- name : a . name ,
50- checked : game . users . players . some ( ( u ) => u . active && u . character ?. id === a . id ) ,
51- } ) ) ;
52-
53- return sheetData ;
43+ return {
44+ ...data ,
45+ rootId : this . id ,
46+ actorInfo : playerActors . map ( ( a ) => ( {
47+ id : a . id ,
48+ name : a . name ,
49+ checked : game . users . players . some ( ( u ) => u . active && u . character ?. id === a . id ) ,
50+ } ) ) ,
51+ } ;
5452 }
5553
56- override async _updateObject ( _event : Event , formData : Record < string , unknown > & PopupFormData ) : Promise < void > {
57- const thisActor = this . object ;
58- const selectedActors : CharacterPF2e [ ] = formData . actorIds . flatMap ( ( actorId ) => {
54+ static async #onSubmit(
55+ this : DistributeCoinsDialog ,
56+ _event : Event ,
57+ form : HTMLFormElement ,
58+ formData : fa . ux . FormDataExtended ,
59+ ) {
60+ // Get actor ids, we need to get it directly since the DOM may not give back an array if only one
61+ const actor = this . actor ;
62+ const actorIds : string [ ] = Array . from ( form . elements ) . flatMap ( ( element ) =>
63+ element instanceof HTMLInputElement && element . name === "actorIds" && element . checked ? element . value : [ ] ,
64+ ) ;
65+
66+ const selectedActors : CharacterPF2e [ ] = actorIds . flatMap ( ( actorId ) => {
5967 const maybeActor = game . actors . get ( actorId ) ;
6068 return maybeActor ?. isOfType ( "character" ) ? maybeActor : [ ] ;
6169 } ) ;
@@ -66,21 +74,21 @@ export class DistributeCoinsPopup extends appv1.api.FormApplication<ActorPF2e, D
6674 }
6775
6876 const coinShare = new Coins ( ) ;
69- if ( formData . breakCoins ) {
70- const thisActorCopperValue = thisActor . inventory . coins . copperValue ;
77+ if ( formData . object . breakCoins ) {
78+ const thisActorCopperValue = actor . inventory . coins . copperValue ;
7179 const copperToDistribute = Math . trunc ( thisActorCopperValue / playerCount ) ;
7280 // return if there is nothing to distribute
7381 if ( copperToDistribute === 0 ) {
7482 ui . notifications . warn ( "Nothing to distribute" ) ;
7583 return ;
7684 }
77- thisActor . inventory . removeCoins ( { cp : copperToDistribute * playerCount } ) ;
85+ actor . inventory . removeCoins ( { cp : copperToDistribute * playerCount } ) ;
7886 coinShare . cp = copperToDistribute % 10 ;
7987 coinShare . sp = Math . trunc ( copperToDistribute / 10 ) % 10 ;
8088 coinShare . gp = Math . trunc ( copperToDistribute / 100 ) % 10 ;
8189 coinShare . pp = Math . trunc ( copperToDistribute / 1000 ) ;
8290 } else {
83- const thisActorCurrency = thisActor . inventory . coins ;
91+ const thisActorCurrency = actor . inventory . coins ;
8492 coinShare . pp = Math . trunc ( thisActorCurrency . pp / playerCount ) ;
8593 coinShare . cp = Math . trunc ( thisActorCurrency . cp / playerCount ) ;
8694 coinShare . gp = Math . trunc ( thisActorCurrency . gp / playerCount ) ;
@@ -92,15 +100,15 @@ export class DistributeCoinsPopup extends appv1.api.FormApplication<ActorPF2e, D
92100 }
93101
94102 const coinsToRemove = coinShare . scale ( playerCount ) ;
95- thisActor . inventory . removeCoins ( coinsToRemove , { byValue : false } ) ;
103+ actor . inventory . removeCoins ( coinsToRemove , { byValue : false } ) ;
96104 }
97105 let message = `Distributed ` ;
98106 if ( coinShare . pp !== 0 ) message += `${ coinShare . pp } pp ` ;
99107 if ( coinShare . gp !== 0 ) message += `${ coinShare . gp } gp ` ;
100108 if ( coinShare . sp !== 0 ) message += `${ coinShare . sp } sp ` ;
101109 if ( coinShare . cp !== 0 ) message += `${ coinShare . cp } cp ` ;
102110 const each = playerCount > 1 ? "each " : "" ;
103- message += `${ each } from ${ thisActor . name } to ` ;
111+ message += `${ each } from ${ actor . name } to ` ;
104112 for ( const actor of selectedActors ) {
105113 await actor . inventory . addCoins ( coinShare ) ;
106114 const index = selectedActors . indexOf ( actor ) ;
@@ -114,21 +122,19 @@ export class DistributeCoinsPopup extends appv1.api.FormApplication<ActorPF2e, D
114122 content : message ,
115123 } ) ;
116124 }
117-
118- /** Prevent Foundry from converting the actor IDs to boolean values */
119- protected override async _onSubmit (
120- event : Event ,
121- options : appv1 . api . OnSubmitFormOptions = { } ,
122- ) : Promise < Record < string , unknown > | false > {
123- const actorIds : string [ ] = Array . from ( this . form . elements ) . flatMap ( ( element ) =>
124- element instanceof HTMLInputElement && element . name === "actorIds" && element . checked ? element . value : [ ] ,
125- ) ;
126- options . updateData = fu . mergeObject ( options . updateData ?? { } , { actorIds : actorIds } ) ;
127- return super . _onSubmit ( event , options ) ;
128- }
129125}
130126
131- interface DistributeCoinsOptions extends appv1 . api . FormApplicationOptions {
127+ interface DistributeCoinsConfiguration extends fa . api . DialogV2Configuration {
128+ actor : ActorPF2e ;
132129 /** An optional initial list of recipients to receive coins */
133130 recipients ?: ActorPF2e [ ] ;
134131}
132+
133+ interface DistributeCoinsContext extends fa . ApplicationRenderContext {
134+ rootId : string ;
135+ actorInfo : {
136+ id : string ;
137+ name : string ;
138+ checked : boolean ;
139+ } [ ] ;
140+ }
0 commit comments