mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
[Cult 4] "NAR-SIE'S HOLIDAYS" , aka "The End of Cult 3.0" (#30672)
* day 1 * day 1.1 * day 2 * day 3 * day 4 * day 5 * day 5.1 * day 6 * day 6.1 * day 7 * day 7.1 * day 8 * day 9 * day 10 * day 11 * day 11.1 * 11.1.1 * day 12 * and on the 13th day, he looked upon his work, and was pleased with what he saw * 13.1 * day 14 * day 15 * day 16 * day 16.1 * fixing conflicts after rebasing post-Europa removal * day 17 * day 17.1 * day 18 * day 18.1 * day 19 * day 19.1 * day 20 * day 20.1 * day 21 * day 21.1
This commit is contained in:
@@ -111,7 +111,8 @@
|
||||
step(controlled,direction)
|
||||
controlled.dir = direction
|
||||
if (blade.loc != start)
|
||||
blade.blood = max(blade.blood-1,0)
|
||||
if (!blade.linked_cultist || (get_dist(get_turf(blade.linked_cultist),get_turf(controller)) > 5))
|
||||
blade.blood = max(blade.blood-1,0)
|
||||
move_delay = 1
|
||||
spawn(blade.movespeed)
|
||||
move_delay = 0
|
||||
|
||||
98
code/datums/body_archive.dm
Normal file
98
code/datums/body_archive.dm
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
/datum/body_archive // basically /datum/mind scans its mob when first created, allowing the original body to be re-created if needed
|
||||
var/mob_type
|
||||
var/datum/dna2/record/dna_records
|
||||
|
||||
/datum/body_archive/New(var/mob/source)
|
||||
if (!source)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
mob_type = source.type
|
||||
if (ishuman(source))
|
||||
var/mob/living/carbon/human/H = source
|
||||
var/datum/organ/internal/brain/Brain = H.internal_organs_by_name["brain"]
|
||||
|
||||
var/datum/dna2/record/R = new /datum/dna2/record()
|
||||
if(!isnull(Brain.owner_dna) && Brain.owner_dna != H.dna)
|
||||
R.dna = Brain.owner_dna.Clone()
|
||||
else
|
||||
R.dna = H.dna.Clone()
|
||||
R.ckey = H.ckey
|
||||
R.id= copytext(md5(R.dna.real_name), 2, 6)
|
||||
R.name=R.dna.real_name
|
||||
R.types=DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE
|
||||
R.languages = H.languages.Copy()
|
||||
R.attack_log = H.attack_log.Copy()
|
||||
R.default_language = H.default_language
|
||||
R.times_cloned = H.times_cloned
|
||||
R.talkcount = H.talkcount
|
||||
|
||||
dna_records = R
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/mob/proc/reset_body(var/datum/body_archive/archive)
|
||||
if (!archive)
|
||||
if (mind && mind.body_archive)
|
||||
archive = mind.body_archive
|
||||
else
|
||||
return
|
||||
|
||||
var/mob/new_mob
|
||||
// can't just do a /mob/living/carbon/human/reset_body() since the mob might have changed to a non-human since then
|
||||
if (archive.mob_type in typesof(/mob/living/carbon/human))
|
||||
var/datum/dna2/record/R = archive.dna_records
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(loc, R.dna.species, delay_ready_dna = TRUE)
|
||||
H.times_cloned = 0
|
||||
H.talkcount = R.talkcount
|
||||
if(isplasmaman(H))
|
||||
H.fire_sprite = "Plasmaman"
|
||||
H.dna = R.dna.Clone()
|
||||
H.dna.flavor_text = R.dna.flavor_text
|
||||
H.dna.species = R.dna.species
|
||||
if(H.dna.species != "Human")
|
||||
H.set_species(H.dna.species, TRUE)
|
||||
H.check_mutations = TRUE
|
||||
H.updatehealth()
|
||||
has_been_shade -= mind
|
||||
mind.transfer_to(H)
|
||||
H.ckey = R.ckey
|
||||
if (H.mind.miming)
|
||||
H.add_spell(new /spell/aoe_turf/conjure/forcewall/mime, "grey_spell_ready")
|
||||
if (H.mind.miming == MIMING_OUT_OF_CHOICE)
|
||||
H.add_spell(new /spell/targeted/oathbreak/)
|
||||
if (isvampire(H))
|
||||
var/datum/role/vampire/V = isvampire(H)
|
||||
V.check_vampire_upgrade()
|
||||
V.update_vamp_hud()
|
||||
H.UpdateAppearance()
|
||||
H.set_species(R.dna.species)
|
||||
H.dna.mutantrace = R.dna.mutantrace
|
||||
H.update_mutantrace()
|
||||
for(var/datum/language/L in R.languages)
|
||||
H.add_language(L.name)
|
||||
if (L == R.default_language)
|
||||
H.default_language = R.default_language
|
||||
H.attack_log = R.attack_log
|
||||
H.real_name = H.dna.real_name
|
||||
H.name = H.real_name
|
||||
H.flavor_text = H.dna.flavor_text
|
||||
if(H.mind)
|
||||
H.mind.suiciding = FALSE
|
||||
H.update_name()
|
||||
if (H.client)
|
||||
H.client.eye = H.client.mob
|
||||
H.client.perspective = MOB_PERSPECTIVE
|
||||
H.updatehealth()
|
||||
domutcheck(H)
|
||||
new_mob = H
|
||||
|
||||
else
|
||||
|
||||
new_mob = new archive.mob_type(loc)
|
||||
mind.transfer_to(new_mob)
|
||||
|
||||
drop_all()
|
||||
qdel(src)
|
||||
return new_mob
|
||||
@@ -29,6 +29,7 @@
|
||||
var/stat_allowed = CONSCIOUS
|
||||
var/hands_needed = 0//how many hands do you need to perform the emote
|
||||
var/static/list/emote_list = list()
|
||||
var/replace_pronouns = TRUE
|
||||
|
||||
/datum/emote/New()
|
||||
if(key_third_person)
|
||||
@@ -99,7 +100,7 @@
|
||||
if(findtext(message, "%s"))
|
||||
message = replacetext(message, "%s", "")
|
||||
return message
|
||||
else
|
||||
else if (replace_pronouns)
|
||||
switch(H.gender)
|
||||
if(MALE)
|
||||
if(findtext(message, "their"))
|
||||
|
||||
@@ -359,14 +359,8 @@
|
||||
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/leader = 1
|
||||
for(var/mob/M in assigned)
|
||||
var/datum/role/cultist/newCultist
|
||||
if (leader) // First of the gang
|
||||
newCultist = new /datum/role/cultist/chief
|
||||
leader = 0
|
||||
else
|
||||
newCultist = new
|
||||
var/datum/role/cultist/newCultist = new
|
||||
newCultist.AssignToRole(M.mind,1)
|
||||
cult.HandleRecruitedRole(newCultist)
|
||||
newCultist.Greet(GREET_ROUNDSTART)
|
||||
|
||||
@@ -374,7 +374,7 @@
|
||||
* /raisestructure
|
||||
* /communication
|
||||
* /summontome
|
||||
* /conjuretalisman
|
||||
* /paraphernalia
|
||||
* /conversion
|
||||
* /stun
|
||||
* /blind
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -87,16 +87,10 @@
|
||||
takeDamage(Proj.damage)
|
||||
return ..()
|
||||
|
||||
/obj/structure/cult/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
if (istype(W, /obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/G = W
|
||||
if(iscarbon(G.affecting))
|
||||
MouseDropTo(G.affecting,user)
|
||||
qdel(W)
|
||||
else if (istype(W))
|
||||
/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>")
|
||||
MouseDropTo(W,user)
|
||||
else
|
||||
user.delayNextAttack(8)
|
||||
user.do_attack_animation(src, W)
|
||||
@@ -206,6 +200,7 @@
|
||||
var/lock_type = /datum/locking_category/buckle/bed
|
||||
var/altar_task = ALTARTASK_NONE
|
||||
var/gem_delay = 300
|
||||
var/narsie_message_cooldown = 0
|
||||
|
||||
var/list/watching_mobs = list()
|
||||
var/list/watcher_maps = list()
|
||||
@@ -248,7 +243,7 @@
|
||||
|
||||
..()
|
||||
|
||||
/obj/structure/cult/altar/attackby(var/obj/item/I, var/mob/user)
|
||||
/obj/structure/cult/altar/attackby(var/obj/item/I, var/mob/user, params)
|
||||
if (altar_task)
|
||||
return ..()
|
||||
if(istype(I,/obj/item/weapon/melee/soulblade) || (istype(I,/obj/item/weapon/melee/cultblade) && !istype(I,/obj/item/weapon/melee/cultblade/nocult)))
|
||||
@@ -289,6 +284,9 @@
|
||||
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))
|
||||
@@ -300,6 +298,10 @@
|
||||
qdel(G)
|
||||
to_chat(user, "<span class='warning'>You move \the [C] on top of \the [src]</span>")
|
||||
return 1
|
||||
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()
|
||||
@@ -387,6 +389,7 @@
|
||||
|
||||
O.forceMove(loc)
|
||||
to_chat(user, "<span class='warning'>You move \the [O] on top of \the [src]</span>")
|
||||
return 1
|
||||
|
||||
|
||||
/obj/structure/cult/altar/proc/checkPosition()
|
||||
@@ -437,19 +440,36 @@
|
||||
stopWatching(user)
|
||||
return
|
||||
if (altar_task)
|
||||
if (altar_task == ALTARTASK_SACRIFICE)
|
||||
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
|
||||
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)
|
||||
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)
|
||||
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, "<span class='warning'>You remove \the [blade] from \the [src]</span>")
|
||||
blade = null
|
||||
playsound(loc, 'sound/weapons/blade1.ogg', 50, 1)
|
||||
update_icon()
|
||||
// TODO UPHEAVAL PART 2, might bring back sacrifices later, for now you can still stab people on altars
|
||||
/*
|
||||
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."),
|
||||
@@ -472,44 +492,50 @@
|
||||
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
|
||||
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
|
||||
if (cult)
|
||||
var/datum/objective/bloodcult_sacrifice/O = locate() in cult.objective_holder.objectives
|
||||
if (O && is_locking(lock_type))
|
||||
var/mob/victim = get_locked(lock_type)[1]
|
||||
if (victim == O.sacrifice_target || (victim.mind && victim.mind == O.sacrifice_mind))
|
||||
altar_task = ALTARTASK_SACRIFICE
|
||||
timeleft = 30
|
||||
timetotal = timeleft
|
||||
update_icon()
|
||||
contributors.Add(user)
|
||||
update_progbar()
|
||||
if (user.client)
|
||||
user.client.images |= progbar
|
||||
var/image/I = image('icons/obj/cult.dmi',"build")
|
||||
I.pixel_y = 8
|
||||
src.overlays += I
|
||||
if (!user.checkTattoo(TATTOO_SILENT))
|
||||
if (prob(5))
|
||||
user.say("Let me show you the dance of my people!","C")
|
||||
if (is_locking(lock_type))
|
||||
altar_task = ALTARTASK_SACRIFICE
|
||||
timeleft = 30
|
||||
timetotal = timeleft
|
||||
update_icon()
|
||||
contributors.Add(user)
|
||||
update_progbar()
|
||||
if (user.client)
|
||||
user.client.images |= progbar
|
||||
var/image/I = image('icons/obj/cult.dmi',"build")
|
||||
I.pixel_y = 8
|
||||
src.overlays += I
|
||||
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
|
||||
/*
|
||||
for(var/mob/M in range(src,40))
|
||||
if (M.z == z && M.client)
|
||||
if (get_dist(M,src)<=20)
|
||||
M.playsound_local(src, get_sfx("explosion"), 50, 1)
|
||||
shake_camera(M, 2, 1)
|
||||
else
|
||||
user.say("Barhah hra zar'garis!","C")
|
||||
if (user.client)
|
||||
user.client.images |= progbar
|
||||
safe_space()
|
||||
for(var/mob/M in range(src,40))
|
||||
if (M.z == z && M.client)
|
||||
if (get_dist(M,src)<=20)
|
||||
M.playsound_local(src, get_sfx("explosion"), 50, 1)
|
||||
shake_camera(M, 2, 1)
|
||||
else
|
||||
M.playsound_local(src, 'sound/effects/explosionfar.ogg', 50, 1)
|
||||
shake_camera(M, 1, 1)
|
||||
spawn()
|
||||
dance_start()
|
||||
else
|
||||
to_chat(user, "<span class='sinister'>This isn't the One.</span>")
|
||||
|
||||
M.playsound_local(src, 'sound/effects/explosionfar.ogg', 50, 1)
|
||||
shake_camera(M, 1, 1)
|
||||
*/
|
||||
spawn()
|
||||
dance_start()
|
||||
*/
|
||||
else if (blade)
|
||||
blade.forceMove(loc)
|
||||
blade.attack_hand(user)
|
||||
@@ -522,7 +548,7 @@
|
||||
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", "Obtain guidance from Nar-Sie to help you complete your objectives."),
|
||||
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")
|
||||
@@ -537,6 +563,14 @@
|
||||
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 = ""
|
||||
@@ -560,7 +594,7 @@
|
||||
extra = " - <span style='color:#FFFF00'>CRITICAL</span>"
|
||||
else if (H.isDead())
|
||||
extra = " - <span style='color:#FF0000'>DEAD</span>"
|
||||
dat += "<li><b>[M.name]</b></li> - [origin_text][extra]"
|
||||
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
|
||||
@@ -574,7 +608,7 @@
|
||||
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=500x300")
|
||||
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)
|
||||
@@ -598,47 +632,19 @@
|
||||
user.client.images |= watcher_maps["\ref[user]"]
|
||||
user.register_event(/event/face, src, /obj/structure/cult/altar/proc/checkPosition)
|
||||
if ("Commune with Nar-Sie")
|
||||
switch(veil_thickness)
|
||||
if (CULT_MENDED)
|
||||
to_chat(user, "...nothing but silence...")
|
||||
if (CULT_PROLOGUE)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>How interesting...</span></span>")
|
||||
if (CULT_ACT_I)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>The conversion rune is <span class='danger'>Join Blood Self</span>, but you now have many new runes at your disposal to help you in your task, therefore I recommend you first summon an Arcane Tome to easily scribe them. The rune that conjures a tome is <span class='danger'>See Blood Hell</span>.</span></span>")
|
||||
if (CULT_ACT_II)
|
||||
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
|
||||
if (cult)
|
||||
var/datum/objective/bloodcult_sacrifice/O = locate() in cult.objective_holder.objectives
|
||||
if (O && !O.IsFulfilled())
|
||||
if (!O.sacrifice_target || !O.sacrifice_target.loc)//if there's no target or its body was destroyed, immediate reroll
|
||||
replace_target()
|
||||
return
|
||||
else
|
||||
var/turf/T = get_turf(O.sacrifice_target)
|
||||
var/datum/shuttle/S = is_on_shuttle(T)
|
||||
if ((T.z == CENTCOMM_Z) && (emergency_shuttle.shuttle == S || emergency_shuttle.escape_pods.Find(S)))
|
||||
to_chat(user,"<b>\The [O.sacrifice_target] has fled the station along with the rest of the crew. Unless we can bring them back in time with a Path rune or sacrifice him where he stands, it's over.</b>")
|
||||
return
|
||||
else if (T.z != STATION_Z)//if the target fled the station, offer to reroll the target. May or not add penalties for that later.
|
||||
var/choice = alert(user,"The target has fled the station, do you wish for another sacrifice target to be selected?","[name]","Yes","No")
|
||||
if (choice == "Yes")
|
||||
replace_target(user)
|
||||
return
|
||||
else
|
||||
to_chat(user,"<b>\The [O.sacrifice_target] is in [get_area_name(O, 1)].</b>")
|
||||
to_chat(user, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>To perform the sacrifice, you'll have to forge a cult blade first. It doesn't matter if the target is alive of not, lay their body down on the altar and plant the blade on their stomach. Next, touch the altar to perform the next step of the ritual. The more of you, the quicker it will be done.</span></span>")
|
||||
if (CULT_ACT_III)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>The crew is now aware of our presence, prepare to draw blood. Your priority is to spill as much blood as you can all over the station, bloody trails left by foot steps count toward this goal. How you obtain the blood, I leave to your ambition, but remember that if the crew destroys every blood stones, you will be doomed.</span></span>")
|
||||
if (CULT_ACT_IV)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>One of the blood stones has become my anchor in this plane, you can touch any other stone to locate it. Touch the anchor to perform the Tear Reality ritual before the crew breaks it.</span></span>")
|
||||
if (CULT_EPILOGUE)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>Remarkable work, [user.real_name], I greatly enjoyed observing this game. Your work is over now, but I may have more in store for you in the future. In the meanwhile, bask in your victory.</span></span>")
|
||||
/* TODO: I'll finish that up someday
|
||||
var/dat = {"<body style="color:#FFFFFF" bgcolor="#110000"><ul>"}
|
||||
dat += {"</ul></body>"}
|
||||
user << browse("<TITLE>Nar-Sie's Tips</TITLE>[dat]", "window=narsietips;size=500x300")
|
||||
onclose(user, "narsietips")
|
||||
*/
|
||||
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()
|
||||
@@ -655,26 +661,6 @@
|
||||
var/obj/item/soulstone/gem/gem = new (loc)
|
||||
gem.pixel_y = 4
|
||||
|
||||
/obj/structure/cult/altar/proc/replace_target(var/mob/user)
|
||||
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
|
||||
if (cult)
|
||||
var/datum/objective/bloodcult_sacrifice/O = locate() in cult.objective_holder.objectives
|
||||
if (O && !O.IsFulfilled())
|
||||
if (O.replace_target(user))
|
||||
for(var/datum/role/cultist/C in cult.members)
|
||||
var/mob/M = C.antag.current
|
||||
if (M && iscultist(M))
|
||||
to_chat(M,"<b>A new target has been assigned. [O.explanation_text]</b>")
|
||||
if (M == O.sacrifice_target)
|
||||
to_chat(M,"<b>There is no greater honor than purposefuly relinquishing your body for the coming of Nar-Sie.</b>")
|
||||
to_chat(M,"<b>Should the target's body be annihilated, or should they flee the station, you may commune with Nar-Sie at an altar to have him designate a new target.</b>")
|
||||
else
|
||||
for(var/datum/role/cultist/C in cult.members)
|
||||
var/mob/M = C.antag.current
|
||||
if (M && iscultist(M))
|
||||
to_chat(M,"<b>There are no elligible targets aboard the station, how did you guys even manage that one?</b>")//if there's literally no humans aboard the station
|
||||
to_chat(M,"<b>There needs to be humans aboard the station, cultist or not, for a target to be selected.</b>")
|
||||
|
||||
/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]
|
||||
@@ -749,7 +735,6 @@
|
||||
var/datum/role/cultist/newCultist = cult.HandleRecruitedMind(shadeMob.mind, TRUE)
|
||||
newCultist.Greet(GREET_SOULBLADE)
|
||||
newCultist.conversion.Add("altar")
|
||||
cult_risk()//risk of exposing the cult early if too many soul blades created
|
||||
|
||||
|
||||
/obj/structure/cult/altar/dance_start()//This is executed at the end of the sacrifice ritual
|
||||
@@ -770,6 +755,14 @@
|
||||
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
|
||||
@@ -790,17 +783,6 @@
|
||||
playsound(src, get_sfx("soulstone"), 50,1)
|
||||
else
|
||||
M.gib()
|
||||
var/turf/T = loc
|
||||
|
||||
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
|
||||
if (cult)
|
||||
if (emergency_shuttle.direction == 2) // Going to centcomm
|
||||
cult.minor_victory()
|
||||
else
|
||||
cult.stage(CULT_ACT_III,T)
|
||||
else
|
||||
message_admins("Blood Cult: A sacrifice was completed...but we cannot find the cult faction...")//failsafe in case of admin varedit fuckery
|
||||
qdel(src)
|
||||
|
||||
#undef ALTARTASK_NONE
|
||||
#undef ALTARTASK_GEM
|
||||
@@ -831,9 +813,10 @@ var/list/cult_spires = list()
|
||||
|
||||
/obj/structure/cult/spire/New()
|
||||
..()
|
||||
cult_spires.Add(src)
|
||||
cult_spires += src
|
||||
set_light(1)
|
||||
stage = clamp(veil_thickness, 1, 3)
|
||||
//TODO (UPHEAVAL PART 2) appearance changes with cult score
|
||||
stage = 1
|
||||
flick("spire[stage]-spawn",src)
|
||||
spawn(10)
|
||||
update_stage()
|
||||
@@ -847,12 +830,12 @@ var/list/cult_spires = list()
|
||||
holomap_markers[HOLOMAP_MARKER_CULT_SPIRE+"_\ref[src]"] = holomarker
|
||||
|
||||
/obj/structure/cult/spire/Destroy()
|
||||
cult_spires.Remove(src)
|
||||
cult_spires -= src
|
||||
holomap_markers -= HOLOMAP_MARKER_CULT_SPIRE+"_\ref[src]"
|
||||
..()
|
||||
|
||||
/obj/structure/cult/spire/proc/upgrade()
|
||||
var/new_stage = clamp(veil_thickness, 1, 3)
|
||||
var/new_stage = clamp(stage, 1, 3)
|
||||
if (new_stage>stage)
|
||||
stage = new_stage
|
||||
alpha = 255
|
||||
@@ -885,7 +868,7 @@ var/list/cult_spires = list()
|
||||
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 = relative_plane(ABOVE_LIGHTING_PLANE)
|
||||
I_spire.plane = ABOVE_LIGHTING_PLANE
|
||||
I_spire.layer = NARSIE_GLOW
|
||||
overlays += I_base
|
||||
overlays += I_spire
|
||||
@@ -916,6 +899,9 @@ var/list/cult_spires = list()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
// For now spires work as cult telecomms relay. Might give them another role later, maybe soul gem production instead of altars
|
||||
|
||||
/*
|
||||
if (!ishuman(user))
|
||||
to_chat(user,"<span class='warning'>Only humans can bear the arcane markings granted by this [name].</span>")
|
||||
return
|
||||
@@ -983,6 +969,7 @@ var/list/cult_spires = list()
|
||||
if (available_tattoos.len > 0)
|
||||
cultist_act(user)
|
||||
break
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //Spawned from the Raise Structure rune. Available from Act II
|
||||
@@ -1061,7 +1048,7 @@ var/list/cult_spires = list()
|
||||
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 = relative_plane(ABOVE_LIGHTING_PLANE)
|
||||
I_lave.plane = ABOVE_LIGHTING_PLANE
|
||||
I_lave.layer = NARSIE_GLOW
|
||||
I_lave.blend_mode = BLEND_ADD
|
||||
overlays += I_base
|
||||
@@ -1112,11 +1099,11 @@ var/list/cult_spires = list()
|
||||
forger = null
|
||||
template = null
|
||||
else
|
||||
anim(target = loc, a_icon = 'icons/obj/cult_64x64.dmi', flick_anim = "forge-work", lay = NARSIE_GLOW, plane = ABOVE_LIGHTING_PLANE)
|
||||
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 = relative_plane(ABOVE_LIGHTING_PLANE)
|
||||
I.plane = ABOVE_LIGHTING_PLANE
|
||||
I.layer = NARSIE_GLOW
|
||||
I.blend_mode = BLEND_ADD
|
||||
I.alpha = (timeleft/timetotal)*255
|
||||
@@ -1161,7 +1148,7 @@ var/list/cult_spires = list()
|
||||
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 = relative_plane(ABOVE_LIGHTING_PLANE)
|
||||
I_lave.plane = ABOVE_LIGHTING_PLANE
|
||||
I_lave.layer = NARSIE_GLOW
|
||||
I_lave.blend_mode = BLEND_ADD
|
||||
overlays += I_base
|
||||
@@ -1172,6 +1159,10 @@ var/list/cult_spires = list()
|
||||
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
|
||||
@@ -1262,7 +1253,7 @@ var/list/cult_spires = list()
|
||||
..()
|
||||
icon_state = i_forge
|
||||
var/image/I = image('icons/obj/cult_64x64.dmi',"[i_forge]-mask")
|
||||
I.plane = relative_plane(ABOVE_LIGHTING_PLANE)
|
||||
I.plane = ABOVE_LIGHTING_PLANE
|
||||
I.layer = NARSIE_GLOW
|
||||
I.blend_mode = BLEND_ADD
|
||||
overlays += I
|
||||
@@ -1325,6 +1316,7 @@ var/list/cult_spires = list()
|
||||
if (3)
|
||||
takeDamage(20)
|
||||
|
||||
/*
|
||||
var/list/bloodstone_list = list()
|
||||
|
||||
/obj/structure/cult/bloodstone
|
||||
@@ -1511,10 +1503,6 @@ var/list/bloodstone_list = list()
|
||||
|
||||
watching_mobs -= user
|
||||
|
||||
/datum/station_holomap/cult/initialize_holomap(var/turf/T, var/isAI=null, var/mob/user=null, var/cursor_icon = "bloodstone-here")
|
||||
station_map = image(extraMiniMaps[HOLOMAP_EXTRA_CULTMAP])
|
||||
cursor = image('icons/holomap_markers.dmi', cursor_icon)
|
||||
|
||||
/obj/structure/cult/bloodstone/update_icon()
|
||||
icon_state = "bloodstone-0"
|
||||
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
|
||||
@@ -1624,6 +1612,7 @@ var/list/bloodstone_list = list()
|
||||
takeDamage(50)
|
||||
if (3)
|
||||
takeDamage(10)
|
||||
*/
|
||||
|
||||
/obj/structure/cult/proc/safe_space()
|
||||
for(var/turf/T in range(5,src))
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
var/runesets_initialized = 0
|
||||
var/list/datum/runeset/global_runesets = list()
|
||||
|
||||
/datum/runeset //Abstract base class
|
||||
var/identifier //Key mapped to this runeset in runesets. Also used to sync runewords and runesets
|
||||
var/list/rune_list = list() //List of all runes, used for various purposes.
|
||||
var/list/words = list()
|
||||
var/list/words_english = list()
|
||||
var/list/words_rune = list()
|
||||
var/list/words_icons = list()
|
||||
|
||||
/proc/initialize_runesets()
|
||||
if(runesets_initialized)
|
||||
return
|
||||
for(var/runeset_cast in subtypesof(/datum/runeset))
|
||||
var/datum/runeset/rune_set = new runeset_cast()
|
||||
for(var/wordset_cast in subtypesof(/datum/runeword))
|
||||
var/datum/runeword/word_set = new wordset_cast()
|
||||
if(rune_set.identifier == word_set.identifier)
|
||||
global_runesets[rune_set.identifier] = rune_set
|
||||
for(var/word_info in subtypesof(word_set))
|
||||
var/datum/runeword/new_word = new word_info()
|
||||
if(new_word.english)
|
||||
rune_set.words[new_word.english] = new_word
|
||||
global_runesets[rune_set.identifier] = rune_set
|
||||
runesets_initialized = 1
|
||||
|
||||
/datum/runeset/blood_cult //Real cultists
|
||||
identifier = "blood_cult"
|
||||
//Hard-coded lists, used by various things for ease of access. Should probably code the initialize_runesets to automatically make these, but whatever.
|
||||
words_english = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide")
|
||||
words_rune = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri")
|
||||
words_icons = list("rune-1","rune-2","rune-4","rune-8","rune-16","rune-32","rune-64","rune-128", "rune-256", "rune-512")
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/runeword
|
||||
var/identifier
|
||||
var/english
|
||||
var/rune
|
||||
var/icon = 'icons/effects/uristrunes.dmi'
|
||||
var/icon_state = ""
|
||||
|
||||
/datum/runeword/blood_cult
|
||||
identifier = "blood_cult"
|
||||
icon = 'icons/effects/uristrunes.dmi'
|
||||
icon_state = ""
|
||||
var/color //Used by path rune markers
|
||||
|
||||
/datum/runeword/blood_cult/travel
|
||||
english = "travel"
|
||||
rune = "ire"
|
||||
icon_state = "rune-1"
|
||||
color = "yellow"
|
||||
|
||||
/datum/runeword/blood_cult/blood
|
||||
english = "blood"
|
||||
rune = "ego"
|
||||
icon_state = "rune-2"
|
||||
color = "maroon"
|
||||
|
||||
/datum/runeword/blood_cult/join
|
||||
english = "join"
|
||||
rune = "nahlizet"
|
||||
icon_state = "rune-4"
|
||||
color = "green"
|
||||
|
||||
/datum/runeword/blood_cult/hell
|
||||
english = "hell"
|
||||
rune = "certum"
|
||||
icon_state = "rune-8"
|
||||
color = "red"
|
||||
|
||||
/datum/runeword/blood_cult/destroy
|
||||
english = "destroy"
|
||||
rune = "veri"
|
||||
icon_state = "rune-16"
|
||||
color = "purple"
|
||||
|
||||
/datum/runeword/blood_cult/technology
|
||||
english = "technology"
|
||||
rune = "jatkaa"
|
||||
icon_state = "rune-32"
|
||||
color = "blue"
|
||||
|
||||
/datum/runeword/blood_cult/self
|
||||
english = "self"
|
||||
rune = "mgar"
|
||||
icon_state = "rune-64"
|
||||
color = null
|
||||
|
||||
/datum/runeword/blood_cult/see
|
||||
english = "see"
|
||||
rune = "balaq"
|
||||
icon_state = "rune-128"
|
||||
color = "fuchsia"
|
||||
|
||||
/datum/runeword/blood_cult/other
|
||||
english = "other"
|
||||
rune = "karazet"
|
||||
icon_state = "rune-256"
|
||||
color = "teal"
|
||||
|
||||
/datum/runeword/blood_cult/hide
|
||||
english = "hide"
|
||||
rune = "geeri"
|
||||
icon_state = "rune-512"
|
||||
color = "silver"
|
||||
@@ -1,4 +1,28 @@
|
||||
|
||||
///////////////////////////////////////VISUAL EFFECTS//////////////////////////////////////////////
|
||||
|
||||
// Based on holopad rays. Causes a Shadow to move from T to C
|
||||
// "sprite" var can be replaced to use another icon_state from icons/effects/96x96.dmi
|
||||
/proc/shadow(var/atom/C,var/turf/T,var/sprite="rune_blind")
|
||||
var/disty = C.y - T.y
|
||||
var/distx = C.x - T.x
|
||||
var/newangle
|
||||
if(!disty)
|
||||
if(distx >= 0)
|
||||
newangle = 90
|
||||
else
|
||||
newangle = 270
|
||||
else
|
||||
newangle = arctan(distx/disty)
|
||||
if(disty < 0)
|
||||
newangle += 180
|
||||
else if(distx < 0)
|
||||
newangle += 360
|
||||
var/matrix/M1 = matrix()
|
||||
var/matrix/M2 = turn(M1.Scale(1,sqrt(distx*distx+disty*disty)),newangle)
|
||||
return anim(target = C, a_icon = 'icons/effects/96x96.dmi', flick_anim = sprite, lay = NARSIE_GLOW, offX = -WORLD_ICON_SIZE, offY = -WORLD_ICON_SIZE, plane = ABOVE_LIGHTING_PLANE, trans = M2)
|
||||
|
||||
|
||||
///////////////////////////////////////CULT RITUALS////////////////////////////////////////////////
|
||||
//Effects spawned by rune spells
|
||||
|
||||
@@ -80,6 +104,9 @@
|
||||
/obj/effect/afterimage/red
|
||||
image_color = "red"
|
||||
|
||||
/obj/effect/afterimage/black
|
||||
image_color = "black"
|
||||
|
||||
/obj/effect/afterimage/New(var/turf/loc, var/atom/model, var/fadout = 5)
|
||||
..()
|
||||
if(model)
|
||||
|
||||
@@ -1,40 +1,28 @@
|
||||
var/list/failure_lines_by_dept = list(
|
||||
COMMAND_POSITIONS = list(
|
||||
"You have failed to lead them. You would have failed to follow." = 3,
|
||||
"And so ends your 'authority.'" = 3,
|
||||
"This is what passes as command these days." = 3,
|
||||
),
|
||||
ENGINEERING_POSITIONS = list(
|
||||
"Our craft is more complex than your pathetic tinkering." = 3,
|
||||
"These machines were beyond your skill anyway." = 3,
|
||||
),
|
||||
MEDICAL_POSITIONS = list(
|
||||
"Your refusal helps no one. The blood will still flow." = 3,
|
||||
"There is no cure for this." = 3,
|
||||
"Nothing can heal the veil." = 3,
|
||||
),
|
||||
SCIENCE_POSITIONS = list(
|
||||
"Your closed mind dishonours you." = 3,
|
||||
"Our secrets were beyond your understanding." = 3,
|
||||
"My science was not for weaklings such as you." = 3,
|
||||
),
|
||||
CIVILIAN_POSITIONS = list(
|
||||
"A little job in life, and a forgotten death." = 3,
|
||||
"This refusal is but a footnote on my story." = 3,
|
||||
"You refused the only opportunity you had to make a difference." = 3,
|
||||
),
|
||||
CARGO_POSITION = list(
|
||||
"I care little for the hoarders of your kind." = 3,
|
||||
"As expected for a glorified crate handler." = 3,
|
||||
),
|
||||
SECURITY_POSITION = list(
|
||||
"You already failed." = 3,
|
||||
"This refusal does not erase your failure." = 3,
|
||||
"Your stubbornness amuses me. I already won." = 3,
|
||||
"I could have freed you." = 3,
|
||||
"You will always remain on the weaker side." = 3,
|
||||
),
|
||||
)
|
||||
|
||||
/*
|
||||
|
||||
Disabling those for now.
|
||||
On one hand I'd rather keep Nar-Sie talking as an admin-only thing
|
||||
On the other hand those don't quite portray the love of blood and chaos that Nar-Sie is associated with, aside from one or two lines those are very generic.
|
||||
|
||||
As for Conversion Failure lines, they're pretty much deprecated since conversion failures no longer kill their victims
|
||||
Also since we might want to try converting them again later no need for Nar-Sie to be this petty, that's not a good image
|
||||
|
||||
|
||||
/* -- Flavour text for refusing/accepting conversion.
|
||||
-- Possible context (static) :
|
||||
=> Dept (weighted 3)
|
||||
=> Specific job (weighted 5)
|
||||
=> Race (weighted 3)
|
||||
=> Specific special role (weighted 5)
|
||||
-- Possible context (dynamic) :
|
||||
=> The guy that converted you is from the same dept (weighted 3)
|
||||
=> Your boss is in the cult (CMO for medbay, ...)
|
||||
=> Your underlings are in the cult
|
||||
=> Your colleagues are in the cult
|
||||
=> Cult has a few/a lot of alive members
|
||||
*/
|
||||
|
||||
|
||||
var/list/acceptance_lines_by_dept = list(
|
||||
COMMAND_POSITIONS = list(
|
||||
@@ -82,18 +70,6 @@ var/list/acceptance_lines_by_dept = list(
|
||||
),
|
||||
)
|
||||
|
||||
var/list/failure_lines_by_specific_job = list(
|
||||
"Paramedic" = list(
|
||||
"You will not save anyone from where I sent you." = 5,
|
||||
),
|
||||
"Trader" = list(
|
||||
"I offered you a home, and you refused." = 5,
|
||||
),
|
||||
"Captain" = list(
|
||||
"Do you feel in charge?" = 5,
|
||||
),
|
||||
)
|
||||
|
||||
var/list/acceptance_lines_by_specific_job = list(
|
||||
"Trader" = list(
|
||||
"And here ends your wandering." = 5,
|
||||
@@ -101,12 +77,6 @@ var/list/acceptance_lines_by_specific_job = list(
|
||||
),
|
||||
)
|
||||
|
||||
var/list/failure_lines_by_specific_race = list(
|
||||
/datum/species/plasmaman = list(
|
||||
"Your loyalty to the company that twisted you into the living dead is amusing." = 3,
|
||||
)
|
||||
)
|
||||
|
||||
var/list/acceptance_lines_by_specific_race = list(
|
||||
/datum/species/plasmaman = list(
|
||||
"The pain ends now." = 3,
|
||||
@@ -169,12 +139,6 @@ var/list/acceptance_lines_by_specific_role = list(
|
||||
|
||||
// Context lines
|
||||
|
||||
var/list/failure_lines_few_cultists = list(
|
||||
"With or without you, my faithful shall triumph." = 3,
|
||||
"Do you truly think you won?" = 3,
|
||||
"I have no need of a coward in times like this." = 3,
|
||||
)
|
||||
|
||||
var/list/acceptance_lines_few_cultists = list(
|
||||
"Be the hand I need in these times." = 3,
|
||||
"You have been chosen." = 3,
|
||||
@@ -186,25 +150,6 @@ var/list/acceptance_lines_numerous_cultists = list(
|
||||
"Nothing will resist our might." = 3,
|
||||
)
|
||||
|
||||
var/list/failure_lines_numerous_cultists = list(
|
||||
"Your refusal changes nothing." = 3,
|
||||
"You will get to see this station fail from the first row." = 3,
|
||||
)
|
||||
|
||||
var/list/acceptance_lines_thin_veil = list(
|
||||
"Soon you will see the fruits of our efforts." = 3,
|
||||
)
|
||||
|
||||
var/list/failure_lines_thin_veil = list(
|
||||
"You chose to witness the end, rather than act." = 5,
|
||||
"Can't you see how pointless it is to resist at this point?" = 5,
|
||||
)
|
||||
|
||||
#define failure_lines_same_dept list( \
|
||||
"[converter.gender == MALE ? "He" : "She"] tried to save you." = 5, \
|
||||
"You betrayed your friend." = 5, \
|
||||
"Your arrogance must have disappointed your friend." = 5, \
|
||||
)
|
||||
|
||||
#define acceptance_lines_same_dept list( \
|
||||
"[converter.gender == MALE ? "He" : "She"] judged you well." = 5, \
|
||||
@@ -213,21 +158,6 @@ var/list/failure_lines_thin_veil = list(
|
||||
)
|
||||
|
||||
|
||||
/* -- Flavour text for refusing/accepting conversion.
|
||||
-- Possible context (static) :
|
||||
=> Dept (weighted 3)
|
||||
=> Specific job (weighted 5)
|
||||
=> Race (weighted 3)
|
||||
=> Specific special role (weighted 5)
|
||||
-- Possible context (dynamic) :
|
||||
=> The guy that converted you is from the same dept (weighted 3)
|
||||
=> Your boss is in the cult (CMO for medbay, ...)
|
||||
=> Your underlings are in the cult
|
||||
=> Your colleagues are in the cult
|
||||
=> Cult is near the end (Act III or higher)
|
||||
=> Cult has a few/a lot of alive members
|
||||
*/
|
||||
|
||||
var/list/all_depts_list = list(
|
||||
COMMAND_POSITIONS,
|
||||
ENGINEERING_POSITIONS,
|
||||
@@ -237,6 +167,130 @@ var/list/all_depts_list = list(
|
||||
CARGO_POSITIONS,
|
||||
SECURITY_POSITIONS,
|
||||
)
|
||||
/datum/faction/bloodcult/proc/send_flavour_text_accept(var/mob/victim, var/mob/converter)
|
||||
// -- Static context
|
||||
// Default lines
|
||||
var/list/valid_lines = list(
|
||||
"Another one joins the fold." = 1,
|
||||
"With each new one, the veil gets thinner." = 1,
|
||||
"All are welcome." = 1,
|
||||
)
|
||||
// The departement
|
||||
var/victim_job = victim?.mind.assigned_role
|
||||
var/converter_job = converter?.mind.assigned_role
|
||||
for (var/list/L in acceptance_lines_by_dept)
|
||||
if (victim_job in L)
|
||||
valid_lines += acceptance_lines_by_dept[L]
|
||||
// The specific job
|
||||
valid_lines += acceptance_lines_by_specific_job[victim_job]
|
||||
// The roles he may add
|
||||
if (victim.mind)
|
||||
for (var/role in victim.mind.antag_roles)
|
||||
valid_lines += acceptance_lines_by_specific_role[role]
|
||||
// The race
|
||||
if (ishuman(victim))
|
||||
var/mob/living/carbon/human/dude = victim
|
||||
valid_lines += acceptance_lines_by_specific_race[dude.species.type]
|
||||
|
||||
// -- Dynamic context
|
||||
// Cultist count
|
||||
var/cultists = 0
|
||||
for (var/datum/role/R in members)
|
||||
if (R.antag && R.antag.current && !R.antag.current.stat) // If he's alive
|
||||
cultists++
|
||||
|
||||
// Not a lot of cultists...
|
||||
if (cultists < 3)
|
||||
valid_lines += acceptance_lines_few_cultists
|
||||
|
||||
// Or a lot of them !
|
||||
else if (cultists > 10)
|
||||
valid_lines += acceptance_lines_numerous_cultists
|
||||
|
||||
// Converter and victim are of the same dept
|
||||
for (var/list/dept in all_depts_list)
|
||||
if ((victim_job in dept) && (converter_job in dept))
|
||||
valid_lines += acceptance_lines_same_dept
|
||||
|
||||
var/chosen_line = pickweight(valid_lines)
|
||||
to_chat(victim, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>[chosen_line]</span>")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var/list/failure_lines_by_dept = list(
|
||||
COMMAND_POSITIONS = list(
|
||||
"You have failed to lead them. You would have failed to follow." = 3,
|
||||
"And so ends your 'authority.'" = 3,
|
||||
"This is what passes as command these days." = 3,
|
||||
),
|
||||
ENGINEERING_POSITIONS = list(
|
||||
"Our craft is more complex than your pathetic tinkering." = 3,
|
||||
"These machines were beyond your skill anyway." = 3,
|
||||
),
|
||||
MEDICAL_POSITIONS = list(
|
||||
"Your refusal helps no one. The blood will still flow." = 3,
|
||||
"There is no cure for this." = 3,
|
||||
"Nothing can heal the veil." = 3,
|
||||
),
|
||||
SCIENCE_POSITIONS = list(
|
||||
"Your closed mind dishonours you." = 3,
|
||||
"Our secrets were beyond your understanding." = 3,
|
||||
"My science was not for weaklings such as you." = 3,
|
||||
),
|
||||
CIVILIAN_POSITIONS = list(
|
||||
"A little job in life, and a forgotten death." = 3,
|
||||
"This refusal is but a footnote on my story." = 3,
|
||||
"You refused the only opportunity you had to make a difference." = 3,
|
||||
),
|
||||
CARGO_POSITION = list(
|
||||
"I care little for the hoarders of your kind." = 3,
|
||||
"As expected for a glorified crate handler." = 3,
|
||||
),
|
||||
SECURITY_POSITION = list(
|
||||
"You already failed." = 3,
|
||||
"This refusal does not erase your failure." = 3,
|
||||
"Your stubbornness amuses me. I already won." = 3,
|
||||
"I could have freed you." = 3,
|
||||
"You will always remain on the weaker side." = 3,
|
||||
),
|
||||
)
|
||||
|
||||
var/list/failure_lines_by_specific_job = list(
|
||||
"Paramedic" = list(
|
||||
"You will not save anyone from where I sent you." = 5,
|
||||
),
|
||||
"Trader" = list(
|
||||
"I offered you a home, and you refused." = 5,
|
||||
),
|
||||
"Captain" = list(
|
||||
"Do you feel in charge?" = 5,
|
||||
),
|
||||
)
|
||||
|
||||
var/list/failure_lines_by_specific_race = list(
|
||||
/datum/species/plasmaman = list(
|
||||
"Your loyalty to the company that twisted you into the living dead is amusing." = 3,
|
||||
)
|
||||
)
|
||||
var/list/failure_lines_few_cultists = list(
|
||||
"With or without you, my faithful shall triumph." = 3,
|
||||
"Do you truly think you won?" = 3,
|
||||
"I have no need of a coward in times like this." = 3,
|
||||
)
|
||||
var/list/failure_lines_numerous_cultists = list(
|
||||
"Your refusal changes nothing." = 3,
|
||||
"You will get to see this station fail from the first row." = 3,
|
||||
)
|
||||
|
||||
#define failure_lines_same_dept list( \
|
||||
"[converter.gender == MALE ? "He" : "She"] tried to save you." = 5, \
|
||||
"You betrayed your friend." = 5, \
|
||||
"Your arrogance must have disappointed your friend." = 5, \
|
||||
)
|
||||
|
||||
|
||||
/datum/faction/bloodcult/proc/send_flavour_text_refuse(var/mob/victim, var/mob/converter)
|
||||
// -- Static context
|
||||
@@ -283,10 +337,6 @@ var/list/all_depts_list = list(
|
||||
for (var/list/dept in all_depts_list)
|
||||
if ((victim_job in dept) && (converter_job in dept))
|
||||
valid_lines += failure_lines_same_dept
|
||||
// Act
|
||||
if (veil_thickness >= CULT_ACT_III)
|
||||
valid_lines += failure_lines_thin_veil
|
||||
|
||||
if(victim.mind && victim.mind.assigned_role == "Chaplain")
|
||||
var/list/cult_blood_chaplain = list("cult", "narsie", "nar'sie", "narnar", "nar-sie")
|
||||
var/list/cult_clock_chaplain = list("ratvar", "clockwork", "ratvarism")
|
||||
@@ -302,55 +352,4 @@ var/list/all_depts_list = list(
|
||||
to_chat(victim, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>[chosen_line]</span>")
|
||||
//to_chat(converter, "Nar-Sie murmurs to [victim]... <span class='warning'>[chosen_line]</span>")
|
||||
|
||||
/datum/faction/bloodcult/proc/send_flavour_text_accept(var/mob/victim, var/mob/converter)
|
||||
// -- Static context
|
||||
// Default lines
|
||||
var/list/valid_lines = list(
|
||||
"Another one joins the fold." = 1,
|
||||
"With each new one, the veil gets thinner." = 1,
|
||||
"All are welcome." = 1,
|
||||
)
|
||||
// The departement
|
||||
var/victim_job = victim?.mind.assigned_role
|
||||
var/converter_job = converter?.mind.assigned_role
|
||||
for (var/list/L in acceptance_lines_by_dept)
|
||||
if (victim_job in L)
|
||||
valid_lines += acceptance_lines_by_dept[L]
|
||||
// The specific job
|
||||
valid_lines += acceptance_lines_by_specific_job[victim_job]
|
||||
// The roles he may add
|
||||
if (victim.mind)
|
||||
for (var/role in victim.mind.antag_roles)
|
||||
valid_lines += acceptance_lines_by_specific_role[role]
|
||||
// The race
|
||||
if (ishuman(victim))
|
||||
var/mob/living/carbon/human/dude = victim
|
||||
valid_lines += acceptance_lines_by_specific_race[dude.species.type]
|
||||
|
||||
// -- Dynamic context
|
||||
// Cultist count
|
||||
var/cultists = 0
|
||||
for (var/datum/role/R in members)
|
||||
if (R.antag && R.antag.current && !R.antag.current.stat) // If he's alive
|
||||
cultists++
|
||||
|
||||
// Not a lot of cultists...
|
||||
if (cultists < 3)
|
||||
valid_lines += acceptance_lines_few_cultists
|
||||
|
||||
// Or a lot of them !
|
||||
else if (cultists > 10)
|
||||
valid_lines += acceptance_lines_numerous_cultists
|
||||
|
||||
// Converter and victim are of the same dept
|
||||
for (var/list/dept in all_depts_list)
|
||||
if ((victim_job in dept) && (converter_job in dept))
|
||||
valid_lines += acceptance_lines_same_dept
|
||||
|
||||
// Act
|
||||
if (veil_thickness >= CULT_ACT_III)
|
||||
valid_lines += acceptance_lines_thin_veil
|
||||
|
||||
var/chosen_line = pickweight(valid_lines)
|
||||
to_chat(victim, "<span class='game say'><span class='danger'>Nar-Sie</span> murmurs, <span class='sinister'>[chosen_line]</span>")
|
||||
//to_chat(converter, "Nar-Sie murmurs to [victim]... <span class='warning'>[chosen_line]</span>")
|
||||
*/
|
||||
@@ -1,5 +1,7 @@
|
||||
#define PAGE_FOREWORD 0
|
||||
#define PAGE_LORE1 101
|
||||
#define PAGE_LORE2 102
|
||||
#define PAGE_LORE3 103
|
||||
|
||||
var/list/arcane_tomes = list()
|
||||
|
||||
@@ -71,46 +73,47 @@ var/list/arcane_tomes = list()
|
||||
|
||||
/obj/item/weapon/tome/proc/tome_text()
|
||||
var/page_data = null
|
||||
var/dat = {"<title>arcane tome</title><body style="color:#5C1D12" background="tomebg.png">
|
||||
var/dat = {"<title>arcane tome</title><body style="color:#FFFFFF" bgcolor="#110000">
|
||||
|
||||
<style>
|
||||
label {display: inline-block; width: 50px;text-align: right;float: left;margin: 0 0 0 -45px;}
|
||||
label {display: inline-block; width: 50px;text-align: right;float: left;margin: 0 0 0 10px;}
|
||||
ul {list-style-type: none;}
|
||||
li:before {content: "-";padding-left: 4px;}
|
||||
a {text-decoration: none; color:#5C1D12}
|
||||
.column {float: left; width: 250px; padding: 0px; height: 300px;}
|
||||
a {text-decoration: none; color:#FFEC66}
|
||||
.column {float: left; width: 400px; padding: 0px; height: 300px;}
|
||||
.row:after {content: ""; display: table; clear: both;}
|
||||
</style>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<div align="center" style="margin: 0 0 0 -10px;"><div style="font-size:20px"><b>The scriptures of <font color=#AE250F>Nar-Sie</b></font></div>The Geometer of Blood</div>
|
||||
<div class="column" style="font-size:18px">
|
||||
<div align="center" style="margin: 0 0 0 -10px;"><div style="font-size:30px"><b>The scriptures of <font color=#FF250F>Nar-Sie</b></font></div>The Geometer of Blood</div>
|
||||
<ul>
|
||||
<a href='byond://?src=\ref[src];page=[PAGE_FOREWORD]'><label> * </label> <li> Foreword</a> </li>"}
|
||||
|
||||
var i = 1
|
||||
for(var/subtype in subtypesof(/datum/rune_spell/blood_cult))
|
||||
var/datum/rune_spell/blood_cult/instance = subtype
|
||||
if (initial(instance.Act_restriction) <= veil_thickness)
|
||||
dat += "<a href='byond://?src=\ref[src];page=[i]'><label> \Roman[i] </label> <li> [initial(instance.name)] </li></a>"
|
||||
if (i == current_page)
|
||||
var/datum/runeword/word1 = initial(instance.word1)
|
||||
var/datum/runeword/word2 = initial(instance.word2)
|
||||
var/datum/runeword/word3 = initial(instance.word3)
|
||||
page_data = {"<div align="center"><b>\Roman[i]<br>[initial(instance.name)]</b><br><i>[initial(word1.english)], [initial(word2.english)], [word3 ? "[initial(word3.english)]" : "<any>"]</i></div><br>"}
|
||||
page_data += initial(instance.page)
|
||||
else
|
||||
dat += "<label> \Roman[i] </label> <li> __________ </li>"
|
||||
for(var/subtype in subtypesof(/datum/rune_spell))
|
||||
var/datum/rune_spell/instance = subtype
|
||||
if (initial(instance.secret))
|
||||
continue
|
||||
dat += "<a href='byond://?src=\ref[src];page=[i]'><label> \Roman[i] </label> <li> [initial(instance.name)] </li></a>"
|
||||
if (i == current_page)
|
||||
var/datum/rune_word/word1 = initial(instance.word1)
|
||||
var/datum/rune_word/word2 = initial(instance.word2)
|
||||
var/datum/rune_word/word3 = initial(instance.word3)
|
||||
page_data = {"<div align="center"><b>\Roman[i]<br>[initial(instance.name)]</b><br><i>[initial(word1.english)], [initial(word2.english)], [word3 ? "[initial(word3.english)]" : "<any>"]</i></div><br>"}
|
||||
page_data += initial(instance.page)
|
||||
i++
|
||||
|
||||
dat += {"<a href='byond://?src=\ref[src];page=[PAGE_LORE1]'><label> * </label> <li> about this tome and our goal </li></a>
|
||||
dat += {"<a href='byond://?src=\ref[src];page=[PAGE_LORE1]'><label> * </label> <li> Addendum I </li></a>
|
||||
<a href='byond://?src=\ref[src];page=[PAGE_LORE2]'><label> * </label> <li> Addendum II </li></a>
|
||||
<a href='byond://?src=\ref[src];page=[PAGE_LORE3]'><label> * </label> <li> Addendum III </li></a>
|
||||
</ul></div>
|
||||
<div class="column"> <div align="left"> <b><ul>"}
|
||||
<div style="font-size:18px" class="column"> <div align="left"> <b><ul>"}
|
||||
|
||||
for (var/obj/item/weapon/talisman/T in talismans)
|
||||
dat += {"<label> * </label><li> <a style="color:#AE250F" href='byond://?src=\ref[src];talisman=\ref[T]'>[T.talisman_name()][(T.uses > 1) ? " [T.uses] uses" : ""]</a> <a style="color:#AE250F" href='byond://?src=\ref[src];remove=\ref[T]'>(x)</a> </li>"}
|
||||
dat += {"<label> * </label><li> <a style="color:#FFEC66" href='byond://?src=\ref[src];talisman=\ref[T]'>[T.talisman_name()][(T.uses > 1) ? " [T.uses] uses" : ""]</a> <a style="color:#AE250F" href='byond://?src=\ref[src];remove=\ref[T]'>(x)</a> </li>"}
|
||||
|
||||
dat += {"</ul></b></div><div style="margin: 0px 20px;" align="justify">"}
|
||||
dat += {"</ul></b></div><div align="justify">"}
|
||||
|
||||
if (page_data)
|
||||
dat += page_data
|
||||
@@ -125,18 +128,33 @@ var/list/arcane_tomes = list()
|
||||
var/dat = null
|
||||
switch (current_page)
|
||||
if (PAGE_FOREWORD)
|
||||
dat = {"<div align="center"><b>Foreword</b></div><br>
|
||||
This tome in your hands is both a guide to the ways of the devotes to Nar-Sie, and a tool to help them performing the cult's rituals.
|
||||
Inside are gathered notes on the various rituals, which you can read to study their use, and learn their runes. You don't have to learn
|
||||
the runes by heart however, as keeping this tome open allows you to immediately remember them when tracing words. Additional pieces of lore
|
||||
are available in the latter pages, aiming to satisfy the curiosity of the assiduous cultists.
|
||||
"}
|
||||
dat = {"<div align="center"><b>Foreword</b></div><br>"}
|
||||
dat += "<i>Written over the ages by a collection of arch-cultists, under the guidance of the geometer himself.</i>\
|
||||
<br><br>Touch a chapter to read it."
|
||||
if (PAGE_LORE1)
|
||||
dat = {"<div align="center"><b>About this tome and our goal</b></div><br>
|
||||
This tome was written under the guidance of Nar-Sie, by devotes who have left behind their flesh enveloppes and taken residence in the realm of the Geometer of Blood.
|
||||
Our goal is to help our kin in the physical world, that is you, achieve the Tear Reality ritual, so that you can all join us and bring along lots of value, in other words blood.
|
||||
This goal has been achieved countless times before by different beings in different place, and this tome has been updated thanks to the knowledge of those who joined us.
|
||||
"}
|
||||
dat = {"<div align="center"><b>Addendum I: "From the other side of the veil"</b></div><br>"}
|
||||
dat += "<i>It is by chance that humanity stumbled upon the realm of Nar-Sie some centuries ago, \
|
||||
although while some of those so called wizards called it a happy little accident, few of them know that the dice was loaded from the start.\
|
||||
<br><br>Nar-Sie threw some artifacts adrift in the bluespace, waiting for some intelligent life to pick them up and trace their way back to him. \
|
||||
For you see, Nar-Sie loves two things about humans, the blood that flows from their veins, and the dramatic circumstances around which said blood ends up flowing from their gaping wounds.\
|
||||
<br><br>How did he know about humanity's existence before they even reached him you might ask? It's quite simple, he could hear the drumming of our heartbeats all the way from the other side of the veil.</i>"
|
||||
if (PAGE_LORE2)
|
||||
dat = {"<div align="center"><b>Addendum II: "From whom the blood spills"</b></div><br>"}
|
||||
dat += "<i>After contact was made between the planes, it was a matter of time before some people would appear who would actively seek Nar-Sie.\
|
||||
<br><br>Either because his love of drama and chaos resonated with them, and they wanted to become his heralds, performing sacrifices for his amusement, \
|
||||
or because they were in awe with his... \"otherworldlyness?\" People who had lived until now grounded in reality, and became quite fascinated with something mystic, yet tangible.\
|
||||
<br><br>And of course, then came those who seeked to defy him. Either in the name of their own gods, or out of their own sense of morality, but little do those know, \
|
||||
Nar-Sie loves them equally, and doesn't care too much from whom the blood spills.</i>"
|
||||
if (PAGE_LORE3)
|
||||
dat = {"<div align="center"><b>Addendum III: "The geometer's calling card"</b></div><br>"}
|
||||
dat += "<i>A common misconception about Nar-Sie is about his title, why is he the Geometer of Blood? Nobody dared ask him directly by fear of offending him, so for a long time, \
|
||||
many cultists just assumed that he was really into geometry, and his powers manifesting from blood drawings of precise patterns would corroborate this hypothesis.\
|
||||
<br><br>Some cultists eventually took it upon themselves to commune with him to get an answer, after performing some sacrifices for good measure. The answer was unexpected, and shed more light on the cult's origins. \
|
||||
They learned that after the wizards cut their way into his plane, it took some time for them to run into him, just like humans aren't aware of every single ant living in their garden. \
|
||||
But when they did arrive upon him, his gigantic form twisted upon the scenery gave them the image of a geometer moth.\
|
||||
<br><br>And just like moths tend to be attracted by light, they saw that Nar-Sie was attracted by blood, so they called him the Geometer of Blood, a title very much to his liking.\
|
||||
<br><br>As humanity ventures deeper and deeper into the darkness of space and toys with powers they understand less and less, Nar-Sie feels them coming closer and closer to him, and wants now to hasten the process. \
|
||||
His cult sends heralds to let humanity know how much he likes them (their blood mostly), and until he's ready to invite them into his realm, they leave blood-splattered space stations across the stars as his calling card.</i>"
|
||||
return dat
|
||||
|
||||
/obj/item/weapon/tome/Topic(href, href_list)
|
||||
@@ -163,7 +181,7 @@ var/list/arcane_tomes = list()
|
||||
usr.put_in_hands(T)
|
||||
|
||||
usr << browse_rsc('icons/tomebg.png', "tomebg.png")
|
||||
usr << browse(tome_text(), "window=arcanetome;size=537x375")
|
||||
usr << browse(tome_text(), "window=arcanetome;size=900x600")
|
||||
|
||||
/obj/item/weapon/tome/attack(var/mob/living/M, var/mob/living/user)
|
||||
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has had the [name] used on him by [user.name] ([user.ckey])</font>")
|
||||
@@ -206,7 +224,7 @@ var/list/arcane_tomes = list()
|
||||
/obj/item/weapon/tome/pickup(var/mob/user)
|
||||
if(iscultist(user) && state == TOME_OPEN)
|
||||
usr << browse_rsc('icons/tomebg.png', "tomebg.png")
|
||||
usr << browse(tome_text(), "window=arcanetome;size=537x375")
|
||||
usr << browse(tome_text(), "window=arcanetome;size=900x600")
|
||||
|
||||
/obj/item/weapon/tome/dropped(var/mob/user)
|
||||
usr << browse(null, "window=arcanetome")
|
||||
@@ -234,7 +252,7 @@ var/list/arcane_tomes = list()
|
||||
playsound(user, "pageturn", 50, 1, -5)
|
||||
state = TOME_OPEN
|
||||
usr << browse_rsc('icons/tomebg.png', "tomebg.png")
|
||||
usr << browse(tome_text(), "window=arcanetome;size=537x375")
|
||||
usr << browse(tome_text(), "window=arcanetome;size=900x600")
|
||||
else
|
||||
icon_state = "tome"
|
||||
item_state = "tome"
|
||||
@@ -270,20 +288,31 @@ var/list/arcane_tomes = list()
|
||||
to_chat(user, "<span class='notice'>You slip \the [I] into \the [src].</span>")
|
||||
if (state == TOME_OPEN)
|
||||
usr << browse_rsc('icons/tomebg.png', "tomebg.png")
|
||||
usr << browse(tome_text(), "window=arcanetome;size=537x375")
|
||||
usr << browse(tome_text(), "window=arcanetome;size=900x600")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This tome cannot contain any more talismans. Use or remove some first.</span>")
|
||||
|
||||
/obj/item/weapon/tome/AltClick(var/mob/user)
|
||||
var/list/choices = list()
|
||||
var/datum/rune_spell/blood_cult/instance
|
||||
var/datum/rune_spell/instance
|
||||
var/list/choice_to_talisman = list()
|
||||
var/image/talisman_image
|
||||
var/blood_messages = 0
|
||||
var/blanks = 0
|
||||
for(var/obj/item/weapon/talisman/T in talismans)
|
||||
talisman_image = new(T)
|
||||
instance = T.spell_type
|
||||
choices += list(list(T, talisman_image, initial(instance.desc_talisman), T.talisman_name()))
|
||||
choice_to_talisman[initial(instance.name)] = T
|
||||
if (T.blood_text)
|
||||
choices += list(list("Bloody Message[blood_messages ? " #[blood_messages+1]" : ""]", talisman_image, "A ghost has scribled a message on this talisman."))
|
||||
choice_to_talisman["Bloody Message[blood_messages ? " #[blood_messages+1]" : ""]"] = T
|
||||
blood_messages++
|
||||
else if (T.spell_type)
|
||||
instance = T.spell_type
|
||||
choices += list(list(T.talisman_name(), talisman_image, initial(instance.desc_talisman)))
|
||||
choice_to_talisman[T.talisman_name()] = T
|
||||
else
|
||||
choices += list(list("Blank Talisman[blanks ? " #[blanks+1]" : ""]", talisman_image, "Just an empty talisman."))
|
||||
choice_to_talisman["Blank Talisman[blanks ? " #[blanks+1]" : ""]"] = T
|
||||
blanks++
|
||||
|
||||
if (state == TOME_CLOSED)
|
||||
icon_state = "tome-open"
|
||||
@@ -292,7 +321,7 @@ var/list/arcane_tomes = list()
|
||||
playsound(user, "pageturn", 50, 1, -5)
|
||||
state = TOME_OPEN
|
||||
var/choice = show_radial_menu(user,loc,choices,'icons/obj/cult_radial3.dmi', "radial-cult2")
|
||||
if(!choice_to_talisman[choice])
|
||||
if(!choice)
|
||||
return
|
||||
var/obj/item/weapon/talisman/chosen_talisman = choice_to_talisman[choice]
|
||||
if(!usr.held_items.Find(src))
|
||||
@@ -307,6 +336,8 @@ var/list/arcane_tomes = list()
|
||||
|
||||
#undef PAGE_FOREWORD
|
||||
#undef PAGE_LORE1
|
||||
#undef PAGE_LORE2
|
||||
#undef PAGE_LORE3
|
||||
|
||||
///////////////////////////////////////TALISMAN////////////////////////////////////////////////
|
||||
|
||||
@@ -343,7 +374,7 @@ var/list/arcane_tomes = list()
|
||||
ignite()
|
||||
|
||||
/obj/item/weapon/talisman/proc/talisman_name()
|
||||
var/datum/rune_spell/blood_cult/instance = spell_type
|
||||
var/datum/rune_spell/instance = spell_type
|
||||
if (blood_text)
|
||||
return "\[blood message\]"
|
||||
if (instance)
|
||||
@@ -367,7 +398,7 @@ var/list/arcane_tomes = list()
|
||||
to_chat(user, "<span class='info'>This one, however, seems pretty unremarkable.</span>")
|
||||
return
|
||||
|
||||
var/datum/rune_spell/blood_cult/instance = spell_type
|
||||
var/datum/rune_spell/instance = spell_type
|
||||
|
||||
if (iscultist(user) || isobserver(user))
|
||||
if (attuned_rune)
|
||||
@@ -392,7 +423,7 @@ var/list/arcane_tomes = list()
|
||||
|
||||
/obj/item/weapon/talisman/attack(var/mob/living/target, var/mob/living/user)
|
||||
if(iscultist(user) && spell_type)
|
||||
var/datum/rune_spell/blood_cult/instance = spell_type
|
||||
var/datum/rune_spell/instance = spell_type
|
||||
if (initial(instance.touch_cast))
|
||||
new spell_type(user, src, "touch", target)
|
||||
qdel(src)
|
||||
@@ -415,7 +446,7 @@ var/list/arcane_tomes = list()
|
||||
var/obj/item/weapon/tome/T = loc
|
||||
T.talismans.Remove(src)
|
||||
user << browse_rsc('icons/tomebg.png', "tomebg.png")
|
||||
user << browse(T.tome_text(), "window=arcanetome;size=537x375")
|
||||
user << browse(T.tome_text(), "window=arcanetome;size=900x600")
|
||||
user.put_in_hands(src)
|
||||
return
|
||||
|
||||
@@ -437,7 +468,7 @@ var/list/arcane_tomes = list()
|
||||
T.talismans.Remove(src)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/talisman/proc/imbue(var/mob/user, var/obj/effect/rune/blood_cult/R)
|
||||
/obj/item/weapon/talisman/proc/imbue(var/mob/user, var/obj/effect/rune/R)
|
||||
if (!user || !R)
|
||||
return
|
||||
|
||||
@@ -445,7 +476,7 @@ var/list/arcane_tomes = list()
|
||||
to_chat(user, "<span class='warning'>Cannot imbue a talisman that has been written on.</span>")
|
||||
return
|
||||
|
||||
var/datum/rune_spell/blood_cult/spell = get_rune_spell(user,null,"examine",R.word1, R.word2, R.word3)
|
||||
var/datum/rune_spell/spell = get_rune_spell(user,null,"examine",R.word1, R.word2, R.word3)
|
||||
if(initial(spell.talisman_absorb) == RUNE_CANNOT)//placing a talisman on a Conjure Talisman rune to try and fax it
|
||||
user.drop_item(src)
|
||||
src.forceMove(get_turf(R))
|
||||
@@ -462,10 +493,6 @@ var/list/arcane_tomes = list()
|
||||
to_chat(user, "<span class='warning'>There is no power in those runes. \The [src] isn't reacting to it.</span>")
|
||||
return
|
||||
|
||||
if (initial(spell.Act_restriction) > veil_thickness)
|
||||
to_chat(user, "<span class='danger'>The veil is still too thick for \the [src] to draw power from this rune.</span>")
|
||||
return
|
||||
|
||||
//blood markings
|
||||
overlays += image(icon,"talisman-[R.word1.icon_state]a")
|
||||
overlays += image(icon,"talisman-[R.word2.icon_state]a")
|
||||
@@ -479,21 +506,19 @@ var/list/arcane_tomes = list()
|
||||
uses = initial(spell.talisman_uses)
|
||||
|
||||
var/talisman_interaction = initial(spell.talisman_absorb)
|
||||
var/datum/rune_spell/blood_cult/active_spell = R.active_spell
|
||||
var/datum/rune_spell/active_spell = R.active_spell
|
||||
if(!istype(R))
|
||||
return
|
||||
if (active_spell)//some runes may change their interaction type dynamically (ie: Path Exit runes)
|
||||
talisman_interaction = active_spell.talisman_absorb
|
||||
if (istype(active_spell,/datum/rune_spell/blood_cult/portalentrance))
|
||||
var/datum/rune_spell/blood_cult/portalentrance/entrance = active_spell
|
||||
if (istype(active_spell,/datum/rune_spell/portalentrance))
|
||||
var/datum/rune_spell/portalentrance/entrance = active_spell
|
||||
if (entrance.network)
|
||||
var/datum/runeset/rune_set = global_runesets["blood_cult"]
|
||||
word_pulse(rune_set.words[entrance.network])
|
||||
else if (istype(active_spell,/datum/rune_spell/blood_cult/portalexit))
|
||||
var/datum/rune_spell/blood_cult/portalentrance/exit = active_spell
|
||||
word_pulse(rune_words[entrance.network])
|
||||
else if (istype(active_spell,/datum/rune_spell/portalexit))
|
||||
var/datum/rune_spell/portalentrance/exit = active_spell
|
||||
if (exit.network)
|
||||
var/datum/runeset/rune_set = global_runesets["blood_cult"]
|
||||
word_pulse(rune_set.words[exit.network])
|
||||
word_pulse(rune_words[exit.network])
|
||||
|
||||
switch(talisman_interaction)
|
||||
if (RUNE_CAN_ATTUNE)
|
||||
@@ -508,7 +533,7 @@ var/list/arcane_tomes = list()
|
||||
message_admins("Error! ([key_name(user)]) managed to imbue a Conjure Talisman rune. That shouldn't be possible!")
|
||||
return
|
||||
|
||||
/obj/item/weapon/talisman/proc/word_pulse(var/datum/runeword/W)
|
||||
/obj/item/weapon/talisman/proc/word_pulse(var/datum/rune_word/W)
|
||||
var/image/I1 = image(icon,"talisman-[W.icon_state]a")
|
||||
animate(I1, 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, loop = -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)
|
||||
@@ -665,6 +690,8 @@ var/list/arcane_tomes = list()
|
||||
var/movespeed = 2//smaller = faster
|
||||
health = 40
|
||||
var/maxHealth = 40
|
||||
var/reflector = FALSE
|
||||
var/mob/living/linked_cultist = null
|
||||
|
||||
/obj/item/weapon/melee/soulblade/Destroy()
|
||||
var/turf/T = get_turf(src)
|
||||
@@ -692,6 +719,13 @@ var/list/arcane_tomes = list()
|
||||
shade = null
|
||||
..()
|
||||
|
||||
/obj/item/weapon/melee/soulblade/attack_hand(var/mob/living/user)
|
||||
if (shade)
|
||||
if (iscultist(user) && (linked_cultist != user))
|
||||
linked_cultist = user
|
||||
to_chat(shade, "<spawn class='notice'>You have made contact with [user]. As long as you remain within 5 tiles of them, you can move by yourself without losing blood, and regenerate blood slowly passively.</span>")
|
||||
..()
|
||||
|
||||
/obj/item/weapon/melee/soulblade/salt_act()
|
||||
qdel(src)
|
||||
|
||||
@@ -787,13 +821,6 @@ var/list/arcane_tomes = list()
|
||||
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/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
|
||||
if (cult)
|
||||
var/datum/objective/bloodcult_sacrifice/O = locate() in cult.objective_holder.objectives
|
||||
if (O && (target == O.sacrifice_target || (target.mind && target.mind == O.sacrifice_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, target, src)
|
||||
qdel(capture_datum)
|
||||
@@ -808,6 +835,7 @@ var/list/arcane_tomes = list()
|
||||
|
||||
if (blood >= 5)
|
||||
blood = max(0,blood-5)
|
||||
update_icon()
|
||||
var/turf/starting = get_turf(user)
|
||||
var/turf/target = get_turf(A)
|
||||
var/obj/item/projectile/bloodslash/BS = new (starting)
|
||||
@@ -843,15 +871,30 @@ var/list/arcane_tomes = list()
|
||||
if (C.take_blood(null,5))//same cost as spin, basically negates the cost, but doesn't let you farm corpses. It lets you make a mess out of them however.
|
||||
blood = min(100,blood+5)
|
||||
to_chat(user, "<span class='warning'>You steal a bit of their blood, but not much.</span>")
|
||||
|
||||
update_icon()
|
||||
if (shade)
|
||||
shade.DisplayUI("Soulblade")
|
||||
else if (M.isBloodedAnimal())
|
||||
var/mob/living/simple_animal/SA = M
|
||||
if (SA.stat != DEAD)
|
||||
blood = min(100,blood+10)
|
||||
to_chat(user, "<span class='warning'>You steal some of their blood!</span>")
|
||||
else
|
||||
blood = min(100,blood+5)
|
||||
to_chat(user, "<span class='warning'>You steal a bit of their blood, but not much.</span>")
|
||||
update_icon()
|
||||
if (shade)
|
||||
shade.DisplayUI("Soulblade")
|
||||
|
||||
/obj/item/weapon/melee/soulblade/setPixelOffsetsFromParams(params, mob/user, base_pixx = 0, base_pixy = 0, clamp = TRUE)
|
||||
..(params, user, -16, -16, FALSE) // clamp has to be false or we can't put the blade in the left and lower portions of a table
|
||||
|
||||
/obj/item/weapon/melee/soulblade/pickup(var/mob/living/user)
|
||||
..()
|
||||
if(!iscultist(user))
|
||||
to_chat(user, "<span class='warning'>An overwhelming feeling of dread comes over you as you pick up \the [src]. It would be wise to rid yourself of this, quickly.</span>")
|
||||
user.Dizzy(120)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/melee/soulblade/dropped(var/mob/user)
|
||||
..()
|
||||
@@ -878,6 +921,11 @@ var/list/arcane_tomes = list()
|
||||
if (istype(loc,/mob/living/carbon))
|
||||
var/mob/living/carbon/C = loc
|
||||
C.update_inv_hands()
|
||||
if (iscultist(C))
|
||||
var/image/I = image('icons/mob/hud.dmi', src, "consthealth[10*round((blood/maxblood)*10)]")
|
||||
I.pixel_x = 16
|
||||
I.pixel_y = 16
|
||||
overlays += I
|
||||
|
||||
|
||||
/obj/item/weapon/melee/soulblade/throw_at(var/atom/targ, var/range, var/speed, var/override = 1, var/fly_speed = 0)
|
||||
@@ -921,7 +969,7 @@ var/list/arcane_tomes = list()
|
||||
|
||||
/obj/item/weapon/melee/soulblade/Cross(var/atom/movable/mover, var/turf/target, var/height=1.5, var/air_group = 0)
|
||||
if(istype(mover, /obj/item/projectile))
|
||||
if (prob(60))
|
||||
if (prob(60) || reflector)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
@@ -950,8 +998,14 @@ var/list/arcane_tomes = list()
|
||||
takeDamage(O.throwforce)
|
||||
|
||||
/obj/item/weapon/melee/soulblade/bullet_act(var/obj/item/projectile/P)
|
||||
. = ..()
|
||||
takeDamage(P.damage)
|
||||
if (reflector)
|
||||
if(!istype(P, /obj/item/projectile/beam)) //has seperate logic
|
||||
P.reflected = 1
|
||||
P.rebound(src)
|
||||
return PROJECTILE_COLLISION_REBOUND // complete projectile permutation
|
||||
else
|
||||
. = ..()
|
||||
takeDamage(P.damage)
|
||||
|
||||
/obj/item/weapon/melee/soulblade/proc/capture_shade(var/mob/living/simple_animal/shade/target, var/mob/user)
|
||||
if(shade)
|
||||
@@ -1101,6 +1155,9 @@ var/list/arcane_tomes = list()
|
||||
actions_types = list(/datum/action/item_action/toggle_anon)
|
||||
var/anon_mode = FALSE
|
||||
|
||||
/obj/item/clothing/head/culthood/NoiseDampening() // those hoods cover the ears
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/head/culthood/attack_self(var/mob/user)
|
||||
if (!iscultist(user))
|
||||
return
|
||||
@@ -1175,6 +1232,31 @@ var/list/arcane_tomes = list()
|
||||
/obj/item/clothing/shoes/cult/salt_act()
|
||||
acid_melt()
|
||||
|
||||
///////////////////////////////////////CULT GLOVES////////////////////////////////////////////////
|
||||
|
||||
|
||||
/obj/item/clothing/gloves/black/cult
|
||||
name = "cult gloves"
|
||||
desc = "These gloves are quite comfortable, and will keep you warm!"
|
||||
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/cultstuff.dmi', "right_hand" = 'icons/mob/in-hand/right/cultstuff.dmi')
|
||||
icon_state = "cult"
|
||||
item_state = "cultgloves"
|
||||
_color = "cult"
|
||||
siemens_coefficient = 0.7
|
||||
heat_conductivity = INS_GLOVES_HEAT_CONDUCTIVITY
|
||||
max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE
|
||||
species_fit = list(VOX_SHAPED, INSECT_SHAPED)
|
||||
mech_flags = MECH_SCAN_FAIL
|
||||
|
||||
/obj/item/clothing/gloves/black/cult/get_cult_power()
|
||||
return 10
|
||||
|
||||
/obj/item/clothing/gloves/black/cult/cultify()
|
||||
return
|
||||
|
||||
/obj/item/clothing/gloves/black/cult/salt_act()
|
||||
acid_melt()
|
||||
|
||||
///////////////////////////////////////CULT ROBES////////////////////////////////////////////////
|
||||
|
||||
/obj/item/clothing/suit/cultrobes
|
||||
@@ -1362,15 +1444,13 @@ var/list/arcane_tomes = list()
|
||||
mech_flags = MECH_SCAN_FAIL
|
||||
|
||||
/obj/item/weapon/bloodcult_pamphlet/attack_self(var/mob/user)
|
||||
if (iscultist(user))
|
||||
return
|
||||
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.OnPostSetup()
|
||||
var/datum/role/cultist/newCultist
|
||||
if (cult.members.len > 0)
|
||||
newCultist = new /datum/role/cultist()
|
||||
else
|
||||
newCultist = new /datum/role/cultist/chief()
|
||||
var/datum/role/cultist/newCultist = new /datum/role/cultist()
|
||||
newCultist.AssignToRole(user.mind,1)
|
||||
cult.HandleRecruitedRole(newCultist)
|
||||
newCultist.OnPostSetup()
|
||||
@@ -1390,7 +1470,7 @@ var/list/arcane_tomes = list()
|
||||
/obj/item/weapon/bloodcult_pamphlet/salt_act()
|
||||
ignite()
|
||||
|
||||
//Jaunter: creates a pylon on spawn, lets you teleport to it on use
|
||||
//Jaunter: creates a pylon on spawn, lets you teleport to it on use. That's an item I made to test and debug cult blood jaunts
|
||||
/obj/item/weapon/bloodcult_jaunter
|
||||
name = "test jaunter"
|
||||
desc = ""
|
||||
@@ -1576,6 +1656,7 @@ var/list/arcane_tomes = list()
|
||||
/obj/item/clothing/head/culthood,
|
||||
/obj/item/clothing/shoes/cult,
|
||||
/obj/item/clothing/suit/cultrobes,
|
||||
/obj/item/clothing/gloves/black/cult,
|
||||
)
|
||||
|
||||
var/list/stored_gear = list()
|
||||
@@ -1655,5 +1736,40 @@ var/list/arcane_tomes = list()
|
||||
/obj/item/weapon/blood_tesseract/cultify()
|
||||
return
|
||||
|
||||
/obj/item/weapon/handcuffs/cult/salt_act()
|
||||
/obj/item/weapon/blood_tesseract/salt_act()
|
||||
throw_impact()
|
||||
|
||||
///////////////////////////////////////BLOOD CANDLE////////////////////////////////////////////////
|
||||
|
||||
/obj/item/candle/blood
|
||||
name = "blood candle"
|
||||
desc = "A candle made out of blood moth wax, burns much longer than regular candles. Used for moody lighting and occult rituals."
|
||||
icon = 'icons/obj/candle.dmi'
|
||||
icon_state = "bloodcandle"
|
||||
|
||||
wax = 1200 // 20 minutes
|
||||
trashtype = /obj/item/trash/blood_candle
|
||||
|
||||
/obj/item/candle/blood/update_icon()
|
||||
overlays.len = 0
|
||||
var/i
|
||||
if(wax > 800)
|
||||
i = 1
|
||||
else if(wax > 400)
|
||||
i = 2
|
||||
else i = 3
|
||||
icon_state = "bloodcandle[i]"
|
||||
if (lit)
|
||||
var/image/I = image(icon,src,"[icon_state]_lit")
|
||||
I.blend_mode = BLEND_ADD
|
||||
if (isturf(loc))
|
||||
I.plane = ABOVE_LIGHTING_PLANE
|
||||
else
|
||||
I.plane = ABOVE_HUD_PLANE // inventory
|
||||
overlays += I
|
||||
|
||||
/obj/item/trash/blood_candle
|
||||
name = "blood candle"
|
||||
desc = "A candle made out of blood moth wax, burns much longer than regular candles. Used for moody lighting and occult rituals."
|
||||
icon = 'icons/obj/candle.dmi'
|
||||
icon_state = "bloodcandle4"
|
||||
|
||||
229
code/datums/gamemode/factions/bloodcult/bloodcult_misc_procs.dm
Normal file
229
code/datums/gamemode/factions/bloodcult/bloodcult_misc_procs.dm
Normal file
@@ -0,0 +1,229 @@
|
||||
|
||||
/*
|
||||
|
||||
* /proc/prepare_cult_holomap
|
||||
* /datum/station_holomap/cult/initialize_holomap
|
||||
* /obj/item/proc/get_cult_power
|
||||
* /mob/proc/get_cult_power
|
||||
* /mob/proc/occult_muted
|
||||
* /mob/proc/get_convertibility
|
||||
* /mob/living/carbon/get_convertibility
|
||||
* /mob/living/carbon/proc/update_convertibility
|
||||
* /mob/living/carbon/proc/implant_pop
|
||||
* /mob/living/carbon/proc/boxify
|
||||
* ///proc/spawn_bloodstones
|
||||
|
||||
*/
|
||||
|
||||
//Instead of updating in realtime, cult holomaps update every time you check them again, saves some CPU.
|
||||
/proc/prepare_cult_holomap()
|
||||
var/image/I = image(extraMiniMaps[HOLOMAP_EXTRA_CULTMAP])
|
||||
for(var/marker in holomap_markers)
|
||||
var/datum/holomap_marker/holomarker = holomap_markers[marker]
|
||||
var/image/markerImage = image(holomarker.icon,holomarker.id)
|
||||
markerImage.color = holomarker.color
|
||||
if(holomarker.z == map.zMainStation && holomarker.filter & HOLOMAP_FILTER_CULT)
|
||||
if(map.holomap_offset_x.len >= map.zMainStation)
|
||||
markerImage.pixel_x = holomarker.x-8+map.holomap_offset_x[map.zMainStation]
|
||||
markerImage.pixel_y = holomarker.y-8+map.holomap_offset_y[map.zMainStation]
|
||||
else
|
||||
markerImage.pixel_x = holomarker.x-8
|
||||
markerImage.pixel_y = holomarker.y-8
|
||||
markerImage.appearance_flags = RESET_COLOR
|
||||
I.overlays += markerImage
|
||||
return I
|
||||
|
||||
/datum/station_holomap/cult/initialize_holomap(var/turf/T, var/isAI=null, var/mob/user=null, var/cursor_icon = "bloodstone-here")
|
||||
station_map = image(extraMiniMaps[HOLOMAP_EXTRA_CULTMAP])
|
||||
cursor = image('icons/holomap_markers.dmi', cursor_icon)
|
||||
|
||||
/obj/item/proc/get_cult_power()
|
||||
return 0
|
||||
|
||||
var/static/list/valid_cultpower_slots = list(
|
||||
slot_wear_suit,
|
||||
slot_head,
|
||||
slot_shoes,
|
||||
)//might add more slots later as I add more items that could fit in them
|
||||
|
||||
/* get_cult_power
|
||||
returns: the combined cult power of every item worn by src.
|
||||
|
||||
*/
|
||||
/mob/proc/get_cult_power()
|
||||
var/power = 0
|
||||
for (var/slot in valid_cultpower_slots)
|
||||
var/obj/item/I = get_item_by_slot(slot)
|
||||
if (istype(I))
|
||||
power += I.get_cult_power()
|
||||
|
||||
return power
|
||||
|
||||
/mob/proc/occult_muted()
|
||||
if (reagents && reagents.has_reagent(HOLYWATER))
|
||||
return 1
|
||||
if (is_implanted(/obj/item/weapon/implant/holy))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/proc/get_convertibility()
|
||||
if (!mind || isDead())
|
||||
return CONVERTIBLE_NOMIND
|
||||
|
||||
if (iscultist(src))
|
||||
return CONVERTIBLE_ALREADY
|
||||
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/get_convertibility()
|
||||
var/convertibility = ..()
|
||||
|
||||
if (!convertibility)
|
||||
//TODO: chaplain stuff
|
||||
//this'll do in the meantime
|
||||
if (mind.assigned_role == "Chaplain")
|
||||
return CONVERTIBLE_NEVER
|
||||
|
||||
var/acceptance = "Never"
|
||||
if (client)
|
||||
acceptance = get_role_desire_str(client.prefs.roles[CULTIST])
|
||||
|
||||
if (jobban_isbanned(src, CULTIST) || isantagbanned(src) || (acceptance == "Never"))
|
||||
return CONVERTIBLE_NEVER
|
||||
|
||||
if (is_loyalty_implanted())
|
||||
return CONVERTIBLE_IMPLANT
|
||||
|
||||
if (acceptance == "Always" || acceptance == "Yes")
|
||||
return CONVERTIBLE_ALWAYS
|
||||
|
||||
return CONVERTIBLE_CHOICE
|
||||
|
||||
return convertibility//no mind, dead, or already a cultist
|
||||
|
||||
/mob/living/carbon/proc/update_convertibility()
|
||||
var/convertibility = get_convertibility()
|
||||
var/image/I = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
switch(convertibility)
|
||||
if (CONVERTIBLE_ALWAYS)
|
||||
I.icon_state = "convertible"
|
||||
if (CONVERTIBLE_CHOICE)
|
||||
I.icon_state = "maybeconvertible"
|
||||
if (CONVERTIBLE_IMPLANT)
|
||||
I.icon_state = "unconvertible"
|
||||
if (CONVERTIBLE_NEVER)
|
||||
I.icon_state = "unconvertible2"
|
||||
|
||||
I.pixel_y = 16 * PIXEL_MULTIPLIER
|
||||
I.plane = ANTAG_HUD_PLANE
|
||||
I.appearance_flags |= RESET_COLOR|RESET_ALPHA
|
||||
|
||||
//inspired from the rune color matrix because boy am I proud of it
|
||||
animate(I, 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 = 2)//9
|
||||
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.7)//8
|
||||
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.4)//7
|
||||
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.1)//6
|
||||
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 = 0.8)//5
|
||||
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 = 0.5)//4
|
||||
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 = 0.2)//3
|
||||
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 = 0.1)//2
|
||||
animate(color = list(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0), time = 5)//1
|
||||
|
||||
hud_list[CONVERSION_HUD] = I
|
||||
|
||||
|
||||
/mob/living/carbon/proc/implant_pop()
|
||||
for(var/obj/item/weapon/implant/loyalty/I in src)
|
||||
if (I.imp_in)
|
||||
to_chat(src, "<span class='sinister'>Your blood pushes back against the loyalty implant, it will visibly pop out within seconds!</span>")
|
||||
spawn(10 SECONDS)
|
||||
if (I.remove())
|
||||
visible_message("<span class='warning'>\The [I] pops out of \the [src]'s head.</span>")
|
||||
|
||||
|
||||
/mob/living/carbon/proc/boxify(var/delete_body = TRUE, var/new_anim = TRUE, var/box_state = "cult")//now its own proc so admins may atomProcCall it if they so desire.
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/M in dview(world.view, T, INVISIBILITY_MAXIMUM))
|
||||
if (M.client)
|
||||
M.playsound_local(T, 'sound/effects/convert_failure.ogg', 75, 0, -4)
|
||||
if (new_anim)
|
||||
var/obj/effect/cult_ritual/conversion/anim = new(T)
|
||||
anim.icon_state = ""
|
||||
flick("rune_convert_failure",anim)
|
||||
anim.Die()
|
||||
var/obj/item/weapon/storage/cult/coffer = new(T)
|
||||
coffer.icon_state = box_state
|
||||
var/obj/item/weapon/reagent_containers/food/drinks/cult/cup = new(coffer)
|
||||
if (istype(src,/mob/living/carbon/human) && dna)
|
||||
take_blood(cup, cup.volume)//Up to 60u
|
||||
cup.on_reagent_change()//so we get the reagentsfillings overlay
|
||||
new/obj/item/weapon/skull(coffer)
|
||||
if (ismonkey(src))
|
||||
var/list/skulless_monkeys = list(
|
||||
/mob/living/carbon/monkey/mushroom,
|
||||
/mob/living/carbon/monkey/diona,
|
||||
/mob/living/carbon/monkey/rock,
|
||||
)
|
||||
var/mob/living/carbon/monkey/M = src
|
||||
if (!(M.species_type in skulless_monkeys))
|
||||
take_blood(cup, cup.volume)//Up to 60u
|
||||
new/obj/item/weapon/skull(coffer)
|
||||
if (isslime(src))
|
||||
cup.reagents.add_reagent(SLIMEJELLY, 50)
|
||||
if (isalien(src))//w/e
|
||||
cup.reagents.add_reagent(RADIUM, 50)
|
||||
|
||||
for(var/obj/item/weapon/implant/loyalty/I in src)
|
||||
I.remove(src)
|
||||
|
||||
for(var/obj/item/I in src)
|
||||
u_equip(I)
|
||||
if(I)
|
||||
I.forceMove(T)
|
||||
I.reset_plane_and_layer()
|
||||
I.dropped(src)
|
||||
I.forceMove(coffer)
|
||||
if (delete_body)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/* Used in Cult 3.0 to get bloodstone spawn location. Might use that bit of code for something else later so I'll keep it there in the meantime.
|
||||
/proc/spawn_bloodstones(var/turf/source = null)
|
||||
//Called at the beginning of ACT III, this is basically the cult's declaration of war on the crew
|
||||
//Spawns 4 structures, one in each quarters of the station
|
||||
//When spawning, those structures break and convert stuff around them, and add a wall layer in case of space exposure.
|
||||
var/list/places_to_spawn = list()
|
||||
for (var/i = 1 to 4)
|
||||
for (var/j = 10; j > 0; j--)
|
||||
/*
|
||||
the value of i governs which corner of the map the bloodstone will try to spawn in.
|
||||
from 1 to 4, the corners will be selected in this order: North-West, South-East, North-East, South-West
|
||||
|
||||
the higher j, the further away from the center of the map will the bloodstone be. it tries 10 times per bloodstone, and searches each time closer to the center
|
||||
*/
|
||||
var/coordX = map.center_x+j*4*(((round(i/2) % 2) == 0) ? -1 : 1 )
|
||||
var/coordY = map.center_y+j*4*(((i % 2) == 0) ? -1 : 1 )
|
||||
|
||||
var/turf/T = get_turf(pick(range(j*3,locate(coordX,coordY,map.zMainStation))))
|
||||
if (!T)
|
||||
message_admins("Blood Cult: !ERROR! spawn_bloodstones() tried to select a null turf at [map.nameLong]. Debug info: i = [i], j = [j]")
|
||||
log_admin("Blood Cult: !ERROR! spawn_bloodstones() tried to select a null turf at [map.nameLong]. Debug info: i = [i], j = [j]")
|
||||
else if(!is_type_in_list(T,list(/turf/space,/turf/unsimulated,/turf/simulated/shuttle)))
|
||||
//Adding some blacklisted areas, specifically solars
|
||||
if (!istype(T.loc,/area/solar) && is_type_in_list(T.loc,the_station_areas))
|
||||
places_to_spawn += T
|
||||
break
|
||||
//A 5th bloodstone will spawn if a proper turf was given as arg (up to 100 tiles from the station center, and not in space or on a shuttle)
|
||||
if (source && (source.z == map.zMainStation) && !isspace(source.loc) && !is_on_shuttle(source) && get_dist(locate(map.center_x,map.center_y,map.zMainStation),source)<100)
|
||||
places_to_spawn.Add(source)
|
||||
for (var/T in places_to_spawn)
|
||||
new /obj/structure/cult/bloodstone(T)
|
||||
|
||||
//Cultists can use those bloodstones to locate the rest of them, they work just like station holomaps
|
||||
|
||||
for(var/obj/structure/cult/bloodstone/B in bloodstone_list)
|
||||
if (!B.loc)
|
||||
qdel(B)
|
||||
message_admins("Blood Cult: !ERROR! A blood stone was somehow spawned in nullspace. It has been destroyed.")
|
||||
log_admin("Blood Cult: !ERROR! A blood stone was somehow spawned in nullspace. It has been destroyed.")
|
||||
*/
|
||||
@@ -435,7 +435,7 @@ var/list/astral_projections = list()
|
||||
var/image/I = image('icons/role_HUD_icons.dmi', loc = imageloc, icon_state = hud_icon)
|
||||
I.pixel_x = 20 * PIXEL_MULTIPLIER
|
||||
I.pixel_y = 20 * PIXEL_MULTIPLIER
|
||||
I.plane = relative_plane(ANTAG_HUD_PLANE)
|
||||
I.plane = ANTAG_HUD_PLANE
|
||||
client.images += I
|
||||
|
||||
|
||||
|
||||
@@ -109,6 +109,13 @@
|
||||
blade.attack_hand(M)
|
||||
blade = null
|
||||
qdel(src)
|
||||
else if (!M.get_inactive_hand())//cultists can catch the blade on the fly
|
||||
blade.forceMove(loc)
|
||||
M.swap_hand() // guarrantees
|
||||
blade.attack_hand(M)
|
||||
M.swap_hand()
|
||||
blade = null
|
||||
qdel(src)
|
||||
else
|
||||
A.attackby(blade,shade)
|
||||
else
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
|
||||
var/list/runes = list()
|
||||
var/list/rune_appearances_cache = list()
|
||||
|
||||
/obj/effect/rune //Abstract, currently only supports blood as a reagent without some serious overriding.
|
||||
name = "rune"
|
||||
desc = "A strange collection of symbols drawn in blood."
|
||||
anchored = 1
|
||||
icon = 'icons/effects/uristrunes.dmi'
|
||||
icon = 'icons/effects/deityrunes.dmi'
|
||||
icon_state = ""
|
||||
layer = RUNE_LAYER
|
||||
plane = ABOVE_TURF_PLANE
|
||||
@@ -13,12 +15,12 @@
|
||||
|
||||
//Whether the rune is pulsating
|
||||
var/animated = 0
|
||||
var/activated = 0 // how many times the rune was activated. goes back to 0 if a word is erased.
|
||||
|
||||
//A rune is made of up to 3 words.
|
||||
var/runeset_identifier = "base"
|
||||
var/datum/runeword/word1
|
||||
var/datum/runeword/word2
|
||||
var/datum/runeword/word3
|
||||
var/datum/rune_word/word1
|
||||
var/datum/rune_word/word2
|
||||
var/datum/rune_word/word3
|
||||
|
||||
//An image we'll show to the AI instead of the rune
|
||||
var/image/blood_image
|
||||
@@ -47,10 +49,16 @@
|
||||
if(AI.client)
|
||||
AI.client.images += blood_image
|
||||
|
||||
var/datum/runeset/rune_set = global_runesets[runeset_identifier]
|
||||
rune_set.rune_list.Add(src)
|
||||
runes += src
|
||||
|
||||
..()
|
||||
//adding to holomaps
|
||||
var/datum/holomap_marker/holomarker = new()
|
||||
holomarker.id = HOLOMAP_MARKER_CULT_RUNE
|
||||
holomarker.filter = HOLOMAP_FILTER_CULT
|
||||
holomarker.x = src.x
|
||||
holomarker.y = src.y
|
||||
holomarker.z = src.z
|
||||
holomap_markers[HOLOMAP_MARKER_CULT_RUNE+"_\ref[src]"] = holomarker
|
||||
|
||||
|
||||
/obj/effect/rune/Destroy()
|
||||
@@ -60,9 +68,15 @@
|
||||
qdel(blood_image)
|
||||
blood_image = null
|
||||
|
||||
word1 = null
|
||||
word2 = null
|
||||
word3 = null
|
||||
if (word1)
|
||||
erase_word(word1.english,blood1)
|
||||
word1 = null
|
||||
if (word2)
|
||||
erase_word(word2.english,blood2)
|
||||
word2 = null
|
||||
if (word3)
|
||||
erase_word(word3.english,blood3)
|
||||
word3 = null
|
||||
|
||||
blood1 = null
|
||||
blood2 = null
|
||||
@@ -72,22 +86,58 @@
|
||||
active_spell.abort()
|
||||
active_spell = null
|
||||
|
||||
var/datum/runeset/rune_set = global_runesets[runeset_identifier]
|
||||
rune_set.rune_list.Remove(src)
|
||||
runes -= src
|
||||
|
||||
//removing from holomaps
|
||||
holomap_markers -= HOLOMAP_MARKER_CULT_RUNE+"_\ref[src]"
|
||||
|
||||
..()
|
||||
|
||||
/obj/effect/rune/ErasableRune()
|
||||
if (activated)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/rune/examine(var/mob/user)
|
||||
..()
|
||||
var/datum/rune_spell/rune_name = get_rune_spell(null, null, "examine", word1,word2,word3)
|
||||
|
||||
//By default everyone can read a rune, so add extra functionality in child classes if that is not wanted.
|
||||
if(can_read_rune(user) || isobserver(user))
|
||||
var/datum/rune_spell/rune_name = get_rune_spell(null, null, "examine", word1,word2,word3)
|
||||
to_chat(user, "<span class='info'>It reads: <i>[word1 ? "[word1.rune]" : ""][word2 ? " [word2.rune]" : ""][word3 ? " [word3.rune]" : ""]</i>. [rune_name ? " That's a <b>[initial(rune_name.name)]</b> rune." : "It doesn't match any rune spells."]</span>")
|
||||
if(rune_name)
|
||||
to_chat(user, initial(rune_name.desc))
|
||||
if (istype(active_spell,/datum/rune_spell/portalentrance))
|
||||
var/datum/rune_spell/portalentrance/PE = active_spell
|
||||
if (PE.network)
|
||||
to_chat(user, "<span class='info'>This entrance was attuned to the <b>[PE.network]</b> path.</span>")
|
||||
if (istype(active_spell,/datum/rune_spell/portalexit))
|
||||
var/datum/rune_spell/portalexit/PE = active_spell
|
||||
if (PE.network)
|
||||
to_chat(user, "<span class='info'>This exit was attuned to the <b>[PE.network]</b> path.</span>")
|
||||
|
||||
//"Cult" chaplains can read the words, but they have to figure out the spell themselves. Also has a chance to trigger a taunt from Nar-Sie.
|
||||
else if(istype(user, /mob/living/carbon/human) && (user.mind.assigned_role == "Chaplain"))
|
||||
var/list/cult_blood_chaplain = list("cult", "narsie", "nar'sie", "narnar", "nar-sie")
|
||||
var/list/cult_clock_chaplain = list("ratvar", "clockwork", "ratvarism")
|
||||
if (religion_name in cult_blood_chaplain)
|
||||
to_chat(user, "<span class='info'>It reads: <i>[word1.rune] [word2.rune] [word3.rune]</i>. What spell was that already?...</span>")
|
||||
if (prob(5))
|
||||
spawn(50)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>???-???</span> murmurs, <span class='sinister'>[pick(\
|
||||
"Your toys won't get you much further",\
|
||||
"Bitter that you weren't chosen?",\
|
||||
"I dig your style, but I crave for your blood.",\
|
||||
"Shall we gamble then? Obviously blood is the only acceptable bargaining chip")].</span></span>")
|
||||
|
||||
//RIP Velard
|
||||
else if (religion_name in cult_clock_chaplain)
|
||||
to_chat(user, "<span class='info'>It reads a bunch of stupid shit.</span>")
|
||||
if (prob(5))
|
||||
spawn(50)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>???-???</span> murmurs, <span class='sinister'>[pick(\
|
||||
"Oh just fuck off",)].</span></span>")
|
||||
|
||||
/obj/effect/rune/proc/can_read_rune(var/mob/user) //Overload for specific criteria.
|
||||
return 1
|
||||
return iscultist(user)
|
||||
|
||||
/obj/effect/rune/cultify()
|
||||
return
|
||||
@@ -99,6 +149,30 @@
|
||||
active_spell.salt_act(T)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/rune/proc/write_word(var/word,var/datum/reagent/blood/blood)
|
||||
if (!word)
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/write_color = DEFAULT_BLOOD
|
||||
if (blood && blood.data["blood_colour"])
|
||||
write_color = blood.data["blood_colour"]
|
||||
anim(target = T, a_icon = 'icons/effects/deityrunes.dmi', flick_anim = "[word]-write", lay = layer+0.1, col = write_color, plane = plane)
|
||||
|
||||
/obj/effect/rune/proc/erase_word(var/word,var/datum/reagent/blood/blood)
|
||||
if (!word)
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/erase_color = DEFAULT_BLOOD
|
||||
if (blood && blood.data["blood_colour"])
|
||||
erase_color = blood.data["blood_colour"]
|
||||
anim(target = T, a_icon = 'icons/effects/deityrunes.dmi', flick_anim = "[word]-erase", lay = layer+0.1, col = erase_color, plane = plane)
|
||||
|
||||
/obj/effect/rune/proc/cast_word(var/word)
|
||||
if (!word)
|
||||
return
|
||||
var/atom/movable/overlay/A = anim(target = get_turf(src), a_icon = 'icons/effects/deityrunes.dmi', a_icon_state = "[word]-tear", lay = layer+0.2, plane = plane)
|
||||
animate(A, alpha = 0,time = 5)
|
||||
|
||||
/obj/effect/rune/ex_act(var/severity)
|
||||
switch (severity)
|
||||
if (1)
|
||||
@@ -113,96 +187,78 @@
|
||||
/obj/effect/rune/blob_act()
|
||||
return
|
||||
|
||||
/obj/effect/rune/update_icon()
|
||||
/obj/effect/rune/update_icon(var/draw_up_to = 3)
|
||||
var/datum/rune_spell/spell = get_rune_spell(null, null, "examine", word1, word2, word3)
|
||||
|
||||
if(spell) // && initial(spell.Act_restriction) <= veil_thickness) Add to bloodcult
|
||||
if (active_spell)
|
||||
return
|
||||
|
||||
overlays.len = 0
|
||||
|
||||
if(spell && activated)
|
||||
animated = 1
|
||||
draw_up_to = 3
|
||||
else
|
||||
animated = 0
|
||||
|
||||
var/lookup = ""
|
||||
if (word1)
|
||||
lookup += "[word1.icon_state]-[animated]-[blood1.data["blood_colour"]]"
|
||||
if (word2)
|
||||
lookup += "-[word2.icon_state]-[animated]-[blood2.data["blood_colour"]]"
|
||||
if (word3)
|
||||
lookup += "-[word3.icon_state]-[animated]-[blood3.data["blood_colour"]]"
|
||||
lookup += "[word1.english]-[animated]-[blood1.data["blood_colour"]]"
|
||||
if (word2 && draw_up_to >= 2)
|
||||
lookup += "-[word2.english]-[animated]-[blood2.data["blood_colour"]]"
|
||||
if (word3 && draw_up_to >= 3)
|
||||
lookup += "-[word3.english]-[animated]-[blood3.data["blood_colour"]]"
|
||||
|
||||
if (lookup in uristrune_cache)
|
||||
icon = uristrune_cache[lookup]
|
||||
var/image/rune_render
|
||||
if (lookup in rune_appearances_cache)
|
||||
rune_render = image(rune_appearances_cache[lookup])
|
||||
else
|
||||
var/icon/I1 = icon('icons/effects/uristrunes.dmi', "")
|
||||
var/image/I1 = image('icons/effects/deityrunes.dmi',src,"")
|
||||
if (word1)
|
||||
I1 = make_iconcache(word1,blood1,animated)
|
||||
var/icon/I2 = icon('icons/effects/uristrunes.dmi', "")
|
||||
if (word2)
|
||||
I2 = make_iconcache(word2,blood2,animated)
|
||||
var/icon/I3 = icon('icons/effects/uristrunes.dmi', "")
|
||||
if (word3)
|
||||
I3 = make_iconcache(word3,blood3,animated)
|
||||
I1.icon_state = word1.english
|
||||
if (blood1.data["blood_colour"])
|
||||
I1.color = blood1.data["blood_colour"]
|
||||
var/image/I2 = image('icons/effects/deityrunes.dmi',src,"")
|
||||
if (word2 && draw_up_to >= 2)
|
||||
I2.icon_state = word2.english
|
||||
if (blood2.data["blood_colour"])
|
||||
I2.color = blood2.data["blood_colour"]
|
||||
var/image/I3 = image('icons/effects/deityrunes.dmi',src,"")
|
||||
if (word3 && draw_up_to >= 3)
|
||||
I3.icon_state = word3.english
|
||||
if (blood3.data["blood_colour"])
|
||||
I3.color = blood3.data["blood_colour"]
|
||||
|
||||
var/icon/I = icon('icons/effects/uristrunes.dmi', "")
|
||||
I.Blend(I1, ICON_OVERLAY)
|
||||
I.Blend(I2, ICON_OVERLAY)
|
||||
I.Blend(I3, ICON_OVERLAY)
|
||||
icon = I
|
||||
uristrune_cache[lookup] = I
|
||||
rune_render = image('icons/effects/deityrunes.dmi',src,"")
|
||||
rune_render.overlays += I1
|
||||
rune_render.overlays += I2
|
||||
rune_render.overlays += I3
|
||||
|
||||
if(animated)
|
||||
if (word1)
|
||||
var/image/I = image('icons/effects/deityrunes.dmi',src,"[word1.english]-tear")
|
||||
I.color = "black"
|
||||
I.appearance_flags = RESET_COLOR
|
||||
rune_render.overlays += I
|
||||
if (word2)
|
||||
var/image/I = image('icons/effects/deityrunes.dmi',src,"[word2.english]-tear")
|
||||
I.color = "black"
|
||||
I.appearance_flags = RESET_COLOR
|
||||
rune_render.overlays += I
|
||||
if (word3)
|
||||
var/image/I = image('icons/effects/deityrunes.dmi',src,"[word3.english]-tear")
|
||||
I.color = "black"
|
||||
I.appearance_flags = RESET_COLOR
|
||||
rune_render.overlays += I
|
||||
|
||||
rune_appearances_cache[lookup] = rune_render
|
||||
overlays += rune_render
|
||||
|
||||
if(animated)
|
||||
idle_pulse()
|
||||
else
|
||||
animate(src)
|
||||
|
||||
/obj/effect/rune/proc/make_iconcache(var/datum/runeword/word, var/datum/reagent/blood/blood, var/animated) //For caching rune icons
|
||||
var/icon/I = icon('icons/effects/uristrunes.dmi', "")
|
||||
if (!blood)
|
||||
blood = new
|
||||
var/lookupword = "[word.icon_state]-[animated]-[blood.data["blood_colour"]]"
|
||||
if(lookupword in uristrune_cache)
|
||||
I = uristrune_cache[lookupword]
|
||||
else
|
||||
I.Blend(icon('icons/effects/uristrunes.dmi', word.icon_state), ICON_OVERLAY)
|
||||
var/finalblood = blood.data["blood_colour"]
|
||||
var/list/blood_hsl = rgb2hsl(GetRedPart(finalblood),GetGreenPart(finalblood),GetBluePart(finalblood))
|
||||
if(blood_hsl.len)
|
||||
var/list/blood_rgb = hsl2rgb(blood_hsl[1],blood_hsl[2],50)//producing a color that is neither too bright nor too dark
|
||||
if(blood_rgb.len)
|
||||
finalblood = rgb(blood_rgb[1],blood_rgb[2],blood_rgb[3])
|
||||
|
||||
var/bc1 = finalblood
|
||||
var/bc2 = finalblood
|
||||
bc1 += "C8"
|
||||
bc2 += "64"
|
||||
|
||||
I.SwapColor(rgb(0, 0, 0, 100), bc1)
|
||||
I.SwapColor(rgb(0, 0, 0, 50), bc1)
|
||||
|
||||
for(var/x = 1, x <= WORLD_ICON_SIZE, x++)
|
||||
for(var/y = 1, y <= WORLD_ICON_SIZE, y++)
|
||||
var/p = I.GetPixel(x, y)
|
||||
|
||||
if(p == null)
|
||||
var/n = I.GetPixel(x, y + 1)
|
||||
var/s = I.GetPixel(x, y - 1)
|
||||
var/e = I.GetPixel(x + 1, y)
|
||||
var/w = I.GetPixel(x - 1, y)
|
||||
|
||||
if(n == "#000000" || s == "#000000" || e == "#000000" || w == "#000000")
|
||||
I.DrawBox(bc1, x, y)
|
||||
|
||||
else
|
||||
var/ne = I.GetPixel(x + 1, y + 1)
|
||||
var/se = I.GetPixel(x + 1, y - 1)
|
||||
var/nw = I.GetPixel(x - 1, y + 1)
|
||||
var/sw = I.GetPixel(x - 1, y - 1)
|
||||
|
||||
if(ne == "#000000" || se == "#000000" || nw == "#000000" || sw == "#000000")
|
||||
I.DrawBox(bc2, x, y)
|
||||
|
||||
I.MapColors(0.5,0,0,0,0.5,0,0,0,0.5)//we'll darken that color a bit
|
||||
return I
|
||||
|
||||
/obj/effect/rune/proc/idle_pulse()
|
||||
//This masterpiece of a color matrix stack produces a nice animation no matter which color the rune is.
|
||||
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)//1
|
||||
@@ -241,9 +297,6 @@
|
||||
else
|
||||
animate(src)
|
||||
|
||||
/obj/effect/rune/attackby(obj/I, mob/user)
|
||||
..()
|
||||
|
||||
|
||||
/obj/effect/rune/Crossed(var/atom/movable/mover)
|
||||
if (ismob(mover))
|
||||
@@ -285,7 +338,20 @@
|
||||
bleeding = user.check_bodypart_bleeding(HANDS)
|
||||
user.assume_contact_diseases(virus2,src,block,bleeding)
|
||||
|
||||
/obj/effect/rune/proc/trigger(var/mob/living/user)
|
||||
/obj/effect/rune/attackby(obj/I, mob/user)
|
||||
..()
|
||||
if(isholyweapon(I))
|
||||
to_chat(user, "<span class='notice'>You disrupt the vile magic with the deadening field of \the [I]!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(I, /obj/item/weapon/tome) || istype(I, /obj/item/weapon/melee/cultblade) || istype(I, /obj/item/weapon/melee/soulblade) || istype(I, /obj/item/weapon/melee/blood_dagger))
|
||||
trigger(user)
|
||||
if(istype(I, /obj/item/weapon/talisman))
|
||||
var/obj/item/weapon/talisman/T = I
|
||||
T.imbue(user,src)
|
||||
return
|
||||
|
||||
/obj/effect/rune/proc/trigger(var/mob/living/user, var/talisman_trigger=0)
|
||||
user.delayNextAttack(5)
|
||||
|
||||
if(!iscultist(user))
|
||||
@@ -298,14 +364,13 @@
|
||||
to_chat(user, "<span class='danger'>You find yourself unable to focus your mind on the arcane words of the rune.</span>")
|
||||
return
|
||||
|
||||
|
||||
if(!user.checkTattoo(TATTOO_SILENT))
|
||||
if(user.is_wearing_item(/obj/item/clothing/mask/muzzle, slot_wear_mask))
|
||||
to_chat(user, "<span class='danger'>You are unable to speak the words of the rune because of \the [user.wear_mask].</span>")
|
||||
return
|
||||
|
||||
if(user.is_mute())
|
||||
to_chat(user, "<span class='danger'>You don't have the ability to perform rituals without voicing the incantations. There has to be some way...</span>")
|
||||
to_chat(user, "<span class='danger'>You don't have the ability to perform rituals without voicing the incantations, there has to be some way...</span>")
|
||||
return
|
||||
|
||||
if(!word1 || !word2 || !word3 || prob(user.getBrainLoss()))
|
||||
@@ -313,18 +378,25 @@
|
||||
|
||||
add_hiddenprint(user)
|
||||
|
||||
if (active_spell)
|
||||
active_spell.midcast(user)
|
||||
if(active_spell)//rune is already channeling a spell? let's see if we can interact with it somehow.
|
||||
if(talisman_trigger)
|
||||
var/datum/rune_spell/active_spell_typecast = active_spell
|
||||
if(!istype(active_spell_typecast))
|
||||
return
|
||||
active_spell_typecast.midcast_talisman(user)
|
||||
else
|
||||
active_spell.midcast(user)
|
||||
return
|
||||
|
||||
reveal()
|
||||
reveal()//concealed rune get automatically revealed upon use (either through using Seer or an attuned talisman). Placed after midcast: exception for Path talismans.
|
||||
|
||||
active_spell = get_rune_spell(user, src, "ritual", word1, word2, word3)
|
||||
|
||||
if (!active_spell)
|
||||
return fizzle(user)
|
||||
else if (active_spell.destroying_self)
|
||||
active_spell = null
|
||||
else
|
||||
if (active_spell.destroying_self)
|
||||
active_spell = null
|
||||
|
||||
/obj/effect/rune/proc/fizzle(var/mob/living/user)
|
||||
var/silent = user.checkTattoo(TATTOO_SILENT)
|
||||
@@ -338,17 +410,33 @@
|
||||
/obj/effect/rune/proc/conceal()
|
||||
if(active_spell && !active_spell.can_conceal)
|
||||
active_spell.abort(RITUALABORT_CONCEAL)
|
||||
animate(src, alpha = 0, time = 5)
|
||||
alpha = 0
|
||||
if (word1)
|
||||
erase_word(word1.english,blood1)
|
||||
if (word2)
|
||||
erase_word(word2.english,blood2)
|
||||
if (word3)
|
||||
erase_word(word3.english,blood3)
|
||||
spawn(6)
|
||||
invisibility=INVISIBILITY_OBSERVER
|
||||
alpha = 127
|
||||
|
||||
/obj/effect/rune/proc/reveal() //Returns 1 if rune was revealed from a invisible state.
|
||||
if(invisibility != 0)
|
||||
alpha = 0
|
||||
invisibility=0
|
||||
animate(src, alpha = 255, time = 5)
|
||||
one_pulse()
|
||||
if (!(active_spell?.custom_rune))
|
||||
overlays.len = 0
|
||||
if (word1)
|
||||
write_word(word1.english,blood1)
|
||||
if (word2)
|
||||
write_word(word2.english,blood2)
|
||||
if (word3)
|
||||
write_word(word3.english,blood3)
|
||||
spawn(8)
|
||||
alpha = 255
|
||||
update_icon()
|
||||
else
|
||||
alpha = 255
|
||||
conceal_cooldown = 1
|
||||
spawn(100)
|
||||
if (src && loc)
|
||||
@@ -385,131 +473,7 @@
|
||||
if(istype(V))
|
||||
virus2["[V.uniqueID]-[V.subID]"] = V.getcopy()
|
||||
|
||||
/////////////////////////BLOOD CULT RUNES//////////////////////
|
||||
|
||||
/obj/effect/rune/blood_cult
|
||||
desc = "A strange collection of symbols drawn in blood."
|
||||
runeset_identifier = "blood_cult"
|
||||
|
||||
/obj/effect/rune/blood_cult/New()
|
||||
..()
|
||||
var/datum/holomap_marker/holomarker = new()
|
||||
holomarker.id = HOLOMAP_MARKER_CULT_RUNE
|
||||
holomarker.filter = HOLOMAP_FILTER_CULT
|
||||
holomarker.x = src.x
|
||||
holomarker.y = src.y
|
||||
holomarker.z = src.z
|
||||
holomap_markers[HOLOMAP_MARKER_CULT_RUNE+"_\ref[src]"] = holomarker
|
||||
|
||||
/obj/effect/rune/blood_cult/Destroy()
|
||||
..()
|
||||
holomap_markers -= HOLOMAP_MARKER_CULT_RUNE+"_\ref[src]" //Add to blood cult rune
|
||||
|
||||
/obj/effect/rune/blood_cult/attackby(obj/I, mob/user)
|
||||
..()
|
||||
if(isholyweapon(I))
|
||||
to_chat(user, "<span class='notice'>You disrupt the vile magic with the deadening field of \the [I]!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
if(istype(I, /obj/item/weapon/tome) || istype(I, /obj/item/weapon/melee/cultblade) || istype(I, /obj/item/weapon/melee/soulblade))
|
||||
trigger(user)
|
||||
if(istype(I, /obj/item/weapon/talisman))
|
||||
var/obj/item/weapon/talisman/T = I
|
||||
T.imbue(user,src)
|
||||
return
|
||||
|
||||
/obj/effect/rune/blood_cult/trigger(var/mob/living/user, var/talisman_trigger=0)
|
||||
user.delayNextAttack(5)
|
||||
|
||||
if(!iscultist(user))
|
||||
to_chat(user, "<span class='danger'>You can't mouth the arcane scratchings without fumbling over them.</span>")
|
||||
return
|
||||
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
if (C.occult_muted())
|
||||
to_chat(user, "<span class='danger'>You find yourself unable to focus your mind on the arcane words of the rune.</span>")
|
||||
return
|
||||
|
||||
if(!user.checkTattoo(TATTOO_SILENT))
|
||||
if(user.is_wearing_item(/obj/item/clothing/mask/muzzle, slot_wear_mask))
|
||||
to_chat(user, "<span class='danger'>You are unable to speak the words of the rune because of \the [user.wear_mask].</span>")
|
||||
return
|
||||
|
||||
if(user.is_mute())
|
||||
to_chat(user, "<span class='danger'>You don't have the ability to perform rituals without voicing the incantations, there has to be some way...</span>")
|
||||
return
|
||||
|
||||
if(!word1 || !word2 || !word3 || prob(user.getBrainLoss()))
|
||||
return fizzle(user)
|
||||
|
||||
add_hiddenprint(user)
|
||||
|
||||
if(active_spell)//rune is already channeling a spell? let's see if we can interact with it somehow.
|
||||
if(talisman_trigger)
|
||||
var/datum/rune_spell/blood_cult/active_spell_typecast = active_spell
|
||||
if(!istype(active_spell_typecast))
|
||||
return
|
||||
active_spell_typecast.midcast_talisman(user)
|
||||
else
|
||||
active_spell.midcast(user)
|
||||
return
|
||||
|
||||
reveal()//concealed rune get automatically revealed upon use (either through using Seer or an attuned talisman). Placed after midcast: exception for Path talismans.
|
||||
|
||||
active_spell = get_rune_spell(user, src, "ritual", word1, word2, word3)
|
||||
|
||||
if (!active_spell)
|
||||
return fizzle(user)
|
||||
else if (active_spell.destroying_self)
|
||||
active_spell = null
|
||||
|
||||
/obj/effect/rune/blood_cult/can_read_rune(var/mob/user) //Overload for specific criteria.
|
||||
return iscultist(user)
|
||||
|
||||
/obj/effect/rune/blood_cult/examine(var/mob/user)
|
||||
..()
|
||||
|
||||
if(can_read_rune(user) || isobserver(user))
|
||||
var/datum/rune_spell/blood_cult/rune_name = get_rune_spell(null, null, "examine", word1,word2,word3)
|
||||
if(rune_name)
|
||||
if (initial(rune_name.Act_restriction) <= veil_thickness)
|
||||
to_chat(user, initial(rune_name.desc))
|
||||
if (istype(active_spell,/datum/rune_spell/blood_cult/portalentrance))
|
||||
var/datum/rune_spell/blood_cult/portalentrance/PE = active_spell
|
||||
if (PE.network)
|
||||
to_chat(user, "<span class='info'>This entrance was attuned to the <b>[PE.network]</b> path.</span>")
|
||||
if (istype(active_spell,/datum/rune_spell/blood_cult/portalexit))
|
||||
var/datum/rune_spell/blood_cult/portalexit/PE = active_spell
|
||||
if (PE.network)
|
||||
to_chat(user, "<span class='info'>This exit was attuned to the <b>[PE.network]</b> path.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>The veil is still too thick for you to draw power from this rune.</span>")
|
||||
|
||||
//"Cult" chaplains can read the words, but they have to figure out the spell themselves. Also has a chance to trigger a taunt from Nar-Sie.
|
||||
else if(istype(user, /mob/living/carbon/human) && (user.mind.assigned_role == "Chaplain"))
|
||||
var/list/cult_blood_chaplain = list("cult", "narsie", "nar'sie", "narnar", "nar-sie")
|
||||
var/list/cult_clock_chaplain = list("ratvar", "clockwork", "ratvarism")
|
||||
if (religion_name in cult_blood_chaplain)
|
||||
to_chat(user, "<span class='info'>It reads: <i>[word1.rune] [word2.rune] [word3.rune]</i>. What spell was that already?...</span>")
|
||||
if (prob(5))
|
||||
spawn(50)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>???-???</span> murmurs, <span class='sinister'>[pick(\
|
||||
"Your toys won't get you much further",\
|
||||
"Bitter that you weren't chosen?",\
|
||||
"I dig your style, but I crave for your blood.",\
|
||||
"Shall we gamble then? Obviously blood is the only acceptable bargaining chip")].</span></span>")
|
||||
|
||||
//RIP Velard
|
||||
else if (religion_name in cult_clock_chaplain)
|
||||
to_chat(user, "<span class='info'>It reads a bunch of stupid shit.</span>")
|
||||
if (prob(5))
|
||||
spawn(50)
|
||||
to_chat(user, "<span class='game say'><span class='danger'>???-???</span> murmurs, <span class='sinister'>[pick(\
|
||||
"Oh just fuck off",)].</span></span>")
|
||||
|
||||
|
||||
/proc/write_rune_word(var/turf/T, var/word = null, var/datum/reagent/blood/source, var/mob/caster = null)
|
||||
/proc/write_rune_word(var/turf/T, var/datum/rune_word/word = null, var/datum/reagent/blood/source, var/mob/caster = null)
|
||||
if (!word)
|
||||
return RUNE_WRITE_CANNOT
|
||||
|
||||
@@ -522,10 +486,8 @@
|
||||
var/newrune = FALSE
|
||||
var/obj/effect/rune/rune = locate() in T
|
||||
if(!rune)
|
||||
var/datum/runeword/rune_typecast = word
|
||||
if(rune_typecast.identifier == "blood_cult") //Lazy fix because I'm not sure how to modularize this automatically. Fix if you want to.//WHYYYYYYYYYYY
|
||||
rune = new /obj/effect/rune/blood_cult(T)
|
||||
newrune = TRUE
|
||||
rune = new /obj/effect/rune(T)
|
||||
newrune = TRUE
|
||||
|
||||
if (rune.word1 && rune.word2 && rune.word3)
|
||||
return RUNE_WRITE_CANNOT
|
||||
@@ -536,6 +498,8 @@
|
||||
message_admins("BLOODCULT: [key_name(caster)] has created a new rune at [formatJumpTo(T)].")
|
||||
rune.add_hiddenprint(caster)
|
||||
|
||||
rune.write_word(word.english,source)
|
||||
|
||||
if (!rune.word1)
|
||||
rune.word1 = word
|
||||
rune.blood1 = new()
|
||||
@@ -553,6 +517,8 @@
|
||||
rune.blood1.data["blood_DNA"] = "O+"
|
||||
if (source.data["virus2"])
|
||||
rune.blood1.data["virus2"] = virus_copylist(source.data["virus2"])
|
||||
spawn (8)
|
||||
rune.update_icon(1)
|
||||
|
||||
else if (!rune.word2)
|
||||
rune.word2 = word
|
||||
@@ -571,6 +537,8 @@
|
||||
rune.blood2.data["blood_DNA"] = "O+"
|
||||
if (source.data["virus2"])
|
||||
rune.blood2.data["virus2"] = virus_copylist(source.data["virus2"])
|
||||
spawn (8)
|
||||
rune.update_icon(2)
|
||||
|
||||
else if (!rune.word3)
|
||||
rune.word3 = word
|
||||
@@ -589,15 +557,15 @@
|
||||
rune.blood3.data["blood_DNA"] = "O+"
|
||||
if (source.data["virus2"])
|
||||
rune.blood3.data["virus2"] = virus_copylist(source.data["virus2"])
|
||||
spawn (8)
|
||||
rune.update_icon(3)
|
||||
|
||||
rune.manage_diseases(source)
|
||||
|
||||
rune.update_icon()
|
||||
if (rune.blood3)
|
||||
return RUNE_WRITE_COMPLETE
|
||||
return RUNE_WRITE_CONTINUE
|
||||
|
||||
|
||||
/proc/erase_rune_word(var/turf/T)
|
||||
var/obj/effect/rune/rune = locate() in T
|
||||
if(!rune)
|
||||
@@ -606,6 +574,7 @@
|
||||
var/word_erased
|
||||
|
||||
if(rune.word3)
|
||||
rune.erase_word(rune.word3.english, rune.blood3)
|
||||
word_erased = rune.word3.rune
|
||||
rune.word3 = null
|
||||
rune.blood3 = null
|
||||
@@ -615,11 +584,13 @@
|
||||
rune.active_spell = null
|
||||
rune.overlays.len = 0
|
||||
else if(rune.word2)
|
||||
rune.erase_word(rune.word2.english, rune.blood2)
|
||||
word_erased = rune.word2.rune
|
||||
rune.word2 = null
|
||||
rune.blood2 = null
|
||||
rune.update_icon()
|
||||
else if(rune.word1)
|
||||
rune.erase_word(rune.word1.english, rune.blood1)
|
||||
word_erased = rune.word1.rune
|
||||
rune.word1 = null
|
||||
rune.blood1 = null
|
||||
@@ -628,4 +599,18 @@
|
||||
message_admins("Error! Trying to erase a word from a rune with no words!")
|
||||
qdel(rune)
|
||||
return null
|
||||
rune.activated = 0
|
||||
return word_erased
|
||||
|
||||
|
||||
/proc/write_full_rune(var/turf/T, var/spell_type, var/datum/reagent/blood/source, var/mob/caster = null)
|
||||
if (!spell_type)
|
||||
return
|
||||
|
||||
var/datum/rune_spell/spell_instance = spell_type
|
||||
var/datum/rune_word/word1_instance = initial(spell_instance.word1)
|
||||
var/datum/rune_word/word2_instance = initial(spell_instance.word2)
|
||||
var/datum/rune_word/word3_instance = initial(spell_instance.word3)
|
||||
write_rune_word(T, rune_words[initial(word1_instance.english)], source, caster)
|
||||
write_rune_word(T, rune_words[initial(word2_instance.english)], source, caster)
|
||||
write_rune_word(T, rune_words[initial(word3_instance.english)], source, caster)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,95 @@
|
||||
|
||||
// Rune Spells that aren't listed when the player tries to draw a guided rune.
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// SUMMON TOME //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//Reason: Redundant with paraphernalia. No harm in keeping the rune somewhat usable until another use is found for that word combination.
|
||||
|
||||
/datum/rune_spell/summontome
|
||||
secret = TRUE
|
||||
name = "Summon Tome"
|
||||
desc = "Bring forth an arcane tome filled with Nar-Sie's knowledge."
|
||||
desc_talisman = "Turns into an arcane tome upon use."
|
||||
invocation = "N'ath reth sh'yro eth d'raggathnor!"
|
||||
word1 = /datum/rune_word/see
|
||||
word2 = /datum/rune_word/blood
|
||||
word3 = /datum/rune_word/hell
|
||||
cost_invoke = 4
|
||||
page = ""
|
||||
|
||||
/datum/rune_spell/summontome/cast()
|
||||
var/obj/effect/rune/R = spell_holder
|
||||
R.one_pulse()
|
||||
|
||||
if (pay_blood())
|
||||
spell_holder.visible_message("<span class='rose'>The rune's symbols merge into each others, and an Arcane Tome takes form in their place</span>")
|
||||
var/turf/T = get_turf(spell_holder)
|
||||
var/obj/item/weapon/tome/AT = new (T)
|
||||
anim(target = AT, a_icon = 'icons/effects/effects.dmi', flick_anim = "tome_spawn")
|
||||
qdel(spell_holder)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/datum/rune_spell/summontome/cast_talisman()//The talisman simply turns into a tome.
|
||||
var/turf/T = get_turf(spell_holder)
|
||||
var/obj/item/weapon/tome/AT = new (T)
|
||||
if (spell_holder == activator.get_active_hand())
|
||||
activator.drop_item(spell_holder, T)
|
||||
activator.put_in_active_hand(AT)
|
||||
else//are we using the talisman from a tome?
|
||||
activator.put_in_hands(AT)
|
||||
flick("tome_spawn",AT)
|
||||
qdel(src)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// STREAM //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//Reason: we don't want a new cultist player to use this rune by accident, better leave it to savvy ones
|
||||
|
||||
/datum/rune_spell/stream
|
||||
secret = TRUE
|
||||
name = "Stream"
|
||||
desc = "Start or stop streaming on Spess.TV."
|
||||
desc_talisman = "Start or stop streaming on Spess.TV."
|
||||
invocation = "L'k' c'mm'nt 'n' s'bscr'b! P'g ch'mp! Kappah!"
|
||||
word1 = /datum/rune_word/other
|
||||
word2 = /datum/rune_word/see
|
||||
word3 = /datum/rune_word/self
|
||||
page = "This rune lets you start (or stop) streaming on Spess.TV so that you can let your audience watch and cheer for you while you slay infidels in the name of Nar-sie. #Sponsored"
|
||||
|
||||
/datum/rune_spell/stream/cast()
|
||||
var/datum/role/streamer/streamer = activator.mind.GetRole(STREAMER)
|
||||
if(!streamer)
|
||||
streamer = new /datum/role/streamer
|
||||
streamer.team = ESPORTS_CULTISTS
|
||||
if(!streamer.AssignToRole(activator.mind, 1))
|
||||
streamer.Drop()
|
||||
return
|
||||
streamer.OnPostSetup()
|
||||
streamer.Greet(GREET_DEFAULT)
|
||||
streamer.AnnounceObjectives()
|
||||
streamer.team = ESPORTS_CULTISTS
|
||||
if(!streamer.camera)
|
||||
streamer.set_camera(new /obj/machinery/camera/arena/spesstv(activator))
|
||||
streamer.toggle_streaming()
|
||||
qdel(src)
|
||||
|
||||
/*
|
||||
Hall of fame of previous deprecated runes, might redesign later, noting their old word combinations there so I can easily retrieve them later.
|
||||
|
||||
MANIFEST GHOST: Blood See Travel
|
||||
SACRIFICE: Hell Blood Join
|
||||
DRAIN BLOOD: Travel Blood Self
|
||||
BLOOD BOIL: Destroy See Blood
|
||||
TEAR REALITY: Hell Join Self
|
||||
|
||||
*/
|
||||
@@ -1,11 +1,14 @@
|
||||
var/list/uristrune_cache = list()
|
||||
|
||||
/spell/cult
|
||||
panel = "Cult"
|
||||
override_base = "cult"
|
||||
user_type = USER_TYPE_CULT
|
||||
|
||||
/spell/cult/trace_rune //Abstract, base for all blood-based rune systems
|
||||
////////////////////BLOOD CULT DRAW RUNE////////////////////////
|
||||
|
||||
// Those two spells replaced by the Cultist mind UI abilities. Keeping those commented out for now so I can more easily salvage some of it code later.
|
||||
/*
|
||||
/spell/cult/trace_rune
|
||||
name = "Trace Rune"
|
||||
desc = "(1 BLOOD) Use available blood to write down words. Three words form a rune."
|
||||
hud_state = "cult_word"
|
||||
@@ -21,52 +24,17 @@ var/list/uristrune_cache = list()
|
||||
cast_delay = 15
|
||||
|
||||
var/list/data = list()
|
||||
var/runeset_identifier = null
|
||||
var/datum/runeword/word = null
|
||||
var/datum/rune_word/word = null
|
||||
var/obj/effect/rune/rune = null
|
||||
var/datum/rune_spell/spell = null
|
||||
var/continue_drawing = 0
|
||||
var/blood_cost = 1
|
||||
|
||||
|
||||
/spell/cult/trace_rune/choose_targets(var/mob/user = usr)
|
||||
return list(user)
|
||||
|
||||
/spell/cult/trace_rune/before_channel(mob/user)
|
||||
if(continue_drawing) //Resets the current spell (tome selection) if continue_drawing is not 1.
|
||||
continue_drawing = 0
|
||||
else
|
||||
spell = null
|
||||
return 0
|
||||
|
||||
/spell/cult/trace_rune/spell_do_after(var/mob/user, var/delay, var/numticks = 3)
|
||||
return ..()
|
||||
//Each variant of rune is handled in their respective class.
|
||||
|
||||
/spell/cult/trace_rune/cast(var/list/targets, var/mob/living/carbon/user)
|
||||
if(rune)
|
||||
if(rune.word1 && rune.word2 && rune.word3)
|
||||
to_chat(user, "<span class='warning'>You cannot add more than 3 words to a rune.</span>")
|
||||
return
|
||||
else if(rune.runeset_identifier != runeset_identifier)
|
||||
to_chat(user, "<span class='warning'>This type of rune is incompatible with the one on the ground.</span>")
|
||||
return
|
||||
var/datum/runeset/rune_set = global_runesets[runeset_identifier]
|
||||
if(write_rune_word(get_turf(user), rune_set.words[word], data["blood"], caster = user) == RUNE_WRITE_CONTINUE)
|
||||
continue_drawing = 1
|
||||
|
||||
perform(user) //Recursion for drawing runes in a row with tome.
|
||||
|
||||
////////////////////BLOOD CULT DRAW RUNE////////////////////////
|
||||
|
||||
/spell/cult/trace_rune/blood_cult
|
||||
name = "Trace Rune"
|
||||
desc = "(1 BLOOD) Use available blood to write down words. Three words form a rune."
|
||||
|
||||
cast_delay = 15
|
||||
|
||||
runeset_identifier = "blood_cult"
|
||||
|
||||
/spell/cult/trace_rune/blood_cult/before_channel(mob/user)
|
||||
if(continue_drawing) //Resets the current spell (tome selection) if continue_drawing is not 1.
|
||||
continue_drawing = 0
|
||||
else
|
||||
@@ -81,8 +49,7 @@ var/list/uristrune_cache = list()
|
||||
to_chat(user,"<span class='danger'>You find yourself unable to focus your mind on the words of Nar-Sie.</span>")
|
||||
return muted
|
||||
|
||||
/spell/cult/trace_rune/blood_cult/spell_do_after(var/mob/user, var/delay, var/numticks = 3)
|
||||
|
||||
/spell/cult/trace_rune/spell_do_after(var/mob/user, var/delay, var/numticks = 3)
|
||||
if(block) //Part of class spell, gets reset back to 0 after done casting. Prevents spamming.
|
||||
return 0
|
||||
block = 1
|
||||
@@ -109,7 +76,7 @@ var/list/uristrune_cache = list()
|
||||
to_chat(user, "<span class='warning'>Without reading the tome, you have trouble continuing to draw the arcane words.</span>")
|
||||
return 0
|
||||
else
|
||||
var/datum/runeword/blood_cult/instance
|
||||
var/datum/rune_word/instance
|
||||
if(!rune)
|
||||
instance = initial(spell.word1)
|
||||
else if (rune.word1.type != initial(spell.word1))
|
||||
@@ -130,11 +97,10 @@ var/list/uristrune_cache = list()
|
||||
else if(tome) //Else if they want to begin starting to draw with the help of a tome, grab all the available runes they can draw
|
||||
var/list/available_runes = list()
|
||||
var/i = 1
|
||||
for(var/blood_spell in subtypesof(/datum/rune_spell/blood_cult))
|
||||
var/datum/rune_spell/blood_cult/instance = blood_spell
|
||||
if(initial(instance.Act_restriction) <= veil_thickness)
|
||||
available_runes.Add("\Roman[i]-[initial(instance.name)]")
|
||||
available_runes["\Roman[i]-[initial(instance.name)]"] = instance
|
||||
for(var/blood_spell in subtypesof(/datum/rune_spell))
|
||||
var/datum/rune_spell/instance = blood_spell
|
||||
available_runes.Add("\Roman[i]-[initial(instance.name)]")
|
||||
available_runes["\Roman[i]-[initial(instance.name)]"] = instance
|
||||
i++
|
||||
if(tome.state == TOME_CLOSED)
|
||||
tome.icon_state = "tome-open"
|
||||
@@ -144,7 +110,7 @@ var/list/uristrune_cache = list()
|
||||
tome.state = TOME_OPEN
|
||||
var/spell_name = input(user,"Draw a rune with the help of the Arcane Tome.", "Trace Complete Rune", null) as null|anything in available_runes
|
||||
spell = available_runes[spell_name]
|
||||
var/datum/runeword/blood_cult/instance
|
||||
var/datum/rune_word/instance
|
||||
if(!rune)
|
||||
instance = initial(spell.word1)
|
||||
else if (rune.word1.type != initial(spell.word1))
|
||||
@@ -165,8 +131,7 @@ var/list/uristrune_cache = list()
|
||||
|
||||
|
||||
else //Otherwise they want to begin drawing each word manually
|
||||
var/datum/runeset/rune_set = global_runesets[runeset_identifier]
|
||||
word = input(user,"Choose a word to add to the rune.", "Trace Rune Word", null) as null|anything in rune_set.words
|
||||
word = input(user,"Choose a word to add to the rune.", "Trace Rune Word", null) as null|anything in rune_words_english
|
||||
if (!word)
|
||||
return 0
|
||||
|
||||
@@ -184,21 +149,16 @@ var/list/uristrune_cache = list()
|
||||
"<span class='warning'>You hear some chanting.</span>")
|
||||
|
||||
if(!user.checkTattoo(TATTOO_SILENT))
|
||||
var/datum/runeset/rune_set = global_runesets[runeset_identifier]
|
||||
var/datum/runeword/rune_word = rune_set.words[word]
|
||||
var/datum/rune_word/rune_word = rune_words[word]
|
||||
user.whisper("...[rune_word.rune]...")
|
||||
return ..()
|
||||
|
||||
/spell/cult/trace_rune/blood_cult/cast(var/list/targets, var/mob/living/carbon/user)
|
||||
/spell/cult/trace_rune/cast(var/list/targets, var/mob/living/carbon/user)
|
||||
if(rune)
|
||||
if(rune.word1 && rune.word2 && rune.word3)
|
||||
to_chat(user, "<span class='warning'>You cannot add more than 3 words to a rune.</span>")
|
||||
return
|
||||
else if(rune.runeset_identifier != runeset_identifier)
|
||||
to_chat(user, "<span class='warning'>This type of rune is incompatible with the one on the ground.</span>")
|
||||
return
|
||||
var/datum/runeset/rune_set = global_runesets[runeset_identifier]
|
||||
if(write_rune_word(get_turf(user), rune_set.words[word], data["blood"], caster = user) == RUNE_WRITE_CONTINUE)
|
||||
if(write_rune_word(get_turf(user), rune_words[word], data["blood"], caster = user) == RUNE_WRITE_CONTINUE)
|
||||
continue_drawing = 1
|
||||
perform(user) //Recursion for drawing runes in a row with tome.
|
||||
else
|
||||
@@ -241,8 +201,9 @@ var/list/uristrune_cache = list()
|
||||
to_chat(user, "<span class='notice'>You retrace your steps, carefully undoing the lines of the [removed_word] rune.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There aren't any rune words left to erase.</span>")
|
||||
*/
|
||||
|
||||
|
||||
// TODO UPHEAVAL PART 2, make this spell available again as a ritual reward. Though instead of using this code it'll probably be activated through mind UI
|
||||
//SPELL III
|
||||
/spell/cult/blood_dagger
|
||||
name = "Blood Dagger"
|
||||
@@ -296,6 +257,7 @@ var/list/uristrune_cache = list()
|
||||
"<span class='warning'>You squeeze the blood in your hand, and it takes the shape of a dagger.</span>")
|
||||
playsound(H, 'sound/weapons/bloodyslice.ogg', 30, 0,-2)
|
||||
|
||||
// TODO UPHEAVAL PART 2, not sure what to do with this spell really, it always kinda sucked and tomes as a whole need an overhaul
|
||||
var/list/arcane_pockets = list()
|
||||
//SPELL IV
|
||||
/spell/cult/arcane_dimension
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
// Tattoos are currently unobtainable and being reworked. Blood Daggers and Cult Chat will be available to cultists in other ways until then.
|
||||
|
||||
/datum/cult_tattoo
|
||||
var/name = "cult tattoo"
|
||||
var/desc = ""
|
||||
@@ -29,16 +31,18 @@
|
||||
///////////////////////////
|
||||
var/list/blood_communion = list()
|
||||
|
||||
/datum/cult_tattoo/bloodpool
|
||||
/datum/cult_tattoo/bloodpool // doesn't actually do anything right now beside give you a cool tattoo
|
||||
name = TATTOO_POOL
|
||||
desc = "All blood costs reduced by 20%. Tributes are split with other bearers of this mark."
|
||||
icon_state = "bloodpool"
|
||||
tier = 1
|
||||
|
||||
/*
|
||||
/datum/cult_tattoo/bloodpool/getTattoo(var/mob/M)
|
||||
..()
|
||||
if (iscultist(M))
|
||||
blood_communion.Add(iscultist(M))
|
||||
*/
|
||||
|
||||
/datum/cult_tattoo/silent
|
||||
name = TATTOO_SILENT
|
||||
@@ -46,7 +50,7 @@ var/list/blood_communion = list()
|
||||
icon_state = "silent"
|
||||
tier = 1
|
||||
|
||||
/datum/cult_tattoo/dagger
|
||||
/datum/cult_tattoo/dagger // now available to all cultists by default
|
||||
name = TATTOO_DAGGER
|
||||
desc = "Materialize a sharp dagger in your hand for a small cost in blood. Use to retrieve."
|
||||
icon_state = "dagger"
|
||||
@@ -64,7 +68,7 @@ var/list/blood_communion = list()
|
||||
// //
|
||||
///////////////////////////
|
||||
|
||||
/datum/cult_tattoo/holy
|
||||
/datum/cult_tattoo/holy // doesn't actually do anything right now beside give you a cool tattoo
|
||||
name = TATTOO_HOLY
|
||||
desc = "Holy water will now only slow you down a bit, and no longer prevent you from casting."
|
||||
icon_state = "holy"
|
||||
@@ -81,7 +85,7 @@ var/list/blood_communion = list()
|
||||
if (iscultist(M))
|
||||
M.add_spell(new /spell/cult/arcane_dimension, "cult_spell_ready", /obj/abstract/screen/movable/spell_master/bloodcult)
|
||||
|
||||
/datum/cult_tattoo/chat
|
||||
/datum/cult_tattoo/chat // functionality moved to Spires
|
||||
name = TATTOO_CHAT
|
||||
desc = "Chat with the cult using :x."
|
||||
icon_state = "chat"
|
||||
@@ -99,6 +103,7 @@ var/list/blood_communion = list()
|
||||
icon_state = "manifest"
|
||||
tier = 3
|
||||
|
||||
/*
|
||||
/datum/cult_tattoo/manifest/getTattoo(var/mob/M)
|
||||
..()
|
||||
var/mob/living/carbon/human/H = bearer
|
||||
@@ -121,6 +126,7 @@ var/list/blood_communion = list()
|
||||
H.status_flags &= ~CANPARALYSE
|
||||
H.regenerate_icons()
|
||||
H.update_dna_from_appearance()
|
||||
*/
|
||||
|
||||
/datum/cult_tattoo/fast
|
||||
name = TATTOO_FAST
|
||||
|
||||
486
code/datums/gamemode/factions/bloodcult/bloodcult_use_blood.dm
Normal file
486
code/datums/gamemode/factions/bloodcult/bloodcult_use_blood.dm
Normal file
@@ -0,0 +1,486 @@
|
||||
|
||||
//When cultists need to pay in blood to use their spells, they have a few options at their disposal:
|
||||
// * If their hands are bloody, they can use the few units of blood on them.
|
||||
// * If there is a blood splatter on the ground that still has a certain amount of fresh blood in it, they can use that?
|
||||
// * If they are grabbing another person, they can stab their nails in their vessels to draw some blood from them
|
||||
// * If they are standing above a bleeding person, they can dip their fingers into their wounds.
|
||||
// * If they are holding a container that has blood in it (such as a beaker or a blood pack), they can pour/squeeze blood from them
|
||||
// * If they are standing above a container that has blood in it, they can dip their fingers into them
|
||||
// * Finally if there are no alternative blood sources, you can always use your own blood.
|
||||
|
||||
/* get_available_blood
|
||||
user: the mob (generally a cultist) trying to spend blood
|
||||
amount_needed: the amount of blood required
|
||||
|
||||
returns: a /list with information on nearby available blood. For use by use_available_blood().
|
||||
*/
|
||||
/proc/get_available_blood(var/mob/user, var/amount_needed = 0)
|
||||
var/data = list(
|
||||
BLOODCOST_TARGET_BLEEDER = null,
|
||||
BLOODCOST_AMOUNT_BLEEDER = 0,
|
||||
BLOODCOST_TARGET_GRAB = null,
|
||||
BLOODCOST_AMOUNT_GRAB = 0,
|
||||
BLOODCOST_TARGET_HANDS = null,
|
||||
BLOODCOST_AMOUNT_HANDS = 0,
|
||||
BLOODCOST_TARGET_HELD = null,
|
||||
BLOODCOST_AMOUNT_HELD = 0,
|
||||
BLOODCOST_LID_HELD = 0,
|
||||
BLOODCOST_TARGET_SPLATTER = null,
|
||||
BLOODCOST_AMOUNT_SPLATTER = 0,
|
||||
BLOODCOST_TARGET_BLOODPACK = null,
|
||||
BLOODCOST_AMOUNT_BLOODPACK = 0,
|
||||
BLOODCOST_HOLES_BLOODPACK = 0,
|
||||
BLOODCOST_TARGET_CONTAINER = null,
|
||||
BLOODCOST_AMOUNT_CONTAINER = 0,
|
||||
BLOODCOST_LID_CONTAINER = 0,
|
||||
BLOODCOST_TARGET_USER = null,
|
||||
BLOODCOST_AMOUNT_USER = 0,
|
||||
BLOODCOST_RESULT = "",
|
||||
BLOODCOST_TOTAL = 0,
|
||||
BLOODCOST_USER = null,
|
||||
)
|
||||
var/turf/T = get_turf(user)
|
||||
var/amount_gathered = 0
|
||||
|
||||
data[BLOODCOST_RESULT] = user
|
||||
|
||||
if (amount_needed == 0)//the cost was probably 1u, and already paid for by blood communion from another cultist
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TRIBUTE
|
||||
return data
|
||||
|
||||
//Is there blood on our hands?
|
||||
var/mob/living/carbon/human/H_user = user
|
||||
if (istype (H_user) && H_user.blood_DNA?.len)
|
||||
data[BLOODCOST_TARGET_HANDS] = H_user
|
||||
var/blood_gathered = min(amount_needed,H_user.bloody_hands)
|
||||
data[BLOODCOST_AMOUNT_HANDS] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
|
||||
if (amount_gathered >= amount_needed)
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_HANDS
|
||||
return data
|
||||
|
||||
//Is there a fresh blood splatter on the turf?
|
||||
for (var/obj/effect/decal/cleanable/blood/B in T)
|
||||
var/blood_volume = B.amount
|
||||
if (blood_volume && B.counts_as_blood)
|
||||
data[BLOODCOST_TARGET_SPLATTER] = B
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_AMOUNT_SPLATTER] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
|
||||
if (amount_gathered >= amount_needed)
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_SPLATTER
|
||||
return data
|
||||
|
||||
//Is the cultist currently grabbing a bleeding mob/corpse that still has blood in it?
|
||||
var/obj/item/weapon/grab/Grab = locate() in user
|
||||
if (Grab)
|
||||
if(ishuman(Grab.affecting))
|
||||
var/mob/living/carbon/human/H = Grab.affecting
|
||||
if(!(H.species.anatomy_flags & NO_BLOOD))
|
||||
var/blood_volume = round(H.vessel.get_reagent_amount(BLOOD))
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_TARGET_GRAB] = H
|
||||
data[BLOODCOST_AMOUNT_GRAB] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
if(ismonkey(Grab.affecting) || isalien(Grab.affecting))//Unlike humans, monkeys take oxy damage when blood is taken from them.
|
||||
var/mob/living/carbon/C = Grab.affecting
|
||||
if(!C.isDead())
|
||||
var/blood_volume = round(max(0,C.health))
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_TARGET_GRAB] = C
|
||||
data[BLOODCOST_AMOUNT_GRAB] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
|
||||
if (amount_gathered >= amount_needed)
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_GRAB
|
||||
return data
|
||||
|
||||
//Is there a bleeding mob/corpse on the turf that still has blood in it?
|
||||
for (var/mob/living/carbon/human/H in T)
|
||||
if(H.species.anatomy_flags & NO_BLOOD)
|
||||
continue
|
||||
if(user != H)
|
||||
for(var/datum/organ/external/org in H.organs)
|
||||
if(org.status & ORGAN_BLEEDING)
|
||||
var/blood_volume = round(H.vessel.get_reagent_amount(BLOOD))
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_TARGET_BLEEDER] = H
|
||||
data[BLOODCOST_AMOUNT_BLEEDER] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
break
|
||||
if (data[BLOODCOST_TARGET_BLEEDER])
|
||||
break
|
||||
|
||||
if (amount_gathered >= amount_needed)
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_BLEEDER
|
||||
return data
|
||||
|
||||
for(var/obj/item/weapon/reagent_containers/G_held in H_user.held_items) //Accounts for if the person has multiple grasping organs
|
||||
if (!istype(G_held) || !round(G_held.reagents.get_reagent_amount(BLOOD)))
|
||||
continue
|
||||
if(istype(G_held, /obj/item/weapon/reagent_containers/blood)) //Bloodbags have their own functionality
|
||||
var/obj/item/weapon/reagent_containers/blood/blood_pack = G_held
|
||||
var/blood_volume = round(blood_pack.reagents.get_reagent_amount(BLOOD))
|
||||
if (blood_volume)
|
||||
data[BLOODCOST_TARGET_BLOODPACK] = blood_pack
|
||||
if (blood_pack.holes)
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_AMOUNT_BLOODPACK] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
else
|
||||
data[BLOODCOST_HOLES_BLOODPACK] = 1
|
||||
if (amount_gathered >= amount_needed)
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_BLOODPACK
|
||||
return data
|
||||
|
||||
else
|
||||
var/blood_volume = round(G_held.reagents.get_reagent_amount(BLOOD))
|
||||
if (blood_volume)
|
||||
data[BLOODCOST_TARGET_HELD] = G_held
|
||||
if (G_held.is_open_container())
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_AMOUNT_HELD] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
else
|
||||
data[BLOODCOST_LID_HELD] = 1
|
||||
|
||||
if (amount_gathered >= amount_needed)
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_HELD
|
||||
return data
|
||||
|
||||
|
||||
//Is there a reagent container on the turf that has blood in it?
|
||||
for (var/obj/item/weapon/reagent_containers/G in T)
|
||||
var/blood_volume = round(G.reagents.get_reagent_amount(BLOOD))
|
||||
if (blood_volume)
|
||||
data[BLOODCOST_TARGET_CONTAINER] = G
|
||||
if (G.is_open_container())
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_AMOUNT_CONTAINER] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
break
|
||||
else
|
||||
data[BLOODCOST_LID_CONTAINER] = 1
|
||||
|
||||
if (amount_gathered >= amount_needed)
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_CONTAINER
|
||||
return data
|
||||
|
||||
//Does the user have blood? (the user can pay in blood without having to bleed first)
|
||||
if(istype(H_user))
|
||||
if(!(H_user.species.anatomy_flags & NO_BLOOD))
|
||||
var/blood_volume = round(H_user.vessel.get_reagent_amount(BLOOD))
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_TARGET_USER] = H_user
|
||||
data[BLOODCOST_AMOUNT_USER] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
else//non-human trying to draw runes eh? let's see...
|
||||
if (ismonkey(user) || isalien(user))
|
||||
var/mob/living/carbon/C_user = user
|
||||
if (!C_user.isDead())
|
||||
var/blood_volume = round(max(0,C_user.health))//Unlike humans, monkeys take oxy damage when blood is taken from them.
|
||||
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
|
||||
data[BLOODCOST_TARGET_USER] = C_user
|
||||
data[BLOODCOST_AMOUNT_USER] = blood_gathered
|
||||
amount_gathered += blood_gathered
|
||||
else if (isconstruct(user))
|
||||
var/mob/living/simple_animal/construct/C_user = user
|
||||
if (!C_user.purge)//Constructs can use runes for free as long as they aren't getting purged by holy water or null rods
|
||||
data[BLOODCOST_TARGET_USER] = C_user
|
||||
data[BLOODCOST_AMOUNT_USER] = amount_needed
|
||||
amount_gathered = amount_needed
|
||||
|
||||
|
||||
if (amount_gathered >= amount_needed)
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_USER
|
||||
return data
|
||||
|
||||
data[BLOODCOST_RESULT] = BLOODCOST_FAILURE
|
||||
return data
|
||||
|
||||
|
||||
/* use_available_blood
|
||||
user: the mob (generally a cultist) trying to spend blood
|
||||
amount_needed: the amount of blood required
|
||||
previous_result: the result of the previous call of this proc if any, to prevent the same flavor text from displaying every single call of this proc in a row
|
||||
tribute: set to 1 when called by a contributor to Blood Communion
|
||||
|
||||
returns: a /list with information on the success/failure of the proc, and in the former case, information the blood that was used (color, type, dna)
|
||||
*/
|
||||
/proc/use_available_blood(var/mob/user, var/amount_needed = 0,var/previous_result = "", var/tribute = 0, var/feedback = TRUE)
|
||||
//Blood Communion
|
||||
var/communion = 0
|
||||
var/communion_data = null
|
||||
var/total_accumulated = 0
|
||||
var/total_needed = amount_needed
|
||||
if (!tribute && iscultist(user))
|
||||
var/datum/role/cultist/mycultist = iscultist(user)
|
||||
if (mycultist in blood_communion)
|
||||
communion = 1
|
||||
amount_needed = max(1,round(amount_needed * 4 / 5))//saving 20% blood
|
||||
var/list/tributers = list()
|
||||
for (var/datum/role/cultist/cultist in blood_communion)
|
||||
if (cultist.antag && cultist.antag.current)
|
||||
var/mob/living/L = cultist.antag.current
|
||||
if (istype(L) && L != user)
|
||||
tributers.Add(L)
|
||||
var/total_per_tribute = max(1,round(amount_needed/max(1,tributers.len+1)))
|
||||
var/tributer_size = tributers.len
|
||||
for (var/i = 1 to tributer_size)
|
||||
var/mob/living/L = pick(tributers)//so it's not always the first one that pays the first blood unit.
|
||||
tributers.Remove(L)
|
||||
var/data = use_available_blood(L, total_per_tribute, "", 1)
|
||||
if (data[BLOODCOST_RESULT] != BLOODCOST_FAILURE)
|
||||
total_accumulated += data[BLOODCOST_TOTAL]
|
||||
if (total_accumulated >= amount_needed - total_per_tribute)//could happen if the cost is less than 1 per tribute
|
||||
communion_data = data//in which case, the blood will carry the data that paid for it
|
||||
break
|
||||
|
||||
//Getting nearby blood sources
|
||||
var/list/data = get_available_blood(user, amount_needed-total_accumulated)
|
||||
|
||||
var/datum/reagent/blood/blood
|
||||
|
||||
//Flavour text and blood data transfer
|
||||
switch (data[BLOODCOST_RESULT])
|
||||
if (BLOODCOST_TRIBUTE)//if the drop of blood was paid for through blood communion, let's get the reference to the blood they used because we can
|
||||
blood = new()
|
||||
if (communion_data && communion_data[BLOODCOST_RESULT])
|
||||
switch(communion_data[BLOODCOST_RESULT])
|
||||
if (BLOODCOST_TARGET_HANDS)
|
||||
var/mob/living/carbon/human/HU = communion_data[BLOODCOST_USER]
|
||||
blood.data["blood_colour"] = HU.bloody_hands_data["blood_colour"]
|
||||
if (HU.blood_DNA && HU.blood_DNA.len)
|
||||
var/blood_DNA = pick(HU.blood_DNA)
|
||||
blood.data["blood_DNA"] = blood_DNA
|
||||
blood.data["blood_type"] = HU.blood_DNA[blood_DNA]
|
||||
//can't get virus data from bloody hands because it'd be a pain in the ass to code for minimal use
|
||||
if (BLOODCOST_TARGET_SPLATTER)
|
||||
var/obj/effect/decal/cleanable/blood/B = communion_data[BLOODCOST_TARGET_SPLATTER]
|
||||
blood = new()
|
||||
blood.data["blood_colour"] = B.basecolor
|
||||
if (B.blood_DNA.len)
|
||||
var/blood_DNA = pick(B.blood_DNA)
|
||||
blood.data["blood_DNA"] = blood_DNA
|
||||
blood.data["blood_type"] = B.blood_DNA[blood_DNA]
|
||||
blood.data["virus2"] = virus_copylist(B.virus2)
|
||||
if (BLOODCOST_TARGET_GRAB)
|
||||
var/mob/living/carbon/CA = communion_data[BLOODCOST_TARGET_GRAB]
|
||||
if (isliving(CA))
|
||||
blood.apply_blood_data(CA.get_blood_data())
|
||||
if (BLOODCOST_TARGET_BLEEDER)
|
||||
var/mob/living/carbon/CA = communion_data[BLOODCOST_TARGET_BLEEDER]
|
||||
if (isliving(CA))
|
||||
blood.apply_blood_data(CA.get_blood_data())
|
||||
if (BLOODCOST_TARGET_HELD)
|
||||
var/obj/item/weapon/reagent_containers/G = communion_data[BLOODCOST_TARGET_HELD]
|
||||
blood = locate() in G.reagents.reagent_list
|
||||
if (BLOODCOST_TARGET_BLOODPACK)
|
||||
var/obj/item/weapon/reagent_containers/blood/B = communion_data[BLOODCOST_TARGET_BLOODPACK]
|
||||
blood = locate() in B.reagents.reagent_list
|
||||
if (BLOODCOST_TARGET_CONTAINER)
|
||||
var/obj/item/weapon/reagent_containers/G = communion_data[BLOODCOST_TARGET_CONTAINER]
|
||||
blood = locate() in G.reagents.reagent_list
|
||||
if (BLOODCOST_TARGET_USER)
|
||||
var/mob/living/carbon/CA = communion_data[BLOODCOST_USER]
|
||||
if (iscarbon(CA))
|
||||
blood.apply_blood_data(CA.get_blood_data())
|
||||
if (isconstruct(CA))//constructs can't get the blood communion tattoo but just in case they do later
|
||||
blood.data["blood_colour"] = "#CC0E00"
|
||||
if (feedback && !tribute && previous_result != BLOODCOST_TRIBUTE)
|
||||
user.visible_message("<span class='warning'>Drips of blood seem to appear out of thin air around \the [user], and fall onto the floor!</span>",
|
||||
"<span class='rose'>An ally has lent you a drip of their blood for your ritual.</span>",
|
||||
"<span class='warning'>You hear a liquid flowing.</span>")
|
||||
if (BLOODCOST_TARGET_HANDS)
|
||||
var/mob/living/carbon/human/H = user
|
||||
blood = new()
|
||||
blood.data["blood_colour"] = H.bloody_hands_data["blood_colour"]
|
||||
if (H.blood_DNA?.len && H.bloody_hands > 0)
|
||||
var/blood_DNA = pick(H.blood_DNA)
|
||||
blood.data["blood_DNA"] = blood_DNA
|
||||
blood.data["blood_type"] = H.blood_DNA[blood_DNA]
|
||||
//can't get virus data from bloody hands because it'd be a pain in the ass to code for minimal use
|
||||
if (feedback && !tribute && previous_result != BLOODCOST_TARGET_HANDS)
|
||||
user.visible_message("<span class='warning'>The blood on \the [user]'s hands drips onto the floor!</span>",
|
||||
"<span class='rose'>You let the blood smeared on your hands join the pool of your summoning.</span>",
|
||||
"<span class='warning'>You hear a liquid flowing.</span>")
|
||||
if (BLOODCOST_TARGET_SPLATTER)
|
||||
var/obj/effect/decal/cleanable/blood/B = data[BLOODCOST_TARGET_SPLATTER]
|
||||
blood = new()
|
||||
blood.data["blood_colour"] = B.basecolor
|
||||
if (B.blood_DNA.len)
|
||||
var/blood_DNA = pick(B.blood_DNA)
|
||||
blood.data["blood_DNA"] = blood_DNA
|
||||
blood.data["blood_type"] = B.blood_DNA[blood_DNA]
|
||||
blood.data["virus2"] = virus_copylist(B.virus2)
|
||||
if (feedback && !tribute && previous_result != BLOODCOST_TARGET_SPLATTER)
|
||||
user.visible_message("<span class='warning'>The blood on the floor below \the [user] starts moving!</span>",
|
||||
"<span class='rose'>You redirect the flow of blood inside the splatters on the floor toward the pool of your summoning.</span>",
|
||||
"<span class='warning'>You hear a liquid flowing.</span>")
|
||||
if (BLOODCOST_TARGET_GRAB)
|
||||
var/mob/living/carbon/C = data[BLOODCOST_TARGET_GRAB]
|
||||
if (iscarbon(C))
|
||||
blood = new()
|
||||
blood.apply_blood_data(C.get_blood_data())
|
||||
if (feedback && !tribute && previous_result != BLOODCOST_TARGET_GRAB)
|
||||
user.visible_message("<span class='warning'>\The [user] stabs their nails inside \the [data[BLOODCOST_TARGET_GRAB]], drawing blood from them!</span>",
|
||||
"<span class='rose'>You stab your nails inside \the [data[BLOODCOST_TARGET_GRAB]] to draw some blood from them.</span>",
|
||||
"<span class='warning'>You hear a liquid flowing.</span>")
|
||||
|
||||
if (BLOODCOST_TARGET_BLEEDER)
|
||||
var/mob/living/carbon/C = data[BLOODCOST_TARGET_BLEEDER]
|
||||
if (iscarbon(C))
|
||||
blood = new()
|
||||
blood.apply_blood_data(C.get_blood_data())
|
||||
if (feedback && !tribute && previous_result != BLOODCOST_TARGET_BLEEDER)
|
||||
user.visible_message("<span class='warning'>\The [user] dips their fingers inside \the [data[BLOODCOST_TARGET_BLEEDER]]'s wounds!</span>",
|
||||
"<span class='rose'>You dip your fingers inside \the [data[BLOODCOST_TARGET_BLEEDER]]'s wounds to draw some blood from them.</span>",
|
||||
"<span class='warning'>You hear a liquid flowing.</span>")
|
||||
if (BLOODCOST_TARGET_HELD)
|
||||
var/obj/item/weapon/reagent_containers/G = data[BLOODCOST_TARGET_HELD]
|
||||
blood = locate() in G.reagents.reagent_list
|
||||
if (!tribute && previous_result != BLOODCOST_TARGET_HELD)
|
||||
user.visible_message("<span class='warning'>\The [user] tips \the [data[BLOODCOST_TARGET_HELD]], pouring blood!</span>",
|
||||
"<span class='rose'>You tip \the [data[BLOODCOST_TARGET_HELD]] to pour the blood contained inside.</span>",
|
||||
"<span class='warning'>You hear a liquid flowing.</span>")
|
||||
if (BLOODCOST_TARGET_BLOODPACK)
|
||||
var/obj/item/weapon/reagent_containers/blood/B = data[BLOODCOST_TARGET_BLOODPACK]
|
||||
blood = locate() in B.reagents.reagent_list
|
||||
if (feedback && !tribute && previous_result != BLOODCOST_TARGET_BLOODPACK)
|
||||
user.visible_message("<span class='warning'>\The [user] squeezes \the [data[BLOODCOST_TARGET_BLOODPACK]], pouring blood!</span>",
|
||||
"<span class='rose'>You squeeze \the [data[BLOODCOST_TARGET_BLOODPACK]] to pour the blood contained inside.</span>",
|
||||
"<span class='warning'>You hear a liquid flowing.</span>")
|
||||
if (BLOODCOST_TARGET_CONTAINER)
|
||||
var/obj/item/weapon/reagent_containers/G = data[BLOODCOST_TARGET_CONTAINER]
|
||||
blood = locate() in G.reagents.reagent_list
|
||||
if (feedback && !tribute && previous_result != BLOODCOST_TARGET_CONTAINER)
|
||||
user.visible_message("<span class='warning'>\The [user] dips their fingers inside \the [data[BLOODCOST_TARGET_CONTAINER]], covering them in blood!</span>",
|
||||
"<span class='rose'>You dip your fingers inside \the [data[BLOODCOST_TARGET_CONTAINER]], covering them in blood.</span>",
|
||||
"<span class='warning'>You hear a liquid flowing.</span>")
|
||||
if (BLOODCOST_TARGET_USER)
|
||||
blood = new()
|
||||
if (!tribute)
|
||||
if (data[BLOODCOST_HOLES_BLOODPACK])
|
||||
to_chat(user, "<span class='warning'>You must puncture \the [data[BLOODCOST_TARGET_BLOODPACK]] before you can squeeze blood from it!</span>")
|
||||
else if (data[BLOODCOST_LID_HELD])
|
||||
to_chat(user, "<span class='warning'>Remove \the [data[BLOODCOST_TARGET_HELD]]'s lid first!</span>")
|
||||
else if (data[BLOODCOST_LID_CONTAINER])
|
||||
to_chat(user, "<span class='warning'>Remove \the [data[BLOODCOST_TARGET_CONTAINER]]'s lid first!</span>")
|
||||
if (iscarbon(user))
|
||||
var/mob/living/carbon/C_user = user
|
||||
blood.apply_blood_data(C_user.get_blood_data())
|
||||
|
||||
if (isconstruct(user))
|
||||
blood.data["blood_colour"] = "#CC0E00"//not like constructs can write runes by themselves currently, but they might do at some point
|
||||
|
||||
if (feedback && !tribute && (previous_result != BLOODCOST_TARGET_USER))
|
||||
if (iscarbon(user))//if the user is holding a sharp weapon, they get a custom message
|
||||
var/obj/item/weapon/W = user.get_active_hand()
|
||||
if (W && W.sharpness_flags & SHARP_BLADE)
|
||||
to_chat(user, "<span class='rose'>You slice open your finger with \the [W] to let a bit of blood flow.</span>")
|
||||
else
|
||||
var/obj/item/weapon/W2 = user.get_inactive_hand()
|
||||
if (W2 && W2.sharpness_flags & SHARP_BLADE)
|
||||
to_chat(user, "<span class='rose'>You slice open your finger with \the [W] to let a bit of blood flow.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='rose'>You bite your finger and let the blood pearl up.</span>")
|
||||
else if (isconstruct(user))
|
||||
to_chat(user, "<span class='rose'>Your shell's connection past the veil lets you perform the ritual without the need for a local source of blood.</span>")
|
||||
if (BLOODCOST_FAILURE)
|
||||
if (!tribute)
|
||||
if (data[BLOODCOST_HOLES_BLOODPACK])
|
||||
to_chat(user, "<span class='danger'>You must puncture \the [data[BLOODCOST_TARGET_BLOODPACK]] before you can squeeze blood from it!</span>")
|
||||
else if (data[BLOODCOST_LID_HELD])
|
||||
to_chat(user, "<span class='danger'>Remove \the [data[BLOODCOST_TARGET_HELD]]'s lid first!</span>")
|
||||
else if (data[BLOODCOST_LID_CONTAINER])
|
||||
to_chat(user, "<span class='danger'>Remove \the [data[BLOODCOST_TARGET_HELD]]'s lid first!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>There is no blood available. Not even in your own body!</span>")
|
||||
|
||||
//Blood is only consumed if there is enough of it
|
||||
if (!data[BLOODCOST_FAILURE])
|
||||
if (data[BLOODCOST_TARGET_HANDS])
|
||||
data[BLOODCOST_TOTAL] += data[BLOODCOST_AMOUNT_HANDS]
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.bloody_hands = max(0, H.bloody_hands - data[BLOODCOST_AMOUNT_HANDS])
|
||||
if (!H.bloody_hands)
|
||||
H.clean_blood()
|
||||
H.update_inv_gloves()
|
||||
if (data[BLOODCOST_TARGET_SPLATTER])
|
||||
data[BLOODCOST_TOTAL] += data[BLOODCOST_AMOUNT_SPLATTER]
|
||||
var/obj/effect/decal/cleanable/blood/B = data[BLOODCOST_TARGET_SPLATTER]
|
||||
B.amount = max(0 , B.amount - data[BLOODCOST_AMOUNT_SPLATTER])
|
||||
if (data[BLOODCOST_TARGET_GRAB])
|
||||
data[BLOODCOST_TOTAL] += data[BLOODCOST_AMOUNT_GRAB]
|
||||
if (ishuman(data[BLOODCOST_TARGET_GRAB]))
|
||||
var/mob/living/carbon/human/H = data[BLOODCOST_TARGET_GRAB]
|
||||
H.vessel.remove_reagent(BLOOD, data[BLOODCOST_AMOUNT_GRAB])
|
||||
H.take_overall_damage(data[BLOODCOST_AMOUNT_GRAB] ? 0.1 : 0)
|
||||
else if (ismonkey(data[BLOODCOST_TARGET_GRAB]))
|
||||
var/mob/living/carbon/monkey/M = data[BLOODCOST_TARGET_GRAB]
|
||||
M.adjustOxyLoss(data[BLOODCOST_AMOUNT_GRAB])
|
||||
else if (isalien(data[BLOODCOST_TARGET_GRAB]))
|
||||
var/mob/living/carbon/alien/A = data[BLOODCOST_TARGET_GRAB]
|
||||
A.adjustBruteLoss(data[BLOODCOST_AMOUNT_GRAB])
|
||||
if (data[BLOODCOST_TARGET_BLEEDER])
|
||||
data[BLOODCOST_TOTAL] += data[BLOODCOST_AMOUNT_BLEEDER]
|
||||
var/mob/living/carbon/human/H = data[BLOODCOST_TARGET_BLEEDER]
|
||||
H.vessel.remove_reagent(BLOOD, data[BLOODCOST_AMOUNT_BLEEDER])
|
||||
H.take_overall_damage(data[BLOODCOST_AMOUNT_BLEEDER] ? 0.1 : 0)
|
||||
if (data[BLOODCOST_TARGET_HELD])
|
||||
data[BLOODCOST_TOTAL] += data[BLOODCOST_AMOUNT_HELD]
|
||||
var/obj/item/weapon/reagent_containers/G = data[BLOODCOST_TARGET_HELD]
|
||||
G.reagents.remove_reagent(BLOOD, data[BLOODCOST_AMOUNT_HELD])
|
||||
if (data[BLOODCOST_TARGET_BLOODPACK])
|
||||
data[BLOODCOST_TOTAL] += data[BLOODCOST_AMOUNT_BLOODPACK]
|
||||
var/obj/item/weapon/reagent_containers/G = data[BLOODCOST_TARGET_BLOODPACK]
|
||||
G.reagents.remove_reagent(BLOOD, data[BLOODCOST_AMOUNT_BLOODPACK])
|
||||
if (data[BLOODCOST_TARGET_CONTAINER])
|
||||
data[BLOODCOST_TOTAL] += data[BLOODCOST_AMOUNT_CONTAINER]
|
||||
var/obj/item/weapon/reagent_containers/G = data[BLOODCOST_TARGET_CONTAINER]
|
||||
G.reagents.remove_reagent(BLOOD, data[BLOODCOST_AMOUNT_CONTAINER])
|
||||
if (data[BLOODCOST_TARGET_USER])
|
||||
data[BLOODCOST_TOTAL] += data[BLOODCOST_AMOUNT_USER]
|
||||
if (ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/blood_before = H.vessel.get_reagent_amount(BLOOD)
|
||||
H.vessel.remove_reagent(BLOOD, data[BLOODCOST_AMOUNT_USER])
|
||||
var/blood_after = H.vessel.get_reagent_amount(BLOOD)
|
||||
if (blood_before > BLOOD_VOLUME_SAFE && blood_after < BLOOD_VOLUME_SAFE)
|
||||
to_chat(user, "<span class='sinister'>You start looking pale.</span>")
|
||||
else if (blood_before > BLOOD_VOLUME_WARN && blood_after < BLOOD_VOLUME_WARN)
|
||||
to_chat(user, "<span class='sinister'>You feel weak from the lack of blood.</span>")
|
||||
else if (blood_before > BLOOD_VOLUME_OKAY && blood_after < BLOOD_VOLUME_OKAY)
|
||||
to_chat(user, "<span class='sinister'>You are about to pass out from the lack of blood.</span>")
|
||||
else if (blood_before > BLOOD_VOLUME_BAD && blood_after < BLOOD_VOLUME_BAD)
|
||||
to_chat(user, "<span class='sinister'>You have trouble focusing, things will go bad if you keep using your blood.</span>")
|
||||
else if (blood_before > BLOOD_VOLUME_SURVIVE && blood_after < BLOOD_VOLUME_SURVIVE)
|
||||
to_chat(user, "<span class='sinister'>It will be all over soon.</span>")
|
||||
H.take_overall_damage(data[BLOODCOST_AMOUNT_USER] ? 0.1 : 0)
|
||||
else if (ismonkey(user) || isalien(user))
|
||||
var/mob/living/carbon/C = user
|
||||
var/blood_before = C.health
|
||||
if (ismonkey(C))
|
||||
C.adjustOxyLoss(data[BLOODCOST_AMOUNT_USER])
|
||||
else if (isalien(C))
|
||||
C.adjustBruteLoss(data[BLOODCOST_AMOUNT_USER])
|
||||
C.updatehealth()
|
||||
var/blood_after = C.health
|
||||
if (blood_before > (C.maxHealth*5/6) && blood_after < (C.maxHealth*5/6))
|
||||
to_chat(user, "<span class='sinister'>You start looking pale.</span>")
|
||||
else if (blood_before > (C.maxHealth*4/6) && blood_after < (C.maxHealth*4/6))
|
||||
to_chat(user, "<span class='sinister'>You feel weak from the lack of blood.</span>")
|
||||
else if (blood_before > (C.maxHealth*3/6) && blood_after < (C.maxHealth*3/6))
|
||||
to_chat(user, "<span class='sinister'>You are about to pass out from the lack of blood.</span>")
|
||||
else if (blood_before > (C.maxHealth*2/6) && blood_after < (C.maxHealth*2/6))
|
||||
to_chat(user, "<span class='sinister'>You have trouble focusing, things will go bad if you keep using your blood.</span>")
|
||||
else if (blood_before > (C.maxHealth*1/6) && blood_after < (C.maxHealth*1/6))
|
||||
to_chat(user, "<span class='sinister'>It will be all over soon.</span>")
|
||||
|
||||
|
||||
if (communion && data[BLOODCOST_TOTAL] + total_accumulated >= amount_needed)
|
||||
data[BLOODCOST_TOTAL] = max(data[BLOODCOST_TOTAL], total_needed)
|
||||
data["blood"] = blood
|
||||
return data
|
||||
103
code/datums/gamemode/factions/bloodcult/bloodcult_words.dm
Normal file
103
code/datums/gamemode/factions/bloodcult/bloodcult_words.dm
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
var/rune_words_initialized = 0
|
||||
var/list/rune_words = list()//datums go in here
|
||||
var/list/rune_words_english = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide")
|
||||
var/list/rune_words_rune = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri")
|
||||
var/list/rune_words_icons = list("rune-1","rune-2","rune-4","rune-8","rune-16","rune-32","rune-64","rune-128", "rune-256", "rune-512")
|
||||
|
||||
/datum/rune_word
|
||||
var/english = "word"//don't change those
|
||||
var/rune = "zek'kon"
|
||||
var/icon = 'icons/effects/uristrunes.dmi'
|
||||
var/icon_state = ""
|
||||
var/color//used by path rune markers
|
||||
var/offset_x = 0
|
||||
var/offset_y = 0
|
||||
|
||||
/proc/initialize_rune_words()
|
||||
if (rune_words_initialized)
|
||||
return
|
||||
for(var/subtype in subtypesof(/datum/rune_word))
|
||||
var/datum/rune_word/new_word = new subtype()
|
||||
rune_words[new_word.english] = new_word
|
||||
rune_words_initialized = 1
|
||||
|
||||
/datum/rune_word/travel
|
||||
english = "travel"
|
||||
rune = "ire"
|
||||
icon_state = "rune-1"
|
||||
color = "yellow"
|
||||
offset_x = 6
|
||||
offset_y = -5
|
||||
|
||||
/datum/rune_word/blood
|
||||
english = "blood"
|
||||
rune = "ego"
|
||||
icon_state = "rune-2"
|
||||
color = "maroon"
|
||||
offset_x = 0
|
||||
offset_y = 5
|
||||
|
||||
/datum/rune_word/join
|
||||
english = "join"
|
||||
rune = "nahlizet"
|
||||
icon_state = "rune-4"
|
||||
color = "green"
|
||||
offset_x = 2
|
||||
offset_y = 1
|
||||
|
||||
/datum/rune_word/hell
|
||||
english = "hell"
|
||||
rune = "certum"
|
||||
icon_state = "rune-8"
|
||||
color = "red"
|
||||
offset_x = 0
|
||||
offset_y = 10
|
||||
|
||||
/datum/rune_word/destroy
|
||||
english = "destroy"
|
||||
rune = "veri"
|
||||
icon_state = "rune-16"
|
||||
color = "purple"
|
||||
offset_x = 10
|
||||
offset_y = 3
|
||||
|
||||
/datum/rune_word/technology
|
||||
english = "technology"
|
||||
rune = "jatkaa"
|
||||
icon_state = "rune-32"
|
||||
color = "blue"
|
||||
offset_x = -10
|
||||
offset_y = 1
|
||||
|
||||
/datum/rune_word/self
|
||||
english = "self"
|
||||
rune = "mgar"
|
||||
icon_state = "rune-64"
|
||||
color = null
|
||||
offset_x = -6
|
||||
offset_y = -9
|
||||
|
||||
/datum/rune_word/see
|
||||
english = "see"
|
||||
rune = "balaq"
|
||||
icon_state = "rune-128"
|
||||
color = "fuchsia"
|
||||
offset_x = 10
|
||||
offset_y = -11
|
||||
|
||||
/datum/rune_word/other
|
||||
english = "other"
|
||||
rune = "karazet"
|
||||
icon_state = "rune-256"
|
||||
color = "teal"
|
||||
offset_x = -8
|
||||
offset_y = 8
|
||||
|
||||
/datum/rune_word/hide
|
||||
english = "hide"
|
||||
rune = "geeri"
|
||||
icon_state = "rune-512"
|
||||
color = "silver"
|
||||
offset_x = -2
|
||||
offset_y = -1
|
||||
@@ -25,27 +25,6 @@
|
||||
var/isbroken = 0
|
||||
light_range = 5
|
||||
light_color = LIGHT_COLOR_RED
|
||||
var/last_check = 0
|
||||
|
||||
/*
|
||||
/obj/structure/cult_legacy/pylon/New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
/obj/structure/cult_legacy/pylon/Destroy()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
/obj/structure/cult_legacy/pylon/process()
|
||||
if(!isbroken && world.time > last_check + 3 SECONDS)
|
||||
last_check = world.time
|
||||
for(var/mob/living/simple_animal/construct/C in view(src, 3))
|
||||
if(C.health < C.maxHealth)
|
||||
if(prob(15))
|
||||
src.visible_message("<span class='sinister'>\the [src] mends some of \the <EM>[C]'s</EM> wounds.</span>")
|
||||
make_tracker_effects(get_turf(src), C)
|
||||
C.health = min(C.maxHealth, C.health + 3) //Not quite as good as artificers
|
||||
*/
|
||||
|
||||
/obj/structure/cult_legacy/pylon/attack_hand(mob/M as mob)
|
||||
attackpylon(M, 5)
|
||||
|
||||
@@ -53,12 +53,8 @@ var/global/list/narsie_list = list()
|
||||
world << sound('sound/effects/wind/wind_5_1.ogg')
|
||||
if(narnar)
|
||||
narsie_spawn_animation()
|
||||
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
|
||||
if (cult)
|
||||
cult.stage(CULT_EPILOGUE)
|
||||
if(!narsie_cometh)//so we don't initiate Hell more than one time.
|
||||
|
||||
if (emergency_shuttle && !cult)//in case of Cult 3.0, the round will end after about 5 minutes
|
||||
if (emergency_shuttle)
|
||||
emergency_shuttle.incall()
|
||||
emergency_shuttle.can_recall = 0
|
||||
if(emergency_shuttle.endtime > world.timeofday + 1800 && emergency_shuttle.location != 1 && !emergency_shuttle.departed)
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
|
||||
/datum/objective/bloodcult
|
||||
name = "Cultist of Nar-Sie"
|
||||
explanation_text = "Set up secret temples dedicated to Nar-Sie, the Geometer of Blood, harbringer of gunk and chaos. Spread your influence among the crew without getting caught by security. Convert the willing and torment the others. Above all, ensure that at least one of you remains alive to spread the cult's influence to other space stations."
|
||||
|
||||
/datum/objective/bloodcult/IsFulfilled()
|
||||
if (..())
|
||||
return TRUE
|
||||
|
||||
var/datum/faction/bloodcult/cult = find_active_faction_by_type(/datum/faction/bloodcult)
|
||||
if (cult && cult.members.len > 0)
|
||||
for (var/datum/role/cultist/C in cult.members)
|
||||
if (C.antag.current && !C.antag.current.isDead())
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
|
||||
/* there might be useful bits of code here to use later so I'm leaving this commented out for convenience for now.
|
||||
/datum/objective/bloodcult_reunion
|
||||
explanation_text = "The Reunion: Meet up with your fellow cultists, and erect an altar aboard the station."
|
||||
name = "Blood Cult: Prologue"
|
||||
@@ -229,3 +247,4 @@
|
||||
|
||||
/datum/objective/bloodcult_feast/IsFulfilled()
|
||||
return TRUE//might expand on that later after release, if I ever get to implement my rework of post-NarSie.
|
||||
*/
|
||||
@@ -16,6 +16,16 @@
|
||||
var/second_chance = 1
|
||||
var/datum/deconversion_ritual/deconversion = null
|
||||
|
||||
//writing runes
|
||||
var/rune_blood_cost = 1 // How much blood spent per rune word written
|
||||
var/verbose = FALSE // Used by the rune writing UI to avoid message spam
|
||||
|
||||
var/cultist_role = CULTIST_ROLE_NONE // Because the role might change on the fly and we don't want to set everything again each time, better not start dealing with subtypes
|
||||
var/time_role_changed_last = 0
|
||||
|
||||
var/datum/role/cultist/mentor = null
|
||||
var/list/acolytes = list()
|
||||
|
||||
/datum/role/cultist/New(var/datum/mind/M, var/datum/faction/fac=null, var/new_id)
|
||||
..()
|
||||
wikiroute = role_wiki[CULTIST]
|
||||
@@ -28,15 +38,6 @@
|
||||
update_cult_hud()
|
||||
antag.current.add_language(LANGUAGE_CULT)
|
||||
|
||||
if((ishuman(antag.current) || ismonkey(antag.current) || isalien(antag.current)) && !(locate(/spell/cult) in antag.current.spell_list))
|
||||
antag.current.add_spell(new /spell/cult/trace_rune/blood_cult, "cult_spell_ready", /obj/abstract/screen/movable/spell_master/bloodcult)
|
||||
antag.current.add_spell(new /spell/cult/erase_rune, "cult_spell_ready", /obj/abstract/screen/movable/spell_master/bloodcult)
|
||||
antag.store_memory("A couple of runes appear clearly in your mind:")
|
||||
antag.store_memory("<B>Raise Structure:</B> BLOOD, TECHNOLOGY, JOIN.")
|
||||
antag.store_memory("<B>Communication:</B> SELF, OTHER, TECHNOLOGY.")
|
||||
antag.store_memory("<B>Summon Tome:</B> SEE, BLOOD, HELL.")
|
||||
antag.store_memory("<hr>")
|
||||
|
||||
/datum/role/cultist/RemoveFromRole(var/datum/mind/M)
|
||||
antag.current.remove_language(LANGUAGE_CULT)
|
||||
remove_cult_hud()
|
||||
@@ -44,6 +45,7 @@
|
||||
antag.current.remove_spell(spell_to_remove)
|
||||
if (src in blood_communion)
|
||||
blood_communion.Remove(src)
|
||||
DropMentorship()
|
||||
if (conversion.len > 0)
|
||||
var/conv = pick(conversion)
|
||||
switch (conv)
|
||||
@@ -74,52 +76,13 @@
|
||||
return
|
||||
update_cult_hud()
|
||||
antag.current.add_language(LANGUAGE_CULT)
|
||||
if((ishuman(antag.current) || ismonkey(antag.current) || isalien(antag.current)) && !(locate(/spell/cult) in antag.current.spell_list))
|
||||
antag.current.add_spell(new /spell/cult/trace_rune/blood_cult, "cult_spell_ready", /obj/abstract/screen/movable/spell_master/bloodcult)
|
||||
antag.current.add_spell(new /spell/cult/erase_rune, "cult_spell_ready", /obj/abstract/screen/movable/spell_master/bloodcult)
|
||||
|
||||
/datum/role/cultist/process()
|
||||
..()
|
||||
if (holywarning_cooldown > 0)
|
||||
holywarning_cooldown--
|
||||
|
||||
if (veil_thickness == CULT_MENDED && antag?.current)
|
||||
if (ishuman(antag.current))
|
||||
var/mob/living/carbon/human/H = antag.current
|
||||
if(H.get_heart() && prob(10))
|
||||
H.visible_message("<span class='danger'>\The [H]'s heart bursts out of \his chest!</span>","<span class='danger'>Your heart bursts out of your chest!</span>")
|
||||
var/obj/item/organ/internal/blown_heart = H.remove_internal_organ(H,H.get_heart(),H.get_organ(LIMB_CHEST))
|
||||
var/list/spawn_turfs = list()
|
||||
for(var/turf/T in orange(1, H))
|
||||
if(!T.density)
|
||||
spawn_turfs.Add(T)
|
||||
if(!spawn_turfs.len)
|
||||
spawn_turfs.Add(get_turf(H))
|
||||
var/mob/living/simple_animal/hostile/heart_attack = new(pick(spawn_turfs))
|
||||
heart_attack.appearance = blown_heart.appearance
|
||||
heart_attack.icon_dead = "heart-off"
|
||||
heart_attack.environment_smash_flags = 0
|
||||
heart_attack.melee_damage_lower = 15
|
||||
heart_attack.melee_damage_upper = 15
|
||||
heart_attack.health = 50
|
||||
heart_attack.maxHealth = 50
|
||||
heart_attack.stat_attack = 1
|
||||
qdel(blown_heart)
|
||||
else
|
||||
H.eye_blurry = max(H.eye_blurry, 30)
|
||||
H.Dizzy(30)
|
||||
H.stuttering = max(H.stuttering, 30)
|
||||
H.Jitter(30)
|
||||
if (prob(70))
|
||||
H.Knockdown(4)
|
||||
else if (prob(70))
|
||||
H.confused = 6
|
||||
H.adjustOxyLoss(20)
|
||||
H.adjustToxLoss(10)
|
||||
else
|
||||
if(isliving(antag.current))
|
||||
var/mob/living/L = antag.current
|
||||
L.adjustBruteLoss(rand(20,50))
|
||||
if ((cultist_role == CULTIST_ROLE_ACOLYTE) && !mentor)
|
||||
FindMentor()
|
||||
|
||||
/datum/role/cultist/Greet(var/greeting,var/custom)
|
||||
if(!greeting)
|
||||
@@ -163,9 +126,6 @@
|
||||
|
||||
to_chat(antag.current, "<span class='info'><a HREF='?src=\ref[antag.current];getwiki=[wikiroute]'>(Wiki Guide)</a></span>")
|
||||
to_chat(antag.current, "<span class='sinister'>You find yourself to be well-versed in the runic alphabet of the cult.</span>")
|
||||
to_chat(antag.current, "<span class='sinister'>A couple of runes linger vividly in your mind.</span><span class='info'> (check your notes).</span>")
|
||||
|
||||
|
||||
|
||||
spawn(1)
|
||||
if (faction)
|
||||
@@ -179,89 +139,117 @@
|
||||
|
||||
/datum/role/cultist/proc/update_cult_hud()
|
||||
var/mob/M = antag?.current
|
||||
if(M && M.client && M.hud_used)
|
||||
if(!M.hud_used.cult_Act_display)
|
||||
M.hud_used.cult_hud()
|
||||
if (!(M.hud_used.cult_Act_display in M.client.screen))
|
||||
M.client.screen += list(M.hud_used.cult_Act_display,M.hud_used.cult_tattoo_display)
|
||||
M.hud_used.cult_Act_display.overlays.len = 0
|
||||
M.hud_used.cult_tattoo_display.overlays.len = 0
|
||||
var/current_act = max(-1,min(5,veil_thickness))
|
||||
var/image/I_act = image('icons/mob/screen1_cult.dmi',"act")
|
||||
I_act.appearance_flags |= RESET_COLOR
|
||||
M.hud_used.cult_Act_display.overlays += I_act
|
||||
var/image/I_tattoos = image('icons/mob/screen1_cult.dmi',"tattoos")
|
||||
I_tattoos.appearance_flags |= RESET_COLOR
|
||||
M.hud_used.cult_tattoo_display.overlays += I_tattoos
|
||||
|
||||
var/image/I_act_indicator = image('icons/mob/screen1_cult.dmi',"[current_act]")
|
||||
if (current_act == CULT_MENDED)
|
||||
I_act_indicator.appearance_flags |= RESET_COLOR
|
||||
M.hud_used.cult_Act_display.overlays += I_act_indicator
|
||||
|
||||
var/image/I_arrow = image('icons/mob/screen1_cult.dmi',"[current_act]a")
|
||||
I_arrow.appearance_flags |= RESET_COLOR
|
||||
M.hud_used.cult_Act_display.overlays += I_arrow
|
||||
switch (current_act)
|
||||
if (CULT_MENDED)
|
||||
M.hud_used.cult_Act_display.name = "..."
|
||||
if (CULT_PROLOGUE)
|
||||
M.hud_used.cult_Act_display.name = "Prologue: The Reunion"
|
||||
if (CULT_ACT_I)
|
||||
M.hud_used.cult_Act_display.name = "Act I: The Followers"
|
||||
if (CULT_ACT_II)
|
||||
M.hud_used.cult_Act_display.name = "Act II: The Sacrifice"
|
||||
if (CULT_ACT_III)
|
||||
M.hud_used.cult_Act_display.name = "Act III: The Blood Bath"
|
||||
if (CULT_ACT_IV)
|
||||
M.hud_used.cult_Act_display.name = "Act IV: The Tear in Reality"
|
||||
if (CULT_EPILOGUE)
|
||||
M.hud_used.cult_Act_display.name = "Epilogue: The Feast"
|
||||
var/tattoos_names = ""
|
||||
var/i = 0
|
||||
for (var/T in tattoos)
|
||||
var/datum/cult_tattoo/tattoo = tattoos[T]
|
||||
if (tattoo)
|
||||
M.hud_used.cult_tattoo_display.overlays += image('icons/mob/screen1_cult.dmi',"t_[tattoo.icon_state]")
|
||||
tattoos_names += "[i ? ", " : ""][tattoo.name]"
|
||||
i++
|
||||
if (!tattoos_names)
|
||||
tattoos_names = "none"
|
||||
M.hud_used.cult_tattoo_display.name = "Arcane Tattoos: [tattoos_names]"
|
||||
|
||||
if (isshade(M))
|
||||
if (istype(M.loc,/obj/item/weapon/melee/soulblade))
|
||||
M.DisplayUI("Soulblade")
|
||||
M.client.screen |= list(M.healths2)
|
||||
else
|
||||
M.client.screen -= list(M.healths2)
|
||||
if(M)
|
||||
M.DisplayUI("Cultist")
|
||||
if (M.client && M.hud_used)
|
||||
if (isshade(M))
|
||||
if (istype(M.loc,/obj/item/weapon/melee/soulblade))
|
||||
M.DisplayUI("Soulblade")
|
||||
M.client.screen |= list(M.healths2)
|
||||
else
|
||||
M.client.screen -= list(M.healths2)
|
||||
|
||||
/datum/role/cultist/proc/remove_cult_hud()
|
||||
var/mob/M = antag?.current
|
||||
if(M && M.client && M.hud_used)
|
||||
qdel(M.hud_used.cult_Act_display)
|
||||
qdel(M.hud_used.cult_tattoo_display)
|
||||
if(M)
|
||||
M.HideUI("Cultist")
|
||||
M.HideUI("Bloodcult Runes")
|
||||
|
||||
/mob/proc/occult_muted()
|
||||
if (checkTattoo(TATTOO_HOLY))
|
||||
return 0
|
||||
if (reagents && reagents.has_reagent(HOLYWATER))
|
||||
return 1
|
||||
if (is_implanted(/obj/item/weapon/implant/holy))
|
||||
return 1
|
||||
return 0
|
||||
/datum/role/cultist/extraPanelButtons()
|
||||
var/dat = ""
|
||||
if (mentor)
|
||||
dat = "<br>Currently under the mentorship of <b>[mentor.antag.name]/([mentor.antag.key])</b><br>"
|
||||
if (acolytes.len)
|
||||
dat += "<br>Currently mentoring "
|
||||
for (var/datum/role/cultist/acolyte in acolytes)
|
||||
dat += "<b>[acolyte.antag.name]/([acolyte.antag.key])</b>, "
|
||||
dat += "<br>"
|
||||
return dat
|
||||
|
||||
/datum/role/cultist/proc/DropMentorship()
|
||||
if (mentor)
|
||||
to_chat(antag.current,"<span class='warning'>You have ended your mentorship under [mentor.antag.name].</span>")
|
||||
to_chat(mentor.antag.current,"<span class='warning'>[antag.name] has ended their mentorship under you.</span>")
|
||||
message_admins("[antag.key]/([antag.name]) has ended their mentorship under [mentor.antag.name]")
|
||||
log_admin("[antag.key]/([antag.name]) has ended their mentorship under [mentor.antag.name]")
|
||||
if (acolytes.len > 0)
|
||||
for (var/datum/role/cultist/acolyte in acolytes)
|
||||
to_chat(antag.current,"<span class='warning'>You have ended your mentorship of [acolyte.antag.name].</span>")
|
||||
to_chat(acolyte.antag.current,"<span class='warning'>[antag.name] has ended their mentorship.</span>")
|
||||
message_admins("[antag.key]/([antag.name]) has ended their mentorship of [acolyte.antag.name]")
|
||||
log_admin("[antag.key]/([antag.name]) has ended their mentorship of [acolyte.antag.name]")
|
||||
|
||||
/datum/role/cultist/proc/ChangeCultistRole(var/new_role)
|
||||
if (!new_role)
|
||||
return
|
||||
var/datum/faction/bloodcult/cult = faction
|
||||
if ((cultist_role == CULTIST_ROLE_MENTOR) && cult)
|
||||
cult.mentor_count--
|
||||
|
||||
cultist_role = new_role
|
||||
|
||||
DropMentorship()
|
||||
|
||||
switch(cultist_role)
|
||||
if (CULTIST_ROLE_ACOLYTE)
|
||||
message_admins("BLOODCULT: [antag.key]/([antag.name]) has become a cultist acolyte.")
|
||||
log_admin("BLOODCULT: [antag.key]/([antag.name]) has become a cultist acolyte.")
|
||||
logo_state = "cult-apprentice-logo"
|
||||
FindMentor()
|
||||
if (!mentor)
|
||||
message_admins("BLOODCULT: [antag.key]/([antag.name]) couldn't find a mentor.")
|
||||
log_admin("BLOODCULT: [antag.key]/([antag.name]) couldn't find a mentor.")
|
||||
if (CULTIST_ROLE_HERALD)
|
||||
message_admins("BLOODCULT: [antag.key]/([antag.name]) has become a cultist herald.")
|
||||
log_admin("BLOODCULT: [antag.key]/([antag.name]) has become a cultist herald.")
|
||||
logo_state = "cult-logo"
|
||||
if (CULTIST_ROLE_MENTOR)
|
||||
message_admins("BLOODCULT: [antag.key]/([antag.name]) has become a cultist mentor.")
|
||||
log_admin("BLOODCULT: [antag.key]/([antag.name]) has become a cultist mentor.")
|
||||
logo_state = "cult-master-logo"
|
||||
if (cult)
|
||||
cult.mentor_count++
|
||||
else
|
||||
logo_state = "cult-logo"
|
||||
cultist_role = CULTIST_ROLE_NONE
|
||||
if (cult)
|
||||
cult.update_hud_icons()
|
||||
if (antag.current)
|
||||
antag.current.DisplayUI("Cultist Left Panel")
|
||||
time_role_changed_last = world.time
|
||||
|
||||
/datum/role/cultist/proc/FindMentor()
|
||||
var/datum/faction/bloodcult/cult = faction
|
||||
if (!cult || !cult.mentor_count)
|
||||
return
|
||||
var/datum/role/cultist/potential_mentor
|
||||
var/min_acolytes = ARBITRARILY_LARGE_NUMBER
|
||||
for (var/datum/role/cultist/C in cult.members)
|
||||
if (C.antag.current.isDead())
|
||||
continue
|
||||
if (C.cultist_role == CULTIST_ROLE_MENTOR)
|
||||
if (C.acolytes.len < min_acolytes || (C.acolytes.len == min_acolytes && prob(50)))
|
||||
min_acolytes = C.acolytes.len
|
||||
potential_mentor = C
|
||||
|
||||
if (potential_mentor)
|
||||
mentor = potential_mentor
|
||||
potential_mentor.acolytes |= src
|
||||
to_chat(antag.current, "<span class='sinister'>You are now in a mentorship under <span class='danger'>[mentor.name], the [mentor.antag.assigned_role=="MODE" ? (mentor.antag.special_role) : (mentor.antag.assigned_role)]</span>. Seek their help to learn the ways of our cult.</span>")
|
||||
to_chat(mentor.antag.current, "<span class='sinister'>You are now mentoring <span class='danger'>[antag.name], the [antag.assigned_role=="MODE" ? (antag.special_role) : (antag.assigned_role)]</span>. </span>")
|
||||
message_admins("[mentor.antag.key]/([mentor.antag.name]) is now mentoring [antag.name]")
|
||||
log_admin("[mentor.antag.key]/([mentor.antag.name]) is now mentoring [antag.name]")
|
||||
|
||||
/datum/role/cultist/handle_reagent(var/reagent_id)
|
||||
var/mob/living/carbon/human/H = antag.current
|
||||
if (!istype(H))
|
||||
return
|
||||
var/unholy = H.checkTattoo(TATTOO_HOLY)
|
||||
var/current_act = clamp(veil_thickness,CULT_MENDED,CULT_EPILOGUE)
|
||||
if (reagent_id == INCENSE_HAREBELLS)
|
||||
if (unholy)
|
||||
H.eye_blurry = max(H.eye_blurry, 3)
|
||||
return
|
||||
else
|
||||
H.eye_blurry = max(H.eye_blurry, 12)
|
||||
H.Dizzy(12)
|
||||
H.stuttering = max(H.stuttering, 12)
|
||||
H.Jitter(12)
|
||||
/* // TODO (UPHEAVAL PART 2) stronger effects the more cult points have been accumulated
|
||||
switch (current_act)
|
||||
if (CULT_MENDED)
|
||||
H.dust()
|
||||
@@ -310,19 +298,17 @@
|
||||
H.confused = 6
|
||||
H.adjustOxyLoss(20)
|
||||
H.adjustToxLoss(10)
|
||||
*/
|
||||
|
||||
/datum/role/cultist/handle_splashed_reagent(var/reagent_id)//also proc'd when holy water is drinked or ingested in any way
|
||||
var/mob/living/carbon/human/H = antag.current
|
||||
if (!istype(H))
|
||||
return
|
||||
var/unholy = H.checkTattoo(TATTOO_HOLY)
|
||||
var/current_act = max(-1,min(5,veil_thickness))
|
||||
if (reagent_id == HOLYWATER)
|
||||
if (holywarning_cooldown <= 0)
|
||||
holywarning_cooldown = 5
|
||||
if (unholy)
|
||||
to_chat(H, "<span class='warning'>You feel the unpleasant touch of holy water, but the mark on your back negates its most debilitating effects.</span>")
|
||||
else
|
||||
to_chat(H, "<span class='danger'>The cold touch of holy water makes your head spin, you're having trouble walking straight.</span>")
|
||||
/* // TODO (UPHEAVAL PART 2) stronger effects the more cult points have been accumulated
|
||||
switch (current_act)
|
||||
if (CULT_MENDED)
|
||||
to_chat(H, "<span class='danger'>The holy water permeates your skin and consumes your cursed blood like mercury digests gold.</span>")
|
||||
@@ -339,11 +325,13 @@
|
||||
if (CULT_EPILOGUE)
|
||||
to_chat(H, "<span class='danger'>Even in these times, holy water proves itself capable of hindering your progression.</span>")
|
||||
|
||||
*/
|
||||
if (reagent_id == HOLYWATER || reagent_id == INCENSE_HAREBELLS)
|
||||
if (unholy)
|
||||
H.eye_blurry = max(H.eye_blurry, 3)
|
||||
return
|
||||
else
|
||||
H.eye_blurry = max(H.eye_blurry, 12)
|
||||
H.Dizzy(12)
|
||||
H.stuttering = max(H.stuttering, 12)
|
||||
H.Jitter(12)
|
||||
/* // TODO (UPHEAVAL PART 2) stronger effects the more cult points have been accumulated
|
||||
switch (current_act)
|
||||
if (CULT_MENDED)
|
||||
H.dust()
|
||||
@@ -392,14 +380,77 @@
|
||||
H.confused = 6
|
||||
H.adjustOxyLoss(20)
|
||||
H.adjustToxLoss(10)
|
||||
*/
|
||||
|
||||
/datum/role/cultist/chief
|
||||
id = CHIEF_CULTIST
|
||||
name = "Chief cultist"
|
||||
logo_state = "cult-chief-logo"
|
||||
/datum/role/cultist/proc/write_rune(var/word_to_draw)
|
||||
var/mob/living/user = antag.current
|
||||
|
||||
/datum/role/cultist/chief/Greet(var/greeting,var/custom)
|
||||
. = ..()
|
||||
if (greeting)
|
||||
to_chat(antag.current, "<span class='notice'>You are the chief cultist. You have been chosen by Nar-Sie to lead this cult to victory. Coordinate with your fellow acolytes, establish a plan, construct a base. Tear down the veil.</span>")
|
||||
to_chat(antag.current, "<span class='notice'>You may speak with your fellow cultists by using ':x'.</span>")
|
||||
if (user.incapacitated())
|
||||
return
|
||||
|
||||
var/muted = user.occult_muted()
|
||||
if (muted)
|
||||
to_chat(user,"<span class='danger'>You find yourself unable to focus your mind on the words of Nar-Sie.</span>")
|
||||
return
|
||||
|
||||
if(!istype(user.loc, /turf))
|
||||
to_chat(user, "<span class='warning'>You do not have enough space to write a proper rune.</span>")
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(user)
|
||||
var/obj/effect/rune/rune = locate() in T
|
||||
|
||||
if(rune)
|
||||
if (rune.invisibility == INVISIBILITY_OBSERVER)
|
||||
to_chat(user, "<span class='warning'>You can feel the presence of a concealed rune here. You have to reveal it before you can add more words to it.</span>")
|
||||
return
|
||||
else if (rune.word1 && rune.word2 && rune.word3)
|
||||
to_chat(user, "<span class='warning'>You cannot add more than 3 words to a rune.</span>")
|
||||
return
|
||||
|
||||
var/datum/rune_word/word = rune_words[word_to_draw]
|
||||
var/list/rune_blood_data = use_available_blood(user, rune_blood_cost, feedback = verbose)
|
||||
if (rune_blood_data[BLOODCOST_RESULT] == BLOODCOST_FAILURE)
|
||||
return
|
||||
|
||||
if (verbose)
|
||||
if(rune)
|
||||
user.visible_message("<span class='warning'>\The [user] chants and paints more symbols on the floor.</span>",\
|
||||
"<span class='warning'>You add another word to the rune.</span>",\
|
||||
"<span class='warning'>You hear chanting.</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>\The [user] begins to chant and paint symbols on the floor.</span>",\
|
||||
"<span class='warning'>You begin drawing a rune on the floor.</span>",\
|
||||
"<span class='warning'>You hear some chanting.</span>")
|
||||
|
||||
if(!user.checkTattoo(TATTOO_SILENT))
|
||||
user.whisper("...[word.rune]...")
|
||||
|
||||
if(rune)
|
||||
if(rune.word1 && rune.word2 && rune.word3)
|
||||
to_chat(user, "<span class='warning'>You cannot add more than 3 words to a rune.</span>")
|
||||
return
|
||||
write_rune_word(get_turf(user), word, rune_blood_data["blood"], caster = user)
|
||||
verbose = FALSE
|
||||
|
||||
|
||||
/datum/role/cultist/proc/erase_rune()
|
||||
var/mob/living/user = antag.current
|
||||
if (!istype(user))
|
||||
return
|
||||
|
||||
if (user.incapacitated())
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(user)
|
||||
var/obj/effect/rune/rune = locate() in T
|
||||
|
||||
if (rune && rune.invisibility == INVISIBILITY_OBSERVER)
|
||||
to_chat(user, "<span class='warning'>You can feel the presence of a concealed rune here, you have to reveal it before you can erase words from it.</span>")
|
||||
return
|
||||
|
||||
var/removed_word = erase_rune_word(get_turf(user))
|
||||
if (removed_word)
|
||||
to_chat(user, "<span class='notice'>You retrace your steps, carefully undoing the lines of the [removed_word] rune.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There aren't any rune words left to erase.</span>")
|
||||
|
||||
@@ -520,7 +520,7 @@
|
||||
to_chat(mob, "<b>[voice_per_admin[user.ckey]]</b> [admin_voice_say] <span class='[admin_voice_style]'>\"[message]\"</span>")
|
||||
|
||||
for(var/mob/dead/observer/O in player_list)
|
||||
to_chat(O, "<span class='game say'><b>[voice_per_admin[user.ckey]]</b> [admin_voice_say] <span class='[admin_voice_style]'>\"[message]\"</span></span>")
|
||||
to_chat(O, "<span class='game say'><b>[voice_per_admin[user.ckey]]</b> [admin_voice_say] (to [mob]) <span class='[admin_voice_style]'>\"[message]\"</span></span>")
|
||||
|
||||
message_admins("Admin [key_name_admin(usr)] has talked to [key_name(mob)] as [voice_per_admin[user.ckey]].")
|
||||
log_rolespeak("[key_name(usr)] as [voice_per_admin[user.ckey]] to [key_name(mob)]: \"[message]\"")
|
||||
|
||||
@@ -596,47 +596,11 @@ The access requirements on the Asteroid Shuttles' consoles have now been revoked
|
||||
|
||||
//////////////BLOOD CULT
|
||||
|
||||
/datum/command_alert/cult_detected
|
||||
name = "Occult Activity Detected - Please Investigate"
|
||||
alert_title = "Occult Activity"
|
||||
force_report = 1
|
||||
/*
|
||||
TODO (UPHEAVAL PART 2) Guess i'll add the future new announcements here
|
||||
|
||||
/datum/command_alert/cult_detected/announce()
|
||||
message = "Irregularities in the fabric of space-time around [station_name()] appear to correlate with the propagation of occult activities. Remember that cult membership is strictly prohibited by Nanotrasen and exposes you to the death penalty, applicable immediately if evidence is made. We encourage the station's security department to investigate, and the rest of the crew to cooperate with them."
|
||||
..()
|
||||
*/
|
||||
|
||||
/datum/command_alert/bloodstones_raised
|
||||
name = "Occult Activity Detected - Station Locked Down"
|
||||
alert_title = "Occult Assault"
|
||||
force_report = 1
|
||||
theme = "endgame"
|
||||
alertlevel = "red"
|
||||
|
||||
/datum/command_alert/bloodstones_raised/announce()
|
||||
message = "Occult energies detected emanating from [station_name()]. Readings suggest an assault from the Cult of Nar-Sie. The station is now locked down under Directive 7-10, until destruction of all the bloodstones has been confirmed. Regroup with your station's security forces and approach the stones with caution, follow your superiors' directions."
|
||||
..()
|
||||
|
||||
/datum/command_alert/bloodstones_anchor
|
||||
name = "Occult Activity Critical - Breach of Space-Time Detected"
|
||||
alert_title = "Occult Assault Critical"
|
||||
force_report = 1
|
||||
theme = "endgame"
|
||||
alertlevel = "red"
|
||||
|
||||
/datum/command_alert/bloodstones_anchor/announce()
|
||||
message = "Occult energies from [station_name()] are reaching a critical point. A breach through space has materialized on one of the bloodstones. It appears to be in [get_area_name(global_anchor_bloodstone, 1)]. Destroy it at all costs, do not let any cultist near it."
|
||||
..()
|
||||
|
||||
/datum/command_alert/bloodstones_broken
|
||||
name = "Occult Activity Ceased - Lock Down Lifted"
|
||||
alert_title = "Occult Gone"
|
||||
force_report = 1
|
||||
stoptheme = 1
|
||||
alertlevel = "blue"
|
||||
|
||||
/datum/command_alert/bloodstones_broken/announce()
|
||||
message = "Destruction of the bloodstones confirmed. The Cult is no longer an immediate threat to Nanotrasen. Lock down of the station has been revoked."
|
||||
..()
|
||||
|
||||
////////MISC STUFF
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
var/active = 0
|
||||
|
||||
var/memory
|
||||
var/datum/body_archive/body_archive
|
||||
|
||||
var/assigned_role
|
||||
var/special_role
|
||||
@@ -558,6 +559,8 @@
|
||||
ticker.minds += mind
|
||||
else
|
||||
world.log << "## DEBUG: mind_initialize(): No ticker ready yet! Please inform Carn"
|
||||
if (!mind.body_archive)
|
||||
mind.body_archive = new(src)
|
||||
if(!mind.name)
|
||||
mind.name = real_name
|
||||
mind.current = src
|
||||
|
||||
@@ -447,7 +447,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality"
|
||||
group = "Supplies"
|
||||
|
||||
/datum/supply_packs/religious//you can only order default-looking bibles for now
|
||||
name = "Religious Paraphernelia"
|
||||
name = "Religious Paraphernalia"
|
||||
contains = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater,
|
||||
/obj/item/weapon/storage/bible,
|
||||
/obj/item/weapon/storage/fancy/incensebox/harebells,
|
||||
|
||||
Reference in New Issue
Block a user