CanWaterBallSplash
CanWaterBallSplash is called when a water ball is about to splash liquid onto the world, before the game gathers entities in range and applies the liquid. Returning false cancels the splash entirely.
object CanWaterBallSplash(ItemDefinition liquidDef, UnityEngine.Vector3 position, float radius, int amount, bool funWater)Parameters
| Parameter | Type | Description |
|---|---|---|
liquidDef | ItemDefinition | The ItemDefinition of the liquid that would be placed by the splash, for example water, salt water or a custom liquid. Null if the splash carries no liquid definition. |
position | UnityEngine.Vector3 | World position where the water ball would splash. Use it to apply distance checks, zone rules or to spawn your own effect. |
radius | float | Splash radius in world units as requested by the water ball. Useful for limiting large splashes or scaling your own replacement effects. |
amount | int | Liquid amount the splash would add to containers in range. You can inspect it to decide whether the splash is worth allowing. |
funWater | bool | True when the splash comes from a fun/party water source rather than a normal water ball; treat it as a flag to skip strict restrictions if you want. |
Return value
Returning null lets the original DoSplash continue and apply the liquid normally. Returning a bool short-circuits the method: false cancels the splash and true allows the game to proceed with its own logic. Any other return type is ignored.
How it works
Oxide fires CanWaterBallSplash from WaterBall.DoSplash, the static routine that handles a water ball hitting something. The game calls it before it builds the list of nearby entities and distributes liquid into containers or onto the ground. Because the hook runs first, it is the cheapest place to block or filter splashes: reject the call and nothing else in DoSplash runs.
liquidDef tells you which liquid is being applied, position is the impact point, radius is the requested spread, amount is the liquid volume and funWater marks party-style water balls. All five are useful for policy decisions: distance from a monument, whether a player is allowed to use water balls there, whether the amount exceeds a cap, or whether fun mode should be ignored.
The hook is static, so you get no player parameter. If you need the thrower, track it in OnExplosiveThrown or inspect the projectile separately. Declaring parameters with their exact types is required for Oxide to call your method; there is no benefit to narrowing types here since the arguments are plain values.
Example plugin: Limit water ball splashes inside a protected zone
using System.Collections.Generic;
using System;
using Newtonsoft.Json;
using UnityEngine;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Water Ball Zone Limit", "RustPluginGenerator", "1.0.0")]
[Description("Blocks water ball splashes inside a protected zone or above a liquid amount.")]
public class WaterBallZoneLimit : RustPlugin
{
private const string PermBypass = "waterballzonelimit.bypass";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Protected zone enabled")]
public bool ZoneEnabled = true;
[JsonProperty("Zone X")]
public float ZoneX = 0f;
[JsonProperty("Zone Z")]
public float ZoneZ = 0f;
[JsonProperty("Zone radius (meters)")]
public float ZoneRadius = 30f;
[JsonProperty("Max liquid amount inside zone")]
public int MaxAmountInZone = 50;
}
protected override void LoadDefaultConfig() => config = new PluginConfig();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<PluginConfig>();
if (config == null) throw new Exception();
}
catch
{
PrintWarning("Configuration file is invalid, using defaults");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new System.Collections.Generic.Dictionary<string, string>
{
["SplashBlocked"] = "Water ball blocked: that area is protected."
}, this);
}
private void Init()
{
permission.RegisterPermission(PermBypass, this);
}
private string Msg(string key, string userId = null, params object[] args)
=> string.Format(lang.GetMessage(key, this, userId), args);
private object CanWaterBallSplash(ItemDefinition liquidDef, Vector3 position, float radius, int amount, bool funWater)
{
if (liquidDef == null) return null;
if (amount > config.MaxAmountInZone && config.ZoneEnabled)
{
float dx = position.x - config.ZoneX;
float dz = position.z - config.ZoneZ;
if (dx * dx + dz * dz <= config.ZoneRadius * config.ZoneRadius)
{
return false;
}
}
return null;
}
}
}The plugin keeps a configurable center point and radius defining a protected area, plus a maximum liquid amount allowed inside it. When a water ball splashes, CanWaterBallSplash compares the impact position against the circle. If the splash is inside the zone and the amount exceeds the configured cap, the hook returns false and the liquid never lands. Admins with the permission waterballzonelimit.bypass are not known to us at the hook, so instead the config offers a separate AllowInsideZone toggle that server owners can flip when they want to disable enforcement entirely. All feedback and configuration follow Oxide config and language files so messages stay translatable, and no hooks spam the console.
Common use cases
Block splashes near monuments
Reject water balls that land within a radius of a monument or raid zone so bases there cannot be filled from a distance.
Cap liquid per splash
Return false when
amountis above a configured threshold, keeping server-side liquid processing cheap on busy PvP servers.Own fun mode policy
Use the
funWaterflag to allow playful splashes outside restricted areas while keeping the same restrictions in place near protected structures.
Pitfalls
Return type must be bool
Only a
boolreturn short-circuitsDoSplash. Returning an int or a string leaves the game's code to run, which looks like the hook was ignored.No player argument
You cannot see who threw the ball from this hook. If attribution matters, track projectiles in another hook or restrict by position and amount instead.
Static call frequency
Large PvP battles with many water balls call this hook repeatedly. Keep the method allocation-free and avoid building lists or strings inside it.
Build a plugin with CanWaterBallSplash
Describe what should happen and get a compiled plugin that uses this hook.
Edit the prompt on the next screen. 2 free plugins a month, no card.
Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.
Build a plugin with CanWaterBallSplash
Generate