From 3146c794bfdf4491b294bac51ad172deb3fba734 Mon Sep 17 00:00:00 2001 From: nmajask Date: Thu, 10 Mar 2022 03:21:25 -0500 Subject: [PATCH 1/5] Pacifist stechkin Gives pacifists who order stechkins from uplinks get a version loaded with soporific rounds. --- code/modules/projectiles/guns/ballistic.dm | 6 +++++- code/modules/projectiles/guns/ballistic/pistol.dm | 5 +++++ code/modules/uplink/uplink_items.dm | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index d513772e19af..fb978991b098 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -167,10 +167,14 @@ bolt_locked = TRUE update_icon() return + load_starting_mag() + update_icon() + +/obj/item/gun/ballistic/proc/load_starting_mag() if (!magazine) magazine = new mag_type(src) chamber_round() - update_icon() + /obj/item/gun/ballistic/update_icon() if (QDELETED(src)) diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index 853d0b633727..8b5416e68348 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -31,6 +31,11 @@ var/obj/item/suppressor/S = new(src) install_suppressor(S) +/obj/item/gun/ballistic/automatic/pistol/pacifist/load_starting_mag() + if (!magazine) + magazine = new /obj/item/ammo_box/magazine/m10mm/sp(src) + chamber_round() + /obj/item/gun/ballistic/automatic/pistol/m1911 name = "\improper M1911" desc = "A classic .45 handgun with a small magazine capacity." diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index a8835d61f0c5..9fb169fbebb0 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -517,6 +517,11 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 6 exclude_modes = list(/datum/game_mode/nuclear/clown_ops) +/datum/uplink_item/dangerous/pistol/spawn_item(spawn_path, mob/user, datum/component/uplink/U) + if(HAS_TRAIT(user, TRAIT_PACIFISM)) + spawn_path = /obj/item/gun/ballistic/automatic/pistol/pacifist + ..() + /datum/uplink_item/dangerous/bolt_action name = "Surplus Rifle" desc = "A horribly outdated bolt action weapon. You've got to be desperate to use this." From 0911b25f62fe5937171b0f8a5f84eed6132fad99 Mon Sep 17 00:00:00 2001 From: nmajask Date: Thu, 10 Mar 2022 03:48:29 -0500 Subject: [PATCH 2/5] Alerts the user Alerts the user of the change of ammunition --- code/modules/uplink/uplink_items.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 9fb169fbebb0..9655ed98925c 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -520,6 +520,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) /datum/uplink_item/dangerous/pistol/spawn_item(spawn_path, mob/user, datum/component/uplink/U) if(HAS_TRAIT(user, TRAIT_PACIFISM)) spawn_path = /obj/item/gun/ballistic/automatic/pistol/pacifist + to_chat(user, span_notice("Your employer has loaded your purchased weapon with non-leathal ammunition")) ..() /datum/uplink_item/dangerous/bolt_action From d9c104635c37bcc4b1c8f65a2b0f04e46af41e70 Mon Sep 17 00:00:00 2001 From: nmajask Date: Thu, 10 Mar 2022 14:01:10 -0500 Subject: [PATCH 3/5] Merge branch 'sleepy-round-stuff' of https://github.com/nmajask/Yogstation-But-Worse into sleepy-round-stuff --- code/_onclick/hud/horror.dm | 36 +- .../antagonists/horror/horror_chemicals.dm | 190 ++--- .../antagonists/horror/horror_datums.dm | 666 +++++++++--------- .../modules/antagonists/horror/horror_html.dm | 202 +++--- .../antagonists/horror/horror_mutate.dm | 192 ++--- code/modules/clothing/under/_under.dm | 3 + code/modules/events/horror.dm | 66 +- .../file_system/programs/crew_monitor.dm | 2 +- html/changelog.html | 2 + html/changelogs/.all_changelog.yml | 2 + 10 files changed, 684 insertions(+), 677 deletions(-) diff --git a/code/_onclick/hud/horror.dm b/code/_onclick/hud/horror.dm index 876dc00be9ca..a9043b5754a5 100644 --- a/code/_onclick/hud/horror.dm +++ b/code/_onclick/hud/horror.dm @@ -1,18 +1,18 @@ -/obj/screen/horror_chemicals - name = "chemicals" - icon_state = "horror_counter" - screen_loc = ui_lingchemdisplay - -/datum/hud/chemical_counter - ui_style = 'icons/mob/screen_midnight.dmi' - var/obj/screen/horror_chemicals/chemical_counter - -/datum/hud/chemical_counter/New(mob/owner) - . = ..() - chemical_counter = new /obj/screen/horror_chemicals - infodisplay += chemical_counter - -/datum/hud/chemical_counter/Destroy() - . = ..() - QDEL_NULL(chemical_counter) - +/obj/screen/horror_chemicals + name = "chemicals" + icon_state = "horror_counter" + screen_loc = ui_lingchemdisplay + +/datum/hud/chemical_counter + ui_style = 'icons/mob/screen_midnight.dmi' + var/obj/screen/horror_chemicals/chemical_counter + +/datum/hud/chemical_counter/New(mob/owner) + . = ..() + chemical_counter = new /obj/screen/horror_chemicals + infodisplay += chemical_counter + +/datum/hud/chemical_counter/Destroy() + . = ..() + QDEL_NULL(chemical_counter) + diff --git a/code/modules/antagonists/horror/horror_chemicals.dm b/code/modules/antagonists/horror/horror_chemicals.dm index d0c6bdc4e04b..50cfdafb7f60 100644 --- a/code/modules/antagonists/horror/horror_chemicals.dm +++ b/code/modules/antagonists/horror/horror_chemicals.dm @@ -1,96 +1,96 @@ -/mob/living/simple_animal/horror/Topic(href, href_list, hsrc) - if(href_list["horror_use_chem"]) - locate(href_list["src"]) - if(!istype(src, /mob/living/simple_animal/horror)) - return - - var/topic_chem = href_list["horror_use_chem"] - var/datum/horror_chem/C - - for(var/datum in typesof(/datum/horror_chem)) - var/datum/horror_chem/test = new datum() - if(test.chemname == topic_chem) - C = test - break - - if(!istype(C, /datum/horror_chem)) - return - - if(!C || !victim || controlling || !src || stat) - return - - if(!istype(C, /datum/horror_chem)) - return - - if(chemicals < C.chemuse) - to_chat(src, span_boldnotice("You need [C.chemuse] chemicals stored to use this chemical!")) - return - - to_chat(src, span_danger("You squirt a measure of [C.chemname] from your reservoirs into [victim]'s bloodstream.")) - victim.reagents.add_reagent(C.R, C.quantity) - chemicals -= C.chemuse - log_game("[src]/([src.ckey]) has injected [C.chemname] into their host [victim]/([victim.ckey])") - - src << output(chemicals, "ViewHorror\ref[src]Chems.browser:update_chemicals") - - ..() - -/datum/horror_chem - var/chemname - var/chem_desc = "This is a chemical" - var/datum/reagent/R - var/chemuse = 30 - var/quantity = 10 - -/datum/horror_chem/epinephrine - chemname = "epinephrine" - R = /datum/reagent/medicine/epinephrine - chem_desc = "Stabilizes critical condition and slowly restores oxygen damage." - -/datum/horror_chem/mannitol - chemname = "mannitol" - R = /datum/reagent/medicine/mannitol - chem_desc = "Heals brain damage." - -/datum/horror_chem/bicaridine - chemname = "bicaridine" - R = /datum/reagent/medicine/bicaridine - chem_desc = "Heals brute damage." - -/datum/horror_chem/kelotane - chemname = "kelotane" - R = /datum/reagent/medicine/kelotane - chem_desc = "Heals burn damage." - -/datum/horror_chem/charcoal - chemname = "charcoal" - R = /datum/reagent/medicine/charcoal - chem_desc = "Slowly heals toxin damage, while also slowly removing any other chemicals." - -/datum/horror_chem/adrenaline - chemname = "adrenaline" - R = /datum/reagent/medicine/changelingadrenaline - chemuse = 100 - chem_desc = "Stimulates the brain, shrugging off effect of stuns while regenerating stamina." - -/datum/horror_chem/rezadone - chemname = "rezadone" - R = /datum/reagent/medicine/rezadone - chemuse = 50 - chem_desc = "Heals cellular damage." - -/datum/horror_chem/pen_acid - chemname = "pentetic acid" - R = /datum/reagent/medicine/pen_acid - chemuse = 50 - chem_desc = "Reduces massive amounts of radiation and toxin damage while purging other chemicals from the body." - -/datum/horror_chem/sal_acid - chemname = "salicyclic acid" - R = /datum/reagent/medicine/sal_acid - chem_desc = "Stimulates the healing of severe bruises. Rapidly heals severe bruising and slowly heals minor ones." - -/datum/horror_chem/oxandrolone - chemname = "oxandrolone" - R = /datum/reagent/medicine/oxandrolone +/mob/living/simple_animal/horror/Topic(href, href_list, hsrc) + if(href_list["horror_use_chem"]) + locate(href_list["src"]) + if(!istype(src, /mob/living/simple_animal/horror)) + return + + var/topic_chem = href_list["horror_use_chem"] + var/datum/horror_chem/C + + for(var/datum in typesof(/datum/horror_chem)) + var/datum/horror_chem/test = new datum() + if(test.chemname == topic_chem) + C = test + break + + if(!istype(C, /datum/horror_chem)) + return + + if(!C || !victim || controlling || !src || stat) + return + + if(!istype(C, /datum/horror_chem)) + return + + if(chemicals < C.chemuse) + to_chat(src, span_boldnotice("You need [C.chemuse] chemicals stored to use this chemical!")) + return + + to_chat(src, span_danger("You squirt a measure of [C.chemname] from your reservoirs into [victim]'s bloodstream.")) + victim.reagents.add_reagent(C.R, C.quantity) + chemicals -= C.chemuse + log_game("[src]/([src.ckey]) has injected [C.chemname] into their host [victim]/([victim.ckey])") + + src << output(chemicals, "ViewHorror\ref[src]Chems.browser:update_chemicals") + + ..() + +/datum/horror_chem + var/chemname + var/chem_desc = "This is a chemical" + var/datum/reagent/R + var/chemuse = 30 + var/quantity = 10 + +/datum/horror_chem/epinephrine + chemname = "epinephrine" + R = /datum/reagent/medicine/epinephrine + chem_desc = "Stabilizes critical condition and slowly restores oxygen damage." + +/datum/horror_chem/mannitol + chemname = "mannitol" + R = /datum/reagent/medicine/mannitol + chem_desc = "Heals brain damage." + +/datum/horror_chem/bicaridine + chemname = "bicaridine" + R = /datum/reagent/medicine/bicaridine + chem_desc = "Heals brute damage." + +/datum/horror_chem/kelotane + chemname = "kelotane" + R = /datum/reagent/medicine/kelotane + chem_desc = "Heals burn damage." + +/datum/horror_chem/charcoal + chemname = "charcoal" + R = /datum/reagent/medicine/charcoal + chem_desc = "Slowly heals toxin damage, while also slowly removing any other chemicals." + +/datum/horror_chem/adrenaline + chemname = "adrenaline" + R = /datum/reagent/medicine/changelingadrenaline + chemuse = 100 + chem_desc = "Stimulates the brain, shrugging off effect of stuns while regenerating stamina." + +/datum/horror_chem/rezadone + chemname = "rezadone" + R = /datum/reagent/medicine/rezadone + chemuse = 50 + chem_desc = "Heals cellular damage." + +/datum/horror_chem/pen_acid + chemname = "pentetic acid" + R = /datum/reagent/medicine/pen_acid + chemuse = 50 + chem_desc = "Reduces massive amounts of radiation and toxin damage while purging other chemicals from the body." + +/datum/horror_chem/sal_acid + chemname = "salicyclic acid" + R = /datum/reagent/medicine/sal_acid + chem_desc = "Stimulates the healing of severe bruises. Rapidly heals severe bruising and slowly heals minor ones." + +/datum/horror_chem/oxandrolone + chemname = "oxandrolone" + R = /datum/reagent/medicine/oxandrolone chem_desc = "Stimulates the healing of severe burns. Rapidly heals severe burns and slowly heals minor ones." \ No newline at end of file diff --git a/code/modules/antagonists/horror/horror_datums.dm b/code/modules/antagonists/horror/horror_datums.dm index 3ab9138356a4..6f75827e090a 100644 --- a/code/modules/antagonists/horror/horror_datums.dm +++ b/code/modules/antagonists/horror/horror_datums.dm @@ -1,333 +1,333 @@ -//ANTAG DATUMS -/datum/antagonist/horror - name = "Horror" - show_in_antagpanel = TRUE - prevent_roundtype_conversion = FALSE - show_name_in_check_antagonists = TRUE - show_to_ghosts = TRUE - var/datum/mind/summoner - -/datum/antagonist/horror/on_gain() - . = ..() - give_objectives() - if(ishorror(owner.current) && owner.current.mind) - var/mob/living/simple_animal/horror/H = owner.current - H.update_horror_hud() - -/datum/antagonist/horror/proc/give_objectives() - if(summoner) - var/datum/objective/newobjective = new - newobjective.explanation_text = "Serve your summoner, [summoner.name]." - newobjective.owner = owner - newobjective.completed = TRUE - objectives += newobjective - else - //succ some souls - var/datum/objective/horrorascend/ascend = new - ascend.owner = owner - ascend.hor = owner.current - ascend.target_amount = rand(5, 8) - objectives += ascend - ascend.update_explanation_text() - - //looking for antagonist we can assist - var/list/possible_targets = list() - for(var/datum/mind/M in SSticker.minds) - if(M.current && M.current.stat != DEAD) - if(ishuman(M.current)) - if(M.special_role) - possible_targets += M - - if(possible_targets.len) - var/datum/mind/M = pick(possible_targets) - var/datum/objective/protect/O = new - O.owner = owner - O.target = M - O.explanation_text = "Protect and assist \the [M.current.real_name], the [M.assigned_role]." - objectives += O - - - //don't die while you're at is - var/datum/objective/survive/survive = new - survive.owner = owner - objectives += survive - -/datum/objective/horrorascend - name = "consume souls" - var/mob/living/simple_animal/horror/hor - -/datum/objective/horrorascend/update_explanation_text() - . = ..() - explanation_text = "Consume [target_amount] souls." - -/datum/objective/horrorascend/check_completion() - if(hor && hor.consumed_souls >= target_amount) - return TRUE - return FALSE - - -//SPAWNER -/obj/item/horrorspawner - name = "suspicious pet carrier" - desc = "It contains some sort of creature inside. You can see tentacles sticking out of it." - icon = 'icons/obj/pet_carrier.dmi' - lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' - righthand_file = 'icons/mob/inhands/items_righthand.dmi' - item_state = "pet_carrier" - icon_state = "pet_carrier_occupied" - var/used = FALSE - color = rgb(130, 105, 160) - -/obj/item/horrorspawner/attack_self(mob/living/user) - if(used) - to_chat(user, "The pet carrier appears unresponsive.") - return - used = TRUE - to_chat(user, "You're attempting to wake up the creature inside the box...") - sleep(5 SECONDS) - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the eldritch horror in service of [user.real_name]?", ROLE_HORROR, null, FALSE, 100) - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) - var/mob/living/simple_animal/horror/H = new /mob/living/simple_animal/horror(get_turf(src)) - H.key = C.key - H.mind.enslave_mind_to_creator(user) - H.mind.add_antag_datum(C) - H.mind.memory += "You are " + span_purple(span_bold("[H.real_name]")) + ", an eldritch horror. Consume souls to evolve.
" - var/datum/antagonist/horror/S = new - S.summoner = user.mind - S.antag_memory += "[user.mind] woke you from your eternal slumber. Aid them in their objectives as a token of gratitude.
" - H.mind.add_antag_datum(S) - log_game("[key_name(user)] has summoned [key_name(H)], an eldritch horror.") - to_chat(user, span_bold("[H.real_name] has awoken into your service!")) - used = TRUE - icon_state = "pet_carrier_open" - sleep(5) - var/obj/item/horrorsummonhorn/horn = new /obj/item/horrorsummonhorn(get_turf(src)) - horn.summoner = user.mind - horn.horror = H - to_chat(user, span_notice("A strange looking [horn] falls out of [src]!")) - else - to_chat(user, "The creatures looks at you with one of it's eyes before going back to slumber.") - used = FALSE - return - -//Summoning horn -/obj/item/horrorsummonhorn - name = "old horn" - desc = "A very old horn. You feel an incredible urge to blow into it." - icon = 'icons/obj/items_and_weapons.dmi' - lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' - righthand_file = 'icons/mob/inhands/items_righthand.dmi' - item_state = "horn" - icon_state = "horn" - var/datum/mind/summoner - var/mob/living/simple_animal/horror/horror - var/cooldown - -/obj/item/horrorsummonhorn/examine(mob/user) - . = ..() - if(user.mind == summoner) - to_chat(user, span_purple("Blowing into this horn will recall the horror back to you. Be wary, the horn is loud, and may attract unwanted attention.")) - -/obj/item/horrorsummonhorn/attack_self(mob/living/user) - if(cooldown > world.time) - to_chat(user, span_notice("Take a breath before you blow [src] again.")) - return - to_chat(user, span_notice("You take a deep breath and prepare to blow into [src]...")) - if(do_mob(user, src, 10 SECONDS)) - if(cooldown > world.time) - return - cooldown = world.time + 10 SECONDS - to_chat(src, span_notice("You blow the horn...")) - playsound(loc, "sound/items/airhorn.ogg", 100, 1, 30) - var/turf/summonplace = get_turf(src) - sleep(5 SECONDS) - if(prob(20)) //yeah you're summoning an eldritch horror allright - new /obj/effect/temp_visual/summon(summonplace) - sleep(10) - var/type = pick(typesof(/mob/living/simple_animal/hostile/abomination)) - var/mob/R = new type(summonplace) - playsound(summonplace, "sound/effects/phasein.ogg", 30) - summonplace.visible_message(span_danger("[R] emerges!")) - else - if(!horror || horror.stat == DEAD) - summonplace.visible_message(span_danger("But nothing responds to the call!")) - else - new /obj/effect/temp_visual/summon(summonplace) - sleep(10) - horror.leave_victim() - horror.forceMove(summonplace) - playsound(summonplace, "sound/effects/phasein.ogg", 30) - summonplace.visible_message(span_notice("[horror] appears out of nowhere!")) - if(user.mind != summoner) - sleep(2 SECONDS) - playsound(summonplace, "sound/effects/glassbr2.ogg", 30, 1) - to_chat(user, span_danger("[src] breaks!")) - qdel(src) -/obj/item/horrorsummonhorn/suicide_act(mob/living/user) //"I am the prettiest unicorn that ever was!" ~Spy 2013 - user.visible_message(span_suicide("[user] stabs [user.p_their()] forehead with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) - return BRUTELOSS -//Tentacle arm -/obj/item/horrortentacle - name = "tentacle" - desc = "A long, slimy, arm-like appendage." - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "horrortentacle" - item_state = "tentacle" - lefthand_file = 'icons/mob/inhands/antag/horror_lefthand.dmi' - righthand_file = 'icons/mob/inhands/antag/horror_righthand.dmi' - resistance_flags = ACID_PROOF - force = 17 - item_flags = ABSTRACT | DROPDEL - weapon_stats = list(SWING_SPEED = 1, ENCUMBRANCE = 0, ENCUMBRANCE_TIME = 0, REACH = 2, DAMAGE_LOW = 0, DAMAGE_HIGH = 0) - range_cooldown_mod = 0 //tentacle is designed to hit from range - hitsound = 'sound/weapons/whip.ogg' -/obj/item/horrortentacle/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) -/obj/item/horrortentacle/examine(mob/user) - . = ..() - to_chat(user, span_velvet(span_bold("Functions:"))) - to_chat(user, span_velvet("All attacks work up to 2 tiles away.")) - to_chat(user, span_velvet("Help intent: Usual help function of an arm.")) - to_chat(user, span_velvet("Disarm intent: Whips the tentacle, disarming your opponent.")) - to_chat(user, span_velvet("Grab intent: Instant aggressive grab on an opponent. Can also throw them!")) - to_chat(user, span_velvet("Harm intent: Whips the tentacle, damaging your opponent.")) - to_chat(user, span_velvet("Also functions to pry open unbolted airlocks.")) -/obj/item/horrortentacle/attack(atom/target, mob/living/user) - if(isliving(target)) - user.Beam(target,"purpletentacle",time=5) - var/mob/living/L = target - switch(user.a_intent) - if(INTENT_HELP) - L.attack_hand(user) - return - if(INTENT_GRAB) - if(L != user) - L.grabbedby(user) - L.grippedby(user, instant = TRUE) - L.Knockdown(30) - return - if(INTENT_DISARM) - if(iscarbon(L)) - var/mob/living/carbon/C = L - var/obj/item/I = C.get_active_held_item() - if(I) - if(C.dropItemToGround(I)) - playsound(loc, "sound/weapons/whipgrab.ogg", 30) - target.visible_message(span_danger("[I] is whipped out of [C]'s hand by [user]!"),span_userdanger("A tentacle whips [I] out of your hand!")) - return - else - to_chat(user, span_danger("You can't seem to pry [I] off [C]'s hands!")) - return - else - C.attack_hand(user) - return - . = ..() -/obj/item/horrortentacle/afterattack(atom/target, mob/user, proximity) - if(isliving(user.pulling) && user.pulling != target) - var/mob/living/H = user.pulling - user.visible_message(span_warning("[user] throws [H] with [user.p_their()] [src]!"), span_warning("You throw [H] with [src].")) - H.throw_at(target, 8, 2) - H.Knockdown(30) - return - if(!proximity) - return - if(istype(target, /obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/A = target - if((!A.requiresID() || A.allowed(user)) && A.hasPower()) - return - if(A.locked) - to_chat(user, span_warning("The airlock's bolts prevent it from being forced!")) - return - if(A.hasPower()) - user.visible_message(span_warning("[user] jams [src] into the airlock and starts prying it open!"), span_warning("You start forcing the airlock open."), - span_italics("You hear a metal screeching sound.")) - playsound(A, 'sound/machines/airlock_alien_prying.ogg', 150, 1) - if(!do_after(user, 10 SECONDS, target = A)) - return - user.visible_message(span_warning("[user] forces the airlock to open with [user.p_their()] [src]!"), span_warning("You force the airlock to open."), - span_italics("You hear a metal screeching sound.")) - A.open(2) - return - . = ..() -/obj/item/horrortentacle/suicide_act(mob/user) //this will never be called, since horror stops suicide, but might as well if they get tentacle through other means - user.visible_message(span_suicide("[src] coils itself around [user] tightly gripping [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide!")) - return (OXYLOSS) -//Pinpointer -/obj/screen/alert/status_effect/agent_pinpointer/horror - name = "Soul locator" - desc = "Find your target soul." -/datum/status_effect/agent_pinpointer/horror - id = "horror_pinpointer" - minimum_range = 0 - range_fuzz_factor = 0 - tick_interval = 20 - alert_type = /obj/screen/alert/status_effect/agent_pinpointer/horror -/datum/status_effect/agent_pinpointer/horror/scan_for_target() - return -//TRAPPED MIND - when horror takes control over your body, you become a mute trapped mind -/mob/living/captive_brain - name = "host brain" - real_name = "host brain" - var/datum/action/innate/resist_control/R - var/mob/living/simple_animal/horror/H - -/mob/living/captive_brain/Initialize(mapload, gen=1) - ..() - R = new - R.Grant(src) - -/mob/living/captive_brain/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) - if(client) - if(client.prefs.muted & MUTE_IC) - to_chat(src, span_danger("You cannot speak in IC (muted).")) - return - if(client.handle_spam_prevention(message,MUTE_IC)) - return - if(ishorror(loc)) - message = sanitize(message) - if(!message) - return - if(stat == 2) - return say_dead(message) - to_chat(src, span_alien(span_italics("You whisper silently, \"[message]\""))) - to_chat(H.victim, span_alien(span_italics("[src] whispers, \"[message]\""))) - for(var/M in GLOB.dead_mob_list) - if(isobserver(M)) - var/rendered = span_changeling("[src] transfers: \"[message]\"") - var/link = FOLLOW_LINK(M, H.victim) - to_chat(M, "[link] [rendered]") - -/mob/living/captive_brain/emote(act, m_type = null, message = null, intentional = FALSE) - return - -/datum/action/innate/resist_control - name = "Resist control" - desc = "Try to take back control over your brain. A strong nerve impulse should do it." - background_icon_state = "bg_ecult" - icon_icon = 'icons/mob/actions/actions_horror.dmi' - button_icon_state = "resist_control" - -/datum/action/innate/resist_control/Activate() - var/mob/living/captive_brain/B = owner - if(B) - B.try_resist() - -/mob/living/captive_brain/resist() - try_resist() - -/mob/living/captive_brain/proc/try_resist() - var/delay = rand(20 SECONDS,30 SECONDS) - if(H.horrorupgrades["deep_control"]) - delay += rand(20 SECONDS,30 SECONDS) - to_chat(src, span_danger("You begin doggedly resisting the parasite's control.")) - to_chat(H.victim, span_danger("You feel the captive mind of [src] begin to resist your control.")) - addtimer(CALLBACK(src, .proc/return_control), delay) - -/mob/living/captive_brain/proc/return_control() - if(!H || !H.controlling) - return - to_chat(src, span_userdanger("With an immense exertion of will, you regain control of your body!")) - to_chat(H.victim, span_danger("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) - H.detatch() +//ANTAG DATUMS +/datum/antagonist/horror + name = "Horror" + show_in_antagpanel = TRUE + prevent_roundtype_conversion = FALSE + show_name_in_check_antagonists = TRUE + show_to_ghosts = TRUE + var/datum/mind/summoner + +/datum/antagonist/horror/on_gain() + . = ..() + give_objectives() + if(ishorror(owner.current) && owner.current.mind) + var/mob/living/simple_animal/horror/H = owner.current + H.update_horror_hud() + +/datum/antagonist/horror/proc/give_objectives() + if(summoner) + var/datum/objective/newobjective = new + newobjective.explanation_text = "Serve your summoner, [summoner.name]." + newobjective.owner = owner + newobjective.completed = TRUE + objectives += newobjective + else + //succ some souls + var/datum/objective/horrorascend/ascend = new + ascend.owner = owner + ascend.hor = owner.current + ascend.target_amount = rand(5, 8) + objectives += ascend + ascend.update_explanation_text() + + //looking for antagonist we can assist + var/list/possible_targets = list() + for(var/datum/mind/M in SSticker.minds) + if(M.current && M.current.stat != DEAD) + if(ishuman(M.current)) + if(M.special_role) + possible_targets += M + + if(possible_targets.len) + var/datum/mind/M = pick(possible_targets) + var/datum/objective/protect/O = new + O.owner = owner + O.target = M + O.explanation_text = "Protect and assist \the [M.current.real_name], the [M.assigned_role]." + objectives += O + + + //don't die while you're at is + var/datum/objective/survive/survive = new + survive.owner = owner + objectives += survive + +/datum/objective/horrorascend + name = "consume souls" + var/mob/living/simple_animal/horror/hor + +/datum/objective/horrorascend/update_explanation_text() + . = ..() + explanation_text = "Consume [target_amount] souls." + +/datum/objective/horrorascend/check_completion() + if(hor && hor.consumed_souls >= target_amount) + return TRUE + return FALSE + + +//SPAWNER +/obj/item/horrorspawner + name = "suspicious pet carrier" + desc = "It contains some sort of creature inside. You can see tentacles sticking out of it." + icon = 'icons/obj/pet_carrier.dmi' + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + item_state = "pet_carrier" + icon_state = "pet_carrier_occupied" + var/used = FALSE + color = rgb(130, 105, 160) + +/obj/item/horrorspawner/attack_self(mob/living/user) + if(used) + to_chat(user, "The pet carrier appears unresponsive.") + return + used = TRUE + to_chat(user, "You're attempting to wake up the creature inside the box...") + sleep(5 SECONDS) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the eldritch horror in service of [user.real_name]?", ROLE_HORROR, null, FALSE, 100) + if(LAZYLEN(candidates)) + var/mob/dead/observer/C = pick(candidates) + var/mob/living/simple_animal/horror/H = new /mob/living/simple_animal/horror(get_turf(src)) + H.key = C.key + H.mind.enslave_mind_to_creator(user) + H.mind.add_antag_datum(C) + H.mind.memory += "You are " + span_purple(span_bold("[H.real_name]")) + ", an eldritch horror. Consume souls to evolve.
" + var/datum/antagonist/horror/S = new + S.summoner = user.mind + S.antag_memory += "[user.mind] woke you from your eternal slumber. Aid them in their objectives as a token of gratitude.
" + H.mind.add_antag_datum(S) + log_game("[key_name(user)] has summoned [key_name(H)], an eldritch horror.") + to_chat(user, span_bold("[H.real_name] has awoken into your service!")) + used = TRUE + icon_state = "pet_carrier_open" + sleep(5) + var/obj/item/horrorsummonhorn/horn = new /obj/item/horrorsummonhorn(get_turf(src)) + horn.summoner = user.mind + horn.horror = H + to_chat(user, span_notice("A strange looking [horn] falls out of [src]!")) + else + to_chat(user, "The creatures looks at you with one of it's eyes before going back to slumber.") + used = FALSE + return + +//Summoning horn +/obj/item/horrorsummonhorn + name = "old horn" + desc = "A very old horn. You feel an incredible urge to blow into it." + icon = 'icons/obj/items_and_weapons.dmi' + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + item_state = "horn" + icon_state = "horn" + var/datum/mind/summoner + var/mob/living/simple_animal/horror/horror + var/cooldown + +/obj/item/horrorsummonhorn/examine(mob/user) + . = ..() + if(user.mind == summoner) + to_chat(user, span_purple("Blowing into this horn will recall the horror back to you. Be wary, the horn is loud, and may attract unwanted attention.")) + +/obj/item/horrorsummonhorn/attack_self(mob/living/user) + if(cooldown > world.time) + to_chat(user, span_notice("Take a breath before you blow [src] again.")) + return + to_chat(user, span_notice("You take a deep breath and prepare to blow into [src]...")) + if(do_mob(user, src, 10 SECONDS)) + if(cooldown > world.time) + return + cooldown = world.time + 10 SECONDS + to_chat(src, span_notice("You blow the horn...")) + playsound(loc, "sound/items/airhorn.ogg", 100, 1, 30) + var/turf/summonplace = get_turf(src) + sleep(5 SECONDS) + if(prob(20)) //yeah you're summoning an eldritch horror allright + new /obj/effect/temp_visual/summon(summonplace) + sleep(10) + var/type = pick(typesof(/mob/living/simple_animal/hostile/abomination)) + var/mob/R = new type(summonplace) + playsound(summonplace, "sound/effects/phasein.ogg", 30) + summonplace.visible_message(span_danger("[R] emerges!")) + else + if(!horror || horror.stat == DEAD) + summonplace.visible_message(span_danger("But nothing responds to the call!")) + else + new /obj/effect/temp_visual/summon(summonplace) + sleep(10) + horror.leave_victim() + horror.forceMove(summonplace) + playsound(summonplace, "sound/effects/phasein.ogg", 30) + summonplace.visible_message(span_notice("[horror] appears out of nowhere!")) + if(user.mind != summoner) + sleep(2 SECONDS) + playsound(summonplace, "sound/effects/glassbr2.ogg", 30, 1) + to_chat(user, span_danger("[src] breaks!")) + qdel(src) +/obj/item/horrorsummonhorn/suicide_act(mob/living/user) //"I am the prettiest unicorn that ever was!" ~Spy 2013 + user.visible_message(span_suicide("[user] stabs [user.p_their()] forehead with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) + return BRUTELOSS +//Tentacle arm +/obj/item/horrortentacle + name = "tentacle" + desc = "A long, slimy, arm-like appendage." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "horrortentacle" + item_state = "tentacle" + lefthand_file = 'icons/mob/inhands/antag/horror_lefthand.dmi' + righthand_file = 'icons/mob/inhands/antag/horror_righthand.dmi' + resistance_flags = ACID_PROOF + force = 17 + item_flags = ABSTRACT | DROPDEL + weapon_stats = list(SWING_SPEED = 1, ENCUMBRANCE = 0, ENCUMBRANCE_TIME = 0, REACH = 2, DAMAGE_LOW = 0, DAMAGE_HIGH = 0) + range_cooldown_mod = 0 //tentacle is designed to hit from range + hitsound = 'sound/weapons/whip.ogg' +/obj/item/horrortentacle/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) +/obj/item/horrortentacle/examine(mob/user) + . = ..() + to_chat(user, span_velvet(span_bold("Functions:"))) + to_chat(user, span_velvet("All attacks work up to 2 tiles away.")) + to_chat(user, span_velvet("Help intent: Usual help function of an arm.")) + to_chat(user, span_velvet("Disarm intent: Whips the tentacle, disarming your opponent.")) + to_chat(user, span_velvet("Grab intent: Instant aggressive grab on an opponent. Can also throw them!")) + to_chat(user, span_velvet("Harm intent: Whips the tentacle, damaging your opponent.")) + to_chat(user, span_velvet("Also functions to pry open unbolted airlocks.")) +/obj/item/horrortentacle/attack(atom/target, mob/living/user) + if(isliving(target)) + user.Beam(target,"purpletentacle",time=5) + var/mob/living/L = target + switch(user.a_intent) + if(INTENT_HELP) + L.attack_hand(user) + return + if(INTENT_GRAB) + if(L != user) + L.grabbedby(user) + L.grippedby(user, instant = TRUE) + L.Knockdown(30) + return + if(INTENT_DISARM) + if(iscarbon(L)) + var/mob/living/carbon/C = L + var/obj/item/I = C.get_active_held_item() + if(I) + if(C.dropItemToGround(I)) + playsound(loc, "sound/weapons/whipgrab.ogg", 30) + target.visible_message(span_danger("[I] is whipped out of [C]'s hand by [user]!"),span_userdanger("A tentacle whips [I] out of your hand!")) + return + else + to_chat(user, span_danger("You can't seem to pry [I] off [C]'s hands!")) + return + else + C.attack_hand(user) + return + . = ..() +/obj/item/horrortentacle/afterattack(atom/target, mob/user, proximity) + if(isliving(user.pulling) && user.pulling != target) + var/mob/living/H = user.pulling + user.visible_message(span_warning("[user] throws [H] with [user.p_their()] [src]!"), span_warning("You throw [H] with [src].")) + H.throw_at(target, 8, 2) + H.Knockdown(30) + return + if(!proximity) + return + if(istype(target, /obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/A = target + if((!A.requiresID() || A.allowed(user)) && A.hasPower()) + return + if(A.locked) + to_chat(user, span_warning("The airlock's bolts prevent it from being forced!")) + return + if(A.hasPower()) + user.visible_message(span_warning("[user] jams [src] into the airlock and starts prying it open!"), span_warning("You start forcing the airlock open."), + span_italics("You hear a metal screeching sound.")) + playsound(A, 'sound/machines/airlock_alien_prying.ogg', 150, 1) + if(!do_after(user, 10 SECONDS, target = A)) + return + user.visible_message(span_warning("[user] forces the airlock to open with [user.p_their()] [src]!"), span_warning("You force the airlock to open."), + span_italics("You hear a metal screeching sound.")) + A.open(2) + return + . = ..() +/obj/item/horrortentacle/suicide_act(mob/user) //this will never be called, since horror stops suicide, but might as well if they get tentacle through other means + user.visible_message(span_suicide("[src] coils itself around [user] tightly gripping [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide!")) + return (OXYLOSS) +//Pinpointer +/obj/screen/alert/status_effect/agent_pinpointer/horror + name = "Soul locator" + desc = "Find your target soul." +/datum/status_effect/agent_pinpointer/horror + id = "horror_pinpointer" + minimum_range = 0 + range_fuzz_factor = 0 + tick_interval = 20 + alert_type = /obj/screen/alert/status_effect/agent_pinpointer/horror +/datum/status_effect/agent_pinpointer/horror/scan_for_target() + return +//TRAPPED MIND - when horror takes control over your body, you become a mute trapped mind +/mob/living/captive_brain + name = "host brain" + real_name = "host brain" + var/datum/action/innate/resist_control/R + var/mob/living/simple_animal/horror/H + +/mob/living/captive_brain/Initialize(mapload, gen=1) + ..() + R = new + R.Grant(src) + +/mob/living/captive_brain/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) + if(client) + if(client.prefs.muted & MUTE_IC) + to_chat(src, span_danger("You cannot speak in IC (muted).")) + return + if(client.handle_spam_prevention(message,MUTE_IC)) + return + if(ishorror(loc)) + message = sanitize(message) + if(!message) + return + if(stat == 2) + return say_dead(message) + to_chat(src, span_alien(span_italics("You whisper silently, \"[message]\""))) + to_chat(H.victim, span_alien(span_italics("[src] whispers, \"[message]\""))) + for(var/M in GLOB.dead_mob_list) + if(isobserver(M)) + var/rendered = span_changeling("[src] transfers: \"[message]\"") + var/link = FOLLOW_LINK(M, H.victim) + to_chat(M, "[link] [rendered]") + +/mob/living/captive_brain/emote(act, m_type = null, message = null, intentional = FALSE) + return + +/datum/action/innate/resist_control + name = "Resist control" + desc = "Try to take back control over your brain. A strong nerve impulse should do it." + background_icon_state = "bg_ecult" + icon_icon = 'icons/mob/actions/actions_horror.dmi' + button_icon_state = "resist_control" + +/datum/action/innate/resist_control/Activate() + var/mob/living/captive_brain/B = owner + if(B) + B.try_resist() + +/mob/living/captive_brain/resist() + try_resist() + +/mob/living/captive_brain/proc/try_resist() + var/delay = rand(20 SECONDS,30 SECONDS) + if(H.horrorupgrades["deep_control"]) + delay += rand(20 SECONDS,30 SECONDS) + to_chat(src, span_danger("You begin doggedly resisting the parasite's control.")) + to_chat(H.victim, span_danger("You feel the captive mind of [src] begin to resist your control.")) + addtimer(CALLBACK(src, .proc/return_control), delay) + +/mob/living/captive_brain/proc/return_control() + if(!H || !H.controlling) + return + to_chat(src, span_userdanger("With an immense exertion of will, you regain control of your body!")) + to_chat(H.victim, span_danger("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) + H.detatch() diff --git a/code/modules/antagonists/horror/horror_html.dm b/code/modules/antagonists/horror/horror_html.dm index 4f70c856805d..9cf8882f8015 100644 --- a/code/modules/antagonists/horror/horror_html.dm +++ b/code/modules/antagonists/horror/horror_html.dm @@ -1,102 +1,102 @@ -/mob/living/simple_animal/horror/proc/get_html_template(content) - var/html = {" - - - Horror Chemicals - - - - - - -
-

