Cortical Borers (#21118)

Adds cortical borers, a midround antag originally from Bay. The code here is from yogstation, baystation and paradise station.

Borers are little brainslugs that when adjacent to a human can infest them. They can supply you with useful chemicals such as medicines and meth, and can revive you from the dead if they have maximum chemicals. They can also take over your body, putting them in control of you while you become a "captive mind". A captive mind can take back control by doing Resist. Health analyzers show borers in people, while medHUDs show borers in control. If you have Sugar in your body the borer can do nothing, it gets kicked out of control if it's controlling and becomes docile. Organ Manipulation surgery on head to remove the borer. If the brain of the body gets removed (decapitation, brain removal surgery, gibbing) the borer falls out of the host and loses control if they were controlling. Changelings can remove borers with Anatomic Panacea or Lesser Form (or Last Resort). Borers can reproduce and have an objective to escape on the shuttle with X hosts alive.
This commit is contained in:
uraniummeltdown
2016-11-09 20:25:41 +00:00
committed by oranges
parent e024b2a284
commit ea81370dce
24 changed files with 1379 additions and 7 deletions

View File

@@ -62,6 +62,8 @@
//Simple animals
#define isanimal(A) (istype(A, /mob/living/simple_animal))
#define isborer(A) (istype(A, /mob/living/simple_animal/borer))
#define isbot(A) (istype(A, /mob/living/simple_animal/bot))
#define iscrab(A) (istype(A, /mob/living/simple_animal/crab))

View File

@@ -23,6 +23,7 @@
#define ROLE_REVENANT "revenant"
#define ROLE_DEVIL "devil"
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
#define ROLE_BORER "borer"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
@@ -45,6 +46,7 @@ var/global/list/special_roles = list(
ROLE_ABDUCTOR = /datum/game_mode/abduction,
ROLE_DEVIL = /datum/game_mode/devil,
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult,
ROLE_BORER,
)
//Job defines for what happens when you fail to qualify for any job during job selection

View File

@@ -442,6 +442,22 @@ var/datum/subsystem/ticker/ticker
for(var/i in total_antagonists)
log_game("[i]s[total_antagonists[i]].")
if(borers.len)
var/total_borers = 0
for(var/mob/living/simple_animal/borer/B in borers)
if(B.stat != DEAD)
total_borers++
if(total_borers)
var/total_borer_hosts = 0
for(var/mob/living/carbon/C in mob_list)
var/mob/living/simple_animal/borer/D = C.has_brain_worms()
var/turf/location = get_turf(C)
if(location.z == ZLEVEL_CENTCOM && C.has_brain_worms() && D.stat != DEAD)
total_borer_hosts++
world << "<b>There were [total_borers] borers alive at round end!</b>"
world << "<b>A total of [total_borer_hosts] borers with hosts escaped on the shuttle alive. The borers needed [total_borer_hosts_needed] hosts on the shuttle so they [(total_borer_hosts_needed <= total_borer_hosts) ? "<font color='green'>won!</font>" : "<font color='red'>lost!</font>"]</b>"
return TRUE
mode.declare_station_goal_completion()
//Adds the del() log to world.log in a format condensable by the runtime condenser found in tools

View File

@@ -377,6 +377,9 @@
time_coeff = 2
/datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner)
if(owner.has_brain_worms())
owner << "<span class='warning'>You feel something strongly clinging to your humanity!</span>"
return
if(..())
return
. = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)

View File

@@ -162,11 +162,14 @@
var/image/holder = hud_list[STATUS_HUD]
var/icon/I = icon(icon, icon_state, dir)
var/virus_state = check_virus()
var/mob/living/simple_animal/borer/B = has_brain_worms()
holder.pixel_y = I.Height() - world.icon_size
if(status_flags & XENO_HOST)
holder.icon_state = "hudxeno"
else if(stat == DEAD || (status_flags & FAKEDEATH))
holder.icon_state = "huddead"
else if(has_brain_worms() && B != null && B.controlling)
holder.icon_state = "hudbrainworm"
else if(virus_state == 2)
holder.icon_state = "hudill"
else if(virus_state == 1)

View File

@@ -10,6 +10,15 @@
/obj/effect/proc_holder/changeling/panacea/sting_action(mob/user)
user << "<span class='notice'>We begin cleansing impurities from our form.</span>"
var/mob/living/simple_animal/borer/B = user.has_brain_worms()
if(B)
if(B.controlling)
B.detatch()
B.leave_victim()
if(iscarbon(user))
var/mob/living/carbon/C = user
C.vomit(0)
user << "<span class='notice'>A parasite exits our form.</span>"
var/obj/item/organ/body_egg/egg = user.getorgan(/obj/item/organ/body_egg)
if(egg)
egg.Remove(user)

