Merge pull request #23238 from GlassEclipse/glasseclipse-branch2

Blood Cult Refactor
This commit is contained in:
Kurfursten
2019-06-19 21:35:48 -05:00
committed by GitHub
12 changed files with 950 additions and 805 deletions

View File

@@ -24,7 +24,8 @@ var/veil_thickness = CULT_PROLOGUE
for (var/obj/structure/cult/spire/S in cult_spires)
S.upgrade()
for (var/obj/effect/rune/R in rune_list)
var/datum/runeset/bloodcult_runeset = global_runesets["blood_cult"]
for (var/obj/effect/rune/R in bloodcult_runeset.rune_list)
R.update_icon()
/proc/spawn_bloodstones(var/turf/source = null)
@@ -107,11 +108,11 @@ var/veil_thickness = CULT_PROLOGUE
to_chat(M,"<span class='warning'>Be mindful, overzealous conversions and soul trapping will bring us unwanted attention. You should focus on the objective with your current force.</span>")
//CULT_PROLOGUE Default thickness, only communication and raise structure runes enabled
//CULT_PROLOGUE Default thickness, only communication and raise structure runes enabled.
//CULT_ACT_I Altar raised. cultists can now convert.
//CULT_ACT_II Cultist amount reached. cultists are now looking for the sacrifice
//CULT_ACT_III Sacrifice complete. cult is now going loud, spreading blood and protecting bloodstones while the crew tries to destroy them
//CULT_ACT_IV Bloodspill threshold reached. bloodstones become indestructible, rift opens above one of them. cultists must open it, crew must close it.
//CULT_ACT_II Cultist amount reached. Cultists are now looking for the sacrifice.
//CULT_ACT_III Sacrifice complete. Cult is now going loud, spreading blood and protecting bloodstones while the crew tries to destroy them.
//CULT_ACT_IV Bloodspill threshold reached. A bloodstone becomes the anchor stone. Cultists must summon Nar-Sie here, whereas crew members must destroy it.
//CULT_EPILOGUE The cult succeeded. The station is no longer reachable from space or through teleportation, and is now part of hell. Nar-Sie hunts the survivors.
//CULT_MENDED The cult failed (bloodstones all destroyed or rift closed). cult magic permanently disabled, living cultists progressively die by themselves.
@@ -133,15 +134,15 @@ var/veil_thickness = CULT_PROLOGUE
var/warning = FALSE
var/list/cult_reminders = list()
/datum/faction/bloodcult/check_win()
return cult_win
/datum/faction/bloodcult/IsSuccessful()
return cult_win
/datum/faction/bloodcult/proc/fail()
if (veil_thickness == CULT_MENDED || veil_thickness == CULT_EPILOGUE)
if(veil_thickness == CULT_MENDED || veil_thickness == CULT_EPILOGUE)
return
stage(CULT_MENDED)
@@ -181,7 +182,7 @@ var/veil_thickness = CULT_PROLOGUE
M.special_role = "Cultist"
/datum/faction/bloodcult/OnPostSetup()
initialize_cultwords()
initialize_runesets()
AppendObjective(/datum/objective/bloodcult_reunion)
@@ -224,7 +225,7 @@ var/veil_thickness = CULT_PROLOGUE
command_alert(/datum/command_alert/bloodstones_broken)
for (var/obj/structure/cult/bloodstone/B in bloodstone_list)
B.takeDamage(B.maxHealth+1)
for (var/obj/effect/rune/R in rune_list)
for (var/obj/effect/rune/R in global_runesets["blood_cult"].rune_list)
R.update_icon()
for (var/datum/role/cultist/C in members)
C.update_cult_hud()
@@ -305,7 +306,7 @@ var/veil_thickness = CULT_PROLOGUE
for (var/obj/structure/cult/spire/S in cult_spires)//spires update their appearance on Act 2 and 3, signaling new available tattoos.
S.upgrade()
for (var/obj/effect/rune/R in rune_list)//runes now available will start pulsing
for (var/obj/effect/rune/R in global_runesets["blood_cult"].rune_list)//runes now available will start pulsing
R.update_icon()
if (istype(new_obj,/datum/objective/bloodcult_bloodbath))
@@ -523,11 +524,67 @@ var/veil_thickness = CULT_PROLOGUE
else
data[BLOODCOST_LID_CONTAINER] = 1
var/mob/living/silicon/robot/robot_user = user
if(istype(robot_user))
var/module_items = robot_user.get_equipped_items() //This function allows robot modules to be used as blood sources. Somewhat important, considering silicons have no blood.
for(var/obj/item/weapon/gripper/G_held in module_items)
if (!istype(G_held) || !G_held.wrapped || !istype(G_held.wrapped,/obj/item/weapon/reagent_containers))
continue
var/obj/item/weapon/reagent_containers/gripper_item = G_held.wrapped
if(round(gripper_item.reagents.get_reagent_amount(BLOOD)))
var/blood_volume = round(gripper_item.reagents.get_reagent_amount(BLOOD))
if (blood_volume)
data[BLOODCOST_TARGET_HELD] = gripper_item
if (gripper_item.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
for(var/obj/item/weapon/reagent_containers/G_held in module_items)
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
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)
//Does the user have blood? (the user can pay in blood without having to bleed first)
if(istype(H_user) && !(H_user.species.flags & NO_BLOOD))
var/blood_volume = round(H_user.vessel.get_reagent_amount(BLOOD))
var/blood_gathered = min(amount_needed-amount_gathered,blood_volume)
@@ -537,8 +594,8 @@ var/veil_thickness = CULT_PROLOGUE
if (amount_gathered >= amount_needed)
data[BLOODCOST_RESULT] = BLOODCOST_TARGET_USER
return data
return data
data[BLOODCOST_RESULT] = BLOODCOST_FAILURE
return data

