diff --git a/.sbproj b/.sbproj index b732cf4..f6de3ac 100644 --- a/.sbproj +++ b/.sbproj @@ -33,7 +33,7 @@ "Name": "My New Config", "GameIdent": "local.are_you___lucker#local", "MapName": "voximity.flat_plane", - "MaxPlayers": 1, + "MaxPlayers": 4, "GameSettings": {}, "Addons": "", "PreLaunchCommand": "", diff --git a/code/Entities/Pawn.cs b/code/Entities/Pawn.cs index c835b48..b96efd7 100644 --- a/code/Entities/Pawn.cs +++ b/code/Entities/Pawn.cs @@ -58,6 +58,7 @@ public partial class Pawn : AnimatedEntity [BindComponent] public UserPawnController Controller { get; } [BindComponent] public PawnAnimator Animator { get; } + [BindComponent] public PawnInventory Inventory { get; } public override Ray AimRay => new Ray( EyePosition, EyeRotation.Forward ); @@ -71,12 +72,7 @@ public partial class Pawn : AnimatedEntity EnableDrawing = true; EnableHideInFirstPerson = true; EnableShadowInFirstPerson = true; - } - - public void Respawn() - { - Components.Create(); - Components.Create(); + SetupPhysicsFromModel( PhysicsMotionType.Keyframed ); } public void DressFromClient( IClient cl ) @@ -91,6 +87,7 @@ public partial class Pawn : AnimatedEntity SimulateRotation(); Controller?.Simulate( cl ); Animator?.Simulate(); + Inventory?.ActiveWeapon?.Simulate( cl ); } public override void BuildInput() @@ -130,4 +127,15 @@ public partial class Pawn : AnimatedEntity EyeRotation = Rotation.Slerp( Rotation, idealRotation, Time.Delta * 10f ); Rotation = EyeRotation; } + + public void LookAt( Vector3 position ) + { + Rotation = Rotation.LookAt( (position - this.Position).Normal, Vector3.Up ); + EyePosition = position; + } + + public override void TakeDamage( DamageInfo info ) + { + base.TakeDamage( info ); + } } diff --git a/code/Entities/RoundManager.cs b/code/Entities/RoundManager.cs index ae7941a..6bcae21 100644 --- a/code/Entities/RoundManager.cs +++ b/code/Entities/RoundManager.cs @@ -26,7 +26,7 @@ public partial class RoundManager : Entity /// /// The number of seconds from the timer starting before the round starts /// - private const float RoundStartCountdownSeconds = 10f; + private const float RoundStartCountdownSeconds = 5f; /// /// The state of the current round diff --git a/code/Entities/Weapons/Weapon.cs b/code/Entities/Weapons/Weapon.cs index c1f6038..95ec514 100644 --- a/code/Entities/Weapons/Weapon.cs +++ b/code/Entities/Weapons/Weapon.cs @@ -1,3 +1,4 @@ +using System; using Sandbox; using System.Collections.Generic; @@ -26,6 +27,9 @@ public partial class Weapon : AnimatedEntity public virtual string ReloadAnimPath => "reload"; public virtual string WeaponName => "weapon"; public virtual float ReloadDuration => 4f; + public virtual CitizenAnimationHelper.HoldTypes HoldType { get; } + protected virtual List HitTags => new List { "solid", "player", "npc" }; + protected virtual float Damage => 20f; private bool Reloading => TimeSinceReloadStarted < ReloadDuration; /// @@ -68,6 +72,7 @@ public partial class Weapon : AnimatedEntity SetParent( pawn, true ); EnableDrawing = true; CreateViewModel( To.Single( pawn ) ); + pawn.SetAnimParameter( "holdtype", (int)HoldType ); } /// @@ -77,6 +82,7 @@ public partial class Weapon : AnimatedEntity { EnableDrawing = false; DestroyViewModel( To.Single( Owner ) ); + Pawn.SetAnimParameter( "holdtype", (int)CitizenAnimationHelper.HoldTypes.None ); } /// @@ -128,7 +134,7 @@ public partial class Weapon : AnimatedEntity /// public virtual bool CanPrimaryAttack() { - if ( !Owner.IsValid() || !Input.Down( "attack1" ) || Ammo == 0 || Reloading ) return false; + if ( !Owner.IsValid() || !Input.Down( "attack1" ) || (Ammo == 0 && MaxAmmo != 0) || Reloading ) return false; var rate = PrimaryRate; if ( rate <= 0 ) return true; @@ -138,7 +144,7 @@ public partial class Weapon : AnimatedEntity private void ReduceAmmoAndPrimaryAttack() { - Ammo--; + Ammo = Math.Max(0, Ammo -1); PrimaryAttack(); } @@ -166,7 +172,7 @@ public partial class Weapon : AnimatedEntity var trace = Trace.Ray( start, end ) .UseHitboxes() - .WithAnyTags( "solid", "player", "npc" ) + .WithAnyTags( HitTags.ToArray() ) .Ignore( this ) .Size( radius ); diff --git a/code/EntityComponents/Pawn/PawnInventory.cs b/code/EntityComponents/Pawn/PawnInventory.cs new file mode 100644 index 0000000..f37e224 --- /dev/null +++ b/code/EntityComponents/Pawn/PawnInventory.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Linq; +using LuckerGame.Entities.Weapons; +using Sandbox; + +namespace LuckerGame.Components.Pawn; + +public partial class PawnInventory : EntityComponent +{ + [Net] private List Weapons { get; set; } = new List(); + [Net, Predicted] public Weapon ActiveWeapon { get; private set; } + + public List GetWeapons() + { + return Weapons.ToList(); + } + + public bool AddWeapon( Weapon weapon ) + { + if ( Weapons.Any( w => w.GetType() == weapon.GetType() ) ) + { + return false; + } + + Weapons.Add( weapon ); + if ( Weapons.Count == 1 ) + { + SetActiveWeapon( weapon ); + } + + return true; + } + + public void NextWeapon() + { + if ( ActiveWeapon == null ) + { + ActiveWeapon = Weapons.FirstOrDefault(); + return; + } + + var weaponIndex = Weapons.IndexOf( ActiveWeapon ); + var nextIndex = (weaponIndex + 1) % Weapons.Count; + var weapon = Weapons[nextIndex]; + SetActiveWeapon( weapon ); + } + + public void SetActiveWeapon( Weapon weapon ) + { + ActiveWeapon?.OnHolster(); + ActiveWeapon = weapon; + ActiveWeapon.OnEquip( Entity ); + } +} diff --git a/code/Minigames/RussianRoulette/RussianPistol.cs b/code/Minigames/RussianRoulette/RussianPistol.cs new file mode 100644 index 0000000..0b314f2 --- /dev/null +++ b/code/Minigames/RussianRoulette/RussianPistol.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using LuckerGame.Entities.Weapons; +using Sandbox; + +namespace LuckerGame.Minigames.RussianRoulette; + +public partial class RussianPistol : Weapon +{ + public override string ModelPath => "weapons/rust_pistol/rust_pistol.vmdl"; + public override string ViewModelPath => "weapons/rust_pistol/v_rust_pistol.vmdl"; + + public override string WeaponName => "Russian Pistol"; + + protected override List HitTags => new List { "victim" }; + + public override CitizenAnimationHelper.HoldTypes HoldType => CitizenAnimationHelper.HoldTypes.Pistol; + + public override int MaxAmmo => 6; + + protected override float Damage => 1000f; + + [ClientRpc] + protected virtual void ShootEffects() + { + Game.AssertClient(); + + Particles.Create( "particles/pistol_muzzleflash.vpcf", EffectEntity, "muzzle" ); + + Pawn.SetAnimParameter( "b_attack", true ); + ViewModelEntity?.SetAnimParameter( "fire", true ); + } + + public override void PrimaryAttack() + { + if ( Random.Shared.Next( 1, Ammo + 1 ) == 1) + { + ShootEffects(); + Pawn.PlaySound( "rust_pistol.shoot" ); + ShootBullet( 0.01f, 100, Damage, 10 ); + } + else + { + Pawn.PlaySound( "denyundo" ); + } + Ammo--; + } + + protected override void Animate() + { + Pawn.SetAnimParameter( "holdtype", (int)CitizenAnimationHelper.HoldTypes.Pistol ); + } +} diff --git a/code/Minigames/RussianRoulette/RussianRouletteMinigame.cs b/code/Minigames/RussianRoulette/RussianRouletteMinigame.cs index 7633166..55ab89f 100644 --- a/code/Minigames/RussianRoulette/RussianRouletteMinigame.cs +++ b/code/Minigames/RussianRoulette/RussianRouletteMinigame.cs @@ -1,31 +1,38 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using LuckerGame.Components.Lucker.Cameras; +using LuckerGame.Components.Pawn; using LuckerGame.Entities; using Sandbox; +using Sandbox.UI; namespace LuckerGame.Minigames.RussianRoulette; +[Library("mg_russian_roulette")] public class RussianRouletteMinigame : Minigame { public override string Name => "Russian Roulette"; private List Players { get; set; } private Pawn Shooter { get; set; } - private const float ShooterDistance = 50f; - private const int CardinalDirections = 4; + private const float ShooterDistance = 80f; + private const float TimeBetweenShots = 7f; + private int Taunted = 0; + + private List DeadVictims => Players + .Select( player => player.Pawn as Pawn ) + .Where( pawn => !pawn.IsValid || pawn.LifeState != LifeState.Alive ) + .ToList(); + + private TimeSince TimeSinceShot { get; set; } public override void Initialize( List players ) { Players = players; Shooter = new Pawn(); - - /*// Spawn shooter at a random spawnpoint - var spawnpoints = Entity.All.OfType(); - var randomSpawnPoint = spawnpoints.OrderBy( x => Guid.NewGuid() ).FirstOrDefault(); - var tx = randomSpawnPoint.Transform; - tx.Position = tx.Position + Vector3.Up * 50.0f; // raise it up - Shooter.Position = tx.Position;*/ + var shooterInventory = Shooter.Components.Create(); + shooterInventory.AddWeapon( new RussianPistol() ); // Setup cameras for players Players.ForEach( player => @@ -39,18 +46,55 @@ public class RussianRouletteMinigame : Minigame var player = pair.Player; var index = pair.Index; var pawn = new Pawn(); + pawn.Name = player.Name; + pawn.Tags.Add( "victim" ); + pawn.Health = 1; player.Pawn = pawn; pawn.DressFromClient( player.Client ); var pawnOffset = ShooterDistance * (index % 2 == 0 ? Vector3.Forward : Vector3.Right) * (index % 4 >= 2 ? -1 : 1); player.Pawn.Position = Shooter.Position + pawnOffset; + pawn.LookAt(Shooter.Position); } ); + TimeSinceShot = 0; } public override void Tick() { - return; + if ( DeadVictims.Any() ) + { + if ( Taunted != int.MaxValue ) + { + ChatBox.AddChatEntry( To.Everyone, "Shooter", "Heh, nothing personnel, kid." ); + Taunted = int.MaxValue; + } + return; + } + if ( TimeSinceShot > TimeBetweenShots ) + { + TimeSinceShot = 0; + Taunted = 0; + Shooter.Inventory.ActiveWeapon.PrimaryAttack(); + if ( !DeadVictims.Any() ) + { + ChatBox.AddChatEntry( To.Everyone, "Shooter", "Fucking lag..." ); + } + } + else if ( TimeSinceShot > TimeBetweenShots * .8f && Taunted == 1) + { + var victim = Players.Select( player => player.Pawn as Pawn ) + .OrderBy( _ => Guid.NewGuid() ) + .FirstOrDefault(); + Shooter.LookAt( victim.Position ); + ChatBox.AddChatEntry( To.Everyone, "Shooter", $"I'm gonna eat you up, {victim.Name}" ); + Taunted++; + } + else if ( TimeSinceShot > TimeBetweenShots / 2 && Taunted == 0) + { + ChatBox.AddChatEntry( To.Everyone, "Shooter", "Im gettin' ready!" ); + Taunted++; + } } public override void Cleanup() diff --git a/code/UI/Hud.razor b/code/UI/Hud.razor index 75e06e5..deb2cb5 100644 --- a/code/UI/Hud.razor +++ b/code/UI/Hud.razor @@ -13,7 +13,6 @@ - @code