View File

@@ -131,6 +131,12 @@ MASS SPECTROMETER
var/mob/living/carbon/human/H = M
if(H.heart_attack && H.stat != DEAD)
user << "<span class='danger'>Subject suffering from heart attack: Apply defibrillator immediately!</span>"
if(iscarbon(M))
var/mob/living/carbon/C = M
if(C.has_brain_worms())
user << "<span class='danger'>Foreign organism detected in subject's cranium. Recommended treatment: Dosage of sucrose solution and removal of object via surgery.</span>"
user << "<span class='info'>Analyzing results for [M]:\n\tOverall status: [mob_status]</span>"
// Damage descriptions

View File

@@ -832,6 +832,12 @@
else
dat += "<td width='20%'><a href='?src=\ref[src];jobban3=alien candidate;jobban4=\ref[M]'>Alien</a></td>"
//Borer
if(jobban_isbanned(M, "borer") || isbanned_dept)
dat += "<td width='20%'><a href='?src=\ref[src];jobban3=borer;jobban4=\ref[M]'><font color=red>Borer</font></a></td>"
else
dat += "<td width='20%'><a href='?src=\ref[src];jobban3=borer;jobban4=\ref[M]'>Borer</a></td>"
dat += "</tr></table>"
usr << browse(dat, "window=jobban2;size=800x450")
return

View File

@@ -289,6 +289,9 @@ Pipelines + Other Objects -> Pipe network
return list()
/obj/machinery/atmospherics/update_remote_sight(mob/user)
if(isborer(user))
user.sight |= (SEE_PIXELS)
else
user.sight |= (SEE_TURFS|BLIND)
//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it.

View File

@@ -157,7 +157,7 @@
/mob/living/proc/canSuicide()
if(stat == CONSCIOUS)
return 1
return TRUE
else if(stat == DEAD)
src << "You're already dead!"
else if(stat == UNCONSCIOUS)
@@ -170,4 +170,7 @@
if(!canmove || restrained()) //just while I finish up the new 'fun' suiciding verb. This is to prevent metagaming via suicide
src << "You can't commit suicide whilst restrained! ((You can type Ghost instead however.))"
return
return 1
if(has_brain_worms())
src << "You can't bring yourself to commit suicide!"
return
return TRUE

View File

@@ -31,10 +31,17 @@
C.update_hair()
/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0)
..()
if(!special)
transfer_identity(C)
C.update_hair()
var/mob/living/simple_animal/borer/B = owner.has_brain_worms()
if(B)
B.leave_victim() //Should remove borer if the brain is removed - RR
if(owner.mind)
src.transfer_identity(C)
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
H.update_hair()
. = ..()
/obj/item/organ/brain/prepare_eat()
return // Too important to eat.

View File

@@ -76,6 +76,11 @@
stat("Internal Atmosphere Info", internal.name)
stat("Tank Pressure", internal.air_contents.return_pressure())
stat("Distribution Pressure", internal.distribute_pressure)
var/mob/living/simple_animal/borer/B = has_brain_worms()
if(B && B.controlling)
stat("Chemicals", B.chemicals)
if(mind)
if(mind.changeling)
stat("Chemical Storage", "[mind.changeling.chem_charges]/[mind.changeling.chem_storage]")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
/datum/borer_chem
var/chemname
var/chem_desc = "This is a chemical"
var/chemuse = 30
var/quantity = 10
/datum/borer_chem/epinephrine
chemname = "epinephrine"
chem_desc = "Stabilizes critical condition and slowly restores oxygen damage. If overdosed, it will deal toxin and oxyloss damage."
/datum/borer_chem/leporazine
chemname = "leporazine"
chem_desc = "This keeps a patient's body temperature stable. High doses can allow short periods of unprotected EVA."
chemuse = 75
/datum/borer_chem/mannitol
chemname = "mannitol"
chem_desc = "Heals brain damage."
/datum/borer_chem/bicaridine
chemname = "bicaridine"
chem_desc = "Heals brute damage."
/datum/borer_chem/kelotane
chemname = "kelotane"
chem_desc = "Heals burn damage."
/datum/borer_chem/charcoal
chemname = "charcoal"
chem_desc = "Slowly heals toxin damage, will also slowly remove any other chemicals."
/datum/borer_chem/methamphetamine
chemname = "methamphetamine"
chem_desc = "Reduces stun times, increases stamina and run speed while dealing brain damage. If overdosed it will deal toxin and brain damage."
chemuse = 50
quantity = 9
/datum/borer_chem/salbutamol
chemname = "salbutamol"
chem_desc = "Heals suffocation damage."
/datum/borer_chem/spacedrugs
chemname = "space_drugs"
chem_desc = "Get your host high as a kite."
chemuse = 75
/*/datum/borer_chem/creagent
chemname = "colorful_reagent"
chem_desc = "Change the colour of your host."
chemuse = 50*/
/datum/borer_chem/ethanol
chemname = "ethanol"
chem_desc = "The most potent alcoholic 'beverage', with the fastest toxicity."
chemuse = 50
/datum/borer_chem/rezadone
chemname = "rezadone"
chem_desc = "Heals cellular damage."