View File

@@ -0,0 +1,109 @@
var/runesets_initialized = 0
var/list/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"

View File

@@ -56,13 +56,13 @@ var/list/arcane_tomes = list()
var i = 1
for(var/subtype in subtypesof(/datum/rune_spell))
var/datum/rune_spell/instance = subtype
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/cultword/word1 = initial(instance.word1)
var/datum/cultword/word2 = initial(instance.word2)
var/datum/cultword/word3 = initial(instance.word3)
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
@@ -241,7 +241,7 @@ var/list/arcane_tomes = list()
/obj/item/weapon/tome/AltClick(var/mob/user)
var/list/choices = list()
var/datum/rune_spell/instance
var/datum/rune_spell/blood_cult/instance
var/list/choice_to_talisman = list()
var/image/talisman_image
for(var/obj/item/weapon/talisman/T in talismans)
@@ -302,7 +302,7 @@ var/list/arcane_tomes = list()
pixel_y=0
/obj/item/weapon/talisman/proc/talisman_name()
var/datum/rune_spell/instance = spell_type
var/datum/rune_spell/blood_cult/instance = spell_type
if (blood_text)
return "\[blood message\]"
if (instance)
@@ -322,7 +322,7 @@ var/list/arcane_tomes = list()
to_chat(user, "<span class='info'>This one however seems pretty unremarkable.</span>")
return
var/datum/rune_spell/instance = spell_type
var/datum/rune_spell/blood_cult/instance = spell_type
if (iscultist(user) || isobserver(user))
if (attuned_rune)
@@ -347,7 +347,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/instance = spell_type
var/datum/rune_spell/blood_cult/instance = spell_type
if (initial(instance.touch_cast))
new spell_type(user, src, "touch", target)
qdel(src)
@@ -392,7 +392,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/R)
/obj/item/weapon/talisman/proc/imbue(var/mob/user, var/obj/effect/rune/blood_cult/R)
if (!user || !R)
return
@@ -400,7 +400,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/spell = get_rune_spell(user,null,"examine",R.word1, R.word2, R.word3)
var/datum/rune_spell/blood_cult/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))
@@ -434,16 +434,19 @@ var/list/arcane_tomes = list()
uses = initial(spell.talisman_uses)
var/talisman_interaction = initial(spell.talisman_absorb)
if (R.active_spell)//some runes may change their interaction type dynamically (ie: Path Exit runes)
talisman_interaction = R.active_spell.talisman_absorb
if (istype(R.active_spell,/datum/rune_spell/portalentrance))
var/datum/rune_spell/portalentrance/entrance = R.active_spell
var/datum/rune_spell/blood_cult/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 (entrance.network)
word_pulse(cultwords[entrance.network])
else if (istype(R.active_spell,/datum/rune_spell/portalexit))
var/datum/rune_spell/portalentrance/exit = R.active_spell
word_pulse(global_runesets["blood_cult"].words[entrance.network])
else if (istype(active_spell,/datum/rune_spell/blood_cult/portalexit))
var/datum/rune_spell/blood_cult/portalentrance/exit = active_spell
if (exit.network)
word_pulse(cultwords[exit.network])
word_pulse(global_runesets["blood_cult"].words[exit.network])
switch(talisman_interaction)
if (RUNE_CAN_ATTUNE)
@@ -458,7 +461,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/cultword/W)
/obj/item/weapon/talisman/proc/word_pulse(var/datum/runeword/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)
@@ -1154,14 +1157,12 @@ var/list/arcane_tomes = list()
armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0)
siemens_coefficient = 0
///////////////////////////////////////DEBUG ITEMS////////////////////////////////////////////////
//Pamphlet: turns you into a cultist
/obj/item/weapon/bloodcult_pamphlet
name = "cult of Nar-Sie pamphlet"
desc = "Looks like a page torn from a tome. One glimpse at it surely can't hurt you."
desc = "Looks like a page torn from one of those cultist tomes. It is titled \"Ten reasons why Nar-Sie can improve your life!\""
icon = 'icons/obj/cult.dmi'
icon_state ="pamphlet"
throwforce = 0
@@ -1232,11 +1233,14 @@ var/list/arcane_tomes = list()
volume = 60
force = 5
throwforce = 7
/obj/item/weapon/reagent_containers/food/drinks/cult/examine(var/mob/user)
..()
if (iscultist(user))
to_chat(user, "<span class='info'>Drinking blood from this cup will always safely replenish your own vessels, regardless of blood types. The opposite is true to non-cultists. Throwing this cup at them may force them to swallow some of its content if their face isn't covered.</span>")
if(issilicon(user))
to_chat(user, "<span class='info'>Drinking blood from this cup will always safely replenish the vessels of cultists, regardless of blood type. It's a shame you're a robot.</span>")
else
to_chat(user, "<span class='info'>Drinking blood from this cup will always safely replenish your own vessels, regardless of blood types. The opposite is true to non-cultists. Throwing this cup at them may force them to swallow some of its content if their face isn't covered.</span>")
else if (get_blood(reagents))
to_chat(user, "<span class='sinister'>Its contents look delicious though. Surely a sip won't hurt...</span>")

