1909 results

using Sandbox.UI;
using Sandbox.UI.Construct;

public class ToastPanel : Panel
{
	public ToastPanel( Toast toast )
	{
		AddClass( toast.Status.ToString() );
		AddClass( toast.Position.ToString() );

		Add.Icon( toast.Status switch
		{
			ToastStatus.Info => "info",
			ToastStatus.Warning => "warning_amber",
			ToastStatus.Success => "check_circle_outline",
			ToastStatus.Error => "error_outline",
			_ => "",
		} );

		Add.Label( toast.Text, "text" );

		AddEventListener( "onclick", ( PanelEvent _ ) => Delete() );

		Invoke( toast.Duration, () => Delete() );
	}

	protected override int BuildHash() => HashCode.Combine( 1 );
}
using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Sandbox;
using Sandbox.Diagnostics;

namespace DataTables;

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class JsonTypeAnnotateAttribute : Attribute
{
}

internal static class Json
{
	public static JsonSerializerOptions Options()
	{
		return new JsonSerializerOptions() { WriteIndented = true };
	}

	public static JsonNode Serialize( object target, bool typeAnnotate, Type typeOverride = null )
	{
		var type = target.GetType();
		var typeDesc = TypeLibrary.GetType( type );

		if ( typeDesc.IsValueType || type.IsAssignableTo( typeof(Resource) ) ||
		     type.IsAssignableTo( typeof(string) ) )
			return Sandbox.Json.ToNode( target );

		if ( type.IsAssignableTo( typeof(IList) ) )
			return SerializeList( (IList)target, typeAnnotate );

		if ( type.IsAssignableTo( typeof(IDictionary) ) )
			return SerializeDictionary( (IDictionary)target, typeAnnotate );

		var node = SerializeObject( target, true, typeOverride );
		if ( typeAnnotate )
			node["__type"] = typeDesc.FullName;
		return node;
	}

	public static JsonNode SerializeDictionary( IDictionary target, bool typeAnnotate )
	{
		JsonObject jdict = new();

		Type keyArg = TypeLibrary.GetGenericArguments( target.GetType() )[0];

		bool isInteger = keyArg == typeof(int);
		bool isString = keyArg == typeof(string);
		bool isReal = keyArg == typeof(float) || keyArg == typeof(double);

		if ( !(isInteger || isString || isReal) )
		{
			Log.Error(
				$"The type '{keyArg.FullName}' is not a supported dictionary key! If you really need this to be supported, please submit an issue @ https://github.com/tzainten/DataTables" );
			return jdict;
		}

		foreach ( var key in target.Keys )
		{
			if ( key is null )
				continue;

			var value = target[key];
			if ( value is null )
				continue;

			jdict.Add( key.ToString(), Serialize( value, typeAnnotate ) );
		}

		return jdict;
	}

	public static JsonArray SerializeList( IList target, bool typeAnnotate )
	{
		JsonArray jarray = new();

		foreach ( var elem in target )
		{
			if ( elem is null )
				continue;

			jarray.Add( Serialize( elem, typeAnnotate ) );
		}

		return jarray;
	}

	public static JsonObject SerializeObject( object target, bool typeAnnotate, Type typeOverride = null )
	{
		JsonObject jobj = new();

		var type = typeOverride ?? target.GetType();
		var typeDesc = TypeLibrary.GetType( type );

		if ( typeDesc.IsValueType || type.IsAssignableTo( typeof(Resource) ) ||
		     type.IsAssignableTo( typeof(string) ) )
			return Sandbox.Json.ToNode( target ).AsObject();

		var members = TypeLibrary.GetFieldsAndProperties( typeDesc );
		foreach ( var member in members )
		{
			object value = null;
			bool shouldAnnotate = false;

			if ( member.IsField )
			{
				FieldDescription field = (FieldDescription)member;
				value = field.GetValue( target );
				if ( value is null )
					continue;

				shouldAnnotate = field.HasAttribute( typeof(JsonTypeAnnotateAttribute) );
				jobj[field.Name] = Serialize( value, shouldAnnotate, !shouldAnnotate ? field.FieldType : null );

				continue;
			}

			PropertyDescription property = (PropertyDescription)member;
			value = property.GetValue( target );
			if ( value is null )
				continue;

			shouldAnnotate = property.HasAttribute( typeof(JsonTypeAnnotateAttribute) );
			jobj[property.Name] = Serialize( value, shouldAnnotate, !shouldAnnotate ? property.PropertyType : null );
		}

		return jobj;
	}

	public static T Deserialize<T>( string json )
	{
		JsonNode node = JsonNode.Parse( json );
		if ( node is null )
			return default;

		return (T)DeserializeInternal( node, typeof(T) );
	}

	public static object DeserializeInternal( JsonNode node, Type type )
	{
		TypeDescription typeDesc = TypeLibrary.GetType( type );
		if ( typeDesc is not null && (typeDesc.IsValueType || type.IsAssignableTo( typeof(Resource) ) ||
		                              type.IsAssignableTo( typeof(string) )) )
		{
			try
			{
				return Sandbox.Json.FromNode( node, type );
			}
			catch ( Exception e )
			{
				return null;
			}
		}

		if ( type.IsAssignableTo( typeof(IDictionary) ) )
			return DeserializeDictionary( node.AsObject(), type );

		switch ( node.GetValueKind() )
		{
			case JsonValueKind.Object:
				return DeserializeObject( node.AsObject(), type );
			case JsonValueKind.Array:
				return DeserializeList( node.AsArray(), type );
			default:
				try
				{
					return Sandbox.Json.FromNode( node, type );
				}
				catch ( Exception e )
				{
					return null;
				}
		}
	}

	public static IList DeserializeList( JsonArray jarray, Type type )
	{
		IList list = TypeLibrary.Create<IList>( type );

		using var enumerator = jarray.GetEnumerator();
		while ( enumerator.MoveNext() )
		{
			var node = enumerator.Current;

			Type genericArg = TypeLibrary.GetGenericArguments( type ).First();

			var elem = DeserializeInternal( node, genericArg );
			if ( elem is null )
				continue;

			if ( elem.GetType().IsAssignableTo( genericArg ) )
				list.Add( elem );
		}

		return list;
	}

	public static IDictionary DeserializeDictionary( JsonObject jobj, Type type )
	{
		IDictionary dict = TypeLibrary.Create<IDictionary>( type );

		using var enumerator = jobj.GetEnumerator();
		while ( enumerator.MoveNext() )
		{
			var pair = enumerator.Current;

			Type[] genericArgs = TypeLibrary.GetGenericArguments( type );
			var keyType = genericArgs[0];

			var key = pair.Key;
			object parsedKey = key;
			if ( keyType == typeof(int) )
			{
				if ( int.TryParse( key, out int num ) )
					parsedKey = num;
			}
			else if ( keyType == typeof(double) )
			{
				if ( double.TryParse( key, out double num ) )
					parsedKey = num;
			}
			else if ( keyType == typeof(float) )
			{
				if ( float.TryParse( key, out float num ) )
					parsedKey = num;
			}

			var node = pair.Value;

			var elem = DeserializeInternal( node, genericArgs[1] );
			if ( elem is null )
				continue;

			Type keyArg = TypeLibrary.GetGenericArguments( type )[0];
			Type valueArg = TypeLibrary.GetGenericArguments( type )[1];

			bool isCorrectKeyType = parsedKey.GetType().IsAssignableTo( keyArg );
			bool isCorrectValueType = elem.GetType().IsAssignableTo( valueArg );

			if ( !isCorrectKeyType || !isCorrectValueType )
				continue;

			if ( elem.GetType().IsAssignableTo( genericArgs[1] ) )
				dict.Add( parsedKey, elem );
		}

		return dict;
	}

	public static object DeserializeObject( JsonObject jobj, Type type )
	{
		jobj.TryGetPropertyValue( "__type", out JsonNode __type );

		TypeDescription typeDesc = null;
		if ( __type is not null )
		{
			typeDesc = TypeLibrary.GetType( __type.GetValue<string>() );
		}
		else
		{
			typeDesc = TypeLibrary.GetType( type );
		}

		if ( typeDesc is null )
			return null;

		object instance = TypeLibrary.Create<object>( typeDesc.TargetType );
		using var enumerator = jobj.GetEnumerator();
		while ( enumerator.MoveNext() )
		{
			var node = enumerator.Current;

			var property = typeDesc.Properties.FirstOrDefault( x =>
				x.IsPublic && !x.IsStatic && x.IsNamed( node.Key ) && x.CanWrite && x.CanRead );
			bool isValidProperty = property is not null;

			var field = typeDesc.Fields.FirstOrDefault( x => x.IsPublic && !x.IsStatic && x.IsNamed( node.Key ) );
			bool isValidField = field is not null;

			if ( !isValidProperty && !isValidField )
				continue;

			var deserializeType = isValidProperty ? property.PropertyType : field.FieldType;
			var value = DeserializeInternal( node.Value, deserializeType );
			if ( value is null )
				continue;

			if ( value.GetType().IsAssignableTo( deserializeType ) )
			{
				if ( isValidProperty )
					property.SetValue( instance, value );
				else
					field.SetValue( instance, value );
			}
		}

		return instance;
	}
}
global using static Sandbox.Internal.GlobalGameNamespace;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "Second Order Dynamics" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "secondorderdynamics" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "andicraft" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "andicraft.secondorderdynamics" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "1/17/2025 7:48:34 PM" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "17" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]

