using Godot; using SupaLidlGame.BoundingBoxes; using SupaLidlGame.Characters; using SupaLidlGame.Extensions; namespace SupaLidlGame.Items.Weapons { public partial class Sword : Weapon { public bool IsAttacking { get; protected set; } [Export] public Hitbox Hitbox { get; set; } [Export] public AnimationPlayer AnimationPlayer { get; set; } /// /// The time frame in seconds for which the weapon will deal damage. /// /// /// The value of AttackTime should be less than the /// value of UseTime /// [Export] public double AttackTime { get; set; } = 0; [Export] public CPUParticles2D ParryParticles { get; set; } public override bool IsParryable { get; protected set; } public override void Equip(Character character) { Visible = true; base.Equip(character); Hitbox.Faction = character.Faction; // character is null before base } public override void Unequip(Character character) { Visible = false; base.Unequip(character); } public override void Use() { // we can't use if we're still using the weapon if (RemainingUseTime > 0) { return; } // reset state of the weapon IsParried = false; IsParryable = true; ParryTimeOrigin = Time.GetTicksMsec(); AnimationPlayer.Stop(); // play animation depending on rotation of weapon string anim = "use"; if (GetNode("Anchor").Rotation > Mathf.DegToRad(50)) { anim = "use2"; } if (Character is NPC) { // NPCs have a slower attack anim += "-npc"; } AnimationPlayer.Play(anim); base.Use(); } public override void Deuse() { //AnimationPlayer.Stop(); Deattack(); base.Deuse(); } public void Attack() { //RemainingAttackTime = AttackTime; IsAttacking = true; Hitbox.IsDisabled = false; } public void Deattack() { IsAttacking = false; IsParryable = false; Hitbox.IsDisabled = true; ProcessHits(); Hitbox.ResetIgnoreList(); AnimationPlayer.PlaybackSpeed = 1; } public override void _Ready() { Hitbox.Damage = Damage; } public override void _Process(double delta) { /* if (RemainingAttackTime > 0) { if ((RemainingAttackTime -= delta) <= 0) { Deattack(); } } */ base._Process(delta); } public void ProcessHits() { if (IsParried) { return; } foreach (BoundingBox box in Hitbox.Hits) { GD.Print("processing hit"); if (box is Hurtbox hurtbox) { hurtbox.InflictDamage(Damage, Character, Knockback); } } } public void AttemptParry(Weapon otherWeapon) { if (IsParryable && otherWeapon.IsParryable) { ParryParticles.Emitting = true; if (ParryTimeOrigin < otherWeapon.ParryTimeOrigin) { // our character was parried IsParried = true; AnimationPlayer.PlaybackSpeed = 0.25f; Character.Stun(1.5f); GetNode("ParrySound").Play(); } } //this.GetAncestor().AddChild(instance); } public override void _on_hitbox_hit(BoundingBox box) { if (IsParried) { return; } if (box is Hitbox hb) { Weapon w = hb.GetAncestor(); if (w is not null) { //Vector2 a = new Vector2(2, 2) * new Vector2(5, 2); AttemptParry(w); } } if (box is Hurtbox hurt) { if (hurt.GetParent() is Character c) { var item = c.Inventory.SelectedItem; if (item is Weapon w) { AttemptParry(w); } } } } } }