diff --git a/modular_ss220/antagonists/_antagonists.dme b/modular_ss220/antagonists/_antagonists.dme
index ba730e2ae2b9..d8692777cee0 100644
--- a/modular_ss220/antagonists/_antagonists.dme
+++ b/modular_ss220/antagonists/_antagonists.dme
@@ -10,6 +10,8 @@
#include "code/antag_mix/antag_mix.dm"
#include "code/shadowlings/shadowling_datum.dm"
#include "code/shadowlings/shadowling_species.dm"
+#include "code/shadowlings/shadowling_language.dm"
+#include "code/shadowlings/shadowling_eyes.dm"
#include "code/shadowlings/spells/shadowling_spell.dm"
#include "code/shadowlings/spells/shadowling_glare.dm"
#include "code/shadowlings/spells/shadowling_shadow_walk.dm"
@@ -18,6 +20,8 @@
#include "code/shadowlings/spells/shadowling_blindness_smoke.dm"
#include "code/shadowlings/spells/shadowling_veil.dm"
#include "code/shadowlings/spells/shadowling_enthrall.dm"
+#include "code/shadowlings/spells/shadowling_tear_the_reality.dm"
+#include "code/shadowlings/spells/shadowling_rift_in.dm"
#include "code/shadowlings/spells/shadow_father_crawl.dm"
#include "code/shadowlings/father_of_shadows.dm"
#include "code/shadowlings/shadowling_traps.dm"
diff --git a/modular_ss220/antagonists/code/shadowlings/father_of_shadows.dm b/modular_ss220/antagonists/code/shadowlings/father_of_shadows.dm
index 28f346c8cc8a..b39c6de20569 100644
--- a/modular_ss220/antagonists/code/shadowlings/father_of_shadows.dm
+++ b/modular_ss220/antagonists/code/shadowlings/father_of_shadows.dm
@@ -24,11 +24,15 @@
speed = 1
maxHealth = 350
health = 350
-
+ /// Used to check light exposure alert state
var/thrown_alert
+ /// Contain list of all traps placed by this shadow father
var/list/obj/structure/shadow_trap/placed_traps = list()
+ /// Used to check state in consumption logic
var/is_consuming = FALSE
+ /// Amount of bodies, consumed by the shadow father
var/consumed = 0
+ /// Used to initialize hud
var/mind_initialized = FALSE
/mob/living/simple_animal/demon/shadow_father/Login()
@@ -68,9 +72,10 @@
adjustBruteLoss(-20)
/mob/living/simple_animal/demon/shadow_father/death(gibbed)
- if(consumed > 0)
- SSticker.mode.begin_shadowling_invasion(src, FALSE)
- . = ..()
+ for(var/trap in placed_traps)
+ qdel(trap)
+ INVOKE_ASYNC(SSticker.mode, TYPE_PROC_REF(/datum/game_mode, begin_shadowling_invasion), src, FALSE)
+ return ..(gibbed)
/mob/living/simple_animal/demon/shadow_father/proc/check_darkness()
var/turf/T = get_turf(src)
@@ -113,6 +118,9 @@
..()
/mob/living/simple_animal/demon/shadow_father/UnarmedAttack(atom/A)
+ // Prevent self-attack
+ if(A == src)
+ return
// Pick a random attack sound for each attack
attack_sound = pick('sound/shadowdemon/shadowattack2.ogg', 'sound/shadowdemon/shadowattack3.ogg', 'sound/shadowdemon/shadowattack4.ogg')
if(!ishuman(A))
diff --git a/modular_ss220/antagonists/code/shadowlings/shadowling_eyes.dm b/modular_ss220/antagonists/code/shadowlings/shadowling_eyes.dm
new file mode 100644
index 000000000000..89dae4a4c1e4
--- /dev/null
+++ b/modular_ss220/antagonists/code/shadowlings/shadowling_eyes.dm
@@ -0,0 +1,6 @@
+// Changing the organ usage action background
+/obj/item/organ/internal/eyes/night_vision/nightmare
+ actions_types = list(/datum/action/item_action/organ_action/use/shadowling)
+
+/datum/action/item_action/organ_action/use/shadowling
+ button_background_icon_state = "shadow_demon_bg"
diff --git a/modular_ss220/antagonists/code/shadowlings/shadowling_gamemode.dm b/modular_ss220/antagonists/code/shadowlings/shadowling_gamemode.dm
index c631aa774ff8..8394f1e81533 100644
--- a/modular_ss220/antagonists/code/shadowlings/shadowling_gamemode.dm
+++ b/modular_ss220/antagonists/code/shadowlings/shadowling_gamemode.dm
@@ -6,21 +6,26 @@
/// Called when shadow father is killed or when special spell is used
/datum/game_mode/proc/begin_shadowling_invasion(mob/living/simple_animal/demon/shadow_father/father, spell_used)
- father.consumed++ //At least one shadowling
+ // Spawning father as shadowling
+ if(spell_used)
+ var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(father.loc)
+ var/mob/living/carbon/human/shadowling/ling = new /mob/living/carbon/human/shadowling(holder)
+ ling.AddSpell(new /datum/spell/shadowling/self/rift_in)
+ ling.key = father.key
+ else
+ father.consumed++ //At least one shadowling
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Вы хотите поиграть за тенелинга?", ROLE_SHADOWLING, TRUE, 25 SECONDS, source = /mob/living/simple_animal/demon/shadow_father, role_cleanname = "Shadowling")
while(father.consumed > 0)
- var/player_to_spawn
- if(spell_used) // Granting shadowling role for father that commited suicide
- player_to_spawn = father.key
- spell_used = FALSE
- else
- var/list/mob/dead/observer/ghost = pick(candidates)
- player_to_spawn = ghost.key
- if(isnull(player_to_spawn))
+ if(candidates.len < 1)
break
+ var/player_to_spawn
+ var/mob/dead/observer/ghost = pick(candidates)
+ candidates.Remove(ghost)
+ player_to_spawn = ghost.key
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(father.loc)
- var/mob/living/carbon/human/shadow/ling/ling = new /mob/living/carbon/human/shadow/ling(holder)
- dust_if_respawnable(player_to_spawn)
+ var/mob/living/carbon/human/shadowling/ling = new /mob/living/carbon/human/shadowling(holder)
+ ling.AddSpell(new /datum/spell/shadowling/self/rift_in)
+ dust_if_respawnable(ghost)
ling.key = player_to_spawn
father.consumed--
diff --git a/modular_ss220/antagonists/code/shadowlings/shadowling_language.dm b/modular_ss220/antagonists/code/shadowlings/shadowling_language.dm
new file mode 100644
index 000000000000..25ea1cbf3fd9
--- /dev/null
+++ b/modular_ss220/antagonists/code/shadowlings/shadowling_language.dm
@@ -0,0 +1,18 @@
+/datum/language/shadowling
+ name = "Шёпот из тени"
+ desc = "В тени всегда есть те, кто слышит все ваши секреты. Шадоулинги используют рэдспейс для связи между собой."
+ speech_verb = "says"
+ colour = "purple"
+ key = "sl"
+ flags = RESTRICTED | HIVEMIND | NOBABEL
+ follow = TRUE
+
+/datum/language/shadowling/get_random_name()
+ var/new_name
+ if(prob(0.1))
+ new_name = "Лучик Доброты" // :)
+ else
+ // Edgelord names ahead
+ new_name += "[pick("Владыка", "Поработитель", "Повелитель", "Мучитель", "Пожиратель", "Угнетатель", "Судья", "Убийца", "Уничтожитель", "Тиран")]"
+ new_name += " [pick("Тьмы", "Тени", "Темноты", "Ужаса", "Страха", "Ненависти", "Зависти", "Злости", "Греха", "Мрака", "Боли", "Кары")]"
+ return new_name
diff --git a/modular_ss220/antagonists/code/shadowlings/shadowling_mob.dm b/modular_ss220/antagonists/code/shadowlings/shadowling_mob.dm
index 0730fd5f7c27..087b254f914b 100644
--- a/modular_ss220/antagonists/code/shadowlings/shadowling_mob.dm
+++ b/modular_ss220/antagonists/code/shadowlings/shadowling_mob.dm
@@ -1,3 +1,3 @@
-/mob/living/carbon/human/shadow/ling/Initialize(mapload)
+// Not subtype of /mob/living/carbon/human/shadow because of weird parent proc call
+/mob/living/carbon/human/shadowling/Initialize(mapload)
. = ..(mapload, /datum/species/shadow/ling)
-
diff --git a/modular_ss220/antagonists/code/shadowlings/shadowling_species.dm b/modular_ss220/antagonists/code/shadowlings/shadowling_species.dm
index bbcee14c9df3..bb3d77cecd86 100644
--- a/modular_ss220/antagonists/code/shadowlings/shadowling_species.dm
+++ b/modular_ss220/antagonists/code/shadowlings/shadowling_species.dm
@@ -7,6 +7,8 @@
name = "Shadowling"
name_plural = "Shadowlings"
+ default_language = "Шёпот из тени"
+ language = "Шёпот из тени"
icobase = 'modular_ss220/antagonists/icons/shadowlings/r_shadowling.dmi'
blacklisted = TRUE
@@ -19,12 +21,6 @@
burn_mod = 1.25
heatmod = 1.5
- has_organ = list(
- INTERNAL_ORGAN_BRAIN = /obj/item/organ/internal/brain,
- INTERNAL_ORGAN_EYES = /obj/item/organ/internal/eyes,
- INTERNAL_ORGAN_EARS = /obj/item/organ/internal/ears,
- )
-
/datum/species/shadow/ling/proc/handle_light(mob/living/carbon/human/H)
var/light_amount = 0
if(isturf(H.loc))
@@ -37,7 +33,7 @@
else
H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN)
if(H.stat != DEAD)
- to_chat(H, "Свет жжёт вас!")//Message spam to say "GET THE FUCK OUT"
+ to_chat(H, "Свет жжёт вас!")/
H << 'sound/weapons/sear.ogg'
else if(light_amount < LIGHT_HEAL_THRESHOLD)
H.clear_alert("lightexposure")
@@ -49,7 +45,7 @@
else
H.heal_overall_damage(5, 7)
H.adjustToxLoss(-5)
- H.adjustBrainLoss(-25) //Shad O. Ling gibbers, "CAN U BE MY THRALL?!!"
+ H.adjustBrainLoss(-25)
H.AdjustEyeBlurry(-2 SECONDS)
H.adjustCloneLoss(-1)
H.SetWeakened(0)
@@ -71,7 +67,7 @@
flesh_color = "#AAAAAA"
burn_mod = 1.1
- heatmod = 1.1
+ heatmod = 1.2
#undef LIGHT_DAM_THRESHOLD
#undef LIGHT_HEAL_THRESHOLD
diff --git a/modular_ss220/antagonists/code/shadowlings/spells/shadowling_rift_in.dm b/modular_ss220/antagonists/code/shadowlings/spells/shadowling_rift_in.dm
new file mode 100644
index 000000000000..6e4fddd1fb87
--- /dev/null
+++ b/modular_ss220/antagonists/code/shadowlings/spells/shadowling_rift_in.dm
@@ -0,0 +1,14 @@
+/datum/spell/shadowling/self/rift_in
+ name = "Проникнуть через разлом"
+ desc = "Вы проникаете через разрыв из мира теней в материальную реальность"
+ stat_allowed = UNCONSCIOUS
+ action_icon_state = "ascend"
+
+/datum/spell/shadowling/self/rift_in/cast(list/targets, mob/user = usr)
+ var/obj/effect/dummy/slaughter/holder = user.loc
+ if(istype(holder))
+ user.forceMove(holder.loc)
+ qdel(holder)
+ user.RemoveSpell(src)
+ return
+
diff --git a/modular_ss220/antagonists/code/shadowlings/spells/shadowling_tear_the_reality.dm b/modular_ss220/antagonists/code/shadowlings/spells/shadowling_tear_the_reality.dm
index d05224a2d21c..3c8b5067f473 100644
--- a/modular_ss220/antagonists/code/shadowlings/spells/shadowling_tear_the_reality.dm
+++ b/modular_ss220/antagonists/code/shadowlings/spells/shadowling_tear_the_reality.dm
@@ -13,8 +13,12 @@
if(father.consumed < 1)
to_chat(father, span_warning("Вам нужно поглотить как минимум одного смертного, чтобы прорвать реальность."))
return FALSE
+
+/datum/spell/shadowling/self/tear_the_reality/cast(list/targets, mob/user)
+ var/mob/living/simple_animal/demon/shadow_father/father = user
var/confirm = tgui_alert(father, "Вы уверены что хотите закончить свою охоту и прорвать реальность? Вы призовёте [father.consumed + 1] тенелингов и гарантированно станите одним из них.", "Закончить охоту?", list("Да", "Я ещё поохочусь"))
if(confirm != "Да")
return
- SSticker.mode.begin_shadowling_invasion(father, TRUE)
+ INVOKE_ASYNC(SSticker.mode, TYPE_PROC_REF(/datum/game_mode, begin_shadowling_invasion), src, TRUE)
+ qdel(user)