{"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( \u0022Checkpoint Placer\u0022 )]\r\n[Icon( \u0022add_location\u0022 )]\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( \u0022[CheckpointPlacer] Active. Next index: \u0022 \u002B _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 == \u0022CheckpointManager\u0022 )\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 = \u0022CheckpointManager\u0022;\r\n\t\t_manager.Components.Create\u003CCheckpointManager\u003E();\r\n\t\tLog.Info( \u0022[CheckpointPlacer] Created CheckpointManager\u0022 );\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\u003CCheckpointRing\u003E();\r\n\t\t\tif ( cp is not null )\r\n\t\t\t\tcount\u002B\u002B;\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( \u0022trigger\u0022 ).Run();\r\n\r\n\t\tif ( !tr.Hit ) return;\r\n\r\n\t\tvar pos = tr.HitPosition \u002B 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( \u0022Left click to place checkpoint \u0022 \u002B _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 = \u0022Checkpoint_\u0022 \u002B _nextIndex;\r\n\r\n\t\tvar col = go.Components.Create\u003CSphereCollider\u003E();\r\n\t\tcol.Radius = 150f;\r\n\t\tcol.IsTrigger = true;\r\n\t\tgo.Tags.Add( \u0022trigger\u0022 );\r\n\r\n\t\tvar cp = go.Components.Create\u003CCheckpointRing\u003E();\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\u003CModelRenderer\u003E();\r\n\t\tmodel.Model = Model.Load( \u0022models/primitives/sphere.vmdl\u0022 );\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\u002B\u002B;\r\n\t\tLog.Info( \u0022[CheckpointPlacer] Placed Checkpoint_\u0022 \u002B (_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( \u0022AddonTitle\u0022, \u0022Checkpoint System\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022AddonIdent\u0022, \u0022checkpointsystem\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022OrgIdent\u0022, \u0022rwtrcsc\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022Ident\u0022, \u0022rwtrcsc.checkpointsystem\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022EngineVersion\u0022, \u002229\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022EngineMinorVersion\u0022, \u00221\u0022 )]\r\n\r\n[assembly: System.Runtime.Versioning.TargetFramework( \u0022.NETCoreApp,Version=v9.0\u0022, FrameworkDisplayName = \u0022.NET 9.0\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022CompileTime\u0022, \u00222026-10-08T19:47:22.9791400Z\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyVersion(\u00220.0.111.0\u0022)]\r\n[assembly: global::System.Reflection.AssemblyFileVersion(\u00220.0.111.0\u0022)]"},{"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\u003Cint\u003E OnCheckpointHit;\r\n\tpublic static Action OnFinishHit;\r\n\r\n\tbool _triggered = false;\r\n\r\n\tbool IsSequential =\u003E 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\u003CCheckpointRing\u003E();\r\n\t\t\tif ( cp is not null \u0026\u0026 !cp.IsFinishLine \u0026\u0026 !cp.IsLastCheckpoint )\r\n\t\t\t\tcount\u002B\u002B;\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 \u003E= 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 =\u003E go.Tags.Has( \u0022player\u0022 ) );\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 \u003E= 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( \u0022[Checkpoint] Finish blocked \uFFFD \u0022 \u002B remaining \u002B \u0022 remaining\u0022 );\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( \u0022[Checkpoint] Finished!\u0022 );\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( \u0022[Checkpoint \u0022 \u002B CheckpointIndex \u002B \u0022] Hit\u0022 );\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\u003Cint\u003E 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 \u002B 1;\r\n\t\tOnCheckpointReachedEvent?.Invoke( index );\r\n\t\tLog.Info( \u0022[CheckpointManager] Checkpoint \u0022 \u002B index \u002B \u0022 reached. Next: \u0022 \u002B NextCheckpoint );\r\n\t}\r\n\r\n\tpublic void OnFinishReached()\r\n\t{\r\n\t\tOnFinishReachedEvent?.Invoke();\r\n\t\tLog.Info( \u0022[CheckpointManager] Finish reached!\u0022 );\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\u003CCheckpointRing\u003E();\r\n\t\t\tcp?.ResetCheckpoint();\r\n\t\t}\r\n\t\tLog.Info( \u0022[CheckpointManager] Reset all checkpoints\u0022 );\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\u003Cint\u003E OnCheckpointHit;\r\n\tpublic static Action OnFinishHit;\r\n\r\n\tbool _triggered = false;\r\n\r\n\tbool IsSequential =\u003E 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\u003CCheckpointRing\u003E();\r\n\t\t\tif ( cp is not null \u0026\u0026 !cp.IsFinishLine \u0026\u0026 !cp.IsLastCheckpoint )\r\n\t\t\t\tcount\u002B\u002B;\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 \u003E= 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 =\u003E go.Tags.Has( \u0022player\u0022 ) );\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 \u003E= 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( \u0022[Checkpoint] Finish blocked \uFFFD \u0022 \u002B remaining \u002B \u0022 remaining\u0022 );\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( \u0022[Checkpoint] Finished!\u0022 );\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( \u0022[Checkpoint \u0022 \u002B CheckpointIndex \u002B \u0022] Hit\u0022 );\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\u003Cint\u003E 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 \u002B 1;\r\n\t\tOnCheckpointReachedEvent?.Invoke( index );\r\n\t\tLog.Info( \u0022[CheckpointManager] Checkpoint \u0022 \u002B index \u002B \u0022 reached. Next: \u0022 \u002B NextCheckpoint );\r\n\t}\r\n\r\n\tpublic void OnFinishReached()\r\n\t{\r\n\t\tOnFinishReachedEvent?.Invoke();\r\n\t\tLog.Info( \u0022[CheckpointManager] Finish reached!\u0022 );\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\u003CCheckpointRing\u003E();\r\n\t\t\tcp?.ResetCheckpoint();\r\n\t\t}\r\n\t\tLog.Info( \u0022[CheckpointManager] Reset all checkpoints\u0022 );\r\n\t}\r\n}\r\n"}]}