ShrinkingZone

版本 v1.0.4·更新於 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.

模組介紹 作者原文

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

安裝與使用 安裝:BepInEx 外掛

  1. 本站下載的壓縮包就是模組本體,通常是 BepInEx 外掛(解壓後得到 .dll 或外掛資料夾)。
  2. 建議流程:用社群模組管理器(如 r2modman)選中本遊戲後匯入該模組,管理器會自動裝好 BepInEx 前置並處理依賴。
  3. 手動流程:先在遊戲目錄裝好 BepInEx 載入器,再把解壓出的 .dll 或外掛資料夾放進 BepInEx/plugins/。
  4. 啟動遊戲,BepInEx 控制台會列印載入日誌;確認這個模組出現在日誌裡即為安裝成功。

帶「前置依賴」的模組需要一併安裝,否則不會載入。功能開關通常在遊戲內或外掛自帶的設定檔裡調整。

前置依賴

下面這些內容需要先安裝,否則該模組不會生效:

willis81808-UnboundLib

檔案與校驗

檔案名稱
ShrinkingZone-1.0.4.zip
檔案大小
25.6 KiB