Add TriggerActionFactory and related resources for button and logic sequence components

This commit is contained in:
2025-10-30 02:21:27 +01:00
parent f2ff758dcb
commit 2c126cd7ea
22 changed files with 250 additions and 13 deletions

View File

@@ -9,6 +9,7 @@ using GameCore.ECS.Interfaces;
using GameCore.Input;
using GameCore.Interaction;
using GameCore.Inventory;
using GameCore.Logic;
using GameCore.Movement;
using GameCore.Physics;
using GameCore.Player;
@@ -21,11 +22,13 @@ public class ComponentFactory
private readonly Dictionary<Type, Func<Resource, IComponent>> _factories = new();
private readonly EffectFactory _effectFactory;
private readonly InteractionRequirementFactory _requirementFactory;
private readonly TriggerActionFactory _triggerActionFactory;
public ComponentFactory(EffectFactory effectFactory, InteractionRequirementFactory requirementFactory)
public ComponentFactory(EffectFactory effectFactory, InteractionRequirementFactory requirementFactory, TriggerActionFactory triggerActionFactory)
{
_effectFactory = effectFactory;
_requirementFactory = requirementFactory;
_triggerActionFactory = triggerActionFactory;
Register<AttributeComponentResource>(CreateAttributeComponent);
Register<WeaponComponentResource>(CreateWeaponComponent);
@@ -40,6 +43,9 @@ public class ComponentFactory
Register<PickupComponentResource>(CreatePickupComponent);
Register<EquipmentComponentResource>(_ => new EquipmentComponent());
Register<DoorComponentResource>(CreateDoorComponent);
Register<WorldIdComponentResource>(res => new WorldIdComponent(res.WorldId));
Register<ButtonComponentResource>(CreateButtonComponent);
Register<LogicSequenceComponentResource>(CreateLogicSequenceComponent);
}
public IComponent Create(Resource resource)
@@ -129,4 +135,47 @@ public class ComponentFactory
return component;
}
private ButtonComponent CreateButtonComponent(ButtonComponentResource resource)
{
var component = new ButtonComponent
{
ChannelId = resource.ChannelId,
IsToggle = resource.IsToggle,
IsOneTimeUse = resource.IsOneTimeUse,
IsPressed = false,
HasBeenUsed = false,
};
foreach (var reqResource in resource.Requirements)
{
var requirement = _requirementFactory.Create(reqResource);
if (requirement != null)
{
component.Requirements.Add(requirement);
}
}
return component;
}
private LogicSequenceComponent CreateLogicSequenceComponent(LogicSequenceComponentResource resource)
{
var component = new LogicSequenceComponent
{
RequiredChannels = resource.RequiredChannels.ToList(),
IsOneTimeTrigger = resource.IsOneTimeTrigger,
};
foreach (var actionResource in resource.OnCompleteActions)
{
var action = _triggerActionFactory.Create(actionResource);
if (action != null)
{
component.OnCompleteActions.Add(action);
}
}
return component;
}
}

View File

@@ -0,0 +1,21 @@
using System;
using CryptonymThunder.Code.Resources;
using GameCore.Logic;
using GameCore.Logic.Interfaces;
namespace CryptonymThunder.Code.Factories;
public class TriggerActionFactory
{
public ITriggerAction Create(TriggerActionResource resource)
{
return resource switch
{
UnlockDoorActionResource unlock => new UnlockDoorAction(unlock.TargetWorldId),
SpawnEntityActionResource spawn => new SpawnEntityAction(spawn.ArchetypeId, spawn.SpawnerWorldId),
DebugMessageActionResource debug => new DebugMessageAction(debug.Message),
_ => throw new ArgumentOutOfRangeException(nameof(resource),
$"TriggerAction type {resource.GetType().Name} not recognized")
};
}
}

View File

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

View File

@@ -15,6 +15,7 @@ using GameCore.Interaction;
using GameCore.Inventory;
using GameCore.Logging;
using GameCore.Logging.Interfaces;
using GameCore.Logic;
using GameCore.Movement;
using GameCore.Player;
using Godot;
@@ -64,7 +65,8 @@ public partial class GamePresenter : Node
var effectFactory = new EffectFactory();
var requirementFactory = new InteractionRequirementFactory();
var componentFactory = new ComponentFactory(effectFactory, requirementFactory);
var triggerActionFactory = new TriggerActionFactory();
var componentFactory = new ComponentFactory(effectFactory, requirementFactory, triggerActionFactory);
var weaponDataService = new GodotWeaponDataService(WeaponDatabase, effectFactory);
_presenterFactory = new PresenterFactory(_world, componentFactory, _presenterRegistry, this);
@@ -85,6 +87,7 @@ public partial class GamePresenter : Node
_world.RegisterSystem(new InteractionSystem(InteractionRange));
_world.RegisterSystem(new DoorSystem());
_world.RegisterSystem(new LogicSequenceSystem(_world));
_world.RegisterSystem(new WeaponSystem());
_world.RegisterSystem(new ProjectileSystem());

