perks/PerkRerollShare.cs

A multiplayer-only Epic perk that, when the local player rerolls, has a chance to spawn a reroll item for nearby teammates. It computes radius and chance by level, finds alive players in range, and uses the Manager RPCs to spawn the item and trigger highlight and dodge/duck effects.

Networking
using System;
using Sandbox;

[Perk( Rarity.Epic, multiplayerMode: MultiplayerMode.OnlyMultiplayer, locked: true, minUnlocksReq: 2, alwaysOfferDebug: false, IncludedCategories = new[] { PerkCategory.Aoe })]
public class PerkRerollShare : Perk
{
	private enum Mod { Chance };

	private const float RADIUS = 300f;


	static PerkRerollShare()
	{
		Register<PerkRerollShare>(
			name: "Reroll Sharing",
			imagePath: "textures/icons/vector/reroll_sharing.png",
			description: level => $"{GetValue( level, Mod.Chance, true )}% chance for nearby players\nto get +1 reroll-item when you reroll",
			upgradeDescription: level => $"{GetValue( level - 1, Mod.Chance, true )}%→{GetValue( level, Mod.Chance, true )}% chance for\nnearby players to get +1 reroll-item\nwhen you reroll"
		);
	}

	public override void Start()
	{
		base.Start();

		HighlightColor = new Color( 0.7f, 0.7f, 1f );
		HighlightDuration = 0.25f;
		HighlightOpacity = 3f;
	}

	public override void Refresh()
	{
		base.Refresh();

	}

	private static float GetValue( int level, Mod mod, bool isPercent = false )
	{
		switch ( mod )
		{
			case Mod.Chance:
			default:
				return isPercent
					? 15f + 10f * level
					: 0.15f + 0.1f * level;
		}
	}

	public override void OnRerollAfter()
	{
		base.OnRerollAfter();

		Vector2 pos = Player.Position2D;
		float radius = RADIUS * Player.Stats[PlayerStat.RadiusMultiplier];
		float chance = GetValue( Level, Mod.Chance );

		foreach ( var player in Manager.Instance.AlivePlayers )
		{
			if ( player == Player )
				continue;

			if ( Game.Random.Float( 0f, 1f ) > chance )
				continue;

			if ( (player.Position2D - pos).LengthSquared < MathF.Pow( radius, 2f ) )
			{
				var targetPos = player.Position2D;
				float time = Game.Random.Float( 0.5f, 0.75f );
				float height = time * 175f * Game.Random.Float( 0.9f, 1.1f );

				Manager.Instance.SpawnItemRpc( "reroll_item", Player.Position2D, player, time, height );

				Highlight();

				var dir = (player.Position2D - Player.Position2D).Normal;
				Player.DodgeDuckRpc( dir, time: Game.Random.Float( 0.1f, 0.125f ) );
			}
		}
	}
}