From dd4efb5a274976e211f91ab16750c4602be34d6d Mon Sep 17 00:00:00 2001 From: Mykhailo Bykhovtsev Date: Sat, 4 Aug 2018 11:14:32 -0700 Subject: [PATCH] EMP resistance items (#4995) Adds cyborg heavy surge prevention module as an upgrade by robotics. It is expensive to make, requires a bit high tech, and can protect cyborg for 1-3 EMP pulses which is purely random when module is installed. Adds IPC surge prevention module via antag uplink. The module comes in the form of modified red nanopaste that only interacts with IPCs. Like cyborg module it gives EMP protection for 1-3 pulses which is purely random by nanopaste. Can be used only once per paste. Cost for it is 14 telecrystals(idk if need to bump it higher, idea is that you can't buy two of them as traitor). adds sprite for new nanopaste with surge module. Cleans up some code in files I worked on. Fixes bug where destroyed cyborg components would vanish. Fixes #5000 --- code/datums/uplink/devices and tools.dm | 5 ++ .../objects/items/robot/robot_upgrades.dm | 16 ++-- code/game/objects/items/stacks/nanopaste.dm | 71 ++++++++++++++++++ .../mob/living/carbon/human/human_defense.dm | 15 ++++ .../mob/living/carbon/human/human_defines.dm | 2 +- .../mob/living/silicon/robot/component.dm | 22 +++++- .../modules/mob/living/silicon/robot/robot.dm | 2 +- .../mob/living/silicon/robot/robot_damage.dm | 18 ++++- code/modules/organs/subtypes/machine.dm | 19 +++++ code/modules/research/mechfab_designs.dm | 8 ++ html/changelogs/Sindorman-emp.yml | 13 ++++ icons/obj/nanopaste.dmi | Bin 311 -> 380 bytes icons/obj/robot_component.dmi | Bin 2415 -> 6319 bytes 13 files changed, 178 insertions(+), 13 deletions(-) create mode 100644 html/changelogs/Sindorman-emp.yml diff --git a/code/datums/uplink/devices and tools.dm b/code/datums/uplink/devices and tools.dm index 6f7021d4b18..6dde1c9aee2 100644 --- a/code/datums/uplink/devices and tools.dm +++ b/code/datums/uplink/devices and tools.dm @@ -21,6 +21,11 @@ path = /obj/item/device/firing_pin desc = "A Syndicate-branded Firing pin - It should be compatible with nearly every weapon onboard." +/datum/uplink_item/item/tools/surge + name = "IPC surge prevention module" + item_cost = 14 + path = /obj/item/stack/nanopaste/surge + desc = "An internal module that allow operative IPC frames to be protected from EMP pulse. The device has limited use that varies between one to three pulses" /datum/uplink_item/item/tools/clerical name = "Morphic Clerical Kit" diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 2a1b30af3fa..71dce7845f3 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -12,7 +12,7 @@ /obj/item/borg/upgrade/proc/action(var/mob/living/silicon/robot/R) if(R.stat == DEAD) - usr << "The [src] will not function on a deceased robot." + to_chat(usr, "The [src] will not function on a deceased robot.") return 1 return 0 @@ -65,7 +65,7 @@ if(..()) return 0 if(R.intenselight) - usr << "This cyborg's light was already upgraded" + to_chat(usr, "This cyborg's light was already upgraded ") return 0 else R.intenselight = 1 @@ -81,7 +81,7 @@ /obj/item/borg/upgrade/restart/action(var/mob/living/silicon/robot/R) if(R.health < 0) - usr << "You have to repair the robot before using this module!" + to_chat(usr, "You have to repair the robot before using this module!") return 0 if(!R.key) @@ -123,8 +123,8 @@ if(..()) return 0 if(!R.module || !(src.type in R.module.supported_upgrades)) - R << "Upgrade mounting error! No suitable hardpoint detected!" - usr << "There's no mounting point for the module!" + to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!") + to_chat(usr, " There's no mounting point for the module!") return 0 var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in R.module @@ -133,12 +133,12 @@ if(!T) T = locate() in R.module.modules if(!T) - usr << "This robot has had its taser removed!" + to_chat(usr, "This robot has had its taser removed!") return 0 if(T.recharge_time <= 2) - R << "Maximum cooling achieved for this hardpoint!" - usr << "There's no room for another cooling unit!" + to_chat(R, "Maximum cooling achieved for this hardpoint!") + to_chat(usr, "There's no room for another cooling unit!") return 0 else diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 9c3830c92b4..8cf15c8d7d4 100644 --- a/code/game/objects/items/stacks/nanopaste.dm +++ b/code/game/objects/items/stacks/nanopaste.dm @@ -58,3 +58,74 @@ return else user << "Nothing to fix in here." + + +/obj/item/stack/nanopaste/surge + name = "modified nanopaste" + singular_name = "nanite swarm" + desc = "A tube of paste containing swarms of repair nanites. This one appears to contain different nanites." + icon = 'icons/obj/nanopaste.dmi' + icon_state = "tube-surge" + origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_MAGNET = 5, TECH_POWER = 5, TECH_COMBAT = 3, TECH_ILLEGAL = 4) + amount = 20 + var/used = FALSE + construction_cost = null + +/obj/item/stack/nanopaste/surge/attack(mob/living/carbon/human/M as mob, mob/user as mob, var/target_zone) + if (!istype(M) || !istype(user)) + return 0 + + if(used) + to_chat(user, "[src] has depleted it's nanites.") + return 0 + + if (isipc(M)) + var/obj/item/organ/surge/s = M.internal_organs_by_name["surge"] + if(isnull(s)) + user.visible_message( + "[user] is trying to apply [src] to [(M == user) ? ("itself") : (M)]!", + "You start applying [src] to [(M == user) ? ("yourself") : (M)]!" + ) + + if (!do_mob(user, M, 2)) + return 0 + + s = new /obj/item/organ/surge() + M.internal_organs += s + M.internal_organs_by_name["surge"] = s + user.visible_message( + "[user] applies some nanite paste to [(M == user) ? ("itself") : (M)]!", + "You apply [src] to [(M == user) ? ("youself") : (M)]." + ) + to_chat(M, "You can feel nanites inside you creating something new. An internal OS voice states \"Warning: surge prevention module has been installed, it has [s.surge_left] preventions left!\"") + amount = 0 + used = TRUE + return 1 + else + if(!s.surge_left) + user.visible_message( + "[user] is trying to apply [src] to [(M == user) ? ("itself") : (M)]!", + "You start applying [src] to [(M == user) ? ("yourself") : (M)]!" + ) + + if (!do_mob(user, M, 2)) + return 0 + + s.surge_left = rand(1, 3) + s.broken = 0 + s.icon_state = "surge_ipc" + + user.visible_message( + "[user] applies some nanite paste to [(M == user) ? ("itself") : (M)]!", + "You apply [src] to [(M == user) ? ("yourself") : (M)]." + ) + to_chat(M, "You can feel nanites inside you regenerating your surge prevention module. An internal OS voice states \"Warning: surge prevention module repaired, it has [s.surge_left] preventions left!\"") + amount = 0 + used = TRUE + return 1 + + to_chat(user, "[(M == user) ? ("You already have") : ("[M] already has")] fully functional surge prevention module installed.") + return 0 + else + to_chat(user, "[src]'s nanites refuse to work on [(M == user) ? ("you") : (M)].") + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 6e459f2cffb..ca8c61ebd00 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -158,6 +158,21 @@ emp_act return 0 /mob/living/carbon/human/emp_act(severity) + if(isipc(src)) + var/obj/item/organ/surge/s = src.internal_organs_by_name["surge"] + if(!isnull(s)) + if(s.surge_left) + playsound(src.loc, 'sound/magic/LightningShock.ogg', 25, 1) + s.surge_left -= 1 + if(s.surge_left) + to_chat(src, "Warning: EMP detected, integrated surge prevention module activated. There are [s.surge_left] preventions left.") + else + s.broken = 1 + s.icon_state = "surge_ipc_broken" + to_chat(src, "Warning: EMP detected, integrated surge prevention module activated. The surge prevention module is fried, replacement recommended.") + return 1 + else + to_chat(src, "Warning: EMP detected, integrated surge prevention module is fried and unable to protect from EMP. Replacement recommended.") for(var/obj/O in src) if(!O) continue O.emp_act(severity) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 70ea3e2cb96..c662701be83 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -112,4 +112,4 @@ var/datum/unarmed_attack/default_attack //default unarmed attack - var/datum/martial_art/martial_art = null \ No newline at end of file + var/datum/martial_art/martial_art = null diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index 83a1e3efd98..78fe1cc1d94 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -40,7 +40,7 @@ // The thing itself isn't there anymore, but some fried remains are. uninstall() installed = -1 - + /datum/robot_component/proc/get_damage(var/type) return Clamp(brute_damage + electronics_damage,0,max_damage) @@ -94,6 +94,17 @@ var/obj/item/weapon/tank/jetpack/carbondioxide/synthetic/tank = null +/datum/robot_component/surge + name = "surge preventor" + external_type = /obj/item/robot_parts/robot_component/surge + max_damage = 60 + installed = 0 + var/surge_left = 0 + +/datum/robot_component/surge/install() + ..() + if(!surge_left) + surge_left = rand(1, 3) /datum/robot_component/jetpack/install() ..() @@ -223,6 +234,7 @@ components["comms"] = new/datum/robot_component/binary_communication(src) components["armour"] = new/datum/robot_component/armour(src) components["jetpack"] = new/datum/robot_component/jetpack(src) + components["surge"] = new/datum/robot_component/surge(src) jetpackComponent = components["jetpack"] jetpackComponent.installed = 0//We start the jetpack as not installed, because its nondefault @@ -272,6 +284,12 @@ icon_state = "armor" icon_state_broken = "armor_broken" +/obj/item/robot_parts/robot_component/surge + name = "surge preventor" + desc = "Cyborg component designed to save internal electronics from damage of EMP pulse." + icon_state = "surge" + icon_state_broken = "surge_broken" + /obj/item/robot_parts/robot_component/camera name = "camera" icon_state = "camera" @@ -291,4 +309,4 @@ /obj/item/robot_parts/robot_component/radio name = "radio" icon_state = "radio" - icon_state_broken = "radio_broken" \ No newline at end of file + icon_state_broken = "radio_broken" diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 4e0417abb3a..b41b7a1022e 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -150,7 +150,7 @@ initialize_components() //if(!unfinished) // Create all the robot parts. - for(var/V in components) if(V != "power cell" && V != "jetpack")//We don't install the jetpack onstart + for(var/V in components) if(V != "power cell" && V != "jetpack" && V != "surge")//We don't install the jetpack onstart var/datum/robot_component/C = components[V] C.installed = 1 C.wrapped = new C.external_type diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm index 8b44277f249..6a7aed3b651 100644 --- a/code/modules/mob/living/silicon/robot/robot_damage.dm +++ b/code/modules/mob/living/silicon/robot/robot_damage.dm @@ -10,7 +10,7 @@ var/amount = 0 for(var/V in components) var/datum/robot_component/C = components[V] - if(C.installed) + if(C.installed) amount += Clamp(C.brute_damage,0,C.max_damage) else if(C.installed == -1) amount += C.max_damage/2 @@ -153,3 +153,19 @@ burn -= (picked.electronics_damage - burn_was) parts -= picked + +/mob/living/silicon/robot/emp_act(severity) + if(components["surge"] && components["surge"].installed) + if(components["surge"].surge_left) + playsound(src.loc, 'sound/magic/LightningShock.ogg', 25, 1) + components["surge"].surge_left -= 1 + visible_message("[src] was not affected by EMP pulse.", "Warning: Power surge detected, source - EMP. Surge prevention module re-routed surge to prevent damage to vital electronics.") + if(components["surge"].surge_left) + to_chat(src, "Surge module has [components["surge"].surge_left] preventions left!") + else + components["surge"].destroy() + to_chat(src, "Module is entirely fried, replacement is recommended.") + return + else + to_chat(src, "Warning: Power surge detected, source - EMP. Surge prevention module is depleted and requires replacement") + ..() \ No newline at end of file diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm index bbf3d0c8330..efe26734538 100644 --- a/code/modules/organs/subtypes/machine.dm +++ b/code/modules/organs/subtypes/machine.dm @@ -82,6 +82,25 @@ owner.Paralyse(emp_counter/6) owner << "%#/ERR: Power leak detected!$%^/" + +/obj/item/organ/surge + name = "surge preventor" + desc = "A small device that give immunity to EMP for few pulses." + icon = 'icons/obj/robot_component.dmi' + icon_state = "surge_ipc" + organ_tag = "surge" + parent_organ = "chest" + vital = 0 + var/surge_left = 0 + var/broken = 0 + +/obj/item/organ/surge/Initialize() + if(!surge_left && !broken) + surge_left = rand(1, 3) + robotize() + . = ..() + + /obj/item/organ/eyes/optical_sensor name = "optical sensor" singular_name = "optical sensor" diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm index fd70777dd8e..253cc435a72 100644 --- a/code/modules/research/mechfab_designs.dm +++ b/code/modules/research/mechfab_designs.dm @@ -96,6 +96,14 @@ id = "armour" build_path = /obj/item/robot_parts/robot_component/armour +/datum/design/item/mechfab/robot/component/surge + name = "Heavy surge prevention module" + desc = "Used to boost prevent damage from EMP. Has limited surge preventions." + id = "borg_surge_module" + materials = list(DEFAULT_WALL_MATERIAL = 20000, "glass" = 6000, "gold" = 10000, "silver" = 15000) // Should be expensive + req_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 2, TECH_MAGNET = 5, TECH_POWER = 5, TECH_ENGINEERING = 4, TECH_COMBAT = 3) + build_path = /obj/item/robot_parts/robot_component/surge + /datum/design/item/mechfab/ripley category = "Ripley" diff --git a/html/changelogs/Sindorman-emp.yml b/html/changelogs/Sindorman-emp.yml new file mode 100644 index 00000000000..1ebfb6095ca --- /dev/null +++ b/html/changelogs/Sindorman-emp.yml @@ -0,0 +1,13 @@ +author: PoZe + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Adds cyborg surge prevention upgrade module. It is an upgrade that makes cyborg being immune to 1-3 EMP pulses. Can be constructed by robotics, but is expensive and high tech. After being fried, module can be replaced with new module" + - rscadd: "Adds IPC surge prevention module. Available only via traitor uplink, costs 14 telecrystals. Just like cyborg module it make user immune to 1-3 EMP pulses. Comes in from uplink as modified nanopaste that is one time use(doesn't heal user). Module can be repaired with another traitor nanopaste" diff --git a/icons/obj/nanopaste.dmi b/icons/obj/nanopaste.dmi index b3c096325f9134bbd4eafc10448c211712bf0984..00bafd43503b5c6984ca4852667c9afbf36ef27b 100644 GIT binary patch delta 295 zcmdna^oJ>f_=LC~IB>w&cxD=d zvChWJ#xu{H0dg3O(`Nqn_4RFT?w&n+c2Z(;!K8iv(~Mb+HN}9s7)yfuf*Bm1-ADs+ z3Maa5lDop+$2In! zzp(SCNteU(YdI#Y)oTJpb9VQxJ21O}lV$CVrgaR5&A3d=->9arI=Uy#FsOdcQv)>Q l?rxBF2`j4)pWCe&7_5?9eKg(oC<5KX;OXk;vd$@?2><|paT5Rl delta 225 zcmeyvw4EuYGr-TCmrII^fq{Y7)59eQNGpIa3p0>x3`su@q~rp8LR=3VIACl%Q)lC4 z#8@N(6hlIEH9UOioy!o*?2NEMVj!ED-4ObaR`gQu&X%Q~loCIE!5PT2qe diff --git a/icons/obj/robot_component.dmi b/icons/obj/robot_component.dmi index 1129f25ab1c10c0121614dd223c23cac16a06fd2..a8a04170f939ad1307a10b3be53f193d0bd455db 100644 GIT binary patch literal 6319 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 hSYwSf)>z{~