{"TotalCount":15,"Files":[{"Ident":"fss.causal","Path":"Assembly.cs","FileName":"Assembly.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"global using Sandbox;\r\nglobal using System.Collections.Generic;\r\n"},{"Ident":"fss.causal","Path":"World/IMovieCondition.cs","FileName":"IMovieCondition.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"namespace Causal;\r\n\r\npublic interface IMovieCondition\r\n{\r\n\tbool HasFailed();\r\n}\r\n"},{"Ident":"fss.causal","Path":"World/Hover.cs","FileName":"Hover.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"using System;\r\n\r\nnamespace Causal;\r\n\r\npublic sealed class Hover : Component, Component.ExecuteInEditor\r\n{\r\n\t[Property] public float HoverHeight { get; set; } = 8f;\r\n\t[Property] public float HoverSpeed { get; set; } = 1.5f;\r\n\t[Property] public float SpinSpeed { get; set; }\r\n\r\n\tprivate bool _hasBase;\r\n\tprivate Vector3 _basePosition;\r\n\tprivate Rotation _baseRotation;\r\n\tprivate Vector3 _lastWrittenPosition;\r\n\tprivate Rotation _lastWrittenRotation;\r\n\tprivate bool _hasLastWritten;\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tfloat offset = MathF.Sin( Time.Now * HoverSpeed ) * HoverHeight;\r\n\r\n\t\tif ( !_hasBase || (_hasLastWritten \u0026\u0026 GameObject.WorldPosition != _lastWrittenPosition) )\r\n\t\t{\r\n\t\t\t_basePosition = GameObject.WorldPosition - Vector3.Up * offset;\r\n\t\t\t_baseRotation = GameObject.WorldRotation;\r\n\t\t\t_hasBase = true;\r\n\t\t}\r\n\t\telse if ( _hasLastWritten \u0026\u0026 GameObject.WorldRotation != _lastWrittenRotation )\r\n\t\t{\r\n\t\t\t_baseRotation = GameObject.WorldRotation * Rotation.FromYaw( -SpinSpeed * Time.Delta );\r\n\t\t}\r\n\r\n\t\t_lastWrittenPosition = _basePosition \u002B Vector3.Up * offset;\r\n\t\tGameObject.WorldPosition = _lastWrittenPosition;\r\n\r\n\t\tif ( SpinSpeed != 0f )\r\n\t\t{\r\n\t\t\tGameObject.WorldRotation *= Rotation.FromYaw( SpinSpeed * Time.Delta );\r\n\t\t}\r\n\r\n\t\t_lastWrittenRotation = GameObject.WorldRotation;\r\n\t\t_hasLastWritten = true;\r\n\t}\r\n\r\n\tprotected override void OnDisabled()\r\n\t{\r\n\t\tRestoreAuthoredTransform();\r\n\t}\r\n\r\n\tprotected override void OnDestroy()\r\n\t{\r\n\t\tRestoreAuthoredTransform();\r\n\t}\r\n\r\n\tprivate void RestoreAuthoredTransform()\r\n\t{\r\n\t\tif ( !_hasBase )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tGameObject.WorldPosition = _basePosition;\r\n\t\tGameObject.WorldRotation = _baseRotation;\r\n\t\t_hasLastWritten = false;\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":"World/ManualMovieCondition.cs","FileName":"ManualMovieCondition.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"namespace Causal;\r\n\r\npublic sealed class ManualMovieCondition : Component, IMovieCondition\r\n{\r\n\t[Property] public bool Failed { get; set; }\r\n\r\n\tpublic bool HasFailed()\r\n\t{\r\n\t\treturn Failed;\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":"Game/TimeShiftManager.cs","FileName":"TimeShiftManager.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"namespace Causal;\r\n\r\ninternal interface ITimeShiftEvent : ISceneEvent\u003CITimeShiftEvent\u003E\r\n{\r\n\tvoid OnTimeShiftRequested() { }\r\n\tvoid OnTimeShifted( bool isCause ) { }\r\n}\r\n\r\npublic sealed class TimeShiftManager : GameObjectSystem\u003CTimeShiftManager\u003E, ITimeShiftEvent, ISceneStartup\r\n{\r\n\tpublic const string CauseTag = \u0022cause\u0022;\r\n\tpublic const string EffectTag = \u0022effect\u0022;\r\n\r\n\t[Property] public float SwitchCooldown { get; set; } = 2f;\r\n\t[Property] public bool StartInCause { get; set; } = true;\r\n\t[Property] public bool StartShiftUnlocked { get; set; } = false;\r\n\r\n\tpublic bool IsCause { get; private set; } = true;\r\n\tpublic bool ShiftUnlocked { get; private set; }\r\n\r\n\tprivate readonly List\u003CGameObject\u003E _causeRoots = new();\r\n\tprivate readonly List\u003CGameObject\u003E _effectRoots = new();\r\n\tprivate TimeSince _timeSinceShift = 99f;\r\n\r\n\tpublic TimeShiftManager( Scene scene ) : base( scene )\r\n\t{\r\n\t}\r\n\r\n\tvoid ISceneStartup.OnHostInitialize()\r\n\t{\r\n\t\tRefreshRoots();\r\n\t\tIsCause = StartInCause;\r\n\t\tShiftUnlocked = StartShiftUnlocked;\r\n\t\t_timeSinceShift = 99f;\r\n\t\tWarmRoots();\r\n\t\tApplyState();\r\n\t}\r\n\r\n\tvoid ITimeShiftEvent.OnTimeShiftRequested()\r\n\t{\r\n\t\tRequestShift();\r\n\t}\r\n\r\n\tpublic void RequestShift()\r\n\t{\r\n\t\tif ( !ShiftUnlocked )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfloat elapsed = _timeSinceShift;\r\n\t\tif ( elapsed \u003E= 0f \u0026\u0026 elapsed \u003C= SwitchCooldown )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_timeSinceShift = 0f;\r\n\t\tIsCause = !IsCause;\r\n\t\tApplyState();\r\n\t\tITimeShiftEvent.Post( x =\u003E x.OnTimeShifted( IsCause ) );\r\n\t}\r\n\r\n\tpublic void UnlockShift()\r\n\t{\r\n\t\tShiftUnlocked = true;\r\n\t}\r\n\r\n\t[ConCmd( \u0022unlock_shift\u0022, Help = \u0022Debug: unlock time shifting before the device pickup exists.\u0022 )]\r\n\tpublic static void UnlockShiftCommand()\r\n\t{\r\n\t\tvar manager = Game.ActiveScene?.GetSystem\u003CTimeShiftManager\u003E();\r\n\t\tif ( manager is null )\r\n\t\t{\r\n\t\t\tLog.Warning( \u0022causal_unlock_shift found no TimeShiftManager.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tmanager.UnlockShift();\r\n\t}\r\n\r\n\tprivate void RefreshRoots()\r\n\t{\r\n\t\t_causeRoots.Clear();\r\n\t\t_effectRoots.Clear();\r\n\r\n\t\tforeach ( var go in Scene.FindAllWithTag( CauseTag ) )\r\n\t\t{\r\n\t\t\tif ( IsTopmostTagged( go, CauseTag ) )\r\n\t\t\t{\r\n\t\t\t\t_causeRoots.Add( go );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tforeach ( var go in Scene.FindAllWithTag( EffectTag ) )\r\n\t\t{\r\n\t\t\tif ( IsTopmostTagged( go, EffectTag ) )\r\n\t\t\t{\r\n\t\t\t\t_effectRoots.Add( go );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static bool IsTopmostTagged( GameObject go, string tag )\r\n\t{\r\n\t\tvar parent = go.Parent;\r\n\t\treturn !parent.IsValid() || !parent.Tags.Has( tag );\r\n\t}\r\n\r\n\tprivate void WarmRoots()\r\n\t{\r\n\t\tforeach ( var go in _causeRoots )\r\n\t\t{\r\n\t\t\tif ( go.IsValid() )\r\n\t\t\t{\r\n\t\t\t\tgo.Enabled = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tforeach ( var go in _effectRoots )\r\n\t\t{\r\n\t\t\tif ( go.IsValid() )\r\n\t\t\t{\r\n\t\t\t\tgo.Enabled = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void ApplyState()\r\n\t{\r\n\t\tif ( _causeRoots.Count == 0 || _effectRoots.Count == 0 )\r\n\t\t{\r\n\t\t\tRefreshRoots();\r\n\t\t}\r\n\r\n\t\tforeach ( var go in _causeRoots )\r\n\t\t{\r\n\t\t\tif ( go.IsValid() )\r\n\t\t\t{\r\n\t\t\t\tgo.Enabled = IsCause;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tforeach ( var go in _effectRoots )\r\n\t\t{\r\n\t\t\tif ( go.IsValid() )\r\n\t\t\t{\r\n\t\t\t\tgo.Enabled = !IsCause;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":"World/BlastDoor.cs","FileName":"BlastDoor.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"using System;\r\nusing Sandbox.MovieMaker;\r\n\r\nnamespace Causal;\r\n\r\npublic sealed class BlastDoor : Component\r\n{\r\n\t[Property] public MovieResource OpenMovie { get; set; }\r\n\t[Property] public MovieResource CloseMovie { get; set; }\r\n\t[Property] public float ActionCooldown { get; set; } = 2f;\r\n\t[Property] public GameObject VfxObject { get; set; }\r\n\t[Property] public float VfxSeconds { get; set; } = 2f;\r\n\t[Property] public bool StartOpen { get; set; }\r\n\t[Property] public bool AllowInterrupt { get; set; } = false;\r\n\t[Property] public bool AdvanceWhileHidden { get; set; } = true;\r\n\r\n\tpublic bool IsOpen { get; private set; }\r\n\r\n\tpublic bool IsAnimating =\u003E _player.IsValid() \u0026\u0026 _player.IsPlaying;\r\n\r\n\tpublic bool CanClose =\u003E CloseMovie is not null \u0026\u0026 CloseMovie.IsValid();\r\n\r\n\tprivate MoviePlayer _player;\r\n\tprivate GameObject _vfx;\r\n\tprivate TimeSince _timeSinceAction = 99f;\r\n\tprivate TimeSince _timeSinceVfx = 99f;\r\n\tprivate bool _vfxShowing;\r\n\tprivate float _storedPosition;\r\n\tprivate bool _wasPlaying;\r\n\tprivate MovieResource _savedMovie;\r\n\tprivate float _savedPosition;\r\n\tprivate float _savedTimeScale = 1f;\r\n\tprivate bool _savedWasPlaying;\r\n\tprivate bool _hasSaved;\r\n\tprivate TimeSince _timeSinceHidden;\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\t_player = GetComponent\u003CMoviePlayer\u003E();\r\n\r\n\t\tif ( !_player.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022BlastDoor on \u0027{GameObject.Name}\u0027 needs a MoviePlayer on the same GameObject.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_player.CreateTargets = false;\r\n\t\tIsOpen = StartOpen;\r\n\t\t_timeSinceAction = 99f;\r\n\t\tResolveVfx();\r\n\t}\r\n\r\n\tpublic void Open()\r\n\t{\r\n\t\tPlay( OpenMovie, true );\r\n\t}\r\n\r\n\tpublic void Close()\r\n\t{\r\n\t\tPlay( CloseMovie, false );\r\n\t}\r\n\r\n\tpublic void Toggle()\r\n\t{\r\n\t\tif ( IsOpen )\r\n\t\t{\r\n\t\t\tClose();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tOpen();\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void OnDisabled()\r\n\t{\r\n\t\tif ( !_player.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_savedMovie = _player.Resource as MovieResource;\r\n\t\tif ( !_savedMovie.IsValid() )\r\n\t\t{\r\n\t\t\t_savedMovie = IsOpen ? OpenMovie : CloseMovie;\r\n\t\t}\r\n\r\n\t\t_savedPosition = _player.PositionSeconds;\r\n\t\t_savedTimeScale = _player.TimeScale;\r\n\t\t_savedWasPlaying = _player.IsPlaying || _storedPosition \u003E 0.05f;\r\n\t\t_timeSinceHidden = 0f;\r\n\t\t_hasSaved = true;\r\n\t}\r\n\r\n\tprotected override void OnEnabled()\r\n\t{\r\n\t\tif ( !_hasSaved )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_hasSaved = false;\r\n\r\n\t\tif ( !_savedWasPlaying || !_savedMovie.IsValid() || !_player.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfloat end = MovieGate.MovieDurationSeconds( _savedMovie );\r\n\t\tfloat target = AdvanceWhileHidden ? _savedPosition \u002B (float)_timeSinceHidden * _savedTimeScale : _savedPosition;\r\n\t\ttarget = end \u003E 0f ? Math.Clamp( target, 0f, Math.Max( 0f, end - 0.05f ) ) : 0f;\r\n\t\t_player.Play( _savedMovie );\r\n\t\t_player.TimeScale = _savedTimeScale;\r\n\t\t_player.PositionSeconds = target;\r\n\t\t_player.IsPlaying = true;\r\n\t\t_storedPosition = target;\r\n\t\t_wasPlaying = true;\r\n\t}\r\n\r\n\tprivate void Play( MovieResource movie, bool targetState )\r\n\t{\r\n\t\tif ( !GameObject.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !_player.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022BlastDoor on \u0027{GameObject.Name}\u0027 has no MoviePlayer.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( movie is null || !movie.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022BlastDoor on \u0027{GameObject.Name}\u0027 is missing its {(targetState ? \u0022OpenMovie\u0022 : \u0022CloseMovie\u0022)}.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( IsOpen == targetState )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( _timeSinceAction \u003C ActionCooldown )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !AllowInterrupt \u0026\u0026 _player.IsPlaying )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_player.Play( movie );\r\n\t\t_timeSinceAction = 0f;\r\n\t\t_storedPosition = 0f;\r\n\t\tIsOpen = targetState;\r\n\t\tif ( targetState )\r\n\t\t{\r\n\t\t\tShowVfx();\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tTickVfx();\r\n\r\n\t\tif ( !_player.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( _player.IsPlaying )\r\n\t\t{\r\n\t\t\t_storedPosition = _player.PositionSeconds;\r\n\t\t\t_wasPlaying = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !_wasPlaying )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_wasPlaying = false;\r\n\t\tfloat pos = _player.PositionSeconds;\r\n\t\tfloat end = ClipEndSeconds();\r\n\t\tbool finished = end \u003E 0f ? pos \u003E= end - 0.05f : pos \u003E= _storedPosition - 0.05f;\r\n\t\tif ( _storedPosition \u003E 0.05f \u0026\u0026 !finished )\r\n\t\t{\r\n\t\t\t_player.PositionSeconds = _storedPosition;\r\n\t\t\t_player.IsPlaying = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t_storedPosition = 0f;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate float ClipEndSeconds()\r\n\t{\r\n\t\tvar clip = _player.Clip;\r\n\t\tif ( clip is null )\r\n\t\t{\r\n\t\t\treturn 0f;\r\n\t\t}\r\n\r\n\t\treturn (float)clip.Duration.TotalSeconds;\r\n\t}\r\n\r\n\tprivate void ResolveVfx()\r\n\t{\r\n\t\t_vfx = VfxObject;\r\n\r\n\t\tif ( !_vfx.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022BlastDoor on \u0027{GameObject.Name}\u0027 has no VfxObject assigned.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_vfx.Enabled = false;\r\n\t}\r\n\r\n\tprivate void ShowVfx()\r\n\t{\r\n\t\tif ( !_vfx.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_vfx.Enabled = true;\r\n\t\t_timeSinceVfx = 0f;\r\n\t\t_vfxShowing = true;\r\n\t}\r\n\r\n\tprivate void TickVfx()\r\n\t{\r\n\t\tif ( !_vfxShowing )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !_vfx.IsValid() )\r\n\t\t{\r\n\t\t\t_vfxShowing = false;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( _timeSinceVfx \u003E= VfxSeconds )\r\n\t\t{\r\n\t\t\t_vfx.Enabled = false;\r\n\t\t\t_vfxShowing = false;\r\n\t\t}\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":"Player/FirstPersonCosmetics.cs","FileName":"FirstPersonCosmetics.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"using System;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Causal;\r\n\r\npublic sealed class FirstPersonCosmetics : Component\r\n{\r\n\t[Property] public SkinnedModelRenderer ArmsRenderer { get; set; }\r\n\t[Property] public SkinnedModelRenderer ClothingRenderer { get; set; }\r\n\t[Property] public ulong ClothingBodyGroups { get; set; } = 1088;\r\n\t[Property] public List\u003Cstring\u003E ExcludedCategories { get; set; } = new() { \u0022Gloves\u0022 };\r\n\t[Property] public List\u003Cstring\u003E RemovedClothingNames { get; set; } = new() { \u0022y_front_pants\u0022 };\r\n\t[Property] public float CosmeticSettleTimeout { get; set; } = 30f;\r\n\r\n\tpublic static bool IsLoadingClothing { get; private set; }\r\n\r\n\tprivate const ulong BareBodyGroups = 21;\r\n\tprivate const ulong ClothedBodyGroups = 20;\r\n\tprivate int _generation;\r\n\tprivate CancellationTokenSource _cts;\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tif ( !ArmsRenderer.IsValid() || !ClothingRenderer.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( \u0022FirstPersonCosmetics has no valid arms/clothing renderer, cosmetics disabled.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_cts = new CancellationTokenSource();\r\n\t\tint generation = \u002B\u002B_generation;\r\n\t\t_ = ApplyCosmeticsAsync( generation, _cts.Token );\r\n\t}\r\n\r\n\tprotected override void OnDestroy()\r\n\t{\r\n\t\t_generation\u002B\u002B;\r\n\t\tif ( _cts is not null )\r\n\t\t{\r\n\t\t\t_cts.Cancel();\r\n\t\t\t_cts.Dispose();\r\n\t\t\t_cts = null;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate async Task ApplyCosmeticsAsync( int generation, CancellationToken token )\r\n\t{\r\n\t\ttry\r\n\t\t{\r\n\t\t\tvar container = ClothingContainer.CreateFromLocalUser();\r\n\t\t\tif ( !IsCurrent( generation, token ) )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tStripExcludedCategories( container );\r\n\r\n\t\t\tIsLoadingClothing = true;\r\n\r\n\t\t\tawait container.ApplyAsync( ClothingRenderer, token );\r\n\t\t\tif ( !IsCurrent( generation, token ) )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tawait WaitForSettled( container, generation, token );\r\n\t\t\tif ( !IsCurrent( generation, token ) )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tSetLoadingForGeneration( generation, false );\r\n\r\n\t\t\tif ( StripExcludedCategories( container ) \u003E 0 )\r\n\t\t\t{\r\n\t\t\t\tcontainer.Apply( ClothingRenderer );\r\n\t\t\t}\r\n\r\n\t\t\tRemoveNamedClothingObjects();\r\n\t\t\tApplyClothingRenderOptions();\r\n\t\t\tApplyClothingBodyGroups();\r\n\t\t\tSetArmsBodyGroups( CountEntries( container ) \u003E 0 ? ClothedBodyGroups : BareBodyGroups );\r\n\t\t}\r\n\t\tcatch ( OperationCanceledException )\r\n\t\t{\r\n\t\t\tSetLoadingForGeneration( generation, false );\r\n\t\t\tSetArmsBodyGroupsForGeneration( generation, BareBodyGroups );\r\n\t\t}\r\n\t\tcatch ( Exception exception )\r\n\t\t{\r\n\t\t\tSetLoadingForGeneration( generation, false );\r\n\t\t\tSetArmsBodyGroupsForGeneration( generation, BareBodyGroups );\r\n\t\t\tLog.Warning( $\u0022FirstPersonCosmetics failed: {exception.Message}\u0022 );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate bool IsCurrent( int generation, CancellationToken token )\r\n\t{\r\n\t\treturn generation == _generation \u0026\u0026 !token.IsCancellationRequested;\r\n\t}\r\n\r\n\tprivate void SetArmsBodyGroupsForGeneration( int generation, ulong groups )\r\n\t{\r\n\t\tif ( generation == _generation )\r\n\t\t{\r\n\t\t\tSetArmsBodyGroups( groups );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void SetArmsBodyGroups( ulong groups )\r\n\t{\r\n\t\tif ( ArmsRenderer.IsValid() )\r\n\t\t{\r\n\t\t\tArmsRenderer.BodyGroups = groups;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void ApplyClothingBodyGroups()\r\n\t{\r\n\t\tif ( ClothingRenderer.IsValid() )\r\n\t\t{\r\n\t\t\tClothingRenderer.BodyGroups = ClothingBodyGroups;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void SetLoadingForGeneration( int generation, bool loading )\r\n\t{\r\n\t\tif ( generation == _generation )\r\n\t\t{\r\n\t\t\tIsLoadingClothing = loading;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void ApplyClothingRenderOptions()\r\n\t{\r\n\t\tif ( !ClothingRenderer.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tApplyClothingRenderOptions( ClothingRenderer.GameObject );\r\n\t}\r\n\r\n\tprivate static void ApplyClothingRenderOptions( GameObject root )\r\n\t{\r\n\t\tif ( !root.IsValid() || root.IsDestroyed )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar renderer = root.GetComponent\u003CSkinnedModelRenderer\u003E();\r\n\t\tif ( renderer.IsValid() )\r\n\t\t{\r\n\t\t\trenderer.RenderType = ModelRenderer.ShadowRenderType.Off;\r\n\t\t\tvar options = renderer.RenderOptions;\r\n\t\t\toptions.Game = false;\r\n\t\t\toptions.Overlay = true;\r\n\t\t\toptions.Bloom = false;\r\n\t\t\toptions.AfterUI = false;\r\n\t\t}\r\n\r\n\t\tforeach ( GameObject child in root.Children )\r\n\t\t{\r\n\t\t\tApplyClothingRenderOptions( child );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void RemoveNamedClothingObjects()\r\n\t{\r\n\t\tif ( RemovedClothingNames is null || RemovedClothingNames.Count == 0 )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !ClothingRenderer.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tint removed = 0;\r\n\t\tRemoveNamedClothingObjects( ClothingRenderer.GameObject, ref removed );\r\n\t\tif ( removed \u003E 0 )\r\n\t\t{\r\n\t\t\tLog.Info( $\u0022FirstPersonCosmetics removed {removed} unwanted clothing objects.\u0022 );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void RemoveNamedClothingObjects( GameObject root, ref int removed )\r\n\t{\r\n\t\tif ( !root.IsValid() || root.IsDestroyed )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tforeach ( GameObject child in root.Children )\r\n\t\t{\r\n\t\t\tif ( !child.IsValid() || child.IsDestroyed )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif ( IsRemovedClothingName( child.Name ) )\r\n\t\t\t{\r\n\t\t\t\tchild.Destroy();\r\n\t\t\t\tremoved\u002B\u002B;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tRemoveNamedClothingObjects( child, ref removed );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate bool IsRemovedClothingName( string name )\r\n\t{\r\n\t\tif ( string.IsNullOrEmpty( name ) || RemovedClothingNames is null )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tforeach ( string removed in RemovedClothingNames )\r\n\t\t{\r\n\t\t\tif ( !string.IsNullOrEmpty( removed ) \u0026\u0026 name.IndexOf( removed, StringComparison.OrdinalIgnoreCase ) \u003E= 0 )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tprivate static int CountEntries( ClothingContainer container )\r\n\t{\r\n\t\tif ( container?.Clothing is null )\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t\tint count = 0;\r\n\t\tforeach ( var entry in container.Clothing )\r\n\t\t{\r\n\t\t\tif ( entry is not null )\r\n\t\t\t{\r\n\t\t\t\tcount\u002B\u002B;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn count;\r\n\t}\r\n\r\n\tprivate int StripExcludedCategories( ClothingContainer container )\r\n\t{\r\n\t\tif ( container?.Clothing is null || ExcludedCategories is null || ExcludedCategories.Count == 0 )\r\n\t\t{\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t\tint stripped = 0;\r\n\t\tvar seen = new List\u003Cstring\u003E();\r\n\t\tvar entries = new List\u003CClothingContainer.ClothingEntry\u003E( container.Clothing );\r\n\t\tforeach ( var entry in entries )\r\n\t\t{\r\n\t\t\tstring category = entry?.Clothing?.Category.ToString();\r\n\t\t\tif ( string.IsNullOrEmpty( category ) )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif ( !seen.Contains( category ) )\r\n\t\t\t{\r\n\t\t\t\tseen.Add( category );\r\n\t\t\t}\r\n\r\n\t\t\tforeach ( string excluded in ExcludedCategories )\r\n\t\t\t{\r\n\t\t\t\tif ( string.Equals( category, excluded, StringComparison.OrdinalIgnoreCase ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontainer.Clothing.Remove( entry );\r\n\t\t\t\t\tstripped\u002B\u002B;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( stripped \u003E 0 )\r\n\t\t{\r\n\t\t\tLog.Info( $\u0022FirstPersonCosmetics excluded {stripped} clothing entries.\u0022 );\r\n\t\t}\r\n\t\telse if ( entries.Count \u003E 0 )\r\n\t\t{\r\n\t\t\tLog.Info( $\u0022FirstPersonCosmetics excluded nothing, categories present: {string.Join( \u0022, \u0022, seen )}\u0022 );\r\n\t\t}\r\n\r\n\t\treturn stripped;\r\n\t}\r\n\r\n\tprivate async Task WaitForSettled( ClothingContainer container, int generation, CancellationToken token )\r\n\t{\r\n\t\tTimeSince elapsed = 0;\r\n\t\twhile ( HasPendingEntries( container ) )\r\n\t\t{\r\n\t\t\tif ( elapsed \u003E CosmeticSettleTimeout )\r\n\t\t\t{\r\n\t\t\t\tLog.Warning( $\u0022FirstPersonCosmetics timed out after {CosmeticSettleTimeout:0}s waiting for downloads, applying what is loaded.\u0022 );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tawait GameTask.DelaySeconds( 0.5f );\r\n\t\t\tif ( !IsCurrent( generation, token ) )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static bool HasPendingEntries( ClothingContainer container )\r\n\t{\r\n\t\tif ( container?.Clothing is null )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tforeach ( var entry in container.Clothing )\r\n\t\t{\r\n\t\t\tif ( entry is not null \u0026\u0026 entry.Clothing is null \u0026\u0026 entry.ItemDefinitionId != 0 )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":"ui/causalmenu.razor.scss","FileName":"causalmenu.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"CausalMenu {\n\tposition: relative;\n\twidth: 100%;\n\theight: 100%;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tjustify-content: center;\n\tpointer-events: all;\n\tbackground-color: rgba(0, 0, 0, 0.55);\n\tbackdrop-filter: blur(8px);\n\tz-index: 1;\n\t// Keep in sync with CausalGameManager.MenuFadeSeconds.\n\ttransition: opacity 0.6s ease;\n\n\t\u0026.fading {\n\t\topacity: 0;\n\t\tpointer-events: none;\n\t}\n\n\t\u0026.hidden {\n\t\tdisplay: none;\n\t\topacity: 0;\n\t\tpointer-events: none;\n\t}\n}\n\n.menu-container {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 64px;\n}\n\n.logo-section {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tanimation: menu-enter 0.7s ease both;\n}\n\n.logo-image {\n\twidth: 520px;\n\tflex-shrink: 0;\n\tfilter: drop-shadow(0 4px 24px rgba(255, 180, 80, 0.2));\n}\n\n.buttons-section {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 24px;\n\tanimation: menu-enter 0.7s ease 0.15s both;\n}\n\n.menu-item {\n\tcolor: rgba(255, 255, 255, 0.75);\n\tfont-size: 34px;\n\tfont-weight: 500;\n\tletter-spacing: 6px;\n\ttext-transform: uppercase;\n\ttext-align: center;\n\tcursor: pointer;\n\ttext-shadow: 0 0 8px rgba(120, 200, 255, 0.35);\n\ttransition: color 0.2s ease, transform 0.18s ease;\n\n\t\u0026:hover {\n\t\tcolor: #fff;\n\t\ttext-shadow: 0 0 18px rgba(170, 220, 255, 0.95);\n\t\ttransform: scale(1.06);\n\t}\n\n\t\u0026:active {\n\t\ttransform: scale(0.98);\n\t}\n}\n\n.menu-item.primary {\n\tanimation-name: menu-pulse;\n\tanimation-duration: 2s;\n\tanimation-timing-function: ease-in-out;\n\tanimation-iteration-count: infinite;\n}\n\n.newgame-row {\n\tposition: relative;\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n}\n\n.menu-item.disabled {\n\tcolor: rgba(255, 255, 255, 0.25);\n\ttext-shadow: none;\n\tcursor: default;\n\tanimation: none;\n\n\t\u0026:hover {\n\t\tcolor: rgba(255, 255, 255, 0.25);\n\t\ttext-shadow: none;\n\t\ttransform: none;\n\t}\n\n\t\u0026:active {\n\t\ttransform: none;\n\t}\n}\n\n.avatar-status {\n\tposition: absolute;\n\tleft: 100%;\n\ttop: 0;\n\tbottom: 0;\n\tmargin-left: 24px;\n\tdisplay: flex;\n\talign-items: center;\n\tfont-size: 20px;\n\tletter-spacing: 2px;\n\tcolor: rgba(180, 230, 255, 0.8);\n\ttext-shadow: 0 0 8px rgba(120, 200, 255, 0.35);\n\twhite-space: nowrap;\n}\n\n@keyframes menu-enter {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: translateY(14px);\n\t}\n\t100% {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n@keyframes menu-pulse {\n\t0% {\n\t\tcolor: rgba(255, 255, 255, 0.75);\n\t\ttext-shadow: 0 0 8px rgba(120, 200, 255, 0.4);\n\t}\n\t50% {\n\t\tcolor: #fff;\n\t\ttext-shadow: 0 0 20px rgba(170, 220, 255, 0.95);\n\t}\n\t100% {\n\t\tcolor: rgba(255, 255, 255, 0.75);\n\t\ttext-shadow: 0 0 8px rgba(120, 200, 255, 0.4);\n\t}\n}\n\n.about-link {\n\tposition: absolute;\n\ttop: 32px;\n\tright: 40px;\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\theight: 48px;\n\tpadding-left: 0;\n\tpadding-right: 0;\n\tbackground-color: rgba(8, 18, 26, 0.55);\n\tbackdrop-filter: blur(4px);\n\tborder: 1px solid rgba(140, 210, 255, 0.35);\n\tborder-radius: 24px;\n\tbox-shadow: 0 0 16px rgba(120, 200, 255, 0.08);\n\tcolor: rgba(190, 225, 255, 0.8);\n\tcursor: pointer;\n\toverflow: hidden;\n\ttransition: border-color 0.2s ease, box-shadow 0.2s ease, padding-left 0.25s ease, padding-right 0.25s ease;\n\tz-index: 150;\n\tpointer-events: all;\n\n\t\u0026:hover {\n\t\tborder-color: rgba(170, 220, 255, 0.9);\n\t\tbox-shadow: 0 0 24px rgba(140, 210, 255, 0.3);\n\t\tpadding-left: 4px;\n\t\tpadding-right: 20px;\n\t}\n\n\t\u0026:active {\n\t\ttransform: scale(0.97);\n\t}\n}\n\n.about-glyph {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex-shrink: 0;\n\twidth: 46px;\n\theight: 46px;\n\tfont-size: 22px;\n\tfont-weight: 600;\n\ttext-shadow: 0 0 8px rgba(120, 200, 255, 0.35);\n}\n\n.about-expand {\n\tmax-width: 0;\n\topacity: 0;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\tcolor: #fff;\n\tfont-size: 17px;\n\tfont-weight: 500;\n\tletter-spacing: 3px;\n\ttext-transform: uppercase;\n\ttext-shadow: 0 0 14px rgba(170, 220, 255, 0.95);\n\ttransition: max-width 0.25s ease, opacity 0.2s ease;\n}\n\n.about-link:hover .about-expand {\n\tmax-width: 240px;\n\topacity: 1;\n}\n\n.about-backdrop {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbackground-color: rgba(0, 0, 0, 1);\n\topacity: 0;\n\tpointer-events: none;\n\tz-index: 200;\n\n\t\u0026.open {\n\t\tpointer-events: all;\n\t}\n}\n\n.about-panel {\n\tposition: absolute;\n\ttop: 0;\n\tright: 0;\n\twidth: min(520px, 92vw);\n\theight: 100%;\n\tdisplay: flex;\n\tflex-direction: column;\n\tbackground: linear-gradient(270deg, rgba(8, 18, 26, 0.97) 0%, rgba(8, 16, 24, 0.92) 100%);\n\tborder-left: 1px solid rgba(140, 210, 255, 0.5);\n\tbox-shadow: -8px 0 48px rgba(120, 200, 255, 0.12);\n\tpadding: 48px 40px 32px;\n\tz-index: 201;\n\tpointer-events: all;\n}\n\n.about-header {\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tjustify-content: flex-end;\n\tmargin-bottom: 0;\n}\n\n.about-title {\n\tcolor: rgba(190, 225, 255, 0.95);\n\tfont-size: 28px;\n\tfont-weight: 600;\n\tletter-spacing: 4px;\n\ttext-transform: uppercase;\n\ttext-shadow: 0 0 14px rgba(140, 210, 255, 0.6);\n}\n\n.about-close {\n\tcolor: rgba(190, 225, 255, 0.6);\n\tfont-size: 24px;\n\tcursor: pointer;\n\tpadding: 8px;\n\ttransition: color 0.2s ease, transform 0.18s ease;\n\n\t\u0026:hover {\n\t\tcolor: #fff;\n\t\ttext-shadow: 0 0 14px rgba(170, 220, 255, 0.95);\n\t\ttransform: scale(1.1);\n\t}\n}\n\n.about-body {\n\tflex-shrink: 1;\n\tflex-grow: 1;\n\toverflow-y: auto;\n\tdisplay: flex;\n\tflex-direction: column;\n\tjustify-content: flex-start;\n\tgap: 26px;\n\tpadding-top: 8px;\n\tpadding-right: 12px;\n\n\tlabel {\n\t\tmargin: 0;\n\t}\n\n\t.about-para {\n\t\tcolor: rgba(220, 235, 245, 0.88);\n\t\tfont-size: 23px;\n\t\tline-height: 1.75;\n\t}\n\n\t.about-quote {\n\t\tcolor: rgba(190, 225, 255, 0.95);\n\t\tfont-style: italic;\n\t\tfont-size: 23px;\n\t\tborder-left: 2px solid rgba(140, 210, 255, 0.5);\n\t\tpadding-left: 16px;\n\t\ttext-shadow: 0 0 10px rgba(140, 210, 255, 0.4);\n\t}\n}\n\n.about-footer {\n\tmargin-top: 24px;\n\tpadding-top: 20px;\n\tborder-top: 1px solid rgba(140, 210, 255, 0.2);\n\tcolor: rgba(170, 210, 240, 0.5);\n\tfont-size: 15px;\n\tletter-spacing: 2px;\n\ttext-transform: uppercase;\n}\n"},{"Ident":"fss.causal","Path":"UI/CausalMenu.razor","FileName":"CausalMenu.razor","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"@using Sandbox;\r\n@using Sandbox.UI;\r\n@using System;\r\n@inherits PanelComponent\r\n@namespace Causal\r\n\r\n\u003Croot class=\u0022@MenuClass\u0022\u003E\r\n\t\u003Cdiv class=\u0022menu-container\u0022\u003E\r\n\t\t\u003Cdiv class=\u0022logo-section\u0022\u003E\r\n\t\t\t\u003Cimg class=\u0022logo-image\u0022 src=\u0022textures/causal-logo.png\u0022 alt=\u0022CAUSAL\u0022 /\u003E\r\n\t\t\u003C/div\u003E\r\n\t\t\u003Cdiv class=\u0022buttons-section\u0022\u003E\r\n\t\t\t\u003Cdiv class=\u0022newgame-row\u0022\u003E\r\n\t\t\t\t\u003Cdiv class=\u0022menu-item primary @NewGameClass\u0022 @onclick=@EnterGame onmouseover=@PlayHoverSound\u003E\r\n\t\t\t\t\t\u003Cspan\u003ENew Game\u003C/span\u003E\r\n\t\t\t\t\u003C/div\u003E\r\n\t\t\t\t@if ( IsApplyingClothing )\r\n\t\t\t\t{\r\n\t\t\t\t\t\u003Clabel class=\u0022avatar-status\u0022\u003EApplying avatar clothing...\u003C/label\u003E\r\n\t\t\t\t}\r\n\t\t\t\u003C/div\u003E\r\n\t\t\t\u003Cdiv class=\u0022menu-item\u0022 @onclick=@QuitGame onmouseover=@PlayHoverSound\u003E\r\n\t\t\t\t\u003Cspan\u003EQuit\u003C/span\u003E\r\n\t\t\t\u003C/div\u003E\r\n\t\t\u003C/div\u003E\r\n\t\u003C/div\u003E\r\n\t\u003Cdiv class=\u0022about-link\u0022 @onclick=@ShowAbout onmouseover=@PlayHoverSound\u003E\r\n\t\t\u003Cspan class=\u0022about-glyph\u0022\u003E?\u003C/span\u003E\r\n\t\t\u003Cspan class=\u0022about-expand\u0022\u003EAbout Causal\u003C/span\u003E\r\n\t\u003C/div\u003E\r\n\t\u003Cdiv class=\u0022about-backdrop\u0022 @ref=\u0022_aboutBackdrop\u0022 @onclick=@HideAbout\u003E\u003C/div\u003E\r\n\t\u003Caside class=\u0022about-panel\u0022 @ref=\u0022_aboutPanel\u0022\u003E\r\n\t\t\u003Cdiv class=\u0022about-header\u0022\u003E\r\n\t\t\t\u003Cdiv class=\u0022about-close\u0022 @onclick=@HideAbout onmouseover=@PlayHoverSound\u003E\r\n\t\t\t\t\u003Cspan\u003E\u0026#10005;\u003C/span\u003E\r\n\t\t\t\u003C/div\u003E\r\n\t\t\u003C/div\u003E\r\n\t\t\u003Cdiv class=\u0022about-body\u0022\u003E\r\n\t\t\t\u003Clabel class=\u0022about-para\u0022\u003EYou have been chosen to be a Causal Agent.\u003C/label\u003E\r\n\t\t\t\u003Clabel class=\u0022about-para\u0022\u003EThe Paralix Research Facility, a remote research station, has sent you there.\u003C/label\u003E\r\n\t\t\t\u003Clabel class=\u0022about-para\u0022\u003EThe facility has been left abandoned with its systems becoming unstable since something went wrong, but the deeper you investigate the more you come to realize that the facility exists in more than one state.\u003C/label\u003E\r\n\t\t\t\u003Clabel class=\u0022about-para\u0022\u003EA construct located here is capable of slipgating time. In order to get to it, you will have to explore the facility, discover histories, and with some hope; to stop it from operating.\u003C/label\u003E\r\n\t\t\t\u003Clabel class=\u0022about-quote\u0022\u003E\u0022Playing with causality comes at a price...\u0022\u003C/label\u003E\r\n\t\t\u003C/div\u003E\r\n\t\t\u003Cdiv class=\u0022about-footer\u0022\u003E\r\n\t\t\t\u003Cspan\u003EGood luck!\u003C/span\u003E\r\n\t\t\u003C/div\u003E\r\n\t\u003C/aside\u003E\r\n\u003C/root\u003E\r\n\r\n@code\r\n{\r\n\t[Property] public float AboutSlideSeconds { get; set; } = 0.25f;\r\n\r\n\tprivate bool _showAbout;\r\n\tprivate bool _aboutClassesOpen;\r\n\tprivate float _slideT;\r\n\tprivate float _lastAppliedRight = float.MaxValue;\r\n\tprivate float _lastAppliedOpacity = -1f;\r\n\r\n\tprivate Panel _aboutBackdrop;\r\n\tprivate Panel _aboutPanel;\r\n\r\n\tprivate TimeSince _timeSinceHover = 10f;\r\n\r\n\tprivate bool IsMenuVisible =\u003E !CausalGameManager.Instance.IsValid() || !CausalGameManager.Instance.IsActive;\r\n\r\n\tprivate bool IsApplyingClothing =\u003E FirstPersonCosmetics.IsLoadingClothing;\r\n\r\n\tprivate string NewGameClass =\u003E IsApplyingClothing ? \u0022disabled\u0022 : \u0022\u0022;\r\n\r\n\tprivate bool IsFading =\u003E CausalGameManager.Instance.IsValid() \u0026\u0026 CausalGameManager.Instance.IsInIntro;\r\n\r\n\tprivate string MenuClass =\u003E !IsMenuVisible ? \u0022hidden\u0022 : (IsFading ? \u0022fading\u0022 : \u0022\u0022);\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tTickAboutSlide();\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tTickAboutSlide();\r\n\r\n\t\tif ( _showAbout \u0026\u0026 Input.EscapePressed )\r\n\t\t{\r\n\t\t\tHideAbout();\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void TickAboutSlide()\r\n\t{\r\n\t\tfloat duration = AboutSlideSeconds \u003C= 0.01f ? 0.01f : AboutSlideSeconds;\r\n\t\t_slideT = MathX.Clamp( _slideT \u002B ( _showAbout ? Time.Delta : -Time.Delta ) / duration, 0f, 1f );\r\n\t\tfloat eased = _slideT * _slideT * ( 3f - 2f * _slideT );\r\n\r\n\t\tif ( _aboutPanel.IsValid() )\r\n\t\t{\r\n\t\t\t// Percent of screen width: the panel can never exceed 92vw, so\r\n\t\t\t// -120% is always fully off-screen with room for the border and\r\n\t\t\t// shadow tail. No measurement, nothing to go stale on resize.\r\n\t\t\tfloat offset = -120f * ( 1f - eased );\r\n\t\t\tif ( MathF.Abs( offset - _lastAppliedRight ) \u003E 0.1f )\r\n\t\t\t{\r\n\t\t\t\t_aboutPanel.Style.Right = Length.Percent( offset );\r\n\t\t\t\t_lastAppliedRight = offset;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( _aboutBackdrop.IsValid() )\r\n\t\t{\r\n\t\t\tfloat opacity = 0.45f * eased;\r\n\t\t\tif ( MathF.Abs( opacity - _lastAppliedOpacity ) \u003E 0.005f )\r\n\t\t\t{\r\n\t\t\t\t_aboutBackdrop.Style.Opacity = opacity;\r\n\t\t\t\t_lastAppliedOpacity = opacity;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( _aboutClassesOpen != _showAbout )\r\n\t\t{\r\n\t\t\tApplyAboutClasses();\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void EnterGame()\r\n\t{\r\n\t\tif ( IsApplyingClothing )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar manager = CausalGameManager.Instance;\r\n\t\tif ( !manager.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( \u0022CausalMenu found no CausalGameManager.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_showAbout = false;\r\n\t\tApplyAboutClasses();\r\n\t\tmanager.BeginIntro();\r\n\t\tStateHasChanged();\r\n\t}\r\n\r\n\tprivate void ShowAbout()\r\n\t{\r\n\t\t_showAbout = true;\r\n\t\tApplyAboutClasses();\r\n\t}\r\n\r\n\tprivate void HideAbout()\r\n\t{\r\n\t\tif ( !_showAbout )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_showAbout = false;\r\n\t\tApplyAboutClasses();\r\n\t}\r\n\r\n\tprivate void ApplyAboutClasses()\r\n\t{\r\n\t\t_aboutBackdrop?.SetClass( \u0022open\u0022, _showAbout );\r\n\t\t_aboutClassesOpen = _showAbout;\r\n\t}\r\n\r\n\tprivate void QuitGame()\r\n\t{\r\n\t\tGame.Close();\r\n\t}\r\n\r\n\tprivate void PlayHoverSound()\r\n\t{\r\n\t\t// onmouseover refires as the cursor crosses child elements and panel\r\n\t\t// rebuilds, so debounce to a single tick per hover.\r\n\t\tif ( _timeSinceHover \u003C 0.15f )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_timeSinceHover = 0f;\r\n\t\tSound.Play( \u0022audio/ui/menuhover.sound\u0022 );\r\n\t}\r\n\r\n\tprotected override int BuildHash() =\u003E HashCode.Combine( IsMenuVisible, IsFading, IsApplyingClothing );\r\n}\r\n"},{"Ident":"fss.causal","Path":"Player/ShiftController.cs","FileName":"ShiftController.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"using Sandbox.MovieMaker;\r\n\r\nnamespace Causal;\r\n\r\npublic sealed class ShiftController : Component\r\n{\r\n\t[Property] public MoviePlayer ShiftPlayer { get; set; }\r\n\t[Property] public float ShiftAtSeconds { get; set; } = 0.5f;\r\n\r\n\tprivate MoviePlayer _shiftPlayer;\r\n\tprivate TimeShiftManager _manager;\r\n\tprivate TimeSince _timeSinceShiftStart;\r\n\tprivate bool _shiftPending;\r\n\tprivate bool _wasPlaying;\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\t_shiftPlayer = ShiftPlayer.IsValid() ? ShiftPlayer : GetComponentInChildren\u003CMoviePlayer\u003E();\r\n\t\t_manager = Game.ActiveScene?.GetSystem\u003CTimeShiftManager\u003E();\r\n\t\tif ( _shiftPlayer.IsValid() )\r\n\t\t{\r\n\t\t\tvar clip = _shiftPlayer.Clip;\r\n\t\t\tif ( clip is not null )\r\n\t\t\t{\r\n\t\t\t\t_ = clip.Duration;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( Input.Pressed( \u0022timeshift\u0022 ) )\r\n\t\t{\r\n\t\t\tTryBeginShift();\r\n\t\t}\r\n\r\n\t\tPollShiftTrigger();\r\n\t}\r\n\r\n\tprivate void TryBeginShift()\r\n\t{\r\n\t\tif ( CausalGameManager.Instance.IsValid() \u0026\u0026 !CausalGameManager.Instance.IsActive )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar manager = GetManager();\r\n\t\tif ( manager is not null \u0026\u0026 !manager.ShiftUnlocked )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !_shiftPlayer.IsValid() )\r\n\t\t{\r\n\t\t\tmanager?.RequestShift();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( _shiftPlayer.IsPlaying )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_shiftPlayer.Play();\r\n\t\t_timeSinceShiftStart = 0;\r\n\t\t_shiftPending = true;\r\n\t}\r\n\r\n\tprivate void PollShiftTrigger()\r\n\t{\r\n\t\tif ( !_shiftPlayer.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tbool playing = _shiftPlayer.IsPlaying;\r\n\r\n\t\tif ( !_shiftPending )\r\n\t\t{\r\n\t\t\t_wasPlaying = playing;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( _timeSinceShiftStart \u003E= ShiftAtSeconds )\r\n\t\t{\r\n\t\t\tFireShift();\r\n\t\t}\r\n\t\telse if ( _wasPlaying \u0026\u0026 !playing )\r\n\t\t{\r\n\t\t\tFireShift();\r\n\t\t}\r\n\r\n\t\t_wasPlaying = playing;\r\n\t}\r\n\r\n\tprivate void FireShift()\r\n\t{\r\n\t\t_shiftPending = false;\r\n\t\tGetManager()?.RequestShift();\r\n\t}\r\n\r\n\tprivate TimeShiftManager GetManager()\r\n\t{\r\n\t\tif ( _manager is not null )\r\n\t\t{\r\n\t\t\treturn _manager;\r\n\t\t}\r\n\r\n\t\t_manager = Game.ActiveScene?.GetSystem\u003CTimeShiftManager\u003E();\r\n\t\treturn _manager;\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":"World/MovieGate.cs","FileName":"MovieGate.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"using System;\r\nusing Sandbox.MovieMaker;\r\n\r\nnamespace Causal;\r\n\r\npublic sealed class MovieGate : Component\r\n{\r\n\tpublic enum HandoffMode\r\n\t{\r\n\t\tAbsolute,\r\n\t\tProportional,\r\n\t\tRestart\r\n\t}\r\n\r\n\t[Property] public MoviePlayer Player { get; set; }\r\n\t[Property] public MovieResource BaseMovie { get; set; }\r\n\t[Property] public MovieResource FailMovie { get; set; }\r\n\t[Property] public HandoffMode Handoff { get; set; } = HandoffMode.Absolute;\r\n\t[Property] public float FailOffset { get; set; }\r\n\t[Property] public float FailCheckFromSeconds { get; set; } = 1f;\r\n\t[Property] public float FailCheckToSeconds { get; set; } = 3f;\r\n\t[Property] public bool AllowInterrupt { get; set; } = true;\r\n\t[Property] public float ActionCooldown { get; set; } = 2f;\r\n\t[Property] public bool AdvanceWhileHidden { get; set; } = true;\r\n\r\n\tpublic bool IsPlaying =\u003E _player.IsValid() \u0026\u0026 _player.IsPlaying;\r\n\tpublic bool HasBranched =\u003E _hasBranched;\r\n\r\n\tprivate MoviePlayer _player;\r\n\tprivate IMovieCondition _condition;\r\n\tprivate TimeSince _timeSinceAction = 99f;\r\n\tprivate TimeSince _timeSinceHidden;\r\n\tprivate float _storedPosition;\r\n\tprivate bool _wasPlaying;\r\n\tprivate bool _hasBranched;\r\n\tprivate MovieResource _savedMovie;\r\n\tprivate float _savedPosition;\r\n\tprivate float _savedTimeScale = 1f;\r\n\tprivate bool _savedWasPlaying;\r\n\tprivate bool _hasSaved;\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tResolvePlayer();\r\n\t\tResolveCondition();\r\n\t}\r\n\r\n\tpublic void PlayBase()\r\n\t{\r\n\t\tif ( !GameObject.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !_player.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022MovieGate on \u0027{GameObject.Name}\u0027 has no MoviePlayer.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( BaseMovie is null || !BaseMovie.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022MovieGate on \u0027{GameObject.Name}\u0027 is missing its BaseMovie.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( _timeSinceAction \u003C ActionCooldown )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !AllowInterrupt \u0026\u0026 _player.IsPlaying )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tMovieResource selected = BaseMovie;\r\n\t\tif ( FailMovie.IsValid() \u0026\u0026 HasFailed() )\r\n\t\t{\r\n\t\t\tselected = FailMovie;\r\n\t\t}\r\n\r\n\t\tPlayAt( selected, 0f, true, _player.TimeScale );\r\n\t\t_hasBranched = selected == FailMovie;\r\n\t\t_timeSinceAction = 0f;\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( !_player.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( _player.IsPlaying )\r\n\t\t{\r\n\t\t\t_storedPosition = _player.PositionSeconds;\r\n\t\t\t_wasPlaying = true;\r\n\t\t\tTickBranch();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !_wasPlaying )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_wasPlaying = false;\r\n\t\tfloat pos = _player.PositionSeconds;\r\n\t\tfloat end = ClipDurationSeconds( _player.Clip );\r\n\t\tbool finished = end \u003E 0f ? pos \u003E= end - 0.05f : pos \u003E= _storedPosition - 0.05f;\r\n\t\tif ( _storedPosition \u003E 0.05f \u0026\u0026 !finished )\r\n\t\t{\r\n\t\t\t_player.PositionSeconds = _storedPosition;\r\n\t\t\t_player.IsPlaying = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t_storedPosition = 0f;\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void OnDisabled()\r\n\t{\r\n\t\tif ( !_player.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_savedMovie = CurrentMovie();\r\n\t\t_savedPosition = _player.PositionSeconds;\r\n\t\t_savedTimeScale = _player.TimeScale;\r\n\t\t_savedWasPlaying = _player.IsPlaying || _storedPosition \u003E 0.05f;\r\n\t\t_timeSinceHidden = 0f;\r\n\t\t_hasSaved = true;\r\n\t}\r\n\r\n\tprotected override void OnEnabled()\r\n\t{\r\n\t\tif ( !_hasSaved )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_hasSaved = false;\r\n\r\n\t\tResolvePlayer();\r\n\r\n\t\tif ( !_savedWasPlaying || !_savedMovie.IsValid() || !_player.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfloat end = MovieDurationSeconds( _savedMovie );\r\n\t\tfloat target = AdvanceWhileHidden ? _savedPosition \u002B (float)_timeSinceHidden * _savedTimeScale : _savedPosition;\r\n\t\ttarget = end \u003E 0f ? Math.Clamp( target, 0f, Math.Max( 0f, end - 0.05f ) ) : 0f;\r\n\t\tPlayAt( _savedMovie, target, true, _savedTimeScale );\r\n\t}\r\n\r\n\tprivate void TickBranch()\r\n\t{\r\n\t\tif ( _hasBranched || !FailMovie.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfloat pos = _storedPosition;\r\n\t\tif ( pos \u003C FailCheckFromSeconds || pos \u003E FailCheckToSeconds )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !HasFailed() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfloat target = MapPosition( pos, ClipDurationSeconds( _player.Clip ), MovieDurationSeconds( FailMovie ), Handoff, FailOffset );\r\n\t\tPlayAt( FailMovie, target, true, _player.TimeScale );\r\n\t\t_hasBranched = true;\r\n\t\t_timeSinceAction = 0f;\r\n\t}\r\n\r\n\tprivate void PlayAt( MovieResource movie, float position, bool resumePlaying, float timeScale )\r\n\t{\r\n\t\tif ( !_player.IsValid() || !movie.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_player.Play( movie );\r\n\t\t_player.TimeScale = timeScale;\r\n\t\t_player.PositionSeconds = position;\r\n\t\t_player.IsPlaying = resumePlaying;\r\n\t\t_storedPosition = resumePlaying ? position : 0f;\r\n\t\t_wasPlaying = resumePlaying;\r\n\t}\r\n\r\n\tprivate bool HasFailed()\r\n\t{\r\n\t\treturn _condition is not null \u0026\u0026 _condition.HasFailed();\r\n\t}\r\n\r\n\tprivate MovieResource CurrentMovie()\r\n\t{\r\n\t\tvar resource = _player.Resource as MovieResource;\r\n\t\tif ( resource.IsValid() )\r\n\t\t{\r\n\t\t\treturn resource;\r\n\t\t}\r\n\r\n\t\treturn _hasBranched ? FailMovie : BaseMovie;\r\n\t}\r\n\r\n\tprivate void ResolvePlayer()\r\n\t{\r\n\t\t_player = Player.IsValid() ? Player : GetComponent\u003CMoviePlayer\u003E();\r\n\r\n\t\tif ( !_player.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022MovieGate on \u0027{GameObject.Name}\u0027 needs a MoviePlayer on the same GameObject.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_player.CreateTargets = false;\r\n\t}\r\n\r\n\tprivate void ResolveCondition()\r\n\t{\r\n\t\t_condition = null;\r\n\r\n\t\tforeach ( var component in Components.GetAll() )\r\n\t\t{\r\n\t\t\tif ( component is IMovieCondition condition )\r\n\t\t\t{\r\n\t\t\t\t_condition = condition;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( _condition is null )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022MovieGate on \u0027{GameObject.Name}\u0027 found no IMovieCondition.\u0022 );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate static float MapPosition( float basePosition, float baseDuration, float failDuration, HandoffMode mode, float offset )\r\n\t{\r\n\t\tfloat mapped = mode switch\r\n\t\t{\r\n\t\t\tHandoffMode.Absolute =\u003E basePosition \u002B offset,\r\n\t\t\tHandoffMode.Proportional =\u003E baseDuration \u003E 0.001f ? basePosition / baseDuration * failDuration : 0f,\r\n\t\t\t_ =\u003E 0f,\r\n\t\t};\r\n\r\n\t\treturn failDuration \u003E 0f ? Math.Clamp( mapped, 0f, Math.Max( 0f, failDuration - 0.05f ) ) : 0f;\r\n\t}\r\n\r\n\tprivate static float ClipDurationSeconds( IMovieClip clip )\r\n\t{\r\n\t\tif ( clip is null )\r\n\t\t{\r\n\t\t\treturn 0f;\r\n\t\t}\r\n\r\n\t\treturn (float)clip.Duration.TotalSeconds;\r\n\t}\r\n\r\n\tinternal static float MovieDurationSeconds( MovieResource movie )\r\n\t{\r\n\t\tif ( !movie.IsValid() || movie.Compiled is null )\r\n\t\t{\r\n\t\t\treturn 0f;\r\n\t\t}\r\n\r\n\t\treturn (float)movie.Compiled.Duration.TotalSeconds;\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":".obj/__compiler_extra.cs","FileName":"__compiler_extra.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"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, \u0022Causal\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022AddonIdent\u0022, \u0022causal\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022OrgIdent\u0022, \u0022fss\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022Ident\u0022, \u0022fss.causal\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-09-16T20:39:46.7421903Z\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyVersion(\u00220.0.115.0\u0022)]\r\n[assembly: global::System.Reflection.AssemblyFileVersion(\u00220.0.115.0\u0022)]"},{"Ident":"fss.causal","Path":"Game/CausalGameManager.cs","FileName":"CausalGameManager.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"namespace Causal;\r\n\r\npublic sealed class CausalGameManager : Component\r\n{\r\n\t[Property] public GameObject Player { get; set; }\r\n\t[Property] public float MenuFadeSeconds { get; set; } = 0.6f;\r\n\t[Property] public float CameraFlightSeconds { get; set; } = 2.2f;\r\n\r\n\tpublic static CausalGameManager Instance { get; private set; }\r\n\r\n\tpublic GameState State { get; private set; } = GameState.Menu;\r\n\r\n\tpublic bool IsActive =\u003E State == GameState.Active;\r\n\tpublic bool IsInIntro =\u003E State == GameState.Intro;\r\n\r\n\tprivate PlayerController _controller;\r\n\tprivate TimeSince _timeSinceIntro;\r\n\tprivate Vector3 _flightFromPosition;\r\n\tprivate Rotation _flightFromRotation;\r\n\r\n\tprotected override void OnAwake()\r\n\t{\r\n\t\tInstance = this;\r\n\t}\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tResolvePlayer();\r\n\t\tEnterMenu();\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( State != GameState.Intro )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tTickIntro();\r\n\t}\r\n\r\n\tprotected override void OnDestroy()\r\n\t{\r\n\t\tif ( Instance == this )\r\n\t\t{\r\n\t\t\tInstance = null;\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void EnterMenu()\r\n\t{\r\n\t\tState = GameState.Menu;\r\n\t\tApplyInputState();\r\n\t}\r\n\r\n\tpublic void BeginIntro()\r\n\t{\r\n\t\tif ( State != GameState.Menu )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !_controller.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022CausalGameManager on \u0027{GameObject.Name}\u0027 found no PlayerController.\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( !Scene.Camera.IsValid() )\r\n\t\t{\r\n\t\t\tEnterGame();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t_flightFromPosition = Scene.Camera.WorldPosition;\r\n\t\t_flightFromRotation = Scene.Camera.WorldRotation;\r\n\t\t_timeSinceIntro = 0;\r\n\t\tState = GameState.Intro;\r\n\t\tApplyInputState();\r\n\t}\r\n\r\n\tpublic void EnterGame()\r\n\t{\r\n\t\tif ( State == GameState.Active )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tState = GameState.Active;\r\n\t\tApplyInputState();\r\n\t}\r\n\r\n\tprivate void TickIntro()\r\n\t{\r\n\t\tif ( !_controller.IsValid() || !Scene.Camera.IsValid() )\r\n\t\t{\r\n\t\t\tEnterGame();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfloat flightDuration = CameraFlightSeconds \u003C= 0.01f ? 0.01f : CameraFlightSeconds;\r\n\t\tfloat flightTime = _timeSinceIntro - MenuFadeSeconds;\r\n\t\tfloat t = flightTime / flightDuration;\r\n\t\tif ( t \u003C 0f )\r\n\t\t{\r\n\t\t\tt = 0f;\r\n\t\t}\r\n\t\tif ( t \u003E 1f )\r\n\t\t{\r\n\t\t\tt = 1f;\r\n\t\t}\r\n\r\n\t\tfloat eased = t * t * (3f - 2f * t);\r\n\r\n\t\tTransform target = _controller.EyeTransform;\r\n\t\tScene.Camera.WorldPosition = Vector3.Lerp( _flightFromPosition, target.Position, eased );\r\n\t\tScene.Camera.WorldRotation = Rotation.Slerp( _flightFromRotation, target.Rotation, eased );\r\n\r\n\t\tif ( t \u003E= 1f )\r\n\t\t{\r\n\t\t\tEnterGame();\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void ResolvePlayer()\r\n\t{\r\n\t\tif ( Player.IsValid() )\r\n\t\t{\r\n\t\t\t_controller = Player.GetComponent\u003CPlayerController\u003E();\r\n\t\t}\r\n\r\n\t\tif ( !_controller.IsValid() )\r\n\t\t{\r\n\t\t\tforeach ( var controller in Scene.GetAllComponents\u003CPlayerController\u003E() )\r\n\t\t\t{\r\n\t\t\t\t_controller = controller;\r\n\t\t\t\tPlayer = controller.GameObject;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( !_controller.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022CausalGameManager on \u0027{GameObject.Name}\u0027 found no PlayerController.\u0022 );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void ApplyInputState()\r\n\t{\r\n\t\tif ( !_controller.IsValid() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tbool active = State == GameState.Active;\r\n\t\t_controller.WishVelocity = 0;\r\n\t\t_controller.UseInputControls = active;\r\n\t\t_controller.UseCameraControls = active;\r\n\t\t_controller.UseLookControls = active;\r\n\t}\r\n\r\n\tpublic enum GameState\r\n\t{\r\n\t\tMenu,\r\n\t\tIntro,\r\n\t\tActive\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":"Player/CausalMoveModeWalk.cs","FileName":"CausalMoveModeWalk.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"using System;\r\nusing Sandbox.Movement;\r\n\r\nnamespace Causal;\r\n\r\n[Icon( \u0022directions_walk\u0022 )]\r\n[Group( \u0022Movement\u0022 )]\r\n[Title( \u0022MoveMode - Walk-C\u0022 )]\r\n[Description( \u0022Walk and sprint with strafe and backpedal speed penalties\u0022 )]\r\npublic sealed class CausalMoveModeWalk : MoveModeWalk\r\n{\r\n\t[Property] public float SideSpeedMultiplier { get; set; } = 0.65f;\r\n\t[Property] public float BackwardSpeedMultiplier { get; set; } = 0.65f;\r\n\r\n\tprivate Vector3.SmoothDamped _smoothedMovement;\r\n\r\n\tpublic override int Score( PlayerController controller )\r\n\t{\r\n\t\treturn base.Score( controller ) \u002B 1;\r\n\t}\r\n\r\n\tpublic override Vector3 UpdateMove( Rotation eyes, Vector3 input )\r\n\t{\r\n\t\teyes = eyes.Angles() with { pitch = 0 };\r\n\r\n\t\tinput = input.ClampLength( 1 );\r\n\r\n\t\tvar direction = eyes * input;\r\n\t\tvar velocity = GetBalancedSpeed( input );\r\n\r\n\t\tif ( direction.IsNearlyZero( 0.1f ) )\r\n\t\t{\r\n\t\t\tdirection = 0;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t_smoothedMovement.Current = direction.Normal * _smoothedMovement.Current.Length;\r\n\t\t}\r\n\r\n\t\t_smoothedMovement.Target = direction * velocity;\r\n\t\t_smoothedMovement.SmoothTime = _smoothedMovement.Target.Length \u003C _smoothedMovement.Current.Length\r\n\t\t\t? Controller.DeaccelerationTime\r\n\t\t\t: Controller.AccelerationTime;\r\n\t\t_smoothedMovement.Update( Time.Delta );\r\n\r\n\t\tif ( _smoothedMovement.Current.IsNearlyZero( 0.01f ) )\r\n\t\t{\r\n\t\t\t_smoothedMovement.Current = 0;\r\n\t\t}\r\n\r\n\t\treturn _smoothedMovement.Current;\r\n\t}\r\n\r\n\tprivate float GetBalancedSpeed( Vector3 input )\r\n\t{\r\n\t\tvar run = Input.Down( Controller.AltMoveButton );\r\n\r\n\t\tif ( Controller.RunByDefault )\r\n\t\t{\r\n\t\t\trun = !run;\r\n\t\t}\r\n\r\n\t\tvar velocity = run ? Controller.RunSpeed : Controller.WalkSpeed;\r\n\r\n\t\tif ( Controller.IsDucking )\r\n\t\t{\r\n\t\t\tvelocity = Controller.DuckedSpeed;\r\n\t\t}\r\n\r\n\t\treturn velocity * GetDirectionSpeedMultiplier( input );\r\n\t}\r\n\r\n\tprivate float GetDirectionSpeedMultiplier( Vector3 input )\r\n\t{\r\n\t\tvar speedMultiplier = 1f;\r\n\r\n\t\tif ( input.x \u003C 0f )\r\n\t\t{\r\n\t\t\tspeedMultiplier *= BackwardSpeedMultiplier;\r\n\t\t}\r\n\r\n\t\tif ( MathF.Abs( input.y ) \u003E 0f )\r\n\t\t{\r\n\t\t\tspeedMultiplier *= MathX.Lerp( 1f, SideSpeedMultiplier, MathF.Abs( input.y ) );\r\n\t\t}\r\n\r\n\t\treturn speedMultiplier;\r\n\t}\r\n}\r\n"},{"Ident":"fss.causal","Path":"World/DoorButton.cs","FileName":"DoorButton.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":381941,"Code":"namespace Causal;\r\n\r\npublic sealed class DoorButton : Component, Component.IPressable\r\n{\r\n\t[Property] public GameObject DoorObject { get; set; }\r\n\r\n\tprivate HighlightOutline _highlight;\r\n\tprivate BlastDoor _door;\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tComponent visual = (Component)GetComponent\u003CModelRenderer\u003E() ?? GetComponent\u003CMeshComponent\u003E();\r\n\t\tif ( !visual.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022DoorButton on \u0027{GameObject.Name}\u0027 found no ModelRenderer or MeshComponent.\u0022 );\r\n\t\t}\r\n\r\n\t\tif ( !DoorObject.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022DoorButton on \u0027{GameObject.Name}\u0027 has no door GameObject assigned.\u0022 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t_door = DoorObject.GetComponent\u003CBlastDoor\u003E() ?? DoorObject.GetComponentInChildren\u003CBlastDoor\u003E();\r\n\t\t\tif ( !_door.IsValid() )\r\n\t\t\t{\r\n\t\t\t\tLog.Warning( $\u0022DoorButton on \u0027{GameObject.Name}\u0027 found no BlastDoor on \u0027{DoorObject.Name}\u0027 or its children.\u0022 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t_highlight = GetComponent\u003CHighlightOutline\u003E();\r\n\t\tif ( !_highlight.IsValid() )\r\n\t\t{\r\n\t\t\tLog.Warning( $\u0022DoorButton on \u0027{GameObject.Name}\u0027 needs a HighlightOutline for hover feedback.\u0022 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t_highlight.Enabled = false;\r\n\t\t}\r\n\t}\r\n\r\n\tpublic bool CanPress( Component.IPressable.Event e )\r\n\t{\r\n\t\treturn _door.IsValid() \u0026\u0026 (!_door.IsOpen || _door.CanClose) \u0026\u0026 (_door.AllowInterrupt || !_door.IsAnimating);\r\n\t}\r\n\r\n\tpublic bool Press( Component.IPressable.Event e )\r\n\t{\r\n\t\tif ( !CanPress( e ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t_door.Toggle();\r\n\t\treturn true;\r\n\t}\r\n\r\n\tpublic bool Pressing( Component.IPressable.Event e )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tpublic void Release( Component.IPressable.Event e )\r\n\t{\r\n\t}\r\n\r\n\tpublic void Hover( Component.IPressable.Event e )\r\n\t{\r\n\t\tif ( _highlight.IsValid() )\r\n\t\t{\r\n\t\t\t_highlight.Enabled = true;\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void Look( Component.IPressable.Event e )\r\n\t{\r\n\t}\r\n\r\n\tpublic void Blur( Component.IPressable.Event e )\r\n\t{\r\n\t\tif ( _highlight.IsValid() )\r\n\t\t{\r\n\t\t\t_highlight.Enabled = false;\r\n\t\t}\r\n\t}\r\n\r\n\tpublic Component.IPressable.Tooltip? GetTooltip( Component.IPressable.Event e )\r\n\t{\r\n\t\tif ( !_door.IsValid() )\r\n\t\t{\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tstring title = _door.IsOpen \u0026\u0026 _door.CanClose ? \u0022Close\u0022 : \u0022Open\u0022;\r\n\t\treturn new Component.IPressable.Tooltip( title, \u0022\u0022, \u0022\u0022, true, this );\r\n\t}\r\n}\r\n"}]}