components/flashlight.cs

A component that implements a player flashlight. It finds first‑person and world models and a spotlight on start, toggles the light on input, updates model animation parameters and visibility based on player state, and broadcasts small RPCs to set spotlight radius, model floats, transform and play click sounds.

NetworkingFile Access
using Sandbox;

public class Flashlight : Component
{
	[Property] public SpotLight Spotlight {get;set;}
	[Property] public Player__Controller Player_Controller {get;set;}
	[Property] public SkinnedModelRenderer Model_Renderer {get;set;}
	[Property] public ModelRenderer WMDL {get;set;}
	
	GameObject c;
	SkinnedModelRenderer VMDL;
	ModelRenderer hold_R;
	SoundEvent Click;
	
	protected override void OnStart()
	{
		c = Scene.Camera.GameObject;
		VMDL = c.GetChild("flashlight").GetComponent<SkinnedModelRenderer>(true);
		hold_R = VMDL.Components.GetInDescendants<ModelRenderer>(true);
		Click = ResourceLibrary.Get<SoundEvent>("prereqs/sound/effects/click/click.sound");
	}
	
	[Sync] public bool Off {get;set;} = true;
	
	protected override void OnUpdate()
	{ _VMDL(); _WMDL(); if (IsProxy) return;
		Toggling(); Positioning();
	}
	
	void Toggling()
	{
		if (Input.Pressed("f"))
		{ Off = !Off; PlaySound(GameObject, Click);
			SpotLight_Set_Radius(Spotlight, Off ? 0 : 500);
			SkinnedModelRenderer_Set_Float(Model_Renderer, "holdtype", Off ? 0 : 4);
			VMDL.GameObject.Enabled = !Off;
		}
	}
	
	void Positioning()
	{
		var Position = Player_Controller.IsThirdPerson ? WorldPosition + Vector3.Zero.WithZ(Player_Controller.Offset) : hold_R.WorldPosition;
		GameObject_Set_WorldPosition(Spotlight.GameObject, Position);
		GameObject_Set_WorldRotation(Spotlight.GameObject, c.WorldRotation);
	}
	
	void _VMDL()
	{ if (Off) return;
		if (IsProxy || Player_Controller.IsThirdPerson)
			VMDL.GameObject.Enabled = false;
		else VMDL.GameObject.Enabled = true;
		
		if (IsProxy)
			return;
		
		if (Player_Controller.State == "run")
			VMDL.Set("move_bob", 1);
		else if (Player_Controller.State == "walk")
			VMDL.Set("move_bob", .5f);
		else VMDL.Set("move_bob", 0);
		
		if (Player_Controller.State == "jump"
			|| Player_Controller.State == "fall")
			VMDL.Set("b_grounded", false);
		else VMDL.Set("b_grounded", true);
	}
	
	void _WMDL()
	{
		if (Off)
		{WMDL.GameObject.Enabled = false; return;}
		WMDL.GameObject.Enabled = true;
		
		if (Player_Controller.IsThirdPerson || IsProxy)
		{WMDL.RenderType = ModelRenderer.ShadowRenderType.On; return;}	
	WMDL.RenderType = ModelRenderer.ShadowRenderType.ShadowsOnly; }
	
	[Rpc.Broadcast]
	public void SpotLight_Set_Radius(SpotLight sl, float r)
	{sl.Radius = r;}
	
	[Rpc.Broadcast]
	public void SkinnedModelRenderer_Set_Float(SkinnedModelRenderer smr, string n, float f)
	{smr.Set(n, f);}
	
	[Rpc.Broadcast]
	public void GameObject_Set_WorldPosition(GameObject go, Vector3 wp)
	{go.WorldPosition = wp;}
	
	[Rpc.Broadcast]
	public void GameObject_Set_WorldRotation(GameObject go, Angles wr)
	{go.WorldRotation = wr;}
	
	[Rpc.Broadcast]
	public void PlaySound(GameObject go, SoundEvent s)
	{go.PlaySound(s);}
protected override void OnDestroy() {if (!IsProxy) VMDL.GameObject.Enabled = false;}}