diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 55bfcaff79..4be0985fbc 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -67,6 +67,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) ) #define isdwarf(A) (is_species(A, /datum/species/dwarf)) #define isdullahan(A) (is_species(A, /datum/species/dullahan)) +#define isvampire(A) (is_species(A,/datum/species/vampire)) // Citadel specific species #define isipcperson(A) (is_species(A, /datum/species/ipc)) @@ -263,4 +264,4 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list( #define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob)) -#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs)) \ No newline at end of file +#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs)) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index a9f2750ce2..afa858afb7 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1563,3 +1563,16 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) if(channels_to_use.len) world.TgsChatBroadcast() + +//Checks to see if either the victim has a garlic necklace or garlic in their blood +/proc/blood_sucking_checks(var/mob/living/carbon/target, check_neck, check_blood) + //Bypass this if the target isnt carbon. + if(!iscarbon(target)) + return TRUE + if(check_neck) + if(istype(target.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace)) + return FALSE + if(check_blood) + if(target.reagents.has_reagent(/datum/reagent/consumable/garlic)) + return FALSE + return TRUE diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 490f0aa0f0..328e008f10 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -367,7 +367,7 @@ blood_display.hud = src infodisplay += blood_display - vamprank_display = new /obj/screen/bloodsucker/rank_counter // Vampire Rank + vamprank_display = new /obj/screen/bloodsucker/rank_counter // Bloodsucker Rank vamprank_display.hud = src infodisplay += vamprank_display diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index f846c9c79e..b0e1d39d9a 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -131,7 +131,7 @@ I.do_stagger_action(src, user) if(I.force) apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage - if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW)) + if(I.damtype == BRUTE) if(prob(33)) I.add_mob_blood(src) var/turf/location = get_turf(src) diff --git a/code/datums/components/crafting/recipes/recipes_clothing.dm b/code/datums/components/crafting/recipes/recipes_clothing.dm index ba47b64b97..b9e3c379b4 100644 --- a/code/datums/components/crafting/recipes/recipes_clothing.dm +++ b/code/datums/components/crafting/recipes/recipes_clothing.dm @@ -294,3 +294,12 @@ /obj/item/bedsheet/cosmos = 1) time = 60 category = CAT_CLOTHING + + +/datum/crafting_recipe/garlic_necklace + name = "Garlic Necklace" + result = /obj/item/clothing/neck/garlic_necklace + reqs = list(/obj/item/reagent_containers/food/snacks/grown/garlic = 15, + /obj/item/stack/cable_coil = 10) + time = 100 //Takes awhile to put all the garlics on the coil and knot it. + category = CAT_CLOTHING diff --git a/code/game/gamemodes/bloodsucker/bloodsucker.dm b/code/game/gamemodes/bloodsucker/bloodsucker.dm index 9515d6063c..bb776d7bc0 100644 --- a/code/game/gamemodes/bloodsucker/bloodsucker.dm +++ b/code/game/gamemodes/bloodsucker/bloodsucker.dm @@ -9,8 +9,14 @@ var/list/vassal_allowed_antags = list(/datum/antagonist/brother, /datum/antagonist/traitor, /datum/antagonist/traitor/internal_affairs, /datum/antagonist/survivalist, \ /datum/antagonist/rev, /datum/antagonist/nukeop, /datum/antagonist/pirate, /datum/antagonist/cult, /datum/antagonist/abductee, /datum/antagonist/valentine, /datum/antagonist/heartbreaker,) // The antags you're allowed to be if turning Vassal. -/proc/isvamp(mob/living/M) - return istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/bloodsucker) + +/proc/AmBloodsucker(mob/living/M, falseIfInDisguise = FALSE) + if(!M.mind) + return FALSE + // No Datum + if(!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) + return FALSE + return TRUE /datum/game_mode/bloodsucker name = "bloodsucker" @@ -70,49 +76,27 @@ // Gamemode is all done being set up. We have all our Vamps. We now pick objectives and let them know what's happening. /datum/game_mode/bloodsucker/post_setup() - // Sunlight (Creating Bloodsuckers manually will check to create this, too) check_start_sunlight() - // Vamps for(var/datum/mind/bloodsucker in bloodsuckers) - // spawn() --> Run block of code but game continues on past it. - // sleep() --> Run block of code and freeze code there (including whoever called us) until it's resolved. - - //Clean Bloodsucker Species (racist?) - //clean_invalid_species(bloodsucker) - // TO-DO !!! - - // Add Bloodsucker Antag Datum (or remove from list on Fail) - if (!make_bloodsucker(bloodsucker)) + if(!make_bloodsucker(bloodsucker)) bloodsuckers -= bloodsucker - - // NOTE: Hunters are done in ..() parent proc - return ..() -// Checking for ACTUALLY Dead Vamps -/datum/game_mode/bloodsucker/are_special_antags_dead() - // Bloodsucker not Final Dead - for(var/datum/mind/bloodsucker in bloodsuckers) - if(!bloodsucker.AmFinalDeath()) - return FALSE - return TRUE - - // Init Sunlight (called from datum_bloodsucker.on_gain(), in case game mode isn't even Bloodsucker /datum/game_mode/proc/check_start_sunlight() // Already Sunlight (and not about to cancel) - if (istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me) + if(istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me) return bloodsucker_sunlight = new () // End Sun (last bloodsucker removed) /datum/game_mode/proc/check_cancel_sunlight() // No Sunlight - if (!istype(bloodsucker_sunlight)) + if(!istype(bloodsucker_sunlight)) return - if (bloodsuckers.len <= 0) + if(bloodsuckers.len <= 0) bloodsucker_sunlight.cancel_me = TRUE qdel(bloodsucker_sunlight) bloodsucker_sunlight = null @@ -151,43 +135,37 @@ // Not High Enough if(creator) var/datum/antagonist/bloodsucker/creator_bloodsucker = creator.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - if(!istype(creator_bloodsucker) || creator_bloodsucker.vamplevel < BLOODSUCKER_LEVEL_TO_EMBRACE) + if(!istype(creator_bloodsucker) || creator_bloodsucker.bloodsucker_level < BLOODSUCKER_LEVEL_TO_EMBRACE) to_chat(creator, "Your blood is too thin to turn this corpse!") return FALSE return TRUE /datum/game_mode/proc/make_bloodsucker(datum/mind/bloodsucker, datum/mind/creator = null) // NOTE: This is a game_mode/proc, NOT a game_mode/bloodsucker/proc! We need to access this function despite the game mode. - if (!can_make_bloodsucker(bloodsucker)) + if(!can_make_bloodsucker(bloodsucker)) return FALSE - // Create Datum: Fledgling var/datum/antagonist/bloodsucker/A // [FLEDGLING] - if (creator) + if(creator) A = new (bloodsucker) A.creator = creator bloodsucker.add_antag_datum(A) // Log message_admins("[bloodsucker] has become a Bloodsucker, and was created by [creator].") log_admin("[bloodsucker] has become a Bloodsucker, and was created by [creator].") - // [MASTER] else A = bloodsucker.add_antag_datum(ANTAG_DATUM_BLOODSUCKER) - - return TRUE - /datum/game_mode/proc/remove_bloodsucker(datum/mind/bloodsucker) bloodsucker.remove_antag_datum(ANTAG_DATUM_BLOODSUCKER) - /datum/game_mode/proc/clean_invalid_species(datum/mind/bloodsucker) // Only checking for Humans here - if (!ishuman(bloodsucker.current) || !bloodsucker.current.client) + if(!ishuman(bloodsucker.current) || !bloodsucker.current.client) return var/am_valid = TRUE var/mob/living/carbon/human/H = bloodsucker.current @@ -202,7 +180,7 @@ // everyone will wonder why you're a human with Plasma clothes (jk they'll know you're antag) // Convert to HUMAN (along with ID and PDA) - if (!am_valid) + if(!am_valid) H.set_species(/datum/species/human) H.real_name = H.client.prefs.custom_names["human"] var/obj/item/card/id/ID = H.wear_id?.GetID() @@ -211,12 +189,13 @@ ID.update_label() -/datum/game_mode/proc/can_make_vassal(mob/living/target, datum/mind/creator, display_warning=TRUE)//, check_antag_or_loyal=FALSE) +/datum/game_mode/proc/can_make_vassal(mob/living/target, datum/mind/creator, display_warning = TRUE)//, check_antag_or_loyal=FALSE) // Not Correct Type: Abort - if (!iscarbon(target) || !creator) + if(!iscarbon(target) || !creator) return FALSE - if (target.stat > UNCONSCIOUS) + if(target.stat > UNCONSCIOUS) return FALSE + // Check Overdose: Am I even addicted to blood? Do I even have any in me? //if (!target.reagents.addiction_list || !target.reagents.reagent_list) //message_admins("DEBUG2: can_make_vassal() Abort: No reagents") @@ -233,23 +212,23 @@ //message_admins("DEBUG4: can_make_vassal() Abort: No Blood") // return 0 // No Mind! - if (!target.mind || !target.mind.key) - if (display_warning) + if(!target.mind || !target.mind.key) + if(display_warning) to_chat(creator, "[target] isn't self-aware enough to be made into a Vassal.") return FALSE // Already MY Vassal var/datum/antagonist/vassal/V = target.mind.has_antag_datum(ANTAG_DATUM_VASSAL) - if (istype(V) && V.master) - if (V.master.owner == creator) - if (display_warning) + if(istype(V) && V.master) + if(V.master.owner == creator) + if(display_warning) to_chat(creator, "[target] is already your loyal Vassal!") else - if (display_warning) + if(display_warning) to_chat(creator, "[target] is the loyal Vassal of another Bloodsucker!") return FALSE // Already Antag or Loyal (Vamp Hunters count as antags) - if (target.mind.enslaved_to || AmInvalidAntag(target.mind)) //!VassalCheckAntagValid(target.mind, check_antag_or_loyal)) // HAS_TRAIT(target, TRAIT_MINDSHIELD, "implant") || - if (display_warning) + if(target.mind.enslaved_to || AmInvalidAntag(target.mind)) //!VassalCheckAntagValid(target.mind, check_antag_or_loyal)) // HAS_TRAIT(target, TRAIT_MINDSHIELD, "implant") || + if(display_warning) to_chat(creator, "[target] resists the power of your blood to dominate their mind!") return FALSE return TRUE @@ -268,24 +247,24 @@ return FALSE // Does even ONE antag appear in this mind that isn't in the list? Then FAIL! for(var/datum/antagonist/antag_datum in M.antag_datums) - if (!(antag_datum.type in vassal_allowed_antags)) // vassal_allowed_antags is a list stored in the game mode, above. + if(!(antag_datum.type in vassal_allowed_antags)) // vassal_allowed_antags is a list stored in the game mode, above. //message_admins("DEBUG VASSAL: Found Invalid: [antag_datum] // [antag_datum.type]") return TRUE //message_admins("DEBUG VASSAL: Valid Antags! (total of [M.antag_datums.len])") // WHEN YOU DELETE THE ABOVE: Remove the 3 second timer on converting the vassal too. return FALSE -/datum/game_mode/proc/make_vassal(mob/living/target, datum/mind/creator) - if (!can_make_vassal(target,creator)) +/datum/game_mode/proc/make_vassal(var/mob/living/target, var/datum/mind/creator) + if(!can_make_vassal(target, creator)) return FALSE // Make Vassal - var/datum/antagonist/vassal/V = new (target.mind) + var/datum/antagonist/vassal/V = new(target.mind) var/datum/antagonist/bloodsucker/B = creator.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) V.master = B target.mind.add_antag_datum(V, V.master.get_team()) // Update Bloodsucker Title (we're a daddy now) B.SelectTitle(am_fledgling = FALSE) // Only works if you have no title yet. - // Log + // Log it message_admins("[target] has become a Vassal, and is enslaved to [creator].") log_admin("[target] has become a Vassal, and is enslaved to [creator].") return TRUE diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 648c227c0a..bc0fec68ba 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -144,6 +144,8 @@ return FALSE if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding. return FALSE + if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker + return FALSE if(clonemind.active) //somebody is using that mind if( ckey(clonemind.key)!=ckey ) return FALSE @@ -159,8 +161,6 @@ mess = TRUE update_icon() return FALSE - if(isvamp(clonemind)) //If the mind is a bloodsucker - return FALSE attempting = TRUE //One at a time!! countdown.start() diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 205ce57251..50e9b94e97 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -72,6 +72,8 @@ to_chat(user, " [M] is at full health.") return FALSE user.visible_message("[user] applies \the [src] on [M].", "You apply \the [src] on [M].") + if(AmBloodsucker(M)) + return M.heal_bodypart_damage((heal_brute/2)) return TRUE if(iscarbon(M)) @@ -148,6 +150,8 @@ return if(iscarbon(M)) return heal_carbon(M, user, 0, heal_burn) + if(AmBloodsucker(M)) + return to_chat(user, "You can't heal [M] with the \the [src]!") /obj/item/stack/medical/ointment/suicide_act(mob/living/user) diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm b/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm index 3a6b4efedb..98fb69e52c 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm @@ -1,12 +1,6 @@ // INTEGRATION: Adding Procs and Datums to existing "classes" -/mob/living/proc/AmBloodsucker(falseIfInDisguise=FALSE) - // No Datum - if(!mind || !mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) - return FALSE - return TRUE - -/mob/living/proc/HaveBloodsuckerBodyparts(var/displaymessage="") // displaymessage can be something such as "rising from death" for Torpid Sleep. givewarningto is the person receiving messages. +/mob/living/proc/HaveBloodsuckerBodyparts(displaymessage = "") // displaymessage can be something such as "rising from death" for Torpid Sleep. givewarningto is the person receiving messages. if(!getorganslot(ORGAN_SLOT_HEART)) if(displaymessage != "") to_chat(src, "Without a heart, you are incapable of [displaymessage].") @@ -21,33 +15,6 @@ return FALSE return TRUE - - -// GET DAMAGE - - -// 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) - if(BP.status < 2) - 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 e774cf4250..efccb5591e 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm @@ -12,10 +12,10 @@ /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 + var/notice_healing 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.1) // -.15 (before tick went from 10 to 30, but we also charge more for faking life now) + AddBloodVolume(passive_blood_drain) // -.1 currently 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...") @@ -25,7 +25,7 @@ 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(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 @@ -39,12 +39,12 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /datum/antagonist/bloodsucker/proc/AddBloodVolume(value) - owner.current.blood_volume = CLAMP(owner.current.blood_volume + value, 0, maxBloodVolume) + owner.current.blood_volume = CLAMP(owner.current.blood_volume + value, 0, max_blood_volume) 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) + var/blood_taken = min(feed_amount, 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)) @@ -82,38 +82,40 @@ /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) + var/actual_regen = regen_rate + additional_regen if(poweron_masquerade == TRUE || owner.current.AmStaked()) return FALSE - owner.current.adjustStaminaLoss(-1.5 + (regenRate * -7) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more. - owner.current.adjustCloneLoss(-0.1 * (regenRate * 2) * mult, 0) - owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (regenRate * 4) * mult) //adjustBrainLoss(-1 * (regenRate * 4) * mult, 0) + if(owner.current.reagents.has_reagent(/datum/reagent/consumable/garlic)) + return FALSE + if(istype(owner.current.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace)) + return FALSE + owner.current.adjustStaminaLoss(-1.5 + (actual_regen * -7) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more. + owner.current.adjustCloneLoss(-0.1 * (actual_regen * 2) * mult, 0) + owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (actual_regen * 4) * mult) // No Bleeding - if(ishuman(owner.current)) //NOTE Current bleeding is horrible, not to count the amount of blood ballistics delete. + /*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 + if(H.bleed_rate > 0) //Only heal bleeding if we are actually bleeding + H.bleed_rate =- 0.5 + actual_regen * 0.2 */ 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 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) + var/amInCoffinWhileTorpor = istype(C.loc, /obj/structure/closet/crate/coffin) && (mult == 0 || HAS_TRAIT(C, TRAIT_FAKEDEATH)) // Check for mult 0 OR death coma. (mult 0 means we're testing from coffin) if(amInCoffinWhileTorpor) mult *= 4 // 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 + fireheal = min(C.getFireLoss(), regen_rate) // NOTE: Burn damage ONLY heals in torpor. C.ExtinguishMob() CureDisabilities() // Extinguish Fire 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 - else - 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 + if(check_limbs(costMult)) + return TRUE + // BRUTE: Always Heal - var/bruteheal = min(C.getBruteLoss_nonProsthetic(), regenRate) - var/toxinheal = min(C.getToxLoss(), regenRate) + var/bruteheal = min(C.getBruteLoss(), actual_regen) + var/toxinheal = min(C.getToxLoss(), actual_regen) // Heal if Damaged if(bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return. if(mult == 0) @@ -127,28 +129,29 @@ //C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above. AddBloodVolume((bruteheal * -0.5 + fireheal * -1 + toxinheal * -0.2) / mult * costMult) // Costs blood to heal 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")) - var/obj/item/bodypart/L = owner.current.get_bodypart( targetLimbZone ) // 2) Limb returns Damaged - AddBloodVolume(50 * 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) - message_admins("T1: [BP] ") - if (istype(BP) && BP.status == 2) - message_admins("T2: [BP] ") - BP.drop_limb() - return TRUE */ - // NOTE: Limbs have a "status", like their hosts "stat". 2 is dead (aka Prosthetic). 1 seems to be idle/alive.*/ - return FALSE + + + +/datum/antagonist/bloodsucker/proc/check_limbs(costMult) + var/limb_regen_cost = 50 * costMult + var/mob/living/carbon/C = owner.current + var/list/missing = C.get_missing_limbs() + if(missing.len && C.blood_volume < limb_regen_cost + 5) + return FALSE + for(var/targetLimbZone in missing) // 1) Find ONE Limb and regenerate it. + C.regenerate_limb(targetLimbZone, FALSE) // regenerate_limbs() <--- If you want to EXCLUDE certain parts, do it like this ----> regenerate_limbs(0, list("head")) + AddBloodVolume(50) + var/obj/item/bodypart/L = C.get_bodypart(targetLimbZone) // 2) Limb returns Damaged + L.brute_dam = 60 + to_chat(C, "Your flesh knits as it regrows your [L]!") + playsound(C, 'sound/magic/demon_consume.ogg', 50, TRUE) + return TRUE + /*for(var/obj/item/bodypart/BP in C.bodyparts) + if(!istype(BP) && !BP.status == 2) + return FALSE + to_chat(C, "Your body expels the [BP]!") + BP.drop_limb() + return TRUE */ /datum/antagonist/bloodsucker/proc/CureDisabilities() var/mob/living/carbon/C = owner.current @@ -179,7 +182,16 @@ if(owner.current.blood_volume < BLOOD_VOLUME_BAD / 2) owner.current.blur_eyes(8 - 8 * (owner.current.blood_volume / BLOOD_VOLUME_BAD)) // Nutrition - owner.current.nutrition = min(owner.current.blood_volume, NUTRITION_LEVEL_FED) // <-- 350 //NUTRITION_LEVEL_FULL + owner.current.nutrition = clamp(owner.current.blood_volume, 545, 0) //The amount of blood is how full we are. + //A bit higher regeneration based on blood volume + if(owner.current.blood_volume < 700) + additional_regen = 0.4 + else if(owner.current.blood_volume < BLOOD_VOLUME_NORMAL) + additional_regen = 0.3 + else if(owner.current.blood_volume < BLOOD_VOLUME_OKAY) + additional_regen = 0.2 + else if(owner.current.blood_volume < BLOOD_VOLUME_BAD) + additional_regen = 0.1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // DEATH @@ -189,7 +201,7 @@ /datum/antagonist/bloodsucker/proc/HandleDeath() // FINAL DEATH // Fire Damage? (above double health) - if(owner.current.getFireLoss_nonProsthetic() >= owner.current.maxHealth * 2.5) + if(owner.current.getFireLoss() >= owner.current.maxHealth * 3) FinalDeath() return // Staked while "Temp Death" or Asleep @@ -209,8 +221,8 @@ // 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_brute = owner.current.getBruteLoss() + var/total_burn = owner.current.getFireLoss() 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) @@ -218,27 +230,25 @@ Torpor_Begin() to_chat(owner, "Your immortal body will not yet relinquish your soul to the abyss. You enter Torpor.") sleep(30) //To avoid spam - if (poweron_masquerade == TRUE) + if(poweron_masquerade == TRUE) to_chat(owner, "Your wounds will not heal until you disable the Masquerade power.") // End Torpor: 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")) + if(!SSticker.mode.is_daylight() && HAS_TRAIT_FROM(owner.current, TRAIT_FAKEDEATH, "bloodsucker")) Torpor_End() // Fake Unconscious if(poweron_masquerade == TRUE && total_damage >= owner.current.getMaxHealth() - HEALTH_THRESHOLD_FULLCRIT) - owner.current.Unconscious(20,1) - //HEALTH_THRESHOLD_CRIT 0 - //HEALTH_THRESHOLD_FULLCRIT -30 - //HEALTH_THRESHOLD_DEAD -100 + owner.current.Unconscious(20, 1) -/datum/antagonist/bloodsucker/proc/Torpor_Begin(amInCoffin=FALSE) +/datum/antagonist/bloodsucker/proc/Torpor_Begin(amInCoffin = FALSE) owner.current.stat = UNCONSCIOUS - owner.current.fakedeath("bloodsucker") // Come after UNCONSCIOUS or else it fails + owner.current.apply_status_effect(STATUS_EFFECT_UNCONSCIOUS) + ADD_TRAIT(owner.current, TRAIT_FAKEDEATH, "bloodsucker") // Come after UNCONSCIOUS or else it fails ADD_TRAIT(owner.current, TRAIT_NODEATH, "bloodsucker") // Without this, you'll just keep dying while you recover. - ADD_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") // So you can heal in 0 G. otherwise you just...heal forever. - ADD_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") // So you can heal in 0 G. otherwise you just...heal forever. + ADD_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") // So you can heal in space. Otherwise you just...heal forever. + ADD_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") // Visuals owner.current.update_sight() owner.current.reload_fullscreen() @@ -247,10 +257,10 @@ if(power.active && !power.can_use_in_torpor) power.DeactivatePower() - /datum/antagonist/bloodsucker/proc/Torpor_End() owner.current.stat = SOFT_CRIT - owner.current.cure_fakedeath("bloodsucker") // Come after SOFT_CRIT or else it fails + owner.current.remove_status_effect(STATUS_EFFECT_UNCONSCIOUS) + REMOVE_TRAIT(owner.current, TRAIT_FAKEDEATH, "bloodsucker") REMOVE_TRAIT(owner.current, TRAIT_NODEATH, "bloodsucker") REMOVE_TRAIT(owner.current, TRAIT_RESISTHIGHPRESSURE, "bloodsucker") REMOVE_TRAIT(owner.current, TRAIT_RESISTLOWPRESSURE, "bloodsucker") @@ -283,18 +293,19 @@ // Free my Vassals! FreeAllVassals() // Elders get Dusted - if(vamplevel >= 4) // (vamptitle) + if(bloodsucker_level >= 4) // (bloodsucker_title) 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.", \ "Your soul escapes your withering body as the abyss welcomes you to your Final Death.", \ "You hear a dry, crackling sound.") + sleep(50) owner.current.dust() // Fledglings get Gibbed else owner.current.visible_message("[owner.current]'s skin bursts forth in a spray of gore and detritus. A horrible cry echoes from what is now a wet pile of decaying meat.", \ "Your soul escapes your withering body as the abyss welcomes you to your Final Death.", \ "You hear a wet, bursting sound.") - owner.current.gib(TRUE, FALSE, FALSE)//Brain cloning is wierd and allows hellbounds. Lets destroy the brain for safety. - playsound(owner.current.loc, 'sound/effects/tendril_destroyed.ogg', 40, 1) + owner.current.gib(TRUE, FALSE, FALSE) //Brain cloning is wierd and allows hellbounds. Lets destroy the brain for safety. + playsound(owner.current, 'sound/effects/tendril_destroyed.ogg', 40, TRUE) @@ -304,15 +315,15 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/mob/proc/CheckBloodsuckerEatFood(var/food_nutrition) - if (!isliving(src)) +/mob/proc/CheckBloodsuckerEatFood(food_nutrition) + if(!isliving(src)) return var/mob/living/L = src - if(!L.AmBloodsucker()) + if(!AmBloodsucker(L)) return - // We're a vamp? Try to eat food... - var/datum/antagonist/bloodsucker/bloodsuckerdatum = mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) - bloodsuckerdatum.handle_eat_human_food(food_nutrition) + // We're a bloodsucker? Try to eat food... + var/datum/antagonist/bloodsucker/B = L.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + B.handle_eat_human_food(food_nutrition) /datum/antagonist/bloodsucker/proc/handle_eat_human_food(food_nutrition, puke_blood = TRUE, masquerade_override) // Called from snacks.dm and drinks.dm diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm index 507e1f2739..5c4b1f2b9f 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm @@ -93,6 +93,14 @@ if(display_error) to_chat(owner, "You have a stake in your chest! Your powers are useless.") return FALSE + if(istype(owner.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/garlic_necklace)) + if(display_error) + to_chat(owner, "") + return FALSE + if(owner.reagents?.has_reagent(/datum/reagent/consumable/garlic)) + if(display_error) + to_chat(owner, "Garlic in your blood is interfering with your powers!") + return FALSE // Incap? if(must_be_capacitated) var/mob/living/L = owner diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm b/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm index 263f91a9a6..b7d98c6783 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm @@ -141,23 +141,23 @@ if(!bloodsuckerdatum.warn_sun_locker) to_chat(M, "Your skin sizzles. The [M.current.loc] doesn't protect well against UV bombardment.") bloodsuckerdatum.warn_sun_locker = TRUE - M.current.adjustFireLoss(0.5 + bloodsuckerdatum.vamplevel / 2) // M.current.fireloss += 0.5 + bloodsuckerdatum.vamplevel / 2 // Do DIRECT damage. Being spaced was causing this to not occur. setFireLoss(bloodsuckerdatum.vamplevel) + M.current.adjustFireLoss(0.5 + bloodsuckerdatum.bloodsucker_level / 2) // M.current.fireloss += 0.5 + bloodsuckerdatum.bloodsucker_level / 2 // Do DIRECT damage. Being spaced was causing this to not occur. setFireLoss(bloodsuckerdatum.bloodsucker_level) M.current.updatehealth() SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_1) // Out in the Open? Buh Bye else if(!bloodsuckerdatum.warn_sun_burn) - if(bloodsuckerdatum.vamplevel > 0) + if(bloodsuckerdatum.bloodsucker_level > 0) to_chat(M, "The solar flare sets your skin ablaze!") else to_chat(M, "The solar flare scalds your neophyte skin!") bloodsuckerdatum.warn_sun_burn = TRUE if(M.current.fire_stacks <= 0) M.current.fire_stacks = 0 - if(bloodsuckerdatum.vamplevel > 0) - M.current.adjust_fire_stacks(0.2 + bloodsuckerdatum.vamplevel / 10) + if(bloodsuckerdatum.bloodsucker_level > 0) + M.current.adjust_fire_stacks(0.2 + bloodsuckerdatum.bloodsucker_level / 10) M.current.IgniteMob() - M.current.adjustFireLoss(2 + bloodsuckerdatum.vamplevel) // M.current.fireloss += 2 + bloodsuckerdatum.vamplevel // Do DIRECT damage. Being spaced was causing this to not occur. //setFireLoss(2 + bloodsuckerdatum.vamplevel) + M.current.adjustFireLoss(2 + bloodsuckerdatum.bloodsucker_level) // M.current.fireloss += 2 + bloodsuckerdatum.bloodsucker_level // Do DIRECT damage. Being spaced was causing this to not occur. //setFireLoss(2 + bloodsuckerdatum.bloodsucker_level) M.current.updatehealth() SEND_SIGNAL(M.current, COMSIG_ADD_MOOD_EVENT, "vampsleep", /datum/mood_event/daylight_2) diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 94c62df696..946be31ed6 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -8,9 +8,9 @@ job_rank = ROLE_BLOODSUCKER threat = 5 // NAME - var/vampname // My Dracula name - var/vamptitle // My Dracula title - var/vampreputation // My "Surname" or description of my deeds + var/bloodsucker_name // My Dracula style name + var/bloodsucker_title // My Dracula style title + var/bloodsucker_reputation // My "Surname" or description of my deeds // CLAN var/datum/team/vampireclan/clan var/list/datum/antagonist/vassal/vassals = list()// Vassals under my control. Periodically remove the dead ones. @@ -20,35 +20,33 @@ var/poweron_feed = FALSE // Am I feeding? var/poweron_masquerade = FALSE // STATS - var/vamplevel = 0 - var/vamplevel_unspent = 1 - var/regenRate = 0.4 // How many points of Brute do I heal per tick? - var/feedAmount = 15 // Amount of blood drawn from a target per tick. - var/maxBloodVolume = 600 // Maximum blood a Vamp can hold via feeding. // BLOOD_VOLUME_NORMAL 550 // BLOOD_VOLUME_SAFE 475 //BLOOD_VOLUME_OKAY 336 //BLOOD_VOLUME_BAD 224 // BLOOD_VOLUME_SURVIVE 122 + var/bloodsucker_level + var/bloodsucker_level_unspent = 1 + var/regen_rate = 0.3 // How fast do I regenerate? + var/additional_regen // How much additional blood regen we gain from bonuses such as high blood. + var/feed_amount = 15 // Amount of blood drawn from a target per tick. + var/max_blood_volume = 600 // Maximum blood a Vamp can hold via feeding. // OBJECTIVES var/list/datum/objective/objectives_given = list() // For removal if needed. var/area/lair var/obj/structure/closet/crate/coffin // TRACKING - var/foodInGut = 0 // How much food to throw up later. You shouldn't have eaten that. - var/warn_sun_locker = FALSE // So we only get the locker burn message once per day. - var/warn_sun_burn = FALSE // So we only get the sun burn message once per day. - var/had_toxlover = FALSE + var/foodInGut // How much food to throw up later. You shouldn't have eaten that. + var/warn_sun_locker // So we only get the locker burn message once per day. + var/warn_sun_burn // So we only get the sun burn message once per day. + var/had_toxlover var/level_bloodcost + var/passive_blood_drain = -0.1 //The amount of blood we loose each bloodsucker life() tick // LISTS var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_NIGHT_VISION, \ TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE) - // NOTES: TRAIT_AGEUSIA <-- Doesn't like flavors. - // REMOVED: TRAIT_NODEATH - // TO ADD: - //var/static/list/defaultOrgans = list (/obj/item/organ/heart/vampheart,/obj/item/organ/heart/vampeyes) /datum/antagonist/bloodsucker/on_gain() SSticker.mode.bloodsuckers |= owner // Add if not already in here (and you might be, if you were picked at round start) SSticker.mode.check_start_sunlight()// Start Sunlight? (if first Vamp) SelectFirstName()// Name & Title - SelectTitle(am_fledgling=TRUE) // If I have a creator, then set as Fledgling. - SelectReputation(am_fledgling=TRUE) + SelectTitle(am_fledgling = TRUE) // If I have a creator, then set as Fledgling. + SelectReputation(am_fledgling = TRUE) AssignStarterPowersAndStats()// Give Powers & Stats forge_bloodsucker_objectives()// Objectives & Team update_bloodsucker_icons_added(owner.current, "bloodsucker") // Add Antag HUD @@ -68,18 +66,18 @@ /datum/antagonist/bloodsucker/greet() var/fullname = ReturnFullName(TRUE) - to_chat(owner, "You are [fullname], a bloodsucking vampire!
") + to_chat(owner, "You are [fullname], a strain of vampire dubbed bloodsucker!
") owner.announce_objectives() to_chat(owner, "* You regenerate your health slowly, you're weak to fire, and you depend on blood to survive. Allow your stolen blood to run too low, and you will find yourself at \ risk of being discovered!
") //to_chat(owner, "As an immortal, your power is linked to your age. The older you grow, the more abilities you will have access to.") - var/vamp_greet - vamp_greet += "* Other Bloodsuckers are not necessarily your friends, but your survival may depend on cooperation. Betray them at your own discretion and peril.
" - vamp_greet += "* Use \",b\" to speak your ancient Bloodsucker language.
" - vamp_greet += "Bloodsucker Tip: Rest in a Coffin to claim it, and that area, as your lair.
" - vamp_greet += "Bloodsucker Tip: Fear the daylight! Solar flares will bombard the station periodically, and only your coffin can guarantee your safety.
" - vamp_greet += "Bloodsucker Tip: You wont loose blood if you are unconcious or sleeping. Use this to your advantage to conserve blood.
" - to_chat(owner, vamp_greet) + var/bloodsucker_greet + bloodsucker_greet += "* Other Bloodsuckers are not necessarily your friends, but your survival may depend on cooperation. Betray them at your own discretion and peril.
" + bloodsucker_greet += "* Use \",b\" to speak your ancient Bloodsucker language.
" + bloodsucker_greet += "Bloodsucker Tip: Rest in a Coffin to claim it, and that area, as your lair.
" + bloodsucker_greet += "Bloodsucker Tip: Fear the daylight! Solar flares will bombard the station periodically, and only your coffin can guarantee your safety.
" + bloodsucker_greet += "Bloodsucker Tip: You wont loose blood if you are unconcious or sleeping. Use this to your advantage to conserve blood.
" + to_chat(owner, bloodsucker_greet) owner.current.playsound_local(null, 'sound/bloodsucker/BloodsuckerAlert.ogg', 100, FALSE, pressure_affected = FALSE) antag_memory += "Although you were born a mortal, in un-death you earned the name [fullname].
" @@ -92,13 +90,13 @@ owner.current.blood_volume = max(owner.current.blood_volume,BLOOD_VOLUME_SAFE) /datum/antagonist/bloodsucker/threat() - return ..()+3*vamplevel + return ..() + 3 * bloodsucker_level /datum/antagonist/bloodsucker/proc/SelectFirstName() // Names (EVERYONE gets one)) if(owner.current.gender == MALE) - vampname = pick("Desmond","Rudolph","Dracul","Vlad","Pyotr","Gregor","Cristian","Christoff","Marcu","Andrei","Constantin","Gheorghe","Grigore","Ilie","Iacob","Luca","Mihail","Pavel","Vasile","Octavian","Sorin", \ + bloodsucker_name = pick("Desmond","Rudolph","Dracul","Vlad","Pyotr","Gregor","Cristian","Christoff","Marcu","Andrei","Constantin","Gheorghe","Grigore","Ilie","Iacob","Luca","Mihail","Pavel","Vasile","Octavian","Sorin", \ "Sveyn","Aurel","Alexe","Iustin","Theodor","Dimitrie","Octav","Damien","Magnus","Caine","Abel", // Romanian/Ancient "Lucius","Gaius","Otho","Balbinus","Arcadius","Romanos","Alexios","Vitellius", // Latin "Melanthus","Teuthras","Orchamus","Amyntor","Axion", // Greek @@ -106,7 +104,7 @@ "Dio") else - vampname = pick("Islana","Tyrra","Greganna","Pytra","Hilda","Andra","Crina","Viorela","Viorica","Anemona","Camelia","Narcisa","Sorina","Alessia","Sophia","Gladda","Arcana","Morgan","Lasarra","Ioana","Elena", \ + bloodsucker_name = pick("Islana","Tyrra","Greganna","Pytra","Hilda","Andra","Crina","Viorela","Viorica","Anemona","Camelia","Narcisa","Sorina","Alessia","Sophia","Gladda","Arcana","Morgan","Lasarra","Ioana","Elena", \ "Alina","Rodica","Teodora","Denisa","Mihaela","Svetla","Stefania","Diyana","Kelssa","Lilith", // Romanian/Ancient "Alexia","Athanasia","Callista","Karena","Nephele","Scylla","Ursa", // Latin "Alcestis","Damaris","Elisavet","Khthonia","Teodora", // Greek @@ -114,57 +112,57 @@ /datum/antagonist/bloodsucker/proc/SelectTitle(am_fledgling = 0, forced = FALSE) // Already have Title - if (!forced && vamptitle != null) + if(!forced && bloodsucker_title != null) return // Titles [Master] - if (!am_fledgling) + if(!am_fledgling) if(owner.current.gender == MALE) - vamptitle = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master") + bloodsucker_title = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master") else - vamptitle = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress") + bloodsucker_title = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress") to_chat(owner, "You have earned a title! You are now known as [ReturnFullName(TRUE)]!") // Titles [Fledgling] else - vamptitle = null + bloodsucker_title = null /datum/antagonist/bloodsucker/proc/SelectReputation(am_fledgling = 0, forced=FALSE) // Already have Reputation - if(!forced && vampreputation != null) + if(!forced && bloodsucker_reputation != null) return // Reputations [Master] if(!am_fledgling) - vampreputation = pick("Butcher","Blood Fiend","Crimson","Red","Black","Terror","Nightman","Feared","Ravenous","Fiend","Malevolent","Wicked","Ancient","Plaguebringer","Sinister","Forgotten","Wretched","Baleful", \ + bloodsucker_reputation = pick("Butcher","Blood Fiend","Crimson","Red","Black","Terror","Nightman","Feared","Ravenous","Fiend","Malevolent","Wicked","Ancient","Plaguebringer","Sinister","Forgotten","Wretched","Baleful", \ "Inqisitor","Harvester","Reviled","Robust","Betrayer","Destructor","Damned","Accursed","Terrible","Vicious","Profane","Vile","Depraved","Foul","Slayer","Manslayer","Sovereign","Slaughterer", \ "Forsaken","Mad","Dragon","Savage","Villainous","Nefarious","Inquisitor","Marauder","Horrible","Immortal","Undying","Overlord","Corrupt","Hellspawn","Tyrant","Sanguineous") if(owner.current.gender == MALE) if(prob(10)) // Gender override - vampreputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King") + bloodsucker_reputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King") else if(prob(10)) // Gender override - vampreputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen") + bloodsucker_reputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen") to_chat(owner, "You have earned a reputation! You are now known as [ReturnFullName(TRUE)]!") // Reputations [Fledgling] else - vampreputation = pick ("Crude","Callow","Unlearned","Neophyte","Novice","Unseasoned","Fledgling","Young","Neonate","Scrapling","Untested","Unproven","Unknown","Newly Risen","Born","Scavenger","Unknowing",\ + bloodsucker_reputation = pick ("Crude","Callow","Unlearned","Neophyte","Novice","Unseasoned","Fledgling","Young","Neonate","Scrapling","Untested","Unproven","Unknown","Newly Risen","Born","Scavenger","Unknowing",\ "Unspoiled","Disgraced","Defrocked","Shamed","Meek","Timid","Broken")//,"Fresh") /datum/antagonist/bloodsucker/proc/AmFledgling() - return !vamptitle + return !bloodsucker_title /datum/antagonist/bloodsucker/proc/ReturnFullName(var/include_rep=0) var/fullname // Name First - fullname = (vampname ? vampname : owner.current.name) + fullname = (bloodsucker_name ? bloodsucker_name : owner.current.name) // Title - if(vamptitle) - fullname = vamptitle + " " + fullname + if(bloodsucker_title) + fullname = bloodsucker_title + " " + fullname // Rep - if(include_rep && vampreputation) - fullname = fullname + " the " + vampreputation + if(include_rep && bloodsucker_reputation) + fullname = fullname + " the " + bloodsucker_reputation return fullname @@ -199,15 +197,12 @@ var/mob/living/carbon/human/H = owner.current var/datum/species/S = H.dna.species // Make Changes - H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank! + H.physiology.brute_mod *= 0.8 H.physiology.cold_mod = 0 H.physiology.stun_mod *= 0.5 H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1 - //S.heatmod += 0.5 // Heat shouldn't affect. Only Fire. - //S.punchstunthreshold = 8 //damage at which punches from this race will stun 9 S.punchdamagelow += 1 //lowest possible punch damage 0 S.punchdamagehigh += 1 //highest possible punch damage 9 - // Clown if(istype(H) && owner.assigned_role == "Clown") H.dna.remove_mutation(CLOWNMUT) to_chat(H, "As a vampiric clown, you are no longer a danger to yourself. Your nature is subdued.") @@ -215,8 +210,6 @@ CheckVampOrgans() // Heart, Eyes // Language owner.current.grant_language(/datum/language/vampiric) - // Soul - //owner.current.hellbound = TRUE Causes wierd stuff owner.hasSoul = FALSE // If false, renders the character unable to sell their soul. owner.isholy = FALSE // is this person a chaplain or admin role allowed to use bibles // Disabilities @@ -248,7 +241,6 @@ // Clown if(istype(H) && owner.assigned_role == "Clown") H.dna.add_mutation(CLOWNMUT) - // NOTE: Use initial() to return things to default! // Physiology owner.current.regenerate_organs() // Update Health @@ -264,13 +256,13 @@ set waitfor = FALSE if(!owner || !owner.current) return - vamplevel_unspent ++ + bloodsucker_level_unspent ++ // Spend Rank Immediately? if(istype(owner.current.loc, /obj/structure/closet/crate/coffin)) SpendRank() else to_chat(owner, "You have grown more ancient! Sleep in a coffin that you have claimed to thicken your blood and become more powerful.") - if(vamplevel_unspent >= 2) + if(bloodsucker_level_unspent >= 2) to_chat(owner, "Bloodsucker Tip: If you cannot find or steal a coffin to use, you can build one from wooden planks.
") /datum/antagonist/bloodsucker/proc/LevelUpPowers() @@ -279,10 +271,10 @@ /datum/antagonist/bloodsucker/proc/SpendRank() set waitfor = FALSE - if(vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current)) + if(bloodsucker_level_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current)) return var/mob/living/L = owner.current - level_bloodcost = maxBloodVolume * 0.2 + level_bloodcost = max_blood_volume * 0.2 //If the blood volume of the bloodsucker is lower than the cost to level up, return and inform the bloodsucker //TODO: Make this into a radial, or perhaps a tgui next UI @@ -298,7 +290,7 @@ if(options.len > 1) var/choice = input(owner.current, "You have the opportunity to grow more ancient at the cost of [level_bloodcost] units of blood. Select a power to advance your Rank.", "Your Blood Thickens...") in options // Cheat-Safety: Can't keep opening/closing coffin to spam levels - if(vamplevel_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal. + if(bloodsucker_level_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal. return if(!istype(owner.current.loc, /obj/structure/closet/crate/coffin)) to_chat(owner.current, "Return to your coffin to advance your Rank.") @@ -329,20 +321,20 @@ // More Health owner.current.setMaxHealth(owner.current.maxHealth + 10) // Vamp Stats - regenRate += 0.05 // Points of brute healed (starts at 0.3) - feedAmount += 2 // Increase how quickly I munch down vics (15) - maxBloodVolume += 100 // Increase my max blood (600) + regen_rate += 0.05 // Points of brute healed (starts at 0.3) + feed_amount += 2 // Increase how quickly I munch down vics (15) + max_blood_volume += 100 // Increase my max blood (600) ///////// - vamplevel ++ - vamplevel_unspent -- + bloodsucker_level ++ + bloodsucker_level_unspent -- // Assign True Reputation - if(vamplevel == 4) + if(bloodsucker_level == 4) SelectReputation(am_fledgling = FALSE, forced = TRUE) - to_chat(owner.current, "You are now a rank [vamplevel] Bloodsucker. Your strength, health, feed rate, regen rate, and maximum blood have all increased!") + to_chat(owner.current, "You are now a rank [bloodsucker_level] Bloodsucker. Your strength, health, feed rate, regen rate, can have up to [bloodsucker_level - count_vassals(owner.current.mind)] vassals, and maximum blood have all increased!") to_chat(owner.current, "Your existing powers have all ranked up as well!") update_hud(TRUE) - owner.current.playsound_local(null, 'sound/effects/pope_entry.ogg', 25, 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. + owner.current.playsound_local(null, 'sound/effects/pope_entry.ogg', 25, TRUE, pressure_affected = FALSE) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -654,13 +646,13 @@ var/datum/antagonist/vassal/mob_V = M.mind.has_antag_datum(ANTAG_DATUM_VASSAL) // Check 2) If they are a BLOODSUCKER, then are they my Master? if (mob_V && atom_B == mob_V.master) - return TRUE // SUCCESS! + return TRUE // Check 3) If I am a BLOODSUCKER, then are they my Vassal? if (mob_B && atom_V && (atom_V in mob_B.vassals)) - return TRUE // SUCCESS! + return TRUE // Check 4) If we are both VASSAL, then do we have the same master? if (atom_V && mob_V && atom_V.master == mob_V.master) - return TRUE // SUCCESS! + return TRUE return FALSE @@ -705,10 +697,10 @@ // Update Rank Counter if(owner.current.hud_used.vamprank_display) - var/valuecolor = vamplevel_unspent ? "#FFFF00" : "#FF0000" - owner.current.hud_used.vamprank_display.update_counter(vamplevel, valuecolor) + var/valuecolor = bloodsucker_level_unspent ? "#FFFF00" : "#FF0000" + owner.current.hud_used.vamprank_display.update_counter(bloodsucker_level, valuecolor) if(updateRank) // Only change icon on special request. - owner.current.hud_used.vamprank_display.icon_state = (vamplevel_unspent > 0) ? "rank_up" : "rank" + owner.current.hud_used.vamprank_display.icon_state = (bloodsucker_level_unspent > 0) ? "rank_up" : "rank" /obj/screen/bloodsucker @@ -718,12 +710,12 @@ invisibility = INVISIBILITY_ABSTRACT /obj/screen/bloodsucker/proc/update_counter(value, valuecolor) - invisibility = 0 // Make Visible + invisibility = 0 -/obj/screen/bloodsucker/blood_counter // NOTE: Look up /obj/screen/devil/soul_counter in _onclick / hud / human.dm - icon = 'icons/mob/actions/bloodsucker.dmi'//'icons/mob/screen_gen.dmi' +/obj/screen/bloodsucker/blood_counter + icon = 'icons/mob/actions/bloodsucker.dmi' name = "Blood Consumed" - icon_state = "blood_display"//"power_display" + icon_state = "blood_display" screen_loc = ui_blood_display /obj/screen/bloodsucker/blood_counter/update_counter(value, valuecolor) @@ -748,22 +740,27 @@ /datum/antagonist/bloodsucker/proc/update_sunlight(value, amDay = FALSE) // No Hud? Get out. - if (!owner.current.hud_used) + if(!owner.current.hud_used) return // Update Sun Time - if (owner.current.hud_used.sunlight_display) + if(owner.current.hud_used.sunlight_display) var/valuecolor = "#BBBBFF" - if (amDay) + if(amDay) valuecolor = "#FF5555" else if(value <= 25) valuecolor = "#FFCCCC" else if(value < 10) valuecolor = "#FF5555" - var/value_string = (value >= 60) ? "[round(value / 60, 1)] m" : "[round(value,1)] s" + var/value_string = (value >= 60) ? "[round(value / 60, 1)] m" : "[round(value, 1)] s" owner.current.hud_used.sunlight_display.update_counter( value_string, valuecolor ) owner.current.hud_used.sunlight_display.icon_state = "sunlight_" + (amDay ? "day":"night") /obj/screen/bloodsucker/sunlight_counter/update_counter(value, valuecolor) ..() - maptext = "
[value]
" + maptext = "
[value]
" + +/datum/antagonist/bloodsucker/proc/count_vassals(datum/mind/master) + var/datum/antagonist/bloodsucker/B = master.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + var/vassal_amount = B.vassals.len + return vassal_amount diff --git a/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm b/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm index e4e26fe034..640c53946f 100644 --- a/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm +++ b/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm @@ -5,7 +5,8 @@ var/obj/item/organ/O // Heart O = owner.current.getorganslot(ORGAN_SLOT_HEART) - if(!istype(O, /obj/item/organ/heart/vampheart)) + + if(!istype(O, /obj/item/organ/heart/vampheart) && !istype(O, /obj/item/organ/heart/demon)) qdel(O) var/obj/item/organ/heart/vampheart/H = new H.Insert(owner.current) diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm index a8925dfb7b..7998a33c7b 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm @@ -115,13 +115,15 @@ qdel(src) /obj/structure/bloodsucker/vassalrack/examine(mob/user) + var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) . = ..() - if(isvamp(user) || isobserver(user)) + if(B || isobserver(user)) . += {"This is the vassal rack, which allows you to thrall crewmembers into loyal minions in your service."} . += {"You need to first secure the vassal rack by clicking on it while it is in your lair."} . += {"Simply click and hold on a victim, and then drag their sprite on the vassal rack. Alt click on the vassal rack to unbuckle them."} . += {"Make sure that the victim is handcuffed, or else they can simply run away or resist, as the process is not instant."} . += {"To convert the victim, simply click on the vassal rack itself. Sharp weapons work faster than other tools."} + . += {" You have only the power for [B.bloodsucker_level - B.count_vassals(user.mind)] vassals"} /* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL) . += {"This is the vassal rack, which allows your master to thrall crewmembers into his minions.\n Aid your master in bringing their victims here and keeping them secure.\n @@ -130,7 +132,7 @@ /obj/structure/bloodsucker/vassalrack/MouseDrop_T(atom/movable/O, mob/user) if(!O.Adjacent(src) || O == user || !isliving(O) || !isliving(user) || useLock || has_buckled_mobs() || user.incapacitated()) return - if(!anchored && isvamp(user)) + if(!anchored && AmBloodsucker(user)) to_chat(user, "Until this rack is secured in place, it cannot serve its purpose.") return // PULL TARGET: Remember if I was pullin this guy, so we can restore this @@ -183,7 +185,7 @@ /obj/structure/bloodsucker/vassalrack/user_unbuckle_mob(mob/living/M, mob/user) // Attempt Unbuckle - if(!isvamp(user)) + if(!AmBloodsucker(user)) if(M == user) M.visible_message("[user] tries to release themself from the rack!",\ "You attempt to release yourself from the rack!") // For sound if not seen --> "You hear a squishy wet noise.") @@ -222,15 +224,15 @@ // Go away. Torturing. if(useLock) return - var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + var/datum/antagonist/bloodsucker/B = 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) + if(istype(B) && !owner) + if(!B.lair) to_chat(user, "You don't have a lair. Claim a coffin to make that location your lair.") - if(bloodsuckerdatum.lair != get_area(src)) - to_chat(user, "You may only activate this structure in your lair: [bloodsuckerdatum.lair].") + if(B.lair != get_area(src)) + to_chat(user, "You may only activate this structure in your lair: [B.lair].") return - switch(alert(user,"Do you wish to afix this structure here? Be aware you wont be able to unsecure it anymore","Secure [src]","Yes", "No")) + switch(alert(user,"Do you wish to afix this structure here? Be aware you wont be able to unsecure it anymore", "Secure [src]", "Yes", "No")) if("Yes") owner = user density = FALSE @@ -241,27 +243,31 @@ return // CHECK TWO: Am I a non-bloodsucker? var/mob/living/carbon/C = pick(buckled_mobs) - if(!istype(bloodsuckerdatum)) + if(!istype(B)) // 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) - if(istype(vassaldatum) && vassaldatum.master == bloodsuckerdatum || C.stat >= DEAD) + var/datum/antagonist/vassal/V = C.mind.has_antag_datum(ANTAG_DATUM_VASSAL) + if(istype(V) && V.master == B || C.stat >= DEAD) unbuckle_mob(C) useLock = FALSE // Failsafe return // Just torture the boy torture_victim(user, C) +#define CONVERT_COST 150 + /obj/structure/bloodsucker/vassalrack/proc/torture_victim(mob/living/user, mob/living/target) - var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) // Check Bloodmob/living/M, force = FALSE, check_loc = TRUE - var/convert_cost = 200 + 200 * bloodsuckerdatum.vassals - if(user.blood_volume < convert_cost + 5) + if(user.blood_volume < CONVERT_COST + 5) to_chat(user, "You don't have enough blood to initiate the Dark Communion with [target].") return + if(B.count_vassals(user.mind) > B.bloodsucker_level) + to_chat(user, "Your power is yet too weak to bring more vassals under your control....") + return // Prep... useLock = TRUE // Step One: Tick Down Conversion from 3 to 0 @@ -302,12 +308,13 @@ 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], you need [convert_cost - user.blood_volume] units more!") + if(user.blood_volume < CONVERT_COST) + to_chat(user, "You don't have enough blood to initiate the Dark Communion with [target], you need [CONVERT_COST - user.blood_volume] units more!") useLock = FALSE return - bloodsuckerdatum.AddBloodVolume(-convert_cost) - target.add_mob_blood(user) + B.AddBloodVolume(-CONVERT_COST) + target.add_mob_blood(user, "Youve used [CONVERT_COST] amount of blood to gain a new vassal!") + to_chat(user, ) user.visible_message("[user] marks a bloody smear on [target]'s forehead and puts a wrist up to [target.p_their()] mouth!", \ "You paint a bloody marking across [target]'s forehead, place your wrist to [target.p_their()] mouth, and subject [target.p_them()] to the Dark Communion.") if(!do_mob(user, src, 50)) @@ -315,21 +322,22 @@ useLock = FALSE return // Convert to Vassal! - if(bloodsuckerdatum && bloodsuckerdatum.attempt_turn_vassal(target)) + if(B && B.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 // return - user.playsound_local(null, 'sound/effects/explosion_distant.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. - target.playsound_local(null, 'sound/effects/explosion_distant.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. - target.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. + user.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE) + target.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE) + target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE) 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) +#undef CONVERT_COST +/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 @@ -454,7 +462,7 @@ /obj/structure/bloodsucker/candelabrum/examine(mob/user) . = ..() - if((isvamp()) || isobserver(user)) + if((AmBloodsucker(user)) || isobserver(user)) . += {"This is a magical candle which drains at the sanity of mortals who are not under your command while it is active."} . += {"You can alt click on it from any range to turn it on remotely, or simply be next to it and click on it to turn it on and off normally."} /* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL) @@ -463,12 +471,12 @@ /obj/structure/bloodsucker/candelabrum/attack_hand(mob/user) var/datum/antagonist/vassal/T = user.mind.has_antag_datum(ANTAG_DATUM_VASSAL) - if(isvamp(user) || istype(T)) + if(AmBloodsucker(user) || istype(T)) toggle() /obj/structure/bloodsucker/candelabrum/AltClick(mob/user) // Bloodsuckers can turn their candles on from a distance. SPOOOOKY. - if(isvamp(user)) + if(AmBloodsucker(user)) toggle() /obj/structure/bloodsucker/candelabrum/proc/toggle(mob/user) @@ -485,7 +493,7 @@ 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) - if(isvamp(H) || T) //We dont want vassals or vampires affected by this + if(AmBloodsucker(H) || T) //We dont want vassals or vampires affected by this return H.hallucination = 20 SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "vampcandle", /datum/mood_event/vampcandle) diff --git a/code/modules/antagonists/bloodsucker/powers/cloak.dm b/code/modules/antagonists/bloodsucker/powers/cloak.dm index 1bb7b02357..a616c39923 100644 --- a/code/modules/antagonists/bloodsucker/powers/cloak.dm +++ b/code/modules/antagonists/bloodsucker/powers/cloak.dm @@ -2,7 +2,7 @@ /datum/action/bloodsucker/cloak name = "Cloak of Darkness" - desc = "Blend into the shadows and become invisible to the untrained eye. Movement is slowed in brightly lit areas." + desc = "Blend into the shadows and become invisible to the untrained eye. Movement is slowed in brightly lit areas, and you cannot dissapear while mortals watch you." button_icon_state = "power_cloak" bloodcost = 5 cooldown = 50 diff --git a/code/modules/antagonists/bloodsucker/powers/feed.dm b/code/modules/antagonists/bloodsucker/powers/feed.dm index bbce221d91..8ac4fcebc1 100644 --- a/code/modules/antagonists/bloodsucker/powers/feed.dm +++ b/code/modules/antagonists/bloodsucker/powers/feed.dm @@ -140,7 +140,7 @@ to_chat(user, "You lean quietly toward [target] and secretly draw out your fangs...") else to_chat(user, "You pull [target] close to you and draw out your fangs...") - if(!do_mob(user, target, feed_time,0,1,extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10) + if(!do_mob(user, target, feed_time, 0, 1, extra_checks = CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10) to_chat(user, "Your feeding was interrupted.") //DeactivatePower(user,target) return @@ -166,7 +166,7 @@ var/deadmessage = target.stat == DEAD ? "" : " [target.p_they(TRUE)] looks dazed, and will not remember this." user.visible_message("[user] puts [target]'s wrist up to [user.p_their()] mouth.", \ "You secretly slip your fangs into [target]'s wrist.[deadmessage]", \ - vision_distance = notice_range, ignored_mobs=target) // Only people who AREN'T the target will notice this action. + vision_distance = notice_range, ignored_mobs = target) // Only people who AREN'T the target will notice this action. // Warn Feeder about Witnesses... var/was_unnoticed = TRUE for(var/mob/living/M in viewers(notice_range, owner)) @@ -257,11 +257,11 @@ to_chat(user, "Your victim is dead. [target.p_their(TRUE)] blood barely nourishes you.") warning_target_dead = TRUE // Full? - if(!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume) + if(!warning_full && user.blood_volume >= bloodsuckerdatum.max_blood_volume) to_chat(user, "You are full. Further blood will be wasted.") warning_full = TRUE // Blood Remaining? (Carbons/Humans only) - if(iscarbon(target) && !target.AmBloodsucker(1)) + if(iscarbon(target) && !AmBloodsucker(target, TRUE)) if(target.blood_volume <= BLOOD_VOLUME_BAD && warning_target_bloodvol > BLOOD_VOLUME_BAD) to_chat(user, "Your victim's blood volume is fatally low!") else if(target.blood_volume <= BLOOD_VOLUME_OKAY && warning_target_bloodvol > BLOOD_VOLUME_OKAY) @@ -275,8 +275,9 @@ break // Blood Gulp Sound - owner.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. - + owner.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE) + if(!amSilent) + target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE) // DONE! //DeactivatePower(user,target) if(amSilent) @@ -294,12 +295,12 @@ /datum/action/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target) - // Bad Vampire. You shouldn't do that. + // Bad Bloodsucker. You shouldn't do that. if(target && target.stat >= DEAD && ishuman(target)) SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankkilled", /datum/mood_event/drankkilled) // BAD // in bloodsucker_life.dm /datum/action/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target) - return ..() && target && (!target_grappled || user.pulling == target)// Active, and still Antag, + return ..() && target && (!target_grappled || user.pulling == target) && blood_sucking_checks(target, TRUE, TRUE) // Active, and still antag, // NOTE: We only care about pulling if target started off that way. Mostly only important for Aggressive feed. /datum/action/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target) diff --git a/code/modules/antagonists/bloodsucker/powers/fortitude.dm b/code/modules/antagonists/bloodsucker/powers/fortitude.dm index f0724f8204..a58034df0d 100644 --- a/code/modules/antagonists/bloodsucker/powers/fortitude.dm +++ b/code/modules/antagonists/bloodsucker/powers/fortitude.dm @@ -33,6 +33,15 @@ if(was_running) user.toggle_move_intent() while(bloodsuckerdatum && ContinueActive(user) || user.m_intent == MOVE_INTENT_RUN) + if(istype(user.buckled, /obj/vehicle)) //We dont want people using fortitude being able to use vehicles + var/obj/vehicle/V = user.buckled + var/datum/component/riding/VRD = V.GetComponent(/datum/component/riding) + if(VRD) + VRD.force_dismount(user) + to_chat(user, "You trip off the [V], your muscles too heavy for it to support you.") + else + V.unbuckle_mob(user, force = TRUE) + to_chat(user, "You fall off the [V], your weight making you too heavy to be supported by it.") // 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. diff --git a/code/modules/food_and_drinks/food/snacks_bread.dm b/code/modules/food_and_drinks/food/snacks_bread.dm index 204e5ce455..99fd2af9bb 100644 --- a/code/modules/food_and_drinks/food/snacks_bread.dm +++ b/code/modules/food_and_drinks/food/snacks_bread.dm @@ -179,6 +179,18 @@ tastes = list("bread" = 1) foodtype = GRAIN +/obj/item/reagent_containers/food/snacks/garlicbread + name = "garlic bread" + desc = "Alas, it is limited." + icon = 'icons/obj/food/burgerbread.dmi' + icon_state = "garlicbread" + item_state = "garlicbread" + bonus_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 2) + list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin= 4, /datum/reagent/consumable/garlic = 2) + bitesize = 3 + tastes = list("bread" = 1, "garlic" = 1, "butter" = 1) + foodtype = GRAIN + /obj/item/reagent_containers/food/snacks/deepfryholder name = "Deep Fried Foods Holder Obj" desc = "If you can see this description the code for the deep fryer fucked up." diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm index a7cad1d7bb..d02ad0f1a0 100644 --- a/code/modules/food_and_drinks/food/snacks_meat.dm +++ b/code/modules/food_and_drinks/food/snacks_meat.dm @@ -207,7 +207,7 @@ name = "raw khinkali" desc = "One hundred khinkalis? Do I look like a pig?" icon_state = "khinkali" - list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1) + list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1, /datum/reagent/consumable/garlic = 1) cooked_type = /obj/item/reagent_containers/food/snacks/khinkali tastes = list("meat" = 1, "onions" = 1, "garlic" = 1) foodtype = MEAT @@ -216,7 +216,7 @@ name = "khinkali" desc = "One hundred khinkalis? Do I look like a pig?" icon_state = "khinkali" - list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/vitamin = 2) + list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/garlic = 1) bitesize = 3 filling_color = "#F0F0F0" tastes = list("meat" = 1, "onions" = 1, "garlic" = 1) diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm index c3890b28eb..335078eb4c 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm @@ -125,6 +125,16 @@ result = /obj/item/reagent_containers/food/snacks/baguette subcategory = CAT_BREAD +/datum/crafting_recipe/food/garlicbread + name = "Garlic Bread" + time = 40 + reqs = list(/obj/item/reagent_containers/food/snacks/grown/garlic = 1, + /obj/item/reagent_containers/food/snacks/breadslice/plain = 1, + /obj/item/reagent_containers/food/snacks/butter = 1 + ) + result = /obj/item/reagent_containers/food/snacks/garlicbread + subcategory = CAT_BREAD + /datum/crafting_recipe/food/butterbiscuit name = "Butter Biscuit" reqs = list( diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm index 528fc61156..385d7fa359 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm @@ -37,7 +37,8 @@ name = "Raw Khinkali" reqs = list( /obj/item/reagent_containers/food/snacks/doughslice = 1, - /obj/item/reagent_containers/food/snacks/faggot = 1 + /obj/item/reagent_containers/food/snacks/faggot = 1, + /obj/item/reagent_containers/food/snacks/grown/garlic = 1 ) result = /obj/item/reagent_containers/food/snacks/rawkhinkali subcategory = CAT_MISCFOOD diff --git a/code/modules/hydroponics/grown/garlic.dm b/code/modules/hydroponics/grown/garlic.dm new file mode 100644 index 0000000000..4184b85008 --- /dev/null +++ b/code/modules/hydroponics/grown/garlic.dm @@ -0,0 +1,29 @@ +/obj/item/seeds/garlic + name = "pack of garlic seeds" + desc = "A packet of extremely pungent seeds." + icon_state = "seed-garlic" + species = "garlic" + plantname = "Garlic Sprouts" + product = /obj/item/reagent_containers/food/snacks/grown/garlic + yield = 6 + potency = 25 + growthstages = 3 + growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' + reagents_add = list(/datum/reagent/consumable/garlic = 0.15, /datum/reagent/consumable/nutriment = 0.1) + +/obj/item/reagent_containers/food/snacks/grown/garlic + seed = /obj/item/seeds/garlic + name = "garlic" + desc = "Delicious, but with a potentially overwhelming odor." + icon_state = "garlic" + filling_color = "#C0C9A0" + bitesize_mod = 2 + tastes = list("garlic" = 1) + wine_power = 10 + +/obj/item/clothing/neck/garlic_necklace + name = "garlic necklace" + desc = "A clove of garlic on a cable, tied to itself in a circle, just might fit around your neck. For loonies people who fear getting their blood sucked." + icon_state = "garlic_necklace" + item_state = "garlic_necklace" + \ No newline at end of file diff --git a/code/modules/hydroponics/grown/onion.dm b/code/modules/hydroponics/grown/onion.dm index 2ebaa6d5e2..a75b9caf5f 100644 --- a/code/modules/hydroponics/grown/onion.dm +++ b/code/modules/hydroponics/grown/onion.dm @@ -14,7 +14,7 @@ weed_chance = 3 growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) - mutatelist = list(/obj/item/seeds/onion/red) + mutatelist = list(/obj/item/seeds/onion/red, /obj/item/seeds/garlic) /obj/item/reagent_containers/food/snacks/grown/onion seed = /obj/item/seeds/onion diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 3769f9eacc..aeddf771b8 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -78,7 +78,7 @@ make_podman = 1 break else - if(M.ckey == ckey && M.stat == DEAD && !M.suiciding) + if(M.ckey == ckey && M.stat == DEAD && !M.suiciding && AmBloodsucker(M)) make_podman = 1 if(isliving(M)) var/mob/living/L = M diff --git a/code/modules/language/vampiric.dm b/code/modules/language/vampiric.dm index 6da54ce844..ab48a17d2f 100644 --- a/code/modules/language/vampiric.dm +++ b/code/modules/language/vampiric.dm @@ -1,4 +1,4 @@ -// VAMPIRE LANGUAGE // +// BLOODSUCKER LANGUAGE // /datum/language/vampiric name = "Blah-Sucker" diff --git a/code/modules/mining/equipment/regenerative_core.dm b/code/modules/mining/equipment/regenerative_core.dm index ae451ba1a8..c14aa097bb 100644 --- a/code/modules/mining/equipment/regenerative_core.dm +++ b/code/modules/mining/equipment/regenerative_core.dm @@ -26,8 +26,8 @@ slot = "hivecore" force = 0 actions_types = list(/datum/action/item_action/organ_action/use) - var/inert = 0 - var/preserved = 0 + var/inert + var/preserved /obj/item/organ/regenerative_core/Initialize() . = ..() @@ -38,7 +38,9 @@ go_inert() /obj/item/organ/regenerative_core/proc/preserved(implanted = 0) - inert = FALSE + if(inert) + name = initial(name) + inert = FALSE preserved = TRUE update_icon() desc = "All that remains of a hivelord. It is preserved, allowing you to use it to heal completely without danger of decay." @@ -69,14 +71,15 @@ /obj/item/organ/regenerative_core/afterattack(atom/target, mob/user, proximity_flag) . = ..() - if(proximity_flag && ishuman(target)) + if(proximity_flag) + apply_healing_core(target, user) + +/obj/item/organ/regenerative_core/proc/apply_healing_core(atom/target, mob/user) + if(ishuman(target)) var/mob/living/carbon/human/H = target if(inert) to_chat(user, "[src] has decayed and can no longer be used to heal.") return - if(isvamp(user)) - to_chat(user, "[src] breaks down as it fails to heal your unholy self") - return else if(H.stat == DEAD) to_chat(user, "[src] are useless on the dead.") @@ -87,22 +90,16 @@ else to_chat(user, "You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.") SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self")) - H.revive(full_heal = 1) + if(AmBloodsucker(H)) + H.revive(full_heal = FALSE) + else + H.revive(full_heal = TRUE) qdel(src) user.log_message("[user] used [src] to heal [H]! Wake the fuck up, Samurai!", LOG_ATTACK, color="green") //Logging for 'old' style legion core use, when clicking on a sprite of yourself or another. /obj/item/organ/regenerative_core/attack_self(mob/user) //Knouli's first hack! Allows for the use of the core in hand rather than needing to click on the target, yourself, to selfheal. Its a rip of the proc just above - but skips on distance check and only uses 'user' rather than 'target' - if(ishuman(user)) //Check if user is human, no need for distance check as it's self heal - var/mob/living/carbon/human/H = user //Set H to user rather than target - if(inert) //Inert cores are useless - to_chat(user, "[src] has decayed and can no longer be used to heal.") - return - else //Skip on check if the target to be healed is dead as, if you are dead, you're not going to be able to use it on yourself! - to_chat(user, "You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.") - SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self")) - H.revive(full_heal = 1) - qdel(src) - H.log_message("[H] used [src] to heal themselves! Making use of Knouli's sexy and intelligent use-in-hand proc!", LOG_ATTACK, color="green") //Logging for 'new' style legion core use, when using the core in-hand. + . = ..() + apply_healing_core(user) /obj/item/organ/regenerative_core/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index 6947ab28f8..eb1b38b9ff 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -247,13 +247,13 @@ /proc/CanHug(mob/living/M) if(!istype(M)) - return 0 + return FALSE if(M.stat == DEAD) - return 0 + return FALSE if(M.getorgan(/obj/item/organ/alien/hivenode)) - return 0 - if(isvamp(M)) - return 0 + return FALSE + if(AmBloodsucker(M)) + return FALSE if(ismonkey(M)) return 1 @@ -262,9 +262,9 @@ if(ishuman(C) && !(SLOT_WEAR_MASK in C.dna.species.no_equip)) var/mob/living/carbon/human/H = C if(H.is_mouth_covered(head_only = 1)) - return 0 - return 1 - return 0 + return FALSE + return TRUE + return FALSE #undef MIN_ACTIVE_TIME #undef MAX_ACTIVE_TIME diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index d3f262403b..40b8de36c5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -854,7 +854,7 @@ /mob/living/carbon/proc/can_defib() var/tlimit = DEFIB_TIME_LIMIT * 10 var/obj/item/organ/heart = getorgan(/obj/item/organ/heart) - if(suiciding || hellbound || HAS_TRAIT(src, TRAIT_HUSK)) + if(suiciding || hellbound || HAS_TRAIT(src, TRAIT_HUSK) || AmBloodsucker(src)) return if((world.time - timeofdeath) > tlimit) return diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index c04167a61f..775f36cfc7 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -43,7 +43,7 @@ C.faction |= "slime" /datum/species/jelly/spec_life(mob/living/carbon/human/H) - if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for vampires + if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for blooduskers return if(!H.blood_volume) H.blood_volume += 5 diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 7c5f0f473a..415cd9889c 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -81,6 +81,9 @@ if(H.blood_volume >= BLOOD_VOLUME_MAXIMUM) to_chat(H, "You're already full!") return + //This checks whether or not they are wearing a garlic clove on their neck + if(!blood_sucking_checks(victim, TRUE, FALSE)) + return if(victim.stat == DEAD) to_chat(H, "You need a living victim!") return @@ -92,6 +95,9 @@ to_chat(victim, "[H] tries to bite you, but stops before touching you!") to_chat(H, "[victim] is blessed! You stop just in time to avoid catching fire.") return + //Here we check now for both the garlic cloves on the neck and for blood in the victims bloodstream. + if(!blood_sucking_checks(victim, TRUE, TRUE)) + return if(!do_after(H, 30, target = victim)) return var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 6ec8e0cfd2..138d7f155e 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -11,6 +11,7 @@ speed = 0 maxHealth = 250 health = 250 + blood_volume = 0 gender = NEUTER mob_biotypes = NONE diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 4d9d15ae5c..ffc0970bdf 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -353,7 +353,7 @@ if(m_intent == MOVE_INTENT_RUN) m_intent = MOVE_INTENT_WALK else - if (HAS_TRAIT(src,TRAIT_NORUNNING)) // FULPSTATION 7/10/19 So you can't run during fortitude. + if (HAS_TRAIT(src,TRAIT_NORUNNING)) to_chat(src, "You find yourself unable to run.") return FALSE m_intent = MOVE_INTENT_RUN diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 7695ef77be..5f2edd5206 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -284,7 +284,7 @@ if(L.mind) L.mind.transfer_to(S) if(owner) - to_chat(S, "You are an animate statue. You cannot move when monitored, but are nearly invincible and deadly when unobserved! Do not harm [owner], your creator.") + to_chat(S, "You are an animated statue. You cannot move when monitored, but are nearly invincible and deadly when unobserved! Do not harm [owner], your creator.") P.forceMove(S) return else diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 384a113b27..5eb5b94de9 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -214,7 +214,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) //For easy bloodsucker disgusting and blood removal /datum/reagent/proc/disgust_bloodsucker(mob/living/carbon/C, disgust, blood_change, blood_puke = TRUE, force) - if(isvamp(C)) + if(AmBloodsucker(C)) var/datum/antagonist/bloodsucker/bloodsuckerdatum = C.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) if(disgust) bloodsuckerdatum.handle_eat_human_food(disgust, blood_puke, force) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index da461ef4ff..7ee233b449 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -579,7 +579,7 @@ All effects don't start immediately, but rather get worse over time; the rate is value = 1.3 /datum/reagent/consumable/ethanol/bloody_mary/on_mob_life(mob/living/carbon/C) - if(isvamp(C)) + if(AmBloodsucker(C)) disgust_bloodsucker(FALSE, 1) //Bloodsuckers get SOME blood from it, for style reasons. if(C.blood_volume < (BLOOD_VOLUME_NORMAL*C.blood_ratio)) C.blood_volume = min((BLOOD_VOLUME_NORMAL*C.blood_ratio), C.blood_volume + 3) //Bloody Mary quickly restores blood loss. diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index fa30609c54..c003fc7111 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -18,6 +18,7 @@ /datum/reagent/consumable/on_mob_life(mob/living/carbon/M) current_cycle++ M.nutrition += nutriment_factor + M.CheckBloodsuckerEatFood(nutriment_factor) holder.remove_reagent(type, metabolization_rate) /datum/reagent/consumable/reaction_mob(mob/living/M, method=TOUCH, reac_volume) @@ -423,6 +424,50 @@ M.emote(pick("twitch","giggle")) ..() +/datum/reagent/consumable/garlic //NOTE: having garlic in your blood stops vampires from biting you. + name = "Garlic Juice" + //id = "garlic" + description = "Crushed garlic. Chefs love it, but it can make you smell bad." + color = "#FEFEFE" + taste_description = "garlic" + metabolization_rate = 0.15 * REAGENTS_METABOLISM + +/datum/reagent/consumable/garlic/on_mob_life(mob/living/carbon/M) + if(isvampire(M)) //incapacitating but not lethal. Unfortunately, vampires cannot vomit. + if(prob(min(25, current_cycle))) + to_chat(M, "You can't get the scent of garlic out of your nose! You can barely think...") + M.Stun(10) + M.Jitter(10) + return + + else if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.job == "Cook") + if(prob(20)) //stays in the system much longer than sprinkles/banana juice, so heals slower to partially compensate + H.heal_bodypart_damage(1, 1, 0) + . = 1 + ..() + +/datum/reagent/consumable/garlic/reaction_mob(mob/living/M, method, reac_volume) + if(AmBloodsucker(M, TRUE)) //Theyll be immune to garlic as long as they masquarade, but they cant do it if they already have it. + switch(method) + if(INGEST) + if(prob(min(30, current_cycle))) + to_chat(M, "You cant get the smell of garlic out of your nose! You cant think straight because of it!") + M.Jitter(15) + if(prob(min(15, current_cycle))) + M.visible_message("Something you ate is burning your stomach!", "[M] clutches their stomach and falls to the ground!") + M.Knockdown(20) + M.emote("scream") + if(prob(min(5, current_cycle)) && iscarbon(M)) + var/mob/living/carbon/C + C.vomit() + if(INJECT) + if(prob(min(20, current_cycle))) + to_chat(M, "You feel like your veins are boiling!") + M.emote("scream") + M.adjustFireLoss(5) + ..() /datum/reagent/consumable/sprinkles name = "Sprinkles" value = 3 diff --git a/icons/mob/clothing/neck.dmi b/icons/mob/clothing/neck.dmi index 68fde7bff9..78073222ca 100644 Binary files a/icons/mob/clothing/neck.dmi and b/icons/mob/clothing/neck.dmi differ diff --git a/icons/obj/clothing/neck.dmi b/icons/obj/clothing/neck.dmi index 622f43ea56..c4c9c94f48 100644 Binary files a/icons/obj/clothing/neck.dmi and b/icons/obj/clothing/neck.dmi differ diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi index 712ea11a3b..c93865ca77 100644 Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi index e746d8f43d..c7c31581f3 100644 Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi index 43e231cbab..62843e3f54 100644 Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ diff --git a/modular_citadel/code/modules/reagents/objects/clothes.dm b/modular_citadel/code/modules/reagents/objects/clothes.dm index 4707d5b460..34af39bbe0 100644 --- a/modular_citadel/code/modules/reagents/objects/clothes.dm +++ b/modular_citadel/code/modules/reagents/objects/clothes.dm @@ -5,7 +5,7 @@ name = "Synthetic hat" icon = 'icons/obj/clothing/hats.dmi' icon_state = "cowboy" - desc = "A sythesized hat, you can't seem to take it off. And tips their hat." + desc = "A synthesized hat, you can't seem to take it off. And tips their hat." armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) //item_flags = NODROP //Tips their hat! diff --git a/tgstation.dme b/tgstation.dme index 5d0ca735bc..d7fa983a7c 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1972,6 +1972,7 @@ #include "code\modules\hydroponics\grown\cotton.dm" #include "code\modules\hydroponics\grown\eggplant.dm" #include "code\modules\hydroponics\grown\flowers.dm" +#include "code\modules\hydroponics\grown\garlic.dm" #include "code\modules\hydroponics\grown\grass_carpet.dm" #include "code\modules\hydroponics\grown\kudzu.dm" #include "code\modules\hydroponics\grown\melon.dm"