Boss Fight computer terminal implementation

This commit is contained in:
2026-04-29 00:51:45 -07:00
parent 507b7e6a83
commit e57085e5f2
10 changed files with 10561 additions and 1435 deletions

View File

@@ -0,0 +1,36 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Zennysoft.Game.Ma;
using Zennysoft.Ma.Adapter;
[Meta(typeof(IAutoNode))]
public partial class ComputerTerminal : Enemy3D
{
public override void _Notification(int what) => this.Notify(what);
public override IEnemyModelView EnemyModelView => _enemyModelView;
[Node] private ComputerTerminalModelView _enemyModelView { get; set; } = default!;
public void OnReady()
{
_enemyModelView.OnDeathAnimationCompleted += _enemyModelView_OnDeathAnimationCompleted;
}
public override async void TakeHit(ElementType damageElementType)
{
base.TakeHit(damageElementType);
}
private void _enemyModelView_OnDeathAnimationCompleted() => CallDeferred(MethodName.QueueFree);
public override void Die()
{
SetProcess(false);
SetPhysicsProcess(false);
_enemyLogic.Input(new EnemyLogic.Input.Defeated());
_player.ExperiencePointsComponent.Gain(ExpGiven);
EnemyModelView.PlayDeathAnimation();
}
}

View File

@@ -0,0 +1 @@
uid://d3r768c1rr0c6

View File

