commit e12acb0238738a06d7976c4525ffd62995ce1c76 Author: Gabriel Kaszewski Date: Sat Aug 23 00:38:46 2025 +0200 Add initial implementation of game mechanics and resources management diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0af181c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +/android/ diff --git a/ParasiticGod.csproj b/ParasiticGod.csproj new file mode 100644 index 0000000..9f33686 --- /dev/null +++ b/ParasiticGod.csproj @@ -0,0 +1,10 @@ + + + net8.0 + true + parasiticgod + + + + + \ No newline at end of file diff --git a/ParasiticGod.sln b/ParasiticGod.sln new file mode 100644 index 0000000..3600dba --- /dev/null +++ b/ParasiticGod.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParasiticGod", "ParasiticGod.csproj", "{0731AE2A-7020-4CF0-B094-E5A85E6F7CD7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + ExportDebug|Any CPU = ExportDebug|Any CPU + ExportRelease|Any CPU = ExportRelease|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0731AE2A-7020-4CF0-B094-E5A85E6F7CD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0731AE2A-7020-4CF0-B094-E5A85E6F7CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0731AE2A-7020-4CF0-B094-E5A85E6F7CD7}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {0731AE2A-7020-4CF0-B094-E5A85E6F7CD7}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {0731AE2A-7020-4CF0-B094-E5A85E6F7CD7}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {0731AE2A-7020-4CF0-B094-E5A85E6F7CD7}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + EndGlobalSection +EndGlobal diff --git a/Resources/Effects/Add_1000_Followers.tres b/Resources/Effects/Add_1000_Followers.tres new file mode 100644 index 0000000..b132a13 --- /dev/null +++ b/Resources/Effects/Add_1000_Followers.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="AddResourceEffect" load_steps=2 format=3 uid="uid://bs5iwc5lsdu0r"] + +[ext_resource type="Script" uid="uid://flyhl4i86han" path="res://Scripts/Core/Effects/AddResourceEffect.cs" id="1_2o4it"] + +[resource] +script = ExtResource("1_2o4it") +TargetResource = 1 +Value = 10000.0 +metadata/_custom_type_script = "uid://flyhl4i86han" diff --git a/Resources/Effects/Add_10_Followers.tres b/Resources/Effects/Add_10_Followers.tres new file mode 100644 index 0000000..059db1d --- /dev/null +++ b/Resources/Effects/Add_10_Followers.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="AddResourceEffect" load_steps=2 format=3 uid="uid://dxiaxhggfqcyb"] + +[ext_resource type="Script" uid="uid://flyhl4i86han" path="res://Scripts/Core/Effects/AddResourceEffect.cs" id="1_2xs1x"] + +[resource] +script = ExtResource("1_2xs1x") +TargetResource = 1 +Value = 100.0 +metadata/_custom_type_script = "uid://flyhl4i86han" diff --git a/Resources/Effects/Add_5_Corruption.tres b/Resources/Effects/Add_5_Corruption.tres new file mode 100644 index 0000000..39d0d47 --- /dev/null +++ b/Resources/Effects/Add_5_Corruption.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="AddResourceEffect" load_steps=2 format=3 uid="uid://dd17hc8jju5ek"] + +[ext_resource type="Script" uid="uid://flyhl4i86han" path="res://Scripts/Core/Effects/AddResourceEffect.cs" id="1_pce0a"] + +[resource] +script = ExtResource("1_pce0a") +TargetResource = 2 +Value = 5.0 +metadata/_custom_type_script = "uid://flyhl4i86han" diff --git a/Resources/Miracles/Fertility Blessing.tres b/Resources/Miracles/Fertility Blessing.tres new file mode 100644 index 0000000..d609c95 --- /dev/null +++ b/Resources/Miracles/Fertility Blessing.tres @@ -0,0 +1,13 @@ +[gd_resource type="Resource" script_class="MiracleDefinition" load_steps=4 format=3 uid="uid://df3cq0eb82x0i"] + +[ext_resource type="Resource" uid="uid://dd17hc8jju5ek" path="res://Resources/Effects/Add_5_Corruption.tres" id="1_jmmaa"] +[ext_resource type="Script" uid="uid://cfn3mx12xism5" path="res://Scripts/Core/MiracleDefinition.cs" id="1_oh2pa"] +[ext_resource type="Resource" uid="uid://dxiaxhggfqcyb" path="res://Resources/Effects/Add_10_Followers.tres" id="2_lg4lk"] + +[resource] +script = ExtResource("1_oh2pa") +Name = "Fertility Blessing" +FaithCost = 100.0 +FollowersRequired = 0 +Effects = Array[Resource]([ExtResource("2_lg4lk"), ExtResource("1_jmmaa")]) +metadata/_custom_type_script = "uid://cfn3mx12xism5" diff --git a/Resources/Miracles/God power.tres b/Resources/Miracles/God power.tres new file mode 100644 index 0000000..8a4f919 --- /dev/null +++ b/Resources/Miracles/God power.tres @@ -0,0 +1,12 @@ +[gd_resource type="Resource" script_class="MiracleDefinition" load_steps=3 format=3 uid="uid://ckdc32ptfjhx6"] + +[ext_resource type="Resource" uid="uid://bs5iwc5lsdu0r" path="res://Resources/Effects/Add_1000_Followers.tres" id="1_bkpio"] +[ext_resource type="Script" uid="uid://cfn3mx12xism5" path="res://Scripts/Core/MiracleDefinition.cs" id="3_oqu5j"] + +[resource] +script = ExtResource("3_oqu5j") +Name = "GOD POWER" +FaithCost = 1.0 +FollowersRequired = 0 +Effects = Array[Resource]([ExtResource("1_bkpio")]) +metadata/_custom_type_script = "uid://cfn3mx12xism5" diff --git a/Resources/Tiers/Followers/follower_tier_1.tres b/Resources/Tiers/Followers/follower_tier_1.tres new file mode 100644 index 0000000..c3f7636 --- /dev/null +++ b/Resources/Tiers/Followers/follower_tier_1.tres @@ -0,0 +1,8 @@ +[gd_resource type="Resource" script_class="TierDefinition" load_steps=2 format=3 uid="uid://8ooxfo2wdbhu"] + +[ext_resource type="Script" uid="uid://c7hh0cy0yrdt8" path="res://Scripts/Core/TierDefinition.cs" id="1_wydwg"] + +[resource] +script = ExtResource("1_wydwg") +Threshold = 0 +metadata/_custom_type_script = "uid://c7hh0cy0yrdt8" diff --git a/Resources/Tiers/Followers/follower_tier_2.tres b/Resources/Tiers/Followers/follower_tier_2.tres new file mode 100644 index 0000000..774076c --- /dev/null +++ b/Resources/Tiers/Followers/follower_tier_2.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="TierDefinition" load_steps=3 format=3 uid="uid://cejeb3467iiyl"] + +[ext_resource type="PackedScene" uid="uid://c2d3ageprpd0o" path="res://Scenes/Followers/followers_tier_1.tscn" id="1_qgnom"] +[ext_resource type="Script" uid="uid://c7hh0cy0yrdt8" path="res://Scripts/Core/TierDefinition.cs" id="2_3uaiv"] + +[resource] +script = ExtResource("2_3uaiv") +Scene = ExtResource("1_qgnom") +Threshold = 0 +metadata/_custom_type_script = "uid://c7hh0cy0yrdt8" diff --git a/Resources/Tiers/Followers/follower_tier_3.tres b/Resources/Tiers/Followers/follower_tier_3.tres new file mode 100644 index 0000000..8fd872e --- /dev/null +++ b/Resources/Tiers/Followers/follower_tier_3.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="TierDefinition" load_steps=3 format=3 uid="uid://q0rha23lx4wl"] + +[ext_resource type="PackedScene" uid="uid://8jnnbe76xjhl" path="res://Scenes/Followers/followers_tier_2.tscn" id="1_a7myf"] +[ext_resource type="Script" uid="uid://c7hh0cy0yrdt8" path="res://Scripts/Core/TierDefinition.cs" id="2_5dexb"] + +[resource] +script = ExtResource("2_5dexb") +Scene = ExtResource("1_a7myf") +Threshold = 50 +metadata/_custom_type_script = "uid://c7hh0cy0yrdt8" diff --git a/Resources/Tiers/Followers/follower_tier_4.tres b/Resources/Tiers/Followers/follower_tier_4.tres new file mode 100644 index 0000000..a374449 --- /dev/null +++ b/Resources/Tiers/Followers/follower_tier_4.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="TierDefinition" load_steps=3 format=3 uid="uid://i1oo0q84q8ps"] + +[ext_resource type="PackedScene" uid="uid://gqqycnreclv2" path="res://Scenes/Followers/followers_tier_3.tscn" id="1_6rce8"] +[ext_resource type="Script" uid="uid://c7hh0cy0yrdt8" path="res://Scripts/Core/TierDefinition.cs" id="2_slqj0"] + +[resource] +script = ExtResource("2_slqj0") +Scene = ExtResource("1_6rce8") +Threshold = 300 +metadata/_custom_type_script = "uid://c7hh0cy0yrdt8" diff --git a/Resources/Tiers/Followers/follower_tier_5.tres b/Resources/Tiers/Followers/follower_tier_5.tres new file mode 100644 index 0000000..8b11b40 --- /dev/null +++ b/Resources/Tiers/Followers/follower_tier_5.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="TierDefinition" load_steps=3 format=3 uid="uid://bwu8k7cyjhf8c"] + +[ext_resource type="PackedScene" uid="uid://iairc1nudt6c" path="res://Scenes/Followers/followers_tier_5.tscn" id="1_h1dq7"] +[ext_resource type="Script" uid="uid://c7hh0cy0yrdt8" path="res://Scripts/Core/TierDefinition.cs" id="2_w5iq4"] + +[resource] +script = ExtResource("2_w5iq4") +Scene = ExtResource("1_h1dq7") +Threshold = 30000 +metadata/_custom_type_script = "uid://c7hh0cy0yrdt8" diff --git a/Resources/Tiers/Huts/hut_tier_1.tres b/Resources/Tiers/Huts/hut_tier_1.tres new file mode 100644 index 0000000..59c042b --- /dev/null +++ b/Resources/Tiers/Huts/hut_tier_1.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="TierDefinition" load_steps=3 format=3 uid="uid://bbkbssvptkyvh"] + +[ext_resource type="Script" uid="uid://c7hh0cy0yrdt8" path="res://Scripts/Core/TierDefinition.cs" id="1_ei6wr"] +[ext_resource type="PackedScene" uid="uid://dbg6c4m1v1rsh" path="res://Scenes/Huts/hut_tier_1.tscn" id="1_uho8r"] + +[resource] +script = ExtResource("1_ei6wr") +Scene = ExtResource("1_uho8r") +Threshold = 40000 +metadata/_custom_type_script = "uid://c7hh0cy0yrdt8" diff --git a/Resources/Tiers/Huts/hut_tier_2.tres b/Resources/Tiers/Huts/hut_tier_2.tres new file mode 100644 index 0000000..faadb81 --- /dev/null +++ b/Resources/Tiers/Huts/hut_tier_2.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="TierDefinition" load_steps=3 format=3 uid="uid://co2sdpwpajjqi"] + +[ext_resource type="PackedScene" uid="uid://cd4hc5b87uyqm" path="res://Scenes/Huts/hut_tier_2.tscn" id="1_trlm4"] +[ext_resource type="Script" uid="uid://c7hh0cy0yrdt8" path="res://Scripts/Core/TierDefinition.cs" id="2_vr1nw"] + +[resource] +script = ExtResource("2_vr1nw") +Scene = ExtResource("1_trlm4") +Threshold = 600000 +metadata/_custom_type_script = "uid://c7hh0cy0yrdt8" diff --git a/Resources/Tiers/Huts/hut_tier_3.tres b/Resources/Tiers/Huts/hut_tier_3.tres new file mode 100644 index 0000000..3534c61 --- /dev/null +++ b/Resources/Tiers/Huts/hut_tier_3.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="TierDefinition" load_steps=3 format=3 uid="uid://b8k30qsd434dp"] + +[ext_resource type="PackedScene" uid="uid://dh6g38sit4hna" path="res://Scenes/Huts/hut_tier_3.tscn" id="1_ex2nw"] +[ext_resource type="Script" uid="uid://c7hh0cy0yrdt8" path="res://Scripts/Core/TierDefinition.cs" id="2_74x2g"] + +[resource] +script = ExtResource("2_74x2g") +Scene = ExtResource("1_ex2nw") +Threshold = 1200000 +metadata/_custom_type_script = "uid://c7hh0cy0yrdt8" diff --git a/Scenes/Followers/FollowerMarker.tscn b/Scenes/Followers/FollowerMarker.tscn new file mode 100644 index 0000000..0555681 --- /dev/null +++ b/Scenes/Followers/FollowerMarker.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=3 format=3 uid="uid://cqkye7yykakns"] + +[ext_resource type="Script" uid="uid://djaf0gv8s7qib" path="res://Scripts/FollowerMarker.cs" id="1_e1v1v"] +[ext_resource type="Texture2D" uid="uid://dcs48aa84w21u" path="res://icon.svg" id="2_woadh"] + +[node name="FollowerMarker" type="Marker2D"] +script = ExtResource("1_e1v1v") +metadata/_custom_type_script = "uid://djaf0gv8s7qib" + +[node name="Sprite2D" type="Sprite2D" parent="."] +visible = false +scale = Vector2(0.235, 0.235) +texture = ExtResource("2_woadh") diff --git a/Scenes/Followers/followers_tier_1.tscn b/Scenes/Followers/followers_tier_1.tscn new file mode 100644 index 0000000..49c9181 --- /dev/null +++ b/Scenes/Followers/followers_tier_1.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=3 format=3 uid="uid://c2d3ageprpd0o"] + +[ext_resource type="Script" uid="uid://cj5libcgnhjml" path="res://Scripts/Follower.cs" id="1_ifsko"] +[ext_resource type="Texture2D" uid="uid://dhrbjqmhqdpef" path="res://Sprites/Follower.png" id="1_miahy"] + +[node name="FollowersTier1" type="Node2D"] +script = ExtResource("1_ifsko") +metadata/_custom_type_script = "uid://cj5libcgnhjml" + +[node name="Follower" type="Sprite2D" parent="."] +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_miahy") diff --git a/Scenes/Followers/followers_tier_2.tscn b/Scenes/Followers/followers_tier_2.tscn new file mode 100644 index 0000000..46b12db --- /dev/null +++ b/Scenes/Followers/followers_tier_2.tscn @@ -0,0 +1,29 @@ +[gd_scene load_steps=3 format=3 uid="uid://8jnnbe76xjhl"] + +[ext_resource type="Script" uid="uid://cj5libcgnhjml" path="res://Scripts/Follower.cs" id="1_1fjl1"] +[ext_resource type="Texture2D" uid="uid://dhrbjqmhqdpef" path="res://Sprites/Follower.png" id="1_dwkko"] + +[node name="FollowersTier2" type="Node2D"] +script = ExtResource("1_1fjl1") +Tier = 1 +metadata/_custom_type_script = "uid://cj5libcgnhjml" + +[node name="Follower" type="Sprite2D" parent="."] +position = Vector2(-4.39999, -4) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_dwkko") + +[node name="Follower2" type="Sprite2D" parent="."] +position = Vector2(-0.399994, -4) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_dwkko") + +[node name="Follower3" type="Sprite2D" parent="."] +position = Vector2(4.60001, -4) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_dwkko") + +[node name="Follower4" type="Sprite2D" parent="."] +position = Vector2(7.60001, -4) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_dwkko") diff --git a/Scenes/Followers/followers_tier_3.tscn b/Scenes/Followers/followers_tier_3.tscn new file mode 100644 index 0000000..7a3baf2 --- /dev/null +++ b/Scenes/Followers/followers_tier_3.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=3 format=3 uid="uid://gqqycnreclv2"] + +[ext_resource type="Script" uid="uid://cj5libcgnhjml" path="res://Scripts/Follower.cs" id="1_dfylr"] +[ext_resource type="Texture2D" uid="uid://dhrbjqmhqdpef" path="res://Sprites/Follower.png" id="1_ep0q4"] + +[node name="FollowersTier3" type="Node2D"] +script = ExtResource("1_dfylr") +Tier = 2 +metadata/_custom_type_script = "uid://cj5libcgnhjml" + +[node name="Follower" type="Sprite2D" parent="."] +position = Vector2(-11.4, -12) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ep0q4") + +[node name="Follower2" type="Sprite2D" parent="."] +position = Vector2(-7.39999, -12) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ep0q4") + +[node name="Follower3" type="Sprite2D" parent="."] +position = Vector2(-2.39999, -12) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ep0q4") + +[node name="Follower4" type="Sprite2D" parent="."] +position = Vector2(0.600006, -12) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ep0q4") + +[node name="Follower5" type="Sprite2D" parent="."] +position = Vector2(2.60001, -9.53674e-07) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ep0q4") + +[node name="Follower6" type="Sprite2D" parent="."] +position = Vector2(6.60001, -9.53674e-07) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ep0q4") + +[node name="Follower7" type="Sprite2D" parent="."] +position = Vector2(11.6, -9.53674e-07) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ep0q4") + +[node name="Follower8" type="Sprite2D" parent="."] +position = Vector2(14.6, -9.53674e-07) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ep0q4") diff --git a/Scenes/Followers/followers_tier_4.tscn b/Scenes/Followers/followers_tier_4.tscn new file mode 100644 index 0000000..d79f530 --- /dev/null +++ b/Scenes/Followers/followers_tier_4.tscn @@ -0,0 +1,68 @@ +[gd_scene load_steps=3 format=3 uid="uid://c04rof865kdfb"] + +[ext_resource type="Script" uid="uid://cj5libcgnhjml" path="res://Scripts/Follower.cs" id="1_0bt7d"] +[ext_resource type="Texture2D" uid="uid://dhrbjqmhqdpef" path="res://Sprites/Follower.png" id="1_ttwdp"] + +[node name="FollowersTier4" type="Node2D"] +script = ExtResource("1_0bt7d") +metadata/_custom_type_script = "uid://cj5libcgnhjml" + +[node name="Follower" type="Sprite2D" parent="."] +position = Vector2(-5.39999, -17) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower2" type="Sprite2D" parent="."] +position = Vector2(-1.39999, -17) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower3" type="Sprite2D" parent="."] +position = Vector2(3.60001, -17) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower4" type="Sprite2D" parent="."] +position = Vector2(6.60001, -17) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower5" type="Sprite2D" parent="."] +position = Vector2(8.60001, -5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower6" type="Sprite2D" parent="."] +position = Vector2(12.6, -5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower7" type="Sprite2D" parent="."] +position = Vector2(17.6, -5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower8" type="Sprite2D" parent="."] +position = Vector2(20.6, -5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower9" type="Sprite2D" parent="."] +position = Vector2(-18.4, -5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower10" type="Sprite2D" parent="."] +position = Vector2(-14.4, -5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower11" type="Sprite2D" parent="."] +position = Vector2(-9.39999, -5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") + +[node name="Follower12" type="Sprite2D" parent="."] +position = Vector2(-6.39999, -5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_ttwdp") diff --git a/Scenes/Followers/followers_tier_5.tscn b/Scenes/Followers/followers_tier_5.tscn new file mode 100644 index 0000000..cb60f26 --- /dev/null +++ b/Scenes/Followers/followers_tier_5.tscn @@ -0,0 +1,88 @@ +[gd_scene load_steps=3 format=3 uid="uid://iairc1nudt6c"] + +[ext_resource type="Script" uid="uid://cj5libcgnhjml" path="res://Scripts/Follower.cs" id="1_4yvkn"] +[ext_resource type="Texture2D" uid="uid://dhrbjqmhqdpef" path="res://Sprites/Follower.png" id="1_28luu"] + +[node name="FollowersTier5" type="Node2D"] +script = ExtResource("1_4yvkn") +metadata/_custom_type_script = "uid://cj5libcgnhjml" + +[node name="Follower" type="Sprite2D" parent="."] +position = Vector2(-7.39999, -15) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower2" type="Sprite2D" parent="."] +position = Vector2(-3.39999, -15) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower3" type="Sprite2D" parent="."] +position = Vector2(1.60001, -15) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower4" type="Sprite2D" parent="."] +position = Vector2(4.60001, -15) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower5" type="Sprite2D" parent="."] +position = Vector2(6.60001, -3) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower6" type="Sprite2D" parent="."] +position = Vector2(10.6, -3) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower7" type="Sprite2D" parent="."] +position = Vector2(15.6, -3) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower8" type="Sprite2D" parent="."] +position = Vector2(18.6, -3) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower9" type="Sprite2D" parent="."] +position = Vector2(-20.4, -3) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower10" type="Sprite2D" parent="."] +position = Vector2(-16.4, -3) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower11" type="Sprite2D" parent="."] +position = Vector2(-11.4, -3) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower12" type="Sprite2D" parent="."] +position = Vector2(-8.39999, -3) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower13" type="Sprite2D" parent="."] +position = Vector2(-7.39999, 5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower14" type="Sprite2D" parent="."] +position = Vector2(-3.39999, 5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower15" type="Sprite2D" parent="."] +position = Vector2(1.60001, 5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") + +[node name="Follower16" type="Sprite2D" parent="."] +position = Vector2(4.60001, 5) +scale = Vector2(0.2, 0.2) +texture = ExtResource("1_28luu") diff --git a/Scenes/Huts/HutMarker.tscn b/Scenes/Huts/HutMarker.tscn new file mode 100644 index 0000000..a2a5a45 --- /dev/null +++ b/Scenes/Huts/HutMarker.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=3 format=3 uid="uid://be5d0d3aweg0l"] + +[ext_resource type="Script" uid="uid://djaf0gv8s7qib" path="res://Scripts/FollowerMarker.cs" id="1_yfid6"] +[ext_resource type="Texture2D" uid="uid://dcs48aa84w21u" path="res://icon.svg" id="2_om77d"] + +[node name="HutMarker" type="Marker2D"] +script = ExtResource("1_yfid6") +metadata/_custom_type_script = "uid://djaf0gv8s7qib" + +[node name="Sprite2D" type="Sprite2D" parent="."] +visible = false +modulate = Color(0.605674, 1.66051e-06, 3.85046e-07, 1) +scale = Vector2(0.235, 0.235) +texture = ExtResource("2_om77d") diff --git a/Scenes/Huts/hut_tier_1.tscn b/Scenes/Huts/hut_tier_1.tscn new file mode 100644 index 0000000..3af5494 --- /dev/null +++ b/Scenes/Huts/hut_tier_1.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=3 format=3 uid="uid://dbg6c4m1v1rsh"] + +[ext_resource type="Script" uid="uid://cj5libcgnhjml" path="res://Scripts/Follower.cs" id="1_ymswo"] +[ext_resource type="Texture2D" uid="uid://clnujxe12l86u" path="res://Sprites/Hut.png" id="2_1pksg"] + +[node name="HutTier1" type="Node2D"] +script = ExtResource("1_ymswo") +metadata/_custom_type_script = "uid://cj5libcgnhjml" + +[node name="Hut" type="Sprite2D" parent="."] +scale = Vector2(0.2, 0.2) +texture = ExtResource("2_1pksg") diff --git a/Scenes/Huts/hut_tier_2.tscn b/Scenes/Huts/hut_tier_2.tscn new file mode 100644 index 0000000..05af487 --- /dev/null +++ b/Scenes/Huts/hut_tier_2.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=3 format=3 uid="uid://cd4hc5b87uyqm"] + +[ext_resource type="Script" uid="uid://cj5libcgnhjml" path="res://Scripts/Follower.cs" id="1_22ax8"] +[ext_resource type="Texture2D" uid="uid://clnujxe12l86u" path="res://Sprites/Hut.png" id="2_xvtw0"] + +[node name="HutTier2" type="Node2D"] +script = ExtResource("1_22ax8") +metadata/_custom_type_script = "uid://cj5libcgnhjml" + +[node name="Hut" type="Sprite2D" parent="."] +scale = Vector2(0.2, 0.2) +texture = ExtResource("2_xvtw0") + +[node name="Hut2" type="Sprite2D" parent="."] +position = Vector2(27, 0) +scale = Vector2(0.2, 0.2) +texture = ExtResource("2_xvtw0") diff --git a/Scenes/Huts/hut_tier_3.tscn b/Scenes/Huts/hut_tier_3.tscn new file mode 100644 index 0000000..7ef5509 --- /dev/null +++ b/Scenes/Huts/hut_tier_3.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=3 format=3 uid="uid://dh6g38sit4hna"] + +[ext_resource type="Script" uid="uid://cj5libcgnhjml" path="res://Scripts/Follower.cs" id="1_ltla2"] +[ext_resource type="Texture2D" uid="uid://clnujxe12l86u" path="res://Sprites/Hut.png" id="2_un0i8"] + +[node name="HutTier3" type="Node2D"] +script = ExtResource("1_ltla2") +metadata/_custom_type_script = "uid://cj5libcgnhjml" + +[node name="Hut" type="Sprite2D" parent="."] +scale = Vector2(0.2, 0.2) +texture = ExtResource("2_un0i8") + +[node name="Hut2" type="Sprite2D" parent="."] +position = Vector2(27, 0) +scale = Vector2(0.2, 0.2) +texture = ExtResource("2_un0i8") + +[node name="Hut3" type="Sprite2D" parent="."] +position = Vector2(-46, 0) +scale = Vector2(0.2, 0.2) +texture = ExtResource("2_un0i8") diff --git a/Scenes/Main/Main.cs b/Scenes/Main/Main.cs new file mode 100644 index 0000000..7a02ec5 --- /dev/null +++ b/Scenes/Main/Main.cs @@ -0,0 +1,44 @@ +using Godot; +using ParasiticGod.Scripts.Core; +using ParasiticGod.Scripts.Singletons; + +namespace ParasiticGod.Scenes.Main; + +public partial class Main : Node +{ + [Export] private Label _faithLabel; + [Export] private Label _followersLabel; + [Export] private Label _corruptionLabel; + [Export] private MiraclePanel _miraclePanel; + [Export] private Sprite2D _worldSprite; + [Export] private Color _deadWorldColor = new Color("#581845"); + + public override void _Ready() + { + GameBus.Instance.StateChanged += OnStateChanged; + + _miraclePanel.PopulateInitialButtons(GameBus.Instance.AllMiracles); + } + + public override void _ExitTree() + { + GameBus.Instance.StateChanged -= OnStateChanged; + } + + private void OnStateChanged(GameState newState) + { + _faithLabel.Text = $"Faith: {newState.Faith:F0} (+{newState.FaithPerSecond:F1}/s)"; + _followersLabel.Text = $"Followers: {newState.Followers}"; + _corruptionLabel.Text = $"Corruption: {newState.Corruption:F0}%"; + + UpdateWorldVisuals(newState.Corruption); + } + + private void UpdateWorldVisuals(double corruption) + { + if (_worldSprite.Material is not ShaderMaterial shaderMaterial) return; + + var ratio = (float)corruption / 100.0f; + shaderMaterial.SetShaderParameter("corruption_level", ratio); + } +} \ No newline at end of file diff --git a/Scenes/Main/Main.cs.uid b/Scenes/Main/Main.cs.uid new file mode 100644 index 0000000..33a69e1 --- /dev/null +++ b/Scenes/Main/Main.cs.uid @@ -0,0 +1 @@ +uid://t71ewkpa5uqs diff --git a/Scenes/Main/Main.tscn b/Scenes/Main/Main.tscn new file mode 100644 index 0000000..67f8355 --- /dev/null +++ b/Scenes/Main/Main.tscn @@ -0,0 +1,229 @@ +[gd_scene load_steps=18 format=3 uid="uid://bfil8sd154327"] + +[ext_resource type="Script" uid="uid://t71ewkpa5uqs" path="res://Scenes/Main/Main.cs" id="1_p8rbg"] +[ext_resource type="Script" uid="uid://b77vh831r1e3c" path="res://Scenes/Main/MiraclePanel.cs" id="2_hcu3t"] +[ext_resource type="PackedScene" uid="uid://rj1fsdlhju5y" path="res://Scenes/Main/miracle_button.tscn" id="3_qdkat"] +[ext_resource type="Texture2D" uid="uid://dg6ac3jb1366r" path="res://Sprites/globe.svg" id="4_i3fi7"] +[ext_resource type="PackedScene" uid="uid://be5d0d3aweg0l" path="res://Scenes/Huts/HutMarker.tscn" id="6_cv8e0"] +[ext_resource type="Script" uid="uid://dj2wyrq07gfp2" path="res://Scripts/PopulationVisualizer.cs" id="8_cv8e0"] +[ext_resource type="Resource" uid="uid://8ooxfo2wdbhu" path="res://Resources/Tiers/Followers/follower_tier_1.tres" id="9_hkvnm"] +[ext_resource type="Shader" uid="uid://bf8nk145fjkgh" path="res://Shaders/corruption_shader.gdshader" id="9_wgovn"] +[ext_resource type="Resource" uid="uid://cejeb3467iiyl" path="res://Resources/Tiers/Followers/follower_tier_2.tres" id="10_5ci8a"] +[ext_resource type="PackedScene" uid="uid://cqkye7yykakns" path="res://Scenes/Followers/FollowerMarker.tscn" id="11_5ci8a"] +[ext_resource type="Resource" uid="uid://q0rha23lx4wl" path="res://Resources/Tiers/Followers/follower_tier_3.tres" id="11_18xdc"] +[ext_resource type="Resource" uid="uid://i1oo0q84q8ps" path="res://Resources/Tiers/Followers/follower_tier_4.tres" id="12_epx8f"] +[ext_resource type="Resource" uid="uid://bwu8k7cyjhf8c" path="res://Resources/Tiers/Followers/follower_tier_5.tres" id="13_hcu3t"] +[ext_resource type="Resource" uid="uid://bbkbssvptkyvh" path="res://Resources/Tiers/Huts/hut_tier_1.tres" id="14_18xdc"] +[ext_resource type="Resource" uid="uid://co2sdpwpajjqi" path="res://Resources/Tiers/Huts/hut_tier_2.tres" id="15_epx8f"] +[ext_resource type="Resource" uid="uid://b8k30qsd434dp" path="res://Resources/Tiers/Huts/hut_tier_3.tres" id="16_hcu3t"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_cv8e0"] +shader = ExtResource("9_wgovn") +shader_parameter/terrain_color = Color(0.152941, 0.682353, 0.376471, 1) +shader_parameter/corrupted_color = Color(0.3, 0.1, 0.2, 1) +shader_parameter/corruption_level = 0.0 +shader_parameter/tolerance = 0.1 + +[node name="World" type="Node2D" node_paths=PackedStringArray("_faithLabel", "_followersLabel", "_corruptionLabel", "_miraclePanel", "_worldSprite")] +script = ExtResource("1_p8rbg") +_faithLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/FaithLabel") +_followersLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/FollowersLabel") +_corruptionLabel = NodePath("UiLayer/Control/MarginContainer/Main/Top/CorruptionLabel") +_miraclePanel = NodePath("UiLayer/Control/MarginContainer/Main/Bottom") +_worldSprite = NodePath("World Sprite") + +[node name="UiLayer" type="CanvasLayer" parent="."] + +[node name="Control" type="Control" parent="UiLayer"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="MarginContainer" type="MarginContainer" parent="UiLayer/Control"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 8 +theme_override_constants/margin_top = 8 +theme_override_constants/margin_right = 8 +theme_override_constants/margin_bottom = 8 + +[node name="Main" type="VBoxContainer" parent="UiLayer/Control/MarginContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 0 + +[node name="Top" type="HBoxContainer" parent="UiLayer/Control/MarginContainer/Main"] +layout_mode = 2 + +[node name="FaithLabel" type="Label" parent="UiLayer/Control/MarginContainer/Main/Top"] +layout_mode = 2 +text = "Faith Label" + +[node name="FollowersLabel" type="Label" parent="UiLayer/Control/MarginContainer/Main/Top"] +layout_mode = 2 +text = "FollowersLabel" + +[node name="CorruptionLabel" type="Label" parent="UiLayer/Control/MarginContainer/Main/Top"] +layout_mode = 2 +text = "CorruptionLabel" + +[node name="Bottom" type="GridContainer" parent="UiLayer/Control/MarginContainer/Main"] +layout_mode = 2 +size_flags_vertical = 6 +columns = 3 +script = ExtResource("2_hcu3t") +_miracleButtonScene = ExtResource("3_qdkat") + +[node name="Camera2D" type="Camera2D" parent="."] + +[node name="World Sprite" type="Sprite2D" parent="."] +material = SubResource("ShaderMaterial_cv8e0") +position = Vector2(-34, -25) +scale = Vector2(2.41247, 2.41247) +texture = ExtResource("4_i3fi7") +metadata/_edit_lock_ = true + +[node name="Hut Markers" type="Node2D" parent="."] + +[node name="HutMarker" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(-1, -29) + +[node name="HutMarker2" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(124, -45) + +[node name="HutMarker3" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(301, -41) + +[node name="HutMarker4" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(392, -192) + +[node name="HutMarker5" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(267, -207) + +[node name="HutMarker6" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(418, -292) + +[node name="HutMarker7" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(491, -413) + +[node name="HutMarker8" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(613, -173) + +[node name="HutMarker9" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(465, -76) + +[node name="HutMarker10" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(352, 168) + +[node name="HutMarker11" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(382, 347) + +[node name="HutMarker12" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(88, 365) + +[node name="HutMarker13" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(-111, 431) + +[node name="HutMarker14" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(175, 513) + +[node name="HutMarker15" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(-228, 311) + +[node name="HutMarker16" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(-439, 282) + +[node name="HutMarker17" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(-334, 162) + +[node name="HutMarker18" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(-341, 428) + +[node name="HutMarker19" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(-148, 567) + +[node name="HutMarker20" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(65, 472) + +[node name="HutMarker21" parent="Hut Markers" instance=ExtResource("6_cv8e0")] +position = Vector2(-209, 28) + +[node name="Followers Markers" type="Node2D" parent="."] + +[node name="FollowerMarker" parent="Followers Markers" instance=ExtResource("11_5ci8a")] + +[node name="FollowerMarker2" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(97, 1) + +[node name="FollowerMarker3" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(222, -34) + +[node name="FollowerMarker4" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(317, -127) + +[node name="FollowerMarker5" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(508, -175) + +[node name="FollowerMarker6" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(568, -317) + +[node name="FollowerMarker7" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(636, -27) + +[node name="FollowerMarker8" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(575, 144) + +[node name="FollowerMarker9" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(365, 215) + +[node name="FollowerMarker10" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(134, 371) + +[node name="FollowerMarker11" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(21, 563) + +[node name="FollowerMarker12" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(-39, 469) + +[node name="FollowerMarker13" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(-257, 402) + +[node name="FollowerMarker14" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(-178, 229) + +[node name="FollowerMarker15" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(-304, 206) + +[node name="FollowerMarker16" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(-463, 349) + +[node name="FollowerMarker17" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(-240, 42) + +[node name="FollowerMarker18" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(-88, -32) + +[node name="FollowerMarker19" parent="Followers Markers" instance=ExtResource("11_5ci8a")] +position = Vector2(82, -234) + +[node name="FollowerPopulationVisualizer" type="Node" parent="." node_paths=PackedStringArray("_markersContainer")] +script = ExtResource("8_cv8e0") +_markersContainer = NodePath("../Followers Markers") +_tiers = Array[Object]([ExtResource("9_hkvnm"), ExtResource("10_5ci8a"), ExtResource("11_18xdc"), ExtResource("12_epx8f"), ExtResource("13_hcu3t")]) +metadata/_custom_type_script = "uid://dj2wyrq07gfp2" + +[node name="HutPopulationVisualizer" type="Node" parent="." node_paths=PackedStringArray("_markersContainer")] +script = ExtResource("8_cv8e0") +_markersContainer = NodePath("../Hut Markers") +_unitsPerMarker = 1 +_tiers = Array[Object]([ExtResource("14_18xdc"), ExtResource("15_epx8f"), ExtResource("16_hcu3t")]) +metadata/_custom_type_script = "uid://dj2wyrq07gfp2" diff --git a/Scenes/Main/MiracleButton.cs b/Scenes/Main/MiracleButton.cs new file mode 100644 index 0000000..a881377 --- /dev/null +++ b/Scenes/Main/MiracleButton.cs @@ -0,0 +1,42 @@ +using Godot; +using ParasiticGod.Scripts.Core; +using ParasiticGod.Scripts.Singletons; + +namespace ParasiticGod.Scenes.Main; + +public partial class MiracleButton : Button +{ + private MiracleDefinition _miracle; + + public override void _Ready() + { + if (_miracle == null) + { + GD.PrintErr($"MiracleButton '{Name}' has no MiracleDefinition assigned."); + SetProcess(false); + return; + } + + Text = $"{_miracle.Name}\nCost: {_miracle.FaithCost} Faith"; + + Pressed += OnPressed; + } + + public override void _ExitTree() + { + Pressed -= OnPressed; + } + + private void OnPressed() + { + GameBus.Instance.PerformMiracle(_miracle); + } + + public void SetMiracle(MiracleDefinition miracle) + { + _miracle = miracle; + Text = $"{_miracle.Name}\nCost: {_miracle.FaithCost} Faith"; + } + + public MiracleDefinition GetMiracle() { return _miracle; } +} \ No newline at end of file diff --git a/Scenes/Main/MiracleButton.cs.uid b/Scenes/Main/MiracleButton.cs.uid new file mode 100644 index 0000000..bfadcf5 --- /dev/null +++ b/Scenes/Main/MiracleButton.cs.uid @@ -0,0 +1 @@ +uid://ctjmwgucwh3le diff --git a/Scenes/Main/MiraclePanel.cs b/Scenes/Main/MiraclePanel.cs new file mode 100644 index 0000000..14b273e --- /dev/null +++ b/Scenes/Main/MiraclePanel.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using Godot; +using ParasiticGod.Scripts.Core; +using ParasiticGod.Scripts.Singletons; + +namespace ParasiticGod.Scenes.Main; + +public partial class MiraclePanel : GridContainer +{ + [Export] private PackedScene _miracleButtonScene; + + public override void _Ready() + { + GameBus.Instance.MiraclesUnlocked += OnMiraclesUnlocked; + GameBus.Instance.MiracleCompleted += OnMiracleCompleted; + } + + public override void _ExitTree() + { + GameBus.Instance.MiraclesUnlocked -= OnMiraclesUnlocked; + GameBus.Instance.MiracleCompleted -= OnMiracleCompleted; + } + + public void PopulateInitialButtons(Dictionary miracles) + { + foreach (var miracle in miracles.Values) + { + if (miracle.UnlockedByDefault) + { + AddButtonForMiracle(miracle); + } + } + } + + private void OnMiraclesUnlocked(List miracles) + { + foreach (var miracle in miracles) + { + AddButtonForMiracle(miracle); + } + } + + private void OnMiracleCompleted(MiracleDefinition miracle) + { + foreach (var child in GetChildren()) + { + if (child is MiracleButton button && button.GetMiracle() == miracle) + { + button.QueueFree(); + break; + } + } + } + + private void AddButtonForMiracle(MiracleDefinition miracle) + { + var buttonInstance = _miracleButtonScene.Instantiate(); + buttonInstance.SetMiracle(miracle); + AddChild(buttonInstance); + } +} \ No newline at end of file diff --git a/Scenes/Main/MiraclePanel.cs.uid b/Scenes/Main/MiraclePanel.cs.uid new file mode 100644 index 0000000..e426907 --- /dev/null +++ b/Scenes/Main/MiraclePanel.cs.uid @@ -0,0 +1 @@ +uid://b77vh831r1e3c diff --git a/Scenes/Main/miracle_button.tscn b/Scenes/Main/miracle_button.tscn new file mode 100644 index 0000000..da0fe07 --- /dev/null +++ b/Scenes/Main/miracle_button.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://rj1fsdlhju5y"] + +[ext_resource type="Script" uid="uid://ctjmwgucwh3le" path="res://Scenes/Main/MiracleButton.cs" id="1_sxcu0"] + +[node name="MiracleButton" type="Button"] +custom_minimum_size = Vector2(128, 64) +offset_right = 8.0 +offset_bottom = 8.0 +script = ExtResource("1_sxcu0") diff --git a/Scripts/Core/Effects/AddResourceEffect.cs b/Scripts/Core/Effects/AddResourceEffect.cs new file mode 100644 index 0000000..e82dcf1 --- /dev/null +++ b/Scripts/Core/Effects/AddResourceEffect.cs @@ -0,0 +1,29 @@ +using System; +using Godot; + +namespace ParasiticGod.Scripts.Core.Effects; + +[GlobalClass] +public partial class AddResourceEffect : Effect +{ + [Export] public ResourceType TargetResource { get; set; } + [Export] public double Value { get; set; } + + public override void Execute(GameState state) + { + switch (TargetResource) + { + case ResourceType.Faith: + state.Faith += Value; + break; + case ResourceType.Followers: + state.Followers += (long)Value; + break; + case ResourceType.Corruption: + state.Corruption += Value; + break; + default: + throw new ArgumentOutOfRangeException(); + } + } +} \ No newline at end of file diff --git a/Scripts/Core/Effects/AddResourceEffect.cs.uid b/Scripts/Core/Effects/AddResourceEffect.cs.uid new file mode 100644 index 0000000..d5958f4 --- /dev/null +++ b/Scripts/Core/Effects/AddResourceEffect.cs.uid @@ -0,0 +1 @@ +uid://flyhl4i86han diff --git a/Scripts/Core/Effects/ApplyBuffEffect.cs b/Scripts/Core/Effects/ApplyBuffEffect.cs new file mode 100644 index 0000000..2603146 --- /dev/null +++ b/Scripts/Core/Effects/ApplyBuffEffect.cs @@ -0,0 +1,24 @@ +using Godot; + +namespace ParasiticGod.Scripts.Core.Effects; + +[GlobalClass] +public partial class ApplyBuffEffect : Effect +{ + public enum BuffTarget { FaithGeneration } + + [Export] public BuffTarget TargetStat { get; set; } + [Export] public float Multiplier { get; set; } = 2.0f; + [Export] public double Duration { get; set; } = 30.0; + + public override void Execute(GameState gameState) + { + var newBuff = new Buff + { + Multiplier = Multiplier, + Duration = Duration + }; + + gameState.ActiveBuffs.Add(newBuff); + } +} \ No newline at end of file diff --git a/Scripts/Core/Effects/ApplyBuffEffect.cs.uid b/Scripts/Core/Effects/ApplyBuffEffect.cs.uid new file mode 100644 index 0000000..e55178d --- /dev/null +++ b/Scripts/Core/Effects/ApplyBuffEffect.cs.uid @@ -0,0 +1 @@ +uid://cmhd8jmckgtep diff --git a/Scripts/Core/Effects/Buff.cs b/Scripts/Core/Effects/Buff.cs new file mode 100644 index 0000000..5960920 --- /dev/null +++ b/Scripts/Core/Effects/Buff.cs @@ -0,0 +1,7 @@ +namespace ParasiticGod.Scripts.Core.Effects; + +public class Buff +{ + public float Multiplier { get; set; } = 1.0f; + public double Duration { get; set; } +} \ No newline at end of file diff --git a/Scripts/Core/Effects/Buff.cs.uid b/Scripts/Core/Effects/Buff.cs.uid new file mode 100644 index 0000000..c43cb59 --- /dev/null +++ b/Scripts/Core/Effects/Buff.cs.uid @@ -0,0 +1 @@ +uid://c5fq6vt4uyce2 diff --git a/Scripts/Core/Effects/ConvertResourceEffect.cs b/Scripts/Core/Effects/ConvertResourceEffect.cs new file mode 100644 index 0000000..b224565 --- /dev/null +++ b/Scripts/Core/Effects/ConvertResourceEffect.cs @@ -0,0 +1,36 @@ +using Godot; + +namespace ParasiticGod.Scripts.Core.Effects; + +[GlobalClass] +public partial class ConvertResourceEffect : Effect +{ + [Export] public ResourceType FromResource { get; set; } + [Export] public double FromAmount { get; set; } + [Export] public ResourceType ToResource { get; set; } + [Export] public double ToAmount { get; set; } + + public override void Execute(GameState gameState) + { + double GetValue(ResourceType type) => type switch { + ResourceType.Faith => gameState.Faith, + ResourceType.Followers => gameState.Followers, + ResourceType.Corruption => gameState.Corruption, + _ => 0 + }; + + void SetValue(ResourceType type, double value) { + switch(type) { + case ResourceType.Faith: gameState.Faith = value; break; + case ResourceType.Followers: gameState.Followers = (long)value; break; + case ResourceType.Corruption: gameState.Corruption = value; break; + } + } + + if (GetValue(FromResource) >= FromAmount) + { + SetValue(FromResource, GetValue(FromResource) - FromAmount); + SetValue(ToResource, GetValue(ToResource) + ToAmount); + } + } +} \ No newline at end of file diff --git a/Scripts/Core/Effects/ConvertResourceEffect.cs.uid b/Scripts/Core/Effects/ConvertResourceEffect.cs.uid new file mode 100644 index 0000000..3496c59 --- /dev/null +++ b/Scripts/Core/Effects/ConvertResourceEffect.cs.uid @@ -0,0 +1 @@ +uid://chiq1n5fde3eo diff --git a/Scripts/Core/Effects/DestroySelfEffect.cs b/Scripts/Core/Effects/DestroySelfEffect.cs new file mode 100644 index 0000000..04510d8 --- /dev/null +++ b/Scripts/Core/Effects/DestroySelfEffect.cs @@ -0,0 +1,11 @@ +using Godot; + +namespace ParasiticGod.Scripts.Core.Effects; + +[GlobalClass] +public partial class DestroySelfEffect : Effect +{ + public override void Execute(GameState gameState) + { + } +} \ No newline at end of file diff --git a/Scripts/Core/Effects/DestroySelfEffect.cs.uid b/Scripts/Core/Effects/DestroySelfEffect.cs.uid new file mode 100644 index 0000000..fe3be25 --- /dev/null +++ b/Scripts/Core/Effects/DestroySelfEffect.cs.uid @@ -0,0 +1 @@ +uid://dhnma6yerqpwn diff --git a/Scripts/Core/Effects/Effect.cs b/Scripts/Core/Effects/Effect.cs new file mode 100644 index 0000000..582f474 --- /dev/null +++ b/Scripts/Core/Effects/Effect.cs @@ -0,0 +1,8 @@ +using Godot; + +namespace ParasiticGod.Scripts.Core.Effects; + +public abstract partial class Effect : Resource +{ + public abstract void Execute(GameState gameState); +} \ No newline at end of file diff --git a/Scripts/Core/Effects/Effect.cs.uid b/Scripts/Core/Effects/Effect.cs.uid new file mode 100644 index 0000000..6a918dd --- /dev/null +++ b/Scripts/Core/Effects/Effect.cs.uid @@ -0,0 +1 @@ +uid://c1futvi1xm03q diff --git a/Scripts/Core/Effects/ModifyStatEffect.cs b/Scripts/Core/Effects/ModifyStatEffect.cs new file mode 100644 index 0000000..8f7e5a0 --- /dev/null +++ b/Scripts/Core/Effects/ModifyStatEffect.cs @@ -0,0 +1,30 @@ +using Godot; + +namespace ParasiticGod.Scripts.Core.Effects; + +[GlobalClass] +public partial class ModifyStatEffect : Effect +{ + public enum Stat { FaithPerFollower } + public enum Operation { Add, Multiply } + + [Export] public Stat TargetStat { get; set; } + [Export] public Operation Op { get; set; } + [Export] public double Value { get; set; } + + public override void Execute(GameState gameState) + { + if (TargetStat == Stat.FaithPerFollower) + { + switch (Op) + { + case Operation.Add: + gameState.FaithPerFollower += Value; + break; + case Operation.Multiply: + gameState.FaithPerFollower *= Value; + break; + } + } + } +} \ No newline at end of file diff --git a/Scripts/Core/Effects/ModifyStatEffect.cs.uid b/Scripts/Core/Effects/ModifyStatEffect.cs.uid new file mode 100644 index 0000000..7542c56 --- /dev/null +++ b/Scripts/Core/Effects/ModifyStatEffect.cs.uid @@ -0,0 +1 @@ +uid://dy6avn8snuuq1 diff --git a/Scripts/Core/Effects/ResourceType.cs b/Scripts/Core/Effects/ResourceType.cs new file mode 100644 index 0000000..9c94cb1 --- /dev/null +++ b/Scripts/Core/Effects/ResourceType.cs @@ -0,0 +1,3 @@ +namespace ParasiticGod.Scripts.Core.Effects; + +public enum ResourceType { Faith, Followers, Corruption } \ No newline at end of file diff --git a/Scripts/Core/Effects/ResourceType.cs.uid b/Scripts/Core/Effects/ResourceType.cs.uid new file mode 100644 index 0000000..174fcdb --- /dev/null +++ b/Scripts/Core/Effects/ResourceType.cs.uid @@ -0,0 +1 @@ +uid://do6aurfs8oif0 diff --git a/Scripts/Core/Effects/UnlockMiracleEffect.cs b/Scripts/Core/Effects/UnlockMiracleEffect.cs new file mode 100644 index 0000000..0067840 --- /dev/null +++ b/Scripts/Core/Effects/UnlockMiracleEffect.cs @@ -0,0 +1,16 @@ +using Godot; +using Godot.Collections; + +namespace ParasiticGod.Scripts.Core.Effects; + +[GlobalClass] +public partial class UnlockMiracleEffect : Effect +{ + [Export] + public Array MiraclesToUnlock { get; set; } + + public override void Execute(GameState gameState) + { + + } +} \ No newline at end of file diff --git a/Scripts/Core/Effects/UnlockMiracleEffect.cs.uid b/Scripts/Core/Effects/UnlockMiracleEffect.cs.uid new file mode 100644 index 0000000..8986c04 --- /dev/null +++ b/Scripts/Core/Effects/UnlockMiracleEffect.cs.uid @@ -0,0 +1 @@ +uid://c1oieyvbcqjcc diff --git a/Scripts/Core/GameLogic.cs b/Scripts/Core/GameLogic.cs new file mode 100644 index 0000000..3f71034 --- /dev/null +++ b/Scripts/Core/GameLogic.cs @@ -0,0 +1,43 @@ +using System; + +namespace ParasiticGod.Scripts.Core; + +public class GameLogic +{ + public void UpdateGameState(GameState state, double delta) + { + state.Faith += state.FaithPerSecond * delta; + + for (var i = state.ActiveBuffs.Count - 1; i >= 0; i--) + { + var buff = state.ActiveBuffs[i]; + buff.Duration -= delta; + if (buff.Duration <= 0) + { + state.ActiveBuffs.RemoveAt(i); + } + } + } + + public bool TryToPerformMiracle(GameState state, MiracleDefinition miracle) + { + if (state.Faith < miracle.FaithCost || state.Followers < miracle.FollowersRequired) + { + return false; + } + + state.Faith -= miracle.FaithCost; + + if (miracle.Effects != null) + { + foreach (var effect in miracle.Effects) + { + effect.Execute(state); + } + } + + state.Corruption = Math.Clamp(state.Corruption, 0, 100); + + return true; + } +} \ No newline at end of file diff --git a/Scripts/Core/GameLogic.cs.uid b/Scripts/Core/GameLogic.cs.uid new file mode 100644 index 0000000..cf49f79 --- /dev/null +++ b/Scripts/Core/GameLogic.cs.uid @@ -0,0 +1 @@ +uid://bgnfh4rd780td diff --git a/Scripts/Core/GameState.cs b/Scripts/Core/GameState.cs new file mode 100644 index 0000000..fdf3791 --- /dev/null +++ b/Scripts/Core/GameState.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using ParasiticGod.Scripts.Core.Effects; + +namespace ParasiticGod.Scripts.Core; + +public class GameState +{ + public double Faith { get; set; } = 50.0; + public double FaithPerFollower { get; set; } = 0.5; + public long Followers { get; set; } = 40; + public double Corruption { get; set; } = 0.0; + + public List ActiveBuffs { get; } = []; + + public double FaithPerSecond + { + get + { + var totalMultiplier = 1.0; + foreach (var buff in ActiveBuffs) + { + totalMultiplier *= buff.Multiplier; + } + return Followers * FaithPerFollower * totalMultiplier; + } + } +} \ No newline at end of file diff --git a/Scripts/Core/GameState.cs.uid b/Scripts/Core/GameState.cs.uid new file mode 100644 index 0000000..b91d684 --- /dev/null +++ b/Scripts/Core/GameState.cs.uid @@ -0,0 +1 @@ +uid://d3on25ypcw528 diff --git a/Scripts/Core/Miracle.cs.uid b/Scripts/Core/Miracle.cs.uid new file mode 100644 index 0000000..8db7e82 --- /dev/null +++ b/Scripts/Core/Miracle.cs.uid @@ -0,0 +1 @@ +uid://cerwpe1s25yim diff --git a/Scripts/Core/MiracleDefinition.cs b/Scripts/Core/MiracleDefinition.cs new file mode 100644 index 0000000..7d13dac --- /dev/null +++ b/Scripts/Core/MiracleDefinition.cs @@ -0,0 +1,18 @@ +using Godot; +using Godot.Collections; +using ParasiticGod.Scripts.Core.Effects; + +namespace ParasiticGod.Scripts.Core; + +[GlobalClass] +public partial class MiracleDefinition : Resource +{ + public string Id { get; set; } + public bool UnlockedByDefault { get; set; } + + [Export] public string Name { get; set; } + [Export] public double FaithCost { get; set; } + [Export] public long FollowersRequired { get; set; } + + [Export] public Array Effects { get; set; } +} \ No newline at end of file diff --git a/Scripts/Core/MiracleDefinition.cs.uid b/Scripts/Core/MiracleDefinition.cs.uid new file mode 100644 index 0000000..ff589e2 --- /dev/null +++ b/Scripts/Core/MiracleDefinition.cs.uid @@ -0,0 +1 @@ +uid://cfn3mx12xism5 diff --git a/Scripts/Core/MiracleDto.cs b/Scripts/Core/MiracleDto.cs new file mode 100644 index 0000000..e6d74e8 --- /dev/null +++ b/Scripts/Core/MiracleDto.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using ParasiticGod.Scripts.Core.Effects; + +namespace ParasiticGod.Scripts.Core; + +public class EffectDto +{ + public string Type { get; set; } + // --- For "AddResource" Effect --- + public ResourceType TargetResource { get; set; } + public double Value { get; set; } + + // --- For "ApplyBuff" Effect --- + public ApplyBuffEffect.BuffTarget TargetBuffStat { get; set; } + public float Multiplier { get; set; } + public double Duration { get; set; } + + // --- For "ConvertResource" Effect --- + public ResourceType FromResource { get; set; } + public double FromAmount { get; set; } + public ResourceType ToResource { get; set; } + public double ToAmount { get; set; } + + // --- For "ModifyStat" Effect --- + public ModifyStatEffect.Stat TargetStat { get; set; } + public ModifyStatEffect.Operation Op { get; set; } + + public List MiraclesToUnlock { get; set; } +} + +public class MiracleDto +{ + public string Name { get; set; } + public double FaithCost { get; set; } + public long FollowersRequired { get; set; } + public bool UnlockedByDefault { get; set; } + public List Effects { get; set; } +} \ No newline at end of file diff --git a/Scripts/Core/MiracleDto.cs.uid b/Scripts/Core/MiracleDto.cs.uid new file mode 100644 index 0000000..289f573 --- /dev/null +++ b/Scripts/Core/MiracleDto.cs.uid @@ -0,0 +1 @@ +uid://ba8j34h6ps8di diff --git a/Scripts/Core/MiracleLoader.cs b/Scripts/Core/MiracleLoader.cs new file mode 100644 index 0000000..58847b0 --- /dev/null +++ b/Scripts/Core/MiracleLoader.cs @@ -0,0 +1,113 @@ +using System; +using System.Text.Json; +using Godot; +using Godot.Collections; +using Newtonsoft.Json; +using ParasiticGod.Scripts.Core.Effects; + +namespace ParasiticGod.Scripts.Core; + +public static class MiracleLoader +{ + private static readonly System.Collections.Generic.Dictionary EffectRegistry = new() + { + { "AddResource", typeof(AddResourceEffect) }, + { "ApplyBuff", typeof(ApplyBuffEffect) }, + { "ConvertResource", typeof(ConvertResourceEffect) }, + { "ModifyStat", typeof(ModifyStatEffect) }, + { "UnlockMiracle", typeof(UnlockMiracleEffect) }, + { "DestroySelf", typeof(DestroySelfEffect) } + }; + + public static System.Collections.Generic.Dictionary LoadMiraclesFromDirectory(string path) + { + var loadedMiracles = new System.Collections.Generic.Dictionary(); + using var dir = DirAccess.Open(path); + if (dir == null) return loadedMiracles; + + dir.ListDirBegin(); + var fileName = dir.GetNext(); + while (!string.IsNullOrEmpty(fileName)) + { + if (!dir.CurrentIsDir() && fileName.EndsWith(".json")) + { + var filePath = path.PathJoin(fileName); + var fileNameNoExt = fileName.GetBaseName(); + var miracle = LoadMiracleFromFile(filePath, fileNameNoExt); // Pass the ID + if (miracle != null) + { + loadedMiracles.Add(fileNameNoExt, miracle); + } + } + fileName = dir.GetNext(); + } + + GD.Print($"Loaded {loadedMiracles.Count} miracles from {path}"); + return loadedMiracles; + } + + private static MiracleDefinition LoadMiracleFromFile(string filePath, string miracleId) + { + var fileContent = FileAccess.GetFileAsString(filePath); + if (string.IsNullOrEmpty(fileContent)) + { + GD.PushError($"Failed to read file or file is empty: {filePath}"); + return null; + } + + var miracleDto = JsonConvert.DeserializeObject(fileContent); + if (miracleDto == null) + { + GD.PushError($"Failed to deserialize miracle JSON: {filePath}"); + return null; + } + + var miracleDef = new MiracleDefinition + { + Id = miracleId, + UnlockedByDefault = miracleDto.UnlockedByDefault, + Name = miracleDto.Name, + FaithCost = miracleDto.FaithCost, + FollowersRequired = miracleDto.FollowersRequired, + Effects = [] + }; + + foreach (var effectDto in miracleDto.Effects) + { + if (EffectRegistry.TryGetValue(effectDto.Type, out var effectType)) + { + var effectInstance = (Effect)Activator.CreateInstance(effectType); + switch (effectInstance) + { + case AddResourceEffect addResourceEffect: + addResourceEffect.TargetResource = effectDto.TargetResource; + addResourceEffect.Value = effectDto.Value; + break; + case ApplyBuffEffect applyBuffEffect: + applyBuffEffect.TargetStat = effectDto.TargetBuffStat; + applyBuffEffect.Multiplier = effectDto.Multiplier; + applyBuffEffect.Duration = effectDto.Duration; + break; + case ConvertResourceEffect convertResourceEffect: + convertResourceEffect.FromResource = effectDto.FromResource; + convertResourceEffect.FromAmount = effectDto.FromAmount; + convertResourceEffect.ToResource = effectDto.ToResource; + convertResourceEffect.ToAmount = effectDto.ToAmount; + break; + case ModifyStatEffect modifyStatEffect: + modifyStatEffect.TargetStat = effectDto.TargetStat; + modifyStatEffect.Op = effectDto.Op; + modifyStatEffect.Value = effectDto.Value; + break; + case UnlockMiracleEffect unlockMiracleEffect: + unlockMiracleEffect.MiraclesToUnlock = new Array(effectDto.MiraclesToUnlock); + break; + } + + miracleDef.Effects.Add(effectInstance); + } + } + + return miracleDef; + } +} \ No newline at end of file diff --git a/Scripts/Core/MiracleLoader.cs.uid b/Scripts/Core/MiracleLoader.cs.uid new file mode 100644 index 0000000..939607d --- /dev/null +++ b/Scripts/Core/MiracleLoader.cs.uid @@ -0,0 +1 @@ +uid://bpagwiy55t230 diff --git a/Scripts/Core/TierDefinition.cs b/Scripts/Core/TierDefinition.cs new file mode 100644 index 0000000..b4e58d3 --- /dev/null +++ b/Scripts/Core/TierDefinition.cs @@ -0,0 +1,10 @@ +using Godot; + +namespace ParasiticGod.Scripts.Core; + +[GlobalClass] +public partial class TierDefinition : Resource +{ + [Export] public PackedScene Scene { get; private set; } + [Export] public long Threshold { get; private set; } +} \ No newline at end of file diff --git a/Scripts/Core/TierDefinition.cs.uid b/Scripts/Core/TierDefinition.cs.uid new file mode 100644 index 0000000..8aa123d --- /dev/null +++ b/Scripts/Core/TierDefinition.cs.uid @@ -0,0 +1 @@ +uid://c7hh0cy0yrdt8 diff --git a/Scripts/Follower.cs b/Scripts/Follower.cs new file mode 100644 index 0000000..fb28994 --- /dev/null +++ b/Scripts/Follower.cs @@ -0,0 +1,10 @@ +using Godot; + +namespace ParasiticGod.Scripts; + +[GlobalClass] +public partial class Follower : Node2D +{ + public enum FollowerTier { Tier1, Tier2, Tier3, Tier4, Tier5 } + [Export] public FollowerTier Tier { get; private set; } +} \ No newline at end of file diff --git a/Scripts/Follower.cs.uid b/Scripts/Follower.cs.uid new file mode 100644 index 0000000..b93d17e --- /dev/null +++ b/Scripts/Follower.cs.uid @@ -0,0 +1 @@ +uid://cj5libcgnhjml diff --git a/Scripts/FollowerMarker.cs b/Scripts/FollowerMarker.cs new file mode 100644 index 0000000..59af2f7 --- /dev/null +++ b/Scripts/FollowerMarker.cs @@ -0,0 +1,27 @@ +using Godot; + +namespace ParasiticGod.Scripts; + +[GlobalClass] +public partial class FollowerMarker : Marker2D +{ + public bool IsOccupied { get; private set; } + public Follower FollowerInstance { get; private set; } + + public void PlaceFollower(Follower followerInstance) + { + if (IsOccupied) return; + AddChild(followerInstance); + followerInstance.Position = Vector2.Zero; + IsOccupied = true; + FollowerInstance = followerInstance; + } + + public void RemoveFollower() + { + if (!IsOccupied) return; + FollowerInstance.QueueFree(); + FollowerInstance = null; + IsOccupied = false; + } +} \ No newline at end of file diff --git a/Scripts/FollowerMarker.cs.uid b/Scripts/FollowerMarker.cs.uid new file mode 100644 index 0000000..1f0ce4a --- /dev/null +++ b/Scripts/FollowerMarker.cs.uid @@ -0,0 +1 @@ +uid://djaf0gv8s7qib diff --git a/Scripts/PopulationVisualizer.cs b/Scripts/PopulationVisualizer.cs new file mode 100644 index 0000000..c4c4266 --- /dev/null +++ b/Scripts/PopulationVisualizer.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using Godot; +using Godot.Collections; +using ParasiticGod.Scripts.Core; +using ParasiticGod.Scripts.Singletons; + +namespace ParasiticGod.Scripts; + +[GlobalClass] +public partial class PopulationVisualizer : Node +{ + [Export] private Node2D _markersContainer; + [Export] private int _unitsPerMarker = 5; + [Export] private Array _tiers; + + private readonly List _markers = []; + private long _lastKnownUnitCount = -1; + private int _lastKnownTierIndex = -1; + private bool _isUpdating = false; + + public override void _Ready() + { + foreach (var child in _markersContainer.GetChildren()) + { + if (child is FollowerMarker marker) + { + _markers.Add(marker); + } + } + + GameBus.Instance.StateChanged += OnStateChanged; + } + + public override void _ExitTree() + { + GameBus.Instance.StateChanged -= OnStateChanged; + } + + private void OnStateChanged(GameState newState) + { + if (_isUpdating) return; + + var currentUnitCount = newState.Followers; + + var currentMarkersToShow = (int)currentUnitCount / _unitsPerMarker; + var lastMarkersToShow = (int)_lastKnownUnitCount / _unitsPerMarker; + var newTierIndex = GetTierIndex(currentUnitCount); + + if (currentMarkersToShow != lastMarkersToShow || newTierIndex != _lastKnownTierIndex) + { + UpdateVisualsProgressively(currentUnitCount, newTierIndex); + } + } + + private int GetTierIndex(long currentUnitCount) + { + for (var i = _tiers.Count - 1; i >= 0; i--) + { + if (currentUnitCount >= _tiers[i].Threshold) + { + return i; + } + } + return -1; + } + + private async void UpdateVisualsProgressively(long currentUnitCount, int newTierIndex) + { + _isUpdating = true; + + if (newTierIndex < 0) + { + _isUpdating = false; + return; + } + + var followersToShow = (int)currentUnitCount / _unitsPerMarker; + var currentTier = _tiers[newTierIndex]; + + for (var i = 0; i < _markers.Count; i++) + { + var marker = _markers[i]; + var needsChange = false; + + if (i < followersToShow) + { + // Note: The 'Follower' script would need a way to know its tier index or resource path + // to do a perfect comparison. For now, we'll just check for occupancy. + if (!marker.IsOccupied || _lastKnownTierIndex != newTierIndex) + { + if (marker.IsOccupied) marker.RemoveFollower(); + var followerInstance = currentTier.Scene.Instantiate(); + marker.PlaceFollower(followerInstance); + needsChange = true; + } + } + else + { + if (marker.IsOccupied) + { + marker.RemoveFollower(); + needsChange = true; + } + } + + if (needsChange) + { + await ToSignal(GetTree().CreateTimer(0.1f), SceneTreeTimer.SignalName.Timeout); + } + } + + _lastKnownUnitCount = currentUnitCount; + _lastKnownTierIndex = newTierIndex; + _isUpdating = false; + } +} \ No newline at end of file diff --git a/Scripts/PopulationVisualizer.cs.uid b/Scripts/PopulationVisualizer.cs.uid new file mode 100644 index 0000000..fb59598 --- /dev/null +++ b/Scripts/PopulationVisualizer.cs.uid @@ -0,0 +1 @@ +uid://dj2wyrq07gfp2 diff --git a/Scripts/Singletons/GameBus.cs b/Scripts/Singletons/GameBus.cs new file mode 100644 index 0000000..9de14bb --- /dev/null +++ b/Scripts/Singletons/GameBus.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using Godot; +using ParasiticGod.Scripts.Core; +using ParasiticGod.Scripts.Core.Effects; + +namespace ParasiticGod.Scripts.Singletons; + +public partial class GameBus : Node +{ + public static GameBus Instance { get; private set; } + public Dictionary AllMiracles { get; private set; } + + private readonly GameState _gameState = new(); + private readonly GameLogic _gameLogic = new(); + + public event Action StateChanged; + public event Action MiraclePerformed; + public event Action> MiraclesUnlocked; + public event Action MiracleCompleted; + + public override void _EnterTree() + { + Instance = this; + AllMiracles = MiracleLoader.LoadMiraclesFromDirectory("user://Mods/Miracles"); + } + + public override void _ExitTree() + { + Instance = null; + } + + public override void _Process(double delta) + { + _gameLogic.UpdateGameState(_gameState, delta); + StateChanged?.Invoke(_gameState); + + if (_gameState.Corruption >= 100) + { + GD.Print("The world has died!"); + GetTree().Quit(); // For now + } + } + + public void PerformMiracle(MiracleDefinition miracle) + { + if (_gameLogic.TryToPerformMiracle(_gameState, miracle)) + { + MiraclePerformed?.Invoke(miracle); + + var miraclesToUnlock = new List(); + foreach (var effect in miracle.Effects) + { + if (effect is UnlockMiracleEffect unlockEffect) + { + foreach (var id in unlockEffect.MiraclesToUnlock) + { + if (AllMiracles.TryGetValue(id, out var def)) + { + miraclesToUnlock.Add(def); + } + } + } + else if (effect is DestroySelfEffect) + { + MiracleCompleted?.Invoke(miracle); + } + } + + if (miraclesToUnlock.Count > 0) + { + MiraclesUnlocked?.Invoke(miraclesToUnlock); + } + } + } +} \ No newline at end of file diff --git a/Scripts/Singletons/GameBus.cs.uid b/Scripts/Singletons/GameBus.cs.uid new file mode 100644 index 0000000..077a62d --- /dev/null +++ b/Scripts/Singletons/GameBus.cs.uid @@ -0,0 +1 @@ +uid://bxtp262r58pb6 diff --git a/Shaders/corruption_shader.gdshader b/Shaders/corruption_shader.gdshader new file mode 100644 index 0000000..30967d7 --- /dev/null +++ b/Shaders/corruption_shader.gdshader @@ -0,0 +1,30 @@ +shader_type canvas_item; + +// The color of the healthy terrain you want to target. +uniform vec4 terrain_color : source_color = vec4(0.0, 1.0, 0.0, 1.0); +// The color the terrain will turn into as it gets corrupted. +uniform vec4 corrupted_color : source_color = vec4(0.3, 0.1, 0.2, 1.0); +// This value will be controlled by your C# script (from 0.0 to 1.0). +uniform float corruption_level : hint_range(0.0, 1.0); +// A small tolerance to catch pixels that aren't *exactly* the terrain color. +uniform float tolerance : hint_range(0.0, 0.5) = 0.1; + +void fragment() { + // Get the original color of the pixel from the sprite's texture. + vec4 original_color = texture(TEXTURE, UV); + + // Calculate the difference between this pixel's color and the healthy terrain color. + // The distance() function is great for comparing colors. + float color_difference = distance(original_color.rgb, terrain_color.rgb); + + // Check if the difference is within our tolerance. + if (color_difference < tolerance) { + // If it's a terrain pixel, mix the original terrain color with the + // corrupted color based on the corruption_level. + vec3 final_color = mix(terrain_color.rgb, corrupted_color.rgb, corruption_level); + COLOR = vec4(final_color, original_color.a); + } else { + // If it's not a terrain pixel (i.e., it's ocean), leave it unchanged. + COLOR = original_color; + } +} diff --git a/Shaders/corruption_shader.gdshader.uid b/Shaders/corruption_shader.gdshader.uid new file mode 100644 index 0000000..625477e --- /dev/null +++ b/Shaders/corruption_shader.gdshader.uid @@ -0,0 +1 @@ +uid://bf8nk145fjkgh diff --git a/Sprites/Follower.png b/Sprites/Follower.png new file mode 100644 index 0000000..f5912bc Binary files /dev/null and b/Sprites/Follower.png differ diff --git a/Sprites/Follower.png.import b/Sprites/Follower.png.import new file mode 100644 index 0000000..793b66d --- /dev/null +++ b/Sprites/Follower.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dhrbjqmhqdpef" +path="res://.godot/imported/Follower.png-568d06ea1b5c1c395e9e42b16183ec13.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Follower.png" +dest_files=["res://.godot/imported/Follower.png-568d06ea1b5c1c395e9e42b16183ec13.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Sprites/Hut.png b/Sprites/Hut.png new file mode 100644 index 0000000..a557fbb Binary files /dev/null and b/Sprites/Hut.png differ diff --git a/Sprites/Hut.png.import b/Sprites/Hut.png.import new file mode 100644 index 0000000..f6680cd --- /dev/null +++ b/Sprites/Hut.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://clnujxe12l86u" +path="res://.godot/imported/Hut.png-fc891375580af52944b1e086f539d137.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Hut.png" +dest_files=["res://.godot/imported/Hut.png-fc891375580af52944b1e086f539d137.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Sprites/Tree.png b/Sprites/Tree.png new file mode 100644 index 0000000..e1d125b Binary files /dev/null and b/Sprites/Tree.png differ diff --git a/Sprites/Tree.png.import b/Sprites/Tree.png.import new file mode 100644 index 0000000..5446006 --- /dev/null +++ b/Sprites/Tree.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cemch3556ibiy" +path="res://.godot/imported/Tree.png-4d71c4eeb5c29f1f5a16c6316200ee5f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Tree.png" +dest_files=["res://.godot/imported/Tree.png-4d71c4eeb5c29f1f5a16c6316200ee5f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Sprites/Untitled_Artwork (1).png.import b/Sprites/Untitled_Artwork (1).png.import new file mode 100644 index 0000000..1a7e0a1 --- /dev/null +++ b/Sprites/Untitled_Artwork (1).png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://crxglfqa5ei13" +path="res://.godot/imported/Untitled_Artwork (1).png-536ad21dc71d72a911413e46d3ca9eb1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Untitled_Artwork (1).png" +dest_files=["res://.godot/imported/Untitled_Artwork (1).png-536ad21dc71d72a911413e46d3ca9eb1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Sprites/Untitled_Artwork (2).png.import b/Sprites/Untitled_Artwork (2).png.import new file mode 100644 index 0000000..14be1b8 --- /dev/null +++ b/Sprites/Untitled_Artwork (2).png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://m01y65j66qj1" +path="res://.godot/imported/Untitled_Artwork (2).png-2e72756cd7ef98f976395527025d6fbc.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Untitled_Artwork (2).png" +dest_files=["res://.godot/imported/Untitled_Artwork (2).png-2e72756cd7ef98f976395527025d6fbc.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Sprites/Untitled_Artwork.png.import b/Sprites/Untitled_Artwork.png.import new file mode 100644 index 0000000..9ad1692 --- /dev/null +++ b/Sprites/Untitled_Artwork.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cxir8p5f2u5k6" +path="res://.godot/imported/Untitled_Artwork.png-76b4af36038944b044ef4f7c2d11b468.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/Untitled_Artwork.png" +dest_files=["res://.godot/imported/Untitled_Artwork.png-76b4af36038944b044ef4f7c2d11b468.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Sprites/globe.svg b/Sprites/globe.svg new file mode 100644 index 0000000..043b73e --- /dev/null +++ b/Sprites/globe.svg @@ -0,0 +1,133 @@ + + + + diff --git a/Sprites/globe.svg.import b/Sprites/globe.svg.import new file mode 100644 index 0000000..af517c3 --- /dev/null +++ b/Sprites/globe.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dg6ac3jb1366r" +path="res://.godot/imported/globe.svg-9c419d879d7f9a7e66b36bfc4b4ebd76.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Sprites/globe.svg" +dest_files=["res://.godot/imported/globe.svg-9c419d879d7f9a7e66b36bfc4b4ebd76.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..9d8b7fa --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..0b99d95 --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dcs48aa84w21u" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..f2025ed --- /dev/null +++ b/project.godot @@ -0,0 +1,33 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Parasitic God" +run/main_scene="uid://bfil8sd154327" +config/features=PackedStringArray("4.4", "C#", "GL Compatibility") +boot_splash/show_image=false +boot_splash/fullsize=false +boot_splash/use_filter=false +config/icon="res://icon.svg" + +[autoload] + +GameBus="*res://Scripts/Singletons/GameBus.cs" + +[dotnet] + +project/assembly_name="ParasiticGod" + +[rendering] + +renderer/rendering_method="gl_compatibility" +renderer/rendering_method.mobile="gl_compatibility" +environment/defaults/default_clear_color=Color(0.160784, 0.501961, 0.72549, 1)