View File

@@ -1,8 +1,7 @@
var/list/rune_list = list()//all runes currently in the world
var/list/uristrune_cache = list()//icon cache, so the whole blending process is only done once per rune.
/obj/effect/rune
/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'
@@ -13,10 +12,11 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
//Whether the rune is pulsating
var/animated = 0
//A rune is made of up to 3 words
var/datum/cultword/word1
var/datum/cultword/word2
var/datum/cultword/word3
//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
//An image we'll show to the AI instead of the rune
var/image/blood_image
@@ -45,15 +45,10 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
if(AI.client)
AI.client.images += blood_image
rune_list.Add(src)
global_runesets[runeset_identifier].rune_list.Add(src)
..()
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()
for(var/mob/living/silicon/ai/AI in player_list)
@@ -74,66 +69,21 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
active_spell.abort()
active_spell = null
rune_list.Remove(src)
holomap_markers -= HOLOMAP_MARKER_CULT_RUNE+"_\ref[src]"
global_runesets[runeset_identifier].rune_list.Remove(src)
..()
/obj/effect/rune/examine(var/mob/user)
..()
var/datum/rune_spell/rune_name = get_rune_spell(null, null, "examine", word1,word2,word3)
//cultists can read the words, and be informed if it calls a spell
if (iscultist(user))
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)
if (initial(rune_name.Act_restriction) <= veil_thickness)
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>")
else
to_chat(user, "<span class='danger'>The veil is still too thick for you to draw power from this rune.</span>")
//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))
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>")
//so do observers
else if (isobserver(user))
to_chat(user, "<span class='info'>[rune_name ? "That's \a <b>[initial(rune_name.name)]</b> rune." : "It doesn't match any rune spell."]</span>")
if (rune_name)
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 not understand the meaning (though they can always check it up). 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
/obj/effect/rune/cultify()
return
@@ -155,12 +105,12 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
/obj/effect/rune/update_icon()
var/datum/rune_spell/spell = get_rune_spell(null, null, "examine", word1, word2, word3)
if(spell && initial(spell.Act_restriction) <= veil_thickness)
if(spell) // && initial(spell.Act_restriction) <= veil_thickness) Add to bloodcult
animated = 1
else
animated = 0
var/lookup = ""
var/lookup = ""
if (word1)
lookup += "[word1.icon_state]-[animated]-[blood1.data["blood_colour"]]"
if (word2)
@@ -173,13 +123,13 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
else
var/icon/I1 = icon('icons/effects/uristrunes.dmi', "")
if (word1)
I1 = make_uristword(word1,blood1,animated)
I1 = make_iconcache(word1,blood1,animated)
var/icon/I2 = icon('icons/effects/uristrunes.dmi', "")
if (word2)
I2 = make_uristword(word2,blood2,animated)
I2 = make_iconcache(word2,blood2,animated)
var/icon/I3 = icon('icons/effects/uristrunes.dmi', "")
if (word3)
I3 = make_uristword(word3,blood3,animated)
I3 = make_iconcache(word3,blood3,animated)
var/icon/I = icon('icons/effects/uristrunes.dmi', "")
I.Blend(I1, ICON_OVERLAY)
@@ -192,47 +142,8 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
idle_pulse()
else
animate(src)
/obj/effect/rune/proc/idle_pulse()
//This masterpiece of a color matrix stack produces a nice animation no matter which color was the blood used for the rune.
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
animate(color = list(1.125,0.06,0,0,0,1.125,0.06,0,0.06,0,1.125,0,0,0,0,1,0,0,0,0), time = 2)//2
animate(color = list(1.25,0.12,0,0,0,1.25,0.12,0,0.12,0,1.25,0,0,0,0,1,0,0,0,0), time = 2)//3
animate(color = list(1.375,0.19,0,0,0,1.375,0.19,0,0.19,0,1.375,0,0,0,0,1,0,0,0,0), time = 1.5)//4
animate(color = list(1.5,0.27,0,0,0,1.5,0.27,0,0.27,0,1.5,0,0,0,0,1,0,0,0,0), time = 1.5)//5
animate(color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)//6
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)//7
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)//8
animate(color = list(2,0.67,0.27,0,0.27,2,0.67,0,0.67,0.27,2,0,0,0,0,1,0,0,0,0), time = 5)//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)//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)//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)//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 = 1)//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 = 1)//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 = 1)//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 = 1)//2
/obj/effect/rune/proc/one_pulse()
animate(src, color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(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)
animate(color = list(1.875,0.56,0.19,0,0.19,1.875,0.56,0,0.56,0.19,1.875,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.75,0.45,0.12,0,0.12,1.75,0.45,0,0.45,0.12,1.75,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 0.75)
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.75)
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)
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.5)
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.25)
animate(color = list(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0), time = 1)
spawn (10)
if(animated)
idle_pulse()
else
animate(src)
/obj/effect/rune/proc/make_uristword(var/datum/cultword/word, var/datum/reagent/blood/blood, var/animated)
/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
@@ -280,19 +191,48 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
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
animate(color = list(1.125,0.06,0,0,0,1.125,0.06,0,0.06,0,1.125,0,0,0,0,1,0,0,0,0), time = 2)//2
animate(color = list(1.25,0.12,0,0,0,1.25,0.12,0,0.12,0,1.25,0,0,0,0,1,0,0,0,0), time = 2)//3
animate(color = list(1.375,0.19,0,0,0,1.375,0.19,0,0.19,0,1.375,0,0,0,0,1,0,0,0,0), time = 1.5)//4
animate(color = list(1.5,0.27,0,0,0,1.5,0.27,0,0.27,0,1.5,0,0,0,0,1,0,0,0,0), time = 1.5)//5
animate(color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)//6
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)//7
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)//8
animate(color = list(2,0.67,0.27,0,0.27,2,0.67,0,0.67,0.27,2,0,0,0,0,1,0,0,0,0), time = 5)//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)//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)//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)//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 = 1)//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 = 1)//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 = 1)//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 = 1)//2
/obj/effect/rune/proc/one_pulse()
animate(src, color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(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)
animate(color = list(1.875,0.56,0.19,0,0.19,1.875,0.56,0,0.56,0.19,1.875,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.75,0.45,0.12,0,0.12,1.75,0.45,0,0.45,0.12,1.75,0,0,0,0,1,0,0,0,0), time = 1)
animate(color = list(1.625,0.35,0.06,0,0.06,1.625,0.35,0,0.35,0.06,1.625,0,0,0,0,1,0,0,0,0), time = 0.75)
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.75)
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)
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.5)
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.25)
animate(color = list(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0), time = 1)
spawn (10)
if(animated)
idle_pulse()
else
animate(src)
/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))
trigger(user)
if(istype(I, /obj/item/weapon/talisman))
var/obj/item/weapon/talisman/T = I
T.imbue(user,src)
return
..()
/obj/effect/rune/Crossed(var/atom/movable/mover)
if (ismob(mover))
@@ -305,19 +245,228 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
if (active_spell && ismob(mover))
active_spell.Removed(mover)
/proc/write_rune_word(var/turf/T,var/datum/reagent/blood/source,var/word = null)
/obj/effect/rune/attack_animal(var/mob/living/simple_animal/user)
if(istype(user, /mob/living/simple_animal/construct))
trigger(user)
/obj/effect/rune/attack_paw(var/mob/living/user)
if(ismonkey(user))
trigger(user)
/obj/effect/rune/attack_hand(var/mob/living/user)
trigger(user)
/obj/effect/rune/attack_robot(var/mob/living/user) //Allows for robots to remotely trigger runes, since attack_robot has infinite range.
trigger(user)
/obj/effect/rune/proc/trigger(var/mob/living/user)
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.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)
if (active_spell)
active_spell.midcast(user)
return
reveal()
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/proc/fizzle(var/mob/living/user)
var/silent = user.checkTattoo(TATTOO_SILENT)
if(!silent)
user.say(pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP","I'F ON'Y I 'AD 'TAB' E"))
one_pulse()
visible_message("<span class='warning'>The markings pulse with a small burst of light, then fall dark.</span>",\
"<span class='warning'>The markings pulse with a small burst of light, then fall dark.</span>",\
"<span class='warning'>You hear a faint fizzle.</span>")
/obj/effect/rune/proc/conceal()
if(active_spell && !active_spell.can_conceal)
active_spell.abort(RITUALABORT_CONCEAL)
animate(src, alpha = 0, time = 5)
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()
conceal_cooldown = 1
spawn(100)
if (src && loc)
conceal_cooldown = 0
return 1
return 0
/////////////////////////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.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)
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/datum/reagent/blood/source, var/word = null)
if (!word)
return 0
//Is there already a rune on the turf? if yes, let's try adding a word to it.
//Add word to a rune if there is one, otherwise create one. However, there can be no more than 3 words.
//Returns 0 if failure, 1 if finished a rune, 2 if success but rune still has room for words.
var/obj/effect/rune/rune = locate() in T
if (!rune)
rune = new/obj/effect/rune(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.
rune = new /obj/effect/rune/blood_cult(T)
if (rune.word1 && rune.word2 && rune.word3)
return 0
//Let's add a word at the end of the pile. This way each world could technically have its own color.
if (!rune.word1)
rune.word1 = word
rune.blood1 = new()
@@ -372,27 +521,27 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
if (source.data["virus2"])
rune.blood3.data["virus2"] = virus_copylist(source.data["virus2"])
//think twice before touching runes made with contaminated blood
if (rune.blood3)
if (rune.blood3) //Viruses spread to the other blood.
rune.virus2 = rune.blood1.data["virus2"] | rune.blood2.data["virus2"] | rune.blood3.data["virus2"]
rune.update_icon()
return 1//That rune now has 3 words, that's a wrap.
return 1
else if (rune.blood2)
rune.virus2 = rune.blood1.data["virus2"] | rune.blood2.data["virus2"]
else if (rune.blood1)
rune.virus2 = rune.blood1.data["virus2"]
rune.update_icon()
return 2//There's room for more words on this rune, let's immediately prompt the player to write another one.
return 2
/proc/erase_rune_word(var/turf/T)
var/obj/effect/rune/rune = locate() in T
if (!rune)
if(!rune)
return null
var/word_erased
if (rune.word3)
if(rune.word3)
word_erased = rune.word3.rune
rune.word3 = null
rune.blood3 = null
@@ -401,12 +550,12 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
rune.active_spell.abort(RITUALABORT_ERASED)
rune.active_spell = null
rune.overlays.len = 0
else if (rune.word2)
else if(rune.word2)
word_erased = rune.word2.rune
rune.word2 = null
rune.blood2 = null
rune.update_icon()
else if (rune.word1)
else if(rune.word1)
word_erased = rune.word1.rune
rune.word1 = null
rune.blood1 = null
@@ -416,89 +565,4 @@ var/list/uristrune_cache = list()//icon cache, so the whole blending process is
qdel(rune)
return null
return word_erased
/obj/effect/rune/attack_animal(var/mob/living/simple_animal/user)
if(istype(user, /mob/living/simple_animal/construct))
trigger(user)
/obj/effect/rune/attack_paw(var/mob/living/user)
if(ismonkey(user))
trigger(user)
/obj/effect/rune/attack_hand(var/mob/living/user)
trigger(user)
/obj/effect/rune/proc/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.muted())
to_chat(user, "<span class='danger'>You find yourself unable to focus your mind on the arcane words of the rune.</span>")
return
var/silent_casting = user.checkTattoo(TATTOO_SILENT)
if (!silent_casting)
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)
if (active_spell)//rune is already channeling a spell? let's see if we can interact with it somehow.
if (talisman_trigger)
active_spell.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/proc/fizzle(var/mob/living/user)
var/silent = user.checkTattoo(TATTOO_SILENT)
if (!silent)
user.say(pick("B'ADMINES SP'WNIN SH'T","IC'IN O'OC","RO'SHA'M I'SA GRI'FF'N ME'AI","TOX'IN'S O'NM FI'RAH","IA BL'AME TOX'IN'S","FIR'A NON'AN RE'SONA","A'OI I'RS ROUA'GE","LE'OAN JU'STA SP'A'C Z'EE SH'EF","IA PT'WOBEA'RD, IA A'DMI'NEH'LP","I'F ON'Y I 'AD 'TAB' E"))
one_pulse()
visible_message("<span class='warning'>The markings pulse with a small burst of light, then fall dark.</span>",\
"<span class='warning'>The markings pulse with a small burst of light, then fall dark.</span>",\
"<span class='warning'>You hear a faint fizzle.</span>")
/obj/effect/rune/proc/conceal()
if (active_spell && !active_spell.can_conceal)
active_spell.abort(RITUALABORT_CONCEAL)
animate(src, alpha = 0, time = 5)
spawn(6)
invisibility=INVISIBILITY_OBSERVER
alpha = 127
/obj/effect/rune/proc/reveal()
if (invisibility != 0)
alpha = 0
invisibility=0
animate(src, alpha = 255, time = 5)
one_pulse()
conceal_cooldown = 1
spawn (100)
if (src && loc)
conceal_cooldown = 0
return 1
return 0