Horror Chemicals

-
- [content] -
"} +/mob/living/simple_animal/horror/proc/get_html_template(content) + var/html = {" + + + Horror Chemicals + + + + + + +
+

Horror Chemicals

+
+ [content] +
"} return html \ No newline at end of file diff --git a/code/modules/antagonists/horror/horror_mutate.dm b/code/modules/antagonists/horror/horror_mutate.dm index 2eaa8e93af92..97cb19c20572 100644 --- a/code/modules/antagonists/horror/horror_mutate.dm +++ b/code/modules/antagonists/horror/horror_mutate.dm @@ -1,97 +1,97 @@ -// Horror mutation menu -// Totally not a copypaste of darkspawn menu, not a copypaste of cellular emporium, i swear. Edit: now looks like guardianbuilder too - -/mob/living/simple_animal/horror/proc/has_ability(typepath) - for(var/datum/action/innate/horror/ability in horrorabilities) - if(istype(ability, typepath)) - return ability - return - -/mob/living/simple_animal/horror/proc/add_ability(typepath) - if(has_ability(typepath)) - return - var/datum/action/innate/horror/action = new typepath - action.B = src - horrorabilities += action - RefreshAbilities() - to_chat(src, span_velvet("You have mutated the [action.name].")) - available_points = max(0, available_points - action.soul_price) - return TRUE - -/mob/living/simple_animal/horror/proc/has_upgrade(id) - return horrorupgrades[id] - -/mob/living/simple_animal/horror/proc/add_upgrade(id) - if(has_upgrade(id)) - return - for(var/V in subtypesof(/datum/horror_upgrade)) - var/datum/horror_upgrade/_U = V - if(initial(_U.id) == id) - var/datum/horror_upgrade/U = new _U(src) - horrorupgrades[id] = TRUE - to_chat(src, "You have adapted the \"[U.name]\" upgrade.") - available_points = max(0, available_points - U.soul_price) - U.unlock() - -//mutation menu, 100% ripoff of psiweb, pls don't sue - -/mob/living/simple_animal/horror/ui_state(mob/user) - return GLOB.always_state - -/mob/living/simple_animal/horror/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "HorrorMutate", "Horror Mutation") - ui.open() - -/mob/living/simple_animal/horror/ui_data(mob/user) - var/list/data = list() - - data["available_points"] = "[available_points] | [consumed_souls] consumed souls total" - - var/list/abilities = list() - var/list/upgrades = list() - - for(var/path in subtypesof(/datum/action/innate/horror)) - var/datum/action/innate/horror/ability = path - - if(initial(ability.blacklisted)) - continue - - var/list/AL = list() - AL["name"] = initial(ability.name) - AL["typepath"] = path - AL["desc"] = initial(ability.desc) - AL["soul_cost"] = initial(ability.soul_price) - AL["owned"] = has_ability(path) - AL["can_purchase"] = !AL["owned"] && available_points >= initial(ability.soul_price) - - abilities += list(AL) - - data["abilities"] = abilities - - for(var/path in subtypesof(/datum/horror_upgrade)) - var/datum/horror_upgrade/upgrade = path - - var/list/DE = list() - DE["name"] = initial(upgrade.name) - DE["id"] = initial(upgrade.id) - DE["desc"] = initial(upgrade.desc) - DE["soul_cost"] = initial(upgrade.soul_price) - DE["owned"] = has_upgrade(initial(upgrade.id)) - DE["can_purchase"] = !DE["owned"] && available_points >= initial(upgrade.soul_price) - - upgrades += list(DE) - - data["upgrades"] = upgrades - - return data - -/mob/living/simple_animal/horror/ui_act(action, params) - if(..()) - return - switch(action) - if("unlock") - add_ability(params["typepath"]) - if("upgrade") +// Horror mutation menu +// Totally not a copypaste of darkspawn menu, not a copypaste of cellular emporium, i swear. Edit: now looks like guardianbuilder too + +/mob/living/simple_animal/horror/proc/has_ability(typepath) + for(var/datum/action/innate/horror/ability in horrorabilities) + if(istype(ability, typepath)) + return ability + return + +/mob/living/simple_animal/horror/proc/add_ability(typepath) + if(has_ability(typepath)) + return + var/datum/action/innate/horror/action = new typepath + action.B = src + horrorabilities += action + RefreshAbilities() + to_chat(src, span_velvet("You have mutated the [action.name].")) + available_points = max(0, available_points - action.soul_price) + return TRUE + +/mob/living/simple_animal/horror/proc/has_upgrade(id) + return horrorupgrades[id] + +/mob/living/simple_animal/horror/proc/add_upgrade(id) + if(has_upgrade(id)) + return + for(var/V in subtypesof(/datum/horror_upgrade)) + var/datum/horror_upgrade/_U = V + if(initial(_U.id) == id) + var/datum/horror_upgrade/U = new _U(src) + horrorupgrades[id] = TRUE + to_chat(src, "You have adapted the \"[U.name]\" upgrade.") + available_points = max(0, available_points - U.soul_price) + U.unlock() + +//mutation menu, 100% ripoff of psiweb, pls don't sue + +/mob/living/simple_animal/horror/ui_state(mob/user) + return GLOB.always_state + +/mob/living/simple_animal/horror/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "HorrorMutate", "Horror Mutation") + ui.open() + +/mob/living/simple_animal/horror/ui_data(mob/user) + var/list/data = list() + + data["available_points"] = "[available_points] | [consumed_souls] consumed souls total" + + var/list/abilities = list() + var/list/upgrades = list() + + for(var/path in subtypesof(/datum/action/innate/horror)) + var/datum/action/innate/horror/ability = path + + if(initial(ability.blacklisted)) + continue + + var/list/AL = list() + AL["name"] = initial(ability.name) + AL["typepath"] = path + AL["desc"] = initial(ability.desc) + AL["soul_cost"] = initial(ability.soul_price) + AL["owned"] = has_ability(path) + AL["can_purchase"] = !AL["owned"] && available_points >= initial(ability.soul_price) + + abilities += list(AL) + + data["abilities"] = abilities + + for(var/path in subtypesof(/datum/horror_upgrade)) + var/datum/horror_upgrade/upgrade = path + + var/list/DE = list() + DE["name"] = initial(upgrade.name) + DE["id"] = initial(upgrade.id) + DE["desc"] = initial(upgrade.desc) + DE["soul_cost"] = initial(upgrade.soul_price) + DE["owned"] = has_upgrade(initial(upgrade.id)) + DE["can_purchase"] = !DE["owned"] && available_points >= initial(upgrade.soul_price) + + upgrades += list(DE) + + data["upgrades"] = upgrades + + return data + +/mob/living/simple_animal/horror/ui_act(action, params) + if(..()) + return + switch(action) + if("unlock") + add_ability(params["typepath"]) + if("upgrade") add_upgrade(params["id"]) \ No newline at end of file diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 692b91214274..6fa8dd46db7f 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -164,6 +164,9 @@ to_chat(user, span_notice("You detach [A] from [src].")) else to_chat(user, span_notice("You detach [A] from [src] and it falls on the floor.")) + var/turf/T = get_turf(src) + if(!T) + T = get_turf(user) A.forceMove(get_turf(src)) if(ishuman(loc)) diff --git a/code/modules/events/horror.dm b/code/modules/events/horror.dm index dd42420f8477..afa1182ff04e 100644 --- a/code/modules/events/horror.dm +++ b/code/modules/events/horror.dm @@ -1,34 +1,34 @@ -/datum/round_event_control/horror - name = "Spawn Eldritch Horror" - typepath = /datum/round_event/ghost_role/horror - max_occurrences = 2 - min_players = 15 - earliest_start = 20 MINUTES - -/datum/round_event/ghost_role/horror - minimum_required = 1 - role_name = "horror" - fakeable = FALSE - -/datum/round_event/ghost_role/horror/spawn_role() - var/list/candidates = get_candidates(ROLE_HORROR, null, ROLE_HORROR) - if(!candidates.len) - return NOT_ENOUGH_PLAYERS - - var/mob/dead/selected = pick_n_take(candidates) - - var/datum/mind/player_mind = new /datum/mind(selected.key) - player_mind.active = 1 - if(!GLOB.generic_event_spawns) - return MAP_ERROR - var/mob/living/simple_animal/horror/S = new /mob/living/simple_animal/horror(get_turf(pick(GLOB.generic_event_spawns))) - player_mind.transfer_to(S) - player_mind.assigned_role = "Eldritch Horror" - player_mind.special_role = "Eldritch Horror" - player_mind.add_antag_datum(/datum/antagonist/horror) - to_chat(S, S.playstyle_string) - SEND_SOUND(S, sound('sound/hallucinations/growl2.ogg')) - message_admins("[ADMIN_LOOKUPFLW(S)] has been made into an eldritch horror by an event.") - log_game("[key_name(S)] was spawned as an eldritch horror by an event.") - spawned_mobs += S +/datum/round_event_control/horror + name = "Spawn Eldritch Horror" + typepath = /datum/round_event/ghost_role/horror + max_occurrences = 2 + min_players = 15 + earliest_start = 20 MINUTES + +/datum/round_event/ghost_role/horror + minimum_required = 1 + role_name = "horror" + fakeable = FALSE + +/datum/round_event/ghost_role/horror/spawn_role() + var/list/candidates = get_candidates(ROLE_HORROR, null, ROLE_HORROR) + if(!candidates.len) + return NOT_ENOUGH_PLAYERS + + var/mob/dead/selected = pick_n_take(candidates) + + var/datum/mind/player_mind = new /datum/mind(selected.key) + player_mind.active = 1 + if(!GLOB.generic_event_spawns) + return MAP_ERROR + var/mob/living/simple_animal/horror/S = new /mob/living/simple_animal/horror(get_turf(pick(GLOB.generic_event_spawns))) + player_mind.transfer_to(S) + player_mind.assigned_role = "Eldritch Horror" + player_mind.special_role = "Eldritch Horror" + player_mind.add_antag_datum(/datum/antagonist/horror) + to_chat(S, S.playstyle_string) + SEND_SOUND(S, sound('sound/hallucinations/growl2.ogg')) + message_admins("[ADMIN_LOOKUPFLW(S)] has been made into an eldritch horror by an event.") + log_game("[key_name(S)] was spawned as an eldritch horror by an event.") + spawned_mobs += S return SUCCESSFUL_SPAWN \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/crew_monitor.dm b/code/modules/modular_computers/file_system/programs/crew_monitor.dm index 03a116890ab3..a9c1ac91af9d 100644 --- a/code/modules/modular_computers/file_system/programs/crew_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/crew_monitor.dm @@ -38,7 +38,7 @@ var/turf/T = get_turf(computer) z = T.z var/list/death_list = GLOB.crewmonitor.death_list?["[z]"] - if(death_list.len > 0) + if(death_list && death_list.len > 0) alarm = TRUE else alarm = FALSE diff --git a/html/changelog.html b/html/changelog.html index 085c39be2eaa..1b59557bdde3 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -66,6 +66,8 @@

