This commit is contained in:
Oscar
2025-06-08 23:43:22 +03:00
parent a6f2e43c49
commit 160429eae6
34 changed files with 5219 additions and 1905 deletions

View File

@@ -0,0 +1,56 @@
public sealed partial class Enemy
{
public bool DebugFootsteps = false;
public bool EnableFootstepSounds = true;
private TimeSince _timeSinceStep;
private void OnFootstepEvent( SceneModel.FootstepEvent e )
{
if ( EnableFootstepSounds && !(_timeSinceStep < 0.2f) )
{
_timeSinceStep = 0f;
PlayFootstepSound( e.Transform.Position, e.Volume, e.FootId );
}
}
[Rpc.Broadcast]
public void PlayFootstepSound( Vector3 worldPosition, float volume, int foot )
{
SceneTrace trace = Scene.Trace;
Vector3 from = worldPosition + WorldRotation.Up * 10f;
Vector3 to = worldPosition + WorldRotation.Down * 20f;
SceneTraceResult sceneTraceResult = trace.Ray( in from, in to ).IgnoreGameObjectHierarchy( GameObject ).Run();
if ( !sceneTraceResult.Hit || sceneTraceResult.Surface == null )
{
if ( DebugFootsteps )
{
DebugOverlay.Sphere( new Sphere( worldPosition, volume ), Color.Red, 10f, default, overlay: true );
}
return;
}
SoundEvent soundEvent = ResourceLibrary.Get<SoundEvent>( (foot == 0)
? sceneTraceResult.Surface.Sounds.FootLeft
: sceneTraceResult.Surface.Sounds.FootRight );
if ( soundEvent == null )
{
if ( DebugFootsteps )
{
DebugOverlay.Sphere( new Sphere( worldPosition, volume ), Color.Orange, 10f, default, overlay: true );
}
return;
}
SoundHandle soundHandle = GameObject.PlaySound( soundEvent, 0f );
// soundHandle.TargetMixer = FootstepMixer.GetOrDefault();
// soundHandle.Volume *= volume * FootstepVolume;
if ( DebugFootsteps )
{
DebugOverlay.Sphere( new Sphere( worldPosition, volume ), default, 10f, default, overlay: true );
DebugOverlay.Text( worldPosition, soundEvent.ResourceName ?? "", 14f, TextFlag.LeftTop, default, 10f,
default );
}
}
}

View File

@@ -0,0 +1,54 @@
namespace Sandbox.Gravity;
public sealed class InteractTeleporter : Component, Component.ITriggerListener
{
[Property] public GameObject ToPosGameObject { get; set; }
[Property, Sync] public List<Dedugan> Players { get; set; } = new();
public void OnTriggerEnter( Collider other )
{
var otherEntity = other.GameObject;
if ( otherEntity.Components.TryGet<Dedugan>( out var controller ) )
{
Players.Add( controller );
}
}
public void OnTriggerExit( Collider other )
{
var otherEntity = other.GameObject;
if ( otherEntity.Components.TryGet<Dedugan>( out var controller ) )
{
Players.Remove( controller );
}
}
public void TeleportAll()
{
foreach ( var controller in Players )
{
Teleport( controller );
}
}
[Rpc.Broadcast]
public void Teleport( Dedugan controller )
{
controller.OverrideGravity = WorldRotation.Down;
controller.GameObject.WorldPosition = ToPosGameObject.WorldPosition;
controller.EyeAngles = new Angles( 0, ToPosGameObject.WorldRotation.Yaw(), 0 ).ToRotation();
controller.Renderer.LocalRotation = new Angles( 0, ToPosGameObject.WorldRotation.Yaw(), 0 ).ToRotation();
}
[Rpc.Broadcast]
public void Teleport( Dedugan controller, Vector3 toPos )
{
controller.OverrideGravity = WorldRotation.Down;
controller.GameObject.WorldPosition = toPos;
controller.EyeAngles = new Angles( 0, ToPosGameObject.WorldRotation.Yaw(), 0 ).ToRotation();
controller.Renderer.LocalRotation = new Angles( 0, ToPosGameObject.WorldRotation.Yaw(), 0 ).ToRotation();
}
}

View File

@@ -12,8 +12,6 @@ public sealed class Teleporter : Component, Component.ITriggerListener
// [Property] public bool ResetGravity { get; set; } = false;
// [Property] public bool NormalGravity { get; set; } = true;
[Property] public GravityType gravityType { get; set; } = GravityType.Down;
public void OnTriggerEnter( Collider other )

View File

