Example project for setting up a BepinEx 5 (mono) plugin to connect a game to Crowd Control
All game-specific code (effects, Harmony patches, metadata, and game state checks) is included
as commented-out examples marked with == EXAMPLE (Anger Foot) ==. The project builds and runs
as-is without any game-specific code; uncomment and adapt the examples for your game instead of
deleting them.
Instructions:
-
Name the Project for Your Game
Both settings are in theALWAYS SET THESE FOR A NEW GAME!blocks:GameNameinBepinExExample\BepinExExample.csproj- names the output DLL (e.g.CrowdControl.AngerFoot.dll)MOD_NAME(andMOD_VERSION) inBepinExExample\CrowdControlMod.cs- the display name shown in the BepinEx log
(MOD_NAMEcan't be moved into the csproj because the[BepInPlugin]attribute requires compile-time constants.)
MOD_GUIDcan stay as-is - only one Crowd Control mod is installed per game.
-
Update References
SetGameBaseDirinBepinExExample\BepinExExample.csprojto your game's install folder.
Update the BepinEx references to point to the BepinEx.dll from the downloaded version of BepinEx.
Add a reference to Assembly-CSharp from the game's data folders. -
Create Effect Functions
Delegates\Effects\Implementations\contains the classes implementing effects.
Each file there is a commented example demonstrating a pattern:CompleteLevel.cs/RestartLevel.cs- instant (non-timed) effectsGodMode.cs/InfiniteAmmo.cs- timed effects toggled on start/stopForceKick.cs- a timed effect that acts every tickPassiveEnemies.cs/StaticEnemies.cs- timed effects with cross-effect conflicts
-
Create Timed Effects
Timed effects are any effects with adefaultDurationon their[Effect]attribute.
Pausing while the game is busy, resuming, and reporting the remaining time to the Crowd Control client are all handled automatically byTimedEffectState. -
Setup IsReady & GetGameState Functions
GameStateManager.cscontains functions calledIsReadyandGetGameState.
IsReadyreturns a boolean indicating whether the game is in a state ready to execute effects.
GetGameStatereturns the current game state (Ready, Paused, NotFocused, Menu, Loading, ...).
State changes are automatically reported to the Crowd Control client as they happen; add your game-specific checks where marked with TODO. -
Define Metadata (Optional)
Delegates\Metadata\MetadataDelegates.cscontains the metadata delegates.
Static methods tagged[Metadata("key")]answerDataRequestqueries from the client, and any keys listed inCommonMetadataare attached to every effect response. -
Attach Action Queue (Uncommon)
In rare cases, the FixedUpdate() method of the plugin is not called automatically as part of the standard game loop.
InCrowdControlMod.csthere is an example harmony patch to attach to the FixedUpdate() function of some universal object.
This should be used if and only if the FixedUpdate() method is not called automatically.
Displaying viewer names:
Viewer names come from external services and may contain characters your game can't render
(emoji, control characters, rich-text markup, etc). Use request.GetViewerDisplayName()
(from EffectRequestEx.cs) instead of reading request.viewer directly - it returns a
sanitized name and falls back to "the crowd" when no usable name is present.
Manual reconnect hotkey:
Press F9 in-game to request a Crowd Control reconnect. The plugin only attempts this when the
Crowd Control client process/semaphore is found, and the hotkey has a 5 second cooldown to avoid spam.
CrowdControlMod.ShowGameUiMessage() is the game-specific hook for displaying reconnect status in
your game's toast/HUD/dialog UI; it is intentionally a no-op in the example pack.
CrowdControlMod.Instance.Client offers helper functions for hiding or disabling effects on the menu:
ShowEffects(params string[] codes) / ShowAllEffects()
HideEffects(params string[] codes) / HideAllEffects()
EnableEffects(params string[] codes) / EnableAllEffects()
DisableEffects(params string[] codes) / DisableAllEffects()
Async variants of all of the above are also available.