Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions code/__DEFINES/bloodsuckers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
/// Deals with constant processes off of LifeTick()
#define COMSIG_LIVING_BIOLOGICAL_LIFE "biological_life"
/// Once blood is this low, will enter Frenzy
#define FRENZY_THRESHOLD_ENTER 25
#define FRENZY_THRESHOLD_ENTER 112
/// Once blood is this high, will exit Frenzy
#define FRENZY_THRESHOLD_EXIT 250
#define FRENZY_THRESHOLD_EXIT 560
/// You have special interactions with Bloodsuckers
#define TRAIT_BLOODSUCKER_HUNTER "bloodsucker_hunter"

Expand All @@ -36,7 +36,12 @@
#define CLAN_TOREADOR "Toreador Clan"
#define CLAN_GANGREL "Gangrel Clan"
#define CLAN_LASOMBRA "Lasombra Clan"
#define CLAN_TZIMISCE "Tzimisce Clan"

#define TRIPLECHEST_MONSTER "Triple Chest (300 Blood)"
#define ARMMY_MONSTER "Armmy (100 Blood)"
#define CALCIUM_MONSTER "Calcium (150 Blood)"
#define HUSK_MONSTER "Husk"
/**
* Power defines
*/
Expand All @@ -53,12 +58,16 @@

/// This Power can be purchased by Bloodsuckers
#define BLOODSUCKER_CAN_BUY (1<<0)
/// This Power can be purchased by Tremere Bloodsuckers
#define TREMERE_CAN_BUY (1<<1)
/// This Power can be purchased by Lasombra Bloodsuckers
#define LASOMBRA_CAN_BUY (1<<1)
/// This Power can be purchased by Gangrel Bloodsuckers
#define GANGREL_CAN_BUY (1<<2)
/// This Power can be purchased by Vassals
#define VASSAL_CAN_BUY (1<<2)
#define VASSAL_CAN_BUY (1<<3)
/// This Power can be purchased by Monster Hunters
#define HUNTER_CAN_BUY (1<<3)
#define HUNTER_CAN_BUY (1<<4)
/// This Power can be purchased by Tzimisce Bloodsuckers
#define TZIMISCE_CAN_BUY (1<<5)

/// This Power is a Toggled Power
#define BP_AM_TOGGLE (1<<0)
Expand Down
1 change: 1 addition & 0 deletions code/__DEFINES/is_helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isethereal(A) (is_species(A, /datum/species/ethereal))
#define isvampire(A) (is_species(A,/datum/species/vampire))
#define ispreternis(A) (is_species(A,/datum/species/preternis))
#define isszlachta(A) (is_species(A, /datum/species/szlachta))

//more carbon mobs
#define ismonkey(A) (istype(A, /mob/living/carbon/monkey))
Expand Down
2 changes: 2 additions & 0 deletions code/__DEFINES/status_effects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@

#define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost and can't use manifest runes

#define STATUS_EFFECT_SHADOWAFFLICTED /datum/status_effect/the_shadow //Heavy hallucinations + ear damage with a shadowman overlay

#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage

#define STATUS_EFFECT_KNUCKLED /datum/status_effect/knuckled //if struck with bloody knuckles or their ability, gets rooted
Expand Down
35 changes: 35 additions & 0 deletions code/datums/status_effects/debuffs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,41 @@
if(owner.reagents)
owner.reagents.del_reagent(/datum/reagent/water/holywater) //can't be deconverted

/datum/status_effect/the_shadow
id = "the_shadow"
status_type = STATUS_EFFECT_REPLACE
alert_type = null
duration = -1
var/mutable_appearance/shadow

/datum/status_effect/the_shadow/on_apply()
if(ishuman(owner))
shadow = mutable_appearance('icons/effects/effects.dmi', "curse")
shadow.pixel_x = -owner.pixel_x
shadow.pixel_y = -owner.pixel_y
owner.add_overlay(shadow)
to_chat(owner, span_boldwarning("The shadows invade your mind, MUST. GET. THEM. OUT"))
return TRUE
return FALSE