@@ -1,6 +1,4 @@
using Sandbox;
public sealed partial class Dedugan
public sealed partial class Dedugan
{
void UpdateCustomAnimations()
{

View File

@@ -1,11 +1,27 @@
public sealed partial class Dedugan
using Sandbox.Citizen;
public sealed partial class Dedugan
{
private float anotherPivot;
private Vector3 pivotOffset;
private void RotateCamera()
{
if ( Input.Keyboard.Pressed( "Q" ) )
{
anotherPivot = 40f;
}
if ( Input.Keyboard.Pressed( "E" ) )
{
anotherPivot = 0;
}
if (RagdollController.Enabled)
{
var offset = RagdollController.WorldRotation.Up * 20f - Camera.WorldRotation.Forward * 200f;
Camera.WorldPosition = Vector3.Lerp(Camera.WorldPosition, RagdollController.WorldPosition + offset, Time.Delta * 5f);
var off = RagdollController.WorldRotation.Up * 20f - Camera.WorldRotation.Forward * 200f;
Camera.WorldPosition = Vector3.Lerp(Camera.WorldPosition, RagdollController.WorldPosition + off, Time.Delta * 5f);
Camera.LocalRotation = Rotation.Lerp(Camera.LocalRotation, EyeAngles.ToRotation(), Time.Delta * 2f);
}
else
@@ -15,11 +31,22 @@
// Camera.LocalPosition = offset * Camera.LocalRotation;
Camera.LocalRotation = EyeAngles.ToRotation();
var pivotOffset = CameraPivot.LocalRotation.Backward * CamOffsetX;
var localPitchOffset = Camera.LocalRotation.Down * MathF.Max( 0f, EyeAngles.pitch ) * 0.32f +
Camera.LocalRotation.Backward * MathF.Max( 0f, EyeAngles.pitch ) * 0.7f +
Camera.LocalRotation.Up * MathF.Min( 0f, EyeAngles.pitch ) * 0.5f +
Camera.LocalRotation.Backward * MathF.Min( 0f, EyeAngles.pitch ) * 0.8f;
Camera.LocalRotation.Backward * MathF.Min( 0f, EyeAngles.pitch ) * 0.8f +
Camera.LocalRotation.Right * -anotherPivot;
if ( AnimationHelper.HoldType == CitizenAnimationHelper.HoldTypes.Pistol )
{
pivotOffset = CameraPivot.LocalRotation.Backward * CamOffsetX * 0.5f + CameraPivot.LocalRotation.Up * 8f;
}
else
{
pivotOffset = CameraPivot.LocalRotation.Backward * CamOffsetX;
}
var offset = (CameraPivot.LocalPosition + pivotOffset ) * EyeAngles.ToRotation() + localPitchOffset;
Camera.LocalPosition = offset;

View File

@@ -0,0 +1,56 @@
public sealed partial class Dedugan
{
public bool DebugFootsteps = false;
public bool EnableFootstepSounds = true;
private TimeSince _timeSinceStep;
private void OnFootstepEvent( SceneModel.FootstepEvent e )
{
if ( Controller.IsOnGround && EnableFootstepSounds && !(_timeSinceStep < 0.2f) )
{
_timeSinceStep = 0f;
PlayFootstepSound( e.Transform.Position, e.Volume, e.FootId );
}
}
[Rpc.Broadcast]
public void PlayFootstepSound( Vector3 worldPosition, float volume, int foot )
{
SceneTrace trace = Scene.Trace;
Vector3 from = worldPosition + WorldRotation.Up * 10f;
Vector3 to = worldPosition + WorldRotation.Down * 20f;
SceneTraceResult sceneTraceResult = trace.Ray( in from, in to ).IgnoreGameObjectHierarchy( GameObject ).Run();
if ( !sceneTraceResult.Hit || sceneTraceResult.Surface == null )
{
if ( DebugFootsteps )
{
DebugOverlay.Sphere( new Sphere( worldPosition, volume ), Color.Red, 10f, default, overlay: true );
}
return;
}
SoundEvent soundEvent = ResourceLibrary.Get<SoundEvent>( (foot == 0)
? sceneTraceResult.Surface.Sounds.FootLeft
: sceneTraceResult.Surface.Sounds.FootRight );
if ( soundEvent == null )
{
if ( DebugFootsteps )
{
DebugOverlay.Sphere( new Sphere( worldPosition, volume ), Color.Orange, 10f, default, overlay: true );
}
return;
}
SoundHandle soundHandle = GameObject.PlaySound( soundEvent, 0f );
// soundHandle.TargetMixer = FootstepMixer.GetOrDefault();
// soundHandle.Volume *= volume * FootstepVolume;
if ( DebugFootsteps )
{
DebugOverlay.Sphere( new Sphere( worldPosition, volume ), default, 10f, default, overlay: true );
DebugOverlay.Text( worldPosition, soundEvent.ResourceName ?? "", 14f, TextFlag.LeftTop, default, 10f,
default );
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Threading.Tasks;
public sealed partial class Dedugan
{
[Rpc.Broadcast]
public void ReportHit( Vector3 dir, int boneIndex, int damage = 10 )
{
Renderer.Set( "hit", true );
Renderer.Set( "hit_bone", boneIndex );
Renderer.Set( "hit_direction", dir );
Renderer.Set( "hit_offset", dir );
Renderer.Set( "hit_strength", 1 );
Health -= damage;
if ( Health <= 0 )
{
_ = RunReportHitAsync();
}
}
private async Task RunReportHitAsync()
{
await GameTask.DelaySeconds( 0.1f );
RagdollController.Enabled = true;
}
}

View File

@@ -5,215 +5,212 @@ using System.Linq;
public sealed partial class Dedugan : Component
{
public Component Pressed { get; set; }
public bool EnablePressing { get; set; } = true;
public Component Hovered { get; set; }
public Component Pressed { get; set; }
public bool EnablePressing { get; set; } = true;
public Component Hovered { get; set; }
[Sync(SyncFlags.Interpolate)]
public Vector3 TracedHitPos { get; set; }
[Sync]
public bool CameraTraceIsHit { get; set; }
public Vector3 TracedHitNormal { get; set; }
[Sync( SyncFlags.Interpolate )] public Vector3 TracedHitPos { get; set; }
[Sync] public bool CameraTraceIsHit { get; set; }
public Vector3 TracedHitNormal { get; set; }
// private TimeSince HoldTime = 0;
// private bool Holding = false;
// private bool HoldingInteractionHappened = false;
// private TimeSince HoldTime = 0;
// private bool Holding = false;
// private bool HoldingInteractionHappened = false;
void InteractionsUpdate()
{
if (!EnablePressing)
{
// Holding = false;
// HoldingInteractionHappened = false;
return;
}
void InteractionsUpdate()
{
if ( !EnablePressing )
{
// Holding = false;
// HoldingInteractionHappened = false;
return;
}
if (Pressed.IsValid())
{
UpdatePressed();
}
else
{
UpdateHovered();
}
}
if ( Pressed.IsValid() )
{
UpdatePressed();
}
else
{
UpdateHovered();
}
private void UpdatePressed()
{
bool flag = Input.Down("use");
if ( Input.Pressed( "Ragdoll" ) )
{
Health = 100;
}
}
if (flag && Pressed.Components.TryGet<IPressable>(out var pressable))
{
flag = pressable.Pressing(new IPressable.Event
{
Ray = new Ray(Camera.WorldPosition, EyeAngles.ToRotation().Forward),
Source = this
});
}
private void UpdatePressed()
{
bool flag = Input.Down( "use" );
if (GetDistanceFromGameObject(Pressed.GameObject, Camera.WorldPosition) > InteractDistance)
{
flag = false;
}
if ( flag && Pressed.Components.TryGet<IPressable>( out var pressable ) )
{
flag = pressable.Pressing( new IPressable.Event
{
Ray = new Ray( Camera.WorldPosition, EyeAngles.ToRotation().Forward ), Source = this
} );
}
if (!flag)
{
StopPressing();
}
}
if ( GetDistanceFromGameObject( Pressed.GameObject, Camera.WorldPosition ) > InteractDistance )
{
flag = false;
}
private void UpdateHovered()
{
SwitchHovered(TryGetLookedAt());
if ( !flag )
{
StopPressing();
}
}
if (Hovered is IPressable pressable)
{
pressable.Look(new IPressable.Event
{
Ray = new Ray(Camera.WorldPosition, EyeAngles.ToRotation().Forward),
Source = this
});
}
private void UpdateHovered()
{
SwitchHovered( TryGetLookedAt() );
if (Input.Down("use"))
{
StartPressing(Hovered);
}
}
if ( Hovered is IPressable pressable )
{
pressable.Look( new IPressable.Event
{
Ray = new Ray( Camera.WorldPosition, EyeAngles.ToRotation().Forward ), Source = this
} );
}
public void StartPressing(Component obj)
{
StopPressing();
if (!obj.IsValid())
{
ISceneEvent<PlayerController.IEvents>.PostToGameObject(GameObject, x => x.FailPressing());
return;
}
if ( Input.Down( "use" ) )
{
StartPressing( Hovered );
}
}
var component = obj.Components.Get<IPressable>(FindMode.EnabledInSelfAndDescendants);
if (component != null)
{
var pressEvent = new IPressable.Event
{
Ray = new Ray(Camera.WorldPosition, EyeAngles.ToRotation().Forward),
Source = this
};
public void StartPressing( Component obj )
{
StopPressing();
if ( !obj.IsValid() )
{
ISceneEvent<PlayerController.IEvents>.PostToGameObject( GameObject, x => x.FailPressing() );
return;
}
if (!component.CanPress(pressEvent))
{
ISceneEvent<PlayerController.IEvents>.PostToGameObject(GameObject, x => x.FailPressing());
return;
}
var component = obj.Components.Get<IPressable>( FindMode.EnabledInSelfAndDescendants );
if ( component != null )
{
var pressEvent = new IPressable.Event
{
Ray = new Ray( Camera.WorldPosition, EyeAngles.ToRotation().Forward ), Source = this
};
component.Press(pressEvent);
}
if ( !component.CanPress( pressEvent ) )
{
ISceneEvent<PlayerController.IEvents>.PostToGameObject( GameObject, x => x.FailPressing() );
return;
}
Pressed = obj;
component.Press( pressEvent );
}
if (Pressed.IsValid())
{
ISceneEvent<PlayerController.IEvents>.PostToGameObject(GameObject, x => x.StartPressing(Pressed));
}
}
Pressed = obj;
public void StopPressing()
{
if (Pressed.IsValid())
{
ISceneEvent<PlayerController.IEvents>.PostToGameObject(GameObject, x => x.StopPressing(Pressed));
if ( Pressed.IsValid() )
{
ISceneEvent<PlayerController.IEvents>.PostToGameObject( GameObject, x => x.StartPressing( Pressed ) );
}
}
if (Pressed is IPressable pressable)
{
pressable.Release(new IPressable.Event
{
Ray = new Ray(Camera.WorldPosition, EyeAngles.ToRotation().Forward),
Source = this
});
}
public void StopPressing()
{
if ( Pressed.IsValid() )
{
ISceneEvent<PlayerController.IEvents>.PostToGameObject( GameObject, x => x.StopPressing( Pressed ) );
Pressed = null;
}
}
if ( Pressed is IPressable pressable )
{
pressable.Release( new IPressable.Event
{
Ray = new Ray( Camera.WorldPosition, EyeAngles.ToRotation().Forward ), Source = this
} );
}
private void SwitchHovered(Component obj)
{
var e = new IPressable.Event
{
Ray = new Ray(Camera.WorldPosition, EyeAngles.ToRotation().Forward),
Source = this
};
Pressed = null;
}
}
if (Hovered == obj)
{
if (Hovered is IPressable pressable)
pressable.Look(e);
return;
}
private void SwitchHovered( Component obj )
{
var e = new IPressable.Event
{
Ray = new Ray( Camera.WorldPosition, EyeAngles.ToRotation().Forward ), Source = this
};
if (Hovered is IPressable oldPressable)
oldPressable.Blur(e);
if ( Hovered == obj )
{
if ( Hovered is IPressable pressable )
pressable.Look( e );
return;
}
Hovered = obj;
if ( Hovered is IPressable oldPressable )
oldPressable.Blur( e );
if (Hovered is IPressable newPressable)
{
newPressable.Hover(e);
newPressable.Look(e);
}
}
Hovered = obj;
private Component TryGetLookedAt()
{
for (float num = 0f; num <= 4f; num += 2f)
{
var from = Scene.Camera.WorldPosition + Scene.Camera.WorldRotation.Forward;
var to = from + Scene.Camera.WorldRotation.Forward * (InteractDistance - num);
var trace = Scene.Trace.Ray(from, to).IgnoreGameObjectHierarchy(GameObject).Radius(num).Run();
if ( Hovered is IPressable newPressable )
{
newPressable.Hover( e );
newPressable.Look( e );
}
}
TracedHitPos = trace.Hit ? trace.HitPosition : trace.EndPosition;
CameraTraceIsHit = trace.Hit;
TracedHitNormal = trace.Normal;
private Component TryGetLookedAt()
{
for ( float num = 0f; num <= 4f; num += 2f )
{
var from = Scene.Camera.WorldPosition + Scene.Camera.WorldRotation.Forward;
var to = from + Scene.Camera.WorldRotation.Forward * (InteractDistance - num);
var trace = Scene.Trace.Ray( from, to ).IgnoreGameObjectHierarchy( GameObject ).Radius( num ).Run();
if (!trace.Hit || !trace.GameObject.IsValid()) continue;
TracedHitPos = trace.Hit ? trace.HitPosition : trace.EndPosition;
CameraTraceIsHit = trace.Hit;
TracedHitNormal = trace.Normal;
Component foundComponent = null;
if ( !trace.Hit || !trace.GameObject.IsValid() ) continue;
ISceneEvent<PlayerController.IEvents>.PostToGameObject(GameObject, x =>
{
foundComponent = x.GetUsableComponent(trace.GameObject) ?? foundComponent;
});
Component foundComponent = null;
if (foundComponent.IsValid()) return foundComponent;
ISceneEvent<PlayerController.IEvents>.PostToGameObject( GameObject, x =>
{
foundComponent = x.GetUsableComponent( trace.GameObject ) ?? foundComponent;
} );
foreach (var component in trace.GameObject.Components.GetAll<IPressable>())
{
if (component.CanPress(new IPressable.Event
{
Ray = new Ray(Camera.WorldPosition, EyeAngles.ToRotation().Forward),
Source = this
}))
{
return component as Component;
}
}
}
if ( foundComponent.IsValid() ) return foundComponent;
return null;
}
foreach ( var component in trace.GameObject.Components.GetAll<IPressable>() )
{
if ( component.CanPress( new IPressable.Event
{
Ray = new Ray( Camera.WorldPosition, EyeAngles.ToRotation().Forward ), Source = this
} ) )
{
return component as Component;
}
}
}
private float GetDistanceFromGameObject(GameObject obj, Vector3 point)
{
Vector3 closest = obj.WorldPosition;
float minDist = Vector3.DistanceBetween(closest, point);
return null;
}
foreach (var col in Pressed.GetComponentsInChildren<Collider>())
{
Vector3 cp = col.FindClosestPoint(point);
float dist = Vector3.DistanceBetween(cp, point);
if (dist < minDist)
minDist = dist;
}
private float GetDistanceFromGameObject( GameObject obj, Vector3 point )
{
Vector3 closest = obj.WorldPosition;
float minDist = Vector3.DistanceBetween( closest, point );
return minDist;
}
foreach ( var col in Pressed.GetComponentsInChildren<Collider>() )
{
Vector3 cp = col.FindClosestPoint( point );
float dist = Vector3.DistanceBetween( cp, point );
if ( dist < minDist )
minDist = dist;
}
return minDist;
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;
partial class Dedugan
{
public static IReadOnlyList<Dedugan> All => InternalPlayers;
public static List<Dedugan> InternalPlayers = new List<Dedugan>();
public static Dedugan Local { get; set; }
private Guid _guid;
public static Dedugan FindLocalPlayer() => Local;
[Sync( SyncFlags.FromHost )]
public Guid ConnectionID
{
get => _guid;
set
{
_guid = value;
Connection = Connection.Find( _guid );
if ( _guid == Connection.Local.Id )
{
Local = this;
// ILocalPlayerEvent.Post( x => x.OnInitialized() );
}
InternalPlayers.RemoveAll( x => !x.IsValid() );
if ( !InternalPlayers.Contains( this ) )
InternalPlayers.Add( this );
}
}
public Connection Connection { get; private set; }
public ulong SteamID => Connection.SteamId;
public string Name => Connection.DisplayName;
public void SetupConnection( Connection connection )
{
ConnectionID = connection.Id;
GameObject.Name = $"{Name} / {SteamID}";
}
public static Dedugan GetByID( Guid id )
=> InternalPlayers.FirstOrDefault( x => x.ConnectionID == id );
}

View File

@@ -0,0 +1,51 @@
using Sandbox.Citizen;
using Sandbox.Weapons;
public sealed partial class Dedugan
{
[Property] public GameObject Gun { get; set; }
[Sync] private bool InAds { get; set; } = false;
private Weapon _weapon { get; set; }
void WeaponStart()
{
_weapon = Gun.Components.Get<Weapon>(FindMode.EverythingInSelfAndDescendants );
Log.Info( $"_weapon: {_weapon}, Network.IsOwner: {Network.IsOwner}" );
}
[Rpc.Broadcast]
void Attack()
{
Renderer.Set( "b_attack", true );
}
void WeaponUpdate()
{
if ( InAds )
{
AnimationHelper.Handedness = CitizenAnimationHelper.Hand.Right;
AnimationHelper.HoldType = CitizenAnimationHelper.HoldTypes.Pistol;
Gun.Enabled = true;
}
else
{
AnimationHelper.Handedness = CitizenAnimationHelper.Hand.Both;
AnimationHelper.HoldType = CitizenAnimationHelper.HoldTypes.None;
Gun.Enabled = false;
}
if ( !Network.IsOwner ) return;
InAds = Input.Down( "Attack2" );
if ( Input.Pressed( "Attack1" ) && InAds )
{
_weapon.Attack();
Attack();
}
}
}

View File

@@ -8,22 +8,23 @@ public sealed partial class Dedugan : Component
[RequireComponent] public ShrimpleCharacterController.ShrimpleCharacterController Controller { get; set; }
[RequireComponent] public CitizenAnimationHelper AnimationHelper { get; set; }
// [Property] public SkinnedModelRenderer Anim {get; set;}
public SkinnedModelRenderer Renderer { get; set; }
[Property] public GameObject Camera { get; set; }
[Property] public GameObject CameraPivot { get; set; }
[Property][Range(1f, 200f, 1f)] public float CamOffsetX { get; set; }
[Property][Range(50f, 1200f, 10f)] public float WalkSpeed { get; set; } = 100f;
[Property][Range(100f, 1500f, 20f)] public float RunSpeed { get; set; } = 300f;
[Property][Range(25f, 1100f, 5f)] public float DuckSpeed { get; set; } = 50f;
[Property][Range(200f, 1500f, 20f)] public float JumpStrength { get; set; } = 350f;
[Property][Range(10f, 500f, 10f)] public float InteractDistance { get; set; } = 350f;
[Property] [Range( 1f, 200f, 1f )] public float CamOffsetX { get; set; }
[Property] [Range( 50f, 1200f, 10f )] public float WalkSpeed { get; set; } = 100f;
[Property] [Range( 100f, 1500f, 20f )] public float RunSpeed { get; set; } = 300f;
[Property] [Range( 25f, 1100f, 5f )] public float DuckSpeed { get; set; } = 50f;
[Property] [Range( 200f, 1500f, 20f )] public float JumpStrength { get; set; } = 350f;
[Property] [Range( 10f, 500f, 10f )] public float InteractDistance { get; set; } = 350f;
[Sync] public Angles NetworkedEyeAngles { get; set; }
public Angles EyeAngles { get; set; }
[Sync] private float IsDucking { get; set; } = 0f;
[Sync] public bool IsDancing { get; set; } = false;
[Sync] public int Health { get; set; } = 100;
private RagdollController RagdollController { get; set; }
public Vector3 OverrideGravity { get; set; } = Vector3.Zero;
@@ -34,65 +35,79 @@ public sealed partial class Dedugan : Component
private Vector3 _right = Vector3.Right;
private Vector3 _wishDirection;
protected override void OnStart()
{
WeaponStart();
RagdollController = Components.Get<RagdollController>();
Renderer = Components.Get<SkinnedModelRenderer>(FindMode.EverythingInSelfAndDescendants);
Renderer = Components.Get<SkinnedModelRenderer>( FindMode.EverythingInSelfAndDescendants );
var cameraComponent = Camera.GetComponent<CameraComponent>();
var listener = Components.Get<AudioListener>(true);
cameraComponent.Enabled = false;
listener.Enabled = false;
if ( !Network.IsOwner ) return;
if (!Network.IsOwner) return;
cameraComponent.Enabled = true;
listener.Enabled = true;
if ( Renderer is null )
return;
Renderer.OnFootstepEvent += OnFootstepEvent;
}
protected override void OnUpdate()
{
if (Network.IsOwner)
UpdateCustomAnimations();
WeaponUpdate();
if ( Network.IsOwner )
{
EyeAngles += Input.AnalogLook;
EyeAngles = EyeAngles.WithPitch(MathX.Clamp(EyeAngles.pitch, -89f, 89f));
EyeAngles = EyeAngles.WithPitch( MathX.Clamp( EyeAngles.pitch, -89f, 89f ) );
NetworkedEyeAngles = EyeAngles;
var targetRotation = Rotation.LookAt(Rotation.FromYaw(EyeAngles.yaw).Forward, -_directionToAxis);
var targetRotation = Rotation.LookAt( Rotation.FromYaw( EyeAngles.yaw ).Forward, -_directionToAxis );
var currentForward = Renderer.LocalRotation.Forward;
float angleDiff = currentForward.Angle(targetRotation.Forward);
if (angleDiff > 15f && Controller.Velocity.Length > 10f)
float angleDiff = currentForward.Angle( targetRotation.Forward );
if ( angleDiff > 15f && Controller.Velocity.Length > 10f )
{
Renderer.LocalRotation = Rotation.Slerp(Renderer.LocalRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 3f);
Renderer.LocalRotation = Rotation.Slerp( Renderer.LocalRotation, Rotation.FromYaw( EyeAngles.yaw ),
Time.Delta * 3f );
}
RotateCamera();
InteractionsUpdate();
}
else
{
EyeAngles = NetworkedEyeAngles;
var targetRotation = Rotation.LookAt(Rotation.FromYaw(EyeAngles.yaw).Forward, -_directionToAxis);
var targetRotation = Rotation.LookAt( Rotation.FromYaw( EyeAngles.yaw ).Forward, -_directionToAxis );
var currentForward = Renderer.LocalRotation.Forward;
float angleDiff = currentForward.Angle(targetRotation.Forward);
if (angleDiff > 15f && Controller.Velocity.Length > 10f)
float angleDiff = currentForward.Angle( targetRotation.Forward );
if ( angleDiff > 15f && Controller.Velocity.Length > 10f )
{
Renderer.LocalRotation = Rotation.Slerp(Renderer.LocalRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 3f);
Renderer.LocalRotation = Rotation.Slerp( Renderer.LocalRotation, Rotation.FromYaw( EyeAngles.yaw ),
Time.Delta * 3f );
}
// Renderer.LocalRotation = Rotation.Slerp(Renderer.LocalRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 5f);
Camera.LocalRotation = EyeAngles.ToRotation();
var pivotOffset = CameraPivot.LocalRotation.Backward * CamOffsetX;
var localPitchOffset = Camera.LocalRotation.Down * MathF.Max( 0f, EyeAngles.pitch ) * 0.32f +
Camera.LocalRotation.Backward * MathF.Max( 0f, EyeAngles.pitch ) * 0.7f +
Camera.LocalRotation.Up * MathF.Min( 0f, EyeAngles.pitch ) * 0.5f +
Camera.LocalRotation.Backward * MathF.Min( 0f, EyeAngles.pitch ) * 0.8f;
var offset = (CameraPivot.LocalPosition + pivotOffset ) * EyeAngles.ToRotation() + localPitchOffset;
Camera.LocalRotation.Backward * MathF.Min( 0f, EyeAngles.pitch ) * 0.8f;
var offset = (CameraPivot.LocalPosition + pivotOffset) * EyeAngles.ToRotation() + localPitchOffset;
Camera.LocalPosition = offset;
}
UpdateCustomAnimations();
}
protected override void OnFixedUpdate()

View File

@@ -7,11 +7,19 @@ public class PlayerDresser : Component, Component.INetworkSpawn
[Property]
public SkinnedModelRenderer BodyRenderer { get; set; }
// public void OnNetworkSpawn( Connection owner )
// {
// Log.Info( $"Hello {owner.Name}" );
// var clothing = new ClothingContainer();
// clothing.Deserialize( owner.GetUserData( "avatar" ) );
// clothing.Apply( BodyRenderer );
// }
public void OnNetworkSpawn( Connection owner )
{
{
Log.Info( $"Hello {owner.Name}" );
var clothing = new ClothingContainer();
clothing.Deserialize( owner.GetUserData( "avatar" ) );
var clothing = ClothingContainer.CreateFromJson( owner.GetUserData( "avatar" ) );
clothing.Height = 1;
clothing.Apply( BodyRenderer );
}
}

View File

@@ -1,48 +1,58 @@
using Sandbox;
public sealed class RagdollController : Component
{
[Group("Setup"), Order(-100), Property] public ModelPhysics bodyPhysics { get; set; }
[Group("Setup"), Order(-100), Property] public SkinnedModelRenderer bodyRenderer { get; set; }
[Group("Config"), Order(0), Property] public bool isLocked { get; set; }
// [Property] public Collider Collider;
[Group( "Setup" ), Order( -100 ), Property]
public ModelPhysics bodyPhysics { get; private set; }
[Group( "Setup" ), Order( -100 ), Property]
public SkinnedModelRenderer bodyRenderer { get; private set; }
[Group( "Config" ), Order( 0 ), Property]
public bool isLocked { get; set; }
[Sync]
public new bool Enabled
{
get => bodyPhysics.Enabled;
private set
get => bodyPhysics.IsValid() && bodyPhysics.Enabled;
set
{
bodyPhysics.Enabled = value;
bodyPhysics.MotionEnabled = value;
bodyRenderer.UseAnimGraph = !value;
if ( bodyPhysics.IsValid() )
{
bodyPhysics.Enabled = value;
bodyPhysics.MotionEnabled = value;
bodyRenderer.UseAnimGraph = !value;
}
// Collider.Enabled = !value;
if ( !value )
{
WorldPosition = bodyRenderer.WorldPosition;
bodyRenderer.LocalPosition = Vector3.Zero;
bodyRenderer.ClearParameters();
bodyRenderer.ClearPhysicsBones();
}
}
}
// protected override void OnStart()
// {
// Collider = GetComponent<Collider>();
//
// Log.Info(Collider.Enabled);
// }
protected override void OnUpdate()
{
if ( Network.IsOwner )
{
if (Input.Pressed( "Ragdoll" ))
if ( Input.Pressed( "Ragdoll" ) )
{
Enabled = !Enabled;
}
if ( Enabled )
{
// Components.GetInChildren<SkinnedModelRenderer>().GameObject.WorldPosition += Vector3.Forward;
bodyPhysics.WorldPosition += Vector3.Forward * Time.Delta * 100f;
// GameObject.WorldPosition += Vector3.Forward;
}
}
var bodyLock = new PhysicsLock();
bodyLock.Pitch = isLocked;
bodyLock.Yaw = isLocked;
@@ -50,7 +60,7 @@ public sealed class RagdollController : Component
bodyLock.X = isLocked;
bodyLock.Y = isLocked;
bodyLock.Z = isLocked;
bodyPhysics.Locking = bodyLock;
bodyPhysics.MotionEnabled = !isLocked;
WorldPosition = bodyRenderer.WorldPosition;

View File

@@ -9,8 +9,8 @@ public sealed class DSPReverb : Component, Component.ITriggerListener
{
[Property] public MixerHandle TargetMixer { get; set; }
[Property] public DspPresetHandle Preset { get; set; }
[Property] [Range(0f, 10f, 0.1f)] public float FadeDuration { get; set; } = 1f;
[Property] public BBox Bounds { get; set; } = new BBox(Vector3.One * -100f, Vector3.One * 100f);
[Property] [Range( 0f, 10f, 0.1f )] public float FadeDuration { get; set; } = 1f;
[Property] public BBox Bounds { get; set; } = new BBox( Vector3.One * -100f, Vector3.One * 100f );
private DspProcessor _processor;
private BoxCollider _triggerCollider;
@@ -28,63 +28,79 @@ public sealed class DSPReverb : Component, Component.ITriggerListener
_triggerCollider.Center = Bounds.Center;
}
public void OnTriggerEnter(Collider other)
public void OnTriggerEnter( Collider other )
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
if(_processor != null) { TargetMixer.Get().RemoveProcessor(_processor);}
_processor = new DspProcessor(Preset.Name);
_processor.Mix = 0f;
TargetMixer.Get().AddProcessor(_processor);
_ = UpdateMixAsync(1f);
if ( other.Components.TryGet<Dedugan>( out Dedugan dedugan ) )
{
if ( dedugan.Connection == Dedugan.Local.Connection )
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
if ( _processor != null ) { TargetMixer.Get().RemoveProcessor( _processor ); }
_processor = new DspProcessor( Preset.Name );
_processor.Mix = 0f;
TargetMixer.Get().AddProcessor( _processor );
_processor.Mix = 1f;
// _ = UpdateMixAsync(1f);
}
}
}
private async Task UpdateMixAsync(float targetMix)
private async Task UpdateMixAsync( float targetMix )
{
float startMix = _processor.Mix;
float elapsed = FadeDuration * ((targetMix == 0f || startMix == 0f) ? 0f : Math.Min(startMix / targetMix, 1f));
float elapsed = FadeDuration *
((targetMix == 0f || startMix == 0f) ? 0f : Math.Min( startMix / targetMix, 1f ));
float lastTime = Time.Now;
while (elapsed < FadeDuration && !_cts.IsCancellationRequested)
while ( elapsed < FadeDuration && !_cts.IsCancellationRequested )
{
await Task.FixedUpdate();
float delta = Time.Now - lastTime;
elapsed += delta;
float t = Math.Clamp(elapsed / FadeDuration, 0f, 1f);
_processor.Mix = Math.Clamp(startMix + (targetMix - startMix) * t, 0f, 1f);
float t = Math.Clamp( elapsed / FadeDuration, 0f, 1f );
_processor.Mix = Math.Clamp( startMix + (targetMix - startMix) * t, 0f, 1f );
lastTime = Time.Now;
}
if (!_cts.IsCancellationRequested)
if ( !_cts.IsCancellationRequested )
{
_processor.Mix = targetMix;
}
}
public void OnTriggerExit(Collider other)
public void OnTriggerExit( Collider other )
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
_ = UpdateMixAsync(0f).ContinueWith( (_) =>
if ( other.Components.TryGet<Dedugan>( out Dedugan dedugan ) )
{
if (_processor == null) return;
TargetMixer.Get().RemoveProcessor(_processor);
_processor = null;
} );
if ( dedugan.Connection == Dedugan.Local.Connection )
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
_processor.Mix = 0f;
}
}
// _ = UpdateMixAsync(0f).ContinueWith( (_) =>
// {
// if (_processor == null) return;
//
// TargetMixer.Get().RemoveProcessor(_processor);
// _processor = null;
// } );
}
protected override void DrawGizmos()
{
base.DrawGizmos();
Gizmo.Draw.Color = Color.Green;
Gizmo.Draw.LineBBox(Bounds);
Gizmo.Draw.LineBBox( Bounds );
}
}

13
Code/UI/ChatHistory.cs Normal file
View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Sandbox;
public static class ChatHistory
{
public static List<Chat.Entry> Entries { get; private set; } = new();
public static void Add(ulong steamid, string author, string message)
{
Entries.Add(new Chat.Entry(steamid, author, message, 0.0f));
}
}

View File

@@ -0,0 +1,55 @@
using Sandbox.Gravity;
namespace Sandbox.UI;
[Icon( "skip_next" )]
public sealed class TeleportMazeButton : InteractionButton
{
[Property] public Maze Maze { get; set; }
[Property] public InteractTeleporter Teleporter { get; set; }
int maxAttempts = 30;
public override bool Press( IPressable.Event e )
{
base.Press( e );
if ( Maze.IsValid() )
{
Maze.RpcRequestMaze();
}
DoTeleport();
return true;
}
private async void DoTeleport()
{
int attempt = 0;
if ( Maze.IsValid() )
{
while ( !Maze.IsReady && attempt < maxAttempts )
{
await Task.Delay( 1000 );
attempt++;
}
if ( Maze.IsReady )
{
// Teleporter.TeleportAll();
foreach ( var player in Teleporter.Players )
{
Teleporter.Teleport( player, Maze.GetRandomCellPosition() );
}
}
else
{
Log.Warning( "Maze was not ready in time. Teleport aborted." );
}
}
else
{
Teleporter.TeleportAll();
}
}
}

103
Code/Weapons/Weapon.cs Normal file
View File

@@ -0,0 +1,103 @@
using System.Threading.Tasks;
namespace Sandbox.Weapons;
public sealed class Weapon : Component
{
[Property] public SkinnedModelRenderer GunRenderer { get; private set; }
[Property] public GameObject BulletOut { get; private set; }
[Property] public GameObject MuzzleLight { get; private set; }
[Property] public GameObject particlePrefab { get; set; }
[Property] public GameObject bloodParticle { get; set; }
[Property] public DecalDefinition ImpactDecal { get; set; }
[Property] public SoundEvent ImpactSound { get; set; }
private SoundPointComponent _sound;
protected override void OnStart()
{
_sound = GameObject.GetComponent<SoundPointComponent>( true );
}
public void Attack()
{
AttackEffects();
Vector3 startPos = Scene.Camera.WorldPosition;
Vector3 dir = Scene.Camera.WorldRotation.Forward;
float maxDistance = 1000f;
var tr = Scene.Trace
.Ray( startPos, startPos + dir * maxDistance )
.IgnoreGameObjectHierarchy( Dedugan.Local.GameObject )
.WithoutTags( "weapon" )
.UseHitboxes()
.Run();
Log.Info( Dedugan.Local.GameObject );
if (tr.Hit && tr.Hitbox != null)
{
var components = tr.GameObject.Components;
var boneIndex = tr.Hitbox.Bone.Index;
// Log.Info($"{tr.GameObject.Name} attacked");
var dedugan = components.Get<Dedugan>();
var enemy = components.Get<Enemy>();
if (dedugan.IsValid() || enemy.IsValid())
{
CreateHitEffects(tr.EndPosition, tr.Normal, true);
}
if (dedugan.IsValid())
{
dedugan.ReportHit(dir, boneIndex);
}
if (enemy.IsValid())
{
enemy.ReportHit(dir, boneIndex);
Log.Info(boneIndex);
}
}
else if ( tr.Hitbox == null )
{
CreateHitEffects( tr.EndPosition, tr.Normal );
}
}
[Rpc.Broadcast]
private void CreateHitEffects( Vector3 position, Vector3 normal, bool blood = false )
{
var rot = Rotation.LookAt( normal );
DestroyAsync(
blood
? bloodParticle.Clone( position, rot )
: particlePrefab.Clone( position, rot ), 0.5f );
}
async void DestroyAsync( GameObject go, float delay )
{
await GameTask.DelaySeconds( delay );
go.Destroy();
}
[Rpc.Broadcast]
public void AttackEffects()
{
_sound?.StartSound();
MuzzleLight.Enabled = true;
GunRenderer.Set( "Fire", true );
_ = AttackEffectsAsync();
}
private async Task AttackEffectsAsync()
{
await GameTask.DelaySeconds( 0.05f );
MuzzleLight.Enabled = false;
}
}