Ungodly Nazi Zombies Install guide · BepInEx 6 + two mods
6.0.0-be.785 v1.0.0

Reference Read in any order

How the Ungodly box thinks

Rarity tiers it works out per map, a luck curve, and pity that cannot fail you.

The stock box gives every weapon in the pool identical odds, forever — the best gun on the map, the worst pistol, and the dud all equally likely, at wave 1 and at wave 50. This mod replaces the decision of which weapon you get, and nothing else about the purchase.

The vanilla purchase pipeline is left completely untouched

Score deduction, the “YOU PURCHASED” message, WeaponManager.AddWeapon, challenge progress, the buy sound — all of it runs exactly as shipped. The plugin changes only which weapon that pipeline hands you, and it makes that decision at the one moment that matters: the instant your purchase commits.

Recovered from the binary

What the stock box actually does

The vanilla logic was reverse-engineered from the game’s IL2CPP metadata and native x64 method bodies before a line of this plugin was written. It is brutally simple, and knowing it makes everything below make sense.

  • Every physics tick, at 50 Hz, every box in the scene rolls a new weapon and stores it in a field — forever, whether anyone is anywhere near it or not.
  • Holding INTERACT grabs whatever that field happened to be on that exact tick. Your prize is literally which 20-millisecond window you clicked in.
  • Flat equal odds for everything in the pool, including the dud entry.
  • No bad-luck protection, no duplicate protection, no round scaling, no anti-streak logic of any kind.

This is why the mod is cheaper than vanilla to run

One of its three patches suppresses that 50 Hz re-roll, which was a managed-to-native interop call on every box on every physics tick. A modded client does less background work per frame than an unmodded one. More on that below.

No configuration

It works out rarity by itself, per map

The first time a box is used, the mod reads the real combat statistics of every weapon in that box’s pool from the game’s own weapon data and computes a composite power score.

WeightStatistic
0.46 Damage per trigger pull (damage × pellet count for shotguns)
0.20 Magazine burst potential (per-pull damage × magazine size)
0.12 Reserve ammo depth
0.08 Bullet penetration count
0.08 Headshot multiplier ceiling
0.06 Effective range

Scores are normalised within that box’s own pool, then cut into five tiers by percentile rank — roughly the top 13% Legendary, then Epic, Rare, Uncommon and Common.

Two hard guarantees

The strongest weapon in any pool is always Legendary and the weakest is always Common. Every map — vanilla, DLC, or a community Mapmaker creation — gets a real jackpot and a real floor, automatically.

Duds are not a tier

The isNothing entry is pulled out of the ladder entirely and handled by its own model, rather than sitting in Common distorting the odds.

Identical on every machine

Tie-breaks are stable by weapon id, so an identical pool tiers identically on every client and every launch. Nothing depends on load order or timing.

It re-checks itself

A fingerprint over the pool’s weapon ids is re-verified every 16 rolls. If a map script or Mapmaker edit changes the pool, the box re-censuses automatically.

A census from the author’s validation run on a 14-slot pool came out like this:

An example census
Legendary  Sniper, AT-Rifle
Epic       Shotgun, Trench, LMG
Rare       Revolver, AR-A, AR-B
Uncommon   Carbine, Flame
Common     Pistol, SMG-A, SMG-B
Dud        Nothing

Tiers are relative to each box, on purpose

A “Legendary” in a starter pool is the best of that pool, not the best in the game. That is what makes the system work on maps the author has never seen — it never needs a hand-written weapon list.

Wave-scaled luck

The box grows with you

Tier weights shift with the current wave, so a wave-30 roll is meaningfully better than a wave-1 roll. These are the odds conditional on a non-dud result:

TierWave 1Wave 10Wave 20Wave 30+
Legendary 5.2% 7.1% 9.3% 11.5%
Epic 11.3% 14.1% 17.3% 20.7%
Rare 18.2% 20.1% 22.2% 24.4%
Uncommon 26.8% 25.1% 23.1% 21.1%
Common 38.5% 33.6% 28.1% 22.4%

Legendary and Epic together move from about 16.5% at wave 1 to about 32% at wave 30 and beyond — roughly doubling — while Common falls from 38.5% to 22.4%. The author’s 400,000-roll validation harness reproduced the wave-1 and wave-30 columns to within ±0.06%.

Pity

Bad luck cannot run away from you

A per-match counter tracks consecutive rolls below Epic — and a dud counts double, because a dud is maximally unlucky.

Soft pity, after 4 misses

Epic odds are multiplied by 1 + 0.35 × steps and Legendary odds by 1 + 0.75 × steps, climbing with every further miss. The longer the drought, the harder the box pushes back.

Hard pity, at 8

The next roll is guaranteed Epic or Legendary, with Legendary taking a 35% share of that guarantee. There is no way past this — it is not a probability boost, it is a floor.

Any Epic-or-better grant resets the counter

Including one you got by ordinary luck rather than through pity.

Validated across 400,000 live rolls

The pity counter never once exceeded the hard-pity band. Endless brutal droughts are not unlikely under this system — they are mathematically impossible.

An aborted purchase does not cost you pity

The commit step runs as a Harmony postfix, which Harmony skips if the sale throws. If a purchase fails partway through, your pity counter does not advance for it.

Nothing

The dud gets an actual model

