From 82d1497ddc969d116681da766b7c7a36c782de48 Mon Sep 17 00:00:00 2001 From: Artur Date: Thu, 5 Dec 2019 17:29:00 +0200 Subject: [PATCH] Fixes bad buds and toxin healing --- code/__DEFINES/status_effects.dm | 3 + code/datums/status_effects/debuffs.dm | 28 ++- .../game/gamemodes/bloodsucker/bloodsucker.dm | 10 +- code/game/gamemodes/bloodsucker/hunter.dm | 3 +- code/game/gamemodes/game_mode.dm | 2 +- .../items/stacks/sheets/sheet_types.dm | 33 +++- .../bloodsucker/bloodsucker_integration.dm | 4 + .../bloodsucker/bloodsucker_life.dm | 166 +++++------------- .../bloodsucker/datum_bloodsucker.dm | 2 +- .../antagonists/bloodsucker/datum_hunter.dm | 22 +-- .../bloodsucker/items/bloodsucker_stake.dm | 62 ++----- .../bloodsucker/powers/bs_fortitude.dm | 11 +- .../bloodsucker/powers/bs_mesmerize.dm | 13 +- code/modules/mob/living/silicon/login.dm | 3 + 14 files changed, 142 insertions(+), 220 deletions(-) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 0f1a36d663..d191ba8f0c 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -81,6 +81,9 @@ #define STATUS_EFFECT_BREASTS_ENLARGEMENT /datum/status_effect/chem/breast_enlarger //Applied slowdown due to the ominous bulk. #define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above. + +#define STATUS_EFFECT_NO_COMBAT_MODE /datum/status_effect/no_combat_mode/ //Wont allow combat mode and will disable it +#define STATUS_EFFECT_MESMERIZE /datum/status_effect/no_combat_mode/mesmerize //Just reskinned no_combat_mode ///////////// // NEUTRAL // ///////////// diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 84ed012b82..7a5d32d48c 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -80,7 +80,31 @@ desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are." icon_state = "asleep" -//TASER +/datum/status_effect/no_combat_mode/ + id = "no_combat_mode" + blocks_combatmode = TRUE + alert_type = null + status_type = STATUS_EFFECT_REPLACE + +/datum/status_effect/no_combat_mode/on_creation(mob/living/new_owner, set_duration) + if(isnum(set_duration)) + duration = set_duration + . = ..() + if(iscarbon(owner)) + var/mob/living/carbon/C = owner + if(C.combatmode) + C.toggle_combat_mode(TRUE) + +/datum/status_effect/no_combat_mode/mesmerize + id = "Mesmerize" + alert_type = /obj/screen/alert/status_effect/mesmerized + +/obj/screen/alert/status_effect/mesmerized + name = "Mesmerized" + desc = "You cant tear your sight from who is in front of you...Their gaze is simply too enthralling.." + icon = 'icons/mob/actions/bloodsucker.dmi' + icon_state = "power_mez" + /datum/status_effect/electrode id = "tased" blocks_combatmode = TRUE @@ -666,4 +690,4 @@ datum/status_effect/pacify if(LAZYLEN(targets) && I) to_chat(owner, "Your arm spasms!") owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK) - owner.throw_item(pick(targets)) \ No newline at end of file + owner.throw_item(pick(targets)) diff --git a/code/game/gamemodes/bloodsucker/bloodsucker.dm b/code/game/gamemodes/bloodsucker/bloodsucker.dm index db92248347..c188036786 100644 --- a/code/game/gamemodes/bloodsucker/bloodsucker.dm +++ b/code/game/gamemodes/bloodsucker/bloodsucker.dm @@ -2,7 +2,7 @@ /datum/game_mode var/list/datum/mind/bloodsuckers = list() // List of minds belonging to this game mode. var/list/datum/mind/vassals = list() // List of minds that have been turned into Vassals. - var/list/datum/mind/vamphunters = list() // List of minds hunting vampires. + //var/list/datum/mind/vamphunters = list() // List of minds hunting vampires. Disabled at the moment var/obj/effect/sunlight/bloodsucker_sunlight // Sunlight Timer. Created on first Bloodsucker assign. Destroyed on last removed Bloodsucker. // LISTS // @@ -18,8 +18,8 @@ false_report_weight = 1 restricted_jobs = list("AI","Cyborg") protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") - required_players = 0 - required_enemies = 1 + required_players = 10 + required_enemies = 2 recommended_enemies = 4 reroll_friendly = 1 enemy_minimum_age = 7 @@ -57,8 +57,8 @@ log_game("[bloodsucker.key] (ckey) has been selected as a Bloodsucker.") antag_candidates.Remove(bloodsucker) // Apparently you can also write antag_candidates -= bloodsucker - // FULPSTATION: Assign Hunters (as many as monsters, plus one) - assign_monster_hunters(bloodsuckers.len, TRUE, bloodsuckers) // FULP + // Assign Hunters (as many as monsters, plus one) + //assign_monster_hunters(bloodsuckers.len, TRUE, bloodsuckers) // Disabled for now // Do we have enough vamps to continue? return bloodsuckers.len >= required_enemies diff --git a/code/game/gamemodes/bloodsucker/hunter.dm b/code/game/gamemodes/bloodsucker/hunter.dm index 49b97b0b21..cec990e9c3 100644 --- a/code/game/gamemodes/bloodsucker/hunter.dm +++ b/code/game/gamemodes/bloodsucker/hunter.dm @@ -1,6 +1,6 @@ - +/* // Called from game mode pre_setup() /datum/game_mode/proc/assign_monster_hunters(monster_count = 4, guaranteed_hunters = FALSE, list/datum/mind/exclude_from_hunter) @@ -47,3 +47,4 @@ A.bad_dude = amEvil hunter.add_antag_datum(A) amEvil = FALSE // Every other hunter is just a boring greytider +*/ diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index b75b2184cd..a56bf8da43 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -81,7 +81,7 @@ ///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things /datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report. - finalize_monster_hunters() + //finalize_monster_hunters() Disabled for now if(!report) report = !CONFIG_GET(flag/no_intercept_report) addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index c10fb0fa2c..56f1a3f9f0 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -228,7 +228,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ /obj/item/stack/sheet/mineral/wood name = "wooden plank" - desc = "One can only guess that this is a bunch of wood." + desc = "One can only guess that this is a bunch of wood. You might be able to make a stake with this if you use something sharp on it" singular_name = "wood plank" icon_state = "sheet-wood" item_state = "sheet-wood" @@ -240,6 +240,35 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ novariants = TRUE grind_results = list("carbon" = 20) + +/obj/item/stack/sheet/mineral/wood/attackby(obj/item/W, mob/user, params) // NOTE: sheet_types.dm is where the WOOD stack lives. Maybe move this over there. + // Taken from /obj/item/stack/rods/attackby in [rods.dm] + if(W.get_sharpness()) + user.visible_message("[user] begins whittling [src] into a pointy object.", \ + "You begin whittling [src] into a sharp point at one end.", \ + "You hear wood carving.") + // 8 Second Timer + if(!do_mob(user, src, 80)) + return + // Make Stake + var/obj/item/stake/basic/new_item = new(usr.loc) + user.visible_message("[user] finishes carving a stake out of [src].", \ + "You finish carving a stake out of [src].") + // Prepare to Put in Hands (if holding wood) + var/obj/item/stack/sheet/mineral/wood/N = src + var/replace = (user.get_inactive_held_item() == N) + // Use Wood + N.use(1) + // If stack depleted, put item in that hand (if it had one) + if (!N && replace) + user.put_in_hands(new_item) + if(istype(W, merge_type)) + var/obj/item/stack/S = W + if(merge(S)) + to_chat(user, "Your [S.name] stack now contains [S.get_amount()] [S.singular_name]\s.") + else + . = ..() + /obj/item/stack/sheet/mineral/wood/Initialize(mapload, new_amount, merge = TRUE) recipes = GLOB.wood_recipes return ..() @@ -695,5 +724,3 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra merge_type = /obj/item/stack/sheet/cotton/durathread pull_effort = 70 loom_result = /obj/item/stack/sheet/durathread - - diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm b/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm index 0fa681e435..5e38a29346 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm @@ -30,14 +30,17 @@ // Do NOT count the damage on prosthetics for this. /mob/living/proc/getBruteLoss_nonProsthetic() return getBruteLoss() + /mob/living/proc/getFireLoss_nonProsthetic() return getFireLoss() + /mob/living/carbon/getBruteLoss_nonProsthetic() var/amount = 0 for(var/obj/item/bodypart/BP in bodyparts) if (BP.status < 2) amount += BP.brute_dam return amount + /mob/living/carbon/getFireLoss_nonProsthetic() var/amount = 0 for(var/obj/item/bodypart/BP in bodyparts) @@ -45,6 +48,7 @@ amount += BP.burn_dam return amount +/mob/living/carbon // EXAMINING /mob/living/carbon/human/proc/ReturnVampExamine(var/mob/viewer) if (!mind || !viewer.mind) diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm index 9eaddad5b5..e2bf217ab9 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm @@ -10,53 +10,27 @@ // // Show as dead when... - - - - - - -/datum/antagonist/bloodsucker/proc/LifeTick() // Should probably run from life.dm, same as handle_changeling +/datum/antagonist/bloodsucker/proc/LifeTick()// Should probably run from life.dm, same as handle_changeling, but will be an utter pain to move set waitfor = FALSE // Don't make on_gain() wait for this function to finish. This lets this code run on the side. - var/notice_healing = FALSE - while (owner && !AmFinalDeath()) // owner.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) == src - - // Deduct Blood - if (owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_DEATHCOMA)) + while(owner && !AmFinalDeath()) // owner.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) == src + if(owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_DEATHCOMA)) // Deduct Blood AddBloodVolume(-0.09) // -.15 (before tick went from 10 to 30, but we also charge more for faking life now) - - // Heal - if (HandleHealing(1)) - if (notice_healing == FALSE && owner.current.blood_volume > 0) + if(HandleHealing(1)) // Heal + if(notice_healing == FALSE && owner.current.blood_volume > 0) to_chat(owner, "The power of your blood begins knitting your wounds...") notice_healing = TRUE - else if (notice_healing == TRUE) - notice_healing = FALSE - - // Apply Low Blood Effects - HandleStarving() - - // Death - HandleDeath() - - // Standard Update - update_hud() - - // Daytime Sleep in Coffin + else if(notice_healing == TRUE) + notice_healing = FALSE // Apply Low Blood Effects + HandleStarving() // Death + HandleDeath() // Standard Update + update_hud()// Daytime Sleep in Coffin if (SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker")) if(istype(owner.current.loc, /obj/structure/closet/crate/coffin)) Torpor_Begin() - - // Wait before next pass - sleep(10)//sleep(30) - - // Free my Vassals! (if I haven't yet) - FreeAllVassals() - - - - + // Wait before next pass + sleep(10) + FreeAllVassals() // Free my Vassals! (if I haven't yet) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -64,18 +38,14 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /datum/antagonist/bloodsucker/proc/AddBloodVolume(value) owner.current.blood_volume = CLAMP(owner.current.blood_volume + value, 0, maxBloodVolume) update_hud() - /datum/antagonist/bloodsucker/proc/HandleFeeding(mob/living/carbon/target, mult=1) // mult: SILENT feed is 1/3 the amount - var/blood_taken = min(feedAmount, target.blood_volume) * mult // Starts at 15 (now 8 since we doubled the Feed time) target.blood_volume -= blood_taken - // Simple Animals lose a LOT of blood, and take damage. This is to keep cats, cows, and so forth from giving you insane amounts of blood. if (!ishuman(target)) target.blood_volume -= (blood_taken / max(target.mob_size, 0.1)) * 3.5 // max() to prevent divide-by-zero @@ -83,33 +53,26 @@ if (target.blood_volume <= 0) target.blood_volume = 0 target.death(0) - /////////// // Shift Body Temp (toward Target's temp, by volume taken) owner.current.bodytemperature = ((owner.current.blood_volume * owner.current.bodytemperature) + (blood_taken * target.bodytemperature)) / (owner.current.blood_volume + blood_taken) // our volume * temp, + their volume * temp, / total volume /////////// - // Reduce Value Quantity if (target.stat == DEAD) // Penalty for Dead Blood blood_taken /= 3 if (!ishuman(target)) // Penalty for Non-Human Blood blood_taken /= 2 //if (!iscarbon(target)) // Penalty for Animals (they're junk food) - - // Apply to Volume AddBloodVolume(blood_taken) - // Reagents (NOT Blood!) if(target.reagents && target.reagents.total_volume) target.reagents.reaction(owner.current, INGEST, 1) // Run Reaction: what happens when what they have mixes with what I have? target.reagents.trans_to(owner.current, 1) // Run transfer of 1 unit of reagent from them to me. - // Blood Gulp Sound owner.current.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, 1) // Play THIS sound for user only. The "null" is where turf would go if a location was needed. Null puts it right in their head. - /datum/mood_event/drankblood description = "I have fed greedly from that which nourishes me.\n" mood_change = 10 @@ -166,86 +129,60 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// /datum/antagonist/bloodsucker/proc/HandleHealing(mult = 1) - // NOTE: Mult of 0 is just a TEST to see if we are injured and need to go into Torpor! - // It is called from your coffin on close (by you only) - - if (poweron_masquerade == TRUE || owner.current.AmStaked()) + //It is called from your coffin on close (by you only) + if(poweron_masquerade == TRUE || owner.current.AmStaked()) return FALSE - - owner.current.adjustStaminaLoss(-2 * (regenRate * 4) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more. + owner.current.adjustStaminaLoss(-3 * (regenRate * 4) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more. owner.current.adjustCloneLoss(-1 * (regenRate * 4) * mult, 0) owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (regenRate * 4) * mult) //adjustBrainLoss(-1 * (regenRate * 4) * mult, 0) - // No Bleeding - if (ishuman(owner.current)) + if (ishuman(owner.current)) //NOTE Current bleeding is horrible, not to count the amount of blood ballistics delete. var/mob/living/carbon/human/H = owner.current H.bleed_rate = 0 - - // Damage Heal: Do I have damage to ANY bodypart? - if (iscarbon(owner.current)) + if (iscarbon(owner.current)) // Damage Heal: Do I have damage to ANY bodypart? var/mob/living/carbon/C = owner.current var/costMult = 1 // Coffin makes it cheaper - - // BURN: Heal in Coffin while Fakedeath, or when damage above maxhealth (you can never fully heal fire) - var/fireheal = 0 + var/fireheal = 0 // BURN: Heal in Coffin while Fakedeath, or when damage above maxhealth (you can never fully heal fire) var/amInCoffinWhileTorpor = istype(C.loc, /obj/structure/closet/crate/coffin) && (mult == 0 || HAS_TRAIT(C, TRAIT_DEATHCOMA)) // Check for mult 0 OR death coma. (mult 0 means we're testing from coffin) if(amInCoffinWhileTorpor) mult *= 5 // Increase multiplier if we're sleeping in a coffin. fireheal = min(C.getFireLoss_nonProsthetic(), regenRate) // NOTE: Burn damage ONLY heals in torpor. costMult = 0.25 - // Extinguish Fire - C.ExtinguishMob() + C.ExtinguishMob() // Extinguish Fire else - // No Blood? Lower Mult - if (owner.current.blood_volume <= 0) + if (owner.current.blood_volume <= 0) // No Blood? Lower Mult mult = 0.25 // Crit from burn? Lower damage to maximum allowed. //if (C.getFireLoss() > owner.current.getMaxHealth()) // fireheal = regenRate / 2 // BRUTE: Always Heal var/bruteheal = min(C.getBruteLoss_nonProsthetic(), regenRate) - + var/toxinheal = min(C.getToxLoss(), regenRate) // Heal if Damaged - if (bruteheal + fireheal > 0) - // Just a check? Don't heal/spend, and return. + if (bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return. if (mult == 0) return TRUE // We have damage. Let's heal (one time) C.adjustBruteLoss(-bruteheal * mult, forced=TRUE)// Heal BRUTE / BURN in random portions throughout the body. C.adjustFireLoss(-fireheal * mult, forced=TRUE) + C.adjustToxLoss(-toxinheal * mult * 2, forced=TRUE) //Toxin healing because vamps arent immune //C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above. - - // Pay Cost AddBloodVolume((bruteheal * -0.5 + fireheal * -1) / mult * costMult) // Costs blood to heal - - // Healed! Done for this tick. - return TRUE - - // Limbs? (And I have no other healing) - if (amInCoffinWhileTorpor) - - // Heal Missing - var/list/missing = owner.current.get_missing_limbs() - if (missing.len) - // Cycle through ALL limbs and regen them! - for (var/targetLimbZone in missing) - // 1) Find ONE Limb and regenerate it. - //var/targetLimbZone = pick(missing) + return TRUE // Healed! Done for this tick. + if (amInCoffinWhileTorpor) // Limbs? (And I have no other healing) + var/list/missing = owner.current.get_missing_limbs() // Heal Missing + if (missing.len) // Cycle through ALL limbs and regen them! + for (var/targetLimbZone in missing) // 1) Find ONE Limb and regenerate it. owner.current.regenerate_limb(targetLimbZone, 0) // regenerate_limbs() <--- If you want to EXCLUDE certain parts, do it like this ----> regenerate_limbs(0, list("head")) - // 2) Limb returns Damaged - var/obj/item/bodypart/L = owner.current.get_bodypart( targetLimbZone ) + var/obj/item/bodypart/L = owner.current.get_bodypart( targetLimbZone ) // 2) Limb returns Damaged AddBloodVolume(20 * costMult) // Costs blood to heal L.brute_dam = 60 to_chat(owner.current, "Your flesh knits as it regrows [L]!") playsound(owner.current, 'sound/magic/demon_consume.ogg', 50, 1) - - // DONE! After regenerating ANY number of limbs, we stop here. return TRUE - /*else // REMOVED: For now, let's just leave prosthetics on. Maybe you WANT to be a robovamp. // Remove Prosthetic/False Limb for(var/obj/item/bodypart/BP in C.bodyparts) @@ -256,38 +193,26 @@ return TRUE // NOTE: Limbs have a "status", like their hosts "stat". 2 is dead (aka Prosthetic). 1 seems to be idle/alive. */ - - // Cure Final Disabilities - CureDisabilities() - - // Remove Embedded! - C.remove_all_embedded_objects() - // Heal Organs (will respawn original eyes etc. but we replace right away, next) - owner.current.regenerate_organs() - // Eyes/Heart + CureDisabilities() // Cure Final Disabilities + C.remove_all_embedded_objects() // Remove Embedded! + owner.current.regenerate_organs() // Heal Organs (will respawn original eyes etc. but we replace right away, next) CheckVampOrgans() // Heart, Eyes - return FALSE - /datum/antagonist/bloodsucker/proc/CureDisabilities() var/mob/living/carbon/C = owner.current - C.cure_blind(list(EYE_DAMAGE))//() C.cure_nearsighted(EYE_DAMAGE) C.set_blindness(0) // Added 9/2/19 C.set_blurriness(0) // Added 9/2/19 C.update_tint() // Added 9/2/19 C.update_sight() // Added 9/2/19 - for(var/O in C.internal_organs) //owner.current.adjust_eye_damage(-100) // This was removed by TG var/obj/item/organ/organ = O organ.setOrganDamage(0) - owner.current.cure_husk() - -// I am hungry! +// I am thirsty for blud! /datum/antagonist/bloodsucker/proc/HandleStarving() // High: Faster Healing @@ -311,7 +236,7 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /datum/antagonist/bloodsucker/proc/HandleDeath() - // FINAL DEATH + // FINAL DEATH // Fire Damage? (above double health) if (owner.current.getFireLoss_nonProsthetic() >= owner.current.getMaxHealth() * 2) FinalDeath() @@ -328,16 +253,15 @@ if (!owner.current.HaveBloodsuckerBodyparts()) FinalDeath() return - // Disable Powers: Masquerade * NOTE * This should happen as a FLAW! //if (stat >= UNCONSCIOUS) // for (var/datum/action/bloodsucker/masquerade/P in powers) // P.Deactivate() - // TEMP DEATH var/total_brute = owner.current.getBruteLoss_nonProsthetic() var/total_burn = owner.current.getFireLoss_nonProsthetic() - var/total_damage = total_brute + total_burn + var/total_toxloss = owner.current.getToxLoss() //This is neater than just putting it in total_damage + var/total_damage = total_brute + total_burn + total_toxloss // Died? Convert to Torpor (fake death) if (owner.current.stat >= DEAD) Torpor_Begin() @@ -345,8 +269,8 @@ if (poweron_masquerade == TRUE) to_chat(owner, "Your wounds will not heal until you disable the Masquerade power.") // End Torpor: - else // No damage, OR brute healed and NOT in coffin (since you cannot heal burn) - if (total_damage <= 0 || total_brute <= 0 && !istype(owner.current.loc, /obj/structure/closet/crate/coffin)) + else // No damage, OR toxin healed AND brute healed and NOT in coffin (since you cannot heal burn) + if (total_damage <= 0 || total_toxloss <= 0 && total_brute <= 0 && !istype(owner.current.loc, /obj/structure/closet/crate/coffin)) // Not Daytime, Not in Torpor if (!SSticker.mode.is_daylight() && HAS_TRAIT_FROM(owner.current, TRAIT_DEATHCOMA, "bloodsucker")) Torpor_End() @@ -377,8 +301,8 @@ owner.current.stat = SOFT_CRIT owner.current.cure_fakedeath("bloodsucker") // Come after SOFT_CRIT or else it fails REMOVE_TRAIT(owner.current, TRAIT_NODEATH, "bloodsucker") - REMOVE_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") // So you can heal in 0 G. otherwise you just...heal forever. - REMOVE_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") // So you can heal in 0 G. otherwise you just...heal forever. + REMOVE_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") + REMOVE_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") to_chat(owner, "You have recovered from Torpor.") @@ -395,20 +319,18 @@ return !current || QDELETED(current) || !isliving(current) || isbrain(current) || !get_turf(current) // NOTE: "isliving()" is not the same as STAT == CONSCIOUS. This is to make sure you're not a BORG (aka silicon) /datum/antagonist/bloodsucker/proc/FinalDeath() - + if(!iscarbon(owner.current)) //Check for non carbons. + owner.current.gib() + return playsound(get_turf(owner.current), 'sound/effects/tendril_destroyed.ogg', 60, 1) owner.current.drop_all_held_items() owner.current.unequip_everything() var/mob/living/carbon/C = owner.current C.remove_all_embedded_objects() - // Make me UN-CLONEABLE owner.current.hellbound = TRUE // This was done during creation, but let's do it again one more time...to make SURE this guy stays dead. - - // Free my Vassals! FreeAllVassals() - // Elders get Dusted if (vamplevel >= 4) // (vamptitle) owner.current.visible_message("[owner.current]'s skin crackles and dries, their skin and bones withering to dust. A hollow cry whips from what is now a sandy pile of remains.", \ diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 8b5c8dff46..e52b63110c 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -200,7 +200,7 @@ var/datum/species/S = H.dna.species // Make Changes S.brutemod *= 0.5 - S.burnmod += 0.2 // <-------------------- Start small, but burn mod increases based on rank! + S.burnmod += 0.1 // <-------------------- Start small, but burn mod increases based on rank! S.coldmod = 0 S.stunmod *= 0.25 S.siemens_coeff *= 0.75 //base electrocution coefficient 1 diff --git a/code/modules/antagonists/bloodsucker/datum_hunter.dm b/code/modules/antagonists/bloodsucker/datum_hunter.dm index 7b07b68b36..2d680d0e09 100644 --- a/code/modules/antagonists/bloodsucker/datum_hunter.dm +++ b/code/modules/antagonists/bloodsucker/datum_hunter.dm @@ -1,3 +1,4 @@ +/* #define HUNTER_SCAN_MIN_DISTANCE 8 #define HUNTER_SCAN_MAX_DISTANCE 35 #define HUNTER_SCAN_PING_TIME 20 //5s update time. @@ -103,7 +104,7 @@ // TAKEN FROM: /datum/action/changeling/pheromone_receptors // pheromone_receptors.dm for a version of tracking that Changelings have! -/* + /datum/status_effect/agent_pinpointer/hunter_edition alert_type = /obj/screen/alert/status_effect/agent_pinpointer/hunter_edition minimum_range = HUNTER_SCAN_MIN_DISTANCE @@ -159,7 +160,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - +/* /datum/action/bloodsucker/trackvamp/ @@ -169,35 +170,25 @@ background_icon_state = "vamp_power_off" //And this is the state for the background icon icon_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the ACTION icon button_icon_state = "power_hunter" //And this is the state for the action icon - - // Action-Related - amToggle = FALSE - cooldown = 200 // 10 ticks, 1 second. + amToggle = FALSE // Action-Related + cooldown = 300 // 10 ticks, 1 second. bloodcost = 0 - - /datum/action/bloodsucker/trackvamp/ActivatePower() var/mob/living/user = owner - to_chat(user, "You look around, scanning your environment and discerning signs of any filthy, wretched affronts to the natural order.") if (!do_mob(user,owner,80)) return - // Add Power // REMOVED //user.apply_status_effect(/datum/status_effect/agent_pinpointer/hunter_edition) // We don't track direction anymore! - // Return text indicating direction display_proximity() - // NOTE: DON'T DEACTIVATE! //DeactivatePower() - - /datum/action/bloodsucker/trackvamp/proc/display_proximity() // Pick target var/turf/my_loc = get_turf(owner) @@ -209,7 +200,7 @@ var/list/datum/mind/monsters = list() monsters += SSticker.mode.bloodsuckers monsters += SSticker.mode.devils - monsters += SSticker.mode.cult + //monsters += SSticker.mode.cult monsters += SSticker.mode.wizards monsters += SSticker.mode.apprentices monsters += SSticker.mode.servants_of_ratvar @@ -301,3 +292,4 @@ var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh) */ +*/ diff --git a/code/modules/antagonists/bloodsucker/items/bloodsucker_stake.dm b/code/modules/antagonists/bloodsucker/items/bloodsucker_stake.dm index a47cc0ce68..822175aa25 100644 --- a/code/modules/antagonists/bloodsucker/items/bloodsucker_stake.dm +++ b/code/modules/antagonists/bloodsucker/items/bloodsucker_stake.dm @@ -33,7 +33,6 @@ attack_verb = list("staked") slot_flags = ITEM_SLOT_BELT w_class = WEIGHT_CLASS_SMALL - hitsound = 'sound/weapons/bladeslice.ogg' force = 6 throwforce = 10 @@ -43,19 +42,14 @@ obj_integrity = 30 max_integrity = 30 //embedded_fall_pain_multiplier - var/staketime = 120 // Time it takes to embed the stake into someone's chest. - - - /obj/item/stake/basic name = "wooden stake" // This exists so Hardened/Silver Stake can't have a welding torch used on them. - /obj/item/stake/basic/attackby(obj/item/W, mob/user, params) - if (istype(W, /obj/item/weldingtool)) + if(istype(W, /obj/item/weldingtool)) //if (amWelded) // to_chat(user, "This stake has already been treated with fire.") // return @@ -67,27 +61,24 @@ "You scorch the pointy end of [src] with the welding tool.", \ "You hear welding.") // 8 Second Timer - if (!do_mob(user, src, 80)) + if(!do_mob(user, src, 80)) return - // Create the Stake qdel(src) var/obj/item/stake/hardened/new_item = new(usr.loc) user.put_in_hands(new_item) - else return ..() - - /obj/item/stake/afterattack(atom/target, mob/user, proximity) //to_chat(world, "DEBUG: Staking ") // Invalid Target, or not targetting chest with HARM intent? - if (!iscarbon(target) || check_zone(user.zone_selected) != "chest" || user.a_intent != INTENT_HARM) + if(!iscarbon(target) || check_zone(user.zone_selected) != "chest" || user.a_intent != INTENT_HARM) return var/mob/living/carbon/C = target // Needs to be Down/Slipped in some way to Stake. - if (!C.can_be_staked()) + if(!C.can_be_staked() || target == user) + to_chat(user, "You cant stake [target] when they are moving moving about! They have to be laying down!") return // Oops! Can't. if(HAS_TRAIT(C, TRAIT_PIERCEIMMUNE)) @@ -96,68 +87,35 @@ // Make Attempt... to_chat(user, "You put all your weight into embedding the stake into [target]'s chest...") playsound(user, 'sound/magic/Demon_consume.ogg', 50, 1) - if (!do_mob(user, C, staketime, 0, 1, extra_checks=CALLBACK(C, /mob/living/carbon/proc/can_be_staked))) // user / target / time / uninterruptable / show progress bar / extra checks + if(!do_mob(user, C, staketime, 0, 1, extra_checks=CALLBACK(C, /mob/living/carbon/proc/can_be_staked))) // user / target / time / uninterruptable / show progress bar / extra checks return - // Drop & Embed Stake user.visible_message("[user.name] drives the [src] into [target]'s chest!", \ "You drive the [src] into [target]'s chest!") playsound(get_turf(target), 'sound/effects/splat.ogg', 40, 1) - user.dropItemToGround(src, TRUE) //user.drop_item() // "drop item" doesn't seem to exist anymore. New proc is user.dropItemToGround() but it doesn't seem like it's needed now? - var/obj/item/bodypart/B = C.get_bodypart("chest") // This was all taken from hitby() in human_defense.dm B.embedded_objects |= src add_mob_blood(target)//Place blood on the stake loc = C // Put INSIDE the character B.receive_damage(w_class * embedding.embedded_impact_pain_multiplier) - - if (C.mind) + if(C.mind) var/datum/antagonist/bloodsucker/bloodsucker = C.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - if (bloodsucker) + if(bloodsucker) // If DEAD or TORPID...kill vamp! - if (C.StakeCanKillMe()) // NOTE: This is the ONLY time a staked Torpid vamp dies. + if(C.StakeCanKillMe()) // NOTE: This is the ONLY time a staked Torpid vamp dies. bloodsucker.FinalDeath() return else to_chat(target, "You have been staked! Your powers are useless, your death forever, while it remains in place.") to_chat(user, "You missed [C.p_their(TRUE)]'s heart! It would be easier if [C.p_they(TRUE)] weren't struggling so much.") - - // Can this target be staked? If someone stands up before this is complete, it fails. Best used on someone stationary. /mob/living/carbon/proc/can_be_staked() //return resting || IsKnockdown() || IsUnconscious() || (stat && (stat != SOFT_CRIT || pulledby)) || (has_trait(TRAIT_FAKEDEATH)) || resting || IsStun() || IsFrozen() || (pulledby && pulledby.grab_state >= GRAB_NECK) - return !(src.canmove) + return (src.resting) // ABOVE: Taken from update_mobility() in living.dm - - - - -/obj/item/stack/sheet/mineral/wood/attackby(obj/item/W, mob/user, params) // NOTE: sheet_types.dm is where the WOOD stack lives. Maybe move this over there. - // Taken from /obj/item/stack/rods/attackby in [rods.dm] - if (W.get_sharpness()) - user.visible_message("[user] begins whittling [src] into a pointy object.", \ - "You begin whittling [src] into a sharp point at one end.", \ - "You hear wood carving.") - // 8 Second Timer - if (!do_mob(user, src, 80)) - return - // Make Stake - var/obj/item/stake/basic/new_item = new(usr.loc) - user.visible_message("[user] finishes carving a stake out of [src].", \ - "You finish carving a stake out of [src].") - // Prepare to Put in Hands (if holding wood) - var/obj/item/stack/sheet/mineral/wood/thisStack = src - var/replace = (user.get_inactive_held_item()==thisStack) - // Use Wood - thisStack.use(1) - // If stack depleted, put item in that hand (if it had one) - if (!thisStack && replace) - user.put_in_hands(new_item) - - /obj/item/stake/hardened // Created by welding and acid-treating a simple stake. name = "hardened stake" diff --git a/code/modules/antagonists/bloodsucker/powers/bs_fortitude.dm b/code/modules/antagonists/bloodsucker/powers/bs_fortitude.dm index eee6942414..826155a445 100644 --- a/code/modules/antagonists/bloodsucker/powers/bs_fortitude.dm +++ b/code/modules/antagonists/bloodsucker/powers/bs_fortitude.dm @@ -7,7 +7,7 @@ desc = "Withstand egregious physical wounds and walk away from attacks that would stun, pierce, and dismember lesser beings. You cannot run while active." button_icon_state = "power_fortitude" bloodcost = 5 - cooldown = 40 + cooldown = 80 bloodsucker_can_buy = TRUE amToggle = TRUE warn_constant_cost = TRUE @@ -15,12 +15,9 @@ var/this_resist // So we can raise and lower your brute resist based on what your level_current WAS. /datum/action/bloodsucker/fortitude/ActivatePower() - var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) var/mob/living/user = owner - to_chat(user, "Your flesh, skin, and muscles become as steel.") - // Traits & Effects ADD_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude") ADD_TRAIT(user, TRAIT_NODISMEMBER, "fortitude") @@ -31,27 +28,21 @@ this_resist = max(0.3, 0.7 - level_current * 0.1) H.physiology.brute_mod *= this_resist//0.5 H.physiology.burn_mod *= this_resist//0.5 - // Stop Running (Taken from /datum/quirk/nyctophobia in negative.dm) var/was_running = (user.m_intent == MOVE_INTENT_RUN) if (was_running) user.toggle_move_intent() - while(bloodsuckerdatum && ContinueActive(user) || user.m_intent == MOVE_INTENT_RUN) - // Pay Blood Toll (if awake) if (user.stat == CONSCIOUS) bloodsuckerdatum.AddBloodVolume(-0.5) // Used to be 0.3 blood per 2 seconds, but we're making it more expensive to keep on. - sleep(20) // Check every few ticks that we haven't disabled this power - // Return to Running (if you were before) if (was_running && user.m_intent != MOVE_INTENT_RUN) user.toggle_move_intent() /datum/action/bloodsucker/fortitude/DeactivatePower(mob/living/user = owner, mob/living/target) ..() - // Restore Traits & Effects REMOVE_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude") REMOVE_TRAIT(user, TRAIT_NODISMEMBER, "fortitude") diff --git a/code/modules/antagonists/bloodsucker/powers/bs_mesmerize.dm b/code/modules/antagonists/bloodsucker/powers/bs_mesmerize.dm index bd185958d3..789f5e860b 100644 --- a/code/modules/antagonists/bloodsucker/powers/bs_mesmerize.dm +++ b/code/modules/antagonists/bloodsucker/powers/bs_mesmerize.dm @@ -5,14 +5,13 @@ // FOLLOW: Target follows you, spouting random phrases from their history (or maybe Poly's or NPC's vocab?) // ATTACK: Target finds a nearby non-Bloodsucker victim to attack. - /datum/action/bloodsucker/targeted/mesmerize name = "Mesmerize" desc = "Dominate the mind of a mortal who can see your eyes." button_icon_state = "power_mez" bloodcost = 30 cooldown = 200 - target_range = 5 + target_range = 3 power_activates_immediately = FALSE message_Trigger = "Whom will you subvert to your will?" must_be_capacitated = TRUE @@ -81,24 +80,23 @@ if (display_error) to_chat(owner, "Your victim must be facing you to see into your eyes.") return FALSE - return TRUE - /datum/action/bloodsucker/targeted/mesmerize/FireTargetedPower(atom/A) // set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done. - var/mob/living/carbon/target = A var/mob/living/user = owner if(istype(target)) target.Stun(40) //Utterly useless without this, its okay since there are so many checks to go through - target.silent += 40 //Shhhh little lamb + target.silent += 45 //Shhhh little lamb + target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 45) //So you cant rotate with combat mode, plus fancy status alert if(do_mob(user, target, 40, 0, TRUE, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target))) PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN! - ADD_TRAIT(target, TRAIT_MUTE, "bloodsucker_mesmerize") + target.silent += 100 + level_current * 15 var/power_time = 90 + level_current * 15 + target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 100 + level_current * 15) to_chat(user, "[target] is fixed in place by your hypnotic gaze.") target.Stun(power_time) //target.silent += power_time / 10 // Silent isn't based on ticks. @@ -110,7 +108,6 @@ // They Woke Up! (Notice if within view) if(istype(user) && target.stat == CONSCIOUS && (target in view(10, get_turf(user))) ) to_chat(user, "[target] has snapped out of their trance.") - REMOVE_TRAIT(target, TRAIT_MUTE, "bloodsucker_mesmerize") /datum/action/bloodsucker/targeted/mesmerize/ContinueActive(mob/living/user, mob/living/target) diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index 82c1435344..81f8fcbef1 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -4,4 +4,7 @@ var/datum/antagonist/rev/rev = mind.has_antag_datum(/datum/antagonist/rev) if(rev) rev.remove_revolutionary(TRUE) + var/datum/antagonist/bloodsucker/V = mind.has_antag_datum(/datum/antagonist/bloodsucker) + if(V) + mind.remove_antag_datum(V) ..()