diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index e5b07ca8..6b7152f0 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -616,18 +616,6 @@
updateDialog()
return
-/obj/machinery/alarm/proc/shock(mob/user, prb)
- if((stat & (NOPOWER))) // unpowered, no shock
- return 0
- if(!prob(prb))
- return 0 //you lucked out, no shock for you
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start() //sparks always.
- if (electrocute_mob(user, get_area(src), src))
- return 1
- else
- return 0
///////////////
//END HACKING//
///////////////
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index d42ead98..731906d7 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -143,18 +143,7 @@ var/global/list/autolathe_recipes_hidden = list( \
user << browse("
Autolathe Control Panel[dat]", "window=autolathe_regular")
onclose(user, "autolathe_regular")
- shock(mob/user, prb)
- if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
- return 0
- if(!prob(prb))
- return 0
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- if (electrocute_mob(user, get_area(src), src, 0.7))
- return 1
- else
- return 0
+
interact(mob/user as mob)
if(istype(user, /mob/living/carbon/human))
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index d5f6ed1e..9fe62563 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -94,11 +94,6 @@
src.view_range = num
cameranet.updateVisibility(src, 0)
-/obj/machinery/camera/proc/shock(var/mob/living/user)
- if(!istype(user))
- return
- user.electrocute_act(10, src)
-
/obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user as mob)
if(!istype(user))
return
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index a2ef4bb7..9dba5ddd 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -597,17 +597,12 @@ About the new airlock wires panel:
// shock user with probability prb (if all connections & power are working)
// returns 1 if shocked, 0 otherwise
// The preceding comment was borrowed from the grille's shock script
-/obj/machinery/door/airlock/proc/shock(mob/user, prb)
- if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock
+/obj/machinery/door/airlock/shock(mob/user, prb)
+ if(!arePowerSystemsOn())
return 0
if(hasShocked)
return 0 //Already shocked someone recently?
- if(!prob(prb))
- return 0 //you lucked out, no shock for you
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start() //sparks always.
- if(electrocute_mob(user, get_area(src), src))
+ if(..())
hasShocked = 1
sleep(10)
hasShocked = 0
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index 5974cce6..ad15d889 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -407,16 +407,6 @@
src.visible_message("\red [src] launches [throw_item.name] at [target.name]!")
return 1
-/obj/machinery/smartfridge/proc/shock(mob/user, prb)
- if(!ispowered) return 0
- if(!prob(prb)) return 0
-
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
-
- return electrocute_mob(user, get_area(src), src, 0.7)
-
/************************
* Secure SmartFridges
*************************/
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index d8f05eb5..5b7a47e7 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -278,3 +278,17 @@ Class Procs:
return
else
user << "The item is secured to the floor too firmly."
+
+/obj/machinery/proc/shock(mob/user, prb)
+// if(inoperable())
+// return 0
+ if(!prob(prb))
+ return 0
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ if (electrocute_mob(user, get_area(src), src, 0.7))
+ return 1
+ else
+ return 0
+
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index b716d941..1d251596 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -567,4 +567,568 @@
return
-//////////////////////////////REMINDER: Make it lock once you place some fucker inside.
\ No newline at end of file
+//////////////////////////////REMINDER: Make it lock once you place some fucker inside.
+
+//God this entire file is fucking awful
+//Suit painter for Bay's special snowflake aliums.
+
+/obj/machinery/suit_cycler
+
+ name = "suit cycler"
+ desc = "An industrial machine for painting and refitting hardsuits."
+ anchored = 1
+ density = 1
+
+ icon = 'icons/obj/suitstorage.dmi'
+ icon_state = "suitstorage000000100"
+
+ req_access = list(access_captain,access_heads)
+
+ var/active = 0 // PLEASE HOLD.
+ var/safeties = 1 // The cycler won't start with a living thing inside it unless safeties are off.
+ var/irradiating = 0 // If this is > 0, the cycler is decontaminating whatever is inside it.
+ var/radiation_level = 2 // 1 is removing germs, 2 is removing blood, 3 is removing phoron.
+ var/model_text = "" // Some flavour text for the topic box.
+ var/locked = 1 // If locked, nothing can be taken from or added to the cycler.
+ var/panel_open = 0 // Hacking!
+ var/can_repair // If set, the cycler can repair hardsuits.
+
+ // Wiring bollocks.
+ var/wires = 15
+ var/electrified = 0
+ var/const/WIRE_EXTEND = 1 // Safeties
+ var/const/WIRE_SCANID = 2 // Locked status
+ var/const/WIRE_SHOCK = 3 // What it says on the tin.
+
+ //Departments that the cycler can paint suits to look like.
+ var/list/departments = list("Engineering","Mining","Medical","Security","Atmos")
+ //Species that the suits can be configured to fit.
+ var/list/species = list("Human","Skrell","Unathi","Tajaran")
+
+ var/target_department
+ var/target_species
+
+ var/mob/living/carbon/human/occupant = null
+ var/obj/item/clothing/suit/space/rig/suit = null
+ var/obj/item/clothing/head/helmet/space/helmet = null
+
+/obj/machinery/suit_cycler/New()
+ ..()
+ target_department = departments[1]
+ target_species = species[1]
+ if(!target_department || !target_species) del(src)
+
+/obj/machinery/suit_cycler/engineering
+ name = "Engineering suit cycler"
+ model_text = "Engineering"
+ req_access = list(access_construction)
+ departments = list("Engineering","Atmos")
+ species = list("Human","Tajaran","Skrell","Unathi") //Add Unathi when sprites exist for their suits.
+
+/obj/machinery/suit_cycler/mining
+ name = "Mining suit cycler"
+ model_text = "Mining"
+ req_access = list(access_mining)
+ departments = list("Mining")
+ species = list("Human","Tajaran","Skrell","Unathi")
+
+/obj/machinery/suit_cycler/security
+ name = "Security suit cycler"
+ model_text = "Security"
+ req_access = list(access_security)
+ departments = list("Security")
+ species = list("Human","Tajaran","Skrell","Unathi")
+
+/obj/machinery/suit_cycler/medical
+ name = "Medical suit cycler"
+ model_text = "Medical"
+ req_access = list(access_medical)
+ departments = list("Medical")
+ species = list("Human","Tajaran","Skrell","Unathi")
+
+/obj/machinery/suit_cycler/syndicate
+ name = "Nonstandard suit cycler"
+ model_text = "Nonstandard"
+ req_access = list(access_syndicate)
+ departments = list("Mercenary")
+ species = list("Human","Tajaran","Skrell","Unathi")
+ can_repair = 1
+
+/obj/machinery/suit_cycler/attack_ai(mob/user as mob)
+ return src.attack_hand(user)
+
+/obj/machinery/suit_cycler/attack_paw(mob/user as mob)
+ user << "\blue The console controls are far too complicated for your tiny brain!"
+ return
+
+/obj/machinery/suit_cycler/attackby(obj/item/I as obj, mob/user as mob)
+
+ if(electrified != 0)
+ if(src.shock(user, 100))
+ return
+
+ //Hacking init.
+ if(istype(I, /obj/item/device/multitool) || istype(I, /obj/item/weapon/wirecutters))
+ if(panel_open)
+ attack_hand(user)
+ return
+ //Other interface stuff.
+ if(istype(I, /obj/item/weapon/grab))
+ var/obj/item/weapon/grab/G = I
+
+ if(!(ismob(G.affecting)))
+ return
+
+ if(locked)
+ user << "\red The suit cycler is locked."
+ return
+
+ if(src.contents.len > 0)
+ user << "\red There is no room inside the cycler for [G.affecting.name]."
+ return
+
+ visible_message("[user] starts putting [G.affecting.name] into the suit cycler.", 3)
+
+ if(do_after(user, 20))
+ if(!G || !G.affecting) return
+ var/mob/M = G.affecting
+ if (M.client)
+ M.client.perspective = EYE_PERSPECTIVE
+ M.client.eye = src
+ M.loc = src
+ src.occupant = M
+
+ src.add_fingerprint(user)
+ del(G)
+
+ src.updateUsrDialog()
+
+ return
+ else if(istype(I,/obj/item/weapon/screwdriver))
+
+ panel_open = !panel_open
+ user << "You [panel_open ? "open" : "close"] the maintenance panel."
+ src.updateUsrDialog()
+ return
+
+ else if(istype(I,/obj/item/weapon/card/emag))
+
+ if(emagged)
+ user << "\red The cycler has already been subverted."
+ return
+
+ var/obj/item/weapon/card/emag/E = I
+ src.updateUsrDialog()
+ E.uses--
+
+ //Clear the access reqs, disable the safeties, and open up all paintjobs.
+ user << "\red You run the sequencer across the interface, corrupting the operating protocols."
+ departments = list("Engineering","Mining","Medical","Security","Atmos","^%###^%$")
+ emagged = 1
+ safeties = 0
+ req_access = list()
+ return
+
+ else if(istype(I,/obj/item/clothing/head/helmet/space))
+
+ if(locked)
+ user << "\red The suit cycler is locked."
+ return
+
+ if(helmet)
+ user << "The cycler already contains a helmet."
+ return
+
+ user << "You fit \the [I] into the suit cycler."
+ user.drop_item()
+ I.loc = src
+ helmet = I
+
+ src.update_icon()
+ src.updateUsrDialog()
+ return
+
+ else if(istype(I,/obj/item/clothing/suit/space/rig))
+
+ if(locked)
+ user << "\red The suit cycler is locked."
+ return
+
+ if(suit)
+ user << "The cycler already contains a hardsuit."
+ return
+
+ var/obj/item/clothing/suit/space/rig/S = I
+
+ if(S.helmet)
+ user << "\The [S] will not fit into the cycler with a helmet attached."
+ return
+
+ if(S.boots)
+ user << "\The [S] will not fit into the cycler with boots attached."
+ return
+
+ user << "You fit \the [I] into the suit cycler."
+ user.drop_item()
+ I.loc = src
+ suit = I
+
+ src.update_icon()
+ src.updateUsrDialog()
+ return
+
+ ..()
+
+/obj/machinery/suit_cycler/attack_hand(mob/user as mob)
+
+ add_fingerprint(user)
+
+ if(..() || stat & (BROKEN|NOPOWER))
+ return
+
+ if(electrified != 0)
+ if(src.shock(user, 100))
+ return
+
+ usr.set_machine(src)
+
+ var/dat = "Suit Cycler Interface"
+
+ if(src.active)
+ dat+= "
The [model_text ? "[model_text] " : ""]suit cycler is currently in use. Please wait..."
+
+ else if(locked)
+ dat += "
The [model_text ? "[model_text] " : ""]suit cycler is currently locked. Please contact your system administrator."
+ if(src.allowed(usr))
+ dat += "
\[unlock unit\]"
+ else
+ dat += "Suit cycler
"
+ dat += "Welcome to the [model_text ? "[model_text] " : ""]suit cycler control panel. \[lock unit\]
"
+
+ dat += "Maintenance
"
+ dat += "Helmet: [helmet ? "\the [helmet]" : "no helmet stored" ]. \[eject\]
"
+ dat += "Suit: [suit ? "\the [suit]" : "no suit stored" ]. \[eject\]"
+
+ if(can_repair && suit && istype(suit))
+ dat += "[(suit.damage ? " \[repair\]" : "")]"
+
+ dat += "
UV decontamination systems: SYSTEM ERROR" : "green'>READY"]
"
+ dat += "Output level: [radiation_level]
"
+ dat += "\[select power level\] \[begin decontamination cycle\]
"
+
+ dat += "Customisation
"
+ dat += "Target product: [target_department], [target_species]."
+ dat += "
\[apply customisation routine\]
"
+
+ if(panel_open)
+ var/list/vendwires = list(
+ "Violet" = 1,
+ "Orange" = 2,
+ "Goldenrod" = 3,
+ )
+ dat += "Access Panel
"
+ for(var/wiredesc in vendwires)
+ var/is_uncut = src.wires & APCWireColorToFlag[vendwires[wiredesc]]
+ dat += "[wiredesc] wire: "
+ if(!is_uncut)
+ dat += "Mend"
+ else
+ dat += "Cut "
+ dat += "Pulse "
+ dat += "
"
+
+ dat += "
"
+ dat += "The orange light is [(electrified == 0) ? "off" : "on"].
"
+ dat += "The red light is [safeties ? "blinking" : "off"].
"
+ dat += "The yellow light is [locked ? "on" : "off"].
"
+
+ user << browse(dat, "window=suit_cycler")
+ onclose(user, "suit_cycler")
+ return
+
+/obj/machinery/suit_cycler/Topic(href, href_list)
+ if(href_list["eject_suit"])
+ if(!suit) return
+ suit.loc = get_turf(src)
+ suit = null
+ else if(href_list["eject_helmet"])
+ if(!helmet) return
+ helmet.loc = get_turf(src)
+ helmet = null
+ else if(href_list["select_department"])
+ var/choice = input("Please select the target department paintjob.","Suit cycler",null) as null|anything in departments
+ if(choice) target_department = choice
+ else if(href_list["select_species"])
+ var/choice = input("Please select the target species configuration.","Suit cycler",null) as null|anything in species
+ if(choice) target_species = choice
+ else if(href_list["select_rad_level"])
+ var/choices = list(1,2,3)
+ if(emagged)
+ choices = list(1,2,3,4,5)
+ radiation_level = input("Please select the desired radiation level.","Suit cycler",null) as null|anything in choices
+ else if(href_list["repair_suit"])
+
+ if(!suit || !can_repair) return
+ active = 1
+ spawn(100)
+ repair_suit()
+ finished_job()
+
+ else if(href_list["apply_paintjob"])
+
+ if(!suit && !helmet) return
+ active = 1
+ spawn(100)
+ apply_paintjob()
+ finished_job()
+
+ else if(href_list["toggle_safties"])
+ safeties = !safeties
+
+ else if(href_list["toggle_lock"])
+
+ if(src.allowed(usr))
+ locked = !locked
+ usr << "You [locked ? "" : "un"]lock \the [src]."
+ else
+ usr << "\red Access denied."
+
+ else if(href_list["begin_decontamination"])
+
+ if(safeties && occupant)
+ usr << "\red The cycler has detected an occupant. Please remove the occupant before commencing the decontamination cycle."
+ return
+
+ active = 1
+ irradiating = 10
+ src.updateUsrDialog()
+
+ sleep(10)
+
+ if(helmet)
+ if(radiation_level > 2)
+ helmet.decontaminate()
+ if(radiation_level > 1)
+ helmet.clean_blood()
+
+ if(suit)
+ if(radiation_level > 2)
+ suit.decontaminate()
+ if(radiation_level > 1)
+ suit.clean_blood()
+
+ else if ((href_list["cutwire"]) && (src.panel_open))
+ var/twire = text2num(href_list["cutwire"])
+ if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) ))
+ usr << "You need wirecutters!"
+ return
+ if (src.isWireColorCut(twire))
+ src.mend(twire)
+ else
+ src.cut(twire)
+
+ else if ((href_list["pulsewire"]) && (src.panel_open))
+ var/twire = text2num(href_list["pulsewire"])
+ if (!istype(usr.get_active_hand(), /obj/item/device/multitool))
+ usr << "You need a multitool!"
+ return
+ if (src.isWireColorCut(twire))
+ usr << "You can't pulse a cut wire."
+ return
+ else
+ src.pulse(twire)
+
+ src.updateUsrDialog()
+ return
+
+/obj/machinery/suit_cycler/process()
+
+ if(electrified > 0)
+ electrified--
+
+ if(!active)
+ return
+
+ if(active && stat & (BROKEN|NOPOWER))
+ active = 0
+ irradiating = 0
+ electrified = 0
+ return
+
+ if(irradiating == 1)
+ finished_job()
+ irradiating = 0
+ return
+
+ irradiating--
+
+ if(occupant)
+ if(prob(radiation_level*2)) occupant.emote("scream")
+ if(radiation_level > 2)
+ occupant.take_organ_damage(0,radiation_level*2 + rand(1,3))
+ if(radiation_level > 1)
+ occupant.take_organ_damage(0,radiation_level + rand(1,3))
+ occupant.radiation += radiation_level*10
+
+/obj/machinery/suit_cycler/proc/finished_job()
+ var/turf/T = get_turf(src)
+ T.visible_message("\icon[src] \blue The [src] pings loudly.")
+ icon_state = initial(icon_state)
+ active = 0
+ src.updateUsrDialog()
+
+/obj/machinery/suit_cycler/proc/repair_suit()
+ if(!suit || !suit.damage || !suit.can_breach)
+ return
+
+ suit.breaches = list()
+ suit.calc_breach_damage()
+
+ return
+
+/obj/machinery/suit_cycler/verb/leave()
+ set name = "Eject Cycler"
+ set category = "Object"
+ set src in oview(1)
+
+ if (usr.stat != 0)
+ return
+
+ eject_occupant(usr)
+
+/obj/machinery/suit_cycler/proc/eject_occupant(mob/user as mob)
+
+ if(locked || active)
+ user << "\red The cycler is locked."
+ return
+
+ if (!occupant)
+ return
+
+ if (occupant.client)
+ occupant.client.eye = occupant.client.mob
+ occupant.client.perspective = MOB_PERSPECTIVE
+
+ occupant.loc = get_turf(occupant)
+ occupant = null
+
+ add_fingerprint(usr)
+ src.updateUsrDialog()
+ src.update_icon()
+
+ return
+
+//HACKING PROCS, MOSTLY COPIED FROM VENDING MACHINES
+/obj/machinery/suit_cycler/proc/isWireColorCut(var/wireColor)
+ var/wireFlag = APCWireColorToFlag[wireColor]
+ return ((src.wires & wireFlag) == 0)
+
+/obj/machinery/suit_cycler/proc/isWireCut(var/wireIndex)
+ var/wireFlag = APCIndexToFlag[wireIndex]
+ return ((src.wires & wireFlag) == 0)
+
+/obj/machinery/suit_cycler/proc/cut(var/wireColor)
+ var/wireFlag = APCWireColorToFlag[wireColor]
+ var/wireIndex = APCWireColorToIndex[wireColor]
+ src.wires &= ~wireFlag
+ switch(wireIndex)
+
+ if(WIRE_EXTEND)
+ safeties = 0
+ if(WIRE_SHOCK)
+ electrified = -1
+ if (WIRE_SCANID)
+ locked = 0
+
+/obj/machinery/suit_cycler/proc/mend(var/wireColor)
+ var/wireFlag = APCWireColorToFlag[wireColor]
+ var/wireIndex = APCWireColorToIndex[wireColor] //not used in this function
+ src.wires |= wireFlag
+ switch(wireIndex)
+ if(WIRE_SHOCK)
+ src.electrified = 0
+
+/obj/machinery/suit_cycler/proc/pulse(var/wireColor)
+ var/wireIndex = APCWireColorToIndex[wireColor]
+ switch(wireIndex)
+ if(WIRE_EXTEND)
+ safeties = !locked
+ if(WIRE_SHOCK)
+ electrified = 30
+ if (WIRE_SCANID)
+ locked = !locked
+
+//There HAS to be a less bloated way to do this. TODO: some kind of table/icon name coding? ~Z
+/obj/machinery/suit_cycler/proc/apply_paintjob()
+
+ if(!target_species || !target_department)
+ return
+
+ if(target_species)
+ if(helmet) helmet.refit_for_species(target_species)
+ if(suit) suit.refit_for_species(target_species)
+
+ switch(target_department)
+ if("Engineering")
+ if(helmet)
+ helmet.name = "engineering hardsuit helmet"
+ helmet.icon_state = "rig0-engineering"
+ helmet.item_state = "eng_helm"
+ helmet.item_color = "engineering"
+ if(suit)
+ suit.name = "engineering hardsuit"
+ suit.icon_state = "rig-engineering"
+ suit.item_state = "eng_hardsuit"
+ if("Mining")
+ if(helmet)
+ helmet.name = "mining hardsuit helmet"
+ helmet.icon_state = "rig0-mining"
+ helmet.item_state = "mining_helm"
+ helmet.item_color = "mining"
+ if(suit)
+ suit.name = "mining hardsuit"
+ suit.icon_state = "rig-mining"
+ suit.item_state = "mining_hardsuit"
+ if("Medical")
+ if(helmet)
+ helmet.name = "medical hardsuit helmet"
+ helmet.icon_state = "rig0-medical"
+ helmet.item_state = "medical_helm"
+ helmet.item_color = "medical"
+ if(suit)
+ suit.name = "medical hardsuit"
+ suit.icon_state = "rig-medical"
+ suit.item_state = "medical_hardsuit"
+ if("Security")
+ if(helmet)
+ helmet.name = "security hardsuit helmet"
+ helmet.icon_state = "rig0-sec"
+ helmet.item_state = "sec_helm"
+ helmet.item_color = "sec"
+ if(suit)
+ suit.name = "security hardsuit"
+ suit.icon_state = "rig-sec"
+ suit.item_state = "sec_hardsuit"
+ if("Atmos")
+ if(helmet)
+ helmet.name = "atmospherics hardsuit helmet"
+ helmet.icon_state = "rig0-atmos"
+ helmet.item_state = "atmos_helm"
+ helmet.item_color = "atmos"
+ if(suit)
+ suit.name = "atmospherics hardsuit"
+ suit.icon_state = "rig-atmos"
+ suit.item_state = "atmos_hardsuit"
+ if("^%###^%$" || "Mercenary")
+ if(helmet)
+ helmet.name = "blood-red hardsuit helmet"
+ helmet.icon_state = "rig0-syndie"
+ helmet.item_state = "syndie_helm"
+ helmet.item_color = "syndie"
+ if(suit)
+ suit.name = "blood-red hardsuit"
+ suit.item_state = "syndie_hardsuit"
+ suit.icon_state = "rig-syndie"
+
+ if(helmet) helmet.name = "refitted [helmet.name]"
+ if(suit) suit.name = "refitted [suit.name]"
\ No newline at end of file
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 3693fa0d..381cc702 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -588,19 +588,6 @@
src.shoot_inventory = !src.shoot_inventory
-/obj/machinery/vending/proc/shock(mob/user, prb)
- if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
- return 0
- if(!prob(prb))
- return 0
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- if (electrocute_mob(user, get_area(src), src, 0.7))
- return 1
- else
- return 0
-
/*
* Vending machine types
*/
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 1b256543..dde17c84 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -39,8 +39,22 @@
var/armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
var/list/allowed = null //suit storage stuff.
var/obj/item/device/uplink/hidden/hidden_uplink = null // All items can have an uplink hidden inside, just remember to add the triggers.
+
+ /* Species-specific sprites, concept stolen from Paradise//vg/.
+ ex:
+ sprite_sheets = list(
+ "Tajaran" = 'icons/cat/are/bad'
+ )
+ If index term exists and icon_override is not set, this sprite sheet will be used.
+ */
+ var/list/sprite_sheets = null
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
+ /* Species-specific sprite sheets for inventory sprites
+ Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called.
+ */
+ var/list/sprite_sheets_obj = null
+
/obj/item/device
icon = 'icons/obj/device.dmi'
@@ -477,6 +491,12 @@
/obj/item/proc/IsShield()
return 0
+/obj/item/proc/get_loc_turf()
+ var/atom/L = loc
+ while(L && !istype(L, /turf/))
+ L = L.loc
+ return loc
+
/obj/item/proc/eyestab(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
var/mob/living/carbon/human/H = M
@@ -525,7 +545,9 @@
"\red You stab yourself in the eyes with [src]!" \
)
if(istype(M, /mob/living/carbon/human))
- var/datum/organ/internal/eyes/eyes = H.internal_organs["eyes"]
+ var/datum/organ/internal/eyes/eyes = H.internal_organs_by_name["eyes"]
+ if(!eyes)
+ return
eyes.damage += rand(3,4)
if(eyes.damage >= eyes.min_bruised_damage)
if(M.stat != 2)
diff --git a/code/game/objects/items/devices/modkit.dm b/code/game/objects/items/devices/modkit.dm
index 1037c6af..02d11f22 100644
--- a/code/game/objects/items/devices/modkit.dm
+++ b/code/game/objects/items/devices/modkit.dm
@@ -7,79 +7,66 @@
desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user."
icon_state = "modkit"
var/parts = MODKIT_FULL
- var/list/from_helmet = list(/obj/item/clothing/head/helmet/space/rig)
- var/list/from_suit = list(/obj/item/clothing/suit/space/rig)
- var/list/to_helmet = list(/obj/item/clothing/head/cardborg)
- var/list/to_suit = list(/obj/item/clothing/suit/cardborg)
+ var/target_species = "Human"
-/obj/item/device/modkit/afterattack(obj/O, mob/user as mob)
- var/flag
- var/to_type
+ var/list/permitted_types = list(
+ /obj/item/clothing/head/helmet/space/rig,
+ /obj/item/clothing/suit/space/rig
+ )
- for(var/i = 1, i <= from_helmet.len, i++)
-// msg_scopes("[from_helmet[i]]")
- if(istype(O, from_helmet[i]))
- to_type = to_helmet[i]
- flag = MODKIT_HELMET
- break
-
- if(istype(O, from_suit[i]))
- flag = MODKIT_SUIT
- to_type = to_suit[i]
- break
-
- if(!flag)
+/obj/item/device/modkit/afterattack(obj/O, mob/user as mob, proximity)
+ if(!proximity)
return
+
+ if (!target_species)
+ return //it shouldn't be null, okay?
- if(!(parts & flag))
+ if(!parts)
user << "This kit has no parts for this modification left."
+ user.drop_from_inventory(src)
+ del(src)
return
- if(istype(O,to_type))
- user << "[O] is already modified."
+
+ var/allowed = 0
+ for (var/permitted_type in permitted_types)
+ if(istype(O, permitted_type))
+ allowed = 1
+
+ var/obj/item/clothing/I = O
+ if (!istype(I) || !allowed)
+ user << "[src] is unable to modify that."
return
+
+ var/excluding = ("exclude" in I.species_restricted)
+ var/in_list = (target_species in I.species_restricted)
+ if (excluding ^ in_list)
+ user << "[I] is already modified."
+ return
+
if(!isturf(O.loc))
user << "[O] must be safely placed on the ground for modification."
return
+
playsound(user.loc, 'sound/items/Screwdriver.ogg', 100, 1)
- msg_scopes("[to_type]")
- var/N = new to_type(O.loc)
- user.visible_message("\red [user] opens \the [src] and modifies \the [O] into \the [N].","\red You open \the [src] and modify \the [O] into \the [N].")
- del(O)
- parts &= ~flag
+
+ user.visible_message("\red [user] opens \the [src] and modifies \the [O].","\red You open \the [src] and modify \the [O].")
+
+ I.refit_for_species(target_species)
+
+ if (istype(I, /obj/item/clothing/head/helmet))
+ parts &= ~MODKIT_HELMET
+ if (istype(I, /obj/item/clothing/suit))
+ parts &= ~MODKIT_SUIT
+
if(!parts)
+ user.drop_from_inventory(src)
del(src)
+/obj/item/device/modkit/examine()
+ ..()
+ usr << "It looks as though it modifies hardsuits to fit [target_species] users."
+
/obj/item/device/modkit/tajaran
- name = "tajara hardsuit modification kit"
- desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user. This one looks like it's meant for Tajara."
-
-//Keep the lists in matching orders to the relative type and keep the parents at the end.
-// /obj/item/clothing/head/helmet/space/rig <- is a parent //i love you, sounds.
- from_helmet = list(/obj/item/clothing/head/helmet/space/rig/security, /obj/item/clothing/head/helmet/space/rig/medical, /obj/item/clothing/head/helmet/space/rig/atmos, /obj/item/clothing/head/helmet/space/rig)
- to_helmet = list(/obj/item/clothing/head/helmet/space/rig/security/tajara, /obj/item/clothing/head/helmet/space/rig/medical/tajara, /obj/item/clothing/head/helmet/space/rig/atmos/tajara, /obj/item/clothing/head/helmet/space/rig/tajara)
-
- from_suit = list(/obj/item/clothing/suit/space/rig/security, /obj/item/clothing/suit/space/rig/medical, /obj/item/clothing/suit/space/rig/atmos, /obj/item/clothing/suit/space/rig)
- to_suit = list(/obj/item/clothing/suit/space/rig/security/tajara, /obj/item/clothing/suit/space/rig/medical/tajara, /obj/item/clothing/suit/space/rig/atmos/tajara, /obj/item/clothing/suit/space/rig/tajara)
-
-/obj/item/device/modkit/unathi
- name = "unathi hardsuit modification kit"
- desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user. This one looks like it's meant for Unathi."
-
- from_helmet = list(/obj/item/clothing/head/helmet/space/rig/security, /obj/item/clothing/head/helmet/space/rig/medical, /obj/item/clothing/head/helmet/space/rig/atmos, /obj/item/clothing/head/helmet/space/rig)
- to_helmet = list(/obj/item/clothing/head/helmet/space/rig/security/unathi, /obj/item/clothing/head/helmet/space/rig/medical/unathi, /obj/item/clothing/head/helmet/space/rig/atmos/unathi, /obj/item/clothing/head/helmet/space/rig/unathi)
-
- from_suit = list(/obj/item/clothing/suit/space/rig/security, /obj/item/clothing/suit/space/rig/medical, /obj/item/clothing/suit/space/rig/atmos, /obj/item/clothing/suit/space/rig)
- to_suit = list(/obj/item/clothing/suit/space/rig/security/unathi, /obj/item/clothing/suit/space/rig/medical/unathi, /obj/item/clothing/suit/space/rig/atmos/unathi, /obj/item/clothing/suit/space/rig/unathi)
-
-/obj/item/device/modkit/skrell
- name = "skrell hardsuit modification kit"
- desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user. This one looks like it's meant for Skrell."
-
- from_helmet = list(/obj/item/clothing/head/helmet/space/rig/security, /obj/item/clothing/head/helmet/space/rig/medical, /obj/item/clothing/head/helmet/space/rig/atmos, /obj/item/clothing/head/helmet/space/rig)
- to_helmet = list(/obj/item/clothing/head/helmet/space/rig/security/skrell, /obj/item/clothing/head/helmet/space/rig/medical/skrell, /obj/item/clothing/head/helmet/space/rig/atmos/skrell, /obj/item/clothing/head/helmet/space/rig/skrell)
-
- from_suit = list(/obj/item/clothing/suit/space/rig/security, /obj/item/clothing/suit/space/rig/medical, /obj/item/clothing/suit/space/rig/atmos, /obj/item/clothing/suit/space/rig)
- to_suit = list(/obj/item/clothing/suit/space/rig/security/skrell, /obj/item/clothing/suit/space/rig/medical/skrell, /obj/item/clothing/suit/space/rig/atmos/skrell, /obj/item/clothing/suit/space/rig/skrell)
-
-
-
+ name = "tajaran hardsuit modification kit"
+ desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user. This one looks like it's meant for Tajaran."
+ target_species = "Tajaran"
\ No newline at end of file
diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm
new file mode 100644
index 00000000..6355fd26
--- /dev/null
+++ b/code/game/objects/items/devices/suit_cooling.dm
@@ -0,0 +1,186 @@
+/obj/item/device/suit_cooling_unit
+ name = "portable suit cooling unit"
+ desc = "A portable heat sink and liquid cooled radiator that can be hooked up to a space suit's existing temperature controls to provide industrial levels of cooling."
+ w_class = 4
+ icon = 'icons/obj/device.dmi'
+ icon_state = "suitcooler0"
+ slot_flags = SLOT_BACK //you can carry it on your back if you want, but it won't do anything unless attached to suit storage
+
+ //copied from tank.dm
+ flags = FPRINT | TABLEPASS | CONDUCT
+ force = 5.0
+ throwforce = 10.0
+ throw_speed = 1
+ throw_range = 4
+
+ origin_tech = "magnets=2;materials=2"
+
+ var/on = 0 //is it turned on?
+ var/cover_open = 0 //is the cover open?
+ var/obj/item/weapon/cell/cell
+ var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here
+ var/charge_consumption = 16.6 //charge per second at max_cooling
+ var/thermostat = T20C
+
+ //TODO: make it heat up the surroundings when not in space
+
+/obj/item/device/suit_cooling_unit/New()
+ processing_objects |= src
+
+ cell = new/obj/item/weapon/cell() //comes with the crappy default power cell - high-capacity ones shouldn't be hard to find
+ cell.loc = src
+
+/obj/item/device/suit_cooling_unit/process()
+ if (!on || !cell)
+ return
+
+ if (!ismob(loc))
+ return
+
+ if (!attached_to_suit(loc)) //make sure they have a suit and we are attached to it
+ return
+
+ var/mob/living/carbon/human/H = loc
+
+ var/efficiency = 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling
+ var/env_temp = get_environment_temperature() //wont save you from a fire
+ var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling)
+
+ if (temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision
+ return
+
+ var/charge_usage = (temp_adj/max_cooling)*charge_consumption
+
+ H.bodytemperature -= temp_adj*efficiency
+
+ cell.use(charge_usage)
+
+ if(cell.charge <= 0)
+ turn_off()
+
+/obj/item/device/suit_cooling_unit/proc/get_environment_temperature()
+ if (ishuman(loc))
+ var/mob/living/carbon/human/H = loc
+ if(istype(H.loc, /obj/mecha))
+ var/obj/mecha/M = loc
+ return M.return_temperature()
+ else if(istype(H.loc, /obj/machinery/atmospherics/unary/cryo_cell))
+ return H.loc:air_contents.temperature
+
+ var/turf/T = get_turf(src)
+ if(istype(T, /turf/space))
+ return 0 //space has no temperature, this just makes sure the cooling unit works in space
+
+ var/datum/gas_mixture/environment = T.return_air()
+ if (!environment)
+ return 0
+
+ return environment.temperature
+
+/obj/item/device/suit_cooling_unit/proc/attached_to_suit(mob/M)
+ if (!ishuman(M))
+ return 0
+
+ var/mob/living/carbon/human/H = M
+
+ if (!H.wear_suit || H.s_store != src)
+ return 0
+
+ return 1
+
+/obj/item/device/suit_cooling_unit/proc/turn_on()
+ if(!cell)
+ return
+ if(cell.charge <= 0)
+ return
+
+ on = 1
+ updateicon()
+
+/obj/item/device/suit_cooling_unit/proc/turn_off()
+ if (ismob(src.loc))
+ var/mob/M = src.loc
+ M.show_message("\The [src] clicks and whines as it powers down.", 2) //let them know in case it's run out of power.
+ on = 0
+ updateicon()
+
+/obj/item/device/suit_cooling_unit/attack_self(mob/user as mob)
+ if(cover_open && cell)
+ if(ishuman(user))
+ user.put_in_hands(cell)
+ else
+ cell.loc = get_turf(loc)
+
+ cell.add_fingerprint(user)
+ cell.updateicon()
+
+ user << "You remove the [src.cell]."
+ src.cell = null
+ updateicon()
+ return
+
+ //TODO use a UI like the air tanks
+ if(on)
+ turn_off()
+ else
+ turn_on()
+ if (on)
+ user << "You switch on the [src]."
+
+/obj/item/device/suit_cooling_unit/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if (istype(W, /obj/item/weapon/screwdriver))
+ if(cover_open)
+ cover_open = 0
+ user << "You screw the panel into place."
+ else
+ cover_open = 1
+ user << "You unscrew the panel."
+ updateicon()
+ return
+
+ if (istype(W, /obj/item/weapon/cell))
+ if(cover_open)
+ if(cell)
+ user << "There is a [cell] already installed here."
+ else
+ user.drop_item()
+ W.loc = src
+ cell = W
+ user << "You insert the [cell]."
+ updateicon()
+ return
+
+ return ..()
+
+/obj/item/device/suit_cooling_unit/proc/updateicon()
+ if (cover_open)
+ if (cell)
+ icon_state = "suitcooler1"
+ else
+ icon_state = "suitcooler2"
+ else
+ icon_state = "suitcooler0"
+
+/obj/item/device/suit_cooling_unit/examine()
+ set src in view(1)
+
+ ..()
+
+ if (on)
+ if (attached_to_suit(src.loc))
+ usr << "It's switched on and running."
+ else
+ usr << "It's switched on, but not attached to anything."
+ else
+ usr << "It is switched off."
+
+ if (cover_open)
+ if(cell)
+ usr << "The panel is open, exposing the [cell]."
+ else
+ usr << "The panel is open."
+
+ if (cell)
+ usr << "The charge meter reads [round(cell.percent())]%."
+ else
+ usr << "It doesn't have a power cell installed."
\ No newline at end of file
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index d96fc888..bfc965f9 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -2,11 +2,18 @@
name = "clothing"
var/list/species_restricted = null //Only these species can wear this kit.
var/gsr = 0
+ /*
+ Sprites used when the clothing item is refit. This is done by setting icon_override.
+ For best results, if this is set then sprite_sheets should be null and vice versa, but that is by no means necessary.
+ Ideally, sprite_sheets_refit should be used for "hard" clothing items that can't change shape very well to fit the wearer (e.g. helmets, hardsuits),
+ while sprite_sheets should be used for "flexible" clothing items that do not need to be refitted (e.g. vox wearing jumpsuits).
+ */
+ var/list/sprite_sheets_refit = null
//BS12: Species-restricted clothing check.
/obj/item/clothing/mob_can_equip(M as mob, slot)
- //if we can equip the item anyway, don't bother with species_restricted (aslo cuts down on spam)
+ //if we can't equip the item anyway, don't bother with species_restricted (cuts down on spam)
if (!..())
return 0
@@ -33,6 +40,46 @@
return 1
+/obj/item/clothing/proc/refit_for_species(var/target_species)
+ //Set species_restricted list
+ switch(target_species)
+ if("Human", "Skrell") //humanoid bodytypes
+ species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox")
+ else
+ species_restricted = list(target_species)
+
+ //Set icon
+ if (sprite_sheets_refit && (target_species in sprite_sheets_refit))
+ icon_override = sprite_sheets_refit[target_species]
+ else
+ icon_override = initial(icon_override)
+
+ if (sprite_sheets_obj && (target_species in sprite_sheets_obj))
+ icon = sprite_sheets_obj[target_species]
+ else
+ icon = initial(icon)
+
+/obj/item/clothing/head/helmet/refit_for_species(var/target_species)
+ //Set species_restricted list
+ switch(target_species)
+ if("Skrell")
+ species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox")
+ if("Human")
+ species_restricted = list("exclude","Skrell","Unathi","Tajaran","Diona","Vox")
+ else
+ species_restricted = list(target_species)
+
+ //Set icon
+ if (sprite_sheets_refit && (target_species in sprite_sheets_refit))
+ icon_override = sprite_sheets_refit[target_species]
+ else
+ icon_override = initial(icon_override)
+
+ if (sprite_sheets_obj && (target_species in sprite_sheets_obj))
+ icon = sprite_sheets_obj[target_species]
+ else
+ icon = initial(icon)
+
//Ears: headsets, earmuffs and tiny objects
/obj/item/clothing/ears
name = "ears"
@@ -105,7 +152,7 @@
var/vision_flags = 0
var/darkness_view = 0//Base human is 2
var/invisa_view = 0
-
+ sprite_sheets = list("Vox" = 'icons/mob/species/vox/eyes.dmi')
/*
SEE_SELF // can see self, no matter what
SEE_MOBS // can see all mobs, no matter what
@@ -131,6 +178,7 @@ BLIND // can't see anything
slot_flags = SLOT_GLOVES
attack_verb = list("challenged")
species_restricted = list("exclude","Unathi","Tajaran")
+ sprite_sheets = list("Vox" = 'icons/mob/species/vox/gloves.dmi')
/obj/item/clothing/gloves/examine()
set src in usr
@@ -151,6 +199,24 @@ BLIND // can't see anything
/obj/item/clothing/gloves/proc/Touch(var/atom/A, var/proximity)
return 0 // return 1 to cancel attack_hand()
+/obj/item/clothing/gloves/attackby(obj/item/weapon/W, mob/user)
+ if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel))
+ if (clipped)
+ user << "The [src] have already been clipped!"
+ update_icon()
+ return
+
+ playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ user.visible_message("\red [user] cuts the fingertips off of the [src].","\red You cut the fingertips off of the [src].")
+
+ clipped = 1
+ name = "mangled [name]"
+ desc = "[desc]
They have had the fingertips cut off of them."
+ if("exclude" in species_restricted)
+ species_restricted -= "Unathi"
+ species_restricted -= "Tajaran"
+ return
+
//Head
/obj/item/clothing/head
name = "head"
@@ -159,13 +225,16 @@ BLIND // can't see anything
slot_flags = SLOT_HEAD
w_class = 2.0
-
//Mask
/obj/item/clothing/mask
name = "mask"
icon = 'icons/obj/clothing/masks.dmi'
body_parts_covered = HEAD
slot_flags = SLOT_MASK
+// body_parts_covered = FACE|EYES
+ sprite_sheets = list("Vox" = 'icons/mob/species/vox/masks.dmi')
+
+/obj/item/clothing/mask/proc/filter_air(datum/gas_mixture/air)
//Shoes
/obj/item/clothing/shoes
@@ -180,6 +249,8 @@ BLIND // can't see anything
permeability_coefficient = 0.50
slowdown = SHOES_SLOWDOWN
species_restricted = list("exclude","Unathi","Tajaran")
+ sprite_sheets = list("Vox" = 'icons/mob/species/vox/shoes.dmi')
+
/obj/item/proc/negates_gravity()
return 0
@@ -190,6 +261,7 @@ BLIND // can't see anything
name = "suit"
var/fire_resist = T0C+100
flags = FPRINT | TABLEPASS
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
allowed = list(/obj/item/weapon/tank/emergency_oxygen)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
slot_flags = SLOT_OCLOTHING
@@ -209,6 +281,7 @@ BLIND // can't see anything
permeability_coefficient = 0.01
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50)
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
+// body_parts_covered = HEAD|FACE|EYES
cold_protection = HEAD
min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE
siemens_coefficient = 0.9
@@ -224,7 +297,7 @@ BLIND // can't see anything
permeability_coefficient = 0.02
flags = FPRINT | TABLEPASS | STOPSPRESSUREDMAGE | THICKMATERIAL
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
- allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen)
+ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit)
slowdown = 3
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50)
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
@@ -233,6 +306,37 @@ BLIND // can't see anything
siemens_coefficient = 0.9
species_restricted = list("exclude","Diona","Vox")
+ var/list/supporting_limbs //If not-null, automatically splints breaks. Checked when removing the suit.
+
+/obj/item/clothing/suit/space/equipped(mob/M)
+ check_limb_support()
+ ..()
+
+/obj/item/clothing/suit/space/dropped()
+ check_limb_support()
+ ..()
+
+// Some space suits are equipped with reactive membranes that support
+// broken limbs - at the time of writing, only the ninja suit, but
+// I can see it being useful for other suits as we expand them. ~ Z
+// The actual splinting occurs in /datum/organ/external/proc/fracture()
+/obj/item/clothing/suit/space/proc/check_limb_support()
+
+ // If this isn't set, then we don't need to care.
+ if(!supporting_limbs || !supporting_limbs.len)
+ return
+
+ var/mob/living/carbon/human/H = src.loc
+
+ // If the holder isn't human, or the holder IS and is wearing the suit, it keeps supporting the limbs.
+ if(!istype(H) || H.wear_suit == src)
+ return
+
+ // Otherwise, remove the splints.
+ for(var/datum/organ/external/E in supporting_limbs)
+ E.status &= ~ ORGAN_SPLINTED
+ supporting_limbs = list()
+
//Under clothing
/obj/item/clothing/under
icon = 'icons/obj/clothing/uniforms.dmi'
@@ -255,6 +359,7 @@ BLIND // can't see anything
var/rolled_down = 0
var/rolled_sleeves = 0
var/basecolor
+ sprite_sheets = list("Vox" = 'icons/mob/species/vox/uniform.dmi')
/obj/item/clothing/under/attackby(obj/item/I, mob/user)
if(hastie)
@@ -279,6 +384,10 @@ BLIND // can't see anything
if(hastie && src.loc == user)
hastie.attack_hand(user)
return
+
+ if ((ishuman(usr) || ismonkey(usr)) && src.loc == user) //make it harder to accidentally undress yourself
+ return
+
..()
//This is to ensure people can take off suits when there is an attached accessory
@@ -375,6 +484,7 @@ BLIND // can't see anything
if(copytext(item_color,-2) != "_d" && rolled_sleeves == 0)
basecolor = item_color
if(basecolor + "_d_s" in icon_states('icons/mob/uniform.dmi'))
+ body_parts_covered = "[basecolor]" ? LEGS|LOWER_TORSO : UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
item_color = item_color == "[basecolor]" ? "[basecolor]_d" : "[basecolor]"
usr.update_inv_w_uniform()
if(rolled_down)
@@ -435,4 +545,8 @@ BLIND // can't see anything
sensor_mode = pick(0,1,2,3)
..()
+/obj/item/clothing/under/emp_act(severity)
+ if (hastie)
+ hastie.emp_act(severity)
+ ..()
diff --git a/code/modules/clothing/spacesuits/breaches.dm b/code/modules/clothing/spacesuits/breaches.dm
new file mode 100644
index 00000000..19f79556
--- /dev/null
+++ b/code/modules/clothing/spacesuits/breaches.dm
@@ -0,0 +1,221 @@
+//A 'wound' system for space suits.
+//Breaches greatly increase the amount of lost gas and decrease the armour rating of the suit.
+//They can be healed with plastic or metal sheeting.
+
+/datum/breach
+ var/class = 0 // Size. Lower is smaller.
+ var/descriptor // 'gaping hole' etc.
+ var/damtype = BURN // Punctured or melted
+ var/obj/item/clothing/suit/space/holder // Suit containing the list of breaches holding this instance.
+
+/obj/item/clothing/suit/space
+
+ var/can_breach = 1 // Set to 0 to disregard all breaching.
+ var/list/breaches = list() // Breach datum container.
+ var/resilience = 0.2 // Multiplier that turns damage into breach class. 1 is 100% of damage to breach, 0.1 is 10%.
+ var/breach_threshold = 3 // Min damage before a breach is possible.
+ var/damage = 0 // Current total damage
+ var/brute_damage = 0 // Specifically brute damage.
+ var/burn_damage = 0 // Specifically burn damage.
+ var/base_name // Used to keep the original name safe while we apply modifiers.
+
+/obj/item/clothing/suit/space/New()
+ ..()
+ base_name = "[name]"
+
+//Some simple descriptors for breaches. Global because lazy, TODO: work out a better way to do this.
+
+var/global/list/breach_brute_descriptors = list(
+ "tiny puncture",
+ "ragged tear",
+ "large split",
+ "huge tear",
+ "gaping wound"
+ )
+
+var/global/list/breach_burn_descriptors = list(
+ "small burn",
+ "melted patch",
+ "sizable burn",
+ "large scorched area",
+ "huge scorched area"
+ )
+
+/datum/breach/proc/update_descriptor()
+
+ //Sanity...
+ class = max(1,min(class,5))
+ //Apply the correct descriptor.
+ if(damtype == BURN)
+ descriptor = breach_burn_descriptors[class]
+ else if(damtype == BRUTE)
+ descriptor = breach_brute_descriptors[class]
+
+//Repair a certain amount of brute or burn damage to the suit.
+/obj/item/clothing/suit/space/proc/repair_breaches(var/damtype, var/amount, var/mob/user)
+
+ if(!can_breach || !breaches || !breaches.len || !damage)
+ user << "There are no breaches to repair on \the [src]."
+ return
+
+ var/list/valid_breaches = list()
+
+ for(var/datum/breach/B in breaches)
+ if(B.damtype == damtype)
+ valid_breaches += B
+
+ if(!valid_breaches.len)
+ user << "There are no breaches to repair on \the [src]."
+ return
+
+ var/amount_left = amount
+ for(var/datum/breach/B in valid_breaches)
+ if(!amount_left) break
+
+ if(B.class <= amount_left)
+ amount_left -= B.class
+ valid_breaches -= B
+ breaches -= B
+ else
+ B.class -= amount_left
+ amount_left = 0
+ B.update_descriptor()
+
+ user.visible_message("[user] patches some of the damage on \the [src].")
+ calc_breach_damage()
+
+/obj/item/clothing/suit/space/proc/create_breaches(var/damtype, var/amount)
+
+ if(!can_breach || !amount)
+ return
+
+ if(!breaches)
+ breaches = list()
+
+ if(damage > 25) return //We don't need to keep tracking it when it's at 250% pressure loss, really.
+
+ if(!loc) return
+ var/turf/T = get_turf(src)
+ if(!T) return
+
+ amount = amount * src.resilience
+
+ //Increase existing breaches.
+ for(var/datum/breach/existing in breaches)
+
+ if(existing.damtype != damtype)
+ continue
+
+ if (existing.class < 5)
+ var/needs = 5 - existing.class
+ if(amount < needs)
+ existing.class += amount
+ amount = 0
+ else
+ existing.class = 5
+ amount -= needs
+
+ if(existing.damtype == BRUTE)
+ T.visible_message("\The [existing.descriptor] on [src] gapes wider!")
+ else if(existing.damtype == BURN)
+ T.visible_message("\The [existing.descriptor] on [src] widens!")
+
+ if (amount)
+ //Spawn a new breach.
+ var/datum/breach/B = new()
+ breaches += B
+
+ B.class = min(amount,5)
+
+ B.damtype = damtype
+ B.update_descriptor()
+ B.holder = src
+
+ if(B.damtype == BRUTE)
+ T.visible_message("\A [B.descriptor] opens up on [src]!")
+ else if(B.damtype == BURN)
+ T.visible_message("\A [B.descriptor] marks the surface of [src]!")
+
+ calc_breach_damage()
+
+//Calculates the current extent of the damage to the suit.
+/obj/item/clothing/suit/space/proc/calc_breach_damage()
+
+ damage = 0
+ brute_damage = 0
+ burn_damage = 0
+
+ if(!can_breach || !breaches || !breaches.len)
+ name = base_name
+ return 0
+
+ for(var/datum/breach/B in breaches)
+ if(!B.class)
+ src.breaches -= B
+ del(B)
+ else
+ damage += B.class
+ if(B.damtype == BRUTE)
+ brute_damage += B.class
+ else if(B.damtype == BURN)
+ burn_damage += B.class
+
+ if(damage >= 3)
+ if(brute_damage >= 3 && brute_damage > burn_damage)
+ name = "punctured [base_name]"
+ else if(burn_damage >= 3 && burn_damage > brute_damage)
+ name = "scorched [base_name]"
+ else
+ name = "damaged [base_name]"
+ else
+ name = "[base_name]"
+
+ return damage
+
+//Handles repairs (and also upgrades).
+
+/obj/item/clothing/suit/space/attackby(obj/item/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/stack/sheet/mineral/plastic) || istype(W,/obj/item/stack/sheet/metal))
+
+ if(istype(src.loc,/mob/living))
+ user << "\red How do you intend to patch a hardsuit while someone is wearing it?"
+ return
+
+ if(!damage || !burn_damage)
+ user << "There is no surface damage on \the [src] to repair."
+ return
+
+ var/obj/item/stack/sheet/P = W
+ if(P.amount < 3)
+ P.use(P.amount)
+ repair_breaches(BURN, ( istype(P,/obj/item/stack/sheet/mineral/plastic) ? P.amount : (P.amount*2) ), user)
+ else
+ P.use(3)
+ repair_breaches(BURN, ( istype(P,/obj/item/stack/sheet/mineral/plastic) ? 3 : 5), user)
+ return
+
+ else if(istype(W, /obj/item/weapon/weldingtool))
+
+ if(istype(src.loc,/mob/living))
+ user << "\red How do you intend to patch a hardsuit while someone is wearing it?"
+ return
+
+ if (!damage || ! brute_damage)
+ user << "There is no structural damage on \the [src] to repair."
+ return
+
+ var/obj/item/weapon/weldingtool/WT = W
+ if(!WT.remove_fuel(5))
+ user << "\red You need more welding fuel to repair this suit."
+ return
+
+ repair_breaches(BRUTE, 3, user)
+ return
+
+ ..()
+
+/obj/item/clothing/suit/space/examine()
+ ..()
+ if(can_breach && breaches && breaches.len)
+ for(var/datum/breach/B in breaches)
+ usr << "\red It has \a [B.descriptor]."
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm
index ef73f239..40fe6bb7 100644
--- a/code/modules/clothing/spacesuits/rig.dm
+++ b/code/modules/clothing/spacesuits/rig.dm
@@ -1,10 +1,10 @@
//Regular rig suits
/obj/item/clothing/head/helmet/space/rig
- name = "engineering hardsuit helmet"
- desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding."
+ name = "hardsuit helmet"
+ desc = "A special helmet designed for work in a hazardous, low-pressure environment."
icon_state = "rig0-engineering"
item_state = "eng_helm"
- armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80)
+ armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 20)
allowed = list(/obj/item/device/flashlight)
var/brightness_on = 4 //luminosity when on
var/on = 0
@@ -12,7 +12,19 @@
icon_action_button = "action_hardhat"
heat_protection = HEAD
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
+
+ //Species-specific stuff.
species_restricted = list("exclude","Unathi","Tajaran","Skrell","Diona","Vox")
+ sprite_sheets_refit = list(
+ "Unathi" = 'icons/mob/species/unathi/helmet.dmi',
+ "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
+ "Skrell" = 'icons/mob/species/skrell/helmet.dmi',
+ )
+ sprite_sheets_obj = list(
+ "Unathi" = 'icons/obj/clothing/species/unathi/hats.dmi',
+ "Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi',
+ "Skrell" = 'icons/obj/clothing/species/skrell/hats.dmi',
+ )
attack_self(mob/user)
if(!isturf(user.loc))
@@ -42,31 +54,288 @@
SetLuminosity(brightness_on)
/obj/item/clothing/suit/space/rig
+ name = "hardsuit"
+ desc = "A special space suit for environments that might pose hazards beyond just the vacuum of space. Provides more protection than a standard space suit."
+ icon_state = "rig-engineering"
+ item_state = "eng_hardsuit"
+ slowdown = 1
+ armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 20)
+ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit)
+ heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
+ max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
+
+ species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox")
+ sprite_sheets_refit = list(
+ "Unathi" = 'icons/mob/species/unathi/suit.dmi',
+ "Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
+ "Skrell" = 'icons/mob/species/skrell/suit.dmi',
+ )
+ sprite_sheets_obj = list(
+ "Unathi" = 'icons/obj/clothing/species/unathi/suits.dmi',
+ "Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi',
+ "Skrell" = 'icons/obj/clothing/species/skrell/suits.dmi',
+ )
+
+ //Breach thresholds, should ideally be inherited by most (if not all) hardsuits.
+ breach_threshold = 18
+ can_breach = 1
+
+ //Component/device holders.
+ var/obj/item/weapon/stock_parts/gloves = null // Basic capacitor allows insulation, upgrades allow shock gloves etc.
+
+ var/attached_boots = 1 // Can't wear boots if some are attached
+ var/obj/item/clothing/shoes/magboots/boots = null // Deployable boots, if any.
+ var/attached_helmet = 1 // Can't wear a helmet if one is deployable.
+ var/obj/item/clothing/head/helmet/helmet = null // Deployable helmet, if any.
+
+ var/list/max_mounted_devices = 0 // Maximum devices. Easy.
+ var/list/can_mount = null // Types of device that can be hardpoint mounted.
+ var/list/mounted_devices = null // Holder for the above device.
+ var/obj/item/active_device = null // Currently deployed device, if any.
+
+/obj/item/clothing/suit/space/rig/equipped(mob/M)
+ ..()
+
+ var/mob/living/carbon/human/H = M
+
+ if(!istype(H)) return
+
+ if(H.wear_suit != src)
+ return
+
+ if(attached_helmet && helmet)
+ if(H.head)
+ M << "You are unable to deploy your suit's helmet as \the [H.head] is in the way."
+ else
+ M << "Your suit's helmet deploys with a hiss."
+ //TODO: Species check, skull damage for forcing an unfitting helmet on?
+ helmet.loc = H
+ H.equip_to_slot(helmet, slot_head)
+ helmet.canremove = 0
+
+ if(attached_boots && boots)
+ if(H.shoes)
+ M << "You are unable to deploy your suit's magboots as \the [H.shoes] are in the way."
+ else
+ M << "Your suit's boots deploy with a hiss."
+ boots.loc = H
+ H.equip_to_slot(boots, slot_shoes)
+ boots.canremove = 0
+
+/obj/item/clothing/suit/space/rig/dropped()
+ ..()
+
+ var/mob/living/carbon/human/H
+
+ if(helmet)
+ H = helmet.loc
+ if(istype(H))
+ if(helmet && H.head == helmet)
+ helmet.canremove = 1
+ H.drop_from_inventory(helmet)
+ helmet.loc = src
+
+ if(boots)
+ H = boots.loc
+ if(istype(H))
+ if(boots && H.shoes == boots)
+ boots.canremove = 1
+ H.drop_from_inventory(boots)
+ boots.loc = src
+
+/*
+/obj/item/clothing/suit/space/rig/verb/get_mounted_device()
+
+ set name = "Deploy Mounted Device"
+ set category = "Object"
+ set src in usr
+
+ if(!can_mount)
+ verbs -= /obj/item/clothing/suit/space/rig/verb/get_mounted_device
+ verbs -= /obj/item/clothing/suit/space/rig/verb/stow_mounted_device
+ return
+
+ if(!istype(usr, /mob/living)) return
+ if(usr.stat) return
+
+ if(active_device)
+ usr << "You already have \the [active_device] deployed."
+ return
+
+ if(!mounted_devices.len)
+ usr << "You do not have any devices mounted on \the [src]."
+ return
+
+/obj/item/clothing/suit/space/rig/verb/stow_mounted_device()
+
+ set name = "Stow Mounted Device"
+ set category = "Object"
+ set src in usr
+
+ if(!can_mount)
+ verbs -= /obj/item/clothing/suit/space/rig/verb/get_mounted_device
+ verbs -= /obj/item/clothing/suit/space/rig/verb/stow_mounted_device
+ return
+
+ if(!istype(usr, /mob/living)) return
+
+ if(usr.stat) return
+
+ if(!active_device)
+ usr << "You have no device currently deployed."
+ return
+*/
+
+/obj/item/clothing/suit/space/rig/verb/toggle_helmet()
+
+ set name = "Toggle Helmet"
+ set category = "Object"
+ set src in usr
+
+ if(!istype(src.loc,/mob/living)) return
+
+ if(!helmet)
+ usr << "There is no helmet installed."
+ return
+
+ var/mob/living/carbon/human/H = usr
+
+ if(!istype(H)) return
+ if(H.stat) return
+ if(H.wear_suit != src) return
+
+ if(H.head == helmet)
+ helmet.canremove = 1
+ H.drop_from_inventory(helmet)
+ helmet.loc = src
+ H << "\blue You retract your hardsuit helmet."
+ else
+ if(H.head)
+ H << "\red You cannot deploy your helmet while wearing another helmet."
+ return
+ //TODO: Species check, skull damage for forcing an unfitting helmet on?
+ helmet.loc = H
+ H.equip_to_slot(helmet, slot_head)
+ helmet.canremove = 0
+ H << "\blue You deploy your hardsuit helmet, sealing you off from the world."
+
+/obj/item/clothing/suit/space/rig/attackby(obj/item/W as obj, mob/user as mob)
+
+ if(!istype(user,/mob/living)) return
+
+ if(user.a_intent == "help")
+
+ if(istype(src.loc,/mob/living))
+ user << "How do you propose to modify a hardsuit while it is being worn?"
+ return
+
+ var/target_zone = user.zone_sel.selecting
+
+ if(target_zone == "head")
+
+ //Installing a component into or modifying the contents of the helmet.
+ if(!attached_helmet)
+ user << "\The [src] does not have a helmet mount."
+ return
+
+ if(istype(W,/obj/item/weapon/screwdriver))
+ if(!helmet)
+ user << "\The [src] does not have a helmet installed."
+ else
+ user << "You detatch \the [helmet] from \the [src]'s helmet mount."
+ helmet.loc = get_turf(src)
+ src.helmet = null
+ return
+ else if(istype(W,/obj/item/clothing/head/helmet/space))
+ if(helmet)
+ user << "\The [src] already has a helmet installed."
+ else
+ user << "You attach \the [W] to \the [src]'s helmet mount."
+ user.drop_item()
+ W.loc = src
+ src.helmet = W
+ return
+ else
+ return ..()
+
+ else if(target_zone == "l_leg" || target_zone == "r_leg" || target_zone == "l_foot" || target_zone == "r_foot")
+
+ //Installing a component into or modifying the contents of the feet.
+ if(!attached_boots)
+ user << "\The [src] does not have boot mounts."
+ return
+
+ if(istype(W,/obj/item/weapon/screwdriver))
+ if(!boots)
+ user << "\The [src] does not have any boots installed."
+ else
+ user << "You detatch \the [boots] from \the [src]'s boot mounts."
+ boots.loc = get_turf(src)
+ boots = null
+ return
+ else if(istype(W,/obj/item/clothing/shoes/magboots))
+ if(boots)
+ user << "\The [src] already has magboots installed."
+ else
+ user << "You attach \the [W] to \the [src]'s boot mounts."
+ user.drop_item()
+ W.loc = src
+ boots = W
+ else
+ return ..()
+
+ /*
+ else if(target_zone == "l_arm" || target_zone == "r_arm" || target_zone == "l_hand" || target_zone == "r_hand")
+
+ //Installing a component into or modifying the contents of the hands.
+
+ else if(target_zone == "torso" || target_zone == "groin")
+
+ //Modifying the cell or mounted devices
+
+ if(!mounted_devices)
+ return
+ */
+
+ else //wat
+ return ..()
+
+ ..()
+
+//Engineering rig
+/obj/item/clothing/head/helmet/space/rig/engineering
+ name = "engineering hardsuit helmet"
+ desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding."
+ icon_state = "rig0-engineering"
+ item_state = "eng_helm"
+ armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80)
+
+/obj/item/clothing/suit/space/rig/engineering
name = "engineering hardsuit"
desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding."
icon_state = "rig-engineering"
item_state = "eng_hardsuit"
slowdown = 1
armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 80)
- allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd)
- heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
- max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
- species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox")
+ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd)
//Chief Engineer's rig
-/obj/item/clothing/head/helmet/space/rig/elite
+/obj/item/clothing/head/helmet/space/rig/engineering/chief
name = "advanced hardsuit helmet"
desc = "An advanced helmet designed for work in a hazardous, low pressure environment. Shines with a high polish."
icon_state = "rig0-white"
item_state = "ce_helm"
item_color = "white"
+ sprite_sheets_refit = null
+ sprite_sheets_obj = null
-/obj/item/clothing/suit/space/rig/elite
+/obj/item/clothing/suit/space/rig/engineering/chief
icon_state = "rig-white"
name = "advanced hardsuit"
desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish."
item_state = "ce_hardsuit"
-
+ sprite_sheets_refit = null
+ sprite_sheets_obj = null
//Mining rig
/obj/item/clothing/head/helmet/space/rig/mining
@@ -96,6 +365,8 @@
siemens_coefficient = 0.6
var/obj/machinery/camera/camera
species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox")
+
+
/obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user)
if(camera)
..(user)
@@ -119,7 +390,7 @@
slowdown = 1
w_class = 3
armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 60)
- allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs)
+ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs)
siemens_coefficient = 0.6
species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox")
@@ -134,6 +405,8 @@
unacidable = 1 //No longer shall our kind be foiled by lone chemists with spray bottles!
armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60)
siemens_coefficient = 0.7
+ sprite_sheets_refit = null
+ sprite_sheets_obj = null
/obj/item/clothing/suit/space/rig/wizard
icon_state = "rig-wiz"
@@ -145,7 +418,8 @@
unacidable = 1
armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60)
siemens_coefficient = 0.7
-
+ sprite_sheets_refit = null
+ sprite_sheets_obj = null
//Medical Rig
/obj/item/clothing/head/helmet/space/rig/medical
@@ -161,7 +435,7 @@
name = "medical hardsuit"
desc = "A special suit that protects against hazardous, low pressure environments. Has minor radiation shielding."
item_state = "medical_hardsuit"
- allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical)
+ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical)
armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 50)
//Security
@@ -180,7 +454,7 @@
desc = "A special suit that protects against hazardous, low pressure environments. Has an additional layer of armor."
item_state = "sec_hardsuit"
armor = list(melee = 60, bullet = 10, laser = 30, energy = 5, bomb = 45, bio = 100, rad = 10)
- allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/melee/baton)
+ allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/melee/baton)
siemens_coefficient = 0.7
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index bf12bc27..c2a98736 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -326,6 +326,7 @@
user << "\The [src] is out of charge."
add_fingerprint(user)
+/*
/obj/item/device/modkit/fluff/omnivac_modkit //Ornate box - Zander Moon - omnivac - SPRITE
name = "ornate box"
desc = "An ornate box, containing the handle of an energy blade."
@@ -334,6 +335,7 @@
parts = MODKIT_HELMET
from_helmet = list(/obj/item/weapon/melee)
to_helmet = list(/obj/item/weapon/melee/baton/fluff/omnivac_baton)
+*/
/obj/item/clothing/head/soft/fluff/nebula_cap //Black baseball cap - Roxy Wallace - nebulaflare - DONE
name = "black baseball cap"
@@ -734,6 +736,7 @@
icon_state = "leo_coat"
item_state = "leo_coat"
+/*
/obj/item/device/modkit/fluff/leo_modkit //Weapon case - Leo Wyatt - keinto - DONE
name = "weapon case"
desc = "A sturdy leather case, with a velvet covered interior.."
@@ -742,6 +745,7 @@
parts = MODKIT_HELMET
from_helmet = list(/obj/item/weapon/gun/projectile/detective/semiauto)
to_helmet = list(/obj/item/weapon/gun/projectile/detective/semiauto/fluff/leo_gun)
+*/
/obj/item/weapon/gun/projectile/detective/semiauto/fluff/leo_gun //Instant Prosecutor - Leo Wyatt - keinto - DONE (stab)
name = "\improper Instant Prosecutor"
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index 9748eca3..28b42db8 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -65,13 +65,13 @@
if (organ_name in organs_by_name)
var/datum/organ/external/O = get_organ(organ_name)
-
+
if(amount > 0)
O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source)
else
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(-amount, 0, internal=0, robo_repair=(O.status & ORGAN_ROBOT))
-
+
hud_updateflag |= 1 << HEALTH_HUD
/mob/living/carbon/human/proc/adjustFireLossByPart(var/amount, var/organ_name, var/obj/damage_source = null)
@@ -80,13 +80,13 @@
if (organ_name in organs_by_name)
var/datum/organ/external/O = get_organ(organ_name)
-
+
if(amount > 0)
O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source)
else
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(0, -amount, internal=0, robo_repair=(O.status & ORGAN_ROBOT))
-
+
hud_updateflag |= 1 << HEALTH_HUD
/mob/living/carbon/human/Stun(amount)
@@ -165,6 +165,10 @@
hud_updateflag |= 1 << HEALTH_HUD
updatehealth()
+
+/*
+In most cases it makes more sense to use apply_damage() instead! And make sure to check armour if applicable.
+*/
//Damages ONE external organ, organ gets randomly selected from damagable ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
@@ -260,10 +264,20 @@ This function restores all organs.
/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null)
//visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]")
+
+ //Handle other types of damage
if((damagetype != BRUTE) && (damagetype != BURN))
+ if(damagetype == HALLOSS)
+ if ((damage > 25 && prob(20)) || (damage > 50 && prob(60)))
+ emote("scream")
+
+
..(damage, damagetype, def_zone, blocked)
return 1
+ //Handle BRUTE and BURN damage
+ handle_suit_punctures(damagetype, damage)
+
if(blocked >= 2) return 0
var/datum/organ/external/organ = null
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 8130627d..7e816ac1 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -27,6 +27,7 @@ emp_act
*/
// END TASER NERF
+ //Laserproof armour
if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/armor/laserproof))
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
var/reflectchance = 40 - round(P.damage/3)
@@ -189,6 +190,7 @@ emp_act
..()
+//Returns 1 if the attack hit, 0 if it missed.
/mob/living/carbon/human/proc/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone)
if(!I || !user) return 0
@@ -296,3 +298,14 @@ emp_act
if(w_uniform)
w_uniform.add_blood(source)
update_inv_w_uniform(0)
+
+/mob/living/carbon/human/proc/handle_suit_punctures(var/damtype, var/damage)
+
+ if(!wear_suit) return
+ if(!istype(wear_suit,/obj/item/clothing/suit/space)) return
+ if(damtype != BURN && damtype != BRUTE) return
+
+ var/obj/item/clothing/suit/space/SS = wear_suit
+ var/penetrated_dam = max(0,(damage - SS.breach_threshold)) // - SS.damage)) - Consider uncommenting this if suits seem too hardy on dev.
+
+ if(penetrated_dam) SS.create_breaches(damtype, penetrated_dam)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 4d4a080a..f547a875 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -135,23 +135,54 @@
if(mind && mind.vampire)
handle_vampire()
+// Calculate how vulnerable the human is to under- and overpressure.
+// Returns 0 (equals 0 %) if sealed in an undamaged suit, 1 if unprotected (equals 100%).
+// Suitdamage can modifiy this in 10% steps.
+/mob/living/carbon/human/proc/get_pressure_weakness()
+
+ var/pressure_adjustment_coefficient = 1 // Assume no protection at first.
+
+ if(wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE) && head && (head.flags & STOPSPRESSUREDMAGE)) // Complete set of pressure-proof suit worn, assume fully sealed.
+ pressure_adjustment_coefficient = 0
+
+ // Handles breaches in your space suit. 10 suit damage equals a 100% loss of pressure protection.
+ if(istype(wear_suit,/obj/item/clothing/suit/space))
+ var/obj/item/clothing/suit/space/S = wear_suit
+ if(S.can_breach && S.damage)
+ pressure_adjustment_coefficient += S.damage * 0.1
+
+ pressure_adjustment_coefficient = min(1,max(pressure_adjustment_coefficient,0)) // So it isn't less than 0 or larger than 1.
+
+ return pressure_adjustment_coefficient
+
+// Calculate how much of the enviroment pressure-difference affects the human.
/mob/living/carbon/human/calculate_affecting_pressure(var/pressure)
- ..()
- var/pressure_difference = abs( pressure - ONE_ATMOSPHERE )
+ var/pressure_difference
+
+ // First get the absolute pressure difference.
+ if(pressure < ONE_ATMOSPHERE) // We are in an underpressure.
+ pressure_difference = ONE_ATMOSPHERE - pressure
+
+ else //We are in an overpressure or standard atmosphere.
+ pressure_difference = pressure - ONE_ATMOSPHERE
+
+ if(pressure_difference < 5) // If the difference is small, don't bother calculating the fraction.
+ pressure_difference = 0
- var/pressure_adjustment_coefficient = 1 //Determins how much the clothing you are wearing protects you in percent.
- if(wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE))
- pressure_adjustment_coefficient -= PRESSURE_SUIT_REDUCTION_COEFFICIENT
- if(head && (head.flags & STOPSPRESSUREDMAGE))
- pressure_adjustment_coefficient -= PRESSURE_HEAD_REDUCTION_COEFFICIENT
- pressure_adjustment_coefficient = max(pressure_adjustment_coefficient,0) //So it isn't less than 0
- pressure_difference = pressure_difference * pressure_adjustment_coefficient
- if(pressure > ONE_ATMOSPHERE)
- return ONE_ATMOSPHERE + pressure_difference
else
+ // Otherwise calculate how much of that absolute pressure difference affects us, can be 0 to 1 (equals 0% to 100%).
+ // This is our relative difference.
+ pressure_difference *= get_pressure_weakness()
+
+ // The difference is always positive to avoid extra calculations.
+ // Apply the relative difference on a standard atmosphere to get the final result.
+ // The return value will be the adjusted_pressure of the human that is the basis of pressure warnings and damage.
+ if(pressure < ONE_ATMOSPHERE)
return ONE_ATMOSPHERE - pressure_difference
+ else
+ return ONE_ATMOSPHERE + pressure_difference
/mob/living/carbon/human
proc/handle_disabilities()
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index b2442020..42a0db50 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -961,14 +961,14 @@
/obj/machinery/power/apc/Topic(href, href_list, var/usingUI = 1)
if(!(isrobot(usr) && (href_list["apcwires"] || href_list["pulse"])))
if(!can_use(usr, 1))
- return
+ return 0
src.add_fingerprint(usr)
if (href_list["apcwires"])
var/t1 = text2num(href_list["apcwires"])
if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) ))
usr << "You need wirecutters!"
- return
+ return 0
if (src.isWireColorCut(t1))
src.mend(t1)
else
@@ -977,10 +977,10 @@
var/t1 = text2num(href_list["pulse"])
if (!istype(usr.get_active_hand(), /obj/item/device/multitool))
usr << "You need a multitool!"
- return
+ return 0
if (src.isWireColorCut(t1))
usr << "You can't pulse a cut wire."
- return
+ return 0
else
src.pulse(t1)
else if (href_list["lock"])
@@ -1027,11 +1027,11 @@
else if( href_list["close"] )
nanomanager.close_user_uis(usr, src)
- return
+ return 0
else if (href_list["close2"])
usr << browse(null, "window=apcwires")
- return
+ return 0
else if (href_list["overload"])
if( istype(usr, /mob/living/silicon) && !src.aidisabled )
@@ -1042,7 +1042,7 @@
if( istype(malfai, /mob/living/silicon/ai) && !src.aidisabled )
if (malfai.malfhacking)
malfai << "You are already hacking an APC."
- return
+ return 0
malfai << "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process."
malfai.malfhack = src
malfai.malfhacking = 1
@@ -1071,7 +1071,7 @@
if(usingUI)
src.updateDialog()
- return
+ return 1
/*/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf)
if(!istype(malf))
@@ -1425,17 +1425,4 @@
malfvacate(1)*/
..()
-/obj/machinery/power/apc/proc/shock(mob/user, prb)
- if(!prob(prb))
- return 0
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- if(isalien(user))
- return 0
- if (electrocute_mob(user, src, src))
- return 1
- else
- return 0
-
#undef APC_UPDATE_ICON_COOLDOWN
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm
index 61c715ec..e6aa55f2 100644
--- a/code/modules/power/singularity/containment_field.dm
+++ b/code/modules/power/singularity/containment_field.dm
@@ -50,7 +50,7 @@
-/obj/machinery/containment_field/proc/shock(mob/living/user as mob)
+/obj/machinery/containment_field/shock(mob/living/user as mob)
if(hasShocked)
return 0
if(!FG1 || !FG2)
@@ -63,17 +63,8 @@
hasShocked = 1
var/shock_damage = min(rand(30,40),rand(30,40))
- user.burn_skin(shock_damage)
- user.updatehealth()
- user.visible_message("\red [user.name] was shocked by the [src.name]!", \
- "\red You feel a powerful shock course through your body sending you flying!", \
- "\red You hear a heavy electrical crack")
+ user.electrocute_act(shock_damage, src)
- var/stun = min(shock_damage, 15)
- user.Stun(stun)
- user.Weaken(10)
-
- user.updatehealth()
var/atom/target = get_edge_target_turf(user, get_dir(src, get_step_away(user, src)))
user.throw_at(target, 200, 4)
diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm
index 9ff75a7d..6d6e0d97 100644
--- a/code/modules/research/rdmachines.dm
+++ b/code/modules/research/rdmachines.dm
@@ -36,20 +36,6 @@
src.disable_wire = pick(w)
w -= src.disable_wire
-/obj/machinery/r_n_d/proc/
- shock(mob/user, prb)
- if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
- return 0
- if(!prob(prb))
- return 0
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- if (electrocute_mob(user, get_area(src), src, 0.7))
- return 1
- else
- return 0
-
/obj/machinery/r_n_d/attack_hand(mob/user as mob)
if (shocked)
shock(user,50)
diff --git a/icons/mob/species/vox/eyes.dmi b/icons/mob/species/vox/eyes.dmi
new file mode 100644
index 00000000..6e15b3e5
Binary files /dev/null and b/icons/mob/species/vox/eyes.dmi differ
diff --git a/icons/mob/species/vox/gloves.dmi b/icons/mob/species/vox/gloves.dmi
index bf57b968..16b4706c 100644
Binary files a/icons/mob/species/vox/gloves.dmi and b/icons/mob/species/vox/gloves.dmi differ
diff --git a/icons/mob/species/vox/head.dmi b/icons/mob/species/vox/head.dmi
index 7149efa9..d0097e8d 100644
Binary files a/icons/mob/species/vox/head.dmi and b/icons/mob/species/vox/head.dmi differ
diff --git a/icons/mob/species/vox/masks.dmi b/icons/mob/species/vox/masks.dmi
new file mode 100644
index 00000000..8f426fa2
Binary files /dev/null and b/icons/mob/species/vox/masks.dmi differ
diff --git a/icons/mob/species/vox/shoes.dmi b/icons/mob/species/vox/shoes.dmi
new file mode 100644
index 00000000..822174fb
Binary files /dev/null and b/icons/mob/species/vox/shoes.dmi differ
diff --git a/icons/mob/species/vox/suit.dmi b/icons/mob/species/vox/suit.dmi
index 3260757f..e3b02e5c 100644
Binary files a/icons/mob/species/vox/suit.dmi and b/icons/mob/species/vox/suit.dmi differ
diff --git a/icons/mob/species/vox/uniform.dmi b/icons/mob/species/vox/uniform.dmi
new file mode 100644
index 00000000..69376d19
Binary files /dev/null and b/icons/mob/species/vox/uniform.dmi differ