From 94ffec0a8dac79aa7e6d25a3b73d924e5b7f42d1 Mon Sep 17 00:00:00 2001 From: Dmytro Meleshko Date: Fri, 24 Jul 2020 14:39:09 +0300 Subject: [PATCH] [crosscode] add code to open the map menu by pressing `M` --- .../assets/data/lang/sc/gui.en_US.json.patch | 16 +++ crosscode/btw-i-use-arch-mod/ccmod.json | 3 +- crosscode/btw-i-use-arch-mod/poststart.js | 100 ++++++++++++++++++ crosscode/btw-i-use-arch-mod/prestart.js | 18 ++-- 4 files changed, 125 insertions(+), 12 deletions(-) create mode 100644 crosscode/btw-i-use-arch-mod/assets/data/lang/sc/gui.en_US.json.patch create mode 100644 crosscode/btw-i-use-arch-mod/poststart.js diff --git a/crosscode/btw-i-use-arch-mod/assets/data/lang/sc/gui.en_US.json.patch b/crosscode/btw-i-use-arch-mod/assets/data/lang/sc/gui.en_US.json.patch new file mode 100644 index 0000000..cf12f73 --- /dev/null +++ b/crosscode/btw-i-use-arch-mod/assets/data/lang/sc/gui.en_US.json.patch @@ -0,0 +1,16 @@ +{ + "labels": { + "options": { + "headers": { + "btw-i-use-arch": "btw I use Arch" + }, + "controls": { + "keys": { + "btw-i-use-arch": { + "open-map-menu": "Open/Close Map Menu" + } + } + } + } + } +} diff --git a/crosscode/btw-i-use-arch-mod/ccmod.json b/crosscode/btw-i-use-arch-mod/ccmod.json index 3b48761..de31768 100644 --- a/crosscode/btw-i-use-arch-mod/ccmod.json +++ b/crosscode/btw-i-use-arch-mod/ccmod.json @@ -3,5 +3,6 @@ "title": "btw I use Arch", "version": "0.0.0", "description": "A mod for masochists like myself", - "prestart": "prestart.js" + "prestart": "prestart.js", + "poststart": "poststart.js" } diff --git a/crosscode/btw-i-use-arch-mod/poststart.js b/crosscode/btw-i-use-arch-mod/poststart.js new file mode 100644 index 0000000..7c7531b --- /dev/null +++ b/crosscode/btw-i-use-arch-mod/poststart.js @@ -0,0 +1,100 @@ +// ac2pic: NOOOOO YOU CAN'T JUST PUT EVERYTHING IN POSTSTART/MAIN +// dmitmel: haha text editor go brrrr + +ig.input.bind(ig.KEY.J, 'aim'); +ig.input.bind(ig.KEY.K, 'dash'); + +function findRootGuiElement(clazz) { + return ig.gui.guiHooks.find(({ gui }) => gui instanceof clazz).gui; +} + +const quickMenu = findRootGuiElement(sc.QuickMenu); + +function onPostUpdate() { + if (ig.loading || sc.model.isPlayerControlBlocked()) return; + + if (ig.input.pressed('btw-i-use-arch.open-map-menu')) { + if ( + sc.model.currentState == sc.GAME_MODEL_STATE.GAME && + sc.model.currentSubState == sc.GAME_MODEL_SUBSTATE.MENU && + sc.menu.currentMenu === sc.MENU_SUBMENU.MAP && + // check if the help screen or a dialog isn't opened, otherwise it will + // block the screen after switching back to the game + ig.interact.entries.last() === sc.menu.buttonInteract + ) { + closeMapMenu(); + sc.BUTTON_SOUND.back.play(); + } else if ( + sc.model.currentState == sc.GAME_MODEL_STATE.GAME && + sc.model.currentSubState == sc.GAME_MODEL_SUBSTATE.RUNNING && + // check if the quick menu has been unlocked yet, the map menu becomes + // available at the same moment + sc.model.player.getCore(sc.PLAYER_CORE.QUICK_MENU) + ) { + let openedMapMenu = openMapMenu(); + sc.BUTTON_SOUND[openedMapMenu ? 'submit' : 'denied'].play(); + } + } +} + +function openMapMenu() { + // Check for the common conditions upfront, because opening and then + // immediately closing the quick menu causes the element indicator in the top + // left corner to jump, which is, of course, undesirable. Other conditions may + // be present implicitly or added explicitely in the future, but these two are + // the obvious ones I could find. + if (!sc.model.isSaveAllowed() || sc.model.isTeleportBlocked()) return false; + + // User's actions required in order to open the map need to be carefully + // emulated here instead of directly calling methods of `sc.model` and + // `sc.menu` because of the model notifications sent during the intended user + // interaction path (which trigger changes to the UI all over the codebase) + // and potential (although unlikely) changes to the internals of the methods + // I'm using here. Also, I chose to use the quick menu instead of the main one + // because the main one is unlocked at the end of the rhombus dungeon which is + // a bit later than the quick one and the map menu in particular both become + // available. + let enteredQuickMenu = sc.model.enterQuickMenu(); + if (!enteredQuickMenu) return false; + // I wonder why this variable isn't set internally by `enteredQuickMenu`, but + // I have to do this here because not doing that creates a very annoying bug + // when the quick menu access method is set to "hold": the quick menu becomes + // impossible to close by pressing shift and to close it you have to open and + // close the map menu again manually. + sc.quickmodel.activeState = true; + + let quickRingMenu = quickMenu.ringmenu; + let mapButton = quickRingMenu.map; + if (!mapButton.active) { + // some additional conditions may be present as noted above, so in the case + // the button intended to be pressed by user is inactive we bail out safely + sc.quickmodel.activeState = false; + sc.model.enterRunning(); + return false; + } + + // And finally, press the "map" button! + quickRingMenu.buttongroup._invokePressCallbacks( + mapButton, + /* fromMouse */ false, + ); + return true; +} + +function closeMapMenu() { + // Let's exit the world map just in case, for the same reason as I emulate + // user interactions in the `openMapMenu` function. + if (sc.menu.mapWorldmapActive) sc.menu.exitWorldMap(); + + sc.model.enterPrevSubState(); +} + +{ + let inputPostUpdateIdx = ig.game.addons.postUpdate.findIndex( + (addon) => addon instanceof sc.GlobalInput, + ); + console.assert(inputPostUpdateIdx >= 0, 'inputPostUpdateIdx >= 0'); + ig.game.addons.postUpdate.splice(inputPostUpdateIdx + 1, 0, { + onPostUpdate, + }); +} diff --git a/crosscode/btw-i-use-arch-mod/prestart.js b/crosscode/btw-i-use-arch-mod/prestart.js index ad60383..bc03b9a 100644 --- a/crosscode/btw-i-use-arch-mod/prestart.js +++ b/crosscode/btw-i-use-arch-mod/prestart.js @@ -1,11 +1,7 @@ -ig.module('game.feature.masochist.keyboard-controls') - .requires('game.main') - .defines(() => { - sc.CrossCode.inject({ - init() { - this.parent(); - ig.input.bind(ig.KEY.J, 'aim'); - ig.input.bind(ig.KEY.K, 'dash'); - }, - }); - }); +sc.OPTIONS_DEFINITION['keys-btw-i-use-arch.open-map-menu'] = { + type: 'CONTROLS', + cat: sc.OPTION_CATEGORY.CONTROLS, + init: { key1: ig.KEY.M }, + hasDivider: true, + header: 'btw-i-use-arch', +};