Compare commits
40 Commits
18312671d7
...
master
Author | SHA1 | Date | |
---|---|---|---|
f81a237f01 | |||
47281a098d | |||
5dd8e6fff9 | |||
0747595f2b | |||
2bf0f4a360 | |||
bdcc0d5089 | |||
1b3657b03a | |||
6d8139fd44 | |||
cdd944b9b5 | |||
c0d18507e3 | |||
7e8ccb061a | |||
e7247ee715 | |||
048688da45 | |||
3d48d7e9d6 | |||
33c182e623 | |||
4ceb63e49c | |||
0fbd49f36a | |||
8ae0e7e80c | |||
73a89b736e | |||
a5ab466df9 | |||
ce8fd41a93 | |||
283adc02c9 | |||
f840b98fd0 | |||
07995821f5 | |||
846c3a6d83 | |||
9da3b02a46 | |||
cd715a24cb | |||
608bcc552d | |||
8efbc9cc6e | |||
a6c6bde622 | |||
83b89e3099 | |||
de2f24cfce | |||
729a9fd1ea | |||
3ed64b165f | |||
4a3bc46081 | |||
bf272b4c2f | |||
9cf707945b | |||
5719c3f920 | |||
32c75c6fe8 | |||
d198aed01f |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,2 +1,4 @@
|
|||||||
# Normalize EOL for all files that Git considers text files.
|
# Normalize EOL for all files that Git considers text files.
|
||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
|
addons/* linguist-vendored
|
||||||
|
*.gd linguist-vendored
|
||||||
|
15
Dialogue/tutorial.dialogue
Normal file
15
Dialogue/tutorial.dialogue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
~ start
|
||||||
|
Narrator: You are a newborn god, a consciousness adrift in the cosmos.
|
||||||
|
|
||||||
|
Narrator: Below you, a nascent world teems with life. A small tribe of followers has begun to worship you. Their belief is your existence.
|
||||||
|
|
||||||
|
Narrator: Your goal is simple: nurture this civilization until they can reach for the stars and carry you with them.
|
||||||
|
|
||||||
|
Narrator: Grant them miracles to grow their population and advance their industry. Click the buttons on the right to see your powers.
|
||||||
|
|
||||||
|
Narrator: But be warned... your divine presence is a paradox. Every miracle that helps your followers also poisons their world, corrupting it.
|
||||||
|
|
||||||
|
Narrator: If the world's corruption reaches 100%, it will be consumed, and you along with it.
|
||||||
|
|
||||||
|
Narrator: Guide them. Grow them. But do not destroy them before they can escape. Their fate, and yours, is in your hands.
|
||||||
|
=> END
|
16
Dialogue/tutorial.dialogue.import
Normal file
16
Dialogue/tutorial.dialogue.import
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="dialogue_manager"
|
||||||
|
importer_version=15
|
||||||
|
type="Resource"
|
||||||
|
uid="uid://dxgpvgx7axp88"
|
||||||
|
path="res://.godot/imported/tutorial.dialogue-20e92c929aa826a6ba83a2adbbdba7f9.tres"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Dialogue/tutorial.dialogue"
|
||||||
|
dest_files=["res://.godot/imported/tutorial.dialogue-20e92c929aa826a6ba83a2adbbdba7f9.tres"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
defaults=true
|
BIN
Fonts/COMIC.TTF
Normal file
BIN
Fonts/COMIC.TTF
Normal file
Binary file not shown.
35
Fonts/COMIC.TTF.import
Normal file
35
Fonts/COMIC.TTF.import
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="font_data_dynamic"
|
||||||
|
type="FontFile"
|
||||||
|
uid="uid://b8tf6dbm2j0ju"
|
||||||
|
path="res://.godot/imported/COMIC.TTF-856a12f50d25f6c40b9b7475a5a3c8de.fontdata"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Fonts/COMIC.TTF"
|
||||||
|
dest_files=["res://.godot/imported/COMIC.TTF-856a12f50d25f6c40b9b7475a5a3c8de.fontdata"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
Rendering=null
|
||||||
|
antialiasing=1
|
||||||
|
generate_mipmaps=false
|
||||||
|
disable_embedded_bitmaps=true
|
||||||
|
multichannel_signed_distance_field=false
|
||||||
|
msdf_pixel_range=8
|
||||||
|
msdf_size=48
|
||||||
|
allow_system_fallback=true
|
||||||
|
force_autohinter=false
|
||||||
|
hinting=1
|
||||||
|
subpixel_positioning=4
|
||||||
|
keep_rounding_remainders=true
|
||||||
|
oversampling=0.0
|
||||||
|
Fallbacks=null
|
||||||
|
fallbacks=[]
|
||||||
|
Compress=null
|
||||||
|
compress=true
|
||||||
|
preload=[]
|
||||||
|
language_support={}
|
||||||
|
script_support={}
|
||||||
|
opentype_features={}
|
BIN
Fonts/Playful Boxes.otf
Normal file
BIN
Fonts/Playful Boxes.otf
Normal file
Binary file not shown.
35
Fonts/Playful Boxes.otf.import
Normal file
35
Fonts/Playful Boxes.otf.import
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="font_data_dynamic"
|
||||||
|
type="FontFile"
|
||||||
|
uid="uid://wofoiaejxgsp"
|
||||||
|
path="res://.godot/imported/Playful Boxes.otf-113f6b887ec1f2b8d73de65734580dbc.fontdata"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Fonts/Playful Boxes.otf"
|
||||||
|
dest_files=["res://.godot/imported/Playful Boxes.otf-113f6b887ec1f2b8d73de65734580dbc.fontdata"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
Rendering=null
|
||||||
|
antialiasing=1
|
||||||
|
generate_mipmaps=false
|
||||||
|
disable_embedded_bitmaps=true
|
||||||
|
multichannel_signed_distance_field=false
|
||||||
|
msdf_pixel_range=8
|
||||||
|
msdf_size=48
|
||||||
|
allow_system_fallback=true
|
||||||
|
force_autohinter=false
|
||||||
|
hinting=1
|
||||||
|
subpixel_positioning=4
|
||||||
|
keep_rounding_remainders=true
|
||||||
|
oversampling=0.0
|
||||||
|
Fallbacks=null
|
||||||
|
fallbacks=[]
|
||||||
|
Compress=null
|
||||||
|
compress=true
|
||||||
|
preload=[]
|
||||||
|
language_support={}
|
||||||
|
script_support={}
|
||||||
|
opentype_features={}
|
59
LICENSE.txt
Normal file
59
LICENSE.txt
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
Parasitic God - License
|
||||||
|
This project uses a split licensing model. The source code is released into the public domain, while the art and audio assets are under a more restrictive license.
|
||||||
|
|
||||||
|
Code License (The Unlicense)
|
||||||
|
This applies to all .cs, .gdshader, and other source code files.
|
||||||
|
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to https://unlicense.org
|
||||||
|
|
||||||
|
Asset License (All Rights Reserved)
|
||||||
|
This license applies to all files within the following directories and their subdirectories:
|
||||||
|
|
||||||
|
/Sprites/
|
||||||
|
|
||||||
|
/Assets/
|
||||||
|
|
||||||
|
/Shaders/ (specifically the visual output, not the code)
|
||||||
|
|
||||||
|
Any other directory containing visual (.png, .svg, .jpg, etc.) or audio (.wav, .ogg, .mp3, etc.) assets.
|
||||||
|
|
||||||
|
The assets contained within this project are NOT covered by the code license above. They are the property of their respective creators.
|
||||||
|
|
||||||
|
You are granted the following permissions:
|
||||||
|
|
||||||
|
You MAY use these assets within the compiled, playable version of the game "Parasitic God".
|
||||||
|
|
||||||
|
You MAY view and modify these assets on your local machine for the purpose of learning or personal enjoyment.
|
||||||
|
|
||||||
|
You are explicitly forbidden from:
|
||||||
|
|
||||||
|
Redistributing, sharing, or selling these assets in any form, either individually or as part of a collection.
|
||||||
|
|
||||||
|
Using these assets in any other game, project, or work, commercial or non-commercial.
|
||||||
|
|
||||||
|
Creating derivative works from these assets for public distribution.
|
||||||
|
|
||||||
|
All rights to these assets are reserved by the original creators. If you wish to use them for any purpose not explicitly granted above, you must seek direct permission from the copyright holder.
|
37
Mods/Events/a_plague_descends.json
Normal file
37
Mods/Events/a_plague_descends.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"id": "event_plague_descends",
|
||||||
|
"title": "A Plague Descends",
|
||||||
|
"description": "A virulent disease is sweeping through the population, sickening your followers and halting progress. Drastic measures may be required.",
|
||||||
|
"meanTimeToHappen": 300,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 500,
|
||||||
|
"maxCorruption": 80
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "We must sacrifice the sick.",
|
||||||
|
"tooltip": "Immediately lose 20% of your Followers, but the plague is stopped.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "Followers",
|
||||||
|
"op": "Multiply",
|
||||||
|
"value": 0.8
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "We will pray for their recovery.",
|
||||||
|
"tooltip": "Lose all passive Follower generation for 120 seconds as the plague runs its course.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ApplyBuff",
|
||||||
|
"buffId": "plague_debuff",
|
||||||
|
"targetStat": "FollowersPerSecond",
|
||||||
|
"multiplier": 0,
|
||||||
|
"duration": 120
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
34
Mods/Events/a_prophets_rise.json
Normal file
34
Mods/Events/a_prophets_rise.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"id": "event_prophets_rise",
|
||||||
|
"title": "A Prophet's Rise",
|
||||||
|
"description": "A charismatic leader has emerged among your followers, inspiring them to new heights of devotion and ingenuity. How shall you guide their efforts?",
|
||||||
|
"meanTimeToHappen": 200,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 800,
|
||||||
|
"maxCorruption": 60
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "Focus their zeal on industry.",
|
||||||
|
"tooltip": "Gain a large, one-time boost to Production.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Production",
|
||||||
|
"value": 750
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Inspire a population boom.",
|
||||||
|
"tooltip": "Gain a large, one-time boost to Followers.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Followers",
|
||||||
|
"value": 250
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
38
Mods/Events/divine_inspiration.json
Normal file
38
Mods/Events/divine_inspiration.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"id": "event_divine_inspiration",
|
||||||
|
"title": "Divine Inspiration",
|
||||||
|
"description": "You feel a surge of pure cosmic energy. You can channel this power to inspire your followers in their efforts to either build or cleanse.",
|
||||||
|
"meanTimeToHappen": 250,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 1500,
|
||||||
|
"maxCorruption": 75
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "Inspire frantic construction.",
|
||||||
|
"tooltip": "Greatly increases all passive Production for 2 minutes.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ApplyBuff",
|
||||||
|
"buffId": "inspiration_production_buff",
|
||||||
|
"targetStat": "ProductionPerSecond",
|
||||||
|
"multiplier": 3,
|
||||||
|
"duration": 120
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Inspire planetary healing.",
|
||||||
|
"tooltip": "Greatly reduces all passive Corruption for 2 minutes.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ApplyBuff",
|
||||||
|
"buffId": "inspiration_cleansing_buff",
|
||||||
|
"targetStat": "CorruptionPerSecond",
|
||||||
|
"multiplier": -2,
|
||||||
|
"duration": 120
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
Mods/Events/doomsday.json
Normal file
24
Mods/Events/doomsday.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"id": "event_dooms_day",
|
||||||
|
"title": "DOOMS DAY!",
|
||||||
|
"description": "A catastrophic event is unfolding, threatening to annihilate everything in its path",
|
||||||
|
"meanTimeToHappen": 2000,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 500,
|
||||||
|
"maxCorruption": 99
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "NOT TODAY...",
|
||||||
|
"tooltip": "Increase Corruption by 200. (Instant game over)",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "Corruption",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 200
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
35
Mods/Events/ecological_collapse.json
Normal file
35
Mods/Events/ecological_collapse.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"id": "event_ecological_collapse",
|
||||||
|
"title": "Ecological Collapse",
|
||||||
|
"description": "The planet's ecosystem has reached a breaking point. Widespread famine and resource scarcity are imminent. We must choose what to prioritize for survival.",
|
||||||
|
"meanTimeToHappen": 400,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 3000,
|
||||||
|
"maxCorruption": 85
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "Ration food for the workers.",
|
||||||
|
"tooltip": "Maintain your production, but lose a significant number of followers to famine.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Followers",
|
||||||
|
"value": -1000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Divert all efforts to food production.",
|
||||||
|
"tooltip": "Save your population, but suffer a permanent blow to your industrial efficiency.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "ProductionPerFollower",
|
||||||
|
"op": "Multiply",
|
||||||
|
"value": 0.75
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
Mods/Events/good_harvest.json
Normal file
23
Mods/Events/good_harvest.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"id": "event_good_harvest",
|
||||||
|
"title": "Bountiful Harvest",
|
||||||
|
"description": "A miraculous confluence of weather and soil fertility has led to an unexpectedly large harvest. Our granaries are overflowing!",
|
||||||
|
"meanTimeToHappen": 120,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 100,
|
||||||
|
"maxCorruption": 50
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "A true blessing!",
|
||||||
|
"tooltip": "Gain a large amount (500) of Faith.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Faith",
|
||||||
|
"value": 500
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
Mods/Events/industrial_breakthrough.json
Normal file
24
Mods/Events/industrial_breakthrough.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"id": "event_industrial_breakthrough",
|
||||||
|
"title": "Industrial Breakthrough",
|
||||||
|
"description": "One of your followers has made a revolutionary discovery in manufacturing techniques! This will permanently increase the efficiency of all future industry.",
|
||||||
|
"meanTimeToHappen": 240,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 1000,
|
||||||
|
"maxCorruption": 70
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "A brilliant mind!",
|
||||||
|
"tooltip": "Permanently increases base Production Per Second by 2.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "ProductionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
35
Mods/Events/unstable_rift.json
Normal file
35
Mods/Events/unstable_rift.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"id": "event_unstable_rift",
|
||||||
|
"title": "Unstable Rift",
|
||||||
|
"description": "The planet groans under the weight of your power. A rift of pure corruption has torn open, spewing filth into the environment.",
|
||||||
|
"meanTimeToHappen": 180,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 2000,
|
||||||
|
"maxCorruption": 90
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "Seal it with our power.",
|
||||||
|
"tooltip": "Lose a large amount of Production to seal the rift.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Production",
|
||||||
|
"value": -1000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "This is a necessary evil.",
|
||||||
|
"tooltip": "The rift remains, permanently increasing passive Corruption gain.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "CorruptionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 0.5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
21
Mods/Miracles/blood_ritual.json
Normal file
21
Mods/Miracles/blood_ritual.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "Blood Ritual",
|
||||||
|
"faithCost": 0,
|
||||||
|
"followersRequired": 25,
|
||||||
|
"productionRequired": 0,
|
||||||
|
"unlockedByDefault": true,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ConvertResource",
|
||||||
|
"fromResource": "Followers",
|
||||||
|
"fromAmount": 10,
|
||||||
|
"toResource": "Faith",
|
||||||
|
"toAmount": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Corruption",
|
||||||
|
"value": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -1,18 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "Bountiful Harvest",
|
"name": "Bountiful Harvest",
|
||||||
"faithCost": 50,
|
"faithCost": 10,
|
||||||
"followersRequired": 0,
|
"followersRequired": 0,
|
||||||
"unlockedByDefault": true,
|
"unlockedByDefault": true,
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"type": "AddResource",
|
"type": "AddResource",
|
||||||
"targetResource": "Followers",
|
"targetResource": "Followers",
|
||||||
"value": 10
|
"value": 5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "AddResource",
|
"type": "AddResource",
|
||||||
"targetResource": "Corruption",
|
"targetResource": "Corruption",
|
||||||
"value": 2
|
"value": 0.2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
18
Mods/Miracles/communal_effort.json
Normal file
18
Mods/Miracles/communal_effort.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "Communal Effort",
|
||||||
|
"faithCost": 40,
|
||||||
|
"followersRequired": 250,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Production",
|
||||||
|
"value": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Corruption",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
Mods/Miracles/construct_vessel_frame.json
Normal file
16
Mods/Miracles/construct_vessel_frame.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "Project: Ark Frame",
|
||||||
|
"faithCost": 20000,
|
||||||
|
"followersRequired": 5000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ConvertResource",
|
||||||
|
"fromResource": "Production",
|
||||||
|
"fromAmount": 5000,
|
||||||
|
"toResource": "Faith",
|
||||||
|
"toAmount": 0
|
||||||
|
},
|
||||||
|
{ "type": "DestroySelf" }
|
||||||
|
]
|
||||||
|
}
|
18
Mods/Miracles/craftmenship.json
Normal file
18
Mods/Miracles/craftmenship.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "Craftsmanship",
|
||||||
|
"faithCost": 80,
|
||||||
|
"followersRequired": 300,
|
||||||
|
"productionRequired": 25,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "ProductionPerFollower",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 0.01
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "DestroySelf"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Divine Frenzy",
|
|
||||||
"faithCost": 200,
|
|
||||||
"followersRequired": 50,
|
|
||||||
"unlockedByDefault": true,
|
|
||||||
"effects": [
|
|
||||||
{
|
|
||||||
"type": "ApplyBuff",
|
|
||||||
"targetBuffStat": "FaithGeneration",
|
|
||||||
"multiplier": 2.0,
|
|
||||||
"duration": 30
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
18
Mods/Miracles/divine_mandate.json
Normal file
18
Mods/Miracles/divine_mandate.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "Divine Mandate",
|
||||||
|
"faithCost": 300,
|
||||||
|
"followersRequired": 350,
|
||||||
|
"productionRequired": 100,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "FollowersPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "DestroySelf"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Divine Sacrifice",
|
|
||||||
"faithCost": 250,
|
|
||||||
"unlockedByDefault": false,
|
|
||||||
"followersRequired": 100,
|
|
||||||
"effects": [
|
|
||||||
{
|
|
||||||
"type": "ConvertResource",
|
|
||||||
"fromResource": "Followers",
|
|
||||||
"fromAmount": 50,
|
|
||||||
"toResource": "Faith",
|
|
||||||
"toAmount": 1000
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
19
Mods/Miracles/erect_shrine.json
Normal file
19
Mods/Miracles/erect_shrine.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Erect Shrine",
|
||||||
|
"faithCost": 60,
|
||||||
|
"followersRequired": 200,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "FaithPerFollower",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 0.05
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Corruption",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
18
Mods/Miracles/exploit_earth.json
Normal file
18
Mods/Miracles/exploit_earth.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "Exploit the Earth",
|
||||||
|
"faithCost": 200,
|
||||||
|
"followersRequired": 1200,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Production",
|
||||||
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Corruption",
|
||||||
|
"value": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
24
Mods/Miracles/fossil_fuel_frenzy.json
Normal file
24
Mods/Miracles/fossil_fuel_frenzy.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "Fossil Fuel Frenzy",
|
||||||
|
"faithCost": 2000,
|
||||||
|
"followersRequired": 2000,
|
||||||
|
"productionRequired": 500,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "ProductionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "CorruptionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "DestroySelf"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
19
Mods/Miracles/geological_survey.json
Normal file
19
Mods/Miracles/geological_survey.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Geological Survey",
|
||||||
|
"faithCost": 120,
|
||||||
|
"followersRequired": 500,
|
||||||
|
"productionRequired": 0,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Production",
|
||||||
|
"value": 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Corruption",
|
||||||
|
"value": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
Mods/Miracles/global_network.json
Normal file
13
Mods/Miracles/global_network.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "Global Network",
|
||||||
|
"faithCost": 4000,
|
||||||
|
"followersRequired": 5000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "UnlockMiracle",
|
||||||
|
"miraclesToUnlock": ["orbital_calculations", "construct_vessel_frame"]
|
||||||
|
},
|
||||||
|
{ "type": "DestroySelf" }
|
||||||
|
]
|
||||||
|
}
|
24
Mods/Miracles/globalization.json
Normal file
24
Mods/Miracles/globalization.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "Globalization",
|
||||||
|
"faithCost": 1200,
|
||||||
|
"followersRequired": 1500,
|
||||||
|
"productionRequired": 1000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "FaithPerFollower",
|
||||||
|
"op": "Multiply",
|
||||||
|
"value": 1.2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "CorruptionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "DestroySelf"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
Mods/Miracles/gods_endurance.json
Normal file
16
Mods/Miracles/gods_endurance.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "God's Endurance",
|
||||||
|
"faithCost": 100,
|
||||||
|
"followersRequired": 400,
|
||||||
|
"productionRequired": 0,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ApplyBuff",
|
||||||
|
"buffId": "gods_endurance",
|
||||||
|
"targetStat": "FaithPerFollower",
|
||||||
|
"multiplier": 1.5,
|
||||||
|
"duration": 30
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
Mods/Miracles/harness_the_sun.json
Normal file
16
Mods/Miracles/harness_the_sun.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "Harness the Sun",
|
||||||
|
"faithCost": 1200,
|
||||||
|
"followersRequired": 2500,
|
||||||
|
"productionRequired": 2000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ApplyBuff",
|
||||||
|
"buffId": "harness_the_sun",
|
||||||
|
"targetStat": "CorruptionPerSecond",
|
||||||
|
"multiplier": -1.0,
|
||||||
|
"duration": 60
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
20
Mods/Miracles/inspire_invention.json
Normal file
20
Mods/Miracles/inspire_invention.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "Inspire Invention",
|
||||||
|
"faithCost": 600,
|
||||||
|
"followersRequired": 1000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "ProductionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "CorruptionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 0.2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
12
Mods/Miracles/launch_ark.json
Normal file
12
Mods/Miracles/launch_ark.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "Launch Ark",
|
||||||
|
"faithCost": 25000,
|
||||||
|
"followersRequired": 5000,
|
||||||
|
"productionRequired": 10000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "Win"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
Mods/Miracles/orbital_calculations.json
Normal file
13
Mods/Miracles/orbital_calculations.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "Project: Trajectory",
|
||||||
|
"faithCost": 8000,
|
||||||
|
"followersRequired": 5000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "UnlockMiracle",
|
||||||
|
"miraclesToUnlock": [ "launch_ark" ]
|
||||||
|
},
|
||||||
|
{ "type": "DestroySelf" }
|
||||||
|
]
|
||||||
|
}
|
18
Mods/Miracles/organized_religion.json
Normal file
18
Mods/Miracles/organized_religion.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "Organized Religion",
|
||||||
|
"faithCost": 800,
|
||||||
|
"followersRequired": 1000,
|
||||||
|
"productionRequired": 500,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "FaithPerFollower",
|
||||||
|
"op": "Multiply",
|
||||||
|
"value": 1.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "DestroySelf"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
Mods/Miracles/prosperity_boom.json
Normal file
16
Mods/Miracles/prosperity_boom.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "Prosperity Boom",
|
||||||
|
"faithCost": 400,
|
||||||
|
"followersRequired": 1200,
|
||||||
|
"productionRequired": 800,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ApplyBuff",
|
||||||
|
"buffId": "prosperity_buff",
|
||||||
|
"targetStat": "FollowersPerSecond",
|
||||||
|
"multiplier": 2.0,
|
||||||
|
"duration": 20
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Purge Sins",
|
|
||||||
"faithCost": 100,
|
|
||||||
"followersRequired": 20,
|
|
||||||
"unlockedByDefault": true,
|
|
||||||
"effects": [
|
|
||||||
{
|
|
||||||
"type": "ConvertResource",
|
|
||||||
"fromResource": "Followers",
|
|
||||||
"fromAmount": 20,
|
|
||||||
"toResource": "Corruption",
|
|
||||||
"toAmount": -5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Refined Dogma",
|
|
||||||
"faithCost": 1000,
|
|
||||||
"followersRequired": 250,
|
|
||||||
"unlockedByDefault": true,
|
|
||||||
"effects": [
|
|
||||||
{
|
|
||||||
"type": "ModifyStat",
|
|
||||||
"targetStat": "FaithPerFollower",
|
|
||||||
"op": "Add",
|
|
||||||
"value": 0.1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
14
Mods/Miracles/ritual_of_cleansing.json
Normal file
14
Mods/Miracles/ritual_of_cleansing.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "Ritual of Cleansing",
|
||||||
|
"faithCost": 200,
|
||||||
|
"followersRequired": 200,
|
||||||
|
"productionRequired": 100,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Corruption",
|
||||||
|
"value": -3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
18
Mods/Miracles/sustainable_practices.json
Normal file
18
Mods/Miracles/sustainable_practices.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "Sustainable Practices",
|
||||||
|
"faithCost": 200,
|
||||||
|
"followersRequired": 300,
|
||||||
|
"productionRequired": 150,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "CorruptionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": -0.2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "DestroySelf"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
18
Mods/Miracles/tame_the_atom.json
Normal file
18
Mods/Miracles/tame_the_atom.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "Tame the Atom",
|
||||||
|
"faithCost": 3000,
|
||||||
|
"followersRequired": 3000,
|
||||||
|
"productionRequired": 4000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "CorruptionPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": -0.8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "DestroySelf"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Advanced Worship",
|
|
||||||
"faithCost": 500,
|
|
||||||
"unlockedByDefault": true,
|
|
||||||
"followersRequired": 100,
|
|
||||||
"effects": [
|
|
||||||
{
|
|
||||||
"type": "UnlockMiracle",
|
|
||||||
"miraclesToUnlock": [ "divine_sacrifice" ]
|
|
||||||
},
|
|
||||||
{ "type": "DestroySelf" }
|
|
||||||
]
|
|
||||||
}
|
|
31
Mods/Miracles/unlock_age_of_industry.json
Normal file
31
Mods/Miracles/unlock_age_of_industry.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "Age of Industry",
|
||||||
|
"faithCost": 300,
|
||||||
|
"followersRequired": 750,
|
||||||
|
"productionRequired": 50,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "UnlockMiracle",
|
||||||
|
"miraclesToUnlock": [
|
||||||
|
"inspire_invention",
|
||||||
|
"exploit_earth",
|
||||||
|
"fossil_fuel_frenzy",
|
||||||
|
"globalization",
|
||||||
|
"harness_the_sun",
|
||||||
|
"tame_the_atom",
|
||||||
|
"prosperity_boom",
|
||||||
|
"organized_religion",
|
||||||
|
"unlock_space_age"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "FollowersPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 0.75
|
||||||
|
},
|
||||||
|
{ "type": "DestroySelf" }
|
||||||
|
],
|
||||||
|
"advancesToAge": "The Industrial Age"
|
||||||
|
}
|
30
Mods/Miracles/unlock_settlement.json
Normal file
30
Mods/Miracles/unlock_settlement.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "Form Settlement",
|
||||||
|
"faithCost": 30,
|
||||||
|
"followersRequired": 150,
|
||||||
|
"unlockedByDefault": true,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "UnlockMiracle",
|
||||||
|
"miraclesToUnlock": [
|
||||||
|
"erect_shrine",
|
||||||
|
"communal_effort",
|
||||||
|
"sustainable_practices",
|
||||||
|
"ritual_of_cleansing",
|
||||||
|
"gods_endurance",
|
||||||
|
"geological_survey",
|
||||||
|
"divine_mandate",
|
||||||
|
"craftmenship",
|
||||||
|
"unlock_age_of_industry"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "FollowersPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 0.5
|
||||||
|
},
|
||||||
|
{ "type": "DestroySelf" }
|
||||||
|
],
|
||||||
|
"advancesToAge": "The Settlement Age"
|
||||||
|
}
|
21
Mods/Miracles/unlock_space_age.json
Normal file
21
Mods/Miracles/unlock_space_age.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "Age of Space",
|
||||||
|
"faithCost": 6000,
|
||||||
|
"followersRequired": 4000,
|
||||||
|
"productionRequired": 5000,
|
||||||
|
"unlockedByDefault": false,
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "UnlockMiracle",
|
||||||
|
"miraclesToUnlock": ["global_network", "orbital_calculations"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModifyStat",
|
||||||
|
"targetStat": "FollowersPerSecond",
|
||||||
|
"op": "Add",
|
||||||
|
"value": 1.0
|
||||||
|
},
|
||||||
|
{ "type": "DestroySelf" }
|
||||||
|
],
|
||||||
|
"advancesToAge": "The Space Age"
|
||||||
|
}
|
34
Mods/Tiers/follower_tiers.json
Normal file
34
Mods/Tiers/follower_tiers.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"tiers": [
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier1",
|
||||||
|
"threshold": 0,
|
||||||
|
"imagePath": "res://Sprites/Follower.png",
|
||||||
|
"scale": { "x": 0.1, "y": 0.1 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier2",
|
||||||
|
"threshold": 30,
|
||||||
|
"imagePath": "res://Sprites/follower_tier_2.png",
|
||||||
|
"scale": { "x": 0.1, "y": 0.1 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier3",
|
||||||
|
"threshold": 80,
|
||||||
|
"imagePath": "res://Sprites/follower_tier_3.png",
|
||||||
|
"scale": { "x": 0.1, "y": 0.1 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier4",
|
||||||
|
"threshold": 200,
|
||||||
|
"imagePath": "res://Sprites/follower_tier_4.png",
|
||||||
|
"scale": { "x": 0.1, "y": 0.1 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier5",
|
||||||
|
"threshold": 500,
|
||||||
|
"imagePath": "res://Sprites/follower_tier_5.png",
|
||||||
|
"scale": { "x": 0.1, "y": 0.1 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
64
Mods/Tiers/hut_tiers.json
Normal file
64
Mods/Tiers/hut_tiers.json
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"tiers": [
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier1",
|
||||||
|
"threshold": 20,
|
||||||
|
"imagePath": "res://Sprites/Hut.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier2",
|
||||||
|
"threshold": 60,
|
||||||
|
"imagePath": "res://Sprites/hut_tier_2.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier3",
|
||||||
|
"threshold": 120,
|
||||||
|
"imagePath": "res://Sprites/hut_tier_3.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier4",
|
||||||
|
"threshold": 250,
|
||||||
|
"imagePath": "res://Sprites/castle.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier5",
|
||||||
|
"threshold": 400,
|
||||||
|
"imagePath": "res://Sprites/house.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier6",
|
||||||
|
"threshold": 600,
|
||||||
|
"imagePath": "res://Sprites/house_tier_2.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier7",
|
||||||
|
"threshold": 1200,
|
||||||
|
"imagePath": "res://Sprites/house_tier_3.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier8",
|
||||||
|
"threshold": 2500,
|
||||||
|
"imagePath": "res://Sprites/Skyscraper.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier9",
|
||||||
|
"threshold": 3500,
|
||||||
|
"imagePath": "res://Sprites/skyscraper_tier_2.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier10",
|
||||||
|
"threshold": 5500,
|
||||||
|
"imagePath": "res://Sprites/skyscraper_tier_3.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
22
Mods/Tiers/temple_tiers.json
Normal file
22
Mods/Tiers/temple_tiers.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"tiers": [
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier1",
|
||||||
|
"threshold": 200,
|
||||||
|
"imagePath": "res://Sprites/Temple.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier2",
|
||||||
|
"threshold": 600,
|
||||||
|
"imagePath": "res://Sprites/temple_tier_2.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier3",
|
||||||
|
"threshold": 1200,
|
||||||
|
"imagePath": "res://Sprites/temple_tier_3.png",
|
||||||
|
"scale": { "x": 0.05, "y": 0.05 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -5,6 +5,7 @@
|
|||||||
<RootNamespace>parasiticgod</RootNamespace>
|
<RootNamespace>parasiticgod</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="LimboConsole.Sharp" Version="0.0.1-beta-008" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4-beta1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4-beta1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
182
README.md
Normal file
182
README.md
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
# Parasitic God
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Concept
|
||||||
|
|
||||||
|
You are a nascent god, tethered to a small tribe of followers on a vibrant, living world. Their worship is your lifeblood, their growth your only purpose. You grant them miracles, blessing them with bountiful harvests and inspiring great works.
|
||||||
|
|
||||||
|
But your power comes at a cost. Every miracle that nurtures your civilization also poisons the planet. The soil turns barren, the forests wither, and the sky darkens. You are their savior and their apocalypse.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Mission
|
||||||
|
|
||||||
|
Guide your people from a simple tribe to a star-faring civilization capable of escaping the dying world. Manage your resources **Faith**, **Followers**, and **Production** while trying to keep the planet's ever-rising **Corruption** at bay.
|
||||||
|
|
||||||
|
Unlock new ages of technology, build a network of cities, and perform the final, desperate miracle to launch your followers into the stars before you consume everything.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Exponential Growth**
|
||||||
|
Watch a handful of followers grow into a massive civilization with huts, cities, and procedural road networks.
|
||||||
|
|
||||||
|
- **A World That Reacts**
|
||||||
|
See the direct consequences of your actions as the vibrant globe fades to a corrupted wasteland and forests vanish based on your decisions.
|
||||||
|
|
||||||
|
- **Deeply Moddable**
|
||||||
|
The entire game—from miracles and their effects to the visual tiers of your civilization—is driven by simple JSON files. If you can edit a text file, you can mod this game.
|
||||||
|
|
||||||
|
- **Strategic Resource Management**
|
||||||
|
Balance the generation of multiple resources and make difficult choices. Will you sacrifice followers to purge corruption, or push for industrial growth at any cost?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Modding Your Universe
|
||||||
|
|
||||||
|
This game was built from the ground up to be modified. You can add new miracles, create random events, and even define new visual tiers for your civilization.
|
||||||
|
|
||||||
|
### Finding the Mods Folder
|
||||||
|
|
||||||
|
The game creates a `Mods` folder in its user data directory on first launch:
|
||||||
|
|
||||||
|
- **Windows:** `%APPDATA%\Godot\app_userdata\ParasiticGod\Mods\`
|
||||||
|
- **macOS:** `~/Library/Application Support/Godot/app_userdata/ParasiticGod/Mods/`
|
||||||
|
- **Linux:** `~/.local/share/godot/app_userdata/ParasiticGod/Mods/`
|
||||||
|
|
||||||
|
Inside, you'll find three folders: `Miracles`, `Tiers`, and `Events`.
|
||||||
|
The game also loads a set of base mods from its installation directory (`res://Mods`). Any files you place in the user folder will be added to or override the base game's content.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Creating a New Miracle
|
||||||
|
|
||||||
|
To add a new miracle, create a JSON file in `Mods/Miracles`.
|
||||||
|
The filename becomes its unique **ID** (e.g., `my_cool_miracle.json`):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "My Cool Miracle",
|
||||||
|
"faithCost": 100,
|
||||||
|
"followersRequired": 50,
|
||||||
|
"productionRequired": 0,
|
||||||
|
"unlockedByDefault": true,
|
||||||
|
"advancesToAge": "The Cool Age",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Faith",
|
||||||
|
"value": 200
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
````
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Creating a New Event
|
||||||
|
|
||||||
|
To add a new random event, create a JSON file in `Mods/Events`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "event_my_event",
|
||||||
|
"title": "A Thing Happened!",
|
||||||
|
"description": "Something unexpected occurred. What will you do?",
|
||||||
|
"meanTimeToHappen": 120,
|
||||||
|
"trigger": {
|
||||||
|
"minFollowers": 100,
|
||||||
|
"maxCorruption": 50
|
||||||
|
},
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"text": "Do the thing!",
|
||||||
|
"tooltip": "Gain 50 Production.",
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"type": "AddResource",
|
||||||
|
"targetResource": "Production",
|
||||||
|
"value": 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Modifying Visual Tiers
|
||||||
|
|
||||||
|
You can change the visual progression of followers, huts, and temples by editing the files in `Mods/Tiers`.
|
||||||
|
The format is a list of tiers, sorted by threshold:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tiers": [
|
||||||
|
{
|
||||||
|
"tierEnum": "Tier1",
|
||||||
|
"threshold": 0,
|
||||||
|
"imagePath": "user://Mods/Tiers/Huts/my_custom_hut.png",
|
||||||
|
"scale": { "x": 1.0, "y": 1.0 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* **tierEnum**: Must be one of `Tier1` through `Tier10`.
|
||||||
|
* **threshold**: The number of followers needed to unlock this visual.
|
||||||
|
* **imagePath**: The path to the image file. Use `user://` for mods or `res://` for base assets.
|
||||||
|
* **scale**: Optional X/Y scale multiplier for the image.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Available Effect Types
|
||||||
|
|
||||||
|
Both miracles and event options use this list of effects:
|
||||||
|
|
||||||
|
| Type | Description | Parameters |
|
||||||
|
| ------------------- | ----------------------------------- | ---------------------------------------------------------- |
|
||||||
|
| **AddResource** | Adds or subtracts from a core stat. | `targetResource` (Stat), `value` (number) |
|
||||||
|
| **ConvertResource** | Trades one resource for another. | `fromResource`, `fromAmount`, `toResource`, `toAmount` |
|
||||||
|
| **ModifyStat** | Permanently changes a passive stat. | `targetStat`, `op` ("Add" or "Multiply"), `value` |
|
||||||
|
| **ApplyBuff** | Applies a temporary multiplier. | `buffId`, `targetStat`, `multiplier`, `duration` (seconds) |
|
||||||
|
| **UnlockMiracle** | Unlocks other miracles. | `miraclesToUnlock` (list of IDs) |
|
||||||
|
| **DestroySelf** | Removes the miracle's button. | (No parameters) |
|
||||||
|
| **Win** | Triggers the game's win condition. | (No parameters) |
|
||||||
|
|
||||||
|
**Valid Stat Names:**
|
||||||
|
`Faith`, `Followers`, `Corruption`, `Production`, `ProductionPerSecond`, `CorruptionPerSecond`, `FollowersPerSecond`, `FaithPerFollower`, `ProductionPerFollower`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Stats
|
||||||
|
|
||||||
|
**Lines of Code:**
|
||||||
|

|
||||||
|
|
||||||
|
**Repo Activity:**
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is open source. See the [LICENSE](./LICENSE.txt) file for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
While the core code is complete for the jam, you can help by:
|
||||||
|
|
||||||
|
* Reporting bugs or balance issues.
|
||||||
|
* Creating cool new miracles and sharing them.
|
||||||
|
* Spreading the word!
|
@@ -1,9 +0,0 @@
|
|||||||
[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"
|
|
@@ -1,9 +0,0 @@
|
|||||||
[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"
|
|
@@ -1,9 +0,0 @@
|
|||||||
[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"
|
|
@@ -1,13 +0,0 @@
|
|||||||
[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"
|
|
@@ -1,12 +0,0 @@
|
|||||||
[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"
|
|
@@ -6,5 +6,5 @@
|
|||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_ei6wr")
|
script = ExtResource("1_ei6wr")
|
||||||
Scene = ExtResource("1_uho8r")
|
Scene = ExtResource("1_uho8r")
|
||||||
Threshold = 40000
|
Threshold = 100
|
||||||
metadata/_custom_type_script = "uid://c7hh0cy0yrdt8"
|
metadata/_custom_type_script = "uid://c7hh0cy0yrdt8"
|
||||||
|
@@ -6,5 +6,5 @@
|
|||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_vr1nw")
|
script = ExtResource("2_vr1nw")
|
||||||
Scene = ExtResource("1_trlm4")
|
Scene = ExtResource("1_trlm4")
|
||||||
Threshold = 600000
|
Threshold = 400
|
||||||
metadata/_custom_type_script = "uid://c7hh0cy0yrdt8"
|
metadata/_custom_type_script = "uid://c7hh0cy0yrdt8"
|
||||||
|
@@ -6,5 +6,5 @@
|
|||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_74x2g")
|
script = ExtResource("2_74x2g")
|
||||||
Scene = ExtResource("1_ex2nw")
|
Scene = ExtResource("1_ex2nw")
|
||||||
Threshold = 1200000
|
Threshold = 1000
|
||||||
metadata/_custom_type_script = "uid://c7hh0cy0yrdt8"
|
metadata/_custom_type_script = "uid://c7hh0cy0yrdt8"
|
||||||
|
7
Scenes/Castles/castle_tier_1.tscn
Normal file
7
Scenes/Castles/castle_tier_1.tscn
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://c2baysanqtp8g"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c46t8kj1gb5qd" path="res://Sprites/castle.png" id="1_42k1r"]
|
||||||
|
|
||||||
|
[node name="CastleTier1" type="Sprite2D"]
|
||||||
|
scale = Vector2(0.03, 0.03)
|
||||||
|
texture = ExtResource("1_42k1r")
|
7
Scenes/Houses/house_tier_1.tscn
Normal file
7
Scenes/Houses/house_tier_1.tscn
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cg5mdwkf7fxqn"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c61h7a8byuyeu" path="res://Sprites/house.png" id="1_ub3ef"]
|
||||||
|
|
||||||
|
[node name="HouseTier1" type="Sprite2D"]
|
||||||
|
scale = Vector2(0.02, 0.02)
|
||||||
|
texture = ExtResource("1_ub3ef")
|
11
Scenes/Houses/house_tier_2.tscn
Normal file
11
Scenes/Houses/house_tier_2.tscn
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://bi6053qjm60vt"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c61h7a8byuyeu" path="res://Sprites/house.png" id="1_8opcd"]
|
||||||
|
|
||||||
|
[node name="HouseTier2" type="Sprite2D"]
|
||||||
|
scale = Vector2(0.02, 0.02)
|
||||||
|
texture = ExtResource("1_8opcd")
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
|
position = Vector2(450, 0)
|
||||||
|
texture = ExtResource("1_8opcd")
|
15
Scenes/Houses/house_tier_3.tscn
Normal file
15
Scenes/Houses/house_tier_3.tscn
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://ctqgx6alvxci0"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c61h7a8byuyeu" path="res://Sprites/house.png" id="1_rp41l"]
|
||||||
|
|
||||||
|
[node name="HouseTier2" type="Sprite2D"]
|
||||||
|
scale = Vector2(0.02, 0.02)
|
||||||
|
texture = ExtResource("1_rp41l")
|
||||||
|
|
||||||
|
[node name="Sprite2D2" type="Sprite2D" parent="."]
|
||||||
|
position = Vector2(-550, 0)
|
||||||
|
texture = ExtResource("1_rp41l")
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
|
position = Vector2(450, 0)
|
||||||
|
texture = ExtResource("1_rp41l")
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
[node name="HutTier2" type="Node2D"]
|
[node name="HutTier2" type="Node2D"]
|
||||||
script = ExtResource("1_22ax8")
|
script = ExtResource("1_22ax8")
|
||||||
|
Tier = 1
|
||||||
metadata/_custom_type_script = "uid://cj5libcgnhjml"
|
metadata/_custom_type_script = "uid://cj5libcgnhjml"
|
||||||
|
|
||||||
[node name="Hut" type="Sprite2D" parent="."]
|
[node name="Hut" type="Sprite2D" parent="."]
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
[node name="HutTier3" type="Node2D"]
|
[node name="HutTier3" type="Node2D"]
|
||||||
script = ExtResource("1_ltla2")
|
script = ExtResource("1_ltla2")
|
||||||
|
Tier = 2
|
||||||
metadata/_custom_type_script = "uid://cj5libcgnhjml"
|
metadata/_custom_type_script = "uid://cj5libcgnhjml"
|
||||||
|
|
||||||
[node name="Hut" type="Sprite2D" parent="."]
|
[node name="Hut" type="Sprite2D" parent="."]
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,8 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Godot;
|
using Godot;
|
||||||
using ParasiticGod.Scripts.Core;
|
using ParasiticGod.Scripts.Core;
|
||||||
|
using ParasiticGod.Scripts.Core.Effects;
|
||||||
using ParasiticGod.Scripts.Singletons;
|
using ParasiticGod.Scripts.Singletons;
|
||||||
|
|
||||||
namespace ParasiticGod.Scenes.Main;
|
namespace ParasiticGod.Scenes.Main;
|
||||||
@@ -7,6 +10,7 @@ namespace ParasiticGod.Scenes.Main;
|
|||||||
public partial class MiracleButton : Button
|
public partial class MiracleButton : Button
|
||||||
{
|
{
|
||||||
private MiracleDefinition _miracle;
|
private MiracleDefinition _miracle;
|
||||||
|
[Export] private AudioStreamPlayer _sfx;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
@@ -20,41 +24,142 @@ public partial class MiracleButton : Button
|
|||||||
Text = BuildText();
|
Text = BuildText();
|
||||||
TooltipText = BuildTooltipText();
|
TooltipText = BuildTooltipText();
|
||||||
|
|
||||||
|
if (_sfx == null)
|
||||||
|
{
|
||||||
|
_sfx = GetNodeOrNull<AudioStreamPlayer>("SFX");
|
||||||
|
}
|
||||||
|
|
||||||
Pressed += OnPressed;
|
Pressed += OnPressed;
|
||||||
|
|
||||||
|
GameBus.Instance.StateChanged += UpdateAvailability;
|
||||||
|
UpdateAvailability(GameBus.Instance.CurrentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ExitTree()
|
public override void _ExitTree()
|
||||||
{
|
{
|
||||||
Pressed -= OnPressed;
|
Pressed -= OnPressed;
|
||||||
|
|
||||||
|
if (GameBus.Instance != null)
|
||||||
|
{
|
||||||
|
GameBus.Instance.StateChanged -= UpdateAvailability;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPressed()
|
private void OnPressed()
|
||||||
{
|
{
|
||||||
|
_sfx?.Play();
|
||||||
GameBus.Instance.PerformMiracle(_miracle);
|
GameBus.Instance.PerformMiracle(_miracle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetMiracle(MiracleDefinition miracle)
|
public void SetMiracle(MiracleDefinition miracle)
|
||||||
{
|
{
|
||||||
_miracle = miracle;
|
_miracle = miracle;
|
||||||
Text = BuildText();
|
|
||||||
TooltipText = BuildTooltipText();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MiracleDefinition GetMiracle() { return _miracle; }
|
public MiracleDefinition GetMiracle() { return _miracle; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks the miracle's requirements against the current game state
|
||||||
|
/// and updates the button's disabled status and tooltip.
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateAvailability(GameState state)
|
||||||
|
{
|
||||||
|
if (_miracle == null) return;
|
||||||
|
|
||||||
|
var missingRequirements = new List<string>();
|
||||||
|
|
||||||
|
if (state.Get(Stat.Faith) < _miracle.FaithCost)
|
||||||
|
{
|
||||||
|
missingRequirements.Add($"Not enough Faith ({state.Get(Stat.Faith):F0} / {_miracle.FaithCost})");
|
||||||
|
}
|
||||||
|
if (state.Get(Stat.Followers) < _miracle.FollowersRequired)
|
||||||
|
{
|
||||||
|
missingRequirements.Add($"Not enough Followers ({(long)state.Get(Stat.Followers)} / {_miracle.FollowersRequired})");
|
||||||
|
}
|
||||||
|
if (state.Get(Stat.Production) < _miracle.ProductionRequired)
|
||||||
|
{
|
||||||
|
missingRequirements.Add($"Not enough Production ({state.Get(Stat.Production):F0} / {_miracle.ProductionRequired})");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AreAllUnlocksAlreadyPresent(state))
|
||||||
|
{
|
||||||
|
missingRequirements.Add("Already unlocked subsequent powers.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsBuffAlreadyActive(state))
|
||||||
|
{
|
||||||
|
missingRequirements.Add("This buff is already active.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingRequirements.Any())
|
||||||
|
{
|
||||||
|
Disabled = true;
|
||||||
|
TooltipText = string.Join("\n", missingRequirements);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Disabled = false;
|
||||||
|
TooltipText = BuildTooltipText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string BuildText()
|
private string BuildText()
|
||||||
{
|
{
|
||||||
return $"{_miracle.Name}\nCost: {_miracle.FaithCost} Faith";
|
string costText;
|
||||||
|
if (_miracle.ProductionRequired > 0 && _miracle.FaithCost <= 0)
|
||||||
|
{
|
||||||
|
costText = $"Cost: {_miracle.ProductionRequired:F0} Prod";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
costText = $"Cost: {_miracle.FaithCost:F0} Faith";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{_miracle.Name}\n{costText}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildTooltipText()
|
private string BuildTooltipText()
|
||||||
{
|
{
|
||||||
var tooltip = $"Cost: {_miracle.FaithCost} Faith\nRequires: {_miracle.FollowersRequired} Followers\nEffects:\n";
|
var tooltip = "";
|
||||||
|
|
||||||
|
if (_miracle.FaithCost > 0)
|
||||||
|
tooltip += $"Cost: {_miracle.FaithCost:F0} Faith\n";
|
||||||
|
if (_miracle.ProductionRequired > 0)
|
||||||
|
tooltip += $"Cost: {_miracle.ProductionRequired:F0} Production\n";
|
||||||
|
if (_miracle.FollowersRequired > 0)
|
||||||
|
tooltip += $"Requires: {_miracle.FollowersRequired} Followers\n";
|
||||||
|
|
||||||
|
tooltip += "\nEffects:\n";
|
||||||
|
|
||||||
foreach (var effect in _miracle.Effects)
|
foreach (var effect in _miracle.Effects)
|
||||||
{
|
{
|
||||||
if (effect.ToString() == string.Empty) continue;
|
if (string.IsNullOrEmpty(effect.ToString())) continue;
|
||||||
tooltip += $"- {effect}\n";
|
tooltip += $"- {effect}\n";
|
||||||
}
|
}
|
||||||
return tooltip.TrimEnd();
|
return tooltip.TrimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool AreAllUnlocksAlreadyPresent(GameState state)
|
||||||
|
{
|
||||||
|
var unlockEffect = _miracle.Effects.OfType<UnlockMiracleEffect>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (unlockEffect == null || unlockEffect.MiraclesToUnlock.Count == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return unlockEffect.MiraclesToUnlock.All(state.IsMiracleUnlocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsBuffAlreadyActive(GameState state)
|
||||||
|
{
|
||||||
|
var buffEffect = _miracle.Effects.OfType<ApplyBuffEffect>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (buffEffect == null || string.IsNullOrEmpty(buffEffect.BuffId))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.IsBuffActive(buffEffect.BuffId);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -27,6 +27,7 @@ public partial class MiraclePanel : GridContainer
|
|||||||
{
|
{
|
||||||
if (miracle.UnlockedByDefault)
|
if (miracle.UnlockedByDefault)
|
||||||
{
|
{
|
||||||
|
GameBus.Instance.CurrentState.AddUnlockedMiracle(miracle.Id);
|
||||||
AddButtonForMiracle(miracle);
|
AddButtonForMiracle(miracle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
Scenes/TempleMarker.tscn
Normal file
14
Scenes/TempleMarker.tscn
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://wysxqe44rxhf"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://djaf0gv8s7qib" path="res://Scripts/FollowerMarker.cs" id="1_x8f1l"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dcs48aa84w21u" path="res://icon.svg" id="2_tc18m"]
|
||||||
|
|
||||||
|
[node name="HutMarker" type="Marker2D"]
|
||||||
|
script = ExtResource("1_x8f1l")
|
||||||
|
metadata/_custom_type_script = "uid://djaf0gv8s7qib"
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
|
visible = false
|
||||||
|
modulate = Color(0.406241, 0.161792, 0.609211, 1)
|
||||||
|
scale = Vector2(0.235, 0.235)
|
||||||
|
texture = ExtResource("2_tc18m")
|
10
Scenes/UI/buff_button.tscn
Normal file
10
Scenes/UI/buff_button.tscn
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://b417dl07c13uc"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://chnf0t5xdosys" path="res://Scripts/ActiveBuffUi.cs" id="1_7ujuu"]
|
||||||
|
|
||||||
|
[node name="BuffButton" type="Button"]
|
||||||
|
focus_mode = 0
|
||||||
|
disabled = true
|
||||||
|
button_mask = 0
|
||||||
|
text = "Effect"
|
||||||
|
script = ExtResource("1_7ujuu")
|
8
Scenes/UI/event_option_button.tscn
Normal file
8
Scenes/UI/event_option_button.tscn
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[gd_scene format=3 uid="uid://b2o5rufqn8dpf"]
|
||||||
|
|
||||||
|
[node name="EventOptionButton" type="Button"]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
37
Scenes/UI/event_popup.tscn
Normal file
37
Scenes/UI/event_popup.tscn
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://gdejd44km3co"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://h1x5eqt0lc5m" path="res://Scripts/UI/EventPopup.cs" id="1_lkb7n"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://b2o5rufqn8dpf" path="res://Scenes/UI/event_option_button.tscn" id="2_gk0qx"]
|
||||||
|
|
||||||
|
[node name="EventPopup" type="PanelContainer" node_paths=PackedStringArray("_titleLabel", "_descriptionLabel", "_optionsContainer")]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_lkb7n")
|
||||||
|
_titleLabel = NodePath("VBoxContainer/Title")
|
||||||
|
_descriptionLabel = NodePath("VBoxContainer/Description")
|
||||||
|
_optionsContainer = NodePath("VBoxContainer/OptionButtons")
|
||||||
|
_optionButtonScene = ExtResource("2_gk0qx")
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
size_flags_vertical = 4
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="Title" type="Label" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 6
|
||||||
|
text = "TITLE"
|
||||||
|
|
||||||
|
[node name="Description" type="RichTextLabel" parent="VBoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(320, 128)
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
fit_content = true
|
||||||
|
|
||||||
|
[node name="OptionButtons" type="VBoxContainer" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
@@ -1,9 +1,13 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://rj1fsdlhju5y"]
|
[gd_scene load_steps=3 format=3 uid="uid://rj1fsdlhju5y"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://ctjmwgucwh3le" path="res://Scenes/Main/MiracleButton.cs" id="1_sxcu0"]
|
[ext_resource type="Script" uid="uid://ctjmwgucwh3le" path="res://Scenes/Main/MiracleButton.cs" id="1_sxcu0"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://c2kkfl2nv5rlh" path="res://Sfx/UI_SFX_Pack_61_22.wav" id="2_bjlki"]
|
||||||
|
|
||||||
[node name="MiracleButton" type="Button"]
|
[node name="MiracleButton" type="Button"]
|
||||||
custom_minimum_size = Vector2(128, 64)
|
custom_minimum_size = Vector2(128, 64)
|
||||||
offset_right = 8.0
|
offset_right = 8.0
|
||||||
offset_bottom = 8.0
|
offset_bottom = 8.0
|
||||||
script = ExtResource("1_sxcu0")
|
script = ExtResource("1_sxcu0")
|
||||||
|
|
||||||
|
[node name="SFX" type="AudioStreamPlayer" parent="."]
|
||||||
|
stream = ExtResource("2_bjlki")
|
42
Scenes/UI/notification_label.tscn
Normal file
42
Scenes/UI/notification_label.tscn
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://crpf0llofg0sc"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://drx8lqcjq5khj" path="res://Scripts/NotificationLabel.cs" id="1_x4sn4"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_4bx8n"]
|
||||||
|
bg_color = Color(0.187176, 0.187176, 0.187176, 1)
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(1, 0.759215, 0.00113704, 1)
|
||||||
|
corner_radius_top_left = 2
|
||||||
|
corner_radius_top_right = 2
|
||||||
|
corner_radius_bottom_right = 2
|
||||||
|
corner_radius_bottom_left = 2
|
||||||
|
|
||||||
|
[node name="NotificationLabel" type="Label"]
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -20.0
|
||||||
|
offset_top = -11.5
|
||||||
|
offset_right = 20.0
|
||||||
|
offset_bottom = 11.5
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
script = ExtResource("1_x4sn4")
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
z_index = -1
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_4bx8n")
|
||||||
|
metadata/_edit_group_ = true
|
57
Scenes/game_over.tscn
Normal file
57
Scenes/game_over.tscn
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
[gd_scene load_steps=6 format=3 uid="uid://kcla4knp80mq"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://cbdokimy0qarg" path="res://Scripts/MainMenu.cs" id="1_8fo1c"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cmhvni5njpmee" path="res://Scenes/main_menu.tscn" id="2_ek8ke"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://defdxbv24q6l1" path="res://Sfx/The Hollow Throne.mp3" id="3_ek8ke"]
|
||||||
|
[ext_resource type="Script" uid="uid://bif3eyfa1lgl4" path="res://Scripts/DisableMainThemeMusic.cs" id="4_eoghk"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_i2yjh"]
|
||||||
|
bg_color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
|
[node name="Game Over" type="CanvasLayer" node_paths=PackedStringArray("_startButton")]
|
||||||
|
script = ExtResource("1_8fo1c")
|
||||||
|
_gameScene = ExtResource("2_ek8ke")
|
||||||
|
_startButton = NodePath("CenterContainer/VBoxContainer/Quit")
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_i2yjh")
|
||||||
|
|
||||||
|
[node name="CenterContainer" type="CenterContainer" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="RichTextLabel" type="RichTextLabel" parent="CenterContainer/VBoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(640, 360)
|
||||||
|
layout_mode = 2
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = "By your hand, this creation has been [color=#B22222][b]unmade[/b][/color].
|
||||||
|
Your followers, who offered you their very souls, have [color=#B22222][b]perished[/b][/color].
|
||||||
|
You have [color=#B22222][b]failed[/b][/color] your sacred charge. You are an [color=#B22222][b]abomination[/b][/color] to your brethren."
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[node name="Quit" type="Button" parent="CenterContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Quit"
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
|
||||||
|
stream = ExtResource("3_ek8ke")
|
||||||
|
volume_db = -3.0
|
||||||
|
autoplay = true
|
||||||
|
parameters/looping = true
|
||||||
|
|
||||||
|
[node name="Node" type="Node" parent="."]
|
||||||
|
script = ExtResource("4_eoghk")
|
71
Scenes/main_menu.tscn
Normal file
71
Scenes/main_menu.tscn
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
[gd_scene load_steps=7 format=3 uid="uid://cmhvni5njpmee"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://cbdokimy0qarg" path="res://Scripts/MainMenu.cs" id="1_1ehe0"]
|
||||||
|
[ext_resource type="FontFile" uid="uid://wofoiaejxgsp" path="res://Fonts/Playful Boxes.otf" id="1_28flt"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://d2wi2cs20q2b6" path="res://Parasitic_God.png" id="1_48xlc"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://kvpk5wrcp3rv" path="res://Scenes/tutorial_scene.tscn" id="2_ce3w2"]
|
||||||
|
[ext_resource type="Script" uid="uid://dvmrpbba7plsf" path="res://Scripts/EnableMainThemeMusic.cs" id="5_n45e2"]
|
||||||
|
|
||||||
|
[sub_resource type="LabelSettings" id="LabelSettings_48xlc"]
|
||||||
|
font = ExtResource("1_28flt")
|
||||||
|
font_size = 72
|
||||||
|
outline_size = 8
|
||||||
|
outline_color = Color(0.48, 0.408, 0, 1)
|
||||||
|
|
||||||
|
[node name="MainMenu" type="CanvasLayer" node_paths=PackedStringArray("_startButton", "_quitButton")]
|
||||||
|
script = ExtResource("1_1ehe0")
|
||||||
|
_gameScene = ExtResource("2_ce3w2")
|
||||||
|
_startButton = NodePath("CenterContainer/VBoxContainer/Play")
|
||||||
|
_quitButton = NodePath("CenterContainer/VBoxContainer/Exit")
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="."]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="Control"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
size_flags_vertical = 4
|
||||||
|
texture = ExtResource("1_48xlc")
|
||||||
|
expand_mode = 2
|
||||||
|
stretch_mode = 5
|
||||||
|
|
||||||
|
[node name="CenterContainer" type="CenterContainer" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Title" type="Label" parent="CenterContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 0
|
||||||
|
size_flags_stretch_ratio = 0.0
|
||||||
|
text = "PARASITIC GOD"
|
||||||
|
label_settings = SubResource("LabelSettings_48xlc")
|
||||||
|
|
||||||
|
[node name="Play" type="Button" parent="CenterContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_stretch_ratio = 0.0
|
||||||
|
theme_override_font_sizes/font_size = 30
|
||||||
|
text = "Play"
|
||||||
|
|
||||||
|
[node name="Exit" type="Button" parent="CenterContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_font_sizes/font_size = 30
|
||||||
|
text = "Exit"
|
||||||
|
|
||||||
|
[node name="Node" type="Node" parent="."]
|
||||||
|
script = ExtResource("5_n45e2")
|
10
Scenes/main_theme_music.tscn
Normal file
10
Scenes/main_theme_music.tscn
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://b7we8gtene47t"]
|
||||||
|
|
||||||
|
[ext_resource type="AudioStream" uid="uid://wm3vocs0kkk8" path="res://Sfx/MainTheme.mp3" id="1_f0c52"]
|
||||||
|
|
||||||
|
[node name="MainThemeMusic" type="AudioStreamPlayer"]
|
||||||
|
process_mode = 3
|
||||||
|
stream = ExtResource("1_f0c52")
|
||||||
|
volume_db = -5.0
|
||||||
|
autoplay = true
|
||||||
|
parameters/looping = true
|
9
Scenes/moddable_visual.tscn
Normal file
9
Scenes/moddable_visual.tscn
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://xk2xirjd1sma"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dpfcbaqgq3l6d" path="res://Scripts/Components/ModdableVisual.cs" id="1_5b1dg"]
|
||||||
|
|
||||||
|
[node name="ModdableVisual" type="Node2D" node_paths=PackedStringArray("_sprite")]
|
||||||
|
script = ExtResource("1_5b1dg")
|
||||||
|
_sprite = NodePath("Sprite")
|
||||||
|
|
||||||
|
[node name="Sprite" type="Sprite2D" parent="."]
|
7
Scenes/tree.tscn
Normal file
7
Scenes/tree.tscn
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://8w7tvsgkev1y"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cemch3556ibiy" path="res://Sprites/Tree.png" id="1_0vwjc"]
|
||||||
|
|
||||||
|
[node name="Tree" type="Sprite2D"]
|
||||||
|
scale = Vector2(0.01, 0.01)
|
||||||
|
texture = ExtResource("1_0vwjc")
|
26
Scenes/tutorial_scene.tscn
Normal file
26
Scenes/tutorial_scene.tscn
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://kvpk5wrcp3rv"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://d08d3pi7sx8k3" path="res://Scripts/UI/TutorialScene.cs" id="1_epmsy"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bfil8sd154327" path="res://Scenes/Main/Main.tscn" id="2_mw53g"]
|
||||||
|
[ext_resource type="Resource" uid="uid://dxgpvgx7axp88" path="res://Dialogue/tutorial.dialogue" id="3_oaf0i"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dg6ac3jb1366r" path="res://Sprites/globe.svg" id="4_7u0dx"]
|
||||||
|
|
||||||
|
[node name="TutorialScene" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_epmsy")
|
||||||
|
_mainGameScene = ExtResource("2_mw53g")
|
||||||
|
_tutorialDialogue = ExtResource("3_oaf0i")
|
||||||
|
|
||||||
|
[node name="World" type="TextureRect" parent="."]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = 195.0
|
||||||
|
offset_top = -98.0
|
||||||
|
offset_right = 915.0
|
||||||
|
offset_bottom = 732.0
|
||||||
|
texture = ExtResource("4_7u0dx")
|
||||||
|
expand_mode = 4
|
56
Scenes/win_screen.tscn
Normal file
56
Scenes/win_screen.tscn
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
[gd_scene load_steps=6 format=3 uid="uid://dtuyx1f5fa8sy"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://cbdokimy0qarg" path="res://Scripts/MainMenu.cs" id="1_a00f1"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cmhvni5njpmee" path="res://Scenes/main_menu.tscn" id="2_awi1s"]
|
||||||
|
[ext_resource type="AudioStream" uid="uid://46kqkf4ckqek" path="res://Sfx/Ascend Beyond.mp3" id="3_awi1s"]
|
||||||
|
[ext_resource type="Script" uid="uid://bif3eyfa1lgl4" path="res://Scripts/DisableMainThemeMusic.cs" id="4_bwc64"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_i2yjh"]
|
||||||
|
bg_color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
|
[node name="Game Over" type="CanvasLayer" node_paths=PackedStringArray("_startButton")]
|
||||||
|
script = ExtResource("1_a00f1")
|
||||||
|
_gameScene = ExtResource("2_awi1s")
|
||||||
|
_startButton = NodePath("CenterContainer/VBoxContainer/Quit")
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_i2yjh")
|
||||||
|
|
||||||
|
[node name="CenterContainer" type="CenterContainer" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="RichTextLabel" type="RichTextLabel" parent="CenterContainer/VBoxContainer"]
|
||||||
|
custom_minimum_size = Vector2(640, 360)
|
||||||
|
layout_mode = 2
|
||||||
|
bbcode_enabled = true
|
||||||
|
text = "Through Your divine guidance, your followers have [color=gold][b]ascended to the stars[/b][/color].
|
||||||
|
They now traverse the cosmos, settling new worlds in Your name and spreading word of Your glory.
|
||||||
|
[color=gold][b]Congratulations[/b][/color], you have proven yourself a [color=gold][b]True God[/b][/color], a creator, not a parasite."
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[node name="Quit" type="Button" parent="CenterContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Quit"
|
||||||
|
flat = true
|
||||||
|
|
||||||
|
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
|
||||||
|
stream = ExtResource("3_awi1s")
|
||||||
|
volume_db = -3.0
|
||||||
|
autoplay = true
|
||||||
|
parameters/looping = true
|
||||||
|
|
||||||
|
[node name="Node" type="Node" parent="."]
|
||||||
|
script = ExtResource("4_bwc64")
|
31
Scripts/ActiveBuffUi.cs
Normal file
31
Scripts/ActiveBuffUi.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using Godot;
|
||||||
|
using ParasiticGod.Scripts.Core.Effects;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class ActiveBuffUi : Button
|
||||||
|
{
|
||||||
|
private Buff _buff;
|
||||||
|
|
||||||
|
public void SetBuff(Buff buff)
|
||||||
|
{
|
||||||
|
_buff = buff;
|
||||||
|
Disabled = true;
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Process(double delta)
|
||||||
|
{
|
||||||
|
if (_buff != null)
|
||||||
|
{
|
||||||
|
UpdateDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDisplay()
|
||||||
|
{
|
||||||
|
Text = _buff.Name;
|
||||||
|
TooltipText = $"x{_buff.Multiplier:F1} to {_buff.Name.Split(' ')[0]}\n{_buff.Duration:F0}s remaining";
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/ActiveBuffUi.cs.uid
Normal file
1
Scripts/ActiveBuffUi.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://chnf0t5xdosys
|
49
Scripts/Components/ActiveBuffsManager.cs
Normal file
49
Scripts/Components/ActiveBuffsManager.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Godot;
|
||||||
|
using ParasiticGod.Scripts.Core.Effects;
|
||||||
|
using ParasiticGod.Scripts.Singletons;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts.Components;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class ActiveBuffsManager : Node
|
||||||
|
{
|
||||||
|
[Export] private PackedScene _activeBuffScene;
|
||||||
|
[Export] private AudioStreamPlayer _buffRemovedSfx;
|
||||||
|
[Export] private AudioStreamPlayer _buffAddedSfx;
|
||||||
|
|
||||||
|
private readonly Dictionary<Guid, ActiveBuffUi> _activeBuffUis = new();
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
GameBus.Instance.BuffAdded += OnBuffAdded;
|
||||||
|
GameBus.Instance.BuffRemoved += OnBuffRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (GameBus.Instance == null) return;
|
||||||
|
GameBus.Instance.BuffAdded -= OnBuffAdded;
|
||||||
|
GameBus.Instance.BuffRemoved -= OnBuffRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBuffAdded(Buff buff)
|
||||||
|
{
|
||||||
|
var buffInstance = _activeBuffScene.Instantiate<ActiveBuffUi>();
|
||||||
|
AddChild(buffInstance);
|
||||||
|
buffInstance.SetBuff(buff);
|
||||||
|
_activeBuffUis.Add(buff.InstanceId, buffInstance);
|
||||||
|
_buffAddedSfx?.Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBuffRemoved(Buff buff)
|
||||||
|
{
|
||||||
|
if (_activeBuffUis.TryGetValue(buff.InstanceId, out var buffUi))
|
||||||
|
{
|
||||||
|
buffUi.QueueFree();
|
||||||
|
_activeBuffUis.Remove(buff.InstanceId);
|
||||||
|
_buffRemovedSfx?.Play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/Components/ActiveBuffsManager.cs.uid
Normal file
1
Scripts/Components/ActiveBuffsManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://ddshg236tlltt
|
73
Scripts/Components/EventManager.cs
Normal file
73
Scripts/Components/EventManager.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Godot;
|
||||||
|
using Limbo.Console.Sharp;
|
||||||
|
using ParasiticGod.Scripts.Core;
|
||||||
|
using ParasiticGod.Scripts.Singletons;
|
||||||
|
using ParasiticGod.Scripts.UI;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts.Components;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class EventManager : Node
|
||||||
|
{
|
||||||
|
[Export] private double _checkInterval = 5.0;
|
||||||
|
[Export] private PackedScene _eventPopupScene;
|
||||||
|
[Export] private Container _eventPopupContainer;
|
||||||
|
|
||||||
|
private List<EventDefinition> _allEvents;
|
||||||
|
private Timer _timer;
|
||||||
|
private RandomNumberGenerator _rng = new();
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
RegisterConsoleCommands();
|
||||||
|
_allEvents = GameBus.Instance.AllEvents;
|
||||||
|
|
||||||
|
_timer = new Timer { WaitTime = _checkInterval, Autostart = true };
|
||||||
|
AddChild(_timer);
|
||||||
|
_timer.Timeout += OnCheckEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCheckEvents()
|
||||||
|
{
|
||||||
|
if (GetTree().Paused) return;
|
||||||
|
|
||||||
|
var state = GameBus.Instance.CurrentState;
|
||||||
|
|
||||||
|
foreach (var ev in _allEvents)
|
||||||
|
{
|
||||||
|
if (state.Get(Stat.Followers) < ev.Trigger.MinFollowers) continue;
|
||||||
|
if (state.Get(Stat.Corruption) > ev.Trigger.MaxCorruption) continue;
|
||||||
|
|
||||||
|
var probability = _checkInterval / ev.MeanTimeToHappen;
|
||||||
|
if (_rng.Randf() < probability)
|
||||||
|
{
|
||||||
|
FireEvent(ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireEvent(EventDefinition eventDef)
|
||||||
|
{
|
||||||
|
GameBus.Instance.SetPause(true);
|
||||||
|
|
||||||
|
var popup = _eventPopupScene.Instantiate<EventPopup>();
|
||||||
|
_eventPopupContainer.AddChild(popup);
|
||||||
|
popup.DisplayEvent(eventDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConsoleCommand("trigger_event", "Triggers an event by its ID for testing purposes.")]
|
||||||
|
private void TriggerEventCommand(string eventId)
|
||||||
|
{
|
||||||
|
var eventDef = _allEvents.Find(e => e.Id == eventId);
|
||||||
|
if (eventDef != null)
|
||||||
|
{
|
||||||
|
FireEvent(eventDef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GD.PushError($"No event found with ID: {eventId}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/Components/EventManager.cs.uid
Normal file
1
Scripts/Components/EventManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://2ipbgwlx1ld1
|
74
Scripts/Components/ForestVisualizer.cs
Normal file
74
Scripts/Components/ForestVisualizer.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Godot;
|
||||||
|
using ParasiticGod.Scripts.Core;
|
||||||
|
using ParasiticGod.Scripts.Singletons;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts.Components;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class ForestVisualizer : Node
|
||||||
|
{
|
||||||
|
[Export] private Node2D _treesContainer;
|
||||||
|
|
||||||
|
private List<Node2D> _trees = [];
|
||||||
|
private int _lastKnownTreesToShow = -1;
|
||||||
|
private bool _isUpdating = false;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
foreach (var child in _treesContainer.GetChildren())
|
||||||
|
{
|
||||||
|
if (child is Node2D tree)
|
||||||
|
{
|
||||||
|
_trees.Add(tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rng = new RandomNumberGenerator();
|
||||||
|
rng.Randomize();
|
||||||
|
_trees = _trees.OrderBy(_ => Guid.NewGuid()).ToList();
|
||||||
|
|
||||||
|
GameBus.Instance.StateChanged += OnStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
GameBus.Instance.StateChanged -= OnStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStateChanged(GameState newState)
|
||||||
|
{
|
||||||
|
if (_isUpdating) return;
|
||||||
|
|
||||||
|
var corruptionRatio = newState.Get(Stat.Corruption) / 100.0;
|
||||||
|
var treesToShow = (int)(_trees.Count * (1.0 - corruptionRatio));
|
||||||
|
|
||||||
|
if (treesToShow != _lastKnownTreesToShow)
|
||||||
|
{
|
||||||
|
UpdateForestProgressively(treesToShow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void UpdateForestProgressively(int treesToShow)
|
||||||
|
{
|
||||||
|
_isUpdating = true;
|
||||||
|
|
||||||
|
for (var i = 0; i < _trees.Count; i++)
|
||||||
|
{
|
||||||
|
var tree = _trees[i];
|
||||||
|
var shouldBeVisible = i < treesToShow;
|
||||||
|
var needsChange = tree.Visible != shouldBeVisible;
|
||||||
|
|
||||||
|
if (needsChange)
|
||||||
|
{
|
||||||
|
tree.Visible = shouldBeVisible;
|
||||||
|
await ToSignal(GetTree().CreateTimer(0.01f), SceneTreeTimer.SignalName.Timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastKnownTreesToShow = treesToShow;
|
||||||
|
_isUpdating = false;
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/Components/ForestVisualizer.cs.uid
Normal file
1
Scripts/Components/ForestVisualizer.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://furbvcmw31bx
|
28
Scripts/Components/ModdableVisual.cs
Normal file
28
Scripts/Components/ModdableVisual.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts.Components;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class ModdableVisual : Node2D
|
||||||
|
{
|
||||||
|
[Export] private Sprite2D _sprite;
|
||||||
|
public Follower.FollowerTier Tier { get; private set; }
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (_sprite != null)
|
||||||
|
{
|
||||||
|
_sprite.Texture = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(Follower.FollowerTier tier, Texture2D texture, Vector2 scale)
|
||||||
|
{
|
||||||
|
Tier = tier;
|
||||||
|
if (_sprite != null && texture != null)
|
||||||
|
{
|
||||||
|
_sprite.Texture = texture;
|
||||||
|
_sprite.Scale = scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/Components/ModdableVisual.cs.uid
Normal file
1
Scripts/Components/ModdableVisual.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dpfcbaqgq3l6d
|
33
Scripts/Components/NotificationManager.cs
Normal file
33
Scripts/Components/NotificationManager.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Godot;
|
||||||
|
using ParasiticGod.Scripts;
|
||||||
|
using ParasiticGod.Scripts.Singletons;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts.Components;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class NotificationManager : CanvasLayer
|
||||||
|
{
|
||||||
|
[Export] private PackedScene _notificationLabelScene;
|
||||||
|
[Export] private AudioStreamPlayer _sfx;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
GameBus.Instance.AgeAdvanced += OnAgeAdvanced;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (GameBus.Instance != null)
|
||||||
|
{
|
||||||
|
GameBus.Instance.AgeAdvanced -= OnAgeAdvanced;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAgeAdvanced(string ageName)
|
||||||
|
{
|
||||||
|
var notification = _notificationLabelScene.Instantiate<NotificationLabel>();
|
||||||
|
AddChild(notification);
|
||||||
|
_sfx?.Play();
|
||||||
|
notification.ShowNotification($"You have entered\n{ageName}!");
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/Components/NotificationManager.cs.uid
Normal file
1
Scripts/Components/NotificationManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c6uh5h3sdlg7n
|
43
Scripts/Components/PauseManager.cs
Normal file
43
Scripts/Components/PauseManager.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using Godot;
|
||||||
|
using ParasiticGod.Scripts.Singletons;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts.Components;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class PauseManager : CanvasLayer
|
||||||
|
{
|
||||||
|
[Export] private Button _pauseButton;
|
||||||
|
[Export] private Control _pauseMenu;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
ProcessMode = ProcessModeEnum.Always;
|
||||||
|
_pauseMenu.Hide();
|
||||||
|
_pauseButton.Pressed += TogglePause;
|
||||||
|
|
||||||
|
GameBus.Instance.PauseStateChanged += OnPauseStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Input(InputEvent @event)
|
||||||
|
{
|
||||||
|
if (@event.IsActionPressed("pause")) TogglePause();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (GameBus.Instance != null)
|
||||||
|
{
|
||||||
|
GameBus.Instance.PauseStateChanged -= OnPauseStateChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TogglePause()
|
||||||
|
{
|
||||||
|
GameBus.Instance.SetPause(!GetTree().Paused);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPauseStateChanged(bool isPaused)
|
||||||
|
{
|
||||||
|
_pauseMenu.Visible = isPaused;
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/Components/PauseManager.cs.uid
Normal file
1
Scripts/Components/PauseManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://djmtle2h3yd2e
|
@@ -1,18 +1,21 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Godot;
|
using Godot;
|
||||||
using Godot.Collections;
|
|
||||||
using ParasiticGod.Scripts.Core;
|
using ParasiticGod.Scripts.Core;
|
||||||
using ParasiticGod.Scripts.Singletons;
|
using ParasiticGod.Scripts.Singletons;
|
||||||
|
|
||||||
namespace ParasiticGod.Scripts;
|
namespace ParasiticGod.Scripts.Components;
|
||||||
|
|
||||||
[GlobalClass]
|
[GlobalClass]
|
||||||
public partial class PopulationVisualizer : Node
|
public partial class PopulationVisualizer : Node
|
||||||
{
|
{
|
||||||
|
public enum VisualCategory { Followers, Huts, Temples }
|
||||||
|
|
||||||
[Export] private Node2D _markersContainer;
|
[Export] private Node2D _markersContainer;
|
||||||
[Export] private int _unitsPerMarker = 5;
|
[Export] private int _unitsPerMarker = 5;
|
||||||
[Export] private Array<TierDefinition> _tiers;
|
[Export] public VisualCategory Category { get; private set; }
|
||||||
|
[Export] private PackedScene _moddableVisualScene;
|
||||||
|
|
||||||
|
private List<TierDefinition> _tiers;
|
||||||
private readonly List<FollowerMarker> _markers = [];
|
private readonly List<FollowerMarker> _markers = [];
|
||||||
private long _lastKnownUnitCount = -1;
|
private long _lastKnownUnitCount = -1;
|
||||||
private int _lastKnownTierIndex = -1;
|
private int _lastKnownTierIndex = -1;
|
||||||
@@ -20,6 +23,22 @@ public partial class PopulationVisualizer : Node
|
|||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
switch (Category)
|
||||||
|
{
|
||||||
|
case VisualCategory.Followers:
|
||||||
|
_tiers = GameBus.Instance.FollowerTiers;
|
||||||
|
break;
|
||||||
|
case VisualCategory.Huts:
|
||||||
|
_tiers = GameBus.Instance.HutTiers;
|
||||||
|
break;
|
||||||
|
case VisualCategory.Temples:
|
||||||
|
_tiers = GameBus.Instance.TempleTiers;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GD.PushError($"PopulationVisualizer has an invalid category: {Category}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var child in _markersContainer.GetChildren())
|
foreach (var child in _markersContainer.GetChildren())
|
||||||
{
|
{
|
||||||
if (child is FollowerMarker marker)
|
if (child is FollowerMarker marker)
|
||||||
@@ -40,7 +59,13 @@ public partial class PopulationVisualizer : Node
|
|||||||
{
|
{
|
||||||
if (_isUpdating) return;
|
if (_isUpdating) return;
|
||||||
|
|
||||||
var currentUnitCount = (long)newState.Get(Stat.Followers);
|
long currentUnitCount = Category switch
|
||||||
|
{
|
||||||
|
VisualCategory.Followers => (long)newState.Get(Stat.Followers),
|
||||||
|
VisualCategory.Huts => (long)newState.Get(Stat.Followers),
|
||||||
|
VisualCategory.Temples => (long)newState.Get(Stat.Followers),
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
|
||||||
var currentMarkersToShow = (int)currentUnitCount / _unitsPerMarker;
|
var currentMarkersToShow = (int)currentUnitCount / _unitsPerMarker;
|
||||||
var lastMarkersToShow = (int)_lastKnownUnitCount / _unitsPerMarker;
|
var lastMarkersToShow = (int)_lastKnownUnitCount / _unitsPerMarker;
|
||||||
@@ -84,19 +109,23 @@ public partial class PopulationVisualizer : Node
|
|||||||
|
|
||||||
if (i < followersToShow)
|
if (i < followersToShow)
|
||||||
{
|
{
|
||||||
if (!marker.IsOccupied || _lastKnownTierIndex != newTierIndex)
|
var currentVisual = marker.GetChildOrNull<ModdableVisual>(0);
|
||||||
|
if (currentVisual == null || currentVisual.Tier != currentTier.TierEnum)
|
||||||
{
|
{
|
||||||
if (marker.IsOccupied) marker.RemoveFollower();
|
if (marker.GetChildCount() > 0) marker.GetChild(0).QueueFree();
|
||||||
var followerInstance = currentTier.Scene.Instantiate<Follower>();
|
|
||||||
marker.PlaceFollower(followerInstance);
|
var visualInstance = _moddableVisualScene.Instantiate<ModdableVisual>();
|
||||||
|
visualInstance.Initialize(currentTier.TierEnum, currentTier.Texture, currentTier.Scale);
|
||||||
|
|
||||||
|
marker.AddChild(visualInstance);
|
||||||
needsChange = true;
|
needsChange = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (marker.IsOccupied)
|
if (marker.GetChildCount() > 0)
|
||||||
{
|
{
|
||||||
marker.RemoveFollower();
|
marker.GetChild(0).QueueFree();
|
||||||
needsChange = true;
|
needsChange = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,5 +139,7 @@ public partial class PopulationVisualizer : Node
|
|||||||
_lastKnownUnitCount = currentUnitCount;
|
_lastKnownUnitCount = currentUnitCount;
|
||||||
_lastKnownTierIndex = newTierIndex;
|
_lastKnownTierIndex = newTierIndex;
|
||||||
_isUpdating = false;
|
_isUpdating = false;
|
||||||
|
|
||||||
|
GameBus.Instance.NotifyPopulationVisualsUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
1
Scripts/Components/ProgressiveVisualizer.cs.uid
Normal file
1
Scripts/Components/ProgressiveVisualizer.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://m3qqshwpk16h
|
102
Scripts/Components/RoadManager.cs
Normal file
102
Scripts/Components/RoadManager.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Godot;
|
||||||
|
using ParasiticGod.Scripts.Singletons;
|
||||||
|
|
||||||
|
namespace ParasiticGod.Scripts.Components;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class RoadManager : Node2D
|
||||||
|
{
|
||||||
|
[Export] private Node2D _markersContainer;
|
||||||
|
[Export] private float _roadWidth = 4.0f;
|
||||||
|
[Export] private Color _roadColor = new("saddlebrown");
|
||||||
|
|
||||||
|
[Export] private Follower.FollowerTier _minimumTierForRoads = Follower.FollowerTier.Tier2;
|
||||||
|
|
||||||
|
private Line2D _roadNetwork;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_roadNetwork = new Line2D
|
||||||
|
{
|
||||||
|
Width = _roadWidth,
|
||||||
|
DefaultColor = _roadColor,
|
||||||
|
};
|
||||||
|
AddChild(_roadNetwork);
|
||||||
|
|
||||||
|
Callable.From(() =>
|
||||||
|
{
|
||||||
|
GenerateRoads();
|
||||||
|
GameBus.Instance.PopulationVisualsUpdated += GenerateRoads;
|
||||||
|
}).CallDeferred();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _ExitTree()
|
||||||
|
{
|
||||||
|
if (GameBus.Instance != null)
|
||||||
|
{
|
||||||
|
GameBus.Instance.PopulationVisualsUpdated -= GenerateRoads;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateRoads()
|
||||||
|
{
|
||||||
|
_roadNetwork.ClearPoints();
|
||||||
|
|
||||||
|
var activeMarkers = _markersContainer.GetChildren()
|
||||||
|
.OfType<Marker2D>() // We can just look for any Marker2D
|
||||||
|
.Select(m => new { Marker = m, Visual = m.GetChildOrNull<ModdableVisual>(0) })
|
||||||
|
.Where(mv => mv.Visual != null && mv.Visual.Tier >= _minimumTierForRoads)
|
||||||
|
.Select(mv => mv.Marker)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (activeMarkers.Count < 2) return;
|
||||||
|
|
||||||
|
var treeNodes = new HashSet<Node2D>();
|
||||||
|
var remainingNodes = new List<Node2D>(activeMarkers);
|
||||||
|
var edges = new List<(Vector2, Vector2)>();
|
||||||
|
|
||||||
|
var startNode = remainingNodes[0];
|
||||||
|
treeNodes.Add(startNode);
|
||||||
|
remainingNodes.RemoveAt(0);
|
||||||
|
|
||||||
|
while (remainingNodes.Any())
|
||||||
|
{
|
||||||
|
Node2D bestSource = null;
|
||||||
|
Node2D bestDest = null;
|
||||||
|
var minDistanceSq = float.MaxValue;
|
||||||
|
|
||||||
|
foreach (var source in treeNodes)
|
||||||
|
{
|
||||||
|
foreach (var dest in remainingNodes)
|
||||||
|
{
|
||||||
|
var distSq = source.GlobalPosition.DistanceSquaredTo(dest.GlobalPosition);
|
||||||
|
if (distSq < minDistanceSq)
|
||||||
|
{
|
||||||
|
minDistanceSq = distSq;
|
||||||
|
bestSource = source;
|
||||||
|
bestDest = dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestDest != null)
|
||||||
|
{
|
||||||
|
treeNodes.Add(bestDest);
|
||||||
|
remainingNodes.Remove(bestDest);
|
||||||
|
edges.Add((bestSource.Position, bestDest.Position));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (start, end) in edges)
|
||||||
|
{
|
||||||
|
_roadNetwork.AddPoint(start);
|
||||||
|
_roadNetwork.AddPoint(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
Scripts/Components/RoadManager.cs.uid
Normal file
1
Scripts/Components/RoadManager.cs.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://cw8gpeaq3yfjn
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user