diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm
index be263c915b8f..b882d6dec2c7 100644
--- a/code/datums/spells/lichdom.dm
+++ b/code/datums/spells/lichdom.dm
@@ -10,10 +10,10 @@
level_max = 0 //cannot be improved
cooldown_min = 10
- var/obj/marked_item
+ var/marked_item_uid
var/mob/living/current_body
var/resurrections = 0
- var/existence_stops_round_end = 0
+ var/existence_stops_round_end = FALSE
action_icon_state = "skeleton"
@@ -30,106 +30,148 @@
return ..()
/obj/effect/proc_holder/spell/lichdom/cast(list/targets, mob/user = usr)
- if(!GLOB.configuration.gamemode.disable_certain_round_early_end)
- existence_stops_round_end = TRUE
- GLOB.configuration.gamemode.disable_certain_round_early_end = TRUE
-
for(var/mob/M in targets)
- var/list/hand_items = list()
- if(iscarbon(M))
- hand_items = list(M.get_active_hand(), M.get_inactive_hand())
-
- if(marked_item && !stat_allowed) //sanity, shouldn't happen without badminry
- marked_item = null
- return
-
- if(stat_allowed) //Death is not my end!
- if(M.stat == CONSCIOUS && iscarbon(M))
- to_chat(M, "You aren't dead enough to revive!")//Usually a good problem to have
-
- cooldown_handler.revert_cast()
- return
-
- if(!marked_item || QDELETED(marked_item)) //Wait nevermind
- to_chat(M, "Your phylactery is gone!")
+ if(stat_allowed)
+ attempt_revive(M)
+ else if(!marked_item_uid)
+ attempt_mark_item(M)
+
+/obj/effect/proc_holder/spell/lichdom/proc/attempt_revive(mob/user)
+ // Can only cast when unconscious/dead
+ if(user.stat == CONSCIOUS)
+ to_chat(user, "You aren't dead enough to revive!")
+ cooldown_handler.revert_cast()
+ return
+
+ // Body was destroyed
+ if(QDELETED(current_body))
+ to_chat(user, "Your body is gone!")
+ return
+
+ // Phylactery was destroyed
+ var/obj/item/marked_item = locateUID(marked_item_uid)
+ if(QDELETED(marked_item))
+ to_chat(user, "Your phylactery is gone!")
+ return
+
+ // Wrong z-level
+ var/turf/body_turf = get_turf(current_body)
+ var/turf/item_turf = get_turf(marked_item)
+ if(body_turf.z != item_turf.z)
+ to_chat(user, "Your phylactery is out of range!")
+ return
+
+ if(isobserver(user))
+ var/mob/dead/observer/O = user
+ O.reenter_corpse()
+
+ // Clean up the old body
+ if(!QDELETED(current_body))
+ if(iscarbon(current_body))
+ var/mob/living/carbon/C = current_body
+ for(var/obj/item/W in C)
+ C.unEquip(W)
+
+ // Give a hint as to where the body is
+ var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf))
+ if(wheres_wizdo)
+ current_body.visible_message("Suddenly [current_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!")
+ body_turf.Beam(item_turf, icon_state = "lichbeam", icon = 'icons/effects/effects.dmi', time = 10 + 10 * resurrections, maxdistance = INFINITY)
+
+ UnregisterSignal(current_body, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_Z_CHANGED))
+ current_body.dust()
+
+ var/stun_time = (1 + resurrections++) * 20 SECONDS
+
+ var/mob/living/carbon/human/lich = new /mob/living/carbon/human(item_turf)
+ lich.set_species(/datum/species/skeleton/lich)
+ lich.real_name = user.mind.name
+ lich.Weaken(stun_time)
+ user.mind.transfer_to(lich)
+ equip_lich(lich)
+ RegisterSignal(lich, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_Z_CHANGED), PROC_REF(check_revivability_handler))
+
+ current_body = lich
+ cooldown_handler.recharge_duration += 1 MINUTES
+ to_chat(lich, "Your bones clatter and shudder as they're pulled back into this world!")
+
+/obj/effect/proc_holder/spell/lichdom/proc/attempt_mark_item(mob/user)
+ var/obj/item/target = user.get_active_hand()
+ if(!target)
+ to_chat(user, "You must hold an item you wish to make your phylactery!")
+ return
+
+ if(target.flags & (ABSTRACT|NODROP))
+ to_chat(user, "[target] cannot be used as your phylactery!")
+ return
+
+ if(!do_after(user, 5 SECONDS, target = target))
+ to_chat(user, "Your soul snaps back to your body as you drop [target]!")
+ return
+
+ name = "RISE!"
+ desc = "Rise from the dead! You will reform at the location of your phylactery and your old body will crumble away."
+ stat_allowed = UNCONSCIOUS
+ cooldown_handler.recharge_duration = 3 MINUTES
+ cooldown_handler.revert_cast()
+
+ if(action && action.button)
+ action.name = action.button.name = name
+ action.desc = action.button.desc = desc
+
+ target.name = "ensouled [target.name]"
+ target.desc += "
A terrible aura surrounds this item, its very existence is offensive to life itself..."
+ target.color = "#003300"
+ marked_item_uid = target.UID()
+
+ current_body = user.mind.current
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ H.set_species(/datum/species/skeleton/lich)
+ H.unEquip(H.wear_suit)
+ H.unEquip(H.head)
+ H.unEquip(H.shoes)
+ H.unEquip(H.head)
+ equip_lich(H)
+
+ RegisterSignal(target, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_Z_CHANGED), PROC_REF(check_revivability_handler))
+ RegisterSignal(current_body, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_Z_CHANGED), PROC_REF(check_revivability_handler))
+ to_chat(user, "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!")
+
+ existence_stops_round_end = TRUE
+ GLOB.configuration.gamemode.disable_certain_round_early_end = TRUE
+
+/obj/effect/proc_holder/spell/lichdom/proc/is_revive_possible()
+ var/obj/item/marked_item = locateUID(marked_item_uid)
+ if(QDELETED(marked_item))
+ return FALSE
+ if(QDELETED(current_body))
+ return FALSE
+ var/turf/body_turf = get_turf(current_body)
+ var/turf/item_turf = get_turf(marked_item)
+ if(body_turf.z != item_turf.z)
+ return FALSE
+ return TRUE
+
+/obj/effect/proc_holder/spell/lichdom/proc/check_revivability_handler()
+ SIGNAL_HANDLER
+
+ // There are other liches about, so round may still continue
+ for(var/datum/mind/M in SSticker.mode.wizards)
+ for(var/obj/effect/proc_holder/spell/lichdom/S in M.spell_list)
+ if(S == src)
+ continue
+ // Other lich can still revive
+ if(S.is_revive_possible())
return
-
- var/turf/user_turf = get_turf(M)
- var/turf/item_turf = get_turf(marked_item)
-
- if(user_turf.z != item_turf.z)
- to_chat(M, "Your phylactery is out of range!")
- return
-
- if(isobserver(M))
- var/mob/dead/observer/O = M
- O.reenter_corpse()
-
- var/mob/living/carbon/human/lich = new /mob/living/carbon/human(item_turf)
-
- lich.real_name = M.mind.name
- M.mind.transfer_to(lich)
- lich.set_species(/datum/species/skeleton/lich) // Wizard variant
- to_chat(lich, "Your bones clatter and shudder as they're pulled back into this world!")
- cooldown_handler.recharge_duration += 1 MINUTES
- var/mob/old_body = current_body
- var/turf/body_turf = get_turf(old_body)
- current_body = lich
- var/stun_time = (1 + resurrections) * 20 SECONDS
- lich.Weaken(stun_time)
- ++resurrections
- equip_lich(lich)
-
- if(old_body && old_body.loc)
- if(iscarbon(old_body))
- var/mob/living/carbon/C = old_body
- for(var/obj/item/W in C)
- C.unEquip(W)
- var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf))
- if(wheres_wizdo)
- old_body.visible_message("Suddenly [old_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!")
- body_turf.Beam(item_turf,icon_state="lichbeam",icon='icons/effects/effects.dmi',time=10+10*resurrections,maxdistance=INFINITY)
- old_body.dust()
-
- if(!marked_item) //linking item to the spell
- message = ""
- for(var/obj/item in hand_items)
- if((ABSTRACT in item.flags) || (NODROP in item.flags))
- continue
- marked_item = item
- to_chat(M, "You begin to focus your very being into [item]...")
- break
-
- if(!marked_item)
- to_chat(M, "You must hold an item you wish to make your phylactery...")
+ // Other lich is still alive
+ if(!QDELETED(S.current_body) && S.current_body.stat != DEAD)
return
- spawn(50)
- if(marked_item.loc != M) //I changed my mind I don't want to put my soul in a cheeseburger!
- to_chat(M, "Your soul snaps back to your body as you drop [marked_item]!")
- marked_item = null
- return
- name = "RISE!"
- desc = "Rise from the dead! You will reform at the location of your phylactery and your old body will crumble away."
- cooldown_handler.recharge_duration = 3 MINUTES
- cooldown_handler.revert_cast()
- stat_allowed = UNCONSCIOUS
- marked_item.name = "Ensouled [marked_item.name]"
- marked_item.desc = "A terrible aura surrounds this item, its very existence is offensive to life itself..."
- marked_item.color = "#003300"
- to_chat(M, "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!")
- current_body = M.mind.current
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- H.set_species(/datum/species/skeleton/lich)
- H.unEquip(H.wear_suit)
- H.unEquip(H.head)
- H.unEquip(H.shoes)
- H.unEquip(H.head)
- equip_lich(H)
+ GLOB.configuration.gamemode.disable_certain_round_early_end = is_revive_possible()
/obj/effect/proc_holder/spell/lichdom/proc/equip_lich(mob/living/carbon/human/H)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), SLOT_HUD_OUTER_SUIT)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), SLOT_HUD_HEAD)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), SLOT_HUD_SHOES)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), SLOT_HUD_JUMPSUIT)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), SLOT_HUD_OUTER_SUIT)
+ H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), SLOT_HUD_HEAD)
+ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), SLOT_HUD_SHOES)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), SLOT_HUD_JUMPSUIT)