Conversation
…sform and weapon Value 0 of each method key is the behaviour you get without any new method, but it had no checkbox: it was whatever "nothing ticked" happened to mean. It is now a first-class option, so each domain reads as exactly-one-of-N. The grouping in the dialog moves from pairwise exclusion to a real group: ticking one box clears the others in its domain, and clearing the last ticked box puts it back rather than leaving the group empty. They stay checkboxes to match the rest of the dialog while behaving as a radio group. No config schema change. The stored integer already encoded 0 as the default, so an existing config keeps its method and simply shows Standard ticked when it holds 0. Labels are localized for all 76 languages, derived from each language's own existing "new method" wording; ten zoom strings inflect around the numeral and carry an explicit form. The three new descriptions cover the directly-cased languages and fall back to English elsewhere.
… in play All six native paths -- weapon New / New 2, transform New / New 2, zoom New 2 / New 3 -- now refuse to fire while the local player's HP is 0. A native call reaches past whatever the game does with a player who is not in play, so the request is dropped rather than deferred: it is not queued, and one already queued when the player leaves play is cleared instead of firing on respawn. The gate sits at both the host queue site and the ARM9 dispatch, because the queue-to-dispatch window is several frames wide and the player can leave play inside it. A native weapon request refuses outright rather than rerouting to the legacy path, so the selected method never silently swaps for one window. The predicate is IsLocalPlayerAlive() rather than a "dead" one: HP 0 also covers not-yet-spawned at match start, so "dead" would have named only half of what it tests. An unresolved HP pointer counts as alive, so a native path is never disabled just because the pointer cache has not been rebuilt. Standard Method is untouched -- that is the game reacting to the emulator's own simulated input, so the game's own handling already applies. Also restores two sections of input-methods.md, Zoom and Lifecycle and interactions, that commit e2bbabf dropped when it replaced the code cave section by range.
…ayer is in play The latch that gates every battle-runtime patch and every match-scoped ARM9 hook fired on the first mode==0x0E && flow==0 frame. That pair says the match is live, not that the local player exists in it, so everything hung off the latch landed during the spawn window. It is now two-stage, and the stages need not fall on the same frame: - BIT_BATTLE_RUNTIME_SEEN is sticky and records that mode/flow reported a live match at least once since join. The pair can stop reporting one again while the player is still waiting to spawn, so once seen it stays seen. - BIT_BATTLE_RUNTIME_MODE, the latch proper, completes on the first frame after that where the local player's HP is not 0. This moves the apply point of the eight PatchSite_BattleRuntime registry entries (OsdColor, LowHpWarning, FpsCameraLock, ShowHeadshotOnline, ShowEnemyHpMeterOnline, DisableDoubleDamageMultiplier, NoPickingUpSpecificItems, TouchScreenAimOnly), the match ARM9 hook install, and the guest trampoline authoring that hangs off it. The match-end poll still lives behind the latch, so a match that never reaches stage 2 is cleaned up by the leave-in-game path, which is also the path that never applied anything in the first place. An unresolved HP pointer counts as in play, so the latch cannot stall on a cold pointer cache. The new flag is cleared wherever BIT_BATTLE_RUNTIME_MODE is, and the three m_flags.packed = 0 resets cover it already.
…hook The battle-runtime latch is a match boundary; respawn is a player boundary, and the two are not the same. Spawn (JP1_0 0201212C) restores HP early but keeps initialising camera, model, animation, gun and HUD state well past that point, and the same player runtime update (0200EEAC) then falls through to the player input update (02026374) and its hook sites. "HP is not 0, the player matches the local one, the latch is on, and we reached the hook" is therefore all satisfied inside the very update that spawned the player, and a native call made there lands on half-initialised state. Every native dispatcher -- DirectInvocation (transform / weapon / zoom Method 2/3), TransformGate, WeaponSwitch and NativeZoomToggle -- now clears its pending request and returns false on that one hook, letting the site's original instruction run untouched. Dropped, not deferred: replaying a pressed edge from before the respawn is the behaviour being prevented. The boundary needs no host latch. Spawn stores the hunter's configured invulnerability into player+0xE1 and the same update decrements it exactly once before reaching the input code, so on that hook and only there player+0xE1 == (uint8_t)([player+0x404] + 0xE2) - 1. The next update reads configured-2, so this costs one input frame instead of the whole invulnerability window, and a native transform or zoom is available again immediately after. Structure offsets are the same on all seven ROMs, so the shared helper needs no per-version address table; it lives in MelonPrimeGameInput.cpp because all four hook fragments are unity-included there. Weapon Method 1 keeps its existing producer-side refusal for the whole invulnerability window unchanged. Evidence: mphCodex Direct-Invocation-Spawn-Freeze-Investigation-JP1_0.md.
…h the shared barrier Both weapon methods refused the whole player+0xE1 != 0 window on the producer side and rerouted that request to the legacy touch path. With the shared first-post-spawn barrier now in every native dispatcher, that older guard is both wider than the ROM's own boundary -- the unsafe moment is the one input hook inside the update that spawned the player, not the entire invulnerability countdown -- and a silent method swap for its duration. Removed from both branches, leaving the dispatcher barrier as the single owner of the spawn boundary for every native method. Nothing else changes: the in-play (HP != 0) refusal and the native-only "report, don't hide" behaviour on an unserviceable site both stay. This deliberately diverges from the mphCodex investigation, which recommends keeping the wider weapon-only guard as a safety margin rather than weakening it on the strength of that investigation alone. Restoring a full-window refusal for the weapon path is the documented fallback if a switch during spawn invulnerability turns out to still be unsafe.
…nerability window Method 2 still froze at match start with the first-post-spawn barrier in place, while Method 1 did not. The barrier is present and correct on the shared dispatcher, and the trampoline disassembles as intended on all seven ROMs, so the one-hook boundary is simply not the whole unsafe region for this path. The investigation documents exactly this fallback (section 10, option B): refuse while player+0xE1 != 0 rather than only on the hook where it reads configured - 1. Applied to the transform command only, so weapon and zoom keep the exact barrier and the producer-side full-window weapon guard removed in the previous commit is not quietly reinstated. The asymmetry with Method 1 is consistent with where each calls the routine: Method 1 redirects into the game's own transform call site, whose surrounding state the game already treats as valid for a form switch, while Method 2 calls it from the player input hook. Clearing the transform request mid-dispatch has to re-check IsValid(), because the command selection below treats "not transform, not weapon" as zoom. Unverified: this is a mitigation chosen from the investigation's documented options, not a root cause that has been observed. If it holds, the remaining question is whether the window can be narrowed again.
…le invulnerability window" This reverts commit 3cd23ee.
…tandard transform fires "Use the Whole Touch Screen for Aiming" neutralises the bottom-screen HUD hit-tests, and the Standard transform works by tapping the touch-screen Transform button, so enabling that option silently stops Standard transforms from firing. Standard weapon change is unaffected because it drives the game's weapon-change state directly rather than through a HUD button, which is why only one of the two appears to break. The new sub-option, shown indented under its parent, restores the patch for the few frames of that tap and puts it straight back. This is the same bracketing the legacy weapon path already does around NoDoubleTapJump, and it goes through the owning module so TouchScreenAimOnly stays the single writer of its patch state. Off by default, and only enabled in the dialog while the parent option is checked, since it does nothing otherwise. The binding row is appended so every historical binding index stays stable; only the tail load range grows. Labels are localized for the directly-cased languages and fall back to English elsewhere. The .ui grid rows below the insertion point shift by one.
…ard path Restores the full-window fallback the weapon new method used to have, and extends it to every native method rather than leaving it weapon-only. While the local player is inside the spawn invulnerability countdown (player+0xE1 != 0), a native method no longer makes a native call: weapon goes through the legacy touch route, and transform and zoom fall through to their Standard branches. The native request is cleared rather than left pending, so nothing replays when the window ends. Zoom keeps the shared pressed-edge latch in sync across the boundary, the same way the alt-form branch already does, so leaving the window mid-hold cannot fire a stale toggle. The dispatcher's first-post-spawn barrier stays. The two cover different cases and are complementary: the producer check cannot see a request queued before the boundary that only reaches the hook after it, and the barrier only sees requests that actually reach a hook. The visible trade is that during the window the selected method is briefly not the one in use -- but the input still does something rather than being swallowed, which is what the weapon path did before and why it was worth restoring.
Develop hud
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.