Cultist Memory (#10622)

This commit is contained in:
Geeves
2020-12-22 15:25:30 +01:00
committed by GitHub
parent 881db313de
commit 6ff5d78786
47 changed files with 484 additions and 293 deletions
+1
View File
@@ -469,6 +469,7 @@
#include "code\game\gamemodes\changeling\implements\powers\stings.dm"
#include "code\game\gamemodes\changeling\implements\powers\suck.dm"
#include "code\game\gamemodes\cult\cult.dm"
#include "code\game\gamemodes\cult\cultist_datum.dm"
#include "code\game\gamemodes\cult\hell_universe.dm"
#include "code\game\gamemodes\cult\narsie.dm"
#include "code\game\gamemodes\cult\cultify\mob.dm"
@@ -10,9 +10,9 @@
/obj/screen/vampire/blood/Click(var/location, var/control, var/params)
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
to_chat(H, SPAN_NOTICE("You have [H.mind.vampire.blood_usable]u of blood to use for vampiric powers."))
to_chat(H, SPAN_WARNING("If it drops too low, you will go into a blood frenzy. You can only store a maximum of [VAMPIRE_MAX_USABLE_BLOOD]u."))
var/datum/vampire/vampire = usr.mind.antag_datums[MODE_VAMPIRE]
to_chat(usr, SPAN_NOTICE("You have [vampire.blood_usable]u of blood to use for vampiric powers."))
to_chat(usr, SPAN_WARNING("If it drops too low, you will go into a blood frenzy. You can only store a maximum of [VAMPIRE_MAX_USABLE_BLOOD]u."))
/obj/screen/vampire/frenzy
name = "frenzy count"
@@ -21,9 +21,9 @@
/obj/screen/vampire/frenzy/Click(var/location, var/control, var/params)
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
to_chat(H, SPAN_WARNING("Your frenzy counter is at [H.mind.vampire.frenzy]."))
to_chat(H, SPAN_WARNING("If it raises too high, you will gain incredible power, but they will be very unsubtle. You can lower your frenzy counter by getting out of holy areas and by obtaining usable blood."))
var/datum/vampire/vampire = usr.mind.antag_datums[MODE_VAMPIRE]
to_chat(usr, SPAN_WARNING("Your frenzy counter is at [vampire.frenzy]."))
to_chat(usr, SPAN_WARNING("If it raises too high, you will gain incredible power, but they will be very unsubtle. You can lower your frenzy counter by getting out of holy areas and by obtaining usable blood."))
/obj/screen/vampire/suck
name = "blood_suck"
+2 -1
View File
@@ -25,7 +25,8 @@
runes_by_name[R.name] = rune
tome_data += "<div class='rune-block'>"
tome_data += "<b>[capitalize_first_letters(R.name)]</b>: <i>[R.desc]</i><br>"
tome_data += "This rune <b><i>[R.can_be_talisman() ? "can" : "cannot"]</i></b> be turned into a talisman.<br><hr>"
tome_data += "This rune <b><i>[R.can_be_talisman() ? "can" : "cannot"]</i></b> be turned into a talisman.<br>"
tome_data += "This rune <b><i>[R.can_memorize() ? "can" : "cannot"]</i></b> be memorized to be scribed without a tome.<br><hr>"
tome_data += "</div>"
/datum/controller/subsystem/cult/proc/add_rune(var/datum/rune/R)
+5 -5
View File
@@ -54,9 +54,7 @@
var/has_been_rev = 0//Tracks if this mind has been a rev or not
var/datum/faction/faction //associated faction
var/datum/changeling/changeling //changeling holder
var/datum/vampire/vampire //vampire holder
var/list/antag_datums = list()
var/rev_cooldown = 0
@@ -88,6 +86,8 @@
/datum/mind/proc/transfer_to(mob/living/new_character)
if(!istype(new_character))
world.log << "## DEBUG: transfer_to(): Some idiot has tried to transfer_to( a non mob/living mob. Please inform Carn"
var/datum/changeling/changeling = antag_datums[MODE_CHANGELING]
var/datum/vampire/vampire = antag_datums[MODE_VAMPIRE]
if(current) //remove ourself from our old body's mind variable
if(changeling)
current.remove_changeling_powers()
@@ -485,8 +485,8 @@
role_alt_title = null
assigned_job = null
//faction = null //Uncommenting this causes a compile error due to 'undefined type', fucked if I know.
changeling = null
vampire = null
for(var/thing in antag_datums)
QDEL_NULL(thing)
initial_account = null
objectives = list()
special_verbs = list()
+2 -1
View File
@@ -26,7 +26,8 @@
faction = "Changeling"
/datum/antagonist/changeling/get_special_objective_text(var/datum/mind/player)
return "<br><b>Changeling ID:</b> [player.changeling.changelingID].<br><b>Genomes Absorbed:</b> [player.changeling.absorbedcount]"
var/datum/changeling/changeling = player.antag_datums[MODE_CHANGELING]
return "<br><b>Changeling ID:</b> [changeling.changelingID].<br><b>Genomes Absorbed:</b> [changeling.absorbedcount]"
/datum/antagonist/changeling/update_antag_mob(var/datum/mind/player)
..()
+9 -1
View File
@@ -87,11 +87,19 @@ var/datum/antagonist/cultist/cult
if(player.current && !istype(player.current, /mob/living/simple_animal/construct))
player.current.add_language(LANGUAGE_CULT)
player.current.verbs |= /datum/antagonist/cultist/proc/appraise_offering
player.current.verbs |= /datum/cultist/proc/memorize_rune
player.current.verbs |= /datum/cultist/proc/forget_rune
player.current.verbs |= /datum/cultist/proc/scribe_rune
player.antag_datums[MODE_CULTIST] = new /datum/cultist()
/datum/antagonist/cultist/remove_antagonist(var/datum/mind/player)
. = ..()
player.current.verbs -= /datum/antagonist/cultist/proc/appraise_offering
player.current.verbs -= /datum/cultist/proc/memorize_rune
player.current.verbs -= /datum/cultist/proc/forget_rune
player.current.verbs -= /datum/cultist/proc/scribe_rune
/datum/antagonist/cultist/can_become_antag(var/datum/mind/player, ignore_role = 1)
if(!..())
@@ -104,7 +112,7 @@ var/datum/antagonist/cultist/cult
/datum/antagonist/cultist/proc/appraise_offering()
set name = "Appraise Offering"
set desc = "Find out if someone close-by can be converted to join the cult, or not."
set category = "IC"
set category = "Cultist"
var/list/targets = list()
for(var/mob/living/carbon/target in view(5, usr))
+5 -3
View File
@@ -29,13 +29,15 @@ var/datum/antagonist/thrall/thralls = null
var/datum/mind/M = user.mind
if(!M)
return
if(M.vampire.master_image)
user.client.images += M.vampire.master_image
var/datum/vampire/vampire = M.antag_datums[MODE_VAMPIRE]
if(vampire.master_image)
user.client.images += vampire.master_image
/datum/antagonist/thrall/update_antag_mob(var/datum/mind/player)
..()
player.current.vampire_make_thrall()
/datum/antagonist/thrall/remove_antagonist(datum/mind/player, show_message, implanted)
player.vampire.lose_master(player.current)
var/datum/vampire/vampire = player.antag_datums[MODE_VAMPIRE]
vampire.lose_master(player.current)
return ..()
+18 -15
View File
@@ -67,33 +67,36 @@ var/datum/antagonist/vampire/vamp = null
/datum/antagonist/vampire/remove_antagonist(var/datum/mind/player, var/show_message = TRUE, var/implanted)
. = ..()
if(.)
var/datum/vampire/vampire = player.antag_datums[MODE_VAMPIRE]
if(player.current.client)
player.current.client.screen -= player.vampire.blood_hud
player.current.client.screen -= player.vampire.frenzy_hud
player.current.client.screen -= vampire.blood_hud
player.current.client.screen -= vampire.frenzy_hud
player.current.verbs -= /datum/antagonist/vampire/proc/vampire_help
for(var/datum/power/vampire/P in vampirepowers)
player.current.verbs -= P.verbpath
QDEL_NULL(player.vampire)
QDEL_NULL(vampire)
/datum/antagonist/vampire/handle_latelogin(var/mob/user)
var/datum/mind/M = user.mind
if(!M)
return
if(M.vampire.master_image)
user.client.images += M.vampire.master_image
if(M.vampire.status & VAMP_ISTHRALL)
var/datum/vampire/vampire = M.antag_datums[MODE_VAMPIRE]
if(vampire.master_image)
user.client.images += vampire.master_image
if(vampire.status & VAMP_ISTHRALL)
return
M.vampire.blood_hud = new /obj/screen/vampire/blood()
M.vampire.frenzy_hud = new /obj/screen/vampire/frenzy()
M.vampire.blood_suck_hud = new /obj/screen/vampire/suck()
user.client.screen += M.vampire.blood_hud
user.client.screen += M.vampire.frenzy_hud
user.client.screen += M.vampire.blood_suck_hud
vampire.blood_hud = new /obj/screen/vampire/blood()
vampire.frenzy_hud = new /obj/screen/vampire/frenzy()
vampire.blood_suck_hud = new /obj/screen/vampire/suck()
user.client.screen += vampire.blood_hud
user.client.screen += vampire.frenzy_hud
user.client.screen += vampire.blood_suck_hud
for(var/thrall in M.vampire.thralls)
for(var/thrall in vampire.thralls)
var/mob/T = thrall
if(T?.mind?.vampire.thrall_image)
user.client.images += T.mind.vampire.thrall_image
var/datum/vampire/T_vampire = T.mind.antag_datums[MODE_VAMPIRE]
if(T_vampire.thrall_image)
user.client.images += T_vampire.thrall_image
/datum/antagonist/vampire/proc/vampire_help()
set category = "Vampire"
@@ -40,8 +40,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
/mob/proc/absorbDNA(var/datum/absorbed_dna/newDNA)
var/datum/changeling/changeling = null
if(src.mind && src.mind.changeling)
changeling = src.mind.changeling
if(mind)
changeling = mind.antag_datums[MODE_CHANGELING]
if(!changeling)
return
@@ -58,8 +58,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind)
return
if(!mind.changeling)
mind.changeling = new /datum/changeling(gender)
if(!mind.antag_datums[MODE_CHANGELING])
mind.antag_datums[MODE_CHANGELING] = new /datum/changeling(gender)
verbs += /datum/changeling/proc/EvolutionMenu
add_language("Changeling")
@@ -70,34 +70,39 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
for(var/P in powers)
powerinstances += new P()
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
// Code to auto-purchase free powers.
for(var/datum/power/changeling/P in powerinstances)
if(!P.genomecost) // Is it free?
if(!(P in mind.changeling.purchasedpowers)) // Do we not have it already?
mind.changeling.purchasePower(mind, P.name, 0) // Purchase it. Don't remake our verbs, we're doing it after this.
if(!(P in changeling.purchasedpowers)) // Do we not have it already?
changeling.purchasePower(mind, P.name, 0) // Purchase it. Don't remake our verbs, we're doing it after this.
for(var/datum/power/changeling/P in mind.changeling.purchasedpowers)
for(var/datum/power/changeling/P in changeling.purchasedpowers)
if(P.isVerb)
if(lesser_form && !P.allowduringlesserform) continue
if(!(P in src.verbs))
src.verbs += P.verbpath
for(var/language in languages)
mind.changeling.absorbed_languages |= language
changeling.absorbed_languages |= language
var/mob/living/carbon/human/H = src
if(istype(H))
var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.get_cloning_variant(), H.languages)
absorbDNA(newDNA)
mind.changeling.mimiced_accent = H.accent
changeling.mimiced_accent = H.accent
return TRUE
//removes our changeling verbs
/mob/proc/remove_changeling_powers()
if(!mind || !mind.changeling)
var/datum/changeling/changeling
if(mind)
changeling = mind.antag_datums[MODE_CHANGELING]
if(!changeling)
return
for(var/datum/power/changeling/P in mind.changeling.purchasedpowers)
for(var/datum/power/changeling/P in changeling.purchasedpowers)
if(P.isVerb)
verbs -= P.verbpath
@@ -110,7 +115,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!iscarbon(src))
return
var/datum/changeling/changeling = src.mind.changeling
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
if(!changeling)
log_and_message_admins("has the changeling_transform() verb but is not a changeling.", src, get_turf(src))
return
@@ -220,9 +220,10 @@ var/list/datum/power/changeling/powerinstances = list()
set category = "Changeling"
set desc = "Buy new abilities with the genomes we obtained."
if(!usr || !usr.mind || !usr.mind.changeling)
var/datum/changeling/changeling = usr.mind.antag_datums[MODE_CHANGELING]
if(!usr || !usr.mind || !changeling)
return
src = usr.mind.changeling
src = changeling
if(!powerinstances.len)
for(var/P in powers)
@@ -480,7 +481,8 @@ var/list/datum/power/changeling/powerinstances = list()
/datum/changeling/proc/purchasePower(var/datum/mind/M, var/power_name, var/remake_verbs = 1)
if(!M || !M.changeling)
var/datum/changeling/changeling = M.antag_datums[MODE_CHANGELING]
if(!M || !changeling)
return
var/datum/power/changeling/power = power_name
@@ -1,9 +1,12 @@
#define CHECK_STING(holder, target) \
if(isliving(target) && holder.a_intent == I_HURT && holder.mind && holder.mind.changeling && holder.mind.changeling.prepared_sting) { \
if(holder.mind.changeling.prepared_sting.can_sting(A)) { \
holder.mind.changeling.prepared_sting.do_sting(A); \
QDEL_NULL(holder.mind.changeling.prepared_sting); \
return; \
if(isliving(target) && holder.a_intent == I_HURT && holder.mind) { \
var/datum/changeling/changeling = holder.mind.antag_datums[MODE_CHANGELING]; \
if(changeling && changeling.prepared_sting) { \
if(changeling.prepared_sting.can_sting(A)) { \
changeling.prepared_sting.do_sting(A); \
QDEL_NULL(changeling.prepared_sting); \
return; \
} \
} \
}
@@ -15,7 +15,8 @@
set desc = "Relinquish your life and enter the land of the dead."
announce_ghost_joinleave(ghostize(1, 0))
changeling_mob.mind.changeling.hivemind_members -= src
var/datum/changeling/changeling = changeling_mob.mind.antag_datums[MODE_CHANGELING]
changeling.hivemind_members -= src
relay_hivemind(SPAN_NOTICE("[src] has left our hivemind to join the living dead."), changeling_mob)
/mob/abstract/hivemind/proc/add_to_hivemind(var/mob/original_body, var/mob/living/carbon/human/ling)
@@ -28,7 +29,8 @@
ckey = original_body.ckey
changeling_mob = ling
if(changeling_mob)
changeling_mob.mind.changeling.hivemind_members[name] = src
var/datum/changeling/changeling = changeling_mob.mind.antag_datums[MODE_CHANGELING]
changeling.hivemind_members[name] = src
introduction(changeling_mob)
/mob/abstract/hivemind/proc/introduction(var/mob/living/carbon/human/ling)
@@ -62,7 +64,8 @@
var/mob/living/simple_animal/hostile/morph/M = new /mob/living/simple_animal/hostile/morph(get_turf(changeling_mob))
M.stop_thinking = TRUE // prevent the AI from taking over when the player ghosts
M.ckey = ckey
changeling_mob.mind.changeling.hivemind_members -= src
var/datum/changeling/changeling = changeling_mob.mind.antag_datums[MODE_CHANGELING]
changeling.hivemind_members -= src
to_chat(M, SPAN_DANGER(FONT_LARGE("You are a morph, released by [changeling_mob]!")))
to_chat(M, SPAN_DANGER("As a morph, you can disguise as objects by alt-clicking on them."))
@@ -287,8 +287,8 @@
C.digitalcamo = !C.digitalcamo
spawn(0)
while(C && C.digitalcamo && C.mind && C.mind.changeling)
C.mind.changeling.chem_charges = max(C.mind.changeling.chem_charges - 1, 0)
while(C && C.digitalcamo && C.mind && changeling)
changeling.chem_charges = max(changeling.chem_charges - 1, 0)
sleep(40)
src.verbs -= /mob/proc/changeling_digitalcamo
@@ -305,7 +305,7 @@
var/datum/changeling/changeling = changeling_power(30, 0, 100, UNCONSCIOUS)
if(!changeling)
return FALSE
src.mind.changeling.chem_charges -= 30
changeling.chem_charges -= 30
var/mob/living/carbon/human/C = src
spawn(0)
@@ -366,11 +366,11 @@
feedback_add_details("changeling_powers","MV")
spawn(0)
while(src && src.mind && src.mind.changeling && src.mind.changeling.mimicing)
src.mind.changeling.chem_charges = max(src.mind.changeling.chem_charges - 1, 0)
while(src?.mind && changeling?.mimicing)
changeling.chem_charges = max(changeling.chem_charges - 1, 0)
sleep(40)
if(src && src.mind && src.mind.changeling)
src.mind.changeling.mimicing = ""
if(changeling)
changeling.mimicing = ""
/mob/proc/armblades()
set category = "Changeling"
@@ -380,7 +380,7 @@
var/datum/changeling/changeling = changeling_power(20, 0, 0)
if(!changeling)
return FALSE
src.mind.changeling.chem_charges -= 20
changeling.chem_charges -= 20
var/mob/living/carbon/M = src
@@ -418,7 +418,7 @@
var/datum/changeling/changeling = changeling_power(20,0,0)
if(!changeling)
return FALSE
src.mind.changeling.chem_charges -= 20
changeling.chem_charges -= 20
var/mob/living/carbon/M = src
@@ -465,7 +465,7 @@
if(alert("Are we sure we wish to reveal ourselves? This will only revert after ten minutes.", , "Yes", "No") == "No") //Changelings have to confirm whether they want to go full horrorform
return
src.mind.changeling.chem_charges -= 40
changeling.chem_charges -= 40
M.visible_message("<span class='danger'>[M] writhes and contorts, their body expanding to inhuman proportions!</span>", \
"<span class='danger'>We begin our transformation to our true form!</span>")
@@ -4,14 +4,13 @@
set name = "Hivemind Eject"
set desc = "Ejects a member of our internal hivemind."
if(!(mind?.changeling))
var/datum/changeling/changeling = changeling_power()
if(!changeling)
return
if(!mind.changeling.hivemind_members.len)
return
var/chosen_player = input("Choose a hivemind member to eject.", "Eject") as null|anything in mind.changeling.hivemind_members
var/chosen_player = input("Choose a hivemind member to eject.", "Eject") as null|anything in changeling.hivemind_members
if(!chosen_player)
return
var/mob/abstract/hivemind/M = mind.changeling.hivemind_members[chosen_player]
var/mob/abstract/hivemind/M = changeling.hivemind_members[chosen_player]
M.ghost() //Deuces
return TRUE
@@ -27,9 +26,10 @@
return TRUE
/mob/proc/relay_hivemind(var/message, var/mob/ling)
if(ling.mind?.changeling)
for(var/H in ling.mind.changeling.hivemind_members) // tell the others in the hivemind
var/mob/M = ling.mind.changeling.hivemind_members[H]
var/datum/changeling/changeling = ling.mind.antag_datums[MODE_CHANGELING]
if(changeling)
for(var/H in changeling.hivemind_members) // tell the others in the hivemind
var/mob/M = changeling.hivemind_members[H]
to_chat(M, message)
to_chat(ling, message)
@@ -41,17 +41,18 @@
set name = "Hivemind Release Morph"
set desc = "Releases a member of our internal hivemind as a morph, at the cost of one of our limbs."
if(!mind?.changeling)
var/datum/changeling/changeling = changeling_power()
if(!changeling)
return
if(!length(mind.changeling.hivemind_members))
if(!length(changeling.hivemind_members))
to_chat(src, SPAN_WARNING("We have no internal hivemind members to release!"))
return
var/chosen_player = input("Choose a hivemind member to release as a morph.", "Hivemind Morph") as null|anything in mind.changeling.hivemind_members
var/chosen_player = input("Choose a hivemind member to release as a morph.", "Hivemind Morph") as null|anything in changeling.hivemind_members
if(!chosen_player)
return
var/mob/abstract/hivemind/M = mind.changeling.hivemind_members[chosen_player]
var/mob/abstract/hivemind/M = changeling.hivemind_members[chosen_player]
M.release_as_morph()
return TRUE
@@ -1,11 +1,13 @@
//Speeds up chemical regeneration
/mob/proc/changeling_fastchemical()
src.mind.changeling.chem_recharge_rate *= 2.5
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
changeling.chem_recharge_rate *= 2.5
return TRUE
//Increases maximum chemical storage
/mob/proc/changeling_engorgedglands()
src.mind.changeling.chem_storage += 50
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
changeling.chem_storage += 50
return TRUE
// HIVE MIND UPLOAD/DOWNLOAD DNA
@@ -14,11 +14,14 @@
stealthy = set_stealthy
/datum/changeling_sting/proc/can_sting(var/mob/living/target)
if(!target)
if(!target || !owner.mind)
return FALSE
if(!(target in view(owner.mind.changeling.sting_range)))
var/datum/changeling/changeling = owner.mind.antag_datums[MODE_CHANGELING]
if(!changeling)
return FALSE
if(!owner.sting_can_reach(target, owner.mind.changeling.sting_range))
if(!(target in view(changeling.sting_range)))
return FALSE
if(!owner.sting_can_reach(target, changeling.sting_range))
to_chat(owner, SPAN_WARNING("Our sting can't reach here!"))
return FALSE
if(!owner.changeling_power(required_chems))
@@ -30,8 +33,9 @@
return TRUE
/datum/changeling_sting/proc/do_sting(var/mob/living/target)
owner.mind.changeling.chem_charges -= required_chems
owner.mind.changeling.sting_range = 1
var/datum/changeling/changeling = owner.mind.antag_datums[MODE_CHANGELING]
changeling.chem_charges -= required_chems
changeling.sting_range = 1
owner.verbs -= verb_path
ADD_VERB_IN(owner, 10, verb_path)
@@ -53,17 +57,18 @@
feedback_add_details("changeling_powers", feedback_tag)
/mob/proc/changeling_sting(var/required_chems = 0, var/verb_path, var/datum_path, var/stealthy = FALSE)
if(istype(mind.changeling.prepared_sting, datum_path))
to_chat(src, SPAN_NOTICE("You unprepare the <b>[mind.changeling.prepared_sting.name]</b>."))
QDEL_NULL(mind.changeling.prepared_sting)
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
if(istype(changeling.prepared_sting, datum_path))
to_chat(src, SPAN_NOTICE("You unprepare the <b>[changeling.prepared_sting.name]</b>."))
QDEL_NULL(changeling.prepared_sting)
return
var/datum/changeling/changeling = changeling_power(required_chems)
changeling = changeling_power(required_chems)
if(!changeling)
return FALSE
changeling.prepared_sting = new datum_path(src, verb_path, required_chems, stealthy)
to_chat(src, SPAN_NOTICE("You prepare to fire the <b>[mind.changeling.prepared_sting.name]</b>."))
to_chat(src, SPAN_NOTICE("You prepare to fire the <b>[changeling.prepared_sting.name]</b>."))
return TRUE
/mob/proc/changeling_hallucinate_sting()
@@ -153,8 +158,8 @@
set name = "Transformation Sting (40)"
set desc = "Causes the target to permanently transform into a collected DNA subject."
if(!length(mind.changeling.absorbed_dna))
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
if(!length(changeling.absorbed_dna))
to_chat(src, SPAN_WARNING("You have no DNA to load this sting with!"))
return
@@ -163,23 +168,23 @@
return
var/list/names = list()
for(var/thing in mind.changeling.absorbed_dna)
for(var/thing in changeling.absorbed_dna)
var/datum/absorbed_dna/DNA = thing
names += "[DNA.name]"
var/S = input(src, "Select the target DNA:", "Target DNA") as null|anything in names
if(!S)
QDEL_NULL(mind.changeling.prepared_sting)
QDEL_NULL(changeling.prepared_sting)
to_chat(src, SPAN_NOTICE("With no DNA chosen, you unprepare the sting."))
return
var/datum/absorbed_dna/chosen_dna = mind.changeling.GetDNA(S)
var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
QDEL_NULL(mind.changeling.prepared_sting)
QDEL_NULL(changeling.prepared_sting)
to_chat(src, SPAN_WARNING("Something went wrong, you do not possess the DNA of this person."))
return
var/datum/changeling_sting/transformation/T = mind.changeling.prepared_sting
var/datum/changeling_sting/transformation/T = changeling.prepared_sting
T.dna_payload = chosen_dna
/datum/changeling_sting/transformation
@@ -253,11 +258,12 @@
set name = "Ranged Sting (10)"
set desc = "Your next sting ability can be used against targets 2 squares away."
if(mind.changeling.sting_range > 1)
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
if(changeling.sting_range > 1)
to_chat(src, SPAN_WARNING("The range of your sting has already been boosted!"))
return
var/datum/changeling/changeling = changeling_power(10, 0, 100)
changeling = changeling_power(10, 0, 100)
if(!changeling)
return FALSE
changeling.chem_charges -= 10
@@ -266,4 +272,4 @@
src.verbs -= /mob/proc/changeling_boost_range
ADD_VERB_IN(src, 5, /mob/proc/changeling_boost_range)
feedback_add_details("changeling_powers", "RS")
return TRUE
return TRUE
@@ -80,17 +80,18 @@
var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.get_cloning_variant(), T.languages)
absorbDNA(newDNA)
if(T.mind && T.mind.changeling)
if(T.mind.changeling.absorbed_dna)
for(var/datum/absorbed_dna/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot
var/datum/changeling/changeling_check = T.mind.antag_datums[MODE_CHANGELING]
if(changeling_check)
if(changeling_check.absorbed_dna)
for(var/datum/absorbed_dna/dna_data in changeling_check.absorbed_dna) //steal all their loot
if(changeling.GetDNA(dna_data.name))
continue
absorbDNA(dna_data)
changeling.absorbedcount++
T.mind.changeling.absorbed_dna.len = TRUE
changeling_check.absorbed_dna.len = TRUE
if(T.mind.changeling.purchasedpowers)
for(var/datum/power/changeling/Tp in T.mind.changeling.purchasedpowers) //who the fuck named these variables?
if(changeling_check.purchasedpowers)
for(var/datum/power/changeling/Tp in changeling_check.purchasedpowers) //who the fuck named these variables?
if(Tp in changeling.purchasedpowers)
continue
else
@@ -100,11 +101,11 @@
else
src.make_changeling()
changeling.chem_charges += T.mind.changeling.chem_charges
changeling.geneticpoints += T.mind.changeling.geneticpoints
T.mind.changeling.chem_charges = 0
T.mind.changeling.geneticpoints = 0
T.mind.changeling.absorbedcount = 0
changeling.chem_charges += changeling_check.chem_charges
changeling.geneticpoints += changeling_check.geneticpoints
changeling_check.chem_charges = 0
changeling_check.geneticpoints = 0
changeling_check.absorbedcount = 0
changeling.absorbedcount++
changeling.isabsorbing = FALSE
+112
View File
@@ -0,0 +1,112 @@
/datum/cultist
var/list/memorized_runes
/datum/cultist/proc/memorize_rune()
set name = "Memorize Rune"
set desc = "Stand atop a rune and memorize it, allowing you to draw it without your tome."
set category = "Cultist"
if(!ishuman(usr))
to_chat(usr, SPAN_WARNING("Your form is too simple to memorize runes!"))
return
if(usr.stat || usr.incapacitated())
to_chat(usr, SPAN_WARNING("You are in no shape to do this."))
return
var/datum/cultist/C = usr.mind.antag_datums[MODE_CULTIST]
if(LAZYLEN(C.memorized_runes) >= 3)
to_chat(usr, SPAN_WARNING("You can only memorize up to three runes!"))
return
var/mob/living/carbon/human/H = usr
var/obj/effect/rune/R = locate() in get_turf(H)
if(R)
if(!R.rune.can_memorize())
to_chat(H, SPAN_WARNING("This rune is too complex to be memorized!"))
return
if(LAZYISIN(C.memorized_runes, R.rune.name))
to_chat(H, SPAN_WARNING("This rune is already memorized!"))
return
H.visible_message("<b>[H]</b> bends over and runs their hands across \the [src].", SPAN_NOTICE("You bend over and run your hands across the patterns of the rune, slowly memorizing it."))
if(!do_after(H, 10 SECONDS, TRUE))
return
LAZYSET(C.memorized_runes, R.rune.name, R.rune.type)
to_chat(H, SPAN_NOTICE("You memorize the [R.rune.name]! You will now be able to scribe it at will."))
else
to_chat(H, SPAN_WARNING("There was no rune beneath you to memorize."))
/datum/cultist/proc/forget_rune()
set name = "Forget Rune"
set desc = "Cleanse the knowledge of a rune from your memory, freeing up space for another."
set category = "Cultist"
if(!ishuman(usr))
to_chat(usr, SPAN_WARNING("Your form is too simple to memorize runes!"))
return
if(usr.stat || usr.incapacitated())
to_chat(usr, SPAN_WARNING("You are in no shape to do this."))
return
var/datum/cultist/C = usr.mind.antag_datums[MODE_CULTIST]
if(!LAZYLEN(C.memorized_runes))
to_chat(usr, SPAN_WARNING("You have no runes memorized!"))
return
var/chosen_rune = input("Choose a rune to forget.") as null|anything in C.memorized_runes
if(!chosen_rune)
return
LAZYREMOVE(C.memorized_runes, chosen_rune)
/datum/cultist/proc/scribe_rune()
set name = "Scribe Rune"
set desc = "Scribe a rune that you have memorized."
set category = "Cultist"
if(!ishuman(usr))
to_chat(usr, SPAN_WARNING("Your form is too simple to memorize runes!"))
return
var/datum/cultist/C = usr.mind.antag_datums[MODE_CULTIST]
if(!LAZYLEN(C.memorized_runes))
to_chat(usr, SPAN_WARNING("You have no runes memorized!"))
return
if(usr.stat || usr.incapacitated())
to_chat(usr, SPAN_WARNING("You are in no shape to do this."))
return
var/chosen_rune = input("Choose a rune to scribe.") as null|anything in C.memorized_runes
if(!chosen_rune)
return
var/mob/living/carbon/human/H = usr
H.visible_message(SPAN_CULT("Blood flows out from \the [H]'s hands, taking shape beneath them..."))
H.drip(4)
if(do_after(H, 15 SECONDS))
create_rune(H, chosen_rune)
/proc/create_rune(var/mob/living/carbon/human/scribe, var/chosen_rune)
if(scribe.stat || scribe.incapacitated())
to_chat(scribe, SPAN_WARNING("You are in no shape to do this."))
return
var/area/A = get_area(scribe)
//prevents using multiple dialogs to layer runes.
if(locate(/obj/effect/rune) in get_turf(scribe)) //This is check is done twice. once when choosing to scribe a rune, once here
to_chat(scribe, SPAN_WARNING("There is already a rune in this location."))
return
log_and_message_admins("created \an [chosen_rune] at \the [A.name] - [scribe.loc.x]-[scribe.loc.y]-[scribe.loc.z].") //only message if it's actually made
var/obj/effect/rune/R = new(get_turf(scribe), SScult.runes_by_name[chosen_rune])
to_chat(scribe, SPAN_CULT("You finish drawing the Geometer's markings."))
R.blood_DNA = list()
R.blood_DNA[scribe.dna.unique_enzymes] = scribe.dna.b_type
R.color = scribe.species.blood_color
R.filters = filter(type="drop_shadow", x = 1, y = 1, size = 4, color = scribe.species.blood_color)
+1 -17
View File
@@ -95,23 +95,7 @@
scribe.drip(4)
if(do_after(scribe, 50))
var/area/A = get_area(scribe)
if(use_check_and_message(scribe))
return
//prevents using multiple dialogs to layer runes.
if(locate(/obj/effect/rune) in get_turf(scribe)) //This is check is done twice. once when choosing to scribe a rune, once here
to_chat(scribe, SPAN_WARNING("There is already a rune in this location."))
return
log_and_message_admins("created \an [chosen_rune] at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].") //only message if it's actually made
var/obj/effect/rune/R = new(get_turf(scribe), SScult.runes_by_name[chosen_rune])
to_chat(scribe, SPAN_CULT("You finish drawing the Geometer's markings."))
R.blood_DNA = list()
R.blood_DNA[scribe.dna.unique_enzymes] = scribe.dna.b_type
R.color = scribe.species.blood_color
R.filters = filter(type="drop_shadow", x = 1, y = 1, size = 4, color = scribe.species.blood_color)
create_rune(scribe, chosen_rune)
else
to_chat(user, SPAN_CULT("The book seems full of illegible scribbles."))
+5 -1
View File
@@ -1,5 +1,6 @@
#define NO_TALISMAN 1
#define HAS_SPECIAL_TALISMAN_ACTION 2
#define CAN_MEMORIZE 2
#define HAS_SPECIAL_TALISMAN_ACTION 4
/datum/rune
var/name // The rune's name.
@@ -42,3 +43,6 @@
/datum/rune/proc/can_be_talisman()
return !(rune_flags & NO_TALISMAN)
/datum/rune/proc/can_memorize()
return rune_flags & CAN_MEMORIZE
@@ -1,6 +1,7 @@
/datum/rune/communicate
name = "communication rune"
desc = "This rune is used to send a message to all acolytes."
rune_flags = CAN_MEMORIZE
/datum/rune/communicate/do_rune_action(mob/living/user, atom/movable/A)
var/input = input(user, "Please choose a message to tell to the other acolytes.", "Voice of Blood", "")//sanitize() below, say() and whisper() have their own
+1 -1
View File
@@ -1,7 +1,7 @@
/datum/rune/convert
name = "conversion rune"
desc = "A rune used to convert the Unenlightened."
rune_flags = NO_TALISMAN
rune_flags = NO_TALISMAN | CAN_MEMORIZE
var/list/converting
@@ -1,7 +1,7 @@
/datum/rune/talisman
name = "talisman creation rune"
desc = "This rune creates a talisman out of a rune around it."
rune_flags = NO_TALISMAN
rune_flags = NO_TALISMAN | CAN_MEMORIZE
/datum/rune/talisman/do_rune_action(mob/living/user, atom/movable/A)
var/obj/item/paper/new_talisman
@@ -1,7 +1,7 @@
/datum/rune/deafen
name = "deafening rune"
desc = "This rune is used to deafen all unbelievers in a wide range around us."
rune_flags = HAS_SPECIAL_TALISMAN_ACTION
rune_flags = HAS_SPECIAL_TALISMAN_ACTION | CAN_MEMORIZE
/datum/rune/deafen/do_rune_action(mob/living/user, atom/movable/A)
do_deafen(user, A, 1, TRUE)
+1 -1
View File
@@ -1,7 +1,7 @@
/datum/rune/ethereal
name = "ethereal rune"
desc = "This rune is used to temporarily send an acolyte into the afterlife."
rune_flags = NO_TALISMAN
rune_flags = NO_TALISMAN | CAN_MEMORIZE
/datum/rune/ethereal/do_rune_action(mob/living/user, atom/movable/A) //some bits copypastaed from admin tools - Urist
if(get_turf(user) == get_turf(A) && ishuman(user))
@@ -1,6 +1,7 @@
/datum/rune/hide_runes
name = "concealment rune"
desc = "This rune is used to conceal other runes in an area around us."
rune_flags = CAN_MEMORIZE
/datum/rune/hide_runes/do_rune_action(mob/living/user, atom/movable/A)
var/rune_found
+1 -1
View File
@@ -1,7 +1,7 @@
/datum/rune/raise_dead
name = "revival rune"
desc = "This rune is used to revive a body in exchange for a dead sacrifice."
rune_flags = NO_TALISMAN
rune_flags = NO_TALISMAN | CAN_MEMORIZE
/datum/rune/raise_dead/do_rune_action(mob/living/user, atom/movable/A)
var/mob/living/carbon/human/corpse_to_raise
@@ -1,7 +1,7 @@
/datum/rune/reveal_runes
name = "revealing rune"
desc = "This rune is used to reveal hidden runes in a radius around us."
rune_flags = HAS_SPECIAL_TALISMAN_ACTION
rune_flags = HAS_SPECIAL_TALISMAN_ACTION | CAN_MEMORIZE
/datum/rune/reveal_runes/do_rune_action(mob/living/user, atom/movable/A)
reveal(user, A, 6, SPAN_WARNING("\The [A] turns into red dust, reveaing the surrounding runes."))
+1
View File
@@ -26,6 +26,7 @@
if(iscultist(user) || isobserver(user))
to_chat(user, rune.get_cultist_fluff_text())
to_chat(user, "This rune [rune.can_be_talisman() ? "<span class='cult'><b><i>can</i></b></span>" : "<span class='warning'><b><i>cannot</i></b></span>"] be turned into a talisman.")
to_chat(user, "This rune [rune.can_memorize() ? "<span class='cult'><b><i>can</i></b></span>" : "<span class='warning'><b><i>cannot</i></b></span>"] be memorized to be scribed without a tome.")
else
to_chat(user, rune.get_normal_fluff_text())
+1 -1
View File
@@ -1,7 +1,7 @@
/datum/rune/sacrifice
name = "sacrificial rune"
desc = "This rune is used to sacrifice an unbeliever."
rune_flags = NO_TALISMAN
rune_flags = NO_TALISMAN | CAN_MEMORIZE
/datum/rune/sacrifice/do_rune_action(mob/living/user, atom/movable/A)
var/list/mob/living/carbon/human/cultists_in_range = list()
@@ -1,7 +1,7 @@
/datum/rune/see_invisible
name = "visibility rune"
desc = "This rune is used to see the invisible."
rune_flags = NO_TALISMAN
rune_flags = NO_TALISMAN | CAN_MEMORIZE
/datum/rune/see_invisible/do_rune_action(mob/living/user, atom/movable/A)
if(user.seer == TRUE)
+4 -2
View File
@@ -600,7 +600,8 @@ datum/objective/capture
n_p ++
else if (SSticker.current_state == GAME_STATE_PLAYING)
for(var/mob/living/carbon/human/P in player_list)
if(P.client && !(P.mind.changeling) && P.mind!=owner)
var/datum/changeling/changeling = P.mind.antag_datums[MODE_CHANGELING]
if(P.client && !changeling && P.mind != owner)
n_p ++
target_amount = min(target_amount, n_p)
@@ -608,7 +609,8 @@ datum/objective/capture
return target_amount
check_completion()
if(owner && owner.changeling && owner.changeling.absorbed_dna && (owner.changeling.absorbedcount >= target_amount))
var/datum/changeling/changeling = owner.antag_datums[MODE_CHANGELING]
if(owner && changeling?.absorbed_dna && (changeling.absorbedcount >= target_amount))
return 1
else
return 0
+3 -2
View File
@@ -60,6 +60,7 @@
/datum/vampire/proc/lose_master(var/mob/M)
QDEL_NULL(thrall_image)
QDEL_NULL(master_image)
if(master?.mind?.vampire)
master.mind.vampire.thralls -= M
if(master)
var/datum/vampire/master_vampire = master.mind.antag_datums[MODE_VAMPIRE]
master_vampire.thralls -= M
master = null
+74 -63
View File
@@ -2,26 +2,28 @@
/mob/proc/make_vampire()
if (!mind)
return
if (!mind.vampire)
mind.vampire = new /datum/vampire()
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if(!vampire)
mind.antag_datums[MODE_VAMPIRE] = new /datum/vampire()
vampire = mind.antag_datums[MODE_VAMPIRE]
// No powers to thralls. Ew.
if (mind.vampire.status & VAMP_ISTHRALL)
if(vampire.status & VAMP_ISTHRALL)
return
mind.vampire.blood_usable += 30
vampire.blood_usable += 30
if(client)
mind.vampire.blood_hud = new /obj/screen/vampire/blood()
mind.vampire.frenzy_hud = new /obj/screen/vampire/frenzy()
client.screen += mind.vampire.blood_hud
client.screen += mind.vampire.frenzy_hud
vampire.blood_hud = new /obj/screen/vampire/blood()
vampire.frenzy_hud = new /obj/screen/vampire/frenzy()
client.screen += vampire.blood_hud
client.screen += vampire.frenzy_hud
verbs += new /datum/antagonist/vampire/proc/vampire_help
for(var/datum/power/vampire/P in vampirepowers)
if(!(P in mind.vampire.purchased_powers))
if(!(P in vampire.purchased_powers))
if(!P.blood_cost)
mind.vampire.add_power(mind, P, 0)
vampire.add_power(mind, P, 0)
else if(P.isVerb && P.verbpath)
verbs += P.verbpath
@@ -29,11 +31,10 @@
// Checks the vampire's bloodlevel and unlocks new powers based on that.
/mob/proc/check_vampire_upgrade()
if (!mind.vampire)
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if(!vampire)
return
var/datum/vampire/vampire = mind.vampire
for (var/datum/power/vampire/P in vampirepowers)
if (P.blood_cost <= vampire.blood_total)
if (!(P in vampire.purchased_powers))
@@ -50,7 +51,7 @@
if (!ishuman(src))
return
var/datum/vampire/vampire = mind.vampire
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if (!vampire)
log_debug("[src] has a vampire power but is not a vampire.")
return
@@ -73,26 +74,30 @@
/mob/proc/vampire_can_affect_target(var/mob/living/carbon/human/T, var/notify = 1, var/account_loyalty_implant = 0, var/ignore_thrall = FALSE, var/affect_ipc = TRUE)
if (!T || !istype(T))
return FALSE
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
// How did you even get here?
if (!mind.vampire)
if (!vampire)
return FALSE
if ((mind.vampire.status & VAMP_FULLPOWER) && !(T.mind && T.mind.vampire && (T.mind.vampire.status & VAMP_FULLPOWER)))
return TRUE
if (T.mind)
if (T.mind.assigned_role == "Chaplain")
if (notify)
var/datum/vampire/vampire_check
if(T.mind)
if(T.mind.assigned_role == "Chaplain")
if(notify)
to_chat(src, "<span class='warning'>Your connection with the Veil is not strong enough to affect a man as devout as them.</span>")
return FALSE
else if (T.mind.vampire && (!(T.mind.vampire.status & VAMP_ISTHRALL) || ((T.mind.vampire.status & VAMP_ISTHRALL) && !ignore_thrall)))
if (notify)
to_chat(src, "<span class='warning'>You lack the power required to affect another creature of the Veil.</span>")
return FALSE
vampire_check = T.mind.antag_datums[MODE_VAMPIRE]
if(vampire_check)
if(!(vampire_check.status & VAMP_ISTHRALL && ignore_thrall))
if(notify)
to_chat(src, "<span class='warning'>You lack the power required to affect another creature of the Veil.</span>")
return FALSE
if(vampire_check)
if((vampire.status & VAMP_FULLPOWER) && !(vampire_check.status & VAMP_FULLPOWER))
return TRUE
if(!affect_ipc && isipc(T))
if (notify)
to_chat(src, SPAN_WARNING("You lack the power to interact with mechanical constructs."))
return FALSE
if(is_special_character(T) && (!(T.mind.vampire.status & VAMP_ISTHRALL)))
if(is_special_character(T) && (!(vampire_check.status & VAMP_ISTHRALL)))
if (notify)
to_chat(src, "<span class='warning'>\The [T]'s mind is too strong to be affected by our powers!</span>")
return FALSE
@@ -123,13 +128,14 @@
return
var/datum/vampire/thrall/thrall = new()
mind.vampire = thrall
mind.antag_datums[MODE_VAMPIRE] = thrall
/mob/proc/vampire_check_frenzy(var/force_frenzy = 0)
if (!mind || !mind.vampire)
if(!mind)
return
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if(!vampire)
return
var/datum/vampire/vampire = mind.vampire
// Thralls don't frenzy.
if (vampire.status & VAMP_ISTHRALL)
return
@@ -176,8 +182,7 @@
vampire.last_frenzy_message = world.time
/mob/proc/vampire_start_frenzy(var/force_frenzy = 0)
var/datum/vampire/vampire = mind.vampire
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if (vampire.status & VAMP_FRENZIED)
return
@@ -196,7 +201,7 @@
verbs += /mob/living/carbon/human/proc/grapple
/mob/proc/vampire_stop_frenzy(var/force_stop = 0)
var/datum/vampire/vampire = mind.vampire
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if (!(vampire.status & VAMP_FRENZIED))
return
@@ -217,57 +222,63 @@
// Removes all vampire powers.
/mob/proc/remove_vampire_powers()
if (!mind || !mind.vampire)
if(!mind)
return
for (var/datum/power/vampire/P in mind.vampire.purchased_powers)
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if(!vampire)
return
for (var/datum/power/vampire/P in vampire.purchased_powers)
if (P.isVerb)
verbs -= P.verbpath
if (mind.vampire.status & VAMP_FRENZIED)
if (vampire.status & VAMP_FRENZIED)
vampire_stop_frenzy(1)
/mob/proc/handle_vampire()
if(mind.vampire.status & VAMP_ISTHRALL)
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if(vampire.status & VAMP_ISTHRALL)
return
// Apply frenzy while in the chapel.
if (istype(get_area(loc), /area/chapel))
mind.vampire.frenzy += 3
vampire.frenzy += 3
if (mind.vampire.blood_usable < 10)
mind.vampire.frenzy += 2
else if (mind.vampire.frenzy > 0)
mind.vampire.frenzy = max(0, mind.vampire.frenzy -= Clamp(mind.vampire.blood_usable * 0.1, 1, 10))
if (vampire.blood_usable < 10)
vampire.frenzy += 2
else if (vampire.frenzy > 0)
vampire.frenzy = max(0, vampire.frenzy -= Clamp(vampire.blood_usable * 0.1, 1, 10))
mind.vampire.frenzy = round(min(mind.vampire.frenzy, 450))
vampire.frenzy = round(min(vampire.frenzy, 450))
vampire_check_frenzy()
if(client)
if(!mind.vampire.blood_hud)
mind.vampire.blood_hud = new /obj/screen/vampire/blood()
client.screen += mind.vampire.blood_hud
if(!mind.vampire.frenzy_hud)
mind.vampire.frenzy_hud = new /obj/screen/vampire/frenzy()
client.screen += mind.vampire.frenzy_hud
if(!mind.vampire.blood_suck_hud)
mind.vampire.blood_suck_hud = new /obj/screen/vampire/suck()
client.screen += mind.vampire.blood_suck_hud
if(!vampire.blood_hud)
vampire.blood_hud = new /obj/screen/vampire/blood()
client.screen += vampire.blood_hud
if(!vampire.frenzy_hud)
vampire.frenzy_hud = new /obj/screen/vampire/frenzy()
client.screen += vampire.frenzy_hud
if(!vampire.blood_suck_hud)
vampire.blood_suck_hud = new /obj/screen/vampire/suck()
client.screen += vampire.blood_suck_hud
mind.vampire.blood_hud.maptext = SMALL_FONTS(7, mind.vampire.blood_usable)
if(mind.vampire.frenzy)
if(!mind.vampire.frenzy_hud.alpha)
animate(mind.vampire.frenzy_hud, 1 SECOND, alpha = 255, LINEAR_EASING)
mind.vampire.frenzy_hud.maptext = SMALL_FONTS(7, mind.vampire.frenzy)
vampire.blood_hud.maptext = SMALL_FONTS(7, vampire.blood_usable)
if(vampire.frenzy)
if(!vampire.frenzy_hud.alpha)
animate(vampire.frenzy_hud, 1 SECOND, alpha = 255, LINEAR_EASING)
vampire.frenzy_hud.maptext = SMALL_FONTS(7, vampire.frenzy)
else
if(mind.vampire.frenzy_hud.alpha)
animate(mind.vampire.frenzy_hud, 1 SECOND, alpha = 0, LINEAR_EASING)
mind.vampire.frenzy_hud.maptext = null
if(vampire.frenzy_hud.alpha)
animate(vampire.frenzy_hud, 1 SECOND, alpha = 0, LINEAR_EASING)
vampire.frenzy_hud.maptext = null
/mob/living/carbon/human/proc/finish_vamp_timeout(vamp_flags = 0)
if (!mind || !mind.vampire)
if(!mind)
return FALSE
if (vamp_flags && !(mind.vampire.status & vamp_flags))
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if(!vampire)
return FALSE
if (vamp_flags && !(vampire.status & vamp_flags))
return FALSE
return TRUE
+33 -30
View File
@@ -56,8 +56,8 @@
return
var/datum/vampire/draining_vamp = null
if(T.mind?.vampire)
draining_vamp = T.mind.vampire
if(T.mind)
draining_vamp = T.mind.antag_datums[MODE_VAMPIRE]
var/target_aware = !!T.client
@@ -85,7 +85,7 @@
playsound(src.loc, 'sound/effects/drain_blood_new.ogg', 50, 1)
while(do_mob(src, T, 50) && vampire.status & VAMP_DRAINING && vampire.blood_usable < VAMPIRE_MAX_USABLE_BLOOD)
if(!mind.vampire)
if(!vampire)
to_chat(src, SPAN_DANGER("Your fangs have disappeared!"))
return
@@ -498,7 +498,8 @@
last_valid_turf = get_turf(owner.loc)
owner.forceMove(src)
if(owner.mind.vampire.status & VAMP_FULLPOWER)
var/datum/vampire/vampire = owner_mob.mind.antag_datums[MODE_VAMPIRE]
if(vampire.status & VAMP_FULLPOWER)
for(var/obj/item/grab/G in list(owner.l_hand, owner.r_hand))
G.affecting.vampire_phase_out(get_turf(G))
G.affecting.forceMove(src)
@@ -748,8 +749,9 @@
to_chat(T, SPAN_DANGER("Your mind blanks as you finish feeding from [src]'s wrist."))
thralls.add_antagonist(T.mind, 1, 1, 0, 1, 1)
T.mind.vampire.assign_master(T, src, vampire)
to_chat(T, SPAN_NOTICE("You have been forced into a blood bond by [T.mind.vampire.master], and are thus their thrall. While a thrall may feel a myriad of emotions towards their master, ranging from fear, to hate, to love; the supernatural bond between them still forces the thrall to obey their master, and to listen to the master's commands.<br><br>You must obey your master's orders, you must protect them, you cannot harm them."))
var/datum/vampire/T_vampire = T.mind.antag_datums[MODE_VAMPIRE]
T_vampire.assign_master(T, src, vampire)
to_chat(T, SPAN_NOTICE("You have been forced into a blood bond by [T_vampire.master], and are thus their thrall. While a thrall may feel a myriad of emotions towards their master, ranging from fear, to hate, to love; the supernatural bond between them still forces the thrall to obey their master, and to listen to the master's commands.<br><br>You must obey your master's orders, you must protect them, you cannot harm them."))
to_chat(src, SPAN_NOTICE("You have completed the thralling process. They are now your slave and will obey your commands."))
admin_attack_log(src, T, "enthralled [key_name(T)]", "was enthralled by [key_name(src)]", "successfully enthralled")
@@ -882,30 +884,30 @@
to_chat(src, SPAN_WARNING("Your fangs are already sunk into a victim's neck!"))
return
if(T.mind.vampire)
var/datum/vampire/draining_vamp = T.mind.vampire
if(T.mind)
var/datum/vampire/draining_vamp = T.mind.antag_datums[MODE_VAMPIRE]
if(draining_vamp)
if(draining_vamp.status & VAMP_ISTHRALL)
var/choice_text = ""
var/denial_response = ""
if(draining_vamp.master == src)
choice_text = "[T] is your thrall. Do you wish to release them from the blood bond and give them the chance to become your equal?"
denial_response = "You opt against giving [T] a chance to ascend, and choose to keep them as a servant."
else
choice_text = "You can feel the taint of another master running in the veins of [T]. Do you wish to release them of their blood bond, and convert them into a vampire, in spite of their master?"
denial_response = "You choose not to continue with the Embrace, and permit [T] to keep serving their master."
if(draining_vamp.status & VAMP_ISTHRALL)
var/choice_text = ""
var/denial_response = ""
if(draining_vamp.master == src)
choice_text = "[T] is your thrall. Do you wish to release them from the blood bond and give them the chance to become your equal?"
denial_response = "You opt against giving [T] a chance to ascend, and choose to keep them as a servant."
if(alert(src, choice_text, "Choices", "Yes", "No") == "No")
to_chat(src, SPAN_NOTICE("[denial_response]"))
return
thralls.remove_antagonist(T.mind, 0, 0)
qdel(draining_vamp)
draining_vamp = null
else
choice_text = "You can feel the taint of another master running in the veins of [T]. Do you wish to release them of their blood bond, and convert them into a vampire, in spite of their master?"
denial_response = "You choose not to continue with the Embrace, and permit [T] to keep serving their master."
if(alert(src, choice_text, "Choices", "Yes", "No") == "No")
to_chat(src, SPAN_NOTICE("[denial_response]"))
to_chat(src, SPAN_WARNING("You feel corruption running in [T]'s blood. Much like yourself, [T.get_pronoun("he")] is already a spawn of the Veil, and cannot be Embraced."))
return
thralls.remove_antagonist(T.mind, 0, 0)
qdel(draining_vamp)
draining_vamp = null
else
to_chat(src, SPAN_WARNING("You feel corruption running in [T]'s blood. Much like yourself, [T.get_pronoun("he")] is already a spawn of the Veil, and cannot be Embraced."))
return
vampire.status |= VAMP_DRAINING
visible_message(SPAN_DANGER("[src] bites [T]'s neck!"), SPAN_DANGER("You bite [T]'s neck and begin to drain their blood, as the first step of introducing the corruption of the Veil to them."), SPAN_NOTICE("You hear a soft puncture and a wet sucking noise."))
@@ -914,7 +916,7 @@
var/drained_all_blood = FALSE
while(do_mob(src, T, 50))
if(!mind.vampire)
if(!vampire)
to_chat(src, SPAN_WARNING("Your fangs have disappeared!"))
return
if(!T.vessel.get_reagent_amount(/datum/reagent/blood))
@@ -947,8 +949,9 @@
to_chat(T, SPAN_DANGER("You awaken. Moments ago, you were dead, your conciousness still forced stuck inside your body. Now you live. You feel different, a strange, dark force now present within you. You have an insatiable desire to drain the blood of mortals, and to grow in power."))
to_chat(src, SPAN_WARNING("You have corrupted another mortal with the taint of the Veil. Beware: they will awaken hungry and maddened; not bound to any master."))
T.mind.vampire.blood_usable = 0
T.mind.vampire.frenzy = 250
var/datum/vampire/T_vampire = T.mind.antag_datums[MODE_VAMPIRE]
T_vampire.blood_usable = 0
T_vampire.frenzy = 250
T.vampire_check_frenzy()
vampire.status &= ~VAMP_DRAINING
@@ -1015,4 +1018,4 @@
G.synch()
verbs -= /mob/living/carbon/human/proc/grapple
ADD_VERB_IN_IF(src, 800, /mob/living/carbon/human/proc/grapple, CALLBACK(src, .proc/finish_vamp_timeout, VAMP_FRENZIED))
ADD_VERB_IN_IF(src, 800, /mob/living/carbon/human/proc/grapple, CALLBACK(src, .proc/finish_vamp_timeout, VAMP_FRENZIED))
@@ -32,7 +32,7 @@
return TRUE
if(ishuman(mover))
var/mob/living/carbon/human/H = mover
if(H.mind.changeling)
if(H.mind.antag_datums[MODE_CHANGELING])
return TRUE
/obj/structure/gore/tendrils/Destroy()
+10 -7
View File
@@ -10,11 +10,13 @@
var/list/ui_users = list()
/obj/structure/mirror/attack_hand(mob/user as mob)
if(shattered)
return
if(shattered) return
if(user.mind && user.mind.vampire && (!(user.mind.vampire.status & VAMP_ISTHRALL)))
to_chat(user, "<span class='notice'>Your reflection appears distorted on the surface of \the [src].</span>")
if(user.mind)
var/datum/vampire/vampire = user.mind.antag_datums[MODE_VAMPIRE]
if(vampire && !(vampire.status & VAMP_ISTHRALL))
to_chat(user, "<span class='notice'>Your reflection appears distorted on the surface of \the [src].</span>")
if(ishuman(user))
var/datum/nano_module/appearance_changer/AC = ui_users[user]
@@ -82,9 +84,10 @@
var/list/ui_users = list()
/obj/item/mirror/attack_self(mob/user as mob)
if(user.mind && user.mind.vampire && (!(user.mind.vampire.status & VAMP_ISTHRALL)))
to_chat(user, "<span class='notice'>Your reflection appears distorted on the surface of \the [src].</span>")
if(user.mind)
var/datum/vampire/vampire = user.mind.antag_datums[MODE_VAMPIRE]
if(vampire && !(vampire.status & VAMP_ISTHRALL))
to_chat(user, "<span class='notice'>Your reflection appears distorted on the surface of \the [src].</span>")
if(ishuman(user))
var/datum/nano_module/appearance_changer/AC = ui_users[user]
+6 -5
View File
@@ -7,11 +7,12 @@
flags = RESTRICTED | HIVEMIND
/datum/language/ling/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
if(speaker.mind && speaker.mind.changeling)
..(speaker,message,speaker.mind.changeling.changelingID)
else
..(speaker,message)
if(speaker.mind)
var/datum/changeling/changeling = speaker.mind.antag_datums[MODE_CHANGELING]
if(changeling)
..(speaker,message, changeling.changelingID)
return
..(speaker,message)
/datum/language/corticalborer
name = LANGUAGE_BORER
+12 -8
View File
@@ -210,12 +210,14 @@
stat(null, "Suit charge: [cell_status]")
if(mind)
if(mind.vampire)
stat("Usable Blood", mind.vampire.blood_usable)
stat("Total Blood", mind.vampire.blood_total)
if(mind.changeling)
stat("Chemical Storage", mind.changeling.chem_charges)
stat("Genetic Damage Time", mind.changeling.geneticdamage)
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if(vampire)
stat("Usable Blood", vampire.blood_usable)
stat("Total Blood", vampire.blood_total)
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
if(changeling)
stat("Chemical Storage", changeling.chem_charges)
stat("Genetic Damage Time", changeling.geneticdamage)
/mob/living/carbon/human/ex_act(severity)
if(!blinded)
@@ -2016,8 +2018,10 @@
/mob/living/carbon/human/get_accent_icon(var/datum/language/speaking, var/mob/hearer, var/force_accent)
var/used_accent = accent //starts with the mob's default accent
if(mind?.changeling)
used_accent = mind.changeling.mimiced_accent
if(mind)
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
if(changeling?.mimiced_accent)
used_accent = changeling.mimiced_accent
if(istype(back,/obj/item/rig)) //checks for the rig voice changer module
var/obj/item/rig/rig = back
@@ -87,8 +87,12 @@
tally = max(0, tally-3)
var/turf/T = get_turf(src)
if(T && !mind.changeling) // changelings don't get movement costs
tally += T.movement_cost
if(T) // changelings don't get movement costs
var/datum/changeling/changeling
if(mind)
changeling = mind.antag_datums[MODE_CHANGELING]
if(!changeling)
tally += T.movement_cost
tally += config.human_delay
+8 -4
View File
@@ -84,8 +84,10 @@
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
if(mind?.vampire)
handle_vampire()
if(mind)
var/datum/vampire/vampire = mind.antag_datums[MODE_VAMPIRE]
if(vampire)
handle_vampire()
/mob/living/carbon/human/think()
..()
@@ -1041,8 +1043,10 @@
playsound_simple(null, pick(scarySounds), 50, TRUE)
/mob/living/carbon/human/proc/handle_changeling()
if(mind && mind.changeling)
mind.changeling.regenerate()
if(mind)
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
if(changeling)
changeling.regenerate()
/mob/living/carbon/human/proc/handle_shock()
if(status_flags & GODMODE)
+4 -2
View File
@@ -79,8 +79,10 @@
var/obj/item/organ/external/head/face = organs_by_name[BP_HEAD]
if(face?.disfigured) // if your face is ruined, your ability to vocalize is also ruined
return "Unknown" // above ling voice mimicing so they don't get caught out immediately
if(mind?.changeling?.mimicing)
return mind.changeling.mimicing
if(mind)
var/datum/changeling/changeling = mind.antag_datums[MODE_CHANGELING]
if(changeling?.mimicing)
return changeling.mimicing
if(GetSpecialVoice())
return GetSpecialVoice()
return real_name
+4 -1
View File
@@ -213,7 +213,10 @@
if (!injected || !our)
return
if(blood_incompatible(injected.data["blood_type"],our.data["blood_type"],injected.data["species"],our.data["species"]) && !(mind && mind.vampire))
var/datum/vampire/vampire
if(mind)
vampire = mind.antag_datums[MODE_VAMPIRE]
if(!vampire && blood_incompatible(injected.data["blood_type"],our.data["blood_type"],injected.data["species"],our.data["species"]))
reagents.add_reagent(/datum/reagent/toxin,amount * 0.5)
reagents.update_total()
else
@@ -48,11 +48,12 @@
/datum/reagent/blood/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
if(ishuman(M))
if (M.mind && M.mind.vampire)
if(M.mind)
var/datum/vampire/vampire = M.mind.antag_datums[MODE_VAMPIRE]
if(M.dna.unique_enzymes == data["blood_DNA"]) //so vampires can't drink their own blood
return
M.mind.vampire.blood_usable += removed
to_chat(M, "<span class='notice'>You have accumulated [M.mind.vampire.blood_usable] [M.mind.vampire.blood_usable > 1 ? "units" : "unit"] of usable blood. It tastes quite stale.</span>")
vampire.blood_usable += removed
to_chat(M, "<span class='notice'>You have accumulated [vampire.blood_usable] [vampire.blood_usable > 1 ? "units" : "unit"] of usable blood. It tastes quite stale.</span>")
return
if(dose > 5)
M.adjustToxLoss(removed)
@@ -218,11 +218,12 @@
/datum/reagent/water/holywater/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
..()
if(ishuman(M))
if (M.mind && M.mind.vampire)
var/datum/vampire/vampire = M.mind.vampire
vampire.frenzy += removed * 5
else if(M.mind && cult.is_antagonist(M.mind) && prob(10))
cult.remove_antagonist(M.mind)
if(M.mind)
var/datum/vampire/vampire = M.mind.antag_datums[MODE_VAMPIRE]
if(vampire)
vampire.frenzy += removed * 5
if(cult.is_antagonist(M.mind) && prob(10))
cult.remove_antagonist(M.mind)
if(alien && alien == IS_UNDEAD)
M.adjust_fire_stacks(10)
M.IgniteMob()
@@ -44,32 +44,34 @@
if(51 to INFINITY) icon_state = "full"
/obj/item/reagent_containers/blood/attack(mob/living/carbon/human/M as mob, mob/living/carbon/human/user as mob, var/target_zone)
if (user == M && (user.mind.vampire))
if (being_feed)
to_chat(user, "<span class='notice'>You are already feeding on \the [src].</span>")
return
if (reagents.get_reagent_amount(/datum/reagent/blood))
user.visible_message("<span class='warning'>[user] raises \the [src] up to their mouth and bites into it.</span>", "<span class='notice'>You raise \the [src] up to your mouth and bite into it, starting to drain its contents.<br>You need to stand still.</span>")
being_feed = TRUE
vampire_marks = TRUE
if (!LAZYLEN(src.other_DNA))
LAZYADD(src.other_DNA, M.dna.unique_enzymes)
src.other_DNA_type = "saliva"
if(user == M && user.mind)
var/datum/vampire/vampire = user.mind.antag_datums[MODE_VAMPIRE]
if(vampire)
if (being_feed)
to_chat(user, "<span class='notice'>You are already feeding on \the [src].</span>")
return
if (reagents.get_reagent_amount(/datum/reagent/blood))
user.visible_message("<span class='warning'>[user] raises \the [src] up to their mouth and bites into it.</span>", "<span class='notice'>You raise \the [src] up to your mouth and bite into it, starting to drain its contents.<br>You need to stand still.</span>")
being_feed = TRUE
vampire_marks = TRUE
if (!LAZYLEN(src.other_DNA))
LAZYADD(src.other_DNA, M.dna.unique_enzymes)
src.other_DNA_type = "saliva"
while (do_after(user, 25, 5, 1))
var/blood_taken = 0
blood_taken = min(5, reagents.get_reagent_amount(/datum/reagent/blood)/4)
while (do_after(user, 25, 5, 1))
var/blood_taken = 0
blood_taken = min(5, reagents.get_reagent_amount(/datum/reagent/blood)/4)
reagents.remove_reagent(/datum/reagent/blood, blood_taken*4)
user.mind.vampire.blood_usable += blood_taken
reagents.remove_reagent(/datum/reagent/blood, blood_taken*4)
vampire.blood_usable += blood_taken
if (blood_taken)
to_chat(user, "<span class='notice'>You have accumulated [user.mind.vampire.blood_usable] [user.mind.vampire.blood_usable > 1 ? "units" : "unit"] of usable blood. It tastes quite stale.</span>")
if (blood_taken)
to_chat(user, "<span class='notice'>You have accumulated [vampire.blood_usable] [vampire.blood_usable > 1 ? "units" : "unit"] of usable blood. It tastes quite stale.</span>")
if (reagents.get_reagent_amount(/datum/reagent/blood) < 1)
break
user.visible_message("<span class='warning'>[user] licks [user.get_pronoun("his")] fangs dry, lowering \the [src].</span>", "<span class='notice'>You lick your fangs clean of the tasteless blood.</span>")
being_feed = FALSE
if (reagents.get_reagent_amount(/datum/reagent/blood) < 1)
break
user.visible_message("<span class='warning'>[user] licks [user.get_pronoun("his")] fangs dry, lowering \the [src].</span>", "<span class='notice'>You lick your fangs clean of the tasteless blood.</span>")
being_feed = FALSE
else
..()
@@ -0,0 +1,7 @@
author: Geeves
delete-after: True
changes:
- backend: "Converted how Vampire and Changeling variables are handled on the backend, let me know if there's something funky."
- rscadd: "Cultists can now memorize up to three runes, and can scribe them at will without a tome, at the cost of taking three times longer to do so. Check the Cultists tab in the top right. Only specific runes can be memorized."