From d40f91eb53b3e7a09bfeda2ab23ec2748e757fac Mon Sep 17 00:00:00 2001 From: forest2001 Date: Fri, 3 Mar 2023 22:38:06 +0000 Subject: [PATCH 01/52] Ported Paradise SS13 Cortical Borers tiny bit of text clean up Working chems working chems p2 Text SPANs Action swap and categories Moved procs to separate file Apparently this didn't go through in the last commmit? Ported Paradise SS13 Cortical Borers tiny bit of text clean up Working chems working chems p2 Text SPANs Action swap and categories Moved procs to separate file reproduction levels icons icons Cure hiding icon Rebase Checks PROC_REF PROC_REF 515 is lame UID Temp Reproduce icon UID death Disables Zombie Powder and stun action wheel too Update ColonialMarinesALPHA.dme Co-authored-by: harryob Lang fix 0.5 Lang fix, property, chem names. Var tidy and chem cats Speech, Chem Fix & Enzyme Grinding Chem log Spans and Ghost chat emote freedom parenthesis stun fix Death handling & hud fix Follow and Death death check Player SimpleMobs in Orbit Enzymes and FOLLOW Defines, Balance, Brain Damage Defines and Balancing Spawn message & Orbit order Orbit order X Impurity Part 1 Luminescence and Icons Icon Rebase Hibernation message types Ported Paradise SS13 Cortical Borers working chems p2 Text SPANs Moved procs to separate file Ported Paradise SS13 Cortical Borers tiny bit of text clean up Working chems working chems p2 Text SPANs Action swap and categories Moved procs to separate file icons icons hiding icon Rebase UID Temp Reproduce icon UID death Disables Zombie Powder and stun action wheel too Update ColonialMarinesALPHA.dme Co-authored-by: harryob Var tidy and chem cats Speech, Chem Fix & Enzyme Grinding Spans and Ghost chat Death handling & hud fix Follow and Death Player SimpleMobs in Orbit Enzymes and FOLLOW Defines, Balance, Brain Damage Defines and Balancing Spawn message & Orbit order Orbit order X Luminescence and Icons Icon Rebase 515 rebase ma antiruntime carbon tests --- code/__DEFINES/chemistry.dm | 1 + code/__DEFINES/language.dm | 1 + code/datums/emergency_calls/custom.dm | 2 +- code/datums/mob_hud.dm | 6 + code/modules/borer/_defines.dm | 8 + code/modules/borer/borer.dm | 407 ++++++++++ code/modules/borer/borer_chemicals.dm | 137 ++++ code/modules/borer/borer_html.dm | 69 ++ code/modules/borer/borer_procs.dm | 720 ++++++++++++++++++ code/modules/mob/holder.dm | 6 + code/modules/mob/language/languages.dm | 44 ++ .../mob/living/carbon/carbon_defines.dm | 2 + code/modules/mob/living/carbon/human/death.dm | 3 + code/modules/mob/living/carbon/human/human.dm | 18 + code/modules/mob/living/carbon/human/life.dm | 3 + code/modules/mob/living/say.dm | 4 + .../mob/living/simple_animal/simple_animal.dm | 5 +- .../chemistry_machinery/reagent_grinder.dm | 10 + .../chemistry_properties/prop_positive.dm | 13 + .../reagents/chemistry_reactions/other.dm | 8 + .../reagents/chemistry_reagents/other.dm | 24 + code/span_macros.dm | 1 + colonialmarines.dme | 5 + icons/mob/brainslug.dmi | Bin 0 -> 4277 bytes icons/mob/hud/actions_borer.dmi | Bin 0 -> 2032 bytes .../tgui/interfaces/BorerChemDispenser.js | 1 + 26 files changed, 1495 insertions(+), 3 deletions(-) create mode 100644 code/modules/borer/_defines.dm create mode 100644 code/modules/borer/borer.dm create mode 100644 code/modules/borer/borer_chemicals.dm create mode 100644 code/modules/borer/borer_html.dm create mode 100644 code/modules/borer/borer_procs.dm create mode 100644 icons/mob/brainslug.dmi create mode 100644 icons/mob/hud/actions_borer.dmi create mode 100644 tgui/packages/tgui/interfaces/BorerChemDispenser.js diff --git a/code/__DEFINES/chemistry.dm b/code/__DEFINES/chemistry.dm index 81031200b51c..9b6f028b208c 100644 --- a/code/__DEFINES/chemistry.dm +++ b/code/__DEFINES/chemistry.dm @@ -82,6 +82,7 @@ #define CHEM_EFFECT_RESIST_NEURO (1<<1) #define CHEM_EFFECT_HYPER_THROTTLE (1<<2) //universal understand but not speech #define CHEM_EFFECT_ORGAN_STASIS (1<<3) //peri stabiliser +#define CHEM_EFFECT_ANTI_PARASITE (1<<4) //PROPERTY_ANTIPARASITIC //Blood plasma diff --git a/code/__DEFINES/language.dm b/code/__DEFINES/language.dm index 8cac90defb26..9aa2ad702a94 100644 --- a/code/__DEFINES/language.dm +++ b/code/__DEFINES/language.dm @@ -15,6 +15,7 @@ #define LANGUAGE_APOLLO "Apollo Link" #define LANGUAGE_TELEPATH "Telepath Implant" +#define LANGUAGE_BORER "Cortical Link" #define ALL_HUMAN_LANGUAGES list(LANGUAGE_ENGLISH, LANGUAGE_JAPANESE, LANGUAGE_CHINESE, LANGUAGE_RUSSIAN, LANGUAGE_GERMAN, LANGUAGE_SPANISH) diff --git a/code/datums/emergency_calls/custom.dm b/code/datums/emergency_calls/custom.dm index 0117c83fc19c..f65fdba536b6 100644 --- a/code/datums/emergency_calls/custom.dm +++ b/code/datums/emergency_calls/custom.dm @@ -28,7 +28,7 @@ return M.transfer_to(H, TRUE) - + to_chat(H, SPAN_ALERT("[objectives]")) players_to_offer -= H return diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm index b1d9a9c2fade..fa2af17240f9 100644 --- a/code/datums/mob_hud.dm +++ b/code/datums/mob_hud.dm @@ -446,6 +446,12 @@ var/list/datum/mob_hud/huds = list( return + var/mob/living/carbon/cortical_borer/B = has_brain_worms() + if(B && B.controlling) + holder.icon_state = "hudbrainworm" + if(!holder2_set) + holder2.icon_state = "hudbrainworm" + return for(var/datum/disease/D in viruses) if(!D.hidden[SCANNER]) diff --git a/code/modules/borer/_defines.dm b/code/modules/borer/_defines.dm new file mode 100644 index 000000000000..15929f6fa492 --- /dev/null +++ b/code/modules/borer/_defines.dm @@ -0,0 +1,8 @@ +/// Chemical categories +#define BORER_CAT_HEAL "Medicines" +#define BORER_CAT_PUNISH "Motivators" +#define BORER_CAT_STIM "Stimulants" +#define BORER_CAT_SELF "Self Protection" + +///Amount of chemicals needed for a borer to reproduce, provided reproduction is toggled. +#define BORER_LARVAE_COST 400 diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm new file mode 100644 index 000000000000..683956bf1fb4 --- /dev/null +++ b/code/modules/borer/borer.dm @@ -0,0 +1,407 @@ +/mob/living/captive_brain + name = "host brain" + real_name = "host brain" + +/mob/living/captive_brain/say(message) + if(client) + if(client.prefs.muted & MUTE_IC) + to_chat(src, SPAN_WARNING("You cannot speak in IC (muted).")) + return + if(client.handle_spam_prevention(message, MUTE_IC)) + return + + if(istype(loc,/mob/living/carbon/cortical_borer)) + message = trim(sanitize(copytext(message, 1, MAX_MESSAGE_LEN))) + if(!message) + return + if(stat == DEAD) + return say_dead(message) + var/mob/living/carbon/cortical_borer/B = loc + to_chat(src, SPAN_BORER("You whisper silently, [message]"), type = MESSAGE_TYPE_RADIO) + to_chat(B.host, SPAN_BORER("The captive mind of [src] whispers, \"[message]\""), type = MESSAGE_TYPE_RADIO) + log_say("BORER: ([key_name(src)] to [key_name(B.host)]) [message]", src) + for (var/mob/dead in GLOB.dead_mob_list) + var/track_borer = " (F)" + if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping + dead.show_message(SPAN_BORER("BORER: ([name] (trapped mind) to [B.truename][track_borer]) whispers: [message]"), SHOW_MESSAGE_VISIBLE) + +/mob/living/captive_brain/say_understands(mob/other, datum/language/speaking = null) + var/mob/living/carbon/cortical_borer/B = loc + if(!istype(B)) + log_debug(EXCEPTION("Trapped mind found without a borer!"), src) + return FALSE + return B.host.say_understands(other, speaking) + +/mob/living/captive_brain/emote(act, m_type = 1, message = null, intentional = FALSE, force_silence = FALSE) + return + +/mob/living/captive_brain/resist() + var/mob/living/carbon/cortical_borer/B = loc + if(!istype(B)) + log_debug(EXCEPTION("Trapped mind found without a borer!"), src) + return + + to_chat(src, SPAN_DANGER("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).")) + to_chat(B.host, SPAN_XENOWARNING("You feel the captive mind of [src] begin to resist your control.")) + + var/delay = (rand(350,450) + B.host.getBrainLoss()) + addtimer(CALLBACK(src, PROC_REF(return_control), B), delay) + +/mob/living/carbon/cortical_borer + name = "cortical borer" + real_name = "cortical borer" + desc = "A small, quivering sluglike creature." + speak_emote = list("chirrups") + icon = 'icons/mob/brainslug.dmi' + icon_state = "brainslug" + speed = 0 + a_intent = INTENT_HARM + status_flags = CANPUSH + attacktext = "nips" + friendly = "prods" + mob_size = MOB_SIZE_SMALL + density = 0 + pass_flags = PASS_FLAGS_CRAWLER + mob_size = MOB_SIZE_SMALL + faction = list("creature") + hud_possible = list(HEALTH_HUD,STATUS_HUD) + universal_understand = TRUE + + holder_type = /obj/item/holder/borer + + var/generation = 1 + var/static/list/borer_names = list( + "Primary", "Secondary", "Tertiary", "Quaternary", "Quinary", "Senary", + "Septenary", "Octonary", "Novenary", "Decenary", "Undenary", "Duodenary", + ) + var/talk_inside_host = FALSE // So that borers don't accidentally give themselves away on a botched message + var/used_dominate + var/attempting_to_dominate = FALSE // To prevent people from spam opening the Dominate Victim input + + var/enzymes = 10 // Enzymes used for chemical injection. + var/max_enzymes = 500 + var/contaminant = 0 //Contaminant builds up on enzyme usage, roughly proportionate to cost of use. + var/max_contaminant = 120 //Decreases through hibernation or reproduction. + var/hibernating = FALSE //Usable inside a host, but not when controlling. Allows clearing of impurities. + + var/mob/living/carbon/human/host // Human host for the brain worm. + var/truename // Name used for brainworm-speak. + var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. + var/controlling // Used in human death check. + var/docile = FALSE // Anti-Parasite or Anti-Enzyme chemicals can stop borers from acting. + var/bonding = FALSE + var/leaving = FALSE + var/hiding = FALSE + var/can_reproduce = FALSE // Locked to manual override to prevent things getting out of hand. + var/infect_hunter = FALSE // Locked for normal use. + + var/list/datum/reagent/synthesized_chems + + /// All of these surely have a better way of being handled. + var/datum/action/innate/borer/talk_to_host/action_talk_to_host = new + var/datum/action/innate/borer/infest_host/action_infest_host = new + var/datum/action/innate/borer/toggle_hide/action_toggle_hide = new + var/datum/action/innate/borer/talk_to_borer/action_talk_to_borer = new + var/datum/action/innate/borer/talk_to_brain/action_talk_to_brain = new + var/datum/action/innate/borer/take_control/action_take_control = new + var/datum/action/innate/borer/give_back_control/action_give_back_control = new + var/datum/action/innate/borer/leave_body/action_leave_body = new + var/datum/action/innate/borer/make_chems/action_make_chems = new + var/datum/action/innate/borer/make_larvae/action_make_larvae = new + var/datum/action/innate/borer/freeze_victim/action_freeze_victim = new + var/datum/action/innate/borer/torment/action_torment = new + var/datum/action/innate/borer/scan_chems/action_scan_chems = new + var/datum/action/innate/borer/hibernate/action_hibernate = new + +/mob/living/carbon/cortical_borer/initialize_pass_flags(datum/pass_flags_container/PF) + ..() + if (PF) + PF.flags_pass = PASS_MOB_THRU|PASS_FLAGS_CRAWLER + PF.flags_can_pass_all = PASS_ALL^PASS_OVER_THROW_ITEM + +/mob/living/carbon/cortical_borer/proc/summon() + var/datum/emergency_call/custom/em_call = new() + em_call.name = "Cortical Borer" + em_call.mob_max = 1 + em_call.players_to_offer = list(src) + em_call.owner = null + em_call.ert_message = "A new Cortical Borer has been birthed!" + em_call.objectives = "Create enjoyable Roleplay. Do not kill your host. Do not take control unless granted permission or directed to by admins. Hivemind is :0 (That's Zero, not Oscar)" + + em_call.activate(announce = FALSE) + + message_admins("A new Cortical Borer has spawned at [get_area(loc)]") + +/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0) + ..(newloc) + generation = gen + add_language(LANGUAGE_BORER) + var/mob_number = rand(1000,9999) + real_name = "Cortical Borer [mob_number]" + truename = "[borer_names[min(generation, borer_names.len)]] [mob_number]" + can_reproduce = reproduction + GrantBorerActions() + GiveBorerHUD() + if((!is_admin_level(z)) && ERT) + summon() + +/mob/living/carbon/cortical_borer/death() + var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] + c_link.broadcast(src, null, null, TRUE) + . = ..() + +/mob/living/carbon/cortical_borer/update_icons() + if(stat == DEAD) + icon_state = "Borer Dead" + + else if(lying) + if((resting || sleeping) && (!knocked_down && !knocked_out && health > 0)) + icon_state = "Borer Resting" + else + icon_state = "Borer Stunned" + else + icon_state = "Borer" + +/mob/living/carbon/cortical_borer/proc/GiveBorerHUD() + var/datum/mob_hud/H = huds[MOB_HUD_MEDICAL_OBSERVER] + H.add_hud_to(src) + +/mob/living/carbon/cortical_borer/can_ventcrawl() + return TRUE + +/mob/living/carbon/cortical_borer/initialize_pass_flags(datum/pass_flags_container/PF) + ..() + if (PF) + PF.flags_pass = PASS_MOB_THRU|PASS_FLAGS_CRAWLER + PF.flags_can_pass_all = PASS_ALL^PASS_OVER_THROW_ITEM + +/mob/living/carbon/cortical_borer/get_status_tab_items() + . = ..() + + var/CR = "Yes" + if(!can_reproduce) + CR = "Forbidden" + else if((enzymes < BORER_LARVAE_COST)) + CR = "No" + + . += "" + . += "Borer:" + . += "Name: [truename]" + . += "Can Reproduce: [CR]" + . += "Enzymes: [round(enzymes)]/[round(max_enzymes)]" + . += "Contaminant: [round(contaminant)]/[round(max_contaminant)]" + if(host) + . += "" + . += "Host Brain Damage: [host.brainloss]/100" + +/mob/living/carbon/cortical_borer/say(message)//I need to parse the message properly so it doesn't look stupid + var/datum/language/parsed_language = parse_language(message) + var/new_message = message + if(parsed_language) + new_message = copytext(message, 3) + if(istype(parsed_language, /datum/language/corticalborer)) + parsed_language.broadcast(src, new_message) + return + if(hibernating) + to_chat(src, SPAN_WARNING("You cannot speak aloud while hibernating!")) + return + if(loc == host && !talk_inside_host) + to_chat(src, SPAN_WARNING("You've disabled audible speech while inside a host! Re-enable it under the borer tab, or stick to borer communications.")) + return + . = ..() + + +/mob/living/carbon/cortical_borer/Life(delta_time) + ..() + if(host) + if(!stat && host.stat != DEAD) + if(((host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && !host.reagents.has_reagent("benzyme")) || host.reagents.has_reagent("bcure")) + if(!docile) + if(controlling) + to_chat(host, SPAN_XENODANGER("You feel the soporific flow of a chemical in your host's blood, lulling you into docility.")) + else + to_chat(src, SPAN_XENODANGER("You feel the soporific flow of a chemical in your host's blood, lulling you into docility.")) + docile = TRUE + else + if(docile) + if(controlling) + to_chat(host, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) + else + to_chat(src, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) + docile = FALSE + if(!hibernating && (enzymes < max_enzymes)) + enzymes++ + if(contaminant > 0) + if(hibernating) + contaminant = max(contaminant -= 1, 0) + else + contaminant = max(contaminant -= 0.1, 0) + if(controlling) + if(docile) + to_chat(host, SPAN_XENOWARNING("You are feeling far too docile to continue controlling your host...")) + host.release_control() + return + else + if(contaminant > 0) + if(!luminosity) + SetLuminosity(2) + contaminant = max(contaminant - 0.3, 0) + else + SetLuminosity(0) + + update_canmove() + update_icons() +/datum/action/innate/borer + icon_file = 'icons/mob/hud/actions_borer.dmi' + +/datum/action/innate/borer/talk_to_host + name = "Converse with Host" + action_icon_state = "borer_whisper" + +/datum/action/innate/borer/talk_to_host/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + B.Communicate() + +/datum/action/innate/borer/infest_host + name = "Infest" + action_icon_state = "borer_infest" + +/datum/action/innate/borer/infest_host/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + B.infest() + +/datum/action/innate/borer/toggle_hide + name = "Toggle Hide" + action_icon_state = "borer_hiding_0" + +/datum/action/innate/borer/toggle_hide/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + B.hide_borer() + + button.overlays.Cut() + button.overlays += image('icons/mob/hud/actions_borer.dmi', button, "borer_hiding_[B.hiding]") + +/datum/action/innate/borer/talk_to_borer + name = "Converse with Borer" + action_icon_state = "borer_whisper" + +/datum/action/innate/borer/talk_to_borer/action_activate() + var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() + B.host = owner + B.host.borer_comm() + +/datum/action/innate/borer/talk_to_brain + name = "Converse with Trapped Mind" + action_icon_state = "borer_whisper" + +/datum/action/innate/borer/talk_to_brain/action_activate() + var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() + B.host = owner + B.host.trapped_mind_comm() + +/datum/action/innate/borer/take_control + name = "Assume Control" + action_icon_state = "borer_control" + +/datum/action/innate/borer/take_control/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + if(B.hibernating) + to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + return + B.bond_brain() + +/datum/action/innate/borer/give_back_control + name = "Release Control" + action_icon_state = "borer_leave" + +/datum/action/innate/borer/give_back_control/action_activate() + var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() + B.host = owner + B.host.release_control() + +/datum/action/innate/borer/leave_body + name = "Leave Host" + action_icon_state = "borer_leave" + +/datum/action/innate/borer/leave_body/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + if(B.hibernating) + to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + return + B.release_host() + +/datum/action/innate/borer/make_chems + name = "Secrete Chemicals" + action_icon_state = "borer_chems" + +/datum/action/innate/borer/make_chems/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + if(B.hibernating) + to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + return + B.secrete_chemicals() + +/datum/action/innate/borer/scan_chems + name = "Scan Chemicals" + action_icon_state = "borer_scan" + +/datum/action/innate/borer/scan_chems/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + if(B.hibernating) + to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + return + borerscan(B, B.host) + +/datum/action/innate/borer/make_larvae + name = "Reproduce" + action_icon_state = "borer_reproduce" + +/datum/action/innate/borer/make_larvae/action_activate() + var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() + B.host = owner + B.host.spawn_larvae() + +/datum/action/innate/borer/freeze_victim + name = "Dominate Victim" + action_icon_state = "borer_stun" + +/datum/action/innate/borer/freeze_victim/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + B.dominate_victim() + +/datum/action/innate/borer/torment + name = "Torment Host" + action_icon_state = "borer_torment" + +/datum/action/innate/borer/torment/action_activate() + var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() + B.host = owner + B.host.punish_host() + +/datum/action/innate/borer/hibernate + name = "Toggle Hibernation" + action_icon_state = "borer_sleeping_0" + +/datum/action/innate/borer/hibernate/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + B.hibernate() + button.overlays.Cut() + button.overlays += image('icons/mob/hud/actions_borer.dmi', button, "borer_sleeping_[B.hibernating]") + +/mob/living/carbon/cortical_borer/MouseDrop(atom/over_object) + if(!CAN_PICKUP(usr, src)) + return ..() + var/mob/living/carbon/H = over_object + if(!istype(H) || !Adjacent(H) || H != usr) return ..() + + if(H.a_intent == INTENT_HELP) + get_scooped(H) + return + else + return ..() + +/mob/living/carbon/cortical_borer/get_scooped(mob/living/carbon/grabber) + if(stat != DEAD) + to_chat(grabber, SPAN_WARNING("You probably shouldn't pick that thing up while it still lives.")) + return + ..() diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm new file mode 100644 index 000000000000..ddb4b775ff5f --- /dev/null +++ b/code/modules/borer/borer_chemicals.dm @@ -0,0 +1,137 @@ +/datum/borer_chem + var/chem_name = "Unset" + /// Chemical identifier, used in the proc to create it. + var/chem_id = "unset" + var/desc = "This is a chemical" + /// Synthetic chemicals. + var/impure = TRUE + var/cost = 50 + var/quantity = 10 + + var/category = BORER_CAT_HEAL + + +//Medical Chems +/datum/borer_chem/human/tricordrazine + chem_name = "Tricordrazine" + chem_id = "tricordrazine" + desc = "Can be used to treat a wide range of injuries." + +/datum/borer_chem/human/anti_toxin + chem_name = "Dylovene" + chem_id = "anti_toxin" + desc = "General use chemical that neutralizes most toxins in the bloodstream. Can be used as a mild anti-hallucinogen and to reduce tiredness." + +/datum/borer_chem/human/dexalin + chem_name = "Dexalin" + chem_id = "dexalin" + desc = "Feeds oxygen directly into red bloodcells. Used as an antidote to lexorin poisoning." + +/datum/borer_chem/human/peridaxon + chem_name = "Peridaxon" + chem_id = "peridaxon" + desc = "Prevents symptoms caused by damaged internal organs while in the bloodstream, but does not fix the organ damage. Overdosing will cause internal tissue damage." + +/datum/borer_chem/human/imidazoline + chem_name = "Imidazoline" + chem_id = "imidazoline" + desc = "Used for treating non-genetic eye trauma." + cost = 90 + quantity = 5 + +/datum/borer_chem/human/alkysine + chem_name = "Alkysine" + chem_id = "alkysine" + desc = "Small amounts can repair extensive brain trauma. Overdosing on alkysine is extremely toxic." + cost = 80 + quantity = 5 + +/datum/borer_chem/human/quickclot + chem_name = "Quickclot" + chem_id = "quickclot" + desc = "Vastly improves the blood's natural ability to coagulate and stop bleeding. Overdosing will result in severe tissue damage." + cost = 90 + quantity = 5 + +/datum/borer_chem/human/iron + chem_id = "Iron" + chem_id = "iron" + desc = "Promotes production of blood. Overdosing on iron is extremely toxic." + cost = 20 + impure = FALSE + +/datum/borer_chem/human/oxycodone + chem_id = "Oxycodone" + chem_id = "oxycodone" + desc = "An extremely strong painkiller." + cost = 120 + quantity = 5 + +/datum/borer_chem/human/epinephrine + chem_name = "Epinephrine" + chem_id = "adrenaline" + desc = "Useful for restarting the heart. Overdosing may stress the heart and cause tissue damage." + + +//"Motivation" Chems +/datum/borer_chem/human/stimulant_brain + chem_name = "Neurological Stimulant" + chem_id = "brain_stimulant" + desc = "A powerful stimulant that enhances brain function. Lethal in high doses. Lasts one minute per unit." + cost = 300 + quantity = 1 + category = BORER_CAT_STIM + +/datum/borer_chem/human/stimulant_muscle + chem_name = "Musculature Stimulant" + chem_id = "speed_stimulant" + desc = "A powerful stimulant that enhances musculature. Lethal in high doses. Lasts one minute per unit." + cost = 300 + quantity = 1 + category = BORER_CAT_STIM + +/datum/borer_chem/human/neurotoxin + chem_name = "Neurotoxin" + chem_id = PLASMA_NEUROTOXIN + desc = "A potent and hallucinagenic neurotoxin." + cost = 125 + quantity = 1 + category = BORER_CAT_PUNISH + +/datum/borer_chem/human/antineurotoxin + chem_name = "Anti-Neurotoxin" + chem_id = "antineurotoxin" + desc = "A bioagent that counteracts neurotoxins." + cost = 100 + category = BORER_CAT_PUNISH + + + +//Yautja chemicals +/datum/borer_chem/yautja/thwei + chem_name = "Thwei" + chem_id = "thwei" + desc = "A synthetic cocktail of chemicals used to accelerate healing in the Yautja species. It has no effect on humans." + cost = 150 + quantity = 20 + + + +//Anti-Sugar +/datum/borer_chem/human/enzyme + chem_name = "Cortical Enzyme" + chem_id = "benzyme" + desc = "An enzyme focused on consuming chemicals in the bloodstream. Helps fight addictions. This will work as a preventative measure against anti-parasite drugs so long as it is in the bloodstream. Can cause brain damage." + cost = 150 + quantity = 8 + category = BORER_CAT_SELF + impure = FALSE + +/datum/borer_chem/yautja/enzyme + chem_name = "Cortical Enzyme" + chem_id = "benzyme" + desc = "An enzyme focused on consuming chemicals in the bloodstream. Helps fight addictions. This will work as a preventative measure against anti-parasite drugs so long as it is in the bloodstream. Can cause brain damage." + cost = 150 + quantity = 6 + category = BORER_CAT_SELF + impure = FALSE diff --git a/code/modules/borer/borer_html.dm b/code/modules/borer/borer_html.dm new file mode 100644 index 000000000000..f11884e8c435 --- /dev/null +++ b/code/modules/borer/borer_html.dm @@ -0,0 +1,69 @@ +/mob/living/carbon/cortical_borer/proc/get_html_template(content) + var/html = {" + + + Biochemical Synthesizer + + + + + + +
+ [content] +
"} + return html diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm new file mode 100644 index 000000000000..9db7f1542c14 --- /dev/null +++ b/code/modules/borer/borer_procs.dm @@ -0,0 +1,720 @@ +//############# Physical Interaction Procs ############# +/mob/living/carbon/cortical_borer/UnarmedAttack(atom/A) + A.attack_borer(src) + +/atom/proc/attack_borer(mob/living/carbon/cortical_borer/user) + return + + +//Brainslug scans the reagents in a target's bloodstream. +/mob/living/carbon/human/attack_borer(mob/M) + borerscan(M, src) + +/proc/borerscan(mob/living/user, mob/living/M) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.reagents) + if(H.reagents.reagent_list.len) + to_chat(user, SPAN_XENONOTICE("Subject contains the following reagents:")) + for(var/datum/reagent/R in H.reagents.reagent_list) + to_chat(user, "[R.overdose != 0 && R.volume >= R.overdose && !(R.flags & REAGENT_CANNOT_OVERDOSE) ? SPAN_WARNING("OD: ") : ""] [round(R.volume, 1)]u [R.name]") + else + to_chat(user, SPAN_XENONOTICE("Subject contains no reagents.")) + +//Brainslug scuttles under a door, same code as used by xeno larva. +/obj/structure/machinery/door/airlock/attack_borer(mob/living/carbon/cortical_borer/M) + M.scuttle(src) + +/mob/living/carbon/cortical_borer/proc/scuttle(obj/structure/S) + var/move_dir = get_dir(src, loc) + for(var/atom/movable/AM in get_turf(S)) + if(AM != S && AM.density && AM.BlockedPassDirs(src, move_dir)) + to_chat(src, SPAN_WARNING("\The [AM] prevents you from squeezing under \the [S]!")) + return + // Is it an airlock? + if(istype(S, /obj/structure/machinery/door/airlock)) + var/obj/structure/machinery/door/airlock/A = S + if(A.locked || A.welded) //Can't pass through airlocks that have been bolted down or welded + to_chat(src, SPAN_WARNING("\The [A] is locked down tight. You can't squeeze underneath!")) + return + visible_message(SPAN_WARNING("\The [src] scuttles underneath \the [S]!"), \ + SPAN_WARNING("You squeeze and scuttle underneath \the [S]."), null, 5) + forceMove(S.loc) + +//############# Action Give/Take Procs ############# +/mob/living/carbon/cortical_borer/proc/GrantBorerActions() + action_infest_host.give_to(src) + action_toggle_hide.give_to(src) + action_freeze_victim.give_to(src) + +/mob/living/carbon/cortical_borer/proc/RemoveBorerActions() + action_infest_host.remove_from(src) + action_toggle_hide.remove_from(src) + action_freeze_victim.remove_from(src) + +/mob/living/carbon/cortical_borer/proc/GrantInfestActions() + action_talk_to_host.give_to(src) + action_leave_body.give_to(src) + action_take_control.give_to(src) + action_make_chems.give_to(src) + action_scan_chems.give_to(src) + action_hibernate.give_to(src) + +/mob/living/carbon/cortical_borer/proc/RemoveInfestActions() + action_talk_to_host.remove_from(src) + action_take_control.remove_from(src) + action_leave_body.remove_from(src) + action_make_chems.remove_from(src) + action_scan_chems.remove_from(src) + action_hibernate.remove_from(src) + +/mob/living/carbon/cortical_borer/proc/GrantControlActions() + action_talk_to_brain.give_to(host) + action_give_back_control.give_to(host) + action_make_larvae.give_to(host) + action_torment.give_to(host) + +/mob/living/carbon/cortical_borer/proc/RemoveControlActions() + action_talk_to_brain.remove_from(host) + action_make_larvae.remove_from(host) + action_give_back_control.remove_from(host) + action_torment.remove_from(host) + +/mob/living/carbon/cortical_borer/proc/hibernate() + hibernating = !hibernating + if(hibernating) + to_chat(src, SPAN_XENONOTICE("You are now hibernating! Your body will dissolve impurities built up from the creation of chemicals, however your enzyme reserves will not replenish. You cannot act beyond communicating whilst in hibernation.")) + sleeping = 2 + else + sleeping = 0 + to_chat(src, SPAN_XENOWARNING("You are no longer hibernating. You have access to your full capabilities once more.")) + +//############# Control Related Procs ############# +//Check for brain worms in head. +/mob/proc/has_brain_worms() + return FALSE + +/mob/living/carbon/has_brain_worms() + if(borer) + return borer + else + return FALSE + + +//Brainslug infests a target +/mob/living/carbon/cortical_borer/verb/infest() + set category = "Borer" + set name = "Infest" + set desc = "Infest a suitable humanoid host." + + if(host) + to_chat(src, "You are already within a host.") + return + if(stat) + to_chat(src, "You cannot infest a target in your current state.") + return + var/list/choices = list() + for(var/mob/living/carbon/human/H in view(1,src)) + var/obj/limb/head/head = H.get_limb("head") + if(head.status & LIMB_ROBOT) + continue + if(isspeciesyautja(H) && !infect_hunter) + continue + if(H.stat != DEAD && Adjacent(H) && !H.has_brain_worms()) + choices += H + var/mob/living/carbon/human/target = tgui_input_list(src, "Who do you wish to infest?", "Targets", choices) + if(!target || !src) + return + if(!Adjacent(target)) + return + if(target.has_brain_worms()) + to_chat(src, SPAN_WARNING("You cannot infest someone who is already infested!")) + return + if(is_mob_incapacitated()) + return + to_chat(src, SPAN_NOTICE("You slither up [target] and begin probing at their ear canal...")) + if(!do_after(src, 50, INTERRUPT_ALL_OUT_OF_RANGE, BUSY_ICON_HOSTILE, target)) + to_chat(src, SPAN_WARNING("As [target] moves away, you are dislodged and fall to the ground.")) + return + if(!target || !src) + return + if(stat) + to_chat(src, SPAN_XENOWARNING("You cannot infest a target in your current state.")) + return + if(target.stat == DEAD) + to_chat(src, SPAN_WARNING("That is not an appropriate target.")) + return + if(target in view(1, src)) + to_chat(src, SPAN_NOTICE("You wiggle into [target]'s ear.")) + /* + if(!target.stat) + to_chat(target, "Something disgusting and slimy wiggles into your ear!") + */ // Let's see how stealthborers work out + perform_infestation(target) + return + else + to_chat(src, "They are no longer in range!") + return + +/mob/living/carbon/cortical_borer/proc/perform_infestation(mob/living/carbon/target) + if(!target) + return + if(target.has_brain_worms()) + to_chat(src, SPAN_XENOWARNING("[target] is already infested!")) + return + host = target + log_interact(src, host, "Borer: [key_name(src)] Infested [key_name(host)]") + target.borer = src + forceMove(target) + host.status_flags |= PASSEMOTES + host.verbs += /mob/living/proc/borer_comm + RemoveBorerActions() + GrantInfestActions() + + +//Brainslug abandons the host +/mob/living/carbon/cortical_borer/verb/release_host() + set category = "Borer" + set name = "Release Host" + set desc = "Slither out of your host." + if(!host) + to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) + return + if(stat) + to_chat(src, SPAN_XENOWARNING("You cannot leave your host in your current state.")) + return + if(docile) + to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) + return + if(!host || !src) + return + if(leaving) + leaving = FALSE + to_chat(src, SPAN_XENOWARNING("You decide against leaving your host.")) + return + to_chat(src, SPAN_XENOHIGHDANGER("You begin disconnecting from [host]'s synapses and prodding at their internal ear canal.")) + leaving = TRUE + addtimer(CALLBACK(src, PROC_REF(let_go)), 200) + +/mob/living/carbon/cortical_borer/proc/let_go() + if(!host || !src || QDELETED(host) || QDELETED(src)) + return + if(!leaving) + return + if(controlling) + return + if(stat) + to_chat(src, SPAN_XENOWARNING("You cannot release a target in your current state.")) + return + + to_chat(src, SPAN_XENOHIGHDANGER("You wiggle out of [host]'s ear and plop to the ground.")) + + leaving = FALSE + leave_host() + +/mob/living/carbon/cortical_borer/proc/leave_host() + if(!host) + return + if(controlling) + detach() + GrantBorerActions() + RemoveInfestActions() + forceMove(get_turf(host)) + + host.reset_view(null) + + var/mob/living/carbon/H = host + H.borer = null + H.verbs -= /mob/living/proc/borer_comm + action_talk_to_borer.remove_from(host) + H.status_flags &= ~PASSEMOTES + host = null + return + + +//Brainslug takes control of the body +/mob/living/carbon/cortical_borer/verb/bond_brain() + set category = "Borer" + set name = "Assume Control" + set desc = "Fully connect to the brain of your host." + + if(!host) + to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) + return + + if(host.stat == DEAD) + to_chat(src, SPAN_XENODANGER("This host is in no condition to be controlled.")) + return + + if(stat) + to_chat(src, SPAN_XENOWARNING("You cannot do that in your current state.")) + return + + if(docile) + to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) + return + + if(bonding) + bonding = FALSE + to_chat(src, SPAN_XENOWARNING("You stop attempting to take control of your host.")) + return + + to_chat(src, "You begin delicately adjusting your connection to the host brain...") + + if(QDELETED(src) || QDELETED(host)) + return + + bonding = TRUE + + var/delay = 300+(host.getBrainLoss()*5) + addtimer(CALLBACK(src, PROC_REF(assume_control)), delay) + +/mob/living/carbon/cortical_borer/proc/assume_control() + if(!host || !src || controlling) + return + if(!bonding) + return + if(docile) + to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) + return + else + to_chat(src, SPAN_XENOHIGHDANGER("You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system.")) + to_chat(host, SPAN_HIGHDANGER("You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.")) + to_chat(host, SPAN_NOTICE("You can [SPAN_BOLD("resist")] this consciousness, but be warned you may suffer some degree of brain damage in the process!")) + var/borer_key = src.key + log_interact(src, host, "Borer: [key_name(src)] Assumed control of [key_name(host)]") + // host -> brain + var/h2b_id = host.computer_id + var/h2b_ip= host.lastKnownIP + host.computer_id = null + host.lastKnownIP = null + + qdel(host_brain) + host_brain = new(src) + + host_brain.ckey = host.ckey + + host_brain.name = host.name + + if(!host_brain.computer_id) + host_brain.computer_id = h2b_id + + if(!host_brain.lastKnownIP) + host_brain.lastKnownIP = h2b_ip + + // self -> host + var/s2h_id = src.computer_id + var/s2h_ip= src.lastKnownIP + src.computer_id = null + src.lastKnownIP = null + + host.ckey = src.ckey + + if(!host.computer_id) + host.computer_id = s2h_id + + if(!host.lastKnownIP) + host.lastKnownIP = s2h_ip + + bonding = FALSE + controlling = TRUE + + host.verbs += /mob/living/carbon/proc/release_control + host.verbs += /mob/living/carbon/proc/punish_host + host.verbs += /mob/living/carbon/proc/spawn_larvae + host.verbs -= /mob/living/proc/borer_comm + host.verbs += /mob/living/proc/trapped_mind_comm + + GrantControlActions() + action_talk_to_borer.remove_from(host) + host.med_hud_set_status() + + if(src && !src.key) + src.key = "@[borer_key]" + return + +//Captive mind reclaims their body. +/mob/living/captive_brain/proc/return_control(mob/living/carbon/cortical_borer/B) + if(!B || !B.controlling) + return + B.host.adjustBrainLoss(rand(5,10)) + to_chat(src, SPAN_DANGER("With an immense exertion of will, you regain control of your body!")) + to_chat(B.host, SPAN_XENODANGER("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) + B.detach() + +///Brain slug proc for voluntary removal of control. +/mob/living/carbon/proc/release_control() + + set category = "Borer" + set name = "Release Control" + set desc = "Release control of your host's body." + + var/mob/living/carbon/cortical_borer/B = has_brain_worms() + + if(B && B.host_brain) + to_chat(src, SPAN_XENONOTICE("You withdraw your probosci, releasing control of [B.host_brain]")) + + B.detach() + + else + log_debug(EXCEPTION("Missing borer or missing host brain upon borer release."), src) + +/mob/living/carbon/cortical_borer/proc/detach() + if(!host || !controlling) + return + + controlling = FALSE + reset_view(null) + + host.verbs -= /mob/living/carbon/proc/release_control + host.verbs -= /mob/living/carbon/proc/punish_host + host.verbs -= /mob/living/carbon/proc/spawn_larvae + host.verbs += /mob/living/proc/borer_comm + host.verbs -= /mob/living/proc/trapped_mind_comm + + RemoveControlActions() + action_talk_to_borer.give_to(host) + host.med_hud_set_status() + sleeping = 0 + if(host_brain) + log_interact(host, src, "Borer: [key_name(host)] Took control back") + // host -> self + var/h2s_id = host.computer_id + var/h2s_ip= host.lastKnownIP + host.computer_id = null + host.lastKnownIP = null + src.ckey = host.ckey + if(!src.computer_id) + src.computer_id = h2s_id + if(!host_brain.lastKnownIP) + src.lastKnownIP = h2s_ip + + // brain -> host + var/b2h_id = host_brain.computer_id + var/b2h_ip = host_brain.lastKnownIP + host_brain.computer_id = null + host_brain.lastKnownIP = null + host.ckey = host_brain.ckey + + if(!host.computer_id) + host.computer_id = b2h_id + if(!host.lastKnownIP) + host.lastKnownIP = b2h_ip + qdel(host_brain) + return + +//Host Has died +/mob/living/carbon/cortical_borer/proc/host_death(perma = FALSE) + if(!(host && loc == host)) + log_debug("Borer ([key_name(src)]) called host_death without being inside a host!") + return + if(controlling) + detach() + to_chat(src, SPAN_HIGHDANGER("You release your proboscis and flee as the psychic shock of your host's death washes over you!")) + if(perma) + to_chat(src, SPAN_HIGHDANGER("You flee your host in anguish!")) + leave_host() + +//############# External Ability Procs ############# +/mob/living/carbon/cortical_borer/verb/hide_borer() + set category = "Borer" + set name = "Hide" + set desc = "Become invisible to the common eye." + + if(host) + to_chat(usr, SPAN_XENOWARNING("You cannot do this while you're inside a host.")) + return + + if(stat != CONSCIOUS) + return + + if(!hiding) + layer = TURF_LAYER+0.2 + to_chat(src, SPAN_XENONOTICE("You are now hiding.")) + hiding = TRUE + else + layer = MOB_LAYER + to_chat(src, SPAN_XENONOTICE("You stop hiding.")) + hiding = FALSE + +/mob/living/carbon/cortical_borer/verb/dominate_victim() + set category = "Borer" + set name = "Dominate Victim" + set desc = "Freeze the limbs of a potential host with supernatural fear." + + if(world.time - used_dominate < 150) + to_chat(src, SPAN_XENOWARNING("You cannot use that ability again so soon.")) + return + if(host) + to_chat(src, SPAN_XENOWARNING("You cannot do that from within a host body.")) + return + if(stat) + to_chat(src, SPAN_XENOWARNING("You cannot do that in your current state.")) + return + if(attempting_to_dominate) + to_chat(src, SPAN_XENOWARNING("You're already targeting someone!")) + return + var/list/choices = list() + for(var/mob/living/carbon/C in view(3,src)) + if((C.stat != DEAD) && !(issynth(C))) + choices += C + if(world.time - used_dominate < 300) + to_chat(src, SPAN_XENOWARNING("You cannot use that ability again so soon.")) + return + attempting_to_dominate = TRUE + var/mob/living/carbon/M = tgui_input_list(src, "Who do you wish to dominate?", "Targets", choices) + if(!M) + attempting_to_dominate = FALSE + return + if(!src) //different statement to avoid a runtime since if the source is deleted then attempting_to_dominate would also be deleted + return + if(M.has_brain_worms()) + to_chat(src, SPAN_XENOWARNING("You cannot dominate someone who is already infested!")) + attempting_to_dominate = FALSE + return + if(is_mob_incapacitated()) + attempting_to_dominate = FALSE + return + if(get_dist(src, M) > 5) //to avoid people remotely doing from across the map etc, 7 is the default view range + to_chat(src, SPAN_XENOWARNING("You're too far away!")) + attempting_to_dominate = FALSE + return + to_chat(src, SPAN_XENONOTICE("You begin to focus your psychic lance on [M], this will take a few seconds.")) + if(!do_after(src, 30, INTERRUPT_OUT_OF_RANGE, NO_BUSY_ICON, M, max_dist = 5)) + to_chat(src, SPAN_XENODANGER("You are out of position to dominate [M], get closer!")) + attempting_to_dominate = FALSE + return + + to_chat(src, SPAN_XENOWARNING("You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread.")) + to_chat(M, SPAN_WARNING("You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.")) + M.KnockDown(3) + used_dominate = world.time + attempting_to_dominate = FALSE + + +//############# Internal Abiity Procs ############# +/mob/living/carbon/proc/punish_host() + set category = "Borer" + set name = "Torment Host" + set desc = "Punish your host with agony." + + var/mob/living/carbon/cortical_borer/B = has_brain_worms() + + if(!B) + return + + if(B.host_brain) + to_chat(src, SPAN_XENONOTICE("You send a punishing spike of psychic agony lancing into your host's brain.")) + to_chat(B.host_brain, SPAN_XENOHIGHDANGER("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")) + + +/mob/living/carbon/proc/spawn_larvae() + set category = "Borer" + set name = "Reproduce" + set desc = "Spawn a new borer." + + var/mob/living/carbon/cortical_borer/B = has_brain_worms() + + if(!B) + return + if(B.can_reproduce) + if(B.enzymes >= BORER_LARVAE_COST) + to_chat(src, SPAN_XENOWARNING("Your host twitches and quivers as you rapdly excrete a larva from your sluglike body.")) + visible_message(SPAN_WARNING("[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!")) + B.enzymes = 0 + var/turf/T = get_turf(src) + T.add_vomit_floor() + B.contaminant = 0 + var/repro = max(B.can_reproduce - 1, 0) + new /mob/living/carbon/cortical_borer(T, B.generation + 1, TRUE, repro) + else + to_chat(src, SPAN_XENONOTICE("You need at least [BORER_LARVAE_COST] enzymes to reproduce!")) + return + else + to_chat(src, SPAN_XENOWARNING("You are not allowed to reproduce!")) + + + +/mob/living/carbon/cortical_borer/verb/secrete_chemicals() + set category = "Borer" + set name = "Secrete Chemicals" + set desc = "Push some chemicals into your host's bloodstream." + + if(!host) + to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) + return + + if(stat) + to_chat(src, SPAN_XENOWARNING("You cannot secrete chemicals in your current state.")) + + if(docile) + to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) + return + + var/content = "" + + content += "" + + if(ishuman(host)) + if(isspeciesyautja(host)) + for(var/datum in subtypesof(/datum/borer_chem/yautja)) + var/datum/borer_chem/C = datum + var/chem = initial(C.chem_id) + var/datum/reagent/R = chemical_reagents_list[chem] + if(R) + content += "" + else + for(var/datum in subtypesof(/datum/borer_chem/human)) + var/datum/borer_chem/C = datum + var/chem = initial(C.chem_id) + var/datum/reagent/R = chemical_reagents_list[chem] + if(R) + content += "" + + content += "
[initial(C.quantity)] units of [R.name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

[initial(C.quantity)] units of [R.name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

" + + var/html = get_html_template(content) + + usr << browse(null, "window=ViewBorer\ref[src]Chems;size=585x400") + usr << browse(html, "window=ViewBorer\ref[src]Chems;size=585x400") + + return + + + +//############# Communication Procs ############# +/mob/living/carbon/cortical_borer/verb/Communicate() + set category = "Borer" + set name = "Converse with Host" + set desc = "Send a silent message to your host." + + if(!host) + to_chat(src, "You do not have a host to communicate with!") + return + + if(host.stat == DEAD) + to_chat(src, SPAN_XENODANGER("Not even you can commune with the dead.")) + return + + if(stat) + to_chat(src, "You cannot do that in your current state.") + return + + var/input = stripped_input(src, "Please enter a message to tell your host.", "Borer", "") + if(!input) + return + + if(src && !QDELETED(src) && !QDELETED(host)) + var/say_string = (docile) ? "slurs" :"states" + if(host) + to_chat(host, SPAN_XENO("[truename] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) + log_say("BORER: ([key_name(src)] to [key_name(host)]) [input]", src) + to_chat(src, SPAN_XENO("[truename] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) + action_talk_to_borer.give_to(host) + for (var/mob/dead in GLOB.dead_mob_list) + var/track_host = " (F)" + if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping + dead.show_message(SPAN_BORER("BORER: ([truename] to [host.real_name][track_host]) [say_string]: [input]"), SHOW_MESSAGE_VISIBLE) + +/mob/living/carbon/cortical_borer/verb/toggle_silence_inside_host() + set name = "Toggle speech inside Host" + set category = "Borer" + set desc = "Toggle whether you will be able to say audible messages while inside your host." + + if(talk_inside_host) + talk_inside_host = FALSE + to_chat(src, SPAN_XENONOTICE("You will no longer talk audibly while inside a host.")) + else + talk_inside_host = TRUE + to_chat(src, SPAN_XENONOTICE("You will now be able to audibly speak from inside of a host.")) + +/mob/living/proc/borer_comm() + set name = "Converse with Borer" + set category = "Borer" + set desc = "Communicate mentally with your borer." + + + var/mob/living/carbon/cortical_borer/B = has_brain_worms() + if(!B) + return + + if(stat == DEAD) + to_chat(src, SPAN_XENODANGER("You're dead, Jim.")) + return + + var/input = stripped_input(src, "Please enter a message to tell the borer.", "Message", "") + if(!input) + return + + to_chat(B, SPAN_XENO("[src] says: [input]"), type = MESSAGE_TYPE_RADIO) + log_say("BORER: ([key_name(src)] to [key_name(B)]) [input]", src) + to_chat(src, SPAN_XENO("[src] says: [input]"), type = MESSAGE_TYPE_RADIO) + for (var/mob/dead in GLOB.dead_mob_list) + var/track_host = " (F)" + if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping + dead.show_message(SPAN_BORER("BORER: ([name][track_host] to [B.truename]) says: [input]"), SHOW_MESSAGE_VISIBLE) + +/mob/living/proc/trapped_mind_comm() + set name = "Converse with Trapped Mind" + set category = "Borer" + set desc = "Communicate mentally with the trapped mind of your host." + + + var/mob/living/carbon/cortical_borer/B = has_brain_worms() + if(!B || !B.host_brain) + return + var/mob/living/captive_brain/CB = B.host_brain + var/input = stripped_input(src, "Please enter a message to tell the trapped mind.", "Message", "") + if(!input) + return + + to_chat(CB, SPAN_XENO("[B.truename] says: [input]"), type = MESSAGE_TYPE_RADIO) + log_say("BORER: ([key_name(src)] to [key_name(CB)]) [input]", B) + to_chat(src, SPAN_XENO("[B.truename] says: [input]"), type = MESSAGE_TYPE_RADIO) + for (var/mob/dead in GLOB.dead_mob_list) + var/track_borer = " (F)" + if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping + dead.show_message(SPAN_BORER("BORER: ([B.truename][track_borer] to [real_name] (trapped mind)) says: [input]"), SHOW_MESSAGE_VISIBLE) + + + + +//############# TOPIC ############# +/mob/living/carbon/cortical_borer/Topic(href, href_list, hsrc) + if(href_list["borer_use_chem"]) + locate(href_list["src"]) + if(!istype(src, /mob/living/carbon/cortical_borer)) + return + if(docile) + to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) + return + + var/topic_chem = href_list["borer_use_chem"] + var/datum/borer_chem/C = null + + for(var/datum in typesof(/datum/borer_chem)) + var/datum/borer_chem/test = datum + if(initial(test.chem_id) == topic_chem) + C = new test() + break + + if(!C || !host || controlling || !src || stat) + return + var/datum/reagent/R = chemical_reagents_list[C.chem_id] + if(enzymes < C.cost) + to_chat(src, SPAN_XENOWARNING("You need [C.cost] enzymes stored to secrete [R.name]!")) + return + var/contamination = round(C.cost / 10) + if(C.impure && ((contaminant + contamination) > max_contaminant)) + to_chat(src, SPAN_XENOWARNING("You are too contaminated to secrete [R.name]!")) + return + to_chat(src, SPAN_XENONOTICE("You squirt a measure of [R.name] from your reservoirs into [host]'s bloodstream.")) + contaminant += contamination + host.reagents.add_reagent(C.chem_id, C.quantity) + enzymes -= C.cost + log_interact(src, host, "[key_name(src)] has injected [C.quantity] units of [R.name] into their host, [key_name(host)]") + + // This is used because we use a static set of datums to determine what chems are available, + // instead of a table or something. Thus, when we instance it, we can safely delete it + qdel(C) + ..() diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index b2a68c997ec9..61b5c07ba159 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -115,3 +115,9 @@ /obj/item/holder/mouse/brown/Tom name = "Tom" desc = "Jerry the cat is not amused." + +/obj/item/holder/borer + name = "cortical borer" + desc = "Gross..." + icon = 'icons/mob/animal.dmi' + icon_state = "brainslug_dead" diff --git a/code/modules/mob/language/languages.dm b/code/modules/mob/language/languages.dm index 546c2bf7714f..5760255ff38d 100644 --- a/code/modules/mob/language/languages.dm +++ b/code/modules/mob/language/languages.dm @@ -202,3 +202,47 @@ color = "tajaran" key = "7" flags = RESTRICTED|HIVEMIND + +/datum/language/corticalborer + name = LANGUAGE_BORER + desc = "Cortical borers possess a strange link between their tiny minds." + speech_verb = "sings" + ask_verb = "sings" + exclaim_verb = "sings" + color = "alien" + key = "0" + flags = RESTRICTED|HIVEMIND + +/datum/language/corticalborer/broadcast(mob/living/speaker, message, speaker_mask, death) + var/mob/living/carbon/cortical_borer/B + if(!speaker_mask) + speaker_mask = speaker + if(iscarbon(speaker)) + var/mob/living/carbon/M = speaker + B = M.has_brain_worms() + else if(istype(speaker,/mob/living/carbon/cortical_borer)) + B = speaker + + if(B) + speaker_mask = B.truename + + var/message_start = "[name], [speaker_mask]" + var/message_body = "[speech_verb], \"[message]\"" + log_say("[key_name(speaker)] : ([name]) [message]") + + for(var/mob/player in GLOB.player_list) + var/understood = FALSE + var/ghost = FALSE + if(istype(player,/mob/dead)) + understood = TRUE + ghost = TRUE + else if((src in player.languages) && check_special_condition(player)) + understood = TRUE + if(understood) + if(!speaker_mask) + speaker_mask = speaker.name + if(death) + var/area/A = get_area(speaker) + to_chat(player, "[message_start] has [SPAN_BOLD("perished")][A? " at [sanitize_area(A.name)]":""]!") + else + to_chat(player, "[ghost? "(F) ":""][message_start] [message_body]") diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index ecd1b6c97ca9..7993a7435e2b 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -23,6 +23,8 @@ var/datum/huntdata/hunter_data //Stores all information relating to Hunters for use with their HUD and other systems. + var/mob/living/carbon/cortical_borer/borer = null + /mob/living/carbon/vv_get_dropdown() . = ..() VV_DROPDOWN_OPTION("", "-----CARBON-----") diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 5496cae5370f..4854bf954e28 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -47,6 +47,9 @@ disable_lights() disable_special_items() disable_headsets() //Disable radios for dead people to reduce load + var/mob/living/carbon/cortical_borer/Player2 = has_brain_worms() + if(Player2) + Player2.host_death(undefibbable) if(pulledby && isxeno(pulledby)) // Xenos lose grab on dead humans pulledby.stop_pulling() //Handle species-specific deaths. diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 4e39b347160b..ffcbb80c6442 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -137,6 +137,24 @@ if(eta_status) . += "Evacuation: [eta_status]" + var/mob/living/carbon/cortical_borer/B = borer + if(B && B.controlling) + + var/CR = "Yes" + if(!B.can_reproduce) + CR = "Forbidden" + else if((B.enzymes < BORER_LARVAE_COST)) + CR = "No" + + . += "" + . += "Borer:" + . += "Name: [B.truename]" + . += "Can Reproduce: [CR]" + . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" + . += "" + . += "Host Brain Damage: [brainloss]/100" + + /mob/living/carbon/human/ex_act(severity, direction, datum/cause_data/cause_data) if(lying) severity *= EXPLOSION_PRONE_MULTIPLIER diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index d64e5d1bfde0..df9f0c259e4f 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -66,6 +66,9 @@ if(life_tick > 5 && timeofdeath && (timeofdeath < 5 || world.time - timeofdeath > revive_grace_period) && !issynth(src)) //We are dead beyond revival, or we're junk mobs spawned like the clowns on the clown shuttle undefibbable = TRUE SEND_SIGNAL(src, COMSIG_HUMAN_SET_UNDEFIBBABLE) + var/mob/living/carbon/cortical_borer/B = has_brain_worms() + if(B) + B.host_death(TRUE) med_hud_set_status() else if(stat != DEAD) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index e5934f4fa13b..bb9cf9309a2b 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -128,6 +128,10 @@ var/list/department_radio_keys = list( continue if(M.loc && (M.locs[1] in hearturfs)) listening |= M + for(var/mob/inner_mob in M.contents) + listening |= inner_mob + for(var/mob/living/captive_brain/brain in inner_mob) + listening |= brain var/speech_bubble_test = say_test(message) var/image/speech_bubble = image('icons/mob/effects/talk.dmi', src, "[bubble_type][speech_bubble_test]", FLY_LAYER) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 2bf44188eff4..9090ac3ebb4d 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -228,6 +228,7 @@ if(icon_gib) new /obj/effect/overlay/temp/gib_animation/animal(loc, src, icon_gib) + /mob/living/simple_animal/attack_animal(mob/living/M as mob) if(M.melee_damage_upper == 0) M.emote("[M.friendly] [src]") @@ -349,7 +350,7 @@ if (targeted_by && target_locked) overlays += target_locked -/mob/living/simple_animal/say(message) +/mob/living/simple_animal/say(message, datum/language/speaking = null) if(stat) return @@ -367,7 +368,7 @@ message = capitalize(trim_left(message)) - ..(message, null, verb, nolog = !ckey) //if the animal has a ckey then it will log the message + ..(message, speaking, verb, nolog = !ckey) //if the animal has a ckey then it will log the message /mob/living/simple_animal/update_canmove() . = ..() diff --git a/code/modules/reagents/chemistry_machinery/reagent_grinder.dm b/code/modules/reagents/chemistry_machinery/reagent_grinder.dm index 1de4a84451e1..2929d3aba0d2 100644 --- a/code/modules/reagents/chemistry_machinery/reagent_grinder.dm +++ b/code/modules/reagents/chemistry_machinery/reagent_grinder.dm @@ -54,6 +54,7 @@ /obj/item/reagent_container/food/snacks/watermelonslice = list("watermelonjuice" = 0), /obj/item/reagent_container/food/snacks/grown/grapes = list("grapejuice" = 0), /obj/item/reagent_container/food/snacks/grown/poisonberries = list("poisonberryjuice" = 0), + /obj/item/holder/borer = list("benzyme" = 0), ) @@ -411,6 +412,15 @@ if(!O.reagents.total_volume) remove_object(O) + //Borer, for enzymes + for(var/obj/item/holder/borer/b_holder in holdingitems) + if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume + beaker.reagents.add_reagent("benzyme",min(6, space)) + remove_object(b_holder) + break + /obj/structure/machinery/reagentgrinder/proc/cleanup() SIGNAL_HANDLER if(linked_storage) diff --git a/code/modules/reagents/chemistry_properties/prop_positive.dm b/code/modules/reagents/chemistry_properties/prop_positive.dm index eb8cb1988665..1bef0df75a34 100644 --- a/code/modules/reagents/chemistry_properties/prop_positive.dm +++ b/code/modules/reagents/chemistry_properties/prop_positive.dm @@ -461,9 +461,22 @@ H.vomit() else A.counter = 90 + if(H.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) + return + + H.chem_effect_flags |= CHEM_EFFECT_ANTI_PARASITE + to_chat(H, SPAN_NOTICE("Your body feels warmer.")) /datum/chem_property/positive/antiparasitic/process_overdose(mob/living/M, potency = 1) M.apply_damage(potency, TOX) + var/mob/living/carbon/cortical_borer/player_2 = M.has_brain_worms() + if(player_2) + if(player_2.controlling) + player_2.detach() + to_chat(src, SPAN_HIGHDANGER("You relinquish the unknown chemical overwhelms you!")) + + player_2.leave_host() + to_chat(src, SPAN_HIGHDANGER("The overwhelming flow of powerful chemicals forces you to flee your host!")) /datum/chem_property/positive/antiparasitic/process_critical(mob/living/M, potency = 1) M.apply_damage(POTENCY_MULTIPLIER_VHIGH*potency, TOX) diff --git a/code/modules/reagents/chemistry_reactions/other.dm b/code/modules/reagents/chemistry_reactions/other.dm index 3956a4d9dc5c..bfa7a57688e6 100644 --- a/code/modules/reagents/chemistry_reactions/other.dm +++ b/code/modules/reagents/chemistry_reactions/other.dm @@ -462,3 +462,11 @@ result = "eggplasma" required_reagents = list("blood" = 10, "eggplasma" = 1) result_amount = 2 + +/datum/chemical_reaction/borer_cure + name = "Anti-Enzyme" + id = "bcure" + result = "bcure" + required_reagents = list("benzyme" = 2, "anti_toxin" = 4) + result_amount = 3 + mob_react = FALSE diff --git a/code/modules/reagents/chemistry_reagents/other.dm b/code/modules/reagents/chemistry_reagents/other.dm index aaf9901f46af..fdb84b7aa48b 100644 --- a/code/modules/reagents/chemistry_reagents/other.dm +++ b/code/modules/reagents/chemistry_reagents/other.dm @@ -1013,3 +1013,27 @@ chemclass = CHEM_CLASS_SPECIAL properties = list(PROPERTY_TRANSFORMATIVE = 4, PROPERTY_NUTRITIOUS = 3, PROPERTY_HEMOGENIC = 1) flags = REAGENT_SCANNABLE + +/datum/reagent/borer_enzyme + name = "Cortical Enzyme" + id = "benzyme" + description = "An enzyme secreted by a parasite that consumes certain chemicals from the bloodstream. Also seems to help fight addictions." + reagent_state = LIQUID + color = "#25c08c" + overdose = LOW_REAGENTS_OVERDOSE + overdose_critical = LOW_REAGENTS_OVERDOSE_CRITICAL + chemclass = CHEM_CLASS_SPECIAL + flags = REAGENT_SCANNABLE|REAGENT_NO_GENERATION + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTIADDICTIVE = 2) + +/datum/reagent/borer_cure + name = "Anti-Enzyme" + id = "bcure" + description = "An anti-parasite drug synthesised from parastic enzymes. Effectively fights toxins in the bloodstream." + reagent_state = LIQUID + color = "#25c08c" + overdose = LOW_REAGENTS_OVERDOSE + overdose_critical = LOW_REAGENTS_OVERDOSE_CRITICAL + chemclass = CHEM_CLASS_SPECIAL + flags = REAGENT_SCANNABLE|REAGENT_NO_GENERATION + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTITOXIN = 4) diff --git a/code/span_macros.dm b/code/span_macros.dm index 77ee3b62d56c..0277c14565c1 100644 --- a/code/span_macros.dm +++ b/code/span_macros.dm @@ -82,6 +82,7 @@ #define SPAN_AVOIDHARM(X) "[X]" #define SPAN_SCANNER(X) "[X]" +#define SPAN_BORER(X) "[X]" #define SPAN_ROSE(X) "[X]" #define SPAN_LANGCHAT(X) "[X]" diff --git a/colonialmarines.dme b/colonialmarines.dme index 3a46b2af5801..75e644a940ec 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -1359,6 +1359,11 @@ #include "code\modules\asset_cache\assets\tgui.dm" #include "code\modules\asset_cache\assets\vending.dm" #include "code\modules\asset_cache\transports\asset_transport.dm" +#include "code\modules\borer\_defines.dm" +#include "code\modules\borer\borer.dm" +#include "code\modules\borer\borer_chemicals.dm" +#include "code\modules\borer\borer_html.dm" +#include "code\modules\borer\borer_procs.dm" #include "code\modules\buildmode\bm-mode.dm" #include "code\modules\buildmode\buildmode.dm" #include "code\modules\buildmode\buttons.dm" diff --git a/icons/mob/brainslug.dmi b/icons/mob/brainslug.dmi new file mode 100644 index 0000000000000000000000000000000000000000..db29b87ac953f66b36ab8fd1596c80f537c02914 GIT binary patch literal 4277 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 JRmN_2{s+a-{Wt&s literal 0 HcmV?d00001 diff --git a/icons/mob/hud/actions_borer.dmi b/icons/mob/hud/actions_borer.dmi new file mode 100644 index 0000000000000000000000000000000000000000..9447b8f546211f96dd4fa71ebe28446e13d25f14 GIT binary patch literal 2032 zcmVC0001ZP)t-sz`(#! zIbbj%I$1zwVlP;HJZ~r*FgzVWNgqil7%U+WBLMZ=HmsP}mH^CV03>f>Hybe*3m7*b zJef1hNGng5Nr+1%QLIy%HX%DjAwFjc3Zw!8wo?G6tTx&80K?ZGmYXztS4((GOI27I zY;Pq0%w~mUX28I}vW^k-00001bW%=J06^y0W&i*Hy?RtwbVOxyV{&P5bZKvH004NL zm6E{$?nJ!Mj?u8nppm$MWWTyNuEDC!7XOkM#28)IRlM2glSZPQ$e4)q9o{$VN3 zo{6s3(FDk(P4E%Jz|}CCt1*CHfXT*yBlyUqo$r9Suyw8TeUlx-b0&^3VQ6Q=J(LE3 z>4?vF;jdAu%DVV`;TtkP#8j>IGD!dc23<)+K~#90?V5{vn>q}D!)!_*q)xh&lbR6d zdU^jxoMd6*D>TVz((fBun+pQzN0x1*Zn2nUmLDNWNPgW;zepGf=V_YupV@=2x8#4+ zp8&Gua>>69fNO~X@H}5G^MXeVtgZyW@RINtKn4-W@-*(CT(MOdbFf}N;@jindL7cA z{1ZU{AVvS902GPxk_hm$kH01e0TdYopnx$-#~ldY!6V*2{^|gD0DRdCGI#(g`O`uP zN8B&~!n5+S2rM^RfWQOblmqBL<0@bw2Wh@qmC+pNBhUxH(Zl_3Hd_=;U;@zOPZ1!` zvy@WCcTlcYkR-)ajsyX@_KyS}0H^S303vW5lw}Gj3UVpHR*MfnNrIEGzzX;m4}lb2kEN6o8@hlMn*1L;no35g_tF1U91pu>NkgF#O=Y*lrjvs{P&pz^yPc z&k-P105BNr8AIRzEcppQ`L_YoGr$WFAo+Il0;>XyhYR355tsnE1^`hxfCR=6^QGDf zhLsq;awEbEwena1NZ$(o;PXO2-5K#ls`u@uR zXkW$w1oa0*#6Y~hC;edxK$3kK2cZ6d|Hw5}-wzR}5A0CK0myzG1t_UM5C#~l@9iPz z5qy13_D2AyKOltr*gaL>yEz~u0AycER(k*{`Ag~#Kn`H(aYlV__Ydko1k|yb>;s;x zT>wEjp!x&&83@j(?@#@M!=Vo5fTSEy_VF_im;f~SOF`wi`Xb6R>U$mH!y(*1AgEfB zef34wCV;yCasVKLGwOQ*q3gSE=mFZjs5`617`?E>w6UeDWm;^T7uTFkMqD9f)e~&{Q)2laR9HrpXwjf z;NP+j1ojY!(&-OCOwK5;?f!w3wL1i|cI-n;tRxg(e?WK}{0U5Aw0R;O4!T}hm?x1^C1pw=>*&h&Ye_*`6 zPx^Jp+7K)NSbt6X(zd@)&j40=F0B5*RDG|L@DKq|&j6NvY1v<>mB;Q62(v#hRo|a> z!$S~2tvt4UY1$9=2ZWIWQ}z91{~%yrnmI7bEVIlq%eU134`09j`ue|Vjx8SR+NN!~ zv#-A%plzF@I@qzUJ9f7R=$fW&wW4dgiviYa{g>acfme`_K7rUD6P6GJ#UONj#J)a( zl;J-f8yNf#1g8F-VGO!1X^%rL zK78FioS^j|AHx}z0qy_ub0DzRf%lFjD$q?I0tcYC|M7tiJo}4e&D;~%+BERm-}&b! z5~xVLS`ldU^23@o0HE!I2Ntk@J-{1#(*UgwK@i}Bg#oS|0><9EcRK{lSwnDb62g(U z=3ON}X5;bvB)oDOGDV<6(D+F>Jq@p1h!8-JL81nsarILR5xZt7X4d#)Lbm5G#iYD! zGa~N{=RnI^^?u1_WXn0*@#!cm#!A}bO`iwo2tE{mYbD3_4geSHzgXYL^+EL+*UvJ` zEVIlqUB7=jz|>|j1KbQC^2l{7fapW#Z2(3dyKe$8R(RY3V6^nQ0YLBnRQ Date: Sun, 2 Apr 2023 05:16:11 +0100 Subject: [PATCH 02/52] Modernisation HUD and more modernisation holder icon follow and PP fix + Life() ack! Minor tweaks and updates ert name ladders x f scanner detection --- code/__DEFINES/mob_hud.dm | 2 + code/__DEFINES/typecheck/xenos.dm | 1 + code/__HELPERS/unsorted.dm | 2 + code/datums/mob_hud.dm | 34 ++-- .../game/machinery/medical_pod/bodyscanner.dm | 3 + .../admin/player_panel/player_panel.dm | 2 + code/modules/borer/_defines.dm | 5 + code/modules/borer/borer.dm | 146 +++++++++++++----- code/modules/borer/borer_procs.dm | 141 ++++++++--------- code/modules/mob/dead/observer/orbit.dm | 5 + code/modules/mob/holder.dm | 4 +- .../mob/living/carbon/human/human_defines.dm | 2 +- .../mob/living/carbon/xenomorph/Xenomorph.dm | 2 +- code/modules/mob/living/living_healthscan.dm | 2 +- .../chemistry_properties/prop_positive.dm | 2 +- code/modules/surgery/brainworm.dm | 80 ++++++++++ colonialmarines.dme | 1 + icons/mob/brainslug.dmi | Bin 4277 -> 4282 bytes icons/mob/hud/hud.dmi | Bin 19035 -> 19314 bytes tgui/packages/tgui/interfaces/HealthScan.js | 5 + tgui/packages/tgui/interfaces/Orbit/index.tsx | 2 + tgui/packages/tgui/interfaces/Orbit/types.ts | 1 + 22 files changed, 312 insertions(+), 130 deletions(-) create mode 100644 code/modules/surgery/brainworm.dm diff --git a/code/__DEFINES/mob_hud.dm b/code/__DEFINES/mob_hud.dm index 69b4aa29eab2..b5cbb56e7456 100644 --- a/code/__DEFINES/mob_hud.dm +++ b/code/__DEFINES/mob_hud.dm @@ -25,6 +25,7 @@ #define STATUS_HUD_XENO_CULTIST "24" // Whether they are a xeno cultist or not #define HUNTER_CLAN "25" //Displays a colored icon to represent ingame Hunter Clans #define HUNTER_HUD "26" //Displays various statuses on mobs for Hunters to identify targets +#define STATUS_HUD_BRAINWORM "27" //Displays infested HUD for brainworms. //data HUD (medhud, sechud) defines #define MOB_HUD_SECURITY_BASIC 1 @@ -44,6 +45,7 @@ #define MOB_HUD_FACTION_PMC 15 #define MOB_HUD_HUNTER 16 #define MOB_HUD_HUNTER_CLAN 17 +#define MOB_HUD_BRAINWORM 18 //for SL/FTL/LZ targeting on locator huds #define TRACKER_SL "track_sl" diff --git a/code/__DEFINES/typecheck/xenos.dm b/code/__DEFINES/typecheck/xenos.dm index 4d1b7819bdf1..6ae8fe1955a0 100644 --- a/code/__DEFINES/typecheck/xenos.dm +++ b/code/__DEFINES/typecheck/xenos.dm @@ -1,5 +1,6 @@ //Xenomorph Hud Test APOPHIS 22MAY2015 #define isxeno(A) (istype(A, /mob/living/carbon/xenomorph)) +#define isborer(A) (istype(A, /mob/living/carbon/cortical_borer)) #define isxeno_human(A) (isxeno(A) || ishuman(A)) //ask walter if i should turn into castechecks diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 5d25df2150c0..25890101758b 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -624,6 +624,8 @@ moblist.Add(M) for(var/mob/living/carbon/xenomorph/M in sortmob) moblist.Add(M) + for(var/mob/living/carbon/cortical_borer/M in sortmob) + moblist.Add(M) for(var/mob/dead/observer/M in sortmob) moblist.Add(M) for(var/mob/new_player/M in sortmob) diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm index fa2af17240f9..a6d4e2c09a09 100644 --- a/code/datums/mob_hud.dm +++ b/code/datums/mob_hud.dm @@ -18,7 +18,8 @@ var/list/datum/mob_hud/huds = list( MOB_HUD_FACTION_CLF = new /datum/mob_hud/faction/clf(), MOB_HUD_FACTION_PMC = new /datum/mob_hud/faction/pmc(), MOB_HUD_HUNTER = new /datum/mob_hud/hunter_hud(), - MOB_HUD_HUNTER_CLAN = new /datum/mob_hud/hunter_clan() + MOB_HUD_HUNTER_CLAN = new /datum/mob_hud/hunter_clan(), + MOB_HUD_BRAINWORM = new /datum/mob_hud/brainworm(), ) /datum/mob_hud @@ -129,7 +130,7 @@ var/list/datum/mob_hud/huds = list( //medical hud used by ghosts /datum/mob_hud/medical/observer - hud_icons = list(HEALTH_HUD, STATUS_HUD_OOC, STATUS_HUD_XENO_CULTIST) + hud_icons = list(HEALTH_HUD, STATUS_HUD_OOC, STATUS_HUD_XENO_CULTIST, STATUS_HUD_BRAINWORM) //infection status that appears on humans, viewed by xenos only and observers. @@ -151,6 +152,8 @@ var/list/datum/mob_hud/huds = list( /datum/mob_hud/hunter_hud hud_icons = list(HUNTER_HUD) +/datum/mob_hud/brainworm + hud_icons = list(HEALTH_HUD_XENO, PLASMA_HUD, PHEROMONE_HUD, QUEEN_OVERWATCH_HUD, ARMOR_HUD_XENO, XENO_STATUS_HUD, XENO_BANISHED_HUD, HEALTH_HUD, STATUS_HUD_OOC, STATUS_HUD_XENO_CULTIST, STATUS_HUD_BRAINWORM) //Security /datum/mob_hud/security @@ -207,7 +210,7 @@ var/list/datum/mob_hud/huds = list( /mob/living/carbon/xenomorph/add_to_all_mob_huds() for(var/datum/mob_hud/hud in huds) - if(!istype(hud, /datum/mob_hud/xeno)) + if(!istype(hud, /datum/mob_hud/xeno) && !istype(hud, /datum/mob_hud/brainworm)) continue hud.add_to_hud(src) @@ -230,7 +233,7 @@ var/list/datum/mob_hud/huds = list( if(istype(hud, /datum/mob_hud/xeno)) hud.remove_from_hud(src) hud.remove_hud_from(src) - else if (istype(hud, /datum/mob_hud/xeno_infection)) + else if (istype(hud, /datum/mob_hud/xeno_infection) || istype(hud, /datum/mob_hud/brainworm)) hud.remove_hud_from(src) @@ -263,6 +266,7 @@ var/list/datum/mob_hud/huds = list( /mob/living/carbon/xenomorph/med_hud_set_health() var/image/holder = hud_list[HEALTH_HUD_XENO] + var/image/holder2 = hud_list[STATUS_HUD_BRAINWORM] var/health_hud_type = "xenohealth" if(stat == DEAD) @@ -278,6 +282,13 @@ var/list/datum/mob_hud/huds = list( amount = -1 //don't want the 'zero health' icon when we are crit holder.icon_state = "[health_hud_type][amount]" + holder2.icon_state = null + if(has_brain_worms()) + holder2.icon_state = "hudbrainwormhost" + holder2.pixel_x = 9 + holder2.pixel_y = -8 + + /mob/living/carbon/xenomorph/proc/overlay_shields() var/image/holder = hud_list[HEALTH_HUD_XENO] holder.overlays.Cut() @@ -340,10 +351,12 @@ var/list/datum/mob_hud/huds = list( holder2.overlays.Cut() var/image/holder3 = hud_list[STATUS_HUD_XENO_INFECTION] var/image/holder4 = hud_list[STATUS_HUD_XENO_CULTIST] + var/image/holder5 = hud_list[STATUS_HUD_BRAINWORM] holder2.color = null holder3.color = null holder4.color = null + holder5.color = null holder4.icon_state = "hudblank" @@ -447,11 +460,14 @@ var/list/datum/mob_hud/huds = list( return var/mob/living/carbon/cortical_borer/B = has_brain_worms() - if(B && B.controlling) - holder.icon_state = "hudbrainworm" - if(!holder2_set) - holder2.icon_state = "hudbrainworm" - return + holder5.icon_state = null + if(B) + holder5.icon_state = "hudbrainwormhost" + if(B.controlling) + holder.icon_state = "hudbrainworm" + if(!holder2_set) + holder2.icon_state = "hudbrainworm" + return for(var/datum/disease/D in viruses) if(!D.hidden[SCANNER]) diff --git a/code/game/machinery/medical_pod/bodyscanner.dm b/code/game/machinery/medical_pod/bodyscanner.dm index 4756121e50ae..3cd2cf075d1b 100644 --- a/code/game/machinery/medical_pod/bodyscanner.dm +++ b/code/game/machinery/medical_pod/bodyscanner.dm @@ -390,6 +390,9 @@ if(occ["sdisabilities"] & NEARSIGHTED) dat += SET_CLASS("Retinal misalignment detected.", INTERFACE_RED) dat += "
" + if(connected.occupant.has_brain_worms()) + dat += SET_CLASS("Cranial anomoly detected.", INTERFACE_RED) + dat += "
" dat += "" return dat diff --git a/code/modules/admin/player_panel/player_panel.dm b/code/modules/admin/player_panel/player_panel.dm index 12686e683521..ada3d1100687 100644 --- a/code/modules/admin/player_panel/player_panel.dm +++ b/code/modules/admin/player_panel/player_panel.dm @@ -201,6 +201,8 @@ M_job = "Monkey" else if(isxeno(M)) M_job = "Alien" + else if(isborer(M)) + M_job = "Brainslug" else M_job = "Carbon-based" else if(isSilicon(M)) //silicon diff --git a/code/modules/borer/_defines.dm b/code/modules/borer/_defines.dm index 15929f6fa492..a1c7b4959e50 100644 --- a/code/modules/borer/_defines.dm +++ b/code/modules/borer/_defines.dm @@ -6,3 +6,8 @@ ///Amount of chemicals needed for a borer to reproduce, provided reproduction is toggled. #define BORER_LARVAE_COST 400 + +#define ACTION_SET_HOSTLESS "actions_hostless" +#define ACTION_SET_HUMANOID "actions_human" +#define ACTION_SET_XENO "actions_xeno" +#define ACTION_SET_CONTROL "actions_control" diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 683956bf1fb4..81afde2f1be9 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -53,7 +53,7 @@ desc = "A small, quivering sluglike creature." speak_emote = list("chirrups") icon = 'icons/mob/brainslug.dmi' - icon_state = "brainslug" + icon_state = "Borer" speed = 0 a_intent = INTENT_HARM status_flags = CANPUSH @@ -70,6 +70,7 @@ holder_type = /obj/item/holder/borer var/generation = 1 + var/stealthy = FALSE var/static/list/borer_names = list( "Primary", "Secondary", "Tertiary", "Quaternary", "Quinary", "Senary", "Septenary", "Octonary", "Novenary", "Decenary", "Undenary", "Duodenary", @@ -93,25 +94,55 @@ var/leaving = FALSE var/hiding = FALSE var/can_reproduce = FALSE // Locked to manual override to prevent things getting out of hand. - var/infect_hunter = FALSE // Locked for normal use. + + var/infect_humans = TRUE // Locked for normal use. + var/infect_xenos = FALSE + var/infect_yautja = FALSE var/list/datum/reagent/synthesized_chems - /// All of these surely have a better way of being handled. - var/datum/action/innate/borer/talk_to_host/action_talk_to_host = new - var/datum/action/innate/borer/infest_host/action_infest_host = new - var/datum/action/innate/borer/toggle_hide/action_toggle_hide = new - var/datum/action/innate/borer/talk_to_borer/action_talk_to_borer = new - var/datum/action/innate/borer/talk_to_brain/action_talk_to_brain = new - var/datum/action/innate/borer/take_control/action_take_control = new - var/datum/action/innate/borer/give_back_control/action_give_back_control = new - var/datum/action/innate/borer/leave_body/action_leave_body = new - var/datum/action/innate/borer/make_chems/action_make_chems = new - var/datum/action/innate/borer/make_larvae/action_make_larvae = new - var/datum/action/innate/borer/freeze_victim/action_freeze_victim = new - var/datum/action/innate/borer/torment/action_torment = new - var/datum/action/innate/borer/scan_chems/action_scan_chems = new - var/datum/action/innate/borer/hibernate/action_hibernate = new + var/current_actions = ACTION_SET_HOSTLESS + var/list/actions_hostless = list( + /datum/action/innate/borer/toggle_hide, + /datum/action/innate/borer/freeze_victim, + /datum/action/innate/borer/infest_host + ) + var/list/actions_humanoidhost = list( + /datum/action/innate/borer/take_control, + /datum/action/innate/borer/talk_to_host, + /datum/action/innate/borer/leave_body, + /datum/action/innate/borer/hibernate, + /datum/action/innate/borer/scan_chems, + /datum/action/innate/borer/make_chems + ) + var/list/actions_xenohost = list( + /datum/action/innate/borer/take_control, + /datum/action/innate/borer/talk_to_host, + /datum/action/innate/borer/leave_body, + /datum/action/innate/borer/hibernate + ) + var/list/actions_control = list( + /datum/action/innate/borer/give_back_control, + /datum/action/innate/borer/make_larvae, + /datum/action/innate/borer/talk_to_brain, + /datum/action/innate/borer/torment + ) + +//################### INIT & LIFE ###################// +/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0) + ..(newloc) + SSmob.living_misc_mobs += src + generation = gen + add_language(LANGUAGE_BORER) + var/mob_number = rand(1000,9999) + real_name = "Cortical Borer [mob_number]" + truename = "[borer_names[min(generation, borer_names.len)]] [mob_number]" + can_reproduce = reproduction + give_new_actions(ACTION_SET_HOSTLESS) + //GrantBorerActions() + GiveBorerHUD() + if((!is_admin_level(z)) && ERT) + summon() /mob/living/carbon/cortical_borer/initialize_pass_flags(datum/pass_flags_container/PF) ..() @@ -119,9 +150,59 @@ PF.flags_pass = PASS_MOB_THRU|PASS_FLAGS_CRAWLER PF.flags_can_pass_all = PASS_ALL^PASS_OVER_THROW_ITEM +/mob/living/carbon/cortical_borer/initialize_pain() + pain = new /datum/pain/zombie(src) +/mob/living/carbon/cortical_borer/initialize_stamina() + stamina = new /datum/stamina/none(src) + +/mob/living/carbon/cortical_borer/updatehealth() + if(status_flags & GODMODE) + health = maxHealth + set_stat(CONSCIOUS) + else + health = maxHealth - getFireLoss() - getBruteLoss() - getToxLoss() //Borer can only take brute, fire and tox damage. + + if(stat != DEAD && !gibbing) + if(health <= -50) //dead + death(last_damage_data) + return + else if(health <= 0) //in crit + handle_crit() + +/mob/living/carbon/cortical_borer/proc/handle_crit() + if(stat == DEAD || gibbing) + return + + sound_environment_override = SOUND_ENVIRONMENT_NONE + set_stat(UNCONSCIOUS) + blinded = TRUE + if(layer != initial(layer)) //Unhide + layer = initial(layer) + recalculate_move_delay = TRUE + if(!lying) + update_canmove() + update_icons() + +/mob/living/carbon/cortical_borer/death() + var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] + c_link.broadcast(src, null, src.truename, TRUE) + SSmob.living_misc_mobs -= src + . = ..() + +/mob/living/carbon/cortical_borer/rejuvenate() + ..() + update_icons() + update_canmove() + SSmob.living_misc_mobs |= src + +/mob/living/carbon/cortical_borer/Destroy() + SSmob.living_misc_mobs -= src + return ..() +//###################################################// + /mob/living/carbon/cortical_borer/proc/summon() var/datum/emergency_call/custom/em_call = new() - em_call.name = "Cortical Borer" + em_call.name = real_name em_call.mob_max = 1 em_call.players_to_offer = list(src) em_call.owner = null @@ -132,24 +213,6 @@ message_admins("A new Cortical Borer has spawned at [get_area(loc)]") -/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0) - ..(newloc) - generation = gen - add_language(LANGUAGE_BORER) - var/mob_number = rand(1000,9999) - real_name = "Cortical Borer [mob_number]" - truename = "[borer_names[min(generation, borer_names.len)]] [mob_number]" - can_reproduce = reproduction - GrantBorerActions() - GiveBorerHUD() - if((!is_admin_level(z)) && ERT) - summon() - -/mob/living/carbon/cortical_borer/death() - var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] - c_link.broadcast(src, null, null, TRUE) - . = ..() - /mob/living/carbon/cortical_borer/update_icons() if(stat == DEAD) icon_state = "Borer Dead" @@ -163,7 +226,7 @@ icon_state = "Borer" /mob/living/carbon/cortical_borer/proc/GiveBorerHUD() - var/datum/mob_hud/H = huds[MOB_HUD_MEDICAL_OBSERVER] + var/datum/mob_hud/H = huds[MOB_HUD_BRAINWORM] H.add_hud_to(src) /mob/living/carbon/cortical_borer/can_ventcrawl() @@ -213,14 +276,16 @@ /mob/living/carbon/cortical_borer/Life(delta_time) ..() + update_canmove() + update_icons() if(host) if(!stat && host.stat != DEAD) if(((host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && !host.reagents.has_reagent("benzyme")) || host.reagents.has_reagent("bcure")) if(!docile) if(controlling) - to_chat(host, SPAN_XENODANGER("You feel the soporific flow of a chemical in your host's blood, lulling you into docility.")) + to_chat(host, SPAN_XENODANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) else - to_chat(src, SPAN_XENODANGER("You feel the soporific flow of a chemical in your host's blood, lulling you into docility.")) + to_chat(src, SPAN_XENODANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) docile = TRUE else if(docile) @@ -248,9 +313,6 @@ contaminant = max(contaminant - 0.3, 0) else SetLuminosity(0) - - update_canmove() - update_icons() /datum/action/innate/borer icon_file = 'icons/mob/hud/actions_borer.dmi' diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 9db7f1542c14..37e036a6b850 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -1,6 +1,9 @@ //############# Physical Interaction Procs ############# /mob/living/carbon/cortical_borer/UnarmedAttack(atom/A) - A.attack_borer(src) + if(istype(A, /obj/structure/ladder)) + A.attack_hand(src) + else + A.attack_borer(src) /atom/proc/attack_borer(mob/living/carbon/cortical_borer/user) return @@ -42,43 +45,47 @@ forceMove(S.loc) //############# Action Give/Take Procs ############# -/mob/living/carbon/cortical_borer/proc/GrantBorerActions() - action_infest_host.give_to(src) - action_toggle_hide.give_to(src) - action_freeze_victim.give_to(src) - -/mob/living/carbon/cortical_borer/proc/RemoveBorerActions() - action_infest_host.remove_from(src) - action_toggle_hide.remove_from(src) - action_freeze_victim.remove_from(src) - -/mob/living/carbon/cortical_borer/proc/GrantInfestActions() - action_talk_to_host.give_to(src) - action_leave_body.give_to(src) - action_take_control.give_to(src) - action_make_chems.give_to(src) - action_scan_chems.give_to(src) - action_hibernate.give_to(src) - -/mob/living/carbon/cortical_borer/proc/RemoveInfestActions() - action_talk_to_host.remove_from(src) - action_take_control.remove_from(src) - action_leave_body.remove_from(src) - action_make_chems.remove_from(src) - action_scan_chems.remove_from(src) - action_hibernate.remove_from(src) - -/mob/living/carbon/cortical_borer/proc/GrantControlActions() - action_talk_to_brain.give_to(host) - action_give_back_control.give_to(host) - action_make_larvae.give_to(host) - action_torment.give_to(host) - -/mob/living/carbon/cortical_borer/proc/RemoveControlActions() - action_talk_to_brain.remove_from(host) - action_make_larvae.remove_from(host) - action_give_back_control.remove_from(host) - action_torment.remove_from(host) +/mob/living/carbon/cortical_borer/proc/give_new_actions(actions_list = ACTION_SET_HOSTLESS, target = src) + for(var/datum/action/innate/borer/action in actions) + action.hide_from(target) + + if(host && current_actions == ACTION_SET_CONTROL) + for(var/datum/action/innate/borer/action in host.actions) + action.hide_from(host) + + var/list/abilities_to_give + switch(actions_list) + if(ACTION_SET_HOSTLESS) + abilities_to_give = actions_hostless.Copy() + if(host) + for(var/datum/action/innate/borer/action in host.actions) + action.hide_from(host) + if(ACTION_SET_HUMANOID) + abilities_to_give = actions_humanoidhost.Copy() + if(ACTION_SET_XENO) + abilities_to_give = actions_xenohost.Copy() + if(ACTION_SET_CONTROL) + if(!host) + return FALSE + abilities_to_give = actions_control.Copy() + target = host + + for(var/path in abilities_to_give) + give_action(target, path) + current_actions = actions_list + return TRUE + +/mob/living/carbon/cortical_borer/proc/get_host_actions() + if(!host) + return FALSE + if(ishuman(host)) + give_new_actions(ACTION_SET_HUMANOID) + else if(isxeno(host)) + give_new_actions(ACTION_SET_XENO) + else + return FALSE + give_action(host, /datum/action/innate/borer/talk_to_borer) + return TRUE /mob/living/carbon/cortical_borer/proc/hibernate() hibernating = !hibernating @@ -114,15 +121,21 @@ to_chat(src, "You cannot infest a target in your current state.") return var/list/choices = list() - for(var/mob/living/carbon/human/H in view(1,src)) - var/obj/limb/head/head = H.get_limb("head") - if(head.status & LIMB_ROBOT) + for(var/mob/living/carbon/candidate in view(1,src)) + var/obj/limb/head/head = candidate.get_limb("head") + if((isborer(candidate)) || (head?.status & (LIMB_DESTROYED|LIMB_ROBOT|LIMB_SYNTHSKIN)))//No infecting synths, or borers. continue - if(isspeciesyautja(H) && !infect_hunter) + if(ishuman(candidate)) + var/mob/living/carbon/human/h_candidate = candidate + if(isspecieshuman(h_candidate) && !infect_humans)//Can it infect humans? Normally, yes. + continue + else if(isspeciesyautja(h_candidate) && !infect_yautja)//Can it infect yautja? Normally, no. + continue + if(isxeno(candidate) && !infect_xenos)//Can it infect xenos? Normally, no. continue - if(H.stat != DEAD && Adjacent(H) && !H.has_brain_worms()) - choices += H - var/mob/living/carbon/human/target = tgui_input_list(src, "Who do you wish to infest?", "Targets", choices) + if(candidate.stat != DEAD && Adjacent(candidate) && !candidate.has_brain_worms()) + choices += candidate + var/mob/living/carbon/target = tgui_input_list(src, "Who do you wish to infest?", "Targets", choices) if(!target || !src) return if(!Adjacent(target)) @@ -146,10 +159,8 @@ return if(target in view(1, src)) to_chat(src, SPAN_NOTICE("You wiggle into [target]'s ear.")) - /* - if(!target.stat) - to_chat(target, "Something disgusting and slimy wiggles into your ear!") - */ // Let's see how stealthborers work out + if(!stealthy && !target.stat) + to_chat(target, SPAN_DANGER("Something disgusting and slimy wiggles into your ear!")) perform_infestation(target) return else @@ -168,8 +179,7 @@ forceMove(target) host.status_flags |= PASSEMOTES host.verbs += /mob/living/proc/borer_comm - RemoveBorerActions() - GrantInfestActions() + get_host_actions() //Brainslug abandons the host @@ -217,16 +227,16 @@ return if(controlling) detach() - GrantBorerActions() - RemoveInfestActions() + give_new_actions(ACTION_SET_HOSTLESS) + forceMove(get_turf(host)) + apply_effect(1, STUN) + log_interact(src, host, "Borer: [key_name(src)] left their host; [key_name(host)]") host.reset_view(null) var/mob/living/carbon/H = host H.borer = null - H.verbs -= /mob/living/proc/borer_comm - action_talk_to_borer.remove_from(host) H.status_flags &= ~PASSEMOTES host = null return @@ -319,14 +329,7 @@ bonding = FALSE controlling = TRUE - host.verbs += /mob/living/carbon/proc/release_control - host.verbs += /mob/living/carbon/proc/punish_host - host.verbs += /mob/living/carbon/proc/spawn_larvae - host.verbs -= /mob/living/proc/borer_comm - host.verbs += /mob/living/proc/trapped_mind_comm - - GrantControlActions() - action_talk_to_borer.remove_from(host) + give_new_actions(ACTION_SET_CONTROL) host.med_hud_set_status() if(src && !src.key) @@ -366,14 +369,7 @@ controlling = FALSE reset_view(null) - host.verbs -= /mob/living/carbon/proc/release_control - host.verbs -= /mob/living/carbon/proc/punish_host - host.verbs -= /mob/living/carbon/proc/spawn_larvae - host.verbs += /mob/living/proc/borer_comm - host.verbs -= /mob/living/proc/trapped_mind_comm - - RemoveControlActions() - action_talk_to_borer.give_to(host) + get_host_actions() host.med_hud_set_status() sleeping = 0 if(host_brain) @@ -456,7 +452,7 @@ return var/list/choices = list() for(var/mob/living/carbon/C in view(3,src)) - if((C.stat != DEAD) && !(issynth(C))) + if((C != src) && (C.stat != DEAD) && !(issynth(C))) choices += C if(world.time - used_dominate < 300) to_chat(src, SPAN_XENOWARNING("You cannot use that ability again so soon.")) @@ -610,7 +606,6 @@ to_chat(host, SPAN_XENO("[truename] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) log_say("BORER: ([key_name(src)] to [key_name(host)]) [input]", src) to_chat(src, SPAN_XENO("[truename] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) - action_talk_to_borer.give_to(host) for (var/mob/dead in GLOB.dead_mob_list) var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index 94d1203493da..39a7eb968368 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -56,6 +56,7 @@ /datum/orbit_menu/ui_static_data(mob/user) var/list/data = list() + var/list/borers = list() var/list/humans = list() var/list/marines = list() var/list/survivors = list() @@ -111,6 +112,9 @@ var/mob/living/player = M serialized["health"] = FLOOR((player.health / player.maxHealth * 100), 1) + if(isborer(player)) + borers += list(serialized) + if(isxeno(player)) var/mob/living/carbon/xenomorph/xeno = player if(xeno.caste) @@ -159,6 +163,7 @@ else if(isAI(M)) humans += list(serialized) + data["borers"] = borers data["humans"] = humans data["marines"] = marines data["survivors"] = survivors diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index 61b5c07ba159..1ad847564617 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -119,5 +119,5 @@ /obj/item/holder/borer name = "cortical borer" desc = "Gross..." - icon = 'icons/mob/animal.dmi' - icon_state = "brainslug_dead" + icon = 'icons/mob/brainslug.dmi' + icon_state = "Borer Dead" diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 13914834509c..820b96d49486 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -136,7 +136,7 @@ var/last_chew = 0 //taken from human.dm - hud_possible = list(HEALTH_HUD,STATUS_HUD, STATUS_HUD_OOC, STATUS_HUD_XENO_INFECTION, STATUS_HUD_XENO_CULTIST, ID_HUD, WANTED_HUD, ORDER_HUD, XENO_HOSTILE_ACID, XENO_HOSTILE_SLOW, XENO_HOSTILE_TAG, XENO_HOSTILE_FREEZE, HUNTER_CLAN, HUNTER_HUD, FACTION_HUD) + hud_possible = list(HEALTH_HUD,STATUS_HUD, STATUS_HUD_OOC, STATUS_HUD_XENO_INFECTION, STATUS_HUD_XENO_CULTIST, ID_HUD, WANTED_HUD, ORDER_HUD, XENO_HOSTILE_ACID, XENO_HOSTILE_SLOW, XENO_HOSTILE_TAG, XENO_HOSTILE_FREEZE, HUNTER_CLAN, HUNTER_HUD, FACTION_HUD, STATUS_HUD_BRAINWORM) var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. var/allow_gun_usage = TRUE var/melee_allowed = TRUE diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index 3449b4db8325..72a0ead4b198 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -44,7 +44,7 @@ see_in_dark = 12 recovery_constant = 1.5 see_invisible = SEE_INVISIBLE_LIVING - hud_possible = list(HEALTH_HUD_XENO, PLASMA_HUD, PHEROMONE_HUD, QUEEN_OVERWATCH_HUD, ARMOR_HUD_XENO, XENO_STATUS_HUD, XENO_BANISHED_HUD, XENO_HOSTILE_ACID, XENO_HOSTILE_SLOW, XENO_HOSTILE_TAG, XENO_HOSTILE_FREEZE, HUNTER_HUD) + hud_possible = list(HEALTH_HUD_XENO, PLASMA_HUD, PHEROMONE_HUD, QUEEN_OVERWATCH_HUD, ARMOR_HUD_XENO, XENO_STATUS_HUD, XENO_BANISHED_HUD, XENO_HOSTILE_ACID, XENO_HOSTILE_SLOW, XENO_HOSTILE_TAG, XENO_HOSTILE_FREEZE, HUNTER_HUD, STATUS_HUD_BRAINWORM) unacidable = TRUE rebounds = TRUE faction = FACTION_XENOMORPH diff --git a/code/modules/mob/living/living_healthscan.dm b/code/modules/mob/living/living_healthscan.dm index 71a433e314b2..5dabec7c58d9 100644 --- a/code/modules/mob/living/living_healthscan.dm +++ b/code/modules/mob/living/living_healthscan.dm @@ -150,7 +150,7 @@ GLOBAL_LIST_INIT(known_implants, subtypesof(/obj/item/implant)) //snowflake :3 data["lung_ruptured"] = human_target_mob.is_lung_ruptured() - + data["brainslug"] = human_target_mob.has_brain_worms() //shrapnel, limbs, limb damage, limb statflags, cyber limbs var/core_fracture_detected = FALSE var/unknown_implants = 0 diff --git a/code/modules/reagents/chemistry_properties/prop_positive.dm b/code/modules/reagents/chemistry_properties/prop_positive.dm index 1bef0df75a34..c0bd02f2762a 100644 --- a/code/modules/reagents/chemistry_properties/prop_positive.dm +++ b/code/modules/reagents/chemistry_properties/prop_positive.dm @@ -473,7 +473,7 @@ if(player_2) if(player_2.controlling) player_2.detach() - to_chat(src, SPAN_HIGHDANGER("You relinquish the unknown chemical overwhelms you!")) + to_chat(src, SPAN_HIGHDANGER("You relinquish control as the unknown chemical overwhelms you!")) player_2.leave_host() to_chat(src, SPAN_HIGHDANGER("The overwhelming flow of powerful chemicals forces you to flee your host!")) diff --git a/code/modules/surgery/brainworm.dm b/code/modules/surgery/brainworm.dm new file mode 100644 index 000000000000..3a379605e36b --- /dev/null +++ b/code/modules/surgery/brainworm.dm @@ -0,0 +1,80 @@ +/datum/surgery/borer_removal + name = "Experimental Cranial Parasite Removal" + priority = SURGERY_PRIORITY_MAXIMUM + possible_locs = list("head") + invasiveness = list(SURGERY_DEPTH_DEEP) + pain_reduction_required = PAIN_REDUCTION_MEDIUM + required_surgery_skill = SKILL_SURGERY_TRAINED + steps = list( + /datum/surgery_step/remove_borer, + ) + +/datum/surgery/borer_removal/can_start(mob/user, mob/living/carbon/patient, obj/limb/L, obj/item/tool) + if(!locate(/obj/structure/machinery/optable) in get_turf(patient)) + return FALSE + + return patient.has_brain_worms() + +//------------------------------------ + +/datum/surgery_step/remove_borer + name = "Remove Cranial Parasite" + desc = "extract the cranial parasite" + accept_hand = TRUE + /*Similar to PINCH, but balanced around 100 = using bare hands. Haemostat is faster and better, + other tools are slower but don't burn the surgeon.*/ + tools = list( + /obj/item/tool/surgery/hemostat = 1.5, + /obj/item/tool/wirecutters = SURGERY_TOOL_MULT_SUBOPTIMAL, + /obj/item/tool/kitchen/utensil/fork = SURGERY_TOOL_MULT_SUBSTITUTE + ) + time = 6 SECONDS + preop_sound = 'sound/surgery/hemostat1.ogg' + success_sound = 'sound/surgery/organ2.ogg' + failure_sound = 'sound/effects/acid_sizzle2.ogg' + +/datum/surgery_step/remove_borer/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + var/mob/living/carbon/cortical_borer/parasite = target.borer + if(parasite) + to_chat(parasite, SPAN_HIGHDANGER("[user] is attempting to extract you from your host's head!")) + else return FALSE + if(tool) + user.affected_message(target, + SPAN_NOTICE("You try to extract the parasite from [target]'s head with \the [tool]."), + SPAN_NOTICE("[user] tries to extract the parasite from your head with \the [tool]."), + SPAN_NOTICE("[user] tries to extract the parasite from [target]'s head with \the [tool].")) + else + user.affected_message(target, + SPAN_NOTICE("You try to extract the parasite from [target]'s head."), + SPAN_NOTICE("[user] tries to extract the parasite from your head."), + SPAN_NOTICE("[user] tries to extract the parasite from [target]'s head.")) + + target.custom_pain("Something hurts horribly in your head!",1) + log_interact(user, target, "[key_name(user)] started to remove a borer from [key_name(target)]'s skull.") + +/datum/surgery_step/remove_borer/success(mob/living/carbon/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + var/mob/living/carbon/cortical_borer/parasite = target.borer + if(parasite) + user.affected_message(target, + SPAN_WARNING("You pull a wriggling parasite out of [target]'s head!"), + SPAN_WARNING("[user] pulls a wriggling parasite out of [target]'s head!"), + SPAN_WARNING("[user] pulls a wriggling parasite out of [target]'s head!")) + + user.count_niche_stat(STATISTICS_NICHE_SURGERY_LARVA) + to_chat(parasite, SPAN_HIGHDANGER("You are ripped forcibly from your host's head!")) + parasite.leave_host() + + log_interact(user, target, "[key_name(user)] removed a parasite from [key_name(target)]'s head with [tool ? "\the [tool]" : "their hands"], ending [surgery].") + +/datum/surgery_step/remove_borer/failure(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) + user.affected_message(target, + SPAN_WARNING("Your hand slips, bruising [target]'s brain!"), + SPAN_WARNING("[user]'s hand slips, bruising your brain!"), + SPAN_WARNING("[user]'s hand slips, bruising [target]'s brain!")) + + target.apply_damage(10, BRAIN) + if(target.stat == CONSCIOUS) + target.emote("scream") + target.apply_damage(15, BURN, target_zone) + log_interact(user, target, "[key_name(user)] failed to remove a parasite from [key_name(target)]'s head with [tool ? "\the [tool]" : "their hands"].") + return FALSE diff --git a/colonialmarines.dme b/colonialmarines.dme index 75e644a940ec..a43815ecc94b 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -2124,6 +2124,7 @@ #include "code\modules\surgery\amputation.dm" #include "code\modules\surgery\bones.dm" #include "code\modules\surgery\brainrepair.dm" +#include "code\modules\surgery\brainworm.dm" #include "code\modules\surgery\chestburster.dm" #include "code\modules\surgery\eye.dm" #include "code\modules\surgery\face.dm" diff --git a/icons/mob/brainslug.dmi b/icons/mob/brainslug.dmi index db29b87ac953f66b36ab8fd1596c80f537c02914..42e83a7753f6aad2688b75046a5e5244e79c38c1 100644 GIT binary patch delta 4116 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

}`Qw_#44R+UX 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 i_5or|WBR?ni}r>kwCRd~rR?Ee8?NF~Yu diff --git a/tgui/packages/tgui/interfaces/HealthScan.js b/tgui/packages/tgui/interfaces/HealthScan.js index cf3e8e59eab9..84ddb1a53d05 100644 --- a/tgui/packages/tgui/interfaces/HealthScan.js +++ b/tgui/packages/tgui/interfaces/HealthScan.js @@ -31,6 +31,7 @@ export const HealthScan = (props, context) => { implants, core_fracture, lung_ruptured, + brainslug, hugged, detail_level, permadead, @@ -195,6 +196,7 @@ export const HealthScan = (props, context) => { {pulse} {internal_bleeding || + (brainslug && bodyscanner) || implants || hugged || core_fracture || @@ -222,6 +224,9 @@ export const HealthScan = (props, context) => { {lung_ruptured && bodyscanner ? ( Ruptured lung detected! ) : null} + {brainslug && bodyscanner ? ( + Cranial anomaly detected! + ) : null} {core_fracture && healthanalyser ? ( Bone fractures detected! Advanced scanner required for location. diff --git a/tgui/packages/tgui/interfaces/Orbit/index.tsx b/tgui/packages/tgui/interfaces/Orbit/index.tsx index a900ee804a28..9f6e9004b951 100644 --- a/tgui/packages/tgui/interfaces/Orbit/index.tsx +++ b/tgui/packages/tgui/interfaces/Orbit/index.tsx @@ -99,6 +99,7 @@ const ObservableSearch = (props, context) => { const ObservableContent = (props, context) => { const { data } = useBackend(context); const { + borers = [], humans = [], marines = [], survivors = [], @@ -117,6 +118,7 @@ const ObservableContent = (props, context) => { return ( + diff --git a/tgui/packages/tgui/interfaces/Orbit/types.ts b/tgui/packages/tgui/interfaces/Orbit/types.ts index 3fe11af8e625..d3b339ae04ed 100644 --- a/tgui/packages/tgui/interfaces/Orbit/types.ts +++ b/tgui/packages/tgui/interfaces/Orbit/types.ts @@ -2,6 +2,7 @@ import { BooleanLike } from 'common/react'; export type OrbitData = { auto_observe: BooleanLike; + borers: Observable[]; humans: Observable[]; marines: Observable[]; survivors: Observable[]; From 30b47129afd422163715881d2118542a0b9ae2af Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sun, 2 Apr 2023 19:28:58 +0100 Subject: [PATCH 03/52] fixes for hivemind --- code/modules/borer/borer.dm | 3 ++- code/modules/mob/language/languages.dm | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 81afde2f1be9..047a80b3214a 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -39,13 +39,14 @@ var/mob/living/carbon/cortical_borer/B = loc if(!istype(B)) log_debug(EXCEPTION("Trapped mind found without a borer!"), src) - return + return FALSE to_chat(src, SPAN_DANGER("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).")) to_chat(B.host, SPAN_XENOWARNING("You feel the captive mind of [src] begin to resist your control.")) var/delay = (rand(350,450) + B.host.getBrainLoss()) addtimer(CALLBACK(src, PROC_REF(return_control), B), delay) + return TRUE /mob/living/carbon/cortical_borer name = "cortical borer" diff --git a/code/modules/mob/language/languages.dm b/code/modules/mob/language/languages.dm index 5760255ff38d..74f058e1ff66 100644 --- a/code/modules/mob/language/languages.dm +++ b/code/modules/mob/language/languages.dm @@ -213,18 +213,16 @@ key = "0" flags = RESTRICTED|HIVEMIND -/datum/language/corticalborer/broadcast(mob/living/speaker, message, speaker_mask, death) +/datum/language/corticalborer/broadcast(mob/living/carbon/speaker, message, speaker_mask, death) var/mob/living/carbon/cortical_borer/B - if(!speaker_mask) - speaker_mask = speaker - if(iscarbon(speaker)) - var/mob/living/carbon/M = speaker - B = M.has_brain_worms() - else if(istype(speaker,/mob/living/carbon/cortical_borer)) + if(isborer(speaker)) B = speaker - + else if(speaker.has_brain_worms()) + B = speaker.has_brain_worms() if(B) speaker_mask = B.truename + if(!speaker_mask) + speaker_mask = speaker.real_name var/message_start = "[name], [speaker_mask]" var/message_body = "[speech_verb], \"[message]\"" From ee1e59f2f9ab2a7b1212c19607b0e6e875cdbe8e Mon Sep 17 00:00:00 2001 From: forest2001 Date: Mon, 3 Apr 2023 06:36:12 +0100 Subject: [PATCH 04/52] Fixes, modernisation & help information --- code/modules/borer/borer.dm | 48 +++- code/modules/borer/borer_procs.dm | 261 +++++++++++------- code/modules/mob/language/languages.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 3 +- .../mob/living/carbon/xenomorph/XenoProcs.dm | 18 ++ icons/mob/hud/actions_borer.dmi | Bin 2032 -> 2089 bytes 6 files changed, 227 insertions(+), 105 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 047a80b3214a..54daabcf341b 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -86,7 +86,7 @@ var/max_contaminant = 120 //Decreases through hibernation or reproduction. var/hibernating = FALSE //Usable inside a host, but not when controlling. Allows clearing of impurities. - var/mob/living/carbon/human/host // Human host for the brain worm. + var/mob/living/carbon/host // Human host for the brain worm. var/truename // Name used for brainworm-speak. var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. var/controlling // Used in human death check. @@ -104,11 +104,13 @@ var/current_actions = ACTION_SET_HOSTLESS var/list/actions_hostless = list( + /datum/action/innate/borer/helpme, /datum/action/innate/borer/toggle_hide, /datum/action/innate/borer/freeze_victim, /datum/action/innate/borer/infest_host ) var/list/actions_humanoidhost = list( + /datum/action/innate/borer/helpme, /datum/action/innate/borer/take_control, /datum/action/innate/borer/talk_to_host, /datum/action/innate/borer/leave_body, @@ -117,12 +119,14 @@ /datum/action/innate/borer/make_chems ) var/list/actions_xenohost = list( + /datum/action/innate/borer/helpme, /datum/action/innate/borer/take_control, /datum/action/innate/borer/talk_to_host, /datum/action/innate/borer/leave_body, /datum/action/innate/borer/hibernate ) var/list/actions_control = list( + /datum/action/innate/borer/helpme, /datum/action/innate/borer/give_back_control, /datum/action/innate/borer/make_larvae, /datum/action/innate/borer/talk_to_brain, @@ -188,6 +192,7 @@ var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] c_link.broadcast(src, null, src.truename, TRUE) SSmob.living_misc_mobs -= src + leave_host() . = ..() /mob/living/carbon/cortical_borer/rejuvenate() @@ -198,6 +203,9 @@ /mob/living/carbon/cortical_borer/Destroy() SSmob.living_misc_mobs -= src + if(host) + for(var/datum/action/innate/borer/action in host.actions) + action.hide_from(host) return ..() //###################################################// @@ -254,9 +262,14 @@ . += "Can Reproduce: [CR]" . += "Enzymes: [round(enzymes)]/[round(max_enzymes)]" . += "Contaminant: [round(contaminant)]/[round(max_contaminant)]" + . += "Health: P:[round(getBruteLoss())] B:[round(getFireLoss())] T:[round(getToxLoss())]" if(host) . += "" - . += "Host Brain Damage: [host.brainloss]/100" + if(ishuman(host)) + . += "Host Brain Damage: [host.brainloss]/100" + else if(isxeno(host)) + // . += "Host Plasma: [plasma_stored]/[plasma_max]" + . += "Host Integrity: [health]/[maxHealth]" /mob/living/carbon/cortical_borer/say(message)//I need to parse the message properly so it doesn't look stupid var/datum/language/parsed_language = parse_language(message) @@ -279,9 +292,14 @@ ..() update_canmove() update_icons() + var/heal_amt = 1 if(host) + heal_amt = 3 if(!stat && host.stat != DEAD) - if(((host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && !host.reagents.has_reagent("benzyme")) || host.reagents.has_reagent("bcure")) + var/mob/living/carbon/human/human_host + if(ishuman(host)) + human_host = host + if(((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && !human_host.reagents.has_reagent("benzyme")) || human_host.reagents.has_reagent("bcure")) if(!docile) if(controlling) to_chat(host, SPAN_XENODANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) @@ -291,7 +309,7 @@ else if(docile) if(controlling) - to_chat(host, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) + to_chat(human_host, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) else to_chat(src, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) docile = FALSE @@ -314,9 +332,31 @@ contaminant = max(contaminant - 0.3, 0) else SetLuminosity(0) + if(bruteloss || fireloss) + heal_overall_damage(heal_amt, heal_amt) + if(toxloss) + apply_damage(-(heal_amt/2), TOX) + +//################### ABILITIES ###################// /datum/action/innate/borer icon_file = 'icons/mob/hud/actions_borer.dmi' +/datum/action/innate/borer/helpme + name = "Help!" + action_icon_state = "borer_help" + +/datum/action/innate/borer/helpme/action_activate() + var/mob/living/carbon/cortical_borer/B + if(!isborer(owner)) + if(owner.has_brain_worms()) + B = owner.has_brain_worms() + else + to_chat(owner, SPAN_DANGER("How did you get this command? It's gone now.")) + hide_action(owner, /datum/action/innate/borer/helpme) + else + B = owner + B.show_help() + /datum/action/innate/borer/talk_to_host name = "Converse with Host" action_icon_state = "borer_whisper" diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 37e036a6b850..224cdc2fac5f 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -1,3 +1,45 @@ +//############# HELP ################## +/mob/living/carbon/cortical_borer/verb/show_help() + set category = "Borer" + set name = "Show Help" + set desc = "Show help for borer commands." + + var/target = src + + var/list/options = list("Communicating") + if(!host) + options += list("Infecting a host") + else if(controlling) + target = host + options = list("Captive Host", "Releasing Control", "Reproducing") + else if(isxeno(host)) + options = list("Assuming Control","Contaminant & Enzymes","Hibernation","Reproducing") + else + options = list("Assuming Control","Contaminant & Enzymes","Hibernation","Secreting Chemicals","Reproducing") + + var/choice = tgui_input_list(target, "What would you like help with?", "Help", options, 20 SECONDS) + + var/help_message = "" + switch(choice) + if("Infecting a host") + help_message = "Infecting a host is the first major step for a borer to complete.\n\nThis is done by getting close to a potential host (This can be Human, Xeno or Yautja depending on settings controlled by admins) and clicking the Infest button in the top left of your screen.\n\nYour host will need to keep still for you to do this, and it's rare that they do so; for this reason you have Dominate Victim, which will allow you to temporarily stun a target.\n\nNote: This is not sufficient to keep them down for 100% of the time it takes to infect however, so be careful with it." + if("Communicating") + help_message = "All borers share a hivemind, the Cortical Link, this can be accessed using :0 (that's ZERO).\n\nThe hivemind can be used by any borer who is NOT in direct control of their host.\n\nAny borer in direct control of a host can only hear what their host can hear.\n\nA borer inside a host can communicate directly with that host using 'Converse with Host'." + if("Captive Host") + help_message = "" + if("Releasing Control") + help_message = "" + if("Reproducing") + help_message = "" + if("Assuming Control") + help_message = "" + if("Contaminant & Enzymes", "Hibernation") + help_message = "" + if("Secreting Chemicals") + help_message = "" + + alert(target, help_message, choice, "Ok") + //############# Physical Interaction Procs ############# /mob/living/carbon/cortical_borer/UnarmedAttack(atom/A) if(istype(A, /obj/structure/ladder)) @@ -33,16 +75,17 @@ for(var/atom/movable/AM in get_turf(S)) if(AM != S && AM.density && AM.BlockedPassDirs(src, move_dir)) to_chat(src, SPAN_WARNING("\The [AM] prevents you from squeezing under \the [S]!")) - return + return FALSE // Is it an airlock? if(istype(S, /obj/structure/machinery/door/airlock)) var/obj/structure/machinery/door/airlock/A = S if(A.locked || A.welded) //Can't pass through airlocks that have been bolted down or welded to_chat(src, SPAN_WARNING("\The [A] is locked down tight. You can't squeeze underneath!")) - return + return FALSE visible_message(SPAN_WARNING("\The [src] scuttles underneath \the [S]!"), \ SPAN_WARNING("You squeeze and scuttle underneath \the [S]."), null, 5) forceMove(S.loc) + return TRUE //############# Action Give/Take Procs ############# /mob/living/carbon/cortical_borer/proc/give_new_actions(actions_list = ACTION_SET_HOSTLESS, target = src) @@ -69,6 +112,8 @@ return FALSE abilities_to_give = actions_control.Copy() target = host + for(var/datum/action/innate/borer/talk_to_borer/action in host.actions) + action.hide_from(host) for(var/path in abilities_to_give) give_action(target, path) @@ -102,11 +147,27 @@ return FALSE /mob/living/carbon/has_brain_worms() - if(borer) + if(isborer(borer)) return borer else return FALSE +/mob/living/carbon/cortical_borer/proc/can_target(mob/living/carbon/target) + var/obj/limb/head/head = target.get_limb("head") + if((isborer(target)) || (head?.status & (LIMB_DESTROYED|LIMB_ROBOT|LIMB_SYNTHSKIN)))//No infecting synths, or borers. + return FALSE + if(ishuman(target)) + var/mob/living/carbon/human/human_target = target + if(isspecieshuman(human_target) && !infect_humans)//Can it infect humans? Normally, yes. + return FALSE + else if(isspeciesyautja(human_target) && !infect_yautja)//Can it infect yautja? Normally, no. + return FALSE + if(isxeno(target) && !infect_xenos)//Can it infect xenos? Normally, no. + return FALSE + if(target.stat != DEAD && Adjacent(target) && !target.has_brain_worms()) + return TRUE + else + return FALSE //Brainslug infests a target /mob/living/carbon/cortical_borer/verb/infest() @@ -116,63 +177,50 @@ if(host) to_chat(src, "You are already within a host.") - return + return FALSE if(stat) to_chat(src, "You cannot infest a target in your current state.") - return + return FALSE var/list/choices = list() for(var/mob/living/carbon/candidate in view(1,src)) - var/obj/limb/head/head = candidate.get_limb("head") - if((isborer(candidate)) || (head?.status & (LIMB_DESTROYED|LIMB_ROBOT|LIMB_SYNTHSKIN)))//No infecting synths, or borers. - continue - if(ishuman(candidate)) - var/mob/living/carbon/human/h_candidate = candidate - if(isspecieshuman(h_candidate) && !infect_humans)//Can it infect humans? Normally, yes. - continue - else if(isspeciesyautja(h_candidate) && !infect_yautja)//Can it infect yautja? Normally, no. - continue - if(isxeno(candidate) && !infect_xenos)//Can it infect xenos? Normally, no. - continue - if(candidate.stat != DEAD && Adjacent(candidate) && !candidate.has_brain_worms()) + if(can_target(candidate)) choices += candidate var/mob/living/carbon/target = tgui_input_list(src, "Who do you wish to infest?", "Targets", choices) - if(!target || !src) - return - if(!Adjacent(target)) - return + if(!target || !src || !Adjacent(target)) + return FALSE if(target.has_brain_worms()) to_chat(src, SPAN_WARNING("You cannot infest someone who is already infested!")) - return + return FALSE if(is_mob_incapacitated()) - return + return FALSE to_chat(src, SPAN_NOTICE("You slither up [target] and begin probing at their ear canal...")) if(!do_after(src, 50, INTERRUPT_ALL_OUT_OF_RANGE, BUSY_ICON_HOSTILE, target)) to_chat(src, SPAN_WARNING("As [target] moves away, you are dislodged and fall to the ground.")) - return + return FALSE if(!target || !src) - return + return FALSE if(stat) to_chat(src, SPAN_XENOWARNING("You cannot infest a target in your current state.")) - return + return FALSE if(target.stat == DEAD) - to_chat(src, SPAN_WARNING("That is not an appropriate target.")) - return + to_chat(src, SPAN_WARNING("You cannot infest the dead.")) + return FALSE if(target in view(1, src)) to_chat(src, SPAN_NOTICE("You wiggle into [target]'s ear.")) if(!stealthy && !target.stat) to_chat(target, SPAN_DANGER("Something disgusting and slimy wiggles into your ear!")) perform_infestation(target) - return + return TRUE else to_chat(src, "They are no longer in range!") - return + return FALSE /mob/living/carbon/cortical_borer/proc/perform_infestation(mob/living/carbon/target) if(!target) - return + return FALSE if(target.has_brain_worms()) to_chat(src, SPAN_XENOWARNING("[target] is already infested!")) - return + return FALSE host = target log_interact(src, host, "Borer: [key_name(src)] Infested [key_name(host)]") target.borer = src @@ -180,6 +228,7 @@ host.status_flags |= PASSEMOTES host.verbs += /mob/living/proc/borer_comm get_host_actions() + return TRUE //Brainslug abandons the host @@ -189,42 +238,42 @@ set desc = "Slither out of your host." if(!host) to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) - return + return FALSE if(stat) to_chat(src, SPAN_XENOWARNING("You cannot leave your host in your current state.")) - return + return FALSE if(docile) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) - return + return FALSE if(!host || !src) - return + return FALSE if(leaving) leaving = FALSE to_chat(src, SPAN_XENOWARNING("You decide against leaving your host.")) - return + return TRUE to_chat(src, SPAN_XENOHIGHDANGER("You begin disconnecting from [host]'s synapses and prodding at their internal ear canal.")) leaving = TRUE addtimer(CALLBACK(src, PROC_REF(let_go)), 200) + return TRUE /mob/living/carbon/cortical_borer/proc/let_go() if(!host || !src || QDELETED(host) || QDELETED(src)) - return - if(!leaving) - return - if(controlling) - return + return FALSE + if(!leaving || controlling) + return FALSE if(stat) to_chat(src, SPAN_XENOWARNING("You cannot release a target in your current state.")) - return + return FALSE to_chat(src, SPAN_XENOHIGHDANGER("You wiggle out of [host]'s ear and plop to the ground.")) leaving = FALSE leave_host() + return TRUE /mob/living/carbon/cortical_borer/proc/leave_host() if(!host) - return + return FALSE if(controlling) detach() give_new_actions(ACTION_SET_HOSTLESS) @@ -239,7 +288,7 @@ H.borer = null H.status_flags &= ~PASSEMOTES host = null - return + return TRUE //Brainslug takes control of the body @@ -250,43 +299,44 @@ if(!host) to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) - return + return FALSE if(host.stat == DEAD) to_chat(src, SPAN_XENODANGER("This host is in no condition to be controlled.")) - return + return FALSE if(stat) to_chat(src, SPAN_XENOWARNING("You cannot do that in your current state.")) - return + return FALSE if(docile) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) - return + return FALSE if(bonding) bonding = FALSE to_chat(src, SPAN_XENOWARNING("You stop attempting to take control of your host.")) - return + return FALSE to_chat(src, "You begin delicately adjusting your connection to the host brain...") if(QDELETED(src) || QDELETED(host)) - return + return FALSE bonding = TRUE var/delay = 300+(host.getBrainLoss()*5) addtimer(CALLBACK(src, PROC_REF(assume_control)), delay) + return TRUE /mob/living/carbon/cortical_borer/proc/assume_control() if(!host || !src || controlling) - return + return FALSE if(!bonding) - return + return FALSE if(docile) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) - return + return FALSE else to_chat(src, SPAN_XENOHIGHDANGER("You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system.")) to_chat(host, SPAN_HIGHDANGER("You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.")) @@ -334,16 +384,17 @@ if(src && !src.key) src.key = "@[borer_key]" - return + return TRUE //Captive mind reclaims their body. /mob/living/captive_brain/proc/return_control(mob/living/carbon/cortical_borer/B) if(!B || !B.controlling) - return + return FALSE B.host.adjustBrainLoss(rand(5,10)) to_chat(src, SPAN_DANGER("With an immense exertion of will, you regain control of your body!")) to_chat(B.host, SPAN_XENODANGER("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) B.detach() + return TRUE ///Brain slug proc for voluntary removal of control. /mob/living/carbon/proc/release_control() @@ -364,7 +415,7 @@ /mob/living/carbon/cortical_borer/proc/detach() if(!host || !controlling) - return + return FALSE controlling = FALSE reset_view(null) @@ -396,20 +447,21 @@ host.computer_id = b2h_id if(!host.lastKnownIP) host.lastKnownIP = b2h_ip - qdel(host_brain) - return + qdel(host_brain) + return TRUE //Host Has died /mob/living/carbon/cortical_borer/proc/host_death(perma = FALSE) if(!(host && loc == host)) log_debug("Borer ([key_name(src)]) called host_death without being inside a host!") - return + return FALSE if(controlling) detach() to_chat(src, SPAN_HIGHDANGER("You release your proboscis and flee as the psychic shock of your host's death washes over you!")) if(perma) to_chat(src, SPAN_HIGHDANGER("You flee your host in anguish!")) leave_host() + return TRUE //############# External Ability Procs ############# /mob/living/carbon/cortical_borer/verb/hide_borer() @@ -419,10 +471,10 @@ if(host) to_chat(usr, SPAN_XENOWARNING("You cannot do this while you're inside a host.")) - return + return FALSE if(stat != CONSCIOUS) - return + return FALSE if(!hiding) layer = TURF_LAYER+0.2 @@ -432,6 +484,7 @@ layer = MOB_LAYER to_chat(src, SPAN_XENONOTICE("You stop hiding.")) hiding = FALSE + return TRUE /mob/living/carbon/cortical_borer/verb/dominate_victim() set category = "Borer" @@ -440,53 +493,53 @@ if(world.time - used_dominate < 150) to_chat(src, SPAN_XENOWARNING("You cannot use that ability again so soon.")) - return + return FALSE if(host) to_chat(src, SPAN_XENOWARNING("You cannot do that from within a host body.")) - return + return FALSE if(stat) to_chat(src, SPAN_XENOWARNING("You cannot do that in your current state.")) - return + return FALSE if(attempting_to_dominate) to_chat(src, SPAN_XENOWARNING("You're already targeting someone!")) - return + return FALSE var/list/choices = list() for(var/mob/living/carbon/C in view(3,src)) - if((C != src) && (C.stat != DEAD) && !(issynth(C))) + if(can_target(C)) choices += C if(world.time - used_dominate < 300) to_chat(src, SPAN_XENOWARNING("You cannot use that ability again so soon.")) - return + return FALSE attempting_to_dominate = TRUE var/mob/living/carbon/M = tgui_input_list(src, "Who do you wish to dominate?", "Targets", choices) if(!M) attempting_to_dominate = FALSE - return + return FALSE if(!src) //different statement to avoid a runtime since if the source is deleted then attempting_to_dominate would also be deleted - return + return FALSE if(M.has_brain_worms()) to_chat(src, SPAN_XENOWARNING("You cannot dominate someone who is already infested!")) attempting_to_dominate = FALSE - return + return FALSE if(is_mob_incapacitated()) attempting_to_dominate = FALSE - return + return FALSE if(get_dist(src, M) > 5) //to avoid people remotely doing from across the map etc, 7 is the default view range to_chat(src, SPAN_XENOWARNING("You're too far away!")) attempting_to_dominate = FALSE - return + return FALSE to_chat(src, SPAN_XENONOTICE("You begin to focus your psychic lance on [M], this will take a few seconds.")) if(!do_after(src, 30, INTERRUPT_OUT_OF_RANGE, NO_BUSY_ICON, M, max_dist = 5)) to_chat(src, SPAN_XENODANGER("You are out of position to dominate [M], get closer!")) attempting_to_dominate = FALSE - return + return FALSE to_chat(src, SPAN_XENOWARNING("You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread.")) to_chat(M, SPAN_WARNING("You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.")) M.KnockDown(3) used_dominate = world.time attempting_to_dominate = FALSE - + return TRUE //############# Internal Abiity Procs ############# /mob/living/carbon/proc/punish_host() @@ -497,11 +550,12 @@ var/mob/living/carbon/cortical_borer/B = has_brain_worms() if(!B) - return + return FALSE if(B.host_brain) to_chat(src, SPAN_XENONOTICE("You send a punishing spike of psychic agony lancing into your host's brain.")) to_chat(B.host_brain, SPAN_XENOHIGHDANGER("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")) + return TRUE /mob/living/carbon/proc/spawn_larvae() @@ -512,7 +566,7 @@ var/mob/living/carbon/cortical_borer/B = has_brain_worms() if(!B) - return + return FALSE if(B.can_reproduce) if(B.enzymes >= BORER_LARVAE_COST) to_chat(src, SPAN_XENOWARNING("Your host twitches and quivers as you rapdly excrete a larva from your sluglike body.")) @@ -523,11 +577,13 @@ B.contaminant = 0 var/repro = max(B.can_reproduce - 1, 0) new /mob/living/carbon/cortical_borer(T, B.generation + 1, TRUE, repro) + return TRUE else to_chat(src, SPAN_XENONOTICE("You need at least [BORER_LARVAE_COST] enzymes to reproduce!")) - return + return FALSE else to_chat(src, SPAN_XENOWARNING("You are not allowed to reproduce!")) + return FALSE @@ -538,21 +594,25 @@ if(!host) to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) - return + return FALSE if(stat) to_chat(src, SPAN_XENOWARNING("You cannot secrete chemicals in your current state.")) + return FALSE if(docile) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) - return + return FALSE var/content = "" content += "" if(ishuman(host)) - if(isspeciesyautja(host)) + var/mob/living/carbon/human/human_host + if(ishuman(host)) + human_host = host + if(isspeciesyautja(human_host)) for(var/datum in subtypesof(/datum/borer_chem/yautja)) var/datum/borer_chem/C = datum var/chem = initial(C.chem_id) @@ -574,7 +634,7 @@ usr << browse(null, "window=ViewBorer\ref[src]Chems;size=585x400") usr << browse(html, "window=ViewBorer\ref[src]Chems;size=585x400") - return + return TRUE @@ -586,19 +646,19 @@ if(!host) to_chat(src, "You do not have a host to communicate with!") - return + return FALSE if(host.stat == DEAD) to_chat(src, SPAN_XENODANGER("Not even you can commune with the dead.")) - return + return FALSE - if(stat) - to_chat(src, "You cannot do that in your current state.") - return + if(stat == DEAD) + to_chat(src, "You're dead, Jim.") + return FALSE var/input = stripped_input(src, "Please enter a message to tell your host.", "Borer", "") if(!input) - return + return FALSE if(src && !QDELETED(src) && !QDELETED(host)) var/say_string = (docile) ? "slurs" :"states" @@ -610,6 +670,7 @@ var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping dead.show_message(SPAN_BORER("BORER: ([truename] to [host.real_name][track_host]) [say_string]: [input]"), SHOW_MESSAGE_VISIBLE) + return TRUE /mob/living/carbon/cortical_borer/verb/toggle_silence_inside_host() set name = "Toggle speech inside Host" @@ -631,15 +692,15 @@ var/mob/living/carbon/cortical_borer/B = has_brain_worms() if(!B) - return + return FALSE if(stat == DEAD) to_chat(src, SPAN_XENODANGER("You're dead, Jim.")) - return + return FALSE var/input = stripped_input(src, "Please enter a message to tell the borer.", "Message", "") if(!input) - return + return FALSE to_chat(B, SPAN_XENO("[src] says: [input]"), type = MESSAGE_TYPE_RADIO) log_say("BORER: ([key_name(src)] to [key_name(B)]) [input]", src) @@ -648,6 +709,7 @@ var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping dead.show_message(SPAN_BORER("BORER: ([name][track_host] to [B.truename]) says: [input]"), SHOW_MESSAGE_VISIBLE) + return TRUE /mob/living/proc/trapped_mind_comm() set name = "Converse with Trapped Mind" @@ -657,11 +719,11 @@ var/mob/living/carbon/cortical_borer/B = has_brain_worms() if(!B || !B.host_brain) - return + return FALSE var/mob/living/captive_brain/CB = B.host_brain var/input = stripped_input(src, "Please enter a message to tell the trapped mind.", "Message", "") if(!input) - return + return FALSE to_chat(CB, SPAN_XENO("[B.truename] says: [input]"), type = MESSAGE_TYPE_RADIO) log_say("BORER: ([key_name(src)] to [key_name(CB)]) [input]", B) @@ -670,7 +732,7 @@ var/track_borer = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping dead.show_message(SPAN_BORER("BORER: ([B.truename][track_borer] to [real_name] (trapped mind)) says: [input]"), SHOW_MESSAGE_VISIBLE) - + return TRUE @@ -679,10 +741,10 @@ if(href_list["borer_use_chem"]) locate(href_list["src"]) if(!istype(src, /mob/living/carbon/cortical_borer)) - return + return FALSE if(docile) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) - return + return FALSE var/topic_chem = href_list["borer_use_chem"] var/datum/borer_chem/C = null @@ -694,15 +756,15 @@ break if(!C || !host || controlling || !src || stat) - return + return FALSE var/datum/reagent/R = chemical_reagents_list[C.chem_id] if(enzymes < C.cost) to_chat(src, SPAN_XENOWARNING("You need [C.cost] enzymes stored to secrete [R.name]!")) - return + return FALSE var/contamination = round(C.cost / 10) if(C.impure && ((contaminant + contamination) > max_contaminant)) to_chat(src, SPAN_XENOWARNING("You are too contaminated to secrete [R.name]!")) - return + return FALSE to_chat(src, SPAN_XENONOTICE("You squirt a measure of [R.name] from your reservoirs into [host]'s bloodstream.")) contaminant += contamination host.reagents.add_reagent(C.chem_id, C.quantity) @@ -712,4 +774,5 @@ // This is used because we use a static set of datums to determine what chems are available, // instead of a table or something. Thus, when we instance it, we can safely delete it qdel(C) + return TRUE ..() diff --git a/code/modules/mob/language/languages.dm b/code/modules/mob/language/languages.dm index 74f058e1ff66..905b6a07670f 100644 --- a/code/modules/mob/language/languages.dm +++ b/code/modules/mob/language/languages.dm @@ -243,4 +243,4 @@ var/area/A = get_area(speaker) to_chat(player, "[message_start] has [SPAN_BOLD("perished")][A? " at [sanitize_area(A.name)]":""]!") else - to_chat(player, "[ghost? "(F) ":""][message_start] [message_body]") + to_chat(player, "[ghost? "(F) ":""][message_start][message_body]") diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ffcbb80c6442..a893709a1ef4 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -137,7 +137,7 @@ if(eta_status) . += "Evacuation: [eta_status]" - var/mob/living/carbon/cortical_borer/B = borer + var/mob/living/carbon/cortical_borer/B = has_brain_worms() if(B && B.controlling) var/CR = "Yes" @@ -151,6 +151,7 @@ . += "Name: [B.truename]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" + . += "Health: P:[round(getBruteLoss())] B:[round(getFireLoss())] T:[round(getToxLoss())]" . += "" . += "Host Brain Damage: [brainloss]/100" diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index dd2ef504965c..2342bd12a81b 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -144,6 +144,24 @@ else . += "Hive Orders: -" + var/mob/living/carbon/cortical_borer/B = has_brain_worms() + if(B && B.controlling) + + var/CR = "Yes" + if(!B.can_reproduce) + CR = "Forbidden" + else if((B.enzymes < BORER_LARVAE_COST)) + CR = "No" + + . += "" + . += "Borer:" + . += "Name: [B.truename]" + . += "Can Reproduce: [CR]" + . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" + . += "Health: P:[round(getBruteLoss())] B:[round(getFireLoss())] T:[round(getToxLoss())]" + . += "" + . += "Host Plasma: [plasma_stored]/[plasma_max]" + . += "Host Integrity: [health]/[maxHealth]" . += "" //A simple handler for checking your state. Used in pretty much all the procs. diff --git a/icons/mob/hud/actions_borer.dmi b/icons/mob/hud/actions_borer.dmi index 9447b8f546211f96dd4fa71ebe28446e13d25f14..99efeb7c5b44c4d1e5199e21cd035c156133dbf6 100644 GIT binary patch delta 1930 zcmV;52X*-H52+B4wSU2SR9JLGWpiV4X>fFDZ*Bkpc$}5e!3u*g3J07mPbxQXkj;B2)znXS2; zIWu4fllCSinP4lkmq)-(8JJ?mnYI|WX~|iSa)Q17u`$h#NPkyjV*n&-w1V(Y^=6!=!#>!Byxm+UeAhpXdD5;kv!i8Y9a$;_(yY5x7Fui z--CbA6bNY+E&u=ql1W5CRCt{2n~Qp)N(_KyXDD*9qg~6fg9zPT-v1F#GGTCTfJ$w5 zzmM$Js=?$Z$$tzaZC9&B7WpeA3dyhU)2|{%!g(CW-E;Qf>n-_0{TU!xuh;x;09?xu z08i8PI?ecifqW(ahL?m70VEKCB#nn16gkU_AqShyBYt~)+-ySnvwtE80L18j6o4X8 z+!6sEck$N*A%HA_0A!G(c-(>T9X#UcpqWUyxp zfqw(A=4Sxq-v&_k053p*{HxitLX7 z(0o7$_qKbgzjtdu4gipSDOu$KsNyeZJ^(dvm)qt{(&w;=Mpv7MZYR}aRQC!jA>kuE0;rRhURg&zh7qT(| z)cF@Z01;f#-z$Ks8k`?U(rW-BaEnlgem)=qLn!R;g#hpH;I-Eg6<(Y`1dam(3@Lm2 z(k;?eA;7;eAHa3sq+qnaR}qkMaDRSKNzfYhaUEDGD8Rop9{>U|4B++mQ}crg{9E>c zz)pcEocRF6w;hb!2WC6m$v z0h*>hsW)5Jwx{;{0ouB58h@>5oAzda%|`#^H*DY)B&3fZ_NRzN1VJ$feSW~cK7f?r zA3l@&^P>w;*L4d76#W+K!2kT9eL4UYk0AOG*8n>H1ELWueWc2do#2aN;D3I^zB&Nk zq+h}4UN{EO=^xfTygK?fAgCMoe>xFC?R|dCJ|58P`y*@vz5kxT)PKJ-j6vH*&8e@& zhs*850b2j@(H~(M(EdL^dje}8cyC#x0$q0@Z~!{{A0Ozzv%iWq%sqf@OargonSXvF zfr`Yd6@glBKdf#70NOryU;+E{0p8e~2558$f&d>Z3@|qZjJ>z-b_nXLQZTm&;hneo zT@^o8&^h3|8w{2HlMxRCk49w1_Tyrzt8^j`xIdh@X5vj^5Ab;%?G$R1^xN| zND&n*7~L}kBMugTy93Of4=l3CzbyX)wKBtRsOt7S Q00000NkvXXt^-0~f=&~GnE(I) delta 1872 zcmV-W2e0_45bzI>wST>OR9JLGWpiV4X>fFDZ*Bkpc$}4z!3u*g42I9`Qxv@q-FDq& zD8s{i1?g(E1#Km%`udXzI}8T#_W$7ve1W9uUOuW?70*g8faHQ#H+4N_Qmn3xb}N^& z6c$`><6bE02wO~E0RbChVWdQg)*)@vT#63$2z&lvDbAjWu7B3i1jwXK@Dann)i9c? zF@Rox$;N;q_{gN4?|`_lb*=M#lO4lzCXO&+XlKJclm>w5h|hQ7uTiSXy7+wI8!|t{ zRIT+gNdN!_T}ebiRCt{2nu~gyIt+lrY)T-cPP&wnnh@xEdH+Y8WMSefG|6ew?;Bd1 z3j*m!mTjbNv45ClmLDNWNPgW;zepGf=V_YupV@=2x8#4+p8&Gua>>69fNO~X@H}5G z^MXeVtgZyW@RINtKn4-W@-*(CT(MOdbFf}N;@jindL7cA{1ZU{AVvS902GPxk_hm$ zkH01e0TdYopnx$-#~ldY!6V*2{^|gD0DRdCGI#(g`G3J`2)+AfC4~d9F(Tjtfd4AX zwPY0#ctfD3DQE*Z0N$TagXcUy|A+FtE202f4XyhYR355tsnE1^`hxfCR=6^QGDfhLsq;awEbEwena1 zNZwmfq=uZIH9}rOk(fa<&0BB#v0R;62M8rV6 zz9;=*3P6&583&;Lfd9xfRo@R0s1NK=#{tNG9R(<=BLHMyN>+OSD)~$54?qrJ>2XGVZ}$)CKm^pWn(PCftX%*>IiUIj__wT9SSBMb;*Oy8m(j zAc8aMdj(L}(f)xXy#^oxHwlFp`U4`+gu?n>2=ERsUU{8R;-wix;1FqGNIBS-Zjvra z0sf8t0L}wv2uACB6#*%u{exP9)_<^%^S~N{68u~J0U!`@0I$BE>L1kL-?9$`_7I5D z=?_3m&M2?#{(+RWI|Q_befBotnMKzI?D0)X5a`UlQJBc*3wS`iR|{=f);S6=r? z2-EO@0JR$d8L)2w1p5QR0T`+8DFSK~fWcqugZ8Bb0PC;W9}sSTV7$Ih`hRuE+7K)N zSbt6X(zd@)&j40=F0B5*RDG|L@DKq|&j6NvY1v<>mB;Q62(v#hRo|a>!$S~2tvt4U zY1$9=2ZWIWQ}z91{~%yrnmI7bEVIlq%eU134`09j`ue|Vjx8SR+NN!~v#-A%plzF@ zI@qzUJ9f7R=$fW&wW4dgi+=&uYyFqsuz^>QkUoLf9}|`k1jQh9eZ;;#ft2AtK9l>? zs|(OHO$P)N{SNcMzdmZ8PC&&Yh(5(NfR6uwXaq~2sPtn;_@x;5*N@m&C*VQ)FBtt7 z#{fG0!}^z3NB;%{O$$HABM~&-^<(z&gh4-?VH+6y4+N(EonZ{RE`Mo{LoPmi-9DV4 z^&cO@8I}R<|MPPou-1Y1jwLG4O&(`=O+@VNW5AR zX!P>Knl=ES?Slsvuzx+k8++3LtqwsD;Ddz$t{no#-n(}@1kG7PaBUL8k+LG>Be&oav_v&=GG zzkfTx)MhaQ+zcS{$aO1#=tJji07f3WZvrq@c-#VDwDh_GKuPcaRQ Date: Mon, 3 Apr 2023 08:17:40 +0100 Subject: [PATCH 05/52] Brain follow, help details & follow tweak. Brains! --- code/__DEFINES/typecheck/xenos.dm | 1 + code/__HELPERS/unsorted.dm | 2 + .../admin/player_panel/player_panel.dm | 2 + code/modules/borer/borer.dm | 45 +++++++++++--- code/modules/borer/borer_procs.dm | 55 ++++++++++++------ code/modules/mob/dead/observer/orbit.dm | 8 +-- code/modules/mob/living/carbon/human/human.dm | 3 +- .../mob/living/carbon/xenomorph/XenoProcs.dm | 3 +- code/modules/mob/living/living_defines.dm | 3 + icons/mob/hud/actions_borer.dmi | Bin 2089 -> 2187 bytes tgui/packages/tgui/interfaces/Orbit/index.tsx | 4 +- tgui/packages/tgui/interfaces/Orbit/types.ts | 2 +- 12 files changed, 91 insertions(+), 37 deletions(-) diff --git a/code/__DEFINES/typecheck/xenos.dm b/code/__DEFINES/typecheck/xenos.dm index 6ae8fe1955a0..a71dbd287e7a 100644 --- a/code/__DEFINES/typecheck/xenos.dm +++ b/code/__DEFINES/typecheck/xenos.dm @@ -1,6 +1,7 @@ //Xenomorph Hud Test APOPHIS 22MAY2015 #define isxeno(A) (istype(A, /mob/living/carbon/xenomorph)) #define isborer(A) (istype(A, /mob/living/carbon/cortical_borer)) +#define iscaptivemind(A) (istype(A, /mob/living/captive_brain)) #define isxeno_human(A) (isxeno(A) || ishuman(A)) //ask walter if i should turn into castechecks diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 25890101758b..e190a64be913 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -626,6 +626,8 @@ moblist.Add(M) for(var/mob/living/carbon/cortical_borer/M in sortmob) moblist.Add(M) + for(var/mob/living/captive_brain/M in sortmob) + moblist.Add(M) for(var/mob/dead/observer/M in sortmob) moblist.Add(M) for(var/mob/new_player/M in sortmob) diff --git a/code/modules/admin/player_panel/player_panel.dm b/code/modules/admin/player_panel/player_panel.dm index ada3d1100687..b1eb9bdf21bd 100644 --- a/code/modules/admin/player_panel/player_panel.dm +++ b/code/modules/admin/player_panel/player_panel.dm @@ -217,6 +217,8 @@ M_job = "Corgi" else M_job = "Animal" + else if(iscaptivemind(M)) + M_job = "Captive Mind" else M_job = "Living" else if(istype(M,/mob/new_player)) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 54daabcf341b..25cf64bcfe96 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -1,6 +1,15 @@ /mob/living/captive_brain - name = "host brain" - real_name = "host brain" + name = "captive mind" + real_name = "captive mind" + icon = 'icons/obj/items/organs.dmi' + icon_state = "xenobrain" + + /// Whether or not the brain is mid-resisting control. + var/resisting_control = FALSE + +/mob/living/captive_brain/New(loc, ...) + . = ..() + give_action(src, /datum/action/innate/borer/brain_resist) /mob/living/captive_brain/say(message) if(client) @@ -40,14 +49,31 @@ if(!istype(B)) log_debug(EXCEPTION("Trapped mind found without a borer!"), src) return FALSE + if(resisting_control) + to_chat(src, SPAN_DANGER("You stop resisting control.")) + to_chat(B.host, SPAN_XENODANGER("The captive mind of [src] is no longer attempting to resist you.")) + resisting_control = FALSE + return FALSE - to_chat(src, SPAN_DANGER("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).")) - to_chat(B.host, SPAN_XENOWARNING("You feel the captive mind of [src] begin to resist your control.")) - + to_chat(src, SPAN_HIGHDANGER("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).")) + to_chat(B.host, SPAN_XENOHIGHDANGER("You feel the captive mind of [src] begin to resist your control.")) + resisting_control = TRUE var/delay = (rand(350,450) + B.host.getBrainLoss()) addtimer(CALLBACK(src, PROC_REF(return_control), B), delay) return TRUE +/datum/action/innate/borer/brain_resist + name = "Resist!" + action_icon_state = "brain_resist" + +/datum/action/innate/borer/brain_resist/action_activate() + if(isliving(owner)) + var/mob/living/live_owner = owner + live_owner.resist() + else + to_chat(owner, SPAN_WARNING("Error: CB1, tell forest2001! ")) + return FALSE +//################################################// /mob/living/carbon/cortical_borer name = "cortical borer" real_name = "cortical borer" @@ -262,7 +288,8 @@ . += "Can Reproduce: [CR]" . += "Enzymes: [round(enzymes)]/[round(max_enzymes)]" . += "Contaminant: [round(contaminant)]/[round(max_contaminant)]" - . += "Health: P:[round(getBruteLoss())] B:[round(getFireLoss())] T:[round(getToxLoss())]" + . += "Health: [health]/[maxHealth]" + . += "Injuries: Brute:[round(getBruteLoss())] Burn:[round(getFireLoss())] Toxin:[round(getToxLoss())]" if(host) . += "" if(ishuman(host)) @@ -302,9 +329,9 @@ if(((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && !human_host.reagents.has_reagent("benzyme")) || human_host.reagents.has_reagent("bcure")) if(!docile) if(controlling) - to_chat(host, SPAN_XENODANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) + to_chat(host, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) else - to_chat(src, SPAN_XENODANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) + to_chat(src, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) docile = TRUE else if(docile) @@ -322,7 +349,7 @@ contaminant = max(contaminant -= 0.1, 0) if(controlling) if(docile) - to_chat(host, SPAN_XENOWARNING("You are feeling far too docile to continue controlling your host...")) + to_chat(host, SPAN_WARNING("You are feeling far too docile to continue controlling your host...")) host.release_control() return else diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 224cdc2fac5f..86b9cebc6308 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -6,37 +6,47 @@ var/target = src - var/list/options = list("Communicating") + var/list/options = list("Communicating","Contaminant & Enzymes") if(!host) options += list("Infecting a host") else if(controlling) target = host - options = list("Captive Host", "Releasing Control", "Reproducing") + options += list("Captive Host", "Releasing Control", "Reproducing") else if(isxeno(host)) - options = list("Assuming Control","Contaminant & Enzymes","Hibernation","Reproducing") + options += list("Assuming Control","Hibernation","Reproducing") else - options = list("Assuming Control","Contaminant & Enzymes","Hibernation","Secreting Chemicals","Reproducing") + options += list("Assuming Control","Hibernation","Secreting Chemicals","Reproducing") var/choice = tgui_input_list(target, "What would you like help with?", "Help", options, 20 SECONDS) var/help_message = "" switch(choice) if("Infecting a host") - help_message = "Infecting a host is the first major step for a borer to complete.\n\nThis is done by getting close to a potential host (This can be Human, Xeno or Yautja depending on settings controlled by admins) and clicking the Infest button in the top left of your screen.\n\nYour host will need to keep still for you to do this, and it's rare that they do so; for this reason you have Dominate Victim, which will allow you to temporarily stun a target.\n\nNote: This is not sufficient to keep them down for 100% of the time it takes to infect however, so be careful with it." + var/possible_targets = "" + if(infect_humans) possible_targets += "\nHumans" + if(infect_xenos) possible_targets += "\nXenos" + if(infect_yautja) possible_targets += "\nYautja" + if(!possible_targets) possible_targets += "No one." + help_message = "Infecting a host is the first major step for a borer to complete.\n\nThis is done by getting close to a potential host (This can be Human, Xeno or Yautja depending on settings controlled by admins) and clicking the Infest button in the top left of your screen.\n\nYour host will need to keep still for you to do this, and it's rare that they do so; for this reason you have Dominate Victim, which will allow you to temporarily stun a target.\n\nNote: Dominate is not sufficient to keep them down for 100% of the time it takes to infect however, so be careful with it.\n\nWhilst inside a host, and NOT in direct control, you can be detected by body scanners but otherwise are hidden from everyone but your host and other borers.\nYou can currently infect: [possible_targets]" if("Communicating") help_message = "All borers share a hivemind, the Cortical Link, this can be accessed using :0 (that's ZERO).\n\nThe hivemind can be used by any borer who is NOT in direct control of their host.\n\nAny borer in direct control of a host can only hear what their host can hear.\n\nA borer inside a host can communicate directly with that host using 'Converse with Host'." if("Captive Host") - help_message = "" + help_message = "Your host is now unable to act or speak to anyone but yourself. While in this state you have complete control of your host body, but you are disconnected from the hivemind.\n\nYour host can resist your control and regain their body however this can cause brain damage in humanoids.\n\nNote: Whilst in direct control of your host medical HUDs will detect you.\n\n\nIMPORTANT: While in direct control of a mob you MUST NOT perform antag actions unless you have permission from staff." if("Releasing Control") - help_message = "" + help_message = "Releasing control will do as it suggests, give your host their body back.\n\nYour host can resist your control and regain their body however this can cause brain damage in humanoids." if("Reproducing") - help_message = "" + var/capability = "able" + if(!can_reproduce) capability = "forbidden" + else if((enzymes < BORER_LARVAE_COST)) capability = "unable" + help_message = "Reproduction will take [BORER_LARVAE_COST] enzymes and direct control of your host.\n\nWhen in direct control you can use the Reproduce ability to spit out a new borer.\nMake sure to do this in a safe place, the new borer will not have a player to start with.\n\nYou are currently [capability] to reproduce." if("Assuming Control") - help_message = "" - if("Contaminant & Enzymes", "Hibernation") - help_message = "" + help_message = "Assuming control will put you in direct control of your host, acting as if you are their player.\n\nYour host will be disassociated with their body, and trapped in their own mind unable to speak to anyone but you.\nWhile in this state you are unable to make use of the hivemind.\n\nYour host can resist your control and regain their body however this can cause brain damage in humanoids.\nYou must assume control to reproduce.\n\nNote: Whilst in direct control of your host medical HUDs will detect you.\n\n\nIMPORTANT: While in direct control of a mob you MUST NOT perform antag actions unless you have permission from staff." + if("Contaminant & Enzymes") + help_message = "Enzymes are the cost of using most of your active abilities, such as secreting chemicals. They are gained passively over time whilst inside a host.\n\nUsing enzymes will in most cases produce Contaminant which upon reaching its capacity will prevent you using abilities.\nYou can clear Contaminant by hibernating when inside a host, alternately Contaminant will naturally be turned into a weak light source whilst outside a host." + if("Hibernation") + help_message = "Hibernation is how you purify contaminants from your body, allowing you to use your enzymes more freely.\n\nYou can only hibernate whilst inside a host, and it renders you unable to act other than to speak to your host.\n\nYou can freely enter or leave hibernation by clicking the Hibernate button." if("Secreting Chemicals") - help_message = "" + help_message = "Whilst inside a humanoid host you can secrete chemicals to facilitate your relationship.\nThese can vary from helpful medications to harmful control measures.\n\nSecreting chemicals costs enzymes and if a chemical is impure will cause you to gain contaminant.\nIf you are at, or will go over, your contaminant capacity you will be unable to secrete chemicals.\nPure chemicals are chemicals native to borers such as Cortical Enzyme." alert(target, help_message, choice, "Ok") @@ -185,6 +195,8 @@ for(var/mob/living/carbon/candidate in view(1,src)) if(can_target(candidate)) choices += candidate + if(!choices) + to_chat(src, SPAN_XENOWARNING("No possible targets found.")) var/mob/living/carbon/target = tgui_input_list(src, "Who do you wish to infest?", "Targets", choices) if(!target || !src || !Adjacent(target)) return FALSE @@ -381,6 +393,7 @@ give_new_actions(ACTION_SET_CONTROL) host.med_hud_set_status() + host.special_mob = TRUE if(src && !src.key) src.key = "@[borer_key]" @@ -388,11 +401,12 @@ //Captive mind reclaims their body. /mob/living/captive_brain/proc/return_control(mob/living/carbon/cortical_borer/B) - if(!B || !B.controlling) + if(!B || !B.controlling || !resisting_control) return FALSE B.host.adjustBrainLoss(rand(5,10)) - to_chat(src, SPAN_DANGER("With an immense exertion of will, you regain control of your body!")) - to_chat(B.host, SPAN_XENODANGER("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) + to_chat(src, SPAN_HIGHDANGER("With an immense exertion of will, you regain control of your body!")) + to_chat(B.host, SPAN_XENOHIGHDANGER("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) + resisting_control = FALSE B.detach() return TRUE @@ -425,6 +439,7 @@ sleeping = 0 if(host_brain) log_interact(host, src, "Borer: [key_name(host)] Took control back") + host.special_mob = FALSE // host -> self var/h2s_id = host.computer_id var/h2s_ip= host.lastKnownIP @@ -457,9 +472,9 @@ return FALSE if(controlling) detach() - to_chat(src, SPAN_HIGHDANGER("You release your proboscis and flee as the psychic shock of your host's death washes over you!")) + to_chat(src, SPAN_XENOHIGHDANGER("You release your proboscis and flee as the psychic shock of your host's death washes over you!")) if(perma) - to_chat(src, SPAN_HIGHDANGER("You flee your host in anguish!")) + to_chat(src, SPAN_XENOHIGHDANGER("You flee your host in anguish!")) leave_host() return TRUE @@ -470,7 +485,7 @@ set desc = "Become invisible to the common eye." if(host) - to_chat(usr, SPAN_XENOWARNING("You cannot do this while you're inside a host.")) + to_chat(usr, SPAN_WARNING("You cannot do this while you're inside a host.")) return FALSE if(stat != CONSCIOUS) @@ -511,6 +526,8 @@ to_chat(src, SPAN_XENOWARNING("You cannot use that ability again so soon.")) return FALSE attempting_to_dominate = TRUE + if(!choices) + to_chat(src, SPAN_XENOWARNING("No possible targets found.")) var/mob/living/carbon/M = tgui_input_list(src, "Who do you wish to dominate?", "Targets", choices) if(!M) attempting_to_dominate = FALSE @@ -554,7 +571,7 @@ if(B.host_brain) to_chat(src, SPAN_XENONOTICE("You send a punishing spike of psychic agony lancing into your host's brain.")) - to_chat(B.host_brain, SPAN_XENOHIGHDANGER("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")) + to_chat(B.host_brain, SPAN_HIGHDANGER("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")) return TRUE diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index 39a7eb968368..bb35d8a87dc8 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -56,7 +56,7 @@ /datum/orbit_menu/ui_static_data(mob/user) var/list/data = list() - var/list/borers = list() + var/list/special_mobs = list() var/list/humans = list() var/list/marines = list() var/list/survivors = list() @@ -112,8 +112,8 @@ var/mob/living/player = M serialized["health"] = FLOOR((player.health / player.maxHealth * 100), 1) - if(isborer(player)) - borers += list(serialized) + if(isborer(player) || iscaptivemind(player) || player.special_mob) + special_mobs += list(serialized) if(isxeno(player)) var/mob/living/carbon/xenomorph/xeno = player @@ -163,7 +163,7 @@ else if(isAI(M)) humans += list(serialized) - data["borers"] = borers + data["special_mobs"] = special_mobs data["humans"] = humans data["marines"] = marines data["survivors"] = survivors diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index a893709a1ef4..d38f6cd34a8d 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -151,7 +151,8 @@ . += "Name: [B.truename]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" - . += "Health: P:[round(getBruteLoss())] B:[round(getFireLoss())] T:[round(getToxLoss())]" + . += "Health: [B.health]/[B.maxHealth]" + . += "Injuries: Brute:[round(B.getBruteLoss())] Burn:[round(B.getFireLoss())] Toxin:[round(B.getToxLoss())]" . += "" . += "Host Brain Damage: [brainloss]/100" diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index 2342bd12a81b..d576a02d708c 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -158,7 +158,8 @@ . += "Name: [B.truename]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" - . += "Health: P:[round(getBruteLoss())] B:[round(getFireLoss())] T:[round(getToxLoss())]" + . += "Health: [B.health]/[B.maxHealth]" + . += "Injuries: Brute:[round(B.getBruteLoss())] Burn:[round(B.getFireLoss())] Toxin:[round(B.getToxLoss())]" . += "" . += "Host Plasma: [plasma_stored]/[plasma_max]" . += "Host Integrity: [health]/[maxHealth]" diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index fc39f98414c5..54c9923f1eda 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -104,3 +104,6 @@ /// This is what the value is changed to when the mob dies. Actual BMV definition in atom/movable. var/dead_black_market_value = 0 + + /// Used to highlight on follow menu. + var/special_mob = FALSE diff --git a/icons/mob/hud/actions_borer.dmi b/icons/mob/hud/actions_borer.dmi index 99efeb7c5b44c4d1e5199e21cd035c156133dbf6..d1098b87d803641b4ca6ee29871f2c6dec5717ae 100644 GIT binary patch delta 2028 zcmVfFDZ*Bkpc$}4zu?mAg42Ea#DGuFBZM$|U zN^z*KAXklEK<^|u_4O+iIuuIdmOp%fFCmG(<@ci0*`rW15TkecsxOD5iWY2wUBmgL zA`95rumuh#z*@#nPe4^|Vc=Lr4HB>2R7EYB0k-;!`6pHRCt{2n~Qp)N(_Ky2Z|tev};*Ah|ulj{U7lp z69(rF>b7UkcYnxktr|>zGMRy-&T6&DB7cP>KKb!|`c=Y6(lpDm;W>M7^@jXG{RJRj zuh;390i;So0BKRI*F~8I3~cTM!0?i!A%GkrkQZ6lLA7C0dN4)^&rUL0LbLeN+~Jg z`T-E0RkuZ8y;A}N4nRsdfd2DT2F&LmD>j=dm;*xuh5%T4IRD*lkD>^40Gj+60u)7_ zQOdXus?7$Hq@2nTFJP+tBY^{uQg{^r5!eo@DuWaSxfNiq#08)v!AV%+JV@<%no#0p zIYeON1%G&YDoZ_4GJ6PN1ol6Ff_Hd;5ZFVIg8u?Dw8V!3=YcZ>oZ~F#F3t*>3zy$#RbzUgRYanojKu%N8dU61~KcNPXd4B$d@_Z3lD?0+Y3fE)#2sN5uk036Ui!)yeI!V`gA6ad!W-5!P?+?V?uOUwFrv;go@ z7=M`O2#`qt7!3A|A+P|}=>1lka% zYk4UcS7LaXY7t(^mB#=;0vEtQumBEpJ;NM)k^~w6EVAJ6axGfRtFi|0;{jy^kgs$? z(%Yixi?Yx)Fc61>rq9UdDDs64u*f2dEPt}dU(+9eo2{|#_=^635KYr~^cMi^5AdLY zV0}Lu0PTw~0H^){4;Tp7_oP2f0SK}$!T{7CaBsP$>iaPQ&550wFaX(af&dlu2mAoB z`raIZ0m0QbWIqBx{Q=JH+wQ6Q-p&CL03iE9u*Lz9$zM@_0CE6Jk1OhXvwzTdB7Y#? zYsfy}iN*%tlmoIqfX{*8iu(T2KRBHlZw?5`0cjtf1Az`elfU9rp34`!x}v^UAwHe_ z{R4t(1lgA_M56=9^RGq#BDkWymjF!@>>miyD*z&}laTYVKfparD6H=}2k-FUl-CI* zUY0`yPJsr75TkuzC+Vu<;9u(x;D0=@h9Fws%LoV&>>o4&w3>aK2gVRo;NR#E009pJ zIQ9Kh|DXZ?hJ7F~hk#dBe*j`~MR{%Z4}@s!ArOsaA7Wx8A$R%%+=;*x0OZ!#Kd=@W zAsqX{hyeHW2O7=fEP1EV9TVUsC@+%>VrT^?%!* zJAAM2+OF-d{`~y_UDuxFn}0p)`*Z*O0Daqbol^8&e>1>#tN!xqH}DGL(*!qK*zs96oR2oWcsl) z{7?+s&qwUb1Mp4y3dZolGJsBhv*F>@(!T*g+rj_ynFw0v^D+B)z<;P8k1!34{zn2` z|IRQ5eV=saF&7`^+lK>`{^Mgj!Z4uxe}0Yx#yarcvqT2E9YSCM4E8@h(1Bxrm28=P z0Nd&YUWYUP{6qp7iB}^6ty+Fq+j#(#eel3M_U{LHV{ZzeQz7sId@w)2y+gp*d;e~R zpuK7c?oC2?=dFF0$$yX8c)mUf@0^BA5~vWgZW2yU!#fuu1W;p;$U$gr{nSFl?pcbN zG5(m4-StZ`DQ~+Nk#~l3pktlmv>zX5^y%5N>hf=L+Je{coBCyN7Yg5R{_k?#*o1I!+R@%-Hg zMD`!d0GO48ab%G_j delta 1930 zcmV;52X*+15vdT6wSU2SR9JLGWpiV4X>fFDZ*Bkpc$}5e!3u*g3J07mPbxQXkj;B2)znXS2; zIWu4fllCSinP4lkmq)-(8JJ?mnYI|WX~|iSa)Q17u`$h#NPkyjV*n&-w1V(Y^=6!=!#>!Byxm+UeAhpXdD5;kv!i8Y9a$;_(yY5x7Fui z--CbA6bNY+E&u=ql1W5CRCt{2n~Qp)N(_KyXDD*9qg~6fg9zPT-v1F#GGTCTfJ$w5 zzmM$Js=?$Z$$tzaZC9&B7WpeA3dyhU)2|{%!g(CW-E;Qf>n-_0{TU!xuh;x;09?xu z08i8PI?ecifqW(ahL?m70VEKCB#nn16gkU_AqShyBYt~)+-ySnvwtE80L18j6o4X8 z+!6sEck$N*A%HA_0A!G(c-(>T9X#UcpqWUyxp zfqw(A=4Sxq-v&_k053p*{HxitLX7 z(0o7$_qKbgzjtdu4gipSDOu$KsNyeZJ^(dvm)qt{(&w;=Mpv7MZYR}aRQC!jA>kuE0;rRhURg&zh7qT(| z)cF@Z01;f#-z$Ks8k`?U(rW-BaEnlgem)=qLn!R;g#hpH;I-Eg6<(Y`1dam(3@Lm2 z(k;?eA;7;eAHa3sq+qnaR}qkMaDRSKNzfYhaUEDGD8Rop9{>U|4B++mQ}crg{9E>c zz)pcEocRF6w;hb!2WC6m$v z0h*>hsW)5Jwx{;{0ouB58h@>5oAzda%|`#^H*DY)B&3fZ_NRzN1VJ$feSW~cK7f?r zA3l@&^P>w;*L4d76#W+K!2kT9eL4UYk0AOG*8n>H1ELWueWc2do#2aN;D3I^zB&Nk zq+h}4UN{EO=^xfTygK?fAgCMoe>xFC?R|dCJ|58P`y*@vz5kxT)PKJ-j6vH*&8e@& zhs*850b2j@(H~(M(EdL^dje}8cyC#x0$q0@Z~!{{A0Ozzv%iWq%sqf@OargonSXvF zfr`Yd6@glBKdf#70NOryU;+E{0p8e~2558$f&d>Z3@|qZjJ>z-b_nXLQZTm&;hneo zT@^o8&^h3|8w{2HlMxRCk49w1_Tyrzt8^j`xIdh@X5vj^5Ab;%?G$R1^xN| zND&n*7~L}kBMugTy93Of4=l3CzbyX)wKBtRsOt7S Q00000NkvXXt^-0~f@6k(HUIzs diff --git a/tgui/packages/tgui/interfaces/Orbit/index.tsx b/tgui/packages/tgui/interfaces/Orbit/index.tsx index 9f6e9004b951..2856598e97b8 100644 --- a/tgui/packages/tgui/interfaces/Orbit/index.tsx +++ b/tgui/packages/tgui/interfaces/Orbit/index.tsx @@ -99,7 +99,7 @@ const ObservableSearch = (props, context) => { const ObservableContent = (props, context) => { const { data } = useBackend(context); const { - borers = [], + special_mobs = [], humans = [], marines = [], survivors = [], @@ -118,7 +118,7 @@ const ObservableContent = (props, context) => { return ( - + diff --git a/tgui/packages/tgui/interfaces/Orbit/types.ts b/tgui/packages/tgui/interfaces/Orbit/types.ts index d3b339ae04ed..d41e3389945e 100644 --- a/tgui/packages/tgui/interfaces/Orbit/types.ts +++ b/tgui/packages/tgui/interfaces/Orbit/types.ts @@ -2,7 +2,7 @@ import { BooleanLike } from 'common/react'; export type OrbitData = { auto_observe: BooleanLike; - borers: Observable[]; + special_mobs: Observable[]; humans: Observable[]; marines: Observable[]; survivors: Observable[]; From f7ba5d512cf0cfbb9cdd6ea36cf43123581c644d Mon Sep 17 00:00:00 2001 From: forest2001 Date: Mon, 3 Apr 2023 23:08:35 +0100 Subject: [PATCH 06/52] reproduction consistencies and hearing fix --- code/modules/borer/borer.dm | 16 ++++++++-------- code/modules/borer/borer_procs.dm | 6 +++--- code/modules/mob/language/languages.dm | 5 ++++- code/modules/mob/living/say.dm | 4 ++++ 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 25cf64bcfe96..52d3c9929ad3 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -133,34 +133,34 @@ /datum/action/innate/borer/helpme, /datum/action/innate/borer/toggle_hide, /datum/action/innate/borer/freeze_victim, - /datum/action/innate/borer/infest_host + /datum/action/innate/borer/infest_host, ) var/list/actions_humanoidhost = list( /datum/action/innate/borer/helpme, - /datum/action/innate/borer/take_control, /datum/action/innate/borer/talk_to_host, - /datum/action/innate/borer/leave_body, /datum/action/innate/borer/hibernate, + /datum/action/innate/borer/take_control, + /datum/action/innate/borer/leave_body, /datum/action/innate/borer/scan_chems, - /datum/action/innate/borer/make_chems + /datum/action/innate/borer/make_chems, ) var/list/actions_xenohost = list( /datum/action/innate/borer/helpme, - /datum/action/innate/borer/take_control, /datum/action/innate/borer/talk_to_host, + /datum/action/innate/borer/hibernate, + /datum/action/innate/borer/take_control, /datum/action/innate/borer/leave_body, - /datum/action/innate/borer/hibernate ) var/list/actions_control = list( /datum/action/innate/borer/helpme, /datum/action/innate/borer/give_back_control, /datum/action/innate/borer/make_larvae, /datum/action/innate/borer/talk_to_brain, - /datum/action/innate/borer/torment + /datum/action/innate/borer/torment, ) //################### INIT & LIFE ###################// -/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0) +/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0, infect_humans = TRUE, infect_xenos = FALSE, infect_yautja = FALSE) ..(newloc) SSmob.living_misc_mobs += src generation = gen diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 86b9cebc6308..96df31acc7d5 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -593,7 +593,7 @@ T.add_vomit_floor() B.contaminant = 0 var/repro = max(B.can_reproduce - 1, 0) - new /mob/living/carbon/cortical_borer(T, B.generation + 1, TRUE, repro) + new /mob/living/carbon/cortical_borer(T, B.generation + 1, TRUE, repro, B.infect_humans, B.infect_xenos, B.infect_yautja) return TRUE else to_chat(src, SPAN_XENONOTICE("You need at least [BORER_LARVAE_COST] enzymes to reproduce!")) @@ -719,9 +719,9 @@ if(!input) return FALSE - to_chat(B, SPAN_XENO("[src] says: [input]"), type = MESSAGE_TYPE_RADIO) + to_chat(B, SPAN_XENO("[src.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) log_say("BORER: ([key_name(src)] to [key_name(B)]) [input]", src) - to_chat(src, SPAN_XENO("[src] says: [input]"), type = MESSAGE_TYPE_RADIO) + to_chat(src, SPAN_XENO("[src.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) for (var/mob/dead in GLOB.dead_mob_list) var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping diff --git a/code/modules/mob/language/languages.dm b/code/modules/mob/language/languages.dm index 905b6a07670f..306a324cbea7 100644 --- a/code/modules/mob/language/languages.dm +++ b/code/modules/mob/language/languages.dm @@ -215,6 +215,7 @@ /datum/language/corticalborer/broadcast(mob/living/carbon/speaker, message, speaker_mask, death) var/mob/living/carbon/cortical_borer/B + if(!message) return FALSE if(isborer(speaker)) B = speaker else if(speaker.has_brain_worms()) @@ -224,6 +225,7 @@ if(!speaker_mask) speaker_mask = speaker.real_name + message = trim(message) var/message_start = "[name], [speaker_mask]" var/message_body = "[speech_verb], \"[message]\"" log_say("[key_name(speaker)] : ([name]) [message]") @@ -243,4 +245,5 @@ var/area/A = get_area(speaker) to_chat(player, "[message_start] has [SPAN_BOLD("perished")][A? " at [sanitize_area(A.name)]":""]!") else - to_chat(player, "[ghost? "(F) ":""][message_start][message_body]") + to_chat(player, "[ghost? "(F) ":""][message_start] [message_body]") + return TRUE diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index bb9cf9309a2b..d1430de4a43d 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -116,6 +116,10 @@ var/list/department_radio_keys = list( for(var/obj/O in M.contents) if(O.flags_atom & USES_HEARING) listening_obj |= O + for(var/mob/inner_mob in M.contents) + listening |= inner_mob + for(var/mob/living/captive_brain/brain in inner_mob) + listening |= brain else if(istype(I, /obj/)) var/obj/O = I hearturfs += O.locs[1] From d917b6acada8849dccfdeebd0bbf76c4ef3cc6d8 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 6 Apr 2023 07:27:51 +0100 Subject: [PATCH 07/52] bitflags! --- code/__DEFINES/borer_defines.dm | 52 ++++++ code/datums/mob_hud.dm | 2 +- code/modules/borer/_defines.dm | 13 -- code/modules/borer/borer.dm | 157 ++++++++---------- code/modules/borer/borer_procs.dm | 82 ++++++--- code/modules/mob/living/carbon/human/human.dm | 2 +- .../mob/living/carbon/xenomorph/XenoProcs.dm | 2 +- .../chemistry_properties/prop_positive.dm | 2 +- code/modules/surgery/brainworm.dm | 1 + colonialmarines.dme | 2 +- icons/mob/hud/actions_borer.dmi | Bin 2187 -> 2693 bytes 11 files changed, 188 insertions(+), 127 deletions(-) create mode 100644 code/__DEFINES/borer_defines.dm delete mode 100644 code/modules/borer/_defines.dm diff --git a/code/__DEFINES/borer_defines.dm b/code/__DEFINES/borer_defines.dm new file mode 100644 index 000000000000..181a7d830f47 --- /dev/null +++ b/code/__DEFINES/borer_defines.dm @@ -0,0 +1,52 @@ +/// Chemical categories +#define BORER_CAT_HEAL "Medicines" +#define BORER_CAT_PUNISH "Motivators" +#define BORER_CAT_STIM "Stimulants" +#define BORER_CAT_SELF "Self Protection" + +///Amount of chemicals needed for a borer to reproduce, provided reproduction is toggled. +#define BORER_LARVAE_COST 400 + +#define ACTION_SET_HOSTLESS "actions_hostless" +#define ACTION_SET_HUMANOID "actions_human" +#define ACTION_SET_XENO "actions_xeno" +#define ACTION_SET_CONTROL "actions_control" + +/// Borer target bitflags +#define BORER_TARGET_HUMANS (1<<0) +#define BORER_TARGET_XENOS (1<<1) +#define BORER_TARGET_YAUTJA (1<<2) + +DEFINE_BITFIELD(borer_flags_targets, list( + "TARGET_HUMANS" = BORER_TARGET_HUMANS, + "TARGET_XENOS" = BORER_TARGET_XENOS, + "TARGET_YAUTJA" = BORER_TARGET_YAUTJA, +)) + +/// Borer active/toggle-able ability flags. +/// Middle of crawling into a new host +#define BORER_PROCESS_INFESTING (1<<0) +/// Middle of taking control of a host body +#define BORER_PROCESS_BONDING (1<<1) +/// Middle of leaving a host +#define BORER_PROCESS_LEAVING (1<<2) +/// Hiding or not. (Changes layer) +#define BORER_ABILITY_HIDE (1<<3) +/// Sleeps to purify contaminant +#define BORER_ABILITY_HIBERNATING (1<<4) + +DEFINE_BITFIELD(borer_flags_actives, list( + "PROCESS_INFESTING" = BORER_PROCESS_INFESTING, + "PROCESS_BONDING" = BORER_PROCESS_BONDING, + "PROCESS_LEAVING" = BORER_PROCESS_LEAVING, + "ACTIVE_HIDING" = BORER_ABILITY_HIDE, + "ACTIVE_HIBERNATING" = BORER_ABILITY_HIBERNATING, +)) + +#define BORER_STATUS_CONTROLLING (1<<0) +#define BORER_STATUS_DOCILE (1<<1) + +DEFINE_BITFIELD(borer_flags_status, list( + "STATUS_CONTROLLING" = BORER_STATUS_CONTROLLING, + "STATUS_DOCILE" = BORER_STATUS_DOCILE, +)) diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm index a6d4e2c09a09..1d0519b54c81 100644 --- a/code/datums/mob_hud.dm +++ b/code/datums/mob_hud.dm @@ -463,7 +463,7 @@ var/list/datum/mob_hud/huds = list( holder5.icon_state = null if(B) holder5.icon_state = "hudbrainwormhost" - if(B.controlling) + if(B.borer_flags_status & BORER_STATUS_CONTROLLING) holder.icon_state = "hudbrainworm" if(!holder2_set) holder2.icon_state = "hudbrainworm" diff --git a/code/modules/borer/_defines.dm b/code/modules/borer/_defines.dm deleted file mode 100644 index a1c7b4959e50..000000000000 --- a/code/modules/borer/_defines.dm +++ /dev/null @@ -1,13 +0,0 @@ -/// Chemical categories -#define BORER_CAT_HEAL "Medicines" -#define BORER_CAT_PUNISH "Motivators" -#define BORER_CAT_STIM "Stimulants" -#define BORER_CAT_SELF "Self Protection" - -///Amount of chemicals needed for a borer to reproduce, provided reproduction is toggled. -#define BORER_LARVAE_COST 400 - -#define ACTION_SET_HOSTLESS "actions_hostless" -#define ACTION_SET_HUMANOID "actions_human" -#define ACTION_SET_XENO "actions_xeno" -#define ACTION_SET_CONTROL "actions_control" diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 52d3c9929ad3..832a96aa35f3 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -115,16 +115,18 @@ var/mob/living/carbon/host // Human host for the brain worm. var/truename // Name used for brainworm-speak. var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. - var/controlling // Used in human death check. var/docile = FALSE // Anti-Parasite or Anti-Enzyme chemicals can stop borers from acting. var/bonding = FALSE var/leaving = FALSE var/hiding = FALSE var/can_reproduce = FALSE // Locked to manual override to prevent things getting out of hand. - var/infect_humans = TRUE // Locked for normal use. - var/infect_xenos = FALSE - var/infect_yautja = FALSE + /// Flags that show what active abilities are toggled. Better than a dozen different boolean vars. + var/borer_flags_actives + /// Flags determining what the borer can infect + var/borer_flags_targets = BORER_TARGET_HUMANS + /// Borer status, controlling or docile. + var/borer_flags_status //Controlling or Docile. Unsure if I want to put hibernating in here or in actives as active abilities will stop enzyme production. var/list/datum/reagent/synthesized_chems @@ -160,7 +162,7 @@ ) //################### INIT & LIFE ###################// -/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0, infect_humans = TRUE, infect_xenos = FALSE, infect_yautja = FALSE) +/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0, new_targets = BORER_TARGET_HUMANS) ..(newloc) SSmob.living_misc_mobs += src generation = gen @@ -169,6 +171,7 @@ real_name = "Cortical Borer [mob_number]" truename = "[borer_names[min(generation, borer_names.len)]] [mob_number]" can_reproduce = reproduction + borer_flags_targets = new_targets give_new_actions(ACTION_SET_HOSTLESS) //GrantBorerActions() GiveBorerHUD() @@ -186,6 +189,55 @@ /mob/living/carbon/cortical_borer/initialize_stamina() stamina = new /datum/stamina/none(src) +/mob/living/carbon/cortical_borer/Life(delta_time) + ..() + update_canmove() + update_icons() + var/heal_amt = 1 + if(host) + heal_amt = 3 + if(!stat && host.stat != DEAD) + var/mob/living/carbon/human/human_host + if(ishuman(host)) + human_host = host + if(((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && !human_host.reagents.has_reagent("benzyme")) || human_host.reagents.has_reagent("bcure")) + if(!docile) + if(borer_flags_status & BORER_STATUS_CONTROLLING) + to_chat(host, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) + else + to_chat(src, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) + docile = TRUE + else + if(docile) + if(borer_flags_status & BORER_STATUS_CONTROLLING) + to_chat(human_host, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) + else + to_chat(src, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) + docile = FALSE + if(!hibernating && (enzymes < max_enzymes)) + enzymes++ + if(contaminant > 0) + if(hibernating) + contaminant = max(contaminant -= 1, 0) + else + contaminant = max(contaminant -= 0.1, 0) + if(borer_flags_status & BORER_STATUS_CONTROLLING) + if(docile) + to_chat(host, SPAN_WARNING("You are feeling far too docile to continue controlling your host...")) + host.release_control() + return + else + if(contaminant > 0) + if(!luminosity) + SetLuminosity(2) + contaminant = max(contaminant - 0.3, 0) + else + SetLuminosity(0) + if(bruteloss || fireloss) + heal_overall_damage(heal_amt, heal_amt) + if(toxloss && !contaminant)//no clearing toxic impurities while contaminated. + apply_damage(-(heal_amt/2), TOX) + /mob/living/carbon/cortical_borer/updatehealth() if(status_flags & GODMODE) health = maxHealth @@ -235,18 +287,6 @@ return ..() //###################################################// -/mob/living/carbon/cortical_borer/proc/summon() - var/datum/emergency_call/custom/em_call = new() - em_call.name = real_name - em_call.mob_max = 1 - em_call.players_to_offer = list(src) - em_call.owner = null - em_call.ert_message = "A new Cortical Borer has been birthed!" - em_call.objectives = "Create enjoyable Roleplay. Do not kill your host. Do not take control unless granted permission or directed to by admins. Hivemind is :0 (That's Zero, not Oscar)" - - em_call.activate(announce = FALSE) - - message_admins("A new Cortical Borer has spawned at [get_area(loc)]") /mob/living/carbon/cortical_borer/update_icons() if(stat == DEAD) @@ -292,11 +332,15 @@ . += "Injuries: Brute:[round(getBruteLoss())] Burn:[round(getFireLoss())] Toxin:[round(getToxLoss())]" if(host) . += "" + var/health_perc = host.maxHealth / 100 + . += "Host Integrity: [host.health / health_perc]%" if(ishuman(host)) - . += "Host Brain Damage: [host.brainloss]/100" + . += "Host Brain Damage: [host.brainloss]%" else if(isxeno(host)) - // . += "Host Plasma: [plasma_stored]/[plasma_max]" - . += "Host Integrity: [health]/[maxHealth]" + var/mob/living/carbon/xenomorph/xeno_host = host + if(xeno_host.plasma_max) + var/plasma_perc = xeno_host.plasma_max / 100 + . += "Host Plasma: [xeno_host.plasma_stored / plasma_perc]%" /mob/living/carbon/cortical_borer/say(message)//I need to parse the message properly so it doesn't look stupid var/datum/language/parsed_language = parse_language(message) @@ -314,56 +358,6 @@ return . = ..() - -/mob/living/carbon/cortical_borer/Life(delta_time) - ..() - update_canmove() - update_icons() - var/heal_amt = 1 - if(host) - heal_amt = 3 - if(!stat && host.stat != DEAD) - var/mob/living/carbon/human/human_host - if(ishuman(host)) - human_host = host - if(((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && !human_host.reagents.has_reagent("benzyme")) || human_host.reagents.has_reagent("bcure")) - if(!docile) - if(controlling) - to_chat(host, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) - else - to_chat(src, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) - docile = TRUE - else - if(docile) - if(controlling) - to_chat(human_host, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) - else - to_chat(src, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) - docile = FALSE - if(!hibernating && (enzymes < max_enzymes)) - enzymes++ - if(contaminant > 0) - if(hibernating) - contaminant = max(contaminant -= 1, 0) - else - contaminant = max(contaminant -= 0.1, 0) - if(controlling) - if(docile) - to_chat(host, SPAN_WARNING("You are feeling far too docile to continue controlling your host...")) - host.release_control() - return - else - if(contaminant > 0) - if(!luminosity) - SetLuminosity(2) - contaminant = max(contaminant - 0.3, 0) - else - SetLuminosity(0) - if(bruteloss || fireloss) - heal_overall_damage(heal_amt, heal_amt) - if(toxloss) - apply_damage(-(heal_amt/2), TOX) - //################### ABILITIES ###################// /datum/action/innate/borer icon_file = 'icons/mob/hud/actions_borer.dmi' @@ -405,6 +399,7 @@ action_icon_state = "borer_hiding_0" /datum/action/innate/borer/toggle_hide/action_activate() + if(!isborer(owner)) return FALSE var/mob/living/carbon/cortical_borer/B = owner B.hide_borer() @@ -434,6 +429,7 @@ action_icon_state = "borer_control" /datum/action/innate/borer/take_control/action_activate() + if(!isborer(owner)) return FALSE var/mob/living/carbon/cortical_borer/B = owner if(B.hibernating) to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) @@ -454,6 +450,7 @@ action_icon_state = "borer_leave" /datum/action/innate/borer/leave_body/action_activate() + if(!isborer(owner)) return FALSE var/mob/living/carbon/cortical_borer/B = owner if(B.hibernating) to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) @@ -465,6 +462,7 @@ action_icon_state = "borer_chems" /datum/action/innate/borer/make_chems/action_activate() + if(!isborer(owner)) return FALSE var/mob/living/carbon/cortical_borer/B = owner if(B.hibernating) to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) @@ -476,6 +474,7 @@ action_icon_state = "borer_scan" /datum/action/innate/borer/scan_chems/action_activate() + if(!isborer(owner)) return FALSE var/mob/living/carbon/cortical_borer/B = owner if(B.hibernating) to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) @@ -517,21 +516,3 @@ B.hibernate() button.overlays.Cut() button.overlays += image('icons/mob/hud/actions_borer.dmi', button, "borer_sleeping_[B.hibernating]") - -/mob/living/carbon/cortical_borer/MouseDrop(atom/over_object) - if(!CAN_PICKUP(usr, src)) - return ..() - var/mob/living/carbon/H = over_object - if(!istype(H) || !Adjacent(H) || H != usr) return ..() - - if(H.a_intent == INTENT_HELP) - get_scooped(H) - return - else - return ..() - -/mob/living/carbon/cortical_borer/get_scooped(mob/living/carbon/grabber) - if(stat != DEAD) - to_chat(grabber, SPAN_WARNING("You probably shouldn't pick that thing up while it still lives.")) - return - ..() diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 96df31acc7d5..fc48062c5b59 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -9,7 +9,7 @@ var/list/options = list("Communicating","Contaminant & Enzymes") if(!host) options += list("Infecting a host") - else if(controlling) + else if(borer_flags_status & BORER_STATUS_CONTROLLING) target = host options += list("Captive Host", "Releasing Control", "Reproducing") else if(isxeno(host)) @@ -23,9 +23,9 @@ switch(choice) if("Infecting a host") var/possible_targets = "" - if(infect_humans) possible_targets += "\nHumans" - if(infect_xenos) possible_targets += "\nXenos" - if(infect_yautja) possible_targets += "\nYautja" + if(borer_flags_targets & BORER_TARGET_HUMANS) possible_targets += "\nHumans" + if(borer_flags_targets & BORER_TARGET_XENOS) possible_targets += "\nXenos" + if(borer_flags_targets & BORER_TARGET_YAUTJA) possible_targets += "\nYautja" if(!possible_targets) possible_targets += "No one." help_message = "Infecting a host is the first major step for a borer to complete.\n\nThis is done by getting close to a potential host (This can be Human, Xeno or Yautja depending on settings controlled by admins) and clicking the Infest button in the top left of your screen.\n\nYour host will need to keep still for you to do this, and it's rare that they do so; for this reason you have Dominate Victim, which will allow you to temporarily stun a target.\n\nNote: Dominate is not sufficient to keep them down for 100% of the time it takes to infect however, so be careful with it.\n\nWhilst inside a host, and NOT in direct control, you can be detected by body scanners but otherwise are hidden from everyone but your host and other borers.\nYou can currently infect: [possible_targets]" if("Communicating") @@ -51,6 +51,19 @@ alert(target, help_message, choice, "Ok") //############# Physical Interaction Procs ############# +/mob/living/carbon/cortical_borer/proc/summon() + var/datum/emergency_call/custom/em_call = new() + em_call.name = real_name + em_call.mob_max = 1 + em_call.players_to_offer = list(src) + em_call.owner = null + em_call.ert_message = "A new Cortical Borer has been birthed!" + em_call.objectives = "Create enjoyable Roleplay. Do not kill your host. Do not take control unless granted permission or directed to by admins. Hivemind is :0 (That's Zero, not Oscar)" + + em_call.activate(announce = FALSE) + + message_admins("A new Cortical Borer has spawned at [get_area(loc)]") + /mob/living/carbon/cortical_borer/UnarmedAttack(atom/A) if(istype(A, /obj/structure/ladder)) A.attack_hand(src) @@ -60,21 +73,48 @@ /atom/proc/attack_borer(mob/living/carbon/cortical_borer/user) return +/mob/living/carbon/cortical_borer/MouseDrop(atom/over_object) + if(!CAN_PICKUP(usr, src)) + return ..() + var/mob/living/carbon/H = over_object + if(!istype(H) || !Adjacent(H) || H != usr) return ..() + + if(H.a_intent == INTENT_HELP) + get_scooped(H) + return + else + return ..() + +/mob/living/carbon/cortical_borer/get_scooped(mob/living/carbon/grabber) + if(stat != DEAD) + to_chat(grabber, SPAN_WARNING("You probably shouldn't pick that thing up while it still lives.")) + return + ..() //Brainslug scans the reagents in a target's bloodstream. /mob/living/carbon/human/attack_borer(mob/M) borerscan(M, src) +/mob/living/carbon/xenomorph/attack_borer(mob/M) + borerscan(M, src) /proc/borerscan(mob/living/user, mob/living/M) if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.reagents) - if(H.reagents.reagent_list.len) + var/mob/living/carbon/human/human_target = M + if(human_target.reagents) + if(human_target.reagents.reagent_list.len) to_chat(user, SPAN_XENONOTICE("Subject contains the following reagents:")) - for(var/datum/reagent/R in H.reagents.reagent_list) + for(var/datum/reagent/R in human_target.reagents.reagent_list) to_chat(user, "[R.overdose != 0 && R.volume >= R.overdose && !(R.flags & REAGENT_CANNOT_OVERDOSE) ? SPAN_WARNING("OD: ") : ""] [round(R.volume, 1)]u [R.name]") else to_chat(user, SPAN_XENONOTICE("Subject contains no reagents.")) + if(isxeno(M)) + var/mob/living/carbon/xenomorph/xeno_target = M + to_chat(user, SPAN_XENONOTICE("Subject status as follows:")) + var/health_perc = xeno_target.maxHealth / 100 + to_chat(user, SPAN_XENONOTICE("Subject is at [xeno_target.health / health_perc]% bio integrity.")) + if(xeno_target.plasma_max) + var/plasma_perc = xeno_target.plasma_max / 100 + to_chat(user, SPAN_XENONOTICE("Subject has [xeno_target.plasma_stored / plasma_perc]% bio plasma.")) //Brainslug scuttles under a door, same code as used by xeno larva. /obj/structure/machinery/door/airlock/attack_borer(mob/living/carbon/cortical_borer/M) @@ -168,11 +208,11 @@ return FALSE if(ishuman(target)) var/mob/living/carbon/human/human_target = target - if(isspecieshuman(human_target) && !infect_humans)//Can it infect humans? Normally, yes. + if(isspecieshuman(human_target) && !(borer_flags_targets & BORER_TARGET_HUMANS))//Can it infect humans? Normally, yes. return FALSE - else if(isspeciesyautja(human_target) && !infect_yautja)//Can it infect yautja? Normally, no. + else if(isspeciesyautja(human_target) && !(borer_flags_targets & BORER_TARGET_YAUTJA))//Can it infect yautja? Normally, no. return FALSE - if(isxeno(target) && !infect_xenos)//Can it infect xenos? Normally, no. + if(isxeno(target) && !(borer_flags_targets & BORER_TARGET_XENOS))//Can it infect xenos? Normally, no. return FALSE if(target.stat != DEAD && Adjacent(target) && !target.has_brain_worms()) return TRUE @@ -271,7 +311,7 @@ /mob/living/carbon/cortical_borer/proc/let_go() if(!host || !src || QDELETED(host) || QDELETED(src)) return FALSE - if(!leaving || controlling) + if(!leaving || borer_flags_status & BORER_STATUS_CONTROLLING) return FALSE if(stat) to_chat(src, SPAN_XENOWARNING("You cannot release a target in your current state.")) @@ -286,7 +326,7 @@ /mob/living/carbon/cortical_borer/proc/leave_host() if(!host) return FALSE - if(controlling) + if(borer_flags_status & BORER_STATUS_CONTROLLING) detach() give_new_actions(ACTION_SET_HOSTLESS) @@ -342,7 +382,7 @@ return TRUE /mob/living/carbon/cortical_borer/proc/assume_control() - if(!host || !src || controlling) + if(!host || !src || borer_flags_status & BORER_STATUS_CONTROLLING) return FALSE if(!bonding) return FALSE @@ -389,7 +429,7 @@ host.lastKnownIP = s2h_ip bonding = FALSE - controlling = TRUE + borer_flags_status |= BORER_STATUS_CONTROLLING give_new_actions(ACTION_SET_CONTROL) host.med_hud_set_status() @@ -401,7 +441,7 @@ //Captive mind reclaims their body. /mob/living/captive_brain/proc/return_control(mob/living/carbon/cortical_borer/B) - if(!B || !B.controlling || !resisting_control) + if(!B || !(B.borer_flags_status & BORER_STATUS_CONTROLLING) || !resisting_control) return FALSE B.host.adjustBrainLoss(rand(5,10)) to_chat(src, SPAN_HIGHDANGER("With an immense exertion of will, you regain control of your body!")) @@ -428,10 +468,10 @@ log_debug(EXCEPTION("Missing borer or missing host brain upon borer release."), src) /mob/living/carbon/cortical_borer/proc/detach() - if(!host || !controlling) + if(!host || !(borer_flags_status & BORER_STATUS_CONTROLLING)) return FALSE - controlling = FALSE + borer_flags_status &= ~BORER_STATUS_CONTROLLING reset_view(null) get_host_actions() @@ -470,7 +510,7 @@ if(!(host && loc == host)) log_debug("Borer ([key_name(src)]) called host_death without being inside a host!") return FALSE - if(controlling) + if(borer_flags_status & BORER_STATUS_CONTROLLING) detach() to_chat(src, SPAN_XENOHIGHDANGER("You release your proboscis and flee as the psychic shock of your host's death washes over you!")) if(perma) @@ -593,7 +633,7 @@ T.add_vomit_floor() B.contaminant = 0 var/repro = max(B.can_reproduce - 1, 0) - new /mob/living/carbon/cortical_borer(T, B.generation + 1, TRUE, repro, B.infect_humans, B.infect_xenos, B.infect_yautja) + new /mob/living/carbon/cortical_borer(T, B.generation + 1, TRUE, repro, B.borer_flags_targets) return TRUE else to_chat(src, SPAN_XENONOTICE("You need at least [BORER_LARVAE_COST] enzymes to reproduce!")) @@ -772,7 +812,7 @@ C = new test() break - if(!C || !host || controlling || !src || stat) + if(!C || !host || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) return FALSE var/datum/reagent/R = chemical_reagents_list[C.chem_id] if(enzymes < C.cost) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index d38f6cd34a8d..6ea25bef6443 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -138,7 +138,7 @@ . += "Evacuation: [eta_status]" var/mob/living/carbon/cortical_borer/B = has_brain_worms() - if(B && B.controlling) + if(B && (B.borer_flags_status & BORER_STATUS_CONTROLLING)) var/CR = "Yes" if(!B.can_reproduce) diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index d576a02d708c..aa1cab74d860 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -145,7 +145,7 @@ . += "Hive Orders: -" var/mob/living/carbon/cortical_borer/B = has_brain_worms() - if(B && B.controlling) + if(B && (B.borer_flags_status & BORER_STATUS_CONTROLLING)) var/CR = "Yes" if(!B.can_reproduce) diff --git a/code/modules/reagents/chemistry_properties/prop_positive.dm b/code/modules/reagents/chemistry_properties/prop_positive.dm index c0bd02f2762a..10f4c50bd264 100644 --- a/code/modules/reagents/chemistry_properties/prop_positive.dm +++ b/code/modules/reagents/chemistry_properties/prop_positive.dm @@ -471,7 +471,7 @@ M.apply_damage(potency, TOX) var/mob/living/carbon/cortical_borer/player_2 = M.has_brain_worms() if(player_2) - if(player_2.controlling) + if(player_2.borer_flags_status & BORER_STATUS_CONTROLLING) player_2.detach() to_chat(src, SPAN_HIGHDANGER("You relinquish control as the unknown chemical overwhelms you!")) diff --git a/code/modules/surgery/brainworm.dm b/code/modules/surgery/brainworm.dm index 3a379605e36b..7ad8223a0fc8 100644 --- a/code/modules/surgery/brainworm.dm +++ b/code/modules/surgery/brainworm.dm @@ -63,6 +63,7 @@ user.count_niche_stat(STATISTICS_NICHE_SURGERY_LARVA) to_chat(parasite, SPAN_HIGHDANGER("You are ripped forcibly from your host's head!")) parasite.leave_host() + parasite.apply_damage(30, BRUTE) log_interact(user, target, "[key_name(user)] removed a parasite from [key_name(target)]'s head with [tool ? "\the [tool]" : "their hands"], ending [surgery].") diff --git a/colonialmarines.dme b/colonialmarines.dme index a43815ecc94b..b52b2daa680c 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -33,6 +33,7 @@ #include "code\__DEFINES\atmospherics.dm" #include "code\__DEFINES\autolathe.dm" #include "code\__DEFINES\blood.dm" +#include "code\__DEFINES\borer_defines.dm" #include "code\__DEFINES\bsql.config.dm" #include "code\__DEFINES\bsql.dm" #include "code\__DEFINES\bullet_traits.dm" @@ -1359,7 +1360,6 @@ #include "code\modules\asset_cache\assets\tgui.dm" #include "code\modules\asset_cache\assets\vending.dm" #include "code\modules\asset_cache\transports\asset_transport.dm" -#include "code\modules\borer\_defines.dm" #include "code\modules\borer\borer.dm" #include "code\modules\borer\borer_chemicals.dm" #include "code\modules\borer\borer_html.dm" diff --git a/icons/mob/hud/actions_borer.dmi b/icons/mob/hud/actions_borer.dmi index d1098b87d803641b4ca6ee29871f2c6dec5717ae..cdf8d9617e138862e6531e4d9feeb99ab4041ada 100644 GIT binary patch literal 2693 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 literal 2187 zcmV;62z2*}P)C0001ZP)t-sz`(#! zIbbj%I$1zwVlP;HJZ~r*FgzVWNgqil7%U+WBLMZ=HmsP}mH^CV03>f>Hybe*3m7*b zJef1hNGng5Nr+1%QLIy%HX%DjAwFjc3Zw!8wo?G6tTx&80K?ZGmYXztS4((GOI27I zY;Pq0%w~mUX28I}vW^k-00001bW%=J06^y0W&i*H$$C^+bVOxyV{&P5bZKvH004NL zm6EXvgFp<1XYVNv-Aiq|b}346sIMSbjb1?SBsulJ4e1R_^iN59cqSV== zP%{vtclxR?hog!XY=T|G`J^HX*x9fJ4ko}_#!pW`Rc&G5SVavIuiaEdEtvtf`itc- zIU%}O<|8o&i1jjjcj!WJ8JU3J`tr$U@yB;QQ6bW!dB z#yvit0jZINe*BM;LAS~?{=Q?P^D=vX_Y1@+-nZ9j$_M}e2JA^hK~#90?VF2wqDl;a zWe18NcC>3*JBZNj<^3P=BohYb4(hgN&v(dftr|>zGMRy-&T6&DB7cP>KKb!|`c=Y6 z(lpDm;W>M7^@jXG{RJRjuh;390i;So0BKRI*F~8I3~cTM!0?i!A%GkrkQZ6lLA7C< zD&%0heZ*gnkK3(JfALQQ9)Jw}M*%1j)h!W7vmyS9zz0y~5P%ZKD2qGbu7gKBef&`Y zZ~)TvAjseV$mGvTDJkOm0T7;5w?$yRQvw7IKuS4){_|7@%;z90Hk&G#149Ic09blB z|J`nnq6l;Vn*1386h)p<%D4`y%?6UBoXQa|V5FKYxOEcz_VtLy&_10yDJ4hXUt; zGX$LDEb*=rPlv++5C-?pQc4S8r$xX80RMGfD9LLeaE3rmQ_y;H0K7k;29J4u{)O^< zD1!id2OvqaW1Y(kC}0}o_0c?FoCP>bGR`YI0^lE21lka%Yk4UcS7LaXY7t(^mB#=;0vEtQumBEpJ;NM)k^~w6EVAJ6axGfR ztFi|0;{jy^kgs$?(%Yixi?Yx)Fc61>rq9UdDDs64u*f2dEV9U7(;tAFt+DR-ivEBQ zP1AVv7Xa)J@SuTUeLouj?Tat~r~UvB7zo$*q(4mo2(mB20Ms9FZ@H%G`!NE|iJh7- z0NHPX02TEI`~b1~-W-Af!PPfpKLSAg0nY8)?y36T&H)hsAp1hF#sQGYUr~PmasW$@ zE9!f*f6#a$Am3}qKH!PQ2H=zfvOj>&f#8bz{?b1Zr2+9FzAD;t(4nUK?;#8i? z7reTnzE>eWo&5a+f@%cWmoG%41IY8QMgStXqP~{^O%v=N2+}J6BCwN?^RYj`JxwUA z?>PtW@Zgl!2_;^ZLj+EN28Ix$ePJi*s^Z{Z>kr^Ou!bO7-^&OH5$qo{0<@ZaoCn4b zRN&v}4*&rV132~lRR5p>|Au`aFo%FwR(}9uaz%M<_78+;>>&`1WglW7=fEP1EV9TVUsC@+ z%>VrT^?%!*JAAM2+OF-d{`~y_UDuxFn?39MbN~GSecN`OQuJMaGr)GM{_^WL@CxG7 zClLE{!V-d@82COPu&)jvrT>r5D9N9@Z3@J;#(#_+;2fKGq2;o;TNzX3tp!TIPniGynWV0vU-{BLb~jepuUi0F-_3z&!Tv2Y6#|3ZPRV@B(}=Kft|1 zz}S2LZib+}Y6$L4LU`w`eV56P*?7J_3GbYSOcJONv~ChkPs2MGA_P!lkjO!3ZT-|j z#O_&&nKAyDklpo5F)44m7?F2|bD(3L{C&&C$dqd?$Cr0uF_zMuzx95A-ocv!a4qHB z{R;p$>u1*YVZB#<#pf4UWRXP{`TFk%OagrM#pZtk5Z-?zX5^y%5N>hf=L+Je{coBCyN7Yg5R{_k?#*o1I!+R z@%-HgMD`!d0GO48ae&D82j&3GnTDqLW Date: Thu, 6 Apr 2023 20:39:14 +0100 Subject: [PATCH 08/52] Gen1 buff chems and gen1 fix --- code/modules/borer/borer.dm | 9 +++++++-- code/modules/borer/borer_chemicals.dm | 16 +++++++++++++++- code/modules/borer/borer_procs.dm | 19 +++++++++++-------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 832a96aa35f3..80240f9eff11 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -112,7 +112,7 @@ var/max_contaminant = 120 //Decreases through hibernation or reproduction. var/hibernating = FALSE //Usable inside a host, but not when controlling. Allows clearing of impurities. - var/mob/living/carbon/host // Human host for the brain worm. + var/mob/living/carbon/host // Carbon host for the brain worm. var/truename // Name used for brainworm-speak. var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. var/docile = FALSE // Anti-Parasite or Anti-Enzyme chemicals can stop borers from acting. @@ -173,8 +173,11 @@ can_reproduce = reproduction borer_flags_targets = new_targets give_new_actions(ACTION_SET_HOSTLESS) - //GrantBorerActions() GiveBorerHUD() + if(generation == 1) + maxHealth = maxHealth + (maxHealth / 2) + max_enzymes = max_enzymes + (max_enzymes / 2) + max_contaminant = max_contaminant + (max_contaminant / 2) if((!is_admin_level(z)) && ERT) summon() @@ -216,6 +219,8 @@ docile = FALSE if(!hibernating && (enzymes < max_enzymes)) enzymes++ + if(generation == 1) + enzymes++ if(contaminant > 0) if(hibernating) contaminant = max(contaminant -= 1, 0) diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index ddb4b775ff5f..09e03fff7567 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -103,9 +103,23 @@ chem_id = "antineurotoxin" desc = "A bioagent that counteracts neurotoxins." cost = 100 - category = BORER_CAT_PUNISH + category = BORER_CAT_STIM +/datum/borer_chem/human/chloralhydrate + chem_name = "Chloral Hydrate" + chem_id = "chloralhydrate" + desc = "A powerful sedative which causes near instant sleepiness, but can be deadly in large quantities." + cost = 125 + quantity = 5 + category = BORER_CAT_PUNISH +/datum/borer_chem/human/potassium_chlorophoride + chem_name = "Potassium Chlorophoride" + chem_id = "potassium_chlorophoride" + desc = "A powerful chemical based on Potassium Chloride that causes instant cardiac arrest." + cost = 250 + quantity = 3 + category = BORER_CAT_PUNISH //Yautja chemicals /datum/borer_chem/yautja/thwei diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index fc48062c5b59..f37b62af89fb 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -38,7 +38,7 @@ var/capability = "able" if(!can_reproduce) capability = "forbidden" else if((enzymes < BORER_LARVAE_COST)) capability = "unable" - help_message = "Reproduction will take [BORER_LARVAE_COST] enzymes and direct control of your host.\n\nWhen in direct control you can use the Reproduce ability to spit out a new borer.\nMake sure to do this in a safe place, the new borer will not have a player to start with.\n\nYou are currently [capability] to reproduce." + help_message = "Reproduction will take a minimum of [BORER_LARVAE_COST] enzymes and direct control of your host.\n\nWhen in direct control you can use the Reproduce ability to spit out a new borer.\nMake sure to do this in a safe place, the new borer will not have a player to start with.\n\nYou are currently [capability] to reproduce." if("Assuming Control") help_message = "Assuming control will put you in direct control of your host, acting as if you are their player.\n\nYour host will be disassociated with their body, and trapped in their own mind unable to speak to anyone but you.\nWhile in this state you are unable to make use of the hivemind.\n\nYour host can resist your control and regain their body however this can cause brain damage in humanoids.\nYou must assume control to reproduce.\n\nNote: Whilst in direct control of your host medical HUDs will detect you.\n\n\nIMPORTANT: While in direct control of a mob you MUST NOT perform antag actions unless you have permission from staff." if("Contaminant & Enzymes") @@ -628,7 +628,10 @@ if(B.enzymes >= BORER_LARVAE_COST) to_chat(src, SPAN_XENOWARNING("Your host twitches and quivers as you rapdly excrete a larva from your sluglike body.")) visible_message(SPAN_WARNING("[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!")) - B.enzymes = 0 + if(B.generation == 1) + B.enzymes -= BORER_LARVAE_COST + else + B.enzymes = 0 var/turf/T = get_turf(src) T.add_vomit_floor() B.contaminant = 0 @@ -675,14 +678,14 @@ var/chem = initial(C.chem_id) var/datum/reagent/R = chemical_reagents_list[chem] if(R) - content += "" + content += "" else for(var/datum in subtypesof(/datum/borer_chem/human)) var/datum/borer_chem/C = datum var/chem = initial(C.chem_id) var/datum/reagent/R = chemical_reagents_list[chem] if(R) - content += "" + content += "" content += "
[initial(C.quantity)] units of [R.name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

[initial(C.quantity)] units of [C.chem_name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

[initial(C.quantity)] units of [R.name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

[initial(C.quantity)] units of [C.chem_name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

" @@ -797,7 +800,7 @@ /mob/living/carbon/cortical_borer/Topic(href, href_list, hsrc) if(href_list["borer_use_chem"]) locate(href_list["src"]) - if(!istype(src, /mob/living/carbon/cortical_borer)) + if(!isborer(src)) return FALSE if(docile) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) @@ -816,13 +819,13 @@ return FALSE var/datum/reagent/R = chemical_reagents_list[C.chem_id] if(enzymes < C.cost) - to_chat(src, SPAN_XENOWARNING("You need [C.cost] enzymes stored to secrete [R.name]!")) + to_chat(src, SPAN_XENOWARNING("You need [C.cost] enzymes stored to secrete [C.chem_name]!")) return FALSE var/contamination = round(C.cost / 10) if(C.impure && ((contaminant + contamination) > max_contaminant)) - to_chat(src, SPAN_XENOWARNING("You are too contaminated to secrete [R.name]!")) + to_chat(src, SPAN_XENOWARNING("You are too contaminated to secrete [C.chem_name]!")) return FALSE - to_chat(src, SPAN_XENONOTICE("You squirt a measure of [R.name] from your reservoirs into [host]'s bloodstream.")) + to_chat(src, SPAN_XENONOTICE("You squirt a measure of [C.chem_name] from your reservoirs into [host]'s bloodstream.")) contaminant += contamination host.reagents.add_reagent(C.chem_id, C.quantity) enzymes -= C.cost From bfc2469eed7cdf98aa2a9065cc2be19a9318409f Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 6 Apr 2023 21:01:01 +0100 Subject: [PATCH 09/52] icon changes --- code/modules/borer/borer.dm | 10 +++++----- icons/mob/hud/actions_borer.dmi | Bin 2693 -> 3118 bytes 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 80240f9eff11..d180567d2a8d 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -385,7 +385,7 @@ /datum/action/innate/borer/talk_to_host name = "Converse with Host" - action_icon_state = "borer_whisper" + action_icon_state = "borer_talk" /datum/action/innate/borer/talk_to_host/action_activate() var/mob/living/carbon/cortical_borer/B = owner @@ -413,7 +413,7 @@ /datum/action/innate/borer/talk_to_borer name = "Converse with Borer" - action_icon_state = "borer_whisper" + action_icon_state = "borer_talk" /datum/action/innate/borer/talk_to_borer/action_activate() var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() @@ -422,7 +422,7 @@ /datum/action/innate/borer/talk_to_brain name = "Converse with Trapped Mind" - action_icon_state = "borer_whisper" + action_icon_state = "borer_talk" /datum/action/innate/borer/talk_to_brain/action_activate() var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() @@ -464,7 +464,7 @@ /datum/action/innate/borer/make_chems name = "Secrete Chemicals" - action_icon_state = "borer_chems" + action_icon_state = "borer_human_chems" /datum/action/innate/borer/make_chems/action_activate() if(!isborer(owner)) return FALSE @@ -476,7 +476,7 @@ /datum/action/innate/borer/scan_chems name = "Scan Chemicals" - action_icon_state = "borer_scan" + action_icon_state = "borer_human_scan" /datum/action/innate/borer/scan_chems/action_activate() if(!isborer(owner)) return FALSE diff --git a/icons/mob/hud/actions_borer.dmi b/icons/mob/hud/actions_borer.dmi index cdf8d9617e138862e6531e4d9feeb99ab4041ada..aab12b0b5b6aea52cf24f0f855d80e9fe5dba48f 100644 GIT binary patch delta 3063 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 FV1kMww#NVf delta 2635 zcmV-R3bggE7=;xjiBL{Q4GJ0x0000DNk~Le0001>0001>2m=5B0K5^G9{>OVc#$O{ zkxCu|ByVDoXdZuJFIcuy0GTt)rmQyE^#H@yAC{XmRahBpZzKsB+>QVM00DGTPE!Ct z=GbNc00ARfFDZ*Bkpc$}q_!ES>v42I9}6j6Jh+HKbzXhCfx3Q}Rx zc0vr?#u6mRN$Kkk80ukCMQCrf^4a{f zy2x!s6#{>1J;{Cr;|t8y)5kDx!$Y3V{!Emk%m_4EH0^o73&STmUMOiuRhCV!AaB8v zHH!L6Eop*=RCy_Ev+D|=nKK@@0NVj+vEM(|`A7V2_9Y7nZSwJJ8DL;lifk{LQ;5Tgo7~e=>hE>pzAECq)sh^mKxXmyYkXLXxM1J`jzJ|~; z2b&DKRc09CF>_FpU-CUaH-tk#-Dz9{xS6_0togTf<({9BkXLd$4G@;`5P|eLVFOplgv0$6yL=dF^x%@Nek74Rn$Dd_+o)7&aHVc$S+N;L-0QZN(AyWX2rT}6* zoea2f_(_(gheH}?Qvs=nrxw6BFk62GqYber3)vnjuut>JfFfR%R^$r=oJ2GZagC_@ zbIczA7>RfjAcFk_lZci%NDYAT9tsd=8Obex7X4AgQ%WKYAVU2l^_MpTAQxRCO$GVl z&0}sb2eW*nKFD)MA|8Hy8YzGcUqh$?OwvuO9`*d0n1h&qkB@^d2N62qfzz9ti1_Hk05gODK(oL!9NO3C3dq2aPn# zPUwl#6a2&P=_xZ-P}8U>RpO~qLE<>oQQl@Y2pA13m>rKI{|P_v(eZz19^wwG1k}Xq z0PULv(V#aQ&Hs~}j>q`pBNnr0j}MQ>Q|1q-ji)-mt|@ac+L-*OBb?vPpD=wOef)VQ zS$sU5#sI?kts74}@&15=9bw1M_kbU81f1lb=MU(LFkb$Ed=J=*r)~Tgz#d|6k&wXw zkg%a}ZuxmC(r;9u{h@ zNq+Z5;A#_hZzHZo`zIQ4kiIvE{^ta&&;N`iNiy6F%mL`wjQ9hhKF1V5qxsIkxd55a z=h%$^&HAD@;9hs#J7)zA`l2sjBJ{Z%0*Xp1>XRr{MPGCS zYV5CqKaDMCRb8LjZ=e=1l>x)j~d%&Lj#r*ZX5xW_a zzUVaGnfv-2^Vau9ZTa>3qSJKx9Bb!bFrZ6c46`L%c3OXJ`4{d>mp&f$uzTC$7s1`z zh|BKYh+TH;`;R^R;ebSA6aKt!+IGx;JH@0K09^iC1F}RK(*n5smm34N#}@=c0GA&v zzmQ9QBS4na<0lCQ04{%PHR5DI!(}C7huV-q1L*K~EeizHUYN7PSsD;%03CjATtCbM zE2x(?pgw=+^Cy}l=mWU?f-k*X@)_o!P8?$L_(-4ywEM*pxlGXy{p2+O_>^VDN>W6-dqzmxr z0Mz;U8kwda`n8$P6yuZZpa9zaH6iMUS(e|RQHOs6LVs!W!#r#bx&Y4(K%E~K3AC9D z0_I^AGy$F+fOfyA8k~qPmppWl=l~C_1>naY0J!}1R;Fun0>T0Lsa72R%%3*un1^33 zlFLLu=awIKCvd=aFL24$&8W#<&vAGF0w9}j!j z!ybPYZd!frhr>Uk{^!&O*F|wH@dRC!MOjqJ$@k z(o>by;sDn$w%0XT3rJBzT>|Y}{&?PU)?T7MC& zVO6b5(Qee=(DK%2-0!;e(iLy@Lm&LA$eI_rs7p9VP{+6LZny3GYrgjG+Ba=H;k`l= zFa7+QUGYN&3)!AYQEC9?+wTD)QQm%U)!zOKh(ve$uZ%BCBvj+2Kj&{Gq4;qQ{+54$ zr7WQq@R`^F-^pzN3HhqN`XwwDHN^0f-^CYSytrDf${f7+A|aemmatHUnB2R~a6mc6 zYd*-uAi;ebHR;ViTrlOrPIa7);2JJT$-ggavp^bylO4D6x~T1z_z`Xj0gc Date: Mon, 26 Feb 2024 22:59:14 +0000 Subject: [PATCH 10/52] fixes --- code/__DEFINES/chemistry.dm | 1 + code/modules/borer/borer.dm | 15 ++++++--------- code/modules/borer/borer_chemicals.dm | 8 ++++++++ code/modules/borer/borer_procs.dm | 10 +++++----- code/modules/mob/living/say.dm | 8 ++++---- .../mob/living/simple_animal/simple_animal.dm | 2 +- .../chemistry_properties/prop_positive.dm | 4 ++-- 7 files changed, 27 insertions(+), 21 deletions(-) diff --git a/code/__DEFINES/chemistry.dm b/code/__DEFINES/chemistry.dm index 078ccbdc2d94..cf586f06cd20 100644 --- a/code/__DEFINES/chemistry.dm +++ b/code/__DEFINES/chemistry.dm @@ -84,6 +84,7 @@ #define CHEM_EFFECT_HYPER_THROTTLE (1<<2) //universal understand but not speech #define CHEM_EFFECT_ORGAN_STASIS (1<<3) //peri stabiliser #define CHEM_EFFECT_NO_BLEEDING (1<<4) //replacement for quickclot +#define CHEM_EFFECT_ANTI_PARASITE (1<<5) //PROPERTY_ANTIPARASITIC //Blood plasma diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index d180567d2a8d..cebc39b731f4 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -194,7 +194,6 @@ /mob/living/carbon/cortical_borer/Life(delta_time) ..() - update_canmove() update_icons() var/heal_amt = 1 if(host) @@ -234,10 +233,11 @@ else if(contaminant > 0) if(!luminosity) - SetLuminosity(2) + set_light(2, 1, "#0f6b32") + set_light_on(TRUE) contaminant = max(contaminant - 0.3, 0) else - SetLuminosity(0) + set_light_on(FALSE) if(bruteloss || fireloss) heal_overall_damage(heal_amt, heal_amt) if(toxloss && !contaminant)//no clearing toxic impurities while contaminated. @@ -267,8 +267,6 @@ if(layer != initial(layer)) //Unhide layer = initial(layer) recalculate_move_delay = TRUE - if(!lying) - update_canmove() update_icons() /mob/living/carbon/cortical_borer/death() @@ -281,7 +279,6 @@ /mob/living/carbon/cortical_borer/rejuvenate() ..() update_icons() - update_canmove() SSmob.living_misc_mobs |= src /mob/living/carbon/cortical_borer/Destroy() @@ -297,8 +294,8 @@ if(stat == DEAD) icon_state = "Borer Dead" - else if(lying) - if((resting || sleeping) && (!knocked_down && !knocked_out && health > 0)) + else if(body_position == LYING_DOWN) + if(!HAS_TRAIT(src, TRAIT_INCAPACITATED) && !HAS_TRAIT(src, TRAIT_FLOORED)) icon_state = "Borer Resting" else icon_state = "Borer Stunned" @@ -306,7 +303,7 @@ icon_state = "Borer" /mob/living/carbon/cortical_borer/proc/GiveBorerHUD() - var/datum/mob_hud/H = huds[MOB_HUD_BRAINWORM] + var/datum/mob_hud/H = GLOB.huds[MOB_HUD_BRAINWORM] H.add_hud_to(src) /mob/living/carbon/cortical_borer/can_ventcrawl() diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index 09e03fff7567..65f75ae3f457 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -121,6 +121,14 @@ quantity = 3 category = BORER_CAT_PUNISH +/datum/borer_chem/human/death_powder + chem_name = "Living Death" + chem_id = "zombiepowder" + desc = "A strong neurotoxin that puts the subject into a death-like state." + cost = 300 + quantity = 1 + category = BORER_CAT_PUNISH + //Yautja chemicals /datum/borer_chem/yautja/thwei chem_name = "Thwei" diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index f37b62af89fb..538c377ef618 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -60,7 +60,7 @@ em_call.ert_message = "A new Cortical Borer has been birthed!" em_call.objectives = "Create enjoyable Roleplay. Do not kill your host. Do not take control unless granted permission or directed to by admins. Hivemind is :0 (That's Zero, not Oscar)" - em_call.activate(announce = FALSE) + em_call.activate(TRUE, FALSE) message_admins("A new Cortical Borer has spawned at [get_area(loc)]") @@ -676,16 +676,16 @@ for(var/datum in subtypesof(/datum/borer_chem/yautja)) var/datum/borer_chem/C = datum var/chem = initial(C.chem_id) - var/datum/reagent/R = chemical_reagents_list[chem] + var/datum/reagent/R = GLOB.chemical_reagents_list[chem] if(R) content += "[initial(C.quantity)] units of [C.chem_name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

" else for(var/datum in subtypesof(/datum/borer_chem/human)) var/datum/borer_chem/C = datum var/chem = initial(C.chem_id) - var/datum/reagent/R = chemical_reagents_list[chem] + var/datum/reagent/R = GLOB.chemical_reagents_list[chem] if(R) - content += "[initial(C.quantity)] units of [C.chem_name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

" + content += "[initial(C.quantity)] units of [initial(C.chem_name)] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

" content += "" @@ -817,7 +817,7 @@ if(!C || !host || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) return FALSE - var/datum/reagent/R = chemical_reagents_list[C.chem_id] + var/datum/reagent/R = GLOB.chemical_reagents_list[C.chem_id] if(enzymes < C.cost) to_chat(src, SPAN_XENOWARNING("You need [C.cost] enzymes stored to secrete [C.chem_name]!")) return FALSE diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index c1668f715262..a3d9e0407f89 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -121,16 +121,16 @@ GLOBAL_LIST_INIT(department_radio_keys, list( var/obj/item/clothing/worn_item = O if((O.flags_atom & USES_HEARING) || ((istype(worn_item) && worn_item.accessories))) listening_obj |= O + for(var/mob/inner_mob in M.contents) + listening |= inner_mob + for(var/mob/living/captive_brain/brain in inner_mob) + listening |= brain else if(istype(I, /obj/structure/surface)) var/obj/structure/surface/table = I hearturfs += table.locs[1] for(var/obj/O in table.contents) if(O.flags_atom & USES_HEARING) listening_obj |= O - for(var/mob/inner_mob in M.contents) - listening |= inner_mob - for(var/mob/living/captive_brain/brain in inner_mob) - listening |= brain else if(istype(I, /obj/)) var/obj/O = I hearturfs += O.locs[1] diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 6f1c16f3e958..63d363b04919 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -355,7 +355,7 @@ message = capitalize(trim_left(message)) - ..(message, speaking, verb, nolog = !ckey) //if the animal has a ckey then it will log the message + ..(message, null, verb, nolog = !ckey) //if the animal has a ckey then it will log the message /mob/living/simple_animal/on_immobilized_trait_gain(datum/source) . = ..() diff --git a/code/modules/reagents/chemistry_properties/prop_positive.dm b/code/modules/reagents/chemistry_properties/prop_positive.dm index 4d48f3a8043a..76fd411e70f6 100644 --- a/code/modules/reagents/chemistry_properties/prop_positive.dm +++ b/code/modules/reagents/chemistry_properties/prop_positive.dm @@ -500,8 +500,8 @@ else embryo.counter = embryo.per_stage_hugged_time - H.chem_effect_flags |= CHEM_EFFECT_ANTI_PARASITE - to_chat(H, SPAN_NOTICE("Your body feels warmer.")) + current_human.chem_effect_flags |= CHEM_EFFECT_ANTI_PARASITE + to_chat(current_human, SPAN_NOTICE("Your body feels warmer.")) /datum/chem_property/positive/antiparasitic/process_overdose(mob/living/M, potency = 1) M.apply_damage(potency, TOX) From 41eac4cd55ee19ac8572067da917b0563488c751 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Mon, 26 Feb 2024 23:02:40 +0000 Subject: [PATCH 11/52] icon conflicts --- icons/mob/hud/hud.dmi | Bin 19314 -> 19488 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/hud/hud.dmi b/icons/mob/hud/hud.dmi index 91c736f694fa598af4fe13959f91139b62de7b08..125b21e2d53b15b1cd51b07d688a0d5a7cacfeed 100644 GIT binary patch literal 19488 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 R4IBVs@O1TaS?83{1OS6FYJva& literal 19314 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

}`Qw_#44R+UX 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 Date: Mon, 26 Feb 2024 23:09:39 +0000 Subject: [PATCH 12/52] fix --- tgui/packages/tgui/interfaces/Orbit/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tgui/packages/tgui/interfaces/Orbit/index.tsx b/tgui/packages/tgui/interfaces/Orbit/index.tsx index 5e2664418643..1bf365c38a2b 100644 --- a/tgui/packages/tgui/interfaces/Orbit/index.tsx +++ b/tgui/packages/tgui/interfaces/Orbit/index.tsx @@ -139,7 +139,11 @@ const ObservableContent = (props) => { return ( - + From 2b1bdaad08e6e0b9152f17475faf2cd1beb2fa1e Mon Sep 17 00:00:00 2001 From: forest2001 Date: Mon, 26 Feb 2024 23:38:36 +0000 Subject: [PATCH 13/52] huds --- code/datums/mob_hud.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm index 3c649aa0c092..c92333f0241c 100644 --- a/code/datums/mob_hud.dm +++ b/code/datums/mob_hud.dm @@ -252,10 +252,10 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list( /mob/living/carbon/xenomorph/remove_from_all_mob_huds() for(var/datum/mob_hud/hud in GLOB.huds) - if(istype(hud, /datum/mob_hud/xeno)) + if(istype(hud, /datum/mob_hud/xeno) || istype(hud, /datum/mob_hud/brainworm)) hud.remove_from_hud(src) hud.remove_hud_from(src, src) - else if (istype(hud, /datum/mob_hud/xeno_infection) || istype(hud, /datum/mob_hud/brainworm)) + else if (istype(hud, /datum/mob_hud/xeno_infection)) hud.remove_hud_from(src, src) if (xeno_hostile_hud) xeno_hostile_hud = FALSE From f375b36dfb2b3e36434826ba02011cfdff33240f Mon Sep 17 00:00:00 2001 From: forest2001 Date: Mon, 26 Feb 2024 23:50:25 +0000 Subject: [PATCH 14/52] more hud fuckery --- code/modules/borer/borer.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index cebc39b731f4..bbadd9a66b1f 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -283,6 +283,8 @@ /mob/living/carbon/cortical_borer/Destroy() SSmob.living_misc_mobs -= src + var/datum/mob_hud/H = GLOB.huds[MOB_HUD_BRAINWORM] + H.remove_hud_from(src, src) if(host) for(var/datum/action/innate/borer/action in host.actions) action.hide_from(host) From c8e3af62152878c43452f3933f80f6a97cc0076a Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 27 Feb 2024 00:01:21 +0000 Subject: [PATCH 15/52] grrr --- code/modules/borer/borer.dm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index bbadd9a66b1f..664e0b8b28c2 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -283,12 +283,18 @@ /mob/living/carbon/cortical_borer/Destroy() SSmob.living_misc_mobs -= src - var/datum/mob_hud/H = GLOB.huds[MOB_HUD_BRAINWORM] - H.remove_hud_from(src, src) + + remove_from_all_mob_huds() if(host) for(var/datum/action/innate/borer/action in host.actions) action.hide_from(host) return ..() + +/mob/living/carbon/cortical_borer/remove_from_all_mob_huds() + for(var/datum/mob_hud/hud in GLOB.huds) + if(istype(hud, /datum/mob_hud/brainworm)) + hud.remove_from_hud(src) + hud.remove_hud_from(src, src) //###################################################// From 183b0cca21a90e1c89ba33cade1270aa7e3af92a Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 27 Feb 2024 00:24:38 +0000 Subject: [PATCH 16/52] I hate that this worked --- code/modules/borer/borer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 664e0b8b28c2..2f3c35400a5b 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -312,7 +312,7 @@ /mob/living/carbon/cortical_borer/proc/GiveBorerHUD() var/datum/mob_hud/H = GLOB.huds[MOB_HUD_BRAINWORM] - H.add_hud_to(src) + H.add_hud_to(src, src) /mob/living/carbon/cortical_borer/can_ventcrawl() return TRUE From 22aa13308feb2f982f1b36f6559dd963e29a80e8 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 27 Feb 2024 16:54:32 +0000 Subject: [PATCH 17/52] fixes and blurb --- code/modules/borer/borer.dm | 3 +- code/modules/borer/borer_chemicals.dm | 11 +--- code/modules/borer/borer_procs.dm | 60 ++++++++++--------- .../reagents/chemistry_reagents/other.dm | 2 +- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 2f3c35400a5b..a650628c32ac 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -176,6 +176,7 @@ GiveBorerHUD() if(generation == 1) maxHealth = maxHealth + (maxHealth / 2) + health = maxHealth max_enzymes = max_enzymes + (max_enzymes / 2) max_contaminant = max_contaminant + (max_contaminant / 2) if((!is_admin_level(z)) && ERT) @@ -202,7 +203,7 @@ var/mob/living/carbon/human/human_host if(ishuman(host)) human_host = host - if(((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && !human_host.reagents.has_reagent("benzyme")) || human_host.reagents.has_reagent("bcure")) + if((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && (!human_host.reagents.has_reagent("benzyme") || human_host.reagents.has_reagent("bcure"))) if(!docile) if(borer_flags_status & BORER_STATUS_CONTROLLING) to_chat(host, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index 65f75ae3f457..386a51b299e2 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -46,22 +46,15 @@ cost = 80 quantity = 5 -/datum/borer_chem/human/quickclot - chem_name = "Quickclot" - chem_id = "quickclot" - desc = "Vastly improves the blood's natural ability to coagulate and stop bleeding. Overdosing will result in severe tissue damage." - cost = 90 - quantity = 5 - /datum/borer_chem/human/iron - chem_id = "Iron" + chem_name = "Iron" chem_id = "iron" desc = "Promotes production of blood. Overdosing on iron is extremely toxic." cost = 20 impure = FALSE /datum/borer_chem/human/oxycodone - chem_id = "Oxycodone" + chem_name = "Oxycodone" chem_id = "oxycodone" desc = "An extremely strong painkiller." cost = 120 diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 538c377ef618..206e9172871f 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -47,8 +47,10 @@ help_message = "Hibernation is how you purify contaminants from your body, allowing you to use your enzymes more freely.\n\nYou can only hibernate whilst inside a host, and it renders you unable to act other than to speak to your host.\n\nYou can freely enter or leave hibernation by clicking the Hibernate button." if("Secreting Chemicals") help_message = "Whilst inside a humanoid host you can secrete chemicals to facilitate your relationship.\nThese can vary from helpful medications to harmful control measures.\n\nSecreting chemicals costs enzymes and if a chemical is impure will cause you to gain contaminant.\nIf you are at, or will go over, your contaminant capacity you will be unable to secrete chemicals.\nPure chemicals are chemicals native to borers such as Cortical Enzyme." - + if(!help_message) + return FALSE alert(target, help_message, choice, "Ok") + return TRUE //############# Physical Interaction Procs ############# /mob/living/carbon/cortical_borer/proc/summon() @@ -674,18 +676,18 @@ human_host = host if(isspeciesyautja(human_host)) for(var/datum in subtypesof(/datum/borer_chem/yautja)) - var/datum/borer_chem/C = datum - var/chem = initial(C.chem_id) + var/datum/borer_chem/current_chem = datum + var/chem = initial(current_chem.chem_id) var/datum/reagent/R = GLOB.chemical_reagents_list[chem] if(R) - content += "[initial(C.quantity)] units of [C.chem_name] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

" + content += "[current_chem.quantity] units of [current_chem.chem_name] ([current_chem.cost] Enzymes)

[current_chem.desc]

" else for(var/datum in subtypesof(/datum/borer_chem/human)) - var/datum/borer_chem/C = datum - var/chem = initial(C.chem_id) + var/datum/borer_chem/current_chem = datum + var/chem = current_chem.chem_id var/datum/reagent/R = GLOB.chemical_reagents_list[chem] if(R) - content += "[initial(C.quantity)] units of [initial(C.chem_name)] ([initial(C.cost)] Enzymes)

[initial(C.desc)]

" + content += "[current_chem.quantity] units of [current_chem.chem_name] ([current_chem.cost] Enzymes)

[current_chem.desc]

" content += "" @@ -724,6 +726,7 @@ var/say_string = (docile) ? "slurs" :"states" if(host) to_chat(host, SPAN_XENO("[truename] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) + show_blurb(host, 15, input, TRUE, "center", "center", COLOR_BROWN, null, null, 1) log_say("BORER: ([key_name(src)] to [key_name(host)]) [input]", src) to_chat(src, SPAN_XENO("[truename] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) for (var/mob/dead in GLOB.dead_mob_list) @@ -750,8 +753,8 @@ set desc = "Communicate mentally with your borer." - var/mob/living/carbon/cortical_borer/B = has_brain_worms() - if(!B) + var/mob/living/carbon/cortical_borer/borer = has_brain_worms() + if(!borer) return FALSE if(stat == DEAD) @@ -762,13 +765,14 @@ if(!input) return FALSE - to_chat(B, SPAN_XENO("[src.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) - log_say("BORER: ([key_name(src)] to [key_name(B)]) [input]", src) + to_chat(borer, SPAN_XENO("[src.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) + show_blurb(borer, 15, input, TRUE, "center", "center", COLOR_BROWN, null, null, 1) + log_say("BORER: ([key_name(src)] to [key_name(borer)]) [input]", src) to_chat(src, SPAN_XENO("[src.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) for (var/mob/dead in GLOB.dead_mob_list) - var/track_host = " (F)" + var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message(SPAN_BORER("BORER: ([name][track_host] to [B.truename]) says: [input]"), SHOW_MESSAGE_VISIBLE) + dead.show_message(SPAN_BORER("BORER: ([name][track_host] to [borer.truename]) says: [input]"), SHOW_MESSAGE_VISIBLE) return TRUE /mob/living/proc/trapped_mind_comm() @@ -807,32 +811,32 @@ return FALSE var/topic_chem = href_list["borer_use_chem"] - var/datum/borer_chem/C = null + var/datum/borer_chem/current_chem = null for(var/datum in typesof(/datum/borer_chem)) var/datum/borer_chem/test = datum - if(initial(test.chem_id) == topic_chem) - C = new test() + if(test.chem_id == topic_chem) + current_chem = new test() break - if(!C || !host || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) + if(!current_chem || !host || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) return FALSE - var/datum/reagent/R = GLOB.chemical_reagents_list[C.chem_id] - if(enzymes < C.cost) - to_chat(src, SPAN_XENOWARNING("You need [C.cost] enzymes stored to secrete [C.chem_name]!")) + var/datum/reagent/R = GLOB.chemical_reagents_list[current_chem.chem_id] + if(enzymes < current_chem.cost) + to_chat(src, SPAN_XENOWARNING("You need [current_chem.cost] enzymes stored to secrete [current_chem.chem_name]!")) return FALSE - var/contamination = round(C.cost / 10) - if(C.impure && ((contaminant + contamination) > max_contaminant)) - to_chat(src, SPAN_XENOWARNING("You are too contaminated to secrete [C.chem_name]!")) + var/contamination = round(current_chem.cost / 10) + if(current_chem.impure && ((contaminant + contamination) > max_contaminant)) + to_chat(src, SPAN_XENOWARNING("You are too contaminated to secrete [current_chem.chem_name]!")) return FALSE - to_chat(src, SPAN_XENONOTICE("You squirt a measure of [C.chem_name] from your reservoirs into [host]'s bloodstream.")) + to_chat(src, SPAN_XENONOTICE("You squirt a measure of [current_chem.chem_name] from your reservoirs into [host]'s bloodstream.")) contaminant += contamination - host.reagents.add_reagent(C.chem_id, C.quantity) - enzymes -= C.cost - log_interact(src, host, "[key_name(src)] has injected [C.quantity] units of [R.name] into their host, [key_name(host)]") + host.reagents.add_reagent(current_chem.chem_id, current_chem.quantity) + enzymes -= current_chem.cost + log_interact(src, host, "[key_name(src)] has injected [current_chem.quantity] units of [R.name] into their host, [key_name(host)]") // This is used because we use a static set of datums to determine what chems are available, // instead of a table or something. Thus, when we instance it, we can safely delete it - qdel(C) + qdel(current_chem) return TRUE ..() diff --git a/code/modules/reagents/chemistry_reagents/other.dm b/code/modules/reagents/chemistry_reagents/other.dm index 89bf04af5a5d..879fded1f180 100644 --- a/code/modules/reagents/chemistry_reagents/other.dm +++ b/code/modules/reagents/chemistry_reagents/other.dm @@ -1049,4 +1049,4 @@ overdose_critical = LOW_REAGENTS_OVERDOSE_CRITICAL chemclass = CHEM_CLASS_SPECIAL flags = REAGENT_SCANNABLE|REAGENT_NO_GENERATION - properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTITOXIN = 4) + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTITOXIN = 4, PROPERTY_ANTIPARASITIC = 2) From 1397c1eefb4bd26c1c27cc3ebf53e36f74d5c885 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 27 Feb 2024 17:12:17 +0000 Subject: [PATCH 18/52] name --- code/modules/borer/borer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index a650628c32ac..6fab1366d8c9 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -168,7 +168,7 @@ generation = gen add_language(LANGUAGE_BORER) var/mob_number = rand(1000,9999) - real_name = "Cortical Borer [mob_number]" + real_name = "Cortical Borer [borer_names[min(generation, borer_names.len)]] [mob_number]" truename = "[borer_names[min(generation, borer_names.len)]] [mob_number]" can_reproduce = reproduction borer_flags_targets = new_targets From 69b9e1fee36ce4b0b94e66a1149c39f5401f2e96 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 27 Feb 2024 17:36:53 +0000 Subject: [PATCH 19/52] death --- code/modules/borer/borer_procs.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 206e9172871f..fe8a769d3bea 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -15,7 +15,7 @@ else if(isxeno(host)) options += list("Assuming Control","Hibernation","Reproducing") else - options += list("Assuming Control","Hibernation","Secreting Chemicals","Reproducing") + options += list("Assuming Control","Hibernation","Secreting Chemicals","Reproducing", "Host Death") var/choice = tgui_input_list(target, "What would you like help with?", "Help", options, 20 SECONDS) @@ -47,6 +47,8 @@ help_message = "Hibernation is how you purify contaminants from your body, allowing you to use your enzymes more freely.\n\nYou can only hibernate whilst inside a host, and it renders you unable to act other than to speak to your host.\n\nYou can freely enter or leave hibernation by clicking the Hibernate button." if("Secreting Chemicals") help_message = "Whilst inside a humanoid host you can secrete chemicals to facilitate your relationship.\nThese can vary from helpful medications to harmful control measures.\n\nSecreting chemicals costs enzymes and if a chemical is impure will cause you to gain contaminant.\nIf you are at, or will go over, your contaminant capacity you will be unable to secrete chemicals.\nPure chemicals are chemicals native to borers such as Cortical Enzyme." + if("Host Death") + help_message = "Upon the death of your host you will be forced to release direct control (if you are currently in control), but otherwise will be largely unaffected. If your host becomes permanently unreviavable however, you will be ejected from their corpse." if(!help_message) return FALSE alert(target, help_message, choice, "Ok") From 7f0ceca7bbe7b6b5e94d768dff0a72f3d1860b9f Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 27 Feb 2024 18:02:25 +0000 Subject: [PATCH 20/52] broadcast --- code/modules/borer/borer.dm | 6 ++++++ code/modules/borer/borer_procs.dm | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 6fab1366d8c9..f02430e450e8 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -1,3 +1,5 @@ +GLOBAL_LIST_EMPTY(living_borers) + /mob/living/captive_brain name = "captive mind" real_name = "captive mind" @@ -181,6 +183,7 @@ max_contaminant = max_contaminant + (max_contaminant / 2) if((!is_admin_level(z)) && ERT) summon() + GLOB.living_borers += src /mob/living/carbon/cortical_borer/initialize_pass_flags(datum/pass_flags_container/PF) ..() @@ -274,6 +277,7 @@ var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] c_link.broadcast(src, null, src.truename, TRUE) SSmob.living_misc_mobs -= src + GLOB.living_borers -= src leave_host() . = ..() @@ -281,9 +285,11 @@ ..() update_icons() SSmob.living_misc_mobs |= src + GLOB.living_borers += src /mob/living/carbon/cortical_borer/Destroy() SSmob.living_misc_mobs -= src + GLOB.living_borers -= src remove_from_all_mob_huds() if(host) diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index fe8a769d3bea..9477ea2a7db6 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -439,6 +439,8 @@ host.med_hud_set_status() host.special_mob = TRUE + GLOB.living_borers += host + if(src && !src.key) src.key = "@[borer_key]" return TRUE @@ -484,6 +486,7 @@ if(host_brain) log_interact(host, src, "Borer: [key_name(host)] Took control back") host.special_mob = FALSE + GLOB.living_borers -= host // host -> self var/h2s_id = host.computer_id var/h2s_ip= host.lastKnownIP @@ -842,3 +845,31 @@ qdel(current_chem) return TRUE ..() + + + +/client/proc/borer_broadcast(msg as text) + set category = "Admin.Factions" + set name = "Borer Impulse" + + if(!src.admin_holder || !(admin_holder.rights & R_MOD)) + to_chat(src, "Only staff members may talk on this channel.") + return + + msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) + + if(!msg) + return + + message_admins("Borer Impulse: [key_name(src)] : [msg]") + + msg = process_chat_markup(msg, list("*")) + + for(var/mob/living/cur_mob in GLOB.living_borers) + if(cur_mob.client) // Send to xenos who are non-staff + to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [msg]")) + + for(var/mob/dead/observer/cur_mob in GLOB.observer_list) + if(cur_mob.client) // Send to observers who are non-staff + to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [src.key]([src.admin_holder.rank]): [msg]")) + From da4ed7b606b1af6b700fa8a9bc755948912f170b Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 27 Feb 2024 18:03:19 +0000 Subject: [PATCH 21/52] errr. usable broadcast --- code/modules/admin/admin_verbs.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index d27e07329a94..116bd5360f23 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -139,6 +139,7 @@ GLOBAL_LIST_INIT(admin_verbs_minor_event, list( /client/proc/admin_biohazard_alert, /client/proc/toggle_hardcore_perma, /client/proc/toggle_bypass_joe_restriction, + /client/proc/borer_broadcast, )) GLOBAL_LIST_INIT(admin_verbs_major_event, list( From 2a2e9247f5fdba997f0667c7467f8b8f3247acaa Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 29 Feb 2024 00:24:12 +0000 Subject: [PATCH 22/52] generations --- code/modules/borer/borer.dm | 35 +++++++++------- code/modules/borer/borer_chemicals.dm | 2 +- code/modules/borer/borer_procs.dm | 40 ++++++++++--------- code/modules/mob/dead/observer/orbit.dm | 2 +- code/modules/mob/language/languages.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 2 +- .../mob/living/carbon/xenomorph/XenoProcs.dm | 2 +- 7 files changed, 47 insertions(+), 38 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index f02430e450e8..226e7bf671d0 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -6,6 +6,8 @@ GLOBAL_LIST_EMPTY(living_borers) icon = 'icons/obj/items/organs.dmi' icon_state = "xenobrain" + special_mob = TRUE //shows up in own observe category + /// Whether or not the brain is mid-resisting control. var/resisting_control = FALSE @@ -34,7 +36,7 @@ GLOBAL_LIST_EMPTY(living_borers) for (var/mob/dead in GLOB.dead_mob_list) var/track_borer = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message(SPAN_BORER("BORER: ([name] (trapped mind) to [B.truename][track_borer]) whispers: [message]"), SHOW_MESSAGE_VISIBLE) + dead.show_message(SPAN_BORER("BORER: ([name] (trapped mind) to [B.real_name][track_borer]) whispers: [message]"), SHOW_MESSAGE_VISIBLE) /mob/living/captive_brain/say_understands(mob/other, datum/language/speaking = null) var/mob/living/carbon/cortical_borer/B = loc @@ -97,6 +99,7 @@ GLOBAL_LIST_EMPTY(living_borers) universal_understand = TRUE holder_type = /obj/item/holder/borer + special_mob = TRUE //shows up in own observe category var/generation = 1 var/stealthy = FALSE @@ -109,13 +112,13 @@ GLOBAL_LIST_EMPTY(living_borers) var/attempting_to_dominate = FALSE // To prevent people from spam opening the Dominate Victim input var/enzymes = 10 // Enzymes used for chemical injection. + var/enzyme_rate = 1 // Rate of increase for enzymes per life tick. Primary generation double. var/max_enzymes = 500 var/contaminant = 0 //Contaminant builds up on enzyme usage, roughly proportionate to cost of use. var/max_contaminant = 120 //Decreases through hibernation or reproduction. var/hibernating = FALSE //Usable inside a host, but not when controlling. Allows clearing of impurities. var/mob/living/carbon/host // Carbon host for the brain worm. - var/truename // Name used for brainworm-speak. var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. var/docile = FALSE // Anti-Parasite or Anti-Enzyme chemicals can stop borers from acting. var/bonding = FALSE @@ -163,24 +166,27 @@ GLOBAL_LIST_EMPTY(living_borers) /datum/action/innate/borer/torment, ) + var/list/ancestry = list() + var/list/offspring = list() + //################### INIT & LIFE ###################// -/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0, new_targets = BORER_TARGET_HUMANS) +/mob/living/carbon/cortical_borer/New(atom/newloc, gen=1, ERT = FALSE, reproduction = 0, new_targets = BORER_TARGET_HUMANS, ancestors = list()) ..(newloc) SSmob.living_misc_mobs += src generation = gen add_language(LANGUAGE_BORER) var/mob_number = rand(1000,9999) - real_name = "Cortical Borer [borer_names[min(generation, borer_names.len)]] [mob_number]" - truename = "[borer_names[min(generation, borer_names.len)]] [mob_number]" + name = "Cortical Borer ([mob_number])" + real_name = "[borer_names[min(generation, borer_names.len)]] [mob_number]" can_reproduce = reproduction borer_flags_targets = new_targets give_new_actions(ACTION_SET_HOSTLESS) GiveBorerHUD() - if(generation == 1) - maxHealth = maxHealth + (maxHealth / 2) + if(generation <= 1) + maxHealth = maxHealth * 1.5 health = maxHealth - max_enzymes = max_enzymes + (max_enzymes / 2) - max_contaminant = max_contaminant + (max_contaminant / 2) + max_enzymes = max_enzymes * 1.5 + max_contaminant = max_contaminant * 1.5 if((!is_admin_level(z)) && ERT) summon() GLOB.living_borers += src @@ -221,9 +227,10 @@ GLOBAL_LIST_EMPTY(living_borers) to_chat(src, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) docile = FALSE if(!hibernating && (enzymes < max_enzymes)) - enzymes++ - if(generation == 1) - enzymes++ + var/increase = enzyme_rate + if(generation <= 1) + increase = enzyme_rate * 2 + enzymes = min(enzymes + increase, max_enzymes) if(contaminant > 0) if(hibernating) contaminant = max(contaminant -= 1, 0) @@ -275,7 +282,7 @@ GLOBAL_LIST_EMPTY(living_borers) /mob/living/carbon/cortical_borer/death() var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] - c_link.broadcast(src, null, src.truename, TRUE) + c_link.broadcast(src, null, real_name, TRUE) SSmob.living_misc_mobs -= src GLOB.living_borers -= src leave_host() @@ -341,7 +348,7 @@ GLOBAL_LIST_EMPTY(living_borers) . += "" . += "Borer:" - . += "Name: [truename]" + . += "Name: [real_name]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(enzymes)]/[round(max_enzymes)]" . += "Contaminant: [round(contaminant)]/[round(max_contaminant)]" diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index 386a51b299e2..ca8d81821a0a 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -119,7 +119,7 @@ chem_id = "zombiepowder" desc = "A strong neurotoxin that puts the subject into a death-like state." cost = 300 - quantity = 1 + quantity = 2 category = BORER_CAT_PUNISH //Yautja chemicals diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 9477ea2a7db6..0bba38516061 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -627,23 +627,25 @@ set name = "Reproduce" set desc = "Spawn a new borer." - var/mob/living/carbon/cortical_borer/B = has_brain_worms() + var/mob/living/carbon/cortical_borer/brainworm = has_brain_worms() - if(!B) + if(!brainworm) return FALSE - if(B.can_reproduce) - if(B.enzymes >= BORER_LARVAE_COST) + if(brainworm.can_reproduce) + if(brainworm.enzymes >= BORER_LARVAE_COST) to_chat(src, SPAN_XENOWARNING("Your host twitches and quivers as you rapdly excrete a larva from your sluglike body.")) visible_message(SPAN_WARNING("[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!")) - if(B.generation == 1) - B.enzymes -= BORER_LARVAE_COST + if(brainworm.generation <= 1) + brainworm.enzymes -= BORER_LARVAE_COST else - B.enzymes = 0 + brainworm.enzymes = 0 var/turf/T = get_turf(src) T.add_vomit_floor() - B.contaminant = 0 - var/repro = max(B.can_reproduce - 1, 0) - new /mob/living/carbon/cortical_borer(T, B.generation + 1, TRUE, repro, B.borer_flags_targets) + brainworm.contaminant = 0 + var/repro = max(brainworm.can_reproduce - 1, 0) + var/ancestors = (brainworm.ancestry += real_name) + var/mob/living/carbon/cortical_borer/birthed = new /mob/living/carbon/cortical_borer(T, brainworm.generation + 1, TRUE, repro, brainworm.borer_flags_targets, ancestors) + brainworm.offspring += birthed.real_name return TRUE else to_chat(src, SPAN_XENONOTICE("You need at least [BORER_LARVAE_COST] enzymes to reproduce!")) @@ -730,14 +732,14 @@ if(src && !QDELETED(src) && !QDELETED(host)) var/say_string = (docile) ? "slurs" :"states" if(host) - to_chat(host, SPAN_XENO("[truename] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) + to_chat(host, SPAN_XENO("[real_name] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) show_blurb(host, 15, input, TRUE, "center", "center", COLOR_BROWN, null, null, 1) log_say("BORER: ([key_name(src)] to [key_name(host)]) [input]", src) - to_chat(src, SPAN_XENO("[truename] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) + to_chat(src, SPAN_XENO("[real_name] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) for (var/mob/dead in GLOB.dead_mob_list) var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message(SPAN_BORER("BORER: ([truename] to [host.real_name][track_host]) [say_string]: [input]"), SHOW_MESSAGE_VISIBLE) + dead.show_message(SPAN_BORER("BORER: ([real_name] to [host.real_name][track_host]) [say_string]: [input]"), SHOW_MESSAGE_VISIBLE) return TRUE /mob/living/carbon/cortical_borer/verb/toggle_silence_inside_host() @@ -777,7 +779,7 @@ for (var/mob/dead in GLOB.dead_mob_list) var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message(SPAN_BORER("BORER: ([name][track_host] to [borer.truename]) says: [input]"), SHOW_MESSAGE_VISIBLE) + dead.show_message(SPAN_BORER("BORER: ([name][track_host] to [borer.real_name]) says: [input]"), SHOW_MESSAGE_VISIBLE) return TRUE /mob/living/proc/trapped_mind_comm() @@ -794,13 +796,13 @@ if(!input) return FALSE - to_chat(CB, SPAN_XENO("[B.truename] says: [input]"), type = MESSAGE_TYPE_RADIO) + to_chat(CB, SPAN_XENO("[B.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) log_say("BORER: ([key_name(src)] to [key_name(CB)]) [input]", B) - to_chat(src, SPAN_XENO("[B.truename] says: [input]"), type = MESSAGE_TYPE_RADIO) + to_chat(src, SPAN_XENO("[B.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) for (var/mob/dead in GLOB.dead_mob_list) var/track_borer = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message(SPAN_BORER("BORER: ([B.truename][track_borer] to [real_name] (trapped mind)) says: [input]"), SHOW_MESSAGE_VISIBLE) + dead.show_message(SPAN_BORER("BORER: ([B.real_name][track_borer] to [real_name] (trapped mind)) says: [input]"), SHOW_MESSAGE_VISIBLE) return TRUE @@ -866,10 +868,10 @@ msg = process_chat_markup(msg, list("*")) for(var/mob/living/cur_mob in GLOB.living_borers) - if(cur_mob.client) // Send to xenos who are non-staff + if(cur_mob.client) // Send to borers to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [msg]")) for(var/mob/dead/observer/cur_mob in GLOB.observer_list) - if(cur_mob.client) // Send to observers who are non-staff + if(cur_mob.client) // Send to observers to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [src.key]([src.admin_holder.rank]): [msg]")) diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index 37b087d02db4..2488d9c96364 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -113,7 +113,7 @@ var/mob/living/player = M serialized["health"] = Floor(player.health / player.maxHealth * 100) - if(isborer(player) || iscaptivemind(player) || player.special_mob) + if(player.special_mob) special_mobs += list(serialized) if(isxeno(player)) diff --git a/code/modules/mob/language/languages.dm b/code/modules/mob/language/languages.dm index a550f5d01ed8..bc7fa0a8eeda 100644 --- a/code/modules/mob/language/languages.dm +++ b/code/modules/mob/language/languages.dm @@ -224,7 +224,7 @@ else if(speaker.has_brain_worms()) B = speaker.has_brain_worms() if(B) - speaker_mask = B.truename + speaker_mask = B.real_name if(!speaker_mask) speaker_mask = speaker.real_name diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 897a9dc81bbb..3c495851f62b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -143,7 +143,7 @@ . += "" . += "Borer:" - . += "Name: [B.truename]" + . += "Name: [B.real_name]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" . += "Health: [B.health]/[B.maxHealth]" diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index 064bee497d10..5d62bb50b0b0 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -156,7 +156,7 @@ . += "" . += "Borer:" - . += "Name: [B.truename]" + . += "Name: [B.real_name]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" . += "Health: [B.health]/[B.maxHealth]" From 815d5d489214b1769918220af7600467bfec5a0e Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 29 Feb 2024 00:52:00 +0000 Subject: [PATCH 23/52] sentries and vents --- code/modules/defenses/sentry.dm | 3 +++ code/modules/mob/living/living_defines.dm | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/code/modules/defenses/sentry.dm b/code/modules/defenses/sentry.dm index bfb44a38a6a5..bd04cbcccf11 100644 --- a/code/modules/defenses/sentry.dm +++ b/code/modules/defenses/sentry.dm @@ -87,6 +87,9 @@ if(!target && targets.len) target = pick(targets) + if(ismob(target.loc)) //Check to prevent certain issues with mobs-in-mobs being shot at, or attempt to be. + targets -= target + target = pick(targets) get_target(target) return TRUE diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 76ed9158b3a1..58dbea746e3c 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -85,7 +85,9 @@ /obj/item/device/radio, /obj/structure/machinery/camera, /obj/limb, - /obj/item/alien_embryo + /obj/item/alien_embryo, + /mob/living/carbon/cortical_borer, + /mob/living/captive_brain ) //blood.dm ///How much blood the mob has From 1f8f35ab10b3ab22efb40bcb8cbd7f8619921cd2 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 29 Feb 2024 10:34:21 +0000 Subject: [PATCH 24/52] liight --- code/modules/borer/borer.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 226e7bf671d0..58b395af3b38 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -207,6 +207,7 @@ GLOBAL_LIST_EMPTY(living_borers) update_icons() var/heal_amt = 1 if(host) + set_light_on(FALSE) heal_amt = 3 if(!stat && host.stat != DEAD) var/mob/living/carbon/human/human_host From 744a392fba551e86203a4b242a3f53c55b4f496b Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 29 Feb 2024 14:00:17 +0000 Subject: [PATCH 25/52] status --- code/modules/borer/borer.dm | 6 +++++- code/modules/mob/living/carbon/human/human.dm | 3 ++- code/modules/mob/living/carbon/xenomorph/XenoProcs.dm | 2 +- code/modules/mob/living/carbon/xenomorph/attack_alien.dm | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 58b395af3b38..c1258f8bd347 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -346,9 +346,12 @@ GLOBAL_LIST_EMPTY(living_borers) CR = "Forbidden" else if((enzymes < BORER_LARVAE_COST)) CR = "No" + var/bore_status = "AWAKE" + if(hibernating) + bore_status = "HIBERNATING" . += "" - . += "Borer:" + . += "Borer: [bore_status]" . += "Name: [real_name]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(enzymes)]/[round(max_enzymes)]" @@ -361,6 +364,7 @@ GLOBAL_LIST_EMPTY(living_borers) . += "Host Integrity: [host.health / health_perc]%" if(ishuman(host)) . += "Host Brain Damage: [host.brainloss]%" + . += "Host Blood Level: [host.blood_volume / 5.6]%" else if(isxeno(host)) var/mob/living/carbon/xenomorph/xeno_host = host if(xeno_host.plasma_max) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 3c495851f62b..0094e5e39368 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -142,7 +142,7 @@ CR = "No" . += "" - . += "Borer:" + . += "Borer: CONTROLLING" . += "Name: [B.real_name]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" @@ -150,6 +150,7 @@ . += "Injuries: Brute:[round(B.getBruteLoss())] Burn:[round(B.getFireLoss())] Toxin:[round(B.getToxLoss())]" . += "" . += "Host Brain Damage: [brainloss]/100" + . += "Host Blood Level: [blood_volume / 5.6]%" /mob/living/carbon/human/ex_act(severity, direction, datum/cause_data/cause_data) diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index 5d62bb50b0b0..4f46eeb22ff8 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -155,7 +155,7 @@ CR = "No" . += "" - . += "Borer:" + . += "Borer: CONTROLLING" . += "Name: [B.real_name]" . += "Can Reproduce: [CR]" . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" diff --git a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm index 9f42f8ae8928..25e06d81b2ab 100644 --- a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm +++ b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm @@ -50,7 +50,7 @@ if(M.behavior_delegate && M.behavior_delegate.handle_slash(src)) return XENO_NO_DELAY_ACTION - if(stat == DEAD) + if(stat == DEAD || (status_flags & FAKEDEATH)) to_chat(M, SPAN_WARNING("[src] is dead, why would we want to touch it?")) return XENO_NO_DELAY_ACTION From 9f419cd2de161a4b959463f9d45153ebdd9f5bb9 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 29 Feb 2024 16:23:16 +0000 Subject: [PATCH 26/52] hud --- code/datums/mob_hud.dm | 22 +++++++++++++++++----- icons/mob/hud/hud.dmi | Bin 19488 -> 19783 bytes 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm index c92333f0241c..52eccdb65b31 100644 --- a/code/datums/mob_hud.dm +++ b/code/datums/mob_hud.dm @@ -309,7 +309,13 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list( holder2.icon_state = null if(has_brain_worms()) - holder2.icon_state = "hudbrainwormhost" + var/worm_icon = "hudbrainwormhost" + switch(borer.generation) + if(0) + worm_icon = "hudbrainwormhostb" + if(1) + worm_icon = "hudbrainwormhostg" + holder2.icon_state = worm_icon holder2.pixel_x = 9 holder2.pixel_y = -8 @@ -484,11 +490,17 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list( return - var/mob/living/carbon/cortical_borer/B = has_brain_worms() + var/mob/living/carbon/cortical_borer/brainworm = has_brain_worms() holder5.icon_state = null - if(B) - holder5.icon_state = "hudbrainwormhost" - if(B.borer_flags_status & BORER_STATUS_CONTROLLING) + if(brainworm) + var/worm_icon = "hudbrainwormhost" + switch(brainworm.generation) + if(0) + worm_icon = "hudbrainwormhostb" + if(1) + worm_icon = "hudbrainwormhostg" + holder5.icon_state = worm_icon + if(brainworm.borer_flags_status & BORER_STATUS_CONTROLLING) holder.icon_state = "hudbrainworm" if(!holder2_set) holder2.icon_state = "hudbrainworm" diff --git a/icons/mob/hud/hud.dmi b/icons/mob/hud/hud.dmi index 125b21e2d53b15b1cd51b07d688a0d5a7cacfeed..741a2f94bd9509fa087fddb6106d95d53b25b1c9 100644 GIT binary patch literal 19783 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 QaQKVC)78&qol`;+06Kucpa1{> literal 19488 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 R4IBVs@O1TaS?83{1OS6FYJva& From d77d5c6e2f29d649ef88567c5dc5c6b3265a6d06 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 29 Feb 2024 16:33:11 +0000 Subject: [PATCH 27/52] death fix --- code/modules/borer/borer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index c1258f8bd347..212390db97af 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -283,7 +283,7 @@ GLOBAL_LIST_EMPTY(living_borers) /mob/living/carbon/cortical_borer/death() var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] - c_link.broadcast(src, null, real_name, TRUE) + c_link.broadcast(src, "Has Died", real_name, TRUE) SSmob.living_misc_mobs -= src GLOB.living_borers -= src leave_host() From 697668cd2f65434081729c59aa2ec6ef60187aa7 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sat, 2 Mar 2024 18:31:15 +0000 Subject: [PATCH 28/52] crit fix --- code/modules/borer/borer.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 212390db97af..656c6a8992c0 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -268,6 +268,8 @@ GLOBAL_LIST_EMPTY(living_borers) return else if(health <= 0) //in crit handle_crit() + else if(health >= 1) + set_stat(CONSCIOUS) /mob/living/carbon/cortical_borer/proc/handle_crit() if(stat == DEAD || gibbing) From d30b6cc5165a4c8821796a6d76b2740e860a5ec6 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sat, 2 Mar 2024 19:49:03 +0000 Subject: [PATCH 29/52] Lighting and admin infect --- code/modules/borer/borer.dm | 3 ++- code/modules/borer/borer_procs.dm | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 656c6a8992c0..0762e99f5b34 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -94,12 +94,13 @@ GLOBAL_LIST_EMPTY(living_borers) density = 0 pass_flags = PASS_FLAGS_CRAWLER mob_size = MOB_SIZE_SMALL - faction = list("creature") + faction = "Cortical" hud_possible = list(HEALTH_HUD,STATUS_HUD) universal_understand = TRUE holder_type = /obj/item/holder/borer special_mob = TRUE //shows up in own observe category + lighting_alpha = 200 var/generation = 1 var/stealthy = FALSE diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 0bba38516061..d293a2e68bc3 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -875,3 +875,6 @@ if(cur_mob.client) // Send to observers to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [src.key]([src.admin_holder.rank]): [msg]")) +/mob/living/carbon/human/proc/make_borer_host(worm_generation = 1, worm_repro = 1) + var/mob/living/carbon/cortical_borer/birthed = new /mob/living/carbon/cortical_borer(src, worm_generation, TRUE, worm_repro) + birthed.perform_infestation(src) From c423d90f6bff4be978b138da90dbcbfe41021084 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sat, 2 Mar 2024 19:50:17 +0000 Subject: [PATCH 30/52] LOGS --- code/modules/borer/borer_procs.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index d293a2e68bc3..385620593228 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -876,5 +876,9 @@ to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [src.key]([src.admin_holder.rank]): [msg]")) /mob/living/carbon/human/proc/make_borer_host(worm_generation = 1, worm_repro = 1) + if(has_brain_worms()) + return FALSE var/mob/living/carbon/cortical_borer/birthed = new /mob/living/carbon/cortical_borer(src, worm_generation, TRUE, worm_repro) birthed.perform_infestation(src) + log_admin("[key_name(src)] was infected with a Cortical Borer by proccall.") + return TRUE From e73605e062ae4cb21faef6e80a3448e6e2c2b11e Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sun, 3 Mar 2024 02:46:19 +0000 Subject: [PATCH 31/52] sentry fix, death silence and chem tweaks --- code/modules/borer/borer.dm | 16 ++++++++-- code/modules/borer/borer_chemicals.dm | 32 +++++++++++++++---- code/modules/borer/borer_procs.dm | 26 +++++++++------ code/modules/defenses/sentry.dm | 3 -- .../living/carbon/xenomorph/attack_alien.dm | 4 +-- 5 files changed, 57 insertions(+), 24 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 0762e99f5b34..b88753dc8c47 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -271,6 +271,7 @@ GLOBAL_LIST_EMPTY(living_borers) handle_crit() else if(health >= 1) set_stat(CONSCIOUS) + blinded = FALSE /mob/living/carbon/cortical_borer/proc/handle_crit() if(stat == DEAD || gibbing) @@ -285,12 +286,13 @@ GLOBAL_LIST_EMPTY(living_borers) update_icons() /mob/living/carbon/cortical_borer/death() - var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] - c_link.broadcast(src, "Has Died", real_name, TRUE) SSmob.living_misc_mobs -= src GLOB.living_borers -= src leave_host() . = ..() + if(!is_admin_level(z)) + var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] + c_link.broadcast(src, "Has Died", real_name, TRUE) /mob/living/carbon/cortical_borer/rejuvenate() ..() @@ -314,7 +316,12 @@ GLOBAL_LIST_EMPTY(living_borers) hud.remove_from_hud(src) hud.remove_hud_from(src, src) //###################################################// - +/mob/living/carbon/cortical_borer/get_examine_text(mob/user) + . = ..() + if(stat == DEAD) + . += SPAN_WARNING("It's dead.") + if(ishuman(user)) + . += SPAN_HELPFUL("You think you could put it in a chemical juicer...") /mob/living/carbon/cortical_borer/update_icons() if(stat == DEAD) @@ -375,6 +382,9 @@ GLOBAL_LIST_EMPTY(living_borers) . += "Host Plasma: [xeno_host.plasma_stored / plasma_perc]%" /mob/living/carbon/cortical_borer/say(message)//I need to parse the message properly so it doesn't look stupid + if(stat == DEAD) + to_chat(src, SPAN_WARNING("You cannot speak from beyond the grave!")) + return FALSE var/datum/language/parsed_language = parse_language(message) var/new_message = message if(parsed_language) diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index ca8d81821a0a..66dab3968167 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -1,3 +1,13 @@ +GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems()) + +/proc/generate_borer_chems() + var/list/chem_list = list() + for(var/chem_datum in subtypesof(/datum/borer_chem/human)) + chem_list += new chem_datum + for(var/chem_datum in subtypesof(/datum/borer_chem/yautja)) + chem_list += new chem_datum + return chem_list + /datum/borer_chem var/chem_name = "Unset" /// Chemical identifier, used in the proc to create it. @@ -10,8 +20,13 @@ var/category = BORER_CAT_HEAL + var/species = "UNSET" + //Medical Chems +/datum/borer_chem/human + species = SPECIES_HUMAN + /datum/borer_chem/human/tricordrazine chem_name = "Tricordrazine" chem_id = "tricordrazine" @@ -72,7 +87,7 @@ chem_id = "brain_stimulant" desc = "A powerful stimulant that enhances brain function. Lethal in high doses. Lasts one minute per unit." cost = 300 - quantity = 1 + quantity = 2 category = BORER_CAT_STIM /datum/borer_chem/human/stimulant_muscle @@ -80,7 +95,7 @@ chem_id = "speed_stimulant" desc = "A powerful stimulant that enhances musculature. Lethal in high doses. Lasts one minute per unit." cost = 300 - quantity = 1 + quantity = 2 category = BORER_CAT_STIM /datum/borer_chem/human/neurotoxin @@ -88,7 +103,7 @@ chem_id = PLASMA_NEUROTOXIN desc = "A potent and hallucinagenic neurotoxin." cost = 125 - quantity = 1 + quantity = 2 category = BORER_CAT_PUNISH /datum/borer_chem/human/antineurotoxin @@ -110,8 +125,8 @@ chem_name = "Potassium Chlorophoride" chem_id = "potassium_chlorophoride" desc = "A powerful chemical based on Potassium Chloride that causes instant cardiac arrest." - cost = 250 - quantity = 3 + cost = 300 + quantity = 5 category = BORER_CAT_PUNISH /datum/borer_chem/human/death_powder @@ -119,10 +134,13 @@ chem_id = "zombiepowder" desc = "A strong neurotoxin that puts the subject into a death-like state." cost = 300 - quantity = 2 + quantity = 5 category = BORER_CAT_PUNISH //Yautja chemicals +/datum/borer_chem/yautja + species = SPECIES_YAUTJA + /datum/borer_chem/yautja/thwei chem_name = "Thwei" chem_id = "thwei" @@ -132,7 +150,7 @@ -//Anti-Sugar +//Anti-Anti-Parasite /datum/borer_chem/human/enzyme chem_name = "Cortical Enzyme" chem_id = "benzyme" diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 385620593228..2f7ba975a123 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -284,6 +284,8 @@ host.status_flags |= PASSEMOTES host.verbs += /mob/living/proc/borer_comm get_host_actions() + faction = target.faction + faction_group = target.faction_group return TRUE @@ -337,6 +339,9 @@ forceMove(get_turf(host)) apply_effect(1, STUN) + faction = "Cortical" + faction_group = list("Cortical") + log_interact(src, host, "Borer: [key_name(src)] left their host; [key_name(host)]") host.reset_view(null) @@ -682,15 +687,19 @@ if(ishuman(host)) human_host = host if(isspeciesyautja(human_host)) - for(var/datum in subtypesof(/datum/borer_chem/yautja)) - var/datum/borer_chem/current_chem = datum - var/chem = initial(current_chem.chem_id) + for(var/datum/borer_chem/chem_datum in GLOB.borer_chemicals) + if(chem_datum.species != SPECIES_YAUTJA) + continue + var/datum/borer_chem/current_chem = chem_datum + var/chem = current_chem.chem_id var/datum/reagent/R = GLOB.chemical_reagents_list[chem] if(R) content += "[current_chem.quantity] units of [current_chem.chem_name] ([current_chem.cost] Enzymes)

[current_chem.desc]

" else - for(var/datum in subtypesof(/datum/borer_chem/human)) - var/datum/borer_chem/current_chem = datum + for(var/datum/borer_chem/chem_datum in GLOB.borer_chemicals) + if(chem_datum.species != SPECIES_HUMAN) + continue + var/datum/borer_chem/current_chem = chem_datum var/chem = current_chem.chem_id var/datum/reagent/R = GLOB.chemical_reagents_list[chem] if(R) @@ -820,10 +829,9 @@ var/topic_chem = href_list["borer_use_chem"] var/datum/borer_chem/current_chem = null - for(var/datum in typesof(/datum/borer_chem)) - var/datum/borer_chem/test = datum - if(test.chem_id == topic_chem) - current_chem = new test() + for(var/datum/borer_chem/chem_datum in GLOB.borer_chemicals) + current_chem = chem_datum + if(current_chem.chem_id == topic_chem) break if(!current_chem || !host || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) diff --git a/code/modules/defenses/sentry.dm b/code/modules/defenses/sentry.dm index 625bd87b24cc..a02e4e7808c9 100644 --- a/code/modules/defenses/sentry.dm +++ b/code/modules/defenses/sentry.dm @@ -87,9 +87,6 @@ if(!target && targets.len) target = pick(targets) - if(ismob(target.loc)) //Check to prevent certain issues with mobs-in-mobs being shot at, or attempt to be. - targets -= target - target = pick(targets) get_target(target) return TRUE diff --git a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm index 25e06d81b2ab..fc6b948792f3 100644 --- a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm +++ b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm @@ -290,13 +290,13 @@ SPAN_DANGER("We nudge our head against [src]."), null, 5, CHAT_TYPE_XENO_FLUFF) /mob/living/proc/is_xeno_grabbable() - if(stat == DEAD) + if(stat == DEAD || (status_flags & FAKEDEATH)) return FALSE return TRUE /mob/living/carbon/human/is_xeno_grabbable() - if(stat != DEAD || chestburst) + if(((stat != DEAD) && !(status_flags & FAKEDEATH)) || chestburst) return TRUE if(status_flags & XENO_HOST) From 537886dfbabe9dc0af0049f3c08da5948a07db98 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sun, 3 Mar 2024 04:32:52 +0000 Subject: [PATCH 32/52] Chemical Overhaul Part 1 --- code/modules/borer/borer.dm | 5 +- code/modules/borer/borer_chemicals.dm | 77 +++++++++++++++---- code/modules/borer/borer_procs.dm | 16 ++-- .../chemistry_machinery/reagent_grinder.dm | 4 +- .../reagents/chemistry_reactions/other.dm | 6 +- .../reagents/chemistry_reagents/other.dm | 24 ------ 6 files changed, 76 insertions(+), 56 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index b88753dc8c47..41f9746199ff 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -134,6 +134,9 @@ GLOBAL_LIST_EMPTY(living_borers) /// Borer status, controlling or docile. var/borer_flags_status //Controlling or Docile. Unsure if I want to put hibernating in here or in actives as active abilities will stop enzyme production. + /// Whether the borer can create chemicals that are marked as restricted. + var/restricted_chems_allowed = FALSE + var/list/datum/reagent/synthesized_chems var/current_actions = ACTION_SET_HOSTLESS @@ -214,7 +217,7 @@ GLOBAL_LIST_EMPTY(living_borers) var/mob/living/carbon/human/human_host if(ishuman(host)) human_host = host - if((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && (!human_host.reagents.has_reagent("benzyme") || human_host.reagents.has_reagent("bcure"))) + if((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && (!human_host.reagents.has_reagent("borerenzyme") || human_host.reagents.has_reagent("borercure"))) if(!docile) if(borer_flags_status & BORER_STATUS_CONTROLLING) to_chat(host, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index 66dab3968167..ecb665c14a2b 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -1,3 +1,41 @@ +/datum/reagent/borer + reagent_state = LIQUID + chemclass = CHEM_CLASS_SPECIAL + flags = REAGENT_SCANNABLE|REAGENT_NO_GENERATION + +/datum/reagent/borer/enzyme + name = "Cortical Enzyme" + id = "borerenzyme" + description = "An enzyme secreted by a parasite that consumes certain chemicals from the bloodstream. Also seems to help fight addictions." + color = "#25c08c" + overdose = LOW_REAGENTS_OVERDOSE + overdose_critical = LOW_REAGENTS_OVERDOSE_CRITICAL + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTIADDICTIVE = 2) + +/datum/reagent/borer/cure + name = "Anti-Enzyme" + id = "borercure" + description = "An anti-parasite drug synthesised from parastic enzymes. Effectively fights toxins in the bloodstream." + color = "#25c08c" + overdose = LOW_REAGENTS_OVERDOSE + overdose_critical = LOW_REAGENTS_OVERDOSE_CRITICAL + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTITOXIN = 4, PROPERTY_ANTIPARASITIC = 2) + +/datum/reagent/borer/shock + name = "Neuroshock" + id = "borershock" + description = "A biosynthetic nerve agent that stimulates cardiomyocytes in critical condition." + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_DEFIBRILLATING = 1, PROPERTY_INTRAVENOUS = 1) + +/datum/reagent/borer/transformative + name = "Biomend" + id = "borertransform" + description = "A biosynthetic agent that mends damage tissue while creating a toxic byproduct." + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_TRANSFORMATIVE = 2, PROPERTY_INTRAVENOUS = 1) + + +////////////// BORER CHEM DATUMS USED IN THE SYNTHESISER MENU /////////////////////// + GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems()) /proc/generate_borer_chems() @@ -19,7 +57,7 @@ GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems( var/quantity = 10 var/category = BORER_CAT_HEAL - + var/restricted = FALSE var/species = "UNSET" @@ -75,11 +113,23 @@ GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems( cost = 120 quantity = 5 -/datum/borer_chem/human/epinephrine - chem_name = "Epinephrine" - chem_id = "adrenaline" - desc = "Useful for restarting the heart. Overdosing may stress the heart and cause tissue damage." +/datum/borer_chem/human/restarter + chem_name = "Neuroshock" + chem_id = "borershock" + desc = "A powerful nerve agent that stimulates the heart. Useful for keeping your host alive. Lethal in high doses." + cost = 300 + quantity = 2 + restricted = TRUE + impure = FALSE +/datum/borer_chem/universal/biomend + chem_name = "Biomend" + chem_id = "borertransform" + desc = "A biosynthetic agent that mends damage tissue while creating a toxic byproduct." + cost = 250 + quantity = 10 + restricted = TRUE + impure = FALSE //"Motivation" Chems /datum/borer_chem/human/stimulant_brain @@ -136,6 +186,7 @@ GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems( cost = 300 quantity = 5 category = BORER_CAT_PUNISH + impure = FALSE //Yautja chemicals /datum/borer_chem/yautja @@ -151,20 +202,14 @@ GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems( //Anti-Anti-Parasite -/datum/borer_chem/human/enzyme - chem_name = "Cortical Enzyme" - chem_id = "benzyme" - desc = "An enzyme focused on consuming chemicals in the bloodstream. Helps fight addictions. This will work as a preventative measure against anti-parasite drugs so long as it is in the bloodstream. Can cause brain damage." - cost = 150 - quantity = 8 - category = BORER_CAT_SELF - impure = FALSE +/datum/borer_chem/universal + species = "Universal" -/datum/borer_chem/yautja/enzyme +/datum/borer_chem/universal/enzyme chem_name = "Cortical Enzyme" - chem_id = "benzyme" + chem_id = "borerenzyme" desc = "An enzyme focused on consuming chemicals in the bloodstream. Helps fight addictions. This will work as a preventative measure against anti-parasite drugs so long as it is in the bloodstream. Can cause brain damage." cost = 150 - quantity = 6 + quantity = 8 category = BORER_CAT_SELF impure = FALSE diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 2f7ba975a123..5c2435d95298 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -688,16 +688,12 @@ human_host = host if(isspeciesyautja(human_host)) for(var/datum/borer_chem/chem_datum in GLOB.borer_chemicals) - if(chem_datum.species != SPECIES_YAUTJA) - continue - var/datum/borer_chem/current_chem = chem_datum - var/chem = current_chem.chem_id - var/datum/reagent/R = GLOB.chemical_reagents_list[chem] - if(R) - content += "[current_chem.quantity] units of [current_chem.chem_name] ([current_chem.cost] Enzymes)

[current_chem.desc]

" - else - for(var/datum/borer_chem/chem_datum in GLOB.borer_chemicals) - if(chem_datum.species != SPECIES_HUMAN) + if(chem_datum.species != "Universal") + if(isspeciesyautja(human_host) && chem_datum.species != SPECIES_YAUTJA) + continue + if(chem_datum.species != SPECIES_HUMAN) + continue + if(chem_datum.restricted && !restricted_chems_allowed) continue var/datum/borer_chem/current_chem = chem_datum var/chem = current_chem.chem_id diff --git a/code/modules/reagents/chemistry_machinery/reagent_grinder.dm b/code/modules/reagents/chemistry_machinery/reagent_grinder.dm index 2929d3aba0d2..39c7783ee45e 100644 --- a/code/modules/reagents/chemistry_machinery/reagent_grinder.dm +++ b/code/modules/reagents/chemistry_machinery/reagent_grinder.dm @@ -54,7 +54,7 @@ /obj/item/reagent_container/food/snacks/watermelonslice = list("watermelonjuice" = 0), /obj/item/reagent_container/food/snacks/grown/grapes = list("grapejuice" = 0), /obj/item/reagent_container/food/snacks/grown/poisonberries = list("poisonberryjuice" = 0), - /obj/item/holder/borer = list("benzyme" = 0), + /obj/item/holder/borer = list("borerenzyme" = 0), ) @@ -417,7 +417,7 @@ if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume) break var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume - beaker.reagents.add_reagent("benzyme",min(6, space)) + beaker.reagents.add_reagent("borerenzyme",min(6, space)) remove_object(b_holder) break diff --git a/code/modules/reagents/chemistry_reactions/other.dm b/code/modules/reagents/chemistry_reactions/other.dm index 376292f8be4e..199f1cdff302 100644 --- a/code/modules/reagents/chemistry_reactions/other.dm +++ b/code/modules/reagents/chemistry_reactions/other.dm @@ -455,8 +455,8 @@ /datum/chemical_reaction/borer_cure name = "Anti-Enzyme" - id = "bcure" - result = "bcure" - required_reagents = list("benzyme" = 2, "anti_toxin" = 4) + id = "borercure" + result = "borercure" + required_reagents = list("borerenzyme" = 2, "anti_toxin" = 4) result_amount = 3 mob_react = FALSE diff --git a/code/modules/reagents/chemistry_reagents/other.dm b/code/modules/reagents/chemistry_reagents/other.dm index 879fded1f180..ae1a42bd5e6d 100644 --- a/code/modules/reagents/chemistry_reagents/other.dm +++ b/code/modules/reagents/chemistry_reagents/other.dm @@ -1026,27 +1026,3 @@ chemclass = CHEM_CLASS_SPECIAL properties = list(PROPERTY_TRANSFORMATIVE = 4, PROPERTY_NUTRITIOUS = 3, PROPERTY_HEMOGENIC = 1) flags = REAGENT_SCANNABLE - -/datum/reagent/borer_enzyme - name = "Cortical Enzyme" - id = "benzyme" - description = "An enzyme secreted by a parasite that consumes certain chemicals from the bloodstream. Also seems to help fight addictions." - reagent_state = LIQUID - color = "#25c08c" - overdose = LOW_REAGENTS_OVERDOSE - overdose_critical = LOW_REAGENTS_OVERDOSE_CRITICAL - chemclass = CHEM_CLASS_SPECIAL - flags = REAGENT_SCANNABLE|REAGENT_NO_GENERATION - properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTIADDICTIVE = 2) - -/datum/reagent/borer_cure - name = "Anti-Enzyme" - id = "bcure" - description = "An anti-parasite drug synthesised from parastic enzymes. Effectively fights toxins in the bloodstream." - reagent_state = LIQUID - color = "#25c08c" - overdose = LOW_REAGENTS_OVERDOSE - overdose_critical = LOW_REAGENTS_OVERDOSE_CRITICAL - chemclass = CHEM_CLASS_SPECIAL - flags = REAGENT_SCANNABLE|REAGENT_NO_GENERATION - properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTITOXIN = 4, PROPERTY_ANTIPARASITIC = 2) From 0f5a5c2bf62fc1a89f4a9e2ae54f41121fcdd6c7 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sun, 3 Mar 2024 17:01:07 +0000 Subject: [PATCH 33/52] Chemical Overhaul Part 2 --- code/__DEFINES/borer_defines.dm | 3 + code/modules/borer/borer.dm | 2 +- code/modules/borer/borer_chemicals.dm | 5 ++ code/modules/borer/borer_procs.dm | 122 ++++++++++++++++++++++---- 4 files changed, 115 insertions(+), 17 deletions(-) diff --git a/code/__DEFINES/borer_defines.dm b/code/__DEFINES/borer_defines.dm index 181a7d830f47..da75d0523315 100644 --- a/code/__DEFINES/borer_defines.dm +++ b/code/__DEFINES/borer_defines.dm @@ -3,9 +3,12 @@ #define BORER_CAT_PUNISH "Motivators" #define BORER_CAT_STIM "Stimulants" #define BORER_CAT_SELF "Self Protection" +#define BORER_CAT_REPLICATED "Replicated" ///Amount of chemicals needed for a borer to reproduce, provided reproduction is toggled. #define BORER_LARVAE_COST 400 +/// Amount of chemicals needed for a borer to replicate a chemical. +#define BORER_REPLICATE_COST 350 #define ACTION_SET_HOSTLESS "actions_hostless" #define ACTION_SET_HUMANOID "actions_human" diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 41f9746199ff..4f8100d62228 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -137,7 +137,7 @@ GLOBAL_LIST_EMPTY(living_borers) /// Whether the borer can create chemicals that are marked as restricted. var/restricted_chems_allowed = FALSE - var/list/datum/reagent/synthesized_chems + var/list/datum/borer_chem/synthesized_chems = list() var/current_actions = ACTION_SET_HOSTLESS var/list/actions_hostless = list( diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index ecb665c14a2b..cfa51e649c1f 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -44,6 +44,8 @@ GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems( chem_list += new chem_datum for(var/chem_datum in subtypesof(/datum/borer_chem/yautja)) chem_list += new chem_datum + for(var/chem_datum in subtypesof(/datum/borer_chem/universal)) + chem_list += new chem_datum return chem_list /datum/borer_chem @@ -60,6 +62,9 @@ GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems( var/restricted = FALSE var/species = "UNSET" +/datum/borer_chem/synthesised + desc = "A chemical replicated from exposure." + category = BORER_CAT_REPLICATED //Medical Chems /datum/borer_chem/human diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 5c2435d95298..bb420f7df538 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -659,7 +659,13 @@ to_chat(src, SPAN_XENOWARNING("You are not allowed to reproduce!")) return FALSE - +/mob/living/carbon/cortical_borer/proc/get_possible_chems() + var/list/possibilities = list() + for(var/datum/borer_chem/chem in GLOB.borer_chemicals) + possibilities += chem + for(var/datum/borer_chem/chem in src.synthesized_chems) + possibilities += chem + return possibilities /mob/living/carbon/cortical_borer/verb/secrete_chemicals() set category = "Borer" @@ -684,33 +690,112 @@ if(ishuman(host)) var/mob/living/carbon/human/human_host - if(ishuman(host)) - human_host = host - if(isspeciesyautja(human_host)) - for(var/datum/borer_chem/chem_datum in GLOB.borer_chemicals) - if(chem_datum.species != "Universal") - if(isspeciesyautja(human_host) && chem_datum.species != SPECIES_YAUTJA) - continue - if(chem_datum.species != SPECIES_HUMAN) + human_host = host + for(var/datum/borer_chem/chem_datum in get_possible_chems()) + if(chem_datum.species != "Universal") + if(isspeciesyautja(human_host)) + if(chem_datum.species != SPECIES_YAUTJA) continue - if(chem_datum.restricted && !restricted_chems_allowed) + else if(chem_datum.species != SPECIES_HUMAN) continue - var/datum/borer_chem/current_chem = chem_datum - var/chem = current_chem.chem_id - var/datum/reagent/R = GLOB.chemical_reagents_list[chem] - if(R) - content += "[current_chem.quantity] units of [current_chem.chem_name] ([current_chem.cost] Enzymes)

[current_chem.desc]

" + if(chem_datum.restricted && !restricted_chems_allowed) + continue + var/datum/borer_chem/current_chem = chem_datum + var/chem = current_chem.chem_id + var/datum/reagent/R = GLOB.chemical_reagents_list[chem] + if(R) + content += "[current_chem.quantity] units of [current_chem.chem_name] ([current_chem.cost] Enzymes)

[current_chem.desc]

" content += "" var/html = get_html_template(content) - usr << browse(null, "window=ViewBorer\ref[src]Chems;size=585x400") usr << browse(html, "window=ViewBorer\ref[src]Chems;size=585x400") return TRUE +/mob/living/carbon/cortical_borer/verb/learn_chemicals() + set category = "Borer" + set name = "Replicate Chemical" + set desc = "Study a chemical compound for replication." + + if(!host) + to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) + return FALSE + + if(stat) + to_chat(src, SPAN_XENOWARNING("You cannot replicate chemicals in your current state.")) + return FALSE + + if(docile) + to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) + return FALSE + + if(enzymes < BORER_REPLICATE_COST) + to_chat(src, SPAN_XENONOTICE("You need at least [BORER_REPLICATE_COST] enzymes to attempt chemical replication!")) + return FALSE + + var/list/options = list() + var/list/options_datums = list() + var/list/existing_chems = list() + for(var/datum/borer_chem/existing_chem in GLOB.borer_chemicals) + if(!(existing_chem.chem_id in existing_chems)) + existing_chems += existing_chem.chem_id + for(var/datum/borer_chem/existing_chem in synthesized_chems) + if(!(existing_chem.chem_id in existing_chems)) + existing_chems += existing_chem.chem_id + + for(var/datum/reagent/potential_chem in host.reagents?.reagent_list) + if(potential_chem.id in existing_chems) + continue + if(potential_chem.volume < potential_chem.overdose) + continue + options += potential_chem.id + options_datums[potential_chem.id] = potential_chem + + if(!options) + to_chat(src, SPAN_XENONOTICE("There are no chemicals within your host you are able to replicate!")) + return FALSE + + var/choice = tgui_input_list(usr, "Which option do you wish to attempt replication for?", "Choose Option", options, 20 SECONDS) + if(!choice) + return FALSE + if(tgui_alert(usr, "Do you wish to attempt replication of '[choice]'?", "Confirm", list("Yes", "No"), 10 SECONDS) != "Yes") + return FALSE + var/datum/reagent/chosen = options_datums[choice] + if(!chosen) + return FALSE + + enzymes -= BORER_REPLICATE_COST + var/failure_mult = 0 + for(var/property in chosen.properties) + failure_mult++ + var/failure_chance = failure_mult * 10 + + chosen.volume = (chosen.volume / 10) + + if(prob(failure_chance)) + to_chat(src, SPAN_XENOWARNING("Replication failed! This chemical has a failure chance of [failure_chance]%!")) + return FALSE + + var/datum/borer_chem/synthesised/new_chem = new + new_chem.chem_id = chosen.id + new_chem.chem_name = chosen.name + new_chem.desc = chosen.description + var/n_species = host.get_species() + if(!n_species) + n_species = "UNSET" + new_chem.species = n_species + + new_chem.cost = ((5 * failure_chance)) + new_chem.quantity = (chosen.overdose / 3) + + synthesized_chems += new_chem + to_chat(src, SPAN_XENONOTICE("Replication successful!")) + + return TRUE + //############# Communication Procs ############# /mob/living/carbon/cortical_borer/verb/Communicate() @@ -829,6 +914,11 @@ current_chem = chem_datum if(current_chem.chem_id == topic_chem) break + if(current_chem.chem_id != topic_chem) + for(var/datum/borer_chem/chem_datum in synthesized_chems) + current_chem = chem_datum + if(current_chem.chem_id == topic_chem) + break if(!current_chem || !host || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) return FALSE From 3bc641f1c49ba5b3ebfcc15e9dd2e3ddead93144 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sun, 3 Mar 2024 17:09:12 +0000 Subject: [PATCH 34/52] Chemical Overhaul Part 3 --- code/modules/borer/borer.dm | 13 +++++++++++++ code/modules/borer/borer_procs.dm | 4 +++- icons/mob/hud/actions_borer.dmi | Bin 3118 -> 3087 bytes 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 4f8100d62228..b62a42f3b522 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -154,6 +154,7 @@ GLOBAL_LIST_EMPTY(living_borers) /datum/action/innate/borer/leave_body, /datum/action/innate/borer/scan_chems, /datum/action/innate/borer/make_chems, + /datum/action/innate/borer/learn_chems, ) var/list/actions_xenohost = list( /datum/action/innate/borer/helpme, @@ -526,6 +527,18 @@ GLOBAL_LIST_EMPTY(living_borers) return borerscan(B, B.host) +/datum/action/innate/borer/learn_chems + name = "Learn Chemicals" + action_icon_state = "borer_human_learn" + +/datum/action/innate/borer/learn_chems/action_activate() + if(!isborer(owner)) return FALSE + var/mob/living/carbon/cortical_borer/B = owner + if(B.hibernating) + to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + return + B.learn_chemicals() + /datum/action/innate/borer/make_larvae name = "Reproduce" action_icon_state = "borer_reproduce" diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index bb420f7df538..10e85b729d7c 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -15,7 +15,7 @@ else if(isxeno(host)) options += list("Assuming Control","Hibernation","Reproducing") else - options += list("Assuming Control","Hibernation","Secreting Chemicals","Reproducing", "Host Death") + options += list("Assuming Control","Hibernation","Secreting Chemicals","Learning Chemicals","Reproducing", "Host Death") var/choice = tgui_input_list(target, "What would you like help with?", "Help", options, 20 SECONDS) @@ -47,6 +47,8 @@ help_message = "Hibernation is how you purify contaminants from your body, allowing you to use your enzymes more freely.\n\nYou can only hibernate whilst inside a host, and it renders you unable to act other than to speak to your host.\n\nYou can freely enter or leave hibernation by clicking the Hibernate button." if("Secreting Chemicals") help_message = "Whilst inside a humanoid host you can secrete chemicals to facilitate your relationship.\nThese can vary from helpful medications to harmful control measures.\n\nSecreting chemicals costs enzymes and if a chemical is impure will cause you to gain contaminant.\nIf you are at, or will go over, your contaminant capacity you will be unable to secrete chemicals.\nPure chemicals are chemicals native to borers such as Cortical Enzyme." + if("Learning Chemicals") + help_message = "Whilst inside a humanoid host you can learn new chemicals to synthesise, costing [BORER_REPLICATE_COST] Enzymes.\n\nThis requires your host to have a chemical in their blood you do not already know, and for that chemical to be in a state of Overdose.\n\nLearning the chemical has a chance to fail, consuming enzymes but producing no results. This is determined by the number of properties the chemical has.\nSuccessful replication of the chemical will permanently allow you to reproduce it.\nSuccessful or not, attempting to replicate a chemical will consume 90% of the amount in your host's bloodstream." if("Host Death") help_message = "Upon the death of your host you will be forced to release direct control (if you are currently in control), but otherwise will be largely unaffected. If your host becomes permanently unreviavable however, you will be ejected from their corpse." if(!help_message) diff --git a/icons/mob/hud/actions_borer.dmi b/icons/mob/hud/actions_borer.dmi index aab12b0b5b6aea52cf24f0f855d80e9fe5dba48f..cfc38cf4d084b6f0d6f41002676be8348c99e3c4 100644 GIT binary patch delta 2947 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 tMs6L2$)sC>qo*rsGb-h%T171AoQr>!yle+ zp0^)=kSeP=)q+}@>lFwkNWgAmJiyKy@isviq?3mODU;n@TjhoZ9b1 z`xF2G3GhioK~#90?VO8Z+BytC8Oxw?7g%n80$pJ=jFzs1K)e6{xhvT?Pub3sHeIy! zK^4b3v1B_EWHcJ&-Q|l$deOh;sOtbU?f=V&M8!W|37}#B%HtBnn3Au_k&X0?`!90> zi;!TR3h55{b}F2Hmu&RrM4p4jkz z|J_DF7%vf&0I4}GcLHvFOprD31}{H;$pOge8D4(;k^`UwQ1y?ey#bL38h|h43BZ4B zfzj;7F8K+eGL-yKIPW?V|^+X6_5#)abR zp8@zjpU=U>i+Mk|IA!&1xe(F5Gyqul-F02G5X}1z<;UD9sc$`q)zhfb$I(8=K_@}` z@cPc@u2WLq`ZTIu$kZ-`2L70f3k=4Ad9G7d-}*w9K34(2RseuOU>X{T-VT?4*D0-U zeJh~_P`Qxn%+WpzqZN#F^CO_qUvo331DJ6G!C9;yc!>)DO8rN;A3zTg27+)OM+-~p zTL5T$ONj=~VQu0;3Qoc;bV}-5xTQ3n;OjR^k|V#mj+@qiqs-@J^^N=g1ZkBzs`jLL zVyo||#X$xcBezYpm9LuDe{ij#n3eiS|qba0j9@(4JV@%v{QT3Sa?O zaN+v30Yv*^YEvE{jF$*X7n;~geae19?_>WB0Bq4-1%QVC1d#}u7+@-Yy-x&b3cy*w z1#}=xd<}r6J|WsOX4wP)8vWC{e7jQ^$dj73dIZo)5`c604i`_1RHga=@6#6Td5*pS z5ZfOU5C+cNNs`^A0TeO71J_$%{|o#b2rAVFM0HKH$KQb<3n1;kzmExu2HKMeIH5Ds z0MIcY{K`iF*In=zo?jtyUUfozefT-5_fq6ZF>eG1fl~-NlMSJ zzaIk#f(q$%Ci<5Ef}kn@oMg6u5txtwruqQRus8`iIFE?Mu1b9X`)6@`mY+n*xe#MB zhtI=B08@Ry_rQKwgt!5)7U4Wp$%Pp7o@$TtkX<8)0RWSlMF3NOeZU9%SJ+m_Vg&?w z7b5IW0KooCdmvyrfKt=w3}=BEV|IQ74E2Gr=dV`_?!j=}VzFAom{gfYnVoA7V^Vn` zgV>p2dmI3p0MOJ2Ja3IH9d`}?@Ta@>lp{baWQ-Nsv%&~ihOGqS)93^N?BWRM>jU0u zCHi0EfBbE=QoB%pibVnt?I{5LW=0RL-j z0Dt8rF;KETkZsQx-Rk=C-t~#b(*ML(-&2c&4D!*X>mchqh`XNVI-f?nUT8Y650qKz zDH$h6YV~c_2ZCU`-R3uIWdIDDL9M=pH=85?n12rn9Vn$G0OR?~0t6!e9@GW+y|b)G z5Ea1F-m;#5L23f1>k~16$iHtJ06hKyc~k>DqyD+}2q@|k@_?<#zt;r#jk0?I5d?XF zCzL(cKR0rrVtpb85c&5Yu(p~Gh_nYcaJT!t+wJg;ku<=5|Fqxlxn2vPecPuHBDKgT zpRLHhLktAlO8NWPh5o$UOs6+u2q+hl`e!WwQ6IQ}h@w6L2LvJpc>W!K2Z9Qzzl(u8 z1OQP1?DtZy1JJznSyi7HiOGK(i1amo5o{|YU*$CUs2>3c;SwW2oZnQR81d`BjR6Ef zh4i-wVgtaF9>A1d*VQNZ0YMPw--Cb%G84dWK8dOUp7_SLd5yW7|;YU2WSw)%KF4;9Bgy>cNmlE(@h5UP<90AorhGEQi5`XB048!JylM4>I}ppj!Suwcpom zr+FCE-%hLR6C-{PkV#($mGbx3x}j0kCq{hb%I4pLD*5~C-BQx^2{Qj41cmdcJ22D_ zwE7l4zo3^sq*V+Z)KPt$^Y=fsILIKMU3woxolj$3%O@x_H_p#@qW@O5{d+%O2=!rq zc#QCGrzniVQ^oe>x3gy{iVjSAH9!=FNB+l?bvhkS9RZwYQqE)tCjCJTa0I5LMPgt1mz@$g<57xoY8-P9zzH=N~V*w$?fNJ05BkAYa#XqElxeiSFL@o$ffG`YC zKp?#5gmF-8-|YE9=kxL+Xd?k&(5J`_@MawLHKsE#{8)8G6Xq*i~Y&dZ7M%s2n>9Xq5#n9@$&dzm% zg>w0_!iWHnkLLjdtLF2Cz(XGX{srsc8(iXofv9H;^ze<+W8fK7QmjwX5{z8EH{maLH{qp)(8NFdh0XBWUP;&s7KjZwqPXS0D8gnNK^ZJI* z7fKtrF#u3{3}To@4+!9sBarw%26R+^E1?3|7y$Ho`4KZ<$bFVFHZbIKP-I2?XUm(p zAlBne0hrF^ z7*zl;-crKu5)4ZAYD>OrPL4F`69W!}0Zng7%K!+QV&N~+00zA&zfY>am2LkC(kgXS zA4qziS{!7MK?WJ5sdSzH?;fDhX3DG|0R9~S)ANPMTROA;S^%c!3n^}@&HC#Am>$cZ zOlz3+R{=0R7(<;{GV8B@0bqJGi6*sY)?WeOVt?{ Date: Tue, 5 Mar 2024 00:29:09 +0000 Subject: [PATCH 35/52] tidy up --- code/modules/borer/borer.dm | 43 ++++++++++++++++--- code/modules/borer/borer_chemicals.dm | 12 ------ code/modules/borer/borer_procs.dm | 12 +++--- code/modules/mob/living/carbon/human/human.dm | 1 + .../mob/living/carbon/xenomorph/XenoProcs.dm | 1 + 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index b62a42f3b522..98d8cf3f81e2 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -1,4 +1,36 @@ -GLOBAL_LIST_EMPTY(living_borers) +/datum/borer_brainlink + var/list/living_borers = list() + var/list/datum/borer_chem/borer_chemicals = list() + var/cortical_directive = "Seek hosts and spread. Avoid detection where possible. Do not assume control without need." // Default directive. + +/datum/borer_brainlink/New() + . = ..() + borer_chemicals = generate_borer_chems() + +GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) + +/datum/borer_brainlink/proc/generate_borer_chems() + var/list/chem_list = list() + for(var/chem_datum in subtypesof(/datum/borer_chem/human)) + chem_list += new chem_datum + for(var/chem_datum in subtypesof(/datum/borer_chem/yautja)) + chem_list += new chem_datum + for(var/chem_datum in subtypesof(/datum/borer_chem/universal)) + chem_list += new chem_datum + return chem_list + +/datum/borer_brainlink/proc/update_directive(new_directive) + cortical_directive = new_directive + + for(var/mob/living/cur_mob in GLOB.brainlink.living_borers) + if(cur_mob.client) // Send to borers + to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: The Cortical Directive has changed.")) + to_chat(cur_mob, SPAN_XENOBOLDNOTICE("[new_directive].")) + + for(var/mob/dead/observer/cur_mob in GLOB.observer_list) + if(cur_mob.client) // Send to observers + to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: The Cortical Directive has changed.")) + to_chat(cur_mob, SPAN_XENOBOLDNOTICE("[new_directive].")) /mob/living/captive_brain name = "captive mind" @@ -194,7 +226,7 @@ GLOBAL_LIST_EMPTY(living_borers) max_contaminant = max_contaminant * 1.5 if((!is_admin_level(z)) && ERT) summon() - GLOB.living_borers += src + GLOB.brainlink.living_borers += src /mob/living/carbon/cortical_borer/initialize_pass_flags(datum/pass_flags_container/PF) ..() @@ -291,7 +323,7 @@ GLOBAL_LIST_EMPTY(living_borers) /mob/living/carbon/cortical_borer/death() SSmob.living_misc_mobs -= src - GLOB.living_borers -= src + GLOB.brainlink.living_borers -= src leave_host() . = ..() if(!is_admin_level(z)) @@ -302,11 +334,11 @@ GLOBAL_LIST_EMPTY(living_borers) ..() update_icons() SSmob.living_misc_mobs |= src - GLOB.living_borers += src + GLOB.brainlink.living_borers += src /mob/living/carbon/cortical_borer/Destroy() SSmob.living_misc_mobs -= src - GLOB.living_borers -= src + GLOB.brainlink.living_borers -= src remove_from_all_mob_huds() if(host) @@ -365,6 +397,7 @@ GLOBAL_LIST_EMPTY(living_borers) bore_status = "HIBERNATING" . += "" + . += "Cortical Directive: [GLOB.brainlink.cortical_directive]" . += "Borer: [bore_status]" . += "Name: [real_name]" . += "Can Reproduce: [CR]" diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index cfa51e649c1f..24b69e3a689e 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -36,18 +36,6 @@ ////////////// BORER CHEM DATUMS USED IN THE SYNTHESISER MENU /////////////////////// -GLOBAL_LIST_INIT_TYPED(borer_chemicals, /datum/borer_chem, generate_borer_chems()) - -/proc/generate_borer_chems() - var/list/chem_list = list() - for(var/chem_datum in subtypesof(/datum/borer_chem/human)) - chem_list += new chem_datum - for(var/chem_datum in subtypesof(/datum/borer_chem/yautja)) - chem_list += new chem_datum - for(var/chem_datum in subtypesof(/datum/borer_chem/universal)) - chem_list += new chem_datum - return chem_list - /datum/borer_chem var/chem_name = "Unset" /// Chemical identifier, used in the proc to create it. diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 10e85b729d7c..e71fe7cb6174 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -446,7 +446,7 @@ host.med_hud_set_status() host.special_mob = TRUE - GLOB.living_borers += host + GLOB.brainlink.living_borers += host if(src && !src.key) src.key = "@[borer_key]" @@ -493,7 +493,7 @@ if(host_brain) log_interact(host, src, "Borer: [key_name(host)] Took control back") host.special_mob = FALSE - GLOB.living_borers -= host + GLOB.brainlink.living_borers -= host // host -> self var/h2s_id = host.computer_id var/h2s_ip= host.lastKnownIP @@ -663,7 +663,7 @@ /mob/living/carbon/cortical_borer/proc/get_possible_chems() var/list/possibilities = list() - for(var/datum/borer_chem/chem in GLOB.borer_chemicals) + for(var/datum/borer_chem/chem in GLOB.brainlink.borer_chemicals) possibilities += chem for(var/datum/borer_chem/chem in src.synthesized_chems) possibilities += chem @@ -741,7 +741,7 @@ var/list/options = list() var/list/options_datums = list() var/list/existing_chems = list() - for(var/datum/borer_chem/existing_chem in GLOB.borer_chemicals) + for(var/datum/borer_chem/existing_chem in GLOB.brainlink.borer_chemicals) if(!(existing_chem.chem_id in existing_chems)) existing_chems += existing_chem.chem_id for(var/datum/borer_chem/existing_chem in synthesized_chems) @@ -912,7 +912,7 @@ var/topic_chem = href_list["borer_use_chem"] var/datum/borer_chem/current_chem = null - for(var/datum/borer_chem/chem_datum in GLOB.borer_chemicals) + for(var/datum/borer_chem/chem_datum in GLOB.brainlink.borer_chemicals) current_chem = chem_datum if(current_chem.chem_id == topic_chem) break @@ -963,7 +963,7 @@ msg = process_chat_markup(msg, list("*")) - for(var/mob/living/cur_mob in GLOB.living_borers) + for(var/mob/living/cur_mob in GLOB.brainlink.living_borers) if(cur_mob.client) // Send to borers to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [msg]")) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 0094e5e39368..92595cee1cd0 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -142,6 +142,7 @@ CR = "No" . += "" + . += "Cortical Directive: [GLOB.brainlink.cortical_directive]" . += "Borer: CONTROLLING" . += "Name: [B.real_name]" . += "Can Reproduce: [CR]" diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index 4f46eeb22ff8..c985d5cc8089 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -155,6 +155,7 @@ CR = "No" . += "" + . += "Cortical Directive: [GLOB.brainlink.cortical_directive]" . += "Borer: CONTROLLING" . += "Name: [B.real_name]" . += "Can Reproduce: [CR]" From dc917dc44cf3b518208b4576b814f54d0e20c35e Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 5 Mar 2024 00:55:41 +0000 Subject: [PATCH 36/52] ancestry fix --- code/modules/borer/borer_procs.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index e71fe7cb6174..72787479c2e5 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -650,7 +650,8 @@ T.add_vomit_floor() brainworm.contaminant = 0 var/repro = max(brainworm.can_reproduce - 1, 0) - var/ancestors = (brainworm.ancestry += real_name) + var/list/ancestors = brainworm.ancestry + ancestors += real_name var/mob/living/carbon/cortical_borer/birthed = new /mob/living/carbon/cortical_borer(T, brainworm.generation + 1, TRUE, repro, brainworm.borer_flags_targets, ancestors) brainworm.offspring += birthed.real_name return TRUE From bac22e82821ae6aad73c96e34ffdfd92c8b80fd9 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 5 Mar 2024 01:01:00 +0000 Subject: [PATCH 37/52] precision reagent scan --- code/modules/borer/borer_procs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 72787479c2e5..82f6c959eba0 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -110,7 +110,7 @@ if(human_target.reagents.reagent_list.len) to_chat(user, SPAN_XENONOTICE("Subject contains the following reagents:")) for(var/datum/reagent/R in human_target.reagents.reagent_list) - to_chat(user, "[R.overdose != 0 && R.volume >= R.overdose && !(R.flags & REAGENT_CANNOT_OVERDOSE) ? SPAN_WARNING("OD: ") : ""] [round(R.volume, 1)]u [R.name]") + to_chat(user, "[R.overdose != 0 && R.volume >= R.overdose && !(R.flags & REAGENT_CANNOT_OVERDOSE) ? SPAN_WARNING("OD: ") : ""] [R.volume]u [R.name]") else to_chat(user, SPAN_XENONOTICE("Subject contains no reagents.")) if(isxeno(M)) From dee964dd2599abf506ce620fcd3fb937bd55e597 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Fri, 15 Mar 2024 03:01:23 +0000 Subject: [PATCH 38/52] icon conflict --- icons/mob/hud/hud.dmi | Bin 19425 -> 19875 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/hud/hud.dmi b/icons/mob/hud/hud.dmi index 507ec0dd485b0976d8c3e00c3a88c55a87f329dd..19f215fdcd09b61c1e1eb45392de9a13135b1064 100644 GIT binary patch literal 19875 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 literal 19425 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 Date: Thu, 21 Mar 2024 08:27:05 +0000 Subject: [PATCH 39/52] f --- code/modules/borer/borer_chemicals.dm | 2 +- code/modules/reagents/chemistry_properties/prop_positive.dm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index 24b69e3a689e..71387b257d62 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -25,7 +25,7 @@ name = "Neuroshock" id = "borershock" description = "A biosynthetic nerve agent that stimulates cardiomyocytes in critical condition." - properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_DEFIBRILLATING = 1, PROPERTY_INTRAVENOUS = 1) + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_DEFIBRILLATING = 2, PROPERTY_INTRAVENOUS = 1) /datum/reagent/borer/transformative name = "Biomend" diff --git a/code/modules/reagents/chemistry_properties/prop_positive.dm b/code/modules/reagents/chemistry_properties/prop_positive.dm index 76fd411e70f6..d4ca619414e0 100644 --- a/code/modules/reagents/chemistry_properties/prop_positive.dm +++ b/code/modules/reagents/chemistry_properties/prop_positive.dm @@ -604,9 +604,9 @@ dead.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, TOX) dead.apply_damage(-potency * POTENCY_MULTIPLIER_LOW, CLONE) if(dead.health < HEALTH_THRESHOLD_DEAD) - return + return TRUE if(!COOLDOWN_FINISHED(src, ghost_notif)) - return + return TRUE var/mob/dead/observer/ghost = dead.get_ghost() if(ghost?.client) COOLDOWN_START(src, ghost_notif, 30 SECONDS) From ba13d8ea2eb4e85bb36e2ed7ff91217bdf5c8e44 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 21 Mar 2024 11:19:39 +0000 Subject: [PATCH 40/52] variable clarification --- code/modules/borer/borer.dm | 84 +++++---- code/modules/borer/borer_chemicals.dm | 2 +- code/modules/borer/borer_procs.dm | 238 +++++++++++++------------- 3 files changed, 166 insertions(+), 158 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 98d8cf3f81e2..10049bc6e4d4 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -63,10 +63,10 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) return say_dead(message) var/mob/living/carbon/cortical_borer/B = loc to_chat(src, SPAN_BORER("You whisper silently, [message]"), type = MESSAGE_TYPE_RADIO) - to_chat(B.host, SPAN_BORER("The captive mind of [src] whispers, \"[message]\""), type = MESSAGE_TYPE_RADIO) - log_say("BORER: ([key_name(src)] to [key_name(B.host)]) [message]", src) + to_chat(B.host_mob, SPAN_BORER("The captive mind of [src] whispers, \"[message]\""), type = MESSAGE_TYPE_RADIO) + log_say("BORER: ([key_name(src)] to [key_name(B.host_mob)]) [message]", src) for (var/mob/dead in GLOB.dead_mob_list) - var/track_borer = " (F)" + var/track_borer = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping dead.show_message(SPAN_BORER("BORER: ([name] (trapped mind) to [B.real_name][track_borer]) whispers: [message]"), SHOW_MESSAGE_VISIBLE) @@ -75,7 +75,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) if(!istype(B)) log_debug(EXCEPTION("Trapped mind found without a borer!"), src) return FALSE - return B.host.say_understands(other, speaking) + return B.host_mob.say_understands(other, speaking) /mob/living/captive_brain/emote(act, m_type = 1, message = null, intentional = FALSE, force_silence = FALSE) return @@ -87,14 +87,14 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) return FALSE if(resisting_control) to_chat(src, SPAN_DANGER("You stop resisting control.")) - to_chat(B.host, SPAN_XENODANGER("The captive mind of [src] is no longer attempting to resist you.")) + to_chat(B.host_mob, SPAN_XENODANGER("The captive mind of [src] is no longer attempting to resist you.")) resisting_control = FALSE return FALSE to_chat(src, SPAN_HIGHDANGER("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).")) - to_chat(B.host, SPAN_XENOHIGHDANGER("You feel the captive mind of [src] begin to resist your control.")) + to_chat(B.host_mob, SPAN_XENOHIGHDANGER("You feel the captive mind of [src] begin to resist your control.")) resisting_control = TRUE - var/delay = (rand(350,450) + B.host.getBrainLoss()) + var/delay = (rand(350,450) + B.host_mob.getBrainLoss()) addtimer(CALLBACK(src, PROC_REF(return_control), B), delay) return TRUE @@ -151,7 +151,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) var/max_contaminant = 120 //Decreases through hibernation or reproduction. var/hibernating = FALSE //Usable inside a host, but not when controlling. Allows clearing of impurities. - var/mob/living/carbon/host // Carbon host for the brain worm. + var/mob/living/carbon/host_mob // Carbon host for the brain worm. var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. var/docile = FALSE // Anti-Parasite or Anti-Enzyme chemicals can stop borers from acting. var/bonding = FALSE @@ -243,17 +243,17 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) ..() update_icons() var/heal_amt = 1 - if(host) + if(host_mob) set_light_on(FALSE) heal_amt = 3 - if(!stat && host.stat != DEAD) + if(!stat && host_mob.stat != DEAD) var/mob/living/carbon/human/human_host - if(ishuman(host)) - human_host = host + if(ishuman(host_mob)) + human_host = host_mob if((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && (!human_host.reagents.has_reagent("borerenzyme") || human_host.reagents.has_reagent("borercure"))) if(!docile) if(borer_flags_status & BORER_STATUS_CONTROLLING) - to_chat(host, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) + to_chat(host_mob, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) else to_chat(src, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) docile = TRUE @@ -276,8 +276,8 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) contaminant = max(contaminant -= 0.1, 0) if(borer_flags_status & BORER_STATUS_CONTROLLING) if(docile) - to_chat(host, SPAN_WARNING("You are feeling far too docile to continue controlling your host...")) - host.release_control() + to_chat(host_mob, SPAN_WARNING("You are feeling far too docile to continue controlling your host...")) + host_mob.release_control() return else if(contaminant > 0) @@ -341,9 +341,9 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) GLOB.brainlink.living_borers -= src remove_from_all_mob_huds() - if(host) - for(var/datum/action/innate/borer/action in host.actions) - action.hide_from(host) + if(host_mob) + for(var/datum/action/innate/borer/action in host_mob.actions) + action.hide_from(host_mob) return ..() /mob/living/carbon/cortical_borer/remove_from_all_mob_huds() @@ -405,15 +405,15 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) . += "Contaminant: [round(contaminant)]/[round(max_contaminant)]" . += "Health: [health]/[maxHealth]" . += "Injuries: Brute:[round(getBruteLoss())] Burn:[round(getFireLoss())] Toxin:[round(getToxLoss())]" - if(host) + if(host_mob) . += "" - var/health_perc = host.maxHealth / 100 - . += "Host Integrity: [host.health / health_perc]%" - if(ishuman(host)) - . += "Host Brain Damage: [host.brainloss]%" - . += "Host Blood Level: [host.blood_volume / 5.6]%" - else if(isxeno(host)) - var/mob/living/carbon/xenomorph/xeno_host = host + var/health_perc = host_mob.maxHealth / 100 + . += "Host Integrity: [host_mob.health / health_perc]%" + if(ishuman(host_mob)) + . += "Host Brain Damage: [host_mob.brainloss]%" + . += "Host Blood Level: [host_mob.blood_volume / 5.6]%" + else if(isxeno(host_mob)) + var/mob/living/carbon/xenomorph/xeno_host = host_mob if(xeno_host.plasma_max) var/plasma_perc = xeno_host.plasma_max / 100 . += "Host Plasma: [xeno_host.plasma_stored / plasma_perc]%" @@ -432,7 +432,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) if(hibernating) to_chat(src, SPAN_WARNING("You cannot speak aloud while hibernating!")) return - if(loc == host && !talk_inside_host) + if(loc == host_mob && !talk_inside_host) to_chat(src, SPAN_WARNING("You've disabled audible speech while inside a host! Re-enable it under the borer tab, or stick to borer communications.")) return . = ..() @@ -491,8 +491,8 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/talk_to_borer/action_activate() var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host = owner - B.host.borer_comm() + B.host_mob = owner + B.host_mob.borer_comm() /datum/action/innate/borer/talk_to_brain name = "Converse with Trapped Mind" @@ -500,8 +500,8 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/talk_to_brain/action_activate() var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host = owner - B.host.trapped_mind_comm() + B.host_mob = owner + B.host_mob.trapped_mind_comm() /datum/action/innate/borer/take_control name = "Assume Control" @@ -521,8 +521,8 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/give_back_control/action_activate() var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host = owner - B.host.release_control() + B.host_mob = owner + B.host_mob.release_control() /datum/action/innate/borer/leave_body name = "Leave Host" @@ -558,7 +558,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) if(B.hibernating) to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) return - borerscan(B, B.host) + borerscan(B, B.host_mob) /datum/action/innate/borer/learn_chems name = "Learn Chemicals" @@ -578,8 +578,8 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/make_larvae/action_activate() var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host = owner - B.host.spawn_larvae() + B.host_mob = owner + B.host_mob.spawn_larvae() /datum/action/innate/borer/freeze_victim name = "Dominate Victim" @@ -595,8 +595,8 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/torment/action_activate() var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host = owner - B.host.punish_host() + B.host_mob = owner + B.host_mob.punish_host() /datum/action/innate/borer/hibernate name = "Toggle Hibernation" @@ -607,3 +607,11 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) B.hibernate() button.overlays.Cut() button.overlays += image('icons/mob/hud/actions_borer.dmi', button, "borer_sleeping_[B.hibernating]") + +/datum/action/innate/borer/transfer_host + name = "Transfer Host" + action_icon_state = "borer_infest" + +/datum/action/innate/borer/infest_host/action_activate() + var/mob/living/carbon/cortical_borer/B = owner + B.transfer_host() diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index 71387b257d62..9f2e8f8bf3c9 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -203,6 +203,6 @@ chem_id = "borerenzyme" desc = "An enzyme focused on consuming chemicals in the bloodstream. Helps fight addictions. This will work as a preventative measure against anti-parasite drugs so long as it is in the bloodstream. Can cause brain damage." cost = 150 - quantity = 8 + quantity = 6 category = BORER_CAT_SELF impure = FALSE diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 82f6c959eba0..167579310c82 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -1,18 +1,18 @@ //############# HELP ################## /mob/living/carbon/cortical_borer/verb/show_help() - set category = "Borer" + set category = "Borer.Misc" set name = "Show Help" set desc = "Show help for borer commands." var/target = src var/list/options = list("Communicating","Contaminant & Enzymes") - if(!host) + if(!host_mob) options += list("Infecting a host") else if(borer_flags_status & BORER_STATUS_CONTROLLING) - target = host + target = host_mob options += list("Captive Host", "Releasing Control", "Reproducing") - else if(isxeno(host)) + else if(isxeno(host_mob)) options += list("Assuming Control","Hibernation","Reproducing") else options += list("Assuming Control","Hibernation","Secreting Chemicals","Learning Chemicals","Reproducing", "Host Death") @@ -148,28 +148,28 @@ for(var/datum/action/innate/borer/action in actions) action.hide_from(target) - if(host && current_actions == ACTION_SET_CONTROL) - for(var/datum/action/innate/borer/action in host.actions) - action.hide_from(host) + if(host_mob && current_actions == ACTION_SET_CONTROL) + for(var/datum/action/innate/borer/action in host_mob.actions) + action.hide_from(host_mob) var/list/abilities_to_give switch(actions_list) if(ACTION_SET_HOSTLESS) abilities_to_give = actions_hostless.Copy() - if(host) - for(var/datum/action/innate/borer/action in host.actions) - action.hide_from(host) + if(host_mob) + for(var/datum/action/innate/borer/action in host_mob.actions) + action.hide_from(host_mob) if(ACTION_SET_HUMANOID) abilities_to_give = actions_humanoidhost.Copy() if(ACTION_SET_XENO) abilities_to_give = actions_xenohost.Copy() if(ACTION_SET_CONTROL) - if(!host) + if(!host_mob) return FALSE abilities_to_give = actions_control.Copy() - target = host - for(var/datum/action/innate/borer/talk_to_borer/action in host.actions) - action.hide_from(host) + target = host_mob + for(var/datum/action/innate/borer/talk_to_borer/action in host_mob.actions) + action.hide_from(host_mob) for(var/path in abilities_to_give) give_action(target, path) @@ -177,15 +177,15 @@ return TRUE /mob/living/carbon/cortical_borer/proc/get_host_actions() - if(!host) + if(!host_mob) return FALSE - if(ishuman(host)) + if(ishuman(host_mob)) give_new_actions(ACTION_SET_HUMANOID) - else if(isxeno(host)) + else if(isxeno(host_mob)) give_new_actions(ACTION_SET_XENO) else return FALSE - give_action(host, /datum/action/innate/borer/talk_to_borer) + give_action(host_mob, /datum/action/innate/borer/talk_to_borer) return TRUE /mob/living/carbon/cortical_borer/proc/hibernate() @@ -227,11 +227,11 @@ //Brainslug infests a target /mob/living/carbon/cortical_borer/verb/infest() - set category = "Borer" + set category = "Borer.Hostless" set name = "Infest" set desc = "Infest a suitable humanoid host." - if(host) + if(host_mob) to_chat(src, "You are already within a host.") return FALSE if(stat) @@ -279,12 +279,12 @@ if(target.has_brain_worms()) to_chat(src, SPAN_XENOWARNING("[target] is already infested!")) return FALSE - host = target - log_interact(src, host, "Borer: [key_name(src)] Infested [key_name(host)]") + host_mob = target + log_interact(src, host_mob, "Borer: [key_name(src)] Infested [key_name(host_mob)]") target.borer = src forceMove(target) - host.status_flags |= PASSEMOTES - host.verbs += /mob/living/proc/borer_comm + host_mob.status_flags |= PASSEMOTES + host_mob.verbs += /mob/living/proc/borer_comm get_host_actions() faction = target.faction faction_group = target.faction_group @@ -293,10 +293,10 @@ //Brainslug abandons the host /mob/living/carbon/cortical_borer/verb/release_host() - set category = "Borer" + set category = "Borer.Infested" set name = "Release Host" set desc = "Slither out of your host." - if(!host) + if(!host_mob) to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) return FALSE if(stat) @@ -305,19 +305,19 @@ if(docile) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) return FALSE - if(!host || !src) + if(!host_mob || !src) return FALSE if(leaving) leaving = FALSE to_chat(src, SPAN_XENOWARNING("You decide against leaving your host.")) return TRUE - to_chat(src, SPAN_XENOHIGHDANGER("You begin disconnecting from [host]'s synapses and prodding at their internal ear canal.")) + to_chat(src, SPAN_XENOHIGHDANGER("You begin disconnecting from [host_mob]'s synapses and prodding at their internal ear canal.")) leaving = TRUE addtimer(CALLBACK(src, PROC_REF(let_go)), 200) return TRUE /mob/living/carbon/cortical_borer/proc/let_go() - if(!host || !src || QDELETED(host) || QDELETED(src)) + if(!host_mob || !src || QDELETED(host_mob) || QDELETED(src)) return FALSE if(!leaving || borer_flags_status & BORER_STATUS_CONTROLLING) return FALSE @@ -325,46 +325,46 @@ to_chat(src, SPAN_XENOWARNING("You cannot release a target in your current state.")) return FALSE - to_chat(src, SPAN_XENOHIGHDANGER("You wiggle out of [host]'s ear and plop to the ground.")) + to_chat(src, SPAN_XENOHIGHDANGER("You wiggle out of [host_mob]'s ear and plop to the ground.")) leaving = FALSE leave_host() return TRUE /mob/living/carbon/cortical_borer/proc/leave_host() - if(!host) + if(!host_mob) return FALSE if(borer_flags_status & BORER_STATUS_CONTROLLING) detach() give_new_actions(ACTION_SET_HOSTLESS) - forceMove(get_turf(host)) + forceMove(get_turf(host_mob)) apply_effect(1, STUN) faction = "Cortical" faction_group = list("Cortical") - log_interact(src, host, "Borer: [key_name(src)] left their host; [key_name(host)]") - host.reset_view(null) + log_interact(src, host_mob, "Borer: [key_name(src)] left their host; [key_name(host_mob)]") + host_mob.reset_view(null) - var/mob/living/carbon/H = host + var/mob/living/carbon/H = host_mob H.borer = null H.status_flags &= ~PASSEMOTES - host = null + host_mob = null return TRUE //Brainslug takes control of the body /mob/living/carbon/cortical_borer/verb/bond_brain() - set category = "Borer" + set category = "Borer.Infested" set name = "Assume Control" set desc = "Fully connect to the brain of your host." - if(!host) + if(!host_mob) to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) return FALSE - if(host.stat == DEAD) + if(host_mob.stat == DEAD) to_chat(src, SPAN_XENODANGER("This host is in no condition to be controlled.")) return FALSE @@ -383,17 +383,17 @@ to_chat(src, "You begin delicately adjusting your connection to the host brain...") - if(QDELETED(src) || QDELETED(host)) + if(QDELETED(src) || QDELETED(host_mob)) return FALSE bonding = TRUE - var/delay = 300+(host.getBrainLoss()*5) + var/delay = 300+(host_mob.getBrainLoss()*5) addtimer(CALLBACK(src, PROC_REF(assume_control)), delay) return TRUE /mob/living/carbon/cortical_borer/proc/assume_control() - if(!host || !src || borer_flags_status & BORER_STATUS_CONTROLLING) + if(!host_mob || !src || borer_flags_status & BORER_STATUS_CONTROLLING) return FALSE if(!bonding) return FALSE @@ -402,22 +402,22 @@ return FALSE else to_chat(src, SPAN_XENOHIGHDANGER("You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system.")) - to_chat(host, SPAN_HIGHDANGER("You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.")) - to_chat(host, SPAN_NOTICE("You can [SPAN_BOLD("resist")] this consciousness, but be warned you may suffer some degree of brain damage in the process!")) + to_chat(host_mob, SPAN_HIGHDANGER("You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.")) + to_chat(host_mob, SPAN_NOTICE("You can [SPAN_BOLD("resist")] this consciousness, but be warned you may suffer some degree of brain damage in the process!")) var/borer_key = src.key - log_interact(src, host, "Borer: [key_name(src)] Assumed control of [key_name(host)]") + log_interact(src, host_mob, "Borer: [key_name(src)] Assumed control of [key_name(host_mob)]") // host -> brain - var/h2b_id = host.computer_id - var/h2b_ip= host.lastKnownIP - host.computer_id = null - host.lastKnownIP = null + var/h2b_id = host_mob.computer_id + var/h2b_ip= host_mob.lastKnownIP + host_mob.computer_id = null + host_mob.lastKnownIP = null qdel(host_brain) host_brain = new(src) - host_brain.ckey = host.ckey + host_brain.ckey = host_mob.ckey - host_brain.name = host.name + host_brain.name = host_mob.name if(!host_brain.computer_id) host_brain.computer_id = h2b_id @@ -431,22 +431,22 @@ src.computer_id = null src.lastKnownIP = null - host.ckey = src.ckey + host_mob.ckey = src.ckey - if(!host.computer_id) - host.computer_id = s2h_id + if(!host_mob.computer_id) + host_mob.computer_id = s2h_id - if(!host.lastKnownIP) - host.lastKnownIP = s2h_ip + if(!host_mob.lastKnownIP) + host_mob.lastKnownIP = s2h_ip bonding = FALSE borer_flags_status |= BORER_STATUS_CONTROLLING give_new_actions(ACTION_SET_CONTROL) - host.med_hud_set_status() - host.special_mob = TRUE + host_mob.med_hud_set_status() + host_mob.special_mob = TRUE - GLOB.brainlink.living_borers += host + GLOB.brainlink.living_borers += host_mob if(src && !src.key) src.key = "@[borer_key]" @@ -456,9 +456,9 @@ /mob/living/captive_brain/proc/return_control(mob/living/carbon/cortical_borer/B) if(!B || !(B.borer_flags_status & BORER_STATUS_CONTROLLING) || !resisting_control) return FALSE - B.host.adjustBrainLoss(rand(5,10)) + B.host_mob.adjustBrainLoss(rand(5,10)) to_chat(src, SPAN_HIGHDANGER("With an immense exertion of will, you regain control of your body!")) - to_chat(B.host, SPAN_XENOHIGHDANGER("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) + to_chat(B.host_mob, SPAN_XENOHIGHDANGER("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) resisting_control = FALSE B.detach() return TRUE @@ -466,7 +466,7 @@ ///Brain slug proc for voluntary removal of control. /mob/living/carbon/proc/release_control() - set category = "Borer" + set category = "Borer.Controlling" set name = "Release Control" set desc = "Release control of your host's body." @@ -481,25 +481,25 @@ log_debug(EXCEPTION("Missing borer or missing host brain upon borer release."), src) /mob/living/carbon/cortical_borer/proc/detach() - if(!host || !(borer_flags_status & BORER_STATUS_CONTROLLING)) + if(!host_mob || !(borer_flags_status & BORER_STATUS_CONTROLLING)) return FALSE borer_flags_status &= ~BORER_STATUS_CONTROLLING reset_view(null) get_host_actions() - host.med_hud_set_status() + host_mob.med_hud_set_status() sleeping = 0 if(host_brain) - log_interact(host, src, "Borer: [key_name(host)] Took control back") - host.special_mob = FALSE - GLOB.brainlink.living_borers -= host + log_interact(host_mob, src, "Borer: [key_name(host_mob)] Took control back") + host_mob.special_mob = FALSE + GLOB.brainlink.living_borers -= host_mob // host -> self - var/h2s_id = host.computer_id - var/h2s_ip= host.lastKnownIP - host.computer_id = null - host.lastKnownIP = null - src.ckey = host.ckey + var/h2s_id = host_mob.computer_id + var/h2s_ip= host_mob.lastKnownIP + host_mob.computer_id = null + host_mob.lastKnownIP = null + src.ckey = host_mob.ckey if(!src.computer_id) src.computer_id = h2s_id if(!host_brain.lastKnownIP) @@ -510,18 +510,18 @@ var/b2h_ip = host_brain.lastKnownIP host_brain.computer_id = null host_brain.lastKnownIP = null - host.ckey = host_brain.ckey + host_mob.ckey = host_brain.ckey - if(!host.computer_id) - host.computer_id = b2h_id - if(!host.lastKnownIP) - host.lastKnownIP = b2h_ip + if(!host_mob.computer_id) + host_mob.computer_id = b2h_id + if(!host_mob.lastKnownIP) + host_mob.lastKnownIP = b2h_ip qdel(host_brain) return TRUE //Host Has died /mob/living/carbon/cortical_borer/proc/host_death(perma = FALSE) - if(!(host && loc == host)) + if(!(host_mob && loc == host_mob)) log_debug("Borer ([key_name(src)]) called host_death without being inside a host!") return FALSE if(borer_flags_status & BORER_STATUS_CONTROLLING) @@ -534,11 +534,11 @@ //############# External Ability Procs ############# /mob/living/carbon/cortical_borer/verb/hide_borer() - set category = "Borer" + set category = "Borer.Hostless" set name = "Hide" set desc = "Become invisible to the common eye." - if(host) + if(host_mob) to_chat(usr, SPAN_WARNING("You cannot do this while you're inside a host.")) return FALSE @@ -556,14 +556,14 @@ return TRUE /mob/living/carbon/cortical_borer/verb/dominate_victim() - set category = "Borer" + set category = "Borer.Hostless" set name = "Dominate Victim" set desc = "Freeze the limbs of a potential host with supernatural fear." if(world.time - used_dominate < 150) to_chat(src, SPAN_XENOWARNING("You cannot use that ability again so soon.")) return FALSE - if(host) + if(host_mob) to_chat(src, SPAN_XENOWARNING("You cannot do that from within a host body.")) return FALSE if(stat) @@ -614,7 +614,7 @@ //############# Internal Abiity Procs ############# /mob/living/carbon/proc/punish_host() - set category = "Borer" + set category = "Borer.Controlling" set name = "Torment Host" set desc = "Punish your host with agony." @@ -630,7 +630,7 @@ /mob/living/carbon/proc/spawn_larvae() - set category = "Borer" + set category = "Borer.Controlling" set name = "Reproduce" set desc = "Spawn a new borer." @@ -671,11 +671,11 @@ return possibilities /mob/living/carbon/cortical_borer/verb/secrete_chemicals() - set category = "Borer" + set category = "Borer.Infested" set name = "Secrete Chemicals" set desc = "Push some chemicals into your host's bloodstream." - if(!host) + if(!host_mob) to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) return FALSE @@ -691,9 +691,9 @@ content += "" - if(ishuman(host)) + if(ishuman(host_mob)) var/mob/living/carbon/human/human_host - human_host = host + human_host = host_mob for(var/datum/borer_chem/chem_datum in get_possible_chems()) if(chem_datum.species != "Universal") if(isspeciesyautja(human_host)) @@ -719,11 +719,11 @@ /mob/living/carbon/cortical_borer/verb/learn_chemicals() - set category = "Borer" + set category = "Borer.Infested" set name = "Replicate Chemical" set desc = "Study a chemical compound for replication." - if(!host) + if(!host_mob) to_chat(src, SPAN_XENOWARNING("You are not inside a host body.")) return FALSE @@ -749,7 +749,7 @@ if(!(existing_chem.chem_id in existing_chems)) existing_chems += existing_chem.chem_id - for(var/datum/reagent/potential_chem in host.reagents?.reagent_list) + for(var/datum/reagent/potential_chem in host_mob.reagents?.reagent_list) if(potential_chem.id in existing_chems) continue if(potential_chem.volume < potential_chem.overdose) @@ -757,7 +757,7 @@ options += potential_chem.id options_datums[potential_chem.id] = potential_chem - if(!options) + if(!options.len) to_chat(src, SPAN_XENONOTICE("There are no chemicals within your host you are able to replicate!")) return FALSE @@ -786,7 +786,7 @@ new_chem.chem_id = chosen.id new_chem.chem_name = chosen.name new_chem.desc = chosen.description - var/n_species = host.get_species() + var/n_species = host_mob.get_species() if(!n_species) n_species = "UNSET" new_chem.species = n_species @@ -802,15 +802,15 @@ //############# Communication Procs ############# /mob/living/carbon/cortical_borer/verb/Communicate() - set category = "Borer" + set category = "Borer.Infested" set name = "Converse with Host" set desc = "Send a silent message to your host." - if(!host) + if(!host_mob) to_chat(src, "You do not have a host to communicate with!") return FALSE - if(host.stat == DEAD) + if(host_mob.stat == DEAD) to_chat(src, SPAN_XENODANGER("Not even you can commune with the dead.")) return FALSE @@ -822,22 +822,22 @@ if(!input) return FALSE - if(src && !QDELETED(src) && !QDELETED(host)) + if(src && !QDELETED(src) && !QDELETED(host_mob)) var/say_string = (docile) ? "slurs" :"states" - if(host) - to_chat(host, SPAN_XENO("[real_name] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) - show_blurb(host, 15, input, TRUE, "center", "center", COLOR_BROWN, null, null, 1) - log_say("BORER: ([key_name(src)] to [key_name(host)]) [input]", src) + if(host_mob) + to_chat(host_mob, SPAN_XENO("[real_name] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) + show_blurb(host_mob, 15, input, TRUE, "center", "center", COLOR_BROWN, null, null, 1) + log_say("BORER: ([key_name(src)] to [key_name(host_mob)]) [input]", src) to_chat(src, SPAN_XENO("[real_name] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) for (var/mob/dead in GLOB.dead_mob_list) - var/track_host = " (F)" + var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message(SPAN_BORER("BORER: ([real_name] to [host.real_name][track_host]) [say_string]: [input]"), SHOW_MESSAGE_VISIBLE) + dead.show_message(SPAN_BORER("BORER: ([real_name] to [host_mob.real_name][track_host]) [say_string]: [input]"), SHOW_MESSAGE_VISIBLE) return TRUE /mob/living/carbon/cortical_borer/verb/toggle_silence_inside_host() set name = "Toggle speech inside Host" - set category = "Borer" + set category = "Borer.Misc" set desc = "Toggle whether you will be able to say audible messages while inside your host." if(talk_inside_host) @@ -849,7 +849,7 @@ /mob/living/proc/borer_comm() set name = "Converse with Borer" - set category = "Borer" + set category = "Borer.Host" set desc = "Communicate mentally with your borer." @@ -870,32 +870,32 @@ log_say("BORER: ([key_name(src)] to [key_name(borer)]) [input]", src) to_chat(src, SPAN_XENO("[src.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) for (var/mob/dead in GLOB.dead_mob_list) - var/track_host = " (F)" + var/track_host = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping dead.show_message(SPAN_BORER("BORER: ([name][track_host] to [borer.real_name]) says: [input]"), SHOW_MESSAGE_VISIBLE) return TRUE /mob/living/proc/trapped_mind_comm() set name = "Converse with Trapped Mind" - set category = "Borer" + set category = "Borer.Controlling" set desc = "Communicate mentally with the trapped mind of your host." - var/mob/living/carbon/cortical_borer/B = has_brain_worms() - if(!B || !B.host_brain) + var/mob/living/carbon/cortical_borer/borer = has_brain_worms() + if(!borer || !borer.host_brain) return FALSE - var/mob/living/captive_brain/CB = B.host_brain + var/mob/living/captive_brain/CB = borer.host_brain var/input = stripped_input(src, "Please enter a message to tell the trapped mind.", "Message", "") if(!input) return FALSE - to_chat(CB, SPAN_XENO("[B.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) - log_say("BORER: ([key_name(src)] to [key_name(CB)]) [input]", B) - to_chat(src, SPAN_XENO("[B.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) + to_chat(CB, SPAN_XENO("[borer.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) + log_say("BORER: ([key_name(src)] to [key_name(CB)]) [input]", borer) + to_chat(src, SPAN_XENO("[borer.real_name] says: [input]"), type = MESSAGE_TYPE_RADIO) for (var/mob/dead in GLOB.dead_mob_list) - var/track_borer = " (F)" + var/track_borer = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message(SPAN_BORER("BORER: ([B.real_name][track_borer] to [real_name] (trapped mind)) says: [input]"), SHOW_MESSAGE_VISIBLE) + dead.show_message(SPAN_BORER("BORER: ([borer.real_name][track_borer] to [real_name] (trapped mind)) says: [input]"), SHOW_MESSAGE_VISIBLE) return TRUE @@ -923,7 +923,7 @@ if(current_chem.chem_id == topic_chem) break - if(!current_chem || !host || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) + if(!current_chem || !host_mob || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) return FALSE var/datum/reagent/R = GLOB.chemical_reagents_list[current_chem.chem_id] if(enzymes < current_chem.cost) @@ -933,11 +933,11 @@ if(current_chem.impure && ((contaminant + contamination) > max_contaminant)) to_chat(src, SPAN_XENOWARNING("You are too contaminated to secrete [current_chem.chem_name]!")) return FALSE - to_chat(src, SPAN_XENONOTICE("You squirt a measure of [current_chem.chem_name] from your reservoirs into [host]'s bloodstream.")) + to_chat(src, SPAN_XENONOTICE("You squirt a measure of [current_chem.chem_name] from your reservoirs into [host_mob]'s bloodstream.")) contaminant += contamination - host.reagents.add_reagent(current_chem.chem_id, current_chem.quantity) + host_mob.reagents.add_reagent(current_chem.chem_id, current_chem.quantity) enzymes -= current_chem.cost - log_interact(src, host, "[key_name(src)] has injected [current_chem.quantity] units of [R.name] into their host, [key_name(host)]") + log_interact(src, host_mob, "[key_name(src)] has injected [current_chem.quantity] units of [R.name] into their host, [key_name(host_mob)]") // This is used because we use a static set of datums to determine what chems are available, // instead of a table or something. Thus, when we instance it, we can safely delete it From 1e95b82a3472a55cbc165297083a7a6318809d8e Mon Sep 17 00:00:00 2001 From: forest2001 Date: Thu, 21 Mar 2024 18:41:39 +0000 Subject: [PATCH 41/52] WIP --- code/modules/borer/borer.dm | 5 ++-- code/modules/borer/borer_wip.dm | 53 +++++++++++++++++++++++++++++++++ colonialmarines.dme | 1 + 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 code/modules/borer/borer_wip.dm diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 10049bc6e4d4..b77ac074b575 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -201,6 +201,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/make_larvae, /datum/action/innate/borer/talk_to_brain, /datum/action/innate/borer/torment, + /datum/action/innate/borer/transfer_host,//WIP ) var/list/ancestry = list() @@ -612,6 +613,6 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) name = "Transfer Host" action_icon_state = "borer_infest" -/datum/action/innate/borer/infest_host/action_activate() - var/mob/living/carbon/cortical_borer/B = owner +/datum/action/innate/borer/transfer_host/action_activate() + var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() B.transfer_host() diff --git a/code/modules/borer/borer_wip.dm b/code/modules/borer/borer_wip.dm new file mode 100644 index 000000000000..adb30b04166a --- /dev/null +++ b/code/modules/borer/borer_wip.dm @@ -0,0 +1,53 @@ +/mob/living/carbon/cortical_borer/proc/transfer_host() + set category = "Borer.Controlling" + set name = "Transfer Host" + set desc = "Transfer from one host to another by direct contact." + + if(!host_mob) + to_chat(src, "You must be in a host to transfer from one to another!.") + return FALSE + if(stat) + to_chat(host_mob, "You cannot infest a target in your current state.") + return FALSE + var/obj/item/grab/grab_effect = host_mob.get_held_item() + if(!istype(grab_effect) || !ishuman(grab_effect.grabbed_thing)) + to_chat(host_mob, SPAN_WARNING("You need to be holding a humanoid target to do this!")) + return FALSE + if(host_mob.grab_level < GRAB_AGGRESSIVE) + to_chat(host_mob, SPAN_WARNING("You need a better grip to do that!")) + return FALSE + + var/mob/living/carbon/target = grab_effect.grabbed_thing + + if(!target || !host_mob.Adjacent(target)) + return FALSE + if(target.stat == DEAD) + to_chat(host_mob, SPAN_WARNING("You cannot infest the dead.")) + return FALSE + if(target.has_brain_worms()) + to_chat(host_mob, SPAN_WARNING("You cannot infest someone who is already infested!")) + return FALSE + if(host_mob.is_mob_incapacitated()) + to_chat(host_mob, "You cannot infest a target in your current state.") + return FALSE + + host_mob.visible_message(SPAN_WARNING("[src] leans forward, holding their head beside that of [target]."), SPAN_NOTICE("You position your host's head beside [target]'s, reading to crawl from one ear to another.")) + if(!do_after(host_mob, 50, INTERRUPT_ALL_OUT_OF_RANGE, BUSY_ICON_HOSTILE, target)) + host_mob.visible_message(SPAN_NOTICE("[src] draws back from [target]."), SPAN_WARNING("You withdraw back into your current host as [target] escapes your clutches.")) + return FALSE + if(!target || !host_mob) + return FALSE + if(stat) + to_chat(host_mob, SPAN_XENOWARNING("You cannot change host in your current state.")) + return FALSE + if(!host_mob.Adjacent(target)) + to_chat(host_mob, "They are no longer in range!") + return FALSE + + to_chat(host_mob, SPAN_NOTICE("You wiggle into [target]'s ear.")) + if(!stealthy && !target.stat) + to_chat(target, SPAN_DANGER("Something disgusting and slimy wiggles into your ear!")) + detach() + leave_host() + perform_infestation(target) + return TRUE diff --git a/colonialmarines.dme b/colonialmarines.dme index 410b3a1b5bb6..997b517d8942 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -1509,6 +1509,7 @@ #include "code\modules\borer\borer_chemicals.dm" #include "code\modules\borer\borer_html.dm" #include "code\modules\borer\borer_procs.dm" +#include "code\modules\borer\borer_wip.dm" #include "code\modules\buildmode\bm-mode.dm" #include "code\modules\buildmode\buildmode.dm" #include "code\modules\buildmode\buttons.dm" From bfa4951f6a8f1c66ec11ed86c2ff3441742709a2 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sun, 5 May 2024 20:12:47 +0100 Subject: [PATCH 42/52] x --- icons/mob/hud/hud.dmi | Bin 19605 -> 20054 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/hud/hud.dmi b/icons/mob/hud/hud.dmi index 8d89fb7812641ce67d21d1cef9030c877f33e7e9..35e7c303a72fd6778e4b8206c9eadeb8cb12094a 100644 GIT binary patch literal 20054 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 Date: Mon, 6 May 2024 00:09:25 +0100 Subject: [PATCH 43/52] death pulse --- code/__DEFINES/borer_defines.dm | 4 +++ code/modules/borer/borer.dm | 51 +++++++++++++++++++++++------- code/modules/borer/borer_procs.dm | 7 +--- icons/mob/brainslug.dmi | Bin 4282 -> 4568 bytes 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/code/__DEFINES/borer_defines.dm b/code/__DEFINES/borer_defines.dm index da75d0523315..3506d14836b9 100644 --- a/code/__DEFINES/borer_defines.dm +++ b/code/__DEFINES/borer_defines.dm @@ -53,3 +53,7 @@ DEFINE_BITFIELD(borer_flags_status, list( "STATUS_CONTROLLING" = BORER_STATUS_CONTROLLING, "STATUS_DOCILE" = BORER_STATUS_DOCILE, )) + + +#define DEATH_CAUSE_PRIMARIES "No living Primaries." +#define DEATH_CAUSE_UNKNOWN "Unknown" diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index b77ac074b575..3414675c2f3f 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -2,6 +2,8 @@ var/list/living_borers = list() var/list/datum/borer_chem/borer_chemicals = list() var/cortical_directive = "Seek hosts and spread. Avoid detection where possible. Do not assume control without need." // Default directive. + var/hardmode = FALSE + var/pulse_triggered = FALSE /datum/borer_brainlink/New() . = ..() @@ -9,6 +11,41 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) +/datum/borer_brainlink/proc/impulse_broadcast(message, size = "Large") + var/transmission = SPAN_XOOC("Cortical Impulse: [message]") + if(size != "Large") + transmission = SPAN_XENOBOLDNOTICE("Cortical Impulse: [message]") + + for(var/mob/living/cur_mob in living_borers) + if(cur_mob.client) // Send to borers + to_chat(cur_mob, transmission) + + for(var/mob/dead/observer/cur_mob in GLOB.observer_list) + if(cur_mob.client) // Send to observers + to_chat(cur_mob, transmission) + +/datum/borer_brainlink/proc/handle_death(mob/living/carbon/cortical_borer/the_dead) + impulse_broadcast("[the_dead.real_name] has died!", "Small") + if(!pulse_triggered && (the_dead.generation <= 1)) + for(var/mob/living/carbon/cortical_borer/borer in living_borers) + if(borer.generation <= 1) + continue + death_pulse(DEATH_CAUSE_PRIMARIES) + break + return + +/datum/borer_brainlink/proc/death_pulse(source = DEATH_CAUSE_UNKNOWN) + pulse_triggered = TRUE + var/death_message = "A wave of death flows across the cortical link!" + switch(source) + if(DEATH_CAUSE_PRIMARIES) + death_message += " All the Primaries have fallen! There is no one strong enough to maintain the link!" + if(DEATH_CAUSE_UNKNOWN) + death_message += " The devastation is unprecedented, and the cause unclear..." + impulse_broadcast(death_message) + for(var/mob/living/borer in living_borers) + borer.death(create_cause_data("Cortical Link Collapse")) + /datum/borer_brainlink/proc/generate_borer_chems() var/list/chem_list = list() for(var/chem_datum in subtypesof(/datum/borer_chem/human)) @@ -22,15 +59,8 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/borer_brainlink/proc/update_directive(new_directive) cortical_directive = new_directive - for(var/mob/living/cur_mob in GLOB.brainlink.living_borers) - if(cur_mob.client) // Send to borers - to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: The Cortical Directive has changed.")) - to_chat(cur_mob, SPAN_XENOBOLDNOTICE("[new_directive].")) - - for(var/mob/dead/observer/cur_mob in GLOB.observer_list) - if(cur_mob.client) // Send to observers - to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: The Cortical Directive has changed.")) - to_chat(cur_mob, SPAN_XENOBOLDNOTICE("[new_directive].")) + impulse_broadcast("The Cortical Directive has changed.") + impulse_broadcast(new_directive, size = "Small") /mob/living/captive_brain name = "captive mind" @@ -328,8 +358,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) leave_host() . = ..() if(!is_admin_level(z)) - var/datum/language/corticalborer/c_link = GLOB.all_languages[LANGUAGE_BORER] - c_link.broadcast(src, "Has Died", real_name, TRUE) + GLOB.brainlink.handle_death(src) /mob/living/carbon/cortical_borer/rejuvenate() ..() diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 167579310c82..434b67e0be09 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -964,13 +964,8 @@ msg = process_chat_markup(msg, list("*")) - for(var/mob/living/cur_mob in GLOB.brainlink.living_borers) - if(cur_mob.client) // Send to borers - to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [msg]")) + GLOB.brainlink.impulse_broadcast(msg) - for(var/mob/dead/observer/cur_mob in GLOB.observer_list) - if(cur_mob.client) // Send to observers - to_chat(cur_mob, SPAN_XOOC("Cortical Impulse: [src.key]([src.admin_holder.rank]): [msg]")) /mob/living/carbon/human/proc/make_borer_host(worm_generation = 1, worm_repro = 1) if(has_brain_worms()) diff --git a/icons/mob/brainslug.dmi b/icons/mob/brainslug.dmi index 42e83a7753f6aad2688b75046a5e5244e79c38c1..2871a4eb026dd106da5e6caa35959f1fca5a25d5 100644 GIT binary patch literal 4568 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 From 9ae3dacacd0decc90397b18c6a10d2d183f9227d Mon Sep 17 00:00:00 2001 From: forest2001 Date: Mon, 1 Jul 2024 18:51:15 +0100 Subject: [PATCH 44/52] fix --- tgui/packages/tgui/interfaces/Orbit/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/tgui/packages/tgui/interfaces/Orbit/index.tsx b/tgui/packages/tgui/interfaces/Orbit/index.tsx index 87ad40679c4f..adde09ae3401 100644 --- a/tgui/packages/tgui/interfaces/Orbit/index.tsx +++ b/tgui/packages/tgui/interfaces/Orbit/index.tsx @@ -295,7 +295,6 @@ const ObservableContent = () => { return ( Date: Mon, 1 Jul 2024 19:02:53 +0100 Subject: [PATCH 45/52] hng --- code/modules/borer/borer.dm | 6 ++++++ code/modules/mob/holder.dm | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index 3414675c2f3f..baa9ddd94174 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -62,6 +62,12 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) impulse_broadcast("The Cortical Directive has changed.") impulse_broadcast(new_directive, size = "Small") +/obj/item/holder/borer + name = "cortical borer" + desc = "Gross..." + icon = 'icons/mob/brainslug.dmi' + icon_state = "Borer Dead" + /mob/living/captive_brain name = "captive mind" real_name = "captive mind" diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index d5adf3c91f53..bcee5b81a100 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -126,9 +126,3 @@ /obj/item/holder/mouse/brown/Tom name = "Tom" desc = "Jerry the cat is not amused." - -/obj/item/holder/borer - name = "cortical borer" - desc = "Gross..." - icon = 'icons/mob/brainslug.dmi' - icon_state = "Borer Dead" From d558e589525aad8128b4beaec0e485cdbce20d26 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Sat, 13 Jul 2024 02:57:00 +0100 Subject: [PATCH 46/52] boop --- code/modules/borer/borer_chemicals.dm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index 9f2e8f8bf3c9..0cc3c7034e5f 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -33,6 +33,14 @@ description = "A biosynthetic agent that mends damage tissue while creating a toxic byproduct." properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_TRANSFORMATIVE = 2, PROPERTY_INTRAVENOUS = 1) +/datum/reagent/borer/super_brain + name = "Synaptic Boost" + id = "borersuperbrain" + description = "An unusual bio-agent that appears to enhance the brain function of subjects. Lethal in high doses." + color = "#076e4c" + overdose = LOW_REAGENTS_OVERDOSE + overdose_critical = LOW_REAGENTS_OVERDOSE + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ENCEPHALOPHRASIVE = 1, PROPERTY_PAINKILLING = 1, PROPERTY_NEUROPEUTIC = 2) ////////////// BORER CHEM DATUMS USED IN THE SYNTHESISER MENU /////////////////////// @@ -181,6 +189,15 @@ category = BORER_CAT_PUNISH impure = FALSE +/datum/borer_chem/human/super_brain + chem_name = "Synaptic Boost" + chem_id = "borersuperbrain" + desc = "A biological agent that boosts a subject's brain function, repairing damage and causing a mild form of telepathy." + cost = 300 + quantity = 3 + category = BORER_CAT_STIM + impure = FALSE + //Yautja chemicals /datum/borer_chem/yautja species = SPECIES_YAUTJA From f90c33f1b4c9eebafa887aa698e396ae596aedc8 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 16 Jul 2024 03:21:55 +0100 Subject: [PATCH 47/52] fixes --- code/modules/borer/borer.dm | 6 ++---- code/modules/borer/borer_chemicals.dm | 8 ++++---- code/modules/borer/borer_procs.dm | 11 ++++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index baa9ddd94174..bbba8aed68f0 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -1,6 +1,7 @@ /datum/borer_brainlink var/list/living_borers = list() var/list/datum/borer_chem/borer_chemicals = list() + var/list/datum/borer_chem/synthesized_chems = list() var/cortical_directive = "Seek hosts and spread. Avoid detection where possible. Do not assume control without need." // Default directive. var/hardmode = FALSE var/pulse_triggered = FALSE @@ -29,9 +30,8 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) if(!pulse_triggered && (the_dead.generation <= 1)) for(var/mob/living/carbon/cortical_borer/borer in living_borers) if(borer.generation <= 1) - continue + break death_pulse(DEATH_CAUSE_PRIMARIES) - break return /datum/borer_brainlink/proc/death_pulse(source = DEATH_CAUSE_UNKNOWN) @@ -205,8 +205,6 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /// Whether the borer can create chemicals that are marked as restricted. var/restricted_chems_allowed = FALSE - var/list/datum/borer_chem/synthesized_chems = list() - var/current_actions = ACTION_SET_HOSTLESS var/list/actions_hostless = list( /datum/action/innate/borer/helpme, diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index 0cc3c7034e5f..e150e63f72f8 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -16,7 +16,7 @@ name = "Anti-Enzyme" id = "borercure" description = "An anti-parasite drug synthesised from parastic enzymes. Effectively fights toxins in the bloodstream." - color = "#25c08c" + color = "#177052" overdose = LOW_REAGENTS_OVERDOSE overdose_critical = LOW_REAGENTS_OVERDOSE_CRITICAL properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ANTITOXIN = 4, PROPERTY_ANTIPARASITIC = 2) @@ -25,19 +25,19 @@ name = "Neuroshock" id = "borershock" description = "A biosynthetic nerve agent that stimulates cardiomyocytes in critical condition." - properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_DEFIBRILLATING = 2, PROPERTY_INTRAVENOUS = 1) + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_DEFIBRILLATING = 5, PROPERTY_INTRAVENOUS = 1) /datum/reagent/borer/transformative name = "Biomend" id = "borertransform" - description = "A biosynthetic agent that mends damage tissue while creating a toxic byproduct." + description = "A biosynthetic agent that mends damaged tissue while creating a toxic byproduct." properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_TRANSFORMATIVE = 2, PROPERTY_INTRAVENOUS = 1) /datum/reagent/borer/super_brain name = "Synaptic Boost" id = "borersuperbrain" description = "An unusual bio-agent that appears to enhance the brain function of subjects. Lethal in high doses." - color = "#076e4c" + color = "#32745e" overdose = LOW_REAGENTS_OVERDOSE overdose_critical = LOW_REAGENTS_OVERDOSE properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ENCEPHALOPHRASIVE = 1, PROPERTY_PAINKILLING = 1, PROPERTY_NEUROPEUTIC = 2) diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index 434b67e0be09..b9922ea70fd9 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -666,7 +666,7 @@ var/list/possibilities = list() for(var/datum/borer_chem/chem in GLOB.brainlink.borer_chemicals) possibilities += chem - for(var/datum/borer_chem/chem in src.synthesized_chems) + for(var/datum/borer_chem/chem in GLOB.brainlink.synthesized_chems) possibilities += chem return possibilities @@ -745,7 +745,7 @@ for(var/datum/borer_chem/existing_chem in GLOB.brainlink.borer_chemicals) if(!(existing_chem.chem_id in existing_chems)) existing_chems += existing_chem.chem_id - for(var/datum/borer_chem/existing_chem in synthesized_chems) + for(var/datum/borer_chem/existing_chem in GLOB.brainlink.synthesized_chems) if(!(existing_chem.chem_id in existing_chems)) existing_chems += existing_chem.chem_id @@ -794,8 +794,9 @@ new_chem.cost = ((5 * failure_chance)) new_chem.quantity = (chosen.overdose / 3) - synthesized_chems += new_chem + GLOB.brainlink.synthesized_chems += new_chem to_chat(src, SPAN_XENONOTICE("Replication successful!")) + GLOB.brainlink.impulse_broadcast("[real_name] has replicated [new_chem.chem_name]!", "Small") return TRUE @@ -918,12 +919,12 @@ if(current_chem.chem_id == topic_chem) break if(current_chem.chem_id != topic_chem) - for(var/datum/borer_chem/chem_datum in synthesized_chems) + for(var/datum/borer_chem/chem_datum in GLOB.brainlink.synthesized_chems) current_chem = chem_datum if(current_chem.chem_id == topic_chem) break - if(!current_chem || !host_mob || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) + if(!current_chem.chem_id != topic_chem || !host_mob || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) return FALSE var/datum/reagent/R = GLOB.chemical_reagents_list[current_chem.chem_id] if(enzymes < current_chem.cost) From 2bfe96f7ea9e0e56141ac98c9a37fbfa24641355 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 16 Jul 2024 04:23:01 +0100 Subject: [PATCH 48/52] chem fix --- code/modules/borer/borer_procs.dm | 3 ++- code/modules/mob/language/languages.dm | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index b9922ea70fd9..fadd4b914385 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -924,7 +924,8 @@ if(current_chem.chem_id == topic_chem) break - if(!current_chem.chem_id != topic_chem || !host_mob || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) + if(!current_chem || !host_mob || (borer_flags_status & BORER_STATUS_CONTROLLING) || !src || stat) + to_chat(src, SPAN_WARNING("ERROR: CHEM FAILURE - CONTACT FOREST2001")) return FALSE var/datum/reagent/R = GLOB.chemical_reagents_list[current_chem.chem_id] if(enzymes < current_chem.cost) diff --git a/code/modules/mob/language/languages.dm b/code/modules/mob/language/languages.dm index fc1619e30aa1..92b56b166136 100644 --- a/code/modules/mob/language/languages.dm +++ b/code/modules/mob/language/languages.dm @@ -217,14 +217,14 @@ flags = RESTRICTED|HIVEMIND /datum/language/corticalborer/broadcast(mob/living/carbon/speaker, message, speaker_mask, death) - var/mob/living/carbon/cortical_borer/B + var/mob/living/carbon/cortical_borer/the_borer if(!message) return FALSE if(isborer(speaker)) - B = speaker + the_borer = speaker else if(speaker.has_brain_worms()) - B = speaker.has_brain_worms() - if(B) - speaker_mask = B.real_name + the_borer = speaker.has_brain_worms() + if(the_borer) + speaker_mask = the_borer.real_name if(!speaker_mask) speaker_mask = speaker.real_name From 01e392f8c50f98c204c6b907a99f40c276496d5a Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 16 Jul 2024 06:11:35 +0100 Subject: [PATCH 49/52] more fixes and flags --- code/__DEFINES/borer_defines.dm | 14 +- code/modules/borer/borer.dm | 160 +++++++++--------- code/modules/borer/borer_procs.dm | 79 +++++---- code/modules/borer/borer_wip.dm | 40 +++++ code/modules/mob/living/carbon/human/human.dm | 24 +-- code/modules/mob/living/carbon/human/life.dm | 6 +- .../mob/living/carbon/xenomorph/XenoProcs.dm | 16 +- icons/mob/hud/actions_borer.dmi | Bin 3316 -> 3558 bytes 8 files changed, 196 insertions(+), 143 deletions(-) diff --git a/code/__DEFINES/borer_defines.dm b/code/__DEFINES/borer_defines.dm index 3506d14836b9..32ca6598845b 100644 --- a/code/__DEFINES/borer_defines.dm +++ b/code/__DEFINES/borer_defines.dm @@ -31,27 +31,29 @@ DEFINE_BITFIELD(borer_flags_targets, list( #define BORER_PROCESS_INFESTING (1<<0) /// Middle of taking control of a host body #define BORER_PROCESS_BONDING (1<<1) -/// Middle of leaving a host -#define BORER_PROCESS_LEAVING (1<<2) +/// Sleeps to purify contaminant +#define BORER_ABILITY_HIBERNATING (1<<2) /// Hiding or not. (Changes layer) #define BORER_ABILITY_HIDE (1<<3) -/// Sleeps to purify contaminant -#define BORER_ABILITY_HIBERNATING (1<<4) DEFINE_BITFIELD(borer_flags_actives, list( "PROCESS_INFESTING" = BORER_PROCESS_INFESTING, "PROCESS_BONDING" = BORER_PROCESS_BONDING, - "PROCESS_LEAVING" = BORER_PROCESS_LEAVING, - "ACTIVE_HIDING" = BORER_ABILITY_HIDE, "ACTIVE_HIBERNATING" = BORER_ABILITY_HIBERNATING, + "ACTIVE_HIDING" = BORER_ABILITY_HIDE, )) +///Borer is in control of their host. #define BORER_STATUS_CONTROLLING (1<<0) +///Anti-Parasite or Anti-Enzyme chemicals can stop borers from acting. #define BORER_STATUS_DOCILE (1<<1) +/// Middle of leaving a host +#define BORER_STATUS_LEAVING (1<<2) DEFINE_BITFIELD(borer_flags_status, list( "STATUS_CONTROLLING" = BORER_STATUS_CONTROLLING, "STATUS_DOCILE" = BORER_STATUS_DOCILE, + "STATUS_LEAVING" = BORER_STATUS_LEAVING, )) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index bbba8aed68f0..b156f770a912 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -97,41 +97,41 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) return if(stat == DEAD) return say_dead(message) - var/mob/living/carbon/cortical_borer/B = loc + var/mob/living/carbon/cortical_borer/the_borer = loc to_chat(src, SPAN_BORER("You whisper silently, [message]"), type = MESSAGE_TYPE_RADIO) - to_chat(B.host_mob, SPAN_BORER("The captive mind of [src] whispers, \"[message]\""), type = MESSAGE_TYPE_RADIO) - log_say("BORER: ([key_name(src)] to [key_name(B.host_mob)]) [message]", src) + to_chat(the_borer.host_mob, SPAN_BORER("The captive mind of [src] whispers, \"[message]\""), type = MESSAGE_TYPE_RADIO) + log_say("BORER: ([key_name(src)] to [key_name(the_borer.host_mob)]) [message]", src) for (var/mob/dead in GLOB.dead_mob_list) - var/track_borer = " (F)" + var/track_borer = " (F)" if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message(SPAN_BORER("BORER: ([name] (trapped mind) to [B.real_name][track_borer]) whispers: [message]"), SHOW_MESSAGE_VISIBLE) + dead.show_message(SPAN_BORER("BORER: ([name] (trapped mind) to [the_borer.real_name][track_borer]) whispers: [message]"), SHOW_MESSAGE_VISIBLE) /mob/living/captive_brain/say_understands(mob/other, datum/language/speaking = null) - var/mob/living/carbon/cortical_borer/B = loc - if(!istype(B)) + var/mob/living/carbon/cortical_borer/the_borer = loc + if(!istype(the_borer)) log_debug(EXCEPTION("Trapped mind found without a borer!"), src) return FALSE - return B.host_mob.say_understands(other, speaking) + return the_borer.host_mob.say_understands(other, speaking) /mob/living/captive_brain/emote(act, m_type = 1, message = null, intentional = FALSE, force_silence = FALSE) return /mob/living/captive_brain/resist() - var/mob/living/carbon/cortical_borer/B = loc - if(!istype(B)) + var/mob/living/carbon/cortical_borer/the_borer = loc + if(!istype(the_borer)) log_debug(EXCEPTION("Trapped mind found without a borer!"), src) return FALSE if(resisting_control) to_chat(src, SPAN_DANGER("You stop resisting control.")) - to_chat(B.host_mob, SPAN_XENODANGER("The captive mind of [src] is no longer attempting to resist you.")) + to_chat(the_borer.host_mob, SPAN_XENODANGER("The captive mind of [src] is no longer attempting to resist you.")) resisting_control = FALSE return FALSE to_chat(src, SPAN_HIGHDANGER("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).")) - to_chat(B.host_mob, SPAN_XENOHIGHDANGER("You feel the captive mind of [src] begin to resist your control.")) + to_chat(the_borer.host_mob, SPAN_XENOHIGHDANGER("You feel the captive mind of [src] begin to resist your control.")) resisting_control = TRUE - var/delay = (rand(350,450) + B.host_mob.getBrainLoss()) - addtimer(CALLBACK(src, PROC_REF(return_control), B), delay) + var/delay = (rand(350,450) + the_borer.host_mob.getBrainLoss()) + addtimer(CALLBACK(src, PROC_REF(return_control), the_borer), delay) return TRUE /datum/action/innate/borer/brain_resist @@ -169,6 +169,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) holder_type = /obj/item/holder/borer special_mob = TRUE //shows up in own observe category lighting_alpha = 200 + huggable = FALSE var/generation = 1 var/stealthy = FALSE @@ -185,13 +186,9 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) var/max_enzymes = 500 var/contaminant = 0 //Contaminant builds up on enzyme usage, roughly proportionate to cost of use. var/max_contaminant = 120 //Decreases through hibernation or reproduction. - var/hibernating = FALSE //Usable inside a host, but not when controlling. Allows clearing of impurities. var/mob/living/carbon/host_mob // Carbon host for the brain worm. var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. - var/docile = FALSE // Anti-Parasite or Anti-Enzyme chemicals can stop borers from acting. - var/bonding = FALSE - var/leaving = FALSE var/hiding = FALSE var/can_reproduce = FALSE // Locked to manual override to prevent things getting out of hand. @@ -286,31 +283,31 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) if(ishuman(host_mob)) human_host = host_mob if((human_host.chem_effect_flags & CHEM_EFFECT_ANTI_PARASITE) && (!human_host.reagents.has_reagent("borerenzyme") || human_host.reagents.has_reagent("borercure"))) - if(!docile) + if(!(borer_flags_status & BORER_STATUS_DOCILE)) if(borer_flags_status & BORER_STATUS_CONTROLLING) to_chat(host_mob, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) else to_chat(src, SPAN_XENOHIGHDANGER("You feel the flow of a soporific chemical in your host's blood, lulling you into docility.")) - docile = TRUE + borer_flags_status |= BORER_STATUS_DOCILE else - if(docile) + if(borer_flags_status & BORER_STATUS_DOCILE) if(borer_flags_status & BORER_STATUS_CONTROLLING) to_chat(human_host, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) else to_chat(src, SPAN_XENONOTICE("You shake off your lethargy as the chemical leaves your host's blood.")) - docile = FALSE - if(!hibernating && (enzymes < max_enzymes)) + borer_flags_status &= ~BORER_STATUS_DOCILE + if(!(borer_flags_actives) && (enzymes < max_enzymes)) var/increase = enzyme_rate if(generation <= 1) increase = enzyme_rate * 2 enzymes = min(enzymes + increase, max_enzymes) if(contaminant > 0) - if(hibernating) + if(borer_flags_actives & BORER_ABILITY_HIBERNATING) contaminant = max(contaminant -= 1, 0) else contaminant = max(contaminant -= 0.1, 0) if(borer_flags_status & BORER_STATUS_CONTROLLING) - if(docile) + if(borer_flags_status & BORER_STATUS_DOCILE) to_chat(host_mob, SPAN_WARNING("You are feeling far too docile to continue controlling your host...")) host_mob.release_control() return @@ -427,7 +424,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) else if((enzymes < BORER_LARVAE_COST)) CR = "No" var/bore_status = "AWAKE" - if(hibernating) + if(borer_flags_actives & BORER_ABILITY_HIBERNATING) bore_status = "HIBERNATING" . += "" @@ -463,7 +460,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) if(istype(parsed_language, /datum/language/corticalborer)) parsed_language.broadcast(src, new_message) return - if(hibernating) + if(borer_flags_actives & BORER_ABILITY_HIBERNATING) to_chat(src, SPAN_WARNING("You cannot speak aloud while hibernating!")) return if(loc == host_mob && !talk_inside_host) @@ -480,32 +477,32 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) action_icon_state = "borer_help" /datum/action/innate/borer/helpme/action_activate() - var/mob/living/carbon/cortical_borer/B + var/mob/living/carbon/cortical_borer/the_borer if(!isborer(owner)) if(owner.has_brain_worms()) - B = owner.has_brain_worms() + the_borer = owner.has_brain_worms() else to_chat(owner, SPAN_DANGER("How did you get this command? It's gone now.")) hide_action(owner, /datum/action/innate/borer/helpme) else - B = owner - B.show_help() + the_borer = owner + the_borer.show_help() /datum/action/innate/borer/talk_to_host name = "Converse with Host" action_icon_state = "borer_talk" /datum/action/innate/borer/talk_to_host/action_activate() - var/mob/living/carbon/cortical_borer/B = owner - B.Communicate() + var/mob/living/carbon/cortical_borer/the_borer = owner + the_borer.Communicate() /datum/action/innate/borer/infest_host name = "Infest" action_icon_state = "borer_infest" /datum/action/innate/borer/infest_host/action_activate() - var/mob/living/carbon/cortical_borer/B = owner - B.infest() + var/mob/living/carbon/cortical_borer/the_borer = owner + the_borer.infest() /datum/action/innate/borer/toggle_hide name = "Toggle Hide" @@ -513,29 +510,29 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/toggle_hide/action_activate() if(!isborer(owner)) return FALSE - var/mob/living/carbon/cortical_borer/B = owner - B.hide_borer() + var/mob/living/carbon/cortical_borer/the_borer = owner + the_borer.hide_borer() button.overlays.Cut() - button.overlays += image('icons/mob/hud/actions_borer.dmi', button, "borer_hiding_[B.hiding]") + button.overlays += image('icons/mob/hud/actions_borer.dmi', button, "borer_hiding_[the_borer.hiding]") /datum/action/innate/borer/talk_to_borer name = "Converse with Borer" action_icon_state = "borer_talk" /datum/action/innate/borer/talk_to_borer/action_activate() - var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host_mob = owner - B.host_mob.borer_comm() + var/mob/living/carbon/cortical_borer/the_borer = owner.has_brain_worms() + the_borer.host_mob = owner + the_borer.host_mob.borer_comm() /datum/action/innate/borer/talk_to_brain name = "Converse with Trapped Mind" action_icon_state = "borer_talk" /datum/action/innate/borer/talk_to_brain/action_activate() - var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host_mob = owner - B.host_mob.trapped_mind_comm() + var/mob/living/carbon/cortical_borer/the_borer = owner.has_brain_worms() + the_borer.host_mob = owner + the_borer.host_mob.trapped_mind_comm() /datum/action/innate/borer/take_control name = "Assume Control" @@ -543,20 +540,20 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/take_control/action_activate() if(!isborer(owner)) return FALSE - var/mob/living/carbon/cortical_borer/B = owner - if(B.hibernating) - to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + var/mob/living/carbon/cortical_borer/the_borer = owner + if(the_borer.borer_flags_actives & BORER_ABILITY_HIBERNATING) + to_chat(the_borer, SPAN_WARNING("You cannot do that while hibernating!")) return - B.bond_brain() + the_borer.bond_brain() /datum/action/innate/borer/give_back_control name = "Release Control" action_icon_state = "borer_leave" /datum/action/innate/borer/give_back_control/action_activate() - var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host_mob = owner - B.host_mob.release_control() + var/mob/living/carbon/cortical_borer/the_borer = owner.has_brain_worms() + the_borer.host_mob = owner + the_borer.host_mob.release_control() /datum/action/innate/borer/leave_body name = "Leave Host" @@ -564,11 +561,11 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/leave_body/action_activate() if(!isborer(owner)) return FALSE - var/mob/living/carbon/cortical_borer/B = owner - if(B.hibernating) - to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + var/mob/living/carbon/cortical_borer/the_borer = owner + if(the_borer.borer_flags_actives & BORER_ABILITY_HIBERNATING) + to_chat(the_borer, SPAN_WARNING("You cannot do that while hibernating!")) return - B.release_host() + the_borer.release_host() /datum/action/innate/borer/make_chems name = "Secrete Chemicals" @@ -576,11 +573,11 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/make_chems/action_activate() if(!isborer(owner)) return FALSE - var/mob/living/carbon/cortical_borer/B = owner - if(B.hibernating) - to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + var/mob/living/carbon/cortical_borer/the_borer = owner + if(the_borer.borer_flags_actives & BORER_ABILITY_HIBERNATING) + to_chat(the_borer, SPAN_WARNING("You cannot do that while hibernating!")) return - B.secrete_chemicals() + the_borer.secrete_chemicals() /datum/action/innate/borer/scan_chems name = "Scan Chemicals" @@ -588,11 +585,11 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/scan_chems/action_activate() if(!isborer(owner)) return FALSE - var/mob/living/carbon/cortical_borer/B = owner - if(B.hibernating) - to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + var/mob/living/carbon/cortical_borer/the_borer = owner + if(the_borer.borer_flags_actives & BORER_ABILITY_HIBERNATING) + to_chat(the_borer, SPAN_WARNING("You cannot do that while hibernating!")) return - borerscan(B, B.host_mob) + borerscan(the_borer, the_borer.host_mob) /datum/action/innate/borer/learn_chems name = "Learn Chemicals" @@ -600,52 +597,55 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) /datum/action/innate/borer/learn_chems/action_activate() if(!isborer(owner)) return FALSE - var/mob/living/carbon/cortical_borer/B = owner - if(B.hibernating) - to_chat(B, SPAN_WARNING("You cannot do that while hibernating!")) + var/mob/living/carbon/cortical_borer/the_borer = owner + if(the_borer.borer_flags_actives & BORER_ABILITY_HIBERNATING) + to_chat(the_borer, SPAN_WARNING("You cannot do that while hibernating!")) return - B.learn_chemicals() + the_borer.learn_chemicals() /datum/action/innate/borer/make_larvae name = "Reproduce" action_icon_state = "borer_reproduce" /datum/action/innate/borer/make_larvae/action_activate() - var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host_mob = owner - B.host_mob.spawn_larvae() + var/mob/living/carbon/cortical_borer/the_borer = owner.has_brain_worms() + the_borer.host_mob = owner + the_borer.host_mob.spawn_larvae() /datum/action/innate/borer/freeze_victim name = "Dominate Victim" action_icon_state = "borer_stun" /datum/action/innate/borer/freeze_victim/action_activate() - var/mob/living/carbon/cortical_borer/B = owner - B.dominate_victim() + var/mob/living/carbon/cortical_borer/the_borer = owner + the_borer.dominate_victim() /datum/action/innate/borer/torment name = "Torment Host" action_icon_state = "borer_torment" /datum/action/innate/borer/torment/action_activate() - var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.host_mob = owner - B.host_mob.punish_host() + var/mob/living/carbon/cortical_borer/the_borer = owner.has_brain_worms() + the_borer.host_mob = owner + the_borer.host_mob.punish_host() /datum/action/innate/borer/hibernate name = "Toggle Hibernation" action_icon_state = "borer_sleeping_0" /datum/action/innate/borer/hibernate/action_activate() - var/mob/living/carbon/cortical_borer/B = owner - B.hibernate() + var/mob/living/carbon/cortical_borer/the_borer = owner + the_borer.hibernate() button.overlays.Cut() - button.overlays += image('icons/mob/hud/actions_borer.dmi', button, "borer_sleeping_[B.hibernating]") + var/is_hibernating = FALSE + if(the_borer.borer_flags_actives & BORER_ABILITY_HIBERNATING) + is_hibernating = TRUE + button.overlays += image('icons/mob/hud/actions_borer.dmi', button, "borer_sleeping_[is_hibernating]") /datum/action/innate/borer/transfer_host name = "Transfer Host" action_icon_state = "borer_infest" /datum/action/innate/borer/transfer_host/action_activate() - var/mob/living/carbon/cortical_borer/B = owner.has_brain_worms() - B.transfer_host() + var/mob/living/carbon/cortical_borer/the_borer = owner.has_brain_worms() + the_borer.transfer_host() diff --git a/code/modules/borer/borer_procs.dm b/code/modules/borer/borer_procs.dm index fadd4b914385..628a276f3476 100644 --- a/code/modules/borer/borer_procs.dm +++ b/code/modules/borer/borer_procs.dm @@ -189,8 +189,12 @@ return TRUE /mob/living/carbon/cortical_borer/proc/hibernate() - hibernating = !hibernating - if(hibernating) + if(borer_flags_actives & BORER_ABILITY_HIBERNATING) + borer_flags_actives &= ~BORER_ABILITY_HIBERNATING + else + borer_flags_actives |= BORER_ABILITY_HIBERNATING + + if(borer_flags_actives & BORER_ABILITY_HIBERNATING) to_chat(src, SPAN_XENONOTICE("You are now hibernating! Your body will dissolve impurities built up from the creation of chemicals, however your enzyme reserves will not replenish. You cannot act beyond communicating whilst in hibernation.")) sleeping = 2 else @@ -302,24 +306,24 @@ if(stat) to_chat(src, SPAN_XENOWARNING("You cannot leave your host in your current state.")) return FALSE - if(docile) + if(borer_flags_status & BORER_STATUS_DOCILE) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) return FALSE if(!host_mob || !src) return FALSE - if(leaving) - leaving = FALSE + if(borer_flags_status & BORER_STATUS_LEAVING) + borer_flags_status &= ~BORER_STATUS_LEAVING to_chat(src, SPAN_XENOWARNING("You decide against leaving your host.")) return TRUE to_chat(src, SPAN_XENOHIGHDANGER("You begin disconnecting from [host_mob]'s synapses and prodding at their internal ear canal.")) - leaving = TRUE + borer_flags_status |= BORER_STATUS_LEAVING addtimer(CALLBACK(src, PROC_REF(let_go)), 200) return TRUE /mob/living/carbon/cortical_borer/proc/let_go() if(!host_mob || !src || QDELETED(host_mob) || QDELETED(src)) return FALSE - if(!leaving || borer_flags_status & BORER_STATUS_CONTROLLING) + if(!(borer_flags_status & BORER_STATUS_LEAVING) || borer_flags_status & BORER_STATUS_CONTROLLING) return FALSE if(stat) to_chat(src, SPAN_XENOWARNING("You cannot release a target in your current state.")) @@ -327,7 +331,7 @@ to_chat(src, SPAN_XENOHIGHDANGER("You wiggle out of [host_mob]'s ear and plop to the ground.")) - leaving = FALSE + borer_flags_status &= ~BORER_STATUS_LEAVING leave_host() return TRUE @@ -372,12 +376,12 @@ to_chat(src, SPAN_XENOWARNING("You cannot do that in your current state.")) return FALSE - if(docile) + if(borer_flags_status & BORER_STATUS_DOCILE) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) return FALSE - if(bonding) - bonding = FALSE + if(borer_flags_actives & BORER_PROCESS_BONDING) + borer_flags_actives &= ~BORER_PROCESS_BONDING to_chat(src, SPAN_XENOWARNING("You stop attempting to take control of your host.")) return FALSE @@ -386,7 +390,7 @@ if(QDELETED(src) || QDELETED(host_mob)) return FALSE - bonding = TRUE + borer_flags_actives |= BORER_PROCESS_BONDING var/delay = 300+(host_mob.getBrainLoss()*5) addtimer(CALLBACK(src, PROC_REF(assume_control)), delay) @@ -395,9 +399,9 @@ /mob/living/carbon/cortical_borer/proc/assume_control() if(!host_mob || !src || borer_flags_status & BORER_STATUS_CONTROLLING) return FALSE - if(!bonding) + if(!(borer_flags_actives & BORER_PROCESS_BONDING)) return FALSE - if(docile) + if(borer_flags_status & BORER_STATUS_DOCILE) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) return FALSE else @@ -439,7 +443,7 @@ if(!host_mob.lastKnownIP) host_mob.lastKnownIP = s2h_ip - bonding = FALSE + borer_flags_actives &= ~BORER_PROCESS_BONDING borer_flags_status |= BORER_STATUS_CONTROLLING give_new_actions(ACTION_SET_CONTROL) @@ -453,14 +457,14 @@ return TRUE //Captive mind reclaims their body. -/mob/living/captive_brain/proc/return_control(mob/living/carbon/cortical_borer/B) - if(!B || !(B.borer_flags_status & BORER_STATUS_CONTROLLING) || !resisting_control) +/mob/living/captive_brain/proc/return_control(mob/living/carbon/cortical_borer/the_borer) + if(!the_borer || !(the_borer.borer_flags_status & BORER_STATUS_CONTROLLING) || !resisting_control) return FALSE - B.host_mob.adjustBrainLoss(rand(5,10)) + the_borer.host_mob.adjustBrainLoss(rand(5,10)) to_chat(src, SPAN_HIGHDANGER("With an immense exertion of will, you regain control of your body!")) - to_chat(B.host_mob, SPAN_XENOHIGHDANGER("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) + to_chat(the_borer.host_mob, SPAN_XENOHIGHDANGER("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.")) resisting_control = FALSE - B.detach() + the_borer.detach() return TRUE ///Brain slug proc for voluntary removal of control. @@ -470,12 +474,12 @@ set name = "Release Control" set desc = "Release control of your host's body." - var/mob/living/carbon/cortical_borer/B = has_brain_worms() + var/mob/living/carbon/cortical_borer/the_borer = has_brain_worms() - if(B && B.host_brain) - to_chat(src, SPAN_XENONOTICE("You withdraw your probosci, releasing control of [B.host_brain]")) + if(the_borer && the_borer.host_brain) + to_chat(src, SPAN_XENONOTICE("You withdraw your probosci, releasing control of [the_borer.host_brain]")) - B.detach() + the_borer.detach() else log_debug(EXCEPTION("Missing borer or missing host brain upon borer release."), src) @@ -618,14 +622,14 @@ set name = "Torment Host" set desc = "Punish your host with agony." - var/mob/living/carbon/cortical_borer/B = has_brain_worms() + var/mob/living/carbon/cortical_borer/the_borer = has_brain_worms() - if(!B) + if(!the_borer) return FALSE - if(B.host_brain) + if(the_borer.host_brain) to_chat(src, SPAN_XENONOTICE("You send a punishing spike of psychic agony lancing into your host's brain.")) - to_chat(B.host_brain, SPAN_HIGHDANGER("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")) + to_chat(the_borer.host_brain, SPAN_HIGHDANGER("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")) return TRUE @@ -683,7 +687,7 @@ to_chat(src, SPAN_XENOWARNING("You cannot secrete chemicals in your current state.")) return FALSE - if(docile) + if(borer_flags_status & BORER_STATUS_DOCILE) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) return FALSE @@ -731,7 +735,7 @@ to_chat(src, SPAN_XENOWARNING("You cannot replicate chemicals in your current state.")) return FALSE - if(docile) + if(borer_flags_status & BORER_STATUS_DOCILE) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) return FALSE @@ -791,8 +795,15 @@ n_species = "UNSET" new_chem.species = n_species - new_chem.cost = ((5 * failure_chance)) - new_chem.quantity = (chosen.overdose / 3) + var/new_cost = (5 * failure_chance) + if(!new_cost) + new_cost = 20 + new_chem.cost = new_cost + + var/new_quantity = chosen.overdose / 3 + if(!new_quantity) + new_quantity = 10 + new_chem.quantity = new_quantity GLOB.brainlink.synthesized_chems += new_chem to_chat(src, SPAN_XENONOTICE("Replication successful!")) @@ -824,7 +835,7 @@ return FALSE if(src && !QDELETED(src) && !QDELETED(host_mob)) - var/say_string = (docile) ? "slurs" :"states" + var/say_string = (borer_flags_status & BORER_STATUS_DOCILE) ? "slurs" :"states" if(host_mob) to_chat(host_mob, SPAN_XENO("[real_name] [say_string]: [input]"), type = MESSAGE_TYPE_RADIO) show_blurb(host_mob, 15, input, TRUE, "center", "center", COLOR_BROWN, null, null, 1) @@ -907,7 +918,7 @@ locate(href_list["src"]) if(!isborer(src)) return FALSE - if(docile) + if(borer_flags_status & BORER_STATUS_DOCILE) to_chat(src, SPAN_XENOWARNING("You are feeling far too docile to do that.")) return FALSE diff --git a/code/modules/borer/borer_wip.dm b/code/modules/borer/borer_wip.dm index adb30b04166a..da7a87fefcaa 100644 --- a/code/modules/borer/borer_wip.dm +++ b/code/modules/borer/borer_wip.dm @@ -51,3 +51,43 @@ leave_host() perform_infestation(target) return TRUE + + +/mob/living/carbon/cortical_borer/proc/make_alpha() + real_name = "Alpha" + generation = 0 + can_reproduce = 2 + max_contaminant = 500 + max_enzymes = 2000 + maxHealth = 500 + health = 500 + + actions_hostless += /datum/action/innate/borer/update_directive + actions_humanoidhost += /datum/action/innate/borer/update_directive + actions_xenohost += /datum/action/innate/borer/update_directive + actions_control += /datum/action/innate/borer/update_directive + give_action(src, /datum/action/innate/borer/update_directive) + + +/datum/action/innate/borer/update_directive + name = "Change Directive" + action_icon_state = "borer_directive" + +/datum/action/innate/borer/update_directive/action_activate() + var/mob/living/carbon/cortical_borer/the_borer = owner + the_borer.update_directive() + +/mob/living/carbon/cortical_borer/proc/update_directive() + set category = "Borer.Misc" + set name = "Update Directive" + set desc = "Update the Cortical Directive." + + if(generation > 0) + to_chat(src, SPAN_BOLDWARNING("You cannot update the directive, you are not the Alpha!")) + return FALSE + + var/new_directive = tgui_input_text(src, "What should the new directive be?", "Cortical Directive", GLOB.brainlink.cortical_directive) + if(!new_directive || new_directive == GLOB.brainlink.cortical_directive) + return FALSE + + GLOB.brainlink.update_directive(new_directive) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c45ab73f13b0..9af0e9e22f87 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -132,23 +132,23 @@ if(SShijack.sd_unlocked) . += "Self Destruct Status: [SShijack.get_sd_eta()]" - var/mob/living/carbon/cortical_borer/B = has_brain_worms() - if(B && (B.borer_flags_status & BORER_STATUS_CONTROLLING)) + var/mob/living/carbon/cortical_borer/the_borer = has_brain_worms() + if(the_borer && (the_borer.borer_flags_status & BORER_STATUS_CONTROLLING)) var/CR = "Yes" - if(!B.can_reproduce) + if(!the_borer.can_reproduce) CR = "Forbidden" - else if((B.enzymes < BORER_LARVAE_COST)) + else if((the_borer.enzymes < BORER_LARVAE_COST)) CR = "No" . += "" . += "Cortical Directive: [GLOB.brainlink.cortical_directive]" . += "Borer: CONTROLLING" - . += "Name: [B.real_name]" + . += "Name: [the_borer.real_name]" . += "Can Reproduce: [CR]" - . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" - . += "Health: [B.health]/[B.maxHealth]" - . += "Injuries: Brute:[round(B.getBruteLoss())] Burn:[round(B.getFireLoss())] Toxin:[round(B.getToxLoss())]" + . += "Enzymes: [round(the_borer.enzymes)]/[round(the_borer.max_enzymes)]" + . += "Health: [the_borer.health]/[the_borer.maxHealth]" + . += "Injuries: Brute:[round(the_borer.getBruteLoss())] Burn:[round(the_borer.getFireLoss())] Toxin:[round(the_borer.getToxLoss())]" . += "" . += "Host Brain Damage: [brainloss]/100" . += "Host Blood Level: [blood_volume / 5.6]%" @@ -1734,15 +1734,15 @@ /mob/living/carbon/human/on_knockedout_trait_gain(datum/source) . = ..() - + update_execute_hud() - + return . /mob/living/carbon/human/on_knockedout_trait_loss(datum/source) . = ..() update_execute_hud() - + return . - + diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index a8a4dbf71c01..5608373977de 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -66,9 +66,9 @@ if(life_tick > 5 && timeofdeath && (timeofdeath < 5 || world.time - timeofdeath > revive_grace_period) && !issynth(src)) //We are dead beyond revival, or we're junk mobs spawned like the clowns on the clown shuttle undefibbable = TRUE SEND_SIGNAL(src, COMSIG_HUMAN_SET_UNDEFIBBABLE) - var/mob/living/carbon/cortical_borer/B = has_brain_worms() - if(B) - B.host_death(TRUE) + var/mob/living/carbon/cortical_borer/the_borer = has_brain_worms() + if(the_borer) + the_borer.host_death(TRUE) med_hud_set_status() else if(stat != DEAD) diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index 9c5786066328..698a44e16734 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -145,23 +145,23 @@ else . += "Hive Orders: -" - var/mob/living/carbon/cortical_borer/B = has_brain_worms() - if(B && (B.borer_flags_status & BORER_STATUS_CONTROLLING)) + var/mob/living/carbon/cortical_borer/the_borer = has_brain_worms() + if(the_borer && (the_borer.borer_flags_status & BORER_STATUS_CONTROLLING)) var/CR = "Yes" - if(!B.can_reproduce) + if(!the_borer.can_reproduce) CR = "Forbidden" - else if((B.enzymes < BORER_LARVAE_COST)) + else if((the_borer.enzymes < BORER_LARVAE_COST)) CR = "No" . += "" . += "Cortical Directive: [GLOB.brainlink.cortical_directive]" . += "Borer: CONTROLLING" - . += "Name: [B.real_name]" + . += "Name: [the_borer.real_name]" . += "Can Reproduce: [CR]" - . += "Enzymes: [round(B.enzymes)]/[round(B.max_enzymes)]" - . += "Health: [B.health]/[B.maxHealth]" - . += "Injuries: Brute:[round(B.getBruteLoss())] Burn:[round(B.getFireLoss())] Toxin:[round(B.getToxLoss())]" + . += "Enzymes: [round(the_borer.enzymes)]/[round(the_borer.max_enzymes)]" + . += "Health: [the_borer.health]/[the_borer.maxHealth]" + . += "Injuries: Brute:[round(the_borer.getBruteLoss())] Burn:[round(the_borer.getFireLoss())] Toxin:[round(the_borer.getToxLoss())]" . += "" . += "Host Plasma: [plasma_stored]/[plasma_max]" . += "Host Integrity: [health]/[maxHealth]" diff --git a/icons/mob/hud/actions_borer.dmi b/icons/mob/hud/actions_borer.dmi index eca5c660e327957bcb0e73d0c84f36c0a651185b..2034ad2e6a21a83b2ddc116821d846820e32d65f 100644 GIT binary patch delta 3336 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 i`u+aaT5Ik9Z2tj3dAe4T0`Xn|0000 Date: Tue, 16 Jul 2024 06:21:20 +0100 Subject: [PATCH 50/52] pulse --- code/modules/borer/borer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index b156f770a912..c07287986b99 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -43,7 +43,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) if(DEATH_CAUSE_UNKNOWN) death_message += " The devastation is unprecedented, and the cause unclear..." impulse_broadcast(death_message) - for(var/mob/living/borer in living_borers) + for(var/mob/living/carbon/cortical_borer/borer/borer in living_borers) borer.death(create_cause_data("Cortical Link Collapse")) /datum/borer_brainlink/proc/generate_borer_chems() From 90ede70f7eed2fae7b10aff483aede15fbc7f35f Mon Sep 17 00:00:00 2001 From: forest2001 Date: Tue, 16 Jul 2024 06:37:10 +0100 Subject: [PATCH 51/52] x --- code/modules/borer/borer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/borer/borer.dm b/code/modules/borer/borer.dm index c07287986b99..cca19c96b364 100644 --- a/code/modules/borer/borer.dm +++ b/code/modules/borer/borer.dm @@ -43,7 +43,7 @@ GLOBAL_DATUM_INIT(brainlink, /datum/borer_brainlink, new) if(DEATH_CAUSE_UNKNOWN) death_message += " The devastation is unprecedented, and the cause unclear..." impulse_broadcast(death_message) - for(var/mob/living/carbon/cortical_borer/borer/borer in living_borers) + for(var/mob/living/carbon/cortical_borer/borer in living_borers) borer.death(create_cause_data("Cortical Link Collapse")) /datum/borer_brainlink/proc/generate_borer_chems() From 9c9dfb571c4e714542fe96effd3e2c31745591b2 Mon Sep 17 00:00:00 2001 From: forest2001 Date: Wed, 17 Jul 2024 01:00:00 +0100 Subject: [PATCH 52/52] synapse duration --- code/modules/borer/borer_chemicals.dm | 2 +- code/modules/borer/borer_wip.dm | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/code/modules/borer/borer_chemicals.dm b/code/modules/borer/borer_chemicals.dm index e150e63f72f8..bbaacb43b8f6 100644 --- a/code/modules/borer/borer_chemicals.dm +++ b/code/modules/borer/borer_chemicals.dm @@ -40,7 +40,7 @@ color = "#32745e" overdose = LOW_REAGENTS_OVERDOSE overdose_critical = LOW_REAGENTS_OVERDOSE - properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ENCEPHALOPHRASIVE = 1, PROPERTY_PAINKILLING = 1, PROPERTY_NEUROPEUTIC = 2) + properties = list(PROPERTY_CROSSMETABOLIZING = 2, PROPERTY_ENCEPHALOPHRASIVE = 1, PROPERTY_PAINKILLING = 1, PROPERTY_NEUROPEUTIC = 2, PROPERTY_HYPOMETABOLIC = 4) ////////////// BORER CHEM DATUMS USED IN THE SYNTHESISER MENU /////////////////////// diff --git a/code/modules/borer/borer_wip.dm b/code/modules/borer/borer_wip.dm index da7a87fefcaa..67421ed34f86 100644 --- a/code/modules/borer/borer_wip.dm +++ b/code/modules/borer/borer_wip.dm @@ -59,8 +59,10 @@ can_reproduce = 2 max_contaminant = 500 max_enzymes = 2000 + enzyme_rate = 3 maxHealth = 500 health = 500 + restricted_chems_allowed = TRUE actions_hostless += /datum/action/innate/borer/update_directive actions_humanoidhost += /datum/action/innate/borer/update_directive