s&box Package Code Search
Search C# source code, UI razor templates, shaders, and configs across s&box packages.
link Raw Facepunch API Link: https://public.facepunch.com/sbox/code/search/1/?ident=rwtrcsc.checkpointsystem&take=20
Showing code results for query:
*
(6 total matches found)
Editor
library
using Editor;
using Sandbox;
[EditorTool]
[Title( "Checkpoint Placer" )]
[Icon( "add_location" )]
public class CheckpointPlacer : EditorTool
{
int _nextIndex = 0;
GameObject _manager;
public override void OnEnabled()
{
EnsureManager();
RecalculateIndex();
Log.Info( "[CheckpointPlacer] Active. Next index: " + _nextIndex );
}
void EnsureManager()
{
foreach ( var go in Scene.GetAllObjects( true ) )
{
if ( go.Name == "CheckpointManager" )
{
_manager = go;
return;
}
}
_manager = new GameObject();
_manager.Name = "CheckpointManager";
_manager.Components.Create<CheckpointManager>();
Log.Info( "[CheckpointPlacer] Created CheckpointManager" );
}
void RecalculateIndex()
{
if ( _manager == null ) return;
int count = 0;
foreach ( var child in _manager.Children )
{
var cp = child.Components.Get<CheckpointRing>();
if ( cp is not null )
count++;
}
_nextIndex = count;
}
public override void OnUpdate()
{
base.OnUpdate();
var ray = Gizmo.CurrentRay;
var tr = Scene.Trace.Ray( ray, 10000f ).WithoutTags( "trigger" ).Run();
if ( !tr.Hit ) return;
var pos = tr.HitPosition + Vector3.Up * 10f;
Gizmo.Draw.Color = Color.Cyan.WithAlpha( 0.5f );
Gizmo.Draw.SolidSphere( pos, 80f );
Gizmo.Draw.Color = Color.White;
Gizmo.Draw.ScreenText( "Left click to place checkpoint " + _nextIndex, new Vector2( 10, 10 ) );
if ( Gizmo.WasLeftMousePressed )
{
EnsureManager();
RecalculateIndex();
PlaceCheckpoint( pos );
}
}
void PlaceCheckpoint( Vector3 position )
{
var go = new GameObject();
go.Parent = _manager;
go.WorldPosition = position;
go.Name = "Checkpoint_" + _nextIndex;
var col = go.Components.Create<SphereCollider>();
col.Radius = 150f;
col.IsTrigger = true;
go.Tags.Add( "trigger" );
var cp = go.Components.Create<CheckpointRing>();
cp.CheckpointIndex = _nextIndex;
cp.IsFinishLine = false;
cp.IsLastCheckpoint = false;
var model = go.Components.Create<ModelRenderer>();
model.Model = Model.Load( "models/primitives/sphere.vmdl" );
model.Tint = Color.Cyan;
go.WorldScale = new Vector3( 0.8f, 0.8f, 3f );
_nextIndex++;
Log.Info( "[CheckpointPlacer] Placed Checkpoint_" + (_nextIndex - 1) );
}
}
Game
library
global using static Sandbox.Internal.GlobalGameNamespace;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Rendering;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "Checkpoint System" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "checkpointsystem" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "rwtrcsc" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "rwtrcsc.checkpointsystem" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "29" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]
[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "2026-10-08T19:47:22.9791400Z" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.111.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.111.0")]
Game
library
using Sandbox;
using System;
using System.Linq;
public sealed class CheckpointRing : Component
{
[Property] public int CheckpointIndex { get; set; } = 0;
[Property] public bool IsFinishLine { get; set; } = false;
[Property] public bool IsLastCheckpoint { get; set; } = false;
[Property] public float DetectionRadius { get; set; } = 150f;
// Events � anyone can listen to these
public static Action<int> OnCheckpointHit;
public static Action OnFinishHit;
bool _triggered = false;
bool IsSequential => CheckpointManager.Instance?.Sequential ?? true;
int TotalCheckpoints()
{
if ( CheckpointManager.Instance == null ) return 0;
int count = 0;
foreach ( var child in CheckpointManager.Instance.GameObject.Children )
{
var cp = child.Components.Get<CheckpointRing>();
if ( cp is not null && !cp.IsFinishLine && !cp.IsLastCheckpoint )
count++;
}
return count;
}
bool AllCheckpointsHit()
{
int total = TotalCheckpoints();
int next = CheckpointManager.Instance?.NextCheckpoint ?? 0;
return next >= total;
}
protected override void OnUpdate()
{
if ( _triggered ) return;
var player = Scene.GetAllObjects( true )
.FirstOrDefault( go => go.Tags.Has( "player" ) );
if ( player == null ) return;
float dist = Vector3.DistanceBetween( WorldPosition, player.WorldPosition );
if ( dist >= DetectionRadius ) return;
if ( IsFinishLine || IsLastCheckpoint )
{
if ( !AllCheckpointsHit() )
{
int remaining = TotalCheckpoints() - (CheckpointManager.Instance?.NextCheckpoint ?? 0);
Log.Info( "[Checkpoint] Finish blocked � " + remaining + " remaining" );
return;
}
}
else if ( IsSequential )
{
int next = CheckpointManager.Instance?.NextCheckpoint ?? 0;
if ( CheckpointIndex != next ) return;
}
_triggered = true;
if ( IsFinishLine || IsLastCheckpoint )
{
Log.Info( "[Checkpoint] Finished!" );
CheckpointManager.Instance?.OnFinishReached();
OnFinishHit?.Invoke();
var cube = CheckpointManager.Instance?.ColorCube;
if ( cube is not null )
cube.Tint = Color.Green;
}
else
{
Log.Info( "[Checkpoint " + CheckpointIndex + "] Hit" );
CheckpointManager.Instance?.OnCheckpointReached( CheckpointIndex );
OnCheckpointHit?.Invoke( CheckpointIndex );
}
}
public void ResetCheckpoint()
{
_triggered = false;
}
}
Game
library
using Sandbox;
using System;
public sealed class CheckpointManager : Component
{
public static CheckpointManager Instance { get; private set; }
[Property] public bool Sequential { get; set; } = true;
[Property] public ModelRenderer ColorCube { get; set; }
[Property] public CheckpointRing FinishLine { get; set; }
[Property] public CheckpointRing LastCheckpoint { get; set; }
// Events
public Action<int> OnCheckpointReachedEvent;
public Action OnFinishReachedEvent;
public int NextCheckpoint { get; private set; } = 0;
protected override void OnAwake()
{
Instance = this;
if ( FinishLine is not null )
{
FinishLine.IsFinishLine = true;
FinishLine.IsLastCheckpoint = false;
}
if ( LastCheckpoint is not null )
{
LastCheckpoint.IsLastCheckpoint = true;
LastCheckpoint.IsFinishLine = false;
}
}
protected override void OnStart()
{
NextCheckpoint = 0;
}
public void OnCheckpointReached( int index )
{
NextCheckpoint = index + 1;
OnCheckpointReachedEvent?.Invoke( index );
Log.Info( "[CheckpointManager] Checkpoint " + index + " reached. Next: " + NextCheckpoint );
}
public void OnFinishReached()
{
OnFinishReachedEvent?.Invoke();
Log.Info( "[CheckpointManager] Finish reached!" );
}
public void ResetAll()
{
NextCheckpoint = 0;
foreach ( var child in GameObject.Children )
{
var cp = child.Components.Get<CheckpointRing>();
cp?.ResetCheckpoint();
}
Log.Info( "[CheckpointManager] Reset all checkpoints" );
}
}
Game
library
using Sandbox;
using System;
using System.Linq;
public sealed class CheckpointRing : Component
{
[Property] public int CheckpointIndex { get; set; } = 0;
[Property] public bool IsFinishLine { get; set; } = false;
[Property] public bool IsLastCheckpoint { get; set; } = false;
[Property] public float DetectionRadius { get; set; } = 150f;
// Events � anyone can listen to these
public static Action<int> OnCheckpointHit;
public static Action OnFinishHit;
bool _triggered = false;
bool IsSequential => CheckpointManager.Instance?.Sequential ?? true;
int TotalCheckpoints()
{
if ( CheckpointManager.Instance == null ) return 0;
int count = 0;
foreach ( var child in CheckpointManager.Instance.GameObject.Children )
{
var cp = child.Components.Get<CheckpointRing>();
if ( cp is not null && !cp.IsFinishLine && !cp.IsLastCheckpoint )
count++;
}
return count;
}
bool AllCheckpointsHit()
{
int total = TotalCheckpoints();
int next = CheckpointManager.Instance?.NextCheckpoint ?? 0;
return next >= total;
}
protected override void OnUpdate()
{
if ( _triggered ) return;
var player = Scene.GetAllObjects( true )
.FirstOrDefault( go => go.Tags.Has( "player" ) );
if ( player == null ) return;
float dist = Vector3.DistanceBetween( WorldPosition, player.WorldPosition );
if ( dist >= DetectionRadius ) return;
if ( IsFinishLine || IsLastCheckpoint )
{
if ( !AllCheckpointsHit() )
{
int remaining = TotalCheckpoints() - (CheckpointManager.Instance?.NextCheckpoint ?? 0);
Log.Info( "[Checkpoint] Finish blocked � " + remaining + " remaining" );
return;
}
}
else if ( IsSequential )
{
int next = CheckpointManager.Instance?.NextCheckpoint ?? 0;
if ( CheckpointIndex != next ) return;
}
_triggered = true;
if ( IsFinishLine || IsLastCheckpoint )
{
Log.Info( "[Checkpoint] Finished!" );
CheckpointManager.Instance?.OnFinishReached();
OnFinishHit?.Invoke();
var cube = CheckpointManager.Instance?.ColorCube;
if ( cube is not null )
cube.Tint = Color.Green;
}
else
{
Log.Info( "[Checkpoint " + CheckpointIndex + "] Hit" );
CheckpointManager.Instance?.OnCheckpointReached( CheckpointIndex );
OnCheckpointHit?.Invoke( CheckpointIndex );
}
}
public void ResetCheckpoint()
{
_triggered = false;
}
}
Game
library
using Sandbox;
using System;
public sealed class CheckpointManager : Component
{
public static CheckpointManager Instance { get; private set; }
[Property] public bool Sequential { get; set; } = true;
[Property] public ModelRenderer ColorCube { get; set; }
[Property] public CheckpointRing FinishLine { get; set; }
[Property] public CheckpointRing LastCheckpoint { get; set; }
// Events
public Action<int> OnCheckpointReachedEvent;
public Action OnFinishReachedEvent;
public int NextCheckpoint { get; private set; } = 0;
protected override void OnAwake()
{
Instance = this;
if ( FinishLine is not null )
{
FinishLine.IsFinishLine = true;
FinishLine.IsLastCheckpoint = false;
}
if ( LastCheckpoint is not null )
{
LastCheckpoint.IsLastCheckpoint = true;
LastCheckpoint.IsFinishLine = false;
}
}
protected override void OnStart()
{
NextCheckpoint = 0;
}
public void OnCheckpointReached( int index )
{
NextCheckpoint = index + 1;
OnCheckpointReachedEvent?.Invoke( index );
Log.Info( "[CheckpointManager] Checkpoint " + index + " reached. Next: " + NextCheckpoint );
}
public void OnFinishReached()
{
OnFinishReachedEvent?.Invoke();
Log.Info( "[CheckpointManager] Finish reached!" );
}
public void ResetAll()
{
NextCheckpoint = 0;
foreach ( var child in GameObject.Children )
{
var cp = child.Components.Get<CheckpointRing>();
cp?.ResetCheckpoint();
}
Log.Info( "[CheckpointManager] Reset all checkpoints" );
}
}
Debug: View Raw JSON Response
{
"TotalCount": 6,
"Files": [
{
"Ident": "rwtrcsc.checkpointsystem",
"Path": "Editor/CheckpointPlacer.cs",
"FileName": "CheckpointPlacer.cs",
"PackageType": "library",
"CodeKind": "Editor",
"AssetVersionId": 421921,
"IsPrivate": false,
"Code": "using Editor;\r\nusing Sandbox;\r\n\r\n[EditorTool]\r\n[Title( \"Checkpoint Placer\" )]\r\n[Icon( \"add_location\" )]\r\npublic class CheckpointPlacer : EditorTool\r\n{\r\n\tint _nextIndex = 0;\r\n\tGameObject _manager;\r\n\r\n\tpublic override void OnEnabled()\r\n\t{\r\n\t\tEnsureManager();\r\n\t\tRecalculateIndex();\r\n\t\tLog.Info( \"[CheckpointPlacer] Active. Next index: \" + _nextIndex );\r\n\t}\r\n\r\n\tvoid EnsureManager()\r\n\t{\r\n\t\tforeach ( var go in Scene.GetAllObjects( true ) )\r\n\t\t{\r\n\t\t\tif ( go.Name == \"CheckpointManager\" )\r\n\t\t\t{\r\n\t\t\t\t_manager = go;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t_manager = new GameObject();\r\n\t\t_manager.Name = \"CheckpointManager\";\r\n\t\t_manager.Components.Create<CheckpointManager>();\r\n\t\tLog.Info( \"[CheckpointPlacer] Created CheckpointManager\" );\r\n\t}\r\n\r\n\tvoid RecalculateIndex()\r\n\t{\r\n\t\tif ( _manager == null ) return;\r\n\r\n\t\tint count = 0;\r\n\t\tforeach ( var child in _manager.Children )\r\n\t\t{\r\n\t\t\tvar cp = child.Components.Get<CheckpointRing>();\r\n\t\t\tif ( cp is not null )\r\n\t\t\t\tcount++;\r\n\t\t}\r\n\t\t_nextIndex = count;\r\n\t}\r\n\r\n\tpublic override void OnUpdate()\r\n\t{\r\n\t\tbase.OnUpdate();\r\n\r\n\t\tvar ray = Gizmo.CurrentRay;\r\n\t\tvar tr = Scene.Trace.Ray( ray, 10000f ).WithoutTags( \"trigger\" ).Run();\r\n\r\n\t\tif ( !tr.Hit ) return;\r\n\r\n\t\tvar pos = tr.HitPosition + Vector3.Up * 10f;\r\n\r\n\t\tGizmo.Draw.Color = Color.Cyan.WithAlpha( 0.5f );\r\n\t\tGizmo.Draw.SolidSphere( pos, 80f );\r\n\r\n\t\tGizmo.Draw.Color = Color.White;\r\n\t\tGizmo.Draw.ScreenText( \"Left click to place checkpoint \" + _nextIndex, new Vector2( 10, 10 ) );\r\n\r\n\t\tif ( Gizmo.WasLeftMousePressed )\r\n\t\t{\r\n\t\t\tEnsureManager();\r\n\t\t\tRecalculateIndex();\r\n\t\t\tPlaceCheckpoint( pos );\r\n\t\t}\r\n\t}\r\n\r\n\tvoid PlaceCheckpoint( Vector3 position )\r\n\t{\r\n\t\tvar go = new GameObject();\r\n\t\tgo.Parent = _manager;\r\n\t\tgo.WorldPosition = position;\r\n\t\tgo.Name = \"Checkpoint_\" + _nextIndex;\r\n\r\n\t\tvar col = go.Components.Create<SphereCollider>();\r\n\t\tcol.Radius = 150f;\r\n\t\tcol.IsTrigger = true;\r\n\t\tgo.Tags.Add( \"trigger\" );\r\n\r\n\t\tvar cp = go.Components.Create<CheckpointRing>();\r\n\t\tcp.CheckpointIndex = _nextIndex;\r\n\t\tcp.IsFinishLine = false;\r\n\t\tcp.IsLastCheckpoint = false;\r\n\r\n\t\tvar model = go.Components.Create<ModelRenderer>();\r\n\t\tmodel.Model = Model.Load( \"models/primitives/sphere.vmdl\" );\r\n\t\tmodel.Tint = Color.Cyan;\r\n\t\tgo.WorldScale = new Vector3( 0.8f, 0.8f, 3f );\r\n\r\n\t\t_nextIndex++;\r\n\t\tLog.Info( \"[CheckpointPlacer] Placed Checkpoint_\" + (_nextIndex - 1) );\r\n\t}\r\n}\r\n"
},
{
"Ident": "rwtrcsc.checkpointsystem",
"Path": ".obj/__compiler_extra.cs",
"FileName": "__compiler_extra.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 421921,
"IsPrivate": false,
"Code": "global using static Sandbox.Internal.GlobalGameNamespace;\r\nglobal using Microsoft.AspNetCore.Components;\r\nglobal using Microsoft.AspNetCore.Components.Rendering;\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"AddonTitle\", \"Checkpoint System\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"AddonIdent\", \"checkpointsystem\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"OrgIdent\", \"rwtrcsc\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"Ident\", \"rwtrcsc.checkpointsystem\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"EngineVersion\", \"29\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"EngineMinorVersion\", \"1\" )]\r\n\r\n[assembly: System.Runtime.Versioning.TargetFramework( \".NETCoreApp,Version=v9.0\", FrameworkDisplayName = \".NET 9.0\" )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \"CompileTime\", \"2026-10-08T19:47:22.9791400Z\" )]\r\n[assembly: global::System.Reflection.AssemblyVersion(\"0.0.111.0\")]\r\n[assembly: global::System.Reflection.AssemblyFileVersion(\"0.0.111.0\")]"
},
{
"Ident": "rwtrcsc.checkpointsystem",
"Path": "Code/CheckpointRing.cs",
"FileName": "CheckpointRing.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 421921,
"IsPrivate": false,
"Code": "using Sandbox;\r\nusing System;\r\nusing System.Linq;\r\npublic sealed class CheckpointRing : Component\r\n{\r\n\t[Property] public int CheckpointIndex { get; set; } = 0;\r\n\t[Property] public bool IsFinishLine { get; set; } = false;\r\n\t[Property] public bool IsLastCheckpoint { get; set; } = false;\r\n\t[Property] public float DetectionRadius { get; set; } = 150f;\r\n\r\n\t// Events \ufffd anyone can listen to these\r\n\tpublic static Action<int> OnCheckpointHit;\r\n\tpublic static Action OnFinishHit;\r\n\r\n\tbool _triggered = false;\r\n\r\n\tbool IsSequential => CheckpointManager.Instance?.Sequential ?? true;\r\n\r\n\tint TotalCheckpoints()\r\n\t{\r\n\t\tif ( CheckpointManager.Instance == null ) return 0;\r\n\t\tint count = 0;\r\n\t\tforeach ( var child in CheckpointManager.Instance.GameObject.Children )\r\n\t\t{\r\n\t\t\tvar cp = child.Components.Get<CheckpointRing>();\r\n\t\t\tif ( cp is not null && !cp.IsFinishLine && !cp.IsLastCheckpoint )\r\n\t\t\t\tcount++;\r\n\t\t}\r\n\t\treturn count;\r\n\t}\r\n\r\n\tbool AllCheckpointsHit()\r\n\t{\r\n\t\tint total = TotalCheckpoints();\r\n\t\tint next = CheckpointManager.Instance?.NextCheckpoint ?? 0;\r\n\t\treturn next >= total;\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( _triggered ) return;\r\n\r\n\t\tvar player = Scene.GetAllObjects( true )\r\n\t\t\t.FirstOrDefault( go => go.Tags.Has( \"player\" ) );\r\n\r\n\t\tif ( player == null ) return;\r\n\r\n\t\tfloat dist = Vector3.DistanceBetween( WorldPosition, player.WorldPosition );\r\n\r\n\t\tif ( dist >= DetectionRadius ) return;\r\n\r\n\t\tif ( IsFinishLine || IsLastCheckpoint )\r\n\t\t{\r\n\t\t\tif ( !AllCheckpointsHit() )\r\n\t\t\t{\r\n\t\t\t\tint remaining = TotalCheckpoints() - (CheckpointManager.Instance?.NextCheckpoint ?? 0);\r\n\t\t\t\tLog.Info( \"[Checkpoint] Finish blocked \ufffd \" + remaining + \" remaining\" );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( IsSequential )\r\n\t\t{\r\n\t\t\tint next = CheckpointManager.Instance?.NextCheckpoint ?? 0;\r\n\t\t\tif ( CheckpointIndex != next ) return;\r\n\t\t}\r\n\r\n\t\t_triggered = true;\r\n\r\n\t\tif ( IsFinishLine || IsLastCheckpoint )\r\n\t\t{\r\n\t\t\tLog.Info( \"[Checkpoint] Finished!\" );\r\n\t\t\tCheckpointManager.Instance?.OnFinishReached();\r\n\t\t\tOnFinishHit?.Invoke();\r\n\r\n\t\t\tvar cube = CheckpointManager.Instance?.ColorCube;\r\n\t\t\tif ( cube is not null )\r\n\t\t\t\tcube.Tint = Color.Green;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tLog.Info( \"[Checkpoint \" + CheckpointIndex + \"] Hit\" );\r\n\t\t\tCheckpointManager.Instance?.OnCheckpointReached( CheckpointIndex );\r\n\t\t\tOnCheckpointHit?.Invoke( CheckpointIndex );\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void ResetCheckpoint()\r\n\t{\r\n\t\t_triggered = false;\r\n\t}\r\n}\r\n"
},
{
"Ident": "rwtrcsc.checkpointsystem",
"Path": "CheckpointManager.cs",
"FileName": "CheckpointManager.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 421921,
"IsPrivate": false,
"Code": "using Sandbox;\r\nusing System;\r\n\r\npublic sealed class CheckpointManager : Component\r\n{\r\n\tpublic static CheckpointManager Instance { get; private set; }\r\n\r\n\t[Property] public bool Sequential { get; set; } = true;\r\n\t[Property] public ModelRenderer ColorCube { get; set; }\r\n\t[Property] public CheckpointRing FinishLine { get; set; }\r\n\t[Property] public CheckpointRing LastCheckpoint { get; set; }\r\n\r\n\t// Events\r\n\tpublic Action<int> OnCheckpointReachedEvent;\r\n\tpublic Action OnFinishReachedEvent;\r\n\r\n\tpublic int NextCheckpoint { get; private set; } = 0;\r\n\r\n\tprotected override void OnAwake()\r\n\t{\r\n\t\tInstance = this;\r\n\r\n\t\tif ( FinishLine is not null )\r\n\t\t{\r\n\t\t\tFinishLine.IsFinishLine = true;\r\n\t\t\tFinishLine.IsLastCheckpoint = false;\r\n\t\t}\r\n\r\n\t\tif ( LastCheckpoint is not null )\r\n\t\t{\r\n\t\t\tLastCheckpoint.IsLastCheckpoint = true;\r\n\t\t\tLastCheckpoint.IsFinishLine = false;\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tNextCheckpoint = 0;\r\n\t}\r\n\r\n\tpublic void OnCheckpointReached( int index )\r\n\t{\r\n\t\tNextCheckpoint = index + 1;\r\n\t\tOnCheckpointReachedEvent?.Invoke( index );\r\n\t\tLog.Info( \"[CheckpointManager] Checkpoint \" + index + \" reached. Next: \" + NextCheckpoint );\r\n\t}\r\n\r\n\tpublic void OnFinishReached()\r\n\t{\r\n\t\tOnFinishReachedEvent?.Invoke();\r\n\t\tLog.Info( \"[CheckpointManager] Finish reached!\" );\r\n\t}\r\n\r\n\tpublic void ResetAll()\r\n\t{\r\n\t\tNextCheckpoint = 0;\r\n\t\tforeach ( var child in GameObject.Children )\r\n\t\t{\r\n\t\t\tvar cp = child.Components.Get<CheckpointRing>();\r\n\t\t\tcp?.ResetCheckpoint();\r\n\t\t}\r\n\t\tLog.Info( \"[CheckpointManager] Reset all checkpoints\" );\r\n\t}\r\n}\r\n"
},
{
"Ident": "rwtrcsc.checkpointsystem",
"Path": "CheckpointRing.cs",
"FileName": "CheckpointRing.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 421921,
"IsPrivate": false,
"Code": "using Sandbox;\r\nusing System;\r\nusing System.Linq;\r\npublic sealed class CheckpointRing : Component\r\n{\r\n\t[Property] public int CheckpointIndex { get; set; } = 0;\r\n\t[Property] public bool IsFinishLine { get; set; } = false;\r\n\t[Property] public bool IsLastCheckpoint { get; set; } = false;\r\n\t[Property] public float DetectionRadius { get; set; } = 150f;\r\n\r\n\t// Events \ufffd anyone can listen to these\r\n\tpublic static Action<int> OnCheckpointHit;\r\n\tpublic static Action OnFinishHit;\r\n\r\n\tbool _triggered = false;\r\n\r\n\tbool IsSequential => CheckpointManager.Instance?.Sequential ?? true;\r\n\r\n\tint TotalCheckpoints()\r\n\t{\r\n\t\tif ( CheckpointManager.Instance == null ) return 0;\r\n\t\tint count = 0;\r\n\t\tforeach ( var child in CheckpointManager.Instance.GameObject.Children )\r\n\t\t{\r\n\t\t\tvar cp = child.Components.Get<CheckpointRing>();\r\n\t\t\tif ( cp is not null && !cp.IsFinishLine && !cp.IsLastCheckpoint )\r\n\t\t\t\tcount++;\r\n\t\t}\r\n\t\treturn count;\r\n\t}\r\n\r\n\tbool AllCheckpointsHit()\r\n\t{\r\n\t\tint total = TotalCheckpoints();\r\n\t\tint next = CheckpointManager.Instance?.NextCheckpoint ?? 0;\r\n\t\treturn next >= total;\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( _triggered ) return;\r\n\r\n\t\tvar player = Scene.GetAllObjects( true )\r\n\t\t\t.FirstOrDefault( go => go.Tags.Has( \"player\" ) );\r\n\r\n\t\tif ( player == null ) return;\r\n\r\n\t\tfloat dist = Vector3.DistanceBetween( WorldPosition, player.WorldPosition );\r\n\r\n\t\tif ( dist >= DetectionRadius ) return;\r\n\r\n\t\tif ( IsFinishLine || IsLastCheckpoint )\r\n\t\t{\r\n\t\t\tif ( !AllCheckpointsHit() )\r\n\t\t\t{\r\n\t\t\t\tint remaining = TotalCheckpoints() - (CheckpointManager.Instance?.NextCheckpoint ?? 0);\r\n\t\t\t\tLog.Info( \"[Checkpoint] Finish blocked \ufffd \" + remaining + \" remaining\" );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( IsSequential )\r\n\t\t{\r\n\t\t\tint next = CheckpointManager.Instance?.NextCheckpoint ?? 0;\r\n\t\t\tif ( CheckpointIndex != next ) return;\r\n\t\t}\r\n\r\n\t\t_triggered = true;\r\n\r\n\t\tif ( IsFinishLine || IsLastCheckpoint )\r\n\t\t{\r\n\t\t\tLog.Info( \"[Checkpoint] Finished!\" );\r\n\t\t\tCheckpointManager.Instance?.OnFinishReached();\r\n\t\t\tOnFinishHit?.Invoke();\r\n\r\n\t\t\tvar cube = CheckpointManager.Instance?.ColorCube;\r\n\t\t\tif ( cube is not null )\r\n\t\t\t\tcube.Tint = Color.Green;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tLog.Info( \"[Checkpoint \" + CheckpointIndex + \"] Hit\" );\r\n\t\t\tCheckpointManager.Instance?.OnCheckpointReached( CheckpointIndex );\r\n\t\t\tOnCheckpointHit?.Invoke( CheckpointIndex );\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void ResetCheckpoint()\r\n\t{\r\n\t\t_triggered = false;\r\n\t}\r\n}\r\n"
},
{
"Ident": "rwtrcsc.checkpointsystem",
"Path": "Code/CheckpointManager.cs",
"FileName": "CheckpointManager.cs",
"PackageType": "library",
"CodeKind": "Game",
"AssetVersionId": 421921,
"IsPrivate": false,
"Code": "using Sandbox;\r\nusing System;\r\n\r\npublic sealed class CheckpointManager : Component\r\n{\r\n\tpublic static CheckpointManager Instance { get; private set; }\r\n\r\n\t[Property] public bool Sequential { get; set; } = true;\r\n\t[Property] public ModelRenderer ColorCube { get; set; }\r\n\t[Property] public CheckpointRing FinishLine { get; set; }\r\n\t[Property] public CheckpointRing LastCheckpoint { get; set; }\r\n\r\n\t// Events\r\n\tpublic Action<int> OnCheckpointReachedEvent;\r\n\tpublic Action OnFinishReachedEvent;\r\n\r\n\tpublic int NextCheckpoint { get; private set; } = 0;\r\n\r\n\tprotected override void OnAwake()\r\n\t{\r\n\t\tInstance = this;\r\n\r\n\t\tif ( FinishLine is not null )\r\n\t\t{\r\n\t\t\tFinishLine.IsFinishLine = true;\r\n\t\t\tFinishLine.IsLastCheckpoint = false;\r\n\t\t}\r\n\r\n\t\tif ( LastCheckpoint is not null )\r\n\t\t{\r\n\t\t\tLastCheckpoint.IsLastCheckpoint = true;\r\n\t\t\tLastCheckpoint.IsFinishLine = false;\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tNextCheckpoint = 0;\r\n\t}\r\n\r\n\tpublic void OnCheckpointReached( int index )\r\n\t{\r\n\t\tNextCheckpoint = index + 1;\r\n\t\tOnCheckpointReachedEvent?.Invoke( index );\r\n\t\tLog.Info( \"[CheckpointManager] Checkpoint \" + index + \" reached. Next: \" + NextCheckpoint );\r\n\t}\r\n\r\n\tpublic void OnFinishReached()\r\n\t{\r\n\t\tOnFinishReachedEvent?.Invoke();\r\n\t\tLog.Info( \"[CheckpointManager] Finish reached!\" );\r\n\t}\r\n\r\n\tpublic void ResetAll()\r\n\t{\r\n\t\tNextCheckpoint = 0;\r\n\t\tforeach ( var child in GameObject.Children )\r\n\t\t{\r\n\t\t\tvar cp = child.Components.Get<CheckpointRing>();\r\n\t\t\tcp?.ResetCheckpoint();\r\n\t\t}\r\n\t\tLog.Info( \"[CheckpointManager] Reset all checkpoints\" );\r\n\t}\r\n}\r\n"
}
]
}