Merge pull request #48 from Citadel-Station-13/master

7/6
This commit is contained in:
EmeraldSundisk
2020-07-06 22:05:40 -07:00
committed by GitHub
29 changed files with 1554 additions and 827 deletions
File diff suppressed because it is too large Load Diff
+71
View File
@@ -0,0 +1,71 @@
//// COOLDOWN SYSTEMS
/*
* We have 2 cooldown systems: timer cooldowns (divided between stoppable and regular) and world.time cooldowns.
*
* When to use each?
*
* * Adding a commonly-checked cooldown, like on a subsystem to check for processing
* * * Use the world.time ones, as they are cheaper.
*
* * Adding a rarely-used one for special situations, such as giving an uncommon item a cooldown on a target.
* * * Timer cooldown, as adding a new variable on each mob to track the cooldown of said uncommon item is going too far.
*
* * Triggering events at the end of a cooldown.
* * * Timer cooldown, registering to its signal.
*
* * Being able to check how long left for the cooldown to end.
* * * Either world.time or stoppable timer cooldowns, depending on the other factors. Regular timer cooldowns do not support this.
*
* * Being able to stop the timer before it ends.
* * * Either world.time or stoppable timer cooldowns, depending on the other factors. Regular timer cooldowns do not support this.
*/
/*
* Cooldown system based on an datum-level associative lazylist using timers.
*/
//INDEXES
#define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet"
//TIMER COOLDOWN MACROS
#define COMSIG_CD_STOP(cd_index) "cooldown_[cd_index]"
#define COMSIG_CD_RESET(cd_index) "cd_reset_[cd_index]"
#define TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, /proc/end_cooldown, cd_source, cd_index), cd_time))
#define TIMER_COOLDOWN_CHECK(cd_source, cd_index) LAZYACCESS(cd_source.cooldowns, cd_index)
#define TIMER_COOLDOWN_END(cd_source, cd_index) LAZYREMOVE(cd_source.cooldowns, cd_index)
/*
* Stoppable timer cooldowns.
* Use indexes the same as the regular tiemr cooldowns.
* They make use of the TIMER_COOLDOWN_CHECK() and TIMER_COOLDOWN_END() macros the same, just not the TIMER_COOLDOWN_START() one.
* A bit more expensive than the regular timers, but can be reset before they end and the time left can be checked.
*/
#define S_TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, /proc/end_cooldown, cd_source, cd_index), cd_time, TIMER_STOPPABLE))
#define S_TIMER_COOLDOWN_RESET(cd_source, cd_index) reset_cooldown(cd_source, cd_index)
#define S_TIMER_COOLDOWN_TIMELEFT(cd_source, cd_index) (timeleft(TIMER_COOLDOWN_CHECK(cd_source, cd_index)))
/*
* Cooldown system based on storing world.time on a variable, plus the cooldown time.
* Better performance over timer cooldowns, lower control. Same functionality.
*/
#define COOLDOWN_DECLARE(cd_index) var/##cd_index = 0
#define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + cd_time)
//Returns true if the cooldown has run its course, false otherwise
#define COOLDOWN_FINISHED(cd_source, cd_index) (cd_source.cd_index < world.time)
#define COOLDOWN_RESET(cd_source, cd_index) cd_source.cd_index = 0
#define COOLDOWN_TIMELEFT(cd_source, cd_index) (max(0, cd_source.cd_index - world.time))
+34
View File
@@ -39,6 +39,9 @@
/// A weak reference to another datum
var/datum/weakref/weak_reference
///Lazy associative list of currently active cooldowns.
var/list/cooldowns
#ifdef TESTING
var/running_find_references
var/last_find_references = 0
@@ -201,3 +204,34 @@
qdel(D)
else
return returned
/**
* Callback called by a timer to end an associative-list-indexed cooldown.
*
* Arguments:
* * source - datum storing the cooldown
* * index - string index storing the cooldown on the cooldowns associative list
*
* This sends a signal reporting the cooldown end.
*/
/proc/end_cooldown(datum/source, index)
if(QDELETED(source))
return
SEND_SIGNAL(source, COMSIG_CD_STOP(index))
TIMER_COOLDOWN_END(source, index)
/**
* Proc used by stoppable timers to end a cooldown before the time has ran out.
*
* Arguments:
* * source - datum storing the cooldown
* * index - string index storing the cooldown on the cooldowns associative list
*
* This sends a signal reporting the cooldown end, passing the time left as an argument.
*/
/proc/reset_cooldown(datum/source, index)
if(QDELETED(source))
return
SEND_SIGNAL(source, COMSIG_CD_RESET(index), S_TIMER_COOLDOWN_TIMELEFT(source, index))
TIMER_COOLDOWN_END(source, index)
+1 -1
View File
@@ -678,7 +678,7 @@
holder.update_transform()
var/danger = CONFIG_GET(number/threshold_body_size_slowdown)
if(features["body_size"] < danger)
var/slowdown = 1 + round(danger/features["body_size"], 0.1) * CONFIG_GET(number/body_size_slowdown_multiplier)
var/slowdown = (1 - round(features["body_size"] / danger, 0.1)) * CONFIG_GET(number/body_size_slowdown_multiplier)
holder.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/small_stride, TRUE, slowdown)
else if(old_size < danger)
holder.remove_movespeed_modifier(/datum/movespeed_modifier/small_stride)
+4 -1
View File
@@ -201,10 +201,13 @@ GLOBAL_LIST_EMPTY(objectives)
return won || ..()
/datum/objective/assassinate/once/process()
won = check_completion()
won = check_midround_completion()
if(won)
STOP_PROCESSING(SSprocessing,src)
/datum/objective/assassinate/once/proc/check_midround_completion()
return won || !considered_alive(target) //The target afking / logging off for a bit during the round doesn't complete it, but them being afk at roundend does.
/datum/objective/assassinate/internal
var/stolen = 0 //Have we already eliminated this target?
+6 -4
View File
@@ -2322,14 +2322,16 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/min = CONFIG_GET(number/body_size_min)
var/max = CONFIG_GET(number/body_size_max)
var/danger = CONFIG_GET(number/threshold_body_size_slowdown)
var/new_body_size = input(user, "Choose your desired sprite size:\n([min*100]%-[max*100]%), Warning: May make your character look distorted[danger > min ? ", and an exponential slowdown will occur for those smaller than [danger*100]%!" : "!"]", "Character Preference", features["body_size"]*100) as num|null
var/new_body_size = input(user, "Choose your desired sprite size: ([min*100]%-[max*100]%)\nWarning: This may make your character look distorted[danger > min ? "! Additionally, a proportional movement speed penalty will be applied to characters smaller than [danger*100]%." : "!"]", "Character Preference", features["body_size"]*100) as num|null
if (new_body_size)
new_body_size = clamp(new_body_size * 0.01, min, max)
var/dorfy
if(danger > new_body_size)
dorfy = alert(user, "The chosen size appears to be smaller than the threshold of [danger*100]%, which will lead to an added exponential slowdown. Are you sure about that?", "Dwarfism Alert", "Yes", "Move it to the threshold", "No")
if(!dorfy || dorfy == "Move it above the threshold")
if((new_body_size + 0.01) < danger) // Adding 0.01 as a dumb fix to prevent the warning message from appearing when exactly at threshold... Not sure why that happens in the first place.
dorfy = alert(user, "You have chosen a size below the slowdown threshold of [danger*100]%. For balancing purposes, the further you go below this percentage, the slower your character will be. Do you wish to keep this size?", "Speed Penalty Alert", "Yes", "Move it to the threshold", "No")
if(dorfy == "Move it to the threshold")
new_body_size = danger
if(!dorfy) //Aborts if this var is somehow empty
return
if(dorfy != "No")
features["body_size"] = new_body_size
if("tongue")
@@ -83,6 +83,7 @@
/obj/item/reagent_containers/food/snacks/meat/slab/chicken
name = "chicken meat"
desc = "A slab of raw chicken. Remember to wash your hands!"
icon_state = "chickenbreast"
cooked_type = /obj/item/reagent_containers/food/snacks/meat/steak/chicken
slice_path = /obj/item/reagent_containers/food/snacks/meat/rawcutlet/chicken
tastes = list("chicken" = 1)
@@ -341,8 +342,14 @@
/obj/item/reagent_containers/food/snacks/meat/steak/chicken
name = "chicken steak" //Can you have chicken steaks? Maybe this should be renamed once it gets new sprites.
icon_state = "chickenbreast_cooked"
tastes = list("chicken" = 1)
/obj/item/reagent_containers/food/snacks/meat/steak/fish
name = "fish fillet"
icon_state = "grilled_carp_slice"
tastes = list("charred sushi" = 1)
/obj/item/reagent_containers/food/snacks/meat/steak/plain
foodtype = MEAT
@@ -361,6 +368,7 @@
/obj/item/reagent_containers/food/snacks/meat/steak/bear
name = "bear steak"
icon_state = "bearcook"
tastes = list("meat" = 1, "salmon" = 1)
/obj/item/reagent_containers/food/snacks/meat/steak/xeno
@@ -22,6 +22,7 @@
list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/toxin/carpotoxin = 2, /datum/reagent/consumable/nutriment/vitamin = 2)
bitesize = 6
filling_color = "#FA8072"
cooked_type = /obj/item/reagent_containers/food/snacks/meat/steak/fish
tastes = list("fish" = 1)
foodtype = MEAT
@@ -136,6 +136,17 @@
tastes = list("fries" = 3, "cheese" = 1)
foodtype = VEGETABLES | GRAIN
/obj/item/reagent_containers/food/snacks/chilicheesefries
name = "chili cheese fries"
desc = "Fries smothered in cheese -and- chilli."
icon_state = "chilicheesefries"
trash = /obj/item/trash/plate
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2)
list_reagents = list(/datum/reagent/consumable/nutriment = 7, /datum/reagent/consumable/nutriment/vitamin = 1)
filling_color = "#FFD700"
tastes = list("fries" = 3, "cheese" = 1)
foodtype = VEGETABLES | GRAIN
/obj/item/reagent_containers/food/snacks/badrecipe
name = "burned mess"
desc = "Someone should be demoted from cook for this."
@@ -537,6 +548,15 @@
tastes = list("butter" = 1)
foodtype = DAIRY
/obj/item/reagent_containers/food/snacks/butter/margarine
name = "stick of margarine"
desc = "A stick of lightly salted vegetable oil."
icon_state = "marge"
list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/cornoil = 2, /datum/reagent/consumable/sodiumchloride = 1)
filling_color = "#FFD700"
tastes = list("butter" = 1)
foodtype = JUNKFOOD
/obj/item/reagent_containers/food/snacks/onionrings
name = "onion rings"
desc = "Onion slices coated in batter."
@@ -21,6 +21,17 @@
tastes = list("toast" = 1)
foodtype = GRAIN
/obj/item/reagent_containers/food/snacks/baconlettucetomato
name = "blt sandwich"
desc = "The classic bacon, lettuce tomato sandwich."
icon = 'icons/obj/food/burgerbread.dmi'
icon_state = "blt"
trash = /obj/item/trash/plate
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1)
list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/nutriment/vitamin = 2)
tastes = list("bacon" = 1, "lettuce" = 1, "tomato" = 1, "mayo" = 1)
foodtype = GRAIN | MEAT | VEGETABLES
/obj/item/reagent_containers/food/snacks/grilledcheese
name = "grilled cheese sandwich"
desc = "Goes great with Tomato soup!"
@@ -136,8 +147,9 @@
/obj/item/reagent_containers/food/snacks/tuna_sandwich
name = "tuna sandwich"
desc = "Both a salad and a sandwich in one."
icon = 'icons/obj/food/burgerbread.dmi'
icon_state = "tunasandwich"
trash = /obj/item/trash/plate
list_reagents = list(/datum/reagent/consumable/nutriment = 12, /datum/reagent/consumable/nutriment/vitamin = 4)
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 3)
tastes = list("tuna" = 4, "mayonnaise" = 2, "bread" = 2)
foodtype = GRAIN | MEAT
@@ -179,3 +179,14 @@
id = /datum/reagent/consumable/bbqsauce
results = list(/datum/reagent/consumable/bbqsauce = 5)
required_reagents = list(/datum/reagent/ash = 1, /datum/reagent/consumable/tomatojuice = 1, /datum/reagent/medicine/salglu_solution = 3, /datum/reagent/consumable/blackpepper = 1)
/datum/chemical_reaction/margarine
name = "Margarine"
id = "margarine"
required_reagents = list(/datum/reagent/consumable/cornoil = 5, /datum/reagent/consumable/soymilk = 5, /datum/reagent/consumable/sodiumchloride = 1)
mix_message = "The ingredients solidify into a stick of margarine."
/datum/chemical_reaction/margarine/on_reaction(datum/reagents/holder, multiplier)
var/location = get_turf(holder.my_atom)
for(var/i = 1, i <= multiplier, i++)
new /obj/item/reagent_containers/food/snacks/butter/margarine(location)
@@ -22,6 +22,15 @@
result = /obj/item/reagent_containers/food/snacks/baconegg
subcategory = CAT_EGG
/datum/crafting_recipe/food/wrap
name = "Egg Wrap"
reqs = list(/datum/reagent/consumable/soysauce = 10,
/obj/item/reagent_containers/food/snacks/friedegg = 1,
/obj/item/reagent_containers/food/snacks/grown/cabbage = 1,
)
result = /obj/item/reagent_containers/food/snacks/eggwrap
subcategory = CAT_EGG
/datum/crafting_recipe/food/omelette
name = "Omelette"
reqs = list(
@@ -14,15 +14,6 @@
result = /obj/item/reagent_containers/food/snacks/chawanmushi
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/wrap
name = "Egg Wrap"
reqs = list(/datum/reagent/consumable/soysauce = 10,
/obj/item/reagent_containers/food/snacks/friedegg = 1,
/obj/item/reagent_containers/food/snacks/grown/cabbage = 1,
)
result = /obj/item/reagent_containers/food/snacks/eggwrap
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/khachapuri
name = "Khachapuri"
reqs = list(
@@ -93,6 +84,16 @@
result = /obj/item/reagent_containers/food/snacks/cheesyfries
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/chilicheesefries
name = "Chilli cheese fries"
reqs = list(
/obj/item/reagent_containers/food/snacks/fries = 1,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
/obj/item/reagent_containers/food/snacks/grown/chili = 1
)
result = /obj/item/reagent_containers/food/snacks/chilicheesefries
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/eggplantparm
name ="Eggplant parmigiana"
reqs = list(
@@ -25,6 +25,17 @@
result = /obj/item/reagent_containers/food/snacks/grilledcheese
subcategory = CAT_SANDWICH
/datum/crafting_recipe/food/baconlettucetomato
name = "BLT sandwich"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/bacon = 2,
/obj/item/reagent_containers/food/snacks/grown/cabbage = 1,
/obj/item/reagent_containers/food/snacks/grown/tomato = 1,
/datum/reagent/consumable/mayonnaise = 5
)
result = /obj/item/reagent_containers/food/snacks/baconlettucetomato
subcategory = CAT_SANDWICH
/datum/crafting_recipe/food/slimesandwich
name = "Jelly sandwich"
reqs = list(
@@ -99,7 +110,7 @@
/obj/item/reagent_containers/food/snacks/breadslice/plain = 2,
/obj/item/reagent_containers/food/snacks/tuna = 1,
/obj/item/reagent_containers/food/snacks/grown/onion = 1,
/obj/item/reagent_containers/food/condiment/mayonnaise = 5
/datum/reagent/consumable/mayonnaise = 5
)
result = /obj/item/reagent_containers/food/snacks/tuna_sandwich
subcategory = CAT_SANDWICH
+8 -8
View File
@@ -277,7 +277,7 @@
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
icon_grow = "bee_balm-grow"
icon_dead = "bee_balm-dead"
mutatelist = list(/obj/item/seeds/poppy/geranium, /obj/item/seeds/bee_balm/honey) //Lower odds of becoming honey
mutatelist = list(/obj/item/seeds/poppy/geranium, /obj/item/seeds/bee_balm/honey_balm) //Lower odds of becoming honey
reagents_add = list(/datum/reagent/medicine/spaceacillin = 0.1, /datum/reagent/space_cleaner/sterilizine = 0.05)
/obj/item/reagent_containers/food/snacks/grown/bee_balm
@@ -291,11 +291,11 @@
foodtype = GROSS
// Beebalm
/obj/item/seeds/bee_balm/honey
/obj/item/seeds/bee_balm/honey_balm
name = "pack of Honey Balm seeds"
desc = "These seeds grow into Honey Balms."
icon_state = "seed-bee_balmalt"
species = "seed-bee_balm_alt"
icon_state = "seed-honey_balm"
species = "honey_balm"
plantname = "Honey Balm Pods"
product = /obj/item/reagent_containers/food/snacks/grown/bee_balm/honey
endurance = 1
@@ -304,16 +304,16 @@
potency = 1
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
icon_grow = "bee_balmalt-grow"
icon_dead = "bee_balmalt-dead"
icon_grow = "honey_balm-grow"
icon_dead = "honey_balm-dead"
reagents_add = list(/datum/reagent/consumable/honey = 0.1, /datum/reagent/lye = 0.3) //To make wax
rarity = 30
/obj/item/reagent_containers/food/snacks/grown/bee_balm/honey
seed = /obj/item/seeds/bee_balm/honey
seed = /obj/item/seeds/bee_balm/honey_balm
name = "honey balm"
desc = "A large honey filled pod of a flower."
icon_state = "bee_balmalt"
icon_state = "honey_balm"
filling_color = "#FF6347"
bitesize_mod = 8
tastes = list("wax" = 1)
+9 -11
View File
@@ -186,9 +186,8 @@
GLOBAL_LIST_EMPTY(employmentCabinets)
/obj/structure/filingcabinet/employment
var/cooldown = 0
icon_state = "employmentcabinet"
var/virgin = 1
var/virgin = TRUE
/obj/structure/filingcabinet/employment/Initialize()
. = ..()
@@ -213,13 +212,12 @@ GLOBAL_LIST_EMPTY(employmentCabinets)
new /obj/item/paper/contract/employment(src, employee)
/obj/structure/filingcabinet/employment/interact(mob/user)
if(!cooldown)
if(virgin)
fillCurrent()
virgin = 0
cooldown = 1
sleep(100) // prevents the devil from just instantly emptying the cabinet, ensuring an easy win.
cooldown = 0
else
if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_EMPLOYMENT_CABINET))
to_chat(user, "<span class='warning'>[src] is jammed, give it a few seconds.</span>")
..()
return ..()
TIMER_COOLDOWN_START(src, COOLDOWN_EMPLOYMENT_CABINET, 10 SECONDS) // prevents the devil from just instantly emptying the cabinet, ensuring an easy win.
if(virgin)
fillCurrent()
virgin = FALSE
return ..()
@@ -258,9 +258,9 @@
var/amount = text2num(params["amount"])
if(amount == null)
amount = text2num(input(usr,
"Max 10. Buffer content will be split evenly.",
"Max 20. Buffer content will be split evenly.",
"How many to make?", 1))
amount = clamp(round(amount), 0, 10)
amount = clamp(round(amount), 0, 20)
if (amount <= 0)
return FALSE
// Get units per item
+16
View File
@@ -50,6 +50,22 @@
-->
<div class="commit sansserif">
<h2 class="date">07 July 2020</h2>
<h3 class="author">KasparoVy updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Fixes misaligned south-facing silver legwraps sprite.</li>
</ul>
<h3 class="author">Owai-Seek updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Bee Balm is now visible.</li>
</ul>
<h3 class="author">Weblure updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed the slowdown formula for small character sprites; you guys don't use custom sprite sizes so just ignore these changes.</li>
<li class="bugfix">Fixed the "Move it to the threshold" button; it now does what it says.</li>
<li class="tweak">Reworded some text to be clearer.</li>
</ul>
<h2 class="date">05 July 2020</h2>
<h3 class="author">Ghommie updated:</h3>
<ul class="changes bgimages16">
+10
View File
@@ -26264,3 +26264,13 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
timothyteakettle:
- tweak: cooking oil is now far less lethal, requiring a higher volume of the reagent
to deal more damage
2020-07-07:
KasparoVy:
- tweak: Fixes misaligned south-facing silver legwraps sprite.
Owai-Seek:
- bugfix: Bee Balm is now visible.
Weblure:
- bugfix: Fixed the slowdown formula for small character sprites; you guys don't
use custom sprite sizes so just ignore these changes.
- bugfix: Fixed the "Move it to the threshold" button; it now does what it says.
- tweak: Reworded some text to be clearer.
@@ -0,0 +1,9 @@
author: "Owai-Seek"
delete-after: True
changes:
- rscadd: "Margarine, Chili Cheese Fries."
- tweak: "Egg Wraps are now categorized under egg foods."
- bugfix: "Tuna Sandwich crafting/sprite is now visible."
- imageadd: "Icons for chicken, cooked chicken, steak, grilled carp, corndogs"
- imageadd: "Icons for chili cheese fries, margarine, BLT sandwich"
- imageadd: "(Unused) icons for raw meatballs, and lard"
@@ -0,0 +1,8 @@
author: "EmeraldSundisk"
delete-after: True
changes:
- rscadd: "CogStation now has an apothecary"
- rscdel: "Removes an outdated note on sleepers"
- tweak: "Readjusts CogStation's chemistry lab"
- tweak: "Slight area designation adjustments for Robotics"
- bugfix: "The arrivals plaque should be readable now"
@@ -0,0 +1,4 @@
author: "DeltaFire15"
delete-after: True
changes:
- bugfix: "The kill-once objective now works properly."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

+1
View File
@@ -38,6 +38,7 @@
#include "code\__DEFINES\configuration.dm"
#include "code\__DEFINES\construction.dm"
#include "code\__DEFINES\contracts.dm"
#include "code\__DEFINES\cooldowns.dm"
#include "code\__DEFINES\cult.dm"
#include "code\__DEFINES\diseases.dm"
#include "code\__DEFINES\DNA.dm"