View File

@@ -125,10 +125,12 @@ public partial class HudPresenterComponent : Control, IPresenterComponent
var lookingAt = _world.GetComponent<IsLookingAtInteractableComponent>(_playerEntity);
if (lookingAt != null)
{
var door = _world.GetComponent<DoorComponent>(lookingAt.Target);
var targetEntity = lookingAt.Target;
var interactKey = "F";
var door = _world.GetComponent<DoorComponent>(targetEntity);
if (door != null)
{
var interactKey = "F";
_interactLabel.Text = door.CurrentState switch
{
DoorComponent.DoorState.Locked => $"[{interactKey}] Interact (Locked)",
@@ -140,7 +142,26 @@ public partial class HudPresenterComponent : Control, IPresenterComponent
}
else
{
_interactLabel.Visible = false;
var button = _world.GetComponent<ButtonComponent>(targetEntity);
if (button != null)
{
if (button.IsOneTimeUse && button.HasBeenUsed)
{
_interactLabel.Text = "(Used)";
}
else if (button.IsToggle)
{
_interactLabel.Text = button.IsPressed ? $"[{interactKey}] Deactivate" : $"[{interactKey}] Activate";
}
else
{
_interactLabel.Text = $"[{interactKey}] Press Button";
}
_interactLabel.Visible = true;
} else
{
_interactLabel.Visible = false;
}
}
}
else

View File

@@ -0,0 +1,15 @@
using Godot;
using Godot.Collections;
namespace CryptonymThunder.Code.Resources;
[GlobalClass]
public partial class ButtonComponentResource : Resource
{
[Export] public string ChannelId { get; set; } = "default_channel";
[Export] public bool IsToggle { get; set; } = false;
[Export] public bool IsOneTimeUse { get; set; } = false;
[ExportGroup("Requirements")]
[Export] public Array<InteractionRequirementResource> Requirements { get; set; } = [];
}

View File

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

View File

@@ -0,0 +1,9 @@
using Godot;
namespace CryptonymThunder.Code.Resources;
[GlobalClass]
public partial class DebugMessageActionResource : TriggerActionResource
{
[Export(PropertyHint.MultilineText)] public string Message { get; set; } = "Trigger Fired!";
}

View File

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

View File

@@ -0,0 +1,12 @@
using Godot;
using Godot.Collections;
namespace CryptonymThunder.Code.Resources;
[GlobalClass]
public partial class LogicSequenceComponentResource : Resource
{
[Export] public Array<string> RequiredChannels { get; set; } = [];
[Export] public Array<TriggerActionResource> OnCompleteActions { get; set; } = [];
[Export] public bool IsOneTimeTrigger { get; set; } = true;
}

View File

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

View File

@@ -0,0 +1,10 @@
using Godot;
namespace CryptonymThunder.Code.Resources;
[GlobalClass]
public partial class SpawnEntityActionResource : TriggerActionResource
{
[Export] public string ArchetypeId { get; set; } = "enemy_grunt";
[Export] public string SpawnerWorldId { get; set; } = "spawner_location_1";
}

View File

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

View File

@@ -0,0 +1,8 @@
using Godot;
namespace CryptonymThunder.Code.Resources;
public partial class TriggerActionResource : Resource
{
}

View File

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

View File

@@ -0,0 +1,9 @@
using Godot;
namespace CryptonymThunder.Code.Resources;
[GlobalClass]
public partial class UnlockDoorActionResource : TriggerActionResource
{
[Export] public string TargetWorldId { get; set; } = "door_to_unlock";
}

View File

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

View File

@@ -0,0 +1,9 @@
using Godot;
namespace CryptonymThunder.Code.Resources;
[GlobalClass]
public partial class WorldIdComponentResource : Resource
{
[Export] public string WorldId { get; set; } = "unique_id_01";
}

View File

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

View File

@@ -3,8 +3,8 @@
[ext_resource type="Script" uid="uid://bxqite0b1di2b" path="res://Code/Presenters/DoorPresenter.cs" id="1_0k8gl"]
[ext_resource type="Script" uid="uid://cratjw4trngpr" path="res://Code/Resources/LerpDoorBehavior.cs" id="2_3dbp0"]
[ext_resource type="Script" uid="uid://b6x8llipvutqs" path="res://Code/Presenters/SceneEntity.cs" id="2_l5dry"]
[ext_resource type="Script" uid="uid://dnyfoaprv6bhw" path="res://Code/Resources/RequiresItemRequirementResource.cs" id="3_3dbp0"]
[ext_resource type="Script" uid="uid://ymtyxkea76mv" path="res://Code/Resources/DoorComponentResource.cs" id="4_g4ryb"]
[ext_resource type="Script" uid="uid://rd33g3u352g6" path="res://Code/Resources/WorldIdComponentResource.cs" id="6_g4ryb"]
[sub_resource type="Resource" id="Resource_3dbp0"]
script = ExtResource("2_3dbp0")
@@ -21,16 +21,17 @@ albedo_color = Color(0.14891627, 0.744422, 0, 1)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_l5dry"]
points = PackedVector3Array(-0.5, -1, -0.15, -0.5, -1, 0.15, -0.5, 1, -0.15, 0.5, -1, -0.15, 0.5, -1, 0.15, -0.5, 1, 0.15, 0.5, 1, -0.15, 0.5, 1, 0.15)
[sub_resource type="Resource" id="Resource_g2hal"]
script = ExtResource("3_3dbp0")
metadata/_custom_type_script = "uid://dnyfoaprv6bhw"
[sub_resource type="Resource" id="Resource_fyehb"]
script = ExtResource("4_g4ryb")
InitialState = 0
Requirements = Array[Object]([SubResource("Resource_g2hal")])
Requirements = Array[Object]([])
metadata/_custom_type_script = "uid://ymtyxkea76mv"
[sub_resource type="Resource" id="Resource_rv1pd"]
script = ExtResource("6_g4ryb")
WorldId = "green_door"
metadata/_custom_type_script = "uid://rd33g3u352g6"
[node name="GreenDoor" type="CharacterBody3D"]
script = ExtResource("1_0k8gl")
_behavior = SubResource("Resource_3dbp0")
@@ -44,5 +45,5 @@ shape = SubResource("ConvexPolygonShape3D_l5dry")
[node name="SceneEntity" type="Node" parent="." groups=["SceneEntities"]]
script = ExtResource("2_l5dry")
ComponentResources = Array[Resource]([SubResource("Resource_fyehb")])
ComponentResources = Array[Resource]([SubResource("Resource_fyehb"), SubResource("Resource_rv1pd")])
metadata/_custom_type_script = "uid://b6x8llipvutqs"

View File

@@ -0,0 +1,35 @@
[gd_scene load_steps=8 format=3 uid="uid://bjbsk8nhi5e4i"]
[ext_resource type="Script" uid="uid://cb7vaw6xqjs1i" path="res://Code/Presenters/EntityPresenter.cs" id="1_qhhav"]
[ext_resource type="Script" uid="uid://b6x8llipvutqs" path="res://Code/Presenters/SceneEntity.cs" id="2_apu07"]
[ext_resource type="Script" uid="uid://cc1okvlx8p0tr" path="res://Code/Resources/ButtonComponentResource.cs" id="3_8x8af"]
[sub_resource type="BoxMesh" id="BoxMesh_kgm0y"]
size = Vector3(0.1, 0.1, 0.1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_o42jp"]
albedo_color = Color(0.20152658, 0.20152658, 0.20152658, 1)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_qhhav"]
points = PackedVector3Array(-0.049999997, -0.04999998, -0.04999998, 0.049997684, 0.049999997, 0.049999997, 0.049997684, 0.049999997, -0.049999997, 0.049997684, -0.049999997, 0.049999997, -0.049999997, 0.04999998, 0.04999998, 0.049997684, -0.049999997, -0.049999997, -0.049999997, 0.04999998, -0.04999998, -0.049999997, -0.04999998, 0.04999998)
[sub_resource type="Resource" id="Resource_nak1n"]
script = ExtResource("3_8x8af")
ChannelId = "green_door_button"
Requirements = null
metadata/_custom_type_script = "uid://cc1okvlx8p0tr"
[node name="Button" type="StaticBody3D"]
script = ExtResource("1_qhhav")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_kgm0y")
surface_material_override/0 = SubResource("StandardMaterial3D_o42jp")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("ConvexPolygonShape3D_qhhav")
[node name="SceneEntity" type="Node" parent="." groups=["SceneEntities"]]
script = ExtResource("2_apu07")
ComponentResources = Array[Resource]([SubResource("Resource_nak1n")])
metadata/_custom_type_script = "uid://b6x8llipvutqs"

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=27 format=4 uid="uid://bkvgcsb8d3v7p"]
[gd_scene load_steps=32 format=4 uid="uid://bkvgcsb8d3v7p"]
[ext_resource type="Script" uid="uid://cfpm5p102f65x" path="res://Code/Presenters/GamePresenter.cs" id="1_qvgq0"]
[ext_resource type="Resource" uid="uid://biev6ri5s8kyf" path="res://Resources/Entities/player.tres" id="2_alii3"]
@@ -14,6 +14,9 @@
[ext_resource type="PackedScene" uid="uid://bfnu4py7n2sv5" path="res://Objects/pistol_pickup.tscn" id="12_00aki"]
[ext_resource type="PackedScene" uid="uid://b1d2gc8goj6gx" path="res://Objects/green_door.tscn" id="13_00aki"]
[ext_resource type="PackedScene" uid="uid://cww3lcsxldnt3" path="res://Objects/green_card_pickup.tscn" id="14_5qvjo"]
[ext_resource type="PackedScene" uid="uid://bjbsk8nhi5e4i" path="res://Objects/green_door_button.tscn" id="15_g7kif"]
[ext_resource type="Script" uid="uid://cgsqrgdok7ovp" path="res://Code/Resources/UnlockDoorActionResource.cs" id="16_vpkaq"]
[ext_resource type="Script" uid="uid://c4csquqmqqqww" path="res://Code/Resources/LogicSequenceComponentResource.cs" id="17_df4ul"]
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_ucfah"]
data = PackedVector3Array(-4.282257, -0.5, 4.977783, -4.282257, -0.5, -4.977783, -4.282257, 0.5, -4.977783, 4.282257, -0.5, -4.977783, -4.282257, -0.5, -4.977783, -4.282257, -0.5, 4.977783, -4.282257, 0.5, -4.977783, -4.282257, -0.5, -4.977783, 4.282257, -0.5, -4.977783, -4.282257, 0.5, -4.977783, -4.282257, 0.5, 4.977783, -4.282257, -0.5, 4.977783, -4.282257, -0.5, 4.977783, -4.282257, 0.5, 4.977783, 4.282257, 0.5, 4.977783, 4.282257, 0.5, 4.977783, -4.282257, 0.5, 4.977783, -4.282257, 0.5, -4.977783, -4.282257, -0.5, 4.977783, 4.282257, -0.5, 4.977783, 4.282257, -0.5, -4.977783, 4.282257, 0.5, 4.977783, 4.282257, -0.5, 4.977783, -4.282257, -0.5, 4.977783, 4.282257, -0.5, -4.977783, 4.282257, -0.5, 4.977783, 4.282257, 0.5, 4.977783, 4.282257, -0.5, -4.977783, 4.282257, 0.5, -4.977783, -4.282257, 0.5, -4.977783, -4.282257, 0.5, -4.977783, 4.282257, 0.5, -4.977783, 4.282257, 0.5, 4.977783, 4.282257, 0.5, 4.977783, 4.282257, 0.5, -4.977783, 4.282257, -0.5, -4.977783)
@@ -65,6 +68,17 @@ BaseValues = Dictionary[int, float]({
})
metadata/_custom_type_script = "uid://dc7wq2ij5kwj5"
[sub_resource type="Resource" id="Resource_q0a86"]
script = ExtResource("16_vpkaq")
TargetWorldId = "green_door"
metadata/_custom_type_script = "uid://cgsqrgdok7ovp"
[sub_resource type="Resource" id="Resource_3hp7m"]
script = ExtResource("17_df4ul")
RequiredChannels = Array[String](["green_door_button"])
OnCompleteActions = Array[Resource]([SubResource("Resource_q0a86")])
metadata/_custom_type_script = "uid://c4csquqmqqqww"
[node name="GameWorld" type="Node3D"]
[node name="Geometry" type="Node" parent="."]
@@ -251,6 +265,19 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.7087288, -0.8145535, 4.614
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.122588, -0.81455374, 1.582226)
[node name="GreenDoor" parent="." instance=ExtResource("13_00aki")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.8655286, -0.0645535, 5.593994)
[node name="Green Card Pickup" parent="." instance=ExtResource("14_5qvjo")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.2713692, -0.86455375, 3.3032908)
[node name="DoorButton" parent="." instance=ExtResource("15_g7kif")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.097641, 0.08375314, 4.357219)
[node name="DoorLogic" type="Node3D" parent="."]
script = ExtResource("5_d0bjv")
metadata/_custom_type_script = "uid://cb7vaw6xqjs1i"
[node name="SceneEntity" type="Node" parent="DoorLogic" groups=["SceneEntities"]]
script = ExtResource("5_f1ejf")
ComponentResources = Array[Resource]([SubResource("Resource_3hp7m")])
metadata/_custom_type_script = "uid://b6x8llipvutqs"