View File

@@ -1,11 +1,11 @@
var/list/uristrune_cache = list()
/spell/cult
panel = "Cult"
override_base = "cult"
user_type = USER_TYPE_CULT
//SPELL I
/spell/cult/trace_rune
/spell/cult/trace_rune //Abstract, base for all blood-based rune systems
name = "Trace Rune"
desc = "(1 BLOOD) Use available blood to write down words. Three words form a rune."
hud_state = "cult_word"
@@ -21,21 +21,54 @@
cast_delay = 15
var/list/data = list()
var/datum/cultword/word = null
var/runeset_identifier = null
var/datum/runeword/word = null
var/obj/effect/rune/rune = null
var/datum/rune_spell/spell = null
var/remember = 0
var/blood_cost = 1
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 (remember)
remember = 0
if(continue_drawing) //Resets the current spell (tome selection) if continue_drawing is not 1.
continue_drawing = 0
else
spell = null//so we're not stuck trying to write the same spell over and over again
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
if(write_rune_word(get_turf(user), data["blood"], word = global_runesets[runeset_identifier].words[word]) > 1)
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
spell = null
if (user.checkTattoo(TATTOO_FAST))
cast_delay = 5
@@ -46,58 +79,75 @@
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/spell_do_after(var/mob/user, var/delay, var/numticks = 3)
/spell/cult/trace_rune/blood_cult/spell_do_after(var/mob/user, var/delay, var/numticks = 3)
if(block)
if(block) //Part of class spell, gets reset back to 0 after done casting. Prevents spamming.
return 0
block = 1
if(!istype(user.loc, /turf))
to_chat(user, "<span class='warning'>You do not have enough space to write a proper rune.</span>")
return 0
var/obj/item/weapon/tome/tome = locate() in user.held_items
var/turf/T = get_turf(user)
rune = locate() in T
rune = locate() in T
if (rune)
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>")
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 0
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 0
var/obj/item/weapon/tome/tome = locate() in user.held_items
if (spell || tome)
if (spell)
if (!tome)
to_chat(user, "<span class='warning'>Without reading the tome, you have trouble remembering the arcane words.</span>")
return 0
if(spell) //If player already begun drawing a rune with help of a tome
if(!tome)
to_chat(user, "<span class='warning'>Without reading the tome, you have trouble continuing to draw the arcane words.</span>")
return 0
else
var/list/available_runes = list()
var/i = 1
for(var/subtype in subtypesof(/datum/rune_spell))
var/datum/rune_spell/instance = subtype
if (initial(instance.Act_restriction) <= veil_thickness)
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"
tome.item_state = "tome-open"
flick("tome-flickopen",tome)
playsound(user, "pageturn", 50, 1, -5)
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/cultword/instance
if (!rune)
var/datum/runeword/blood_cult/instance
if(!rune)
instance = initial(spell.word1)
else if (rune.word1.type != initial(spell.word1))
to_chat(user, "<span class='warning'>This rune's first word conflicts with the [initial(spell.name)] rune's syntax.</span>")
to_chat(user, "<span class='warning'>[rune.word1.type] --- [spell.word1.type]</span>")
return 0
else if (!rune.word2)
instance = initial(spell.word2)
else if (rune.word2.type != initial(spell.word2))
to_chat(user, "<span class='warning'>This rune's second word conflicts with the [initial(spell.name)] rune's syntax.</span>")
return 0
else if (!rune.word3)
instance = initial(spell.word3)
else
to_chat(user, "<span class='warning'>You cannot add more than 3 words to a rune.</span>")
return 0
word = initial(instance.english)
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
i++
if(tome.state == TOME_CLOSED)
tome.icon_state = "tome-open"
tome.item_state = "tome-open"
flick("tome-flickopen",tome)
playsound(user, "pageturn", 50, 1, -5)
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
if(!rune)
instance = initial(spell.word1)
else if (rune.word1.type != initial(spell.word1))
to_chat(user, "<span class='warning'>This rune's first word conflicts with the [initial(spell.name)] rune's syntax.</span>")
to_chat(user, "<span class='warning'>[rune.word1.type] --- [spell.word1.type]</span>")
return 0
else if (!rune.word2)
instance = initial(spell.word2)
@@ -106,23 +156,22 @@
return 0
else if (!rune.word3)
instance = initial(spell.word3)
else//wtf?
else
to_chat(user, "<span class='warning'>You cannot add more than 3 words to a rune.</span>")
return 0
word = initial(instance.english)
word = initial(instance.english)
else
word = input(user,"Choose a word to add to the rune.", "Trace Rune Word", null) as null|anything in cultwords
else //Otherwise they want to begin drawing each word manually
word = input(user,"Choose a word to add to the rune.", "Trace Rune Word", null) as null|anything in global_runesets[runeset_identifier].words
if (!word)
return 0
data = use_available_blood(user, blood_cost)
data = use_available_blood(user, blood_cost)
if (data[BLOODCOST_RESULT] == BLOODCOST_FAILURE)
return 0
if (rune)
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>")
@@ -131,32 +180,31 @@
"<span class='warning'>You begin drawing a rune on the floor.</span>",\
"<span class='warning'>You hear some chanting.</span>")
var/datum/cultword/r_word = cultwords[word]
if (user.checkTattoo(TATTOO_SILENT))
return ..()
user.whisper("...[r_word.rune]...")
if(!user.checkTattoo(TATTOO_SILENT))
user.whisper("...[global_runesets[runeset_identifier].words[word].rune]...")
return ..()
/spell/cult/trace_rune/cast(var/list/targets, var/mob/living/carbon/user)
..()
if (rune && rune.word1 && rune.word2 && rune.word3)
to_chat(user, "<span class='warning'>You cannot add more than 3 words to a rune.</span>")
return
if (write_rune_word(get_turf(user) ,data["blood"] ,word = cultwords[word]) > 1)
remember = 1
perform(user)//imediately try writing another word
/spell/cult/trace_rune/blood_cult/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
if(write_rune_word(get_turf(user), data["blood"], word = global_runesets[runeset_identifier].words[word]) > 1)
continue_drawing = 1
perform(user) //Recursion for drawing runes in a row with tome.
else
var/obj/item/weapon/tome/tome = locate() in user.held_items
if (tome && tome.state == TOME_OPEN)
if(tome && tome.state == TOME_OPEN)
tome.icon_state = "tome"
tome.item_state = "tome"
flick("tome-stun",tome)
tome.state = TOME_CLOSED
//SPELL II
/spell/cult/erase_rune
/spell/cult/erase_rune //Works on all types of runes unless specified otherwise.
name = "Erase Rune"
desc = "Remove the last word written of the rune you're standing above."
hud_state = "cult_erase"

