Skip to content

Commit

Permalink
Bloodsucker fixes (#2102)
Browse files Browse the repository at this point in the history
* bloodsucker fixing upping

* Use DisplayTimeText
  • Loading branch information
Absolucy authored Jun 6, 2024
1 parent 2f18e25 commit 1d47c94
Show file tree
Hide file tree
Showing 33 changed files with 106 additions and 112 deletions.
4 changes: 4 additions & 0 deletions code/__DEFINES/bloodsuckers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@
*/
/// Source trait for Bloodsuckers-related traits
#define BLOODSUCKER_TRAIT "bloodsucker_trait"
/// Source trait for bloodsuckers in torpor.
#define TORPOR_TRAIT "torpor_trait"
/// Source trait for bloodsucker mesmerization.
#define MESMERIZED_TRAIT "mesmerized_trait"
/// Source trait for Monster Hunter-related traits
#define HUNTER_TRAIT "monsterhunter_trait"
/// Source trait while Feeding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
if(!master || (master == owner.current))
return TRUE
var/datum/antagonist/bloodsucker/bloodsuckerdatum = master.mind.has_antag_datum(/datum/antagonist/bloodsucker)
if(bloodsuckerdatum && bloodsuckerdatum.broke_masquerade)
if(bloodsuckerdatum?.broke_masquerade)
//vassal stealing
return TRUE
to_chat(owner.current, span_danger("[conversion_target]'s mind is overwhelmed with too much external force to put your own!"))
Expand All @@ -52,7 +52,7 @@
* time, ranges from 1 at 20 pop to 4 at 40 pop
*/
/datum/antagonist/bloodsucker/proc/return_current_max_vassals()
var/total_players = GLOB.joined_player_list.len
var/total_players = length(GLOB.joined_player_list)
switch(total_players)
if(1 to 20)
return 1
Expand All @@ -72,8 +72,7 @@
return FALSE

//Check if they used to be a Vassal and was stolen.
var/datum/antagonist/vassal/old_vassal = conversion_target.mind.has_antag_datum(/datum/antagonist/vassal)
if(old_vassal)
if(IS_VASSAL(conversion_target))
conversion_target.mind.remove_antag_datum(/datum/antagonist/vassal)

var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.has_antag_datum(/datum/antagonist/bloodsucker)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@

// Default Report
var/objectives_complete = TRUE
if(objectives.len)
if(length(objectives))
report += printobjectives(objectives)
for(var/datum/objective/objective in objectives)
if(objective.objective_name == "Optional Objective")
Expand All @@ -351,10 +351,10 @@
break

// Now list their vassals
if(vassals.len)
report += "<span class='header'>Their Vassals were...</span>"
if(length(vassals))
report += span_header("Their Vassals were...")
for(var/datum/antagonist/vassal/all_vassals as anything in vassals)
if(!all_vassals.owner)
if(QDELETED(all_vassals?.owner))
continue
var/list/vassal_report = list()
vassal_report += "<b>[all_vassals.owner.name]</b>"
Expand All @@ -367,7 +367,7 @@
vassal_report += " and was the <b>Revenge Vassal</b>"
report += vassal_report.Join()

if(objectives.len == 0 || objectives_complete)
if(!length(objectives) || objectives_complete)
report += "<span class='greentext big'>The [name] was successful!</span>"
else
report += "<span class='redtext big'>The [name] has failed!</span>"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,21 @@
* person_selecting - Mob override for stuff like Admins selecting someone's clan.
*/
/datum/antagonist/bloodsucker/proc/assign_clan_and_bane(mob/person_selecting)
if(my_clan)
if(my_clan || owner.current.has_status_effect(/datum/status_effect/frenzy))
return
if(owner.current.has_status_effect(/datum/status_effect/frenzy))
return
if(!person_selecting)
person_selecting = owner.current
person_selecting ||= owner.current

var/list/options = list()
var/list/radial_display = list()
for(var/datum/bloodsucker_clan/all_clans as anything in typesof(/datum/bloodsucker_clan))
if(!initial(all_clans.joinable_clan)) //flavortext only
if(!all_clans::joinable_clan) //flavortext only
continue
options[initial(all_clans.name)] = all_clans
options[all_clans::name] = all_clans

var/datum/radial_menu_choice/option = new
option.image = image(icon = initial(all_clans.join_icon), icon_state = initial(all_clans.join_icon_state))
option.info = "[initial(all_clans.name)] - [span_boldnotice(initial(all_clans.join_description))]"
radial_display[initial(all_clans.name)] = option
option.image = image(icon = all_clans::join_icon, icon_state = all_clans::join_icon_state)
option.info = "[all_clans::name] - [span_boldnotice(all_clans::join_description)]"
radial_display[all_clans::name] = option

var/chosen_clan = show_radial_menu(person_selecting, owner.current, radial_display)
chosen_clan = options[chosen_clan]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
owner.add_client_colour(/datum/client_colour/cursed_heart_blood)
var/obj/cuffs = user.get_item_by_slot(ITEM_SLOT_HANDCUFFED)
var/obj/legcuffs = user.get_item_by_slot(ITEM_SLOT_LEGCUFFED)
if(user.handcuffed || user.legcuffed)
if(!QDELETED(user.handcuffed) || !QDELETED(user.legcuffed))
user.clear_cuffs(cuffs, TRUE)
user.clear_cuffs(legcuffs, TRUE)
bloodsuckerdatum.frenzied = TRUE
Expand All @@ -90,6 +90,6 @@

/datum/status_effect/frenzy/tick()
var/mob/living/carbon/human/user = owner
if(!bloodsuckerdatum.frenzied)
if(!bloodsuckerdatum?.frenzied)
return
user.adjustFireLoss(1.5 + (bloodsuckerdatum.humanity_lost / 10))
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
if(length(guardians) && !allow_multiple)
balloon_alert(user, "already have one!")
return
if(user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling) && !allow_changeling)
if(user.mind?.has_antag_datum(/datum/antagonist/changeling) && !allow_changeling)
to_chat(user, ling_failure)
return
if(used)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
else if(bloodsucker_blood_volume > BLOOD_VOLUME_BAD)
valuecolor = "#FFAAAA"

