|
1 | 1 | /datum/component/synthetic_endoskeleton |
2 | 2 | /// The synthetic that owns this component. Equivalent to `parent`, we just use this for ease of use. |
3 | 3 | var/mob/living/carbon/human/owner |
4 | | - /// The posibrain of our parent. |
5 | | - var/obj/item/organ/internal/machine/posibrain/posibrain |
6 | 4 | /** |
7 | 5 | * The synthetic endoskeleton is our answer to the eternal problem of IPCs being unable to be brainmed complaint because |
8 | 6 | * of a lack of mechanics to represent pain, organ breaking, or bleeding/respiration, which is how humans in brainmed are |
9 | 7 | * taken down nonlethally, or before they die. |
10 | 8 | */ |
11 | 9 | var/damage = 0 |
12 | 10 | /// The maximum damage the endoskeleton can take before triggering the safety shutdown. |
13 | | - var/damage_maximum = 200 |
| 11 | + var/max_damage = 200 |
| 12 | + |
| 13 | + /// Time until next message. |
| 14 | + var/message_cooldown = 10 SECONDS |
| 15 | + /// World.time of last message sent. |
| 16 | + var/last_sent_message = 0 |
14 | 17 |
|
15 | 18 | /datum/component/synthetic_endoskeleton/Initialize(...) |
16 | 19 | . = ..() |
17 | 20 | if(isipc(parent)) |
18 | 21 | owner = parent |
19 | | - var/obj/item/organ/internal/machine/posibrain/possible_brain = owner.internal_organs_by_name[BP_BRAIN] |
20 | | - if(!istype(possible_brain)) |
21 | | - log_debug("Synthetic endoskeleton somehow could not find a brain. Deleting.") |
22 | | - qdel_self() |
23 | | - else |
24 | | - posibrain = possible_brain |
25 | 22 | else |
26 | 23 | log_debug("Synthetic endoskeleton component spawned on non-IPC. Deleting.") |
27 | 24 | qdel_self() |
28 | 25 |
|
29 | 26 | RegisterSignal(owner, COMSIG_EXTERNAL_ORGAN_DAMAGE, PROC_REF(receive_damage)) |
30 | 27 | RegisterSignal(owner, COMSIG_SYNTH_ENDOSKELETON_REPAIR, PROC_REF(heal_damage)) |
| 28 | + RegisterSignal(owner, COMSIG_SYNTH_ENDOSKELETON_FULL_REPAIR, PROC_REF(full_repair)) |
31 | 29 |
|
32 | 30 | /datum/component/synthetic_endoskeleton/Destroy(force) |
33 | 31 | owner = null |
34 | | - posibrain = null |
35 | 32 | return ..() |
36 | 33 |
|
37 | 34 | /** |
38 | 35 | * Signal handler called when an external synthetic limb receives damage. |
39 | 36 | */ |
40 | | -/datum/component/synthetic_endoskeleton/proc/receive_damage(amount) |
| 37 | +/datum/component/synthetic_endoskeleton/proc/receive_damage(atom/source, amount) |
41 | 38 | SIGNAL_HANDLER |
42 | | - damage = max(damage + amount, damage_maximum) |
| 39 | + damage = min(damage + amount, max_damage) |
43 | 40 | handle_exoskeleton_damage() |
44 | 41 |
|
45 | 42 | /** |
46 | 43 | * Signal handler called when the endoskeleton is repaired. |
47 | 44 | */ |
48 | | -/datum/component/synthetic_endoskeleton/proc/heal_damage(amount) |
| 45 | +/datum/component/synthetic_endoskeleton/proc/heal_damage(atom/source, amount) |
49 | 46 | SIGNAL_HANDLER |
50 | 47 | damage = max(damage - amount, 0) |
51 | | - var/damage_ratio = damage_maximum / damage |
| 48 | + var/damage_ratio = damage / max_damage |
52 | 49 | switch(damage_ratio) |
53 | 50 | if(0 to 0.3) |
54 | 51 | owner.remove_movespeed_modifier(/datum/movespeed_modifier/endoskeleton) |
|
61 | 58 | if(!damage) |
62 | 59 | STOP_PROCESSING(SSprocessing, src) |
63 | 60 |
|
| 61 | +/** |
| 62 | + * Does a full repair of the endoskeleton, also restoring max_damage to initial state. |
| 63 | + */ |
| 64 | +/datum/component/synthetic_endoskeleton/proc/full_repair(atom/source) |
| 65 | + max_damage = initial(max_damage) |
| 66 | + heal_damage(source, max_damage) |
| 67 | + |
64 | 68 | /** |
65 | 69 | * The function that handles exoskeleton damage effects. |
66 | 70 | */ |
67 | 71 | /datum/component/synthetic_endoskeleton/proc/handle_exoskeleton_damage() |
68 | 72 | if(damage) |
69 | 73 | START_PROCESSING(SSprocessing, src) |
70 | | - var/damage_ratio = damage_maximum / damage |
| 74 | + var/damage_ratio = damage / max_damage |
71 | 75 | switch(damage_ratio) |
72 | 76 | if(0.3 to 0.5) |
73 | | - to_chat(owner, SPAN_WARNING("Your self-preservation warning system notifies you of moderate damage to your endoskeleton's supports!")) |
| 77 | + notify_owner(owner, SPAN_WARNING("Your self-preservation warning system notifies you of moderate damage to your endoskeleton's supports!")) |
74 | 78 | owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/endoskeleton, multiplicative_slowdown = 1) |
75 | 79 | if(0.5 to 0.75) |
76 | | - to_chat(owner, SPAN_WARNING("Your self-preservation warning system notifies you of major damage to your endoskeleton!")) |
| 80 | + notify_owner(owner, SPAN_WARNING("Your self-preservation warning system notifies you of major damage to your endoskeleton!")) |
| 81 | + spark(owner, 2, GLOB.alldirs) |
77 | 82 | owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/endoskeleton, multiplicative_slowdown = 2) |
78 | | - if(0.75 to 1) |
79 | | - to_chat(owner, SPAN_DANGER(FONT_LARGE("Your self-preservation routines are starting to kick in! Your endoskeleton is falling apart!"))) |
| 83 | + if(0.75 to 0.99) |
| 84 | + notify_owner(owner, SPAN_DANGER("Your self-preservation routines are starting to kick in! Your endoskeleton is falling apart!")) |
| 85 | + spark(owner, 3, GLOB.alldirs) |
80 | 86 | owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/endoskeleton, multiplicative_slowdown = 3) |
81 | 87 | if(1 to INFINITY) |
82 | | - owner.visible_message(SPAN_DANGER("[owner]'s limbs seize up and [owner.get_pronoun("he")] falls to the ground!"), SPAN_DANGER(FONT_LARGE("Your self-preservation routines kick in and you enter a safety shutdown mode!"))) |
83 | | - SEND_SIGNAL(owner, COMSIG_SYNTH_SELF_PRESERVATION_TOGGLED) |
| 88 | + SEND_SIGNAL(owner, COMSIG_SYNTH_SET_SELF_PRESERVATION, TRUE) |
84 | 89 |
|
85 | 90 | /datum/component/synthetic_endoskeleton/process() |
86 | | - var/damage_ratio = damage_maximum / damage |
| 91 | + if(owner.stat) |
| 92 | + return |
| 93 | + |
| 94 | + var/damage_ratio = damage / max_damage |
87 | 95 | switch(damage_ratio) |
88 | 96 | if(0.3 to 0.5) |
89 | 97 | if(prob(5)) |
90 | | - to_chat(owner, SPAN_MACHINE_WARNING("Warning: Endoskeleton integrity at [100 - (damage_ratio * 100)]%.")) |
| 98 | + notify_owner(owner, SPAN_MACHINE_WARNING("Warning: Endoskeleton integrity at [100 - (damage_ratio * 100)]%.")) |
91 | 99 | if(0.5 to 0.75) |
92 | 100 | if(prob(10)) |
93 | | - to_chat(owner, SPAN_MACHINE_WARNING("WARNING: Endoskeleton integrity at [100 - (damage_ratio * 100)]%!")) |
94 | | - to_chat(owner, SPAN_WARNING("The mangled and exposed wires in your endoskeleton spark!")) |
| 101 | + notify_owner(owner, SPAN_MACHINE_WARNING("WARNING: Endoskeleton integrity at [100 - (damage_ratio * 100)]%!")) |
| 102 | + notify_owner(owner, SPAN_WARNING("The mangled and exposed wires in your endoskeleton spark!")) |
95 | 103 | spark(owner, 3, GLOB.alldirs) |
96 | 104 | owner.bodytemperature += 10 |
97 | 105 | if(0.75 to 1) |
98 | | - if(prob(20)) |
99 | | - to_chat(owner, SPAN_MACHINE_DANGER("ENDOSKELETON INTEGRITY CRITICAL. Your self preservation blares at you to return to safety!")) |
100 | | - to_chat(owner, SPAN_WARNING("Your frame creaks and groans, threatening to break apart at the metallic seams!")) |
| 106 | + if(prob(15)) |
| 107 | + notify_owner(owner, SPAN_MACHINE_DANGER(FONT_LARGE("ENDOSKELETON INTEGRITY CRITICAL. Your self preservation blares at you to return to safety!"))) |
| 108 | + notify_owner(owner, SPAN_DANGER("Your frame creaks and groans, threatening to break apart at the metallic seams!")) |
101 | 109 | spark(owner, 4, GLOB.alldirs) |
102 | 110 | owner.bodytemperature += 20 |
| 111 | + |
| 112 | +/** |
| 113 | + * Wrapper to_chat proc with a stat check. |
| 114 | + */ |
| 115 | +/datum/component/synthetic_endoskeleton/proc/notify_owner(mob/living/carbon/human/user, message) |
| 116 | + if(user.is_asystole() || (last_sent_message + message_cooldown > world.time)) |
| 117 | + return |
| 118 | + |
| 119 | + to_chat(user, message) |
| 120 | + last_sent_message = world.time |
0 commit comments