View File

@@ -1,96 +0,0 @@
var/cultwords_initialized = 0
var/list/cultwords = list()//datums go in here
var/list/cultwords_english = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide")
var/list/cultwords_rune = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri")
var/list/cultwords_icons = list("rune-1","rune-2","rune-4","rune-8","rune-16","rune-32","rune-64","rune-128", "rune-256", "rune-512")
/datum/cultword
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
/proc/initialize_cultwords()
if (cultwords_initialized)
return
for(var/subtype in subtypesof(/datum/cultword))
var/datum/cultword/new_word = new subtype()
cultwords[new_word.english] = new_word
cultwords_initialized = 1
//for now we're not calling it anywhere, but should we want to randomize words again later, that's what that proc is for.
/proc/randomize_cultwords()
var/list/available_rnwords = cultwords_rune
var/list/available_icons = cultwords_icons
for(var/datum/cultword/cultword in cultwords)
var/picked_rnword = pick(available_rnwords)
var/picked_icon = pick(available_icons)
cultword.rune = picked_rnword
cultword.icon_state = picked_icon
available_rnwords.Remove(picked_rnword)
available_icons.Remove(picked_icon)
for (var/obj/effect/rune/rune in rune_list)
rune.update_icon()
/datum/cultword/travel
english = "travel"
rune = "ire"
icon_state = "rune-1"
color = "yellow"
/datum/cultword/blood
english = "blood"
rune = "ego"
icon_state = "rune-2"
color = "maroon"
/datum/cultword/join
english = "join"
rune = "nahlizet"
icon_state = "rune-4"
color = "green"
/datum/cultword/hell
english = "hell"
rune = "certum"
icon_state = "rune-8"
color = "red"
/datum/cultword/destroy
english = "destroy"
rune = "veri"
icon_state = "rune-16"
color = "purple"
/datum/cultword/technology
english = "technology"
rune = "jatkaa"
icon_state = "rune-32"
color = "blue"
/datum/cultword/self
english = "self"
rune = "mgar"
icon_state = "rune-64"
color = null
/datum/cultword/see
english = "see"
rune = "balaq"
icon_state = "rune-128"
color = "fuchsia"
/datum/cultword/other
english = "other"
rune = "karazet"
icon_state = "rune-256"
color = "teal"
/datum/cultword/hide
english = "hide"
rune = "geeri"
icon_state = "rune-512"
color = "silver"

