diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 81ee5c3989..1464927c3a 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -243,6 +243,11 @@ description = "I have been scorched by the unforgiving rays of the sun.\n" mood_change = -6 timeout = 15 MINUTES + +/datum/mood_event/bloodsucker_disgust + description = "Something I recently ate was horrifyingly disgusting.\n" + mood_change = -5 + timeout = 5 MINUTES /datum/mood_event/nanite_sadness description = "+++++++HAPPINESS SUPPRESSION+++++++\n" diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm index 0179c60ef1..e774cf4250 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm @@ -315,7 +315,7 @@ bloodsuckerdatum.handle_eat_human_food(food_nutrition) -/datum/antagonist/bloodsucker/proc/handle_eat_human_food(var/food_nutrition) // Called from snacks.dm and drinks.dm +/datum/antagonist/bloodsucker/proc/handle_eat_human_food(food_nutrition, puke_blood = TRUE, masquerade_override) // Called from snacks.dm and drinks.dm set waitfor = FALSE if(!owner.current || !iscarbon(owner.current)) return @@ -324,14 +324,14 @@ C.nutrition -= food_nutrition foodInGut += food_nutrition // Already ate some bad clams? Then we can back out, because we're already sick from it. - if (foodInGut != food_nutrition) + if(foodInGut != food_nutrition) return // Haven't eaten, but I'm in a Human Disguise. - else if (poweron_masquerade) + else if(poweron_masquerade && !masquerade_override) to_chat(C, "Your stomach turns, but your \"human disguise\" keeps the food down...for now.") // Keep looping until we purge. If we have activated our Human Disguise, we ignore the food. But it'll come up eventually... var/sickphase = 0 - while (foodInGut) + while(foodInGut) sleep(50) C.adjust_disgust(10 * sickphase) // Wait an interval... @@ -340,24 +340,29 @@ if(C.stat == DEAD) return // Put up disguise? Then hold off the vomit. - if(poweron_masquerade) + if(poweron_masquerade && !masquerade_override) if(sickphase > 0) to_chat(C, "Your stomach settles temporarily. You regain your composure...for now.") sickphase = 0 continue switch(sickphase) - if (1) + if(1) to_chat(C, "You feel unwell. You can taste ash on your tongue.") C.Stun(10) - if (2) + if(2) to_chat(C, "Your stomach turns. Whatever you ate tastes of grave dirt and brimstone.") C.Dizzy(15) C.Stun(13) - if (3) + if(3) to_chat(C, "You purge the food of the living from your viscera! You've never felt worse.") - C.vomit(foodInGut * 4, foodInGut * 2, 0) // (var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1, var/toxic = 0) - C.blood_volume = max(0, C.blood_volume - foodInGut * 2) + //Puke blood only if puke_blood is true, and loose some blood, else just puke normally. + if(puke_blood) + C.blood_volume = max(0, C.blood_volume - foodInGut * 2) + C.vomit(foodInGut * 4, foodInGut * 2, 0) + else + C.vomit(foodInGut * 4, FALSE, 0) C.Stun(30) //C.Dizzy(50) foodInGut = 0 + SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "vampdisgust", /datum/mood_event/bloodsucker_disgust) sickphase ++ diff --git a/code/modules/hydroponics/grown/tomato.dm b/code/modules/hydroponics/grown/tomato.dm index 53c3389695..d3525c951d 100644 --- a/code/modules/hydroponics/grown/tomato.dm +++ b/code/modules/hydroponics/grown/tomato.dm @@ -36,7 +36,7 @@ plantname = "Blood-Tomato Plants" product = /obj/item/reagent_containers/food/snacks/grown/tomato/blood mutatelist = list() - reagents_add = list(/datum/reagent/blood = 0.2, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) + reagents_add = list(/datum/reagent/blood/tomato = 0.2, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) rarity = 20 /obj/item/reagent_containers/food/snacks/grown/tomato/blood @@ -47,7 +47,7 @@ splat_type = /obj/effect/gibspawner/generic filling_color = "#FF0000" foodtype = FRUIT | GROSS - grind_results = list(/datum/reagent/consumable/ketchup = 0, /datum/reagent/blood = 0) + grind_results = list(/datum/reagent/consumable/ketchup = 0, /datum/reagent/blood/tomato = 0) distill_reagent = /datum/reagent/consumable/ethanol/bloody_mary // Blue Tomato diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 4aabd82d6a..bd6c37973f 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -221,3 +221,13 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) rs += "[R.name], [R.volume]" return rs.Join(" | ") + +//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)) + var/datum/antagonist/bloodsucker/bloodsuckerdatum = C.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + if(disgust) + bloodsuckerdatum.handle_eat_human_food(disgust, blood_puke, force) + if(blood_change) + bloodsuckerdatum.AddBloodVolume(blood_change) + diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 4b65776ce9..e22f8caf89 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -579,8 +579,8 @@ 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((HAS_TRAIT(C, TRAIT_NOMARROW))) - return + if(isvamp(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/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index adc30ecdc9..9794b58112 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -13,7 +13,7 @@ shot_glass_icon_state = "shotglassred" pH = 7.4 -/datum/reagent/blood/reaction_mob(mob/living/L, method=TOUCH, reac_volume) +/datum/reagent/blood/reaction_mob(mob/living/L, method = TOUCH, reac_volume) if(data && data["viruses"]) for(var/thing in data["viruses"]) var/datum/disease/D = thing @@ -26,6 +26,18 @@ else //ingest, patch or inject L.ForceContractDisease(D) + if(data["blood_type"] == "SY") + //Synthblood is very disgusting to bloodsuckers. They will puke it out to expel it, unless they have masquarade on + switch(reac_volume) + if(0 to 3) + disgust_bloodsucker(L, 3, FALSE, FALSE, FALSE) + if(3 to 6) + //If theres more than 8 units, they will start expelling it, even if they are masquarading. + disgust_bloodsucker(L, 5, FALSE, FALSE, TRUE) + else + //If they have too much in them, they will also puke out their blood. + disgust_bloodsucker(L, 7, -5, TRUE, TRUE) + if(iscarbon(L)) var/mob/living/carbon/C = L var/blood_id = C.get_blood_id() @@ -37,10 +49,8 @@ L.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) /datum/reagent/blood/on_mob_life(mob/living/carbon/C) //Because lethals are preferred over stamina. damnifino. - if((HAS_TRAIT(C, TRAIT_NOMARROW))) - return //We dont want vampires getting toxed from blood var/blood_id = C.get_blood_id() - if((blood_id == /datum/reagent/blood || blood_id == /datum/reagent/blood/jellyblood)) + if((blood_id in GLOB.blood_reagent_types) && !HAS_TRAIT(C, TRAIT_NOMARROW)) if(!data || !(data["blood_type"] in get_safe_blood(C.dna.blood_type))) //we only care about bloodtype here because this is where the poisoning should be C.adjustToxLoss(rand(2,8)*REM, TRUE, TRUE) //forced to ensure people don't use it to gain beneficial toxin as slime person ..() @@ -117,7 +127,7 @@ if(!istype(D, /datum/disease/advance)) preserve += D data["viruses"] = preserve - return 1 + return TRUE /datum/reagent/blood/proc/get_diseases() . = list() @@ -142,6 +152,13 @@ taste_mult = 1.3 pH = 4 +/datum/reagent/blood/tomato + data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null) + name = "Tomato Blood" + description = "This highly resembles blood, but it doesnt actually function like it, resembling more ketchup, with a more blood-like consistency." + taste_description = "sap" //Like tree sap? + pH = 7.45 + /datum/reagent/blood/jellyblood/on_mob_life(mob/living/carbon/M) if(prob(10)) if(M.dna?.species?.exotic_bloodtype != "GEL") diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index 2f5fb067ea..3296586c94 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -89,7 +89,7 @@ blood_type = "BUG" /obj/item/reagent_containers/blood/attackby(obj/item/I, mob/user, params) - if (istype(I, /obj/item/pen) || istype(I, /obj/item/toy/crayon)) + if(istype(I, /obj/item/pen) || istype(I, /obj/item/toy/crayon)) if(!user.is_literate()) to_chat(user, "You scribble illegibly on the label of [src]!") return @@ -107,25 +107,31 @@ 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)) +/obj/item/reagent_containers/blood/attack(mob/living/carbon/C, mob/user, def_zone) + if(user.a_intent == INTENT_HELP && reagents.total_volume > 0 && iscarbon(C) && user.a_intent == INTENT_HELP) + if(C.is_mouth_covered()) + to_chat(user, "You cant drink from the [src] while your mouth is covered.") + return + if(user != C) + user.visible_message("[user] forces [C] to drink from the [src].", \ + "You force [C] to drink from the [src]") + if(!do_mob(user, C, 50)) return else - if(!do_mob(user, M, 10)) + if(!do_mob(user, C, 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/gulp_size = 3 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) + reagents.reaction(C, INGEST, fraction) //checkLiked(fraction, M) // Blood isn't food, sorry. + reagents.trans_to(C, gulp_size) + reagents.remove_reagent(src, 2) //Inneficency, so hey, IVs are usefull. + playsound(C.loc,'sound/items/drink.ogg', rand(10, 50), TRUE) + return ..() /obj/item/reagent_containers/blood/bluespace @@ -133,3 +139,14 @@ 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! + +/obj/item/reagent_containers/blood/bluespace/attack(mob/living/carbon/C, mob/user, def_zone) + if(user.a_intent == INTENT_HELP) + if(user != C) + to_chat(user, "You can't force people to drink from the [src]. Nothing comes out from it.") + return + else + to_chat(user, "You try to suck on the [src], but nothing comes out.") + return + else + ..()