UI/Puzzle/LockPanelInspector.cs
using Opium;
using Sandbox.UI;
using Sandbox.UI.Construct;
using static CombinationLockInteractor;
using static LockPanelInspector.Lock;
public class LockPanelInspector : Panel
{
public LockType LockType { get; set; }
public string StartingCombination { get; set; } = "1234";
public CombinationLockInteractor CombinationLockInteractor { get; set; }
public CombinationLockUI CombinationLockUI { get; set; }
private SceneWorld World;
private ScenePanel ScenePanel;
private Vector3 camoffset;
protected override void OnParametersSet()
{
base.OnParametersSet();
Rebuild();
}
public void Rebuild()
{
ScenePanel?.Delete( true );
ScenePanel = null;
World?.Delete();
World = null;
World = new();
CreatePadLock( LockType );
PadLockModel.SetMaterialGroup( "view" );
PadLockModel.Attributes.SetCombo( "D_VERTEX_SNAP", 0 );
camoffset = Vector3.Backward * 8;
camoffset += Vector3.Left * 2.5f + Vector3.Down * 3f;
var camrot = Rotation.From( 0, 0, -90 );
camrot *= Rotation.From( 15, -20, 0 );
ScenePanel = Add.ScenePanel( World, camoffset, camrot, 75 );
new SceneDirectionalLight( World, Rotation.From( 50, 40, 0 ), Color.White * 1.0f + Color.Cyan * 0.05f );
ScenePanel.Style.Width = Length.Percent( 100 );
ScenePanel.Style.Height = Length.Percent( 100 );
}
public override void Tick()
{
base.Tick();
if ( CombinationLockInteractor.Type == LockType.PadlockA )
{
if ( Input.Pressed( "left" ) ) PreviousDial();
if ( Input.Pressed( "right" ) ) NextDial();
if ( Input.Pressed( "forward" ) ) DecreaseDial();
if ( Input.Pressed( "backward" ) ) IncreaseDial();
}
else if ( CombinationLockInteractor.Type == LockType.PadlockB )
{
if ( Input.Pressed( "left" ) ) DecreaseDial();
if ( Input.Pressed( "right" ) ) IncreaseDial();
if ( Input.Pressed( "forward" ) ) PreviousDial();
if ( Input.Pressed( "backward" ) ) NextDial();
}
else if ( CombinationLockInteractor.Type == LockType.PadLockC )
{
if ( Input.Pressed( "left" ) ) PreviousDial();
if ( Input.Pressed( "right" ) ) NextDial();
if ( Input.Pressed( "forward" ) ) IncreaseDial();
if ( Input.Pressed( "backward" ) ) DecreaseDial();
}
if ( Input.Pressed( "use" ) )
{
if ( CombinationLockInteractor.CurrentCombination == CombinationLockInteractor.Solution )
{
CombinationLockUI.Solved = true;
CombinationLockUI.Submit();
}
}
UpdateDialSelection();
}
public Dial Dials;
SceneModel PadLockModel { get; set; }
void IncreaseDial()
{
var currentDial = GetCurrentDial();
currentDial.CurrentNumber = (currentDial.CurrentNumber + 1) % 10;
currentDial.UpdateRotation();
CombinationLockInteractor.Edited = true;
Sound.Play( "combolock_dial_01" );
}
void DecreaseDial()
{
var currentDial = GetCurrentDial();
currentDial.CurrentNumber = (currentDial.CurrentNumber - 1 + 10) % 10;
currentDial.UpdateRotation();
CombinationLockInteractor.Edited = true;
Sound.Play( "combolock_dial_01" );
}
void PreviousDial()
{
GetCurrentDial().Selected = false;
activeDialIndex = (activeDialIndex - 1 + dials.Count) % dials.Count;
GetCurrentDial().Selected = true;
}
void NextDial()
{
GetCurrentDial().Selected = false;
activeDialIndex = (activeDialIndex + 1) % dials.Count;
GetCurrentDial().Selected = true;
}
void UpdateDialSelection()
{
foreach ( var dial in dials )
{
dial.SetSelectedMaterial();
}
if ( lockType != LockType.PadLockC )
{
CombinationLockInteractor.CurrentCombination = $"{dial1.CurrentNumber}{dial2.CurrentNumber}{dial3.CurrentNumber}{dial4.CurrentNumber}";
}
else
{
CombinationLockInteractor.CurrentCombination = $"{dial1.CurrentNumber}{dial2.CurrentNumber}{dial3.CurrentNumber}{dial4.CurrentNumber}{dial5.CurrentNumber}";
}
}
Dial GetCurrentDial()
{
return dials[activeDialIndex];
}
Dial dial1;
Dial dial2;
Dial dial3;
Dial dial4;
Dial dial5;
List<Dial> dials = new List<Dial> { };
LockType lockType { get; set; }
int activeDialIndex = 0;
void CreatePadLock( LockType type )
{
lockType = type;
if ( type == LockType.PadlockA )
{
var offset = new Vector3( 0, 0, 0 );
//Create Padlock A
PadLockModel = new SceneModel( World, "models/interact/padlocks/padlock_a.vmdl", Transform.Zero );
PadLockModel.SetMaterialGroup( "view" );
PadLockModel.Position = offset;
PadLockModel.Rotation = Rotation.From( 0, 180, 90f );
PadLockModel.SetBodyGroup( "wheels", 1 );
var selectedDial = Material.Load( "models/interact/padlocks/padlock_a_selected.vmat" );
dial1 = new Lock.Dial();
dial1.Model = new SceneModel( World, "models/interact/padlocks/padlock_a_wheel.vmdl", Transform.Zero );
dial1.Number = 1;
dial1.Model.SetMaterialGroup( "view" );
dial1.Model.Position = new Vector3( 0, 0, 0 );
dial1.Selected = true;
dial1.SelectedMaterial = selectedDial;
dials.Add( dial1 );
dial1.UpdateRotation();
dial1.Type = type;
dial2 = new Lock.Dial();
dial2.Model = new SceneModel( World, "models/interact/padlocks/padlock_a_wheel.vmdl", Transform.Zero );
dial2.Number = 2;
dial2.Model.SetMaterialGroup( "view" );
dial2.Model.Position = new Vector3( 0, 0, 0.615f );
dial2.Selected = false;
dial2.SelectedMaterial = selectedDial;
dials.Add( dial2 );
dial2.UpdateRotation();
dial2.Type = type;
dial3 = new Lock.Dial();
dial3.Model = new SceneModel( World, "models/interact/padlocks/padlock_a_wheel.vmdl", Transform.Zero );
dial3.Number = 3;
dial3.Model.SetMaterialGroup( "view" );
dial3.Model.Position = new Vector3( 0, 0, 1.23f );
dial3.Selected = false;
dial3.SelectedMaterial = selectedDial;
dials.Add( dial3 );
dial3.UpdateRotation();
dial3.Type = type;
dial4 = new Lock.Dial();
dial4.Model = new SceneModel( World, "models/interact/padlocks/padlock_a_wheel.vmdl", Transform.Zero );
dial4.Number = 4;
dial4.Model.SetMaterialGroup( "view" );
dial4.Model.Position = new Vector3( 0, 0, 1.845f );
dial4.Selected = false;
dial4.SelectedMaterial = selectedDial;
dials.Add( dial4 );
dial4.UpdateRotation();
dial4.Type = type;
if ( StartingCombination.Length == 4 && StartingCombination.All( char.IsDigit ) )
{
// Parse each character to set the CurrentNumber for each dial
dial1.CurrentNumber = int.Parse( StartingCombination[0].ToString() );
dial2.CurrentNumber = int.Parse( StartingCombination[1].ToString() );
dial3.CurrentNumber = int.Parse( StartingCombination[2].ToString() );
dial4.CurrentNumber = int.Parse( StartingCombination[3].ToString() );
// Make sure to call UpdateRotation() for each dial here if necessary
dial1.UpdateRotation();
dial2.UpdateRotation();
dial3.UpdateRotation();
dial4.UpdateRotation();
}
}
else if ( type == LockType.PadlockB )
{
//Create Padlock B
PadLockModel = new SceneModel( World, "models/interact/padlocks/padlock_b.vmdl", Transform.Zero );
PadLockModel.SetMaterialGroup( "view" );
PadLockModel.Rotation = Rotation.From( 0, 180, 90f );
PadLockModel.SetBodyGroup( "wheels", 1 );
var selectedDial = Material.Load( "models/interact/padlocks/padlock_b_selected.vmat" );
dial1 = new Lock.Dial();
dial1.Model = new SceneModel( World, "models/interact/padlocks/padlock_b_wheel.vmdl", Transform.Zero );
dial1.Number = 1;
dial1.Model.SetMaterialGroup( "view" );
dial1.Model.Position = new Vector3( 0, 0, 0 );
dial1.Selected = true;
dial1.SelectedMaterial = selectedDial;
dials.Add( dial1 );
dial1.Type = type;
dial1.UpdateRotation();
dial2 = new Lock.Dial();
dial2.Model = new SceneModel( World, "models/interact/padlocks/padlock_b_wheel.vmdl", Transform.Zero );
dial2.Number = 2;
dial2.Model.SetMaterialGroup( "view" );
dial2.Model.Position = new Vector3( 0, -0.666f, 0 );
dial2.Selected = false;
dial2.SelectedMaterial = selectedDial;
dials.Add( dial2 );
dial2.Type = type;
dial2.UpdateRotation();
dial3 = new Lock.Dial();
dial3.Model = new SceneModel( World, "models/interact/padlocks/padlock_b_wheel.vmdl", Transform.Zero );
dial3.Number = 3;
dial3.Model.SetMaterialGroup( "view" );
dial3.Model.Position = new Vector3( 0, -1.332f, 0 );
dial3.Selected = false;
dial3.SelectedMaterial = selectedDial;
dials.Add( dial3 );
dial3.Type = type;
dial3.UpdateRotation();
dial4 = new Lock.Dial();
dial4.Model = new SceneModel( World, "models/interact/padlocks/padlock_b_wheel.vmdl", Transform.Zero );
dial4.Number = 4;
dial4.Model.SetMaterialGroup( "view" );
dial4.Model.Position = new Vector3( 0, -2f, 0 );
dial4.Selected = false;
dial4.SelectedMaterial = selectedDial;
dials.Add( dial4 );
dial4.Type = type;
dial4.UpdateRotation();
if ( StartingCombination.Length == 4 && StartingCombination.All( char.IsDigit ) )
{
// Parse each character to set the CurrentNumber for each dial
dial1.CurrentNumber = int.Parse( StartingCombination[0].ToString() );
dial2.CurrentNumber = int.Parse( StartingCombination[1].ToString() );
dial3.CurrentNumber = int.Parse( StartingCombination[2].ToString() );
dial4.CurrentNumber = int.Parse( StartingCombination[3].ToString() );
// Make sure to call UpdateRotation() for each dial here if necessary
dial1.UpdateRotation();
dial2.UpdateRotation();
dial3.UpdateRotation();
dial4.UpdateRotation();
}
}
else if ( type == LockType.PadLockC )
{
PadLockModel = new SceneModel( World, "models/interact/padlocks/padlock_c.vmdl", Transform.Zero );
PadLockModel.SetMaterialGroup( "view" );
PadLockModel.Rotation = Rotation.From( 0, 180, 90f );
PadLockModel.SetBodyGroup( "wheels", 1 );
var selectedDial = Material.Load( "models/interact/padlocks/padlock_c_selected.vmat" );
dial1 = new Lock.Dial();
dial1.Model = new SceneModel( World, "models/interact/padlocks/padlock_c_wheel.vmdl", Transform.Zero );
dial1.Number = 1;
dial1.Model.SetMaterialGroup( "view" );
dial1.Model.Position = new Vector3( 0, 0, -0.69f );
dial1.Selected = true;
dial1.SelectedMaterial = selectedDial;
dials.Add( dial1 );
dial1.Type = type;
dial1.UpdateRotation();
dial2 = new Lock.Dial();
dial2.Model = new SceneModel( World, "models/interact/padlocks/padlock_c_wheel.vmdl", Transform.Zero );
dial2.Number = 2;
dial2.Model.SetMaterialGroup( "view" );
dial2.Model.Position = new Vector3( 0, 0, -0.265f );
dial2.Selected = false;
dial2.SelectedMaterial = selectedDial;
dials.Add( dial2 );
dial2.Type = type;
dial2.UpdateRotation();
dial3 = new Lock.Dial();
dial3.Model = new SceneModel( World, "models/interact/padlocks/padlock_c_wheel.vmdl", Transform.Zero );
dial3.Number = 3;
dial3.Model.SetMaterialGroup( "view" );
dial3.Model.Position = new Vector3( 0, 0, 0.1575f );
dial3.Selected = false;
dial3.SelectedMaterial = selectedDial;
dial3.Type = type;
dials.Add( dial3 );
dial3.UpdateRotation();
dial4 = new Lock.Dial();
dial4.Model = new SceneModel( World, "models/interact/padlocks/padlock_c_wheel.vmdl", Transform.Zero );
dial4.Number = 4;
dial4.Model.SetMaterialGroup( "view" );
dial4.Model.Position = new Vector3( 0, 0, 0.58f );
dial4.Selected = false;
dial4.SelectedMaterial = selectedDial;
dial4.Type = type;
dials.Add( dial4 );
dial4.UpdateRotation();
dial5 = new Lock.Dial();
dial5.Model = new SceneModel( World, "models/interact/padlocks/padlock_c_wheel.vmdl", Transform.Zero );
dial5.Number = 5;
dial5.Model.SetMaterialGroup( "view" );
dial5.Model.Position = new Vector3( 0, 0, 1.0f );
dial5.Selected = false;
dial5.SelectedMaterial = selectedDial;
dial5.Type = type;
dials.Add( dial5 );
dial5.UpdateRotation();
if ( StartingCombination.Length == 5 && StartingCombination.All( char.IsDigit ) )
{
// Parse each character to set the CurrentNumber for each dial
dial1.CurrentNumber = int.Parse( StartingCombination[0].ToString() );
dial2.CurrentNumber = int.Parse( StartingCombination[1].ToString() );
dial3.CurrentNumber = int.Parse( StartingCombination[2].ToString() );
dial4.CurrentNumber = int.Parse( StartingCombination[3].ToString() );
dial5.CurrentNumber = int.Parse( StartingCombination[4].ToString() );
// Make sure to call UpdateRotation() for each dial here if necessary
dial1.UpdateRotation();
dial2.UpdateRotation();
dial3.UpdateRotation();
dial4.UpdateRotation();
dial5.UpdateRotation();
}
}
}
public class Lock
{
public class Dial
{
public int Number { get; set; }
public int CurrentNumber { get; set; }
public SceneModel Model { get; set; }
public bool Selected { get; set; } = false;
public Material SelectedMaterial { get; set; }
public Material DefaultMaterial { get; set; }
public LockType Type { get; set; }
public void SetSelectedMaterial()
{
if ( Selected )
{
Model.SetMaterialGroup( "selected" );
}
else
Model.SetMaterialGroup( "view" );
}
public void UpdateRotation()
{
float rotation = -36 * CurrentNumber;
if ( Type == LockType.PadlockA )
{
Model.Rotation = Rotation.From( 180, rotation, 270 );
}
else if ( Type == LockType.PadlockB )
{
Model.Rotation = Rotation.From( -rotation, 180, 90 );
}
else if ( Type == LockType.PadLockC )
{
Model.Rotation = Rotation.From( 180, -rotation, 270 );
}
}
}
}
}