View File

@@ -23,7 +23,7 @@
antag.current.add_language(LANGUAGE_CULT)
if((ishuman(antag.current) || ismonkey(antag.current)) && !(locate(/spell/cult) in antag.current.spell_list))
antag.current.add_spell(new /spell/cult/trace_rune, "cult_spell_ready", /obj/abstract/screen/movable/spell_master/bloodcult)
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:")

View File

@@ -10,7 +10,7 @@
if(ismalf(src))
to_chat(src, "<b>These laws may be changed by other players, or by you being the traitor.</b>")
for(var/obj/effect/rune/rune in rune_list) //HOLY FUCK WHO THOUGHT LOOPING THROUGH THE WORLD WAS A GOOD IDEA
for(var/obj/effect/rune/rune in global_runesets["blood_cult"].rune_list) //HOLY FUCK WHO THOUGHT LOOPING THROUGH THE WORLD WAS A GOOD IDEA
client.images += rune.blood_image
regenerate_icons()

View File

@@ -6,6 +6,7 @@
var/flashed = 0
var/syndicate = 0
var/cult_permitted = 0 //For use in some special items to allow silicons to be converted
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
var/list/alarms_to_show = list()
var/list/alarms_to_clear = list()

View File

@@ -97,7 +97,7 @@ var/savefile/panicfile
paperwork_setup()
initialize_cultwords()
initialize_runesets()
//sun = new /datum/sun()
radio_controller = new /datum/controller/radio()

View File

@@ -322,6 +322,7 @@
#include "code\datums\gamemode\factions\bloodcult\bloodcult.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_buildings.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_cultify_exceptions.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_data.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_effects.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_flavourlines.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_hell_rising.dm"
@@ -333,7 +334,6 @@
#include "code\datums\gamemode\factions\bloodcult\bloodcult_runespells.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_spells.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_tattoos.dm"
#include "code\datums\gamemode\factions\bloodcult\bloodcult_words.dm"
#include "code\datums\gamemode\factions\legacy_cult\cult.dm"
#include "code\datums\gamemode\factions\legacy_cult\cult_items.dm"
#include "code\datums\gamemode\factions\legacy_cult\cult_structures.dm"