

A scaling library for R.E.P.O. modders. Handles the hard parts of scaling game objects -- physics, audio, animation, colliders, NavMesh, multiplayer sync -- so you don't have to.
v0.6.0: Loom's arms finally track a shrunken body. Six new
ScaleOptions(separate restore speed, impact flash, camera shake, voice pitch, bonk-expand, external Apply lock) plusScaleManager.ForceApply/ForceRestorefor the owning mod to bypass the lock. Held forceGrabPoint items sit at eye height when shrunken instead of waist.ScaleController.CurrentOptionsexposes the active session's option snapshot.
If you're building a mod that changes the size of things (shrink rays, growth potions, whatever), ScalerCore gives you a clean API and takes care of the edge cases.
This is a library, not a standalone mod. End users don't need to interact with it directly. If you're a player, you probably got here because a mod like ShrinkerGun: COMPRESSOR depends on it.
For modders building size-changing mechanics. If you're looking for a shrink ray, check out ShrinkerGun: COMPRESSOR which is built on ScalerCore.
Reference ScalerCore.dll in your project. Add a hard dependency in your plugin:
[BepInDependency("Vippy.ScalerCore", BepInDependency.DependencyFlags.HardDependency)]
ScalerCore automatically attaches ScaleController components to all enemies, players, valuables, items, carts, and doors at runtime via Harmony patches. You don't need to add them yourself.
using ScalerCore;
// Shrink with default options (40% scale)
ScaleManager.Apply(targetGameObject);
// Shrink with custom options
var opts = ScaleOptions.Default;
opts.Factor = 0.5f;
opts.Duration = 60f;
ScaleManager.Apply(targetGameObject, opts);
// Restore with animation
ScaleManager.Restore(targetGameObject);
// Restore instantly (for bonk/damage reactions)
ScaleManager.RestoreImmediate(targetGameObject);
// Check state
bool tiny = ScaleManager.IsScaled(targetGameObject);
ScaleManager.Apply is host-authoritative. The host calls it, and RPCs propagate to all clients automatically. Late-joining players receive the current state on connect.
ScalerCore attaches a ScaleController (a MonoBehaviourPunCallbacks) to every enemy, player, valuable, item, and door. On the first scale operation, the controller:
ScaleHandlerRegistry based on what the object isLateUpdate to fight game code that resets localScaleBuilt-in handlers cover enemies, players, valuables, items, carts, and doors.
Implement IScaleHandler and register it with a predicate:
using ScalerCore;
using ScalerCore.Handlers;
public class MyBossHandler : IScaleHandler
{
public void Setup(ScaleController ctrl)
{
// Cache components, set ScaleTarget if the visual root
// is different from the physics root
}
public void OnScale(ScaleController ctrl)
{
// Called when the object is scaled down
}
public void OnRestore(ScaleController ctrl, bool isBonk)
{
// Called when restored. isBonk = true means instant (damage),
// false means animated (timer/gun toggle)
}
public void OnUpdate(ScaleController ctrl) { }
public void OnLateUpdate(ScaleController ctrl) { }
public void OnDestroy(ScaleController ctrl) { }
}
Register it at plugin startup. Use priority > 0 to override built-in handlers:
ScaleHandlerRegistry.Register(
new MyBossHandler(),
go => go.GetComponentInParent<EnemyParent>()?.name.Contains("MyBoss") == true,
priority: 10
);
The registry resolves handlers by checking predicates in descending priority order. First match wins.
| Method | Description |
|---|---|
Apply(GameObject target) |
Scale with default options (ScaleOptions.Default). |
Apply(GameObject target, ScaleOptions options) |
Scale with custom options. Same factor on an already-scaled target toggles it back; different factor rescales. |
ApplyIfNotScaled(GameObject target) |
Scale only if not already scaled. No-op if already scaled. Returns true if scaling was applied. |
ApplyIfNotScaled(GameObject target, ScaleOptions options) |
Same with custom options. Ideal for cart mods and continuous triggers. |
GetController(GameObject target) |
Get the ScaleController for a game object (resolves through PlayerShrinkLink). Returns null if none. |
Restore(GameObject target) |
Restore with smooth animation. No-op when locked via RejectExternalApply. |
RestoreImmediate(GameObject target) |
Restore instantly (respects bonk immunity timer). No-op when locked via RejectExternalApply. |
ForceApply(GameObject target, ScaleOptions options) |
Apply without the RejectExternalApply check. For the mod that owns the lock. |
ForceRestore(GameObject target) |
Restore without the RejectExternalApply check. For the mod that owns the lock. |
UpdateOptions(GameObject target, ScaleOptions options) |
Replace the stored options on a live session without re-dispatching scale. Read CurrentOptions, mutate, pass back. Useful when restore-direction fields (RestoreSpeed, SuppressImpactFlash, SuppressCameraShake) need to track a config change mid-session. Returns false on missing controller, no active session, or RejectExternalApply lock. |
ForceUpdateOptions(GameObject target, ScaleOptions options) |
UpdateOptions without the lock check. For the mod that owns the lock. |
IsScaled(GameObject target) |
Returns true if the object is currently scaled. |
CleanupAll() |
Restore all scaled objects. Called automatically on level change. |
Attached automatically to game objects. Key public members:
| Member | Description |
|---|---|
IsScaled |
Whether the object is currently scaled. |
OriginalScale |
The object's scale before any modification. |
CurrentOptions |
Snapshot of the active session's options. Read-only. |
TargetType |
What kind of object this is (ScaleTargets.Players, .Enemies, etc.). |
ScaleTarget |
Override in handler's Setup to scale a different transform than the controller's. |
AllowManualScale |
Static bool, gates debug shrink/expand requests. Host sets it. |
RequestBonkExpand() |
Client-safe expand request (sends RPC to host if called on non-host). |
RequestManualExpand() |
Manual expand (skips bonk immunity). |
RequestManualShrink() |
Manual shrink request. |
public interface IScaleHandler
{
void Setup(ScaleController ctrl);
void OnScale(ScaleController ctrl);
void OnRestore(ScaleController ctrl, bool isBonk);
void OnUpdate(ScaleController ctrl);
void OnLateUpdate(ScaleController ctrl);
void OnDestroy(ScaleController ctrl);
}
| Method | Description |
|---|---|
Register(IScaleHandler handler, Func<GameObject, bool> predicate, int priority = 0) |
Register a handler. Higher priority wins. Built-ins use priority 0. |
Resolve(GameObject target) |
Returns the highest-priority matching handler, or null. |
Each Apply() call takes a ScaleOptions struct. Use ScaleOptions.Default as a starting point and override what you need.
| Field | Default | Description |
|---|---|---|
Factor |
0.4 |
Scale multiplier (0.4 = 40% of original size) |
Duration |
0 |
Seconds until auto-restore (0 = permanent) |
Speed |
2.0 |
Scale animation speed (used for both directions when RestoreSpeed is 0) |
RestoreSpeed |
0 |
Animation speed for the expand direction. 0 falls back to Speed. |
BonkImmuneDuration |
5.0 |
Grace period after scaling before damage can restore |
MassCap |
50.0 |
Max rigidbody mass while scaled |
SpeedFactor |
0.75 |
Enemy NavMesh speed multiplier |
AnimSpeedMultiplier |
1.5 |
Player animation speed while scaled |
FootstepPitchMultiplier |
1.5 |
Player footstep pitch while scaled |
AllowedTargets |
All |
Flags: Players, Enemies, Items, Valuables, All |
InvertedMode |
false |
If true, scaled state is the default and bonk temporarily grows back |
SuppressValueDropExpand |
false |
If true, valuables won't expand when damaged while scaled (for cart mods) |
PreserveMass |
false |
If true, rigidbody mass stays at original value while scaled (for cart mods) |
SuppressImpactFlash |
false |
Skips the impact flash on shrink/expand (for cart-style mods that fire constantly) |
SuppressCameraShake |
false |
Skips the camera shake on expand (pair with SuppressImpactFlash for a silent restore) |
SuppressVoicePitch |
false |
No audio pitch shift on the controller's sounds or player's voice chat |
IgnoreBonkExpand |
false |
Damage does not restore the controller. Covers every bonk path. |
RejectExternalApply |
false |
External Apply/Restore/RestoreImmediate calls from other mods no-op. Owning mod uses ForceApply/ForceRestore. |
Flags enum for filtering what Apply() affects:
var opts = ScaleOptions.Default;
opts.AllowedTargets = ScaleTargets.Enemies | ScaleTargets.Valuables;
ScaleManager.Apply(target, opts); // skips players and items
ScalerCore is a pure library with no user-facing config. All scaling behavior (factor, speed, duration, etc.) is controlled per-call via ScaleOptions -- consuming mods expose whatever settings make sense for them.
For enemies:
For players:
For valuables:
For items:
For non-pocketable items (carts, cart cannon, cart laser, tracker):
For all types:
ShrinkerGun: COMPRESSOR is a shrink ray gun built on ScalerCore. Shows how to build ScaleOptions, call Apply, and handle per-target-type durations.