@@ -31,7 +31,7 @@ globalThis.pbta = {
3131 utils
3232} ;
3333
34- Hooks . once ( "init" , async function ( ) {
34+ Hooks . once ( "init" , ( ) => {
3535 globalThis . pbta = game . pbta = Object . assign ( game . system , globalThis . pbta ) ;
3636
3737 CONFIG . ui . combat = applications . combat . PbtACombatTracker ;
@@ -104,27 +104,32 @@ Hooks.once("init", async function () {
104104} ) ;
105105
106106Hooks . on ( "i18nInit" , ( ) => {
107+ const activeModules = [ ...game . modules . entries ( ) ] . filter ( ( [ key , m ] ) => m . active && m . flags [ key ] ?. [ "pbta-override" ] ) ;
108+
109+ if ( activeModules . length > 1 && game . user . isGM ) {
110+ const names = activeModules . map ( ( [ key , m ] ) => m . name ) . join ( ", " ) ;
111+ ui . notifications . warn ( game . i18n . format ( "PBTA.Warnings.TooManyModules" , { names } ) ) ;
112+ }
113+ game . pbta . moduleConfig = activeModules . length > 0 ;
114+
107115 registerSettings ( ) ;
108116
109117 // Build out character data structures.
110118 const pbtaSettings = game . settings . get ( "pbta" , "sheetConfig" ) ;
111119
112- // Retrieve overridden config, if enabled.
113- if ( pbtaSettings ?. overridden && game . settings . get ( "pbta" , "sheetConfigOverride" ) ) {
120+ if ( pbtaSettings . overridden && game . pbta . moduleConfig ) {
114121 game . pbta . sheetConfig = pbtaSettings . overridden ;
115- } else if ( pbtaSettings ?. computed ) {
116- // Otherwise, retrieve computed config.
122+ } else if ( pbtaSettings . computed ) {
117123 game . pbta . sheetConfig = utils . convertSheetConfig ( pbtaSettings . computed ) ;
118124 } else {
119- // Fallback to empty config.
120125 game . pbta . sheetConfig = pbtaSettings ;
121126 }
122127} ) ;
123128
124129/**
125130 * This function runs after game data has been requested and loaded from the servers, so documents exist
126131 */
127- Hooks . once ( "setup" , function ( ) {
132+ Hooks . once ( "setup" , ( ) => {
128133 // Localize CONFIG objects once up-front
129134 const toLocalize = [ ] ;
130135 for ( let o of toLocalize ) {
@@ -134,100 +139,14 @@ Hooks.once("setup", function () {
134139 } , { } ) ;
135140 }
136141
137- if ( game . user . isGM ) {
138- Hooks . on ( "renderSettings" , ( app , html ) => {
139- const header = document . createElement ( "h2" ) ;
140- header . innerText = game . i18n . localize ( "Powered by the Apocalypse" ) ;
141-
142- const pbtaSettings = document . createElement ( "div" ) ;
143- html . find ( "#settings-game" ) ?. after ( header , pbtaSettings ) ;
144-
145- const buttons = [
146- {
147- action : ( ev ) => {
148- ev . preventDefault ( ) ;
149- let menu = game . settings . menus . get ( "pbta.sheetConfigMenu" ) ;
150- let app = new menu . type ( ) ;
151- app . render ( true ) ;
152- } ,
153- iconClasses : [ "fas" , "fa-file-alt" ] ,
154- label : "PBTA.Settings.sheetConfig.label"
155- } ,
156- {
157- action : ( ev ) => {
158- ev . preventDefault ( ) ;
159- window . open ( "https://asacolips.gitbook.io/pbta-system/" , "pbtaHelp" , "width=1032,height=720" ) ;
160- } ,
161- iconClasses : [ "fas" , "fa-question-circle" ] ,
162- label : "PBTA.Settings.button.help"
163- }
164- ] . map ( ( { action, iconClasses, label } ) => {
165- const button = document . createElement ( "button" ) ;
166- button . type = "button" ;
167-
168- const icon = document . createElement ( "i" ) ;
169- icon . classList . add ( ...iconClasses ) ;
170-
171- button . append ( icon , game . i18n . localize ( label ) ) ;
172-
173- button . addEventListener ( "click" , action ) ;
174-
175- return button ;
176- } ) ;
177-
178- pbtaSettings . append ( ...buttons ) ;
179- } ) ;
142+ if ( game . modules . get ( "babele" ) ?. active ) {
143+ Hooks . on ( "babele.ready" , ( ) => utils . getPlaybooks ( ) ) ;
144+ } else {
145+ utils . getPlaybooks ( ) ;
180146 }
181147} ) ;
182148
183- Hooks . once ( "ready" , async function ( ) {
184- // Override sheet config.
185- if ( game . user . isGM ) {
186- // Force sheet config override off, unless a module changes it.
187- await game . settings . set ( "pbta" , "sheetConfigOverride" , false ) ;
188-
189- // Allow modules to override the sheet config.
190- Hooks . callAll ( "pbtaSheetConfig" ) ;
191-
192- // @todo find something better than this timeout hack.
193- const timeout = 1000 ;
194- setTimeout ( ( ) => {
195- // Retrieve the previous configuration.
196- let existingConfig = game . settings . get ( "pbta" , "sheetConfig" ) ?? { } ;
197- // @todo hack to fix the old the default value. Remove in a future update.
198- if ( typeof existingConfig !== "object" ) {
199- existingConfig = { } ;
200- }
201- // If a module enabled the override, assign it to the config so that player
202- // clients can use it without the GM being logged in.
203- if ( game . settings . get ( "pbta" , "sheetConfigOverride" ) ) {
204- existingConfig . overridden = game . pbta . sheetConfig ;
205- game . settings . set ( "pbta" , "sheetConfig" , existingConfig ) ;
206- } else if ( existingConfig ?. overridden ) {
207- // Otherwise, delete the override config.
208-
209- // If not tomlString exists, delete the config outright to prevent
210- // it from being malformed.
211- if ( ! existingConfig ?. tomlString ) {
212- ui . notifications . info ( game . i18n . localize ( "PBTA.Messages.sheetConfig.overrideRemoved" ) ) ;
213- existingConfig = null ;
214- } else {
215- // Otherwise, restore the previous config.
216-
217- // Delete overrides.
218- delete existingConfig . overridden ;
219- delete existingConfig . computed ;
220- // Restore computed config and reapply.
221- existingConfig . computed = utils . parseTomlString ( existingConfig . tomlString ) ;
222- game . pbta . sheetConfig = utils . convertSheetConfig ( existingConfig . computed ) ;
223- utils . applyActorTemplates ( true ) ;
224- ui . notifications . info ( game . i18n . localize ( "PBTA.Messages.sheetConfig.previousSettingRestored" ) ) ;
225- }
226- game . settings . set ( "pbta" , "sheetConfig" , existingConfig ) ;
227- }
228- } , timeout ) ;
229- }
230-
149+ Hooks . once ( "ready" , ( ) => {
231150 // Wait to register hotbar drop hook on ready so that modules could register earlier if they want to
232151 Hooks . on ( "hotbarDrop" , ( bar , data , slot ) => {
233152 if ( [ "Item" ] . includes ( data . type ) ) {
@@ -236,12 +155,26 @@ Hooks.once("ready", async function () {
236155 }
237156 } ) ;
238157
239- CONFIG . PBTA = PBTA ;
158+ if ( game . user . isGM ) {
159+ Hooks . callAll ( "pbta.sheetConfig" ) ;
160+ let existingConfig = game . settings . get ( "pbta" , "sheetConfig" ) ?? { } ;
161+ const { overridden, tomlString } = existingConfig ;
162+ if ( game . pbta . moduleConfig ) {
163+ existingConfig . overridden = game . pbta . sheetConfig ;
164+ } else if ( overridden ) {
165+ if ( ! tomlString ) {
166+ ui . notifications . info ( game . i18n . localize ( "PBTA.Messages.sheetConfig.overrideRemoved" ) ) ;
167+ existingConfig = { } ;
168+ } else {
169+ delete existingConfig . overridden ;
240170
241- if ( game . modules . get ( "babele" ) ?. active && game . i18n . lang !== "en" ) {
242- Hooks . on ( "babele.ready" , ( ) => utils . getPlaybooks ( ) ) ;
243- } else {
244- utils . getPlaybooks ( ) ;
171+ existingConfig . computed = utils . parseTomlString ( existingConfig . tomlString ) ;
172+ game . pbta . sheetConfig = utils . convertSheetConfig ( existingConfig . computed ) ;
173+ utils . applyActorTemplates ( true ) ;
174+ ui . notifications . info ( game . i18n . localize ( "PBTA.Messages.sheetConfig.previousSettingRestored" ) ) ;
175+ }
176+ }
177+ game . settings . set ( "pbta" , "sheetConfig" , existingConfig ) ;
245178 }
246179
247180 // Apply structure to actor types.
@@ -276,6 +209,52 @@ Hooks.on("renderChatMessage", (data, html, options) => {
276209
277210Hooks . on ( "renderChatLog" , ( app , html , data ) => documents . ItemPbta . chatListeners ( html ) ) ;
278211Hooks . on ( "renderChatPopout" , ( app , html , data ) => documents . ItemPbta . chatListeners ( html ) ) ;
212+ Hooks . on ( "renderSettings" , ( app , html ) => {
213+ if ( ! game . user . isGM ) return ;
214+ const header = document . createElement ( "h2" ) ;
215+ header . innerText = game . i18n . localize ( "Powered by the Apocalypse" ) ;
216+
217+ const pbtaSettings = document . createElement ( "div" ) ;
218+ html . find ( "#settings-game" ) ?. after ( header , pbtaSettings ) ;
219+
220+ const buttons = [
221+ {
222+ action : ( ev ) => {
223+ ev . preventDefault ( ) ;
224+ window . open ( "https://asacolips.gitbook.io/pbta-system/" , "pbtaHelp" , "width=1032,height=720" ) ;
225+ } ,
226+ iconClasses : [ "fas" , "fa-question-circle" ] ,
227+ label : "PBTA.Settings.button.help"
228+ }
229+ ] ;
230+ if ( ! game . pbta . moduleConfig ) {
231+ buttons . unshift ( {
232+ action : ( ev ) => {
233+ ev . preventDefault ( ) ;
234+ let menu = game . settings . menus . get ( "pbta.sheetConfigMenu" ) ;
235+ let app = new menu . type ( ) ;
236+ app . render ( true ) ;
237+ } ,
238+ iconClasses : [ "fas" , "fa-file-alt" ] ,
239+ label : "PBTA.Settings.sheetConfig.label"
240+ } ) ;
241+ }
242+ const formattedButtons = buttons . map ( ( { action, iconClasses, label } ) => {
243+ const button = document . createElement ( "button" ) ;
244+ button . type = "button" ;
245+
246+ const icon = document . createElement ( "i" ) ;
247+ icon . classList . add ( ...iconClasses ) ;
248+
249+ button . append ( icon , game . i18n . localize ( label ) ) ;
250+
251+ button . addEventListener ( "click" , action ) ;
252+
253+ return button ;
254+ } ) ;
255+
256+ pbtaSettings . append ( ...formattedButtons ) ;
257+ } ) ;
279258
280259/**
281260 * Configure explicit lists of attributes that are trackable on the token HUD and in the combat tracker.
0 commit comments