[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.140.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.140.0")]
using Andicraft.SecondOrderDynamics;
using Sandbox;

namespace Andicraft.SecondOrderDynamics.Components;

[Title( "Second Order Dynamics - Follow Target" ), Category("Second Order Dynamics")]
public class FollowTargetComponent : Component
{
	[Property] public GameObject FollowTarget { get; set; }

	/// <summary>
	/// Reset the dynamics if the object moves further than this distance in one frame
	/// </summary>
	[Property] public float TeleportDistanceThreshold { get; set; } = 32 * 10;

	[Property] public DynamicsParameters PositionParameters { get; set; } = new();
	[Property] public DynamicsParameters RotationParameters { get; set; } = new();

	private Vector3Dynamics _positionDynamics;
	private RotationDynamics _rotationDynamics;

	private Vector3 _previousFollowPos = default;
	
	protected override void OnStart()
	{
		_positionDynamics = new Vector3Dynamics( PositionParameters, FollowTarget.WorldPosition );
		_rotationDynamics = new RotationDynamics( RotationParameters, FollowTarget.WorldRotation );

		_previousFollowPos = FollowTarget.WorldPosition;
	}

	protected override void OnUpdate()
	{
		if ( FollowTarget == null ) return;

		if ( FollowTarget.WorldPosition.DistanceSquared( _previousFollowPos ) >
		     TeleportDistanceThreshold * TeleportDistanceThreshold )
		{
			Warp();
			_previousFollowPos = FollowTarget.WorldPosition;
			return;
		}
		
		WorldPosition = _positionDynamics.Update( Time.Delta, FollowTarget.WorldPosition );
		WorldRotation = _rotationDynamics.Update( Time.Delta, FollowTarget.WorldRotation );

		_previousFollowPos = FollowTarget.WorldPosition;
	}

	/// <summary>
	/// Resets the following target, useful for when you teleport or jump somewhere
	/// </summary>
	public void Warp()
	{
		_positionDynamics.Reset( FollowTarget.WorldPosition );
		_rotationDynamics.Reset( FollowTarget.WorldRotation );

		WorldPosition = FollowTarget.WorldPosition;
		WorldRotation = FollowTarget.WorldRotation;
	}

	public void UpdatePositionParameters( DynamicsParameters p )
	{
		PositionParameters = p;
		_positionDynamics.UpdateParameters( p );
	}

	public void UpdateRotationParameters( DynamicsParameters p )
	{
		RotationParameters = p;
		_rotationDynamics.UpdateParameters( p );
	}
}
using Sandbox;

[Title("[DEMO] Follow Mouse On Plane"), Category("Second Order Dynamics (Demo)")]
public sealed class DemoFollowMouse : Component
{
	[Property] private CameraComponent Camera { get; set; }
	[Property] private float PlaneDistance { get; set; } = 100;
	[Property] private GameObject TargetObject { get; set; }
	
	protected override void OnUpdate()
	{
		var ray = Camera.ScreenPixelToRay( Mouse.Position );
		var p = new Plane( Camera.WorldPosition + Camera.WorldTransform.Forward * PlaneDistance,
			Camera.WorldTransform.Backward );
		var pt = p.Trace( ray );
		
		if (pt.HasValue)
			TargetObject.WorldPosition = pt.Value;
	}
}
using System;
using Sandbox;

namespace Andicraft.SecondOrderDynamics;

/// <summary>
/// Helper class that lets you run dynamics on a Color.
/// </summary>
public class ColorDynamics
{
	private FloatDynamics _h;
	private Vector2Dynamics _sv;
	private FloatDynamics _alpha;

	private Vector3 _currentHsv;
	private Color _currentColor;

	public Color CurrentValue => _currentColor;
	public float CurrentAlpha => _currentColor.a;

	public ColorDynamics(float frequency, float damping, float response, Color startingValue)
	{
		_currentHsv = startingValue.ToOkHsv();

		_h = new(frequency, damping, response, _currentHsv.x)
		{
			MinWrapValue = 0f,
			MaxWrapValue = 1f
		};

		_sv = new Vector2Dynamics(frequency, damping, response, new Vector2(_currentHsv.z, _currentHsv.y));

		_alpha = new FloatDynamics(frequency, damping, response, startingValue.a);
	}

	public void SetFrequency(float f)
	{
		_h.SetFrequency(f);
		_sv.SetFrequency(f);
		_alpha.SetFrequency(f);
	}

	public void SetDamping(float d)
	{
		_h.SetDamping(d);
		_sv.SetDamping(d);
		_alpha.SetDamping(d);
	}

	public void SetResponse(float r)
	{
		_h.SetResponse(r);
		_sv.SetResponse(r);
		_alpha.SetResponse(r);
	}

	public void Reset(Color value)
	{
		var targetColor = value.ToOkHsv();
		_currentColor = value;
		_currentHsv = targetColor;

		_h.Reset(_currentHsv.x);
		_sv.Reset(new Vector2(_currentHsv.y, _currentHsv.z));
		_alpha.Reset(value.a);
	}

	public Color Update(float deltaTime, Color target, bool setVelocity = false, Vector4 velocity = default)
	{
		var targetHsv = target.ToOkHsv();
		var h = _h.Update(deltaTime, targetHsv.x, setVelocity, velocity.x);
		var sv = _sv.Update(deltaTime, new Vector2(targetHsv.y, targetHsv.z), setVelocity,
			new Vector2(velocity.y, velocity.z));
		var a = _alpha.Update(deltaTime, target.a, setVelocity, velocity.w);
		_currentHsv = new Vector3(h, sv.x.Saturate(), sv.y.Saturate());

		var col = OkColor.OkHsvToColor(_currentHsv);
		col.a = a.Saturate();
		_currentColor = col;
		return _currentColor;
	}
}
// Copyright(c) 2021 Bjorn Ottosson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files(the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using System;

namespace Andicraft.SecondOrderDynamics;

// Straight up port of OKColor to allow ColorDynamics to work nicely
public static class OkColor
{

    // Finds the maximum saturation possible for a given hue that fits in sRGB
    // Saturation here is defined as S = C/L
    // a and b must be normalized so a^2 + b^2 == 1
    private static double ComputeMaxSaturation (in double a, in double b)
    {
        // Max saturation will be when one of r, g or b goes below zero.

        // Select different coefficients depending on which component goes below zero first
        double k0, k1, k2, k3, k4, wl, wm, ws;

        if (-1.88170328d * a - 0.80936493d * b > 1.0d)
        {
            // Re component
            k0 = 1.19086277d;
            k1 = 1.76576728d;
            k2 = 0.59662641d;
            k3 = 0.75515197d;
            k4 = 0.56771245d;
            wl = 4.0767416621d;
            wm = -3.3077115913d;
            ws = 0.2309699292d;
        }
        else if (1.81444104d * a - 1.19445276d * b > 1.0d)
        {
            // Green component
            k0 = 0.73956515d;
            k1 = -0.45954404d;
            k2 = 0.08285427d;
            k3 = 0.1254107d;
            k4 = 0.14503204d;
            wl = -1.2684380046d;
            wm = 2.6097574011d;
            ws = -0.3413193965d;
        }
        else
        {
            // Blue component
            k0 = 1.35733652d;
            k1 = -0.00915799d;
            k2 = -1.1513021d;
            k3 = -0.50559606d;
            k4 = +0.00692167d;
            wl = -0.0041960863d;
            wm = -0.7034186147d;
            ws = 1.707614701d;
        }

        // Approximate max saturation using a polynomial:
        double S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;

        // Do one step Halley's method to get closer
        // this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite
        // this should be sufficient for most applications, otherwise do two/three steps

        double k_l = 0.3963377774d * a + 0.2158037573d * b;
        double k_m = -0.1055613458d * a - 0.0638541728d * b;
        double k_s = -0.0894841775d * a - 1.291485548d * b;

        {
            double l_ = 1.0d + S * k_l;
            double m_ = 1.0d + S * k_m;
            double s_ = 1.0d + S * k_s;

            double l = l_ * l_ * l_;
            double m = m_ * m_ * m_;
            double s = s_ * s_ * s_;

            double l_dS = 3.0d * k_l * l_ * l_;
            double m_dS = 3.0d * k_m * m_ * m_;
            double s_dS = 3.0d * k_s * s_ * s_;

            double l_dS2 = 6.0d * k_l * k_l * l_;
            double m_dS2 = 6.0d * k_m * k_m * m_;
            double s_dS2 = 6.0d * k_s * k_s * s_;

            double f = wl * l + wm * m + ws * s;
            double f1 = wl * l_dS + wm * m_dS + ws * s_dS;
            double f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;

            double sDenom = (f1 * f1 - 0.5d * f * f2);
            if (sDenom != 0.0d) { S = S - f * f1 / sDenom; }
        }

        return S;
    }

    private static (double L, double C) FindCusp (in double a, in double b)
    {
        // First, find the maximum saturation (saturation S = C/L)
        double S_cusp = OkColor.ComputeMaxSaturation (a, b);

        // Convert to linear sRGB to find the first point where at least one of r,g or b >= 1:
        var rgb_at_max = OkColor.OkLabToLinearSrgb ((L: 1.0d, a: S_cusp * a, b: S_cusp * b));
        double L_cusp = Math.Pow (1.0d / Math.Max (Math.Max (rgb_at_max.r, rgb_at_max.g), rgb_at_max.b), 1.0d / 3.0d);
        double C_cusp = L_cusp * S_cusp;

        return (L: L_cusp, C: C_cusp);
    }

    // Finds intersection of the line defined by
    // L = L0 * (1 - t) + t * L1;
    // C = t * C1;
    // a and b must be normalized so a^2 + b^2 == 1
    private static double FindGamutIntersection (in double a, in double b, in double L1, in double C1, in double L0, (double L, double C) cusp)
    {
        // Find the intersection for upper and lower half seprately
        double t = 0.0d;
        if (((L1 - L0) * cusp.C - (cusp.L - L0) * C1) <= 0.0d)
        {
            // Lower half
            double tDenom = (C1 * cusp.L + cusp.C * (L0 - L1));
            if (tDenom != 0.0d) { t = cusp.C * L0 / tDenom; }
        }
        else
        {
            // Upper half

            // First intersect with triangle
            double tDenom = C1 * (cusp.L - 1.0d) + cusp.C * (L0 - L1);
            if (tDenom != 0.0d) { t = cusp.C * (L0 - 1.0d) / tDenom; }

            // Then one step Halley's method
            {
                double dL = L1 - L0;
                double dC = C1;

                double k_l = 0.3963377774d * a + 0.2158037573d * b;
                double k_m = -0.1055613458d * a - 0.0638541728d * b;
                double k_s = -0.0894841775d * a - 1.2914855480d * b;

                double l_dt = dL + dC * k_l;
                double m_dt = dL + dC * k_m;
                double s_dt = dL + dC * k_s;

                // If higher accuracy is required, 2 or 3 iterations of the following block can be used:
                {
                    double L = L0 * (1.0d - t) + t * L1;
                    double C = t * C1;

                    double l_ = L + C * k_l;
                    double m_ = L + C * k_m;
                    double s_ = L + C * k_s;

                    double l = l_ * l_ * l_;
                    double m = m_ * m_ * m_;
                    double s = s_ * s_ * s_;

                    double ldt = 3.0d * l_dt * l_ * l_;
                    double mdt = 3.0d * m_dt * m_ * m_;
                    double sdt = 3.0d * s_dt * s_ * s_;

                    double ldt2 = 6.0d * l_dt * l_dt * l_;
                    double mdt2 = 6.0d * m_dt * m_dt * m_;
                    double sdt2 = 6.0d * s_dt * s_dt * s_;

                    double r0 = 4.0767416621d * l - 3.3077115913d * m + 0.2309699292d * s - 1.0d;
                    double r1 = 4.0767416621d * ldt - 3.3077115913d * mdt + 0.2309699292d * sdt;
                    double r2 = 4.0767416621d * ldt2 - 3.3077115913d * mdt2 + 0.2309699292d * sdt2;

                    double rDenom = r1 * r1 - 0.5d * r0 * r2;
                    double ur = (rDenom != 0.0d) ? r1 / rDenom : 0.0d;
                    double tr = -r0 * ur;

                    double g0 = -1.2684380046d * l + 2.6097574011d * m - 0.3413193965d * s - 1.0d;
                    double g1 = -1.2684380046d * ldt + 2.6097574011d * mdt - 0.3413193965d * sdt;
                    double g2 = -1.2684380046d * ldt2 + 2.6097574011d * mdt2 - 0.3413193965d * sdt2;

                    double gDenom = g1 * g1 - 0.5d * g0 * g2;
                    double ug = (gDenom != 0.0d) ? g1 / gDenom : 0.0d;
                    double tg = -g0 * ug;

                    double b0 = -0.0041960863d * l - 0.7034186147d * m + 1.7076147010d * s - 1.0d;
                    double b1 = -0.0041960863d * ldt - 0.7034186147d * mdt + 1.7076147010d * sdt;
                    double b2 = -0.0041960863d * ldt2 - 0.7034186147d * mdt2 + 1.7076147010d * sdt2;

                    double bDenom = b1 * b1 - 0.5d * b0 * b2;
                    double ub = (bDenom != 0.0d) ? b1 / bDenom : 0.0d;
                    double tb = -b0 * ub;

                    tr = ur >= 0.0d ? tr : Single.MaxValue;
                    tg = ug >= 0.0d ? tg : Single.MaxValue;
                    tb = ub >= 0.0d ? tb : Single.MaxValue;

                    t = t + Math.Min (tr, Math.Min (tg, tb));
                }
            }
        }

        return t;
    }

    private static (double C_0, double C_mid, double C_max) GetCs (in double L, in double a_, in double b_)
    {
        var cusp = OkColor.FindCusp (a_, b_);

        double C_max = OkColor.FindGamutIntersection (a_, b_, L, 1.0d, L, cusp);
        var ST_max = OkColor.ToSt (cusp);

        // Scale factor to compensate for the curved part of gamut shape:
        double k = C_max / Math.Min ((L * ST_max.S), (1.0d - L) * ST_max.T);

        double C_mid = 0.0d;
        {
            var ST_mid = OkColor.GetSTMid (a_, b_);

            // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma.
            double C_a = L * ST_mid.S;
            double C_b = (1.0d - L) * ST_mid.T;
            double cae4 = C_a * C_a * C_a * C_a;
            double cbe4 = C_b * C_b * C_b * C_b;
            C_mid = 0.9d * k * Math.Sqrt (Math.Sqrt (1.0d / (1.0d / cae4 + 1.0d / cbe4)));
        }

        double C_0 = 0.0d;
        {
            // for C_0, the shape is independent of hue, so ST are constant. Values picked to roughly be the average values of ST.
            double C_a = L * 0.4d;
            double C_b = (1.0d - L) * 0.8d;

            // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma.
            C_0 = Math.Sqrt (1.0d / (1.0d / (C_a * C_a) + 1.0d / (C_b * C_b)));
        }

        return (C_0: C_0, C_mid: C_mid, C_max: C_max);
    }

    // Returns a smooth approximation of the location of the cusp
    // This polynomial was created by an optimization process
    // It has been designed so that S_mid < S_max and T_mid < T_max
    private static (double S, double T) GetSTMid (in double a_, in double b_)
    {
        double S = 0.11516993d;
        double sDenom = 7.4477897d + 4.1590124d * b_ +
            a_ * (-2.19557347d + 1.75198401d * b_ +
                a_ * (-2.13704948d - 10.02301043d * b_ +
                    a_ * (-4.24894561d + 5.38770819d * b_ +
                        4.69891013d * a_)));
        if (sDenom != 0.0d) { S += 1.0d / sDenom; }

        double T = 0.11239642d;
        double tDenom = 1.6132032d - 0.68124379d * b_ +
            a_ * (0.40370612d + 0.90148123d * b_ +
                a_ * (-0.27087943d + 0.6122399d * b_ +
                    a_ * (0.00299215d - 0.45399568d * b_ - 0.14661872d * a_)));
        if (tDenom != 0.0d) { T += 1.0d / tDenom; }

        return (S: S, T: T);
    }

    private static (double L, double a, double b) LinearSrgbToOkLab (in (double r, double g, double b) c)
    {
        double cr = c.r;
        double cg = c.g;
        double cb = c.b;

        double l = 0.4122214708d * cr + 0.5363325363d * cg + 0.0514459929d * cb;
        double m = 0.2119034982d * cr + 0.6806995451d * cg + 0.1073969566d * cb;
        double s = 0.0883024619d * cr + 0.2817188376d * cg + 0.6299787005d * cb;

        double lCbrt = Math.Pow (l, 1.0d / 3.0d);
        double mCbrt = Math.Pow (m, 1.0d / 3.0d);
        double sCbrt = Math.Pow (s, 1.0d / 3.0d);

        return (
            L: 0.2104542553d * lCbrt + 0.793617785d * mCbrt - 0.0040720468d * sCbrt,
            a: 1.9779984951d * lCbrt - 2.428592205d * mCbrt + 0.4505937099d * sCbrt,
            b: 0.0259040371d * lCbrt + 0.7827717662d * mCbrt - 0.808675766d * sCbrt);
    }

    public static (double L, double a, double b) OkHslToOkLab (in (double h, double s, double l) hsl)
    {
        // With single-precision numbers, this can generate invalid values, NaNs, infinities, etc.

        double l = hsl.l;
        if (l >= 1.0d) { return (L: 1.0d, a: 0.0d, b: 0.0d); }
        if (l <= 0.0d) { return (L: 0.0d, a: 0.0d, b: 0.0d); }

        double s = hsl.s;
        if (s < 0.0d) { s = 0.0d; }
        if (s > 1.0d) { s = 1.0d; }

        double hRad = hsl.h * 6.283185307179586d;
        double a_ = Math.Cos (hRad);
        double b_ = Math.Sin (hRad);
        double L = OkColor.ToeInv (l);

        var cs = OkColor.GetCs (L, a_, b_);
        double c0 = cs.C_0;
        double cMid = cs.C_mid;
        double cMax = cs.C_max;

        double mid = 0.8d;
        double midInv = 1.25d;

        double C = 0.0d;
        double t = 0.0d;
        double k0 = 0.0d;
        double k1 = 0.0d;
        double k2 = 1.0d;

        if (s < mid)
        {
            t = midInv * s;

            k1 = mid * c0;
            if (cMid != 0.0d) { k2 = (1.0d - k1 / cMid); }

            double kDenom = 1.0d - k2 * t;
            if (kDenom != 0.0d) { C = t * k1 / kDenom; }
        }
        else
        {
            double tDenom = 1.0d - mid;
            if (tDenom != 0.0d) { t = (s - mid) / tDenom; }

            k0 = cMid;
            if (c0 != 0.0d) { k1 = (1.0d - mid) * cMid * cMid * midInv * midInv / c0; }

            double cDenom = cMax - cMid;
            k2 = 1.0d;
            if (cDenom != 0.0d) { k2 = 1.0d - k1 / cDenom; }

            double kDenom = 1.0d - k2 * t;
            if (kDenom != 0.0d) { C = k0 + t * k1 / kDenom; }
        }

        return (L: L, a: C * a_, b: C * b_);
    }

    public static (double r, double g, double b) OkHslToSrgb (in (double h, double s, double l) hsl)
    {
        return OkColor.OkLabToSrgb (OkColor.OkHslToOkLab (hsl));
    }

    public static (double L, double a, double b) OkHsvToOkLab (in (double h, double s, double v) hsv)
    {
        double v = hsv.v;
        if (v <= 0.0d) { return (L: 0.0d, a: 0.0d, b: 0.0d); }
        if (v > 1.0d) { v = 1.0d; }

        double s = hsv.s;
        if (s < 0.0d) { s = 0.0d; }
        if (s > 1.0d) { s = 1.0d; }

        double hRad = hsv.h * 6.283185307179586d;
        double a_ = Math.Cos (hRad);
        double b_ = Math.Sin (hRad);

        var cusp = OkColor.FindCusp (a_, b_);
        var stMax = OkColor.ToSt (cusp);
        double sMax = stMax.S;
        double tMax = stMax.T;
        double s0 = 0.5d;
        double k = 1.0d;
        if (sMax != 0.0d) { k = 1.0d - s0 / sMax; }

        // first we compute L and V as if the gamut is a perfect triangle:

        // L, C when v==1:
        double vDenom = s0 + tMax - tMax * k * s;
        double lv = 1.0d;
        double cv = 0.0d;
        if (vDenom != 0.0d)
        {
            lv = 1.0d - s * s0 / vDenom;
            cv = s * tMax * s0 / vDenom;
        }

        double L = v * lv;
        double C = v * cv;

        // then we compensate for both toe and the curved top part of the triangle:
        double lvt = OkColor.ToeInv (lv);
        double cvt = 0.0d;
        if (lv != 0.0d) { cvt = cv * lvt / lv; }

        double lNew = OkColor.ToeInv (L);
        if (L != 0.0d) { C = C * lNew / L; }
        L = lNew;

        var rgbScale = OkColor.OkLabToLinearSrgb ((L: lvt, a: a_ * cvt, b: b_ * cvt));
        double maxComp = Math.Max (rgbScale.r, Math.Max (rgbScale.g, Math.Max (rgbScale.b, 0.0d)));
        double lScale = 0.0d;
        if (maxComp != 0.0d)
        {
            lScale = Math.Pow (1.0d / maxComp, 1.0d / 3.0d);
        }

        C = C * lScale;
        return (
            L: L * lScale,
            a: C * a_,
            b: C * b_);
    }

    public static (double r, double g, double b) OkHsvToSrgb (in (double h, double s, double v) hsv)
    {
        return OkColor.OkLabToSrgb (OkColor.OkHsvToOkLab (hsv));
    }

    static (double r, double g, double b) OkLabToLinearSrgb (in (double L, double a, double b) c)
    {
        double cl = c.L;
        double ca = c.a;
        double cb = c.b;

        double lCbrt = cl + 0.3963377774d * ca + 0.2158037573d * cb;
        double mCbrt = cl - 0.1055613458d * ca - 0.0638541728d * cb;
        double sCbrt = cl - 0.0894841775d * ca - 1.291485548d * cb;

        double l = lCbrt * lCbrt * lCbrt;
        double m = mCbrt * mCbrt * mCbrt;
        double s = sCbrt * sCbrt * sCbrt;

        return (
            r: 4.0767416621d * l - 3.3077115913d * m + 0.2309699292d * s,
            g: -1.2684380046d * l + 2.6097574011d * m - 0.3413193965d * s,
            b: -0.0041960863d * l - 0.7034186147d * m + 1.707614701d * s);
    }

    public static (double h, double s, double l) OkLabToOkHsl (in (double L, double a, double b) lab)
    {
        double L = lab.L;
        if (L > 1.0d - Single.Epsilon) { return (h: 0.0d, s: 0.0d, l: 1.0d); }
        if (L < Single.Epsilon) { return (h: 0.0d, s: 0.0d, l: 0.0d); }

        // This has to be gt epsilon, not gt zero to avoid glitches.
        double Csq = lab.a * lab.a + lab.b * lab.b;
        if (Csq > Single.Epsilon)
        {
            double C = Math.Sqrt (Csq);
            double a_ = lab.a / C;
            double b_ = lab.b / C;

            // 1.0 / math.pi = 0.3183098861837907
            double h = 0.5d + 0.5d * (Math.Atan2 (-lab.b, -lab.a) * 0.3183098861837907d);

            var cs = OkColor.GetCs (L, a_, b_);
            double c0 = cs.C_0;
            double cMid = cs.C_mid;
            double cMax = cs.C_max;

            // Inverse of the interpolation in okhsl_to_srgb:
            double mid = 0.8d;
            double midInv = 1.25d;

            double s = 0.0d;
            if (C < cMid)
            {
                double k1 = mid * c0;
                double k2 = 1.0d;
                if (cMid != 0.0d) { k2 = (1.0d - k1 / cMid); }

                double tDenom = k1 + k2 * C;
                double t = 0.0d;
                if (tDenom != 0.0d) { t = C / tDenom; }

                s = t * mid;
            }
            else
            {
                double k0 = cMid;
                double k1 = 0.0d;
                if (c0 != 0.0d)
                {
                    k1 = (1.0d - mid) * cMid * cMid * midInv * midInv / c0;
                }

                double cDenom = cMax - cMid;
                double k2 = 1.0d;
                if (cDenom != 0.0d) { k2 = 1.0d - k1 / cDenom; }

                double tDenom = k1 + k2 * (C - k0);
                double t = 0.0d;
                if (tDenom != 0.0d) { t = (C - k0) / tDenom; }

                s = mid + (1.0d - mid) * t;
            }

            return (h: h, s: s, l: OkColor.Toe (L));
        }
        else
        {
            return (h: 0.0d, s: 0.0d, l: L);
        }
    }

    public static (double h, double s, double v) OkLabToOkHsv (in (double L, double a, double b) lab)
    {
        double L = lab.L;
        if (L > 1.0d - Single.Epsilon) { return (h: 0.0d, s: 0.0d, v: 1.0d); }
        if (L < Single.Epsilon) { return (h: 0.0d, s: 0.0d, v: 0.0d); }

        // This has to be gt epsilon, not gt zero to avoid glitches.
        double csq = lab.a * lab.a + lab.b * lab.b;
        if (csq > Single.Epsilon)
        {
            double C = Math.Sqrt (csq);
            double a_ = lab.a / C;
            double b_ = lab.b / C;

            // 1.0 / math.pi = 0.3183098861837907
            double h = 0.5d + 0.5d * (Math.Atan2 (-lab.b, -lab.a) * 0.3183098861837907d);

            var cusp = OkColor.FindCusp (a_, b_);
            var stMax = OkColor.ToSt (cusp);
            double sMax = stMax.S;
            double tMax = stMax.T;
            double s0 = 0.5d;
            double k = 1.0d;
            if (sMax != 0.0d) { k = 1.0d - s0 / sMax; }

            // first we find L_v, C_v, L_vt and C_vt
            double tDenom = C + L * tMax;
            double t = 0.0d;
            if (tDenom != 0.0d) { t = tMax / tDenom; }
            double lv = t * L;
            double cv = t * C;

            double lvt = OkColor.ToeInv (lv);
            double cvt = 0.0d;
            if (lv != 0.0d) { cvt = cv * lvt / lv; }

            // we can then use these to invert the step that compensates for the toe and the curved top part of the triangle:
            var rgbScale = OkColor.OkLabToLinearSrgb (
                (L: lvt,
                    a: a_ * cvt,
                    b: b_ * cvt));
            double scaleDenom = Math.Max (rgbScale.r, Math.Max (rgbScale.g, Math.Max (rgbScale.b, 0.0d)));
            double lScale = 0.0d;
            if (scaleDenom != 0.0d)
            {
                lScale = Math.Pow (1.0d / scaleDenom, 1.0d / 3.0d);
                L = L / lScale;
                C = C / lScale;
            }

            double toel = OkColor.Toe (L);
            C = C * toel / L;
            L = toel;

            // we can now compute v and s:
            double v = 0.0d;
            if (lv != 0.0d) { v = L / lv; }

            double s = 0.0d;
            double sDenom = ((tMax * s0) + tMax * k * cv);
            if (sDenom != 0.0d) { s = (s0 + tMax) * cv / sDenom; }

            return (h: h, s: s, v: v);
        }
        else
        {
            return (h: 0.0d, s: 0.0d, v: L);
        }
    }

    public static (double r, double g, double b) OkLabToSrgb (in (double L, double a, double b) lab)
    {
        var lrgb = OkColor.OkLabToLinearSrgb (lab);
        return (
            r: OkColor.SrgbTransferFunction (lrgb.r),
            g: OkColor.SrgbTransferFunction (lrgb.g),
            b: OkColor.SrgbTransferFunction (lrgb.b));
    }

    public static (double h, double s, double l) SrgbToOkHsl (in (double r, double g, double b) srgb)
    {
        return OkColor.OkLabToOkHsl (OkColor.SrgbToOkLab (srgb));
    }

    public static (double h, double s, double v) SrgbToOkHsv (in (double r, double g, double b) srgb)
    {
        return OkColor.OkLabToOkHsv (OkColor.SrgbToOkLab (srgb));
    }

    public static (double L, double a, double b) SrgbToOkLab (in (double r, double g, double b) srgb)
    {
        return OkColor.LinearSrgbToOkLab ((
            r: OkColor.SrgbTransferFunctionInv (srgb.r),
            g: OkColor.SrgbTransferFunctionInv (srgb.g),
            b: OkColor.SrgbTransferFunctionInv (srgb.b)));
    }

    static double SrgbTransferFunction (in double a)
    {
        return 0.0031308d >= a ? 12.92d * a : 1.055d * Math.Pow (a, 1.0d / 2.4d) - 0.055d;
    }

    static double SrgbTransferFunctionInv (in double a)
    {
        return 0.04045d < a ? Math.Pow ((a + 0.055d) / 1.055d, 2.4d) : a / 12.92d;
    }

    static (double S, double T) ToSt (in (double L, double C) cusp)
    {
        double L = cusp.L;
        double C = cusp.C;
        if (L != 0.0d && L != 1.0d)
        {
            return (S: C / L, T: C / (1.0d - L));
        }
        else if (L != 0.0d)
        {
            return (S: C / L, T: 0.0d);
        }
        else if (L != 1.0d)
        {
            return (S: 0.0d, T: C / (1.0d - L));
        }
        else
        {
            return (S: 0.0d, T: 0.0d);
        }
    }

    static double Toe (in double x)
    {
        double y = 1.170873786407767d * x - 0.206d;
        return 0.5d * (y + Math.Sqrt (y * y + 0.14050485436893204d * x));
    }

    static double ToeInv (in double x)
    {
        double denom = 1.170873786407767d * (x + 0.03d);
        return (denom != 0.0) ? (x * x + 0.206d * x) / denom : 0.0d;
    }

    public static Vector3 ToOkHsv(this Color c)
    {
        (double, double, double) col = (c.r, c.g, c.b);
        (double, double, double) hsv = SrgbToOkHsv(col);

        return new Vector3((float)hsv.Item1, (float)hsv.Item2, (float)hsv.Item3);
    }

    public static Color OkHsvToColor(Vector3 hsv)
    {
        (double, double, double) col = (hsv.x, hsv.y, hsv.z);
        (double, double, double) rgb = OkHsvToSrgb(col);

        return new Color((float)rgb.Item1, (float)rgb.Item2, (float)rgb.Item3);
    }
}
using System;

namespace Andicraft.SecondOrderDynamics;

public class Vector4Dynamics : SecondOrderDynamics<Vector4>
{
	/// <inheritdoc/>
	public Vector4Dynamics(Vector4 startingValue) : base(startingValue)
	{
	}

	/// <inheritdoc/>
	public Vector4Dynamics(Vector3 parameters, Vector4 startingValue) : base(parameters, startingValue)
	{
	}

	/// <inheritdoc/>
	public Vector4Dynamics(float frequency, float damping, float response, Vector4 startingValue) : base(frequency, damping, response, startingValue)
	{
	}

	/// <inheritdoc/>
	public override void Reset(Vector4 value)
	{
		_previousValue = value;
		_currentValue = value;
		_velocity = Vector4.Zero;
	}

	/// <inheritdoc/>
	public override Vector4 Update(float deltaTime, Vector4 target, bool setVelocity = false, Vector4 velocity = default)
	{
		if (setVelocity == false)
		{
			velocity = (target - _previousValue) / deltaTime;
			_previousValue = target;
		}

		var k2Stable = MathF.Max(k2, MathF.Max(deltaTime * deltaTime / 2 + deltaTime * k1 / 2, deltaTime * k1));
		_currentValue += deltaTime * _velocity;
		_velocity += deltaTime * (target + k3 * velocity - _currentValue - k1 * _velocity) / k2Stable;
		return _currentValue;
	}
}
global using Microsoft.AspNetCore.Components; 
global using Microsoft.AspNetCore.Components.Rendering;
using System.Collections.Generic;
using Sandbox;

[Group("Noblox")]
public class RbxlRoot : Component {
    public InstanceComponent[] IdToInstance {get; set;}

    [Property, ReadOnly]
    public int InstanceCount {get; set;}
    [Property, ReadOnly]
    public int ClassCount {get; set;}

    [Property, ReadOnly]
    public int ImportedObjectCount {get; set;}

    private List<GameObject> debris = new();

    /// <summary>
    /// add to cleanup list, so it will be deleted. Do not use by itself
    /// </summary>
    public void AddToCleanup(GameObject obj) => debris.Add(obj);

    /// <summary>
    /// Cleans up a debris list.
    /// </summary>
    /// <returns>Instances removed total</returns>
    public int Cleanup() {
        int i = 0;
        foreach(var obj in debris) {
            obj.Destroy();
            i++;
        }

        debris = new List<GameObject>();
        return i;
    }
}
using Sandbox;

[Group("Noblox Instances")]
public class RopeComponent : ConstraintComponent {

    [Property, ReadOnly]
    public float Length {get; set;} 

    public override void ConstraintSetup(GameObject part0, GameObject part1) {
        if (part0.GetComponent<InstanceComponent>().ClassName == "Attachment") {
            part0 = part0.Parent;
        }
        if (part1.GetComponent<InstanceComponent>().ClassName == "Attachment") {
            part1 = part1.Parent;
        }

        var joint = part0.Components.GetOrCreate<SpringJoint>();
        joint.Frequency = 10;
        joint.Body = part1;
    }
}
using System.Threading.Tasks;
using Sandbox;
using System.IO;
using Sandbox.Utility;

public sealed class LocalFile : Component
{



	public void Save( string FileName, Curve HeightCurve, int Noise1Type, int Noise1Seed, Curve Noise1Weight, float Noise1Frequency, int Noise2Type, int Noise2Seed, Curve Noise2Weight, float Noise2Frequency, int Noise3Type, int Noise3Seed, Curve Noise3Weight, float Noise3Frequency, int FalloffValue, int Resolution, Vector2 TerrainOffset, Vector2 FalloffCenter, int SampleRes, int Noise1Octave, int Noise2Octave, int Noise3Octave, float Noise1gain, float Noise2gain, float Noise3gain, float Noise1Lac, float Noise2Lac, float Noise3Lac)
	{
		//Makes filename string
		string FloatsName = FileName + " Floats" + ".json";
		string CurvesName = FileName + " Curves" + ".json";

		//Writes data to json
		FileSystem.Data.WriteJson( FloatsName, new float[25] { Noise1Type, Noise1Seed, Noise1Frequency, Noise2Type, Noise2Seed, Noise2Frequency, Noise3Type, Noise3Seed, Noise3Frequency, FalloffValue, Resolution, TerrainOffset.x, TerrainOffset.y, FalloffCenter.x, FalloffCenter.y, SampleRes, Noise1Octave, Noise2Octave, Noise3Octave, Noise1gain, Noise2gain, Noise3gain, Noise1Lac, Noise2Lac, Noise3Lac } );
		FileSystem.Data.WriteJson( CurvesName, new Curve[4] { HeightCurve, Noise1Weight, Noise2Weight, Noise3Weight } );

		

		Log.Info( "Saved " + FileName.ToString() + " as " + FloatsName.ToString() + " and " + CurvesName.ToString());
		Log.Info( "Saved at: " + FileSystem.Data.GetFullPath( FloatsName ).ToString() );

	}

	public void Load( string FileName, out float[] LoadedFloatValues, out Curve[] LoadedCurveValues )
	{
		//Makes filename string
		string FloatsName = FileName + " Floats" + ".json";
		string CurvesName = FileName + " Curves" + ".json";

		LoadedCurveValues = new Curve[4];
		LoadedFloatValues = new float[25];


		if ( FileSystem.Data.ReadJson<float[]>( FloatsName ) != null && FileSystem.Data.ReadJson<Curve[]>( CurvesName ) != null ) //Checks for file
		{
			//Loads File
			LoadedFloatValues = FileSystem.Data.ReadJson<float[]>( FloatsName );
			LoadedCurveValues = FileSystem.Data.ReadJson<Curve[]>( CurvesName );

		}
		else
		{

			Log.Error( "FILE NOT FOUND" );

		}
		


	}



}
using Sandbox;
using System.Numerics;

public sealed class SpawnTrigger : Component, Component.ITriggerListener
{

	public async void OnTriggerEnter( Collider other )
	{
		var player = other.Components.Get<GudeMovement>();

		if ( player != null ) 
		{	
			var gravity = player.Gravity;

			var directionalInfluence = player.DirectionalInfluence;

			var spawn = player.Spawned;

			Log.Info( "Get Ready!!!" );

			if (  spawn == true )
			{
				player.Rigidbody.Velocity = Vector3.Zero;

				player.Gravity = 0;

				player.DirectionalInfluence = 0;

				await Task.DelaySeconds( 2 );

				player.DirectionalInfluence = directionalInfluence;

				player.Gravity = gravity;

			}
		}
	}

	public void OnTriggerExit( Collider other )
	{
		var player = other.Components.Get<GudeMovement>();

		if ( player != null )
		{
			var spawn = player.Spawned;

			Log.Info( "Left Trigger" );

			if ( spawn == true )
			{
				player.Spawned = false;
			}
		}
	}
}
namespace MANIFOLD.Camera {
    /// <summary>
    /// Locks the <see cref="VirtualCamera"/> to it's <see cref="VirtualCamera.TrackingTarget"/>.
    /// </summary>
    [Title(LibraryData.TITLE_SPLIT + "Hard Lock"), Category(LibraryData.CATEGORY), Icon("lock")]
    public sealed class CameraHardLock : CameraExtension {
        public enum OrientMode {
            /// <summary>
            /// The target's orientation is not taken into account.
            /// </summary>
            None,
            /// <summary>
            /// The target's orientation only affects the position.
            /// </summary>
            [Title("Position Only")]
            NoRotation,
            /// <summary>
            /// The target's orientation affects both position and rotation.
            /// </summary>
            [Title("Position and Rotation")]
            Full
        }

        /// <summary>
        /// How should the Target's orientation be handled?
        /// </summary>
        [Property, Title("Orientation Handling")]
        public OrientMode Orient { get; set; } = OrientMode.Full;

        private GameObject lastTarget;
        private Vector3 targetBindRelativePos;
        private Vector3 targetBindLocalPos;
        private Rotation targetBindLocalRot;
        
        protected internal override void OnCameraInitialize() {
            if (!Camera.TrackingTarget.IsValid()) return;
            BindValues();
        }

        protected internal override void OnCameraUpdate(ref Vector3 localPosition, ref Rotation localRotation) {
            if (!Camera.TrackingTarget.IsValid()) return;
            if (Camera.TrackingTarget != lastTarget) {
                BindValues();
            }
            
            GameObject target = Camera.TrackingTarget;
            switch (Orient) {
                case OrientMode.None: {
                    Camera.WorldPosition = target.WorldPosition + targetBindRelativePos;
                    break;
                }
                case OrientMode.NoRotation: {
                    Camera.WorldPosition = target.WorldPosition + (targetBindLocalPos * target.WorldRotation);
                    break;
                }
                case OrientMode.Full: {
                    Camera.WorldPosition = target.WorldPosition + (targetBindLocalPos * target.WorldRotation);
                    Camera.WorldRotation = target.WorldRotation * targetBindLocalRot;
                    break;
                }
            }
        }

        private void BindValues() {
            lastTarget = Camera.TrackingTarget;
            targetBindRelativePos = WorldPosition - Camera.TrackingTarget.WorldPosition;
            
            Rotation inverse = Camera.TrackingTarget.WorldRotation.Inverse;
            targetBindLocalRot = WorldRotation * inverse;
            targetBindLocalPos = (WorldPosition - Camera.TrackingTarget.WorldPosition) * inverse;
        }
    }
}
using System.Collections.Generic;
using Sandbox;
using Sandbox.Utility;

namespace MANIFOLD.Camera {
    /// <summary>
    /// The actual brain of the camera system.
    /// </summary>
    public sealed class CameraSystem : GameObjectSystem {
        private CameraBrain mainCameraBrain;
        private bool cameraStackDirty;
        private LinkedList<VirtualCamera> cameraStack;

        private VirtualCamera transitionFrom;
        private VirtualCamera transitionTo;

        private bool inTransition;
        private bool reverseTransition;
        private float currentTransitionTimer;
        private float currentTransitionElapsed;
        private TransitionData currentTransitionData;

        public CameraBrain Brain => mainCameraBrain;
        public VirtualCamera LastCamera => transitionFrom;
        public VirtualCamera CurrentCamera => transitionTo;
        
        public CameraSystem(Scene scene) : base(scene) {
            cameraStack = new LinkedList<VirtualCamera>();
            
            Listen(Stage.FinishUpdate, 100, CameraUpdate, "camera.update");
        }
        
        private void CameraUpdate() {
            if (!FindBrain()) return;
            
            if (Scene.IsEditor) {
                if (!mainCameraBrain.UpdateInEditor) {
                    return;
                }
            }

            if (cameraStackDirty) {
                OnStackEdit();
            }

            if (!transitionTo.IsValid()) return;
            GetCameraTransform(transitionTo, out Vector3 toPos, out Rotation toRot);
            
            if (!Scene.IsEditor && inTransition) {
                float linearFactor = currentTransitionTimer / currentTransitionData.Duration;
                float easedFactor = 0f;

                {
                    float offset = currentTransitionElapsed / currentTransitionData.Duration;
                    float evalTime = linearFactor.Remap(offset, 1);

                    if (currentTransitionData.Mode == TransitionMode.Predefined) {
                        var func = Easing.GetFunction(currentTransitionData.EaseFunction.ToString());
                        easedFactor = func(evalTime) + currentTransitionElapsed;
                    } else if (currentTransitionData.Mode == TransitionMode.Curve) {
                        easedFactor = currentTransitionData.EaseCurve.Evaluate(evalTime);
                    }

                    easedFactor = easedFactor.Remap(0, 1, offset);
                }

                GetCameraTransform(transitionFrom, out Vector3 fromPos, out Rotation fromRot);
                mainCameraBrain.WorldPosition = Vector3.Lerp(fromPos, toPos, easedFactor);
                mainCameraBrain.WorldRotation = Rotation.Slerp(fromRot, toRot, easedFactor);
                mainCameraBrain.Camera.FieldOfView = MathX.Lerp(GetCameraFOV(transitionFrom), GetCameraFOV(transitionTo), easedFactor);

                currentTransitionTimer += mainCameraBrain.UseRealTime ? RealTime.Delta : Time.Delta;
                if (currentTransitionTimer >= currentTransitionData.Duration) {
                    currentTransitionTimer = currentTransitionData.Duration;
                    inTransition = false;
                }
            } else {
                mainCameraBrain.WorldPosition = toPos;
                mainCameraBrain.WorldRotation = toRot;
                mainCameraBrain.Camera.FieldOfView = GetCameraFOV(transitionTo);
            }
        }

        private void GetCameraTransform(VirtualCamera cam, out Vector3 pos, out Rotation rot) {
            cam.DoExtensionUpdate(out Vector3 localPos, out Rotation localRot);
            pos = cam.WorldPosition + (localPos * cam.WorldRotation);
            rot = cam.WorldRotation * localRot;
        }

        private float GetCameraFOV(VirtualCamera cam) {
            if (cam.FOVMode == FOVMode.Vertical) return (2 * float.Atan(float.Tan(cam.FieldOfView.DegreeToRadian() / 2) * Screen.Aspect)).RadianToDegree();
            return cam.FieldOfView;
        }
        
        public void ActivateCamera(VirtualCamera newCamera, bool updateNow = false) {
            if (!mainCameraBrain.IsValid()) {
                Log.Warning($"Tried to activate virtual camera '${newCamera.GameObject.Name}' but there is no brain in the scene.");
            }
            
            VirtualCamera highestCamera = null;
            foreach (VirtualCamera camera in cameraStack) {
                if (camera.Priority <= newCamera.Priority) {
                    highestCamera = camera;
                }
            }

            if (highestCamera != null) {
                cameraStack.AddAfter(cameraStack.Find(highestCamera), newCamera);
            } else {
                cameraStack.AddLast(newCamera);
            }

            
            cameraStackDirty = true;
            if (updateNow) {
                OnStackEdit();
            }
        }

        public void DeactivateCamera(VirtualCamera camera, bool updateNow = false) {
            cameraStack.Remove(camera);
            cameraStackDirty = true;
            if (updateNow) {
                OnStackEdit();
            }
        }

        private bool FindBrain() {
            if (mainCameraBrain.IsValid()) return true;
            mainCameraBrain = Scene.Components.GetInDescendants<CameraBrain>();
            return mainCameraBrain.IsValid();
        }
        
        private void OnStackEdit() {
            var lastNode = cameraStack.Last;
            if (lastNode == null) return;

            // var previousNode = lastNode.Previous;
            // if (previousNode != null) {
            //     transitionFrom = previousNode.Value;
            // }

            VirtualCamera newTo = lastNode.Value;
            if (newTo != transitionTo && transitionTo.IsValid()) {
                TransitionData newData = newTo.UseCustomTransition ? newTo.TransitionData : mainCameraBrain.TransitionData;

                if (newData.Mode != TransitionMode.Cut) {
                    inTransition = true;

                    if (newTo == transitionFrom) {
                        float elapsedNorm = 1 - (currentTransitionTimer / currentTransitionData.Duration);
                        currentTransitionTimer = newData.Duration * elapsedNorm;
                        currentTransitionElapsed = newData.AbsoluteEase ? 0f : newData.Duration * elapsedNorm;
                    } else {
                        currentTransitionTimer = 0;
                        currentTransitionElapsed = 0;
                    }
                }
                currentTransitionData = newData;
                transitionFrom = transitionTo;
            }
            transitionTo = newTo;
            cameraStackDirty = false;
        }
    }
}
global using Microsoft.AspNetCore.Components; 
global using Microsoft.AspNetCore.Components.Rendering;
using System.Threading.Tasks;
using Sandbox.Utility;

namespace MANIFOLD.Camera {
    public enum FOVMode { Vertical, Horizontal }
    
    /// <summary>
    /// Imagine a <see cref="CameraComponent"/> but it isn't real.
    /// </summary>
    [EditorHandle("materials/gizmo/virtual_cam.png")]
    [Title(LibraryData.TITLE_SPLIT + "Virtual Camera"), Icon("videocam"), Category(LibraryData.CATEGORY)]
    public sealed class VirtualCamera : Component, Component.ExecuteInEditor {
        /// <summary>
        /// This camera's priority in the stack.
        /// </summary>
        [Property]
        public int Priority { get; set; }
        
        /// <summary>
        /// Which type of field of view to use.
        /// <see cref="FOVMode.Vertical"/> is recommended.
        /// </summary>
        [Property, Header("Lens"), Title("FOV Type")]
        public FOVMode FOVMode { get; set; }
        /// <summary>
        /// Camera's field of view in degrees.
        /// </summary>
        [Property, Range(0, 180)]
        public float FieldOfView { get; set; } = 90f;
        
        /// <summary>
        /// Does this camera have an look target?
        /// If not, <see cref="TrackingTarget"/> is used.
        /// </summary>
        [Property, Header("Targets")]
        public bool UseLookTarget { get; set; }
        /// <summary>
        /// Target to track. Used as the <see cref="LookTarget"/> as well by default.
        /// </summary>
        [Property]
        public GameObject TrackingTarget { get; set; }
        /// <summary>
        /// Target to look at.
        /// </summary>
        [Property, ShowIf(nameof(UseLookTarget), true)]
        public GameObject LookTarget { get; set; }

        /// <summary>
        /// Should switching to this camera use a special transition?
        /// </summary>
        [Property, Header("Transition")]
        public bool UseCustomTransition { get; set; } = false;
        [ShowIf(nameof(UseCustomTransition), true)]
        [Property]
        public TransitionData TransitionData { get; set; }
        
        private CameraSystem internalSystem;
        private List<CameraExtension> extensions;
        private int lastComponentCount;
        
        public CameraSystem System {
            get {
                if (internalSystem == null) {
                    internalSystem = Scene.GetSystem<CameraSystem>();
                }
                return internalSystem;
            }
        }
        public bool IsActive => System.CurrentCamera == this;

        internal void OnSystemInit(CameraSystem system) {
            internalSystem = system;
            
            extensions = Components.GetAll<CameraExtension>(FindMode.EverythingInSelf).ToList();
            foreach (CameraExtension ext in extensions) {
                ext.Camera = this;
                ext.OnCameraInitialize();
            }
        }

        internal void DoExtensionUpdate(out Vector3 localPos, out Rotation localRot) {
            localPos = Vector3.Zero;
            localRot = Rotation.Identity;

            foreach (CameraExtension ext in extensions) {
                ext.OnCameraUpdate(ref localPos, ref localRot);
            }
        }

        protected override void OnStart() {
            if (internalSystem == null) {
                OnSystemInit(Scene.GetSystem<CameraSystem>());
            }
        }

        protected override void OnEnabled() {
            if (internalSystem == null) {
                OnSystemInit(Scene.GetSystem<CameraSystem>());
            }
            
            System.ActivateCamera(this);
        }

        protected override void OnDisabled() {
            System.DeactivateCamera(this);
        }

        protected override void OnUpdate() {
            if (!Scene.IsEditor) return; // we probably dont need to check this at runtime right?
            if (lastComponentCount != Components.Count) {
                extensions = Components.GetAll<CameraExtension>(FindMode.EverythingInSelf).ToList();
                Log.Info("component count has changed");
                lastComponentCount = Components.Count;
            }
        }
        
        protected override void DrawGizmos() {
            if (IsActive) return;
            if (!System.Brain.IsValid()) return;
            CameraComponent camera = System.Brain.Camera;

            float horizontalAngle = FieldOfView;
            // THIS IS WRONG BUT GOOD ENOUGH
            float verticalAngle = horizontalAngle * (camera.ScreenRect.Height / camera.ScreenRect.Width); // cam fov is horizontal

            Vector3 origin = Vector3.Zero;
            Vector3 forward = Vector3.Forward;
            Ray tl = new Ray(origin, forward * new Angles(verticalAngle * 0.5f, horizontalAngle * 0.5f, 0f));
            Ray tr = new Ray(origin, forward * new Angles(verticalAngle * 0.5f, -horizontalAngle * 0.5f, 0f));
            Ray bl = new Ray(origin, forward * new Angles(-verticalAngle * 0.5f, horizontalAngle * 0.5f, 0f));
            Ray br = new Ray(origin, forward * new Angles(-verticalAngle * 0.5f, -horizontalAngle * 0.5f, 0f));
            
            Frustum frustum = Frustum.FromCorners(tl, tr, br, bl, camera.ZNear, camera.ZFar);

            Gizmo.Draw.Color = new Color(0.5f, 0f, 0f);
            Gizmo.Draw.LineFrustum(frustum);
        }
    }
}
global using static Sandbox.Internal.GlobalGameNamespace;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "BetterUI" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "betterui" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "umblestudio" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "umblestudio.betterui" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "1/20/2025 1:22:55 PM" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "17" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]

