This commit is contained in:
cblech
2025-07-25 20:20:34 +02:00
parent b6373e6a2b
commit f6e9a6f9b5
22 changed files with 193 additions and 30 deletions
+1
View File
@@ -0,0 +1 @@
Babushka
@@ -82,4 +82,3 @@ func add_end_control(control:Control) -> void:
if control.has_method('refresh'): if control.has_method('refresh'):
control.refresh() control.refresh()
end_control = control end_control = control
@@ -4,11 +4,12 @@ importer="scene"
importer_version=1 importer_version=1
type="PackedScene" type="PackedScene"
uid="uid://b3kyrsoobmkhp" uid="uid://b3kyrsoobmkhp"
valid=false path="res://.godot/imported/best_house_blender.blend-ac89c74aef2f275bdf4b4baadee17c0c.scn"
[deps] [deps]
source_file="res://art/mockups/3d/best_house_blender.blend" source_file="res://art/mockups/3d/best_house_blender.blend"
dest_files=["res://.godot/imported/best_house_blender.blend-ac89c74aef2f275bdf4b4baadee17c0c.scn"]
[params] [params]
+2
View File
@@ -1,5 +1,6 @@
join Yeli center join Yeli center
join Vesna2 center join Vesna2 center
[quest_complete quest_resource="res://resources/quests/demo/5_talk_yeli_3.tres"]
Yeli (_part_side): Great! Now I need you to plant some tomatoes! Yeli (_part_side): Great! Now I need you to plant some tomatoes!
label plant tomatoes label plant tomatoes
Yeli (_part_side): Use the hoe to break up the soil. Then plant the seeds and water the fields. Yeli (_part_side): Use the hoe to break up the soil. Then plant the seeds and water the fields.
@@ -7,4 +8,5 @@ Yeli (_part_side): Got it?
- Of course! - Of course!
- Wait … How do I plant the tomatoes again? - Wait … How do I plant the tomatoes again?
jump plant tomatoes jump plant tomatoes
[quest_activate quest_resource="res://resources/quests/demo/6_till_and_water.tres"]
[end_timeline] [end_timeline]
+3 -1
View File
@@ -1,10 +1,12 @@
join Yeli center join Yeli center
join Vesna2 center join Vesna2 center
[quest_complete quest_resource="res://resources/quests/demo/3_talk_yeli_2.tres"]
Yeli (_part_side): Thank you, my child! Your Yeli is not so agile anymore. Yeli (_part_side): Thank you, my child! Your Yeli is not so agile anymore.
Vesna2: But youre diligent! Youve started with the preparation for dinner. Vesna2: But youre diligent! Youve started with the preparation for dinner.
Yeli (_part_side): Indeed, I have. Yeli (_part_side): Indeed, I have.
Yeli (_part_side): But, oh my, those ducks messed up the tomatos. Yeli (_part_side): But, oh my, those ducks messed up the tomatos.
Yeli (_part_side): Oh, would you like to assist me? Yeli (_part_side): Oh, would you like to assist me?
Vesna2: What do I have to do? Vesna2: What do I have to do?
Yeli (_part_side): First, take the hoe and watering can over there! Then come back to me! Yeli (_part_side): First, take the hoe and watering can over there! Then come back to me!
[quest_activate quest_resource="res://resources/quests/demo/4_collect_tools.tres"]
[end_timeline] [end_timeline]
+6 -1
View File
@@ -1,4 +1,9 @@
Fuck you
if {ACTIVEQUEST} == "1_talk_yeli_1": if {ACTIVEQUEST} == "1_talk_yeli_1":
jump quest1_ducks_start/ jump quest1_ducks_start/
elif {ACTIVEQUEST} == "3_talk_yeli_2":
jump quest2_tomatoes_start/
elif {ACTIVEQUEST} == "5_talk_yeli_3":
jump quest2_tomatoes_interim/
else: else:
No Dialog for active quest {ACTIVEQUEST} No Dialog for active quest "{ACTIVEQUEST}"
+3
View File
@@ -111,6 +111,9 @@ directories/tres_directory={
"1_talk_yeli_1": "res://resources/quests/demo/1_talk_yeli_1.tres", "1_talk_yeli_1": "res://resources/quests/demo/1_talk_yeli_1.tres",
"2_collect_ducks": "res://resources/quests/demo/2_collect_ducks.tres", "2_collect_ducks": "res://resources/quests/demo/2_collect_ducks.tres",
"3_talk_yeli_2": "res://resources/quests/demo/3_talk_yeli_2.tres", "3_talk_yeli_2": "res://resources/quests/demo/3_talk_yeli_2.tres",
"4_collect_tools": "res://resources/quests/demo/4_collect_tools.tres",
"5_talk_yeli_3": "res://resources/quests/demo/5_talk_yeli_3.tres",
"6_till_and_water": "res://resources/quests/demo/6_till_and_water.tres",
"Babushka_NPC_Namebox_background": "res://dialog/Babushka_NPC_Namebox_background.tres", "Babushka_NPC_Namebox_background": "res://dialog/Babushka_NPC_Namebox_background.tres",
"InputFieldsStyle": "res://addons/dialogic/Editor/Events/styles/InputFieldsStyle.tres", "InputFieldsStyle": "res://addons/dialogic/Editor/Events/styles/InputFieldsStyle.tres",
"MainTheme": "res://addons/dialogic/Editor/Theme/MainTheme.tres", "MainTheme": "res://addons/dialogic/Editor/Theme/MainTheme.tres",
+1 -1
View File
@@ -4,7 +4,7 @@
[resource] [resource]
script = ExtResource("1_70pjl") script = ExtResource("1_70pjl")
id = "3_talk_yeil_2" id = "3_talk_yeli_2"
title = "Talk to Yeli again" title = "Talk to Yeli again"
description = "All ducks are collected. Head back to yeli." description = "All ducks are collected. Head back to yeli."
metadata/_custom_type_script = "uid://vji5lp4qc8pp" metadata/_custom_type_script = "uid://vji5lp4qc8pp"
@@ -0,0 +1,10 @@
[gd_resource type="Resource" script_class="QuestResource" load_steps=2 format=3 uid="uid://d2swjixbnqkbw"]
[ext_resource type="Script" uid="uid://vji5lp4qc8pp" path="res://scripts/CSharp/Common/Quest/QuestResource.cs" id="1_e51xd"]
[resource]
script = ExtResource("1_e51xd")
id = "4_collect_tools"
title = "Collect the farm tools"
description = "Collect the Watering Can next to the well and the Hoe by the fence."
metadata/_custom_type_script = "uid://vji5lp4qc8pp"
+10
View File
@@ -0,0 +1,10 @@
[gd_resource type="Resource" script_class="QuestResource" load_steps=2 format=3 uid="uid://5t8g0firdif0"]
[ext_resource type="Script" uid="uid://vji5lp4qc8pp" path="res://scripts/CSharp/Common/Quest/QuestResource.cs" id="1_x7fvu"]
[resource]
script = ExtResource("1_x7fvu")
id = "5_talk_yeli_3"
title = "Talk to Yeli again"
description = "After the long and agonizing task of finding and collecting two tools, go talk to Yeli once again."
metadata/_custom_type_script = "uid://vji5lp4qc8pp"
@@ -0,0 +1,10 @@
[gd_resource type="Resource" script_class="QuestResource" load_steps=2 format=3 uid="uid://h05jgxqtq37m"]
[ext_resource type="Script" uid="uid://vji5lp4qc8pp" path="res://scripts/CSharp/Common/Quest/QuestResource.cs" id="1_745w5"]
[resource]
script = ExtResource("1_745w5")
id = "6_till_and_water"
title = "Till and water the fields"
description = "Use the hoe to break up the soil. Then plant the seeds and water the fields."
metadata/_custom_type_script = "uid://vji5lp4qc8pp"
+34 -4
View File
@@ -1,4 +1,4 @@
[gd_scene load_steps=107 format=3 uid="uid://gigb28qk8t12"] [gd_scene load_steps=113 format=3 uid="uid://gigb28qk8t12"]
[ext_resource type="PackedScene" uid="uid://c25udixd5m6l0" path="res://prefabs/characters/Player2D.tscn" id="1_7wfwe"] [ext_resource type="PackedScene" uid="uid://c25udixd5m6l0" path="res://prefabs/characters/Player2D.tscn" id="1_7wfwe"]
[ext_resource type="Texture2D" uid="uid://8sr11ex30n0m" path="res://art/mockups/Kenney_Backgrounds/Samples/uncolored_hills.png" id="2_7b2ri"] [ext_resource type="Texture2D" uid="uid://8sr11ex30n0m" path="res://art/mockups/Kenney_Backgrounds/Samples/uncolored_hills.png" id="2_7b2ri"]
@@ -67,6 +67,10 @@
[ext_resource type="PackedScene" uid="uid://muuxxgvx33fp" path="res://prefabs/farm/duck.tscn" id="62_i36hd"] [ext_resource type="PackedScene" uid="uid://muuxxgvx33fp" path="res://prefabs/farm/duck.tscn" id="62_i36hd"]
[ext_resource type="Script" uid="uid://cldtt4atgymm5" path="res://scripts/CSharp/Common/Quest/QuestTrigger.cs" id="66_2065p"] [ext_resource type="Script" uid="uid://cldtt4atgymm5" path="res://scripts/CSharp/Common/Quest/QuestTrigger.cs" id="66_2065p"]
[ext_resource type="Resource" uid="uid://cm8kftow8br00" path="res://resources/quests/demo/1_talk_yeli_1.tres" id="67_tm0yg"] [ext_resource type="Resource" uid="uid://cm8kftow8br00" path="res://resources/quests/demo/1_talk_yeli_1.tres" id="67_tm0yg"]
[ext_resource type="Script" uid="uid://c741nyedy26mx" path="res://scripts/CSharp/Common/QuestBehaviour/DetectInventoryContains.cs" id="68_hux6i"]
[ext_resource type="Resource" uid="uid://d2swjixbnqkbw" path="res://resources/quests/demo/4_collect_tools.tres" id="68_lbnqo"]
[ext_resource type="Script" uid="uid://be54lnb6gg81f" path="res://scripts/CSharp/Common/Inventory/ItemInstance.cs" id="69_4rgbr"]
[ext_resource type="Resource" uid="uid://5t8g0firdif0" path="res://resources/quests/demo/5_talk_yeli_3.tres" id="69_l4wxt"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_wtdui"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_wtdui"]
shader = ExtResource("13_7p0hq") shader = ExtResource("13_7p0hq")
@@ -260,6 +264,18 @@ stream_0/stream = ExtResource("39_di1ed")
stream_1/stream = ExtResource("40_ceriq") stream_1/stream = ExtResource("40_ceriq")
stream_2/stream = ExtResource("49_d77e7") stream_2/stream = ExtResource("49_d77e7")
[sub_resource type="Resource" id="Resource_y820s"]
script = ExtResource("69_4rgbr")
blueprint = ExtResource("28_ipqaa")
amount = 1
metadata/_custom_type_script = "uid://be54lnb6gg81f"
[sub_resource type="Resource" id="Resource_50loj"]
script = ExtResource("69_4rgbr")
blueprint = ExtResource("28_6b2nr")
amount = 1
metadata/_custom_type_script = "uid://be54lnb6gg81f"
[node name="BabushkaSceneFarmOutside2d" type="Node2D"] [node name="BabushkaSceneFarmOutside2d" type="Node2D"]
script = ExtResource("34_e5b7x") script = ExtResource("34_e5b7x")
_sceneNamesToLoad = PackedStringArray("res://scenes/Babushka_scene_indoor_common_room.tscn") _sceneNamesToLoad = PackedStringArray("res://scenes/Babushka_scene_indoor_common_room.tscn")
@@ -2300,14 +2316,22 @@ max_distance = 2e+07
playback_type = 2 playback_type = 2
script = ExtResource("40_w3jkj") script = ExtResource("40_w3jkj")
[node name="QuestInstantStart" type="Node" parent="."] [node name="SpeicialQuestTrigger" type="Node" parent="."]
[node name="QuestTrigger" type="Node" parent="QuestInstantStart"] [node name="QuestInstantStart" type="Node" parent="SpeicialQuestTrigger"]
[node name="QuestTrigger" type="Node" parent="SpeicialQuestTrigger/QuestInstantStart"]
script = ExtResource("66_2065p") script = ExtResource("66_2065p")
questResource = ExtResource("67_tm0yg") questResource = ExtResource("67_tm0yg")
toStatus = 1 toStatus = 1
makeCurrent = true makeCurrent = true
[node name="ToolsCollectedTrigger" type="Node" parent="SpeicialQuestTrigger"]
script = ExtResource("68_hux6i")
_itemsToContain = Array[Resource]([SubResource("Resource_y820s"), SubResource("Resource_50loj")])
_onActiveQuest = ExtResource("68_lbnqo")
_toNextQuest = ExtResource("69_l4wxt")
[connection signal="FilledWateringCan" from="YSorted/Vesna" to="Audio/SFX/FillWater SFX2" method="PlayOneShot"] [connection signal="FilledWateringCan" from="YSorted/Vesna" to="Audio/SFX/FillWater SFX2" method="PlayOneShot"]
[connection signal="WateringField" from="YSorted/Vesna/FarmingControls" to="Audio/SFX/Watering SFX" method="PlayOneShot"] [connection signal="WateringField" from="YSorted/Vesna/FarmingControls" to="Audio/SFX/Watering SFX" method="PlayOneShot"]
[connection signal="InteractedTool" from="YSorted/Brünnen/InteractionArea" to="YSorted/Vesna" method="TryFillWateringCan"] [connection signal="InteractedTool" from="YSorted/Brünnen/InteractionArea" to="YSorted/Vesna" method="TryFillWateringCan"]
@@ -2317,9 +2341,15 @@ makeCurrent = true
[connection signal="FieldCreated" from="YSorted/Farm visuals/FieldParent" to="Audio/SFX/Farming SFX" method="PlayOneShot"] [connection signal="FieldCreated" from="YSorted/Farm visuals/FieldParent" to="Audio/SFX/Farming SFX" method="PlayOneShot"]
[connection signal="input_event" from="YSorted/Farm visuals/FieldParent/Area2D" to="YSorted/Vesna/FarmingControls" method="InputEventPressedOn"] [connection signal="input_event" from="YSorted/Farm visuals/FieldParent/Area2D" to="YSorted/Vesna/FarmingControls" method="InputEventPressedOn"]
[connection signal="GoalReached" from="YSorted/ducks" to="YSorted/ducks/DialogicToggle" method="ToggleDialogue"] [connection signal="GoalReached" from="YSorted/ducks" to="YSorted/ducks/DialogicToggle" method="ToggleDialogue"]
[connection signal="DuckCollected" from="YSorted/ducks/Duck2" to="YSorted/ducks" method="Increment"]
[connection signal="DuckCollected" from="YSorted/ducks/Duck3" to="YSorted/ducks" method="Increment"]
[connection signal="DuckCollected" from="YSorted/ducks/Duck4" to="YSorted/ducks" method="Increment"]
[connection signal="DuckCollected" from="YSorted/ducks/Duck5" to="YSorted/ducks" method="Increment"]
[connection signal="DuckCollected" from="YSorted/ducks/Duck6" to="YSorted/ducks" method="Increment"]
[connection signal="DuckCollected" from="YSorted/ducks/Duck7" to="YSorted/ducks" method="Increment"]
[connection signal="Dialogue" from="YSorted/ducks/DialogicToggle" to="YSorted/ducks/dialogic starter" method="open"] [connection signal="Dialogue" from="YSorted/ducks/DialogicToggle" to="YSorted/ducks/dialogic starter" method="open"]
[connection signal="finished" from="Audio/Background Music Ramp up" to="Audio/Background Music loop" method="PlayFromOffset"] [connection signal="finished" from="Audio/Background Music Ramp up" to="Audio/Background Music loop" method="PlayFromOffset"]
[connection signal="ready" from="QuestInstantStart" to="QuestInstantStart/QuestTrigger" method="Trigger"] [connection signal="ready" from="SpeicialQuestTrigger/QuestInstantStart" to="SpeicialQuestTrigger/QuestInstantStart/QuestTrigger" method="Trigger"]
[editable path="YSorted/Vesna"] [editable path="YSorted/Vesna"]
[editable path="YSorted/Brünnen/InteractionArea"] [editable path="YSorted/Brünnen/InteractionArea"]
@@ -2,6 +2,7 @@
using System; using System;
using Godot; using Godot;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Babushka.scripts.CSharp.Common.Inventory; namespace Babushka.scripts.CSharp.Common.Inventory;
@@ -120,12 +121,29 @@ public partial class InventoryInstance : Node
{ {
if (destinationSlot < 0 || destinationSlot >= _slots.Count) if (destinationSlot < 0 || destinationSlot >= _slots.Count)
return InventoryActionResult.DestinationDoesNotExists; return InventoryActionResult.DestinationDoesNotExists;
if (!_slots[destinationSlot].IsEmpty()) if (!_slots[destinationSlot].IsEmpty())
return InventoryActionResult.DestinationFull; return InventoryActionResult.DestinationFull;
_slots[destinationSlot].itemInstance = itemInstance; _slots[destinationSlot].itemInstance = itemInstance;
EmitSignal(SignalName.InventoryContentsChanged); EmitSignal(SignalName.InventoryContentsChanged);
return InventoryActionResult.Success; return InventoryActionResult.Success;
} }
}
public int TotalItemsOfBlueprint(ItemResource blueprint)
{
return _slots
.Where(i => !i.IsEmpty() && i.itemInstance!.blueprint == blueprint)
.Sum(i => i.itemInstance!.amount);
}
public bool HasItems(ItemInstance item)
{
return TotalItemsOfBlueprint(item.blueprint) >= item.amount;
}
public bool HasItems(IEnumerable<ItemInstance> items)
{
return items.All(HasItems);
}
}
@@ -1,9 +1,13 @@
namespace Babushka.scripts.CSharp.Common.Inventory; using Godot;
namespace Babushka.scripts.CSharp.Common.Inventory;
public class ItemInstance // Do not instantiate this resource
// But it has to be a resource because Godot
[GlobalClass]
public partial class ItemInstance: Resource
{ {
public ItemResource blueprint; [Export] public ItemResource blueprint;
public int amount = 1; [Export] public int amount = 1;
public ItemInstance Clone() public ItemInstance Clone()
{ {
@@ -19,9 +19,6 @@ public partial class QuestManager : Node
[Signal] [Signal]
public delegate void DialogicActiveQuestEventHandler(string value); public delegate void DialogicActiveQuestEventHandler(string value);
[Export(PropertyHint.ArrayType)]
public QuestResource[] questsAccessibleFromDialogic;
public override void _EnterTree() public override void _EnterTree()
{ {
Instance = this; Instance = this;
@@ -81,12 +78,4 @@ public partial class QuestManager : Node
EmitSignalQuestsChanged(); EmitSignalQuestsChanged();
EmitSignalDialogicActiveQuest(_followQuest?.id ?? "none"); EmitSignalDialogicActiveQuest(_followQuest?.id ?? "none");
} }
// functions to call from Dialogic
public void DlSetQuestActiveAndFollow(string questId)
{
var resource = questsAccessibleFromDialogic.First(qr => qr.id == questId);
ChangeQuestStatus(resource, QuestStatus.Status.Active);
SetFollowQuest(resource);
}
} }
@@ -1,20 +1,22 @@
using Godot; using Godot;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using Babushka.scripts.CSharp.Common.Quest; using Babushka.scripts.CSharp.Common.Quest;
using Godot.Collections; using Godot.Collections;
public partial class QuestTestingScript : Node public partial class QuestTestingScript : Node
{ {
[Export(PropertyHint.ArrayType)] [Export(PropertyHint.ArrayType)]
private Array<QuestResource> _questsToActivate; private Array<QuestResource>? _questsToActivate;
public override void _EnterTree() public override void _EnterTree()
{ {
Debug.Assert(_questsToActivate != null);
foreach (var questResource in _questsToActivate) foreach (var questResource in _questsToActivate)
{ {
QuestManager.Instance.ChangeQuestStatus(questResource, QuestStatus.Status.Active); QuestManager.Instance!.ChangeQuestStatus(questResource, QuestStatus.Status.Active);
} }
} }
} }
@@ -0,0 +1,33 @@
using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
using Babushka.scripts.CSharp.Common.Inventory;
using Babushka.scripts.CSharp.Common.Quest;
public partial class DetectInventoryContains : QuestFulfillmentBase
{
[Export(PropertyHint.ArrayType)] private ItemInstance[] _itemsToContain;
public override void _Ready()
{
QuestManager.Instance!.QuestsChanged += Update;
InventoryManager.Instance.playerInventory.InventoryContentsChanged += Update;
Update();
}
public override void _ExitTree()
{
QuestManager.Instance!.QuestsChanged -= Update;
InventoryManager.Instance.playerInventory.InventoryContentsChanged -= Update;
}
private void Update()
{
if (IsQuestActive() && InventoryManager.Instance.playerInventory.HasItems(_itemsToContain))
{
Fulfill();
}
}
}
@@ -0,0 +1 @@
uid://c741nyedy26mx
@@ -0,0 +1,6 @@
using Godot;
using System;
public partial class DetectToolCollection : Node
{
}
@@ -0,0 +1 @@
uid://caohn76m3n3nm
@@ -0,0 +1,35 @@
using Godot;
using System;
using System.Linq;
using Babushka.scripts.CSharp.Common.Quest;
public abstract partial class QuestFulfillmentBase : Node
{
[Export] private QuestResource _onActiveQuest;
[Export] private QuestResource _toNextQuest;
[Export] private bool _whenFulfilledSetActiveQuestToDone = true;
[Export] private bool _whenFulfilledSetNextQuestToActive = true;
[Export] private bool _whenFulfilledSetNextQuestToFollow = true;
protected void Fulfill()
{
if (_whenFulfilledSetActiveQuestToDone)
{
QuestManager.Instance!.ChangeQuestStatus(_onActiveQuest, QuestStatus.Status.Done);
}
if (_whenFulfilledSetNextQuestToActive)
{
QuestManager.Instance!.ChangeQuestStatus(_toNextQuest, QuestStatus.Status.Active);
}
if (_whenFulfilledSetNextQuestToFollow)
{
QuestManager.Instance!.SetFollowQuest(_toNextQuest);
}
}
protected bool IsQuestActive()
{
return QuestManager.Instance!.GetActiveQuests().Any(q => q.Key == _onActiveQuest);
}
}
@@ -0,0 +1 @@
uid://dw158xraniqkd