Compare commits
5 Commits
legacy
...
bbf0a765d5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbf0a765d5 | ||
|
|
bce1f8e1f7 | ||
|
|
3e9d64cb00 | ||
|
|
b9dbe07e1f | ||
|
|
4a338d9502 |
15
.sbproj
15
.sbproj
@@ -37,20 +37,7 @@
|
|||||||
"GameSettings": {},
|
"GameSettings": {},
|
||||||
"Addons": "",
|
"Addons": "",
|
||||||
"PreLaunchCommand": "",
|
"PreLaunchCommand": "",
|
||||||
"PostLaunchCommand": "lucker_minigames_per_round 1"
|
"PostLaunchCommand": ""
|
||||||
}
|
|
||||||
],
|
|
||||||
"PackageSettings": [
|
|
||||||
{
|
|
||||||
"DisplayType": "Integer",
|
|
||||||
"Choices": [],
|
|
||||||
"ConVarName": "lucker_minigames_per_round",
|
|
||||||
"DisplayName": "Minigames Per Round",
|
|
||||||
"DefaultValue": "1",
|
|
||||||
"Description": "The number of minigames played per round",
|
|
||||||
"Group": "Other",
|
|
||||||
"Minimum": 1,
|
|
||||||
"Maximum": 12
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,22 @@
|
|||||||
using LuckerGame.Components.Lucker.Cameras;
|
using LuckerGame.Components.Lucker.Cameras;
|
||||||
using LuckerGame.EntityComponents.Lucker;
|
|
||||||
using LuckerGame.Events;
|
using LuckerGame.Events;
|
||||||
using Sandbox;
|
using Sandbox;
|
||||||
|
|
||||||
namespace LuckerGame.Entities;
|
namespace LuckerGame.Entities;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a person playing the game.
|
/// Represents a Player.
|
||||||
/// This could belong to a Client or a Bot and represents a common entity to operate on for games and keeping score
|
/// This could belong to a Client or a Bot and represents a common entity to operate on for games and keeping score
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class Lucker : Entity
|
public partial class Lucker : Entity
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity this lucker controls. This value is networked and should be accessed through <see cref="Pawn"/>.
|
/// The entity this Player currently controls
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Net] private Entity InternalPawn { get; set; }
|
public Entity Pawn { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Accesses or sets the entity this lucker currently controls
|
/// Before the round has started, this player indicated they were ready
|
||||||
/// </summary>
|
|
||||||
public Entity Pawn
|
|
||||||
{
|
|
||||||
get => InternalPawn;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
InternalPawn = value;
|
|
||||||
if ( value != null )
|
|
||||||
{
|
|
||||||
value.Owner = this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Before the round has started, this lucker indicated they were ready
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Net] public bool Ready { get; set; }
|
[Net] public bool Ready { get; set; }
|
||||||
|
|
||||||
@@ -42,23 +25,20 @@ public partial class Lucker : Entity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[BindComponent] public AbstractCamera Camera { get; }
|
[BindComponent] public AbstractCamera Camera { get; }
|
||||||
|
|
||||||
[BindComponent] public LuckerStats Stats { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates and properly sets up a <see cref="Lucker"/> entity for a given client
|
/// Creates and properly sets up a Player entity for a given client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client">the client to own the lucker</param>
|
/// <param name="client">the client to own the player</param>
|
||||||
/// <returns>the newly created lucker</returns>
|
/// <returns>the newly created player</returns>
|
||||||
public static Lucker CreateLuckerForClient( IClient client )
|
public static Lucker CreateLuckerForClient( IClient client )
|
||||||
{
|
{
|
||||||
var lucker = new Lucker();
|
var player = new Lucker();
|
||||||
client.Pawn = lucker;
|
client.Pawn = player;
|
||||||
lucker.Owner = client as Entity;
|
player.Owner = client as Entity;
|
||||||
lucker.Name = client.Name;
|
player.Name = client.Name;
|
||||||
lucker.Components.Create<RTSCamera>();
|
var camera = player.Components.Create<RTSCamera>();
|
||||||
lucker.Components.Create<LuckerStats>();
|
|
||||||
|
|
||||||
return lucker;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -69,12 +49,12 @@ public partial class Lucker : Entity
|
|||||||
public static void ReadyUpCommand(bool readyState)
|
public static void ReadyUpCommand(bool readyState)
|
||||||
{
|
{
|
||||||
var client = ConsoleSystem.Caller;
|
var client = ConsoleSystem.Caller;
|
||||||
var lucker = client.Pawn as Lucker;
|
var player = client.Pawn as Lucker;
|
||||||
lucker.SetReady( readyState );
|
player.SetReady( readyState );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets this lucker's ready state
|
/// Sets this player's ready state
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ready">the ready state being set</param>
|
/// <param name="ready">the ready state being set</param>
|
||||||
public void SetReady(bool ready)
|
public void SetReady(bool ready)
|
||||||
@@ -82,7 +62,7 @@ public partial class Lucker : Entity
|
|||||||
Ready = ready;
|
Ready = ready;
|
||||||
if ( Game.IsServer )
|
if ( Game.IsServer )
|
||||||
{
|
{
|
||||||
Event.Run( LuckerEvent.LuckerReady, this, ready );
|
Event.Run( LuckerEvent.PlayerReady, this, ready );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,20 +12,8 @@ namespace LuckerGame.Entities;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class MinigameManager : Entity
|
public partial class MinigameManager : Entity
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The currently loaded minigame
|
|
||||||
/// </summary>
|
|
||||||
[Net] public Minigame LoadedMinigame { get; private set; }
|
[Net] public Minigame LoadedMinigame { get; private set; }
|
||||||
|
private List<Minigame> AvailableMinigames { get; set; }
|
||||||
/// <summary>
|
|
||||||
/// A cached list of available minigames. Gets reloaded on a hotreload
|
|
||||||
/// </summary>
|
|
||||||
private List<TypeDescription> AvailableMinigames { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The luckers involved in the current minigame
|
|
||||||
/// </summary>
|
|
||||||
private List<Lucker> InvolvedLuckers { get; set; }
|
|
||||||
|
|
||||||
public override void Spawn()
|
public override void Spawn()
|
||||||
{
|
{
|
||||||
@@ -33,17 +21,13 @@ public partial class MinigameManager : Entity
|
|||||||
FindMinigames();
|
FindMinigames();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartMinigame(List<Lucker> luckers, string minigameName = null)
|
public void StartMinigame(List<Lucker> players, string minigameName = null)
|
||||||
{
|
{
|
||||||
InvolvedLuckers = luckers.ToList();
|
|
||||||
if (CheckForMinigames())
|
if (CheckForMinigames())
|
||||||
{
|
{
|
||||||
LoadedMinigame = string.IsNullOrEmpty( minigameName )
|
LoadedMinigame = string.IsNullOrEmpty( minigameName ) ? AvailableMinigames.OrderBy( _ => Guid.NewGuid() ).FirstOrDefault() : TypeLibrary.Create<Minigame>( minigameName );
|
||||||
? TypeLibrary.Create<Minigame>( AvailableMinigames.OrderBy( _ => Guid.NewGuid() ).FirstOrDefault()
|
|
||||||
.TargetType )
|
|
||||||
: TypeLibrary.Create<Minigame>( minigameName );
|
|
||||||
ChatBox.AddInformation( To.Everyone, $"Starting {LoadedMinigame.Name}" );
|
ChatBox.AddInformation( To.Everyone, $"Starting {LoadedMinigame.Name}" );
|
||||||
LoadedMinigame.Initialize( luckers );
|
LoadedMinigame.Initialize( players );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +46,7 @@ public partial class MinigameManager : Entity
|
|||||||
{
|
{
|
||||||
AvailableMinigames = TypeLibrary.GetTypes<Minigame>()
|
AvailableMinigames = TypeLibrary.GetTypes<Minigame>()
|
||||||
.Where( type => !type.IsAbstract && !type.IsInterface )
|
.Where( type => !type.IsAbstract && !type.IsInterface )
|
||||||
.ToList();
|
.Select( td => TypeLibrary.Create<Minigame>( td.TargetType ) ).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Event.Hotload]
|
[Event.Hotload]
|
||||||
@@ -71,48 +55,12 @@ public partial class MinigameManager : Entity
|
|||||||
FindMinigames();
|
FindMinigames();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void Tick()
|
||||||
/// Goes through the luckers included in the loaded minigame and deletes and nulls out any pawns assigned to them
|
|
||||||
/// </summary>
|
|
||||||
private void CleanupLuckerPawns()
|
|
||||||
{
|
|
||||||
if ( LoadedMinigame is not { IsValid: true } || InvolvedLuckers == null)
|
|
||||||
{
|
|
||||||
Log.Warning( "Attempted to clean up players without a minigame loaded!" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
InvolvedLuckers.ForEach( lucker =>
|
|
||||||
{
|
|
||||||
lucker.Pawn?.Delete();
|
|
||||||
lucker.Pawn = null;
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called once per tick by the RoundManager. Ticks any running minigame.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>true if the current minigame has ended, else false</returns>
|
|
||||||
public bool Tick()
|
|
||||||
{
|
{
|
||||||
if ( LoadedMinigame is not { IsValid: true } )
|
if ( LoadedMinigame is not { IsValid: true } )
|
||||||
{
|
{
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
var ended = LoadedMinigame.Tick();
|
LoadedMinigame.Tick();
|
||||||
if ( !ended )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
EndMinigame();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EndMinigame()
|
|
||||||
{
|
|
||||||
LoadedMinigame.Cleanup();
|
|
||||||
CleanupLuckerPawns();
|
|
||||||
LoadedMinigame.Delete();
|
|
||||||
LoadedMinigame = null;
|
|
||||||
InvolvedLuckers = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,21 +47,11 @@ public partial class RoundManager : Entity
|
|||||||
|
|
||||||
#region In Progress State
|
#region In Progress State
|
||||||
|
|
||||||
/// <summary>
|
private const int MinigamesPerRound = 1;
|
||||||
/// The number of minigames that should be played per round, settable via a convar
|
|
||||||
/// </summary>
|
|
||||||
[ConVar.Replicated("lucker_minigames_per_round")]
|
|
||||||
private static int MinigamesPerRound { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
private int MinigamesLeftInRound { get; set; }
|
||||||
/// The number of minigames left in the current round
|
|
||||||
/// </summary>
|
|
||||||
public int MinigamesLeftInRound { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
private List<Lucker> Players { get; set; }
|
||||||
/// The luckers playing in the current round
|
|
||||||
/// </summary>
|
|
||||||
private List<Lucker> Luckers { get; set; }
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -86,29 +76,16 @@ public partial class RoundManager : Entity
|
|||||||
|
|
||||||
if ( RoundState == RoundState.InProgress )
|
if ( RoundState == RoundState.InProgress )
|
||||||
{
|
{
|
||||||
var ended = MinigameManager.Tick();
|
MinigameManager.Tick();
|
||||||
if ( ended )
|
|
||||||
{
|
|
||||||
MinigamesLeftInRound--;
|
|
||||||
if ( MinigamesLeftInRound > 0 )
|
|
||||||
{
|
|
||||||
MinigameManager.StartMinigame( Luckers );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RoundState = RoundState.NotStarted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is triggered whenever a lucker readies up or readies down
|
/// Is triggered whenever a player readies up
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="readyLucker">the lucker that readied up</param>
|
/// <param name="readyLucker">the player that readied up, discarded</param>
|
||||||
/// <param name="ready">the lucker's ready state</param>
|
[LuckerEvent.PlayerReady]
|
||||||
[LuckerEvent.LuckerReady]
|
public void HandlePlayerReady( Lucker readyLucker, bool ready )
|
||||||
public void HandleLuckerReady( Lucker readyLucker, bool ready )
|
|
||||||
{
|
{
|
||||||
if ( RoundState != RoundState.NotStarted && RoundState != RoundState.StartCountdown )
|
if ( RoundState != RoundState.NotStarted && RoundState != RoundState.StartCountdown )
|
||||||
{
|
{
|
||||||
@@ -117,9 +94,9 @@ public partial class RoundManager : Entity
|
|||||||
Log.Info( $"{readyLucker.Client.Name} set ready to {ready}" );
|
Log.Info( $"{readyLucker.Client.Name} set ready to {ready}" );
|
||||||
var message = $"{readyLucker.Client.Name} is {(ready ? "now ready." : "no longer ready.")}";
|
var message = $"{readyLucker.Client.Name} is {(ready ? "now ready." : "no longer ready.")}";
|
||||||
ChatBox.AddInformation( To.Everyone, message );
|
ChatBox.AddInformation( To.Everyone, message );
|
||||||
var luckers = All.OfType<Lucker>().ToList();
|
var players = All.OfType<Lucker>().ToList();
|
||||||
var readiedCount = luckers.Count( lucker => lucker.Ready );
|
var readiedCount = players.Count( player => player.Ready );
|
||||||
var totalCount = luckers.Count;
|
var totalCount = players.Count;
|
||||||
if ( (float)readiedCount / totalCount > RequiredReadyPercent && RoundState == RoundState.NotStarted )
|
if ( (float)readiedCount / totalCount > RequiredReadyPercent && RoundState == RoundState.NotStarted )
|
||||||
{
|
{
|
||||||
Log.Info( "Countdown started" );
|
Log.Info( "Countdown started" );
|
||||||
@@ -142,13 +119,8 @@ public partial class RoundManager : Entity
|
|||||||
}
|
}
|
||||||
|
|
||||||
RoundState = RoundState.InProgress;
|
RoundState = RoundState.InProgress;
|
||||||
Luckers = All.OfType<Lucker>().ToList();
|
Players = All.OfType<Lucker>().ToList();
|
||||||
Luckers.ForEach( lucker =>
|
MinigameManager.StartMinigame( Players, minigameName );
|
||||||
{
|
|
||||||
lucker.Ready = false;
|
|
||||||
} );
|
|
||||||
MinigamesLeftInRound = MinigamesPerRound;
|
|
||||||
MinigameManager.StartMinigame( Luckers, minigameName );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConCmd.Server( "start_round" )]
|
[ConCmd.Server( "start_round" )]
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public partial class Weapon : AnimatedEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the weapon is either removed from the pawn, or holstered.
|
/// Called when the weapon is either removed from the player, or holstered.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void OnHolster()
|
public void OnHolster()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ using Sandbox;
|
|||||||
|
|
||||||
namespace LuckerGame.Components.Lucker.Cameras;
|
namespace LuckerGame.Components.Lucker.Cameras;
|
||||||
|
|
||||||
public abstract class AbstractCamera : EntityComponent<Entities.Lucker>, ISingletonComponent
|
public abstract partial class AbstractCamera : EntityComponent<Entities.Lucker>, ISingletonComponent
|
||||||
{
|
{
|
||||||
public virtual bool ShouldShowCursor => false;
|
public virtual bool ShouldShowCursor => false;
|
||||||
protected Vector3 CameraPosition { get; set; }
|
public Vector3 CameraPosition { get; set; }
|
||||||
protected Rotation CameraRotation { get; set; }
|
protected Rotation CameraRotation { get; set; }
|
||||||
protected float FieldOfView { get; set; }
|
protected float FieldOfView { get; set; }
|
||||||
protected IEntity FirstPersonViewer { get; set; }
|
protected IEntity FirstPersonViewer { get; set; }
|
||||||
@@ -20,7 +20,7 @@ public abstract class AbstractCamera : EntityComponent<Entities.Lucker>, ISingle
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles any input dependent camera updates (ie moving around a top down cam)
|
/// Handles any input dependent camera updates (ie moving around a top down cam)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void BuildInput();
|
public virtual void BuildInput() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies Camera parameters to the static Camera
|
/// Applies Camera parameters to the static Camera
|
||||||
|
|||||||
41
code/EntityComponents/Lucker/Cameras/FixedCamera.cs
Normal file
41
code/EntityComponents/Lucker/Cameras/FixedCamera.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using Sandbox;
|
||||||
|
|
||||||
|
namespace LuckerGame.Components.Lucker.Cameras;
|
||||||
|
|
||||||
|
public partial class FixedCamera : AbstractCamera, ISingletonComponent
|
||||||
|
{
|
||||||
|
[Net] public float FieldOfViewValue { get; set; } = 70f;
|
||||||
|
public override bool ShouldShowCursor => true;
|
||||||
|
protected override void UpdateCameraParameters()
|
||||||
|
{
|
||||||
|
FieldOfView = FieldOfViewValue;
|
||||||
|
FirstPersonViewer = null;
|
||||||
|
SoundSource = new Transform { Position = CameraPosition };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ClientRpc doesn't allow for nullable versions of non-nullable types
|
||||||
|
/// so here we are
|
||||||
|
/// </summary>
|
||||||
|
public void UpdateCameraPositionRotation( Vector3? position = null, Rotation? rotation = null )
|
||||||
|
{
|
||||||
|
CameraPosition = (Vector3)(position.Equals( null ) ? CameraPosition : position);
|
||||||
|
CameraRotation = (Rotation)(rotation.Equals( null ) ? CameraRotation : rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ClientRpc]
|
||||||
|
public void LookAt( Vector3 position )
|
||||||
|
{
|
||||||
|
UpdateCameraPositionRotation( position );
|
||||||
|
}
|
||||||
|
[ClientRpc]
|
||||||
|
public void LookAt( Rotation rotation )
|
||||||
|
{
|
||||||
|
UpdateCameraPositionRotation( rotation: rotation );
|
||||||
|
}
|
||||||
|
[ClientRpc]
|
||||||
|
public void LookAt( Vector3 position, Rotation rotation )
|
||||||
|
{
|
||||||
|
UpdateCameraPositionRotation( position, rotation );
|
||||||
|
}
|
||||||
|
}
|
||||||
15
code/EntityComponents/Lucker/LuckerClientInput.cs
Normal file
15
code/EntityComponents/Lucker/LuckerClientInput.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Sandbox;
|
||||||
|
|
||||||
|
namespace LuckerGame.EntityComponents.Lucker;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A component for capturing and passing around a client's input for an attached Lucker
|
||||||
|
/// </summary>
|
||||||
|
public class LuckerClientInput : EntityComponent<Entities.Lucker>
|
||||||
|
{
|
||||||
|
[ClientInput]
|
||||||
|
public Vector3 InputDirection { get; set; }
|
||||||
|
|
||||||
|
[ClientInput]
|
||||||
|
public Angles ViewAngles { get; set; }
|
||||||
|
}
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
using Sandbox;
|
|
||||||
using Sandbox.UI;
|
|
||||||
|
|
||||||
namespace LuckerGame.EntityComponents.Lucker;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the stats associated with a lucker during a lobby.
|
|
||||||
/// </summary>
|
|
||||||
public partial class LuckerStats : EntityComponent<Entities.Lucker>, ISingletonComponent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The lucker's current score.
|
|
||||||
/// </summary>
|
|
||||||
[Net] private long Score { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds points to this lucker's score
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="points">points to add (or remove if negative)</param>
|
|
||||||
public void AddScore( long points )
|
|
||||||
{
|
|
||||||
Score += points;
|
|
||||||
if ( points == 0 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = $"{Entity.Name} {(points > 0 ? "gained" : "lost")} {points} points!";
|
|
||||||
ChatBox.AddInformation( To.Everyone, message );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resets this lucker's score to zero
|
|
||||||
/// </summary>
|
|
||||||
public void ResetScore()
|
|
||||||
{
|
|
||||||
Score = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets this lucker's current score
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>this lucker's current score</returns>
|
|
||||||
public long GetScore()
|
|
||||||
{
|
|
||||||
return Score;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,16 +4,16 @@ namespace LuckerGame.Events;
|
|||||||
|
|
||||||
public static partial class LuckerEvent
|
public static partial class LuckerEvent
|
||||||
{
|
{
|
||||||
public const string LuckerReady = "lucker.luckerReady";
|
public const string PlayerReady = "lucker.playerReady";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event is run on the server whenever a lucker changes ready state
|
/// Event is run on the server whenever a player changes ready state
|
||||||
/// The event handler is given the lucker that readied up and their new ready state
|
/// The event handler is given the player that readied up and their new ready state
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodArguments(typeof(Entities.Lucker), typeof(bool))]
|
[MethodArguments(typeof(Entities.Lucker), typeof(bool))]
|
||||||
public class LuckerReadyAttribute : EventAttribute
|
public class PlayerReadyAttribute : EventAttribute
|
||||||
{
|
{
|
||||||
public LuckerReadyAttribute() : base(LuckerReady)
|
public PlayerReadyAttribute() : base(PlayerReady)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,13 @@ public abstract class Minigame : Entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the minigame with a list of luckers playing it.
|
/// Initializes the minigame with a list of luckers playing it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="luckers">the luckers who made it into the minigame</param>
|
/// <param name="players">the players who made it into the minigame</param>
|
||||||
public abstract void Initialize(List<Lucker> luckers);
|
public abstract void Initialize(List<Lucker> players);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Once a minigame is loaded and initialized, this method is called once per server tick.
|
/// Once a minigame is loaded and initialized, this method is called once per server tick.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>true if the minigame has ended, false otherwise</returns>
|
public abstract void Tick();
|
||||||
public abstract bool Tick();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cleans up any entities and components created by this minigame.
|
/// Cleans up any entities and components created by this minigame.
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public partial class RussianPistol : Weapon
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Pawn.PlaySound( "player_use_fail" );
|
Pawn.PlaySound( "denyundo" );
|
||||||
}
|
}
|
||||||
Ammo--;
|
Ammo--;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,102 +14,87 @@ namespace LuckerGame.Minigames.RussianRoulette;
|
|||||||
public class RussianRouletteMinigame : Minigame
|
public class RussianRouletteMinigame : Minigame
|
||||||
{
|
{
|
||||||
public override string Name => "Russian Roulette";
|
public override string Name => "Russian Roulette";
|
||||||
private List<Lucker> Luckers { get; set; }
|
private List<Lucker> Players { get; set; }
|
||||||
private Pawn Shooter { get; set; }
|
private Entities.Pawn Shooter { get; set; }
|
||||||
|
|
||||||
private const float ShooterDistance = 80f;
|
private const float ShooterDistance = 80f;
|
||||||
private const float TimeBetweenShots = 7f;
|
private const float TimeBetweenShots = 7f;
|
||||||
private const float TimeBetweenDeathAndEnd = 5f;
|
|
||||||
private const string ShooterName = "The Russian";
|
|
||||||
private int Taunted = 0;
|
private int Taunted = 0;
|
||||||
private Pawn ShooterTarget;
|
|
||||||
|
|
||||||
private List<Pawn> DeadVictims => Luckers
|
private List<Entities.Pawn> DeadVictims => Players
|
||||||
.Select( lucker => lucker.Pawn as Pawn )
|
.Select( player => player.Pawn as Entities.Pawn )
|
||||||
.Where( pawn => pawn is not { IsValid: true } || pawn.LifeState != LifeState.Alive )
|
.Where( pawn => !pawn.IsValid || pawn.LifeState != LifeState.Alive )
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
private TimeSince TimeSinceShot { get; set; }
|
private TimeSince TimeSinceShot { get; set; }
|
||||||
private TimeSince TimeSinceDeadVictim { get; set; }
|
|
||||||
|
|
||||||
public override void Initialize( List<Lucker> luckers )
|
public override void Initialize( List<Lucker> players )
|
||||||
{
|
{
|
||||||
Luckers = luckers;
|
Players = players;
|
||||||
Shooter = new Pawn();
|
Shooter = new Entities.Pawn();
|
||||||
Shooter.Name = ShooterName;
|
|
||||||
var shooterInventory = Shooter.Components.Create<PawnInventory>();
|
var shooterInventory = Shooter.Components.Create<PawnInventory>();
|
||||||
shooterInventory.AddWeapon( new RussianPistol() );
|
shooterInventory.AddWeapon( new RussianPistol() );
|
||||||
|
|
||||||
// Setup cameras for luckers
|
// Setup cameras for players
|
||||||
Luckers.ForEach( lucker =>
|
Players.ForEach( player =>
|
||||||
{
|
{
|
||||||
lucker.Components.Create<RTSCamera>();
|
player.Components.Create<RTSCamera>();
|
||||||
lucker.Position = Shooter.Position;
|
player.Position = Shooter.Position;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
Luckers.Select((lucker, i) => (Lucker: lucker, Index: i) ).ToList().ForEach( pair =>
|
Players.Select((player, i) => (Player: player, Index: i) ).ToList().ForEach( pair =>
|
||||||
{
|
{
|
||||||
var lucker = pair.Lucker;
|
var player = pair.Player;
|
||||||
var index = pair.Index;
|
var index = pair.Index;
|
||||||
var pawn = new Pawn();
|
var pawn = new Entities.Pawn();
|
||||||
pawn.Name = lucker.Name;
|
pawn.Name = player.Name;
|
||||||
pawn.Tags.Add( "victim" );
|
pawn.Tags.Add( "victim" );
|
||||||
pawn.Health = 1;
|
pawn.Health = 1;
|
||||||
lucker.Pawn = pawn;
|
player.Pawn = pawn;
|
||||||
pawn.DressFromClient( lucker.Client );
|
pawn.DressFromClient( player.Client );
|
||||||
|
|
||||||
var pawnOffset = ShooterDistance * (index % 2 == 0 ? Vector3.Forward : Vector3.Right) * (index % 4 >= 2 ? -1 : 1);
|
var pawnOffset = ShooterDistance * (index % 2 == 0 ? Vector3.Forward : Vector3.Right) * (index % 4 >= 2 ? -1 : 1);
|
||||||
|
|
||||||
lucker.Pawn.Position = Shooter.Position + pawnOffset;
|
player.Pawn.Position = Shooter.Position + pawnOffset;
|
||||||
pawn.LookAt(Shooter.Position);
|
pawn.LookAt(Shooter.Position);
|
||||||
} );
|
} );
|
||||||
TimeSinceShot = 0;
|
TimeSinceShot = 0;
|
||||||
Taunted = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Tick()
|
public override void Tick()
|
||||||
{
|
{
|
||||||
// Someone is dead, we're getting ready to end
|
|
||||||
if ( DeadVictims.Any() )
|
if ( DeadVictims.Any() )
|
||||||
{
|
{
|
||||||
if ( Taunted != int.MaxValue )
|
if ( Taunted != int.MaxValue )
|
||||||
{
|
{
|
||||||
ChatBox.AddChatEntry( To.Everyone, Shooter.Name, "Heh, nothing personnel, kid." );
|
ChatBox.AddChatEntry( To.Everyone, "Shooter", "Heh, nothing personnel, kid." );
|
||||||
Taunted = int.MaxValue;
|
Taunted = int.MaxValue;
|
||||||
TimeSinceDeadVictim = 0;
|
|
||||||
}
|
|
||||||
else if(TimeSinceDeadVictim > TimeBetweenDeathAndEnd)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if ( TimeSinceShot > TimeBetweenShots )
|
if ( TimeSinceShot > TimeBetweenShots )
|
||||||
{
|
{
|
||||||
TimeSinceShot = 0;
|
TimeSinceShot = 0;
|
||||||
Taunted = 0;
|
Taunted = 0;
|
||||||
Shooter.Inventory.ActiveWeapon.PrimaryAttack();
|
Shooter.Inventory.ActiveWeapon.PrimaryAttack();
|
||||||
if ( !DeadVictims.Any() )
|
if ( !DeadVictims.Any() )
|
||||||
{
|
{
|
||||||
ChatBox.AddChatEntry( To.Everyone, Shooter.Name, "Fucking lag..." );
|
ChatBox.AddChatEntry( To.Everyone, "Shooter", "Fucking lag..." );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( TimeSinceShot > TimeBetweenShots * .8f && Taunted == 1)
|
else if ( TimeSinceShot > TimeBetweenShots * .8f && Taunted == 1)
|
||||||
{
|
{
|
||||||
ShooterTarget = Luckers.Select( lucker => lucker.Pawn as Pawn )
|
var victim = Players.Select( player => player.Pawn as Racer )
|
||||||
.OrderBy( _ => Guid.NewGuid() )
|
.OrderBy( _ => Guid.NewGuid() )
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
Shooter.LookAt( ShooterTarget.Position );
|
Shooter.LookAt( victim.Position );
|
||||||
var chance = 1f / Shooter.Inventory.ActiveWeapon.Ammo;
|
ChatBox.AddChatEntry( To.Everyone, "Shooter", $"I'm gonna eat you up, {victim.Name}" );
|
||||||
ChatBox.AddChatEntry( To.Everyone, Shooter.Name, $"Good luck, {ShooterTarget.Name}! You have a {chance:P0} chance to die!" );
|
|
||||||
Taunted++;
|
Taunted++;
|
||||||
}
|
}
|
||||||
else if ( TimeSinceShot > TimeBetweenShots / 2 && Taunted == 0)
|
else if ( TimeSinceShot > TimeBetweenShots / 2 && Taunted == 0)
|
||||||
{
|
{
|
||||||
ChatBox.AddChatEntry( To.Everyone, Shooter.Name, "Im gettin' ready!" );
|
ChatBox.AddChatEntry( To.Everyone, "Shooter", "Im gettin' ready!" );
|
||||||
Taunted++;
|
Taunted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Cleanup()
|
public override void Cleanup()
|
||||||
|
|||||||
23
code/Minigames/TerryRaces/HoveringTextCreator.cs
Normal file
23
code/Minigames/TerryRaces/HoveringTextCreator.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using LuckerGame.UI;
|
||||||
|
using Sandbox;
|
||||||
|
|
||||||
|
public class HoveringTextCreator : Entity
|
||||||
|
{
|
||||||
|
private string Text { get; set; }
|
||||||
|
private Entity TargetEntity { get; set; }
|
||||||
|
|
||||||
|
public HoveringTextCreator()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public HoveringTextCreator(string text, Entity targetEntity)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
TargetEntity = targetEntity;
|
||||||
|
}
|
||||||
|
public override void ClientSpawn()
|
||||||
|
{
|
||||||
|
base.ClientSpawn();
|
||||||
|
var hoveringText = new HoveringText(Text, TargetEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
64
code/Minigames/TerryRaces/Racer.cs
Normal file
64
code/Minigames/TerryRaces/Racer.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using LuckerGame.Entities;
|
||||||
|
using LuckerGame.UI;
|
||||||
|
using Sandbox;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Reflection.Metadata.Ecma335;
|
||||||
|
|
||||||
|
public class Racer : Pawn
|
||||||
|
{
|
||||||
|
public float Speed;
|
||||||
|
private float SpeedModifier = 1f;
|
||||||
|
private Random Random { get; set; }
|
||||||
|
private HoveringText NameTag { get; set; }
|
||||||
|
|
||||||
|
public Racer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Racer( Random random )
|
||||||
|
{
|
||||||
|
Random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ClientSpawn()
|
||||||
|
{
|
||||||
|
base.ClientSpawn();
|
||||||
|
NameTag = new( Name, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ContinueRacing()
|
||||||
|
{
|
||||||
|
SetAnimParameter( "move_x", Speed * 500f * SpeedModifier );
|
||||||
|
ModifySpeed();
|
||||||
|
Position = Position.WithY( Position.y - (Speed * SpeedModifier) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ModifySpeed()
|
||||||
|
{
|
||||||
|
var roll = Random.NextDouble();
|
||||||
|
switch ( roll )
|
||||||
|
{
|
||||||
|
case >= .90 and < .95:
|
||||||
|
SpeedModifier = 2f;
|
||||||
|
break;
|
||||||
|
case >= .95:
|
||||||
|
SpeedModifier = 0.5f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopRacing()
|
||||||
|
{
|
||||||
|
SetAnimParameter( "move_x", 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateSpeed( double minSpeed, double maxSpeed )
|
||||||
|
{
|
||||||
|
Speed = (float)(RandomExtensions.NextDouble( Random, minSpeed, maxSpeed ));
|
||||||
|
}
|
||||||
|
}
|
||||||
123
code/Minigames/TerryRaces/TerryRacesMinigame.cs
Normal file
123
code/Minigames/TerryRaces/TerryRacesMinigame.cs
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Reflection.Metadata.Ecma335;
|
||||||
|
using LuckerGame.Components.Lucker.Cameras;
|
||||||
|
using LuckerGame.Components.Pawn;
|
||||||
|
using LuckerGame.Entities;
|
||||||
|
using Sandbox;
|
||||||
|
using Sandbox.UI;
|
||||||
|
|
||||||
|
namespace LuckerGame.Minigames.TerryRaces;
|
||||||
|
|
||||||
|
[Library( "mg_terry_races" )]
|
||||||
|
public class TerryRaces : Minigame
|
||||||
|
{
|
||||||
|
public override string Name => "Terry Races";
|
||||||
|
private Random random = new Random();
|
||||||
|
private HoveringTextCreator NameTag { get; set; }
|
||||||
|
private Racer WinningRacer = null;
|
||||||
|
private FixedCamera Camera;
|
||||||
|
private List<Lucker> Players { get; set; }
|
||||||
|
private List<Racer> Racers { get; set; } = new List<Racer>();
|
||||||
|
private List<string> RacerNames = new List<string>
|
||||||
|
{
|
||||||
|
"Terrance",
|
||||||
|
"Terrie",
|
||||||
|
"TearBear",
|
||||||
|
"Theresa"
|
||||||
|
};
|
||||||
|
private float StartingY = 290f;
|
||||||
|
private float FinishLineY = -300f;
|
||||||
|
private float StartingX = 90f;
|
||||||
|
private float RacerXOffset = 60f;
|
||||||
|
private float MinimumSpeed = .90f;
|
||||||
|
private float MaximumSpeed = 1.1f;
|
||||||
|
|
||||||
|
public override void Initialize( List<Lucker> players )
|
||||||
|
{
|
||||||
|
Players = players;
|
||||||
|
|
||||||
|
// Setup cameras for players
|
||||||
|
Players.ForEach( player =>
|
||||||
|
{
|
||||||
|
Camera = player.Components.Create<FixedCamera>();
|
||||||
|
Camera.LookAt( new Vector3(0f, 0f, 400f), Rotation.FromPitch( -270 ) );
|
||||||
|
Camera.FieldOfViewValue = 100f;
|
||||||
|
} );
|
||||||
|
|
||||||
|
SpawnRacers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Tick()
|
||||||
|
{
|
||||||
|
Racers.ForEach( racer =>
|
||||||
|
{
|
||||||
|
if (WinningRacer == null)
|
||||||
|
{
|
||||||
|
GetWinningRacer();
|
||||||
|
racer.ContinueRacing();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
racer.StopRacing();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Cleanup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SpawnRacers()
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < RacerNames.Count; i++ )
|
||||||
|
{
|
||||||
|
var clothing = new ClothingContainer();
|
||||||
|
var racer = new Racer(random);
|
||||||
|
var x = StartingX - RacerXOffset * i;
|
||||||
|
|
||||||
|
clothing.Toggle( GetRandomBottomClothing() );
|
||||||
|
clothing.Toggle( GetRandomHatClothing() );
|
||||||
|
clothing.DressEntity( racer );
|
||||||
|
|
||||||
|
racer.Name = RacerNames[i];
|
||||||
|
racer.Position = new Vector3( x, StartingY, 0 );
|
||||||
|
racer.Rotation = Rotation.FromYaw( -90 );
|
||||||
|
racer.GenerateSpeed(MinimumSpeed, MaximumSpeed );
|
||||||
|
|
||||||
|
Racers.Add( racer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Clothing GetRandomBottomClothing()
|
||||||
|
{
|
||||||
|
return ResourceLibrary
|
||||||
|
.GetAll<Clothing>()
|
||||||
|
.Where( c => c.Category == Clothing.ClothingCategory.Bottoms )
|
||||||
|
.OrderBy( _ => Guid.NewGuid() )
|
||||||
|
.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Clothing GetRandomHatClothing()
|
||||||
|
{
|
||||||
|
return ResourceLibrary
|
||||||
|
.GetAll<Clothing>()
|
||||||
|
.Where( c => c.Category == Clothing.ClothingCategory.Hat )
|
||||||
|
.OrderBy( _ => Guid.NewGuid() )
|
||||||
|
.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetWinningRacer()
|
||||||
|
{
|
||||||
|
foreach ( Racer racer in Racers )
|
||||||
|
{
|
||||||
|
if ( racer.Position.y <= FinishLineY )
|
||||||
|
{
|
||||||
|
WinningRacer = racer;
|
||||||
|
Log.Info( $"Winning racer: {racer.Name}" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
code/RandomExtensions.cs
Normal file
11
code/RandomExtensions.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
public static class RandomExtensions
|
||||||
|
{
|
||||||
|
public static double NextDouble(
|
||||||
|
this Random random,
|
||||||
|
double minValue,
|
||||||
|
double maxValue )
|
||||||
|
{
|
||||||
|
return random.NextDouble() * (maxValue - minValue) + minValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
code/UI/HoveringText.razor
Normal file
30
code/UI/HoveringText.razor
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
@using Sandbox;
|
||||||
|
@using Sandbox.UI;
|
||||||
|
|
||||||
|
@namespace LuckerGame.UI
|
||||||
|
@attribute [StyleSheet]
|
||||||
|
@inherits WorldPanel
|
||||||
|
|
||||||
|
<root class="card">
|
||||||
|
<label class="text">@Text</label>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private Entity TargetEntity;
|
||||||
|
private string Text;
|
||||||
|
|
||||||
|
public HoveringText(string text, Entity targetEntity)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
TargetEntity = targetEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
[GameEvent.Client.Frame]
|
||||||
|
private void OnFrame()
|
||||||
|
{
|
||||||
|
if (!TargetEntity.IsValid()) return;
|
||||||
|
Log.Info($"{Text} to {TargetEntity.Position}");
|
||||||
|
Position = TargetEntity.Position + Vector3.Up * 65f;
|
||||||
|
Rotation = Rotation.LookAt(-Screen.GetDirection(new Vector2(Screen.Width * 0.5f, Screen.Height * 0.5f)));
|
||||||
|
}
|
||||||
|
}
|
||||||
7
code/UI/HoveringText.razor.scss
Normal file
7
code/UI/HoveringText.razor.scss
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
hoveringtext {
|
||||||
|
white-space: nowrap;
|
||||||
|
.text {
|
||||||
|
font-size: 150px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
<VoiceList/>
|
<VoiceList/>
|
||||||
<VotingLobby/>
|
<VotingLobby/>
|
||||||
<Scoreboard/>
|
<Scoreboard/>
|
||||||
<CameraCursor/>
|
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
@code
|
@code
|
||||||
|
|||||||
@@ -5,13 +5,10 @@
|
|||||||
@attribute [StyleSheet]
|
@attribute [StyleSheet]
|
||||||
@inherits Panel
|
@inherits Panel
|
||||||
|
|
||||||
<root>
|
@if (ShouldShowCursor)
|
||||||
@if (ShouldShowCursor)
|
{
|
||||||
{
|
<root/>
|
||||||
<div class="camera-cursor"/>
|
}
|
||||||
}
|
|
||||||
</root>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
CameraCursor {
|
CameraCursor {
|
||||||
.camera-cursor {
|
pointer-events: all;
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
<root>
|
<root>
|
||||||
<div class="scoreboard-panel">
|
<div class="scoreboard-panel">
|
||||||
@foreach (var lucker in Luckers)
|
@foreach (var player in Luckers)
|
||||||
{
|
{
|
||||||
<label>@lucker.Name</label>
|
<label>@player.Name</label>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</root>
|
</root>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
protected override int BuildHash()
|
protected override int BuildHash()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(Luckers.Select(lucker => lucker.Name).ToList());
|
return HashCode.Combine(Luckers.Select(player => player.Name).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
@using Sandbox;
|
|
||||||
@using System;
|
|
||||||
@using System.Linq;
|
|
||||||
@using System.Threading.Tasks;
|
|
||||||
@using Sandbox.Menu;
|
|
||||||
@using Sandbox.UI;
|
|
||||||
|
|
||||||
@namespace LuckerGame.UI.MainMenu
|
|
||||||
@inherits Panel
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<label class="game-title">
|
|
||||||
@Game.Menu.Package.Title
|
|
||||||
</label>
|
|
||||||
|
|
||||||
@if ( Lobby == null )
|
|
||||||
{
|
|
||||||
<div class="controls">
|
|
||||||
<a class="button">Loading...</a>
|
|
||||||
|
|
||||||
<a class="button" href="/lobby/list">Return</a>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
<div class="col">
|
|
||||||
<label>Members (@Lobby.MemberCount/@Lobby.MaxMembers)</label>
|
|
||||||
|
|
||||||
<div class="span">
|
|
||||||
@foreach (var member in Lobby.Members)
|
|
||||||
{
|
|
||||||
<img class="avatar" src="avatar:@member.Id" tooltip="@member.Name" />
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if ( Lobby.Owner.IsMe )
|
|
||||||
{
|
|
||||||
<div class="span">
|
|
||||||
@if ( MaxPlayersSupported > 1 )
|
|
||||||
{
|
|
||||||
<FormGroup class="form-group">
|
|
||||||
<Label>Maximum Players</Label>
|
|
||||||
<Control>
|
|
||||||
<SliderControl ShowRange=@true Min=@(1f) Max=@MaxPlayersSupported Value:bind=@Game.Menu.Lobby.MaxMembers />
|
|
||||||
</Control>
|
|
||||||
</FormGroup>
|
|
||||||
}
|
|
||||||
|
|
||||||
<FormGroup class="form-group">
|
|
||||||
<Label>Map</Label>
|
|
||||||
<Control>
|
|
||||||
<SlimPackageCard OnLaunch=@OnMapClicked Package=@MapPackage />
|
|
||||||
</Control>
|
|
||||||
</FormGroup>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="spacer" />
|
|
||||||
|
|
||||||
|
|
||||||
<a class="button" @onclick=@LeaveLobby>Leave Lobby</a>
|
|
||||||
|
|
||||||
<a class="button" @onclick=@Start>Start</a>
|
|
||||||
|
|
||||||
<a class="button" href="/lobby/list">Return</a>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
Friend Owner => Lobby.Owner;
|
|
||||||
ILobby Lobby => Game.Menu.Lobby;
|
|
||||||
|
|
||||||
int MaxPlayersSupported { get; set; } = 1;
|
|
||||||
Package MapPackage { get; set; }
|
|
||||||
|
|
||||||
void OnMapClicked()
|
|
||||||
{
|
|
||||||
Game.Overlay.ShowPackageSelector( "type:map sort:popular", OnMapSelected );
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnMapSelected( Package map )
|
|
||||||
{
|
|
||||||
MapPackage = map;
|
|
||||||
Game.Menu.Lobby.Map = map.FullIdent;
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LeaveLobby()
|
|
||||||
{
|
|
||||||
Lobby?.Leave();
|
|
||||||
|
|
||||||
this.Navigate( "/lobby/list" );
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task Start()
|
|
||||||
{
|
|
||||||
await Game.Menu.StartServerAsync( Game.Menu.Lobby.MaxMembers, $"{Game.Menu.Lobby.Owner.Name}'s game", Game.Menu.Lobby.Map );
|
|
||||||
}
|
|
||||||
|
|
||||||
async void FetchPackage()
|
|
||||||
{
|
|
||||||
MapPackage = await Package.FetchAsync( Game.Menu.Lobby?.Map ?? "facepunch.square", true );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnAfterTreeRender( bool firstTime )
|
|
||||||
{
|
|
||||||
FetchPackage();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
MaxPlayersSupported = Game.Menu.Package.GetMeta<int>( "MaxPlayers", 1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
@using Sandbox;
|
|
||||||
@using System.Linq;
|
|
||||||
@using System.Threading.Tasks;
|
|
||||||
@using Sandbox.Menu;
|
|
||||||
@using Sandbox.UI;
|
|
||||||
@namespace LuckerGame.UI.MainMenu
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<div class="game-title">
|
|
||||||
@Game.Menu.Package.Title
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
@if (Game.InGame)
|
|
||||||
{
|
|
||||||
<a class="button" onclick=@LeaveGame>Leave</a>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<a class="button" href="/setup">Play</a>
|
|
||||||
|
|
||||||
<a class="button" href="/lobby/list">Lobbies</a>
|
|
||||||
|
|
||||||
@if ( Game.Menu.Package.SupportsSavedGames && Game.Menu.SavedGames.Any())
|
|
||||||
{
|
|
||||||
<a class="button" href="/setup/save">Load Save</a>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<a class="button" @onclick=@Game.Menu.Close>Quit</a>
|
|
||||||
</div>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
void LeaveGame()
|
|
||||||
{
|
|
||||||
Game.Menu.LeaveServer( "Leaving" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
@using Sandbox;
|
|
||||||
@using Sandbox.UI;
|
|
||||||
@using System.Linq;
|
|
||||||
@using System.Threading.Tasks;
|
|
||||||
@using Sandbox.Menu;
|
|
||||||
|
|
||||||
@inherits RootPanel
|
|
||||||
@implements Sandbox.Menu.ILoadingScreenPanel
|
|
||||||
@attribute [StyleSheet]
|
|
||||||
@namespace LuckerGame.UI.MainMenu
|
|
||||||
|
|
||||||
<root style="flex-direction: column;">
|
|
||||||
<div class="background" />
|
|
||||||
|
|
||||||
<div style="flex-grow: 1;" />
|
|
||||||
|
|
||||||
<div class="controls" style="flex-direction: row; justify-content: center;">
|
|
||||||
<a class="button">@( Progress.Title ?? "Loading..." )</a>
|
|
||||||
</div>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
public LoadingProgress Progress;
|
|
||||||
|
|
||||||
public void OnLoadingProgress( LoadingProgress progress )
|
|
||||||
{
|
|
||||||
Progress = progress;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
|
|
||||||
LoadingScreen
|
|
||||||
{
|
|
||||||
background-color: #262934;
|
|
||||||
padding: 128px 128px;
|
|
||||||
opacity: 1;
|
|
||||||
flex-direction: column;
|
|
||||||
font-size: 25px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
transition: all 0.3s ease-out;
|
|
||||||
color: rgba( white, 0.8 );
|
|
||||||
|
|
||||||
.background
|
|
||||||
{
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-image: url( https://files.facepunch.com/tony/1b1311b1/boxes.webm );
|
|
||||||
opacity: 0.2;
|
|
||||||
background-size: contain;
|
|
||||||
filter: blur( 20px );
|
|
||||||
mask: linear-gradient( 45deg, white, white, black );
|
|
||||||
mask-scope: filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:intro
|
|
||||||
{
|
|
||||||
opacity: 0;
|
|
||||||
transform: scaleX( 1.1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-title
|
|
||||||
{
|
|
||||||
font-family: Roboto;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 70px;
|
|
||||||
color: rgba( white, 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls
|
|
||||||
{
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 50px;
|
|
||||||
align-items: flex-start;
|
|
||||||
font-family: Roboto;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
@using Sandbox;
|
|
||||||
@using System;
|
|
||||||
@using System.Linq;
|
|
||||||
@using System.Threading.Tasks;
|
|
||||||
@using Sandbox.Menu;
|
|
||||||
@using Sandbox.UI;
|
|
||||||
@namespace LuckerGame.UI.MainMenu
|
|
||||||
@inherits Panel
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<label class="game-title">
|
|
||||||
@Game.Menu.Package.Title
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
<div class="span">
|
|
||||||
<label>Showing @Game.Menu.Lobbies.Count() @(Game.Menu.Lobbies.Count() == 1 ? "lobby" : "lobbies")</label>
|
|
||||||
<i class="with-click" tooltip="Refresh lobbies" @onclick=@Refresh>refresh</i>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="scroll">
|
|
||||||
@foreach ( var lobby in Game.Menu.Lobbies )
|
|
||||||
{
|
|
||||||
<a class="button" @onclick=@( () => JoinLobby( lobby ) ) >@(lobby.Owner.Name)'s lobby (@lobby.MemberCount/@lobby.MaxMembers)</a>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="spacer" />
|
|
||||||
|
|
||||||
<a class="button" @onclick=@CreateLobbyAsync>Create Lobby</a>
|
|
||||||
<a class="button" href="/">Return</a>
|
|
||||||
</div>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
public async void CreateLobbyAsync()
|
|
||||||
{
|
|
||||||
await Game.Menu.CreateLobbyAsync( 64, "game", true );
|
|
||||||
Game.Menu.Lobby.Map = "facepunch.square";
|
|
||||||
this.Navigate( "/lobby/active" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void JoinLobby( ILobby lobby )
|
|
||||||
{
|
|
||||||
if ( lobby == null ) return;
|
|
||||||
|
|
||||||
// don't exist in two lobbies at once
|
|
||||||
Game.Menu.Lobby?.Leave();
|
|
||||||
|
|
||||||
await lobby.JoinAsync();
|
|
||||||
this.Navigate( "/lobby/active" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Refresh()
|
|
||||||
{
|
|
||||||
await Game.Menu.QueryLobbiesAsync( null, 1 );
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int BuildHash()
|
|
||||||
{
|
|
||||||
return HashCode.Combine( Game.Menu.Lobbies.Count() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
@using System;
|
|
||||||
@using Sandbox;
|
|
||||||
@using Sandbox.UI;
|
|
||||||
|
|
||||||
@inherits Sandbox.UI.NavHostPanel
|
|
||||||
@implements Sandbox.Menu.IGameMenuPanel
|
|
||||||
@attribute [StyleSheet]
|
|
||||||
@namespace LuckerGame.UI.MainMenu
|
|
||||||
|
|
||||||
<root style="flex-direction: column;">
|
|
||||||
<div class="background" />
|
|
||||||
<div class="navigator-canvas" slot="navigator-canvas" />
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
public MainMenu()
|
|
||||||
{
|
|
||||||
DefaultUrl = "/";
|
|
||||||
|
|
||||||
AddDestination( "/", typeof( FrontPage ) );
|
|
||||||
AddDestination( "/setup", typeof( SetupGame ) );
|
|
||||||
|
|
||||||
AddDestination( "/lobby/list", typeof( LobbyBrowser ) );
|
|
||||||
AddDestination( "/lobby/active", typeof( ActiveLobby ) );
|
|
||||||
|
|
||||||
BindClass( "ingame", () => Game.InGame );
|
|
||||||
}
|
|
||||||
|
|
||||||
[GameEvent.Menu.ServerJoined]
|
|
||||||
public void OnServerJoined() => Navigate( "/" );
|
|
||||||
|
|
||||||
[GameEvent.Menu.ServerLeave]
|
|
||||||
public void OnServerLeave() => Navigate ("/" );
|
|
||||||
|
|
||||||
protected override int BuildHash()
|
|
||||||
{
|
|
||||||
return HashCode.Combine( Game.InGame, Game.Menu.Lobby, Game.Menu.Lobby?.Map );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
|
|
||||||
MainMenu
|
|
||||||
{
|
|
||||||
background-color: #262934;
|
|
||||||
padding: 128px 128px;
|
|
||||||
opacity: 1;
|
|
||||||
flex-direction: column;
|
|
||||||
font-size: 25px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
transition: all 0.3s ease-out;
|
|
||||||
color: rgba( white, 0.8 );
|
|
||||||
|
|
||||||
.background
|
|
||||||
{
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-image: url( https://files.facepunch.com/tony/1b1311b1/boxes.webm );
|
|
||||||
opacity: 0.2;
|
|
||||||
background-size: cover;
|
|
||||||
filter: blur( 20px );
|
|
||||||
mask: linear-gradient( 45deg, white, white, black );
|
|
||||||
mask-scope: filter;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:intro
|
|
||||||
{
|
|
||||||
opacity: 0;
|
|
||||||
transform: scaleX( 1.1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
&.ingame
|
|
||||||
{
|
|
||||||
background-color: #262934ee;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
|
|
||||||
.background
|
|
||||||
{
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll
|
|
||||||
{
|
|
||||||
flex-direction: column;
|
|
||||||
max-height: 386px;
|
|
||||||
overflow: scroll;
|
|
||||||
gap: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spacer
|
|
||||||
{
|
|
||||||
height: 1px;
|
|
||||||
background-image: linear-gradient( to right, rgba( white, 0.4 ), rgba( white, 0 ) );
|
|
||||||
width: 512px;
|
|
||||||
margin: 16px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-title
|
|
||||||
{
|
|
||||||
font-family: Roboto Condensed;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 70px;
|
|
||||||
color: rgba( white, 1 );
|
|
||||||
padding-bottom: 64px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.col
|
|
||||||
{
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls
|
|
||||||
{
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 50px;
|
|
||||||
align-items: flex-start;
|
|
||||||
text-transform: uppercase;
|
|
||||||
|
|
||||||
a, .button
|
|
||||||
{
|
|
||||||
font-family: Roboto;
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
{
|
|
||||||
color: rgba( white, 1 );
|
|
||||||
font-weight: 900;
|
|
||||||
sound-in: ui.button.over;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active
|
|
||||||
{
|
|
||||||
sound-in: ui.button.press;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.span
|
|
||||||
{
|
|
||||||
gap: 128px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigator-canvas
|
|
||||||
{
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigator-body
|
|
||||||
{
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
top: 0;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
transition: opacity 0.15s ease-out;
|
|
||||||
|
|
||||||
&.hidden
|
|
||||||
{
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FormGroup
|
|
||||||
{
|
|
||||||
flex-direction: column;
|
|
||||||
min-width: 300px;
|
|
||||||
gap:16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
SlimPackageCard
|
|
||||||
{
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 12px;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
> i
|
|
||||||
{
|
|
||||||
&:hover
|
|
||||||
{
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
transform: scale( 1.1 );
|
|
||||||
sound-in: ui.button.over;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active
|
|
||||||
{
|
|
||||||
sound-in: ui.button.press;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i
|
|
||||||
{
|
|
||||||
font-family: Material Icons;
|
|
||||||
text-transform: lowercase;
|
|
||||||
|
|
||||||
&.with-click
|
|
||||||
{
|
|
||||||
&:hover
|
|
||||||
{
|
|
||||||
cursor: pointer;
|
|
||||||
color: white;
|
|
||||||
transform: scale( 1.1 );
|
|
||||||
sound-in: ui.button.over;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active
|
|
||||||
{
|
|
||||||
sound-in: ui.button.press;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar
|
|
||||||
{
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
{
|
|
||||||
border: 1px solid white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
@using Sandbox;
|
|
||||||
@using System;
|
|
||||||
@using System.Linq;
|
|
||||||
@using Sandbox.UI;
|
|
||||||
@namespace LuckerGame.UI.MainMenu
|
|
||||||
@inherits Panel
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<label class="game-title">
|
|
||||||
@Game.Menu.Package.Title
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
@foreach ( var save in Game.Menu.SavedGames.OrderByDescending( x => x.Time ) )
|
|
||||||
{
|
|
||||||
<a class="button" @onclick=@(() => LoadSavedGame( save ))>@save.Name - @save.Time</a>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="spacer" />
|
|
||||||
|
|
||||||
<a class="button" href="/">Return</a>
|
|
||||||
</div>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
async void LoadSavedGame( SavedGame save )
|
|
||||||
{
|
|
||||||
if ( save != null )
|
|
||||||
{
|
|
||||||
Game.Menu.Lobby.SavedGame = save.Name;
|
|
||||||
|
|
||||||
if ( !string.IsNullOrEmpty( save.Map ) )
|
|
||||||
Game.Menu.Lobby.Map = save.Map;
|
|
||||||
|
|
||||||
await Game.Menu.StartServerAsync( Game.Menu.Lobby.MaxMembers, Game.Menu.Lobby.Title, Game.Menu.Lobby.Map ?? "facepunch.square" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int BuildHash()
|
|
||||||
{
|
|
||||||
return HashCode.Combine( Game.Menu.Lobby, Game.Menu.Lobby?.Map );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
@using Sandbox;
|
|
||||||
@using System;
|
|
||||||
@using System.Linq;
|
|
||||||
@using System.Threading.Tasks;
|
|
||||||
@using Sandbox.Menu;
|
|
||||||
@using Sandbox.UI;
|
|
||||||
@namespace LuckerGame.UI.MainMenu
|
|
||||||
@inherits Panel
|
|
||||||
|
|
||||||
<root>
|
|
||||||
<label class="game-title">
|
|
||||||
@Game.Menu.Package.Title
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
<div class="span">
|
|
||||||
@if ( MaxPlayersSupported > 1 )
|
|
||||||
{
|
|
||||||
<FormGroup class="form-group">
|
|
||||||
<Label>Maximum Players</Label>
|
|
||||||
<Control>
|
|
||||||
<SliderControl ShowRange=@true Min=@(1f) Max=@MaxPlayersSupported Value:bind=@Game.Menu.Lobby.MaxMembers />
|
|
||||||
</Control>
|
|
||||||
</FormGroup>
|
|
||||||
}
|
|
||||||
|
|
||||||
<FormGroup class="form-group">
|
|
||||||
<Label>Map</Label>
|
|
||||||
<Control>
|
|
||||||
<SlimPackageCard OnLaunch=@OnMapClicked Package=@MapPackage />
|
|
||||||
</Control>
|
|
||||||
</FormGroup>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="spacer" />
|
|
||||||
|
|
||||||
<a class="button" onclick=@Play>Start</a>
|
|
||||||
<a class="button" href="/">Return</a>
|
|
||||||
</div>
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
int MaxPlayersSupported { get; set; } = 1;
|
|
||||||
int MaxPlayers { get; set; } = 1;
|
|
||||||
Package MapPackage { get; set; }
|
|
||||||
|
|
||||||
void OnMapClicked()
|
|
||||||
{
|
|
||||||
Game.Overlay.ShowPackageSelector( "type:map sort:popular", OnMapSelected );
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnMapSelected( Package map )
|
|
||||||
{
|
|
||||||
MapPackage = map;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
|
||||||
{
|
|
||||||
MaxPlayersSupported = Game.Menu.Package.GetMeta<int>( "MaxPlayers", 1 );
|
|
||||||
MaxPlayers = MaxPlayersSupported;
|
|
||||||
|
|
||||||
MapPackage = await Package.FetchAsync( "facepunch.square", false );
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task Play()
|
|
||||||
{
|
|
||||||
await Game.Menu.StartServerAsync( MaxPlayers, $"My game", MapPackage.FullIdent );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int BuildHash()
|
|
||||||
{
|
|
||||||
return HashCode.Combine( MaxPlayers, MapPackage );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
@using System;
|
|
||||||
@using Sandbox;
|
|
||||||
@namespace LuckerGame.UI.MainMenu
|
|
||||||
@inherits Sandbox.UI.Panel
|
|
||||||
|
|
||||||
<root>
|
|
||||||
@if ( Package == null )
|
|
||||||
{
|
|
||||||
<div class="button" @onclick=@OnCardClicked>Select Package</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="button" @onclick=@OnCardClicked>@Package.Title</div>
|
|
||||||
<i tooltip="See information about this package" @onclick=@( () => Game.Overlay.ShowPackageModal( Package.FullIdent ) )>info</i>
|
|
||||||
}
|
|
||||||
</root>
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
public Package Package { get; set; }
|
|
||||||
public System.Action OnLaunch { get; set; }
|
|
||||||
|
|
||||||
void OnCardClicked()
|
|
||||||
{
|
|
||||||
OnLaunch?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int BuildHash()
|
|
||||||
{
|
|
||||||
return HashCode.Combine( Package );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
<div class="voting-panel primary-color-translucent-background">
|
<div class="voting-panel primary-color-translucent-background">
|
||||||
@if (RoundManager.RoundState == RoundState.NotStarted)
|
@if (RoundManager.RoundState == RoundState.NotStarted)
|
||||||
{
|
{
|
||||||
<label class="header">Waiting for luckers...</label>
|
<label class="header">Waiting for players...</label>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user