View File

@@ -0,0 +1,49 @@
/datum/round_event_control/borer
name = "Borer"
typepath = /datum/round_event/borer
weight = 20
max_occurrences = 1
min_players = 15
earliest_start = 12000
/datum/round_event/borer
announceWhen = 3000 //Borers get 5 minutes till the crew tries to murder them.
var/successSpawn = 0
var/spawncount = 2
/datum/round_event/borer/setup()
spawncount = rand(2, 4)
/datum/round_event/borer/announce()
if(successSpawn)
priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/AI/aliens.ogg') //Borers seem like normal xenomorphs.
/datum/round_event/borer/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in machines)
if(qdeleted(temp_vent))
continue
if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
if(temp_vent_parent.other_atmosmch.len > 20)
vents += temp_vent
if(!vents.len)
message_admins("An event attempted to spawn a borer but no suitable vents were found. Shutting down.")
return kill()
var/total_humans = 0
for(var/mob/living/carbon/human/H in mob_list)
if(H.stat != DEAD)
total_humans++
total_borer_hosts_needed = round(6 + total_humans/7)
while(spawncount >= 1 && vents.len)
var/obj/vent = pick_n_take(vents)
new /mob/living/simple_animal/borer(vent.loc)
successSpawn = TRUE
spawncount--

View File

@@ -0,0 +1,125 @@
/mob/living/simple_animal/borer/proc/get_html_template(content)
var/html = {"<!DOCTYPE html">
<html>
<head>
<title>Borer Chemicals</title>
<link rel='stylesheet' type='text/css' href='icons.css'>
<link rel='stylesheet' type='text/css' href='shared.css'>
<style type='text/css'>
body {
padding: 10;
margin: 0;
font-size: 12px;
color: #ffffff;
line-height: 170%;
font-family: Verdana, Geneva, sans-serif;
background: #272727 url(uiBackground.png) 50% 0 repeat-x;
overflow-x: hidden;
}
a, a:link, a:visited, a:active, .link, .linkOn, .linkOff, .selected, .disabled {
color: #ffffff;
text-decoration: none;
background: #40628a;
border: 1px solid #161616;
padding: 2px 2px 2px 2px;
margin: 2px 2px 2px 2px;
cursor: pointer;
display: inline-block;
}
a:hover, .linkActive:hover {
background: #507aac;
cursor: pointer;
}
img {
border: 0px;
}
p {
padding: 4px;
margin: 0px;
}
h1, h2, h3, h4, h5, h6 {
margin: 0;
padding: 16px 0 8px 0;
color: #517087;
clear: both;
}
h1 {
font-size: 15px;
}
h2 {
font-size: 14px;
}
h3 {
font-size: 13px;
}
h4 {
font-size: 12px;
}
#header {
margin: 3px;
padding: 0px;
}
table {
width: 570px;
margin: 10px;
}
td {
border: solid 1px #000;
width: 560px;
}
.chem-select {
width: 560px;
margin: 5px;
text-align: center;
}
.enabled {
background-color: #0a0;
}
.disabled {
background-color: #a00;
}
.shown {
display: block;
}
.hidden {
display: none;
}
</style>
<script src="jquery.min.js"></script>
<script type='text/javascript'>
function update_chemicals(chemicals) {
$('#chemicals').text(chemicals);
}
$(function() {
});
</script>
</head>
<body scroll='yes'><div id='content'>
<h1 id='header'>Borer Chemicals</h1>
<br />
[content]
</div></body></html>"}
return html

