ShrinkingZone

v1.0.4·Updated 2026-09-29

A closing perimeter that shrinks over time, damaging players caught outside it based on their max health. Sound effects are available but OFF by default following reports of motion sickness.

About this mod Author’s original text

ShrinkingZone — ROUNDS Mod

A closing "safe zone" for ROUNDS: a circular perimeter that shrinks over time,

damaging any player caught outside it (battle-royale ring style).

Files

  • ShrinkingZonePlugin.cs — BepInEx plugin entry point, hooks round start/end.
  • ZoneController.cs — spawns the ring visual, shrinks it, and damages players outside it.
  • ShrinkingZoneMod.csproj — build project; references the 4 game DLLs needed to compile.
  • manifest.json — package manifest.

Requirements

  • BepInEx (5.4.x) installed for ROUNDS
  • UnboundLib — round lifecycle hooks
  • (Optional) ModdingUtils — extra player/health helpers if you want cleaner damage calls
  • Visual Studio / Rider / VS Code with the.NET SDK
  • References to Assembly-CSharp.dll, UnityEngine.dll, BepInEx.dll, and UnboundLib.dll

from your ROUNDS install (ROUNDS/BepInEx/plugins/ and ROUNDS/ROUNDS_Data/Managed)

Verified against Assembly-CSharp.dll / UnboundLib.dll via dnSpy

Every field/method/attribute name below has been confirmed against the real

game and library assemblies — no more guessing left in this mod. Kept here as

a reference in case you update BepInEx/UnboundLib/the game later and need to

re-check anything that might have changed.

  • ~~How to enumerate active players~~ ✅ Confirmed: PlayerManager.instance.players

is a public List players. Code already matches this exactly.

  • ~~How to apply damage, and how to read max health~~ ✅ Confirmed:
  • Player.data is a CharacterData with plain public floats

health and maxHealth.

  • Damage is dealt through a DamagableEvent (subclass of abstract

Damagable) sitting on the player's GameObject — accessed via

player.GetComponent() since no cached field was found.

  • Real signature: `TakeDamage(Vector2 damage, Vector2 damagePosition,

GameObject damagingWeapon = null, Player damagingPlayer = null,

bool lethal = true, bool ignoreBlock = false). Note damage` is a

Vector2 (magnitude = amount, direction = knockback), not a float —

ZoneController.ApplyZoneDamage now builds this vector pointing back

toward the zone center.

  • ~~Round start/end hook names~~ ✅ Confirmed: GameModeHooks is a

public static class holding plain const string identifiers —

HookRoundStart = "RoundStart" and HookRoundEnd = "RoundEnd" — exactly

matching what ShrinkingZonePlugin.cs already uses.

All three items above are confirmed — see the "Multiplayer / networking"

section below for the remaining (now also resolved) networking-specific checks.

Tuning

All the knobs are public static fields at the top of ShrinkingZonePlugin:

StartRadius = 30f;

FinalRadius = 3f;

ShrinkStartDelay = 5f;

ShrinkDuration = 25f;

DamagePercentPerSecond = 0.05f; // 5% of the player's MAX health per second

DamageTickInterval = 0.5f;

Damage scales off each player's max health rather than a flat number, so

the zone hurts proportionally regardless of health-boosting cards a player has

picked up. At the defaults, a player fully outside the zone loses 5% of their

max health every second (i.e. dies in ~20s of standing outside it).

Multiplayer / networking

The zone is now host-authoritative:

  • Only the master client (PhotonNetwork.IsMasterClient) advances the

shrink timer and computes the "true" radius.

  • Every SyncInterval (default 0.2s) the host broadcasts `(center, radius,

timer) to all clients via NetworkingManager.RPC(...)`, landing on the

static [UnboundRPC] RPCA_SyncZoneState method on every machine.

  • Non-host clients never compute their own radius — they just render whatever

the last synced value was. This is what keeps everyone's ring visually

identical instead of drifting apart from frame-rate/timing differences.

  • Damage is still applied locally per-client, but only for players that

client actually owns (PhotonView.IsMine), to avoid multiple machines

applying the same damage tick to the same player.

Things to verify for the networking layer specifically

  • ~~NetworkingManager.RPC signature~~ ✅ Confirmed:

public static void RPC(Type targetType, string m

Install & use Install: BepInEx plugin

  1. The archive from playbuff is the mod itself — usually a BepInEx plugin (a .dll or a plugin folder once unzipped).
  2. Recommended: use a community mod manager (such as r2modman) — pick this game, import the mod, and the manager sets up BepInEx and its dependencies for you.
  3. Manual route: install the BepInEx loader in the game folder, then drop the unzipped .dll or plugin folder into BepInEx/plugins/.
  4. Launch the game — the BepInEx console logs every plugin it loads; seeing this mod in the log means it is installed.

Mods with listed dependencies need those installed too, or they will not load. Options are usually changed in-game or in the plugin's config file.

Dependencies

Install these first, or the mod will not work:

willis81808-UnboundLib

File & checksum

Filename
ShrinkingZone-1.0.4.zip
File size
25.6 KiB