/datum/status_effect/the_shadow/tick()
var/turf/T = get_turf(owner)
var/light_amount = T.get_lumcount()
if(light_amount > 0.2)
to_chat(owner, span_notice("As the light reaches the shadows, they dissipate!"))
qdel(src)
if(owner.stat == DEAD)
qdel(src)
owner.hallucination += 2
owner.confused += 2
owner.adjustEarDamage(0, 5)

/datum/status_effect/the_shadow/Destroy()
if(owner)
owner.cut_overlay(shadow)
QDEL_NULL(shadow)
return ..()

/datum/status_effect/crusher_mark
id = "crusher_mark"
duration = 300 //if you leave for 30 seconds you lose the mark, deal with it
Expand Down
5 changes: 3 additions & 2 deletions code/game/gamemodes/bloodsuckers/bloodsucker.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs

if(CONFIG_GET(flag/protect_assistant_from_antagonist))
restricted_jobs += "Assistant"

Expand All @@ -54,8 +55,8 @@

/datum/game_mode/bloodsucker/generate_report()
return "There's been a report of the undead roaming around the sector, especially those that display Vampiric abilities.\
They've displayed the ability to disguise themselves as anyone and brainwash the minds of people they capture alive.\
Please take care of the crew and their health, as it is impossible to tell if one is lurking in the darkness behind."
They've displayed the ability to disguise themselves as anyone and brainwash the minds of people they capture alive.\
Please take care of the crew and their health, as it is impossible to tell if one is lurking in the darkness behind."

/datum/game_mode/bloodsucker/make_antag_chance(mob/living/carbon/human/character)
var/bloodsuckercap = min(round(GLOB.joined_player_list.len / (3 * 4)) + 2, round(GLOB.joined_player_list.len / 2))
Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/doors/airlock.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1249,7 +1249,7 @@

if(istype(I, /obj/item/jawsoflife))
if(isElectrified())
shock(user,100)//it's like sticking a forck in a power socket
shock(user,100)//it's like sticking a fork in a power socket
return

