/
githubmirror
/
vgstation13
Обзор
Документация
Войти
/
githubmirror
/
vgstation13
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
Bleeding-Edge
code/game/objects/items/soulstone.dm
759 строк
34 KB
DeityLink
Cult Polish and admin QoL (#36578)
26 май 2024, 13:34
Не верифицирован
26 май 2024, 13:34
54b400d
Код
Авторство
О чём код?
/* * Contains: * Soul Stone Shard * Soul Gem * Soul Capture Datum * Construct Shell */ ///////////////////////////////////////SOUL STONE SHARD//////////////////////////////////////////////// /obj/item/soulstone name = "soul stone shard" icon = 'icons/obj/wizard.dmi' icon_state = "soulstone" item_state = "shard-soulstone" inhand_states = list("left_hand" = 'icons/mob/in-hand/left/shards.dmi', "right_hand" = 'icons/mob/in-hand/right/shards.dmi') desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artefacts power." w_class = W_CLASS_TINY layer = ABOVE_OBJ_LAYER flags = FPRINT slot_flags = SLOT_BELT mech_flags = MECH_SCAN_FAIL origin_tech = Tc_BLUESPACE + "=4;" + Tc_MATERIALS + "=4" sharpness_flags = SHARP_TIP | SHARP_BLADE surgerysound = 'sound/items/scalpel.ogg' var/mob/living/simple_animal/shade/shade = null /obj/item/soulstone/Destroy() eject_shade() shade = null//just to be sure ..() /obj/item/soulstone/suicide_act(var/mob/living/user) to_chat(viewers(user), "<span class='danger'>[user] swallows \the [src] and begins to choke on it! [shade ? "It looks like they are trying to commit suicide" : ""].</span>") user.drop_from_inventory(src) if (ishuman(user)) var/datum/organ/external/chest/C = user.get_organ(LIMB_CHEST) C.hidden = src//just in case the capture doesn't go through, the gem will have to be extracted from the chest through surgery. user.update_inv_hands() src.forceMove(user) if(shade || !iscarbon(user)) return (SUICIDE_ACT_OXYLOSS) else//allows wielder to captures their own soul sleep(10) var/datum/soul_capture/capture_datum = new() capture_datum.suicide(user, user, src) qdel(capture_datum) /obj/item/soulstone/examine(mob/user) ..() if (shade) to_chat(user, "<span class='notice'>The shade of [shade.real_name] is in there.</span>") if(!shade.client) to_chat(user, "<span class='warning'>It appears to be dormant.</span>") /obj/item/soulstone/attack(var/mob/living/M, var/mob/user) add_fingerprint(user) if (ismob(M)) M.visible_message("<span class='warning'>\The [user] taps \the [M] with \the [src].</span>","You tap \the [M] with \the [src].") if(istype(M, /mob/living/carbon)) if(shade) to_chat(user, "<span class='warning'>\The [src] is full! Use or free an existing soul to make room.</span>") return //Making sure we're not soulstoning a sacrifice target for any version of cult var/datum/faction/cult/narsie/old_cult = find_active_faction_by_type(/datum/faction/cult/narsie) if(old_cult?.is_sacrifice_target(M.mind)) to_chat(user, "<span class='warning'>\The [src] is unable to rip this soul. Such a powerful soul, it must be coveted by some powerful being.</span>") return var/datum/soul_capture/capture_datum = new() capture_datum.init_datum(user, M, src) qdel(capture_datum) else to_chat(user, "<span class='warning'>\The [src] doesn't seem compatible with that creature's soul.</span>") else ..() /obj/item/soulstone/attack_self(mob/user) add_fingerprint(user) if (!shade) to_chat(user, "<span class='warning'>There is no shade in there yet. Critically wound someone and tap them with this to capture their soul. Their corpse is destroyed in the process.</span>") return if (alert(user,"Release the Shade?","[name]","Yes","No") == "Yes") if (!shade || user.stat || user.restrained() || !in_range(src, user)) return eject_shade(user) /obj/item/soulstone/cultify() return /obj/item/soulstone/proc/capture_shade(var/mob/living/simple_animal/shade/target, var/mob/user) if (target.stat == DEAD) to_chat(user, "<span class='danger'>Capture failed!: </span>The shade has already been banished!") else if(shade) to_chat(user, "<span class='danger'>Capture failed!: </span>\The [src] is already full! Release its shade before you can capture another one.") else target.forceMove(src) //put shade in stone shade = target target.status_flags |= GODMODE target.canmove = 0 target.health = target.maxHealth//full heal icon_state = "soulstone2" item_state = "shard-soulstone2" if (istype(src,/obj/item/soulstone/gem)) name = "Soul Gem: [target.real_name]" else name = "Soul Stone: [target.real_name]" user.update_inv_hands() to_chat(target, "Your soul has been captured by the soul stone, its arcane energies are reknitting your ethereal form, healing you.") to_chat(user, "<span class='notice'><b>Capture successful!</b>: </span>[target.real_name]'s has been captured and stored within the soul stone.") //Is our user a cultist? Then you're a cultist too now! if (iscultist(user)) if(!iscultist(target)) var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult) if (cult && !cult.CanConvert()) to_chat(user, "<span class='danger'>The cult has too many members already. But this shade will obey you nonetheless.</span>") target.master = user return var/datum/role/cultist/newCultist = new newCultist.AssignToRole(target.mind,1) if (!cult) cult = ticker.mode.CreateFaction(/datum/faction/bloodcult, null, 1) cult.HandleRecruitedRole(newCultist) newCultist.OnPostSetup() newCultist.Greet(GREET_SOULSTONE) newCultist.conversion["soulstone"] = user else if (iscultist(target)) var/datum/role/cultist = iscultist(target) to_chat(target, "<span class='userdanger'>Your new master is NOT a cultist, you are henceforth disconnected from the rest of the cult.</span>") cultist.Drop() target.add_language(LANGUAGE_CULT)//re-adding cult languages, as all shades can speak it if (target.master != user) to_chat(target, "<span class='userdanger'>You are to follow your new master [user.real_name]'s commands and help them in their goal.</span>") target.master = user /obj/item/soulstone/proc/eject_shade(var/mob/user) if (!shade) return shade.forceMove(get_turf(src)) shade.status_flags &= ~GODMODE if(user) if (shade.master == user) to_chat(shade, "<b>You have been released from your prison, but you are still bound to [shade.master.real_name]'s will. Help them suceed in their goals at all costs.</b>") else to_chat(shade, "<b>You have been released from your prison by [user.real_name] and are now bound to their will. Help them suceed in their goals at all costs.</b>") shade.canmove = 1 shade.cancel_camera() shade = null icon_state = "soulstone" item_state = "shard-soulstone" name = "soul stone shard" if (ismob(loc)) var/mob/mob_loc = loc mob_loc.update_inv_hands() ///////////////////////////////////////SOUL GEM//////////////////////////////////////////////// /obj/item/soulstone/gem name = "soul gem" desc = "A freshly cut stone which appears to hold the same soul catching properties as shards of the Soul Stone. This one however is cut to perfection." icon = 'icons/obj/cult.dmi' icon_state = "soulstone" item_state = "shard-soulstone" inhand_states = list("left_hand" = 'icons/mob/in-hand/left/shards.dmi', "right_hand" = 'icons/mob/in-hand/right/shards.dmi') sharpness_flags = 0 surgerysound = 'sound/items/scalpel.ogg' /obj/item/soulstone/gem/throw_impact(var/atom/hit_atom, var/speed, var/mob/user) if (!..() && isturf(loc)) var/obj/item/soulstone/S = new(loc) if (shade) shade.forceMove(S) S.shade = shade S.icon_state = "soulstone2" S.item_state = "shard-soulstone2" S.name = "Soul Stone: [shade.real_name]" shade = null playsound(S, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) qdel(src) /obj/item/soulstone/gem/eject_shade(var/mob/user) ..() name = "soul gem" /////////////////////////////////////SOUL CAPTURE DATUM////////////////////////////////////////////////// /datum/soul_capture var/gem = FALSE//gem captures gather the target's equipment inside a coffer for the sake of convenience var/blade = FALSE//soul blade do a few more things differently, we also don't want soul blades to return a message after every hit var/suicide = FALSE var/obj/item/receptacle //the stone, gem or blade /datum/soul_capture/Destroy() receptacle = null ..() /datum/soul_capture/proc/init_datum(var/mob/user, var/atom/target, var/obj/item/soul_receptacle) receptacle = soul_receptacle if (istype(receptacle, /obj/item/weapon/melee/soulblade)) gem = TRUE blade = TRUE if (istype(receptacle, /obj/item/soulstone/gem)) gem = TRUE if (iscarbon(target)) init_body(target,user) if (istype(target, /obj/item/organ/external/head)) init_head(target,user) /datum/soul_capture/proc/suicide(var/mob/user, var/atom/target, var/obj/item/soul_receptacle) suicide = TRUE receptacle = soul_receptacle if (istype(receptacle, /obj/item/weapon/melee/soulblade)) gem = TRUE blade = TRUE if (istype(receptacle, /obj/item/soulstone/gem)) gem = TRUE if (iscarbon(target)) var/mob/M = target if (M.client) capture_soul(target, M.client, target) /datum/soul_capture/proc/init_body(var/mob/living/carbon/target, var/mob/user) //first of all, let's check that our target has a soul, somewhere if(!target.client) //no client? the target could be either braindead, decapitated, or catatonic, let's check which var/mob/living/carbon/human/humanTarget = null var/datum/organ/internal/brain/humanBrain = null if(ishuman(target)) humanTarget = target humanBrain = humanTarget.internal_organs_by_name["brain"] if(!humanTarget || (humanTarget && humanBrain)) //our target either is a monkey or alien, or is a human with their head. Did they have a soul in the first place? if so, where is it right now if(!target.mind) //if a mob doesn't have a mind, that means it never had a player controlling him if (!blade) to_chat(user, "<span class='warning'>\The [receptacle] isn't reacting, looks like this target doesn't have much of a soul.</span>") return else //otherwise, that means the player either disconnected or ghosted. we can track their key from their mind, //but first let's make sure that they are dead or in crit var/mob/new_target = null for(var/mob/M in player_list) if(M.key == target.mind.key) new_target = M if(!new_target) if (!blade) to_chat(user, "<span class='warning'>\The [receptacle] isn't reacting, looks like this target's soul went far, far away.</span>") return else if(!istype(new_target,/mob/dead/observer)) if (!blade) to_chat(user, "<span class='warning'>\The [receptacle] isn't reacting, looks like this target's soul already reincarnated.</span>") return else //if the player ghosted, you don't need to put his body into crit to successfully soulstone them. to_chat(new_target, "<span class='danger'>You feel your soul getting sucked into \the [receptacle].</span>") to_chat(user, "<span class='rose'>\The [receptacle] reacts to the corpse and starts glowing.</span>") for(var/obj/item/device/gps/secure/SPS in get_contents_in_object(humanTarget)) SPS.stripped(humanTarget) //The victim is already dead, consider the SPS stripped capture_soul(user,new_target.client,target) else if(humanTarget) //aw shit, our target is a brain/headless human, let's try and locate the head. var/obj/item/organ/external/head/target_head = humanTarget.decapitated?.get() if(!target_head) if (!blade) to_chat(user, "<span class='warning'>\The [receptacle] isn't reacting, looks like their brain has been removed or head has been destroyed.</span>") return else if(target_head.z != humanTarget.z || get_dist(humanTarget, target_head) > 5)//F I V E T I L E S if (!blade) to_chat(user, "<span class='warning'>\The [receptacle] isn't reacting, the head needs to be closer from the body.</span>") return else init_head(receptacle, target_head, user) return else //if the body still has a client, then all we have to make sure of is that he's dead or in crit if (target.stat == CONSCIOUS) if (!blade) to_chat(user, "<span class='warning'>Kill or maim the victim first!</span>") else if(!target.isInCrit() && target.stat != DEAD) if (!blade) to_chat(user, "<span class='warning'>The victim is holding on, weaken them further!</span>") else to_chat(target, "<span class='danger'>You feel your soul getting sucked into \the [receptacle].</span>") to_chat(user, "<span class='rose'>\The [receptacle] reacts to the corpse and starts glowing.</span>") for(var/obj/item/device/gps/secure/SPS in get_contents_in_object(target)) SPS.OnMobDeath(target) //The victim was killed by this capture_soul(user,target.client,target) /datum/soul_capture/proc/init_head(var/obj/item/organ/external/head/humanHead, var/mob/user) if(!humanHead.organ_data) to_chat(user, "<span class='rose'>\The [receptacle] isn't reacting, looks like their brain was separated from their head.</span>") return var/mob/living/carbon/brain/humanBrainMob = humanHead.brainmob if(!humanBrainMob.client) if(!humanBrainMob.mind) to_chat(user, "<span class='warning'>\The [receptacle] isn't reacting, looks like this target doesn't have much of a soul.</span>") return else var/mob/new_target = null for(var/mob/M in player_list) if(M.key == humanBrainMob.mind.key) new_target = M if(!new_target) to_chat(user, "<span class='warning'>\The [receptacle] isn't reacting, looks like this target's soul went far, far away.</span>") return else if(!istype(new_target,/mob/dead/observer)) to_chat(user, "<span class='warning'>\The [receptacle] isn't reacting, looks like this target's soul already reincarnated.</span>") return else to_chat(new_target, "<span class='danger'>You feel your soul getting sucked into \the [receptacle].</span>") to_chat(user, "<span class='rose'>\The [receptacle] reacts to the corpse and starts glowing.</span>") capture_soul(user,new_target.client,humanHead,humanHead.origin_body?.get()) else to_chat(humanBrainMob, "<span class='danger'>You feel your soul getting sucked into \the [receptacle].</span>") to_chat(user, "<span class='rose'>\The [receptacle] reacts to the corpse and starts glowing.</span>") capture_soul(user, humanBrainMob.client, humanHead, humanHead.origin_body?.get()) /datum/soul_capture/proc/capture_soul(var/mob/living/carbon/user, var/client/targetClient, var/atom/movable/target, var/atom/movable/add_target = null) //user is the guy using the soulstone //targetClient is the client of the guy we're soulstoning, so we don't lose track of him between the beginning and the end of the soulstoning. //target is the source of the guy's soul (his body, or his head if decapitated) //add_target is his body if he has been decapitated, for cosmetic purposes (and so it dusts) if(!targetClient) return if (suicide) receptacle.forceMove(get_turf(target)) var/mob/living/carbon/body = null var/datum/mind/mind = null if(istype(target,/mob/living/carbon)) body = target else if(istype(add_target,/mob/living/carbon)) body = add_target var/true_name = "Unknown" if(body) if(body.mind) mind = body.mind true_name = body.real_name var/turf/T = get_turf(body) if (gem)//if we're using a gem, let's store everything in a neat coffer along with some of the victim's blood body.boxify(FALSE, TRUE, "cult") else//otherwise just drop it on the ground for(var/obj/item/W in body) body.drop_from_inventory(W) body.dropBorers(1) body.invisibility = 101 var/datum/organ/external/head_organ = body.get_organ(LIMB_HEAD) if(head_organ && head_organ.status & ORGAN_DESTROYED) if (!gem) new /obj/effect/decal/remains/human/noskull(T) anim(target = T, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-h2-nohead", sleeptime = 26) else if (!gem) if (ishuman(body)) new /obj/effect/decal/remains/human(T) else if (isalien(body)) new /obj/effect/decal/remains/xeno(T) if(body.lying) anim(target = T, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-h2", sleeptime = 26) else anim(target = T, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-h", sleeptime = 26) if(!gem && ishuman(body)) var/mob/living/carbon/human/H = body if (H.decapitated?.get() == target)//just making sure we're dealing with the right head new /obj/item/weapon/skull(get_turf(target)) target.invisibility = 101 //It's not possible to interact with the body normally now, but we don't want to delete it just yet if(ismob(target)) var/mob/M = target true_name = M.real_name if(!gem) new /obj/effect/decal/cleanable/ash(get_turf(target)) else if(istype(target,/obj/item/organ/external/head)) var/obj/item/organ/external/head/H = target var/mob/living/carbon/brain/BM = H.brainmob mind = BM.mind true_name = BM.real_name new /obj/item/weapon/skull(get_turf(target)) //Scary sound playsound(receptacle, get_sfx("soulstone"), 50,1) //Are we capturing a cult-banned player as a cultist? Sucks for them! if (iscultist(user) && (jobban_isbanned(body, CULTIST) || isantagbanned(body))) to_chat(body, "<span class='danger'>A cultist tried to capture your soul, but due to past behaviour you have been banned from the role. Your body will instead dust away.</span>") to_chat(user, "<span class='notice'>Their soul wasn't fit for our cult, and wasn't accepted by \the [receptacle].</span>") //Cleaning up the corpse qdel(target) if(add_target) qdel(add_target) return if (body) message_admins("BLOODCULT: [key_name(body)] has been soul-stoned by [key_name(user)][iscultist(user) ? ", a cultist." : "a NON-cultist."].") log_admin("BLOODCULT: [key_name(body)] has been soul-stoned by [key_name(user)][iscultist(user) ? ", a cultist." : "a NON-cultist."].") add_logs(user, body, "captured [body.name]'s soul", object=receptacle) //Creating a shade inside the stone and putting the victim in control var/mob/living/simple_animal/shade/shadeMob if(iscultist(user)) shadeMob = new /mob/living/simple_animal/shade(receptacle)//put shade in stone else shadeMob = new /mob/living/simple_animal/shade/noncult(receptacle) shadeMob.status_flags |= GODMODE //So they won't die inside the stone somehow shadeMob.canmove = 0//Can't move out of the soul stone if (suicide) shadeMob.soulblade_ritual = TRUE shadeMob.name = "[true_name] the Shade" shadeMob.real_name = "[true_name]" mind.transfer_to(shadeMob) shadeMob.cancel_camera() //Changing the soulstone's icon and description if (istype(receptacle, /obj/item/soulstone)) var/obj/item/soulstone/sstone = receptacle sstone.icon_state = "soulstone2" sstone.item_state = "shard-soulstone2" sstone.name = "Soul [gem ? "Gem" : "Stone"]: [true_name]" sstone.shade = shadeMob else if (istype(receptacle, /obj/item/weapon/melee/soulblade)) shadeMob.give_blade_powers() var/obj/item/weapon/melee/soulblade/sblade = receptacle if (suicide) sblade.blood = max(sblade.blood, 50) sblade.shade = shadeMob sblade.dir = NORTH sblade.update_icon() user.update_inv_hands() if (!suicide) to_chat(shadeMob, "<span class='notice'>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>") to_chat(user, "<span class='notice'>[true_name]'s soul has been ripped from their body and stored within \the [receptacle].</span>") shadeMob.master = user else to_chat(shadeMob, "<span class='notice'>You have ripped your own soul from your body and now reside within \the [receptacle]. What's the next step of your master plan?</span>") if (!suicide) //Is our user a cultist? Then you're a cultist too now! if (iscultist(user)) if (!iscultist(shadeMob)) var/datum/role/cultist/newCultist = new newCultist.AssignToRole(shadeMob.mind,1) var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult) if (!cult) cult = ticker.mode.CreateFaction(/datum/faction/bloodcult, null, 1) cult.HandleRecruitedRole(newCultist) newCultist.OnPostSetup() newCultist.Greet(GREET_SOULSTONE) newCultist.conversion["soulstone"] = user if (!(shadeMob.mind in cult.previously_converted)) cult.previously_made_prisoner |= shadeMob.mind var/datum/role/cultist/C = user.mind.GetRole(CULTIST) if (shadeMob.mind in cult.previously_made_prisoner) C.gain_devotion(50, DEVOTION_TIER_4, "soulstone_prisoner", shadeMob)//making someone prisoner already grants 250 devotion on top. else C.gain_devotion(300, DEVOTION_TIER_4, "soulstone", shadeMob) else if (iscultist(shadeMob)) var/datum/role/cultist = iscultist(shadeMob) to_chat(shadeMob, "<span class='userdanger'>Your new master is NOT a cultist, you are henceforth disconnected from the rest of the cult. You are to follow your new master's commands and help them in their goal.</span>") cultist.Drop() shadeMob.add_language(LANGUAGE_CULT)//re-adding cult languages, as all shades can speak it //Pretty particles var/turf/T1 = get_turf(target) var/turf/T2 = null if(add_target && add_target.loc) T2 = get_turf(add_target) make_tracker_effects(T1, user) if(T2) make_tracker_effects(T2, user) //Cleaning up the corpse qdel(target) if(add_target) qdel(add_target) /////////////////////////////////////////CONSTRUCT SHELLS////////////////////////////////////////////// /obj/structure/constructshell//the original one that looks like an armor name = "empty shell" icon = 'icons/obj/wizard.dmi' icon_state = "construct" desc = "A wicked machine used by those skilled in magical arts. It is inactive." flags = FPRINT /obj/structure/constructshell/cultify() return /obj/structure/constructshell/cult//the legacy cult one icon_state = "construct-cult" desc = "This eerie contraption looks like it would come alive if supplied with a missing ingredient." /obj/structure/constructshell/cult/alt//the cult 3.0 one icon = 'icons/obj/cult.dmi' icon_state = "shell" /obj/structure/constructshell/attackby(var/obj/item/O, var/mob/user) if(istype(O, /obj/item/soulstone)) create_construct(O,user) return 1 else return ..() /obj/structure/constructshell/attack_construct(var/mob/user) if (istype(user, /mob/living/simple_animal/construct/builder)) for (var/obj/item/soulstone/gem/gem in range(1,user)) create_construct(gem, user) return 1 to_chat(user, "<span class='warning'>If there was a soul gem near you, you could set it inside this shell.</span>") return 1 return 0 /obj/structure/constructshell/proc/make_shade_beacon(var/obj/item/soulstone/stone, var/mob/user) return FALSE /obj/structure/constructshell/cult/alt/make_shade_beacon(var/obj/item/soulstone/gem/gem, var/mob/user) if (istype(gem)) qdel(gem) var/obj/structure/shadebeacon/newbeacon = new (loc) if (fingerprints) newbeacon.fingerprints = fingerprints.Copy() to_chat(user, "<span class='notice'>You've set \the [gem] onto \the [src]. A wandering shade can use it to become a construct by itself.</span>") return TRUE return FALSE //Making a Construct /obj/structure/constructshell/proc/create_construct(var/obj/item/soulstone/stone, var/mob/user) if (!stone.shade) if (make_shade_beacon(stone,user)) qdel(src) return to_chat(user, "<span class='warning'>\The [stone] is empty! The shell doesn't react.</span>") return var/mob/living/simple_animal/shade/soul = stone.shade var/mob/living/simple_animal/construct/new_construct var/perfect = FALSE if (istype(stone,/obj/item/soulstone/gem))//Constructs created with a soul gem have extra properties perfect = TRUE var/list/choices = list( list("Artificer", "radial_artificer[perfect ? "2" : ""]", "Though fragile, this construct can reshape its surroundings, conjuring walls, floors, and most importantly, repair other constructs. Additionally, they may operate some cult structures.[perfect ? " <b>Can open gateways to summon eldritch monsters from the realm of Nar-Sie.</b>" : ""]"), list("Wraith", "radial_wraith[perfect ? "2" : ""]", "The fastest of deadliest of constructs, at the cost of a relatively fragile build. Can easily scout and escape by phasing through the veil. Its claws can pry open unpowered airlocks.[perfect ? " <b>Can fire bolts that nail their victims to the floor.</b>" : ""]"), list("Juggernaut", "radial_juggernaut[perfect ? "2" : ""]", "Sturdy, powerful, at the cost of a snail's pace. However, its fists can break walls apart, along with some machinery. Can conjure a temporary forcefield.[perfect ? " <b>Can dash forward over a small distance, knocking down anyone in front of them for a second.</b>" : ""]"), ) var/construct_class = show_radial_menu(user,src,choices,'icons/obj/cult_radial3.dmi',"radial-cult2") if (!Adjacent(user) || (!isconstruct(user) && stone != user.get_active_hand()) || (isconstruct(user) && !stone.Adjacent(user)) || !construct_class || soul.loc != stone) return//sanity check after we've picked a construct class switch(construct_class) if("Juggernaut") if (perfect) new_construct = new /mob/living/simple_animal/construct/armoured/perfect(get_turf(src.loc)) else new_construct = new /mob/living/simple_animal/construct/armoured(get_turf(src.loc)) new_construct.setup_type(user) soul.mind.transfer_to(new_construct) to_chat(new_construct, "<B>You are a Juggernaut. Though slow, your shell can withstand extreme punishment, your body can reflect energy and laser weapons, and you can create temporary shields that blocks pathing and projectiles. You fists can punch people and regular walls apart.</B>") if (perfect) flick("make_juggernaut2", new_construct) to_chat(new_construct, "<B>You can dash over a small distance, knocking down anyone on your path for a second.</B>") to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>") new_construct.cancel_camera() if("Wraith") if (perfect) new_construct = new /mob/living/simple_animal/construct/wraith/perfect(get_turf(src.loc)) else new_construct = new /mob/living/simple_animal/construct/wraith(get_turf(src.loc)) new_construct.setup_type(user) soul.mind.transfer_to(new_construct) to_chat(new_construct, "<B>You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls for a few seconds. Use it both for surprise attacks and strategic retreats.</B>") if (perfect) flick("make_wraith2", new_construct) to_chat(new_construct, "<B>You can fire red bolts that can temporarily prevent their victims from moving. You recharge a bolt every 5 seconds, up to 3 bolts.</B>") to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>") new_construct.cancel_camera() if("Artificer") if (perfect) new_construct = new /mob/living/simple_animal/construct/builder/perfect(get_turf(src.loc)) else new_construct = new /mob/living/simple_animal/construct/builder(get_turf(src.loc)) new_construct.setup_type(user) soul.mind.transfer_to(new_construct) to_chat(new_construct, "<B>You are an Artificer. You are incredibly weak and fragile, but you can heal both yourself and other constructs (by clicking on yourself/them). You can build (and deconstruct) new walls and floors, or replace existing ones by clicking on them, as well as place pylons that act as light source (these block paths but can be easily broken),</B><I>and most important of all you can produce the tools to create new constructs</I><B> (remember to periodically produce new soulstones for your master, and place empty shells in your hideout or when asked.).</B>") if (perfect) flick("make_artificer2", new_construct) to_chat(new_construct, "<B>You can channel a gateway from the realm of Nar-Sie to summon a minion to protect an area.</B>") to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>") new_construct.cancel_camera() if (!new_construct) return if (iscultist(new_construct)) var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult) cult.check_ritual("build_construct", new_construct) if(islegacycultist(user))//legacy cult stuff var/datum/faction/cult/narsie/cult_round = find_active_faction_by_member(user.mind.GetRole(LEGACY_CULTIST)) if(istype(cult_round)) cult_round.HandleRecruitedMind(new_construct.mind, TRUE) new_construct.real_name = soul.real_name new_construct.name = "[new_construct.real_name] the [construct_class]" for(var/atom/A in stone)//we get rid of the empty shade once we've transferred its mind to the construct, so it isn't dropped on the floor when the soulstone is destroyed. qdel(A) qdel(stone) qdel(src) /////////////////////////////////////////SHADE BEACONS////////////////////////////////////////////// //cult 3.0 shells with a gem already set on them, allowing shades to become constructs by themselves. /obj/structure/shadebeacon name = "shade beacon" icon = 'icons/obj/cult.dmi' icon_state = "beacon" desc = "This shell has been fit with an empty soul gem. Maybe a shade could make use of it." flags = FPRINT /obj/structure/shadebeacon/cultify() return /obj/structure/shadebeacon/attack_hand(var/mob/user) if (iscarbon(user)) user.put_in_active_hand(new /obj/item/soulstone/gem(loc)) var/obj/structure/constructshell/cult/alt/newshell = new (loc) if (fingerprints) newshell.fingerprints = fingerprints.Copy() qdel(src) return 1 return ..() /obj/structure/shadebeacon/attack_animal(var/mob/user) if (istype(user, /mob/living/simple_animal/construct/builder)) new /obj/item/soulstone/gem(loc) var/obj/structure/constructshell/cult/alt/newshell = new (loc) if (fingerprints) newshell.fingerprints = fingerprints.Copy() qdel(src) return 1 if (istype(user, /mob/living/simple_animal/shade)) create_construct(user) return 0 /obj/structure/shadebeacon/proc/create_construct(var/mob/living/simple_animal/shade/user) var/mob/living/simple_animal/construct/new_construct var/list/choices = list( list("Artificer", "radial_artificer2", "Though fragile, this construct can reshape its surroundings, conjuring walls, floors, and most importantly, repair other constructs. Additionally, they may operate some cult structures. <b>Can open gateways to summon eldritch monsters from the realm of Nar-Sie.</b>"), list("Wraith", "radial_wraith2", "The fastest of deadliest of constructs, at the cost of a relatively fragile build. Can easily scout and escape by phasing through the veil. Its claws can pry open unpowered airlocks. <b>Can fire bolts that nail their victims to the floor.</b>"), list("Juggernaut", "radial_juggernaut2", "Sturdy, powerful, at the cost of a snail's pace. However, its fists can break walls apart, along with some machinery. Can conjure a temporary forcefield. <b>Can dash forward over a small distance, knocking down anyone in front of them for a second.</b>"), ) var/construct_class = show_radial_menu(user,src,choices,'icons/obj/cult_radial3.dmi',"radial-cult2") if (!Adjacent(user) || !construct_class) return switch(construct_class) if("Juggernaut") new_construct = new /mob/living/simple_animal/construct/armoured/perfect(get_turf(src.loc)) new_construct.setup_type(user) new_construct.real_name = user.real_name user.mind.transfer_to(new_construct) to_chat(new_construct, "<B>You are a Juggernaut. Though slow, your shell can withstand extreme punishment, your body can reflect energy and laser weapons, and you can create temporary shields that blocks pathing and projectiles. You fists can punch people and regular walls apart.</B>") flick("make_juggernaut2", new_construct) to_chat(new_construct, "<B>You can dash over a small distance, knocking down anyone on your path for a second.</B>") to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>") if (!iscultist(new_construct)) to_chat(new_construct, "<B>As a self-made construct, you are unbounded from anyone's will.</B>") new_construct.cancel_camera() if("Wraith") new_construct = new /mob/living/simple_animal/construct/wraith/perfect(get_turf(src.loc)) new_construct.setup_type(user) new_construct.real_name = user.real_name user.mind.transfer_to(new_construct) to_chat(new_construct, "<B>You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls for a few seconds. Use it both for surprise attacks and strategic retreats.</B>") flick("make_wraith2", new_construct) to_chat(new_construct, "<B>You can fire red bolts that can temporarily prevent their victims from moving. You recharge a bolt every 5 seconds, up to 3 bolts.</B>") to_chat(new_construct, "<B>You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.</B>") if (!iscultist(new_construct)) to_chat(new_construct, "<B>As a self-made construct, you are unbounded from anyone's will.</B>") new_construct.cancel_camera() if("Artificer") new_construct = new /mob/living/simple_animal/construct/builder/perfect(get_turf(src.loc)) new_construct.setup_type(user) new_construct.real_name = user.real_name user.mind.transfer_to(new_construct) to_chat(new_construct, "<B>You are an Artificer. You are incredibly weak and fragile, but you can heal both yourself and other constructs (by clicking on yourself/them). You can build (and deconstruct) new walls and floors, or replace existing ones by clicking on them, as well as place pylons that act as light source (these block paths but can be easily broken),</B><I>and most important of all you can produce the tools to create new constructs</I><B> (remember to periodically produce new soulstones for your master, and place empty shells in your hideout or when asked.).</B>") flick("make_artificer2", new_construct) to_chat(new_construct, "<B>You can channel a gateway from the realm of Nar-Sie to summon a minion to protect an area.</B>") if (!iscultist(new_construct)) to_chat(new_construct, "<B>As a self-made construct, you are unbounded from anyone's will.</B>") new_construct.cancel_camera() if (!new_construct) return new_construct.name = "[new_construct.real_name] the [construct_class]" qdel(user) qdel(src)