diff --git a/Characters/Character.cs b/Characters/Character.cs
index 7546533..168b31d 100644
--- a/Characters/Character.cs
+++ b/Characters/Character.cs
@@ -26,9 +26,6 @@ public partial class Character : CharacterBody2D, IFaction
}
}
- [Export]
- public float Stealth { get; protected set; } = 0;
-
[Signal]
public delegate void HealthChangedEventHandler(Events.HealthChangedArgs args);
@@ -168,6 +165,9 @@ public partial class Character : CharacterBody2D, IFaction
}
}
+ ///
+ /// Handles the Character's death.
+ ///
public virtual void Die()
{
if (HurtAnimation.HasAnimation("death"))
@@ -190,11 +190,20 @@ public partial class Character : CharacterBody2D, IFaction
NetImpulse += impulse / Mass;
}
+ ///
+ /// Stuns the Chararacter for an amount of time. If
+ /// is less than the Character's current
+ /// stun time left, it will have no effect.
+ ///
public virtual void Stun(float time)
{
StunTime = Mathf.Max(time, StunTime);
}
+ ///
+ /// Draws the character so that its sprite and inventory items face the
+ /// character's direction.
+ ///
protected virtual void DrawTarget()
{
Vector2 target = Target;
@@ -213,6 +222,10 @@ public partial class Character : CharacterBody2D, IFaction
Inventory.Rotation = angle;
}
+ ///
+ /// Use the current item the character is using. Prefer to call this over
+ /// Item.Use as it will check if the character is stunned or alive.
+ ///
public void UseCurrentItem()
{
if (StunTime > 0 || !IsAlive)
@@ -264,6 +277,9 @@ public partial class Character : CharacterBody2D, IFaction
}
}
+ ///
+ /// Override this method to modify the damage the character takes.
+ ///
protected virtual float ReceiveDamage(
float damage,
Character inflictor,
@@ -285,6 +301,9 @@ public partial class Character : CharacterBody2D, IFaction
_curDamageText.ShowText();
}
+ ///
+ /// Handles the character taking damage.
+ ///
protected virtual void OnReceivedDamage(
float damage,
Character inflictor,
@@ -348,6 +367,7 @@ public partial class Character : CharacterBody2D, IFaction
}
}
+#if DEBUG
///
/// For debugging purposes
///
@@ -355,7 +375,12 @@ public partial class Character : CharacterBody2D, IFaction
{
OnReceivedDamage(damage, null, 0);
}
+#endif
+ ///
+ /// Plays a footstep sound. This should be called through an
+ /// AnimationPlayer to sync sounds with animations.
+ ///
public virtual void Footstep()
{
if (GetNode("Effects/Footstep") is AudioStreamPlayer2D player)
@@ -364,6 +389,15 @@ public partial class Character : CharacterBody2D, IFaction
}
}
+ ///
+ /// Returns whether the Character has line of sight with
+ /// .
+ ///
+ /// The character to check for LOS
+ ///
+ /// Determines whether the raycast should pass through world clips (physics
+ /// layer 5)
+ ///
public bool HasLineOfSight(Character character, bool excludeClip = false)
{
var exclude = new Godot.Collections.Array();
diff --git a/Characters/NPC.cs b/Characters/NPC.cs
index 1143e5d..fedf3c0 100644
--- a/Characters/NPC.cs
+++ b/Characters/NPC.cs
@@ -96,29 +96,9 @@ public partial class NPC : Character
};
}
- public override void _Draw()
- {
-#if DEBUG
- for (int i = 0; i < 16; i++)
- {
- Vector2 vec = _weightDirs[i] * _weights[i] * 32;
- Color c = Colors.Green;
- if (_bestWeightIdx == i)
- {
- c = Colors.Blue;
- }
- else if (_weights[i] < 0)
- {
- c = Colors.Red;
- vec = -vec;
- }
- DrawLine(Vector2.Zero, vec, c);
- }
-#endif
-
- base._Draw();
- }
-
+ ///
+ /// Finds the NPC's best character to target.
+ ///
public virtual Character FindBestTarget()
{
float bestScore = float.MaxValue;
@@ -136,21 +116,9 @@ public partial class NPC : Character
float score = 0;
score += Position.DistanceTo(character.Position);
- score *= (character.Stealth + 1);
-
- // if the character has enough stealth, the dot product of the
- // enemy's current direction and to the character will affect
- // the score
- // TODO: implement
if (score < bestScore)
{
- // if the character has enough stealth, they won't be
- // targeted if the NPC is not able to see
- if (!HasLineOfSight(character) && character.Stealth >= 1)
- {
- continue;
- }
bestScore = score;
bestChar = character;
}
@@ -170,132 +138,4 @@ public partial class NPC : Character
ThinkerStateMachine.PhysicsProcess(delta);
base._PhysicsProcess(delta);
}
-
- public void ThinkProcess(double delta)
- {
- if ((_thinkTimeElapsed += delta) > ThinkTime)
- {
- _thinkTimeElapsed = 0;
- Think();
-#if DEBUG_NPC
- QueueRedraw();
-#endif
- }
-
- if (!ShouldMove || (!ShouldMoveWhenUsingItem && Inventory.IsUsingItem))
- {
- Direction = Vector2.Zero;
- }
- else
- {
- Direction = _weightDirs[_bestWeightIdx];
- }
- }
-
- public void UpdateWeights(Vector2 pos)
- {
- // FIXME: TODO: remove all the spaghetti
- Vector2 dir = Target.Normalized();
- float distSq = GlobalPosition.DistanceSquaredTo(pos);
-
- var spaceState = GetWorld2D().DirectSpaceState;
- var exclude = new Godot.Collections.Array();
- exclude.Add(this.GetRid());
-
- // calculate weights based on distance
- for (int i = 0; i < 16; i++)
- {
- float directDot = _weightDirs[i].Dot(dir);
- // clamp dot from [-1, 1] to [0, 1]
- directDot = (directDot + 1) / 2;
-
- float strafeDot = Math.Abs(_weightDirs[i].Dot(dir.Clockwise90()));
- float currDirDot = (_weightDirs[i].Dot(Direction) + 1) / 16;
- strafeDot = Mathf.Pow((strafeDot + 1) / 2, 2) + currDirDot;
-
- // favor strafing when getting closer
- if (distSq > _preferredWeightDistanceSq)
- {
- _weights[i] = directDot;
- }
- else if (distSq > _maxWeightDistanceSq)
- {
- float dDotWeight = Mathf.Sqrt(distSq / 4096);
- float sDotWeight = 1 - dDotWeight;
- _weights[i] = (dDotWeight * directDot) +
- (sDotWeight * strafeDot);
- }
- else
- {
- _weights[i] = strafeDot;
- }
- }
-
- // subtract weights that collide
- for (int i = 0; i < 16; i++)
- {
- var rayParams = new PhysicsRayQueryParameters2D
- {
- Exclude = exclude,
- CollideWithBodies = true,
- From = GlobalPosition,
- To = GlobalPosition + (_weightDirs[i] * 24),
- CollisionMask = 1 + 2 + 16
- };
-
- var result = spaceState.IntersectRay(rayParams);
-
- // if we hit something
- if (result.Count > 0)
- {
- // then we subtract the value of this from the other weights
- float oldWeight = _weights[i];
- for (int j = 0; j < 16; j++)
- {
- if (i == j)
- {
- _weights[i] = 0;
- }
- else
- {
- float dot = _weightDirs[i].Dot(_weightDirs[j]);
- _weights[j] -= _weights[j] * dot;
- }
- }
- }
- }
-
-
- float bestWeight = 0;
- for (int i = 0; i < 16; i++)
- {
- if (_weights[i] > bestWeight)
- {
- _bestWeightIdx = i;
- bestWeight = _weights[i];
- }
- }
- }
-
- protected virtual void Think()
- {
- // TODO: the entity should wander if it doesn't find a best target
- Character bestTarget = FindBestTarget();
- if (bestTarget is not null)
- {
- Vector2 pos = FindBestTarget().GlobalPosition;
- Target = pos - GlobalPosition;
- Vector2 dir = Target;
- float dist = GlobalPosition.DistanceSquaredTo(pos);
- UpdateWeights(pos);
-
- if (dist < 1600 && CanAttack)
- {
- if (Inventory.SelectedItem is Weapon weapon)
- {
- UseCurrentItem();
- }
- }
- }
- }
}
diff --git a/Characters/Player.cs b/Characters/Player.cs
index d74a1d2..18702fc 100644
--- a/Characters/Player.cs
+++ b/Characters/Player.cs
@@ -51,10 +51,6 @@ public sealed partial class Player : Character
public override void _Process(double delta)
{
base._Process(delta);
-
- var mod = Sprite.SelfModulate;
- mod.A = 1 - (Stealth / 2);
- Sprite.SelfModulate = mod;
}
public override void _Input(InputEvent @event)
@@ -65,6 +61,9 @@ public sealed partial class Player : Character
}
}
+ ///
+ /// Respawns the player with full health and plays spawn animation
+ ///
public void Spawn()
{
Health = 100;
diff --git a/Items/Item.cs b/Items/Item.cs
index df47050..78ee0b3 100644
--- a/Items/Item.cs
+++ b/Items/Item.cs
@@ -23,6 +23,12 @@ public abstract partial class Item : Node2D
public Character CharacterOwner { get; set; }
+ ///
+ /// Determines if the item is being used. This property determines if
+ /// a character can use another item or not.
+ /// See
+ ///
+ ///
public virtual bool IsUsing => false;
///
diff --git a/Items/Weapons/Sword.cs b/Items/Weapons/Sword.cs
index 1578c9f..76a1964 100644
--- a/Items/Weapons/Sword.cs
+++ b/Items/Weapons/Sword.cs
@@ -7,6 +7,9 @@ using SupaLidlGame.State.Weapon;
namespace SupaLidlGame.Items.Weapons;
+///
+/// A basic melee weapon.
+///
public partial class Sword : Weapon, IParryable
{
public bool IsAttacking { get; protected set; }
@@ -77,6 +80,9 @@ public partial class Sword : Weapon, IParryable
EnableParry(Time.GetTicksMsec());
}
+ ///
+ /// Makes this melee weapon be able to parry and be parried.
+ ///
public void EnableParry(ulong parryTimeOrigin)
{
IsParried = false;
@@ -84,6 +90,9 @@ public partial class Sword : Weapon, IParryable
ParryTimeOrigin = parryTimeOrigin;
}
+ ///
+ /// Makes this melee weapon be able to parry and be parried.
+ ///
public void DisableParry()
{
IsParryable = false;
@@ -113,6 +122,10 @@ public partial class Sword : Weapon, IParryable
base.DeuseAlt();
}
+ ///
+ /// Enables the weapon's hitbox. Prefer to call this from a state machine
+ /// rather than managing state through the weapon script.
+ ///
public void Attack()
{
//RemainingAttackTime = AttackTime;
@@ -120,6 +133,9 @@ public partial class Sword : Weapon, IParryable
Hitbox.IsDisabled = false;
}
+ ///
+ /// Disables the weapon's hitbox and processes all hurtboxes it hit.
+ ///
public void Deattack()
{
IsAttacking = false;
@@ -161,6 +177,9 @@ public partial class Sword : Weapon, IParryable
base._Process(delta);
}
+ ///
+ /// Processes all hits and applies damages to hurtboxes.
+ ///
public void ProcessHits()
{
if (IsParried)
@@ -199,6 +218,10 @@ public partial class Sword : Weapon, IParryable
}
}
+ ///
+ /// Stuns the wepaon holder. This is unique to swords and melee weapons
+ /// if they can parry.
+ ///
public void Stun()
{
IsParried = true;
@@ -238,9 +261,4 @@ public partial class Sword : Weapon, IParryable
}
}
}
-
- protected void SetAnimationCondition(string condition, bool value)
- {
-
- }
}
diff --git a/State/StateMachine.cs b/State/StateMachine.cs
index 5be3f54..c680c39 100644
--- a/State/StateMachine.cs
+++ b/State/StateMachine.cs
@@ -18,11 +18,28 @@ public abstract partial class StateMachine : Node where T : Node, IState
ChangeState(InitialState);
}
+ ///
+ /// Changes the state of the StateMachine.
+ ///
+ /// The next state to transition to.
+ ///
+ /// if is a
+ /// valid state, otherwise
+ ///
public virtual bool ChangeState(T nextState)
{
return ChangeState(nextState, out Stack _);
}
+ ///
+ /// Changes the state of the StateMachine.
+ ///
+ /// The next state to transition to.
+ /// The actual state.
+ ///
+ /// if is a
+ /// valid state, otherwise
+ ///
public bool ChangeState(T nextState, out T finalState)
{
var status = ChangeState(nextState, out Stack states);
@@ -30,6 +47,15 @@ public abstract partial class StateMachine : Node where T : Node, IState
return status;
}
+ ///
+ /// Changes the state of the StateMachine.
+ ///
+ /// The next state to transition to.
+ /// Stack of all states that transitioned/proxied.
+ ///
+ /// if is a
+ /// valid state, otherwise
+ ///
public bool ChangeState(T nextState, out Stack states)
{
states = new Stack();
@@ -71,14 +97,35 @@ public abstract partial class StateMachine : Node where T : Node, IState
}
///
- /// Changes the current state to a state of type U which must inherit from T.
+ /// Changes the state of the StateMachine of type
+ /// which must inherit from
+ /// .
///
+ /// The type of the state to transition to.
+ /// The resulting state to be transitioned to.
+ ///
+ /// if is a
+ /// valid state, otherwise
+ ///
public bool ChangeState(out U state) where U : T
{
state = this.FindChildOfType();
return ChangeState(state);
}
+ ///
+ /// Changes the state of the StateMachine with node name
+ /// .
+ ///
+ /// The type of the state to transition to.
+ ///
+ /// The name of the node.
+ ///
+ /// The resulting state to be transitioned to.
+ ///
+ /// if is a
+ /// valid state, otherwise
+ ///
public bool ChangeState(string name, out T state)
{
state = GetNode(name);