diff --git a/Scenes/Interactable/ScriptableAreaTrigger.tscn b/Scenes/Interactable/ScriptableAreaTrigger.tscn new file mode 100644 index 00000000..49574787 --- /dev/null +++ b/Scenes/Interactable/ScriptableAreaTrigger.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=4 format=3 uid="uid://fxvlaidieiv7"] + +[ext_resource type="Script" path="res://Scripts/Activables/ScriptableBase.cs" id="1_jpwi6"] +[ext_resource type="Script" path="res://Scripts/Interactables/AreaTrigger.cs" id="1_l5s1w"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_1nht3"] + +[node name="ScriptableAreaTrigger" type="Node2D"] +script = ExtResource("1_jpwi6") +Events = Array[Object]([]) + +[node name="AreaTrigger" type="Area2D" parent="."] +collision_layer = 4 +collision_mask = 2 +script = ExtResource("1_l5s1w") +OneTime = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="AreaTrigger"] +shape = SubResource("RectangleShape2D_1nht3") + +[connection signal="Activated" from="AreaTrigger" to="." method="Start"] +[connection signal="area_entered" from="AreaTrigger" to="AreaTrigger" method="_on_area_entered"] diff --git a/Scenes/test.tscn b/Scenes/test.tscn index 8afd1fc6..a4eff5a4 100644 --- a/Scenes/test.tscn +++ b/Scenes/test.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=46 format=4 uid="uid://bv451a8wgty4u"] +[gd_scene load_steps=54 format=4 uid="uid://bv451a8wgty4u"] [ext_resource type="Script" path="res://Scripts/GameManager.cs" id="1_8tmoj"] [ext_resource type="PackedScene" uid="uid://bghghp5ep4w2j" path="res://Scenes/player.tscn" id="2_8mh54"] @@ -42,6 +42,10 @@ [ext_resource type="PackedScene" uid="uid://d0yes7huiyisw" path="res://Scenes/Items/Blue_Keycard.tscn" id="35_rblsn"] [ext_resource type="PackedScene" uid="uid://r25rq6ijgm6m" path="res://Scenes/Items/Green_Keycard.tscn" id="36_f8fh1"] [ext_resource type="Script" path="res://Scripts/Activables/PlayerMover.cs" id="37_wxy1q"] +[ext_resource type="PackedScene" uid="uid://fxvlaidieiv7" path="res://Scenes/Interactable/ScriptableAreaTrigger.tscn" id="43_kf3qc"] +[ext_resource type="Script" path="res://Scripts/Resources/Events/MovePlayerEvent.cs" id="44_klwgh"] +[ext_resource type="Script" path="res://Scripts/Resources/Events/ActivateEvent.cs" id="45_emjoj"] +[ext_resource type="Script" path="res://Scripts/Resources/Events/DialogueStartEvent.cs" id="46_i0omr"] [sub_resource type="CircleShape2D" id="CircleShape2D_vuevm"] @@ -49,6 +53,31 @@ [sub_resource type="CircleShape2D" id="CircleShape2D_8wuck"] +[sub_resource type="Resource" id="Resource_4f4id"] +script = ExtResource("44_klwgh") +RelativeTargetPosition = Vector2(0, -64) +MovementTime = 1.0 +EaseType = 2 +TransitionType = 0 +WaitForCompletion = true + +[sub_resource type="Resource" id="Resource_s2o7m"] +script = ExtResource("45_emjoj") +ActivationType = 2 +Targets = Array[NodePath]([NodePath("../Factory Tilemaps/HorizontalDoor3"), NodePath("../Factory Tilemaps/HorizontalDoor5")]) +WaitForCompletion = true + +[sub_resource type="Resource" id="Resource_b1dht"] +script = ExtResource("46_i0omr") +TimelineName = "Rumia_Intro" +WaitForCompletion = true + +[sub_resource type="Resource" id="Resource_xrgpy"] +script = ExtResource("45_emjoj") +ActivationType = 0 +Targets = Array[NodePath]([NodePath("../Rumia")]) +WaitForCompletion = true + [node name="GameScene" type="Node2D" node_paths=PackedStringArray("PlayerSpawnMarker")] position = Vector2(38, 39) script = ExtResource("1_8tmoj") @@ -281,7 +310,7 @@ script = ExtResource("25_rpwvt") position = Vector2(-1111, -22) [node name="AreaTrigger" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("28_6au4t")] -position = Vector2(-1487, -366) +position = Vector2(-1357, -356) Target = NodePath("../PlayerMover") OneTime = true @@ -376,3 +405,7 @@ position = Vector2(-808, -400) [node name="Ammo4" parent="." instance=ExtResource("34_17pjh")] position = Vector2(-791, -401) + +[node name="ScriptableAreaTrigger" parent="." instance=ExtResource("43_kf3qc")] +position = Vector2(-1487, -396) +Events = Array[Object]([SubResource("Resource_4f4id"), SubResource("Resource_s2o7m"), SubResource("Resource_b1dht"), SubResource("Resource_xrgpy")]) diff --git a/Scripts/Activables/ScriptableBase.cs b/Scripts/Activables/ScriptableBase.cs new file mode 100644 index 00000000..e69c7693 --- /dev/null +++ b/Scripts/Activables/ScriptableBase.cs @@ -0,0 +1,62 @@ +using System; +using Cirno.Scripts.Resources.Events; +using Godot; +using Godot.Collections; + +namespace Cirno.Scripts.Activables; + +public partial class ScriptableBase : Node2D +{ + [Export] public Array Events; + + private EventResource CurrentEvent => Events[_currentEventIndex]; + + private int _currentEventIndex = 0; + + private bool _started = false; + + public override void _Ready() + { + + } + + public void Start() + { + _started = true; + StartEvent(CurrentEvent); + } + + private void StartEvent(EventResource eventResource) + { + eventResource.Start(this); + } + + public override void _Process(double delta) + { + if (!_started) return; + + CurrentEvent.UpdateEvent(delta); + + if (!CurrentEvent.WaitForCompletion || CurrentEvent.IsComplete()) + { + // This loops + //_currentEventIndex = (_currentEventIndex + 1) % Events.Count; + _currentEventIndex++; + if (_currentEventIndex >= Events.Count) + { + // It's over + _started = false; + _currentEventIndex = 0; + return; + } + + CurrentEvent.Start(this); + } + // if (_currentHealth <= CurrentPhase.Threshold && currentPhaseIndex + 1 < Phases.Count) + // { + // currentPhaseIndex++; + // _bossHud.SpellCardName = CurrentPhase.PhaseName; + // StartPhase(CurrentPhase); + // } + } +} \ No newline at end of file diff --git a/Scripts/Door.cs b/Scripts/Door.cs index ac89371e..355db5cf 100644 --- a/Scripts/Door.cs +++ b/Scripts/Door.cs @@ -46,17 +46,36 @@ public partial class Door : Activable public override void Activate(ActivationType activationType = ActivationType.Toggle) { - switch (State) + switch (activationType) { - case DoorState.Closed: + case ActivationType.Toggle: + switch (State) + { + case DoorState.Closed: + Open(); + break; + case DoorState.Open: + Close(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + break; + case ActivationType.Enable: Open(); break; - case DoorState.Open: + case ActivationType.Disable: Close(); break; + case ActivationType.Use: + break; + case ActivationType.Destroy: + break; default: - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(activationType), activationType, null); } + + } private void SetState(DoorState state) diff --git a/Scripts/Interactables/AreaEventTrigger.cs b/Scripts/Interactables/AreaEventTrigger.cs new file mode 100644 index 00000000..791d553e --- /dev/null +++ b/Scripts/Interactables/AreaEventTrigger.cs @@ -0,0 +1,6 @@ +namespace Cirno.Scripts.Interactables; + +public partial class AreaEventTrigger +{ + +} \ No newline at end of file diff --git a/Scripts/Interactables/AreaTrigger.cs b/Scripts/Interactables/AreaTrigger.cs index b1a2ed7b..5a98226a 100644 --- a/Scripts/Interactables/AreaTrigger.cs +++ b/Scripts/Interactables/AreaTrigger.cs @@ -12,6 +12,9 @@ public partial class AreaTrigger : Area2D [Export] public bool DoNotActivateOnFirst { get; set; } private int _activations = 0; + + [Signal] + public delegate void ActivatedEventHandler(); public bool Activate(InteractionController player) { @@ -23,12 +26,17 @@ public partial class AreaTrigger : Area2D if (OneTime && _activations > 0) return false; - if (Target is not IActivable target) + if (Target != null) { - GD.PrintErr($"Target {Target.Name} is not activable"); - return false; + if (Target is not IActivable target) + { + GD.PrintErr($"Target {Target.Name} is not activable"); + return false; + } + target.Activate(); } - target.Activate(); + + EmitSignal(nameof(Activated)); _activations++; diff --git a/Scripts/Resources/Events/ActivateEvent.cs b/Scripts/Resources/Events/ActivateEvent.cs new file mode 100644 index 00000000..639fcfb0 --- /dev/null +++ b/Scripts/Resources/Events/ActivateEvent.cs @@ -0,0 +1,56 @@ +using Godot; +using Godot.Collections; + +namespace Cirno.Scripts.Resources.Events; + +[GlobalClass] +public partial class ActivateEvent : EventResource +{ + [Export] public ActivationType ActivationType = ActivationType.Toggle; + + [Export] public Array Targets; + + private Node2D _parent; + + private bool _isComplete = false; + + protected void ActivateTargets() + { + foreach (var activationTarget in Targets) + { + ActivateTarget(_parent.GetNode(activationTarget)); + } + } + + private bool ActivateTarget(Node2D activationTarget) + { + if (activationTarget is not IActivable target) + { + GD.PrintErr($"Target {activationTarget.Name} is not activable"); + return false; + } + + target?.Activate(ActivationType); + + GD.Print($"{activationTarget.Name} activated"); + + return true; + } + + public override void Start(Node2D parent) + { + _parent = parent; + ActivateTargets(); + _isComplete = true; + } + + public override void UpdateEvent(double delta) + { + + } + + public override bool IsComplete() + { + return _isComplete; + } +} \ No newline at end of file diff --git a/Scripts/Resources/Events/DialogueStartEvent.cs b/Scripts/Resources/Events/DialogueStartEvent.cs new file mode 100644 index 00000000..07d7021d --- /dev/null +++ b/Scripts/Resources/Events/DialogueStartEvent.cs @@ -0,0 +1,52 @@ +using Godot; + +namespace Cirno.Scripts.Resources.Events; + +[GlobalClass] +public partial class DialogueStartEvent : EventResource +{ + [Export] public string TimelineName = "timeline"; + private Node _dialogic; + private GameManager _gameManager; + private bool _isComplete = false; + + public override void Start(Node2D parent) + { + _gameManager = parent.GetGameManager(); + + _dialogic = parent.GetNode("/root/Dialogic"); + + _gameManager.ChangeState(GameState.Dialogue); + + _dialogic.Connect("timeline_ended", Callable.From(OnTimelineEnded)); + + _dialogic.Call("start", TimelineName); + } + + private void OnTimelineEnded() + { + + if (_dialogic.IsConnected("timeline_ended", Callable.From(OnTimelineEnded))) + { + _dialogic.Disconnect("timeline_ended", Callable.From(OnTimelineEnded)); + } + + DialogueEndAction(); + } + + private void DialogueEndAction() + { + _gameManager.ChangeState(GameState.Playing); + _isComplete = true; + } + + public override void UpdateEvent(double delta) + { + + } + + public override bool IsComplete() + { + return _isComplete; + } +} \ No newline at end of file diff --git a/Scripts/Resources/Events/EventResource.cs b/Scripts/Resources/Events/EventResource.cs new file mode 100644 index 00000000..3717faf6 --- /dev/null +++ b/Scripts/Resources/Events/EventResource.cs @@ -0,0 +1,12 @@ +using Godot; + +namespace Cirno.Scripts.Resources.Events; + +[GlobalClass] +public abstract partial class EventResource : Resource +{ + [Export] public bool WaitForCompletion = true; + public abstract void Start(Node2D parent); + public abstract void UpdateEvent(double delta); + public abstract bool IsComplete(); +} \ No newline at end of file diff --git a/Scripts/Resources/Events/MovePlayerEvent.cs b/Scripts/Resources/Events/MovePlayerEvent.cs new file mode 100644 index 00000000..da76a54f --- /dev/null +++ b/Scripts/Resources/Events/MovePlayerEvent.cs @@ -0,0 +1,56 @@ +using System.Threading.Tasks; +using Godot; + +namespace Cirno.Scripts.Resources.Events; + +[GlobalClass] +public partial class MovePlayerEvent : EventResource +{ + [Export] + public Vector2 RelativeTargetPosition = Vector2.Zero; + + [Export] + public float MovementTime = 1f; + + [Export] + public Tween.EaseType EaseType = Tween.EaseType.InOut; + + [Export] + public Tween.TransitionType TransitionType = Tween.TransitionType.Linear; + + private bool _isComplete = false; + + private GameManager _gameManager; + + public override void Start(Node2D parentNode) + { + _gameManager = parentNode.GetGameManager(); + _isComplete = false; + + _ = MovePlayer(); + } + + protected async Task MovePlayer() + { + _gameManager.Player.RequestMovementDisable(true); + + Tween tween = _gameManager.GetTree().CreateTween(); + tween.SetEase(EaseType); + tween.SetTrans(TransitionType); + tween.TweenProperty(_gameManager.Player, "global_position", _gameManager.Player.GlobalPosition + RelativeTargetPosition, MovementTime); + + // Wait for the tween to finish + await ToSignal(tween, "finished"); + + _gameManager.Player.RequestMovementDisable(false); + + _isComplete = true; + } + + public override void UpdateEvent(double delta) { } + + public override bool IsComplete() + { + return _isComplete; + } +} \ No newline at end of file