[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.293.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.293.0")]
/// <summary>
/// Animates a component by scaling it between a minimum and maximum scale value.
/// </summary>

using System;

namespace BetterUI.Animations;

public class ScaleAnimation : AnimationBase
{
	/// <summary>
	/// Gets or sets the minimum scale factor.
	/// </summary>
	[Property]
	public float MinScale { get; set; } = 0.8f;

	/// <summary>
	/// Gets or sets the maximum scale factor.
	/// </summary>
	[Property]
	public float MaxScale { get; set; } = 1.2f;

	protected override void OnAnimate( float t )
	{
		var easedTime = ApplyEasing( NormalizedTime, Easing );
		var scale = MinScale + (MaxScale - MinScale) * (0.5f + 0.5f * MathF.Sin( easedTime * MathF.PI * 2 ));

		WorldScale = new Vector3(
			Axis.x > 0 ? scale : 1f,
			Axis.y > 0 ? scale : 1f,
			Axis.z > 0 ? scale : 1f
		);
	}
}
using System;

namespace BetterUI.Extensions;

/// <summary>
/// Extensions for property descriptions.
/// </summary>
internal static class PropertyDescriptionExtensions
{
	/// <summary>
	/// Checks if a property is a cascading property with the given name and type.
	/// </summary>
	/// <param name="prop">The property to check.</param>
	/// <param name="name">The name of the cascading property.</param>
	/// <param name="type">The type of the cascading property.</param>
	/// <returns>True if the property is a cascading property with the given name and type. False otherwise.</returns>
	public static bool IsCascadingProperty( this PropertyDescription prop, string name, Type type )
	{
		var attr = prop.GetCustomAttribute<CascadingPropertyAttribute>();
		if ( attr is null ) return false;
		
		return (attr.Name == name && type == prop.PropertyType) || type == prop.PropertyType;
	}
}
namespace BetterUI;

/// <summary>
/// An event that can be listened to in order to receive notifications
/// </summary>
public interface INotificationEvent : ISceneEvent<INotificationEvent>
{
	/// <summary>
	/// Called when a new notification is added to the system.
	/// </summary>
	/// <param name="notification">The notification that was added.</param>
	void OnNotification( INotification notification );

	/// <summary>
	/// Called when the notification system is changed.
	/// </summary>
	/// <param name="system">The new notification system.</param>
	void OnNotificationSystemChanged( NotificationSystem system );
}
@namespace BetterUI
@inherits Panel

@ChildContent
@namespace BetterUI
@inherits Panel
using System;

namespace BetterUI;

/// <summary>
/// An attribute that can be applied to a type to specify a notification view for a <see cref="Notification"/>.
/// </summary>
/// <remarks>
/// The type that this attribute is applied to must be a panel.
/// </remarks>
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct )]
public sealed class NotificationViewAttribute( Type type ) : Attribute
{
	/// <summary>
	/// The type of the notification view.
	/// </summary>
	public Type Type => type;
}
using System;

