349 lines
14 KiB
C#
349 lines
14 KiB
C#
using Godot;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
public partial class Humanoid : CharacterBody3D {
|
|
Options _Options;
|
|
Reference _Reference;
|
|
|
|
[Export]
|
|
public AnimationTree Animator;
|
|
[Export]
|
|
public AnimQuickState CurrentAnimation;
|
|
[Export]
|
|
public Vector2 InputDirection;
|
|
|
|
UIMode CurrentUIMode = UIMode.Game;
|
|
(UIMode, Control)[] UIFrames;
|
|
public ProgressBar HealthBar;
|
|
ProgressBar StaminaBar;
|
|
public ITool EquippedTool;
|
|
Node Backpack;
|
|
|
|
public string PlayerName = "";
|
|
public float Health = 100;
|
|
public float MaxHealth = 100;
|
|
public float Stamina = 100;
|
|
public float MaxStamina = 100;
|
|
public float StaminaDrain = 5;
|
|
public float StaminaCharge = 5;
|
|
public float JumpStamina = 10;
|
|
public bool Running = false;
|
|
|
|
public float JumpVelocity = 5.5f;
|
|
public float RotationSpeed = 1f;
|
|
public float FallDistanceForDamage = 15;
|
|
public float FallDamageScale = 5f;
|
|
public Ability Ability;
|
|
public float Gravity = ProjectSettings.GetSetting( "physics/3d/default_gravity" ).AsSingle();
|
|
public bool mouseLock = true;
|
|
public float Speed {
|
|
get {
|
|
if( Running ) {
|
|
return 9f;
|
|
}
|
|
return 5f;
|
|
}
|
|
}
|
|
|
|
public override void _EnterTree() {
|
|
_Options = GetNode<Options>( "/root/Options" );
|
|
_Reference = GetNode<Reference>("/root/Reference");
|
|
|
|
string[] Data = Name.ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
string PID = Data[0];
|
|
string AID = Data[1];
|
|
PlayerName = Data[2];
|
|
|
|
this.SetMultiplayerAuthority( Convert.ToInt32(PID), true );
|
|
if( IsMultiplayerAuthority() ) {
|
|
_Reference.Humanoid = this;
|
|
_Options.isAlive = true;
|
|
_Reference.Humanoid = this;
|
|
_Reference.Camera = GetChild<Camera3D>( 0 );
|
|
_Reference.Camera.GetChild<AudioListener3D>(0).MakeCurrent();
|
|
_Reference.Camera.Current = true;
|
|
UIFrames = new (UIMode, Control) [] {
|
|
( UIMode.Game, GetNode<Control>( "/root/GameRoot/UI/GameUI/Game" ) ),
|
|
( UIMode.Inventory, GetNode<Control>( "/root/GameRoot/UI/GameUI/Inventory" ) ),
|
|
( UIMode.Pause, GetNode<Control>( "/root/GameRoot/UI/SettingsFrame" ) )
|
|
};
|
|
HealthBar = GetNode<ProgressBar>( "/root/GameRoot/UI/GameUI/Game/HealthBar" );
|
|
StaminaBar = GetNode<ProgressBar>( "/root/GameRoot/UI/GameUI/Game/StaminaBar" );
|
|
|
|
Input.MouseMode = Input.MouseModeEnum.ConfinedHidden;
|
|
|
|
SetUIMode( CurrentUIMode );
|
|
HealthBar.MaxValue = MaxHealth;
|
|
HealthBar.Value = Health;
|
|
StaminaBar.MaxValue = MaxStamina;
|
|
StaminaBar.Value = Stamina;
|
|
EquipTool( 0 );
|
|
|
|
List<Vector3> spawnPoints = new List<Vector3>();
|
|
foreach (Node3D cur in _Reference.PlayerSpawnPoints.GetChildren()){
|
|
spawnPoints.Add(cur.GlobalPosition);
|
|
}
|
|
|
|
int chosenSpawn = new Random(DateTime.Now.Millisecond).Next(0, spawnPoints.Count);
|
|
this.SetDeferred("global_position", spawnPoints[chosenSpawn]);
|
|
|
|
Ability _Ability = (Ability)Convert.ToInt32(AID);
|
|
if (_Ability == Ability.Vitality){
|
|
MaxHealth *= 1.25f;
|
|
Health = MaxHealth;
|
|
} else if ( _Ability == Ability.Stamina ){
|
|
MaxStamina *= 1.25f;
|
|
StaminaCharge *= 1.25f;
|
|
Stamina = MaxStamina;
|
|
} else if ( _Ability == Ability.Strength ){
|
|
_Reference.Inventory.UpdateMaxWeight(500);
|
|
}
|
|
GetNode<Node3D>("PlayerModel").Visible = false;
|
|
}
|
|
}
|
|
|
|
public enum AnimQuickState{
|
|
Idle,
|
|
Walk,
|
|
Run,
|
|
Jump
|
|
}
|
|
|
|
Vector3 GetMovement( float deltaTime ) {
|
|
|
|
// Copy current velocity off the CharacterBody3d
|
|
Vector3 velocity = Velocity;
|
|
|
|
if( CurrentUIMode == UIMode.Game ) {
|
|
// Add the gravity.
|
|
if ( IsOnFloor() ) {
|
|
if ( Input.GetActionStrength( "Jump" ) == 1 && Stamina >= JumpStamina ) {
|
|
CurrentAnimation = AnimQuickState.Jump;
|
|
Stamina -= JumpStamina;
|
|
velocity.Y = JumpVelocity;
|
|
}
|
|
} else {
|
|
CurrentAnimation = AnimQuickState.Idle;
|
|
velocity.Y -= Gravity * deltaTime;
|
|
}
|
|
|
|
if (Running && Stamina <= 0){
|
|
Running = false;
|
|
}
|
|
|
|
// Get the input direction and handle the movement/deceleration.
|
|
Vector2 inputDir = Input.GetVector("Left", "Right", "Forward", "Backward");
|
|
Vector3 direction = (Transform.Basis * new Vector3(inputDir.X, 0, inputDir.Y)).Normalized();
|
|
if( direction != Vector3.Zero ) { // If there was input
|
|
velocity.X = direction.X * Speed;
|
|
velocity.Z = direction.Z * Speed;
|
|
if (Running){
|
|
Stamina -= deltaTime * StaminaDrain;
|
|
StaminaBar.Value = Stamina;
|
|
StaminaBar.MaxValue = MaxStamina;
|
|
CurrentAnimation = AnimQuickState.Run;
|
|
InputDirection = inputDir;
|
|
}else{
|
|
if (Stamina < MaxStamina){
|
|
Stamina += deltaTime * StaminaCharge / 2;
|
|
StaminaBar.Value = Stamina;
|
|
StaminaBar.MaxValue = MaxStamina;
|
|
}
|
|
CurrentAnimation = AnimQuickState.Walk;
|
|
InputDirection = inputDir;
|
|
}
|
|
} else { // If there was no input
|
|
velocity.X = Mathf.MoveToward( Velocity.X, 0, Speed );
|
|
velocity.Z = Mathf.MoveToward( Velocity.Z, 0, Speed );
|
|
if (Stamina < MaxStamina){
|
|
Stamina += deltaTime * StaminaCharge;
|
|
StaminaBar.Value = Stamina;
|
|
StaminaBar.MaxValue = MaxStamina;
|
|
}
|
|
CurrentAnimation = AnimQuickState.Idle;
|
|
}
|
|
} else {
|
|
velocity = new Vector3 (
|
|
Mathf.MoveToward( Velocity.X, 0, Speed /6 ),
|
|
velocity.Y - (Gravity * deltaTime),
|
|
Mathf.MoveToward( Velocity.Z, 0, Speed /6 )
|
|
);
|
|
if (Stamina < MaxStamina){
|
|
Stamina += deltaTime * StaminaCharge;
|
|
StaminaBar.Value = Stamina;
|
|
StaminaBar.MaxValue = MaxStamina;
|
|
}
|
|
CurrentAnimation = AnimQuickState.Idle;
|
|
}
|
|
|
|
return velocity;
|
|
}
|
|
|
|
public void EquipTool(int BackpackIndex ) {
|
|
if( Backpack == null ) {
|
|
Backpack = GetNode<Node>( "/root/GameRoot/UI/GameUI/Game/ToolBar" );
|
|
}
|
|
var Children = Backpack.GetChildren();
|
|
if( Children.Count > BackpackIndex ) {
|
|
foreach( Label cur in Children ) {
|
|
cur.Modulate = new Color( 1, 1, 1 );
|
|
}
|
|
if (EquippedTool != null ) {
|
|
EquippedTool.UnEquipped();
|
|
}
|
|
// If same button is pressed put tool away
|
|
Label UILabel = Backpack.GetChild<Label>( BackpackIndex );
|
|
UILabel.Modulate = new Color(1,0,1);
|
|
EquippedTool = ( ITool )UILabel.GetChild(0);
|
|
EquippedTool.Equiped();
|
|
}
|
|
}
|
|
|
|
enum UIMode {
|
|
Game,
|
|
Inventory,
|
|
Pause
|
|
}
|
|
|
|
void SetUIMode(UIMode mode) {
|
|
if (CurrentUIMode == UIMode.Inventory ) {
|
|
foreach( var cur in UIFrames ) {
|
|
if( cur.Item1 == UIMode.Inventory ) {
|
|
Inventory inv = (Inventory)cur.Item2;
|
|
if( inv._splitFrame != null ) {
|
|
inv._splitFrame.Free();
|
|
inv._splitFrame = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CurrentUIMode = mode;
|
|
foreach (var cur in UIFrames) {
|
|
if (cur.Item1 == mode) {
|
|
cur.Item2.Visible = true;
|
|
} else {
|
|
cur.Item2.Visible = false;
|
|
}
|
|
}
|
|
if (mode == UIMode.Game) {
|
|
Input.MouseMode = Input.MouseModeEnum.Captured;
|
|
mouseLock = true;
|
|
} else {
|
|
Input.MouseMode = Input.MouseModeEnum.Visible;
|
|
mouseLock = false;
|
|
}
|
|
}
|
|
|
|
public override void _Input( InputEvent _event ) {
|
|
if( IsMultiplayerAuthority() ) {
|
|
if( _event is InputEventKey eventKey ) {
|
|
int KeyCode = (int)eventKey.PhysicalKeycode;
|
|
if( eventKey.Keycode == Key.Escape ) {
|
|
if( eventKey.Pressed ) {
|
|
if( CurrentUIMode != UIMode.Pause ) {
|
|
SetUIMode( UIMode.Pause );
|
|
} else {
|
|
SetUIMode( UIMode.Game );
|
|
}
|
|
}
|
|
} else if( eventKey.Keycode == Key.Tab ) {
|
|
if( eventKey.Pressed ) {
|
|
if( CurrentUIMode != UIMode.Inventory ) {
|
|
SetUIMode( UIMode.Inventory );
|
|
} else {
|
|
SetUIMode( UIMode.Game );
|
|
}
|
|
}
|
|
}
|
|
if( CurrentUIMode == UIMode.Game ) {
|
|
if( eventKey.Keycode == Key.Shift ) {
|
|
if( eventKey.Pressed && Stamina > 0 ) {
|
|
Running = true;
|
|
} else {
|
|
Running = false;
|
|
}
|
|
} else if( eventKey.Pressed && KeyCode >= 49 && KeyCode <= 57 ) {
|
|
EquipTool( KeyCode - 49 );
|
|
} else if( eventKey.Pressed ) {
|
|
if( EquippedTool != null ) {
|
|
EquippedTool.KeyPress( eventKey.Keycode );
|
|
}
|
|
} else if( !eventKey.Pressed ) {
|
|
if( EquippedTool != null ) {
|
|
EquippedTool.KeyRelease( eventKey.Keycode );
|
|
}
|
|
}
|
|
}
|
|
} else if ( _event is InputEventMouseMotion ) {
|
|
if( mouseLock ) {
|
|
InputEventMouseMotion inputEventMouseMotion = (InputEventMouseMotion)_event;
|
|
Vector2 LookChange = inputEventMouseMotion.Relative;
|
|
|
|
// Horizontal Rotation
|
|
RotateY( LookChange.X * RotationSpeed * -0.002f );
|
|
// Vertical Rotation
|
|
_Reference.Camera.RotateX( LookChange.Y * RotationSpeed * -0.002f );
|
|
if( _Reference.Camera.RotationDegrees.X < -90 ) {
|
|
_Reference.Camera.RotationDegrees = new Vector3( -90, _Reference.Camera.RotationDegrees.Y, _Reference.Camera.RotationDegrees.Z );
|
|
} else if( _Reference.Camera.RotationDegrees.X > 90 ) {
|
|
_Reference.Camera.RotationDegrees = new Vector3( 90, _Reference.Camera.RotationDegrees.Y, _Reference.Camera.RotationDegrees.Z );
|
|
}
|
|
}
|
|
} else if ( _event is InputEventMouseButton _mouseevent ) {
|
|
if( mouseLock ) {
|
|
if( _mouseevent.ButtonIndex == MouseButton.Left ) {
|
|
if( EquippedTool != null && _mouseevent.Pressed ) {
|
|
EquippedTool.LeftMouseDown();
|
|
} else if( EquippedTool != null && !_mouseevent.Pressed ) {
|
|
EquippedTool.LeftMouseUp();
|
|
}
|
|
} else if( _mouseevent.ButtonIndex == MouseButton.Right ) {
|
|
if( EquippedTool != null && _mouseevent.Pressed ) {
|
|
EquippedTool.RightMouseDown();
|
|
} else if( EquippedTool != null && !_mouseevent.Pressed ) {
|
|
EquippedTool.RightMouseUp();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetAnimation(){
|
|
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)Animator.Get("parameters/playback");
|
|
stateMachine.Travel( CurrentAnimation.ToString() );
|
|
Animator.Set("parameters/Walk/BlendSpace2D/blend_position", InputDirection);
|
|
Animator.Set("parameters/Run/BlendSpace2D/blend_position", InputDirection);
|
|
}
|
|
|
|
float LastY = -1;
|
|
public override void _PhysicsProcess( double _dT ) {
|
|
SetAnimation();
|
|
if( IsMultiplayerAuthority() ) {
|
|
float deltaTime = Convert.ToSingle( _dT );
|
|
|
|
// Fall Damage
|
|
if( IsOnFloor() ) {
|
|
if( LastY != -1 ) {
|
|
float FallDistance = LastY - GlobalPosition.Y;
|
|
if( FallDistance > FallDistanceForDamage ) {
|
|
_Reference.GameHandler.TakeDamage( (FallDistance - FallDistanceForDamage) * FallDamageScale, 0, Multiplayer.GetUniqueId() );
|
|
}
|
|
LastY = -1;
|
|
}
|
|
} else {
|
|
if( LastY == -1 ) {
|
|
LastY = GlobalPosition.Y;
|
|
}
|
|
}
|
|
|
|
// Copy the Velocity back onto the CharacterBody3d
|
|
Velocity = GetMovement( deltaTime );
|
|
// Apply Motion
|
|
MoveAndSlide();
|
|
}
|
|
}
|
|
|
|
} |