diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 3720cdf17e3..74f542bda05 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -433,3 +433,6 @@ var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
// Evil narsie colour
#define NARSIE_WINDOW_COLOUR "#7D1919"
+// Defib stats
+#define DEFIB_TIME_LIMIT 120
+#define DEFIB_TIME_LOSS 60
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 4211a3fc106..34360228de4 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -1726,7 +1726,11 @@
return G
break
-
+/datum/mind/proc/grab_ghost(force)
+ var/mob/dead/observer/G = get_ghost(even_if_they_cant_reenter = force)
+ . = G
+ if(G)
+ G.reenter_corpse()
/mob/proc/sync_mind()
mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist)
diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm
index e22248ff602..66bcfd61398 100644
--- a/code/game/gamemodes/blob/blobs/blob_mobs.dm
+++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm
@@ -212,13 +212,17 @@
mob_size = MOB_SIZE_LARGE
see_invisible = SEE_INVISIBLE_MINIMUM
see_in_dark = 8
+ var/independent = FALSE
/mob/living/simple_animal/hostile/blob/blobbernaut/New()
..()
- verbs -= /mob/living/verb/pulled //no pulling people deep into the blob
+ if(!independent) //no pulling people deep into the blob
+ verbs -= /mob/living/verb/pulled
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
if(..())
+ if(independent)
+ return // strong independent blobbernaut that don't need no blob
var/damagesources = 0
if(!(locate(/obj/effect/blob) in range(2, src)))
damagesources++
@@ -271,3 +275,7 @@
factory.naut = null //remove this naut from its factory
factory.maxhealth = initial(factory.maxhealth)
flick("blobbernaut_death", src)
+
+/mob/living/simple_animal/hostile/blob/blobbernaut/independent
+ independent = TRUE
+ gold_core_spawnable = 1
diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm
index b6fccab0bb2..a2b0f999bb8 100644
--- a/code/game/gamemodes/miniantags/morph/morph.dm
+++ b/code/game/gamemodes/miniantags/morph/morph.dm
@@ -144,14 +144,18 @@
visible_message("[src] twists and dissolves into a pile of green flesh!", \
"Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--")
restore()
+ barf_contents()
..()
-/mob/living/simple_animal/hostile/morph/Destroy()
+/mob/living/simple_animal/hostile/morph/proc/barf_contents()
for(var/atom/movable/AM in src)
AM.loc = loc
if(prob(90))
step(AM, pick(alldirs))
- return ..()
+
+/mob/living/simple_animal/hostile/morph/wabbajack_act(mob/living/new_mob)
+ barf_contents()
+ . = ..()
/mob/living/simple_animal/hostile/morph/Aggro() // automated only
..()
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index 3495ad1344a..6925d1b392f 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -137,27 +137,24 @@
// HOT. PINK.
//color = "#FF69B4"
-
-/mob/living/simple_animal/slaughter/laughter/New()
- ..()
-
/mob/living/simple_animal/slaughter/laughter/death()
+ release_friends()
+ . = ..()
+
+/mob/living/simple_animal/slaughter/laughter/wabbajack_act()
+ release_friends()
+ . = ..()
+
+/mob/living/simple_animal/slaughter/laughter/proc/release_friends()
if(!consumed_mobs)
- return ..()
+ return
for(var/mob/living/M in consumed_mobs)
M.loc = get_turf(src)
if(M.revive(full_heal = 1))
- // Feel there should be a better way of FORCING a mob's ghost
- // back into the body
- if(!M.ckey)
- for(var/mob/dead/observer/ghost in player_list)
- if(M.real_name == ghost.real_name)
- ghost.reenter_corpse()
- break
- M << "You leave the [src]'s warm embrace, and feel ready to take on the world."
-
- return ..()
+ M.grab_ghost(force = FALSE)
+ M << "You leave the [src]'s warm embrace, \
+ and feel ready to take on the world."
/mob/living/simple_animal/slaughter/laughter/bloodcrawl_swallow(var/mob/living/victim)
if(consumed_mobs)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 6102f97caee..146610a5197 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -173,6 +173,10 @@ MASS SPECTROMETER
// Time of death
if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
user << "Time of Death: [M.tod]"
+ var/tdelta = world.time - M.timeofdeath
+ if(tdelta < (DEFIB_TIME_LIMIT * 10))
+ user << "Subject died [tdelta / 10] seconds \
+ ago, defibrillation may be possible!"
for(var/datum/disease/D in M.viruses)
if(!(D.visibility_flags & HIDDEN_SCANNER))
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index c04ead47e26..0bb8b547514 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -1,5 +1,4 @@
//backpack item
-
/obj/item/weapon/defibrillator
name = "defibrillator"
desc = "A device that delivers powerful shocks to detachable paddles that resuscitate incapacitated patients."
@@ -19,6 +18,7 @@
var/obj/item/weapon/twohanded/shockpaddles/paddles
var/obj/item/weapon/stock_parts/cell/high/bcell = null
var/combat = 0 //can we revive through space suits?
+ var/grab_ghost = FALSE // Do we pull the ghost back into their body?
/obj/item/weapon/defibrillator/New() //starts without a cell for rnd
..()
@@ -297,6 +297,7 @@
var/obj/item/weapon/defibrillator/defib
var/req_defib = 1
var/combat = 0 //If it penetrates armor and gives additional functionality
+ var/grab_ghost = FALSE
/obj/item/weapon/twohanded/shockpaddles/proc/recharge(var/time)
if(req_defib || !time)
@@ -382,178 +383,186 @@
else
user << "You aren't sure how to revive that..."
return
- else
- var/mob/living/carbon/human/H = M
- if(user.a_intent == "disarm")
- if(req_defib && defib.safety)
- return
- if(!req_defib && !combat)
- return
- busy = 1
- H.visible_message("[user] has touched [H.name] with [src]!", \
- "[user] has touched [H.name] with [src]!")
- H.adjustStaminaLoss(50)
- H.Weaken(5)
- H.updatehealth() //forces health update before next life tick
- playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
- H.emote("gasp")
- add_logs(user, M, "stunned", src)
- if(req_defib)
- defib.deductcharge(revivecost)
- cooldown = 1
- busy = 0
- update_icon()
- if(req_defib)
- defib.cooldowncheck(user)
- else
- recharge(60)
+ var/mob/living/carbon/human/H = M
+
+ if(user.a_intent == "disarm")
+ if(req_defib && defib.safety)
return
- if(user.zone_selected == "chest")
- if(user.a_intent == "harm")
- if(req_defib && defib.safety)
+ if(!req_defib && !combat)
+ return
+ busy = 1
+ H.visible_message("[user] has touched [H.name] with [src]!", \
+ "[user] has touched [H.name] with [src]!")
+ H.adjustStaminaLoss(50)
+ H.Weaken(5)
+ H.updatehealth() //forces health update before next life tick
+ playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
+ H.emote("gasp")
+ add_logs(user, M, "stunned", src)
+ if(req_defib)
+ defib.deductcharge(revivecost)
+ cooldown = 1
+ busy = 0
+ update_icon()
+ if(req_defib)
+ defib.cooldowncheck(user)
+ else
+ recharge(60)
+ return
+
+ if(user.zone_selected != "chest")
+ user << "You need to target your patient's \
+ chest with [src]!"
+ return
+ if(user.a_intent == "harm")
+ if(req_defib && defib.safety)
+ return
+ if(!req_defib && !combat)
+ return
+ user.visible_message("[user] begins to place [src] on [M.name]'s chest.",
+ "You overcharge the paddles and begin to place them onto [M]'s chest...")
+ busy = 1
+ update_icon()
+ if(do_after(user, 30, target = M))
+ user.visible_message("[user] places [src] on [M.name]'s chest.",
+ "You place [src] on [M.name]'s chest and begin to charge them.")
+ var/turf/T = get_turf(defib)
+ playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
+ if(req_defib)
+ T.audible_message("\The [defib] lets out an urgent beep and lets out a steadily rising hum...")
+ else
+ user.audible_message("[src] let out an urgent beep.")
+ if(do_after(user, 30, target = M)) //Takes longer due to overcharging
+ if(!M)
+ busy = 0
+ update_icon()
return
- if(!req_defib && !combat)
+ if(M && M.stat == DEAD)
+ user << "[M] is dead."
+ playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ busy = 0
+ update_icon()
return
- user.visible_message("[user] begins to place [src] on [M.name]'s chest.",
- "You overcharge the paddles and begin to place them onto [M]'s chest...")
- busy = 1
- update_icon()
- if(do_after(user, 30, target = M))
- user.visible_message("[user] places [src] on [M.name]'s chest.",
- "You place [src] on [M.name]'s chest and begin to charge them.")
- var/turf/T = get_turf(defib)
- playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
- if(req_defib)
- T.audible_message("\The [defib] lets out an urgent beep and lets out a steadily rising hum...")
- else
- user.audible_message("[src] let out an urgent beep.")
- if(do_after(user, 30, target = M)) //Takes longer due to overcharging
- if(!M)
- busy = 0
- update_icon()
- return
- if(M && M.stat == DEAD)
- user << "[M] is dead."
- playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
- busy = 0
- update_icon()
- return
- user.visible_message("[user] shocks [M] with \the [src]!", "You shock [M] with \the [src]!")
- playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 100, 1, -1)
- playsound(loc, 'sound/weapons/Egloves.ogg', 100, 1, -1)
- var/mob/living/carbon/human/HU = M
- M.emote("scream")
- if(!HU.heart_attack)
- HU.heart_attack = 1
- if(!HU.stat)
- HU.visible_message("[M] thrashes wildly, clutching at their chest!",
- "You feel a horrible agony in your chest!")
- HU.apply_damage(50, BURN, "chest")
- add_logs(user, M, "overloaded the heart of", defib)
- M.Weaken(5)
- M.Jitter(100)
- if(req_defib)
- defib.deductcharge(revivecost)
- cooldown = 1
- busy = 0
- update_icon()
- if(!req_defib)
- recharge(60)
- if(req_defib && (defib.cooldowncheck(user)))
- return
+ user.visible_message("[user] shocks [M] with \the [src]!", "You shock [M] with \the [src]!")
+ playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 100, 1, -1)
+ playsound(loc, 'sound/weapons/Egloves.ogg', 100, 1, -1)
+ var/mob/living/carbon/human/HU = M
+ M.emote("scream")
+ if(!HU.heart_attack)
+ HU.heart_attack = 1
+ if(!HU.stat)
+ HU.visible_message("[M] thrashes wildly, clutching at their chest!",
+ "You feel a horrible agony in your chest!")
+ HU.apply_damage(50, BURN, "chest")
+ add_logs(user, M, "overloaded the heart of", defib)
+ M.Weaken(5)
+ M.Jitter(100)
+ if(req_defib)
+ defib.deductcharge(revivecost)
+ cooldown = 1
busy = 0
update_icon()
- return
- if(!H.suiciding && !(H.disabilities & NOCLONE)&& !H.hellbound)
- H.notify_ghost_cloning("Your heart is being defibrillated. Re-enter your corpse if you want to be revived!", source = src)
+ if(!req_defib)
+ recharge(60)
+ if(req_defib && (defib.cooldowncheck(user)))
+ return
+ busy = 0
+ update_icon()
+ return
+ if((!req_defib && grab_ghost) || (req_defib && defib.grab_ghost))
+ H.notify_ghost_cloning("Your heart is being defibrillated!")
+ H.grab_ghost() // Shove them back in their body.
+ else if(!H.suiciding && !(H.disabilities & NOCLONE)&& !H.hellbound)
+ H.notify_ghost_cloning("Your heart is being defibrillated. Re-enter your corpse if you want to be revived!", source = src)
- user.visible_message("[user] begins to place [src] on [M.name]'s chest.", "You begin to place [src] on [M.name]'s chest...")
- busy = 1
- update_icon()
- if(do_after(user, 30, target = M)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
- user.visible_message("[user] places [src] on [M.name]'s chest.", "You place [src] on [M.name]'s chest.")
- playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
- var/tplus = world.time - H.timeofdeath
- var/tlimit = 1200 //past this much time the patient is unrecoverable (in deciseconds)
- var/tloss = 600 //brain damage starts setting in on the patient after some time left rotting
- var/total_burn = 0
- var/total_brute = 0
- if(do_after(user, 20, target = M)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
- for(var/obj/item/carried_item in H.contents)
- if(istype(carried_item, /obj/item/clothing/suit/space))
- if((!src.combat && !req_defib) || (req_defib && !defib.combat))
- user.audible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient's chest is obscured. Operation aborted.")
- playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
- busy = 0
- update_icon()
- return
- if(H.stat == DEAD)
- M.visible_message("[M]'s body convulses a bit.")
- playsound(get_turf(src), "bodyfall", 50, 1)
- playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
- total_brute = H.getBruteLoss()
- total_burn = H.getFireLoss()
-
- var/failed = null
-
- if (H.suiciding || (H.disabilities & NOCLONE))
- failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Recovery of patient impossible. Further attempts futile."
- else if (H.hellbound)
- failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's soul appears to be on another plane of existance. Further attempts futile."
- else if (tplus > tlimit)
- failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Body has decayed for too long. Further attempts futile."
- else if (!H.getorgan(/obj/item/organ/heart))
- failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's heart is missing."
- else if(total_burn >= 180 || total_brute >= 180)
- failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile."
- else if(H.get_ghost())
- failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - No activity in patient's brain. Further attempts may be successful."
- else
- var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
- if(!BR || BR.damaged_brain)
- failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain is missing or damaged beyond point of no return. Further attempts futile."
-
- if(failed)
- user.visible_message(failed)
- playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
- else
- //If the body has been fixed so that they would not be in crit when defibbed, give them oxyloss to put them back into crit
- if (H.health > halfwaycritdeath)
- H.adjustOxyLoss(H.health - halfwaycritdeath, 0)
- else
- var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
- var/mobhealth = H.health
- H.adjustOxyLoss((mobhealth - halfwaycritdeath) * (H.getOxyLoss() / overall_damage), 0)
- H.adjustToxLoss((mobhealth - halfwaycritdeath) * (H.getToxLoss() / overall_damage), 0)
- H.adjustFireLoss((mobhealth - halfwaycritdeath) * (total_burn / overall_damage), 0)
- H.adjustBruteLoss((mobhealth - halfwaycritdeath) * (total_brute / overall_damage), 0)
- user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Resuscitation successful.")
- playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
- H.revive()
- H.emote("gasp")
- if(tplus > tloss)
- H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))))
- add_logs(user, M, "revived", defib)
- if(req_defib)
- defib.deductcharge(revivecost)
- cooldown = 1
- update_icon()
- if(req_defib)
- defib.cooldowncheck(user)
- else
- recharge(60)
- else if(H.heart_attack)
- H.heart_attack = 0
- user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.")
- playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
- else
- user.visible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient is not in a valid state. Operation aborted.")
+ user.visible_message("[user] begins to place [src] on [M.name]'s chest.", "You begin to place [src] on [M.name]'s chest...")
+ busy = 1
+ update_icon()
+ if(do_after(user, 30, target = M)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
+ user.visible_message("[user] places [src] on [M.name]'s chest.", "You place [src] on [M.name]'s chest.")
+ playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
+ var/tplus = world.time - H.timeofdeath
+ // past this much time the patient is unrecoverable
+ // (in deciseconds)
+ var/tlimit = DEFIB_TIME_LIMIT * 10
+ // brain damage starts setting in on the patient after
+ // some time left rotting
+ var/tloss = DEFIB_TIME_LOSS * 10
+ var/total_burn = 0
+ var/total_brute = 0
+ if(do_after(user, 20, target = M)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
+ for(var/obj/item/carried_item in H.contents)
+ if(istype(carried_item, /obj/item/clothing/suit/space))
+ if((!src.combat && !req_defib) || (req_defib && !defib.combat))
+ user.audible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient's chest is obscured. Operation aborted.")
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
- busy = 0
- update_icon()
- else
- user << "You need to target your patient's chest with [src]!"
- return
+ busy = 0
+ update_icon()
+ return
+ if(H.stat == DEAD)
+ M.visible_message("[M]'s body convulses a bit.")
+ playsound(get_turf(src), "bodyfall", 50, 1)
+ playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
+ total_brute = H.getBruteLoss()
+ total_burn = H.getFireLoss()
+
+ var/failed = null
+
+ if (H.suiciding || (H.disabilities & NOCLONE))
+ failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Recovery of patient impossible. Further attempts futile."
+ else if (H.hellbound)
+ failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's soul appears to be on another plane of existance. Further attempts futile."
+ else if (tplus > tlimit)
+ failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Body has decayed for too long. Further attempts futile."
+ else if (!H.getorgan(/obj/item/organ/heart))
+ failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's heart is missing."
+ else if(total_burn >= 180 || total_brute >= 180)
+ failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile."
+ else if(H.get_ghost())
+ failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - No activity in patient's brain. Further attempts may be successful."
+ else
+ var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
+ if(!BR || BR.damaged_brain)
+ failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain is missing or damaged beyond point of no return. Further attempts futile."
+
+ if(failed)
+ user.visible_message(failed)
+ playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ else
+ //If the body has been fixed so that they would not be in crit when defibbed, give them oxyloss to put them back into crit
+ if (H.health > halfwaycritdeath)
+ H.adjustOxyLoss(H.health - halfwaycritdeath, 0)
+ else
+ var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
+ var/mobhealth = H.health
+ H.adjustOxyLoss((mobhealth - halfwaycritdeath) * (H.getOxyLoss() / overall_damage), 0)
+ H.adjustToxLoss((mobhealth - halfwaycritdeath) * (H.getToxLoss() / overall_damage), 0)
+ H.adjustFireLoss((mobhealth - halfwaycritdeath) * (total_burn / overall_damage), 0)
+ H.adjustBruteLoss((mobhealth - halfwaycritdeath) * (total_brute / overall_damage), 0)
+ user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Resuscitation successful.")
+ playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
+ H.revive()
+ H.emote("gasp")
+ if(tplus > tloss)
+ H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))))
+ add_logs(user, M, "revived", defib)
+ if(req_defib)
+ defib.deductcharge(revivecost)
+ cooldown = 1
+ update_icon()
+ if(req_defib)
+ defib.cooldowncheck(user)
+ else
+ recharge(60)
+ else if(H.heart_attack)
+ H.heart_attack = 0
+ user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.")
+ playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
+ else
+ user.visible_message("[req_defib ? "[defib]" : "[src]"] buzzes: Patient is not in a valid state. Operation aborted.")
+ playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
+ busy = 0
+ update_icon()
/obj/item/weapon/twohanded/shockpaddles/syndicate
name = "syndicate defibrillator paddles"
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index a04bb808579..2e077506d22 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1024,3 +1024,18 @@ Sorry Giacom. Please don't be mad :(
for(var/datum/objective/sintouched/acedia/A in src.mind.objectives)
return 1
return 0
+
+// Called when we are hit by a bolt of polymorph and changed
+// Generally the mob we are currently in, is about to be deleted
+/mob/living/proc/wabbajack_act(mob/living/new_mob)
+ if(mind)
+ mind.transfer_to(new_mob)
+ else
+ new_mob.key = key
+
+ for(var/para in hasparasites())
+ var/mob/living/simple_animal/hostile/guardian/G = para
+ G.summoner = new_mob
+ G.Recall()
+ G << "Your summoner has changed \
+ form to [new_mob]!"
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
index c6b108c951a..7c710cf6c8c 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
@@ -156,6 +156,13 @@
update_drone_icon()
updateSeeStaticMobs()
+/mob/living/simple_animal/drone/proc/liberate()
+ // F R E E D R O N E
+ laws = "1. You are a Free Drone."
+ src << laws
+ seeStatic = FALSE
+ updateSeeStaticMobs()
+
/mob/living/simple_animal/drone/proc/update_drone_icon()
//Different icons for different hack states
if(!hacked)
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 5b0ed1aaa8d..7f67da0ad76 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -1,3 +1,8 @@
+var/list/slime_colours = list("rainbow", "grey", "purple", "metal", "orange",
+ "blue", "dark blue", "dark purple", "yellow", "silver", "pink", "red",
+ "gold", "green", "adamantine", "oil", "light pink", "bluespace",
+ "cerulean", "sepia", "black", "pyrite")
+
/mob/living/simple_animal/slime
name = "baby slime"
icon = 'icons/mob/slimes.dmi'
@@ -16,7 +21,7 @@
response_disarm = "shoos"
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
- speak_emote = list("chirps")
+ speak_emote = list("telepathically chirps")
bubble_icon = "slime"
layer = 5
@@ -83,19 +88,26 @@
var/datum/action/innate/slime/evolve/E = new
E.Grant(src)
create_reagents(100)
- spawn (0)
- number = rand(1, 1000)
- name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
- icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
- icon_dead = "[icon_state] dead"
- real_name = name
- slime_mutation = mutation_table(colour)
- var/sanitizedcolour = replacetext(colour, " ", "")
- coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
+ spawn(0)
+ set_colour(colour)
..()
+/mob/living/simple_animal/slime/proc/set_colour(new_colour)
+ colour = new_colour
+
+ number = rand(1, 1000)
+ name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
+ real_name = name
+ slime_mutation = mutation_table(colour)
+ var/sanitizedcolour = replacetext(colour, " ", "")
+ coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
+ regenerate_icons()
+
+/mob/living/simple_animal/slime/proc/random_colour()
+ set_colour(pick(slime_colours))
+
/mob/living/simple_animal/slime/regenerate_icons()
- overlays.len = 0
+ overlays.Cut()
var/icon_text = "[colour] [is_adult ? "adult" : "baby"] slime"
icon_dead = "[icon_text] dead"
if(stat != DEAD)
@@ -107,7 +119,7 @@
..()
/mob/living/simple_animal/slime/movement_delay()
- if(bodytemperature >= 330.23) // 135 F
+ if(bodytemperature >= 330.23) // 135 F or 57.08 C
return -1 // slimes become supercharged at high temperatures
. = ..()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 5efb361452b..543a564c788 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -764,6 +764,10 @@ var/next_mob_id = 0
if(mind)
return mind.get_ghost(even_if_they_cant_reenter)
+/mob/proc/grab_ghost(force)
+ if(mind)
+ return mind.grab_ghost(force = force)
+
/mob/proc/notify_ghost_cloning(var/message = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!", var/sound = 'sound/effects/genetics.ogg', var/atom/source = null)
var/mob/dead/observer/ghost = get_ghost()
if(ghost)
diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm
index cbe4524c9f9..b0e825110af 100644
--- a/code/modules/projectiles/projectile/magic.dm
+++ b/code/modules/projectiles/projectile/magic.dm
@@ -61,12 +61,9 @@
var/mob/living/carbon/C = target
C.regenerate_limbs()
if(target.revive(full_heal = 1))
- if(!target.ckey)
- for(var/mob/dead/observer/ghost in player_list)
- if(target.real_name == ghost.real_name)
- ghost.reenter_corpse()
- break
- target << "You rise with a start, you're alive!!!"
+ target.grab_ghost(force = TRUE) // even suicides
+ target << "You rise with a start, \
+ you're alive!!!"
else if(target.stat != DEAD)
target << "You feel great!"
@@ -175,7 +172,7 @@
if("drone")
new_mob = new /mob/living/simple_animal/drone(M.loc)
var/mob/living/simple_animal/drone/D = new_mob
- D.update_drone_hack()
+ D.liberate() // F R E E D R O N E
if(issilicon(new_mob))
new_mob.gender = M.gender
new_mob.invisibility = 0
@@ -186,9 +183,10 @@
new_mob.languages |= HUMAN
if("slime")
new_mob = new /mob/living/simple_animal/slime(M.loc)
+ var/mob/living/simple_animal/slime/slimey = new_mob
if(prob(50))
- var/mob/living/simple_animal/slime/Slime = new_mob
- Slime.is_adult = 1
+ slimey.is_adult = 1
+ slimey.random_colour()
new_mob.languages |= HUMAN
if("xeno")
if(prob(50))
@@ -220,7 +218,7 @@
if("spiderhunter")
new_mob = new /mob/living/simple_animal/hostile/poison/giant_spider/hunter(M.loc)
if("blobbernaut")
- new_mob = new /mob/living/simple_animal/hostile/blob/blobbernaut(M.loc)
+ new_mob = new /mob/living/simple_animal/hostile/blob/blobbernaut/independent(M.loc)
if("magicarp")
new_mob = new /mob/living/simple_animal/hostile/carp/ranged(M.loc)
if("chaosmagicarp")
@@ -279,10 +277,8 @@
M.attack_log += text("\[[time_stamp()]\] [M.real_name] ([M.ckey]) became [new_mob.real_name].")
new_mob.a_intent = "harm"
- if(M.mind)
- M.mind.transfer_to(new_mob)
- else
- new_mob.key = M.key
+
+ M.wabbajack_act(new_mob)
new_mob << "Your form morphs into that of a [randomize]."