From 69746693b5aa10cf33a0df3f844bc41b9393b2ac Mon Sep 17 00:00:00 2001 From: Geeves Date: Fri, 15 May 2020 22:39:32 +0200 Subject: [PATCH] Borer Tweaks and Changes (#8682) Spawned borers now get added to the Ghostspawner menu, allowing players to inhabit them even if they didn't catch the original request. Borers have gained the ability to survey their host's health, allowing them to better choose when to administer certain chemicals. Borers now regenerate chemicals even if their host is unconscious. Awakening psionics now take 15 seconds instead of 10, and the host now gets a message about feeling something bad coming on, allowing them to make a dash to safety and or seclusion. Skrell returning from Srom no longer eject controlling borers to the lobby by replacing their ckey into the aether. Skrell no longer spontaneously die when entering Srom on a map that doesn't have a Srom location. --- aurorastation.dme | 1 + code/controllers/subsystems/ghostroles.dm | 30 +++++++++++++++++++ code/game/antagonist/alien/borer.dm | 4 +-- code/game/jobs/whitelist.dm | 3 ++ code/game/objects/items/devices/scanners.dm | 21 ++++++------- code/modules/ghostroles/spawner/base.dm | 6 ++++ .../modules/ghostroles/spawner/human/golem.dm | 12 ++------ .../ghostroles/spawner/simplemob/borer.dm | 24 +++++++++++++++ code/modules/mob/living/carbon/slime/items.dm | 18 ++--------- .../mob/living/simple_animal/borer/borer.dm | 28 ++++++++++------- .../simple_animal/borer/borer_powers.dm | 19 ++++++++++-- code/modules/shareddream/dream_entry.dm | 17 +++++++++-- html/changelogs/geeves-borer_stuff.yml | 11 +++++++ 13 files changed, 143 insertions(+), 51 deletions(-) create mode 100644 code/modules/ghostroles/spawner/simplemob/borer.dm create mode 100644 html/changelogs/geeves-borer_stuff.yml diff --git a/aurorastation.dme b/aurorastation.dme index a4b5cddfe62..efa7ecfef51 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -1587,6 +1587,7 @@ #include "code\modules\ghostroles\spawner\human\responseteams\response_team.dm" #include "code\modules\ghostroles\spawner\human\responseteams\syndicate.dm" #include "code\modules\ghostroles\spawner\human\responseteams\tcfl.dm" +#include "code\modules\ghostroles\spawner\simplemob\borer.dm" #include "code\modules\ghostroles\spawner\simplemob\maintdrone.dm" #include "code\modules\ghostroles\spawner\simplemob\rat.dm" #include "code\modules\ghostroles\spawner\simplemob\spider.dm" diff --git a/code/controllers/subsystems/ghostroles.dm b/code/controllers/subsystems/ghostroles.dm index f4077093f43..b6274eabe09 100644 --- a/code/controllers/subsystems/ghostroles.dm +++ b/code/controllers/subsystems/ghostroles.dm @@ -2,6 +2,7 @@ /datum/controller/subsystem/ghostroles name = "Ghost Roles" + init_order = SS_INIT_JOBS flags = SS_NO_FIRE var/list/list/spawnpoints = list() //List of the available spawnpoints by spawnpoint type @@ -10,6 +11,10 @@ var/list/spawners = list() //List of the available spawner datums + // For special spawners that have mobile or object spawnpoints + var/list/spawn_types = list("Golems", "Borers") + var/list/spawn_atom = list() + /datum/controller/subsystem/ghostroles/Recover() src.spawnpoints = SSghostroles.spawnpoints src.spawners = SSghostroles.spawners @@ -36,6 +41,9 @@ CHECK_TICK update_spawnpoint_status_by_identifier(identifier) + for(var/spawn_type in spawn_types) + spawn_atom[spawn_type] = list() + //Adds a spawnpoint to the spawnpoint list /datum/controller/subsystem/ghostroles/proc/add_spawnpoints(var/obj/effect/ghostspawpoint/P) if(!P.identifier) //If the spawnpoint has no identifier -> Abort @@ -177,3 +185,25 @@ for(var/i in S.spawnpoints) update_spawnpoint_status_by_identifier(i) return + +/datum/controller/subsystem/ghostroles/proc/add_spawn_atom(var/ghost_role_name, var/atom/spawn_atom) + if(ghost_role_name && spawn_atom) + var/datum/ghostspawner/G = spawners[ghost_role_name] + if(G) + G.spawn_atoms += spawn_atom + if(length(G.spawn_atoms) == 1) + G.enable() + +/datum/controller/subsystem/ghostroles/proc/remove_spawn_atom(var/ghost_role_name, var/atom/spawn_atom) + if(ghost_role_name && spawn_atom) + var/datum/ghostspawner/G = spawners[ghost_role_name] + if(G) + G.spawn_atoms -= spawn_atom + if(!length(G.spawn_atoms)) + G.disable() + +/datum/controller/subsystem/ghostroles/proc/get_spawn_atoms(var/ghost_role_name) + var/datum/ghostspawner/G = spawners[ghost_role_name] + if(G) + return G.spawn_atoms + return list() diff --git a/code/game/antagonist/alien/borer.dm b/code/game/antagonist/alien/borer.dm index 97fb9fc08e1..6487bdb8f39 100644 --- a/code/game/antagonist/alien/borer.dm +++ b/code/game/antagonist/alien/borer.dm @@ -4,7 +4,7 @@ var/datum/antagonist/xenos/borer/borers id = MODE_BORER role_text = "Cortical Borer" role_text_plural = "Cortical Borers" - mob_path = /mob/living/simple_animal/borer + mob_path = /mob/living/simple_animal/borer/roundstart bantype = "Borer" welcome_text = "Use your Infest power to crawl into the ear of a host and fuse with their brain. You can only take control temporarily, and at risk of hurting your host, so be clever and careful; your host is encouraged to help you however they can. Talk to your fellow borers with ,x." antag_indicator = "brainworm" @@ -65,4 +65,4 @@ var/datum/antagonist/xenos/borer/borers var/obj/item/organ/external/head = borer.host.get_organ(BP_HEAD) head.implants += borer else - ..() + ..() \ No newline at end of file diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index 272e94f203e..e5e651e99c4 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -122,6 +122,9 @@ var/list/whitelist = list() if (!istype(C) || C.holder) return 0 + if(!dbcon.IsConnected()) + return TRUE + var/age_to_beat = 0 // Assume it's an antag role. diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 0b04983db58..8c79e007bb0 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -68,18 +68,19 @@ BREATH ANALYZER else . = "moderate" -/proc/health_scan_mob(var/mob/M, var/mob/living/user, var/show_limb_damage = TRUE) - if (((user.is_clumsy()) || (DUMB in user.mutations)) && prob(50)) - user.visible_message("\The [user] runs the scanner over the floor.", "You run the scanner over the floor.", "You hear metal repeatedly clunking against the floor.") - to_chat(user, "Scan results for the floor:") - to_chat(user, "Overall Status: Healthy") - return +/proc/health_scan_mob(var/mob/M, var/mob/living/user, var/show_limb_damage = TRUE, var/just_scan = FALSE) + if(!just_scan) + if (((user.is_clumsy()) || (DUMB in user.mutations)) && prob(50)) + user.visible_message("\The [user] runs the scanner over the floor.", "You run the scanner over the floor.", "You hear metal repeatedly clunking against the floor.") + to_chat(user, "Scan results for the floor:") + to_chat(user, "Overall Status: Healthy") + return - if(!usr.IsAdvancedToolUser()) - to_chat(usr, "You don't have the dexterity to do this!") - return + if(!usr.IsAdvancedToolUser()) + to_chat(usr, "You don't have the dexterity to do this!") + return - user.visible_message("[user] runs the scanner over [M].","You run the scanner over [M].") + user.visible_message("[user] runs the scanner over [M].","You run the scanner over [M].") if(!istype(M, /mob/living/carbon/human)) to_chat(user, "This scanner is designed for humanoid patients only.") diff --git a/code/modules/ghostroles/spawner/base.dm b/code/modules/ghostroles/spawner/base.dm index be8ab0c54b4..27849a07342 100644 --- a/code/modules/ghostroles/spawner/base.dm +++ b/code/modules/ghostroles/spawner/base.dm @@ -8,6 +8,7 @@ //Vars regarding the spawnpoints and conditions of the spawner var/list/spawnpoints = null //List of the applicable spawnpoints (by name) + var/list/spawn_atoms = list() // List of atoms you can spawn at var/landmark_name = null //Alternatively you can specify a landmark name var/max_count = 0 //How often can this spawner be used var/count = 0 //How ofen has this spawner been used @@ -94,6 +95,11 @@ //This proc selects the spawnpoint to use. /datum/ghostspawner/proc/select_spawnpoint(var/use=TRUE) + if(length(spawn_atoms)) + var/chosen_spawn_atom = pick(spawn_atoms) + var/turf/T = get_turf(chosen_spawn_atom) + if(T) + return T if(!isnull(spawnpoints)) for(var/spawnpoint in spawnpoints) //Loop through the applicable spawnpoints var/turf/T = SSghostroles.get_spawnpoint(spawnpoint, use) //Gets the first matching spawnpoint or null if none are available diff --git a/code/modules/ghostroles/spawner/human/golem.dm b/code/modules/ghostroles/spawner/human/golem.dm index 6a03bd8c370..e1f484a2320 100644 --- a/code/modules/ghostroles/spawner/human/golem.dm +++ b/code/modules/ghostroles/spawner/human/golem.dm @@ -14,18 +14,12 @@ //The proc to actually spawn in the user /datum/ghostspawner/human/golem/spawn_mob(mob/user) - var/obj/effect/golemrune/rune - var/list/global_runes = list() - - for(var/obj/effect/golemrune/eligible_rune in golem_runes) - global_runes += eligible_rune - - if(!length(global_runes)) + if(!length(spawn_atoms)) to_chat(user, span("danger", "There are no available golem runes to spawn at!")) return FALSE - rune = pick(global_runes) + var/obj/effect/golemrune/rune = pick(spawn_atoms) - if(user) + if(user && rune) return rune.spawn_golem(user) return FALSE \ No newline at end of file diff --git a/code/modules/ghostroles/spawner/simplemob/borer.dm b/code/modules/ghostroles/spawner/simplemob/borer.dm new file mode 100644 index 00000000000..14f43abb5d1 --- /dev/null +++ b/code/modules/ghostroles/spawner/simplemob/borer.dm @@ -0,0 +1,24 @@ +/datum/ghostspawner/simplemob/borer + short_name = "borer" + name = "Cortical Borer" + desc = "Infest crew, reproduce, repeat." + tags = list("Antagonist") + + enabled = FALSE + + spawn_mob = /mob/living/simple_animal/borer + +/datum/ghostspawner/simplemob/borer/select_spawnpoint(var/use) + return TRUE //We just fake it here, since the spawnpoint is selected if someone is spawned in. + +//The proc to actually spawn in the user +/datum/ghostspawner/simplemob/borer/spawn_mob(mob/user) + if(!length(spawn_atoms)) + to_chat(user, SPAN_DANGER("There are no available borers to spawn at!")) + return FALSE + + var/mob/living/simple_animal/borer/spawn_borer = pick(spawn_atoms) + + if(user && spawn_borer) + return spawn_borer.spawn_into_borer(user) + return FALSE \ No newline at end of file diff --git a/code/modules/mob/living/carbon/slime/items.dm b/code/modules/mob/living/carbon/slime/items.dm index 87f8cf02f35..fea57c6be4f 100644 --- a/code/modules/mob/living/carbon/slime/items.dm +++ b/code/modules/mob/living/carbon/slime/items.dm @@ -216,8 +216,6 @@ icon = 'icons/obj/chemical.dmi' icon_state = "bottle17" -var/list/global/golem_runes = list() - /obj/effect/golemrune anchored = TRUE desc = "A strange rune used to create golems. It glows when spirits are nearby." @@ -233,25 +231,15 @@ var/list/global/golem_runes = list() . = ..() START_PROCESSING(SSprocessing, src) announce_to_ghosts() - golem_runes += src - if(length(golem_runes) == 1) - for(var/role_spawner in SSghostroles.spawners) - if(role_spawner == "golem") - var/datum/ghostspawner/human/golem/golem_spawner = SSghostroles.spawners[role_spawner] - golem_spawner.enable() + SSghostroles.add_spawn_atom("golem", src) /obj/effect/golemrune/random_type/Initialize() . = ..() golem_type = pick(golem_types) /obj/effect/golemrune/Destroy() - . = ..() - golem_runes -= src - if(!length(golem_runes)) - for(var/role_spawner in SSghostroles.spawners) - if(role_spawner == "golem") - var/datum/ghostspawner/human/golem/golem_spawner = SSghostroles.spawners[role_spawner] - golem_spawner.disable() + SSghostroles.remove_spawn_atom("golem", src) + return ..() /obj/effect/golemrune/process() var/mob/abstract/observer/ghost diff --git a/code/modules/mob/living/simple_animal/borer/borer.dm b/code/modules/mob/living/simple_animal/borer/borer.dm index 5b15400ced1..d111ab63a8a 100644 --- a/code/modules/mob/living/simple_animal/borer/borer.dm +++ b/code/modules/mob/living/simple_animal/borer/borer.dm @@ -21,7 +21,7 @@ maxHealth = 40 health = 40 pass_flags = PASSTABLE - universal_understand = 1 + universal_understand = TRUE holder_type = /obj/item/holder/borer mob_size = 1 hunger_enabled = FALSE @@ -33,10 +33,10 @@ 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/has_reproduced - var/roundstart + var/request_player = TRUE /mob/living/simple_animal/borer/roundstart - roundstart = TRUE + request_player = FALSE /mob/living/simple_animal/borer/LateLogin() ..() @@ -52,15 +52,23 @@ verbs += /mob/living/proc/hide truename = "[pick("Primary","Secondary","Tertiary","Quaternary")]-[rand(1000,9999)]" - if(!roundstart) - request_player() + if(request_player && !ckey && !client) + SSghostroles.add_spawn_atom("borer", src) + var/area/A = get_area(src) + if(A) + say_dead_direct("A borer has been birthed in [A.name]! Spawn in as it by using the ghost spawner menu in the ghost tab.") + +/mob/living/simple_animal/borer/death(gibbed, deathmessage) + SSghostroles.remove_spawn_atom("borer", src) + return ..(gibbed,deathmessage) /mob/living/simple_animal/borer/Life() ..() if(host) - if(!stat && !host.stat) + if(!stat && host.stat != DEAD) if(chemicals < 250) chemicals++ + if(host && !host.stat) if(controlling && prob(host.getBrainLoss()/20)) host.say("*[pick(list("blink","blink_r","choke","drool","twitch","twitch_s","gasp"))]") @@ -152,10 +160,10 @@ host = null return -//Procs for grabbing players. -/mob/living/simple_animal/borer/proc/request_player() - var/datum/ghosttrap/G = get_ghost_trap("cortical borer") - G.request_player(src, "A cortical borer needs a player.") +/mob/living/simple_animal/borer/proc/spawn_into_borer(var/mob/user) + ckey = user.ckey + qdel(user) + SSghostroles.remove_spawn_atom("borer", src) /mob/living/simple_animal/borer/cannot_use_vents() return diff --git a/code/modules/mob/living/simple_animal/borer/borer_powers.dm b/code/modules/mob/living/simple_animal/borer/borer_powers.dm index 4ee1ace42f7..996089d7b68 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_powers.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_powers.dm @@ -414,7 +414,7 @@ /mob/living/simple_animal/borer/verb/awaken_psionics() set category = "Abilities" set name = "Awaken Host Psionics (150)" - set desc = "Probe into your host an unlock their psionic potential." + set desc = "Probe into your host and unlock their psionic potential. Note, it will give them a seizure as their brain realizes its potential." if(!host) to_chat(src, span("notice", "You are not inside a host body.")) @@ -437,7 +437,8 @@ chemicals -= 150 to_chat(src, span("notice", "You probe your tendrils deep within your host's zona bovinae, seeking to unleash their potential.")) to_chat(host, span("danger", "You feel some tendrils probe at the back of your head...")) - addtimer(CALLBACK(src, .proc/jumpstart_psi), 100) + to_chat(host, FONT_LARGE(SPAN_WARNING("You feel something terrible coming on..."))) + addtimer(CALLBACK(src, .proc/jumpstart_psi), 150) /mob/living/simple_animal/borer/proc/jumpstart_psi() to_chat(src, span("notice", "You succeed in interfacing with the host's zona bovinae, this will be a painful process for them.")) @@ -486,3 +487,17 @@ to_chat(src, span("notice", "You successfully manage to upgrade your host's [selected_faculty] faculty.")) to_chat(host, span("good", "A breeze of fresh air washes over your mind, you feel powerful!")) to_chat(host, span("notice", "You have been psionically enlightened. You are now a [psychic_ranks_to_strings[host.psi.ranks[selected_faculty]]] in the [selected_faculty] faculty.")) + +/mob/living/simple_animal/borer/verb/host_health_scan() + set category = "Abilities" + set name = "Inspect Host Health" + set desc = "Survey your host for injuries, allowing you to better treat them." + + if(!host) + to_chat(src, SPAN_WARNING("You have no host to scan.")) + return + if(stat) + to_chat(src, SPAN_WARNING("You cannot do that in your current state.")) + return + + health_scan_mob(host, src, TRUE, TRUE) \ No newline at end of file diff --git a/code/modules/shareddream/dream_entry.dm b/code/modules/shareddream/dream_entry.dm index 8ef626d173f..be94d60815f 100644 --- a/code/modules/shareddream/dream_entry.dm +++ b/code/modules/shareddream/dream_entry.dm @@ -8,7 +8,9 @@ var/list/dream_entries = list() // If either changes, they should be nocked back to the real world. if(can_commune() && stat == UNCONSCIOUS && sleeping > 1) if(!istype(bg) && client) // Don't spawn a brainghost if we're not logged in. - bg = new(src) // Generate a new brainghost. + bg = new /mob/living/brain_ghost(src) // Generate a new brainghost. + if(isnull(bg)) // Prevents you from getting kicked if the brain ghost didn't spawn - geeves + return bg.ckey = ckey bg.client = client ckey = "@[bg.ckey]" @@ -27,8 +29,17 @@ var/list/dream_entries = list() log_and_message_admins("has left the shared dream",bg) var/mob/living/brain_ghost/old_bg = bg bg = null - ckey = old_bg.ckey + + var/return_text = "You are ripped from the Srom as your body awakens." + var/mob/return_mob = src + + var/mob/living/simple_animal/borer/B = has_brain_worms() + if(B?.host_brain) + return_mob = B.host_brain + return_text = "You are ripped from the Srom as you return to the captivity of your own mind." + + return_mob.ckey = old_bg.ckey old_bg.show_message("[bg] fades as their connection is severed.") animate(old_bg, alpha=0, time = 200) QDEL_IN(old_bg, 20) - to_chat(src, "You are ripped from the Srom as your body awakens.") \ No newline at end of file + to_chat(return_mob, SPAN_WARNING("[return_text]")) \ No newline at end of file diff --git a/html/changelogs/geeves-borer_stuff.yml b/html/changelogs/geeves-borer_stuff.yml new file mode 100644 index 00000000000..832273e9bb7 --- /dev/null +++ b/html/changelogs/geeves-borer_stuff.yml @@ -0,0 +1,11 @@ +author: Geeves + +delete-after: True + +changes: + - rscadd: "Spawned borers now get added to the Ghostspawner menu, allowing players to inhabit them even if they didn't catch the original request." + - rscadd: "Borers have gained the ability to survey their host's health, allowing them to better choose when to administer certain chemicals." + - tweak: "Borers now regenerate chemicals even if their host is unconscious." + - rscadd: "Awakening psionics now take 15 seconds instead of 10, and the host now gets a message about feeling something bad coming on, allowing them to make a dash to safety and or seclusion." + - bugfix: "Skrell returning from Srom no longer eject controlling borers to the lobby by replacing their ckey into the aether." + - bugfix: "Skrell no longer spontaneously die when entering Srom on a map that doesn't have a Srom location." \ No newline at end of file