ToasterBiome updated:

adamsong updated:

  • Veil now works on light prisms
  • +
  • fixed runtime in crew_monitor.dm
  • +
  • fixed runtime in remove_accessory

cuackles updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 1d5a982a5889..4f8f82cd4ecb 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -30278,5 +30278,7 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - bugfix: flashlights on guns properly clear their overlay instead of all overlays adamsong: - tweak: Veil now works on light prisms + - bugfix: fixed runtime in crew_monitor.dm + - bugfix: fixed runtime in remove_accessory cuackles: - tweak: tweaked a few things From 5bce362b92ce484f1086835de217955711466a9d Mon Sep 17 00:00:00 2001 From: nmajask Date: Thu, 10 Mar 2022 15:20:43 -0500 Subject: [PATCH 4/5] Reworks the implementation Makes starting mag a variable and changes the check to look for pacifism being a quirk. --- code/modules/projectiles/guns/ballistic.dm | 12 +++++++----- code/modules/projectiles/guns/ballistic/pistol.dm | 6 ++---- code/modules/uplink/uplink_items.dm | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index fb978991b098..91623c736add 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -49,6 +49,8 @@ var/spawnwithmagazine = TRUE ///Compatible magazines with the gun var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info + ///What magazine this gun starts with, if null it will just use mag_type + var/starting_mag_type ///Whether the sprite has a visible magazine or not var/mag_display = FALSE ///Whether the sprite has a visible ammo display or not @@ -167,13 +169,13 @@ bolt_locked = TRUE update_icon() return - load_starting_mag() - update_icon() - -/obj/item/gun/ballistic/proc/load_starting_mag() if (!magazine) - magazine = new mag_type(src) + if (!starting_mag_type) + magazine = new mag_type(src) + else + magazine = new starting_mag_type(src) chamber_round() + update_icon() /obj/item/gun/ballistic/update_icon() diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index 8b5416e68348..8ef466d727ab 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -31,10 +31,8 @@ var/obj/item/suppressor/S = new(src) install_suppressor(S) -/obj/item/gun/ballistic/automatic/pistol/pacifist/load_starting_mag() - if (!magazine) - magazine = new /obj/item/ammo_box/magazine/m10mm/sp(src) - chamber_round() +/obj/item/gun/ballistic/automatic/pistol/pacifist + starting_mag_type = /obj/item/ammo_box/magazine/m10mm/sp /obj/item/gun/ballistic/automatic/pistol/m1911 name = "\improper M1911" diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 9655ed98925c..c915383a65e7 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -518,7 +518,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) exclude_modes = list(/datum/game_mode/nuclear/clown_ops) /datum/uplink_item/dangerous/pistol/spawn_item(spawn_path, mob/user, datum/component/uplink/U) - if(HAS_TRAIT(user, TRAIT_PACIFISM)) + if(HAS_TRAIT_FROM(user, TRAIT_PACIFISM, ROUNDSTART_TRAIT)) spawn_path = /obj/item/gun/ballistic/automatic/pistol/pacifist to_chat(user, span_notice("Your employer has loaded your purchased weapon with non-leathal ammunition")) ..() From 6523bc0070f729190e2e8364d9fa9e90dfb566b6 Mon Sep 17 00:00:00 2001 From: nmajask Date: Fri, 11 Mar 2022 09:01:24 -0500 Subject: [PATCH 5/5] Update code/modules/uplink/uplink_items.dm Co-authored-by: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com> --- code/modules/uplink/uplink_items.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index c915383a65e7..945b20f30bfc 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -520,7 +520,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) /datum/uplink_item/dangerous/pistol/spawn_item(spawn_path, mob/user, datum/component/uplink/U) if(HAS_TRAIT_FROM(user, TRAIT_PACIFISM, ROUNDSTART_TRAIT)) spawn_path = /obj/item/gun/ballistic/automatic/pistol/pacifist - to_chat(user, span_notice("Your employer has loaded your purchased weapon with non-leathal ammunition")) + to_chat(user, span_notice("Your employer has loaded your purchased weapon with non-lethal ammunition")) ..() /datum/uplink_item/dangerous/bolt_action