diff --git a/baystation12.dme b/baystation12.dme index 3285a6fcb61..a4dce912325 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -754,6 +754,7 @@ #include "code\modules\clothing\shoes\magboots.dm" #include "code\modules\clothing\shoes\miscellaneous.dm" #include "code\modules\clothing\spacesuits\alien.dm" +#include "code\modules\clothing\spacesuits\breaches.dm" #include "code\modules\clothing\spacesuits\captain.dm" #include "code\modules\clothing\spacesuits\ert.dm" #include "code\modules\clothing\spacesuits\miscellaneous.dm" diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 5674ea90987..2bed9273e2e 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -228,24 +228,23 @@ synd_mob.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/c20r(synd_mob), slot_belt) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack) + var/obj/item/clothing/suit/space/rig/syndi/new_suit = new(synd_mob) + var/obj/item/clothing/head/helmet/space/rig/syndi/new_helmet = new(synd_mob) + if(synd_mob.species) + var/race = synd_mob.species.name - if(race == "Unathi") - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/unathi(synd_mob), slot_wear_suit) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/unathi(synd_mob), slot_head) - else if(race == "Tajaran") - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/tajara(synd_mob), slot_wear_suit) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/tajara(synd_mob), slot_head) - else if(race == "Skrell") - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/skrell(synd_mob), slot_wear_suit) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/skrell(synd_mob), slot_head) - else - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/human(synd_mob), slot_wear_suit) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/human(synd_mob), slot_head) - else - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/human(synd_mob), slot_wear_suit) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/human(synd_mob), slot_head) + switch(race) + if("Unathi") + new_suit.species_restricted = list("Unathi") + if("Tajaran") + new_suit.species_restricted = list("Tajaran") + if("Skrell") + new_suit.species_restricted = list("Skrell") + + synd_mob.equip_to_slot_or_del(new_suit, slot_wear_suit) + synd_mob.equip_to_slot_or_del(new_helmet, slot_head) var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(synd_mob) E.imp_in = synd_mob diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 1d8fd6a36b7..bcb58cd8b61 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -567,4 +567,554 @@ 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 repairing, painting and equipping 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! + + // 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 = "Engineering" + var/target_species = "Human" + + 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/engineering + name = "Engineering suit cycler" + model_text = "Engineering" + req_access = list(access_construction) + departments = list("Engineering","Atmos") + species = list("Human","Unathi","Tajaran") + +/obj/machinery/suit_cycler/mining + name = "Mining suit cycler" + model_text = "Mining" + req_access = list(access_mining) + departments = list("Mining") + species = list("Human","Unathi","Tajaran") + +/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(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"]) + target_department = input("Please select the target department paintjob.","Suit cycler",null) as null|anything in departments + else if(href_list["select_species"]) + target_species = input("Please select the target species configuration.","Suit cycler",null) as null|anything in species + 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) 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("\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 + +/obj/machinery/suit_cycler/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 + +//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 + + switch(target_species) + if("Human" || "Skrell") + if(helmet) helmet.species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox") + if(suit) suit.species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox") + if("Unathi") + if(helmet) helmet.species_restricted = list("Unathi") + if(suit) suit.species_restricted = list("Unathi") + if("Tajaran") + if(helmet) helmet.species_restricted = list("Tajaran") + if(suit) suit.species_restricted = list("Tajaran") + + 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("^%###^%$") + 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" \ No newline at end of file diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 1b10ee72b95..94376231559 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -38,6 +38,15 @@ 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. /obj/item/device diff --git a/code/game/objects/items/devices/modkit.dm b/code/game/objects/items/devices/modkit.dm index a7c221aa58f..dd7c1231f45 100644 --- a/code/game/objects/items/devices/modkit.dm +++ b/code/game/objects/items/devices/modkit.dm @@ -7,41 +7,51 @@ 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/from_helmet = /obj/item/clothing/head/helmet/space/rig - var/from_suit = /obj/item/clothing/suit/space/rig - var/to_helmet = /obj/item/clothing/head/cardborg - var/to_suit = /obj/item/clothing/suit/cardborg + var/list/target_species = list("Human","Skrell") + + var/list/permitted_types = list( + /obj/item/clothing/head/helmet/space/rig, + /obj/item/clothing/suit/space/rig + ) /obj/item/device/modkit/afterattack(obj/O, mob/user as mob) - var/flag - var/to_type - if(istype(O,from_helmet)) - flag = MODKIT_HELMET - to_type = to_helmet - else if(istype(O,from_suit)) - flag = MODKIT_SUIT - to_type = to_suit - else - return - if(!(parts & flag)) + + if(!parts) user << "This kit has no parts for this modification left." + user.drop_from_inventory(src) + del(src) return + + /* TODO: list comparison if(istype(O,to_type)) user << "[O] 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) - 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].") + + var/obj/item/clothing/I = O + if(istype(I)) + I.species_restricted = target_species.Copy() + + parts-- if(!parts) + user.drop_from_inventory(src) del(src) /obj/item/device/modkit/tajaran - name = "tajara hardsuit modification kit" + 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 Tajara." - to_helmet = /obj/item/clothing/head/helmet/space/rig/tajara - to_suit = /obj/item/clothing/suit/space/rig/tajara \ No newline at end of file + target_species = list("Tajaran") + +/obj/item/device/modkit/examine() + ..() + usr << "It looks as though it modifies hardsuits to fit the following users:" + for(var/species in target_species) + usr << "- [species]" \ No newline at end of file diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index f14101fcd9f..72f0ce03e53 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -43,7 +43,11 @@ icon_state = "voxmask" item_state = "voxmask" permeability_coefficient = 0.01 - species_restricted = ("Vox") + species_restricted = list("Vox","Vox Armalis") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/mask.dmi', + "Vox Armalis" = 'icons/mob/species/armalis/mask.dmi', + ) toggle() set category = "Object" diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index 4e931595fa4..902d9471492 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -1,20 +1,4 @@ -// Tajaran rigs. -/obj/item/clothing/head/helmet/space/rig/tajara - desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding. This one doesn't look like it was made for humans." - icon_state = "rig0-taj-helmet" - item_state = "rig0-taj-helmet" - item_color = "taj-helmet" - species_restricted = list("Tajaran") - -/obj/item/clothing/suit/space/rig/tajara - desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding. This one doesn't look like it was made for humans." - icon_state = "rig-taj" - item_state = "rig-taj" - item_color = "rig-taj" - species_restricted = list("Tajaran") - //Skrell space gear. Sleek like a wetsuit. - /obj/item/clothing/head/helmet/space/skrell name = "Skrellian helmet" desc = "Smoothly contoured and polished to a shine. Still looks like a fishbowl." @@ -52,7 +36,6 @@ item_color = "skrell_suit_black" //Unathi space gear. Huge and restrictive. - /obj/item/clothing/head/helmet/space/unathi armor = list(melee = 40, bullet = 30, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 50) heat_protection = HEAD @@ -98,7 +81,6 @@ // Vox space gear (vaccuum suit, low pressure armour) // Can't be equipped by any other species due to bone structure and vox cybernetics. - /obj/item/clothing/suit/space/vox w_class = 3 allowed = list(/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,/obj/item/weapon/tank) @@ -106,12 +88,20 @@ armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE - species_restricted = list("Vox") + species_restricted = list("Vox", "Vox Armalis") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/suit.dmi', + "Vox Armalis" = 'icons/mob/species/armalis/suit.dmi', + ) /obj/item/clothing/head/helmet/space/vox armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30) flags = HEADCOVERSEYES|STOPSPRESSUREDMAGE - species_restricted = list("Vox") + species_restricted = list("Vox","Vox Armalis") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/head.dmi', + "Vox Armalis" = 'icons/mob/species/armalis/head.dmi', + ) /obj/item/clothing/head/helmet/space/vox/pressure name = "alien helmet" @@ -130,14 +120,12 @@ icon_state = "vox-carapace" item_state = "vox-carapace" desc = "A glowing visor, perhaps stolen from a depressed Cylon." - species_restricted = list("Vox","Vox Armalis") /obj/item/clothing/suit/space/vox/carapace name = "alien carapace armour" icon_state = "vox-carapace" item_state = "vox-carapace" desc = "An armoured, segmented carapace with glowing purple lights. It looks pretty run-down." - species_restricted = list("Vox","Vox Armalis") /obj/item/clothing/head/helmet/space/vox/stealth name = "alien stealth helmet" @@ -188,16 +176,25 @@ item_state = "gloves-vox" siemens_coefficient = 0 permeability_coefficient = 0.05 - item_color="gloves-vox" + item_color = "gloves-vox" species_restricted = list("Vox","Vox Armalis") - + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/gloves.dmi', + "Vox Armalis" = 'icons/mob/species/armalis/gloves.dmi', + ) /obj/item/clothing/shoes/magboots/vox desc = "A pair of heavy, jagged armoured foot pieces, seemingly suitable for a velociraptor." name = "vox magclaws" item_state = "boots-vox" icon_state = "boots-vox" + species_restricted = list("Vox","Vox Armalis") + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/feet.dmi', + "Vox Armalis" = 'icons/mob/species/armalis/feet.dmi', + ) + action_button_name = "Toggle the magclaws" /obj/item/clothing/shoes/magboots/vox/attack_self(mob/user) @@ -235,50 +232,4 @@ set src in view() ..() if (magpulse) - usr << "It would be hard to take these off without relaxing your grip first." //theoretically this message should only be seen by the wearer when the claws are equipped. - -//Species-specific Syndicate rigs. - -/obj/item/clothing/head/helmet/space/rig/syndi/tajara - icon_state = "rig0-syndie-taj" - item_state = "syndie_helm" - item_color = "syndie-taj" - species_restricted = list("Tajaran") - -/obj/item/clothing/suit/space/rig/syndi/tajara - item_state = "syndie_hardsuit" - icon_state = "rig-syndie-taj" - species_restricted = list("Tajaran") - -/obj/item/clothing/head/helmet/space/rig/syndi/unathi - icon_state = "rig0-syndie-unathi" - item_state = "syndie_helm" - item_color = "syndie-unathi" - species_restricted = list("Unathi") - -/obj/item/clothing/suit/space/rig/syndi/unathi - item_state = "syndie_hardsuit" - icon_state = "rig-syndie-unathi" - species_restricted = list("Unathi") - -/obj/item/clothing/head/helmet/space/rig/syndi/skrell - icon_state = "rig0-syndie-skrell" - item_state = "syndie_helm" - item_color = "syndie-skrell" - species_restricted = list("Skrell") - -/obj/item/clothing/suit/space/rig/syndi/skrell - item_state = "syndie_hardsuit" - icon_state = "rig-syndie-skrell" - species_restricted = list("Skrell") - -/obj/item/clothing/head/helmet/space/rig/syndi/human - icon_state = "rig0-syndie-human" - item_state = "syndie_helm" - item_color = "syndie-human" - species_restricted = list("Human") - -/obj/item/clothing/suit/space/rig/syndi/human - item_state = "syndie_hardsuit" - icon_state = "rig-syndie-human" - species_restricted = list("Human") + usr << "It would be hard to take these off without relaxing your grip first." //theoretically this message should only be seen by the wearer when the claws are equipped. \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/breaches.dm b/code/modules/clothing/spacesuits/breaches.dm new file mode 100644 index 00000000000..19f795561c0 --- /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 9a527b32135..ab3f723674c 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -12,7 +12,14 @@ 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 = list( + "Unathi" = 'icons/mob/species/unathi/helmet.dmi', + "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi', + "Skrell" = 'icons/mob/species/skrell/helmet.dmi' + ) attack_self(mob/user) if(!isturf(user.loc)) @@ -51,7 +58,239 @@ 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") + sprite_sheets = list( + "Unathi" = 'icons/mob/species/unathi/suit.dmi', + "Tajaran" = 'icons/mob/species/tajaran/suit.dmi', + "Skrell" = 'icons/mob/species/skrell/suit.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 ..() + + ..() //Chief Engineer's rig /obj/item/clothing/head/helmet/space/rig/elite @@ -60,13 +299,14 @@ icon_state = "rig0-white" item_state = "ce_helm" item_color = "white" + sprite_sheets = null /obj/item/clothing/suit/space/rig/elite 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 = null //Mining rig /obj/item/clothing/head/helmet/space/rig/mining @@ -89,9 +329,9 @@ /obj/item/clothing/head/helmet/space/rig/syndi name = "blood-red hardsuit helmet" desc = "An advanced helmet designed for work in special operations. Property of Gorlex Marauders." - icon_state = "rig0-syndi" + icon_state = "rig0-syndie" item_state = "syndie_helm" - item_color = "syndi" + item_color = "syndie" armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 60) siemens_coefficient = 0.6 var/obj/machinery/camera/camera @@ -112,7 +352,7 @@ usr << "This helmet has a built-in camera. It's [camera ? "" : "in"]active." /obj/item/clothing/suit/space/rig/syndi - icon_state = "rig-syndi" + icon_state = "rig-syndie" name = "blood-red hardsuit" desc = "An advanced suit that protects against injuries during special operations. Property of Gorlex Marauders." item_state = "syndie_hardsuit" @@ -134,6 +374,7 @@ 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 = null /obj/item/clothing/suit/space/rig/wizard icon_state = "rig-wiz" @@ -145,7 +386,7 @@ unacidable = 1 armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60) siemens_coefficient = 0.7 - + sprite_sheets = null //Medical Rig /obj/item/clothing/head/helmet/space/rig/medical diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 1b12f625620..3583b6822e4 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -229,6 +229,8 @@ 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/obj/used_weapon = null) + handle_suit_punctures(damagetype, damage) + //visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]") if((damagetype != BRUTE) && (damagetype != BURN)) ..(damage, damagetype, def_zone, blocked) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 44deb248ca8..12a16567c56 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -53,6 +53,7 @@ emp_act if(check_shields(P.damage, "the [P.name]")) P.on_hit(src, 2, def_zone) + handle_suit_punctures(P.damage_type, P.damage) return 2 //BEGIN BOOK'S TASER NERF. @@ -296,3 +297,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 - max(0,(SS.breach_threshold - SS.damage)))) + + 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 036a84b8b1a..a687940ea2b 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -133,12 +133,24 @@ var/pressure_difference = abs( pressure - ONE_ATMOSPHERE ) 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 + + if(wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) + pressure_adjustment_coefficient -= PRESSURE_SUIT_REDUCTION_COEFFICIENT + + //Handles breaches in your space suit. 10 suit damage equals a 100% loss of pressure reduction. + if(istype(wear_suit,/obj/item/clothing/suit/space)) + var/obj/item/clothing/suit/space/S = wear_suit + if(S.can_breach && S.damage) + var/pressure_loss = S.damage * 0.1 + pressure_adjustment_coefficient += pressure_loss + + pressure_adjustment_coefficient = min(1,max(pressure_adjustment_coefficient,0)) //So it isn't less than 0 or larger than 1. + pressure_difference = pressure_difference * pressure_adjustment_coefficient + if(pressure > ONE_ATMOSPHERE) return ONE_ATMOSPHERE + pressure_difference else diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index d2bcbfd5a68..07bfca799f6 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -546,7 +546,12 @@ proc/get_damage_icon_part(damage_state, body_part) if(!t_color) t_color = icon_state var/image/standing = image("icon_state" = "[t_color]_s") - standing.icon = ((w_uniform.icon_override) ? w_uniform.icon_override : (species.sprite_sheets["uniform"] ? species.sprite_sheets["uniform"] : 'icons/mob/uniform.dmi')) + if(w_uniform.icon_override) + standing.icon = w_uniform.icon_override + else if(w_uniform.sprite_sheets && w_uniform.sprite_sheets[species.name]) + standing.icon = w_uniform.sprite_sheets[species.name] + else + standing.icon = 'icons/mob/uniform.dmi' if(w_uniform.blood_DNA) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "uniformblood") @@ -594,7 +599,15 @@ proc/get_damage_icon_part(damage_state, body_part) if(gloves) var/t_state = gloves.item_state if(!t_state) t_state = gloves.icon_state - var/image/standing = image("icon" = ((gloves.icon_override) ? gloves.icon_override : (species.sprite_sheets["gloves"] ? species.sprite_sheets["gloves"] : 'icons/mob/hands.dmi')), "icon_state" = "[t_state]") + + var/image/standing + if(gloves.icon_override) + standing = image("icon" = gloves.icon_override, "icon_state" = "[t_state]") + else if(gloves.sprite_sheets && gloves.sprite_sheets[species.name]) + standing = image("icon" = gloves.sprite_sheets[species.name], "icon_state" = "[t_state]") + else + standing = image("icon" = 'icons/mob/hands.dmi', "icon_state" = "[t_state]") + if(gloves.blood_DNA) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "bloodyhands") bloodsies.color = gloves.blood_color @@ -613,7 +626,14 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_glasses(var/update_icons=1) if(glasses) - overlays_standing[GLASSES_LAYER] = image("icon" = ((glasses.icon_override) ? glasses.icon_override : (species.sprite_sheets["eyes"] ? species.sprite_sheets["eyes"] : 'icons/mob/eyes.dmi')), "icon_state" = "[glasses.icon_state]") + + if(glasses.icon_override) + overlays_standing[GLASSES_LAYER] = image("icon" = glasses.icon_override, "icon_state" = "[glasses.icon_state]") + else if(glasses.sprite_sheets && glasses.sprite_sheets[species.name]) + overlays_standing[GLASSES_LAYER]= image("icon" = glasses.sprite_sheets[species.name], "icon_state" = "[glasses.icon_state]") + else + overlays_standing[GLASSES_LAYER]= image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]") + else overlays_standing[GLASSES_LAYER] = null if(update_icons) update_icons() @@ -621,20 +641,44 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_ears(var/update_icons=1) if(l_ear || r_ear) if(l_ear) + var/t_type = l_ear.icon_state - if(l_ear.icon_override || species.sprite_sheets["ears"]) t_type = "[t_type]_l" - overlays_standing[EARS_LAYER] = image("icon" = ((l_ear.icon_override) ? l_ear.icon_override : (species.sprite_sheets["ears"] ? species.sprite_sheets["ears"] : 'icons/mob/ears.dmi')), "icon_state" = "[t_type]") + if(l_ear.icon_override) + t_type = "[t_type]_l" + overlays_standing[EARS_LAYER] = image("icon" = l_ear.icon_override, "icon_state" = "[t_type]") + else if(l_ear.sprite_sheets && l_ear.sprite_sheets[species.name]) + t_type = "[t_type]_l" + overlays_standing[EARS_LAYER] = image("icon" = l_ear.sprite_sheets[species.name], "icon_state" = "[t_type]") + else + overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") + if(r_ear) + var/t_type = r_ear.icon_state - if(r_ear.icon_override || species.sprite_sheets["ears"]) t_type = "[t_type]_r" - overlays_standing[EARS_LAYER] = image("icon" = ((r_ear.icon_override) ? r_ear.icon_override : (species.sprite_sheets["ears"] ? species.sprite_sheets["ears"] : 'icons/mob/ears.dmi')), "icon_state" = "t_type]") + if(r_ear.icon_override) + t_type = "[t_type]_r" + overlays_standing[EARS_LAYER] = image("icon" = r_ear.icon_override, "icon_state" = "[t_type]") + else if(r_ear.sprite_sheets && r_ear.sprite_sheets[species.name]) + t_type = "[t_type]_r" + overlays_standing[EARS_LAYER] = image("icon" = r_ear.sprite_sheets[species.name], "icon_state" = "[t_type]") + else + overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") + else overlays_standing[EARS_LAYER] = null if(update_icons) update_icons() /mob/living/carbon/human/update_inv_shoes(var/update_icons=1) if(shoes) - var/image/standing = image("icon" = ((shoes.icon_override) ? shoes.icon_override : (species.sprite_sheets["feet"] ? species.sprite_sheets["feet"] : 'icons/mob/feet.dmi')), "icon_state" = "[shoes.icon_state]") + + var/image/standing + if(shoes.icon_override) + standing = image("icon" = shoes.icon_override, "icon_state" = "[shoes.icon_state]") + else if(shoes.sprite_sheets && shoes.sprite_sheets[species.name]) + standing = image("icon" = shoes.sprite_sheets[species.name], "icon_state" = "[shoes.icon_state]") + else + standing = image("icon" = 'icons/mob/feet.dmi', "icon_state" = "[shoes.icon_state]") + if(shoes.blood_DNA) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "shoeblood") bloodsies.color = shoes.blood_color @@ -665,14 +709,22 @@ proc/get_damage_icon_part(damage_state, body_part) head.screen_loc = ui_head //TODO var/image/standing if(istype(head,/obj/item/clothing/head/kitty)) - standing = image("icon" = head:mob) + standing = image("icon" = head:mob) else - standing = image("icon" = ((head.icon_override) ? head.icon_override : (species.sprite_sheets["head"] ? species.sprite_sheets["head"] : 'icons/mob/head.dmi')), "icon_state" = "[head.icon_state]") + if(head.icon_override) + standing = image("icon" = head.icon_override, "icon_state" = "[head.icon_state]") + else if(head.sprite_sheets && head.sprite_sheets[species.name]) + standing = image("icon" = head.sprite_sheets[species.name], "icon_state" = "[head.icon_state]") + else + standing = image("icon" = 'icons/mob/head.dmi', "icon_state" = "[head.icon_state]") + if(head.blood_DNA) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") bloodsies.color = head.blood_color standing.overlays += bloodsies - overlays_standing[HEAD_LAYER] = standing + + overlays_standing[HEAD_LAYER] = standing + else overlays_standing[HEAD_LAYER] = null if(update_icons) update_icons() @@ -682,16 +734,29 @@ proc/get_damage_icon_part(damage_state, body_part) belt.screen_loc = ui_belt //TODO var/t_state = belt.item_state if(!t_state) t_state = belt.icon_state - overlays_standing[BELT_LAYER] = image("icon" = ((belt.icon_override) ? belt.icon_override : (species.sprite_sheets["belt"] ? species.sprite_sheets["belt"] : 'icons/mob/belt.dmi')), "icon_state" = "[t_state]") + + if(belt.icon_override) + overlays_standing[BELT_LAYER] = image("icon" = belt.icon_override, "icon_state" = "[t_state]") + else if(belt.sprite_sheets && belt.sprite_sheets[species.name]) + overlays_standing[BELT_LAYER] = image("icon" = belt.sprite_sheets[species.name], "icon_state" = "[t_state]") + else + overlays_standing[BELT_LAYER] = image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[t_state]") else - overlays_standing[BELT_LAYER] = null + overlays_standing[BELT_LAYER] = null if(update_icons) update_icons() /mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) if( wear_suit && istype(wear_suit, /obj/item/clothing/suit) ) //TODO check this wear_suit.screen_loc = ui_oclothing //TODO - var/image/standing = image("icon" = ((wear_suit.icon_override) ? wear_suit.icon_override : (species.sprite_sheets["suit"] ? species.sprite_sheets["suit"] : 'icons/mob/suit.dmi')), "icon_state" = "[wear_suit.icon_state]") + + var/image/standing + if(wear_suit.icon_override) + standing = image("icon" = wear_suit.icon_override, "icon_state" = "[wear_suit.icon_state]") + else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.name]) + standing = image("icon" = wear_suit.sprite_sheets[species.name], "icon_state" = "[wear_suit.icon_state]") + else + standing = image("icon" = 'icons/mob/suit.dmi', "icon_state" = "[wear_suit.icon_state]") if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) ) drop_from_inventory(handcuffed) @@ -726,7 +791,15 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1) if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/tie) ) ) wear_mask.screen_loc = ui_mask //TODO - var/image/standing = image("icon" = ((wear_mask.icon_override) ? wear_mask.icon_override : (species.sprite_sheets["mask"] ? species.sprite_sheets["mask"] : 'icons/mob/mask.dmi')), "icon_state" = "[wear_mask.icon_state]") + + var/image/standing + if(wear_mask.icon_override) + standing = image("icon" = wear_mask.icon_override, "icon_state" = "[wear_mask.icon_state]") + else if(wear_mask.sprite_sheets && wear_mask.sprite_sheets[species.name]) + standing = image("icon" = wear_mask.sprite_sheets[species.name], "icon_state" = "[wear_mask.icon_state]") + else + standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]") + if( !istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA ) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "maskblood") bloodsies.color = wear_mask.blood_color @@ -740,7 +813,12 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_back(var/update_icons=1) if(back) back.screen_loc = ui_back //TODO - overlays_standing[BACK_LAYER] = image("icon" = ((back.icon_override) ? back.icon_override : (species.sprite_sheets["back"] ? species.sprite_sheets["back"] : 'icons/mob/back.dmi')), "icon_state" = "[back.icon_state]") + if(back.icon_override) + overlays_standing[BACK_LAYER] = image("icon" = back.icon_override, "icon_state" = "[back.icon_state]") + else if(back.sprite_sheets && back.sprite_sheets[species.name]) + overlays_standing[BACK_LAYER] = image("icon" = back.sprite_sheets[species.name], "icon_state" = "[back.icon_state]") + else + overlays_standing[BACK_LAYER] = image("icon" = 'icons/mob/back.dmi', "icon_state" = "[back.icon_state]") else overlays_standing[BACK_LAYER] = null if(update_icons) update_icons() @@ -781,8 +859,16 @@ proc/get_damage_icon_part(damage_state, body_part) r_hand.screen_loc = ui_rhand //TODO var/t_state = r_hand.item_state if(!t_state) t_state = r_hand.icon_state - if(r_hand.icon_override || species.sprite_sheets["held"]) t_state = "[t_state]_r" - overlays_standing[R_HAND_LAYER] = image("icon" = ((r_hand.icon_override) ? r_hand.icon_override : (species.sprite_sheets["held"] ? species.sprite_sheets["held"] : 'icons/mob/items_righthand.dmi')), "icon_state" = "[t_state]") + + if(r_hand.icon_override) + t_state = "[t_state]_r" + overlays_standing[R_HAND_LAYER] = image("icon" = r_hand.icon_override, "icon_state" = "[t_state]") + else if(r_hand.sprite_sheets && r_hand.sprite_sheets[species.name]) + t_state = "[t_state]_r" + overlays_standing[R_HAND_LAYER] = image("icon" = r_hand.sprite_sheets[species.name], "icon_state" = "[t_state]") + else + overlays_standing[R_HAND_LAYER] = image("icon" = 'icons/mob/items_righthand.dmi', "icon_state" = "[t_state]") + if (handcuffed) drop_r_hand() else overlays_standing[R_HAND_LAYER] = null @@ -794,8 +880,16 @@ proc/get_damage_icon_part(damage_state, body_part) l_hand.screen_loc = ui_lhand //TODO var/t_state = l_hand.item_state if(!t_state) t_state = l_hand.icon_state - if(l_hand.icon_override || species.sprite_sheets["held"]) t_state = "[t_state]_l" - overlays_standing[L_HAND_LAYER] = image("icon" = ((l_hand.icon_override) ? l_hand.icon_override : (species.sprite_sheets["held"] ? species.sprite_sheets["held"] : 'icons/mob/items_lefthand.dmi')), "icon_state" = "[t_state]") + + if(l_hand.icon_override) + t_state = "[t_state]_l" + overlays_standing[L_HAND_LAYER] = image("icon" = l_hand.icon_override, "icon_state" = "[t_state]") + else if(l_hand.sprite_sheets && l_hand.sprite_sheets[species.name]) + t_state = "[t_state]_l" + overlays_standing[L_HAND_LAYER] = image("icon" = l_hand.sprite_sheets[species.name], "icon_state" = "[t_state]") + else + overlays_standing[L_HAND_LAYER] = image("icon" = 'icons/mob/items_lefthand.dmi', "icon_state" = "[t_state]") + if (handcuffed) drop_l_hand() else overlays_standing[L_HAND_LAYER] = null diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm index 096631f2dd1..bef9282daac 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/species.dm @@ -49,26 +49,6 @@ var/race_key = 0 var/icon/icon_template - /* Species-specific sprites, concept stolen from Paradise//vg/. - ex: - sprite_sheets = list( - "held" = 'icons/mob/path', - "uniform" = 'icons/mob/path', - "suit" = 'icons/mob/path', - "belt" = 'icons/mob/path' - "head" = 'icons/mob/path', - "back" = 'icons/mob/path', - "mask" = 'icons/mob/path', - "ears" = 'icons/mob/path', - "eyes" = 'icons/mob/path', - "feet" = 'icons/mob/path', - "gloves" = 'icons/mob/path' - ) - If index term exists and icon_override is not set, this sprite sheet will be used. - */ - - var/list/sprite_sheets = list() - /datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. //This is a basic humanoid limb setup. H.organs = list() @@ -210,14 +190,6 @@ blood_color = "#2299FC" flesh_color = "#808D11" - sprite_sheets = list( - "suit" = 'icons/mob/species/vox/suit.dmi', - "head" = 'icons/mob/species/vox/head.dmi', - "mask" = 'icons/mob/species/vox/mask.dmi', - "feet" = 'icons/mob/species/vox/feet.dmi', - "gloves" = 'icons/mob/species/vox/gloves.dmi' - ) - /datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) H.verbs += /mob/living/carbon/human/proc/leap @@ -261,14 +233,6 @@ tail = "armalis_tail" icon_template = 'icons/mob/human_races/r_armalis.dmi' - sprite_sheets = list( - "suit" = 'icons/mob/species/armalis/suit.dmi', - "gloves" = 'icons/mob/species/armalis/gloves.dmi', - "feet" = 'icons/mob/species/armalis/feet.dmi', - "head" = 'icons/mob/species/armalis/head.dmi', - "held" = 'icons/mob/species/armalis/held.dmi' - ) - /datum/species/vox/create_organs(var/mob/living/carbon/human/H) ..() //create organs first. diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 77e8f04b0fc..84160577208 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/species/armalis/mask.dmi b/icons/mob/species/armalis/mask.dmi new file mode 100644 index 00000000000..e69de29bb2d diff --git a/icons/mob/species/skrell/helmet.dmi b/icons/mob/species/skrell/helmet.dmi new file mode 100644 index 00000000000..61ada41abf6 Binary files /dev/null and b/icons/mob/species/skrell/helmet.dmi differ diff --git a/icons/mob/species/skrell/suit.dmi b/icons/mob/species/skrell/suit.dmi new file mode 100644 index 00000000000..2e471725988 Binary files /dev/null and b/icons/mob/species/skrell/suit.dmi differ diff --git a/icons/mob/species/tajaran/helmet.dmi b/icons/mob/species/tajaran/helmet.dmi new file mode 100644 index 00000000000..1fe4f2caca3 Binary files /dev/null and b/icons/mob/species/tajaran/helmet.dmi differ diff --git a/icons/mob/species/tajaran/suit.dmi b/icons/mob/species/tajaran/suit.dmi new file mode 100644 index 00000000000..c5fa9468262 Binary files /dev/null and b/icons/mob/species/tajaran/suit.dmi differ diff --git a/icons/mob/species/unathi/helmet.dmi b/icons/mob/species/unathi/helmet.dmi new file mode 100644 index 00000000000..c67afdfe82d Binary files /dev/null and b/icons/mob/species/unathi/helmet.dmi differ diff --git a/icons/mob/species/unathi/suit.dmi b/icons/mob/species/unathi/suit.dmi new file mode 100644 index 00000000000..0b736b5f045 Binary files /dev/null and b/icons/mob/species/unathi/suit.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index b17b1ed23b4..ee9b6369644 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index ec7b9bdcc96..67d085a46b0 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index cdb4f3f6ebc..e9d1a3d3f03 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