View File

@@ -0,0 +1,37 @@
/mob/living/simple_animal/borer/Topic(href, href_list, hsrc)
if(href_list["borer_use_chem"])
locate(href_list["src"])
if(!istype(src, /mob/living/simple_animal/borer))
return
var/topic_chem = href_list["borer_use_chem"]
var/datum/borer_chem/C
for(var/datum in typesof(/datum/borer_chem))
var/datum/borer_chem/test = new datum()
if(test.chemname == topic_chem)
C = test
break
if(!istype(C, /datum/borer_chem))
return
if(!C || !victim || controlling || !src || stat)
return
if(!istype(C, /datum/borer_chem))
return
if(chemicals < C.chemuse)
src << "<span class='boldnotice'>You need [C.chemuse] chemicals stored to use this chemical!</span>"
return
src << "<span class='userdanger'>You squirt a measure of [C.chemname] from your reservoirs into [victim]'s bloodstream.</span>"
victim.reagents.add_reagent(C.chemname, C.quantity)
chemicals -= C.chemuse
log_game("[src]/([src.ckey]) has injected [C.chemname] into their host [victim]/([victim.ckey])")
src << output(chemicals, "ViewBorer\ref[src]Chems.browser:update_chemicals")
..()

View File

@@ -67,6 +67,11 @@
else if(implement_type in implements_extract)
current_type = "extract"
var/list/organs = target.getorganszone(target_zone)
var/mob/living/simple_animal/borer/B = target.has_brain_worms()
if(target.has_brain_worms())
user.visible_message("[user] begins to extract [B] from [target]'s [parse_zone(target_zone)].",
"<span class='notice'>You begin to extract [B] from [target]'s [parse_zone(target_zone)]...</span>")
return TRUE
if(!organs.len)
user << "<span class='notice'>There is no removeable organs in [target]'s [parse_zone(target_zone)]!</span>"
return -1
@@ -107,6 +112,13 @@
"<span class='notice'>You insert [tool] into [target]'s [parse_zone(target_zone)].</span>")
else if(current_type == "extract")
var/mob/living/simple_animal/borer/B = target.has_brain_worms()
if(B && B.victim == target)
user.visible_message("[user] successfully extracts [B] from [target]'s [parse_zone(target_zone)]!",
"<span class='notice'>You successfully extract [B] from [target]'s [parse_zone(target_zone)].</span>")
add_logs(user, target, "surgically removed [B] from", addition="INTENT: [uppertext(user.a_intent)]")
B.leave_victim()
return FALSE
if(I && I.owner == target)
user.visible_message("[user] successfully extracts [I] from [target]'s [parse_zone(target_zone)]!",
"<span class='notice'>You successfully extract [I] from [target]'s [parse_zone(target_zone)].</span>")

View File

@@ -30,7 +30,7 @@
L.embedded_objects -= I
if(objects > 0)
user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L]!", "<span class='notice'>You sucessfully remove [objects] objects from [H]'s [L.name].</span>")
user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L]!", "<span class='notice'>You successfully remove [objects] objects from [H]'s [L.name].</span>")
else
user << "<span class='warning'>You find no objects embedded in [H]'s [L]!</span>"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -119,6 +119,8 @@ h1.alert, h2.alert {color: #000000;}
.alien {color: #543354;}
.noticealien {color: #00c000;}
.alertalien {color: #00c000; font-weight: bold;}
.borer {color: #543354; font-style: italic;}
.changeling {color: #800080; font-style: italic;}
.interface {color: #330033;}

View File

@@ -1502,6 +1502,11 @@
#include "code\modules\mob\living\simple_animal\simple_animal.dm"
#include "code\modules\mob\living\simple_animal\spawner.dm"
#include "code\modules\mob\living\simple_animal\status_procs.dm"
#include "code\modules\mob\living\simple_animal\borer\borer.dm"
#include "code\modules\mob\living\simple_animal\borer\borer_chemicals.dm"
#include "code\modules\mob\living\simple_animal\borer\borer_event.dm"
#include "code\modules\mob\living\simple_animal\borer\borer_html.dm"
#include "code\modules\mob\living\simple_animal\borer\borer_topic.dm"
#include "code\modules\mob\living\simple_animal\bot\bot.dm"
#include "code\modules\mob\living\simple_animal\bot\cleanbot.dm"
#include "code\modules\mob\living\simple_animal\bot\construction.dm"