namespace BetterUI.Animations;

/// <summary>
/// Animates a component rotating around a central point in a pendulum-like motion.
/// </summary>
public class PendulumAnimation : AnimationBase
{
	/// <summary>
	/// The minimum angle of rotation (in degrees) that the component will reach.
	/// </summary>
	[Property]
	public float MinAngle { get; set; } = -45f;

	/// <summary>
	/// The maximum angle of rotation (in degrees) that the component will reach.
	/// </summary>
	[Property]
	public float MaxAngle { get; set; } = 45f;

	protected override void OnAnimate( float t )
	{
		var easedTime = ApplyEasing( NormalizedTime, Easing );
		var angle = MinAngle + (MaxAngle - MinAngle) * (0.5f + 0.5f * MathF.Sin( easedTime * MathF.PI * 2 ));

		WorldRotation = Rotation.FromAxis( Vector3.Up, angle );
	}
}
global using Microsoft.AspNetCore.Components; 
global using Microsoft.AspNetCore.Components.Rendering;
namespace SmallFishUtils;

// Originally taken from Facepunch source code, thank you!
public abstract class Singleton<T> : Component, IHotloadManaged where T : Singleton<T>
{
	public static T Instance { get; private set; }

	protected override void OnAwake()
	{
		if ( Instance.IsValid() )
		{
			Log.Warning( $"Multiple Singletons found of type: {TypeLibrary.GetType<T>().Name}" );
			Destroy();
			return;
		}

		if ( Active )
		{
			Instance = (T)this;
		}
	}

