diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 3407b3342b..ffcb5ac231 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -125,7 +125,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isbot(A) (istype(A, /mob/living/simple_animal/bot))
-#define isshade(A) (istype(A, /mob/living/simple_animal/shade))
+#define isshade(A) (istype(A, /mob/living/simple_animal/hostile/construct/shade))
#define ismouse(A) (istype(A, /mob/living/simple_animal/mouse))
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 82302a2e06..8e14c7a58e 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -323,3 +323,4 @@
/// This trait is added by the parry system.
#define ACTIVE_PARRY_TRAIT "active_parry"
#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
+#define TRAIT_SACRIFICED "sacrificed" //Makes sure that people cant be cult sacrificed twice.
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index 605b20a4f3..e30f0e260d 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -13,6 +13,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_NEARSIGHT" = TRAIT_NEARSIGHT,
"TRAIT_FAT" = TRAIT_FAT,
"TRAIT_HUSK" = TRAIT_HUSK,
+ "TRAIT_SACRIFICED" = TRAIT_SACRIFICED,
"TRAIT_NOCLONE" = TRAIT_NOCLONE,
"TRAIT_CLUMSY" = TRAIT_CLUMSY,
"TRAIT_CHUNKYFINGERS" = TRAIT_CHUNKYFINGERS,
diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm
index 47b93928d4..9a0665e91f 100644
--- a/code/controllers/subsystem/traumas.dm
+++ b/code/controllers/subsystem/traumas.dm
@@ -52,7 +52,7 @@ SUBSYSTEM_DEF(traumas)
"doctors" = typecacheof(list(/mob/living/simple_animal/bot/medbot)),
"the supernatural" = typecacheof(list(/mob/living/simple_animal/hostile/construct,
/mob/living/simple_animal/hostile/clockwork, /mob/living/simple_animal/drone/cogscarab,
- /mob/living/simple_animal/revenant, /mob/living/simple_animal/shade)),
+ /mob/living/simple_animal/revenant, /mob/living/simple_animal/hostile/construct/shade)),
"aliens" = typecacheof(list(/mob/living/carbon/alien, /mob/living/simple_animal/slime)),
"conspiracies" = typecacheof(list(/mob/living/simple_animal/bot/secbot, /mob/living/simple_animal/bot/ed209, /mob/living/simple_animal/drone,
/mob/living/simple_animal/pet/penguin)),
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index fe2bdf90b1..8941c540ae 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -508,7 +508,7 @@
/obj/machinery/door/airlock/cult/allowed(mob/living/L)
if(!density)
return 1
- if(friendly || iscultist(L) || istype(L, /mob/living/simple_animal/shade) || isconstruct(L))
+ if(friendly || iscultist(L) || isshade(L) || isconstruct(L))
if(!stealthy)
new openingoverlaytype(loc)
return 1
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 58146be20f..a15e1368d8 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -492,7 +492,7 @@
var/possessed = FALSE
/obj/item/nullrod/scythe/talking/process()
- for(var/mob/living/simple_animal/shade/S in contents)
+ for(var/mob/living/simple_animal/hostile/construct/shade/S in contents)
if(S.mind)
return
else
@@ -516,7 +516,7 @@
if(LAZYLEN(candidates))
var/mob/C = pick(candidates)
- var/mob/living/simple_animal/shade/S = new(src)
+ var/mob/living/simple_animal/hostile/construct/shade/S = new(src)
S.real_name = name
S.name = name
S.ckey = C.ckey
@@ -537,7 +537,7 @@
possessed = FALSE
/obj/item/nullrod/scythe/talking/Destroy()
- for(var/mob/living/simple_animal/shade/S in contents)
+ for(var/mob/living/simple_animal/hostile/construct/shade/S in contents)
to_chat(S, "You were destroyed!")
qdel(S)
return ..()
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index 244b8c804b..476f35fe4c 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -198,7 +198,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
if(istype(A, /obj/item/cult_bastard))
for(var/obj/item/soulstone/SS in A.contents)
SS.usability = TRUE
- for(var/mob/living/simple_animal/shade/EX in SS)
+ for(var/mob/living/simple_animal/hostile/construct/shade/EX in SS)
SSticker.mode.remove_cultist(EX.mind, 1, 0)
EX.icon_state = "ghost1"
EX.name = "Purified [EX.name]"
@@ -217,7 +217,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
if(do_after(user, 40, target = SS))
playsound(src,'sound/effects/pray_chaplain.ogg',60,1)
SS.usability = TRUE
- for(var/mob/living/simple_animal/shade/EX in SS)
+ for(var/mob/living/simple_animal/hostile/construct/shade/EX in SS)
SSticker.mode.remove_cultist(EX.mind, 1, 0)
EX.icon_state = "ghost1"
EX.name = "Purified [EX.name]"
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 03376df905..ad8dd168eb 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -508,7 +508,7 @@
if("constructwraith")
M.change_mob_type( /mob/living/simple_animal/hostile/construct/wraith , null, null, delmob )
if("shade")
- M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob )
+ M.change_mob_type( /mob/living/simple_animal/hostile/construct/shade , null, null, delmob )
/////////////////////////////////////new ban stuff
diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm
index 6e3fcfae2a..a2ec4a47a4 100644
--- a/code/modules/antagonists/cult/cult.dm
+++ b/code/modules/antagonists/cult/cult.dm
@@ -295,6 +295,8 @@
++cultplayers
else
++alive
+ if(!alive)
+ return
var/ratio = cultplayers/alive
if(ratio > CULT_RISEN && !cult_risen)
for(var/datum/mind/B in members)
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 6cc2fb94b8..276729b359 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -82,7 +82,7 @@ Runes can either be invoked by one's self or with many different cultists. Each
fail_invoke()
/obj/effect/rune/attack_animal(mob/living/simple_animal/M)
- if(istype(M, /mob/living/simple_animal/shade) || istype(M, /mob/living/simple_animal/hostile/construct))
+ if(isshade(M) || istype(M, /mob/living/simple_animal/hostile/construct))
if(construct_invoke || !iscultist(M)) //if you're not a cult construct we want the normal fail message
attack_hand(M)
else
@@ -191,7 +191,7 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/convert/do_invoke_glow()
return
-/obj/effect/rune/convert/invoke(var/list/invokers)
+/obj/effect/rune/convert/invoke(list/invokers)
if(rune_in_use)
return
var/list/myriad_targets = list()
@@ -203,11 +203,16 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
log_game("Offer rune failed - no eligible targets")
return
+ var/mob/living/L = pick(myriad_targets)
+ if(HAS_TRAIT(L, TRAIT_SACRIFICED))
+ fail_invoke()
+ log_game("Offer rune failed - target has already been sacrificed")
+ to_chat(invokers, "[L] has already been sacrificed!")
+ return
rune_in_use = TRUE
visible_message("[src] pulses blood red!")
var/oldcolor = color
color = RUNE_COLOR_DARKRED
- var/mob/living/L = pick(myriad_targets)
var/is_clock = is_servant_of_ratvar(L)
var/mob/living/F = invokers[1]
@@ -264,7 +269,7 @@ structure_check() searches for nearby cultist structures required for the invoca
H.uncuff()
H.stuttering = 0
H.cultslurring = 0
- return 1
+ return TRUE
/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers)
var/mob/living/first_invoker = invokers[1]
@@ -308,12 +313,16 @@ structure_check() searches for nearby cultist structures required for the invoca
stone.invisibility = 0
if(sacrificial)
+ ADD_TRAIT(sacrificial, TRAIT_SACRIFICED, "sacrificed")
if(iscyborg(sacrificial))
- playsound(sacrificial, 'sound/magic/disable_tech.ogg', 100, 1)
- sacrificial.dust() //To prevent the MMI from remaining
- else
- playsound(sacrificial, 'sound/magic/disintegrate.ogg', 100, 1)
- sacrificial.gib()
+ var/mob/living/silicon/robot/bot = sacrificial
+ playsound(sacrificial, 'sound/magic/disable_tech.ogg', 100, TRUE)
+ bot.deconstruct()
+
+ else if(ishuman(sacrificial))
+ playsound(sacrificial, 'sound/magic/disintegrate.ogg', 100, TRUE)
+ var/mob/living/carbon/human/H = sacrificial
+ H.spew_organ(2, 6)
return TRUE
/obj/effect/rune/empower
diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm
index 46961c0caf..abef18ade0 100644
--- a/code/modules/antagonists/wizard/equipment/soulstone.dm
+++ b/code/modules/antagonists/wizard/equipment/soulstone.dm
@@ -36,7 +36,7 @@
/obj/item/soulstone/examine(mob/user)
. = ..()
- if(usability || iscultist(user, TRUE) || iswizard(user) || isobserver(user))
+ if(usability || iscultist(user) || iswizard(user) || isobserver(user))
if (old_shard)
. += "A soulstone, used to capture a soul, either from dead humans or from freed shades."
else
@@ -46,7 +46,7 @@
. += "This shard is spent; it is now just a creepy rock."
/obj/item/soulstone/Destroy() //Stops the shade from being qdel'd immediately and their ghost being sent back to the arrival shuttle.
- for(var/mob/living/simple_animal/shade/A in src)
+ for(var/mob/living/simple_animal/hostile/construct/shade/A in src)
A.death()
return ..()
@@ -58,7 +58,7 @@
to_chat(user, "Your body is wracked with debilitating pain!")
return
if(spent)
- to_chat(user, "There is no power left in the shard.")
+ to_chat(user, "There is no power left in [src].")
return
if(!ishuman(M))//If target is not a human.
return ..()
@@ -81,7 +81,7 @@
release_shades(user)
/obj/item/soulstone/proc/release_shades(mob/user)
- for(var/mob/living/simple_animal/shade/A in src)
+ for(var/mob/living/simple_animal/hostile/construct/shade/A in src)
A.status_flags &= ~GODMODE
A.forceMove(get_turf(user))
A.mobility_flags = MOBILITY_FLAGS_DEFAULT
@@ -103,12 +103,12 @@
/obj/structure/constructshell/examine(mob/user)
. = ..()
- if(iscultist(user, TRUE) || iswizard(user) || user.stat == DEAD)
- . += "A construct shell, used to house bound souls from a soulstone."
- . += "Placing a soulstone with a soul into this shell allows you to produce your choice of the following:"
- . += "An Artificer, which can produce more shells and soulstones, as well as fortifications."
- . += "A Wraith, which does high damage and can jaunt through walls, though it is quite fragile."
- . += "A Juggernaut, which is very hard to kill and can produce temporary walls, but is slow."
+ if(iscultist(user) || iswizard(user) || user.stat == DEAD)
+ . += {"A construct shell, used to house bound souls from a soulstone.\n
+ Placing a soulstone with a soul into this shell allows you to produce your choice of the following:\n
+ An Artificer, which can produce more shells and soulstones, as well as fortifications.\n
+ A Wraith, which does high damage and can jaunt through walls, though it is quite fragile.\n
+ A Juggernaut, which is very hard to kill and can produce temporary walls, but is slow."}
/obj/structure/constructshell/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/soulstone))
@@ -145,14 +145,14 @@
if("VICTIM")
var/mob/living/carbon/human/T = target
var/datum/antagonist/cult/C = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
- if(C && C.cult_team?.is_sacrifice_target(T.mind))
+ if(C?.cult_team.is_sacrifice_target(T.mind))
if(iscultist(user))
to_chat(user, "\"This soul is mine. SACRIFICE THEM!\"")
else
- to_chat(user, "The soulstone seems to reject this soul.")
+ to_chat(user, "[src] seems to reject this soul.")
return FALSE
if(contents.len)
- to_chat(user, "Capture failed!: The soulstone is full! Free an existing soul to make room.")
+ to_chat(user, "Capture failed!: [src] is full! Free an existing soul to make room.")
else
if((!old_shard && T.stat != CONSCIOUS) || (old_shard && T.stat == DEAD))
if(T.client == null)
@@ -167,7 +167,7 @@
to_chat(user, "Capture failed!: Kill or maim the victim first!")
if("SHADE")
- var/mob/living/simple_animal/shade/T = target
+ var/mob/living/simple_animal/hostile/construct/shade/T = target
if(contents.len)
to_chat(user, "Capture failed!: The soulstone is full! Free an existing soul to make room.")
else
@@ -177,13 +177,13 @@
T.health = T.maxHealth
icon_state = "soulstone2"
name = "soulstone: Shade of [T.real_name]"
- to_chat(T, "Your soul has been captured by the soulstone. Its arcane energies are reknitting your ethereal form.")
+ to_chat(T, "Your soul has been captured by [src]. Its arcane energies are reknitting your ethereal form.")
if(user != T)
- to_chat(user, "Capture successful!: [T.real_name]'s soul has been captured and stored within the soulstone.")
+ to_chat(user, "Capture successful!: [T.real_name]'s soul has been captured and stored within [src].")
if("CONSTRUCT")
var/obj/structure/constructshell/T = target
- var/mob/living/simple_animal/shade/A = locate() in src
+ var/mob/living/simple_animal/hostile/construct/shade/A = locate() in src
if(A)
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
if(!T || !T.loc)
@@ -199,8 +199,8 @@
if(iscultist(user) || iswizard(user))
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, A, user, 0, T.loc)
- else
- makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder/noncult, A, user, 0, T.loc)
+ else
+ return
for(var/datum/mind/B in SSticker.mode.cult)
if(B == A.mind)
SSticker.mode.cult -= A.mind
@@ -208,19 +208,24 @@
qdel(T)
qdel(src)
else
- to_chat(user, "Creation failed!: The soul stone is empty! Go kill someone!")
+ to_chat(user, "Creation failed!: [src] is empty! Go kill someone!")
/proc/makeNewConstruct(mob/living/simple_animal/hostile/construct/ctype, mob/target, mob/stoner = null, cultoverride = 0, loc_override = null)
+ if(QDELETED(target))
+ return
var/mob/living/simple_animal/hostile/construct/newstruct = new ctype((loc_override) ? (loc_override) : (get_turf(target)))
if(stoner)
newstruct.faction |= "[REF(stoner)]"
newstruct.master = stoner
var/datum/action/innate/seek_master/SM = new()
SM.Grant(newstruct)
- target.transfer_ckey(newstruct)
+ newstruct.key = target.key
+ if(target.type == /mob/living/simple_animal/hostile/construct/shade) //Make sure we remember which body belonged to the shade
+ var/mob/living/simple_animal/hostile/construct/shade/shade = target
+ newstruct.original_mind = shade.original_mind
var/obj/screen/alert/bloodsense/BS
- if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker && SSticker.mode)
+ if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker?.mode)
SSticker.mode.add_cultist(newstruct.mind, 0)
if(iscultist(stoner) || cultoverride)
to_chat(newstruct, "You are still bound to serve the cult[stoner ? " and [stoner]":""], follow [stoner ? stoner.p_their() : "their"] orders and help [stoner ? stoner.p_them() : "them"] complete [stoner ? stoner.p_their() : "their"] goals at all costs.")
@@ -234,19 +239,18 @@
/obj/item/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/user, vic = 0)
- new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton
+ if(HAS_TRAIT_FROM(T, TRAIT_SACRIFICED, "sacrificed"))
+ if(user)
+ to_chat(user, "This body has already been harvested!")
+ return
+ ADD_TRAIT(T, TRAIT_SACRIFICED, "sacrificed")
T.stop_sound_channel(CHANNEL_HEARTBEAT)
- T.invisibility = INVISIBILITY_ABSTRACT
- T.dust_animation()
- QDEL_IN(T, 5)
- var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src)
- S.status_flags |= GODMODE //So they won't die inside the stone somehow
- S.mobility_flags = NONE //Can't move out of the soul stone
+ var/mob/living/simple_animal/hostile/construct/shade/S = new /mob/living/simple_animal/hostile/construct/shade(src)
S.name = "Shade of [T.real_name]"
S.real_name = "Shade of [T.real_name]"
T.transfer_ckey(S)
+ S.original_mind = T.mind.current
S.copy_languages(T, LANGUAGE_MIND)//Copies the old mobs languages into the new mob holder.
- S.copy_languages(user, LANGUAGE_MASTER)
S.update_atom_languages()
grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue
if(user)
@@ -264,7 +268,7 @@
to_chat(user, "Capture successful!: [T.real_name]'s soul has been ripped from [T.p_their()] body and stored within the soul stone.")
-/obj/item/soulstone/proc/getCultGhost(mob/living/carbon/human/T, mob/U)
+/obj/item/soulstone/proc/getCultGhost(mob/living/carbon/human/T, mob/user)
var/mob/dead/observer/chosen_ghost
for(var/mob/dead/observer/ghost in GLOB.player_list) //We put them back in their body
@@ -279,13 +283,12 @@
if(!T)
return FALSE
if(!chosen_ghost)
- to_chat(U, "There were no spirits willing to become a shade.")
+ to_chat(user, "There were no spirits willing to become a shade.")
return FALSE
if(contents.len) //If they used the soulstone on someone else in the meantime
return FALSE
T.ckey = chosen_ghost.ckey
for(var/obj/item/W in T)
T.dropItemToGround(W)
- init_shade(T, U)
- qdel(T)
+ init_shade(T, user)
return TRUE
diff --git a/code/modules/holiday/halloween/halloween.dm b/code/modules/holiday/halloween/halloween.dm
index d3b9b92b4f..d44b94aaf3 100644
--- a/code/modules/holiday/halloween/halloween.dm
+++ b/code/modules/holiday/halloween/halloween.dm
@@ -86,7 +86,7 @@
else if(trapped == HOWLING_GHOST)
visible_message("[pick("OooOOooooOOOoOoOOooooOOOOO", "BooOOooOooooOOOO", "BOO!", "WoOOoOoooOooo")]")
playsound(loc, 'sound/spookoween/ghosty_wind.ogg', 300, 1)
- new /mob/living/simple_animal/shade/howling_ghost(loc)
+ new /mob/living/simple_animal/hostile/construct/shade/howling_ghost(loc)
trapped = 0
else if(trapped == SCARY_BATS)
@@ -123,7 +123,7 @@
//Spookoween Ghost//
////////////////////
-/mob/living/simple_animal/shade/howling_ghost
+/mob/living/simple_animal/hostile/construct/shade/howling_ghost
name = "ghost"
real_name = "ghost"
icon = 'icons/mob/mob.dmi'
@@ -137,13 +137,13 @@
layer = 4
var/timer = 0
-/mob/living/simple_animal/shade/howling_ghost/Initialize()
+/mob/living/simple_animal/hostile/construct/shade/howling_ghost/Initialize()
. = ..()
icon_state = pick("ghost","ghostian","ghostian2","ghostking","ghost1","ghost2")
icon_living = icon_state
timer = rand(1,15)
-/mob/living/simple_animal/shade/howling_ghost/Life()
+/mob/living/simple_animal/hostile/construct/shade/howling_ghost/Life()
..()
timer--
if(prob(20))
@@ -152,16 +152,16 @@
spooky_ghosty()
timer = rand(1,15)
-/mob/living/simple_animal/shade/howling_ghost/proc/EtherealMove(direction)
+/mob/living/simple_animal/hostile/construct/shade/howling_ghost/proc/EtherealMove(direction)
forceMove(get_step(src, direction))
setDir(direction)
-/mob/living/simple_animal/shade/howling_ghost/proc/roam()
+/mob/living/simple_animal/hostile/construct/shade/howling_ghost/proc/roam()
if(prob(80))
var/direction = pick(NORTH,SOUTH,EAST,WEST,NORTHEAST,NORTHWEST,SOUTHEAST,SOUTHWEST)
EtherealMove(direction)
-/mob/living/simple_animal/shade/howling_ghost/proc/spooky_ghosty()
+/mob/living/simple_animal/hostile/construct/shade/howling_ghost/proc/spooky_ghosty()
if(prob(20)) //haunt
playsound(loc, pick('sound/spookoween/ghosty_wind.ogg','sound/spookoween/ghost_whisper.ogg','sound/spookoween/chain_rattling.ogg'), 300, 1)
if(prob(10)) //flickers
@@ -175,7 +175,7 @@
step(I,direction)
return
-/mob/living/simple_animal/shade/howling_ghost/CanPass(atom/movable/mover, turf/target)
+/mob/living/simple_animal/hostile/construct/shade/howling_ghost/CanPass(atom/movable/mover, turf/target)
return 1
///////////////////////////
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 26486f255a..ebe5372e63 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -611,7 +611,7 @@
update_mobility()
UpdateStaminaBuffer()
update_health_hud()
-
+
/mob/living/carbon/update_sight()
if(!client)
return
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 95bd8d8991..af8382a82b 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -44,6 +44,7 @@
var/can_repair_constructs = FALSE
var/can_repair_self = FALSE
var/runetype
+ var/original_mind
/mob/living/simple_animal/hostile/construct/Initialize()
. = ..()
@@ -66,6 +67,11 @@
CR.button.screen_loc = "6:[pos],4:-2"
CR.button.moved = "6:[pos],4:-2"
+/mob/living/simple_animal/hostile/construct/death()
+ if(original_mind)
+ transfer_ckey(original_mind)
+ ..()
+
/mob/living/simple_animal/hostile/construct/Login()
..()
to_chat(src, playstyle_string)
@@ -107,7 +113,7 @@
return
/mob/living/simple_animal/hostile/construct/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
- return 0
+ return FALSE
/mob/living/simple_animal/hostile/construct/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
. = ..()
diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm
index 75182b85e5..b46b56f472 100644
--- a/code/modules/mob/living/simple_animal/shade.dm
+++ b/code/modules/mob/living/simple_animal/shade.dm
@@ -1,53 +1,33 @@
-/mob/living/simple_animal/shade
+/mob/living/simple_animal/hostile/construct/shade
name = "Shade"
real_name = "Shade"
desc = "A bound spirit."
- gender = PLURAL
- icon = 'icons/mob/mob.dmi'
icon_state = "shade"
icon_living = "shade"
mob_biotypes = MOB_SPIRIT
maxHealth = 40
health = 40
- spacewalk = TRUE
- healable = 0
- speak_emote = list("hisses")
emote_hear = list("wails.","screeches.")
response_help_continuous = "puts their hand through"
response_help_simple = "put your hand through"
- response_disarm_continuous = "flails at"
- response_disarm_simple = "flail at"
- response_harm_continuous = "punches"
- response_harm_simple = "punch"
- speak_chance = 1
melee_damage_lower = 5
melee_damage_upper = 12
attack_verb_continuous = "metaphysically strikes"
attack_verb_simple = "metaphysically strike"
- minbodytemp = 0
- maxbodytemp = INFINITY
- 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)
- stop_automated_movement = 1
- status_flags = 0
- faction = list("cult")
- status_flags = CANPUSH
- movement_type = FLYING
+ speed = -1 //they don't have to lug a body made of runed metal around
loot = list(/obj/item/ectoplasm)
- del_on_death = TRUE
- initial_language_holder = /datum/language_holder/construct
- blood_volume = 0
- has_field_of_vision = FALSE //we are a spoopy ghost
+ playstyle_string = "You are a shade! Your job is to survive until you are granted a shell, and help out cultists with casting runes!"
-/mob/living/simple_animal/shade/death()
+/mob/living/simple_animal/hostile/construct/shade/death()
deathmessage = "lets out a contented sigh as [p_their()] form unwinds."
..()
-/mob/living/simple_animal/shade/canSuicide()
+/mob/living/simple_animal/hostile/construct/shade/canSuicide()
if(istype(loc, /obj/item/soulstone)) //do not suicide inside the soulstone
- return 0
+ return FALSE
return ..()
-/mob/living/simple_animal/shade/attack_animal(mob/living/simple_animal/M)
+/mob/living/simple_animal/hostile/construct/shade/attack_animal(mob/living/simple_animal/M)
if(isconstruct(M))
var/mob/living/simple_animal/hostile/construct/C = M
if(!C.can_repair_constructs)
@@ -62,7 +42,7 @@
else if(src != M)
return ..()
-/mob/living/simple_animal/shade/attackby(obj/item/O, mob/user, params) //Marker -Agouri
+/mob/living/simple_animal/hostile/construct/shade/attackby(obj/item/O, mob/user, params) //Marker -Agouri
if(istype(O, /obj/item/soulstone))
var/obj/item/soulstone/SS = O
SS.transfer_soul("SHADE", src, user)
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 7de30a7095..3a7e270567 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -617,7 +617,7 @@
return 1
if(ispath(MP, /mob/living/simple_animal/hostile/mushroom))
return 1
- if(ispath(MP, /mob/living/simple_animal/shade))
+ if(ispath(MP, /mob/living/simple_animal/hostile/construct/shade))
return 1
if(ispath(MP, /mob/living/simple_animal/hostile/killertomato))
return 1