Vanilla gives the “Nothing” entry flat pool odds forever, which is why it can hit you three times in a row on wave 40. Here it has rules.

  • Starts at 8% on wave 1 and decays −0.5% per wave to a 2% floor — an early sting, late-game mercy.
  • Never on your first roll of a match.
  • Never twice in a row.
  • Never while soft or hard pity is active.

If a box’s pool contains no dud entry at all, the dud stage simply does not exist for that box.

Fairness bags

No clumping, and duplicates get deferred

Picking a tier is only half the decision. Within each tier the mod draws from a shuffled bag — the same principle Tetris uses for its pieces — so every weapon of that tier is offered once before any repeats, and a fresh shuffle can never open with the card that just left.

On top of that, any weapon you already hold, or received within your last three grants, is deferred behind every fresh option remaining in the current bag cycle.

Duplicates stay possible, and that is deliberate

The game’s own AddWeapon on a weapon you already hold is its ammo refill path, so removing duplicates entirely would remove a real use of the box. A bag’s final card can still be a held one.

What the measurements showed across 400,000 live rolls: zero back-to-back identical grants, and a held weapon never opened a bag cycle while a fresh same-tier alternative existed — 0 occurrences in 5,000 forced cycles.

Casino-grade

Where the randomness comes from

Every roll comes from a session-seeded xoshiro256** generator with SplitMix64 expansion and Lemire unbiased bounded sampling — pure managed maths, statistically independent of frame timing.

It is completely separate from the engine’s own random number generator, so nothing else in the game — weapon spread, zombie spawns, effects — is ever perturbed by this plugin. It also means your prize no longer depends on the millisecond you happened to press the key, which is the single biggest change in feel.

By construction

Modded and unmodded players can share a lobby

This is worth explaining rather than just asserting, because it is a genuinely unusual property for a mod that changes what items you receive.

In this game the box purchase is driven entirely by the purchasing client. The rolled index is never synchronised over the network in vanilla — every client’s copy of a box already holds a different value at all times, and it has never mattered, because only the buyer’s own value is ever read.

The mod keeps that contract exactly. It writes the chosen index immediately before the untouched vanilla purchase body runs, on the buyer’s machine only.

  • No RPCs are added, no Photon messages are altered, no protocol changes exist for the network to disagree about.
  • Host or client makes no difference — the buy path is identical either way.
  • Pity, dud memory and grant history are per player, per match. Your luck is yours, and it resets automatically on a new lobby or map load.
  • An unmodded friend simply keeps vanilla odds on their own purchases. Nothing breaks for either of you.

Compare this with the zombie AI

The two mods take opposite approaches for good reasons. Zombies are host-authoritative, so the AI mod drives them from the host only. Box purchases are already client-owned, so this mod needs no such rule. Each follows the contract the game itself established.

Performance

It costs less than vanilla

Zero per-frame cost

The mod has no update loop or coroutine of its own — it is purely event-driven. And because it suppresses vanilla’s 50 Hz re-roll on every box, a modded client does less background work per frame than an unmodded one.

Per purchase

One pass of plain managed arithmetic over the pool, at human click rate. The steady-state roll path allocates nothing — bags, tier tables and score data are all preallocated at census.

Per census

One pass of stat reads per box, once, the first time that box is used. Weapon names are copied to managed strings there, so even debug logging never touches interop again.

Memory

Per-box data is pure managed state in a cache capped at 64 boxes. No engine references are held, so an unloaded scene can never leak through this plugin. Worst case is a few kilobytes.

Self-healing

What happens if the game updates

The mod is built to fail into vanilla rather than into a broken state, which is the right trade for something that decides what weapon you get.

  • The three patch groups apply independently. If a future update renames one target, that group alone logs [SKIP] and its path runs pure vanilla while the rest keeps working.
  • Every engine entry point is exception-jailed. Three unexpected faults trip a permanent kill switch for the session: all patches step aside, the vanilla re-roll resumes instantly, and the game is left in a completely stock state.
  • Even a faulted roll writes a valid in-range index wherever possible, so a stale or out-of-range prize is not reachable.
  • The mod can never leave the box worse than vanilla. That is the design constraint the whole reliability model is built around.

If the kill switch trips you will see it in the console, in plain language:

BepInEx console · the kill switch
UngodlyMysteryBox is standing down for the rest of this game session. The box now
runs 100% vanilla logic (including the vanilla FixedUpdate re-roll). Nothing is
left in a modified state.

Stated, not hidden

Honest limitations

LimitationWhy
Fire rate is excluded from the power model The metadata alone cannot prove whether the game's fire-rate field means shots per second or delay between shots, and guessing wrong would invert the ranking. The magazine-burst term already separates weapon archetypes well.
Luck is per-client Exactly like vanilla. The box index was never network-synced by the game, so this mod does not sync it either.
Tiers are relative to each pool By design — it is what lets the system work on maps that did not exist when the mod was written.
Unresolvable pool entries score mid-pool If a weapon controller cannot be resolved, that entry is scored exactly mid-pool. If an entire pool is unresolvable, that box falls back to high-quality uniform rolls — still frame-decorrelated, still cheaper than vanilla.

Optional

Watching it work

At the default Info level you get the load banner, which patch groups engaged, one census line per box, and session resets. Set the log level to Debug in BepInEx\config\BepInEx.cfg and you additionally get the full per-tier weapon list at census and a one-line verdict for every roll: tier, weapon, and pity state.

Turning the BepInEx console on is what makes any of this visible. It is worth doing for a round just to watch the census run.

Install the mystery box