From 174eddbf8a0efb80ceb7e15d551836fd7d8401d9 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 11:56:42 +0100
Subject: [PATCH 01/79] Update is_helpers.dm
---
code/__DEFINES/is_helpers.dm | 2 ++
1 file changed, 2 insertions(+)
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 40b7a0d550d1..25669ee1bedd 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -113,6 +113,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isrevenant(A) (istype(A, /mob/living/simple_animal/revenant))
+#define ishorror(A) (istype(A, /mob/living/simple_animal/horror))
+
#define isbot(A) (istype(A, /mob/living/simple_animal/bot))
#define isshade(A) (istype(A, /mob/living/simple_animal/shade))
From 14baad40b127096c3fa5ab816bfa3a955f3f973c Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 11:57:53 +0100
Subject: [PATCH 02/79] Update role_preferences.dm
---
code/__DEFINES/role_preferences.dm | 2 ++
1 file changed, 2 insertions(+)
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index 00dc098a3d34..27cff08dd797 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -44,6 +44,7 @@
#define ROLE_GANG "gangster" // Yogs
#define ROLE_DARKSPAWN "darkspawn" // Yogs
#define ROLE_HOLOPARASITE "Holoparasite" // Yogs
+#define ROLE_HORROR "Eldritch Horror" // Yogs
#define ROLE_INFILTRATOR "Infiltrator" // Yogs
#define ROLE_ZOMBIE "Zombie"
@@ -63,6 +64,7 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_MALF,
ROLE_REV = /datum/game_mode/revolution,
ROLE_ALIEN,
+ ROLE_HORROR,
ROLE_PAI,
ROLE_CULTIST = /datum/game_mode/cult,
ROLE_BLOB,
From fba5222447eb23848e6c44533b69359f5f17b414 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 11:58:52 +0100
Subject: [PATCH 03/79] Update names.dm
---
code/_globalvars/lists/names.dm | 1 +
1 file changed, 1 insertion(+)
diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm
index e36e464685e0..32029882bf1d 100644
--- a/code/_globalvars/lists/names.dm
+++ b/code/_globalvars/lists/names.dm
@@ -20,6 +20,7 @@ GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt")
GLOBAL_LIST_INIT(ethereal_names, world.file2list("strings/names/ethereal.txt"))
GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt"))
GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt"))
+GLOBAL_LIST_INIT(horror_names, world.file2list("strings/names/horror.txt"))
GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt"))
GLOBAL_LIST_INIT(megacarp_last_names, world.file2list("strings/names/megacarp2.txt"))
From 4e866c01c02778f40548eed21cd6aeb4486eb3f8 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 11:59:34 +0100
Subject: [PATCH 04/79] Add files via upload
---
code/_onclick/hud/horror.dm | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 code/_onclick/hud/horror.dm
diff --git a/code/_onclick/hud/horror.dm b/code/_onclick/hud/horror.dm
new file mode 100644
index 000000000000..372bc198c96f
--- /dev/null
+++ b/code/_onclick/hud/horror.dm
@@ -0,0 +1,17 @@
+/obj/screen/horror_chemicals
+ name = "chemicals"
+ icon_state = "horror_counter"
+ screen_loc = ui_lingchemdisplay
+
+/datum/hud/chemical_counter
+ ui_style = 'icons/mob/screen_midnight.dmi'
+ var/obj/screen/horror_chemicals/chemical_counter
+
+/datum/hud/chemical_counter/New(mob/owner)
+ . = ..()
+ chemical_counter = new /obj/screen/horror_chemicals
+ infodisplay += chemical_counter
+
+/datum/hud/chemical_counter/Destroy()
+ . = ..()
+ chemical_counter = null
From 25f1079bfd095dd3413447bb22765fefdeac6b25 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:00:49 +0100
Subject: [PATCH 05/79] Update miscellaneous.dm
---
code/game/objects/effects/temporary_visuals/miscellaneous.dm | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 12315ff83940..f7d7f5779dc5 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -483,3 +483,8 @@
layer = FLY_LAYER
duration = 0.48 SECONDS
mouse_opacity = 0
+
+/obj/effect/temp_visual/summon
+ randomdir = 0
+ duration = 20
+ icon_state = "summon"
From f8b4f131e1960e4cb2f5d152767857afd5a0efdd Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:13:39 +0100
Subject: [PATCH 06/79] Update sql_ban_system.dm
---
code/modules/admin/sql_ban_system.dm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/code/modules/admin/sql_ban_system.dm b/code/modules/admin/sql_ban_system.dm
index e460a43f3fa4..617ec1323a7e 100644
--- a/code/modules/admin/sql_ban_system.dm
+++ b/code/modules/admin/sql_ban_system.dm
@@ -266,10 +266,10 @@
break_counter++
output += ""
var/list/long_job_lists = list("Civilian" = GLOB.original_civilian_positions,
- "Ghost and Other Roles" = list(ROLE_BRAINWASHED, ROLE_DEATHSQUAD, ROLE_DRONE, ROLE_FUGITIVE, ROLE_HOLOPARASITE, ROLE_LAVALAND, ROLE_MIND_TRANSFER, ROLE_POSIBRAIN, ROLE_SENTIENCE),
+ "Ghost and Other Roles" = list(ROLE_BRAINWASHED, ROLE_DEATHSQUAD, ROLE_DRONE, ROLE_FUGITIVE, ROLE_HOLOPARASITE, ROLE_HORROR, ROLE_LAVALAND, ROLE_MIND_TRANSFER, ROLE_POSIBRAIN, ROLE_SENTIENCE),
"Antagonist Positions" = list(ROLE_ABDUCTOR, ROLE_ALIEN, ROLE_BLOB,
ROLE_BROTHER, ROLE_CHANGELING, ROLE_CULTIST,
- ROLE_DEVIL, ROLE_FUGITIVE, ROLE_HOLOPARASITE, ROLE_INTERNAL_AFFAIRS, ROLE_MALF,
+ ROLE_DEVIL, ROLE_FUGITIVE, ROLE_HOLOPARASITE, ROLE_HORROR, ROLE_INTERNAL_AFFAIRS, ROLE_MALF,
ROLE_MONKEY, ROLE_NINJA, ROLE_OPERATIVE,
ROLE_REV, ROLE_REVENANT,
ROLE_REV_HEAD, ROLE_SERVANT_OF_RATVAR, ROLE_SYNDICATE,
From 3bb37d340bc19610f6128c1663d72b5d0a48df4f Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:14:34 +0100
Subject: [PATCH 07/79] Update headcrab.dm
---
code/modules/antagonists/changeling/powers/headcrab.dm | 3 +++
1 file changed, 3 insertions(+)
diff --git a/code/modules/antagonists/changeling/powers/headcrab.dm b/code/modules/antagonists/changeling/powers/headcrab.dm
index ee2130a52e7c..f9c825a304b7 100644
--- a/code/modules/antagonists/changeling/powers/headcrab.dm
+++ b/code/modules/antagonists/changeling/powers/headcrab.dm
@@ -33,6 +33,9 @@
to_chat(S, span_userdanger("Your sensors are disabled by a shower of blood!"))
S.Paralyze(60)
var/turf = get_turf(user)
+ var/mob/living/simple_animal/horror/H = user.has_horror_inside()
+ if(H)
+ H.leave_victim()
user.gib()
. = TRUE
sleep(5) // So it's not killed in explosion
From de0f4f0a3775937ce70d1e711577eeb2f697ec04 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:15:09 +0100
Subject: [PATCH 08/79] Update panacea.dm
---
code/modules/antagonists/changeling/powers/panacea.dm | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/code/modules/antagonists/changeling/powers/panacea.dm b/code/modules/antagonists/changeling/powers/panacea.dm
index 0bc43b1f33bb..a509014e8e28 100644
--- a/code/modules/antagonists/changeling/powers/panacea.dm
+++ b/code/modules/antagonists/changeling/powers/panacea.dm
@@ -10,6 +10,13 @@
//Heals the things that the other regenerative abilities don't.
/datum/action/changeling/panacea/sting_action(mob/user)
to_chat(user, span_notice("We cleanse impurities from our form."))
+ var/mob/living/simple_animal/horror/H = user.has_horror_inside()
+ if(H)
+ H.leave_victim()
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ C.vomit(0, toxic = TRUE)
+ to_chat(user, "A parasite exits our form.")
..()
var/list/bad_organs = list(
user.getorgan(/obj/item/organ/body_egg),
From 739e7bff6ffe6caba7e4f974c89961786fb2183c Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:26:16 +0100
Subject: [PATCH 09/79] Update suicide.dm
---
code/modules/client/verbs/suicide.dm | 3 +++
1 file changed, 3 insertions(+)
diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm
index 8ed47046ed96..82a22afa7745 100644
--- a/code/modules/client/verbs/suicide.dm
+++ b/code/modules/client/verbs/suicide.dm
@@ -257,6 +257,9 @@
if(UNCONSCIOUS)
to_chat(src, span_warning("You need to be conscious to commit suicide!"))
return FALSE
+ if(has_horror_inside())
+ to_chat(src, "Something inside your head stops your action!")
+ return
if(DEAD)
to_chat(src, span_warning("You're already dead!"))
return FALSE
From 19b49f25731eff1f3d87ce341d3838e3bedad889 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:27:04 +0100
Subject: [PATCH 10/79] Update suicide.dm
---
code/modules/client/verbs/suicide.dm | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm
index 82a22afa7745..f26416fe6098 100644
--- a/code/modules/client/verbs/suicide.dm
+++ b/code/modules/client/verbs/suicide.dm
@@ -257,9 +257,6 @@
if(UNCONSCIOUS)
to_chat(src, span_warning("You need to be conscious to commit suicide!"))
return FALSE
- if(has_horror_inside())
- to_chat(src, "Something inside your head stops your action!")
- return
if(DEAD)
to_chat(src, span_warning("You're already dead!"))
return FALSE
@@ -277,4 +274,7 @@
if(!(mobility_flags & MOBILITY_USE)) //just while I finish up the new 'fun' suiciding verb. This is to prevent metagaming via suicide
to_chat(src, "You can't commit suicide whilst immobile! ((You can type Ghost instead however.))")
return
+ if(has_horror_inside())
+ to_chat(src, "Something inside your head stops your action!")
+ return
return TRUE
From 825fb104a6f9afe4082e8aebeafd3434b82de591 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:28:18 +0100
Subject: [PATCH 11/79] Update brain_item.dm
---
code/modules/mob/living/brain/brain_item.dm | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm
index a62bc5b2cc3d..afb0dba21fcc 100644
--- a/code/modules/mob/living/brain/brain_item.dm
+++ b/code/modules/mob/living/brain/brain_item.dm
@@ -56,6 +56,10 @@
/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0, no_id_transfer = FALSE)
..()
+ if(!special)
+ if(C.has_horror_inside())
+ var/mob/living/simple_animal/horror/B = C.has_horror_inside()
+ B.leave_victim()
if(C.mind && C.mind.has_antag_datum(/datum/antagonist/changeling))
var/datum/antagonist/changeling/bruh = C.mind.has_antag_datum(/datum/antagonist/changeling)
for(var/d in bruh.purchasedpowers)
From 79a111338ff26d69628f50ab33de50ca17251aa1 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:29:34 +0100
Subject: [PATCH 12/79] Update death.dm
---
code/modules/mob/living/carbon/death.dm | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm
index 9f26b38f384d..61cb09bc23da 100644
--- a/code/modules/mob/living/carbon/death.dm
+++ b/code/modules/mob/living/carbon/death.dm
@@ -25,7 +25,10 @@
stomach_contents.Remove(M)
//yogs end
M.forceMove(Tsec)
- visible_message(span_danger("[M] bursts out of [src]!"))
+ if(ishorror(M)) //eldritch horror(aka. borer) check, they die along with their host to prevent mind controlled suicides
+ M.gib()
+ else
+ visible_message("[M] bursts out of [src]!")
..()
/mob/living/carbon/spill_organs(no_brain, no_organs, no_bodyparts)
From 107ce13bc4c083ea4145b0f387afd0db64f8d09d Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:30:37 +0100
Subject: [PATCH 13/79] Update human.dm
---
code/modules/mob/living/carbon/human/human.dm | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 790157d0ccf2..6f5819d098d5 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -73,7 +73,10 @@
. += ""
. += "Hivemind Vessels: [hivemind.hive_size] (+[hivemind.size_mod])"
. += "Psychic Link Duration: [(hivemind.track_bonus + TRACKER_DEFAULT_TIME)/10] seconds"
-
+ var/mob/living/simple_animal/horror/H = has_horror_inside()
+ if(H && H.controlling)
+ . += ""
+ . += "Horror chemicals: [H.chemicals]"
if(mind)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
From c42949472bb09ebf1953f8553ed44fd4542c9262 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:31:23 +0100
Subject: [PATCH 14/79] Update transform_procs.dm
---
code/modules/mob/transform_procs.dm | 3 +++
1 file changed, 3 insertions(+)
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 4199e99630a8..20c9190da6f3 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -3,6 +3,9 @@
/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG))
if (notransform || transformation_timer)
return
+ if(has_horror_inside())
+ to_chat(src, "You feel something strongly clinging to your humanity!")
+ return
//Handle items on mob
if(tr_flags & TR_KEEPITEMS)
From 106e2bd2ba7594b62e5cecd1f3257622f5652cf3 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:44:42 +0100
Subject: [PATCH 15/79] Update organ_manipulation.dm
---
code/modules/surgery/organ_manipulation.dm | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm
index cac1afb711c3..42a2f3322d13 100644
--- a/code/modules/surgery/organ_manipulation.dm
+++ b/code/modules/surgery/organ_manipulation.dm
@@ -102,6 +102,11 @@
else if(implement_type in implements_extract)
current_type = "extract"
var/list/organs = target.getorganszone(target_zone)
+ var/mob/living/simple_animal/horror/H = target.has_horror_inside()
+ if(H)
+ user.visible_message("[user] begins to extract [H] from [target]'s [parse_zone(target_zone)].",
+ "You begin to extract [H] from [target]'s [parse_zone(target_zone)]...")
+ return TRUE
if(!organs.len)
to_chat(user, span_notice("There are no removable organs in [target]'s [parse_zone(target_zone)]!"))
return -1
@@ -143,6 +148,13 @@
"[user] inserts something into [target]'s [parse_zone(target_zone)]!")
else if(current_type == "extract")
+ var/mob/living/simple_animal/horror/H = target.has_horror_inside()
+ if(H && H.victim == target)
+ user.visible_message("[user] successfully extracts [H] from [target]'s [parse_zone(target_zone)]!",
+ "You successfully extract [H] from [target]'s [parse_zone(target_zone)].")
+ log_combat(user, target, "surgically removed [H] from", addition="INTENT: [uppertext(user.a_intent)]")
+ H.leave_victim()
+ return FALSE
if(I && I.owner == target)
display_results(user, target, span_notice("You successfully extract [I] from [target]'s [parse_zone(target_zone)]."),
"[user] successfully extracts [I] from [target]'s [parse_zone(target_zone)]!",
From d860d9679f2f897389025a094055def01a8c4dc4 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 12:46:19 +0100
Subject: [PATCH 16/79] Update uplink_items.dm
---
code/modules/uplink/uplink_items.dm | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index a6921686d8c3..931fb8757d0a 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -1950,6 +1950,17 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
restricted_roles = list("Chaplain")
surplus = 5 //Very low chance to get it in a surplus crate even without being the chaplain
+/datum/uplink_item/role_restricted/horror
+ name = "Horror-in-a-box"
+ desc = "When dissecting the head of a dead Nanotrasen scientist, our surgeons noticed an incredibly peculiar creature inside and managed to extract it into safe containment. \
+ Either a failed experiment or otherworldly monster, this creature has been trained to aid whoever wakes it up. If you aren't afraid of it entering your head, it can prove a useful ally. \
+ We take no responsibility for your newfound madness and accept no refunds."
+ item = /obj/item/horrorspawner
+ cost = 16
+ surplus = 0
+ restricted_roles = list("Curator")
+ player_minimum = 20
+
/datum/uplink_item/role_restricted/explosive_hot_potato
name = "Exploding Hot Potato"
desc = "A potato rigged with explosives. On activation, a special mechanism is activated that prevents it from being dropped. \
From b6f465bf3fb00e82bbe40497ffacaee64fdaa323 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 13:30:39 +0100
Subject: [PATCH 17/79] Create horror.dm
---
code/modules/antagonists/horror/horror.dm | 1 +
1 file changed, 1 insertion(+)
create mode 100644 code/modules/antagonists/horror/horror.dm
diff --git a/code/modules/antagonists/horror/horror.dm b/code/modules/antagonists/horror/horror.dm
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/code/modules/antagonists/horror/horror.dm
@@ -0,0 +1 @@
+
From 7fc6b04fc2290efb0e4d510e0e867c3bf9c322cb Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 13:31:15 +0100
Subject: [PATCH 18/79] Add files via upload
---
code/modules/antagonists/horror/horror.dm | 845 +++++++++++++++++-
.../horror/horror_abilities_and_upgrades.dm | 454 ++++++++++
.../antagonists/horror/horror_chemicals.dm | 96 ++
.../antagonists/horror/horror_datums.dm | 348 ++++++++
.../modules/antagonists/horror/horror_html.dm | 102 +++
.../antagonists/horror/horror_mutate.dm | 99 ++
6 files changed, 1943 insertions(+), 1 deletion(-)
create mode 100644 code/modules/antagonists/horror/horror_abilities_and_upgrades.dm
create mode 100644 code/modules/antagonists/horror/horror_chemicals.dm
create mode 100644 code/modules/antagonists/horror/horror_datums.dm
create mode 100644 code/modules/antagonists/horror/horror_html.dm
create mode 100644 code/modules/antagonists/horror/horror_mutate.dm
diff --git a/code/modules/antagonists/horror/horror.dm b/code/modules/antagonists/horror/horror.dm
index 8b137891791f..7e1bbd426e2b 100644
--- a/code/modules/antagonists/horror/horror.dm
+++ b/code/modules/antagonists/horror/horror.dm
@@ -1 +1,844 @@
-
+/mob/living/simple_animal/horror
+ name = "eldritch horror"
+ real_name = "eldritch horror"
+ desc = "Your eyes can barely comprehend what they're looking at."
+ icon_state = "horror"
+ icon_living = "horror"
+ icon_dead = "horror_dead"
+ icon_gib = "horror_gib"
+ health = 50
+ maxHealth = 50
+ melee_damage_lower = 10
+ melee_damage_upper = 10
+ see_in_dark = 7
+ stop_automated_movement = TRUE
+ attacktext = "bites"
+ speak_emote = list("gurgles")
+ attack_sound = 'sound/weapons/bite.ogg'
+ pass_flags = PASSTABLE | PASSMOB
+ mob_size = MOB_SIZE_SMALL
+ faction = list("neutral","silicon","hostile","creature","heretics")
+ ventcrawler = VENTCRAWLER_ALWAYS
+ initial_language_holder = /datum/language_holder/universal
+ hud_type = /datum/hud/chemical_counter
+
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ minbodytemp = 0
+ maxbodytemp = 1500
+
+ var/playstyle_string = "You are an eldritch horror, an evermutating parasitic abomination. Seek human souls to consume. \
+ Crawl into people's heads and steal their essence. Use it to mutate yourself, giving you access to more power and abilities. \
+ You operate on chemicals that get built up while you spend time in someone's head. You are weak when outside, play carefully.\
+ Check your notes to see which chemical reagent is your bane, and avoid from getting in contact with it. "
+
+ var/mob/living/carbon/victim
+ var/datum/mind/target
+ var/mob/living/captive_brain/host_brain
+ var/truename = null
+ var/available_points = 4
+ var/consumed_souls = 0
+ var/list/horrorabilities = list() //An associative list ("id" = ability datum) containing the abilities the horror has
+ var/list/horrorupgrades = list() //same, but for permanent upgrades
+ var/bonding = FALSE
+ var/controlling = FALSE
+ var/chemicals = 10
+ var/chem_regen_rate = 2
+ var/used_freeze
+ var/used_target
+ var/horror_chems = list(/datum/horror_chem/epinephrine,/datum/horror_chem/mannitol,/datum/horror_chem/bicaridine,/datum/horror_chem/kelotane,/datum/horror_chem/charcoal)
+
+ var/leaving = FALSE
+ var/hiding = FALSE
+ var/invisible = FALSE
+ var/waketimerid = null
+ var/datum/action/innate/horror/talk_to_horror/talk_to_horror_action = new
+
+/mob/living/simple_animal/horror/Initialize(mapload, gen=1)
+ ..()
+ real_name = "Eldritch horror"
+ truename = "[pick(GLOB.horror_names)]"
+
+ //default abilities
+ add_ability("mutate")
+ add_ability("seek_soul")
+ add_ability("consume_soul")
+ add_ability("talk_to_host")
+ add_ability("freeze_victim")
+ add_ability("infest")
+ add_ability("toggle_hide")
+ add_ability("talk_to_brain")
+ add_ability("take_control")
+ add_ability("leave_body")
+ add_ability("make_chems")
+ add_ability("talk_to_brain")
+ add_ability("release_control")
+ RefreshAbilities()
+
+ var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
+ hud.add_hud_to(src)
+ update_horror_hud()
+
+
+/mob/living/simple_animal/horror/Destroy()
+ host_brain = null
+ victim = null
+ return ..()
+
+
+/mob/living/simple_animal/horror/proc/has_chemicals(amt)
+ return chemicals >= amt
+
+/mob/living/simple_animal/horror/proc/use_chemicals(amt)
+ if(!has_chemicals(amt))
+ return FALSE
+ chemicals -= amt
+ update_horror_hud()
+ return TRUE
+
+/mob/living/simple_animal/horror/proc/regenerate_chemicals(amt)
+ chemicals += amt
+ chemicals = min(250, chemicals)
+ update_horror_hud()
+
+/mob/living/simple_animal/horror/proc/update_horror_hud()
+ if(!src || !hud_used)
+ return
+ var/datum/hud/chemical_counter/H = hud_used
+ var/obj/screen/counter = H.chemical_counter
+ counter.maptext = "
[chemicals]
"
+
+/mob/living/simple_animal/horror/proc/can_use_ability()
+ if(stat != CONSCIOUS)
+ to_chat(src, "You cannot do that in your current state.")
+ return FALSE
+ return TRUE
+
+/mob/living/simple_animal/horror/proc/SearchTarget()
+ if(target)
+ if(world.time - used_target < 3 MINUTES)
+ to_chat(src, "You cannot use that ability again so soon.")
+ return
+ if(alert("You already have a target ([target.name]). Would you like to change that target?","Swap targets?","Yes","No") != "Yes")
+ return
+
+ var/list/possible_targets = list()
+ for(var/datum/mind/M in SSticker.minds)
+ if(M.current && M.current.stat != DEAD)
+ if(ishuman(M.current))
+ if(mind.enslaved_to != M.current && M.hasSoul)
+ possible_targets[M] = M
+
+ var/list/selected_targets = list()
+ var/list/icons = list()
+ while(selected_targets.len != 4)
+ if(possible_targets.len <= 0)
+ break
+ var/datum/mind/M = pick(possible_targets)
+ selected_targets[M] = M
+ possible_targets -= M
+
+ var/mob/living/carbon/human/H = M.current
+ icons [M] = H
+
+ used_target = world.time
+
+ var/entry_name = show_radial_menu(src, (victim ? src.loc : src), icons, tooltips = TRUE)
+ target = selected_targets[entry_name]
+
+ //you didn't select your target? let me do that for you, my friend
+ if(selected_targets.len > 0 && !target)
+ target = pick(selected_targets)
+
+ if(target)
+ to_chat(src,"You caught their scent. Go and consume [target.current.real_name], the [target.assigned_role]'s soul!")
+ apply_status_effect(/datum/status_effect/agent_pinpointer/horror)
+ for(var/datum/status_effect/agent_pinpointer/horror/status in status_effects)
+ status.scan_target = target.current
+ else
+ //refund cooldown
+ used_target = 0
+ to_chat(src,"Failed to select a target!")
+
+/mob/living/simple_animal/horror/proc/ConsumeSoul()
+ if(!can_use_ability())
+ return
+
+ if(!victim.mind.hasSoul)
+ to_chat(src, "This host doesn't have a soul!")
+ return
+
+ if(victim == mind.enslaved_to)
+ to_chat(src, "No, not yet... We still need them...")
+ return
+
+ if(victim.mind != target)
+ to_chat(src, "This soul isn't your target, you can't consume it!")
+ return
+
+ to_chat(src, "You begin consuming [victim.name]'s soul!")
+ if(do_after(src, 200, target = victim, stayStill = FALSE))
+ consume()
+
+/mob/living/simple_animal/horror/proc/consume()
+ if(!can_use_ability() || !victim || !victim.mind.hasSoul || victim.mind != target)
+ return
+ consumed_souls++
+ available_points++
+ to_chat(src, "You succeed in consuming [victim.name]'s soul!")
+ to_chat(src.victim, "You suddenly feel weak and hollow inside...")
+ victim.health -= 20
+ victim.maxHealth -= 20
+ victim.mind.hasSoul = FALSE
+ target = null
+ remove_status_effect(/datum/status_effect/agent_pinpointer/horror)
+ playsound(src, 'sound/effects/curseattack.ogg', 150)
+ playsound(src, 'sound/effects/ghost.ogg', 50)
+
+/mob/living/simple_animal/horror/proc/Communicate()
+ if(!can_use_ability())
+ return
+ if(!src.victim)
+ to_chat(src, "You do not have a host to communicate with!")
+ return
+
+ var/input = stripped_input(src, "Please enter a message to tell your host.", "Horror", null)
+ if(!input)
+ return
+
+ if(src && !QDELETED(src) && !QDELETED(src.victim))
+ if(src.victim)
+ to_chat(victim, "[truename] slurs: [input]")
+ log_say("Horror Communication: [key_name(src)] -> [key_name(victim)] : [input]")
+ for(var/M in GLOB.dead_mob_list)
+ if(isobserver(M))
+ var/rendered = "Horror Communication from [truename] : [input]"
+ var/link = FOLLOW_LINK(M, src)
+ to_chat(M, "[link] [rendered]")
+ to_chat(src, "[truename] slurs: [input]")
+ add_verb(victim, /mob/living/proc/horror_comm)
+ talk_to_horror_action.Grant(victim)
+
+/mob/living/proc/horror_comm()
+ set name = "Converse with Horror"
+ set category = "Horror"
+ set desc = "Communicate mentally with the thing in your head."
+
+ var/mob/living/simple_animal/horror/B = has_horror_inside()
+ if(B)
+ var/input = stripped_input(src, "Please enter a message to tell the horror.", "Message", "")
+ if(!input)
+ return
+
+ to_chat(B, "[src.name] says: [input]")
+ src.log_talk("Horror Communication: [key_name(src)] -> [key_name(B)] : [input]", LOG_SAY, tag="changeling")
+
+ for(var/M in GLOB.dead_mob_list)
+ if(isobserver(M))
+ var/rendered = "Horror Communication from [B.truename] : [input]"
+ var/link = FOLLOW_LINK(M, src)
+ to_chat(M, "[link] [rendered]")
+ to_chat(src, "[src] says: [input]")
+
+/mob/living/proc/trapped_mind_comm()
+ var/mob/living/simple_animal/horror/B = has_horror_inside()
+ if(!B || !B.host_brain)
+ return
+ var/mob/living/captive_brain/CB = B.host_brain
+ var/input = stripped_input(src, "Please enter a message to tell the trapped mind.", "Message", null)
+ if(!input)
+ return
+
+ to_chat(CB, "[B.truename] says: [input]")
+ log_say("Horror Communication: [key_name(B)] -> [key_name(CB)] : [input]")
+
+ for(var/M in GLOB.dead_mob_list)
+ if(isobserver(M))
+ var/rendered = "Horror Communication from [B.truename] : [input]"
+ var/link = FOLLOW_LINK(M, src)
+ to_chat(M, "[link] [rendered]")
+ to_chat(src, "[B.truename] says: [input]")
+
+/mob/living/simple_animal/horror/Life()
+ ..()
+ if(horrorupgrades["regen"])
+ heal_overall_damage(5)
+
+ if(invisible) //don't regenerate chemicals when invisible
+ if(has_chemicals(5))
+ use_chemicals(5)
+ alpha = max(alpha - 100, 1)
+ else
+ to_chat(src, "You ran out of chemicals to support your invisibility.")
+ invisible = FALSE
+ Update_Invisibility_Button()
+ else
+ if(horrorupgrades["nohost_regen"])
+ regenerate_chemicals(chem_regen_rate)
+ else if(victim)
+ if(victim.stat == DEAD)
+ regenerate_chemicals(1)
+ else
+ regenerate_chemicals(chem_regen_rate)
+ alpha = min(255, alpha + 50)
+
+ if(victim)
+ if(stat != DEAD && victim.stat != DEAD)
+ heal_overall_damage(1)
+
+/mob/living/simple_animal/horror/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
+ if(victim)
+ to_chat(src, "You cannot speak out loud while inside a host!")
+ return
+ return ..()
+
+/mob/living/simple_animal/horror/emote(act, m_type = null, message = null, intentional = FALSE)
+ if(victim)
+ to_chat(src, "You cannot emote while inside a host!")
+ return
+ return ..()
+
+/mob/living/simple_animal/horror/UnarmedAttack(atom/A)
+ if(istype(A, /obj/machinery/door/airlock))
+ visible_message("[src] slips their tentacles into the airlock and starts prying it open!", "You start moving onto the airlock.")
+ playsound(A, 'sound/misc/splort.ogg', 50, 1)
+ if(!do_after(src, 5 SECONDS, target = A))
+ return
+ visible_message("[src] forces themselves through the airlock!", "You force yourself through the airlock.")
+ forceMove(get_turf(A))
+ playsound(A, 'sound/machines/airlock_alien_prying.ogg', 50, 1)
+ return
+ if(isliving(A))
+ if(victim || A == src.mind.enslaved_to)
+ healthscan(usr, A)
+ chemscan(usr, A)
+ else
+ alpha = 255
+ if(hiding)
+ var/datum/action/innate/horror/H = has_ability("toggle_hide")
+ H.Activate()
+ if(invisible)
+ var/datum/action/innate/horror/H = has_ability("chameleon")
+ H.Activate()
+ Update_Invisibility_Button()
+ ..()
+
+/mob/living/simple_animal/horror/ex_act()
+ if(victim)
+ return
+
+ ..()
+
+/mob/living/simple_animal/horror/proc/infect_victim()
+ if(!can_use_ability())
+ return
+ if(victim)
+ to_chat(src, "You are already within a host.")
+
+ if(stat == DEAD)
+ return
+
+ var/list/choices = list()
+ for(var/mob/living/carbon/H in view(1,src))
+ if(H!=src && Adjacent(H))
+ choices += H
+
+ if(!choices.len)
+ return
+ var/mob/living/carbon/H = choices.len > 1 ? input(src,"Who do you wish to infest?") in null|choices : choices[1]
+ if(!H || !src)
+ return
+
+ if(!Adjacent(H))
+ return
+
+ if(H.has_horror_inside())
+ to_chat(src, "[H] is already infested!")
+ return
+
+ to_chat(src, "You slither your tentacles up [H] and begin probing at their ear canal...")
+ if(!do_mob(src, H, 30))
+ to_chat(src, "As [H] moves away, you are dislodged and fall to the ground.")
+ return
+
+ if(!H || !src)
+ return
+
+ Infect(H)
+
+/mob/living/simple_animal/horror/proc/Infect(mob/living/carbon/C)
+ if(!C)
+ return
+ var/obj/item/bodypart/head/head = C.get_bodypart(BODY_ZONE_HEAD)
+ if(!head)
+ to_chat(src, "[C] doesn't have a head!")
+ return
+ var/hasbrain = FALSE
+ for(var/obj/item/organ/brain/X in C.internal_organs)
+ hasbrain = TRUE
+ break
+ if(!hasbrain)
+ to_chat(src, "[C] doesn't have a brain! ")
+ return
+
+ if(C.has_horror_inside())
+ to_chat(src, "[C] is already infested!")
+ return
+
+ if((!C.key || !C.mind) && C != target.current)
+ to_chat(src, "[C]'s mind seems unresponsive. Try someone else!")
+ return
+
+ invisible = FALSE
+ Update_Invisibility_Button()
+ victim = C
+ forceMove(victim)
+ RefreshAbilities()
+ log_game("[src]/([src.ckey]) has infested [victim]/([victim.ckey]")
+
+/mob/living/simple_animal/horror/proc/secrete_chemicals()
+ if(!victim)
+ to_chat(src, "You are not inside a host body.")
+ return
+
+ if(!can_use_ability())
+ return
+
+ var content = ""
+ content += "Chemicals: [chemicals]
"
+
+ content += ""
+
+ for(var/datum in horror_chems)
+ var/datum/horror_chem/C = new datum()
+ if(C.chemname)
+ content += "| [C.chemname] ([C.chemuse]) [C.chem_desc] |
"
+
+ content += "
"
+
+ var/html = get_html_template(content)
+
+ usr << browse(null, "window=ViewHorror\ref[src]Chems;size=600x800")
+ usr << browse(html, "window=ViewHorror\ref[src]Chems;size=600x800")
+
+/mob/living/simple_animal/horror/proc/hide()
+ if(victim)
+ to_chat(src, "You cannot do this while you're inside a host.")
+ return
+
+ if(stat != CONSCIOUS)
+ return
+
+ if(!hiding)
+ layer = LATTICE_LAYER
+ visible_message("[src] scurries to the ground!", \
+ "You are now hiding.")
+ hiding = TRUE
+ else
+ layer = MOB_LAYER
+ visible_message("[src] slowly peaks up from the ground...", \
+ "You stop hiding.")
+ hiding = FALSE
+
+/mob/living/simple_animal/horror/proc/go_invisible()
+ if(victim)
+ to_chat(src, "You cannot do this while you're inside a host.")
+ return
+
+ if(!can_use_ability())
+ return
+
+ if(!has_chemicals(10))
+ to_chat(src, "You don't have enough chemicals to do that.")
+ return
+
+ if(!invisible)
+ to_chat(src, "You focus your chameleon skin to blend into the environment.")
+ invisible = TRUE
+ else
+ to_chat(src, "You stop your camouflage.")
+ invisible = FALSE
+
+/mob/living/simple_animal/horror/proc/freeze_victim()
+ if(world.time - used_freeze < 150)
+ to_chat(src, "You cannot use that ability again so soon.")
+ return
+
+ if(victim)
+ to_chat(src, "You cannot do that from within a host body.")
+ return
+
+ if(!can_use_ability())
+ return
+
+ var/list/choices = list()
+ for(var/mob/living/carbon/C in view(1,src))
+ if(C.stat == CONSCIOUS)
+ choices += C
+
+ if(!choices.len)
+ return
+
+ if(!src || stat != CONSCIOUS || victim || (world.time - used_freeze < 150))
+ return
+
+ layer = MOB_LAYER
+ for (var/mob/living/carbon/M in range(1, src))
+ if(!M || !Adjacent(M))
+ return
+
+ if(horrorupgrades["paralysis"])
+ playsound(loc, "sound/effects/sparks4.ogg", 30, 1, -1)
+ M.Stun(50)
+ M.SetSleeping(70)
+ M.electrocute_act(15, src, 1, FALSE, FALSE, FALSE, 1, FALSE)
+ else
+ to_chat(M, "You feel something wrapping around your leg, pulling you down!")
+ playsound(loc, "sound/weapons/whipgrab.ogg", 30, 1, -1)
+ M.Stun(50)
+ M.Knockdown(70)
+ used_freeze = world.time
+
+/mob/living/simple_animal/horror/proc/is_leaving()
+ return leaving
+
+/mob/living/simple_animal/horror/proc/release_victim()
+ if(!victim)
+ to_chat(src, "You are not inside a host body.")
+ return
+
+ if(!can_use_ability())
+ return
+
+ if(leaving)
+ leaving = FALSE
+ to_chat(src, "You decide against leaving your host.")
+ return
+
+ to_chat(src, "You begin disconnecting from [victim]'s synapses and prodding at their internal ear canal.")
+
+ if(victim.stat != DEAD && !horrorupgrades["invisible_exit"])
+ to_chat(victim, "An odd, uncomfortable pressure begins to build inside your skull, behind your ear...")
+
+ leaving = TRUE
+ if(do_after(src, 100, target = victim, extra_checks = CALLBACK(src, .proc/is_leaving), stayStill = FALSE))
+ release_host()
+
+/mob/living/simple_animal/horror/proc/release_host()
+ if(!victim || !src || QDELETED(victim) || QDELETED(src))
+ return
+
+ if(controlling)
+ return
+
+ if(stat != CONSCIOUS)
+ to_chat(src, "You cannot release your host in your current state.")
+ return
+
+ if(horrorupgrades["invisible_exit"])
+ alpha = 60
+ if(has_ability("chameleon"))
+ invisible = TRUE
+ Update_Invisibility_Button()
+ to_chat(src, "You silently wiggle out of [victim]'s ear and plop to the ground before vanishing via reflective solution that covers you.")
+ else
+ to_chat(src, "You wiggle out of [victim]'s ear and plop to the ground.")
+ if(victim.mind)
+ if(!horrorupgrades["invisible_exit"])
+ to_chat(victim, "Something slimy wiggles out of your ear and plops to the ground!")
+
+ leaving = FALSE
+
+ leave_victim()
+
+/mob/living/simple_animal/horror/proc/leave_victim()
+ if(!victim)
+ return
+
+ if(controlling)
+ detatch()
+
+ forceMove(get_turf(victim))
+
+ reset_perspective(null)
+ machine = null
+
+ victim.reset_perspective(null)
+ victim.machine = null
+
+ var/mob/living/V = victim
+ remove_verb(V, /mob/living/proc/horror_comm)
+ talk_to_horror_action.Remove(victim)
+
+ for(var/obj/item/horrortentacle/T in victim)
+ victim.visible_message("[victim]'s tentacle transforms back!", "Your tentacle disappears!")
+ playsound(victim, 'sound/effects/blobattack.ogg', 30, 1)
+ qdel(T)
+ victim = null
+
+ RefreshAbilities()
+ return
+
+/mob/living/simple_animal/horror/proc/jumpstart()
+ if(!victim)
+ to_chat(src, "You need a host to be able to use this.")
+ return
+
+ if(!can_use_ability())
+ return
+
+ if(victim.stat != DEAD)
+ to_chat(src, "Your host is already alive!")
+ return
+
+ if(!has_chemicals(250))
+ to_chat(src, "You need 250 chemicals to use this!")
+ return
+
+ if(victim.stat == DEAD)
+ victim.tod = null
+ victim.setToxLoss(0)
+ victim.setOxyLoss(0)
+ victim.setCloneLoss(0)
+ victim.SetUnconscious(0)
+ victim.SetStun(0)
+ victim.SetKnockdown(0)
+ victim.radiation = 0
+ victim.heal_overall_damage(victim.getBruteLoss(), victim.getFireLoss())
+ victim.reagents.clear_reagents()
+ for(var/organ in victim.internal_organs)
+ var/obj/item/organ/O = organ
+ O.setOrganDamage(0)
+ victim.restore_blood()
+ victim.remove_all_embedded_objects()
+ victim.revive()
+ log_game("[src]/([src.ckey]) has revived [victim]/([victim.ckey]")
+ chemicals -= 250
+ to_chat(src, "You send a jolt of energy to your host, reviving them!")
+ victim.grab_ghost(force = TRUE) //brings the host back, no eggscape
+ to_chat(victim, "You bolt upright, gasping for breath!")
+
+/mob/living/simple_animal/horror/proc/view_memory()
+ if(!victim)
+ to_chat(src, "You need a host to be able to use this.")
+ return
+
+ if(!can_use_ability())
+ return
+
+ if(victim.stat == DEAD)
+ to_chat(src, "Your host brain is unresponsive. They are dead!")
+ return
+
+ if(prob(20))
+ to_chat(victim, "You suddenly feel your memory being tangled with...")//chance to alert the victim
+
+ if(victim.mind)
+ var/datum/mind/suckedbrain = victim.mind
+ to_chat(src, "You skim through [victim]'s memories...[suckedbrain.memory]")
+ for(var/A in suckedbrain.antag_datums)
+ var/datum/antagonist/antag_types = A
+ var/list/all_objectives = antag_types.objectives.Copy()
+ if(antag_types.antag_memory)
+ to_chat(src, "[antag_types.antag_memory]")
+ if(LAZYLEN(all_objectives))
+ to_chat(src, "Objectives:")
+ var/obj_count = 1
+ for(var/O in all_objectives)
+ var/datum/objective/objective = O
+ to_chat(src, "Objective #[obj_count++]: [objective.explanation_text]")
+ var/list/datum/mind/other_owners = objective.get_owners() - suckedbrain
+ if(other_owners.len)
+ for(var/mind in other_owners)
+ var/datum/mind/M = mind
+ to_chat(src, "Conspirator: [M.name]")
+
+ var/list/recent_speech = list()
+ var/list/say_log = list()
+ var/log_source = victim.logging
+ for(var/log_type in log_source)
+ var/nlog_type = text2num(log_type)
+ if(nlog_type & LOG_SAY)
+ var/list/reversed = log_source[log_type]
+ if(islist(reversed))
+ say_log = reverseRange(reversed.Copy())
+ break
+ if(LAZYLEN(say_log))
+ for(var/spoken_memory in say_log)
+ if(recent_speech.len >= 5)//up to 5 random lines of speech, favoring more recent speech
+ break
+ if(prob(50))
+ recent_speech[spoken_memory] = say_log[spoken_memory]
+ if(recent_speech.len)
+ to_chat(src, "You catch some drifting memories of their past conversations...")
+ for(var/spoken_memory in recent_speech)
+ to_chat(src, "[recent_speech[spoken_memory]]")
+ var/mob/living/carbon/human/H = victim
+ var/datum/dna/the_dna = H.has_dna()
+ if(the_dna)
+ to_chat(src, "You uncover that [H.p_their()] true identity is [the_dna.real_name].")
+
+/mob/living/simple_animal/horror/proc/is_bonding()
+ return bonding
+
+/mob/living/simple_animal/horror/proc/bond_brain()
+ if(!victim)
+ to_chat(src, "You are not inside a host body.")
+ return
+
+ if(!can_use_ability())
+ return
+
+ if(victim.stat == DEAD)
+ to_chat(src, "This host lacks enough brain function to control.")
+ return
+
+ if(bonding)
+ bonding = FALSE
+ to_chat(src, "You stop attempting to take control of your host.")
+ return
+
+ to_chat(src, "You begin delicately adjusting your connection to the host brain...")
+
+ if(QDELETED(src) || QDELETED(victim))
+ return
+
+ bonding = TRUE
+
+ var/delay = 200
+ if(horrorupgrades["fast_control"])
+ delay -= 120
+ if(do_after(src, delay, target = victim, extra_checks = CALLBACK(src, .proc/is_bonding), stayStill = FALSE))
+ assume_control()
+
+/mob/living/simple_animal/horror/proc/assume_control()
+ if(!victim || !src || controlling || victim.stat == DEAD)
+ return
+ if(is_servant_of_ratvar(victim) || iscultist(victim))
+ to_chat(src, "[victim]'s mind seems to be blocked by some unknown force!")
+ bonding = FALSE
+ return
+ if(HAS_TRAIT(victim, TRAIT_MINDSHIELD))
+ to_chat(src, "[victim]'s mind seems to be shielded from your influence!")
+ bonding = FALSE
+ return
+ else
+ RegisterSignal(victim, COMSIG_MOB_APPLY_DAMAGE, .proc/hit_detatch)
+ log_game("[src]/([src.ckey]) assumed control of [victim]/([victim.ckey] with eldritch powers.")
+ to_chat(src, "You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system.")
+ to_chat(victim, "You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.")
+
+ qdel(host_brain)
+ host_brain = new(src)
+ host_brain.H = src
+ victim.mind.transfer_to(host_brain)
+ if(victim.key)
+ host_brain.key = victim.key
+
+ to_chat(host_brain, "You are trapped in your own mind. You feel that there must be a way to resist!")
+
+ mind.transfer_to(victim)
+
+ bonding = FALSE
+ controlling = TRUE
+
+ remove_verb(victim, /mob/living/proc/horror_comm)
+ talk_to_horror_action.Remove(victim)
+ GrantControlActions()
+
+ victim.med_hud_set_status()
+ if(target)
+ victim.apply_status_effect(/datum/status_effect/agent_pinpointer/horror)
+ for(var/datum/status_effect/agent_pinpointer/horror/status in victim.status_effects)
+ status.scan_target = target
+
+/mob/living/carbon/proc/release_control()
+ var/mob/living/simple_animal/horror/B = has_horror_inside()
+ if(B && B.host_brain)
+ to_chat(src, "You withdraw your probosci, releasing control of [B.host_brain]")
+ B.detatch()
+
+//Check for brain worms in head.
+/mob/proc/has_horror_inside()
+ for(var/I in contents)
+ if(ishorror(I))
+ return I
+ return FALSE
+
+/mob/living/simple_animal/horror/proc/hit_detatch()
+ if(victim.health <= 75)
+ detatch()
+ to_chat(src, "Upon taking damage, [victim]s brain detected danger, and hastily took over.")
+ to_chat(victim, "Your body is under attack, your brain immediately took over!")
+
+/mob/living/simple_animal/horror/proc/detatch()
+ if(!victim || !controlling)
+ return
+
+ controlling = FALSE
+ UnregisterSignal(victim, COMSIG_MOB_APPLY_DAMAGE)
+ add_verb(victim, /mob/living/proc/horror_comm)
+ RemoveControlActions()
+ RefreshAbilities()
+ talk_to_horror_action.Grant(victim)
+
+ victim.med_hud_set_status()
+ victim.remove_status_effect(/datum/status_effect/agent_pinpointer/horror)
+
+ victim.mind.transfer_to(src)
+ if(host_brain)
+ host_brain.mind.transfer_to(victim)
+ if(host_brain.key)
+ victim.key = host_brain.key
+
+ log_game("[src]/([src.ckey]) released control of [victim]/([victim.ckey]")
+ qdel(host_brain)
+
+/mob/living/simple_animal/horror/proc/Update_Invisibility_Button()
+ var/datum/action/innate/horror/action = has_ability("chameleon")
+ if(action)
+ action.button_icon_state = "horror_sneak_[invisible ? "true" : "false"]"
+ action.UpdateButtonIcon()
+
+/mob/living/simple_animal/horror/proc/GrantHorrorActions()
+ for(var/A in horrorabilities)
+ var/datum/action/innate/horror/ability = horrorabilities[A]
+ if("horror" in ability.category)
+ ability.Grant(src)
+
+/mob/living/simple_animal/horror/proc/RemoveHorrorActions()
+ for(var/A in horrorabilities)
+ var/datum/action/innate/horror/ability = horrorabilities[A]
+ if("horror" in ability.category)
+ ability.Remove(src)
+
+/mob/living/simple_animal/horror/proc/GrantInfestActions()
+ for(var/A in horrorabilities)
+ var/datum/action/innate/horror/ability = horrorabilities[A]
+ if("infest" in ability.category)
+ ability.Grant(src)
+
+/mob/living/simple_animal/horror/proc/RemoveInfestActions()
+ for(var/A in horrorabilities)
+ var/datum/action/innate/horror/ability = horrorabilities[A]
+ if("infest" in ability.category)
+ ability.Remove(src)
+
+/mob/living/simple_animal/horror/proc/GrantControlActions()
+ for(var/A in horrorabilities)
+ var/datum/action/innate/horror/ability = horrorabilities[A]
+ if("control" in ability.category)
+ ability.Grant(victim)
+
+/mob/living/simple_animal/horror/proc/RemoveControlActions()
+ for(var/A in horrorabilities)
+ var/datum/action/innate/horror/ability = horrorabilities[A]
+ if("control" in ability.category)
+ ability.Remove(victim)
+
+/mob/living/simple_animal/horror/proc/RefreshAbilities() //control abilities technically don't belong to horror
+ if(victim)
+ RemoveHorrorActions()
+ GrantInfestActions()
+ else
+ RemoveInfestActions()
+ GrantHorrorActions()
\ No newline at end of file
diff --git a/code/modules/antagonists/horror/horror_abilities_and_upgrades.dm b/code/modules/antagonists/horror/horror_abilities_and_upgrades.dm
new file mode 100644
index 000000000000..7dccc7b97869
--- /dev/null
+++ b/code/modules/antagonists/horror/horror_abilities_and_upgrades.dm
@@ -0,0 +1,454 @@
+//ABILITIES
+
+/datum/action/innate/horror
+ background_icon_state = "bg_ecult"
+ icon_icon = 'icons/mob/actions/actions_horror.dmi'
+ var/id //The ability's ID, for giving, taking and such
+ var/blacklisted = FALSE //If the ability can't be mutated
+ var/soul_price = 0 //How much souls the ability costs to buy; if this is 0, it isn't listed on the catalog
+ var/chemical_cost = 0 //How much chemicals the ability costs to use
+ var/mob/living/simple_animal/horror/B //Horror holding the ability
+ var/category //category for when the ability is active, "horror" is for creature, "infest" is during infestation, "controlling" is when a horror is controlling a body
+
+/datum/action/innate/horror/New(Target, horror)
+ B = horror
+ ..()
+
+/datum/action/innate/horror/IsAvailable()
+ if(!B)
+ return
+ if(!B.has_chemicals(chemical_cost))
+ return
+ . = ..()
+
+/datum/action/innate/horror/mutate
+ name = "Mutate"
+ id = "mutate"
+ desc = "Use consumed souls to mutate your abilities."
+ button_icon_state = "mutate"
+ blacklisted = TRUE
+ category = list("horror")
+
+/datum/action/innate/horror/mutate/Activate()
+ to_chat(usr, "You focus on mutating your body...")
+ B.ui_interact(usr)
+ return TRUE
+
+/datum/action/innate/horror/seek_soul
+ name = "Seek target soul"
+ id = "seek_soul"
+ desc = "Search for a soul weak enough for you to consume."
+ button_icon_state = "seek_soul"
+ blacklisted = TRUE
+ category = list("horror","infest")
+
+/datum/action/innate/horror/seek_soul/Activate()
+ B.SearchTarget()
+
+/datum/action/innate/horror/consume_soul
+ name = "Consume soul"
+ id = "consume_soul"
+ desc = "Consume your target's soul."
+ button_icon_state = "consume_soul"
+ blacklisted = TRUE
+ category = list("infest")
+
+/datum/action/innate/horror/consume_soul/Activate()
+ B.ConsumeSoul()
+
+/datum/action/innate/horror/talk_to_host
+ name = "Converse with Host"
+ id = "talk_to_host"
+ desc = "Send a silent message to your host."
+ button_icon_state = "talk_to_host"
+ blacklisted = TRUE
+ category = list("infest")
+
+/datum/action/innate/horror/talk_to_host/Activate()
+ B.Communicate()
+
+/datum/action/innate/horror/infest_host
+ name = "Infest"
+ id = "infest"
+ desc = "Infest a suitable humanoid host."
+ button_icon_state = "infest"
+ blacklisted = TRUE
+ category = list("horror")
+
+/datum/action/innate/horror/infest_host/Activate()
+ B.infect_victim()
+
+/datum/action/innate/horror/toggle_hide
+ name = "Toggle Hide"
+ id = "toggle_hide"
+ desc = "Become invisible to the common eye. Toggled on or off."
+ button_icon_state = "horror_hiding_false"
+ blacklisted = TRUE
+ category = list("horror")
+
+/datum/action/innate/horror/toggle_hide/Activate()
+ B.hide()
+ button_icon_state = "horror_hiding_[B.hiding ? "true" : "false"]"
+ UpdateButtonIcon()
+
+/datum/action/innate/horror/talk_to_horror
+ name = "Converse with Horror"
+ id = "talk_to_horror"
+ desc = "Communicate mentally with your horror."
+ button_icon_state = "talk_to_horror"
+ blacklisted = TRUE
+
+/datum/action/innate/horror/talk_to_horror/Activate()
+ var/mob/living/O = owner
+ O.horror_comm()
+
+/datum/action/innate/horror/talk_to_brain
+ name = "Converse with Trapped Mind"
+ id = "talk_to_brain"
+ desc = "Communicate mentally with the trapped mind of your host."
+ button_icon_state = "talk_to_trapped_mind"
+ blacklisted = TRUE
+ category = list("control")
+
+/datum/action/innate/horror/talk_to_brain/Activate()
+ B.victim.trapped_mind_comm()
+
+/datum/action/innate/horror/take_control
+ name = "Assume Control"
+ id = "take_control"
+ desc = "Fully connect to the brain of your host."
+ button_icon_state = "horror_brain"
+ blacklisted = TRUE
+ category = list("infest")
+
+/datum/action/innate/horror/take_control/Activate()
+ B.bond_brain()
+
+/datum/action/innate/horror/give_back_control
+ name = "Release Control"
+ id = "release_control"
+ desc = "Release control of your host's body."
+ button_icon_state = "horror_leave"
+ blacklisted = TRUE
+ category = list("control")
+
+/datum/action/innate/horror/give_back_control/Activate()
+ B.victim.release_control()
+
+/datum/action/innate/horror/leave_body
+ name = "Release Host"
+ id = "leave_body"
+ desc = "Slither out of your host."
+ button_icon_state = "horror_leave"
+ blacklisted = TRUE
+ category = list("infest")
+
+/datum/action/innate/horror/leave_body/Activate()
+ B.release_victim()
+
+/datum/action/innate/horror/make_chems
+ name = "Secrete chemicals"
+ id = "make_chems"
+ desc = "Push some chemicals into your host's bloodstream."
+ icon_icon = 'icons/obj/chemical.dmi'
+ button_icon_state = "minidispenser"
+ blacklisted = TRUE
+ category = list("infest")
+
+/datum/action/innate/horror/make_chems/Activate()
+ B.secrete_chemicals()
+
+/datum/action/innate/horror/freeze_victim
+ name = "Knockdown victim"
+ id = "freeze_victim"
+ desc = "Use your tentacle to trip a victim, stunning for a short duration."
+ button_icon_state = "trip"
+ blacklisted = TRUE
+ category = list("horror")
+
+/datum/action/innate/horror/freeze_victim/Activate()
+ B.freeze_victim()
+ UpdateButtonIcon()
+ addtimer(CALLBACK(src, .proc/UpdateButtonIcon), 150)
+
+/datum/action/innate/horror/freeze_victim/IsAvailable()
+ if(world.time - B.used_freeze < 150)
+ return FALSE
+ else
+ return ..()
+
+//non-default abilities, can be mutated
+
+/datum/action/innate/horror/tentacle
+ name = "Grow Tentacle"
+ id = "tentacle"
+ desc = "Makes your host grow a tentacle in their arm. Costs 50 chemicals to activate."
+ button_icon_state = "tentacle"
+ chemical_cost = 50
+ category = list("infest", "control")
+ soul_price = 2
+
+/datum/action/innate/horror/tentacle/IsAvailable()
+ if(!active && !B.has_chemicals(chemical_cost))
+ return FALSE
+ return ..()
+
+/datum/action/innate/horror/tentacle/New()
+ ..()
+ START_PROCESSING(SSfastprocess, src)
+
+/datum/action/innate/horror/tentacle/Destroy()
+ STOP_PROCESSING(SSfastprocess, src)
+ return ..()
+
+/datum/action/innate/horror/tentacle/process()
+ ..()
+ active = locate(/obj/item/horrortentacle) in B.victim
+ UpdateButtonIcon()
+
+
+/datum/action/innate/horror/tentacle/Activate()
+ B.use_chemicals(50)
+ B.victim.visible_message("[B.victim]'s arm contorts into tentacles!", "Your arm transforms into a giant tentacle. Examine it to see possible uses.")
+ playsound(B.victim, 'sound/effects/blobattack.ogg', 30, 1)
+ to_chat(B, "You transform [B.victim]'s arm into a tentacle!")
+ var/obj/item/horrortentacle/T = new
+ B.victim.put_in_hands(T)
+ return TRUE
+
+/datum/action/innate/horror/tentacle/Deactivate()
+ B.victim.visible_message("[B.victim]'s tentacle transforms back!", "Your tentacle disappears!")
+ playsound(B.victim, 'sound/effects/blobattack.ogg', 30, 1)
+ to_chat(B, "You transform [B.victim]'s arm back.")
+ for(var/obj/item/horrortentacle/T in B.victim)
+ qdel(T)
+ return TRUE
+
+/datum/action/innate/horror/transfer_host
+ name = "Transfer to another Host"
+ id = "transfer_host"
+ desc = "Move into another host directly. Grabbing makes the process faster."
+ button_icon_state = "transfer_host"
+ category = list("infest", "control")
+ soul_price = 1
+ var/transferring = FALSE
+
+/datum/action/innate/horror/transfer_host/proc/is_transferring(var/mob/living/carbon/C)
+ return transferring && C in range(1, B.victim)
+
+/datum/action/innate/horror/transfer_host/Activate()
+ if(transferring)
+ transferring = FALSE
+ to_chat(src, "You decide against leaving your host.")
+ return
+
+ var/list/choices = list()
+ for(var/mob/living/carbon/C in range(1,B.victim))
+ if(C!=B.victim && C.Adjacent(B.victim))
+ choices += C
+
+ if(!choices.len)
+ return
+ var/mob/living/carbon/C = choices.len > 1 ? input(owner,"Who do you wish to infest?") in null|choices : choices[1]
+ if(!C || !B)
+ return
+ if(!C.Adjacent(B.victim))
+ return
+ var/obj/item/bodypart/head/head = C.get_bodypart(BODY_ZONE_HEAD)
+ if(!head)
+ to_chat(owner, "[C] doesn't have a head!")
+ return
+ var/hasbrain = FALSE
+ for(var/obj/item/organ/brain/X in C.internal_organs)
+ hasbrain = TRUE
+ break
+ if(!hasbrain)
+ to_chat(owner, "[C] doesn't have a brain! ")
+ return
+ if((!C.key || !C.mind) && C != B.target.current)
+ to_chat(owner, "[C]'s mind seems unresponsive. Try someone else!")
+ return
+ if(C.has_horror_inside())
+ to_chat(owner, "[C] is already infested!")
+ return
+
+ to_chat(owner, "You move your tentacles away from [B.victim] and begin to transfer to [C]...")
+ var/delay = 20 SECONDS
+ var/silent
+ if(B.victim.pulling != C)
+ silent = TRUE
+ else
+ switch(B.victim.grab_state)
+ if(GRAB_PASSIVE)
+ delay = 10 SECONDS
+ if(GRAB_AGGRESSIVE)
+ delay = 5 SECONDS
+ if(GRAB_NECK)
+ delay = 3 SECONDS
+ else
+ delay = 1 SECONDS
+
+ transferring = TRUE
+ if(!do_after(B.victim, delay, target = C, extra_checks = CALLBACK(src, .proc/is_transferring, C), stayStill = FALSE))
+ to_chat(owner, "As [C] moves away, your transfer gets interrupted!")
+ transferring = FALSE
+ return
+ transferring = FALSE
+ if(!C || !B || !(C in range(1,B.victim)))
+ return
+ B.leave_victim()
+ B.Infect(C)
+ if(!silent)
+ to_chat(C, "Something slimy wiggles into your ear!")
+ playsound(B, 'sound/effects/blobattack.ogg', 30, 1)
+
+/datum/action/innate/horror/jumpstart_host
+ name = "Revive Host"
+ id = "jumpstart_host"
+ desc = "Bring your host back to life."
+ button_icon_state = "revive"
+ category = list("infest")
+ soul_price = 2
+
+/datum/action/innate/horror/jumpstart_host/Activate()
+ B.jumpstart()
+
+/datum/action/innate/horror/view_memory
+ name = "View Memory"
+ id = "view_memory"
+ desc = "Read recent memory of the host you're inside of."
+ button_icon_state = "view_memory"
+ category = list("infest")
+ soul_price = 1
+
+/datum/action/innate/horror/view_memory/Activate()
+ B.view_memory()
+
+/datum/action/innate/horror/chameleon
+ name = "Chameleon Skin"
+ id = "chameleon"
+ desc = "Adjust your skin color to blend into environment. Costs 5 chemicals per tick, also stopping chemical regeneration while active. Attacking stops the invisibility completely."
+ button_icon_state = "horror_sneak_false"
+ category = list("horror")
+ soul_price = 1
+
+/datum/action/innate/horror/chameleon/Activate()
+ B.go_invisible()
+ button_icon_state = "horror_sneak_[B.invisible ? "true" : "false"]"
+ UpdateButtonIcon()
+
+//UPGRADES
+/datum/horror_upgrade
+ var/name = "horror upgrade"
+ var/desc = "This is an upgrade."
+ var/id
+ var/soul_price = 0 //How much souls an upgrade costs to buy
+ var/mob/living/simple_animal/horror/B //Horror holding the upgrades
+
+/datum/horror_upgrade/proc/unlock()
+ if(!B)
+ return
+ apply_effects()
+ qdel(src)
+ return TRUE
+
+/datum/horror_upgrade/New(owner)
+ ..()
+ B = owner
+
+/datum/horror_upgrade/proc/apply_effects()
+ return
+
+//Upgrades the stun ability
+/datum/horror_upgrade/paralysis
+ name = "Electrocharged tentacle"
+ id = "paralysis"
+ desc = "Empowers your tentacle knockdown ability by giving it extra charge, knocking your victim down unconcious."
+ soul_price = 3
+
+/datum/horror_upgrade/paralysis/apply_effects()
+ var/datum/action/innate/horror/A = B.has_ability("freeze_victim")
+ if(A)
+ A.name = "Paralyze Victim"
+ A.desc = "Shock a victim with an electrically charged tentacle."
+ A.button_icon_state = "paralyze"
+ B.update_action_buttons()
+
+//Increases chemical regeneration rate by 2
+/datum/horror_upgrade/chemical_regen
+ name = "Efficient chemical glands"
+ id = "chem_regen"
+ desc = "Your chemical glands work more efficiently. Unlocking this increases your chemical regeneration."
+ soul_price = 2
+
+/datum/horror_upgrade/chemical_regen/apply_effects()
+ B.chem_regen_rate += 2
+
+//Lets horror regenerate chemicals outside of a host
+/datum/horror_upgrade/nohost_regen
+ name = "Independent chemical glands"
+ id = "nohost_regen"
+ desc = "Your chemical glands become less parasitic and let you regenerate chemicals on their own without need for a host."
+ soul_price = 2
+
+//Lets horror regenerate health
+/datum/horror_upgrade/regen
+ name = "Regenerative skin"
+ id = "regen"
+ desc = "Your skin adapts to sustained damage and slowly regenerates itself, healing your wounds over time."
+ soul_price = 1
+
+//Triples horror's health pool
+/datum/horror_upgrade/hp_up
+ name = "Rhino skin" //Horror can....roll?
+ id = "hp_up"
+ desc = "Your skin becomes hard as rock, greatly increasing your maximum health - and odds of survival outside of host."
+ soul_price = 2
+
+/datum/horror_upgrade/hp_up/apply_effects()
+ B.health = round(min(B.maxHealth,B.health * 3))
+ B.maxHealth = round(B.maxHealth * 3)
+
+//Makes horror almost invisible for a short time after leaving a host
+/datum/horror_upgrade/invisibility
+ name = "Reflective fluids"
+ id = "invisible_exit"
+ desc = "You build up reflective solution inside host's brain. Upon exiting a host, you're briefly covered in it, rendering you near invisible for a few seconds. This mutation also makes the host unable to notice you exiting it directly."
+ soul_price = 2
+
+//Increases melee damage to 20
+/datum/horror_upgrade/dmg_up
+ name = "Sharpened teeth"
+ id = "dmg_up"
+ desc = "Your teeth become sharp blades, this mutation increases your melee damage."
+ soul_price = 2
+
+/datum/horror_upgrade/dmg_up/apply_effects()
+ B.attacktext = "crushes"
+ B.attack_sound = 'sound/weapons/pierce_slow.ogg' //chunky
+ B.melee_damage_lower += 10
+ B.melee_damage_upper += 10
+
+//Expands the reagent selection horror can make
+/datum/horror_upgrade/upgraded_chems
+ name = "Advanced reagent synthesis"
+ id = "upgraded_chems"
+ desc = "Lets you synthetize adrenaline, salicyclic acid, oxandrolone, pentetic acid and rezadone into your host."
+ soul_price = 2
+
+/datum/horror_upgrade/upgraded_chems/apply_effects()
+ B.horror_chems += list(/datum/horror_chem/adrenaline,/datum/horror_chem/sal_acid,/datum/horror_chem/oxandrolone,/datum/horror_chem/pen_acid,/datum/horror_chem/rezadone)
+
+//faster mind control
+/datum/horror_upgrade/fast_control
+ name = "Precise probosci"
+ id = "fast_control"
+ desc = "Your probosci become more precise, allowing you to take control over your host's brain noticably faster."
+ soul_price = 2
+
+//makes it longer for host to snap out of mind control
+/datum/horror_upgrade/deep_control
+ name = "Insulated probosci"
+ id = "deep_control"
+ desc = "Your probosci become insulated, protecting them from neural shocks. This makes it harder for the host to regain control over their body."
+ soul_price = 2
\ No newline at end of file
diff --git a/code/modules/antagonists/horror/horror_chemicals.dm b/code/modules/antagonists/horror/horror_chemicals.dm
new file mode 100644
index 000000000000..71b42fca9676
--- /dev/null
+++ b/code/modules/antagonists/horror/horror_chemicals.dm
@@ -0,0 +1,96 @@
+/mob/living/simple_animal/horror/Topic(href, href_list, hsrc)
+ if(href_list["horror_use_chem"])
+ locate(href_list["src"])
+ if(!istype(src, /mob/living/simple_animal/horror))
+ return
+
+ var/topic_chem = href_list["horror_use_chem"]
+ var/datum/horror_chem/C
+
+ for(var/datum in typesof(/datum/horror_chem))
+ var/datum/horror_chem/test = new datum()
+ if(test.chemname == topic_chem)
+ C = test
+ break
+
+ if(!istype(C, /datum/horror_chem))
+ return
+
+ if(!C || !victim || controlling || !src || stat)
+ return
+
+ if(!istype(C, /datum/horror_chem))
+ return
+
+ if(chemicals < C.chemuse)
+ to_chat(src, "You need [C.chemuse] chemicals stored to use this chemical!")
+ return
+
+ to_chat(src, "You squirt a measure of [C.chemname] from your reservoirs into [victim]'s bloodstream.")
+ victim.reagents.add_reagent(C.R, C.quantity)
+ chemicals -= C.chemuse
+ log_game("[src]/([src.ckey]) has injected [C.chemname] into their host [victim]/([victim.ckey])")
+
+ src << output(chemicals, "ViewHorror\ref[src]Chems.browser:update_chemicals")
+
+ ..()
+
+/datum/horror_chem
+ var/chemname
+ var/chem_desc = "This is a chemical"
+ var/datum/reagent/R
+ var/chemuse = 30
+ var/quantity = 10
+
+/datum/horror_chem/epinephrine
+ chemname = "epinephrine"
+ R = /datum/reagent/medicine/epinephrine
+ chem_desc = "Stabilizes critical condition and slowly restores oxygen damage."
+
+/datum/horror_chem/mannitol
+ chemname = "mannitol"
+ R = /datum/reagent/medicine/mannitol
+ chem_desc = "Heals brain damage."
+
+/datum/horror_chem/bicaridine
+ chemname = "bicaridine"
+ R = /datum/reagent/medicine/bicaridine
+ chem_desc = "Heals brute damage."
+
+/datum/horror_chem/kelotane
+ chemname = "kelotane"
+ R = /datum/reagent/medicine/kelotane
+ chem_desc = "Heals burn damage."
+
+/datum/horror_chem/charcoal
+ chemname = "charcoal"
+ R = /datum/reagent/medicine/charcoal
+ chem_desc = "Slowly heals toxin damage, while also slowly removing any other chemicals."
+
+/datum/horror_chem/adrenaline
+ chemname = "adrenaline"
+ R = /datum/reagent/medicine/changelingadrenaline
+ chemuse = 100
+ chem_desc = "Stimulates the brain, shrugging off effect of stuns while regenerating stamina."
+
+/datum/horror_chem/rezadone
+ chemname = "rezadone"
+ R = /datum/reagent/medicine/rezadone
+ chemuse = 50
+ chem_desc = "Heals cellular damage."
+
+/datum/horror_chem/pen_acid
+ chemname = "pentetic acid"
+ R = /datum/reagent/medicine/pen_acid
+ chemuse = 50
+ chem_desc = "Reduces massive amounts of radiation and toxin damage while purging other chemicals from the body."
+
+/datum/horror_chem/sal_acid
+ chemname = "salicyclic acid"
+ R = /datum/reagent/medicine/sal_acid
+ chem_desc = "Stimulates the healing of severe bruises. Rapidly heals severe bruising and slowly heals minor ones."
+
+/datum/horror_chem/oxandrolone
+ chemname = "oxandrolone"
+ R = /datum/reagent/medicine/oxandrolone
+ chem_desc = "Stimulates the healing of severe burns. Rapidly heals severe burns and slowly heals minor ones."
\ No newline at end of file
diff --git a/code/modules/antagonists/horror/horror_datums.dm b/code/modules/antagonists/horror/horror_datums.dm
new file mode 100644
index 000000000000..12203b7c39bc
--- /dev/null
+++ b/code/modules/antagonists/horror/horror_datums.dm
@@ -0,0 +1,348 @@
+//ANTAG DATUMS
+/datum/antagonist/horror
+ name = "Horror"
+ show_in_antagpanel = TRUE
+ prevent_roundtype_conversion = FALSE
+ show_name_in_check_antagonists = TRUE
+ show_to_ghosts = TRUE
+ var/datum/mind/summoner
+
+/datum/antagonist/horror/on_gain()
+ . = ..()
+ give_objectives()
+ if(ishorror(owner) && owner.current.mind)
+ var/mob/living/simple_animal/horror/H = owner.current
+ H.update_horror_hud()
+
+/datum/antagonist/horror/proc/give_objectives()
+ if(summoner)
+ var/datum/objective/newobjective = new
+ newobjective.explanation_text = "Serve your summoner, [summoner.name]."
+ newobjective.owner = owner
+ newobjective.completed = TRUE
+ objectives += newobjective
+ else
+ //succ some souls
+ var/datum/objective/horrorascend/ascend = new
+ ascend.owner = owner
+ ascend.target_amount = rand(6, 10)
+ objectives += ascend
+ ascend.update_explanation_text()
+
+ //looking for antagonist we can assist
+ var/list/possible_targets = list()
+ for(var/datum/mind/M in SSticker.minds)
+ if(M.current && M.current.stat != DEAD)
+ if(ishuman(M.current))
+ if(M.special_role)
+ possible_targets += M
+
+ if(possible_targets.len)
+ var/datum/mind/M = pick(possible_targets)
+ var/datum/objective/protect/O = new
+ O.owner = owner
+ O.target = M
+ O.explanation_text = "Protect and assist \the [M.current.real_name], the [M.assigned_role]."
+ objectives += O
+
+
+ //don't die while you're at is
+ var/datum/objective/survive/survive = new
+ survive.owner = owner
+ objectives += survive
+
+/datum/objective/horrorascend
+ name = "consume souls"
+
+/datum/objective/horrorascend/update_explanation_text()
+ . = ..()
+ explanation_text = "Consume [target_amount] souls."
+
+/datum/objective/horrorascend/check_completion()
+ var/mob/living/simple_animal/horror/H = owner.current
+ if(istype(H) && H.consumed_souls > target_amount)
+ return TRUE
+ return FALSE
+
+
+//SPAWNER
+/obj/item/horrorspawner
+ name = "suspicious pet carrier"
+ desc = "It contains some sort of creature inside. You can see tentacles sticking out of it."
+ icon = 'icons/obj/pet_carrier.dmi'
+ lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/items_righthand.dmi'
+ item_state = "pet_carrier"
+ icon_state = "pet_carrier_occupied"
+ var/used = FALSE
+ color = rgb(130, 105, 160)
+
+/obj/item/horrorspawner/attack_self(mob/living/user)
+ if(used)
+ to_chat(user, "The pet carrier appears unresponsive.")
+ return
+ used = TRUE
+ to_chat(user, "You're attempting to wake up the creature inside the box...")
+ sleep(5 SECONDS)
+ var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the eldritch horror in service of [user.real_name]?", ROLE_HORROR, null, FALSE, 100)
+ if(LAZYLEN(candidates))
+ var/mob/dead/observer/C = pick(candidates)
+ var/mob/living/simple_animal/horror/H = new /mob/living/simple_animal/horror(get_turf(src))
+ H.key = C.key
+ H.mind.enslave_mind_to_creator(user)
+ H.mind.add_antag_datum(C)
+ H.mind.memory += "You are [H.truename], an eldritch horror. Consume souls to evolve.
"
+ var/datum/antagonist/horror/S = new
+ S.summoner = user.mind
+ S.antag_memory += "[user.mind] woke you from your eternal slumber. Aid them in their objectives as a token of gratitude.
"
+ H.mind.add_antag_datum(S)
+ log_game("[key_name(user)] has summoned [key_name(H)], an eldritch horror.")
+ to_chat(user, "[H.truename] has awoken into your service!")
+ used = TRUE
+ icon_state = "pet_carrier_open"
+ sleep(5)
+ var/obj/item/horrorsummonhorn/horn = new /obj/item/horrorsummonhorn(get_turf(src))
+ horn.summoner = user.mind
+ horn.horror = H
+ to_chat(user, "A strange looking [horn] falls out of [src]!")
+ else
+ to_chat(user, "The creatures looks at you with one of it's eyes before going back to slumber.")
+ used = FALSE
+ return
+
+//Summoning horn
+/obj/item/horrorsummonhorn
+ name = "old horn"
+ desc = "A very old horn. You feel an incredible urge to blow into it."
+ icon = 'icons/obj/items_and_weapons.dmi'
+ lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/items_righthand.dmi'
+ item_state = "horn"
+ icon_state = "horn"
+ var/datum/mind/summoner
+ var/mob/living/simple_animal/horror/horror
+ var/cooldown
+
+/obj/item/horrorsummonhorn/examine(mob/user)
+ . = ..()
+ if(user.mind == summoner)
+ to_chat(user, "Blowing into this horn will recall the horror back to you. Be wary, the horn is loud, and may attract unwanted attention.")
+
+/obj/item/horrorsummonhorn/attack_self(mob/living/user)
+ if(cooldown > world.time)
+ to_chat(user, "Take a breath before you blow [src] again.")
+ return
+ to_chat(user, "You take a deep breath and prepare to blow into [src]...")
+ if(do_mob(user, src, 10 SECONDS))
+ if(cooldown > world.time)
+ return
+ cooldown = world.time + 10 SECONDS
+ to_chat(src, "You blow the horn...")
+ playsound(loc, "sound/items/airhorn.ogg", 100, 1, 30)
+ var/turf/summonplace = get_turf(src)
+ sleep(5 SECONDS)
+ if(prob(20)) //yeah you're summoning an eldritch horror allright
+ new /obj/effect/temp_visual/summon(summonplace)
+ sleep(10)
+ var/type = pick(typesof(/mob/living/simple_animal/hostile/abomination))
+ var/mob/R = new type(summonplace)
+ playsound(summonplace, "sound/effects/phasein.ogg", 30)
+ summonplace.visible_message("[R] emerges!")
+ else
+ if(!horror || horror.stat == DEAD)
+ summonplace.visible_message("But nothing responds to the call!")
+ else
+ new /obj/effect/temp_visual/summon(summonplace)
+ sleep(10)
+ horror.leave_victim()
+ horror.forceMove(summonplace)
+ playsound(summonplace, "sound/effects/phasein.ogg", 30)
+ summonplace.visible_message("[horror] appears out of nowhere!")
+ if(user.mind != summoner)
+ sleep(2 SECONDS)
+ playsound(summonplace, "sound/effects/glassbr2.ogg", 30, 1)
+ to_chat(user, "[src] breaks!")
+ qdel(src)
+
+/obj/item/horrorsummonhorn/suicide_act(mob/living/user) //"I am the prettiest unicorn that ever was!" ~Spy 2013
+ user.visible_message("[user] stabs [user.p_their()] forehead with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ return BRUTELOSS
+
+//Tentacle arm
+/obj/item/horrortentacle
+ name = "tentacle"
+ desc = "A long, slimy, arm-like appendage."
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "horrortentacle"
+ item_state = "tentacle"
+ lefthand_file = 'icons/mob/inhands/antag/horror_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/antag/horror_righthand.dmi'
+ resistance_flags = ACID_PROOF
+ force = 17
+ item_flags = ABSTRACT | DROPDEL
+ reach = 2
+ hitsound = 'sound/weapons/whip.ogg'
+
+/obj/item/horrortentacle/Initialize(mapload)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
+
+/obj/item/horrortentacle/examine(mob/user)
+ . = ..()
+ to_chat(user, "Functions:")
+ to_chat(user, "All attacks work up to 2 tiles away.")
+ to_chat(user, "Help intent: Usual help function of an arm.")
+ to_chat(user, "Disarm intent: Whips the tentacle, disarming your opponent.")
+ to_chat(user, "Grab intent: Instant aggressive grab on an opponent. Can also throw them!")
+ to_chat(user, "Harm intent: Whips the tentacle, damaging your opponent.")
+ to_chat(user, "Also functions to pry open unbolted airlocks.")
+
+/obj/item/horrortentacle/attack(atom/target, mob/living/user)
+ if(isliving(target))
+ user.Beam(target,"purpletentacle",time=5)
+ var/mob/living/L = target
+ switch(user.a_intent)
+ if(INTENT_HELP)
+ L.attack_hand(user)
+ return
+ if(INTENT_GRAB)
+ if(L != user)
+ L.grabbedby(user)
+ L.grippedby(user, instant = TRUE)
+ L.Knockdown(30)
+ return
+ if(INTENT_DISARM)
+ if(iscarbon(L))
+ var/mob/living/carbon/C = L
+ var/obj/item/I = C.get_active_held_item()
+ if(I)
+ if(C.dropItemToGround(I))
+ playsound(loc, "sound/weapons/whipgrab.ogg", 30)
+ target.visible_message("[I] is whipped out of [C]'s hand by [user]!","A tentacle whips [I] out of your hand!")
+ return
+ else
+ to_chat(user, "You can't seem to pry [I] off [C]'s hands!")
+ return
+ else
+ C.attack_hand(user)
+ return
+ . = ..()
+
+/obj/item/horrortentacle/afterattack(atom/target, mob/user, proximity)
+ if(isliving(user.pulling) && user.pulling != target)
+ var/mob/living/H = user.pulling
+ user.visible_message("[user] throws [H] with [user.p_their()] [src]!", "You throw [H] with [src].")
+ H.throw_at(target, 8, 2)
+ H.Knockdown(30)
+ return
+ if(!proximity)
+ return
+ if(istype(target, /obj/machinery/door/airlock))
+ var/obj/machinery/door/airlock/A = target
+
+ if((!A.requiresID() || A.allowed(user)) && A.hasPower())
+ return
+ if(A.locked)
+ to_chat(user, "The airlock's bolts prevent it from being forced!")
+ return
+
+ if(A.hasPower())
+ user.visible_message("[user] jams [src] into the airlock and starts prying it open!", "You start forcing the airlock open.",
+ "You hear a metal screeching sound.")
+ playsound(A, 'sound/machines/airlock_alien_prying.ogg', 150, 1)
+ if(!do_after(user, 10 SECONDS, target = A))
+ return
+ user.visible_message("[user] forces the airlock to open with [user.p_their()] [src]!", "You force the airlock to open.",
+ "You hear a metal screeching sound.")
+ A.open(2)
+ return
+ . = ..()
+
+/obj/item/horrortentacle/suicide_act(mob/user) //funnily enough, this will never be called, since horror stops suicide
+ user.visible_message("[src] coils itself around [user] tightly gripping [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide!")
+ return (OXYLOSS)
+
+//Pinpointer
+/obj/screen/alert/status_effect/agent_pinpointer/horror
+ name = "Soul locator"
+ desc = "Find your target soul."
+
+/datum/status_effect/agent_pinpointer/horror
+ id = "horror_pinpointer"
+ minimum_range = 0
+ range_fuzz_factor = 0
+ tick_interval = 20
+ alert_type = /obj/screen/alert/status_effect/agent_pinpointer/horror
+
+/datum/status_effect/agent_pinpointer/horror/scan_for_target()
+ return
+
+//TRAPPED MIND - when horror takes control over your body, you become a mute trapped mind
+/mob/living/captive_brain
+ name = "host brain"
+ real_name = "host brain"
+ var/datum/action/innate/resist_control/R
+ var/mob/living/simple_animal/horror/H
+
+/mob/living/captive_brain/Initialize(mapload, gen=1)
+ ..()
+ R = new
+ R.Grant(src)
+
+/mob/living/captive_brain/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
+ if(client)
+ if(client.prefs.muted & MUTE_IC)
+ to_chat(src, "You cannot speak in IC (muted).")
+ return
+ if(client.handle_spam_prevention(message,MUTE_IC))
+ return
+
+ if(ishorror(loc))
+ message = sanitize(message)
+ if(!message)
+ return
+ log_say("[key_name(src)] : [message]")
+ if(stat == 2)
+ return say_dead(message)
+
+ to_chat(src, "You whisper silently, \"[message]\"")
+ to_chat(H.victim, "The captive mind of [src] whispers, \"[message]\"")
+
+ for (var/mob/M in GLOB.player_list)
+ if(isnewplayer(M))
+ continue
+ else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
+ to_chat(M, "Thought-speech, [src] -> [H.truename]: [message]")
+
+/mob/living/captive_brain/emote(act, m_type = null, message = null, intentional = FALSE)
+ return
+
+/datum/action/innate/resist_control
+ name = "Resist control"
+ desc = "Try to take back control over your brain. A strong nerve impulse should do it."
+ background_icon_state = "bg_ecult"
+ icon_icon = 'icons/mob/actions/actions_horror.dmi'
+ button_icon_state = "resist_control"
+
+/datum/action/innate/resist_control/Activate()
+ var/mob/living/captive_brain/B = owner
+ if(B)
+ B.try_resist()
+
+/mob/living/captive_brain/resist()
+ try_resist()
+
+/mob/living/captive_brain/proc/try_resist()
+ var/delay = rand(20 SECONDS,30 SECONDS)
+ if(H.horrorupgrades["deep_control"])
+ delay += rand(20 SECONDS,30 SECONDS)
+ to_chat(src, "You begin doggedly resisting the parasite's control.")
+ to_chat(H.victim, "You feel the captive mind of [src] begin to resist your control.")
+ addtimer(CALLBACK(src, .proc/return_control), delay)
+
+/mob/living/captive_brain/proc/return_control()
+ if(!H || !H.controlling)
+ return
+ to_chat(src, "With an immense exertion of will, you regain control of your body!")
+ to_chat(H.victim, "You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")
+ H.detatch()
\ No newline at end of file
diff --git a/code/modules/antagonists/horror/horror_html.dm b/code/modules/antagonists/horror/horror_html.dm
new file mode 100644
index 000000000000..4f70c856805d
--- /dev/null
+++ b/code/modules/antagonists/horror/horror_html.dm
@@ -0,0 +1,102 @@
+/mob/living/simple_animal/horror/proc/get_html_template(content)
+ var/html = {"
+
+
+ Horror Chemicals
+
+
+
+
+
+
+
+
+
+ [content]
+
"}
+ return html
\ No newline at end of file
diff --git a/code/modules/antagonists/horror/horror_mutate.dm b/code/modules/antagonists/horror/horror_mutate.dm
new file mode 100644
index 000000000000..8c48fd808d99
--- /dev/null
+++ b/code/modules/antagonists/horror/horror_mutate.dm
@@ -0,0 +1,99 @@
+// Horror mutation menu
+// Totally not a copypaste of darkspawn menu, not a copypaste of cellular emporium, i swear.
+
+/mob/living/simple_animal/horror/proc/has_ability(id)
+ if(isnull(horrorabilities[id]))
+ return
+ return horrorabilities[id]
+
+/mob/living/simple_animal/horror/proc/add_ability(id)
+ if(has_ability(id))
+ return
+ for(var/V in subtypesof(/datum/action/innate/horror))
+ var/datum/action/innate/horror/H = V
+ if(initial(H.id) == id)
+ var/datum/action/innate/horror/action = new H(null, src)
+ horrorabilities[id] = action
+ action.B = src
+ RefreshAbilities()
+ to_chat(src, "You have mutated the [action.name].")
+ available_points = max(0, available_points - action.soul_price)
+ return TRUE
+
+/mob/living/simple_animal/horror/proc/has_upgrade(id)
+ return horrorupgrades[id]
+
+/mob/living/simple_animal/horror/proc/add_upgrade(id)
+ if(has_upgrade(id))
+ return
+ for(var/V in subtypesof(/datum/horror_upgrade))
+ var/datum/horror_upgrade/_U = V
+ if(initial(_U.id) == id)
+ var/datum/horror_upgrade/U = new _U(src)
+ horrorupgrades[id] = TRUE
+ to_chat(src, "You have adapted the \"[U.name]\" upgrade.")
+ available_points = max(0, available_points - U.soul_price)
+ U.unlock()
+
+//mutation menu, 100% ripoff of psiweb, pls don't sue
+
+/mob/living/simple_animal/horror/ui_state(mob/user)
+ return GLOB.always_state
+
+/mob/living/simple_animal/horror/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "HorrorMutate", "Horror Mutation")
+ ui.open()
+
+/mob/living/simple_animal/horror/ui_data(mob/user)
+ var/list/data = list()
+
+ data["available_points"] = "[available_points] | [consumed_souls] consumed souls total"
+
+ var/list/abilities = list()
+ var/list/upgrades = list()
+
+ for(var/path in subtypesof(/datum/action/innate/horror))
+ var/datum/action/innate/horror/ability = path
+
+ if(initial(ability.blacklisted))
+ continue
+
+ var/list/AL = list()
+ AL["name"] = initial(ability.name)
+ AL["id"] = initial(ability.id)
+ AL["desc"] = initial(ability.desc)
+ AL["soul_cost"] = initial(ability.soul_price)
+ AL["owned"] = has_ability(initial(ability.id))
+ AL["can_purchase"] = !AL["owned"] && available_points >= initial(ability.soul_price)
+
+ abilities += list(AL)
+
+ data["abilities"] = abilities
+
+ for(var/path in subtypesof(/datum/horror_upgrade))
+ var/datum/horror_upgrade/upgrade = path
+
+ var/list/DE = list()
+ DE["name"] = initial(upgrade.name)
+ DE["id"] = initial(upgrade.id)
+ DE["desc"] = initial(upgrade.desc)
+ DE["soul_cost"] = initial(upgrade.soul_price)
+ DE["owned"] = has_upgrade(initial(upgrade.id))
+ DE["can_purchase"] = !DE["owned"] && available_points >= initial(upgrade.soul_price)
+
+ upgrades += list(DE)
+
+ data["upgrades"] = upgrades
+
+ return data
+
+/mob/living/simple_animal/horror/ui_act(action, params)
+ if(..())
+ return
+ switch(action)
+ if("unlock")
+ add_ability(params["id"])
+ if("upgrade")
+ add_upgrade(params["id"])
\ No newline at end of file
From f396a6bdb3a584d9c7ecf7964535115c8c12043b Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 13:32:47 +0100
Subject: [PATCH 19/79] Add files via upload
---
code/modules/events/horror.dm | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
create mode 100644 code/modules/events/horror.dm
diff --git a/code/modules/events/horror.dm b/code/modules/events/horror.dm
new file mode 100644
index 000000000000..dd42420f8477
--- /dev/null
+++ b/code/modules/events/horror.dm
@@ -0,0 +1,34 @@
+/datum/round_event_control/horror
+ name = "Spawn Eldritch Horror"
+ typepath = /datum/round_event/ghost_role/horror
+ max_occurrences = 2
+ min_players = 15
+ earliest_start = 20 MINUTES
+
+/datum/round_event/ghost_role/horror
+ minimum_required = 1
+ role_name = "horror"
+ fakeable = FALSE
+
+/datum/round_event/ghost_role/horror/spawn_role()
+ var/list/candidates = get_candidates(ROLE_HORROR, null, ROLE_HORROR)
+ if(!candidates.len)
+ return NOT_ENOUGH_PLAYERS
+
+ var/mob/dead/selected = pick_n_take(candidates)
+
+ var/datum/mind/player_mind = new /datum/mind(selected.key)
+ player_mind.active = 1
+ if(!GLOB.generic_event_spawns)
+ return MAP_ERROR
+ var/mob/living/simple_animal/horror/S = new /mob/living/simple_animal/horror(get_turf(pick(GLOB.generic_event_spawns)))
+ player_mind.transfer_to(S)
+ player_mind.assigned_role = "Eldritch Horror"
+ player_mind.special_role = "Eldritch Horror"
+ player_mind.add_antag_datum(/datum/antagonist/horror)
+ to_chat(S, S.playstyle_string)
+ SEND_SOUND(S, sound('sound/hallucinations/growl2.ogg'))
+ message_admins("[ADMIN_LOOKUPFLW(S)] has been made into an eldritch horror by an event.")
+ log_game("[key_name(S)] was spawned as an eldritch horror by an event.")
+ spawned_mobs += S
+ return SUCCESSFUL_SPAWN
\ No newline at end of file
From e15f4393ca886831480a38a24aeb791f284de2e0 Mon Sep 17 00:00:00 2001
From: ChesterTheCheesy <71487903+ChesterTheCheesy@users.noreply.github.com>
Date: Tue, 14 Dec 2021 13:33:37 +0100
Subject: [PATCH 20/79] Add files via upload
---
icons/effects/effects.dmi | Bin 901936 -> 902657 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 1a3d0b762527243958295149516bb3cdcd8f6e72..59a5ad1a79a33649f2faac93d6676964a44e24b8 100644
GIT binary patch
delta 16330
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
n)&$1?GhZ1`{{I;8Qc1%D4ET74xtB3Q
Date: Tue, 14 Dec 2021 13:34:35 +0100
Subject: [PATCH 21/79] Add files via upload
---
icons/mob/animal.dmi | Bin 235830 -> 250180 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index eec8a5886a3326d9115021cbc2a55f0f775c80bf..4928ed0fa3af6d8f42ee3d147e58390644442a02 100644
GIT binary patch
literal 250180
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