2022-11-10 20:29:53 -08:00
|
|
|
using Godot;
|
2022-11-25 09:11:46 -08:00
|
|
|
using SupaLidlGame.Extensions;
|
2022-11-19 21:21:12 -08:00
|
|
|
using SupaLidlGame.Items;
|
|
|
|
using SupaLidlGame.Utils;
|
2022-11-10 20:29:53 -08:00
|
|
|
|
|
|
|
namespace SupaLidlGame.Characters
|
|
|
|
{
|
2022-11-19 21:21:12 -08:00
|
|
|
public partial class Character : CharacterBody2D, IFaction
|
2022-11-10 20:29:53 -08:00
|
|
|
{
|
2022-11-12 16:45:04 -08:00
|
|
|
[Export]
|
2022-11-18 13:53:51 -08:00
|
|
|
public float Speed { get; protected set; } = 32.0f;
|
2022-11-12 16:45:04 -08:00
|
|
|
|
2022-11-25 09:11:46 -08:00
|
|
|
[Export]
|
|
|
|
public float Friction { get; protected set; } = 4.0f;
|
|
|
|
|
2022-11-13 19:52:09 -08:00
|
|
|
[Export]
|
|
|
|
public float Mass
|
|
|
|
{
|
|
|
|
get => _mass;
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (value > 0)
|
|
|
|
_mass = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float _mass = 1.0f;
|
|
|
|
|
2022-11-10 20:29:53 -08:00
|
|
|
public float JumpVelocity { get; protected set; } = -400.0f;
|
2022-11-13 19:52:09 -08:00
|
|
|
|
2022-11-10 20:29:53 -08:00
|
|
|
public float AccelerationMagnitude { get; protected set; } = 256.0f;
|
|
|
|
|
|
|
|
public Vector2 Acceleration => Direction * AccelerationMagnitude;
|
|
|
|
|
2022-11-25 09:11:46 -08:00
|
|
|
public Vector2 NetImpulse { get; set; } = Vector2.Zero;
|
|
|
|
|
2022-11-13 15:42:04 -08:00
|
|
|
public Vector2 Direction { get; set; } = Vector2.Zero;
|
|
|
|
|
|
|
|
public Vector2 Target { get; set; } = Vector2.Zero;
|
|
|
|
|
2022-11-25 09:11:46 -08:00
|
|
|
[Export]
|
2022-11-19 21:21:12 -08:00
|
|
|
public float Health
|
|
|
|
{
|
|
|
|
get => _health;
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (!IsAlive && value < 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_health = value;
|
|
|
|
GD.Print(_health);
|
|
|
|
if (_health <= 0)
|
|
|
|
{
|
|
|
|
Die();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-25 09:11:46 -08:00
|
|
|
public bool IsAlive => Health > 0;
|
|
|
|
|
2022-11-19 21:21:12 -08:00
|
|
|
protected float _health = 100f;
|
|
|
|
|
2022-11-25 09:11:46 -08:00
|
|
|
public double StunTime { get; set; }
|
2022-11-19 21:21:12 -08:00
|
|
|
|
|
|
|
[Export]
|
|
|
|
public AnimatedSprite2D Sprite { get; set; }
|
|
|
|
|
|
|
|
[Export]
|
|
|
|
public Inventory Inventory { get; set; }
|
2022-11-13 19:52:09 -08:00
|
|
|
|
2022-11-13 15:42:04 -08:00
|
|
|
[Export]
|
|
|
|
public State.Machine StateMachine { get; set; }
|
2022-11-10 20:29:53 -08:00
|
|
|
|
2022-11-19 21:21:12 -08:00
|
|
|
[Export]
|
|
|
|
public ushort Faction { get; set; }
|
|
|
|
|
2022-11-10 20:29:53 -08:00
|
|
|
public override void _Process(double delta)
|
|
|
|
{
|
2022-11-13 15:42:04 -08:00
|
|
|
if (StateMachine != null)
|
|
|
|
{
|
|
|
|
StateMachine.Process(delta);
|
|
|
|
}
|
2022-11-19 21:21:12 -08:00
|
|
|
|
2023-01-29 12:05:44 -08:00
|
|
|
Sprite.FlipH = Target.X < 0;
|
2022-11-19 21:21:12 -08:00
|
|
|
DrawTarget();
|
2022-11-13 15:42:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public override void _Input(InputEvent @event)
|
|
|
|
{
|
|
|
|
if (StateMachine != null)
|
|
|
|
{
|
|
|
|
StateMachine.Input(@event);
|
|
|
|
}
|
2022-11-10 20:29:53 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
|
|
{
|
2022-11-13 15:42:04 -08:00
|
|
|
if (StateMachine != null)
|
|
|
|
{
|
|
|
|
StateMachine.PhysicsProcess(delta);
|
|
|
|
}
|
2022-11-10 20:29:53 -08:00
|
|
|
}
|
2022-11-13 19:52:09 -08:00
|
|
|
|
2022-11-19 21:21:12 -08:00
|
|
|
/// <summary>
|
|
|
|
/// Modify the <c>Character</c>'s velocity
|
|
|
|
/// </summary>
|
|
|
|
public virtual void ModifyVelocity()
|
|
|
|
{
|
2022-11-25 09:11:46 -08:00
|
|
|
if (StunTime > 0)
|
|
|
|
{
|
|
|
|
Velocity *= 0.25f;
|
|
|
|
}
|
2022-11-19 21:21:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public virtual void Die()
|
|
|
|
{
|
|
|
|
GD.Print("lol died");
|
|
|
|
QueueFree();
|
|
|
|
}
|
|
|
|
|
2022-11-13 19:52:09 -08:00
|
|
|
public void ApplyImpulse(Vector2 impulse, bool resetVelocity = false)
|
|
|
|
{
|
|
|
|
// delta p = F delta t
|
|
|
|
if (resetVelocity)
|
|
|
|
Velocity = Vector2.Zero;
|
2022-11-25 09:11:46 -08:00
|
|
|
NetImpulse += impulse / Mass;
|
|
|
|
}
|
|
|
|
|
|
|
|
public virtual void Stun(float time)
|
|
|
|
{
|
|
|
|
StunTime += time;
|
2022-11-13 19:52:09 -08:00
|
|
|
}
|
|
|
|
|
2022-11-19 21:21:12 -08:00
|
|
|
protected void DrawTarget()
|
|
|
|
{
|
|
|
|
Vector2 target = Target;
|
2023-01-29 12:05:44 -08:00
|
|
|
float angle = Mathf.Atan2(target.Y, Mathf.Abs(target.X));
|
2022-11-19 21:21:12 -08:00
|
|
|
Vector2 scale = Inventory.Scale;
|
2023-01-29 12:05:44 -08:00
|
|
|
if (target.X < 0)
|
2022-11-19 21:21:12 -08:00
|
|
|
{
|
2023-01-29 12:05:44 -08:00
|
|
|
scale.Y = -1;
|
2022-11-19 21:21:12 -08:00
|
|
|
angle = Mathf.Pi - angle;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-01-29 12:05:44 -08:00
|
|
|
scale.Y = 1;
|
2022-11-19 21:21:12 -08:00
|
|
|
}
|
|
|
|
Inventory.Scale = scale;
|
|
|
|
Inventory.Rotation = angle;
|
|
|
|
}
|
|
|
|
|
2022-11-25 09:11:46 -08:00
|
|
|
public void UseCurrentItem()
|
|
|
|
{
|
|
|
|
if (StunTime > 0)
|
|
|
|
{
|
|
|
|
GD.Print("tried to use weapon but stunned");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Inventory.SelectedItem is Weapon weapon)
|
|
|
|
{
|
|
|
|
weapon.Use();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-25 11:59:55 -08:00
|
|
|
public virtual void _on_hurtbox_received_damage(
|
|
|
|
float damage,
|
2022-11-19 21:21:12 -08:00
|
|
|
Character inflictor,
|
|
|
|
float knockback,
|
|
|
|
Vector2 knockbackOrigin = default,
|
|
|
|
Vector2 knockbackVector = default)
|
2022-11-13 19:52:09 -08:00
|
|
|
{
|
|
|
|
Health -= damage;
|
2022-11-25 09:11:46 -08:00
|
|
|
|
2022-11-25 11:59:55 -08:00
|
|
|
// create damage text
|
2022-11-25 09:11:46 -08:00
|
|
|
var textScene = GD.Load<PackedScene>("res://UI/FloatingText.tscn");
|
|
|
|
var instance = textScene.Instantiate<UI.FloatingText>();
|
|
|
|
instance.Text = Mathf.Round(damage).ToString();
|
|
|
|
instance.GlobalPosition = GlobalPosition;
|
|
|
|
this.GetAncestor<TileMap>().AddChild(instance);
|
|
|
|
|
2022-11-25 11:59:55 -08:00
|
|
|
// apply knockback
|
2022-11-19 21:21:12 -08:00
|
|
|
Vector2 knockbackDir = knockbackVector;
|
|
|
|
if (knockbackDir == default)
|
|
|
|
{
|
|
|
|
if (knockbackOrigin == default)
|
|
|
|
{
|
|
|
|
knockbackOrigin = inflictor.GlobalPosition;
|
|
|
|
}
|
|
|
|
|
|
|
|
knockbackDir = knockbackOrigin.DirectionTo(GlobalPosition);
|
|
|
|
}
|
|
|
|
|
2022-11-25 11:59:55 -08:00
|
|
|
ApplyImpulse(knockbackDir.Normalized() * knockback);
|
|
|
|
|
|
|
|
// play damage animation
|
|
|
|
var anim = GetNode<AnimationPlayer>("FlashAnimation");
|
|
|
|
if (anim != null)
|
2022-11-25 09:11:46 -08:00
|
|
|
{
|
2022-11-25 11:59:55 -08:00
|
|
|
anim.Stop();
|
|
|
|
anim.Play("Hurt");
|
2022-11-25 09:11:46 -08:00
|
|
|
}
|
|
|
|
|
2022-11-25 11:59:55 -08:00
|
|
|
// if anyone involved is a player, shake their screen
|
|
|
|
Player plr = inflictor as Player ?? this as Player;
|
|
|
|
if (plr is not null)
|
|
|
|
{
|
2022-11-26 14:53:24 -08:00
|
|
|
plr.Camera.Shake(1, 0.4f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.GetNode("HurtSound") is AudioStreamPlayer2D sound)
|
|
|
|
{
|
2023-03-19 23:36:36 -07:00
|
|
|
// very small pitch deviation
|
|
|
|
sound.At(GlobalPosition).WithPitchDeviation(0.125f).Play();
|
2022-11-25 11:59:55 -08:00
|
|
|
}
|
2022-11-13 19:52:09 -08:00
|
|
|
}
|
2022-11-10 20:29:53 -08:00
|
|
|
}
|
|
|
|
}
|