Shell May Cry: A comprehensive rework of synthetics. (#20721)

https://www.youtube.com/watch?v=9mPvZ96pHJI

A pull request commissioned by the Synthetic Lore Team to
comprehensively rework synthetics (read: IPCs) and how they work in
Aurora. The objective is to make IPCs as unique as possible from humans,
upgrading the robotic feel and atmosphere, while also preserving a good
sense of balance in-game.

Key features:

- A comprehensive expansion of synthetic organs, all of which now
fulfill a purpose: hydraulics, cooling units, power systems, actuators,
diagnostics units.
- Customizable organs with benefits and drawbacks, such as with cooling
units and power systems.
- Unique ways to repair the organs and more involved steps.
- Unique damage mechanics - every organ has wiring and electronics which
affect its functioning, and they are defended by plating which provides
natural armour.
- Improved and immersive diagnostics.
- Unique features, benefits, and drawbacks for every IPC frame.
- A rework of the positronic brain, which can be either destroyed or
shut down, alongside effects caused by low integrity.
- A rework of how EMPs affect IPC organs.
- Non-binary damage states for each organ.

To-do:

- [x] Finish the unique features for each frame.
- [x] Look into if mechanical synthskin is possible.
- [x] Power system.
- [x] Posibrain mechanics.
- [ ] Passive cooling expansion.
- [x] EMP mechanics.
- [x] Repair mechanics.
- [x] Mob weight mechanics.
- [ ] Gurney for heavy mobs.
- [x] New augments.
- [ ] IPC tag scanning and flashing.

---------

Signed-off-by: Werner <1331699+Arrow768@users.noreply.github.com>
Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: Geeves <22774890+Geevies@users.noreply.github.com>
Co-authored-by: Werner <1331699+Arrow768@users.noreply.github.com>
This commit is contained in:
Matt Atlas
2025-12-21 17:26:23 +01:00
committed by GitHub
parent 1898ad3417
commit e0aa218843
201 changed files with 5962 additions and 896 deletions
@@ -0,0 +1,98 @@
/datum/tgui_module/ipc_diagnostic
var/mob/patient
/datum/tgui_module/ipc_diagnostic/New(mob/user, mob/target)
. = ..()
patient = target
/datum/tgui_module/ipc_diagnostic/Destroy(force)
patient = null
return ..()
/datum/tgui_module/ipc_diagnostic/ui_interact(var/mob/user, var/datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "DiagnosticsUnit", "Diagnostics Unit", 400, 600)
ui.open()
/datum/tgui_module/ipc_diagnostic/ui_data(mob/user)
var/list/data = list()
data["broken"] = FALSE
if(isipc(patient))
var/mob/living/carbon/human/ipc = patient
var/datum/species/machine/machine_species = ipc.species // need to manually set to ipc species because of machine_ui_theme
var/obj/item/organ/internal/machine/internal_diagnostics/diagnostics = ipc.internal_organs_by_name[BP_DIAGNOSTICS_SUITE]
if(!istype(diagnostics))
data["broken"] = TRUE
data["patient_name"] = ipc.real_name
data["broken"] = diagnostics.is_broken()
data["integrity"] = diagnostics.get_integrity()
data["temp"] = round(convert_k2c(ipc.bodytemperature))
data["machine_ui_theme"] = machine_species.machine_ui_theme
data["organs"] = list()
for(var/obj/item/organ/internal/organ in ipc.internal_organs)
var/list/organ_data = list()
// this check is here first so we can avoid useless calculations in case the organ isn't visible from the diag suite
if(istype(organ, /obj/item/organ/internal/machine))
var/obj/item/organ/internal/machine/machine_organ = organ
if(!machine_organ.diagnostics_suite_visible)
continue
organ_data["wiring_status"] = edit_organ_status(machine_organ.wiring.get_status(), diagnostics)
organ_data["plating_status"] = edit_organ_status(machine_organ.plating.get_status(), diagnostics)
organ_data["electronics_status"] = edit_organ_status(machine_organ.electronics.get_status(), diagnostics)
organ_data["diagnostics_info"] = machine_organ.get_diagnostics_info()
organ_data["name"] = organ.name
organ_data["desc"] = organ.desc
organ_data["damage"] = edit_organ_status(organ.damage, diagnostics)
organ_data["max_damage"] = organ.max_damage
data["organs"] += list(organ_data)
data["robolimb_self_repair_cap"] = ROBOLIMB_SELF_REPAIR_CAP
data["limbs"] = list()
for(var/obj/item/organ/external/limb in ipc.organs)
if(limb.brute_dam || limb.burn_dam)
data["limbs"] += list(list("name" = limb.name, "brute_damage" = edit_organ_status(limb.brute_dam, diagnostics), "burn_damage" = edit_organ_status(limb.burn_dam, diagnostics), "max_damage" = limb.max_damage))
var/obj/item/organ/internal/machine/power_core/C = ipc.internal_organs_by_name[BP_CELL]
if(C)
data["charge_percent"] = C.percent()
var/datum/component/synthetic_endoskeleton/endoskeleton = ipc.GetComponent(/datum/component/synthetic_endoskeleton)
if(istype(endoskeleton))
data["endoskeleton_damage"] = endoskeleton.damage
data["endoskeleton_max_damage"] = endoskeleton.max_damage
var/datum/component/armor/synthetic/synth_armor = ipc.GetComponent(/datum/component/armor/synthetic)
if(istype(synth_armor))
data["armor_data"] = list()
var/list/armor_damage = synth_armor.get_visible_damage()
for(var/key in armor_damage)
data["armor_data"] += list(list("key" = key, "status" = armor_damage[key]))
return data
/**
* Edits a status number based on the diagnostics unit's status.
* The more damaged the diagnostics unit, the more errant a reading may be.
*/
/datum/tgui_module/ipc_diagnostic/proc/edit_organ_status(number, obj/item/organ/internal/machine/internal_diagnostics/diagnostics)
if(!diagnostics)
// what the hell are we doing here
return 0
var/integrity = diagnostics.get_integrity()
if(integrity > IPC_INTEGRITY_THRESHOLD_LOW)
return number
var/variancy = (100 / integrity * rand(1, (100 / integrity * 10)))
var/sign = prob(variancy) ? pick(1, -1) : 1
var/random_number = sign * (rand(1, 100 / integrity))
return number + (sign * rand(1, variancy) + random_number)
@@ -0,0 +1,88 @@
/datum/tgui_module/neural_configuration
var/mob/living/carbon/human/owner
/datum/tgui_module/neural_configuration/New(mob/user, mob/target)
. = ..()
if(!isipc(target))
log_debug("Neural configuration created without IPC target!")
qdel(src)
owner = target
/datum/tgui_module/neural_configuration/Destroy(force)
owner = null
return ..()
/datum/tgui_module/neural_configuration/ui_interact(var/mob/user, var/datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "NeuralConfiguration", "Neural Configuration", 400, 400)
ui.open()
/datum/tgui_module/neural_configuration/ui_data(mob/user)
var/list/data = list()
var/obj/item/organ/internal/machine/posibrain/posibrain = owner.internal_organs_by_name[BP_BRAIN]
if(istype(posibrain))
data["neural_coherence"] = posibrain.damage
data["max_neural_coherence"] = posibrain.max_damage
data["owner_real_name"] = posibrain.owner.real_name
data["firewall"] = posibrain.firewall
data["p2p_communication"] = posibrain.p2p_communication_allowed
var/obj/item/organ/internal/machine/access_port/port = owner.internal_organs_by_name[BP_ACCESS_PORT]
if(istype(port) && !port.is_broken())
data["port"] = TRUE
if(port.access_cable && istype(port.access_cable.target, /obj/item/organ/internal/machine/access_port))
var/obj/item/organ/internal/machine/access_port/other_port = port.access_cable.target
if(isipc(other_port.owner))
var/mob/living/carbon/human/connected_ipc = other_port.owner
data["port_connected"] = connected_ipc.real_name
if(other_port && !other_port.is_broken())
data["port_can_communicate"] = TRUE
return data
/datum/tgui_module/neural_configuration/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
switch(action)
if("toggle_firewall")
var/obj/item/organ/internal/machine/posibrain/posibrain = owner.internal_organs_by_name[BP_BRAIN]
if(istype(posibrain))
posibrain.toggle_firewall()
. = TRUE
if("toggle_p2p")
var/obj/item/organ/internal/machine/posibrain/posibrain = owner.internal_organs_by_name[BP_BRAIN]
if(istype(posibrain))
posibrain.toggle_p2p()
. = TRUE
if("talk_p2p")
var/obj/item/organ/internal/machine/access_port/port = owner.internal_organs_by_name[BP_ACCESS_PORT]
if(istype(port) && !port.is_broken())
if(port.access_cable && istype(port.access_cable.target, /obj/item/organ/internal/machine/access_port))
var/obj/item/organ/internal/machine/access_port/other_port = port.access_cable.target
if(isipc(other_port.owner))
var/mob/living/carbon/human/connected_ipc = other_port.owner
if(other_port && !other_port.is_broken())
if(connected_ipc.client)
var/obj/item/organ/internal/machine/posibrain/other_posibrain = connected_ipc.internal_organs_by_name[BP_BRAIN]
if(!other_posibrain.p2p_communication_allowed)
to_chat(owner, SPAN_MACHINE_WARNING("[connected_ipc.real_name]'s Virtual Communication ports are not open."))
return
var/message = sanitize_tg(tgui_input_text(owner, "Enter a peer-to-peer message to send to [connected_ipc.real_name].", "Virtual Communication", max_length = MAX_MESSAGE_LEN))
// re-do all the checks just in case. bit ass but oh well
if(message && !port.is_broken() && (port.access_cable.target && port.access_cable.target == connected_ipc && !other_port.is_broken()))
var/p2p_message = SPAN_ITALIC("Virtual Communication, ") + SPAN_BOLD("[owner.real_name] transmits: ") + SPAN_MACHINE_WARNING(message)
to_chat(connected_ipc, p2p_message)
log_say("VIRTUAL COMMUNICATION: [owner]/[owner.client.ckey] to [connected_ipc]/[connected_ipc.client.ckey]: [message]")
. = TRUE
else
to_chat(owner, SPAN_WARNING("That posibrain seems to be in deep sleep."))
. = FALSE
else
to_chat(owner, SPAN_WARNING("The other port isn't responding at all!"))
. = FALSE
if(.)
sound_to(owner, 'sound/effects/neural_config.ogg')
+11
View File
@@ -64,3 +64,14 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
if(ismech(src_object))
return UI_INTERACTIVE
return ..()
/mob/living/carbon/human/default_can_use_topic(src_object)
. = ..()
var/obj/item/organ/internal/machine/wireless_access/access_point = internal_organs_by_name[BP_WIRELESS_ACCESS]
if(istype(access_point))
// Just like robots, these IPCs can interact with anything they can see.
var/list/clientviewlist = getviewsize(client.view)
if(get_dist(src, src_object) <= min(clientviewlist[1], clientviewlist[2]))
return UI_INTERACTIVE
return UI_DISABLED // Otherwise they can keep the UI open.