Files
vgstation13/code/datums/gamemode/factions/bloodcult/bloodcult_buildings.dm
DeityLink 54b400ddfe Cult Polish and admin QoL (#36578)
* better pillar lights

* more scoreboard cult info, and admin panel info

* derp

* remove leftover soulstone cap

* herp

* geez

* change

* ahhhh

* polish

* ahem
2024-05-26 05:34:34 -05:00

2229 lines
75 KiB
Plaintext

/obj/structure/cult
density = 1
anchored = 1
icon = 'icons/obj/cult.dmi'
health = 50
maxHealth = 50
var/sound_damaged = null
var/sound_destroyed = null
var/conceal_cooldown = 0
var/timeleft = 0
var/timetotal = 0
var/list/contributors = list()// list of cultists currently participating in the ritual
var/min_contributors = 1 // how many cultists we need for the current ritual
var/image/progbar = null//progress bar
var/cancelling = 3//check to abort the ritual if interrupted
var/custom_process = 0
/obj/structure/cult/get_cult_power()
return 1//light emitted by those won't be reduced during the eclipse
/obj/structure/cult/proc/conceal()
var/obj/structure/cult/concealed/C = new(loc)
C.pixel_x = pixel_x
C.pixel_y = pixel_y
forceMove(C)
C.held = src
C.icon = icon
C.icon_state = icon_state
/obj/structure/cult/proc/reveal()
conceal_cooldown = 1
spawn (100)
if (src && loc)
conceal_cooldown = 0
/obj/structure/cult/concealed
density = 0
anchored = 1
alpha = 127
invisibility = INVISIBILITY_OBSERVER
var/obj/structure/cult/held = null
/obj/structure/cult/concealed/reveal()
if (held)
held.forceMove(loc)
held.reveal()
held = null
qdel(src)
/obj/structure/cult/concealed/conceal()
return
/obj/structure/cult/concealed/takeDamage(var/damage)
return
//if you want indestructible buildings, just make a custom takeDamage() proc
/obj/structure/cult/proc/takeDamage(var/damage)
health -= damage
if (health <= 0)
if (sound_destroyed)
playsound(src, sound_destroyed, 100, 1)
qdel(src)
else
update_icon()
//duh
/obj/structure/cult/cultify()
return
/obj/structure/cult/clockworkify()
return
//nuh-uh
/obj/structure/cult/dissolvable()
return 0
/obj/structure/cult/can_mech_drill()
return TRUE
/obj/structure/cult/mech_drill_act(var/severity, var/child=null)
return ex_act(severity, child)
/obj/structure/cult/ex_act(var/severity)
switch(severity)
if (1)
takeDamage(100)
if (2)
takeDamage(20)
if (3)
takeDamage(4)
/obj/structure/cult/blob_act()
playsound(src, sound_damaged, 75, 1)
takeDamage(20)
/obj/structure/cult/bullet_act(var/obj/item/projectile/Proj)
takeDamage(Proj.damage)
return ..()
/obj/structure/cult/attackby(var/obj/item/weapon/W, var/mob/user, params)
if (istype(W))
if(user.a_intent == I_HELP || W.force == 0)
visible_message("<span class='warning'>\The [user] gently taps \the [src] with \the [W].</span>")
else
user.delayNextAttack(8)
user.do_attack_animation(src, W)
// if (W.hitsound)
// playsound(src, W.hitsound, 50, 1, -1)
if (sound_damaged)
playsound(src, sound_damaged, 75, 1)
if(isholyweapon(W))
playsound(loc, 'sound/weapons/welderattack.ogg', 50, 1)
takeDamage(W.force*2)
else
takeDamage(W.force)
if (W.attack_verb)
visible_message("<span class='warning'>\The [user] [pick(W.attack_verb)] \the [src] with \the [W].</span>")
else
visible_message("<span class='warning'>\The [user] hits \the [src] with \the [W].</span>")
..()
/obj/structure/cult/attack_paw(var/mob/user)
return attack_hand(user)
/obj/structure/cult/attack_hand(var/mob/living/user)
if(user.a_intent == I_HURT)
user.delayNextAttack(8)
user.visible_message("<span class='danger'>[user.name] [pick("kicks","punches")] \the [src]!</span>", \
"<span class='danger'>You strike at \the [src]!</span>", \
"You hear stone cracking.")
takeDamage(user.get_unarmed_damage(src))
if (sound_damaged)
playsound(src, sound_damaged, 75, 1)
else if(iscultist(user))
cultist_act(user)
else
noncultist_act(user)
/obj/structure/cult/proc/cultist_act(var/mob/user)
return 1
/obj/structure/cult/proc/noncultist_act(var/mob/user)
to_chat(user,"<span class='sinister'>You feel madness taking its toll, trying to figure out \the [name]'s purpose</span>")
//might add some hallucinations or brain damage later, checks for cultist chaplains, etc
return 1
/obj/structure/cult/attack_construct(var/mob/user)
if (!Adjacent(user))
return 0
if(istype(user,/mob/living/simple_animal/construct/builder))
cultist_act(user)
return 1
return 0
/obj/structure/cult/beam_connect(var/obj/effect/beam/B)
..()
last_beamchecks["\ref[B]"]=world.time+1
apply_beam_damage(B) // Contact damage for larger beams (deals 1/10th second of damage)
if(!custom_process && !(src in processing_objects))
processing_objects.Add(src)
/obj/structure/cult/beam_disconnect(var/obj/effect/beam/B)
..()
apply_beam_damage(B)
last_beamchecks.Remove("\ref[B]") // RIP
if(beams.len == 0)
if(!custom_process)
processing_objects.Remove(src)
/obj/structure/cult/apply_beam_damage(var/obj/effect/beam/B)
var/lastcheck=last_beamchecks["\ref[B]"]
// Standard damage formula / 2
var/damage = ((world.time - lastcheck)/10) * (B.get_damage() / 20)
// Actually apply damage
takeDamage(damage)
// Update check time.
last_beamchecks["\ref[B]"]=world.time
/obj/structure/cult/handle_beams()
// New beam damage code (per-tick)
for(var/obj/effect/beam/B in beams)
apply_beam_damage(B)
/obj/structure/cult/process()
handle_beams()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //Spawned from the Raise Structure rune. Available from the beginning. Trigger progress to ACT I
// CULT ALTAR //Allows communication with Nar-Sie for advice and info on the Cult's current objective.
// //ACT II : Allows Soulstone crafting, Used to sacrifice the target on the Station
///////////////////////////ACT III : Can plant an empty Soul Blade in it to prompt observers to become the blade's shade
#define ALTARTASK_NONE 0
#define ALTARTASK_GEM 1
#define ALTARTASK_SACRIFICE_HUMAN 2
#define ALTARTASK_SACRIFICE_ANIMAL 3
/obj/structure/cult/altar
name = "altar"
desc = "A bloodstained altar dedicated to Nar-Sie."
icon_state = "altar"
health = 100
maxHealth = 100
sound_damaged = 'sound/effects/stone_hit.ogg'
sound_destroyed = 'sound/effects/stone_crumble.ogg'
layer = TABLE_LAYER
pass_flags_self = PASSTABLE
var/obj/item/weapon/melee/soulblade/blade = null
var/lock_type = /datum/locking_category/buckle/bed
var/altar_task = ALTARTASK_NONE
var/gem_delay = 300
var/narsie_message_cooldown = 0
var/mob/sacrificer // who started the sacrifice ritual
var/image/build
var/list/watching_mobs = list()
var/list/watcher_maps = list()
var/datum/station_holomap/cult/holomap_datum
var/list/can_plant = list(
/obj/item/weapon/kitchen/utensil/knife/large/ritual,
/obj/item/weapon/melee/soulblade,
/obj/item/weapon/melee/cultblade,
/obj/item/weapon/melee/cultblade/nocult,
)
var/trapped = FALSE
/obj/structure/cult/altar/New()
..()
flick("[icon_state]-spawn", src)
var/image/I = image(icon, "altar_overlay")
I.plane = relative_plane(ABOVE_HUMAN_PLANE)
overlays.Add(I)
for (var/mob/living/carbon/C in loc)
Crossed(C)
var/datum/holomap_marker/holomarker = new()
holomarker.id = HOLOMAP_MARKER_CULT_ALTAR
holomarker.filter = HOLOMAP_FILTER_CULT
holomarker.x = src.x
holomarker.y = src.y
holomarker.z = src.z
holomap_markers[HOLOMAP_MARKER_CULT_ALTAR+"_\ref[src]"] = holomarker
holomap_datum = new
if(ticker && holomaps_initialized)
initialize()
/obj/structure/cult/altar/initialize()
holomap_datum.initialize_holomap(get_turf(src), cursor_icon = "altar-here")
//mostly for mappers
for (var/obj/item/I in loc)
if (is_type_in_list(I, can_plant))
I.forceMove(src)
blade = I
update_icon()
/obj/structure/cult/altar/Destroy()
stopWatching()
if (blade)
if (loc)
blade.forceMove(loc)
else
qdel(blade)
blade = null
flick("[icon_state]-break", src)
holomap_markers -= HOLOMAP_MARKER_CULT_ALTAR+"_\ref[src]"
..()
/obj/structure/cult/altar/attackby(var/obj/item/I, var/mob/user, params)
if (altar_task)
return ..()
if(is_type_in_list(I, can_plant))
if (blade)
to_chat(user,"<span class='warning'>You must remove \the [blade] planted into \the [src] first.</span>")
return 1
var/turf/T = get_turf(user)
playsound(T, 'sound/weapons/bloodyslice.ogg', 50, 1)
user.drop_item(I, T, 1)
I.forceMove(src)
blade = I
update_icon()
var/mob/living/carbon/C = locate() in loc
var/mob/living/simple_animal/S = locate() in loc
if (C && C.lying)
C.unlock_from()
C.update_canmove()
lock_atom(C, lock_type)
C.apply_damage(blade.force, BRUTE, LIMB_CHEST)
I.add_blood(C)
var/datum/role/cultist/cul = iscultist(user)
if (cul)
cul.gain_devotion(0, DEVOTION_TIER_0, "altar_plant", src)
if (C == user)
user.visible_message("<span class='danger'>\The [user] holds \the [I] above their stomach and impales themselves on \the [src]!</span>","<span class='danger'>You hold \the [I] above your stomach and impale yourself on \the [src]!</span>")
else
user.visible_message("<span class='danger'>\The [user] holds \the [I] above \the [C]'s stomach and impales them on \the [src]!</span>","<span class='danger'>You hold \the [I] above \the [C]'s stomach and impale them on \the [src]!</span>")
else if(S)
S.unlock_from()
S.update_canmove()
S.pixel_y = 6
lock_atom(S, lock_type)
if(S.stat != DEAD)
S.death()
I.add_blood()
var/datum/role/cultist/cul = iscultist(user)
if (cul)
cul.gain_devotion(0, DEVOTION_TIER_0, "altar_plant", src)
user.visible_message("<span class='danger'>\The [user] holds \the [I] above \the [S] and impales it on \the [src]!</span>","<span class='danger'>You hold \the [I] above \the [S] and impale it on \the [src]!</span>")
else
to_chat(user, "You plant \the [blade] on top of \the [src]</span>")
processing_objects += src
var/datum/role/cultist/cul = iscultist(user)
if (cul)
cul.gain_devotion(0, DEVOTION_TIER_0, "altar_plant", src)
if (istype(blade) && !blade.shade)
var/icon/logo_icon = icon('icons/logos.dmi', "shade-blade")
for(var/mob/M in observers)
if(!M.client || isantagbanned(M) || jobban_isbanned(M, CULTIST) || M.client.is_afk())
continue
if (iscultist(M))
var/datum/role/cultist/cultist = iscultist(M)
if (cultist.second_chance)
to_chat(M, "[bicon(logo_icon)]<span class='recruit'>\The [user] has planted a Soul Blade on an altar, opening a small crack in the veil that allows you to become the blade's resident shade. (<a href='?src=\ref[src];signup=\ref[M]'>Possess now!</a>)</span>[bicon(logo_icon)]")
return 1
if (istype(I, /obj/item/weapon/grab))
if (blade)
to_chat(user,"<span class='warning'>You must remove \the [blade] planted on \the [src] first.</span>")
return 1
var/obj/item/weapon/grab/G = I
if(iscarbon(G.affecting))
if (blade)
to_chat(user,"<span class='warning'>You must remove \the [blade] planted on \the [src] first.</span>")
return 1
var/mob/living/carbon/C = G.affecting
C.unlock_from()
if (!do_after(user,C,15))
return
if (ishuman(C))
C.resting = 1
C.update_canmove()
C.forceMove(loc)
qdel(G)
to_chat(user, "<span class='warning'>You move \the [C] on top of \the [src]</span>")
return 1
if(user.a_intent != I_HURT)
if(user.drop_item(I, loc))
if((I.loc == loc) && params)
I.setPixelOffsetsFromParams(params, user, pixel_x, pixel_y)
return 1
..()
/obj/structure/cult/altar/update_icon()
icon_state = "altar"
overlays.len = 0
if (blade)
var/image/I
if(istype(blade, /obj/item/weapon/kitchen/utensil/knife/large/ritual))
I = image(icon, "altar-ritualknife")
else if (!istype(blade))
I = image(icon, "altar-cultblade")
else if (blade.shade)
I = image(icon, "altar-soulblade-full")
else
I = image(icon, "altar-soulblade")
I.plane = relative_plane(ABOVE_HUMAN_PLANE)
I.pixel_y = 3
overlays.Add(I)
var/image/I = image(icon, "altar_overlay")
I.plane = relative_plane(ABOVE_HUMAN_PLANE)
overlays.Add(I)
if (health < maxHealth/3)
overlays.Add("altar_damage2")
else if (health < 2*maxHealth/3)
overlays.Add("altar_damage1")
//We want people on top of the altar to appear slightly higher
/obj/structure/cult/altar/Crossed(var/atom/movable/mover)
if (iscarbon(mover))
mover.pixel_y += 7 * PIXEL_MULTIPLIER
/obj/structure/cult/altar/Uncrossed(var/atom/movable/mover)
if (iscarbon(mover))
mover.pixel_y -= 7 * PIXEL_MULTIPLIER
//They're basically the height of regular tables
/obj/structure/cult/altar/Cross(var/atom/movable/mover, var/turf/target, var/height=1.5, var/air_group = 0)
if(air_group || (height==0))
return 1
if(ismob(mover))
var/mob/M = mover
if(M.flying)
return 1
if(istype(mover) && mover.checkpass(pass_flags_self))
return 1
else
return 0
/obj/structure/cult/altar/MouseDropTo(var/atom/movable/O, var/mob/user)
if (altar_task)
return
if (!istype(O))
return
if(user.incapacitated() || user.lying)
return
if(O.anchored || !Adjacent(user) || !user.Adjacent(O))
return
if (user.get_active_hand() == O)
if(!user.drop_item(O))
return
else
if(!ismob(O))
return
if(O.loc == user || !isturf(O.loc) || !isturf(user.loc))
return
var/mob/living/L = O
if(!istype(L) || L.locked_to)
return
if (blade)
to_chat(user,"<span class='warning'>You must remove \the [blade] planted on \the [src] first.</span>")
return 1
if (!do_after(user,L,15))
return
L.unlock_from()
if (ishuman(L) && L != user)
L.resting = TRUE
L.update_canmove()
add_fingerprint(L)
O.forceMove(loc)
if(O == user)
to_chat(user, "<span class='warning'>You climb on top of \the [src].</span>")
user.resting = TRUE
else
to_chat(user, "<span class='warning'>You move \the [O] on top of \the [src].</span>")
return 1
/obj/structure/cult/altar/proc/checkPosition()
for(var/mob/M in watching_mobs)
if(get_dist(src,M) > 1)
stopWatching(M)
/obj/structure/cult/altar/proc/stopWatching(var/mob/user)
if(!user)
for(var/mob/M in watching_mobs)
if(M.client)
spawn(5)//we give it time to fade out
M.client.images -= watcher_maps["\ref[M]"]
M.unregister_event(/event/face, src, /obj/structure/cult/altar/proc/checkPosition)
animate(watcher_maps["\ref[M]"], alpha = 0, time = 5, easing = LINEAR_EASING)
watching_mobs = list()
else
if(user.client)
spawn(5)//we give it time to fade out
if(!(user in watching_mobs))
user.client.images -= watcher_maps["\ref[user]"]
watcher_maps -= "\ref[user]"
user.unregister_event(/event/face, src, /obj/structure/cult/altar/proc/checkPosition)
animate(watcher_maps["\ref[user]"], alpha = 0, time = 5, easing = LINEAR_EASING)
watching_mobs -= user
/obj/structure/cult/altar/conceal()
if (blade || altar_task)
return
anim(location = loc,target = loc,a_icon = icon, flick_anim = "[icon_state]-conceal")
for (var/mob/living/carbon/C in loc)
Uncrossed(C)
..()
/obj/structure/cult/altar/reveal()
flick("[icon_state]-spawn", src)
..()
for (var/mob/living/carbon/C in loc)
Crossed(C)
/obj/structure/cult/altar/cultist_act(var/mob/user,var/menu="default")
.=..()
if (!.)
return
if(user in watching_mobs)
stopWatching(user)
return
if (altar_task)
switch (altar_task)
if (ALTARTASK_GEM)
to_chat(user, "<span class='warning'>You must wait before the Altar's current task is over.</span>")
if (ALTARTASK_SACRIFICE_HUMAN to ALTARTASK_SACRIFICE_ANIMAL)
if (user in contributors)
return
if (!user.checkTattoo(TATTOO_SILENT))
if (prob(5))
user.say("Let me show you the dance of my people!","C")
else
user.say("Barhah hra zar'garis!","C")
contributors.Add(user)
if (user.client)
user.client.images |= progbar
return
if(is_locking(lock_type))
var/mob/M = get_locked(lock_type)[1]
if(M != user)
var/choices = list(
list("Remove Blade", "radial_altar_remove", "Pull the blade off, freeing the victim."),
list("Sacrifice", "radial_altar_sacrifice", "Initiate the sacrifice ritual. The ritual can only proceed if the proper victim has been nailed to the altar."),
)
var/task = show_radial_menu(user,loc,choices,'icons/obj/cult_radial3.dmi',"radial-cult2")
if (!is_locking(lock_type) || !Adjacent(user) || !task)
return
switch (task)
if ("Remove Blade")
if (do_after(user,src,20))
M.visible_message("<span class='notice'>\The [M] was freed from \the [src] by \the [user]!</span>","You were freed from \the [src] by \the [user].")
unlock_atom(M)
if(istype(M, /mob/living/simple_animal))
M.pixel_y = 0
if (blade)
blade.forceMove(loc)
blade.attack_hand(user)
to_chat(user, "<span class='warning'>You remove \the [blade] from \the [src]</span>")
processing_objects -= src
blade = null
playsound(loc, 'sound/weapons/blade1.ogg', 50, 1)
update_icon()
if ("Sacrifice")
// First we'll check for any blockers around it since we'll dance using forceMove to allow up to 8 dancers without them bumping into each others
// Of course this means that walls and objects placed AFTER the start of the dance can be crossed by dancing but that's good enough.
for (var/turf/T in orange(1,src))
if (T.density)
to_chat(user, "<span class='warning'>\The [T] would hinder the ritual. Either dismantle it or use an altar located in a more spacious area.</span>")
return
var/atom/A = T.has_dense_content()
if (A && (A != src) && !ismob(A)) // mobs get a free pass
to_chat(user, "<span class='warning'>\The [A] would hinder the ritual. Either move it or use an altar located in a more spacious area.</span>")
return
if(ishuman(M))
altar_task = ALTARTASK_SACRIFICE_HUMAN
else
altar_task = ALTARTASK_SACRIFICE_ANIMAL
StartSacrifice(user)
return
else if (blade)
if(is_locking(lock_type))
if (do_after(user,src,20))
unlock_atom(get_locked(lock_type)[1])
blade.forceMove(loc)
blade.attack_hand(user)
to_chat(user, "<span class='notice'>You remove \the [blade] from \the [src]</span>")
processing_objects -= src
blade = null
playsound(loc, 'sound/weapons/blade1.ogg', 50, 1)
update_icon()
else
blade.forceMove(loc)
blade.attack_hand(user)
to_chat(user, "<span class='notice'>You remove \the [blade] from \the [src]</span>")
processing_objects -= src
blade = null
playsound(loc, 'sound/weapons/blade1.ogg', 50, 1)
update_icon()
return
else
var/choices = list(
list("Consult Roster", "radial_altar_roster", "Check the names and status of all of the cult's members."),
list("Look through Veil", "radial_altar_map", "Check the veil for tears to locate other occult constructions."),
list("Commune with Nar-Sie", "radial_altar_commune", "Make contact with Nar-Sie."),
list("Conjure Soul Gem", "radial_altar_gem", "Order the altar to sculpt you a Soul Gem, to capture the soul of your enemies."),
)
var/task = show_radial_menu(user,loc,choices,'icons/obj/cult_radial3.dmi',"radial-cult2")
if (is_locking(lock_type) || !Adjacent(user) || !task)
return
switch (task)
if ("Consult Roster")
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
if (!cult)
return
var/dat = {"<body style="color:#FFFFFF" bgcolor="#110000">"}
dat += "<b>Our cult can currently grow up to [cult.cultist_cap] members.</b>"
dat += "<ul>"
for (var/datum/role/cultist/C in cult.members)
var/datum/mind/M = C.antag
var/conversion = ""
var/cult_role = ""
switch (C.cultist_role)
if (CULTIST_ROLE_ACOLYTE)
cult_role = "Acolyte"
if (CULTIST_ROLE_MENTOR)
cult_role = "Mentor"
else
cult_role = "Herald"
if (C.conversion.len > 0)
conversion = pick(C.conversion)
var/origin_text = ""
switch (conversion)
if ("converted")
origin_text = "Converted by [C.conversion[conversion]]"
if ("resurrected")
origin_text = "Resurrected by [C.conversion[conversion]]"
if ("soulstone")
origin_text = "Soul captured by [C.conversion[conversion]]"
if ("altar")
origin_text = "Volunteer shade"
if ("sacrifice")
origin_text = "Sacrifice"
else
origin_text = "Founder"
var/mob/living/carbon/H = C.antag.current
var/extra = ""
if (H && istype(H))
if (H.isInCrit())
extra = " - <span style='color:#FFFF00'>CRITICAL</span>"
else if (H.isDead())
extra = " - <span style='color:#FF0000'>DEAD</span>"
dat += "<li><b>[M.name] ([cult_role])</b></li> - [origin_text][extra]"
for(var/obj/item/weapon/handcuffs/cult/cuffs in cult.bindings)
if (iscarbon(cuffs.loc))
var/mob/living/carbon/C = cuffs.loc
if (C.handcuffed == cuffs && cuffs.gaoler && cuffs.gaoler.antag)
var/datum/mind/gaoler = cuffs.gaoler.antag
var/extra = ""
if (C && istype(C))
if (C.isInCrit())
extra = " - <span style='color:#FFFF00'>CRITICAL</span>"
else if (C.isDead())
extra = " - <span style='color:#FF0000'>DEAD</span>"
dat += "<li><span style='color:#FFFF00'><b>[C.real_name]</b></span></li> - Prisoner of [gaoler.name][extra]"
dat += {"</ul></body>"}
user << browse("<TITLE>Cult Roster</TITLE>[dat]", "window=cultroster;size=600x400")
onclose(user, "cultroster")
if ("Look through Veil")
if(user.hud_used && user.hud_used.holomap_obj)
if(!("\ref[user]" in watcher_maps))
var/image/personnal_I = prepare_cult_holomap()
var/turf/T = get_turf(src)
if(map.holomap_offset_x.len >= T.z)
holomap_datum.cursor.pixel_x = (T.x-8+map.holomap_offset_x[T.z])*PIXEL_MULTIPLIER
holomap_datum.cursor.pixel_y = (T.y-8+map.holomap_offset_y[T.z])*PIXEL_MULTIPLIER
else
holomap_datum.cursor.pixel_x = (T.x-8)*PIXEL_MULTIPLIER
holomap_datum.cursor.pixel_y = (T.y-8)*PIXEL_MULTIPLIER
if (T.z == map.zMainStation)
personnal_I.overlays += holomap_datum.cursor
watcher_maps["\ref[user]"] = personnal_I
var/image/I = watcher_maps["\ref[user]"]
I.loc = user.hud_used.holomap_obj
I.alpha = 0
animate(watcher_maps["\ref[user]"], alpha = 255, time = 5, easing = LINEAR_EASING)
watching_mobs |= user
user.client.images |= watcher_maps["\ref[user]"]
user.register_event(/event/face, src, /obj/structure/cult/altar/proc/checkPosition)
if ("Commune with Nar-Sie")
if(narsie_message_cooldown)
to_chat(user, "<span class='warning'>This altar has already sent a message in the past 30 seconds, wait a moment.</span>")
return
var/input = stripped_input(user, "Please choose a message to transmit to Nar-Sie through the veil. Know that he can be fickle, and abuse of this ritual will leave your body asunder. Communion does not guarantee a response. There is a 30 second delay before you may commune again, be clear, full and concise.", "To abort, send an empty message.", "")
if(!input || !Adjacent(user))
return
NarSie_announce(input, usr)
to_chat(usr, "<span class='notice'>Your communion has been received.</span>")
var/turf/T = get_turf(usr)
log_say("[key_name(usr)] (@[T.x],[T.y],[T.z]) has communed with Nar-Sie: [input]")
narsie_message_cooldown = 1
spawn(30 SECONDS)
narsie_message_cooldown = 0
if ("Conjure Soul Gem")
altar_task = ALTARTASK_GEM
update_icon()
overlays += "altar-soulstone1"
spawn (gem_delay/3)
update_icon()
overlays += "altar-soulstone2"
sleep (gem_delay/3)
update_icon()
overlays += "altar-soulstone3"
sleep (gem_delay/3)
altar_task = ALTARTASK_NONE
update_icon()
var/obj/item/soulstone/gem/gem = new (loc)
gem.pixel_y = 4
/obj/structure/cult/altar/proc/StartSacrifice(var/mob/user)
var/mob/M = get_locked(lock_type)[1]
switch(altar_task)
if(ALTARTASK_SACRIFICE_HUMAN)
if((!istype(blade, /obj/item/weapon/melee/cultblade) && !istype(blade, /obj/item/weapon/melee/soulblade)) || istype(blade, /obj/item/weapon/melee/cultblade/nocult))
to_chat(user, "<span class='warning'>\The [blade] is too weak to perform such a sacrifice. Forge a stronger blade.</span>")
altar_task = ALTARTASK_NONE
return
timeleft = 30
timetotal = timeleft
min_contributors = 1//monkey, or other carbon lifeforms
if (ishuman(M))
if (M.mind)
min_contributors = 3
to_chat(user, "<span class='sinister'>You need <span class='danger'>3</span> cultists to partake in the ritual for the sacrifice to proceed.</span>")
if(ALTARTASK_SACRIFICE_ANIMAL)
timeleft = 15
timetotal = timeleft
min_contributors = 1
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
if (cult)
if (is_locking(lock_type))
sacrificer = user
update_icon()
contributors.Add(user)
update_progbar()
if (user.client)
user.client.images |= progbar
build = image('icons/obj/cult.dmi',"build")
build.pixel_y = 8
src.overlays += build
if (!user.checkTattoo(TATTOO_SILENT))
if (prob(5))
user.say("Let me show you the dance of my people!","C")
else
user.say("Barhah hra zar'garis!","C")
if (user.client)
user.client.images |= progbar
spawn()
dance_start()
/obj/structure/cult/altar/noncultist_act(var/mob/user)//Non-cultists can still remove blades planted on altars.
if(is_locking(lock_type))
var/mob/M = get_locked(lock_type)[1]
if(M != user)
if (do_after(user,src,20))
M.visible_message("<span class='notice'>\The [M] was freed from \the [src] by \the [user]!</span>","You were freed from \the [src] by \the [user].")
unlock_atom(M)
if (blade)
blade.forceMove(loc)
blade.attack_hand(user)
to_chat(user, "You remove \the [blade] from \the [src]</span>")
processing_objects -= src
blade = null
playsound(loc, 'sound/weapons/blade1.ogg', 50, 1)
update_icon()
else if (blade)
blade.forceMove(loc)
blade.attack_hand(user)
to_chat(user, "You remove \the [blade] from \the [src]</span>")
processing_objects -= src
blade = null
playsound(loc, 'sound/weapons/blade1.ogg', 50, 1)
update_icon()
if (trapped) //soulblade sanctum trapped altar
trapped = FALSE
var/list/possible_floors = list()
for (var/turf/simulated/floor/F in orange(1,get_turf(src)))
possible_floors.Add(F)
for (var/i = 1 to 4)
if (possible_floors.len <= 0)
break
var/turf/T = pick(possible_floors)
if (T)
possible_floors.Remove(T)
new /obj/effect/cult_ritual/backup_spawn(T)
spawn(1)
for (var/obj/structure/mannequin/cult/MC in range(loc, 7))
MC.Awaken()
return
else
to_chat(user,"<span class='sinister'>You feel madness taking its toll, trying to figure out \the [name]'s purpose.</span>")
return 1
/obj/structure/cult/altar/process()
if (istype(blade))
blade.blood = min(blade.maxblood,blade.blood+10)
if (blade.blood == blade.maxblood)
processing_objects -= src
else
processing_objects -= src
/obj/structure/cult/altar/Topic(href, href_list)
if(href_list["signup"])
var/mob/M = usr
if(!isobserver(M) || !iscultist(M))
return
var/mob/dead/observer/O = M
var/obj/item/weapon/melee/soulblade/blade = locate() in src
if (!istype(blade))
to_chat(usr, "<span class='warning'>The blade was removed from \the [src].</span>")
return
if (blade.shade)
to_chat(usr, "<span class='warning'>Another shade was faster, and is currently possessing \the [blade].</span>")
return
var/mob/living/simple_animal/shade/shadeMob = new(blade)
blade.shade = shadeMob
shadeMob.status_flags |= GODMODE
shadeMob.canmove = 0
var/datum/role/cultist/cultist = iscultist(M)
cultist.second_chance = 0
shadeMob.real_name = M.mind.name
shadeMob.name = "[shadeMob.real_name] the Shade"
M.mind.transfer_to(shadeMob)
O.can_reenter_corpse = 1
O.reenter_corpse()
/* Only cultists get brought back this way now, so let's assume they kept their identity.
spawn()
var/list/shade_names = list("Orenmir","Felthorn","Sparda","Vengeance","Klinge")
shadeMob.real_name = pick(shade_names)
shadeMob.real_name = copytext(sanitize(input(shadeMob, "You have no memories of your previous life, if you even had one. What name will you give yourself?", "Give yourself a new name", "[shadeMob.real_name]") as null|text),1,MAX_NAME_LEN)
shadeMob.name = "[shadeMob.real_name] the Shade"
if (shadeMob.mind)
shadeMob.mind.name = shadeMob.real_name
*/
shadeMob.cancel_camera()
shadeMob.give_blade_powers()
blade.dir = NORTH
blade.update_icon()
update_icon()
//Automatically makes them cultists
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
if (!cult)
cult = ticker.mode.CreateFaction(/datum/faction/bloodcult, null, 1)
var/datum/role/cultist/newCultist = cult.HandleRecruitedMind(shadeMob.mind, TRUE)
newCultist.Greet(GREET_SOULBLADE)
newCultist.conversion.Add("altar")
/obj/structure/cult/altar/dance_start()//This is executed at the end of the sacrifice ritual
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
if (!cult) // this should not happen
cult = ticker.mode.CreateFaction(/datum/faction/bloodcult, null, 1)
overlays -= build
. = ..()//true if the ritual was successful
min_contributors = initial(min_contributors)
if(!.)
altar_task = ALTARTASK_NONE
return
if(!is_locking(lock_type))
return
switch(altar_task)
if(ALTARTASK_SACRIFICE_HUMAN)
altar_task = ALTARTASK_NONE
update_icon()
var/mob/M = get_locked(lock_type)[1]
if (istype(blade) && !blade.shade && M.mind)//If an empty soul blade was the tool used for the ritual, let's make them its shade.
var/mob/living/simple_animal/shade/new_shade = M.change_mob_type( /mob/living/simple_animal/shade , null, null, 1 )
blade.forceMove(loc)
blade.blood = blade.maxblood
new_shade.forceMove(blade)
blade.shade = new_shade
blade.update_icon()
blade = null
for(var/mob/living/L in dview(world.view, loc, INVISIBILITY_MAXIMUM))
if (L.client)
L.playsound_local(loc, 'sound/effects/convert_failure.ogg', 75, 0, -4)
playsound(loc, get_sfx("soulstone"), 50,1)
var/obj/effect/cult_ritual/conversion/anim = new(loc)
anim.icon_state = ""
flick("rune_convert_refused",anim)
anim.Die()
if (!iscultist(new_shade))
var/datum/role/cultist/newCultist = new
newCultist.AssignToRole(new_shade.mind,1)
cult.HandleRecruitedRole(newCultist)
newCultist.OnPostSetup()
newCultist.Greet(GREET_SACRIFICE)
newCultist.conversion.Add("sacrifice")
new_shade.status_flags |= GODMODE
new_shade.canmove = 0
new_shade.soulblade_ritual = TRUE
new_shade.name = "[M.real_name] the Shade"
new_shade.real_name = "[M.real_name]"
new_shade.give_blade_powers()
playsound(src, get_sfx("soulstone"), 50,1)
else
anim(target = src, a_icon = 'icons/effects/effects.dmi', flick_anim = "rune_sac", lay = ABOVE_SINGULO_LAYER, plane = EFFECTS_PLANE)
spawn(5)
M.gib()
if(ALTARTASK_SACRIFICE_ANIMAL)
altar_task = ALTARTASK_NONE
var/mob/living/M = get_locked(lock_type)[1]
anim(target = src, a_icon = 'icons/effects/effects.dmi', flick_anim = "rune_sac", lay = ABOVE_SINGULO_LAYER, plane = EFFECTS_PLANE)
var/turf/TU = get_turf(src)
spawn(5)
var/obj/item/weapon/reagent_containers/R = locate(/obj/item/weapon/reagent_containers) in TU.contents
if(R)
var/remaining = R.volume - R.reagents.total_volume
if(R && R.is_open_container())
if(istype(M, /mob/living/simple_animal/mouse))
M.take_blood(R, min(remaining, 30))
else
M.take_blood(R, min(remaining, 60))
R.on_reagent_change()
qdel(M)
bloodmess_splatter(TU)
playsound(src, "gib", 30, 0, -3)
/obj/structure/cult/altar/ritual_reward(var/mob/M)
var/datum/role/cultist/C = M.mind.GetRole(CULTIST)
if (C)
switch(altar_task)
if(ALTARTASK_SACRIFICE_HUMAN)
var/mob/O = get_locked(lock_type)[1]
if (O.mind)
C.gain_devotion(500, DEVOTION_TIER_4, "altar_sacrifice_human", O)
else//monkey-human
C.gain_devotion(200, DEVOTION_TIER_4, "altar_sacrifice_human_nomind", O)
if(ALTARTASK_SACRIFICE_ANIMAL)
var/mob/O = get_locked(lock_type)[1]
if (ismonkey(O))
C.gain_devotion(200, DEVOTION_TIER_3, "altar_sacrifice_monkey", O)
else
C.gain_devotion(200, DEVOTION_TIER_3, "altar_sacrifice_animal", O)
#undef ALTARTASK_NONE
#undef ALTARTASK_GEM
#undef ALTARTASK_SACRIFICE_HUMAN
#undef ALTARTASK_SACRIFICE_ANIMAL
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //Spawned from the Raise Structure rune.
// CULT SPIRE //Enables rune-less cult comms for cultists on their current Z-Level
// //
///////////////////////////
var/list/cult_spires = list()
/obj/structure/cult/spire
name = "spire"
desc = "A blood-red needle surrounded by dangerous looking...teeth?."
icon = 'icons/obj/cult_64x64.dmi'
icon_state = ""
health = 100
maxHealth = 100
pixel_x = -16 * PIXEL_MULTIPLIER
pixel_y = -4 * PIXEL_MULTIPLIER
sound_damaged = 'sound/effects/stone_hit.ogg'
sound_destroyed = 'sound/effects/stone_crumble.ogg'
plane = EFFECTS_PLANE
layer = BELOW_PROJECTILE_LAYER
light_color = "#FF0000"
var/stage = 1
/obj/structure/cult/spire/New()
..()
cult_spires += src
set_light(1)
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
if (cult)
switch(cult.stage)
if (BLOODCULT_STAGE_MISSED, BLOODCULT_STAGE_DEFEATED)
stage = 1
if (BLOODCULT_STAGE_NORMAL)
stage = 2
if (BLOODCULT_STAGE_READY, BLOODCULT_STAGE_ECLIPSE, BLOODCULT_STAGE_NARSIE)
stage = 3
flick("spire[stage]-spawn",src)
spawn(10)
update_stage()
var/datum/holomap_marker/holomarker = new()
holomarker.id = HOLOMAP_MARKER_CULT_SPIRE
holomarker.filter = HOLOMAP_FILTER_CULT
holomarker.x = src.x
holomarker.y = src.y
holomarker.z = src.z
holomap_markers[HOLOMAP_MARKER_CULT_SPIRE+"_\ref[src]"] = holomarker
/obj/structure/cult/spire/Destroy()
cult_spires -= src
holomap_markers -= HOLOMAP_MARKER_CULT_SPIRE+"_\ref[src]"
..()
/obj/structure/cult/spire/proc/upgrade(var/new_stage)
new_stage = clamp(new_stage, 1, 3)
if (new_stage>stage)
alpha = 255
overlays.len = 0
color = null
flick("spire[new_stage]-morph", src)
spawn(3)
update_stage()
else if (new_stage<stage)
alpha = 255
overlays.len = 0
color = null
flick("spire[new_stage]-demorph", src)
spawn(3)
update_stage()
stage = new_stage
/obj/structure/cult/spire/proc/update_stage()
animate(src, alpha = 128, color = list(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0), time = 10, loop = -1)
animate(alpha = 144, color = list(1.125,0.06,0,0,0,1.125,0.06,0,0.06,0,1.125,0,0,0,0,1,0,0,0,0), time = 2)
animate(alpha = 160, color = list(1.25,0.12,0,0,0,1.25,0.12,0,0.12,0,1.25,0,0,0,0,1,0,0,0,0), time = 2)
animate(alpha = 176, color = list(1.375,0.19,0,0,0,1.375,0.19,0,0.19,0,1.375,0,0,0,0,1,0,0,0,0), time = 1.5)
animate(alpha = 192, color = list(1.5,0.27,0,0,0,1.5,0.27,0,0.27,0,1.5,0,0,0,0,1,0,0,0,0), time = 1.5)
animate(alpha = 208, color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 224, color = list(1.75,0.45,0.12,0,0.12,1.75,0.45,0,0.45,0.12,1.75,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 240, color = list(1.875,0.56,0.19,0,0.19,1.875,0.56,0,0.56,0.19,1.875,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 255, color = list(2,0.67,0.27,0,0.27,2,0.67,0,0.67,0.27,2,0,0,0,0,1,0,0,0,0), time = 5)
animate(alpha = 240, color = list(1.875,0.56,0.19,0,0.19,1.875,0.56,0,0.56,0.19,1.875,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 224, color = list(1.75,0.45,0.12,0,0.12,1.75,0.45,0,0.45,0.12,1.75,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 208, color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 192, color = list(1.5,0.27,0,0,0,1.5,0.27,0,0.27,0,1.5,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 176, color = list(1.375,0.19,0,0,0,1.375,0.19,0,0.19,0,1.375,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 160, color = list(1.25,0.12,0,0,0,1.25,0.12,0,0.12,0,1.25,0,0,0,0,1,0,0,0,0), time = 1)
animate(alpha = 144, color = list(1.125,0.06,0,0,0,1.125,0.06,0,0.06,0,1.125,0,0,0,0,1,0,0,0,0), time = 1)
overlays.len = 0
var/image/I_base = image('icons/obj/cult_64x64.dmi',"spire[stage]")
I_base.plane = relative_plane(EFFECTS_PLANE)
I_base.layer = BELOW_PROJECTILE_LAYER
I_base.appearance_flags |= RESET_COLOR//we don't want the stone to pulse
var/image/I_spire = image('icons/obj/cult_64x64.dmi',"spire[stage]-light")
I_spire.plane = ABOVE_LIGHTING_PLANE
I_spire.layer = NARSIE_GLOW
overlays += I_base
overlays += I_spire
/obj/structure/cult/spire/conceal()
overlays.len = 0
set_light(0)
anim(location = loc,target = loc,a_icon = 'icons/obj/cult_64x64.dmi', flick_anim = "spire[stage]-conceal", lay = BELOW_PROJECTILE_LAYER, offX = pixel_x, offY = pixel_y, plane = EFFECTS_PLANE)
..()
var/obj/structure/cult/concealed/C = loc
if (istype(C))
C.icon_state = "spire[stage]"
/obj/structure/cult/spire/reveal()
..()
set_light(1)
flick("spire[stage]-spawn", src)
animate(src)
alpha = 255
color = list(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0)
spawn(10)
update_stage()
/obj/structure/cult/spire/cultist_act(var/mob/user,var/menu="default")
.=..()
if (!.)
return
// For now spires work as cult telecomms relay. Eventually they'll serve as a link between the station and the blood realm.
/*
if (!ishuman(user))
to_chat(user,"<span class='warning'>Only humans can bear the arcane markings granted by this [name].</span>")
return
var/mob/living/carbon/human/H = user
var/datum/role/cultist/C = iscultist(H)
var/list/available_tattoos = list("tier1","tier2","tier3")
for (var/tattoo in C.tattoos)
var/datum/cult_tattoo/CT = C.tattoos[tattoo]
available_tattoos -= "tier[CT.tier]"
var/tattoo_tier = 0
if (available_tattoos.len <= 0)
to_chat(user,"<span class='warning'>You cannot bear any additional mark.</span>")
return
if ("tier1" in available_tattoos)
tattoo_tier = 1
else if ("tier2" in available_tattoos)
tattoo_tier = 2
else if ("tier3" in available_tattoos)
tattoo_tier = 3
if (!tattoo_tier)
return
var/list/choices = list()
if (stage >= tattoo_tier)
for (var/subtype in subtypesof(/datum/cult_tattoo))
var/datum/cult_tattoo/T = new subtype
if (T.tier == tattoo_tier)
choices += list(list(T.name, "radial_[T.icon_state]", T.desc)) //According to BYOND docs, when adding to a list, "If an argument is itself a list, each item in the list will be added." My solution to that, because I am a genius, is to add a list within a list.
to_chat(H, "<span class='danger'>[T.name]</span>: [T.desc]")
else
to_chat(user,"<span class='warning'>Come back to acquire another mark once your cult is a step closer to its goal.</span>")
return
var/tattoo = show_radial_menu(user,loc,choices,'icons/obj/cult_radial2.dmi',"radial-cult2")//spawning on loc so we aren't offset by pixel_x/pixel_y, or affected by animate()
for (var/tat in C.tattoos)
var/datum/cult_tattoo/CT = C.tattoos[tat]
if (CT.tier == tattoo_tier)//the spire won't let cultists get multiple tattoos of the same tier.
return
if (!Adjacent(user))//stay here you bloke!
return
for (var/subtype in subtypesof(/datum/cult_tattoo))
var/datum/cult_tattoo/T = new subtype
if (T.name == tattoo)
var/datum/cult_tattoo/new_tattoo = T
C.tattoos[new_tattoo.name] = new_tattoo
anim(target = loc, a_icon = 'icons/effects/32x96.dmi', flick_anim = "tattoo_send", lay = NARSIE_GLOW, plane = ABOVE_LIGHTING_PLANE)
spawn (3)
C.update_cult_hud()
new_tattoo.getTattoo(H)
anim(target = H, a_icon = 'icons/effects/32x96.dmi', flick_anim = "tattoo_receive", lay = NARSIE_GLOW, plane = ABOVE_LIGHTING_PLANE)
sleep(1)
H.update_mutations()
var/atom/movable/overlay/tattoo_markings = anim(target = H, a_icon = 'icons/mob/cult_tattoos.dmi', flick_anim = "[new_tattoo.icon_state]_mark", sleeptime = 30, lay = NARSIE_GLOW, plane = ABOVE_LIGHTING_PLANE)
animate(tattoo_markings, alpha = 0, time = 30)
available_tattoos -= "tier[new_tattoo.tier]"
if (available_tattoos.len > 0)
cultist_act(user)
break
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //Spawned from the Raise Structure rune
// CULT FORGE //Also a source of heat
// //
///////////////////////////
/obj/structure/cult/forge
name = "forge"
desc = "Molten rocks flow down its cracks producing a searing heat, better not stand too close for long."
icon = 'icons/obj/cult_64x64.dmi'
icon_state = ""
health = 100
maxHealth = 100
pixel_x = -16 * PIXEL_MULTIPLIER
pixel_y = -16 * PIXEL_MULTIPLIER
sound_damaged = 'sound/effects/stone_hit.ogg'
sound_destroyed = 'sound/effects/stone_crumble.ogg'
plane = EFFECTS_PLANE
layer = BELOW_PROJECTILE_LAYER
light_color = LIGHT_COLOR_ORANGE
custom_process = 1
var/heating_power = 40000
var/set_temperature = 50
var/mob/forger = null
var/template = null
var/forge_icon = ""
var/obj/effect/cult_ritual/forge/forging = null
/obj/structure/cult/forge/New()
..()
processing_objects.Add(src)
set_light(2)
flick("forge-spawn",src)
spawn(10)
setup_overlays()
var/datum/holomap_marker/holomarker = new()
holomarker.id = HOLOMAP_MARKER_CULT_FORGE
holomarker.filter = HOLOMAP_FILTER_CULT
holomarker.x = src.x
holomarker.y = src.y
holomarker.z = src.z
holomap_markers[HOLOMAP_MARKER_CULT_FORGE+"_\ref[src]"] = holomarker
/obj/structure/cult/forge/Destroy()
if (forging)
qdel(forging)
forging = null
forger = null
processing_objects.Remove(src)
holomap_markers -= HOLOMAP_MARKER_CULT_FORGE+"_\ref[src]"
..()
/obj/structure/cult/forge/proc/setup_overlays()
animate(src, alpha = 255, time = 10, loop = -1)
animate(alpha = 240, time = 2)
animate(alpha = 224, time = 2)
animate(alpha = 208, time = 1.5)
animate(alpha = 192, time = 1.5)
animate(alpha = 176, time = 1)
animate(alpha = 160, time = 1)
animate(alpha = 144, time = 1)
animate(alpha = 128, time = 3)
animate(alpha = 144, time = 1)
animate(alpha = 160, time = 1)
animate(alpha = 176, time = 1)
animate(alpha = 192, time = 1.5)
animate(alpha = 208, time = 1.5)
animate(alpha = 224, time = 2)
animate(alpha = 240, time = 2)
overlays.len = 0
var/image/I_base = image('icons/obj/cult_64x64.dmi',"forge")
I_base.plane = relative_plane(EFFECTS_PLANE)
I_base.layer = BELOW_PROJECTILE_LAYER
I_base.appearance_flags |= RESET_ALPHA //we don't want the stone to pulse
var/image/I_lave = image('icons/obj/cult_64x64.dmi',"forge-lightmask")
I_lave.plane = ABOVE_LIGHTING_PLANE
I_lave.layer = NARSIE_GLOW
I_lave.blend_mode = BLEND_ADD
overlays += I_base
overlays += I_lave
/obj/structure/cult/forge/process()
..()
if (isturf(loc))
var/turf/simulated/L = loc
if(istype(L))
try_hotspot_expose(TEMPERATURE_FLAME, SMALL_FLAME, 0)//we start fires in plasma atmos
var/datum/gas_mixture/env = L.return_air()
if (env.total_moles > 0)//we cannot manipulate temperature in a vacuum
if(env.temperature != set_temperature + T0C)
var/datum/gas_mixture/removed = env.remove_volume(0.5 * CELL_VOLUME)
if(removed)
var/heat_capacity = removed.heat_capacity()
if(heat_capacity)
if(removed.temperature < set_temperature + T0C)
removed.temperature = min(removed.temperature + heating_power/heat_capacity, 1000)
env.merge(removed)
if(!istype(loc,/turf/space))
for (var/mob/living/carbon/M in view(src,3))
M.bodytemperature += (6-round(M.get_cult_power()/30))/((get_dist(src,M)+1))//cult gear reduces the heat buildup
if (forging)
if (forger)
if (!Adjacent(forger) || forger.incapacitated())
if (forger.client)
forger.client.images -= progbar
forger = null
return
else
timeleft--
update_progbar()
var/datum/role/cultist/C = iscultist(forger)
if (C)
C.gain_devotion(10, DEVOTION_TIER_2, "[forge_icon]",timeleft)
if (timeleft<=0)
playsound(L, 'sound/effects/forge_over.ogg', 50, 0, -3)
if (forger.client)
forger.client.images -= progbar
QDEL_NULL(forging)
var/obj/item/I = new template(L)
if (istype(I))
I.plane = EFFECTS_PLANE
I.layer = PROJECTILE_LAYER
I.pixel_y = 12
else
I.forceMove(get_turf(forger))
forger = null
template = null
else
anim(target = loc, a_icon = 'icons/obj/cult_64x64.dmi', flick_anim = "forge-work", lay = NARSIE_GLOW, offX = pixel_x, offY = pixel_y, plane = ABOVE_LIGHTING_PLANE)
playsound(L, 'sound/effects/forge.ogg', 50, 0, -4)
forging.overlays.len = 0
var/image/I = image('icons/obj/cult_64x64.dmi',"[forging.icon_state]-mask")
I.plane = ABOVE_LIGHTING_PLANE
I.layer = NARSIE_GLOW
I.blend_mode = BLEND_ADD
I.alpha = (timeleft/timetotal)*255
forging.overlays += I
/obj/structure/cult/forge/conceal()
overlays.len = 0
set_light(0)
anim(location = loc,target = loc,a_icon = 'icons/obj/cult_64x64.dmi', flick_anim = "forge-conceal", lay = BELOW_PROJECTILE_LAYER, offX = pixel_x, offY = pixel_y, plane = EFFECTS_PLANE)
..()
var/obj/structure/cult/concealed/C = loc
if (istype(C))
C.icon_state = "forge"
/obj/structure/cult/forge/reveal()
..()
animate(src)
alpha = 255
set_light(2)
flick("forge-spawn", src)
spawn(10)
animate(src, alpha = 255, time = 10, loop = -1)
animate(alpha = 240, time = 2)
animate(alpha = 224, time = 2)
animate(alpha = 208, time = 1.5)
animate(alpha = 192, time = 1.5)
animate(alpha = 176, time = 1)
animate(alpha = 160, time = 1)
animate(alpha = 144, time = 1)
animate(alpha = 128, time = 3)
animate(alpha = 144, time = 1)
animate(alpha = 160, time = 1)
animate(alpha = 176, time = 1)
animate(alpha = 192, time = 1.5)
animate(alpha = 208, time = 1.5)
animate(alpha = 224, time = 2)
animate(alpha = 240, time = 2)
var/image/I_base = image('icons/obj/cult_64x64.dmi',"forge")
I_base.plane = relative_plane(EFFECTS_PLANE)
I_base.layer = BELOW_PROJECTILE_LAYER
I_base.appearance_flags |= RESET_ALPHA //we don't want the stone to pulse
var/image/I_lave = image('icons/obj/cult_64x64.dmi',"forge-lightmask")
I_lave.plane = ABOVE_LIGHTING_PLANE
I_lave.layer = NARSIE_GLOW
I_lave.blend_mode = BLEND_ADD
overlays += I_base
overlays += I_lave
/obj/structure/cult/forge/attackby(var/obj/item/I, var/mob/user)
if(istype(I,/obj/item/clothing/mask/cigarette))
var/obj/item/clothing/mask/cigarette/fag = I
fag.light("<span class='notice'>\The [user] lights \the [fag] by bringing its tip close to \the [src]'s molten flow.</span>")
return 1
if(istype(I,/obj/item/candle))
var/obj/item/candle/stick = I
stick.light("<span class='notice'>\The [user] lights \the [stick] by bringing its wick close to \the [src]'s molten flow.</span>")
return 1
if(istype(I,/obj/item/weapon/talisman) || istype(I,/obj/item/weapon/paper) || istype(I,/obj/item/weapon/tome))
I.ashify_item(user)
return 1
..()
/obj/structure/cult/proc/update_progbar()
if (!progbar)
progbar = image("icon" = 'icons/effects/doafter_icon.dmi', "loc" = src, "icon_state" = "prog_bar_0")
progbar.pixel_z = WORLD_ICON_SIZE
progbar.plane = HUD_PLANE
progbar.pixel_x = 16 * PIXEL_MULTIPLIER
progbar.pixel_y = 16 * PIXEL_MULTIPLIER
progbar.appearance_flags = RESET_ALPHA|RESET_COLOR
progbar.layer = HUD_ABOVE_ITEM_LAYER
progbar.icon_state = "prog_bar_[round((100 - min(1, timeleft / timetotal) * 100), 10)]"
/obj/structure/cult/altar/update_progbar()
if (!progbar)
progbar = image("icon" = 'icons/effects/doafter_icon.dmi', "loc" = src, "icon_state" = "prog_bar_0")
progbar.pixel_z = WORLD_ICON_SIZE
progbar.plane = HUD_PLANE
progbar.layer = HUD_ABOVE_ITEM_LAYER
progbar.icon_state = "prog_bar_[round((100 - min(1, timeleft / timetotal) * 100), 10)]"
/obj/structure/cult/forge/cultist_act(var/mob/user,var/menu="default")
.=..()
if (!.)
return
if (template)
if (forger)
if (forger == user)
to_chat(user, "You are already working at this forge.")
else
to_chat(user, "\The [forger] is currently working at this forge already.")
else
to_chat(user, "You resume working at the forge.")
forger = user
if (forger.client)
forger.client.images |= progbar
return
var/list/choices = list(
list("Forge Blade", "radial_blade", "A powerful ritual blade, the signature weapon of the bloodthirsty cultists. Features a notch in which a Soul Gem can fit."),
list("Forge Construct Shell", "radial_constructshell", "A polymorphic sculpture that can be shaped into a powerful ally by inserting a full Soul Gem or Shard."),
list("Forge Helmet", "radial_helmet", "This protective helmet offers the same enhancing powers that a Cult Hood provides, on top of being space proof."),
list("Forge Armor", "radial_armor", "This protective armor offers the same enhancing powers that Cult Robes provide, on top of being space proof."),
)
var/task = show_radial_menu(user,loc,choices,'icons/obj/cult_radial.dmi',"radial-cult")//spawning on loc so we aren't offset by pixel_x/pixel_y, or affected by animate()
if (template || !Adjacent(user) || !task )
return
forge_icon = ""
switch (task)
if ("Forge Blade")
template = /obj/item/weapon/melee/cultblade
timeleft = 10
forge_icon = "forge_blade"
if ("Forge Armor")
template = /obj/item/clothing/suit/space/cult
timeleft = 23
forge_icon = "forge_armor"
if ("Forge Helmet")
template = /obj/item/clothing/head/helmet/space/cult
timeleft = 8
forge_icon = "forge_helmet"
if ("Forge Construct Shell")
template = /obj/structure/constructshell/cult/alt
timeleft = 25
forge_icon = "forge_shell"
timetotal = timeleft
forger = user
update_progbar()
if (forger.client)
forger.client.images |= progbar
forging = new (loc,forge_icon)
/obj/effect/cult_ritual/forge
icon = 'icons/obj/cult_64x64.dmi'
icon_state = ""
pixel_x = -16 * PIXEL_MULTIPLIER
pixel_y = -16 * PIXEL_MULTIPLIER
plane = EFFECTS_PLANE
layer = PROJECTILE_LAYER
/obj/effect/cult_ritual/forge/New(var/turf/loc, var/i_forge="")
..()
icon_state = i_forge
var/image/I = image('icons/obj/cult_64x64.dmi',"[i_forge]-mask")
I.plane = ABOVE_LIGHTING_PLANE
I.layer = NARSIE_GLOW
I.blend_mode = BLEND_ADD
overlays += I
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //Spawns next to blood stones
// OBSIDIAN PILLAR //
// //
///////////////////////////
/obj/structure/cult/pillar
name = "obsidian pillar"
icon_state = "pillar-enter"
icon = 'icons/obj/cult_64x64.dmi'
pixel_x = -16 * PIXEL_MULTIPLIER
health = 200
maxHealth = 200
sound_damaged = 'sound/effects/stone_hit.ogg'
sound_destroyed = 'sound/effects/stone_crumble.ogg'
plane = EFFECTS_PLANE
layer = BELOW_PROJECTILE_LAYER
var/alt = 0
/obj/structure/cult/pillar/New()
..()
var/turf/T = loc
if (!T)
qdel(src)
return
for (var/obj/O in loc)
if (istype(O, /obj/structure/window))
var/obj/structure/window/W = O
if (!W.is_fulltile)//reduces breaches ever so slightly
continue
if(O == src)
continue
O.ex_act(2)
if(!O.gcDestroyed && (istype(O, /obj/structure) || istype(O, /obj/machinery)))
qdel(O)
T.ChangeTurf(/turf/simulated/floor/engine/cult)
T.turf_animation('icons/effects/effects.dmi',"cultfloor", 0, 0, MOB_LAYER-1, anim_plane = TURF_PLANE)
/obj/structure/cult/pillar/Destroy()
new /obj/effect/decal/cleanable/ash(loc)
..()
/obj/structure/cult/pillar/alt
icon_state = "pillaralt-enter"
alt = 1
/obj/structure/cult/pillar/update_icon()
icon_state = "pillar[alt ? "alt": ""]2"
set_light(1.5, 2.5, LIGHT_COLOR_RED)
overlays.len = 0
if (health < maxHealth/3)
icon_state = "pillar[alt ? "alt": ""]0"
else if (health < 2*maxHealth/3)
icon_state = "pillar[alt ? "alt": ""]1"
/obj/structure/cult/pillar/conceal()
return
/obj/structure/cult/pillar/ex_act(var/severity)
switch(severity)
if (1)
takeDamage(200)
if (2)
takeDamage(100)
if (3)
takeDamage(20)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //Re-added as a cosmetic structure by admin request
// BLOOD STONE //
// //
///////////////////////////
/obj/structure/cult/bloodstone
name = "blood stone"
icon_state = "bloodstone-enter1"
icon = 'icons/obj/cult_64x64.dmi'
pixel_x = -16 * PIXEL_MULTIPLIER
health = 1800
maxHealth = 1800
sound_damaged = 'sound/effects/stone_hit.ogg'
sound_destroyed = 'sound/effects/stone_crumble.ogg'
plane = EFFECTS_PLANE
layer = BELOW_PROJECTILE_LAYER
light_color = "#FF0000"
var/ready = FALSE
var/image/image_base
var/image/image_circle
var/image/image_stones
var/image/image_lights
var/image/image_damage
var/datum/faction/bloodcult/cult
var/list/pillars = list()
/obj/structure/cult/bloodstone/New()
..()
set_light(3)
cult = find_active_faction_by_type(/datum/faction/bloodcult)
image_base = image('icons/obj/cult_64x64.dmi',"bloodstone-base-old")
image_base.appearance_flags |= RESET_COLOR
image_base.layer = BLOODSTONE_BASE
image_damage = image('icons/obj/cult_64x64.dmi',"bloodstone_damage0")
image_circle = image('icons/obj/cult_64x64.dmi',"large_circle")
image_circle.plane = relative_plane(ABOVE_TURF_PLANE)
image_circle.layer = ABOVE_TILE_LAYER
image_circle.appearance_flags |= RESET_COLOR
image_circle.pixel_y = -16
image_stones = image('icons/obj/cult_64x64.dmi',"tear_stones")
image_stones.plane = relative_plane(OBJ_PLANE)
image_stones.layer = BELOW_TABLE_LAYER
image_stones.appearance_flags |= RESET_COLOR
image_stones.pixel_y = -16
image_lights = image('icons/obj/cult_64x64.dmi',"tear_stones_light")
image_lights.plane = relative_plane(ABOVE_OBJ_PLANE)
image_lights.layer = TABLE_LAYER
image_lights.pixel_y = -16
/obj/structure/cult/bloodstone/proc/overlays_pre()
overlays += image_base
overlays += image_circle
overlays += image_stones
overlays += image_lights
update_moody_light_index("tear_stones",'icons/lighting/moody_lights_64x64.dmi', "tear_stones", offY = -16)
/obj/structure/cult/bloodstone/admin/overlays_pre()
overlays += image_base
/obj/structure/cult/bloodstone/proc/overlays_post()
overlays -= image_base
image_base.icon_state = "bloodstone-base"
overlays += image_base
/obj/structure/cult/bloodstone/admin/overlays_post()
return
/obj/structure/cult/bloodstone/proc/flashy_entrance(var/datum/rune_spell/tearreality/TR)
for (var/obj/O in loc)
if (O != src && !istype(O,/obj/item/weapon/melee/soulblade))
O.ex_act(2)
safe_space()
overlays_pre()
explosion_sound(TR)
TR?.pillar_update(1)
spawn(10)
pillars = list()
icon_state = "bloodstone-enter2"
explosion_sound(TR)
TR?.pillar_update(2)
var/turf/T1 = locate(x-2,y-2,z)
pillars += new /obj/structure/cult/pillar(T1)
var/turf/T2 = locate(x+2,y-2,z)
pillars += new /obj/structure/cult/pillar/alt(T2)
var/turf/T3 = locate(x-2,y+2,z)
pillars += new /obj/structure/cult/pillar(T3)
var/turf/T4 = locate(x+2,y+2,z)
pillars += new /obj/structure/cult/pillar/alt(T4)
sleep(10)
icon_state = "bloodstone-enter3"
explosion_sound(TR)
TR?.pillar_update(3)
for (var/obj/structure/cult/pillar/P in pillars)
P.update_icon()
sleep(10)
ready = TRUE
overlays_post()
set_animate()
/obj/structure/cult/bloodstone/proc/explosion_sound(var/datum/rune_spell/tearreality/TR)
for(var/mob/M in player_list)
if (M.z == z && M.client)
if (TR || (get_dist(M,src)<=20))//If there's a tear reality rune, then spires should be appearing all over the station, so no point not having it be loud
M.playsound_local(src, get_sfx("explosion"), 50, 1)
shake_camera(M, 4, 1)
else
M.playsound_local(src, 'sound/effects/explosionfar.ogg', 50, 1)
shake_camera(M, 1, 1)
/obj/structure/cult/bloodstone/Destroy()
new /obj/effect/decal/cleanable/ash(loc)
new /obj/item/weapon/ectoplasm(loc)
if (cult && (cult.bloodstone == src))
cult.bloodstone = null
spawn()
cult.stage(BLOODCULT_STAGE_DEFEATED)
for (var/obj/effect/rune/R in src)
R.active_spell?.abort()
..()
/obj/structure/cult/bloodstone/attack_construct(var/mob/user)
if (!Adjacent(user))
return 0
cultist_act(user)
return 1
/*
/obj/structure/cult/bloodstone/cultist_act(var/mob/user)
.=..()
if (!.)
return
if(isliving(user))
var/obj/effect/cult_ritual/dance/dance_center = locate() in loc
if (dance_center)
dance_center.add_dancer(user)
else
dance_center = new(loc, user)
if (prob(5))
user.say("Let me show you the dance of my people!","C")
else
user.say("Tok-lyr rqa'nap g'lt-ulotf!","C")
*/
/obj/structure/cult/bloodstone/conceal()
return
/obj/structure/cult/bloodstone/takeDamage(var/damage)
if (cult && (cult.stage == BLOODCULT_STAGE_NARSIE))
return
health -= damage
if (health <= 0)
if (sound_destroyed)
playsound(src, sound_destroyed, 100, 1)
qdel(src)
else
update_icon()
/obj/structure/cult/bloodstone/ex_act(var/severity)
switch(severity)
if (1)
takeDamage(250)
if (2)
takeDamage(50)
if (3)
takeDamage(10)
/obj/structure/cult/bloodstone/singularity_act(var/singularity_size=0,var/obj/machinery/singularity/S)
switch(singularity_size)
if(1 to 4)
ex_act(3)
if(5 to 8)
ex_act(2)
if(9 to INFINITY)
ex_act(1)
return 0
/obj/structure/cult/bloodstone/singularity_pull(S, current_size, repel = FALSE)//we don't want that one to come unanchored
return
/obj/structure/cult/bloodstone/update_icon()
if (!ready)
return
icon_state = "bloodstone-0"
if (cult)
icon_state = "bloodstone-[clamp(round(9*(world.time - cult.bloodstone_rising_time) / (cult.bloodstone_target_time - cult.bloodstone_rising_time)), 0, 9)]"
overlays -= image_damage
update_moody_light_index("crystal",'icons/lighting/moody_lights_64x64.dmi', icon_state)
if (health < maxHealth/3)
image_damage.icon_state = "bloodstone_damage2"
update_moody_light_index("damage",'icons/lighting/moody_lights_64x64.dmi', "bloodstone_damage2")
else if (health < 2*maxHealth/3)
image_damage.icon_state = "bloodstone_damage1"
update_moody_light_index("damage",'icons/lighting/moody_lights_64x64.dmi', "bloodstone_damage1")
else
image_damage.icon_state = "bloodstone_damage0"
kill_moody_light_index("damage")
overlays += image_damage
/obj/structure/cult/bloodstone/admin/update_icon()
icon_state = "bloodstone-9-old"
overlays -= image_damage
update_moody_light_index("crystal",'icons/lighting/moody_lights_64x64.dmi', icon_state)
if (health < maxHealth/3)
image_damage.icon_state = "bloodstone_damage2"
update_moody_light_index("damage",'icons/lighting/moody_lights_64x64.dmi', "bloodstone_damage2")
else if (health < 2*maxHealth/3)
image_damage.icon_state = "bloodstone_damage1"
update_moody_light_index("damage",'icons/lighting/moody_lights_64x64.dmi', "bloodstone_damage1")
else
image_damage.icon_state = "bloodstone_damage0"
kill_moody_light_index("damage")
overlays += image_damage
/obj/structure/cult/bloodstone/proc/set_animate()
animate(src, color = list(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0), time = 10, loop = -1)
animate(color = list(1.125,0.06,0,0,0,1.125,0.06,0,0.06,0,1.125,0,0,0,0,1,0,0,0,0), time = 2)
animate(color = list(1.25,0.12,0,0,0,1.25,0.12,0,0.12,0,1.25,0,0,0,0,1,0,0,0,0), time = 2)
animate(color = list(1.375,0.19,0,0,0,1.375,0.19,0,0.19,0,1.375,0,0,0,0,1,0,0,0,0), time = 1.5)
animate(color = list(1.5,0.27,0,0,0,1.5,0.27,0,0.27,0,1.5,0,0,0,0,1,0,0,0,0), time = 1.5)
animate(color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.75,0.45,0.12,0,0.12,1.75,0.45,0,0.45,0.12,1.75,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.875,0.56,0.19,0,0.19,1.875,0.56,0,0.56,0.19,1.875,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(2,0.67,0.27,0,0.27,2,0.67,0,0.67,0.27,2,0,0,0,0,1,0,0,0,0), time = 5)
animate(color = list(1.875,0.56,0.19,0,0.19,1.875,0.56,0,0.56,0.19,1.875,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.75,0.45,0.12,0,0.12,1.75,0.45,0,0.45,0.12,1.75,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.5,0.27,0,0,0,1.5,0.27,0,0.27,0,1.5,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.375,0.19,0,0,0,1.375,0.19,0,0.19,0,1.375,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.25,0.12,0,0,0,1.25,0.12,0,0.12,0,1.25,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.125,0.06,0,0,0,1.125,0.06,0,0.06,0,1.125,0,0,0,0,1,0,0,0,0), time = 1)
update_icon()
/*
/obj/structure/cult/bloodstone
name = "blood stone"
icon_state = "bloodstone-enter1"
icon = 'icons/obj/cult_64x64.dmi'
pixel_x = -16 * PIXEL_MULTIPLIER
health = 600
maxHealth = 600
sound_damaged = 'sound/effects/stone_hit.ogg'
sound_destroyed = 'sound/effects/stone_crumble.ogg'
plane = EFFECTS_PLANE
layer = BELOW_PROJECTILE_LAYER
light_color = "#FF0000"
var/list/watching_mobs = list()
var/list/watcher_maps = list()
var/datum/station_holomap/holomap_datum
var/anchor = FALSE
/obj/structure/cult/bloodstone/New()
..()
var/datum/holomap_marker/newMarker = new()
newMarker.id = HOLOMAP_MARKER_BLOODSTONE
newMarker.filter = HOLOMAP_FILTER_CULT
newMarker.x = x
newMarker.y = y
newMarker.z = z
holomap_markers[HOLOMAP_MARKER_BLOODSTONE+"_\ref[src]"] = newMarker
holomap_datum = new /datum/station_holomap/cult()
holomap_datum.initialize_holomap(get_turf(src))
bloodstone_list.Add(src)
for (var/obj/O in loc)
if (O != src && !istype(O,/obj/item/weapon/melee/soulblade))
O.ex_act(2)
safe_space()
set_light(3)
for(var/mob/M in player_list)
if (M.z == z && M.client)
if (get_dist(M,src)<=20)
M.playsound_local(src, get_sfx("explosion"), 50, 1)
shake_camera(M, 4, 1)
else
M.playsound_local(src, 'sound/effects/explosionfar.ogg', 50, 1)
shake_camera(M, 1, 1)
spawn(10)
var/list/pillars = list()
icon_state = "bloodstone-enter2"
for(var/mob/M in player_list)
if (M.z == z && M.client)
if (get_dist(M,src)<=20)
M.playsound_local(src, get_sfx("explosion"), 50, 1)
shake_camera(M, 4, 1)
else
M.playsound_local(src, 'sound/effects/explosionfar.ogg', 50, 1)
shake_camera(M, 1, 1)
var/turf/T1 = locate(x-2,y-2,z)
pillars += new /obj/structure/cult/pillar(T1)
var/turf/T2 = locate(x+2,y-2,z)
pillars += new /obj/structure/cult/pillar/alt(T2)
var/turf/T3 = locate(x-2,y+2,z)
pillars += new /obj/structure/cult/pillar(T3)
var/turf/T4 = locate(x+2,y+2,z)
pillars += new /obj/structure/cult/pillar/alt(T4)
sleep(10)
icon_state = "bloodstone-enter3"
for(var/mob/M in player_list)
if (M.z == z && M.client)
if (get_dist(M,src)<=20)
M.playsound_local(src, get_sfx("explosion"), 50, 1)
shake_camera(M, 4, 1)
else
M.playsound_local(src, 'sound/effects/explosionfar.ogg', 50, 1)
shake_camera(M, 1, 1)
for (var/obj/structure/cult/pillar/P in pillars)
P.update_icon()
/obj/structure/cult/bloodstone/Destroy()
bloodstone_list.Remove(src)
new /obj/effect/decal/cleanable/ash(loc)
new /obj/item/weapon/ectoplasm(loc)
var/datum/holomap_marker/holomarker = new()
holomarker.id = HOLOMAP_MARKER_BLOODSTONE_BROKEN
holomarker.filter = HOLOMAP_FILTER_CULT
holomarker.x = src.x
holomarker.y = src.y
holomarker.z = src.z
holomap_markers[HOLOMAP_MARKER_BLOODSTONE+"_\ref[src]"] = holomarker
/* --no need to update the map
if(holomarker.z == map.zMainStation && holomarker.filter & HOLOMAP_FILTER_CULT)
if(map.holomap_offset_x.len >= map.zMainStation)
updated_map.Blend(icon(holomarker.icon,holomarker.id), ICON_OVERLAY, holomarker.x-8+map.holomap_offset_x[map.zMainStation] , holomarker.y-8+map.holomap_offset_y[map.zMainStation])
else
updated_map.Blend(icon(holomarker.icon,holomarker.id), ICON_OVERLAY, holomarker.x-8, holomarker.y-8)
extraMiniMaps[HOLOMAP_EXTRA_CULTMAP] = updated_map
*/
for(var/obj/structure/cult/bloodstone/B in bloodstone_list)
if (B != src && !B.loc)
message_admins("Blood Cult: A blood stone was somehow spawned in nullspace. It has been destroyed.")
qdel(B)
if (bloodstone_list.len <= 0 || anchor)
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
if (cult)
cult.fail()
if(anchor)
global_anchor_bloodstone = null
..()
/obj/structure/cult/bloodstone/attack_construct(var/mob/user)
if (!Adjacent(user))
return 0
cultist_act(user)
return 1
/obj/structure/cult/bloodstone/cultist_act(var/mob/user)
.=..()
if (!.)
return
if(isliving(user))
if(user in watching_mobs)
stopWatching(user)
else
if (anchor)
if (user in contributors)
return
if (!user.checkTattoo(TATTOO_SILENT))
if (prob(5))
user.say("Let me show you the dance of my people!","C")
else
user.say("Tok-lyr rqa'nap g'lt-ulotf!","C")
contributors.Add(user)
if (user.client)
update_progbar()
user.client.images |= progbar
else if(user.hud_used && user.hud_used.holomap_obj)
if(!("\ref[user]" in watcher_maps))
var/image/personnal_I = prepare_cult_holomap()
var/turf/T = get_turf(src)
if(map.holomap_offset_x.len >= T.z)
holomap_datum.cursor.pixel_x = (T.x-9+map.holomap_offset_x[T.z])*PIXEL_MULTIPLIER
holomap_datum.cursor.pixel_y = (T.y-9+map.holomap_offset_y[T.z])*PIXEL_MULTIPLIER
else
holomap_datum.cursor.pixel_x = (T.x-9)*PIXEL_MULTIPLIER
holomap_datum.cursor.pixel_y = (T.y-9)*PIXEL_MULTIPLIER
personnal_I.overlays += holomap_datum.cursor
watcher_maps["\ref[user]"] = personnal_I
var/image/I = watcher_maps["\ref[user]"]
I.loc = user.hud_used.holomap_obj
I.alpha = 0
animate(watcher_maps["\ref[user]"], alpha = 255, time = 5, easing = LINEAR_EASING)
watching_mobs |= user
user.client.images |= watcher_maps["\ref[user]"]
user.register_event(/event/face, src, /obj/structure/cult/bloodstone/proc/checkPosition)
/obj/structure/cult/bloodstone/proc/checkPosition()
for(var/mob/M in watching_mobs)
if(get_dist(src,M) > 1)
stopWatching(M)
/obj/structure/cult/bloodstone/proc/stopWatching(var/mob/user)
if(!user)
for(var/mob/M in watching_mobs)
if(M.client)
spawn(5)//we give it time to fade out
M.client.images -= watcher_maps["\ref[M]"]
M.unregister_event(/event/face, src, /obj/structure/cult/bloodstone/proc/checkPosition)
animate(watcher_maps["\ref[M]"], alpha = 0, time = 5, easing = LINEAR_EASING)
watching_mobs = list()
else
if(user.client)
spawn(5)//we give it time to fade out
if(!(user in watching_mobs))
user.client.images -= watcher_maps["\ref[user]"]
watcher_maps -= "\ref[user]"
user.unregister_event(/event/face, src, /obj/structure/cult/bloodstone/proc/checkPosition)
animate(watcher_maps["\ref[user]"], alpha = 0, time = 5, easing = LINEAR_EASING)
watching_mobs -= user
/obj/structure/cult/bloodstone/update_icon()
icon_state = "bloodstone-0"
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
if (cult)
var/datum/objective/bloodcult_bloodbath/O = locate() in cult.objective_holder.objectives
if (O)
icon_state = "bloodstone-[max(0,min(9,round(cult.bloody_floors.len*100/O.target_bloodspill/10)))]"
overlays.len = 0
var/image/I_base = image('icons/obj/cult_64x64.dmi',"bloodstone-base")
I_base.appearance_flags |= RESET_COLOR//we don't want the stone to pulse
overlays += I_base
if (health < maxHealth/3)
overlays.Add("bloodstone_damage2")
else if (health < 2*maxHealth/3)
overlays.Add("bloodstone_damage1")
/obj/structure/cult/bloodstone/proc/set_animate()
animate(src, color = list(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0), time = 10, loop = -1)
animate(color = list(1.125,0.06,0,0,0,1.125,0.06,0,0.06,0,1.125,0,0,0,0,1,0,0,0,0), time = 2)
animate(color = list(1.25,0.12,0,0,0,1.25,0.12,0,0.12,0,1.25,0,0,0,0,1,0,0,0,0), time = 2)
animate(color = list(1.375,0.19,0,0,0,1.375,0.19,0,0.19,0,1.375,0,0,0,0,1,0,0,0,0), time = 1.5)
animate(color = list(1.5,0.27,0,0,0,1.5,0.27,0,0.27,0,1.5,0,0,0,0,1,0,0,0,0), time = 1.5)
animate(color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.75,0.45,0.12,0,0.12,1.75,0.45,0,0.45,0.12,1.75,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.875,0.56,0.19,0,0.19,1.875,0.56,0,0.56,0.19,1.875,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(2,0.67,0.27,0,0.27,2,0.67,0,0.67,0.27,2,0,0,0,0,1,0,0,0,0), time = 5)
animate(color = list(1.875,0.56,0.19,0,0.19,1.875,0.56,0,0.56,0.19,1.875,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.75,0.45,0.12,0,0.12,1.75,0.45,0,0.45,0.12,1.75,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.5,0.27,0,0,0,1.5,0.27,0,0.27,0,1.5,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.375,0.19,0,0,0,1.375,0.19,0,0.19,0,1.375,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.25,0.12,0,0,0,1.25,0.12,0,0.12,0,1.25,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.125,0.06,0,0,0,1.125,0.06,0,0.06,0,1.125,0,0,0,0,1,0,0,0,0), time = 1)
update_icon()
/obj/structure/cult/bloodstone/conceal()
return
/obj/structure/cult/bloodstone/takeDamage(var/damage)
if(veil_thickness == CULT_EPILOGUE)
return
var/backup = (health > (2*maxHealth/3)) + (health > (maxHealth/3))
health -= damage
if (health <= 0)
if (sound_destroyed)
playsound(src, sound_destroyed, 100, 1)
qdel(src)
else
if (backup > (health > (2*maxHealth/3)) + (health > (maxHealth/3)))
summon_backup()
update_icon()
/obj/structure/cult/bloodstone/proc/summon_backup()
var/list/possible_floors = list()
for (var/turf/simulated/floor/F in orange(1,get_turf(src)))
possible_floors.Add(F)
var/monsters_to_spawn = 1
if (health < (maxHealth / 2))
monsters_to_spawn++
for (var/i = 1 to monsters_to_spawn)
if (possible_floors.len <= 0)
break
var/turf/T = pick(possible_floors)
if (T)
possible_floors.Remove(T)
new /obj/effect/cult_ritual/backup_spawn(T)
/obj/structure/cult/bloodstone/dance_start()
while(!gcDestroyed && loc && anchor)
for (var/mob/M in contributors)
if (!iscultist(M) || get_dist(src,M) > 1 || (M.stat != CONSCIOUS))
if (M.client)
M.client.images -= progbar
contributors.Remove(M)
continue
if (contributors.len > 0)
timeleft -= 1 + round(contributors.len/3)//Additional dancers will complete the ritual faster
if (timeleft <= 0)
break
update_progbar()
dance_step()
sleep(3)
dance_step()
sleep(3)
dance_step()
sleep(6)
else
timeleft = min(timeleft+1,60)
sleep(10)
for (var/mob/M in contributors)
if (M.client)
M.client.images -= progbar
contributors.Remove(M)
anchor = FALSE
for (var/obj/structure/teleportwarp/TW in src.loc)
qdel(TW)
if (!gcDestroyed && loc)
new /obj/machinery/singularity/narsie/large(src.loc)
SSpersistence_map.setSavingFilth(FALSE)
return 1
/obj/structure/cult/bloodstone/ex_act(var/severity)
switch(severity)
if (1)
takeDamage(250)
if (2)
takeDamage(50)
if (3)
takeDamage(10)
*/
/obj/structure/cult/proc/safe_space()
for(var/turf/T in range(5,src))
var/dist = cheap_pythag(T.x - src.x, T.y - src.y)
if (dist <= 2.5)
T.ChangeTurf(/turf/simulated/floor/engine/cult)
T.turf_animation('icons/effects/effects.dmi',"cultfloor", 0, 0, MOB_LAYER-1, anim_plane = TURF_PLANE)
for (var/obj/structure/S in T)
if (!istype(S,/obj/structure/cult))
qdel(S)
for (var/obj/machinery/M in T)
qdel(M)
else if (dist <= 4.5)
if (istype(T,/turf/space))
T.ChangeTurf(/turf/simulated/floor/engine/cult)
T.turf_animation('icons/effects/effects.dmi',"cultfloor", 0, 0, MOB_LAYER-1, anim_plane = TURF_PLANE)
else
T.cultify()
else if (dist <= 5.5)
if (istype(T,/turf/space))
T.ChangeTurf(/turf/simulated/wall/cult)
T.turf_animation('icons/effects/effects.dmi',"cultwall", 0, 0, MOB_LAYER-1, anim_plane = TURF_PLANE)
else
T.cultify()
//inspired from LoZ:Oracle of Seasons
/obj/structure/cult/proc/dance_start()
while(timeleft > 0)
for (var/mob/M in contributors)
if (!iscultist(M) || get_dist(src,M) > 1 || M.incapacitated() || M.occult_muted())
if (M.client)
M.client.images -= progbar
contributors.Remove(M)
continue
if (contributors.len <= 0)
return 0
if(contributors.len < min_contributors)
sleep(10)
continue
timeleft -= 1 + round(contributors.len/2)//Additional dancers will complete the ritual faster
update_progbar()
dance_step()
sleep(3)
dance_step()
sleep(3)
dance_step()
sleep(6)
for (var/mob/M in contributors)
if (M.client)
M.client.images -= progbar
ritual_reward(M)
contributors.Remove(M)
return 1
/obj/structure/cult/proc/ritual_reward(var/mob/M)
return
/obj/structure/cult/proc/dance_step()
var/dance_move = pick("clock","counter","spin")
switch(dance_move)
if ("clock")
for (var/mob/M in contributors)
INVOKE_EVENT(M, /event/before_move)
switch (get_dir(src,M))
if (NORTHWEST,NORTH)
M.forceMove(get_step(M,EAST))
M.dir = EAST
if (NORTHEAST,EAST)
M.forceMove(get_step(M,SOUTH))
M.dir = SOUTH
if (SOUTHEAST,SOUTH)
M.forceMove(get_step(M,WEST))
M.dir = WEST
if (SOUTHWEST,WEST)
M.forceMove(get_step(M,NORTH))
M.dir = NORTH
INVOKE_EVENT(M, /event/after_move)
INVOKE_EVENT(M, /event/moved, "mover" = M)
if ("counter")
for (var/mob/M in contributors)
INVOKE_EVENT(M, /event/before_move)
switch (get_dir(src,M))
if (NORTHEAST,NORTH)
M.forceMove(get_step(M,WEST))
M.dir = WEST
if (SOUTHEAST,EAST)
M.forceMove(get_step(M,NORTH))
M.dir = NORTH
if (SOUTHWEST,SOUTH)
M.forceMove(get_step(M,EAST))
M.dir = EAST
if (NORTHWEST,WEST)
M.forceMove(get_step(M,SOUTH))
M.dir = SOUTH
INVOKE_EVENT(M, /event/after_move)
INVOKE_EVENT(M, /event/moved, "mover" = M)
if ("spin")
for (var/mob/M in contributors)
spawn()
M.dir = SOUTH
INVOKE_EVENT(M, /event/face)
sleep(0.75)
M.dir = EAST
INVOKE_EVENT(M, /event/face)
sleep(0.75)
M.dir = NORTH
INVOKE_EVENT(M, /event/face)
sleep(0.75)
M.dir = WEST
INVOKE_EVENT(M, /event/face)
sleep(0.75)
M.dir = SOUTH
INVOKE_EVENT(M, /event/face)
/obj/structure/cult/pylon
name = "pylon"
desc = "A floating crystal that hums with an unearthly energy."
icon_state = "pylon"
light_range = 5
light_color = LIGHT_COLOR_RED
health = 50
maxHealth = 50
sound_damaged = 'sound/effects/Glasshit.ogg'
sound_destroyed = 'sound/effects/stone_crumble.ogg'
plane = EFFECTS_PLANE
layer = BELOW_PROJECTILE_LAYER
var/broken = FALSE
/obj/structure/cult/pylon/attack_hand(var/mob/M)
attackpylon(M, 5)
/obj/structure/cult/pylon/attack_animal(var/mob/living/simple_animal/user)
if(istype(user, /mob/living/simple_animal/construct/builder))
if(broken)
repair(user)
return
attackpylon(user, user.melee_damage_upper)
/obj/structure/cult/pylon/attackby(var/obj/item/W, var/mob/user)
attackpylon(user, W.force)
/obj/structure/cult/pylon/proc/attackpylon(mob/user as mob, var/damage)
if(!broken)
if(prob(1+ damage * 5))
to_chat(user, "You hit the pylon, and its crystal breaks apart!")
for(var/mob/M in viewers(src))
if(M == user)
continue
M.show_message("[user.name] smashed the pylon!", 1, "You hear a tinkle of crystal shards.", 2)
playsound(src, 'sound/effects/Glassbr3.ogg', 75, 1)
broken = TRUE
setDensity(FALSE)
icon_state = "pylon-broken"
set_light(0)
kill_moody_light()
else
to_chat(user, "You hit the pylon!")
playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
else
playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
if(prob(damage * 2))
to_chat(user, "You pulverize what was left of the pylon!")
qdel(src)
else
to_chat(user, "You hit the pylon!")
/obj/structure/cult/pylon/proc/repair(var/mob/user)
if(broken)
to_chat(user, "You repair the pylon.")
broken = FALSE
setDensity(TRUE)
icon_state = "pylon"
sound_damaged = 'sound/effects/Glasshit.ogg'
set_light(5)
update_moody_light('icons/lighting/moody_lights.dmi', "pylon")
/obj/structure/cult/pylon/takeDamage()
..()
if(health <= 20 && !broken)
playsound(src, 'sound/effects/Glassbr3.ogg', 75, 1)
visible_message("<span class='warning'>\The [src] breaks apart!</span>")
icon_state = "pylon-broken"
sound_damaged = 'sound/effects/stone_hit.ogg'
set_light(0)
setDensity(FALSE)
broken = TRUE
kill_moody_light()
/obj/structure/cult/pylon/New()
..()
flick("[icon_state]-spawn", src)
update_moody_light('icons/lighting/moody_lights.dmi', "pylon-spawn")
spawn(12)
update_moody_light('icons/lighting/moody_lights.dmi', "pylon")