if(blood_display)
blood_display.maptext = FORMAT_BLOODSUCKER_HUD_TEXT(valuecolor, bloodsucker_blood_volume)
blood_display?.maptext = FORMAT_BLOODSUCKER_HUD_TEXT(valuecolor, bloodsucker_blood_volume)

if(vamprank_display)
if(bloodsucker_level_unspent > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
if(!owner)
INVOKE_ASYNC(src, PROC_REF(HandleDeath))
return
if(HAS_TRAIT(owner.current, TRAIT_NODEATH))
if(HAS_TRAIT_FROM(owner.current, TRAIT_NODEATH, TORPOR_TRAIT))
check_end_torpor()
// Deduct Blood
if(owner.current.stat == CONSCIOUS && !HAS_TRAIT(owner.current, TRAIT_IMMOBILIZED) && !HAS_TRAIT(owner.current, TRAIT_NODEATH))
if(owner.current.stat == CONSCIOUS && !HAS_TRAIT(owner.current, TRAIT_IMMOBILIZED) && !HAS_TRAIT_FROM(owner.current, TRAIT_NODEATH, TORPOR_TRAIT))
INVOKE_ASYNC(src, PROC_REF(AddBloodVolume), -BLOODSUCKER_PASSIVE_BLOOD_DRAIN) // -.1 currently
if(HandleHealing())
if((COOLDOWN_FINISHED(src, bloodsucker_spam_healing)) && bloodsucker_blood_volume > 0)
Expand Down Expand Up @@ -83,7 +83,7 @@
/datum/antagonist/bloodsucker/proc/HandleHealing(mult = 1)
var/actual_regen = bloodsucker_regen_rate + additional_regen
// Don't heal if I'm staked or on Masquerade (+ not in a Coffin). Masqueraded Bloodsuckers in a Coffin however, will heal.
if(owner.current.am_staked() || (HAS_TRAIT(owner.current, TRAIT_MASQUERADE) && !HAS_TRAIT(owner.current, TRAIT_NODEATH)))
if(owner.current.am_staked() || (HAS_TRAIT(owner.current, TRAIT_MASQUERADE) && !HAS_TRAIT_FROM(owner.current, TRAIT_NODEATH, TORPOR_TRAIT)))
return FALSE
owner.current.adjustCloneLoss(-1 * (actual_regen * 4) * mult, 0)
owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (actual_regen * 4) * mult) //adjustBrainLoss(-1 * (actual_regen * 4) * mult, 0)
Expand All @@ -95,7 +95,7 @@
var/fireheal = 0 // BURN: Heal in Coffin while Fakedeath, or when damage above maxhealth (you can never fully heal fire)
// Checks if you're in a coffin here, additionally checks for Torpor right below it.
var/amInCoffin = istype(user.loc, /obj/structure/closet/crate/coffin)
if(amInCoffin && HAS_TRAIT(user, TRAIT_NODEATH))
if(amInCoffin && HAS_TRAIT_FROM(user, TRAIT_NODEATH, TORPOR_TRAIT))
if(HAS_TRAIT(owner.current, TRAIT_MASQUERADE) && (COOLDOWN_FINISHED(src, bloodsucker_spam_healing)))
to_chat(user, span_alert("You do not heal while your Masquerade ability is active."))
COOLDOWN_START(src, bloodsucker_spam_healing, BLOODSUCKER_SPAM_MASQUERADE)
Expand All @@ -108,7 +108,7 @@
if(check_limbs(costMult))
return TRUE
// In Torpor, but not in a Coffin? Heal faster anyways.
else if(HAS_TRAIT(user, TRAIT_NODEATH))
else if(HAS_TRAIT_FROM(user, TRAIT_NODEATH, TORPOR_TRAIT))
fireheal = min(user.getFireLoss_nonProsthetic(), actual_regen) / 1.2 // 20% slower than being in a coffin
mult *= 3
// Heal if Damaged
Expand All @@ -123,7 +123,7 @@
var/limb_regen_cost = 50 * -costMult
var/mob/living/carbon/user = owner.current
var/list/missing = user.get_missing_limbs()
if(missing.len && (bloodsucker_blood_volume < limb_regen_cost + 5))
if(length(missing) && (bloodsucker_blood_volume < limb_regen_cost + 5))
return FALSE
for(var/missing_limb in missing) //Find ONE Limb and regenerate it.
user.regenerate_limb(missing_limb, FALSE)
Expand Down Expand Up @@ -155,7 +155,7 @@
organ.set_organ_damage(0)
if(!HAS_TRAIT(bloodsuckeruser, TRAIT_MASQUERADE))
var/obj/item/organ/internal/heart/current_heart = bloodsuckeruser.get_organ_slot(ORGAN_SLOT_HEART)
current_heart.beating = FALSE
current_heart?.beating = FALSE
var/obj/item/organ/internal/eyes/current_eyes = bloodsuckeruser.get_organ_slot(ORGAN_SLOT_EYES)
if(current_eyes)
current_eyes.flash_protect = max(initial(current_eyes.flash_protect) - 1, FLASH_PROTECTION_SENSITIVE)
Expand Down Expand Up @@ -199,7 +199,7 @@
FinalDeath()
return
// Temporary Death? Convert to Torpor.
if(HAS_TRAIT(owner.current, TRAIT_NODEATH))
if(HAS_TRAIT_FROM(owner.current, TRAIT_NODEATH, TORPOR_TRAIT))
return
to_chat(owner.current, span_danger("Your immortal body will not yet relinquish your soul to the abyss. You enter Torpor."))
check_begin_torpor(TRUE)
Expand All @@ -215,7 +215,7 @@
if(bloodsucker_blood_volume >= FRENZY_THRESHOLD_EXIT && frenzied)
owner.current.remove_status_effect(/datum/status_effect/frenzy)
// BLOOD_VOLUME_BAD: [224] - Jitter
if(bloodsucker_blood_volume < BLOOD_VOLUME_BAD && prob(0.5) && !HAS_TRAIT(owner.current, TRAIT_NODEATH) && !HAS_TRAIT(owner.current, TRAIT_MASQUERADE))
if(bloodsucker_blood_volume < BLOOD_VOLUME_BAD && prob(0.5) && !HAS_TRAIT_FROM(owner.current, TRAIT_NODEATH, TORPOR_TRAIT) && !HAS_TRAIT(owner.current, TRAIT_MASQUERADE))
owner.current.set_timed_status_effect(3 SECONDS, /datum/status_effect/jitter, only_if_higher = TRUE)
// BLOOD_VOLUME_SURVIVE: [122] - Blur Vision
if(bloodsucker_blood_volume < BLOOD_VOLUME_SURVIVE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
///Disables all powers, accounting for torpor
/datum/antagonist/bloodsucker/proc/DisableAllPowers(forced = FALSE)
for(var/datum/action/cooldown/bloodsucker/power as anything in powers)
if(forced || ((power.check_flags & BP_CANT_USE_IN_TORPOR) && HAS_TRAIT(owner.current, TRAIT_NODEATH)))
if(forced || ((power.check_flags & BP_CANT_USE_IN_TORPOR) && HAS_TRAIT_FROM(owner.current, TRAIT_NODEATH, TORPOR_TRAIT)))
if(power.active)
power.DeactivatePower()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
/// Check Vassals and get their occupations
/datum/objective/bloodsucker/proc/get_vassal_occupations()
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.has_antag_datum(/datum/antagonist/bloodsucker)
if(!bloodsuckerdatum || !bloodsuckerdatum.vassals.len)
if(!length(bloodsuckerdatum?.vassals))
return FALSE
var/list/all_vassal_jobs = list()
var/vassal_job
Expand Down Expand Up @@ -310,7 +310,7 @@
var/list/datum/mind/monsters = list()
for(var/datum/antagonist/monster in GLOB.antagonists)
var/datum/mind/brain = monster.owner
if(!brain || brain == owner)
if(QDELETED(brain) || brain == owner)
continue
if(brain.current.stat == DEAD)
continue
Expand All @@ -319,7 +319,7 @@
if(brain.has_antag_datum(/datum/antagonist/changeling))
monsters += brain

return completed || !monsters.len
return completed || !length(monsters)



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@
/mob/living/carbon/transfer_blood_to(atom/movable/AM, amount, forced)
. = ..()

if(!mind)
return
var/datum/antagonist/bloodsucker/bloodsuckerdatum = mind.has_antag_datum(/datum/antagonist/bloodsucker)
if(!bloodsuckerdatum)
return
bloodsuckerdatum.bloodsucker_blood_volume -= amount
var/datum/antagonist/bloodsucker/bloodsuckerdatum = mind?.has_antag_datum(/datum/antagonist/bloodsucker)
bloodsuckerdatum?.bloodsucker_blood_volume -= amount

/// Prevents using a Memento Mori
/obj/item/clothing/neck/necklace/memento_mori/memento(mob/living/carbon/human/user)
Expand All @@ -42,10 +38,9 @@

// Used when analyzing a Bloodsucker, Masquerade will hide brain traumas (Unless you're a Beefman)
/mob/living/carbon/get_traumas()
if(!mind)
if(QDELETED(mind))
return ..()
var/datum/antagonist/bloodsucker/bloodsuckerdatum = IS_BLOODSUCKER(src)
if(bloodsuckerdatum && HAS_TRAIT(src, TRAIT_MASQUERADE))
if(IS_BLOODSUCKER(src) && HAS_TRAIT(src, TRAIT_MASQUERADE))
return
return ..()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

/obj/item/soulstone/bloodsucker/get_ghost_to_replace_shade(mob/living/carbon/victim, mob/user)
var/mob/dead/observer/chosen_ghost = victim.get_ghost(FALSE, TRUE)
if(!chosen_ghost || !chosen_ghost.client)
if(QDELETED(chosen_ghost?.client))
victim.dust()
return FALSE
victim.unequip_everything()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
if(owner.current.am_staked() && COOLDOWN_FINISHED(src, bloodsucker_spam_sol_burn))
to_chat(owner.current, span_userdanger("You are staked! Remove the offending weapon from your heart before sleeping."))
COOLDOWN_START(src, bloodsucker_spam_sol_burn, BLOODSUCKER_SPAM_SOL) //This should happen twice per Sol
if(!HAS_TRAIT(owner.current, TRAIT_NODEATH))
if(!HAS_TRAIT_FROM(owner.current, TRAIT_NODEATH, TORPOR_TRAIT))
check_begin_torpor(TRUE)
owner.current.add_mood_event("vampsleep", /datum/mood_event/coffinsleep)
return
Expand Down Expand Up @@ -122,7 +122,7 @@
var/total_burn = user.getFireLoss_nonProsthetic()
var/total_damage = total_brute + total_burn
/// Checks - Not daylight & Has more than 10 Brute/Burn & not already in Torpor
if(!SSsunlight.sunlight_active && total_damage >= 10 && !HAS_TRAIT(owner.current, TRAIT_NODEATH))
if(!SSsunlight.sunlight_active && total_damage >= 10 && !HAS_TRAIT_FROM(owner.current, TRAIT_NODEATH, TORPOR_TRAIT))
torpor_begin()

/datum/antagonist/bloodsucker/proc/check_end_torpor()
Expand All @@ -147,15 +147,15 @@
// Force them to go to sleep
REMOVE_TRAIT(owner.current, TRAIT_SLEEPIMMUNE, BLOODSUCKER_TRAIT)
// Without this, you'll just keep dying while you recover.
owner.current.add_traits(list(TRAIT_NODEATH, TRAIT_FAKEDEATH, TRAIT_DEATHCOMA, TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTHIGHPRESSURE), BLOODSUCKER_TRAIT)
owner.current.add_traits(list(TRAIT_NODEATH, TRAIT_FAKEDEATH, TRAIT_DEATHCOMA, TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTHIGHPRESSURE), TORPOR_TRAIT)
owner.current.set_timed_status_effect(0 SECONDS, /datum/status_effect/jitter, only_if_higher = TRUE)
// Disable ALL Powers
DisableAllPowers()

/datum/antagonist/bloodsucker/proc/torpor_end()
owner.current.grab_ghost()
to_chat(owner.current, span_warning("You have recovered from Torpor."))
owner.current.remove_traits(list(TRAIT_NODEATH, TRAIT_FAKEDEATH, TRAIT_DEATHCOMA, TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTHIGHPRESSURE), BLOODSUCKER_TRAIT)
REMOVE_TRAITS_IN(owner.current, TORPOR_TRAIT)
if(!HAS_TRAIT(owner.current, TRAIT_MASQUERADE))
ADD_TRAIT(owner.current, TRAIT_SLEEPIMMUNE, BLOODSUCKER_TRAIT)
heal_vampire_organs()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

// Delete Next Portal if it's time (it will remove its partner)
var/obj/effect/client_image_holder/phobetor/first_on_the_stack = created_firsts[1]
if(created_firsts.len && world.time >= first_on_the_stack.created_on + first_on_the_stack.exist_length)
if(length(created_firsts) && world.time >= first_on_the_stack.created_on + first_on_the_stack.exist_length)
var/targetGate = first_on_the_stack
created_firsts -= targetGate
qdel(targetGate)
Expand Down
4 changes: 2 additions & 2 deletions monkestation/code/modules/bloodsuckers/clans/_clan_base.dm
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
if(initial(power.purchase_flags) & BLOODSUCKER_CAN_BUY && !(locate(power) in bloodsuckerdatum.powers))
options[initial(power.name)] = power

if(options.len < 1)
if(length(options) < 1)
to_chat(bloodsuckerdatum.owner.current, span_notice("You grow more ancient by the night!"))
else
// Give them the UI to purchase a power.
Expand Down Expand Up @@ -242,7 +242,7 @@
option.info = "[initial(vassaldatums.name)] - [span_boldnotice(initial(vassaldatums.vassal_description))]"
radial_display[initial(vassaldatums.name)] = option

if(!options.len)
if(!length(options))
return

to_chat(bloodsuckerdatum.owner.current, span_notice("You can change who this Vassal is, who are they to you?"))
Expand Down
2 changes: 1 addition & 1 deletion monkestation/code/modules/bloodsuckers/clans/tremere.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
continue
options[initial(power.name)] = power

if(options.len < 1)
if(length(options) < 1)
to_chat(bloodsuckerdatum.owner.current, span_notice("You grow more ancient by the night!"))
else
// Give them the UI to purchase a power.
Expand Down
2 changes: 1 addition & 1 deletion monkestation/code/modules/bloodsuckers/clans/venture.dm
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
if(initial(power.purchase_flags) & VASSAL_CAN_BUY && !(locate(power) in vassaldatum.powers))
options[initial(power.name)] = power

if(options.len < 1)
if(length(options) < 1)
to_chat(bloodsuckerdatum.owner.current, span_notice("You grow more ancient by the night!"))
else
// Give them the UI to purchase a power.
Expand Down
Loading

0 comments on commit 1d47c94

Please sign in to comment.