Player.cs
using System;
namespace GuessIt;
public sealed class Player : Component, Component.INetworkSpawn
{
[Sync( SyncFlags.FromHost )] public int Score { get; set; } = 0;
[Sync( SyncFlags.FromHost )] public bool HasGuessed { get; set; } = false;
[Sync] public float ColorHue { get; set; } = 0.0f;
[Property] public SkinnedModelRenderer Body { get; set; }
[Property] public CameraComponent Camera { get; set; }
[Property] public Voice Voice { get; set; }
public Texture CameraTexture;
public Color Color => new ColorHsv( ColorHue, 0.4f, 1f ).ToColor();
public bool IsDrawing => GameMenu.Instance?.CurrentlyDrawing == this;
public static Player Local => Game.ActiveScene.GetAllComponents<Player>().FirstOrDefault( x => x.Network.OwnerId == Connection.Local.Id );
TimeSince _timeSinceCreated;
bool _isIdle;
Dictionary<string, float> HappyMorph => new()
{
{ "innerbrowraiserL", 1f },
{ "innerbrowraiserR", 1f },
{ "outerbrowraiserL", 0.5f },
{ "outerbrowraiserR", 0.5f },
{ "cheekinflateL", 0.1f },
{ "cheekinflateR", 0.1f },
{ "openjawL", 0.25f },
{ "openjawR", 0.25f },
{ "lipcornerpullerL", 1f },
{ "lipcornerpullerR", 1f },
{ "openmouthL", 1f },
{ "openmouthR", 1f }
};
Dictionary<string, float> AngryMorph => new()
{
{ "browlowererL", 1f },
{ "browlowererR", 1f },
{ "eyelidbuldgelower", 1f },
{ "innerbrowraiserL", 1f },
{ "innerbrowraiserR", 1f },
{ "nosewrinklerL", 1f },
{ "nosewrinklerR", 1f },
{ "jawsuck", 1f },
{ "lipcornerdepresserL", 1f },
{ "lipcornerdepresserR", 1f },
{ "openjawL", 0.8f },
{ "openjawR", 0.8f },
{ "upperLipFunneler", 0.5f },
{ "upperlipraiserL", 1f },
{ "upperlipraiserR", 1f }
};
int[] WinningPoses => new int[] { 1, 3, 4, 5, 6 };
int[] LosingPoses => new int[] { 2, 7 };
protected override void OnAwake()
{
base.OnAwake();
var idTag = Id.ToString().Substring( 0, 12 );
GameObject.Tags.Add( idTag );
Camera.RenderTags.Add( "light" );
Camera.RenderTags.Add( idTag );
Body.GameObject.Enabled = false;
_timeSinceCreated = -Random.Shared.Float( 0, 2f );
}
protected override void OnStart()
{
base.OnStart();
if ( !IsProxy )
{
ColorHue = Random.Shared.Float( 0, 360f );
GameMenu.Instance?.RequestCanvas();
}
CameraTexture = Texture.CreateRenderTarget( $"av_{Network.Owner.Id}", ImageFormat.RGBA8888, new( 128, 128 ) );
}
public void OnNetworkSpawn( Connection owner )
{
var clothing = new ClothingContainer();
clothing.Deserialize( owner.GetUserData( "avatar" ) );
if ( clothing.PrefersHuman )
{
Body.Model = Model.Load( "models/citizen_human/citizen_human_male.vmdl" );
}
clothing.Apply( Body );
Camera.LocalPosition = new Vector3( 32, 0, 112 * clothing.Height );
}
protected override void OnUpdate()
{
base.OnUpdate();
var isSeen = _timeSinceCreated >= 0f;
if ( isSeen && !_isIdle )
{
Body.Set( "special_idle_states", 1 );
Body.GameObject.Enabled = true;
_isIdle = true;
SetPose( 0 );
}
if ( Camera.IsValid() && CameraTexture is not null )
{
Camera.OrthographicHeight = 256;
Camera.RenderToTexture( CameraTexture );
}
Voice.Enabled = (HasGuessed == Local.HasGuessed) || !IsDrawing || (IsDrawing && Local.HasGuessed);
}
protected override void OnDestroy()
{
base.OnDestroy();
CameraTexture?.Dispose();
CameraTexture = null;
}
public void ApplyMorph( Dictionary<string, float> morphs )
{
foreach ( var name in Body.Morphs.Names )
{
Body.Morphs.Clear( name );
}
if ( morphs is null ) return;
foreach ( var morph in morphs )
{
Body.Morphs.Set( morph.Key, morph.Value );
}
}
public void SetPose( int pose )
{
Body.Set( "special_idle_states", pose == 0 ? 1 : 0 );
Body.Set( "holdtype_pose", pose );
}
public void ResetPose()
{
_timeSinceCreated = -Random.Shared.Float( 0, 2f );
_isIdle = false;
ApplyMorph( null );
}
public void SetWinPose()
{
var pose = WinningPoses[Random.Shared.Next( 0, WinningPoses.Length )];
SetPose( pose );
ApplyMorph( HappyMorph );
}
public void SetLosePose()
{
var pose = LosingPoses[Random.Shared.Next( 0, LosingPoses.Length )];
SetPose( pose );
ApplyMorph( AngryMorph );
}
[Rpc.Broadcast]
public void BroadcastResetPose()
{
ResetPose();
}
[Rpc.Broadcast]
public void BroadcastHappyMorph()
{
SetWinPose();
}
[Rpc.Broadcast]
public void BroadcastAngryMorph()
{
SetLosePose();
}
}