changed doc to 3-stage boss
							parent
							
								
									020337494a
								
							
						
					
					
						commit
						edf186be56
					
				
											
												Binary file not shown.
											
										
									
								| 
						 | 
					@ -31,4 +31,9 @@ public abstract partial class Boss : Enemy
 | 
				
			||||||
                .RegisterBoss(_isActive ? this : null);
 | 
					                .RegisterBoss(_isActive ? this : null);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override void _Ready()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        base._Ready();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
using Godot;
 | 
					using Godot;
 | 
				
			||||||
using GodotUtilities;
 | 
					using GodotUtilities;
 | 
				
			||||||
 | 
					using SupaLidlGame.Extensions;
 | 
				
			||||||
using SupaLidlGame.State.Character;
 | 
					using SupaLidlGame.State.Character;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace SupaLidlGame.Characters;
 | 
					namespace SupaLidlGame.Characters;
 | 
				
			||||||
| 
						 | 
					@ -12,6 +13,8 @@ public partial class Doc : Boss
 | 
				
			||||||
    public Items.Weapons.Sword Lance { get; set; }
 | 
					    public Items.Weapons.Sword Lance { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected bool _dashedAway = false;
 | 
					    protected bool _dashedAway = false;
 | 
				
			||||||
 | 
					    protected CharacterDashState _dashState;
 | 
				
			||||||
 | 
					    protected float _originalDashModifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override float Health
 | 
					    public override float Health
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -37,9 +40,9 @@ public partial class Doc : Boss
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            switch (Health)
 | 
					            switch (Health)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                case < 200:
 | 
					                case < 300:
 | 
				
			||||||
                    return 3;
 | 
					                    return 3;
 | 
				
			||||||
                case < 400:
 | 
					                case < 600:
 | 
				
			||||||
                    return 2;
 | 
					                    return 2;
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    return 1;
 | 
					                    return 1;
 | 
				
			||||||
| 
						 | 
					@ -57,6 +60,10 @@ public partial class Doc : Boss
 | 
				
			||||||
        TelegraphAnimation = GetNode<AnimationPlayer>("Animations/Telegraph");
 | 
					        TelegraphAnimation = GetNode<AnimationPlayer>("Animations/Telegraph");
 | 
				
			||||||
        base._Ready();
 | 
					        base._Ready();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _dashState = StateMachine.FindChildOfType<CharacterDashState>();
 | 
				
			||||||
 | 
					        _originalDashModifier = _dashState.VelocityModifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when we are hurt, start the boss fight
 | 
					        // when we are hurt, start the boss fight
 | 
				
			||||||
        Hurt += (Events.HealthChangedArgs args) =>
 | 
					        Hurt += (Events.HealthChangedArgs args) =>
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -130,28 +137,56 @@ public partial class Doc : Boss
 | 
				
			||||||
            if (CanAttack && StunTime <= 0)
 | 
					            if (CanAttack && StunTime <= 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                bool isTargetStunned = bestTarget.StunTime > 0;
 | 
					                bool isTargetStunned = bestTarget.StunTime > 0;
 | 
				
			||||||
                if (!isTargetStunned && dist < 2500)
 | 
					
 | 
				
			||||||
                {
 | 
					                bool shouldDashAway = false;
 | 
				
			||||||
                    if (Inventory.SelectedItem is Items.Weapon weapon)
 | 
					                bool shouldDashTowards = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                var lance = Inventory.SelectedItem as Items.Weapons.Sword;
 | 
				
			||||||
 | 
					                var lanceState = lance.StateMachine.CurrentState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                float dot = Direction.Normalized()
 | 
				
			||||||
 | 
					                    .Dot(bestTarget.Direction.Normalized());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // doc will still dash if you are farther than normal but
 | 
				
			||||||
 | 
					                // moving towards him
 | 
				
			||||||
 | 
					                float distThreshold = 2500 - (dot * 400);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // or just directly dash towards you if you are too far
 | 
				
			||||||
 | 
					                float distTowardsThreshold = 22500;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // dash towards if lance in anticipate state
 | 
				
			||||||
 | 
					                shouldDashTowards = (isTargetStunned || _dashedAway) &&
 | 
				
			||||||
 | 
					                    lanceState is State.Weapon.SwordAnticipateState ||
 | 
				
			||||||
 | 
					                    dist > distTowardsThreshold;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                shouldDashAway = dist < distThreshold && !isTargetStunned;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                //if (!isTargetStunned && dist < 2500 && !_dashedAway)
 | 
				
			||||||
 | 
					                if (shouldDashAway && !shouldDashTowards)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // dash away if too close
 | 
					                    // dash away if too close
 | 
				
			||||||
 | 
					                    _dashState.VelocityModifier = _originalDashModifier;
 | 
				
			||||||
                    DashTo(-dir);
 | 
					                    DashTo(-dir);
 | 
				
			||||||
                    UseCurrentItem();
 | 
					                    UseCurrentItem();
 | 
				
			||||||
                    _dashedAway = true;
 | 
					                    _dashedAway = true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                }
 | 
					                else if (shouldDashTowards && !shouldDashAway)
 | 
				
			||||||
                else if (isTargetStunned || (dist < 3600 && _dashedAway))
 | 
					 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (!Inventory.SelectedItem.IsUsing)
 | 
					                    // dash to player's predicted position
 | 
				
			||||||
                    {
 | 
					                    _dashState.VelocityModifier = _originalDashModifier * 1.75f;
 | 
				
			||||||
                        DashTo(dir);
 | 
					                    var dashSpeed = _dashState.VelocityModifier * Speed;
 | 
				
			||||||
                        UseCurrentItem();
 | 
					                    var newPos = Utils.Physics.PredictNewPosition(
 | 
				
			||||||
 | 
					                        GlobalPosition,
 | 
				
			||||||
 | 
					                        dashSpeed,
 | 
				
			||||||
 | 
					                        pos,
 | 
				
			||||||
 | 
					                        bestTarget.Velocity,
 | 
				
			||||||
 | 
					                        out float _);
 | 
				
			||||||
 | 
					                    DashTo(GlobalPosition.DirectionTo(newPos));
 | 
				
			||||||
                    _dashedAway = false;
 | 
					                    _dashedAway = false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void DashTo(Vector2 direction)
 | 
					    private void DashTo(Vector2 direction)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
[gd_scene load_steps=61 format=3 uid="uid://d2skjvvx6fal0"]
 | 
					[gd_scene load_steps=62 format=3 uid="uid://d2skjvvx6fal0"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[ext_resource type="Script" path="res://Characters/Doc.cs" id="2_3elet"]
 | 
					[ext_resource type="Script" path="res://Characters/Doc.cs" id="2_3elet"]
 | 
				
			||||||
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_5jxom"]
 | 
					[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_5jxom"]
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@
 | 
				
			||||||
[ext_resource type="Animation" uid="uid://8e8r3y1imvsx" path="res://Assets/Animations/stun.res" id="21_ixn4k"]
 | 
					[ext_resource type="Animation" uid="uid://8e8r3y1imvsx" path="res://Assets/Animations/stun.res" id="21_ixn4k"]
 | 
				
			||||||
[ext_resource type="PackedScene" uid="uid://p7oijq6dbvvk" path="res://Items/Weapons/DocLance.tscn" id="24_2es2r"]
 | 
					[ext_resource type="PackedScene" uid="uid://p7oijq6dbvvk" path="res://Items/Weapons/DocLance.tscn" id="24_2es2r"]
 | 
				
			||||||
[ext_resource type="PackedScene" uid="uid://bauucuqvjwbxp" path="res://Items/Weapons/DocLanceHold.tscn" id="26_0tntj"]
 | 
					[ext_resource type="PackedScene" uid="uid://bauucuqvjwbxp" path="res://Items/Weapons/DocLanceHold.tscn" id="26_0tntj"]
 | 
				
			||||||
 | 
					[ext_resource type="AudioStream" uid="uid://cqj44je3mvk60" path="res://Assets/Sounds/rauuul.wav" id="26_js7p2"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"]
 | 
					[sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"]
 | 
				
			||||||
resource_local_to_scene = true
 | 
					resource_local_to_scene = true
 | 
				
			||||||
| 
						 | 
					@ -467,7 +468,7 @@ BossStateMachine = NodePath("BossStateMachine")
 | 
				
			||||||
BossName = "Doc, The Two-Time"
 | 
					BossName = "Doc, The Two-Time"
 | 
				
			||||||
Music = ExtResource("3_eo4lg")
 | 
					Music = ExtResource("3_eo4lg")
 | 
				
			||||||
HandTexture = ExtResource("4_8lqj6")
 | 
					HandTexture = ExtResource("4_8lqj6")
 | 
				
			||||||
Health = 800.0
 | 
					Health = 900.0
 | 
				
			||||||
Sprite = NodePath("Sprite")
 | 
					Sprite = NodePath("Sprite")
 | 
				
			||||||
Inventory = NodePath("Inventory")
 | 
					Inventory = NodePath("Inventory")
 | 
				
			||||||
StateMachine = NodePath("StateMachine")
 | 
					StateMachine = NodePath("StateMachine")
 | 
				
			||||||
| 
						 | 
					@ -507,8 +508,8 @@ NPC = NodePath("../..")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="Dart" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ChooseAttackState", "Doc", "NPC")]
 | 
					[node name="Dart" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ChooseAttackState", "Doc", "NPC")]
 | 
				
			||||||
script = ExtResource("8_1hoax")
 | 
					script = ExtResource("8_1hoax")
 | 
				
			||||||
Duration = 8.0
 | 
					Duration = 6.0
 | 
				
			||||||
AttackDuration = 1.0
 | 
					AttackDuration = 1.5
 | 
				
			||||||
Projectile = ExtResource("11_23p3o")
 | 
					Projectile = ExtResource("11_23p3o")
 | 
				
			||||||
ChooseAttackState = NodePath("../ChooseAttack")
 | 
					ChooseAttackState = NodePath("../ChooseAttack")
 | 
				
			||||||
Doc = NodePath("../..")
 | 
					Doc = NodePath("../..")
 | 
				
			||||||
| 
						 | 
					@ -613,6 +614,11 @@ emitting = false
 | 
				
			||||||
amount = 32
 | 
					amount = 32
 | 
				
			||||||
process_material = SubResource("ParticleProcessMaterial_j1srf")
 | 
					process_material = SubResource("ParticleProcessMaterial_j1srf")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="BattleCry" type="AudioStreamPlayer2D" parent="Effects"]
 | 
				
			||||||
 | 
					stream = ExtResource("26_js7p2")
 | 
				
			||||||
 | 
					volume_db = 3.0
 | 
				
			||||||
 | 
					attenuation = 0.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="Sprite" type="Sprite2D" parent="."]
 | 
					[node name="Sprite" type="Sprite2D" parent="."]
 | 
				
			||||||
modulate = Color(1, 1, 1, 0.5)
 | 
					modulate = Color(1, 1, 1, 0.5)
 | 
				
			||||||
y_sort_enabled = true
 | 
					y_sort_enabled = true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ texture = ExtResource("2_klp8v")
 | 
				
			||||||
hframes = 5
 | 
					hframes = 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="Hitbox" parent="." instance=ExtResource("3_kojrj")]
 | 
					[node name="Hitbox" parent="." instance=ExtResource("3_kojrj")]
 | 
				
			||||||
Damage = 14.0
 | 
					Damage = 45.0
 | 
				
			||||||
Knockback = 200.0
 | 
					Knockback = 200.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="CollisionShape2D" parent="Hitbox" index="0"]
 | 
					[node name="CollisionShape2D" parent="Hitbox" index="0"]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,7 +108,7 @@ ProjectileName = "Unwanted Frequency"
 | 
				
			||||||
Speed = 124.0
 | 
					Speed = 124.0
 | 
				
			||||||
Direction = Vector2(1, 1)
 | 
					Direction = Vector2(1, 1)
 | 
				
			||||||
Hitbox = NodePath("Hitbox")
 | 
					Hitbox = NodePath("Hitbox")
 | 
				
			||||||
Lifetime = 7.0
 | 
					Lifetime = 4.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="Hitbox" parent="." instance=ExtResource("2_gxtvd")]
 | 
					[node name="Hitbox" parent="." instance=ExtResource("2_gxtvd")]
 | 
				
			||||||
collision_layer = 0
 | 
					collision_layer = 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,7 +157,7 @@ public partial class Sword : Weapon, IParryable
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        IsParried = true;
 | 
					        IsParried = true;
 | 
				
			||||||
        AnimationPlayer.SpeedScale = 0.25f;
 | 
					        AnimationPlayer.SpeedScale = 0.25f;
 | 
				
			||||||
        Character.Stun(1);
 | 
					        Character.Stun(2);
 | 
				
			||||||
        GetNode<AudioStreamPlayer2D>("ParrySound")
 | 
					        GetNode<AudioStreamPlayer2D>("ParrySound")
 | 
				
			||||||
            .OnWorld()
 | 
					            .OnWorld()
 | 
				
			||||||
            .WithPitchDeviation(0.125f)
 | 
					            .WithPitchDeviation(0.125f)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ public partial class DocExitState : NPCState
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _currentDuration = Duration;
 | 
					        _currentDuration = Duration;
 | 
				
			||||||
        TelegraphAnimationPlayer.Play("exit_out");
 | 
					        TelegraphAnimationPlayer.Play("exit_out");
 | 
				
			||||||
 | 
					        NPC.ShouldMove = false;
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ public partial class DocLanceState : DocAttackState
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        var state = base.Enter(previousState);
 | 
					        var state = base.Enter(previousState);
 | 
				
			||||||
        _doc.ShouldMove = true;
 | 
					        _doc.ShouldMove = true;
 | 
				
			||||||
 | 
					        _doc.GetNode<AudioStreamPlayer2D>("Effects/BattleCry").Play();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //if (_doc.Intensity > 2)
 | 
					        //if (_doc.Intensity > 2)
 | 
				
			||||||
        //{
 | 
					        //{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,8 +45,8 @@ public partial class DocShungiteDartState : DocAttackState
 | 
				
			||||||
        var playerPos = player.GlobalPosition;
 | 
					        var playerPos = player.GlobalPosition;
 | 
				
			||||||
        // global position is (from npc to player) * 2 = (2 * npc) - player
 | 
					        // global position is (from npc to player) * 2 = (2 * npc) - player
 | 
				
			||||||
        //projectile.GlobalPosition = 2 * NPC.GlobalPosition - playerPos;
 | 
					        //projectile.GlobalPosition = 2 * NPC.GlobalPosition - playerPos;
 | 
				
			||||||
        Vector2 position1 = 2 * NPC.GlobalPosition - playerPos;
 | 
					        Vector2 position1 = 3 * NPC.GlobalPosition - 2 * playerPos;
 | 
				
			||||||
        Vector2 position2 = 2 * playerPos - NPC.GlobalPosition;
 | 
					        Vector2 position2 = 3 * playerPos - 2 * NPC.GlobalPosition;
 | 
				
			||||||
        Vector2 direction1 = position1.DirectionTo(playerPos);
 | 
					        Vector2 direction1 = position1.DirectionTo(playerPos);
 | 
				
			||||||
        Vector2 direction2 = -direction1;
 | 
					        Vector2 direction2 = -direction1;
 | 
				
			||||||
        SpawnProjectile(position1, direction1);
 | 
					        SpawnProjectile(position1, direction1);
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ public partial class DocShungiteDartState : DocAttackState
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((_currentDuration -= delta) <= 0)
 | 
					        if ((_currentDuration -= delta) <= 0 || Doc.Intensity > 2)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return ChooseAttackState;
 | 
					            return ChooseAttackState;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ public partial class DocShungiteSpikeState : DocShungiteDartState
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((_currentAttackDuration -= delta) <= 0)
 | 
					        if ((_currentAttackDuration -= delta) <= 0 || Doc.Intensity > 2)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Attack();
 | 
					            Attack();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ public partial class DocTelegraphState : NPCState
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        _currentDuration = Duration;
 | 
					        _currentDuration = Duration;
 | 
				
			||||||
        TelegraphAnimationPlayer.Play("enter_in");
 | 
					        TelegraphAnimationPlayer.Play("enter_in");
 | 
				
			||||||
 | 
					        NPC.ShouldMove = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var player = this.GetAncestor<Utils.World>().CurrentPlayer;
 | 
					        var player = this.GetAncestor<Utils.World>().CurrentPlayer;
 | 
				
			||||||
        Vector2 randVec;
 | 
					        Vector2 randVec;
 | 
				
			||||||
| 
						 | 
					@ -36,8 +37,8 @@ public partial class DocTelegraphState : NPCState
 | 
				
			||||||
            float randY = GD.RandRange(-112, 112);
 | 
					            float randY = GD.RandRange(-112, 112);
 | 
				
			||||||
            randVec = new Vector2(randX, randY);
 | 
					            randVec = new Vector2(randX, randY);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        while (randVec.DistanceSquaredTo(player.GlobalPosition) < 1024);
 | 
					        while (randVec.DistanceSquaredTo(player.GlobalPosition) < 9216);
 | 
				
			||||||
        // can not teleport within 32 units of the player
 | 
					        // can not teleport within 96 units of the player
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        NPC.GlobalPosition = randVec;
 | 
					        NPC.GlobalPosition = randVec;
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue