This commit is contained in:
Pal
2025-10-07 00:30:31 -07:00
13 changed files with 63 additions and 83 deletions

View File

@@ -52,6 +52,7 @@ public partial class DataViewer : Control
Camera3D.Position = Camera3D.Position.Clamp(new Vector3(0, 0, 1), new Vector3(0, 0, 4));
ModelPivot.Rotation = ModelPivot.Rotation.Clamp(Mathf.DegToRad(-60), Mathf.DegToRad(60));
_currentModel.SetCurrentDirection(_currentModel.GlobalBasis, -CameraPivot.Basis.Z);
Description.Text = (-CameraPivot.RotationDegrees).ToString();
if (Input.IsActionJustPressed(GameInputs.Attack))
_currentModel.PlayPrimaryAttackAnimation();

View File

@@ -78,6 +78,7 @@ layout_mode = 2
stretch = true
[node name="SubViewport" type="SubViewport" parent="CenterContainer/VBoxContainer/HBoxContainer/SubViewportContainer"]
own_world_3d = true
handle_input_locally = false
size = Vector2i(500, 500)
render_target_update_mode = 4

View File

@@ -1,9 +1,6 @@
[gd_scene load_steps=4 format=3 uid="uid://c16i1gmg6yu5a"]
[gd_scene load_steps=2 format=3 uid="uid://c16i1gmg6yu5a"]
[ext_resource type="Script" uid="uid://03k48fke03vu" path="res://src/data_viewer/DataViewerRepository.cs" id="1_1cvot"]
[ext_resource type="PackedScene" uid="uid://bjg8wyvp8q6oc" path="res://src/enemy/enemy_types/02. michael/MichaelModelView.tscn" id="2_8autu"]
[ext_resource type="PackedScene" uid="uid://bli0t0d6ommvi" path="res://src/enemy/enemy_types/01. sproingy/SproingyModelView.tscn" id="3_0bpmu"]
[node name="DataViewerRepository" type="Node"]
script = ExtResource("1_1cvot")
_modelsToDisplay = [ExtResource("2_8autu"), ExtResource("3_0bpmu")]

View File

