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