if(!density)//already open
Expand Down
21 changes: 10 additions & 11 deletions code/modules/antagonists/bloodsuckers/bloodsucker_daylight.dm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// 1 minute
#define TIME_BLOODSUCKER_DAY 60
/// 10 minutes
#define TIME_BLOODSUCKER_NIGHT 600
/// 45 seconds
#define TIME_BLOODSUCKER_DAY 45
/// 15 minutes
#define TIME_BLOODSUCKER_NIGHT 900
/// 1.5 minutes
#define TIME_BLOODSUCKER_DAY_WARN 90
/// 30 seconds
Expand Down Expand Up @@ -88,17 +88,15 @@
var/datum/antagonist/bloodsucker/bloodsuckerdatum = bloodsucker_minds.has_antag_datum(/datum/antagonist/bloodsucker)
if(!istype(bloodsuckerdatum))
continue
if(bloodsuckerdatum.my_clan == CLAN_GANGREL)
if(bloodsuckerdatum.my_clan == CLAN_GANGREL)
give_transform_power()
if(!iscarbon(bloodsucker_minds.current))
qdel(bloodsucker_minds.current)
if(bloodsuckerdatum.altar_uses > 0)
to_chat(bloodsuckerdatum, span_notice("Your Altar uses have been reset!"))
bloodsuckerdatum.altar_uses = 0
warn_daylight(4, span_userdanger("Solar flares bombard the station with deadly UV light!<br><span class = ''>Stay in cover for the next [TIME_BLOODSUCKER_DAY / 60] minutes or risk Final Death!"), \
warn_daylight(4, span_userdanger("Solar flares bombard the station with deadly UV light!<br><span class = ''>Stay in cover for the next [TIME_BLOODSUCKER_DAY] seconds or risk Final Death!"), \
span_userdanger("Solar flares bombard the station with UV light!"), \
span_userdanger("The sunlight is visible throughout the station, the Bloodsuckers must be asleep by now!"))
message_admins("BLOODSUCKER NOTICE: Daylight Beginning (Lasts for [TIME_BLOODSUCKER_DAY / 60] minutes.)")
message_admins("BLOODSUCKER NOTICE: Daylight Beginning (Lasts for [TIME_BLOODSUCKER_DAY] seconds.)")

/obj/effect/sunlight/proc/warn_daylight(danger_level = 0, vampwarn = "", vassalwarn = "", hunteralert = "")
for(var/datum/mind/bloodsucker_minds as anything in get_antag_minds(/datum/antagonist/bloodsucker))
Expand Down Expand Up @@ -181,13 +179,14 @@
var/datum/antagonist/bloodsucker/bloodsuckerdatum = bloodsucker_minds.has_antag_datum(/datum/antagonist/bloodsucker)
for(var/datum/action/bloodsucker/power in bloodsuckerdatum.powers)
if(istype(power, /datum/action/bloodsucker/gohome))
bloodsuckerdatum.powers -= power
power.Remove(bloodsucker_minds.current)
bloodsuckerdatum.RemovePower(power)

/obj/effect/sunlight/proc/give_transform_power()
for(var/datum/mind/bloodsucker_minds as anything in get_antag_minds(/datum/antagonist/bloodsucker))
if(!istype(bloodsucker_minds) || !istype(bloodsucker_minds.current))
continue
var/datum/antagonist/bloodsucker/bloodsuckerdatum = bloodsucker_minds.has_antag_datum(/datum/antagonist/bloodsucker)
if(bloodsuckerdatum.my_clan != CLAN_GANGREL)
continue
if(!(locate(/datum/action/bloodsucker/gangrel/transform) in bloodsuckerdatum.powers))
bloodsuckerdatum.BuyPower(new /datum/action/bloodsucker/gangrel/transform)
82 changes: 54 additions & 28 deletions code/modules/antagonists/bloodsuckers/bloodsucker_flaws.dm
Original file line number Diff line number Diff line change
@@ -1,53 +1,79 @@
/////////////////////////////////////////////////////////////////////////////////////////
// Any changes to clans have to be reflected in '/obj/item/book/kindred' /search proc. //
/////////////////////////////////////////////////////////////////////////////////////////
/datum/antagonist/bloodsucker/proc/AssignClanAndBane()
/datum/antagonist/bloodsucker/proc/AssignClanAndBane(tzimisce = FALSE)
var/mob/living/carbon/human/bloodsucker = owner.current
if(tzimisce)
my_clan = CLAN_TZIMISCE
to_chat(owner, span_announce("As you arrive near the station, you recall all you know and why you are here.\n\
* As a part of the Tzimisce Clan, you are able to <i>Dice</i> corpses into muscle pieces.\n\
* With muscles pieces you are able to mutilate dead husked vassals into greater beings,\n\
* The more you climb up the Ranks the more research you gather about fleshcrafting and beings you can make.\n\
* Remember to fuel a vassalrack with the muscles to be able to toy with those dead vassals, you are also able to ressurect people this way.\n\
* Finally, your Favorite Vassal will turn into a battle monster to help you in combat."))
AddHumanityLost(5.6)
BuyPower(new /datum/action/bloodsucker/targeted/dice)
bloodsucker.faction |= "bloodhungry" //flesh monster's clan
var/list/powerstoremove = list(/datum/action/bloodsucker/veil, /datum/action/bloodsucker/masquerade)
for(var/datum/action/bloodsucker/P in powers)
if(is_type_in_list(P, powerstoremove))
RemovePower(P)
return
var/static/list/clans = list(
CLAN_GANGREL,
//CLAN_LASOMBRA,
"None",
CLAN_LASOMBRA,
)
var/list/options = list()
options = clans
// Brief descriptions in case they don't read the Wiki.
to_chat(owner, span_announce("List of all Clans:\n\
Gangrel - Prone to Frenzy, special power.\n\
None - Continue living without a clan."))
Gangrel - Prone to Frenzy, strange outcomes from being on frenzy, special power.\n\
Lasombra - Life in the shadows, very weak to fire but no brute damage, upgradable abilities through tasks."))

var/answer = input("You have Ranked up far enough to remember your clan. Which clan are you part of?", "Our mind feels luxurious...") in options
if(!answer || answer == "None")
if(!answer)
to_chat(owner, span_warning("You have wilingfully decided to stay ignorant."))
return
var/mob/living/carbon/human/bloodsucker = owner.current
//switch(answer)
if(answer == CLAN_GANGREL)
my_clan = CLAN_GANGREL
to_chat(owner, span_announce("You have Ranked up enough to learn: You are part of the Gangrel Clan!\n\
* As part of the Gangrel Clan, your inner beast has a stronger impact in your undead life.\n\
* You are prone to falling into a frenzy, and will unleash a wild beast form when doing so,\n\
* Though once per night you are able to unleash your inner beast to help you in combat.\n\
* Due to growing more feral you've also strayed away from other bloodsuckers and will only be able to maintain one vassal.\n\
* Finally, your Favorite Vassal will gain the Minor Beast Form ability to help you in combat."))
AddHumanityLost(22.4)
BuyPower(new /datum/action/bloodsucker/gangrel/transform)
bloodsucker.faction |= "bloodhungry" //i love animals i love animals
/*if(CLAN_LASOMBRA)
switch(answer)
if(CLAN_GANGREL)
my_clan = CLAN_GANGREL
to_chat(owner, span_announce("You have Ranked up enough to learn: You are part of the Gangrel Clan!\n\
* As part of the Gangrel Clan, your inner beast has a stronger impact in your undead life.\n\
* You are prone to falling into a frenzy, and will unleash a wild beast form when doing so,\n\
* Though once per night you are able to unleash your inner beast to help you in combat.\n\
* Due to growing more feral you've also strayed away from other bloodsuckers and will only be able to maintain one vassal.\n\
* Finally, your Favorite Vassal will gain the Minor Beast Form ability to help you in combat."))
AddHumanityLost(16.8)
BuyPower(new /datum/action/bloodsucker/gangrel/transform)
bloodsucker.faction |= "bloodhungry" //i love animals i love animals
RemovePower(/datum/action/bloodsucker/masquerade)
var/datum/objective/bloodsucker/frenzy/gangrel_objective = new
gangrel_objective.owner = owner
objectives += gangrel_objective
if(CLAN_LASOMBRA)
my_clan = CLAN_LASOMBRA
to_chat(owner, span_announce("You have Ranked up enough to learn: You are part of the Lasombra Clan!\n\
* As part of the Lasombra Clan, your past teachings have taught you how to become in touch with the Abyss and practice it's prophecies.\n\
* As part of the Lasombra Clan, your past teachings have shown you how to become in touch with the Abyss and practice it's prophecies.\n\
* It'll take long before the Abyss can break through this plane's veil, but you'll try to salvage any of the energy that comes through,\n\
* To harness it's energy a ritual must be done each night to gain a shadowpoint, shadowpoints let's you upgrades normal abilities into upgraded ones.\n\
* To harness it's energy you must first find an influence and make a Resting Place altar to feed the harvested essence to.\n\
* On the Resting Place you can give ranks or blood in exchange for shadowpoints, that can be spent on the table to ascend your abilities.\n\
* The Abyss has blackened your veins and made you immune to brute damage but highly receptive to burn, so you might need to be extra careful when on Torpor.\n\
* Finally, your Favorite Vassal will gain the Minor Glare and Shadow Walk abilities to help you in combat."))
ADD_TRAIT(bloodsucker, TRAIT_BRUTEIMMUNE, BLOODSUCKER_TRAIT)
ADD_TRAIT(bloodsucker, TRAIT_SCORCHED, BLOODSUCKER_TRAIT)
* Finally, your Favorite Vassal will gain the Lesser Glare and Shadow Walk abilities to help you in combat."))
bloodsucker.physiology.burn_mod *= 2
bloodsucker.physiology.brute_mod *= 0
bloodsucker.eye_color = "f00"
ADD_TRAIT(bloodsucker, CULT_EYES, BLOODSUCKER_TRAIT)
bloodsucker.update_body()
var/obj/item/organ/heart/nightmare/nightmarish_heart = new
nightmarish_heart.Insert(bloodsucker)
nightmarish_heart.Stop()
for(var/obj/item/light_eater/blade in bloodsucker.held_items)
QDEL_NULL(blade)
owner.teach_crafting_recipe(/datum/crafting_recipe/meatcoffin)*/


GLOB.reality_smash_track.AddMind(owner)
var/datum/objective/bloodsucker/hierarchy/lasombra_objective = new
lasombra_objective.owner = owner
objectives += lasombra_objective
to_chat(owner, span_notice("You have also learned how to channel the abyss's power into an iron knight's armor that can be build in the structure ta and activated as a trap for your lair."))
owner.teach_crafting_recipe(/datum/crafting_recipe/possessedarmor)
owner.teach_crafting_recipe(/datum/crafting_recipe/restingplace)
owner.announce_objectives()
14 changes: 7 additions & 7 deletions code/modules/antagonists/bloodsuckers/bloodsucker_frenzy.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,20 @@
status_type = STATUS_EFFECT_UNIQUE
duration = -1
tick_interval = 10
examine_text = "<span class='notice'>They seem... inhumane, and feral!</span>"
alert_type = /atom/movable/screen/alert/status_effect/frenzy
examine_text = span_notice("They seem... inhumane, and feral!")
alert_type = /obj/screen/alert/status_effect/frenzy
/// Store whether they were an advancedtooluser, to give the trait back upon exiting.
var/was_tooluser = FALSE
/// The stored Bloodsucker antag datum
var/datum/antagonist/bloodsucker/bloodsuckerdatum

/atom/movable/screen/alert/status_effect/frenzy
/obj/screen/alert/status_effect/frenzy
name = "Frenzy"
desc = "You are in a Frenzy! You are entirely Feral and, depending on your Clan, fighting for your life!"
icon = 'icons/mob/actions/actions_bloodsucker.dmi'
icon_state = "power_recover"

/atom/movable/screen/alert/status_effect/masquerade/MouseEntered(location,control,params)
/obj/screen/alert/status_effect/masquerade/MouseEntered(location,control,params)
desc = initial(desc)
return ..()

Expand All @@ -51,7 +51,7 @@

// Disable ALL Powers and notify their entry
bloodsuckerdatum.DisableAllPowers()
to_chat(owner, span_userdanger("<FONT size = 3>Blood! You need Blood, now! You enter a total Frenzy!"))
to_chat(owner, span_userdanger("<FONT size = 3>Blood! You need Blood, now! You enter a total Frenzy! Your skin starts sizzling...."))
to_chat(owner, span_announce("* Bloodsucker Tip: While in Frenzy, you instantly Aggresively grab, have stun resistance, cannot speak, hear, or use any powers outside of Feed and Trespass (If you have it)."))
// Stamina resistances
user.physiology.stamina_mod *= 0.4
Expand All @@ -71,7 +71,7 @@
user.clear_cuffs(cuffs, TRUE)
user.clear_cuffs(legcuffs, TRUE)
// Keep track of how many times we've entered a Frenzy.
bloodsuckerdatum.frenzies += 1
bloodsuckerdatum.frenzies++
bloodsuckerdatum.frenzied = TRUE
return ..()

Expand All @@ -97,4 +97,4 @@
var/mob/living/carbon/human/user = owner
if(!bloodsuckerdatum.frenzied)
return
user.adjustFireLoss(1.5 + (bloodsuckerdatum.humanity_lost / 10))
user.adjustFireLoss(0.5 + (bloodsuckerdatum.humanity_lost / 15))
11 changes: 2 additions & 9 deletions code/modules/antagonists/bloodsuckers/bloodsucker_integration.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@
return
. = ..()

/// Prevents Bloodsuckers from naturally regenerating Blood - Even while on masquerade
/mob/living/carbon/human/handle_blood(delta_time, times_fired)
if(mind && IS_BLOODSUCKER(src))
return
/// For Vassals -- Bloodsuckers get this removed while on Masquerade, so we don't want to remove the check above.
if(HAS_TRAIT(src, TRAIT_NOPULSE))
return
. = ..()

/mob/living/carbon/human/natural_bodytemperature_stabilization(datum/gas_mixture/environment, delta_time, times_fired)
// Return 0 as your natural temperature. Species proc handle_environment() will adjust your temperature based on this.
if(HAS_TRAIT(src, TRAIT_COLDBLOODED))
Expand Down Expand Up @@ -53,6 +44,8 @@
if(bloodsuckerdatum)
. += ""
. += "Blood Drank: [bloodsuckerdatum.total_blood_drank]"
if(bloodsuckerdatum.current_task)
. += "Task Blood Drank: [bloodsuckerdatum.task_blood_drank]"


// INTEGRATION: Adding Procs and Datums to existing "classes" //
Expand Down
Loading