From 6ae3935feba92088c735dbfee01dd9e8a565871a Mon Sep 17 00:00:00 2001 From: Anorak2020 <145682013+Anorak2024@users.noreply.github.com> Date: Thu, 7 Nov 2024 19:02:33 +0300 Subject: [PATCH] add: vampire sucking effects (#6029) --- code/__DEFINES/vampire_defines.dm | 2 + .../antagonists/vampire/vampire_datum.dm | 63 ++++++++++++------- .../antagonists/vampire/vampire_subclasses.dm | 24 +++++++ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/code/__DEFINES/vampire_defines.dm b/code/__DEFINES/vampire_defines.dm index a0663014e6f..90123400739 100644 --- a/code/__DEFINES/vampire_defines.dm +++ b/code/__DEFINES/vampire_defines.dm @@ -16,3 +16,5 @@ #define NEW_NULLIFICATION 1 //nulifiaction like the new vampires #define OLD_NULLIFICATION 2 //nulifiaction like the goon vampires + +#define REQ_BLOOD_FOR_SUBCLASS_ACT 400 // total blood required for a special subclass action diff --git a/code/modules/antagonists/vampire/vampire_datum.dm b/code/modules/antagonists/vampire/vampire_datum.dm index ab388e1ffa9..362a11ff5cf 100644 --- a/code/modules/antagonists/vampire/vampire_datum.dm +++ b/code/modules/antagonists/vampire/vampire_datum.dm @@ -198,12 +198,13 @@ /datum/antagonist/vampire/proc/handle_bloodsucking(mob/living/carbon/human/target, suck_rate_override) draining = target + var/mob/living/carbon/human/cur = owner.current var/unique_suck_id = target.UID() var/blood = 0 var/blood_volume_warning = 9999 //Blood volume threshold for warnings var/cycle_counter = 0 var/time_per_action - var/vampire_dir = get_dir(owner.current, target) + var/vampire_dir = get_dir(cur, target) var/old_bloodusable = 0 //used to see if we increased our blood usable @@ -213,20 +214,20 @@ else suck_rate_final = suck_rate - if(owner.current.is_muzzled()) - to_chat(owner.current, span_warning("[owner.current.wear_mask] мешает вам укусить [target]!")) + if(cur.is_muzzled()) + to_chat(cur, span_warning("[cur.wear_mask] мешает вам укусить [target]!")) draining = null return - add_attack_logs(owner.current, target, "vampirebit & is draining their blood.", ATKLOG_ALMOSTALL) + add_attack_logs(cur, target, "vampirebit & is draining their blood.", ATKLOG_ALMOSTALL) - if(!iscarbon(owner.current)) + if(!iscarbon(cur)) target.LAssailant = null else - target.LAssailant = owner.current + target.LAssailant = cur var/is_target_grabbed = FALSE - if(target.pulledby == owner.current && owner.current.grab_state > GRAB_PASSIVE) + if(target.pulledby == cur && cur.grab_state > GRAB_PASSIVE) is_target_grabbed = TRUE if(!is_target_grabbed || vampire_dir == NORTHEAST || vampire_dir == NORTHWEST || \ @@ -238,25 +239,27 @@ cycle_counter = STATE_GRABBING time_per_action = suck_rate_final*BITE_TIME_MOD - while(do_after(owner.current, time_per_action, target, NONE, interaction_key = DOAFTER_SOURCE_VAMPIRE_SUCKING, max_interact_count = 1)) + while(do_after(cur, time_per_action, target, NONE, interaction_key = DOAFTER_SOURCE_VAMPIRE_SUCKING, max_interact_count = 1)) cycle_counter++ - owner.current.face_atom(target) + cur.face_atom(target) old_bloodusable = bloodusable switch(cycle_counter) if(STATE_CLOSING_IN) - owner.current.visible_message(span_danger("[owner.current] приближается к [target]"), \ + cur.visible_message(span_danger("[cur] приближается к [target]"), \ span_danger("Вы приближаетесь к [target]")) getting_closer_animation(target, STATE_CLOSING_IN, vampire_dir) time_per_action = suck_rate_final*GRABBING_TIME_MOD continue + if(STATE_GRABBING) - owner.current.visible_message(span_danger("[owner.current] грубо хватает шею [target]"), \ + cur.visible_message(span_danger("[cur] грубо хватает шею [target]"), \ span_danger("Вы грубо хватает шею [target]")) getting_closer_animation(target, STATE_GRABBING, vampire_dir) time_per_action = suck_rate_final*BITE_TIME_MOD continue + if(STATE_BITE) - owner.current.visible_message(span_danger("[owner.current] вонзает [genderize_ru(owner.current.gender, "его", "её", "его", "их")] клыки!"), \ + cur.visible_message(span_danger("[cur] вонзает [genderize_ru(cur.gender, "его", "её", "его", "их")] клыки!"), \ span_danger("Вы вонзаете клыки в шею [target] и начинаете высасывать [genderize_ru(target.gender, "его", "её", "его", "их")] кровь."), \ span_italics("Вы слышите тихий звук прокола и влажные хлюпающие звуки.")) bite_animation(target, vampire_dir) @@ -265,9 +268,9 @@ if(unique_suck_id in drained_humans) if(drained_humans[unique_suck_id] >= BLOOD_DRAIN_LIMIT) - to_chat(owner.current, span_warning("Вы поглотили всю жизненную эссенцию [target], дальнейшее питьё крови будет только утолять голод!")) + to_chat(cur, span_warning("Вы поглотили всю жизненную эссенцию [target], дальнейшее питьё крови будет только утолять голод!")) target.blood_volume = max(target.blood_volume - 25, 0) - owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + 5)) + cur.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, cur.nutrition + 5)) continue @@ -275,29 +278,47 @@ if(target.ckey || target.player_ghosted) //Requires ckey regardless if monkey or humanoid, or the body has been ghosted before it died blood = min(20, target.blood_volume) adjust_blood(target, blood * BLOOD_GAINED_MODIFIER) - to_chat(owner.current, span_boldnotice("Вы накопили [bloodtotal] единиц[declension_ru(bloodtotal, "у", "ы", "")] крови[bloodusable != old_bloodusable ? ", и теперь вам доступно [bloodusable] единиц[declension_ru(bloodusable, "а", "ы", "")] крови" : ""].")) + cur.adjustBruteLoss(-3) + cur.adjustFireLoss(-3) + cur.adjustOxyLoss(-10) + cur.adjustToxLoss(-2) + cur.adjustBrainLoss(-1) + for(var/obj/item/organ/external/bodypart as anything in cur.bodyparts) + if(bodypart.has_fracture() && prob(5)) + to_chat(cur, span_notice("You feel a burning sensation in your [bodypart.name] as it straightens involuntarily!")) + bodypart.mend_fracture() + + if(bodypart.has_internal_bleeding() && prob(5)) + to_chat(cur, span_notice("You feel a burning sensation in your [bodypart.name] as your veins begin to recover!")) + bodypart.stop_internal_bleeding() + + if(bloodtotal >= REQ_BLOOD_FOR_SUBCLASS_ACT) + subclass?.on_blood_sucking(owner) + + to_chat(cur, span_boldnotice("Вы накопили [bloodtotal] единиц[declension_ru(bloodtotal, "у", "ы", "")] крови[bloodusable != old_bloodusable ? ", и теперь вам доступно [bloodusable] единиц[declension_ru(bloodusable, "а", "ы", "")] крови" : ""].")) target.blood_volume = max(target.blood_volume - 25, 0) //Blood level warnings (Code 'borrowed' from Fulp) if(target.blood_volume) if(target.blood_volume <= BLOOD_VOLUME_BAD && blood_volume_warning > BLOOD_VOLUME_BAD) - to_chat(owner.current, span_danger("У вашей жертвы остаётся опасно мало крови!")) + to_chat(cur, span_danger("У вашей жертвы остаётся опасно мало крови!")) else if(target.blood_volume <= BLOOD_VOLUME_OKAY && blood_volume_warning > BLOOD_VOLUME_OKAY) - to_chat(owner.current, span_warning("У вашей жертвы остаётся тревожно мало крови!")) + to_chat(cur, span_warning("У вашей жертвы остаётся тревожно мало крови!")) + blood_volume_warning = target.blood_volume //Set to blood volume, so that you only get the message once else - to_chat(owner.current, span_warning("Вы выпили свою жертву досуха!")) + to_chat(cur, span_warning("Вы выпили свою жертву досуха!")) break if(!target.ckey && !target.player_ghosted)//Only runs if there is no ckey and the body has not being ghosted while alive - to_chat(owner.current, span_boldnotice("Питьё крови у [target] насыщает вас, но доступной крови от этого вы не получаете.")) - owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + 5)) + to_chat(cur, span_boldnotice("Питьё крови у [target] насыщает вас, но доступной крови от этого вы не получаете.")) + cur.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, cur.nutrition + 5)) else - owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + (blood / 2))) + cur.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, cur.nutrition + (blood / 2))) stop_sucking() diff --git a/code/modules/antagonists/vampire/vampire_subclasses.dm b/code/modules/antagonists/vampire/vampire_subclasses.dm index a3af73d3147..0884168f95c 100644 --- a/code/modules/antagonists/vampire/vampire_subclasses.dm +++ b/code/modules/antagonists/vampire/vampire_subclasses.dm @@ -28,6 +28,9 @@ ) +/datum/vampire_subclass/proc/on_blood_sucking(mob/living/carbon/human/H) + return + /datum/vampire_subclass/proc/add_subclass_ability(datum/antagonist/vampire/vamp) for(var/thing in standard_powers) if(vamp.bloodtotal >= standard_powers[thing]) @@ -51,6 +54,14 @@ /obj/effect/proc_holder/spell/vampire/self/eternal_darkness, /datum/vampire_passive/xray) +/datum/vampire_subclass/umbrae/on_blood_sucking(mob/living/carbon/human/H) + var/list/lights = list() + for(var/obj/machinery/light/L in GLOB.machines) + if(L.status && L.z == H.z) + lights += L + + var/obj/machinery/light/L = pick(lights) + L.break_light_tube() /datum/vampire_subclass/hemomancer name = "hemomancer" @@ -63,6 +74,8 @@ fully_powered_abilities = list(/datum/vampire_passive/full, /obj/effect/proc_holder/spell/vampire/self/blood_spill) +/datum/vampire_subclass/hemomancer/on_blood_sucking(mob/living/carbon/human/H) + H.blood_volume = min(H.blood_volume + 5, BLOOD_VOLUME_NORMAL) /datum/vampire_subclass/gargantua name = "gargantua" @@ -76,6 +89,9 @@ /obj/effect/proc_holder/spell/vampire/charge) improved_rejuv_healing = TRUE +/datum/vampire_subclass/gargantua/on_blood_sucking(mob/living/carbon/human/H) + H.adjustBruteLoss(-2) + H.adjustFireLoss(-2) /datum/vampire_subclass/dantalion name = "dantalion" @@ -92,6 +108,11 @@ /obj/effect/proc_holder/spell/vampire/hysteria, /datum/vampire_passive/increment_thrall_cap/three) +/datum/vampire_subclass/dantalion/on_blood_sucking(mob/living/carbon/human/H) + for(var/datum/mind/thrall in H?.mind?.som?.serv) + thrall.current?.adjustBruteLoss(-3) + thrall.current?.adjustFireLoss(-3) + thrall.current?.adjustOxyLoss(-5) /datum/vampire_subclass/bestia name = "bestia" @@ -110,6 +131,9 @@ /datum/vampire_passive/dissection_cap/two) improved_rejuv_healing = TRUE +/datum/vampire_subclass/bestia/on_blood_sucking(mob/living/carbon/human/H) + H.adjustBruteLoss(-2) + H.adjustFireLoss(-2) /datum/vampire_subclass/ancient name = "ancient"