mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-11 15:14:27 +01:00
504 lines
21 KiB
Plaintext
504 lines
21 KiB
Plaintext
// This whole file really needs reorganising at some point, or at the very least the construct stuff should be moved somewhere else.
|
|
/obj/item/soulstone
|
|
name = "soul stone shard"
|
|
icon = 'icons/obj/wizard.dmi'
|
|
icon_state = "soulstone"
|
|
item_state = "electronic"
|
|
belt_icon = "soulstone"
|
|
var/icon_state_full = "soulstone2"
|
|
desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artifact's power."
|
|
w_class = WEIGHT_CLASS_TINY
|
|
slot_flags = SLOT_FLAG_BELT
|
|
origin_tech = "bluespace=4;materials=5"
|
|
|
|
/// Should we show rays? Triggered by a held body
|
|
var/animate_rays = FALSE
|
|
/// Does this soulstone ask the victim whether they want to be turned into a shade
|
|
var/optional = FALSE
|
|
/// Can this soul stone be used by anyone, or only cultists/wizards?
|
|
var/usability = FALSE
|
|
/// Can this soul stone be used more than once?
|
|
var/reusable = TRUE
|
|
/// If the soul stone can only be used once, has it been used?
|
|
var/spent = FALSE
|
|
|
|
/// For tracking during the 'optional' bit
|
|
var/opt_in = FALSE
|
|
var/purified = FALSE
|
|
|
|
|
|
/obj/item/soulstone/proc/can_use(mob/living/user)
|
|
if(IS_CULTIST(user) && purified && !iswizard(user))
|
|
return FALSE
|
|
|
|
if(IS_CULTIST(user) || iswizard(user) || (HAS_MIND_TRAIT(user, TRAIT_HOLY) && purified) || usability)
|
|
return TRUE
|
|
|
|
return FALSE
|
|
|
|
/obj/item/soulstone/proc/was_used()
|
|
if(!reusable)
|
|
spent = TRUE
|
|
name = "dull [initial(name)]"
|
|
desc = "A fragment of the legendary treasure known simply as \
|
|
the 'Soul Stone'. The shard lies still, dull and lifeless; \
|
|
whatever spark it once held long extinguished."
|
|
|
|
/obj/item/soulstone/anybody
|
|
usability = TRUE
|
|
|
|
/obj/item/soulstone/anybody/purified
|
|
icon_state = "purified_soulstone"
|
|
icon_state_full = "purified_soulstone2"
|
|
purified = TRUE
|
|
optional = TRUE
|
|
|
|
/obj/item/soulstone/anybody/purified/chaplain
|
|
name = "mysterious old shard"
|
|
reusable = FALSE
|
|
|
|
/obj/item/soulstone/pickup(mob/living/user)
|
|
. = ..()
|
|
if(IS_CULTIST(user) && purified && !iswizard(user))
|
|
to_chat(user, "<span class='danger'>[src] reeks of holy magic. You will need to cleanse it with a ritual dagger before anything can be done with it.</span>")
|
|
return
|
|
if(HAS_MIND_TRAIT(user, TRAIT_HOLY))
|
|
to_chat(user, "<span class='danger'>An overwhelming feeling of dread comes over you as you pick up [src]. It looks fragile enough to break with your hands.</span>")
|
|
return
|
|
if(!can_use(user))
|
|
to_chat(user, "<span class='danger'>An overwhelming feeling of dread comes over you as you pick up [src].</span>")
|
|
|
|
/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)
|
|
A.death()
|
|
STOP_PROCESSING(SSobj, src)
|
|
return ..()
|
|
|
|
/obj/item/soulstone/process()
|
|
. = ..()
|
|
if(animate_rays)
|
|
var/new_filter = isnull(get_filter("ray"))
|
|
if(!purified)
|
|
ray_filter_helper(1, 40,"#c926ae", 6, 20)
|
|
else
|
|
ray_filter_helper(1, 40,"#268dc9", 6, 20)
|
|
if(new_filter)
|
|
animate(get_filter("ray"), offset = 10, time = 10 SECONDS, loop = -1)
|
|
animate(offset = 0, time = 10 SECONDS)
|
|
|
|
//////////////////////////////Capturing////////////////////////////////////////////////////////
|
|
/obj/item/soulstone/attack(mob/living/carbon/human/M, mob/living/user)
|
|
if(M == user)
|
|
return
|
|
|
|
if(!can_use(user))
|
|
user.Weaken(10 SECONDS)
|
|
user.emote("scream")
|
|
to_chat(user, "<span class='userdanger'>Your body is wracked with debilitating pain!</span>")
|
|
return
|
|
|
|
if(spent)
|
|
to_chat(user, "<span class='warning'>There is no power left in the shard.</span>")
|
|
return
|
|
|
|
if(!ishuman(M)) //If target is not a human
|
|
return ..()
|
|
|
|
if(!M.mind)
|
|
to_chat(user, "<span class='warning'>This being has no soul!</span>")
|
|
return ..()
|
|
|
|
if(jobban_isbanned(M, ROLE_CULTIST) || jobban_isbanned(M, ROLE_SYNDICATE))
|
|
to_chat(user, "<span class='warning'>A mysterious force prevents you from trapping this being's soul.</span>")
|
|
return ..()
|
|
|
|
if(IS_CULTIST(user) && IS_CULTIST(M))
|
|
to_chat(user, "<span class='cultlarge'>\"Come now, do not capture your fellow's soul.\"</span>")
|
|
return ..()
|
|
|
|
if((M.mind.offstation_role && M.mind.special_role != SPECIAL_ROLE_ERT) || HAS_MIND_TRAIT(M, TRAIT_XENOBIO_SPAWNED_HUMAN))
|
|
to_chat(user, "<span class='warning'>This being's soul seems worthless. Not even the stone will absorb it.</span>")
|
|
return ..()
|
|
|
|
if(optional)
|
|
if(!M.ckey)
|
|
to_chat(user, "<span class='warning'>They have no soul!</span>")
|
|
return
|
|
|
|
to_chat(user, "<span class='warning'>You attempt to channel [M]'s soul into [src]. You must give the soul some time to react and stand still...</span>")
|
|
|
|
var/mob/player_mob = M
|
|
var/ghost = M.get_ghost()
|
|
if(ghost) // In case our player ghosted and we need to throw the alert at their ghost instead
|
|
player_mob = ghost
|
|
var/client/player_client = player_mob.client
|
|
to_chat(player_mob, "<span class='warning'>[user] is trying to capture your soul into [src]! Click the button in the top right of the game window to respond.</span>")
|
|
SEND_SOUND(player_client, sound('sound/misc/notice2.ogg'))
|
|
window_flash(player_client)
|
|
|
|
var/atom/movable/screen/alert/notify_soulstone/A = player_mob.throw_alert("\ref[src]_soulstone_thingy", /atom/movable/screen/alert/notify_soulstone)
|
|
if(player_client.prefs && player_client.prefs.UI_style)
|
|
A.icon = ui_style2icon(player_client.prefs.UI_style)
|
|
|
|
// Pass the stuff to the alert itself
|
|
A.stone = src
|
|
A.stoner = user.real_name
|
|
|
|
// Layer shenanigans to make the alert display the soulstone
|
|
var/old_layer = layer
|
|
var/old_plane = plane
|
|
layer = FLOAT_LAYER
|
|
plane = FLOAT_PLANE
|
|
A.overlays += src
|
|
layer = old_layer
|
|
plane = old_plane
|
|
|
|
// Give the victim 10 seconds to respond
|
|
sleep(10 SECONDS)
|
|
|
|
if(!opt_in)
|
|
to_chat(user, "<span class='warning'>The soul resists your attempts at capturing it!</span>")
|
|
return
|
|
|
|
opt_in = FALSE
|
|
|
|
if(spent)//checking one more time against shenanigans
|
|
return
|
|
|
|
add_attack_logs(user, M, "Stolestone'd with [name]")
|
|
transfer_soul("VICTIM", M, user)
|
|
return
|
|
|
|
/obj/item/soulstone/attackby(obj/item/O, mob/user)
|
|
if(istype(O, /obj/item/storage/bible) && !IS_CULTIST(user) && HAS_MIND_TRAIT(user, TRAIT_HOLY))
|
|
if(purified)
|
|
return
|
|
to_chat(user, "<span class='notice'>You begin to exorcise [src].</span>")
|
|
playsound(src, 'sound/hallucinations/veryfar_noise.ogg', 40, TRUE)
|
|
if(do_after(user, 40, target = src))
|
|
remove_filter("ray")
|
|
usability = TRUE
|
|
purified = TRUE
|
|
optional = TRUE
|
|
icon_state = "purified_soulstone"
|
|
icon_state_full = "purified_soulstone2"
|
|
for(var/mob/M in contents)
|
|
if(M.mind)
|
|
icon_state = "purified_soulstone2"
|
|
if(IS_CULTIST(M))
|
|
M.mind.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE)
|
|
to_chat(M, "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of [GET_CULT_DATA(entity_title1, "Nar'Sie")] \
|
|
and the memories of your time as their servant with it.</span>")
|
|
to_chat(M, "<span class='danger'>Assist [user], your saviour, and get vengeance on those who enslaved you!</span>")
|
|
else
|
|
to_chat(M, "<span class='danger'>Your soulstone has been exorcised, and you are now bound to obey [user].</span>")
|
|
|
|
for(var/mob/living/simple_animal/shade/EX in src)
|
|
EX.holy = TRUE
|
|
EX.icon_state = "shade_angelic"
|
|
user.visible_message("<span class='notice'>[user] purifies [src]!</span>", "<span class='notice'>You purify [src]!</span>")
|
|
|
|
else if(istype(O, /obj/item/melee/cultblade/dagger) && IS_CULTIST(user))
|
|
if(!purified)
|
|
return
|
|
to_chat(user, "<span class='notice'>You begin to cleanse [src] of holy magic.</span>")
|
|
if(do_after(user, 40, target = src))
|
|
remove_filter("ray")
|
|
usability = FALSE
|
|
purified = FALSE
|
|
optional = FALSE
|
|
icon_state = "soulstone"
|
|
icon_state_full = "soulstone2"
|
|
for(var/mob/M in contents)
|
|
if(M.mind)
|
|
icon_state = "soulstone2"
|
|
M.mind.add_antag_datum(/datum/antagonist/cultist)
|
|
to_chat(M, "<span class='cult'>Your shard has been cleansed of holy magic, and you are now bound to the cult's will. Obey them and assist in their goals.</span>")
|
|
for(var/mob/living/simple_animal/shade/EX in src)
|
|
EX.holy = FALSE
|
|
EX.icon_state = GET_CULT_DATA(shade_icon_state, "shade")
|
|
to_chat(user, "<span class='notice'>You have cleansed [src] of holy magic.</span>")
|
|
else
|
|
..()
|
|
|
|
/obj/item/soulstone/attack_self(mob/living/user)
|
|
var/mob/living/simple_animal/shade/S = locate(/mob/living/simple_animal/shade) in contents
|
|
if(!in_range(src, user) || !S)
|
|
return
|
|
|
|
if(can_use(user))
|
|
release_shades(user)
|
|
return
|
|
|
|
if(!HAS_MIND_TRAIT(user, TRAIT_HOLY))
|
|
to_chat(user, "<span class='notice'>The shard feels too tough to shatter, you are not holy enough to free its captive!</span>")
|
|
return
|
|
|
|
if(!do_after_once(user, 10 SECONDS, FALSE, src))
|
|
return
|
|
|
|
if(!S)
|
|
return
|
|
|
|
var/datum/component/construct_held_body/body_holder = S.GetComponent(/datum/component/construct_held_body)
|
|
var/atom/movable/dropped_body = body_holder.held_body
|
|
body_holder.drop_body()
|
|
if(!dropped_body)
|
|
return
|
|
|
|
user.visible_message("[user] shatters the soulstone apart! Releasing [dropped_body] from their prison!", "You shatter the soulstone holding [dropped_body], binding them free!", "You hear something shatter with a ghastly crack.")
|
|
new /obj/effect/temp_visual/cult/sparks(get_turf(src))
|
|
playsound(src, 'sound/effects/pylon_shatter.ogg', 40, TRUE)
|
|
qdel(src)
|
|
|
|
/obj/item/soulstone/proc/release_shades(mob/user)
|
|
for(var/mob/living/simple_animal/shade/A in src)
|
|
A.forceMove(get_turf(user))
|
|
A.cancel_camera()
|
|
if(purified)
|
|
icon_state = "purified_soulstone"
|
|
else
|
|
icon_state = "soulstone"
|
|
name = initial(name)
|
|
if(IS_CULTIST(A))
|
|
to_chat(A, "<span class='userdanger'>You have been released from your prison, but you are still bound to the cult's will. Help them succeed in their goals at all costs.</span>")
|
|
else
|
|
to_chat(A, "<span class='userdanger'>You have been released from your prison, but you are still bound to your [purified ? "saviour" : "creator"]'s will.</span>")
|
|
was_used()
|
|
remove_filter("ray")
|
|
STOP_PROCESSING(SSobj, src)
|
|
animate_rays = FALSE
|
|
|
|
///////////////////////////Transferring to constructs/////////////////////////////////////////////////////
|
|
/obj/structure/constructshell
|
|
name = "empty shell"
|
|
icon = 'icons/obj/wizard.dmi'
|
|
icon_state = "construct-cult"
|
|
desc = "A wicked machine used by those skilled in magical arts. It is inactive"
|
|
/// Is someone currently placing a soulstone into the shell
|
|
var/active = FALSE
|
|
|
|
/obj/structure/constructshell/examine(mob/user)
|
|
. = ..()
|
|
if(in_range(user, src) && (IS_CULTIST(user) || iswizard(user) || user.stat == DEAD))
|
|
. += "<span class='cult'>A construct shell, used to house bound souls from a soulstone.</span>"
|
|
. += "<span class='cult'>Placing a soulstone with a soul into this shell allows you to produce your choice of the following:</span>"
|
|
. += "<span class='cultitalic'>An <b>Artificer</b>, which can produce <b>more shells and soulstones</b>, as well as fortifications.</span>"
|
|
. += "<span class='cultitalic'>A <b>Wraith</b>, which does high damage and can jaunt through walls, though it is quite fragile.</span>"
|
|
. += "<span class='cultitalic'>A <b>Juggernaut</b>, which is very hard to kill and can produce temporary walls, but is slow.</span>"
|
|
|
|
/obj/structure/constructshell/attackby(obj/item/I, mob/living/user, params)
|
|
if(istype(I, /obj/item/soulstone))
|
|
var/obj/item/soulstone/SS = I
|
|
if(!SS.can_use(user))
|
|
to_chat(user, "<span class='danger'>An overwhelming feeling of dread comes over you as you attempt to place the soulstone into the shell.</span>")
|
|
user.Confused(20 SECONDS)
|
|
return
|
|
SS.transfer_soul("CONSTRUCT", src, user)
|
|
SS.was_used()
|
|
else
|
|
return ..()
|
|
|
|
////////////////////////////Proc for moving soul in and out off stone//////////////////////////////////////
|
|
// this whole proc is pain
|
|
/obj/item/soulstone/proc/transfer_soul(choice, target, mob/living/user)
|
|
switch(choice)
|
|
if("FORCE")
|
|
var/mob/living/T = target
|
|
T.grab_ghost(FALSE) // If they haven't DC'd or ahudded, put them back in their body
|
|
if(T.client) // If there's someone in the body
|
|
init_shade(T, user)
|
|
else // Poll ghosts
|
|
to_chat(user, "<span class='userdanger'>Capture failed!</span> The soul has already fled its mortal frame. You attempt to bring it back...")
|
|
T.Paralyse(40 SECONDS)
|
|
if(!get_cult_ghost(T, user, TRUE))
|
|
// no luck, dont shard them.
|
|
to_chat(user, "<span class='userdanger'>No soul responds to the soul stone.</span>")
|
|
|
|
if("VICTIM")
|
|
var/mob/living/carbon/human/T = target
|
|
if(T.stat == CONSCIOUS)
|
|
to_chat(user, "<span class='danger'>Capture failed!</span> Kill or maim the victim first!")
|
|
else
|
|
if(!length(T.client_mobs_in_contents))
|
|
to_chat(user, "<span class='warning'>They have no soul!</span>")
|
|
else
|
|
if(T.client == null)
|
|
to_chat(user, "<span class='userdanger'>Capture failed!</span> The soul has already fled its mortal frame. You attempt to bring it back...")
|
|
get_cult_ghost(T, user, get_new_player = !T.ghost_can_reenter())
|
|
else
|
|
if(length(contents))
|
|
to_chat(user, "<span class='danger'>Capture failed!</span> The soul stone is full! Use or free an existing soul to make room.")
|
|
else
|
|
init_shade(T, user, TRUE)
|
|
|
|
if("SHADE")
|
|
var/mob/living/simple_animal/shade/T = target
|
|
if(!can_use(user))
|
|
user.Weaken(10 SECONDS)
|
|
to_chat(user, "<span class='userdanger'>Your body is wracked with debilitating pain!</span>")
|
|
return
|
|
if(T.stat == DEAD)
|
|
to_chat(user, "<span class='danger'>Capture failed!</span> The shade has already been banished!")
|
|
if((IS_CULTIST(T) && purified) || (T.holy && !purified))
|
|
to_chat(user, "<span class='danger'>Capture failed!</span> The shade recoils away from [src]!")
|
|
else
|
|
if(locate(/mob/living/simple_animal/shade) in contents)
|
|
to_chat(user, "<span class='danger'>Capture failed!</span>: The soul stone is full! Use or free an existing soul to make room.")
|
|
else
|
|
T.forceMove(src) // Put the shade into the stone.
|
|
T.health = T.maxHealth
|
|
icon_state = icon_state_full
|
|
name = "soulstone : [T.name]"
|
|
to_chat(T, "<span class='notice'>Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form</span>")
|
|
to_chat(user, "<span class='notice'>Capture successful!</span> [T.name]'s has been recaptured and stored within the soul stone.")
|
|
animate_rays = TRUE
|
|
START_PROCESSING(SSobj, src)
|
|
|
|
if("CONSTRUCT")
|
|
var/obj/structure/constructshell/shell = target
|
|
var/mob/living/simple_animal/shade/shade = locate() in src
|
|
var/list/construct_types = list("Juggernaut" = /mob/living/simple_animal/hostile/construct/armoured,
|
|
"Wraith" = /mob/living/simple_animal/hostile/construct/wraith,
|
|
"Artificer" = /mob/living/simple_animal/hostile/construct/builder)
|
|
/// Custom construct icons for different cults
|
|
var/list/construct_icons = list("Juggernaut" = image(icon = 'icons/mob/cult.dmi', icon_state = GET_CULT_DATA(get_icon("juggernaut"), "behemoth")),
|
|
"Wraith" = image(icon = 'icons/mob/cult.dmi', icon_state = GET_CULT_DATA(get_icon("wraith"), "floating")),
|
|
"Artificer" = image(icon = 'icons/mob/cult.dmi', icon_state = GET_CULT_DATA(get_icon("builder"), "artificer")))
|
|
|
|
if(shade)
|
|
var/construct_choice = show_radial_menu(user, shell, construct_icons, custom_check = CALLBACK(src, PROC_REF(radial_check), user), require_near = TRUE)
|
|
var/picked_class = construct_types[construct_choice]
|
|
if((picked_class && !QDELETED(shell) && !QDELETED(src)) && user.Adjacent(shell) && !user.incapacitated() && radial_check(user))
|
|
var/mob/living/simple_animal/hostile/construct/C = new picked_class(shell.loc)
|
|
C.init_construct(shade, src, shell)
|
|
to_chat(C, C.playstyle_string)
|
|
to_chat(C, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Construct)</span>")
|
|
else
|
|
to_chat(user, "<span class='danger'>Creation failed!</span>: The soul stone is empty! Go kill someone!")
|
|
|
|
/obj/item/soulstone/proc/radial_check(mob/user)
|
|
if(!ishuman(user)) // Should never happen, but just in case
|
|
return FALSE
|
|
|
|
var/mob/living/carbon/human/H = user
|
|
if(!H.is_in_hands(src)) // Not holding the soulstone
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/mob/living/simple_animal/hostile/construct/proc/init_construct(mob/living/simple_animal/shade/shade, obj/item/soulstone/SS, obj/structure/constructshell/shell)
|
|
if(shade.mind)
|
|
shade.mind.transfer_to(src)
|
|
if(SS.usability)
|
|
// Replace regular soulstone summoning with anyuse soulstones
|
|
if(is_type_in_list(/datum/spell/aoe/conjure/build/soulstone, mob_spell_list))
|
|
RemoveSpell(/datum/spell/aoe/conjure/build/soulstone)
|
|
AddSpell(new /datum/spell/aoe/conjure/build/soulstone/any)
|
|
if(SS.purified)
|
|
make_holy()
|
|
// Replace regular soulstone summoning with purified soulstones
|
|
if(is_type_in_list(/datum/spell/aoe/conjure/build/soulstone, mob_spell_list))
|
|
RemoveSpell(/datum/spell/aoe/conjure/build/soulstone)
|
|
AddSpell(new /datum/spell/aoe/conjure/build/soulstone/holy)
|
|
else if(mind.has_antag_datum(/datum/antagonist/cultist)) // Re-grant cult actions, lost in the transfer
|
|
var/datum/action/innate/cult/comm/CC = new
|
|
var/datum/action/innate/cult/check_progress/D = new
|
|
CC.Grant(src)
|
|
D.Grant(src)
|
|
SSticker.mode.cult_team.study_objectives(src) // Display objectives again
|
|
to_chat(src, "<span class='userdanger'>You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.</span>")
|
|
else
|
|
to_chat(src, "<span class='userdanger'>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</span>")
|
|
|
|
SEND_SIGNAL(shade, COMSIG_SHADE_TO_CONSTRUCT_TRANSFER, src)
|
|
cancel_camera()
|
|
qdel(shell)
|
|
qdel(shade)
|
|
qdel(SS)
|
|
|
|
/proc/make_new_construct(mob/living/simple_animal/hostile/construct/c_type, mob/target, mob/user, cult_override = FALSE, create_smoke = FALSE)
|
|
if(jobban_isbanned(target, ROLE_CULTIST))
|
|
return
|
|
var/mob/living/simple_animal/hostile/construct/C = new c_type(get_turf(target))
|
|
if(create_smoke)
|
|
new /obj/effect/particle_effect/smoke/sleeping(target.loc)
|
|
C.faction |= "\ref[user]"
|
|
C.key = target.key
|
|
if(user && IS_CULTIST(user) || cult_override)
|
|
C.mind.add_antag_datum(/datum/antagonist/cultist)
|
|
if(user && IS_CULTIST(user))
|
|
to_chat(C, "<B>You are still bound to serve the cult, follow their orders and help them complete their goals at all costs.</B>")
|
|
else
|
|
to_chat(C, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>")
|
|
C.cancel_camera()
|
|
|
|
/obj/item/soulstone/proc/init_shade(mob/living/M, mob/user, forced = FALSE)
|
|
START_PROCESSING(SSobj, src)
|
|
var/type = get_shade_type()
|
|
var/mob/living/simple_animal/shade/S = new type(src)
|
|
S.name = "Shade of [M.real_name]"
|
|
S.real_name = "Shade of [M.real_name]"
|
|
S.key = M.key
|
|
S.cancel_camera()
|
|
name = "soulstone: [S.name]"
|
|
icon_state = icon_state_full
|
|
|
|
if(user)
|
|
S.faction |= "\ref[user]" //Add the master as a faction, allowing inter-mob cooperation
|
|
if(iswizard(user))
|
|
var/datum/antagonist/wizard/construct/construct = new /datum/antagonist/wizard/construct()
|
|
construct.my_creator = user
|
|
S.mind.add_antag_datum(construct)
|
|
if(IS_CULTIST(user))
|
|
S.mind.add_antag_datum(/datum/antagonist/cultist)
|
|
to_chat(S, "<span class='userdanger'>Your soul has been captured! You are now bound to the cult's will. Help them succeed in their goals at all costs.</span>")
|
|
else
|
|
S.mind.store_memory("<b>Serve [user.real_name], your creator.</b>")
|
|
to_chat(S, "<span class='userdanger'>Your soul has been captured! You are now bound to [user.real_name]'s will. Help them succeed in their goals at all costs.</span>")
|
|
if(forced && user)
|
|
to_chat(user, "<span class='notice'><b>Capture successful!</b>:</span> [M.real_name]'s soul has been ripped from [user.p_their()] body and stored within the soul stone.")
|
|
if(!isrobot(M))
|
|
for(var/obj/item/I in M)
|
|
M.unEquip(I)
|
|
|
|
var/target_body = M
|
|
if(isbrain(M))
|
|
target_body = M.loc // get the brain organ instead of the brain mob
|
|
|
|
S.AddComponent(/datum/component/construct_held_body, target_body)
|
|
animate_rays = TRUE
|
|
|
|
/obj/item/soulstone/proc/get_shade_type()
|
|
if(purified)
|
|
return /mob/living/simple_animal/shade/holy
|
|
return /mob/living/simple_animal/shade/cult
|
|
|
|
/obj/item/soulstone/proc/get_cult_ghost(mob/living/M, mob/user, get_new_player = FALSE)
|
|
var/mob/dead/observer/chosen_ghost
|
|
|
|
if(!get_new_player)
|
|
for(var/mob/dead/observer/ghost in GLOB.player_list) // We put them back in their body
|
|
if(ghost.mind && ghost.mind.current == M && ghost.client)
|
|
chosen_ghost = ghost
|
|
break
|
|
|
|
if(!chosen_ghost) // Failing that, we grab a ghost
|
|
var/list/consenting_candidates
|
|
if(purified)
|
|
consenting_candidates = SSghost_spawns.poll_candidates("Would you like to play as a Holy Shade?", ROLE_SENTIENT, FALSE, poll_time = 10 SECONDS, source = /mob/living/simple_animal/shade/holy, role_cleanname = "holy shade")
|
|
else
|
|
consenting_candidates = SSghost_spawns.poll_candidates("Would you like to play as a Shade?", ROLE_SENTIENT, FALSE, poll_time = 10 SECONDS, source = /mob/living/simple_animal/shade, role_cleanname = "shade")
|
|
if(length(consenting_candidates))
|
|
chosen_ghost = pick(consenting_candidates)
|
|
if(!M)
|
|
return FALSE
|
|
if(!chosen_ghost)
|
|
to_chat(user, "<span class='danger'>There were no spirits willing to become a shade.</span>")
|
|
return FALSE
|
|
if(length(contents)) //If they used the soulstone on someone else in the meantime
|
|
return FALSE
|
|
M.ckey = chosen_ghost.ckey
|
|
dust_if_respawnable(chosen_ghost)
|
|
init_shade(M, user)
|
|
return TRUE
|