diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 4bd268ca2547e..2844ad94387b8 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -4439,6 +4439,11 @@ /area/abductor_ship) "alj" = ( /obj/structure/closet/abductor, +/obj/item/reagent_containers/glass/bottle/chloralhydrate, +/obj/item/reagent_containers/glass/bottle/chloralhydrate, +/obj/item/reagent_containers/glass/bottle/morphine, +/obj/item/reagent_containers/glass/bottle/morphine, +/obj/item/reagent_containers/glass/bottle/morphine, /turf/open/floor/plating/abductor, /area/abductor_ship) "alk" = ( diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index cda67caaab80f..8028ef989bc08 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -4,7 +4,7 @@ /// an attack must do this much damage after armor in order to roll for being a wound (incremental pressure damage need not apply) #define WOUND_MINIMUM_DAMAGE 5 /// an attack must do this much damage after armor in order to be eliigible to dismember a suitably mushed bodypart -#define DISMEMBER_MINIMUM_DAMAGE 10 +#define DISMEMBER_MINIMUM_DAMAGE 20 /// any damage dealt over this is ignored for damage rolls unless the target has the frail quirk (35^1.4=145) #define WOUND_MAX_CONSIDERED_DAMAGE 35 diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index d97ddde00a011..e231084cfec93 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -241,10 +241,9 @@ GLOBAL_LIST_EMPTY(uplinks) if (!user || user.incapacitated()) return if(U.hijack_only) - if(!(usr.mind.special_role == ROLE_OPERATIVE) || !(usr.mind.special_role == "nukie mid") || !(usr.mind.special_role == "Lone Operative"))//nukies get items that regular traitors only get with hijack. If a hijack-only item is not for nukies, then exclude it via the gamemode list. - if(!(locate(/datum/objective/hijack) in usr.mind.get_all_objectives()) || !(locate(/datum/objective/martyr) in usr.mind.get_all_objectives())) - to_chat(usr, "InteQ выдает этот чрезвычайно опасный предмет только агентам, получившим особо сложное задание.") - return + if(!(usr.mind.special_role == ROLE_OPERATIVE) || !(usr.mind.special_role == "nukie mid") || !(usr.mind.special_role == "Lone Operative") || !(locate(/datum/objective/hijack) in usr.mind.get_all_objectives()) || !(locate(/datum/objective/martyr) in usr.mind.get_all_objectives()))//nukies get items that regular traitors only get with hijack. If a hijack-only item is not for nukies, then exclude it via the gamemode list. + to_chat(usr, "InteQ выдает этот чрезвычайно опасный предмет только агентам, получившим особо сложное задание.") + return if(telecrystals < U.cost || U.limited_stock == 0) return diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm index b5b55c1e14ae4..39203e922d428 100644 --- a/code/datums/diseases/advance/symptoms/flesh_eating.dm +++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm @@ -85,7 +85,6 @@ Bonus */ /datum/symptom/flesh_death - name = "Autophagocytosis Necrosis" desc = "The virus rapidly consumes infected cells, leading to heavy and widespread damage." stealth = -2 diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 0dc08eeedbcc5..e5d91736845aa 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -33,13 +33,15 @@ name = "Infectious Zombie" id = "memezombies" limbs_id = SPECIES_ZOMBIE - inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_NOSOFTCRIT, TRAIT_FAKEDEATH) + inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_NOSOFTCRIT,TRAIT_FAKEDEATH) mutanthands = /obj/item/zombie_hand armor = 20 // 120 damage to KO a zombie, which kills it speedmod = 1.6 // they're very slow + burnmod = 0.75 + brutemod = 0.75 mutanteyes = /obj/item/organ/eyes/night_vision/zombie blacklisted_quirks = list(/datum/quirk/nonviolent) - var/heal_rate = 1 + var/heal_rate = 5 var/regen_cooldown = 0 /datum/species/zombie/infectious/check_roundstart_eligible() diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm index d53d729630627..697884025cf2e 100644 --- a/code/modules/reagents/reagent_containers/bottle.dm +++ b/code/modules/reagents/reagent_containers/bottle.dm @@ -254,7 +254,7 @@ // Viro bottles /obj/item/reagent_containers/glass/bottle/romerol - name = "romerol bottle" + name = "Romerol Bottle" desc = "A small bottle of Romerol. The REAL zombie powder." list_reagents = list(/datum/reagent/romerol = 30) diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm index a755b1c127770..37aaad554d85a 100644 --- a/code/modules/zombie/organs.dm +++ b/code/modules/zombie/organs.dm @@ -1,5 +1,5 @@ /obj/item/organ/zombie_infection - name = "festering ooze" + name = "Festering Ooze" desc = "A black web of pus and viscera." zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_ZOMBIE @@ -23,57 +23,61 @@ GLOB.zombie_infection_list -= src . = ..() -/obj/item/organ/zombie_infection/Insert(var/mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) +/obj/item/organ/zombie_infection/Insert(mob/living/carbon/organ_mob, special, drop_if_replaced) . = ..() - // BLUEMOON ADD START - роботы вообще не могут быть зомби - if(owner.mob_biotypes & MOB_ROBOTIC) - qdel(src) - return - // BLUEMOON ADD END + START_PROCESSING(SSobj, src) -/obj/item/organ/zombie_infection/Remove(special = FALSE) - if(owner) - if(iszombie(owner) && old_species) - owner.set_species(old_species) - if(timer_id) - deltimer(timer_id) +/obj/item/organ/zombie_infection/Remove(mob/living/carbon/M, special = FALSE) + . = ..() + STOP_PROCESSING(SSobj, src) + if(iszombie(M) && old_species && !special) + M.set_species(old_species) + if(timer_id) + deltimer(timer_id) + +/obj/item/organ/zombie_infection/Insert(mob/living/carbon/organ_owner, special) + . = ..() + RegisterSignal(organ_owner, COMSIG_LIVING_DEATH, PROC_REF(organ_owner_died)) + +/obj/item/organ/zombie_infection/Remove(mob/living/carbon/organ_owner, special) . = ..() - STOP_PROCESSING(SSobj, src) //Required to be done after the parent call to avoid conflicts with organ decay. + UnregisterSignal(organ_owner, COMSIG_LIVING_DEATH) + +/obj/item/organ/zombie_infection/proc/organ_owner_died(mob/living/carbon/source, gibbed) + SIGNAL_HANDLER + if(iszombie(source)) + qdel(src) // Congrats you somehow died so hard you stopped being a zombie /obj/item/organ/zombie_infection/on_find(mob/living/finder) - to_chat(finder, "Inside the head is a disgusting black \ + to_chat(finder, span_warning("Inside the head is a disgusting black \ web of pus and viscera, bound tightly around the brain like some \ - biological harness.") + biological harness.")) -/obj/item/organ/zombie_infection/process() +/obj/item/organ/zombie_infection/process(seconds_per_tick, times_fired) if(!owner) return if(!(src in owner.internal_organs)) - INVOKE_ASYNC(src,.proc/Remove,owner) + Remove(owner) if(owner.mob_biotypes & MOB_MINERAL)//does not process in inorganic things return if (causes_damage && !iszombie(owner) && owner.stat != DEAD) - owner.adjustToxLoss(1) - if (prob(10)) - to_chat(owner, "You feel sick...") - if(timer_id) - return - if(owner.suiciding) + owner.adjustToxLoss(0.5 * seconds_per_tick) + if (SPT_PROB(5, seconds_per_tick)) + to_chat(owner, span_danger("You feel sick...")) + if(timer_id || !owner.getorgan(/obj/item/organ/brain)) return if(owner.stat != DEAD && !converts_living) return - if(!owner.getorgan(/obj/item/organ/brain)) - return if(!iszombie(owner)) - to_chat(owner, "You can feel your heart stopping, but something isn't right... \ - life has not abandoned your broken form. You can only feel a deep and immutable hunger that \ - not even death can stop, you will rise again!") + to_chat(owner, "Кажется, ваше сердце остановилось... однако что-то здесь не так! \ + Жизнь не желает покидать вашу оболочку... что-то поддерживает вашу жизнь и это что-то вызывает у вас непреодолимый голод. \ + Ничего, даже смерть, не сможет убить вас!") var/revive_time = rand(revive_time_min, revive_time_max) var/flags = TIMER_STOPPABLE - timer_id = addtimer(CALLBACK(src, .proc/zombify), revive_time, flags) + timer_id = addtimer(CALLBACK(src, PROC_REF(zombify), owner), revive_time, flags) -/obj/item/organ/zombie_infection/proc/zombify() +/obj/item/organ/zombie_infection/proc/zombify(mob/living/carbon/target) timer_id = null if(!converts_living && owner.stat != DEAD) @@ -81,9 +85,9 @@ if(!iszombie(owner)) old_species = owner.dna.species.type - owner.set_species(/datum/species/zombie/infectious) + target.set_species(/datum/species/zombie/infectious) - var/stand_up = (owner.stat == DEAD) || (owner.stat == UNCONSCIOUS) + var/stand_up = (target.stat == DEAD) || (target.stat == UNCONSCIOUS) //Fully heal the zombie's damage the first time they rise owner.setToxLoss(0, 0) @@ -93,13 +97,13 @@ if(!owner.revive()) return - owner.grab_ghost() - owner.visible_message("[owner] suddenly convulses, as [owner.ru_who()][stand_up ? " stagger to [owner.ru_ego()] feet and" : ""] gain a ravenous hunger in [owner.ru_ego()] eyes!", "You HUNGER!") - playsound(owner.loc, 'sound/hallucinations/far_noise.ogg', 50, 1) - owner.do_jitter_animation(living_transformation_time) - owner.Stun(living_transformation_time) - to_chat(owner, "You are now a zombie! You claw and bite, turning your fellow crewmembers into friends that help spread the plague.") - to_chat(owner, "You are a zombie. Please act like one. Letting the crew remove the tumor inside your brain is a dick move to whoever infected you. Please do not do it.") + owner.visible_message("[owner] suddenly convulses, as [owner.p_they()][stand_up ? " stagger to [owner.p_their()] feet and" : ""] gain a ravenous hunger in [owner.p_their()] eyes!", "You HUNGER!") + + to_chat(target, span_alien("You HUNGER!")) + to_chat(target, span_alertalien("You are now a zombie! Do not seek to be cured, do not help any non-zombies in any way, do not harm your zombie brethren and spread the disease by killing others. You are a creature of hunger and violence.")) + playsound(target, 'sound/hallucinations/far_noise.ogg', 50, 1) + target.do_jitter_animation(living_transformation_time) + target.Stun(living_transformation_time) /obj/item/organ/zombie_infection/nodamage causes_damage = FALSE diff --git a/modular_bluemoon/shower_trait/shower_trait.dm b/modular_bluemoon/shower_trait/shower_trait.dm index d8ee0986368a1..a60344df7f28e 100644 --- a/modular_bluemoon/shower_trait/shower_trait.dm +++ b/modular_bluemoon/shower_trait/shower_trait.dm @@ -16,8 +16,8 @@ mood_quirk = TRUE var/cleanse_level = CLEAN //уровень чистоты персонажа - var/warning_level = 0 // предупреждения для игрока в чат. Обнуляются при достижении чистоты в 100 и меньше var/doing_shower = FALSE // оповещение, что персонаж вошёл в душ и игроку нужно подождать, пока он не станет чистым + var/warning_level = 0 // предупреждения для игрока в чат. Обнуляются при достижении чистоты в 100 и меньше /datum/quirk/bluemoon_shower_need/on_spawn() . = ..() @@ -42,7 +42,7 @@ if(DIRTY to VERY_DIRTY) SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "need_shower", /datum/mood_event/need_shower/dirty) if(warning_level < 2) - to_chat(quirk_holder, span_warning("Мне нужно сходить в душ.")) + to_chat(quirk_holder, span_phobia("Мне нужно сходить в душ.")) warning_level = 2 if(VERY_DIRTY to INFINITY) SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "need_shower", /datum/mood_event/need_shower/very_dirty) @@ -60,17 +60,20 @@ SIGNAL_HANDLER var/cleaning_efficiency = 10 // 3.5~ минуты с 1000 + if(cleanse_level <= 10) // снижение нагрузки, чтобы стояние куклы под душем с этим квирком не генерило постоянно все проверки внизу + return + if(!check_for_clothing()) to_chat(quirk_holder, span_warning("Нужно снять одежду, не подходящую для душа! Бюстгалтер и трусы допустимы.")) return var/area/A = get_area(quirk_holder) - if(A in typesof(/area/security/prison, /area/commons/toilet, /area/command/heads_quarters/captain, /area/commons/dorms, /area/command/blueshielquarters, /area/service/chapel/main/monastery, /area/mine/laborcamp)) + if(A.type in typesof(/area/security/prison, /area/commons/toilet, /area/command/heads_quarters/captain, /area/commons/dorms, /area/command/blueshielquarters, /area/service/chapel/main/monastery, /area/mine/laborcamp)) if(!doing_shower && warning_level != 0) - to_chat(quirk_holder, span_notice("Теперь постоять под душем и помыться...")) + to_chat(quirk_holder, span_notice("Теперь только подождать... Есть время разгрузить голову и расслабиться.")) doing_shower = TRUE cleaning_efficiency = 20 // 1.7~ минут с 1000 - else + else // За поставленный в неподходящей зоне душ и мытьё там штраф if(!doing_shower && warning_level != 0) to_chat(quirk_holder, span_warning("Я смогу помыться, но это место плохо подходит для душевой и это будет в два раза дольше. Дормиторий, уборные, личные каюты подходят куда лучше...")) doing_shower = TRUE @@ -83,26 +86,27 @@ if(holder.w_shirt) // мыться в футболках нельзя if(!(holder.w_shirt.type in typesof(/obj/item/clothing/underwear/shirt/bra, /obj/item/clothing/underwear/shirt/top))) // мыться в лифчике можно - return FALSE + return if(holder.back) // мыться с рюкзаком нельзя - return FALSE + return if(holder.gloves) // мыться в перчатках нельзя if(!(holder.gloves.type in typesof(/obj/item/clothing/accessory/ring))) // с кольцами можно - return FALSE + return if(holder.w_uniform) // мыться в униформе нельзя if(holder.w_uniform.body_parts_covered & CHEST) // можно, если униформа закрывает грудь - return FALSE + return if(holder.wear_suit) // мыться в костюме нельзя - return FALSE + return if(!get_location_accessible(holder, BODY_ZONE_HEAD)) // мыться в шапочке нельзя - return FALSE + return + if(!get_location_accessible(holder, BODY_ZONE_PRECISE_L_FOOT)) // мыться в обуви нельзя - return FALSE + return return TRUE // в наушниках, очках, галстуках, части нижнего белья можно мыться @@ -120,7 +124,7 @@ mood_change = -2 /datum/mood_event/need_shower/very_dirty - description = span_phobia("Мне ОЧЕНЬ нужно сходить в душ!\n") + description = span_boldwarning("Мне ОЧЕНЬ нужно сходить в душ!\n") mood_change = -4 /* @@ -147,7 +151,7 @@ return var/matrix/M = matrix() M.Scale(0.6) - overlay = image('modular_bluemoon/shower_trait/steam.dmi', "steam_single", pixel_y = 12, layer = -FIRE_LAYER) + overlay = image('modular_bluemoon/shower_trait/stink.dmi', "steam_single", pixel_y = 12, layer = -FIRE_LAYER) overlay.transform = M owner.add_overlay(overlay) @@ -155,3 +159,11 @@ owner.cut_overlay(overlay) overlay = null return ..() + +#undef STATUS_EFFECT_STINK + +#undef CLEAN +#undef FINE_CLEAN +#undef FIRST_WARNING +#undef DIRTY +#undef VERY_DIRTY diff --git a/modular_bluemoon/shower_trait/stink.dmi b/modular_bluemoon/shower_trait/stink.dmi new file mode 100644 index 0000000000000..16bbc8d8804b6 Binary files /dev/null and b/modular_bluemoon/shower_trait/stink.dmi differ