diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index d25f8779c0..058fd864bd 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -45,7 +45,7 @@ // Bloodsucker related antag datums #define ANTAG_DATUM_BLOODSUCKER /datum/antagonist/bloodsucker #define ANTAG_DATUM_VASSAL /datum/antagonist/vassal -#define ANTAG_DATUM_HUNTER /datum/antagonist/vamphunter +//#define ANTAG_DATUM_HUNTER /datum/antagonist/vamphunter Disabled for now // BLOODSUCKER #define BLOODSUCKER_LEVEL_TO_EMBRACE 3 diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index bc2709bdda..d5e3f828b8 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -36,7 +36,7 @@ #define ROLE_INTERNAL_AFFAIRS "internal affairs agent" #define ROLE_GANG "gangster" #define ROLE_BLOODSUCKER "bloodsucker" -#define ROLE_MONSTERHUNTER "monster hunter" +//#define ROLE_MONSTERHUNTER "monster hunter" Disabled for now //Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. //The gamemode specific ones are just so the gamemodes can query whether a player is old enough @@ -63,8 +63,8 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs, ROLE_SENTIENCE, ROLE_GANG = /datum/game_mode/gang, - ROLE_BLOODSUCKER = /datum/game_mode/bloodsucker, - ROLE_MONSTERHUNTER + ROLE_BLOODSUCKER = /datum/game_mode/bloodsucker + //ROLE_MONSTERHUNTER Disabled for now )) //Job defines for what happens when you fail to qualify for any job during job selection diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index d191ba8f0c..fdbbc3fbf6 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -46,7 +46,7 @@ #define STATUS_EFFECT_SLEEPING /datum/status_effect/incapacitating/sleeping //the affected is asleep -#define STATUS_EFFECT_TASED /datum/status_effect/electrode //the affected has been tased, preventing fine muscle control +#define STATUS_EFFECT_TASED /datum/status_effect/no_combat_mode/electrode/ //the affected has been tased, preventing fine muscle control #define STATUS_EFFECT_PACIFY /datum/status_effect/pacify //the affected is pacified, preventing direct hostile actions @@ -82,7 +82,7 @@ #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_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/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index f4ca3a8ebd..833deb2378 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -176,3 +176,8 @@ /datum/mood_event/revenant_blight/add_effects() description = "Just give up, [pick("no one will miss you", "there is nothing you can do to help", "even a clown would be more useful than you", "does it even matter in the end?")]...\n" + +/datum/mood_event/vampcandle + description = "Something is making your mind feel... loose...\n" + mood_change = -20 + timeout = 1 MINUTES diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 7a5d32d48c..a9fc3881cb 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -105,14 +105,11 @@ icon = 'icons/mob/actions/bloodsucker.dmi' icon_state = "power_mez" -/datum/status_effect/electrode +/datum/status_effect/no_combat_mode/electrode id = "tased" - blocks_combatmode = TRUE - status_type = STATUS_EFFECT_REPLACE - alert_type = null -/datum/status_effect/electrode/on_creation(mob/living/new_owner, set_duration) - if(isnum(set_duration)) +/datum/status_effect/no_combat_mode/electrode/on_creation(mob/living/new_owner, set_duration) + if(isnum(set_duration)) //TODO, figure out how to grab from subtype duration = set_duration . = ..() if(iscarbon(owner)) @@ -121,17 +118,17 @@ C.toggle_combat_mode(TRUE) C.add_movespeed_modifier(MOVESPEED_ID_TASED_STATUS, TRUE, override = TRUE, multiplicative_slowdown = 8) -/datum/status_effect/electrode/on_remove() +/datum/status_effect/no_combat_mode/electrode/on_remove() if(iscarbon(owner)) var/mob/living/carbon/C = owner C.remove_movespeed_modifier(MOVESPEED_ID_TASED_STATUS) . = ..() -/datum/status_effect/electrode/tick() +/datum/status_effect/no_combat_mode/electrode/tick() if(owner) owner.adjustStaminaLoss(5) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing. -/datum/status_effect/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y +/datum/status_effect/no_combat_mode/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y return 2 //OTHER DEBUFFS diff --git a/code/game/gamemodes/bloodsucker/bloodsucker.dm b/code/game/gamemodes/bloodsucker/bloodsucker.dm index c188036786..fb6dd4604a 100644 --- a/code/game/gamemodes/bloodsucker/bloodsucker.dm +++ b/code/game/gamemodes/bloodsucker/bloodsucker.dm @@ -18,7 +18,7 @@ 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 = 10 + required_players = 20 required_enemies = 2 recommended_enemies = 4 reroll_friendly = 1 @@ -29,7 +29,7 @@ Bloodsuckers: The crew are cattle, while you are both shepherd and slaughterhouse.\n\ Crew: Put an end to the undead infestation before the station is overcome!" -/datum/game_mode/traitor/bros/generate_report() +/datum/game_mode/bloodsucker/generate_report() return "Reports indicate that some of your crew may have toppled statues in the past week, angering the gods and becoming cursed with undeath and a desire for blood. Watch out for crewmembers that seem to shun the light or are found pale and delirious." // Seems to be run by game ONCE, and finds all potential players to be antag. diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 56f1a3f9f0..02fb98e585 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -248,10 +248,10 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ "You begin whittling [src] into a sharp point at one end.", \ "You hear wood carving.") // 8 Second Timer - if(!do_mob(user, src, 80)) + if(!do_after(user, 80, TRUE, src)) return // Make Stake - var/obj/item/stake/basic/new_item = new(usr.loc) + var/obj/item/stake/basic/new_item = new(user.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) diff --git a/code/modules/antagonists/bloodsucker/items/bloodsucker_items.dm b/code/modules/antagonists/bloodsucker/items/bloodsucker_items.dm deleted file mode 100644 index 7215573092..0000000000 --- a/code/modules/antagonists/bloodsucker/items/bloodsucker_items.dm +++ /dev/null @@ -1,55 +0,0 @@ - - - -// For blood packs, etc. that need new functions for when they're used. - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// RECIPES: When crafting objects in craft.dm, we now record who made the item. -///atom/movable -// var/mob/crafter // Who made me? (via Craft skill) Used by Bloodsucker crypt furniture to know who gets to use the buildings. - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - -// BLOOD BAGS! Add ability to drank em - - -/obj/item/reagent_containers/blood/attack(mob/M, mob/user, def_zone) - - if(user.a_intent == INTENT_HELP && reagents.total_volume > 0) - if (user != M) - user.visible_message("[user] forces [M] to drink from the [src].", \ - "You put the [src] up to [M]'s mouth.") - if (!do_mob(user, M, 50)) - return - else - if (!do_mob(user, M, 10)) - return - user.visible_message("[user] puts the [src] up to their mouth.", \ - "You take a sip from the [src].") - - // Safety: In case you spam clicked the blood bag on yourself, and it is now empty (below will divide by zero) - if (reagents.total_volume <= 0) - return - - // Taken from drinks.dm // - var/gulp_size = 5 - var/fraction = min(gulp_size / reagents.total_volume, 1) - //checkLiked(fraction, M) // Blood isn't food, sorry. - reagents.reaction(M, INGEST, fraction) - reagents.trans_to(M, gulp_size) - playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1) - - ..() - - diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm index 128398a3b0..36e2d634c6 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm @@ -172,7 +172,7 @@ if(istype(W, cutting_tool)) to_chat(user, "This is a much more complex mechanical structure than you thought. You don't know where to begin cutting [src].") return - else if (anchored && istype(W, /obj/item/wrench)) // Can't unanchor unless owner. + else if(anchored && istype(W, /obj/item/wrench)) // Can't unanchor unless owner. to_chat(user, "The coffin won't come unanchored from the floor.") return diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm index 2a4e2b31c6..d319017ede 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm @@ -233,13 +233,10 @@ //. = ..() // Taken from sacrificial altar in divine.dm //if(.) // return - // Go away. Torturing. if (useLock) return - var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - // CHECK ONE: Am I claiming this? Is it in the right place? if (istype(bloodsuckerdatum) && !owner) if (!bloodsuckerdatum.lair) @@ -253,18 +250,15 @@ density = FALSE anchored = TRUE return //No, you cant move this ever again - // No One Home if (!has_buckled_mobs()) return - // CHECK TWO: Am I a non-bloodsucker? var/mob/living/carbon/C = pick(buckled_mobs) if (!istype(bloodsuckerdatum)) // Try to release this guy user_unbuckle_mob(C, user) return - // Bloodsucker Owner! Let the boy go. if (C.mind) var/datum/antagonist/vassal/vassaldatum = C.mind.has_antag_datum(ANTAG_DATUM_VASSAL) @@ -272,26 +266,19 @@ unbuckle_mob(C) useLock = FALSE // Failsafe return - // Just torture the boy torture_victim(user, C) - /obj/structure/bloodsucker/vassalrack/proc/torture_victim(mob/living/user, mob/living/target) - // Check Bloodmob/living/M, force = FALSE, check_loc = TRUE if (user.blood_volume < convert_cost + 5) to_chat(user, "You don't have enough blood to initiate the Dark Communion with [target].") return - // Prep... useLock = TRUE - - // Step One: Tick Down Conversion from 3 to 0 // Step Two: Break mindshielding/antag (on approve) // Step Three: Blood Ritual - // Conversion Process if (convert_progress > 0) to_chat(user, "You prepare to initiate [target] into your service.") @@ -314,10 +301,8 @@ // Still Need More Persuasion... else to_chat(user, "[target] could use [convert_progress == 1?"a little":"some"] more persuasion.") - useLock = FALSE return - // Check: Mindshield & Antag if (!disloyalty_confirm && RequireDisloyalty(target)) if (!do_disloyalty(user,target)) @@ -328,7 +313,6 @@ to_chat(user, "[target] looks ready for the Dark Communion.") useLock = FALSE return - // Check: Blood if (user.blood_volume < convert_cost) to_chat(user, "You don't have enough blood to initiate the Dark Communion with [target].") @@ -343,11 +327,9 @@ to_chat(user, "The ritual has been interrupted!") useLock = FALSE return - // Convert to Vassal! if (bloodsuckerdatum && bloodsuckerdatum.attempt_turn_vassal(target)) remove_loyalties(target) // In case of Mindshield, or appropriate Antag (Traitor, Internal, etc) - //if (!target.buckled) // to_chat(user, "The ritual has been interrupted!") // useLock = FALSE @@ -358,16 +340,12 @@ target.Jitter(25) target.emote("laugh") //remove_victim(target) // Remove on CLICK ONLY! - useLock = FALSE - /obj/structure/bloodsucker/vassalrack/proc/do_torture(mob/living/user, mob/living/target, mult=1) - var/torture_time = 15 // Fifteen seconds if you aren't using anything. Shorter with weapons and such. var/torture_dmg_brute = 2 var/torture_dmg_burn = 0 - // Get Bodypart var/target_string = "" var/obj/item/bodypart/BP = null @@ -376,7 +354,6 @@ BP = pick(C.bodyparts) if (BP) target_string += BP.name - // Get Weapon var/obj/item/I = user.get_active_held_item() if (!istype(I)) @@ -384,7 +361,6 @@ // Create Strings var/method_string = I?.attack_verb?.len ? pick(I.attack_verb) : pick("harmed","tortured","wrenched","twisted","scoured","beaten","lashed","scathed") var/weapon_string = I ? I.name : pick("bare hands","hands","fingers","fists") - // Weapon Bonus + SFX if (I) torture_time -= I.force / 4 @@ -399,33 +375,23 @@ welder.welding = TRUE torture_time -= 5 torture_dmg_burn += 5 - I.play_tool_sound(target) torture_time = max(50, torture_time * 10) // Minimum 5 seconds. - // Now run process. if (!do_mob(user, target, torture_time * mult)) return FALSE - // SUCCESS if (I) playsound(loc, I.hitsound, 30, 1, -1) I.play_tool_sound(target) - target.visible_message("[user] has [method_string] [target]'s [target_string] with [user.p_their()] [weapon_string]!", \ "[user] has [method_string] your [target_string] with [user.p_their()] [weapon_string]!") if (!target.is_muzzled()) target.emote("scream") target.Jitter(5) target.apply_damages(brute = torture_dmg_brute, burn = torture_dmg_burn, def_zone = (BP ? BP.body_zone : null)) // take_overall_damage(6,0) - return TRUE - - - - - /obj/structure/bloodsucker/vassalrack/proc/do_disloyalty(mob/living/user, mob/living/target) // OFFER YES/NO NOW! @@ -492,38 +458,47 @@ light_power = 3 light_range = 0 // to 2 density = FALSE - anchored = TRUE + anchored = FALSE var/lit = FALSE - ///obj/structure/bloodsucker/candelabrum/is_hot() // candle.dm //return FALSE +/datum/component/nanites/Destroy() + STOP_PROCESSING(SSobj, src) + /obj/structure/bloodsucker/candelabrum/update_icon() icon_state = "candelabrum[lit ? "_lit" : ""]" /obj/structure/bloodsucker/candelabrum/attack_hand(mob/user) - // Unlight (only a Vamp can light it) - var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - if (istype(bloodsuckerdatum)) - lit = !lit - if (lit) - set_light(2,3,"#66FFFF") - to_chat(user, "You wave your hand over the candelabrum. It springs to life.") - else - set_light(0) - update_icon() + var/datum/antagonist/bloodsucker/V = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) //I wish there was a better way to do this + var/datum/antagonist/vassal/T = user.mind.has_antag_datum(ANTAG_DATUM_VASSAL) + if(istype(V) || istype(T)) + toggle() /obj/structure/bloodsucker/candelabrum/AltClick(mob/user) + var/datum/antagonist/bloodsucker/V = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) // Bloodsuckers can turn their candles on from a distance. SPOOOOKY. - var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - if (istype(bloodsuckerdatum)) - attack_hand(user) - + if(istype(V)) + toggle() +/obj/structure/bloodsucker/candelabrum/proc/toggle(mob/user) + lit = !lit + if(lit) + set_light(2, 3, "#66FFFF") + START_PROCESSING(SSobj, src) + else + set_light(0) + STOP_PROCESSING(SSobj, src) + update_icon() +/obj/structure/bloodsucker/candelabrum/process() + if(lit) + for(var/mob/living/carbon/human/H in viewers(7, src)) + var/datum/antagonist/vassal/T = H.mind.has_antag_datum(ANTAG_DATUM_VASSAL) + var/datum/antagonist/bloodsucker/V = H.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + if(V || T) //We dont want vassals or vampires affected by this + return + H.hallucination = 5 + SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "vampcandle", /datum/mood_event/vampcandle) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - - // OTHER THINGS TO USE: HUMAN BLOOD. /obj/effect/decal/cleanable/blood diff --git a/code/modules/antagonists/bloodsucker/powers/bs_haste.dm b/code/modules/antagonists/bloodsucker/powers/bs_haste.dm index c3337eb391..b9e35c6a4b 100644 --- a/code/modules/antagonists/bloodsucker/powers/bs_haste.dm +++ b/code/modules/antagonists/bloodsucker/powers/bs_haste.dm @@ -5,7 +5,7 @@ /datum/action/bloodsucker/targeted/haste name = "Immortal Haste" - desc = "Sprint anywhere in the blink of an eye, slipping past open doors. Those nearby may be knocked away, stunned, or left empty-handed." + desc = "Dash somewhere with supernatural speed. Those nearby may be knocked away, stunned, or left empty-handed." button_icon_state = "power_speed" bloodcost = 6 cooldown = 30 @@ -67,14 +67,16 @@ if (rand(0, 5) < level_current) playsound(get_turf(newtarget), "sound/weapons/punch[rand(1,4)].ogg", 15, 1, -1) newtarget.Knockdown(10 + level_current * 5) + newtarget.adjustStaminaLoss(10 + 5 * level_current) newtarget.Stun(5 + level_current * 2) + newtarget.adjustStaminaLoss(5 + 3 * level_current) if(newtarget.IsStun()) newtarget.spin(10,1) if (rand(0,4)) newtarget.drop_all_held_items() foundtargets += newtarget sleep(1) - if (user) + if(user) user.update_canmove() //Let the poor guy move again /datum/action/bloodsucker/targeted/haste/DeactivatePower(mob/living/user = owner, mob/living/target) diff --git a/code/modules/antagonists/bloodsucker/powers/bs_lunge.dm b/code/modules/antagonists/bloodsucker/powers/bs_lunge.dm index 4a36431b18..53b8365b44 100644 --- a/code/modules/antagonists/bloodsucker/powers/bs_lunge.dm +++ b/code/modules/antagonists/bloodsucker/powers/bs_lunge.dm @@ -66,9 +66,10 @@ // LEVEL 2: If behind target, mute or unconscious! if (do_knockdown) // && level_current >= 1) target.Knockdown(15 + 10 * level_current,1) + target.adjustStaminaLoss(40 + 10 * level_current) // Cancel Walk (we were close enough to contact them) walk(owner, 0) - //target.Paralyze(10,1) + target.Stun(10,1) //Without this the victim can just walk away target.grabbedby(owner) // Taken from mutations.dm under changelings target.grippedby(owner, instant = TRUE) //instant aggro grab diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index fe35981bfe..04cec0bc91 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -107,8 +107,29 @@ else return ..() +/obj/item/reagent_containers/blood/attack(mob/M, mob/user, def_zone) + if(user.a_intent == INTENT_HELP && reagents.total_volume > 0) + if (user != M) + to_chat(user, "You force [M] to drink from the [src]") + user.visible_message("[user] forces [M] to drink from the [src].") + if (!do_mob(user, M, 50)) + return + else + if (!do_mob(user, M, 10)) + return + to_chat(user, "You take a sip from the [src].") + user.visible_message("[user] puts the [src] up to their mouth.") + if (reagents.total_volume <= 0) // Safety: In case you spam clicked the blood bag on yourself, and it is now empty (below will divide by zero) + return + var/gulp_size = 5 + var/fraction = min(gulp_size / reagents.total_volume, 1) + reagents.reaction(M, INGEST, fraction) //checkLiked(fraction, M) // Blood isn't food, sorry. + reagents.trans_to(M, gulp_size) + playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1) + ..() + /obj/item/reagent_containers/blood/bluespace name = "bluespace blood pack" desc = "Contains blood used for transfusion, this one has been made with bluespace technology to hold much more blood. Must be attached to an IV drip." icon_state = "bsbloodpack" - volume = 600 //its a blood bath! \ No newline at end of file + volume = 600 //its a blood bath! diff --git a/tgstation.dme b/tgstation.dme index 9219159405..a568a02ea6 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1226,7 +1226,6 @@ #include "code\modules\antagonists\bloodsucker\datum_bloodsucker.dm" #include "code\modules\antagonists\bloodsucker\datum_hunter.dm" #include "code\modules\antagonists\bloodsucker\datum_vassal.dm" -#include "code\modules\antagonists\bloodsucker\items\bloodsucker_items.dm" #include "code\modules\antagonists\bloodsucker\items\bloodsucker_organs.dm" #include "code\modules\antagonists\bloodsucker\items\bloodsucker_stake.dm" #include "code\modules\antagonists\bloodsucker\objects\bloodsucker_coffin.dm"