@@ -25,8 +25,12 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
[Node] public AnimationTree AnimationTree { get; set; } = default!;
[ExportGroup("Animation Debug")]
[Export(PropertyHint.Enum)]
[ExportGroup("Enemy Model Properties")]
[Export(PropertyHint.Range, "0.0, 1.0")]
private float _upperThreshold { get; set; } = 0.5f;
[Export(PropertyHint.Range, "-1.0, 0.0")]
private float _lowerThreshold { get; set; } = -0.5f;
EnemyDirection _enemyDirection { get; set; } = EnemyDirection.Forward;
private AnimationNodeStateMachinePlayback _stateMachine;
@@ -36,7 +40,7 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
_stateMachine = (AnimationNodeStateMachinePlayback)AnimationTree.Get("parameters/playback");
}
public void SetCurrentDirection(Basis enemyBasis, Vector3 cameraDirection) => _enemyDirection = GetEnemyDirection(enemyBasis, cameraDirection, 0.55f, 0.45f);
public void SetCurrentDirection(Basis enemyBasis, Vector3 cameraDirection) => _enemyDirection = GetEnemyDirection(enemyBasis, cameraDirection, _upperThreshold, _lowerThreshold);
public void PlayPrimaryAttackAnimation() => _stateMachine.Travel(_primaryAttackName);
@@ -52,17 +56,17 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
public void PlayHitAnimation()
{
LoadShader("res://src/vfx/shaders/DamageHit.gdshader");
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 1.0f);
LoadShader("res://src/vfx/shaders/DamageHit.gdshader");
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 1.0f);
}
public void PlayDeathAnimation()
{
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 0.8f);
tweener.TweenCallback(Callable.From(QueueFree));
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
var tweener = GetTree().CreateTween();
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 0.8f);
tweener.TweenCallback(Callable.From(QueueFree));
}
private EnemyDirection GetEnemyDirection(
@@ -71,14 +75,14 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
float rotateUpperThreshold,
float rotateLowerThreshold)
{
var enemyForwardDirection = enemyBasis.Z;
var enemyLeftDirection = enemyBasis.X;
var enemyForwardDirection = enemyBasis.Z;
var enemyLeftDirection = enemyBasis.X;
var leftDotProduct = enemyLeftDirection.Dot(cameraDirection);
var forwardDotProduct = enemyForwardDirection.Dot(cameraDirection);
var leftDotProduct = enemyLeftDirection.Dot(cameraDirection);
var forwardDotProduct = enemyForwardDirection.Dot(cameraDirection);
// Check if forward facing. If the dot product is -1, the enemy is facing the camera.
if (forwardDotProduct < -rotateUpperThreshold)
if (forwardDotProduct < _lowerThreshold)
{
SetForward();
return EnemyDirection.Forward;
@@ -93,17 +97,17 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
else
{
// If the dot product of the perpendicular direction is positive (up to 1), the enemy is facing to the left (since it's mirrored).
if (leftDotProduct > 0)
if (leftDotProduct < _lowerThreshold)
{
SetRight();
return EnemyDirection.Right;
return EnemyDirection.Left;
}
// Check if side facing. If the dot product is close to zero in the positive or negative direction, its close to the threshold for turning.
if (Mathf.Abs(forwardDotProduct) < rotateLowerThreshold)
if (leftDotProduct > rotateUpperThreshold)
{
SetLeft();
return EnemyDirection.Left;
return EnemyDirection.Right;
}
}
@@ -112,14 +116,14 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
private void LoadShader(string shaderPath)
{
var shader = GD.Load<Shader>(shaderPath);
var sprites = FindChildren("*", "AnimatedSprite2D", true).Cast<AnimatedSprite2D>();
foreach (var sprite in sprites)
{
sprite.Material = new ShaderMaterial();
var shaderMaterial = (ShaderMaterial)sprite.Material;
shaderMaterial.Shader = shader;
}
var shader = GD.Load<Shader>(shaderPath);
var sprites = FindChildren("*", "AnimatedSprite2D", true).Cast<AnimatedSprite2D>();
foreach (var sprite in sprites)
{
sprite.Material = new ShaderMaterial();
var shaderMaterial = (ShaderMaterial)sprite.Material;
shaderMaterial.Shader = shader;
}
}
private void SetShaderValue(float shaderValue)

View File

@@ -796,8 +796,12 @@ switch_mode = 2
advance_mode = 2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_l2wq1"]
reset = false
switch_mode = 1
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_jwlar"]
reset = false
switch_mode = 1
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_fdoul"]
@@ -812,13 +816,11 @@ states/Walking/position = Vector2(653, 100)
transitions = ["Start", "Idle", SubResource("AnimationNodeStateMachineTransition_djeua"), "Idle", "Primary Attack", SubResource("AnimationNodeStateMachineTransition_8wbs7"), "Primary Attack", "Idle", SubResource("AnimationNodeStateMachineTransition_mnr4r"), "Idle", "Walking", SubResource("AnimationNodeStateMachineTransition_l2wq1"), "Walking", "Idle", SubResource("AnimationNodeStateMachineTransition_jwlar"), "Walking", "Primary Attack", SubResource("AnimationNodeStateMachineTransition_fdoul")]
[node name="EnemyModelView" type="Node3D"]
transform = Transform3D(3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0)
script = ExtResource("1_oh25a")
EnemyLoreInfo = SubResource("Resource_ivy74")
_enemyDirection = 1
[node name="Sprite3D" type="Sprite3D" parent="."]
transform = Transform3D(1.5, 0, 0, 0, 1.5, 0, 0, 0, 1.5, 0, 0, 0)
transform = Transform3D(6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0)
pixel_size = 0.001
billboard = 2
shaded = true
@@ -846,7 +848,6 @@ material = ExtResource("3_ivy74")
position = Vector2(100, 100)
sprite_frames = SubResource("SpriteFrames_6drt6")
animation = &"idle_left_walk"
frame = 6
[node name="Hitbox" type="Area3D" parent="."]
unique_name_in_owner = true

View File

@@ -800,12 +800,17 @@ advance_mode = 2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_ck0ak"]
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_y4gx8"]
reset = false
switch_mode = 2
advance_mode = 2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_fxhv6"]
reset = false
switch_mode = 1
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_pxi1p"]
reset = false
switch_mode = 1
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_gejfr"]
@@ -1184,7 +1189,6 @@ animations = [{
[node name="EnemyModelView" type="Node3D"]
script = ExtResource("1_o4cc2")
EnemyLoreInfo = SubResource("Resource_gby04")
_enemyDirection = 1
[node name="Sprite3D" type="Sprite3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.086869, 0)

View File

@@ -7191,7 +7191,7 @@ script = ExtResource("1_ol7va")
EnemyLoreInfo = SubResource("Resource_500at")
[node name="Sprite3D" type="Sprite3D" parent="."]
transform = Transform3D(1.5, 0, 0, 0, 1.5, 0, 0, 0, 1.5, 0, 3.13673, 0)
transform = Transform3D(1.5, 0, 0, 0, 1.5, 0, 0, 0, 1.5, 0, 1.85151, 0)
billboard = 2
alpha_cut = 1
texture_filter = 0

View File

@@ -6,7 +6,7 @@ namespace Zennysoft.Game.Ma;
public interface IEnemyLogic : ILogicBlock<EnemyLogic.State>;
[Meta, Id("enemy_logic")]
[LogicBlock(typeof(State), Diagram = true)]
[LogicBlock(typeof(State), Diagram = false)]
public partial class EnemyLogic : LogicBlock<EnemyLogic.State>, IEnemyLogic
{
public override Transition GetInitialState() => To<State.Idle>();

View File

@@ -1,31 +0,0 @@
@startuml EnemyLogic
state "EnemyLogic State" as Zennysoft_Game_Ma_EnemyLogic_State {
state "Alive" as Zennysoft_Game_Ma_EnemyLogic_State_Alive {
state "Activated" as Zennysoft_Game_Ma_EnemyLogic_State_Activated {
state "Attacking" as Zennysoft_Game_Ma_EnemyLogic_State_Attacking
state "FollowPlayer" as Zennysoft_Game_Ma_EnemyLogic_State_FollowPlayer
state "Patrolling" as Zennysoft_Game_Ma_EnemyLogic_State_Patrolling
}
state "Idle" as Zennysoft_Game_Ma_EnemyLogic_State_Idle
}
state "Defeated" as Zennysoft_Game_Ma_EnemyLogic_State_Defeated
}
Zennysoft_Game_Ma_EnemyLogic_State_Alive --> Zennysoft_Game_Ma_EnemyLogic_State_Attacking : AttackTimer
Zennysoft_Game_Ma_EnemyLogic_State_Alive --> Zennysoft_Game_Ma_EnemyLogic_State_Attacking : StartAttacking
Zennysoft_Game_Ma_EnemyLogic_State_Alive --> Zennysoft_Game_Ma_EnemyLogic_State_Defeated : EnemyDefeated
Zennysoft_Game_Ma_EnemyLogic_State_Alive --> Zennysoft_Game_Ma_EnemyLogic_State_FollowPlayer : Alerted
Zennysoft_Game_Ma_EnemyLogic_State_Alive --> Zennysoft_Game_Ma_EnemyLogic_State_Idle : StopMoving
Zennysoft_Game_Ma_EnemyLogic_State_Attacking --> Zennysoft_Game_Ma_EnemyLogic_State_Idle : StopMoving
Zennysoft_Game_Ma_EnemyLogic_State_FollowPlayer --> Zennysoft_Game_Ma_EnemyLogic_State_FollowPlayer : PhysicsTick
Zennysoft_Game_Ma_EnemyLogic_State_FollowPlayer --> Zennysoft_Game_Ma_EnemyLogic_State_Idle : LostPlayer
Zennysoft_Game_Ma_EnemyLogic_State_Idle --> Zennysoft_Game_Ma_EnemyLogic_State_Patrolling : StartPatrol
Zennysoft_Game_Ma_EnemyLogic_State_Patrolling --> Zennysoft_Game_Ma_EnemyLogic_State_Idle : StopMoving
Zennysoft_Game_Ma_EnemyLogic_State_Patrolling --> Zennysoft_Game_Ma_EnemyLogic_State_Patrolling : PatrolToRandomSpot
Zennysoft_Game_Ma_EnemyLogic_State_Patrolling --> Zennysoft_Game_Ma_EnemyLogic_State_Patrolling : PhysicsTick
Zennysoft_Game_Ma_EnemyLogic_State_Alive : OnAttackTimer → TakeAction
Zennysoft_Game_Ma_EnemyLogic_State_Alive : OnEnemyDefeated → Defeated
[*] --> Zennysoft_Game_Ma_EnemyLogic_State_Idle
@enduml

View File

@@ -1,6 +1,5 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Zennysoft.Game.Ma;
using Godot;
using System.Collections.Generic;
using System.Linq;
@@ -54,10 +53,4 @@ public partial class RescuedItems : Node3D
Game.RescuedItems.Items.Clear();
}
public void OnSpawnItemsEntered(Node3D body)
{
GD.Print("Spawn items");
SpawnRescuedItems();
}
}

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://tc5kdfoggrng"]
[ext_resource type="Script" path="res://src/item_rescue/RescuedItems.cs" id="1_m08l5"]
[ext_resource type="Script" uid="uid://cav0todblih41" path="res://src/item_rescue/RescuedItems.cs" id="1_m08l5"]
[node name="Rescued Items" type="Node3D"]
script = ExtResource("1_m08l5")

View File

@@ -16,27 +16,30 @@ public partial class Overworld : Node3D, IDungeonFloor
[Node] private Area3D Exit { get; set; } = default!;
[Node] private RescuedItems RescuedItems { get; set; } = default!;
public ImmutableList<IDungeonRoom> Rooms => [];
public bool FloorIsLoaded { get; set; }
public void InitializeDungeon()
{
Show();
Exit.AreaEntered += Exit_AreaEntered;
FloorIsLoaded = true;
Show();
Exit.AreaEntered += Exit_AreaEntered;
RescuedItems.SpawnRescuedItems();
FloorIsLoaded = true;
}
private void Exit_AreaEntered(Area3D area)
{
if (area.GetOwner() is IPlayer)
ExitReached();
if (area.GetOwner() is IPlayer)
ExitReached();
}
public void ExitReached() => Game.FloorExitReached();
public Transform3D GetPlayerSpawnPoint()
{
return PlayerSpawnPoint.GlobalTransform;
return PlayerSpawnPoint.GlobalTransform;
}
}

View File

@@ -139,6 +139,7 @@
[ext_resource type="PackedScene" uid="uid://cjj6wabswtkk1" path="res://src/npc/Caretaker/Caretaker.tscn" id="80_8isf0"]
[ext_resource type="CompressedTexture2DArray" uid="uid://c0kjnbpgaa6bs" path="res://src/map/assets/caustics.png" id="84_r86sn"]
[ext_resource type="Texture2D" uid="uid://cbsdc4uthojov" path="res://src/map/assets/waternormal2.jpg" id="85_0u0mt"]
[ext_resource type="PackedScene" uid="uid://tc5kdfoggrng" path="res://src/item_rescue/RescuedItems.tscn" id="141_b6pah"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_o2o3t"]
resource_name = "Material"
@@ -17891,5 +17892,11 @@ light_energy = 0.329
shadow_enabled = true
omni_range = 60.893
[node name="Item Transport" type="Node3D" parent="."]
[node name="RescuedItems" parent="Item Transport" instance=ExtResource("141_b6pah")]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -349.863, 9.41853, 131.703)
[editable path="Actors/Clalo"]
[editable path="Actors/Caretaker of Saints"]