@@ -0,0 +1,75 @@
[gd_scene load_steps=10 format=3 uid="uid://bv6j6lai6461"]
[ext_resource type="PackedScene" uid="uid://8vt5veihktqc" path="res://src/enemy/enemy_types/17. computer_terminal/ComputerTerminalModelViewA.tscn" id="1_7wavs"]
[ext_resource type="Script" uid="uid://d3r768c1rr0c6" path="res://src/enemy/enemy_types/17. computer_terminal/ComputerTerminal.cs" id="1_egp0b"]
[ext_resource type="AudioStream" uid="uid://ba8xendacec6" path="res://src/audio/sfx/item_kyuu_layer_2.ogg" id="3_ehcta"]
[ext_resource type="AudioStream" uid="uid://b7ycb6qvitpmw" path="res://src/audio/sfx/player_HITENEMY_3.ogg" id="4_ipfpg"]
[ext_resource type="AudioStream" uid="uid://bf7adfdd857hw" path="res://src/audio/sfx/enemy_morph.ogg" id="5_o6j4k"]
[ext_resource type="AudioStream" uid="uid://mp00rngkpfjg" path="res://src/audio/sfx/enemy_palan_death.ogg" id="6_u48wx"]
[sub_resource type="CylinderShape3D" id="CylinderShape3D_ehcta"]
radius = 5.79248
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ehcta"]
radius = 1.2543
height = 5.64948
[sub_resource type="CylinderShape3D" id="CylinderShape3D_ipfpg"]
height = 3.98828
radius = 0.886719
[node name="ComputerTerminalA" type="CharacterBody3D"]
script = ExtResource("1_egp0b")
[node name="EnemyModelView" parent="." instance=ExtResource("1_7wavs")]
unique_name_in_owner = true
[node name="HitSounds" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13.448, 26.9238, 68.7264)
[node name="AbsorbSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("3_ehcta")
bus = &"SFX"
[node name="HitSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("4_ipfpg")
bus = &"SFX"
[node name="MorphSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("5_o6j4k")
bus = &"SFX"
[node name="DieSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("6_u48wx")
bus = &"SFX"
[node name="AggroSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
bus = &"SFX"
[node name="PlayerDetector" type="Area3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13.448, 26.9238, 68.7264)
collision_layer = 0
collision_mask = 34
[node name="CollisionShape3D" type="CollisionShape3D" parent="PlayerDetector"]
shape = SubResource("CylinderShape3D_ehcta")
[node name="CollisionShape" type="CollisionShape3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, -13.3541, 27.8415, 68.7295)
shape = SubResource("CapsuleShape3D_ehcta")
[node name="Collision" type="Area3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13.4615, 27.2374, 68.7257)
collision_layer = 2048
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="Collision"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.321487, 0)
shape = SubResource("CylinderShape3D_ipfpg")

View File

@@ -0,0 +1,75 @@
[gd_scene load_steps=10 format=3 uid="uid://dbc7d6ost3gm0"]
[ext_resource type="Script" uid="uid://d3r768c1rr0c6" path="res://src/enemy/enemy_types/17. computer_terminal/ComputerTerminal.cs" id="1_26pph"]
[ext_resource type="PackedScene" uid="uid://kvdblehunij1" path="res://src/enemy/enemy_types/17. computer_terminal/ComputerTerminalModelViewB.tscn" id="2_vejbs"]
[ext_resource type="AudioStream" uid="uid://ba8xendacec6" path="res://src/audio/sfx/item_kyuu_layer_2.ogg" id="4_82vh5"]
[ext_resource type="AudioStream" uid="uid://b7ycb6qvitpmw" path="res://src/audio/sfx/player_HITENEMY_3.ogg" id="5_47ny6"]
[ext_resource type="AudioStream" uid="uid://bf7adfdd857hw" path="res://src/audio/sfx/enemy_morph.ogg" id="6_e55x4"]
[ext_resource type="AudioStream" uid="uid://mp00rngkpfjg" path="res://src/audio/sfx/enemy_palan_death.ogg" id="7_xasc3"]
[sub_resource type="CylinderShape3D" id="CylinderShape3D_yh205"]
radius = 5.79248
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cippe"]
radius = 1.2543
height = 5.64948
[sub_resource type="CylinderShape3D" id="CylinderShape3D_vejbs"]
height = 3.98828
radius = 0.886719
[node name="ComputerTerminalB" type="CharacterBody3D"]
script = ExtResource("1_26pph")
[node name="EnemyModelView" parent="." instance=ExtResource("2_vejbs")]
unique_name_in_owner = true
[node name="HitSounds" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12.5704, 26.9238, 69.4637)
[node name="AbsorbSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("4_82vh5")
bus = &"SFX"
[node name="HitSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("5_47ny6")
bus = &"SFX"
[node name="MorphSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("6_e55x4")
bus = &"SFX"
[node name="DieSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
stream = ExtResource("7_xasc3")
bus = &"SFX"
[node name="AggroSFX" type="AudioStreamPlayer3D" parent="HitSounds"]
unique_name_in_owner = true
bus = &"SFX"
[node name="PlayerDetector" type="Area3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12.5704, 26.9238, 69.4637)
collision_layer = 0
collision_mask = 34
[node name="CollisionShape3D" type="CollisionShape3D" parent="PlayerDetector"]
shape = SubResource("CylinderShape3D_yh205")
[node name="CollisionShape" type="CollisionShape3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 12.6642, 27.8415, 69.4668)
shape = SubResource("CapsuleShape3D_cippe")
[node name="Collision" type="Area3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12.6205, 27.2374, 69.3876)
collision_layer = 2048
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="Collision"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.321487, 0)
shape = SubResource("CylinderShape3D_vejbs")

View File

@@ -0,0 +1,50 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using System.Linq;
using Zennysoft.Game.Ma;
using Zennysoft.Ma.Adapter;
[Meta(typeof(IAutoNode))]
public partial class ComputerTerminalModelView : EnemyModelView3D
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] protected IPlayer _player => this.DependOn(() => GetParent().GetChildren().OfType<IPlayer>().Single());
[Node] public AnimationPlayer AnimationPlayer { get; set; } = default!;
[Node] public Node3D ComputerExplodes { get; set; } = default!;
[Node] public Node3D Pivot { get; set; }
[Signal] public delegate void OnDeathAnimationCompletedEventHandler();
public void Setup()
{
AnimationPlayer.AnimationFinished += AnimationPlayer_AnimationFinished;
}
public void OnPhysicsProcess(double delta)
{
GetRotationAngle(Pivot);
}
public override void PlayHitAnimation() => AnimationPlayer.Play("Hit");
public override void PlayDeathAnimation() => AnimationPlayer.Play("Animation");
private float GetRotationAngle(Node3D rotationNode)
{
var target = new Vector3(_player.GlobalPosition.X, Position.Y, _player.GlobalPosition.Z);
rotationNode.LookAt(target, Vector3.Up, true);
rotationNode.RotateY(Rotation.Y);
return rotationNode.Rotation.Y;
}
private void AnimationPlayer_AnimationFinished(StringName animName)
{
if (animName == "Animation")
EmitSignal(SignalName.OnDeathAnimationCompleted);
}
}

View File

@@ -16,14 +16,39 @@ public partial class BossRoomB : SpecialFloor, IBossRoom, IDungeonFloor
[Node] public DemonWall DemonWall { get; set; } = default!; [Node] public DemonWall DemonWall { get; set; } = default!;
[Node] public ComputerTerminal ComputerTerminalA { get; set; } = default!;
[Node] public ComputerTerminal ComputerTerminalB { get; set; } = default!;
[Node] private Area3D ActivateTrap { get; set; } = default!; [Node] private Area3D ActivateTrap { get; set; } = default!;
[Node] private Area3D _exit { get; set; } = default!; [Node] private Area3D _exit { get; set; } = default!;
[Node] private CollisionShape3D BridgeCollision { get; set; } = default!;
[Node] private AnimationPlayer BridgeAnimationPlayer { get; set; } = default!;
public void OnReady() public void OnReady()
{ {
ActivateTrap.BodyEntered += ActivateTrap_AreaEntered; ActivateTrap.BodyEntered += ActivateTrap_AreaEntered;
_exit.AreaEntered += Exit_AreaEntered; _exit.AreaEntered += Exit_AreaEntered;
BridgeAnimationPlayer.AnimationFinished += BridgeAnimationPlayer_AnimationFinished;
ComputerTerminalA.HealthComponent.HealthReachedZero += TerminalDefeated;
ComputerTerminalB.HealthComponent.HealthReachedZero += TerminalDefeated;
}
private void TerminalDefeated()
{
if (ComputerTerminalA.HealthComponent.CurrentHP.Value <= 0 && ComputerTerminalB.HealthComponent.CurrentHP.Value <= 0)
OpenBridgeFull();
else
OpenBridgeHalf();
}
private void BridgeAnimationPlayer_AnimationFinished(StringName animName)
{
if (animName == "Bridge Extend Full")
BridgeCollision.SetDeferred(CollisionShape3D.PropertyName.Disabled, true);
} }
private void ActivateTrap_AreaEntered(Node3D area) => StartBossFight(); private void ActivateTrap_AreaEntered(Node3D area) => StartBossFight();
@@ -35,21 +60,31 @@ public partial class BossRoomB : SpecialFloor, IBossRoom, IDungeonFloor
public void StartBossFight() public void StartBossFight()
{ {
DemonWall.Activate(); DemonWall.Activate();
} }
public void ExitReached() public void ExitReached()
=> Game.FloorExitReached(); => Game.FloorExitReached();
public void OpenBridgeHalf()
{
BridgeAnimationPlayer.Play("Bridge Extend Half");
}
public void OpenBridgeFull()
{
BridgeAnimationPlayer.Play("Bridge Extend Full");
}
private void Exit_AreaEntered(Area3D area) private void Exit_AreaEntered(Area3D area)
{ {
if (area.GetOwner() is IPlayer) if (area.GetOwner() is IPlayer)
ExitReached(); ExitReached();
} }
public void OnExitTree() public void OnExitTree()
{ {
ActivateTrap.BodyEntered -= ActivateTrap_AreaEntered; ActivateTrap.BodyEntered -= ActivateTrap_AreaEntered;
_exit.AreaEntered -= Exit_AreaEntered; _exit.AreaEntered -= Exit_AreaEntered;
} }
} }

File diff suppressed because one or more lines are too long