	void IHotloadManaged.Destroyed( Dictionary<string, object> state )
	{
		state["IsActive"] = Instance == this;
	}

	void IHotloadManaged.Created( IReadOnlyDictionary<string, object> state )
	{
		if ( state.GetValueOrDefault( "IsActive" ) is true )
		{
			Instance = (T)this;
		}
	}

	protected override void OnDestroy()
	{
		if ( Instance == this )
		{
			Instance = null;
		}
	}
}
using System;
using System.Collections.Generic;

namespace Sandbox.k.ECS.Core;

public class Filter
{
	private World _world;
	private List<Type> _with = new(); 
	private List<Type> _without = new(); 
	
	public Filter( World world )
	{
		_world = world;
	}

	public Filter With<T>()
	{
		_with.Add(typeof(T));
		return this;
	}

	public Filter Without<T>()
	{
		_without.Add(typeof(T));
		return this;
	}

	public IEnumerable<int> GetEntities()
	{
		var entities = _world.EntityManager.Entities;
		var result = new List<int>();
		foreach ( var entity in entities )
		{
			if ( _world.EntityManager.IsAlive(entity) )
			{
				bool hasAll = true;
				foreach ( var type in _with )
				{
					if ( !_world.HasComponent(type, entity) )
					{
						hasAll = false;
						break;
					}
				}

				if ( !hasAll ) continue;

				foreach ( var type in _without )
				{
					if ( _world.HasComponent(type, entity) )
					{
						hasAll = false;
						break;
					}
				}

				if ( hasAll )
					result.Add(entity);
			}
		}

		return result;
	}

	public void Clear()
	{
		_with.Clear();
		_without.Clear();
	}
}
using System.Collections.Generic;

namespace ExtendedCollections;

public static class ListExtensions
{
    public static T GetAndRemoveAt<T>(this IList<T> list, int index)
    {
        var value = list[index];
        list.RemoveAt(index);
        return value;
    }
}
global using static Sandbox.Internal.GlobalGameNamespace;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Rendering;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "FI Prop Grabber" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "fipropgrabber" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "fawasinteractive" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "fawasinteractive.fipropgrabber" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "5/16/2025 10:28:19 PM" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "19" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]

[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.324.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.324.0")]
namespace Minima.TikTokLive;

/// Thanks to the awesome people at TikTok-Live-Connector
/// https://github.com/zerodytrash/TikTok-Live-Connector/blob/ecde03a3113b45c30e9d43b6a686ef6b40d297e2/.proto/tiktok-schema.ts

/// <summary>
///	Represents a chat message in the room.
/// </summary>
public class WebcastChatMessage : BaseWebcastMessage {
	public WebcastChatMessageEvent? Event { get; set; }
	public User? User { get; set; }
	public string Comment { get; set; }
	public bool VisibleToSender { get; set; }
	public WebcastChatMessageImageModel? Background { get; set; }
	public string FullScreenTextColor { get; set; }
	public WebcastChatMessageImageModel? BackgroundImageV2 { get; set; }
	public WebcastChatMessageImageModel? GiftImage { get; set; }
	public int InputType { get; set; }
	public User? AtUser { get; set; }
	public WebcastSubEmote[] Emotes { get; set; }
	public string ContentLanguage { get; set; }
	public int QuickChatScene { get; set; }
	public int CommunityflaggedStatus { get; set; }
	public WebcastChatMessageCommentQualityScore[] CommentQualityScores { get; set; }
	public WebcastChatMessageUserIdentity? UserIdentity { get; set; }
	public WebcastChatMessageCommentTag[] CommentTag { get; set; }
	public string ScreenTime { get; set; }
	public string Signature { get; set; }
	public string SignatureVersion { get; set; }
	public string EcStreamerKey { get; set; }

	public override void Handle( TikTokLiveConnector tikTokLiveConnector ) =>
		ITikTokLiveEvents.Post( ttle => ttle.OnChat( this ) );

	public struct WebcastChatMessageEvent {
		public string MsgId { get; set; }
		public string CreateTime { get; set; }
		public WebcastChatMessageEventDetails? EventDetails { get; set; }

		public struct WebcastChatMessageEventDetails {
			public string DisplayType { get; set; }
			public string Label { get; set; }
		}
	}

	public struct WebcastChatMessageImageModel {
		public string[] MUrls { get; set; }
		public string MUri { get; set; }
		public int Height { get; set; }
		public int Width { get; set; }
		public string AvgColor { get; set; }
		public int ImageType { get; set; }
		public string Schema { get; set; }
		public WebcastChatMessageImageModelContent? Content { get; set; }
		public bool IsAnimated { get; set; }

		public struct WebcastChatMessageImageModelContent {
			public string Name { get; set; }
			public string FontColor { get; set; }
			public string Level { get; set; }
		}
	}

	public struct WebcastSubEmote {
		public int PlaceInComment { get; set; }
		public WebcastSubEmoteDetails? Emote { get; set; }

		public struct WebcastSubEmoteDetails {
			public string EmoteId { get; set; }
			public WebcastSubEmoteImage? Image { get; set; }

			public struct WebcastSubEmoteImage {
				public string ImageUrl { get; set; }
			}
		}
	}

	public struct WebcastChatMessageCommentQualityScore {
		public string Version { get; set; }
		public string Score { get; set; }
	}

	public struct WebcastChatMessageUserIdentity {
		public bool IsGiftGiverOfAnchor { get; set; }
		public bool IsSubscriberOfAnchor { get; set; }
		public bool IsMutualFollowingWithAnchor { get; set; }
		public bool IsFollowerOfAnchor { get; set; }
		public bool IsModeratorOfAnchor { get; set; }
		public bool IsAnchor { get; set; }
	}

	// Use enum for tags
	public enum WebcastChatMessageCommentTag {
		CommentTagNormal = 0,
		CommentTagCandidate = 1,
		CommentTagOverage = 2,
		Unrecognized = -1
	}
}
namespace Minima.TikTokLive;

/// Thanks to the awesome people at TikTok-Live-Connector
/// https://github.com/zerodytrash/TikTok-Live-Connector/blob/ecde03a3113b45c30e9d43b6a686ef6b40d297e2/.proto/tiktok-schema.ts

/// <summary>
/// Represents a gift given in a TikTok live webcast.
/// </summary>
public class WebcastGiftMessage : BaseWebcastMessage {
	public WebcastGiftMessageEvent? Event { get; set; }
	public int GiftId { get; set; }
	public int RepeatCount { get; set; }
	public User? User { get; set; }
	public int RepeatEnd { get; set; }
	public string GroupId { get; set; }
	public WebcastGiftMessageGiftDetails? GiftDetails { get; set; }
	public string MonitorExtra { get; set; }
	public WebcastGiftMessageGiftExtra? GiftExtra { get; set; }

	public override void Handle( TikTokLiveConnector tikTokLiveConnector ) =>
		ITikTokLiveEvents.Post( ttle => ttle.OnGift( this ) );

	public struct WebcastGiftMessageEvent {
		public string MsgId { get; set; }
		public string CreateTime { get; set; }
		public WebcastGiftMessageEventDetails? EventDetails { get; set; }

		public struct WebcastGiftMessageEventDetails {
			public string DisplayType { get; set; }
			public string Label { get; set; }
		}
	}

	public struct WebcastGiftMessageGiftDetails {
		public WebcastGiftMessageGiftImage? GiftImage { get; set; }
		public string GiftName { get; set; }
		public string Describe { get; set; }
		public int GiftType { get; set; }
		public int DiamondCount { get; set; }

		public struct WebcastGiftMessageGiftImage {
			public string GiftPictureUrl { get; set; }
		}
	}

	public struct WebcastGiftMessageGiftExtra {
		public string Timestamp { get; set; }
		public string ReceiverUserId { get; set; }
	}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Meteor.VehicleTool.Vehicle.Powertrain;
using Meteor.VehicleTool.Vehicle.Wheel;
using Sandbox;
namespace Meteor.VehicleTool.Vehicle;

public partial class VehicleController
{
	[Property, FeatureEnabled( "Powertrain", Icon = "power" )]
	public bool UsePowertrain { get; set; } = true;

	[Property, Feature( "Powertrain" ), Group( "Properties" )] public float MaxBrakeTorque { get; set; } = 3000;
	[Property, Feature( "Powertrain" ), Group( "Properties" )] public float HandBrakeTorque { get; set; } = 50000;

	[Property, Feature( "Powertrain" ), Group( "Components" )] public Engine Engine { get; set; }
	[Property, Feature( "Powertrain" ), Group( "Components" )] public Clutch Clutch { get; set; }
	[Property, Feature( "Powertrain" ), Group( "Components" )] public Transmission Transmission { get; set; }
	[Property, Feature( "Powertrain" ), Group( "Components" )] public Differential Differential { get; set; }


	private GameObject powertrainGameObject;

	[Property, Feature( "Powertrain" )] public List<WheelCollider> MotorWheels { get; set; }
	[Property, Feature( "Powertrain" )] public List<WheelCollider> HandBrakeWheels { get; set; }
	public List<WheelPowertrain> PowertrainWheels { get; private set; } = [];

	[Button, Feature( "Powertrain" )]
	internal void FindWheels()
	{
		PowertrainWheels = Differential.Components.GetAll<WheelPowertrain>( FindMode.InDescendants ).ToList();
	}


	[Button, Feature( "Powertrain" )]
	internal void CreatePowertrain()
	{
		using var undoScope = Scene.Editor?.UndoScope( "Create Powertrain" ).WithComponentCreations().WithGameObjectCreations().Push();
		if ( !powertrainGameObject.IsValid() )
		{
			powertrainGameObject = null;
		}
		powertrainGameObject ??= new GameObject( true, "Powertrain" );

		if ( !Engine.IsValid() )
			Engine = new GameObject( powertrainGameObject, true, "Engine" ).GetOrAddComponent<Engine>();

		Engine.Controller = this;
		Engine.Inertia = 0.25f;
		Engine.Ignition = false;

		if ( !Clutch.IsValid() )
			Clutch = new GameObject( Engine.GameObject, true, "Clutch" ).GetOrAddComponent<Clutch>();

		Clutch.Controller = this;
		Clutch.Inertia = 0.02f;

		Engine.Output = Clutch;

		if ( !Transmission.IsValid() )
			Transmission = new GameObject( Clutch.GameObject, true, "Transmission" ).GetOrAddComponent<Transmission>();

		Transmission.Controller = this;
		Transmission.Inertia = 0.01f;

		Clutch.Output = Transmission;

		Differential = new TreeBuilder( Transmission, MotorWheels ).Root.Diff;

		Transmission.Output = Differential;

		PowertrainWheels = Differential.Components.GetAll<WheelPowertrain>( FindMode.InDescendants ).ToList();

	}


	private void UpdateBrakes()
	{
		foreach ( var wheel in Wheels )
			wheel.BrakeTorque = SwappedBrakes * MaxBrakeTorque;

		foreach ( var wheel in HandBrakeWheels )
			wheel.BrakeTorque += Handbrake * MaxBrakeTorque;
	}

}



internal class TreeNode
{
	internal TreeNode Left { get; set; }
	internal TreeNode Right { get; set; }
	public WheelPowertrain Item { get; set; }
	public Differential Diff { get; set; }
	public bool IsLeaf => Left == null && Right == null;
}

internal class TreeBuilder
{
	internal TreeNode Root { get; private set; }

	internal TreeBuilder( PowertrainComponent parent, List<WheelCollider> items )
	{
		if ( items == null || items.Count == 0 )
			throw new ArgumentException( "Items list cannot be null or empty." );

		Root = BuildTree( parent, items, 0, items.Count - 1 );
	}

	private static TreeNode BuildTree( PowertrainComponent parent, List<WheelCollider> items, int start, int end )
	{
		if ( start > end )
			return null;

		if ( start == end )
		{

			var leaf = new TreeNode() { Item = new GameObject( parent.GameObject, true, $"Wheel {items[start].GameObject.Name}" ).GetOrAddComponent<WheelPowertrain>() };
			leaf.Item.Controller = parent.Controller;
			leaf.Item.Wheel = items[start];
			leaf.Item.Inertia = 0.01f;
			var parentd = parent as Differential;
			if ( (start + 1) % 2 == 0 )
			{
				GameTask.RunInThreadAsync( () =>
				{
					parentd.OutputB = leaf.Item;
				} );
			}
			else
			{
				GameTask.RunInThreadAsync( () =>
				{
					parent.Output = leaf.Item;
				} );
			}

			return leaf;
		}

		int mid = (start + end) / 2;
		var diff = new GameObject( parent.GameObject, true, "Differential" ).GetOrAddComponent<Differential>();
		diff.Controller = parent.Controller;
		diff.Inertia = 0.1f;
		var node = new TreeNode
		{
			Left = BuildTree( diff, items, start, mid ),
			Right = BuildTree( diff, items, mid + 1, end ),
			Diff = diff
		};
		diff.Output = node.Left.Diff;
		diff.OutputB = node.Right.Diff;
		return node;
	}
}
using System;
using Sandbox;

namespace Meteor.VehicleTool.Vehicle.Wheel;

public struct PacejkaCurve
{
	// X // B
	[Range( 0, 30 )] public float Stiffnes;

	// Y // C
	[Range( 0, 5 )] public float ShapeFactor;

	// Z // D
	[Range( 0, 2 )] public float PeakValue;

	// W // E
	[Range( 0, 2 )] public float CurvatureFactor;

	public PacejkaCurve( float stiffnes, float shapeFactor, float peakValue, float curvatureFactor ) : this()
	{
		Stiffnes = stiffnes;
		ShapeFactor = shapeFactor;
		PeakValue = peakValue;
		CurvatureFactor = curvatureFactor;
		UpdateFrictionCurve();
	}

	/// <summary>
	/// Slip at which the friction preset has highest friction.
	/// </summary>
	public float PeakSlip;

	private Curve Curve;

	/// <summary>
	/// Gets the slip at which the friction is the highest for this friction curve.
	/// </summary>
	private readonly float GetPeakSlip()
	{
		float peakSlip = -1;
		float yMax = 0;

		for ( float i = 0; i < 1f; i += 0.01f )
		{
			float y = Curve.Evaluate( i );
			if ( y > yMax )
			{
				yMax = y;
				peakSlip = i;
			}
		}

		return peakSlip;
	}
	public readonly float Evaluate( float time ) => Curve.Evaluate( Math.Abs( time ) );


	/// <summary>
	///     Generate Curve from B,C,D and E parameters of Pacejka's simplified magic formula
	/// </summary>
	private void UpdateFrictionCurve()
	{
		Curve.Frame[] frames = new Curve.Frame[20];
		float t = 0;

		for ( int i = 0; i < frames.Length; i++ )
		{
			float v = GetFrictionValue( t );
			frames[i] = new Curve.Frame( t, v );

			if ( i <= 10 )
			{
				t += 0.02f;
			}
			else
			{
				t += 0.1f;
			}
		}
		Curve = new( frames );

		PeakSlip = GetPeakSlip();
	}

	private readonly float GetFrictionValue( float slip )
	{
		float B = Stiffnes;
		float C = ShapeFactor;
		float D = PeakValue;
		float E = CurvatureFactor;
		float t = MathF.Abs( slip );
		return D * MathF.Sin( C * MathF.Atan( B * t - E * (B * t - MathF.Atan( B * t )) ) );
	}

	public static readonly PacejkaCurve Asphalt = new( 9f, 2.15f, 0.933f, 0.971f );
	public static readonly PacejkaCurve AsphaltWet = new( 9f, 2.35f, 0.82f, 0.907f );
	public static readonly PacejkaCurve Generic = new( 8f, 1.9f, 0.8f, 0.99f );
	public static readonly PacejkaCurve Grass = new( 7.38f, 1.1f, 0.538f, 1f );
	public static readonly PacejkaCurve Dirt = new( 7.38f, 1.1f, 0.538f, 1f );
	public static readonly PacejkaCurve Gravel = new( 5.39f, 1.03f, 0.634f, 1f );
	public static readonly PacejkaCurve Ice = new( 1.2f, 2f, 0.16f, 1f );
	public static readonly PacejkaCurve Rock = new( 7.24f, 2.11f, 0.59f, 1f );
	public static readonly PacejkaCurve Sand = new( 5.13f, 1.2f, 0.443f, 0.5f );
	public static readonly PacejkaCurve Snow = new( 8.5f, 1.1f, 0.4f, 0.9f );
	public static readonly PacejkaCurve Tracks = new( 0.1f, 2f, 2f, 1f );

	public static PacejkaCurve GetPreset( PacejkaPreset preset )
	{
		return preset switch
		{
			PacejkaPreset.Asphalt => Asphalt,
			PacejkaPreset.AsphaltWet => AsphaltWet,
			PacejkaPreset.Generic => Generic,
			PacejkaPreset.Grass => Grass,
			PacejkaPreset.Dirt => Dirt,
			PacejkaPreset.Gravel => Gravel,
			PacejkaPreset.Ice => Ice,
			PacejkaPreset.Rock => Rock,
			PacejkaPreset.Sand => Sand,
			PacejkaPreset.Snow => Snow,
			PacejkaPreset.Tracks => Tracks,
			_ => Asphalt,
		};
	}
}

public enum PacejkaPreset
{
	Asphalt,
	AsphaltWet,
	Generic,
	Grass,
	Dirt,
	Gravel,
	Ice,
	Rock,
	Sand,
	Snow,
	Tracks,
}
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Meteor.VehicleTool.Vehicle;
using Meteor.VehicleTool.Vehicle.Wheel;
using Sandbox;
namespace Meteor.VehicleTool;

public sealed class VehicleCreator : Component
{
	[Property] public GameObject Model { get; set; }
	[Property, Group( "Wheels" )] public List<GameObject> Wheels { get; set; }
	[Property, Group( "Wheels" )] public List<GameObject> MotorWheels { get; set; }
	[Property, Group( "Wheels" )] public List<GameObject> SteeringWheels { get; set; }
	[Property, Group( "Wheels" )] public List<GameObject> HandBrakeWheels { get; set; }

	[Property, Group( "Engine" )] public List<SoundFile> AcsendingSounds { get; set; }
	[Property, Group( "Engine" )] public List<SoundFile> DecsendingSounds { get; set; }

	[Button]
	internal void CreateCar()
	{

		using var undo = Scene.Editor.UndoScope( "Create Car" ).WithComponentCreations().WithComponentDestructions( this ).Push();

		var controller = AddComponent<VehicleController>();

		List<WheelCollider> motors = [];
		List<WheelCollider> steering = [];
		List<WheelCollider> handBrake = [];

		var maxRPM = 0;
		foreach ( var item in Wheels )
		{
			GameObject p = new( item.Parent, true, $"WheelCollider ({item.Name})" )
			{
				WorldPosition = item.WorldPosition,
				WorldRotation = WorldRotation,
			};
			var collider = p.AddComponent<WheelCollider>();
			collider.UseVisual = true;
			collider.Controller = controller;

			item.SetParent( new( item.Parent, true, $"Wrap ({item.Name})" )
			{
				WorldPosition = item.WorldPosition,
				WorldRotation = WorldRotation,
			} );
			collider.RendererObject = item.Parent;

			if ( MotorWheels.Contains( item ) )
				motors.Add( collider );

			if ( SteeringWheels.Contains( item ) )
				steering.Add( collider );

			if ( HandBrakeWheels.Contains( item ) )
				handBrake.Add( collider );

			collider.SetBoundsToVisual();
			collider.CreateColliders();
		}

		Dictionary<int, SoundFile> acsendingSounds = [];
		Dictionary<int, SoundFile> decsendingSounds = [];

		foreach ( var item in AcsendingSounds )
		{
			var rpm = ExtractInteger( item.ResourceName );
			acsendingSounds.TryAdd( rpm, item );
			maxRPM = Math.Max( maxRPM, rpm );
		}

		foreach ( var item in DecsendingSounds )
			decsendingSounds.TryAdd( ExtractInteger( item.ResourceName ), item );


		controller.AcsendingSounds = acsendingSounds;
		controller.DecsendingSounds = decsendingSounds;

		controller.HandBrakeWheels = handBrake;
		controller.SteeringWheels = steering;
		controller.MotorWheels = motors;

		controller.Body.MassOverride = 1500;

		var size = Model.GetLocalBounds().Size;
		controller.CameraOffset = controller.CameraOffset.WithX( size.x * 1.5f ).WithZ( size.z / 2f );
		controller.ConnectWheels();
		controller.CreatePowertrain();
		controller.Engine.RevLimiterRPM = maxRPM;

		Destroy();
	}

	public static int ExtractInteger( string input )
	{
		Match match = Regex.Match( input, @"\d+" );
		if ( match.Success )
			return int.Parse( match.Value );
		throw new FormatException( "No integer found in the input." );
	}
}
using System;
using Sandbox;
namespace Meteor.VehicleTool;

public static class MathM
{
	public static float ExpDecay( float a, float b, float decay, float dt ) => b + (a - b) * MathF.Exp( -decay * dt );
	public static float AngleDifference( float a, float b ) => ((((b - a) % 360) + 540) % 360) - 180;
	public static float ExpDecayAngle( float a, float b, float decay, float dt ) => ExpDecay( a, a + AngleDifference( a, b ), decay, dt );

	/// <summary>
	///     Converts angular velocity (rad/s) to rotations per minute.
	/// </summary>
	public static float AngularVelocityToRPM( this float angularVelocity ) => angularVelocity * 9.5492965855137f;

	/// <summary>
	///     Converts rotations per minute to angular velocity (rad/s).
	/// </summary>
	public static float RPMToAngularVelocity( this float RPM ) => RPM * 0.10471975511966f;


	public static float Map( float x, float a, float b, float c, float d ) => (x - a) / (b - a) * (d - c) + c;

	public static float Fade( float n, float min, float mid, float max )
	{
		if ( n < min || n > max )
			return 0;

		if ( n > mid )
			min = mid - (max - mid);

		return MathF.Cos( (1 - ((n - min) / (mid - min))) * (MathF.PI / 2) );
	}

	public static Vector3 MeterToInch( this Vector3 v ) => new( v.x.MeterToInch(), v.y.MeterToInch(), v.z.MeterToInch() );
	public static Vector3 InchToMeter( this Vector3 v ) => new( v.x.InchToMeter(), v.y.InchToMeter(), v.z.InchToMeter() );
	public static Vector3 InchToMillimeter( this Vector3 v ) => new( v.x.InchToMillimeter(), v.y.InchToMillimeter(), v.z.InchToMillimeter() );
	public static Vector3 MillimeterToInch( this Vector3 v ) => new( v.x.MillimeterToInch(), v.y.MillimeterToInch(), v.z.MillimeterToInch() );

	public static float SignedAngle( this Vector3 from, Vector3 to, Vector3 axis )
	{
		float unsignedAngle = Vector3.GetAngle( from, to );

		float cross_x = from.y * to.z - from.z * to.y;
		float cross_y = from.z * to.x - from.x * to.z;
		float cross_z = from.x * to.y - from.y * to.x;
		float sign = MathF.Sign( axis.x * cross_x + axis.y * cross_y + axis.z * cross_z );
		return unsignedAngle * sign;
	}


	public struct LinearSmoothFloat( float inRate = 1, float outRate = 1, float inValue = 0 )
	{
		public float value = inValue;
		public float Get( float sample, float dt )
		{
			var dif = sample - value;
			if ( dif * value >= 0 )
			{
				value += dif * Math.Min( outRate * dt / Math.Abs( dif ), 1 );
			}
			else
				value += dif * Math.Min( inRate * dt / Math.Abs( dif ), 1 );

			return Math.Clamp( value, -1, 1 );
		}
	}
	public struct NonLinearSmoothFloat( float inRate = 1, float outRate = 1, float inValue = 0 )
	{
		public float value = inValue;
		public float Get( float sample, float dt )
		{
			var dif = sample - value;
			float ratedt;
			if ( dif * value >= 0 )
				ratedt = outRate * dt;
			else
				ratedt = inRate * dt;

			value += dif * ratedt / (1 + ratedt);
			return value;
		}
	}

	public struct SpringFloat( float spring = 10, float damp = 2, float inValue = 0 )
	{
		public float value = inValue;
		public float vel;
		public float Get( float sample, float dt )
		{
			vel = vel * Math.Max( 1 - damp * dt, 0 ) + (sample - value) * Math.Min( spring * dt, 1 / dt );
			value += vel * dt;

			return value;
		}
	}

}
using Meteor.VehicleTool.Vehicle;
using Sandbox;

namespace Meteor.VehicleTool;

public class WheelSkidMarkManager : Component
{
	[Property] VehicleController controller { get; set; }

	protected override void OnStart()
	{
		foreach ( var wheel in controller.Wheels )
		{
			wheel.GetOrAddComponent<WheelSkidMarkComponent>();
		}
	}
}
global using static Sandbox.Internal.GlobalGameNamespace;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Rendering;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "k.DlContainer2" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "kdlcontainer2" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "kfe" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "kfe.kdlcontainer2" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "6/8/2025 2:03:14 AM" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "19" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]

[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.111.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.111.0")]
using System;
using Sandbox;

namespace Orizon;

internal static class ClientOnlyHelper
{
	private static void EnsureClient()
	{
		if ( !Networking.IsClient )
			throw new Exception( "Only the client can call this method" );
	}

	internal static void __client_only_wrapper( WrappedMethod m, params object[] args )
	{
		EnsureClient();
		m.Resume();
	}

	internal static T __client_only_wrapper<T>( WrappedMethod<T> m, params object[] args )
	{
		EnsureClient();
		return m.Resume();
	}
}
using System;
using System.Collections.Generic;
using Sandbox;

namespace Orizon;

/// <summary>
/// Provides a way to send RPC requests from the client to the server.
/// </summary>
public static class RpcServer
{
	private static readonly Dictionary<Type, Delegate> _handlers = new();

	/// <summary>
	/// Registers a handler for an RPC request type.
	/// </summary>
	/// <typeparam name="TRequest">The type of the request.</typeparam>
	/// <typeparam name="TResponse">The type of the response.</typeparam>
	/// <param name="handler">The handler to register.</param>
	public static void RegisterHandler<TRequest, TResponse>( Func<TRequest, TResponse> handler )
		where TRequest : struct, IRpcRequest
		where TResponse : struct, IRpcResponse
	{
		_handlers[typeof(TRequest)] = handler;
	}

	/// <summary>
	/// Handles an incoming RPC request on the host.
	/// </summary>
	/// <param name="request">The request to handle.</param>
	[Rpc.Host]
	internal static void HandleRequest( IRpcRequest request )
	{
		var reqType = request.GetType();

		if ( _handlers.TryGetValue( reqType, out var handler ) )
		{
			var result = handler.DynamicInvoke( request );
			if ( result is not IRpcResponse response ) return;

			response.CallbackId = request.CallbackId;
			
			using ( Rpc.FilterInclude( Rpc.Caller ) )
				RpcTransport.SendToClient( response );
		}
		else
		{
			throw new Exception( $"Aucun handler enregistré pour le type {reqType.Name}" );
		}
	}
}
using System;
using System.Threading.Tasks;
using Sandbox;

namespace Orizon;

/// <summary>
/// Provides a way to send RPC requests from the client to the server.
/// </summary>
public static class RpcClient
{
	/// <summary>
	/// Sends a request to the server and waits for the response.
	/// </summary>
	/// <typeparam name="TRequest">The type of the request.</typeparam>
	/// <typeparam name="TResponse">The type of the response.</typeparam>
	/// <param name="request">The request to send.</param>
	/// <returns>The response from the server.</returns>
	[ClientOnly]
	public static async Task<TResponse> SendRpc<TRequest, TResponse>( TRequest request )
		where TRequest : struct, IRpcRequest
		where TResponse : struct, IRpcResponse
	{
		request.CallbackId = Guid.NewGuid();

		RpcTransport.SendToServer( request );
		return await RpcCallbackManager.WaitForResponse<TResponse>( request.CallbackId );
	}

	/// <summary>
	/// Called by the RPC system when a response is received from the server.
	/// </summary>
	/// <param name="response">The response received from the server.</param>
	[Rpc.Broadcast(NetFlags.Reliable | NetFlags.HostOnly)]
	internal static void OnRpcResponse( IRpcResponse response )
	{
		RpcCallbackManager.CompleteResponse( response.CallbackId, response );
	}
}
using Sandbox;

namespace Maxine;

/// <summary>
/// An implementation for Facepunch's default character controller.
/// </summary>
[Title( "Maxine's Simple Stamina - Simple Stamina for default player controller" )]
public sealed class StaminaForTheDefaultPlayerController : Component
{
	[Property] private Stamina Stamina;
	[Property] private PlayerController controller;
	[Property] private float minimumSpeedBeforeConsumingStamina =  300;
	[Property] private float staminaToConsume = 1f;

	protected override void OnAwake()
	{
		base.OnAwake();
		controller ??= GetComponent<PlayerController>();
		Stamina ??= GetComponent<Stamina>();
	}

	protected override void OnUpdate()
	{
		base.OnUpdate();
		if ( controller == null ) return;
		VelocityCheck( controller.Velocity );
	}

	private void VelocityCheck( Vector3 velocity )
	{
		if ( velocity.Length >= minimumSpeedBeforeConsumingStamina && controller.IsOnGround )
		{
			Stamina.ConsumeStamina( staminaToConsume );
			if ( Stamina.CurrentStamina <= 0 )
			{
				controller.WishVelocity = velocity / 6;
				controller.GroundVelocity = -velocity / 1.25f;
			}
		}
	}
}
using Sandbox;
using System;

namespace RacingGame;

/// <summary>
/// Basic component for vehicle camera
/// </summary>
[Category( "Racing Game" )]
[Title( "Orbit Camera" )]
[Icon( "camera" )]
public sealed class OrbitCamera : Component
{
	[Group( "Reset" ), Property] public float ResetDebounce { get; set; } = 3.0f;
	[Group( "Reset" ), Property] public float ResetLerpTime { get; set; } = 2.5f;
	[Group( "Following" ), Property] public float Distance { get; set; } = 256f;
	[Group( "Following" ), Property] public float Height { get; set; } = 32f;

	[Group( "Sensitivity" ), Property] public float LookSensitivity { get; set; } = 5.0f;
	[Group( "Sensitivity" ), Property] public float PositionSensitivity { get; set; } = 5.0f;
	[Group( "Sensitivity" ), Property] public float RotationSensitivity { get; set; } = 5.0f;

	[Group( "Tuning" ), Property] public float PullbackRate { get; set; } = 0.05f;
	[Group( "Tuning" ), Property] public RangedFloat PullbackRange { get; set; } = new RangedFloat( 0, 800f );
	[Group( "Tuning" ), Property] public float PivotRate { get; set; } = 90f;

	private Angles _lookDir;

	protected override void OnFixedUpdate()
	{
		if ( Scene.IsEditor )
			return;

		if ( !Car.Local.IsValid() )
			return;

		var target = Car.Local.CameraTarget;

		//
		// Analog look
		//
		{
			var analogLook = Input.AnalogLook;

			if ( Input.UsingController )
			{
				var theta = MathF.Atan2( -analogLook.yaw, analogLook.pitch );
				var angleDeg = theta.RadianToDegree();
				var targetDir = new Angles( 0, angleDeg, 0 );
				_lookDir = _lookDir.LerpTo( targetDir, LookSensitivity * Time.Delta );
			}
			else
			{
				_lookDir += analogLook;
			}
		}

		//
		// Follow camera
		//
		{
			var offset = _lookDir.ToRotation().Backward * Distance * target.Transform.World.Rotation;
			offset += Vector3.Up * Height;

			var targetPosition = target.Transform.Position + offset;
			var targetRotation = Rotation.LookAt( target.Transform.Position - targetPosition ).Angles();

			Transform.Position = Vector3.Lerp( Transform.Position, targetPosition, PositionSensitivity * Time.Delta );
			Transform.Rotation = Rotation.Lerp( Transform.Rotation, targetRotation, RotationSensitivity * Time.Delta );
		}
	}
}
using Sandbox;

public struct WheelFrictionInfo
{
	public float ExtremumSlip { get; set; }
	public float ExtremumValue { get; set; }
	public float AsymptoteSlip { get; set; }
	public float AsymptoteValue { get; set; }
	public float Stiffness { get; set; }

	public WheelFrictionInfo()
	{
		ExtremumSlip = 1.0f;
		ExtremumValue = 20000.0f;
		AsymptoteSlip = 2.0f;
		AsymptoteValue = 10000.0f;
		Stiffness = 1.0f;
	}

	public float Evaluate( float slip )
	{
		var value = 0.0f;

		if ( slip <= ExtremumSlip )
		{
			value = (slip / ExtremumSlip) * ExtremumValue;
		}
		else
		{
			value = ExtremumValue - ((slip - ExtremumSlip) / (AsymptoteSlip - ExtremumSlip)) * (ExtremumValue - AsymptoteValue);
		}

		return (value * Stiffness).Clamp( 0, float.MaxValue );
	}
}
using Sandbox;
using System;

public static class Vector2Extensions
{
	/// <summary>
	/// Gets a boundary proximity factor for a Vector2, where:
	/// 0.0 = center of [0,1] space (not near any boundary)
	/// 1.0 = at or beyond any boundary edge
	/// </summary>
	/// <param name="position">The position to check</param>
	/// <returns>Boundary proximity factor (0.0-1.0)</returns>
	public static float GetBoundaryProximityFactor( this Vector2 position )
	{
		// Calculate distance from center (0.5, 0.5)
		float centerX = 0.5f;
		float centerY = 0.5f;

		// Normalize positions to -0.5 to 0.5 range (distance from center)
		float normalizedX = MathF.Abs( position.x - centerX );
		float normalizedY = MathF.Abs( position.y - centerY );

		// Find the maximum normalized coordinate (closest boundary)
		float maxDistance = MathF.Max( normalizedX, normalizedY );

		// Convert to 0-1 range where 0 = center, 1 = boundary
		float proximityFactor = maxDistance * 2f; // *2 because max distance from center is 0.5
		proximityFactor = MathX.Clamp( proximityFactor, 0, 1 );

		return proximityFactor;
	}
}
global using static Sandbox.Internal.GlobalGameNamespace;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Rendering;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "Quick Asset Menu" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "quickassetmenu" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "alex" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "alex.quickassetmenu" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "3/23/2025 3:06:06 PM" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "17" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]

[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.247.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.247.0")]
using Sandbox;

global using Sandbox;
global using System;
global using System.Threading;
global using System.Threading.Tasks;
global using System.Text.Json.Serialization;
global using static Sandbox.Internal.GlobalGameNamespace;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Rendering;
[assembly: global::System.Reflection.AssemblyMetadata( "AddonTitle", "Fading screens" )]
[assembly: global::System.Reflection.AssemblyMetadata( "AddonIdent", "fadingscreens" )]
[assembly: global::System.Reflection.AssemblyMetadata( "OrgIdent", "workbot" )]
[assembly: global::System.Reflection.AssemblyMetadata( "Ident", "workbot.fadingscreens" )]
[assembly: global::System.Reflection.AssemblyMetadata( "CompileTime", "3/30/2025 4:09:28 PM" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineVersion", "17" )]
[assembly: global::System.Reflection.AssemblyMetadata( "EngineMinorVersion", "1" )]

[assembly: System.Runtime.Versioning.TargetFramework( ".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0" )]
[assembly: global::System.Reflection.AssemblyVersion("0.0.115.0")]
[assembly: global::System.Reflection.AssemblyFileVersion("0.0.115.0")]
namespace Sandbox.k.Common;

public struct ConstraintsSettingsBase<T>
{
	[Property] public T Offset { get; set; }
}