Skip to content

Commit

Permalink
[MIRROR] Cybernetic brains for androids [MDB IGNORE] (#25034)
Browse files Browse the repository at this point in the history
* Cybernetic brains for androids (#79421)

## About The Pull Request

A while ago, androids were changed to have robotic eyes and ears rather
than organic ones, for obvious reasons. But androids still have one
organic organ left; the brain. This PR adds a new cybernetic brain
organ, currently only used by androids. It has most of the benefits of
robotic organs, such as not rotting, but it also has the drawbacks, like
being unaffected by chemicals (mannitol being the big one) and being
somewhat vulnerable to EMPs.

In terms of EMP vulnerability, the brains are pretty safe. They take 10
brain damage per light EMP, capped at 20 total brain damage. They take
20 damage from each heavy EMP, capped at 100 total. This should allow
for EMPs to be debilitating without making them lethal when spammed.

Normal brains can be repaired by pouring mannitol over them, but
obviously this doesn't make sense for robotic brains. Instead, you can
use a multitool to repair removed robot brains. I'm still workshopping
ways to repair the brain without totally removing it. I had an idea for
new cybernetic organ repair surgeries, but it would also make more sense
to put all that in a separate PR.

Here is a picture of the new brain, with a normal brain for comparison:

![brainpic](https://github.com/tgstation/tgstation/assets/21979502/3b32e839-8670-4e8a-9c07-fb8f062879f2)

## Why It's Good For The Game

The robotic species should actually have entirely robotic parts, and
other people might come up with cool uses for this that I haven't
thought of.
## Changelog
:cl:
add: Androids now have robotic brains instead of organic brains.
/:cl:

* Cybernetic brains for androids

---------

Co-authored-by: GPeckman <[email protected]>
  • Loading branch information
2 people authored and FFMirrorBot committed Nov 16, 2023
1 parent 226c328 commit 1ab06cb
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 37 deletions.
59 changes: 59 additions & 0 deletions code/modules/mob/living/brain/brain_cybernetic.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/obj/item/organ/internal/brain/cybernetic
name = "cybernetic brain"
desc = "A mechanical brain found inside of androids. Not to be confused with a positronic brain."
icon_state = "brain-c"
organ_flags = ORGAN_ROBOTIC | ORGAN_VITAL
failing_desc = "seems to be broken, and will not work without repairs."

/obj/item/organ/internal/brain/cybernetic/brain_damage_examine()
if(suicided)
return span_info("Its circuitry is smoking slightly. They must not have been able to handle the stress of it all.")
if(brainmob && (decoy_override || brainmob.client || brainmob.get_ghost()))
if(organ_flags & ORGAN_FAILING)
return span_info("It seems to still have a bit of energy within it, but it's rather damaged... You may be able to repair it with a <b>multitool</b>.")
else if(damage >= BRAIN_DAMAGE_DEATH*0.5)
return span_info("You can feel the small spark of life still left in this one, but it's got some dents. You may be able to restore it with a <b>multitool</b>.")
else
return span_info("You can feel the small spark of life still left in this one.")
else
return span_info("This one is completely devoid of life.")

/obj/item/organ/internal/brain/cybernetic/check_for_repair(obj/item/item, mob/user)
if (item.tool_behaviour == TOOL_MULTITOOL) //attempt to repair the brain
if (brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing
to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!"))
return TRUE

if (DOING_INTERACTION(user, src))
to_chat(user, span_warning("you're already repairing [src]!"))
return TRUE

user.visible_message(span_notice("[user] slowly starts to repair [src] with [item]."), span_notice("You slowly start to repair [src] with [item]."))
var/did_repair = FALSE
while(damage > 0)
if(item.use_tool(src, user, 3 SECONDS, volume = 50))
did_repair = TRUE
set_organ_damage(max(0, damage - 20))
else
break

if (did_repair)
if (damage > 0)
user.visible_message(span_notice("[user] partially repairs [src] with [item]."), span_notice("You partially repair [src] with [item]."))
else
user.visible_message(span_notice("[user] fully repairs [src] with [item], causing its warning light to stop flashing."), span_notice("You fully repair [src] with [item], causing its warning light to stop flashing."))
else
to_chat(user, span_warning("You failed to repair [src] with [item]!"))

return TRUE
return FALSE

/obj/item/organ/internal/brain/cybernetic/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
switch(severity) // Hard cap on brain damage from EMP
if (EMP_HEAVY)
apply_organ_damage(20, BRAIN_DAMAGE_SEVERE)
if (EMP_LIGHT)
apply_organ_damage(10, BRAIN_DAMAGE_MILD)
78 changes: 41 additions & 37 deletions code/modules/mob/living/brain/brain_item.dm
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,6 @@
// Brain size logic
transform = transform.Scale(brain_size)

/obj/item/organ/internal/brain/examine()
. = ..()
if(brain_size < 1)
. += span_notice("It is a bit on the smaller side...")
if(brain_size > 1)
. += span_notice("It is bigger than average...")

/obj/item/organ/internal/brain/Insert(mob/living/carbon/brain_owner, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE)
. = ..()
if(!.)
Expand Down Expand Up @@ -177,32 +170,17 @@
L.mind.transfer_to(brainmob)
to_chat(brainmob, span_notice("You feel slightly disoriented. That's normal when you're just a brain."))

/obj/item/organ/internal/brain/attackby(obj/item/O, mob/user, params)
/obj/item/organ/internal/brain/attackby(obj/item/item, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)

if(istype(O, /obj/item/borg/apparatus/organ_storage))
if(istype(item, /obj/item/borg/apparatus/organ_storage))
return //Borg organ bags shouldn't be killing brains

if(damage && O.is_drainable() && O.reagents.has_reagent(/datum/reagent/medicine/mannitol)) //attempt to heal the brain
. = TRUE //don't do attack animation.
if(brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing
to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!"))
return

user.visible_message(span_notice("[user] starts to slowly pour the contents of [O] onto [src]."), span_notice("You start to slowly pour the contents of [O] onto [src]."))
if(!do_after(user, 3 SECONDS, src))
to_chat(user, span_warning("You failed to pour the contents of [O] onto [src]!"))
return

user.visible_message(span_notice("[user] pours the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink."), span_notice("You pour the contents of [O] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink."))
var/amount = O.reagents.get_reagent_amount(/datum/reagent/medicine/mannitol)
var/healto = max(0, damage - amount * 2)
O.reagents.remove_all(ROUND_UP(O.reagents.total_volume / amount * (damage - healto) * 0.5)) //only removes however much solution is needed while also taking into account how much of the solution is mannitol
set_organ_damage(healto) //heals 2 damage per unit of mannitol, and by using "set_organ_damage", we clear the failing variable if that was up
return
if (check_for_repair(item, user))
return TRUE

// Cutting out skill chips.
if(length(skillchips) && O.get_sharpness() == SHARP_EDGED)
if(length(skillchips) && item.get_sharpness() == SHARP_EDGED)
to_chat(user,span_notice("You begin to excise skillchips from [src]."))
if(do_after(user, 15 SECONDS, target = src))
for(var/chip in skillchips)
Expand All @@ -225,31 +203,57 @@
return

if(brainmob) //if we aren't trying to heal the brain, pass the attack onto the brainmob.
O.attack(brainmob, user) //Oh noooeeeee
item.attack(brainmob, user) //Oh noooeeeee

if(O.force != 0 && !(O.item_flags & NOBLUDGEON))
if(item.force != 0 && !(item.item_flags & NOBLUDGEON))
user.do_attack_animation(src)
playsound(loc, 'sound/effects/meatslap.ogg', 50)
set_organ_damage(maxHealth) //fails the brain as the brain was attacked, they're pretty fragile.
visible_message(span_danger("[user] hits [src] with [O]!"))
to_chat(user, span_danger("You hit [src] with [O]!"))
visible_message(span_danger("[user] hits [src] with [item]!"))
to_chat(user, span_danger("You hit [src] with [item]!"))

/obj/item/organ/internal/brain/proc/check_for_repair(obj/item/item, mob/user)
if(damage && item.is_drainable() && item.reagents.has_reagent(/datum/reagent/medicine/mannitol) && (organ_flags & ORGAN_ORGANIC)) //attempt to heal the brain
if(brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing
to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!"))
return TRUE

user.visible_message(span_notice("[user] starts to slowly pour the contents of [item] onto [src]."), span_notice("You start to slowly pour the contents of [item] onto [src]."))
if(!do_after(user, 3 SECONDS, src))
to_chat(user, span_warning("You failed to pour the contents of [item] onto [src]!"))
return TRUE

user.visible_message(span_notice("[user] pours the contents of [item] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink."), span_notice("You pour the contents of [item] onto [src], causing it to reform its original shape and turn a slightly brighter shade of pink."))
var/amount = item.reagents.get_reagent_amount(/datum/reagent/medicine/mannitol)
var/healto = max(0, damage - amount * 2)
item.reagents.remove_all(ROUND_UP(item.reagents.total_volume / amount * (damage - healto) * 0.5)) //only removes however much solution is needed while also taking into account how much of the solution is mannitol
set_organ_damage(healto) //heals 2 damage per unit of mannitol, and by using "set_organ_damage", we clear the failing variable if that was up
return TRUE
return FALSE

/obj/item/organ/internal/brain/examine(mob/user)
. = ..()
if(length(skillchips))
. += span_info("It has a skillchip embedded in it.")
. += brain_damage_examine()
if(brain_size < 1)
. += span_notice("It is a bit on the smaller side...")
if(brain_size > 1)
. += span_notice("It is bigger than average...")

/// Needed so subtypes can override examine text while still calling parent
/obj/item/organ/internal/brain/proc/brain_damage_examine()
if(suicided)
. += span_info("It's started turning slightly grey. They must not have been able to handle the stress of it all.")
return
return span_info("It's started turning slightly grey. They must not have been able to handle the stress of it all.")
if(brainmob && (decoy_override || brainmob.client || brainmob.get_ghost()))
if(organ_flags & ORGAN_FAILING)
. += span_info("It seems to still have a bit of energy within it, but it's rather damaged... You may be able to restore it with some <b>mannitol</b>.")
return span_info("It seems to still have a bit of energy within it, but it's rather damaged... You may be able to restore it with some <b>mannitol</b>.")
else if(damage >= BRAIN_DAMAGE_DEATH*0.5)
. += span_info("You can feel the small spark of life still left in this one, but it's got some bruises. You may be able to restore it with some <b>mannitol</b>.")
return span_info("You can feel the small spark of life still left in this one, but it's got some bruises. You may be able to restore it with some <b>mannitol</b>.")
else
. += span_info("You can feel the small spark of life still left in this one.")
return span_info("You can feel the small spark of life still left in this one.")
else
. += span_info("This one is completely devoid of life.")
return span_info("This one is completely devoid of life.")

/obj/item/organ/internal/brain/attack(mob/living/carbon/C, mob/user)
if(!istype(C))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
meat = null
mutantbrain = /obj/item/organ/internal/brain/cybernetic
mutanttongue = /obj/item/organ/internal/tongue/robot
mutantstomach = null
mutantappendix = null
Expand Down
Binary file modified icons/obj/medical/organs/organs.dmi
Binary file not shown.
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -4767,6 +4767,7 @@
#include "code\modules\mob\living\basic\vermin\mouse.dm"
#include "code\modules\mob\living\basic\vermin\space_bat.dm"
#include "code\modules\mob\living\brain\brain.dm"
#include "code\modules\mob\living\brain\brain_cybernetic.dm"
#include "code\modules\mob\living\brain\brain_item.dm"
#include "code\modules\mob\living\brain\brain_say.dm"
#include "code\modules\mob\living\brain\death.dm"
Expand Down

0 comments on commit 1ab06cb

Please sign in to comment.