diff --git a/aurora.dme b/aurora.dme index 97e737de..1e11d8f1 100644 --- a/aurora.dme +++ b/aurora.dme @@ -39,6 +39,7 @@ #define FILE_DIR "icons/obj/clothing/species/tajaran" #define FILE_DIR "icons/obj/clothing/species/unathi" #define FILE_DIR "icons/obj/custom_items" +#define FILE_DIR "icons/obj/door_braces" #define FILE_DIR "icons/obj/doors" #define FILE_DIR "icons/obj/flora" #define FILE_DIR "icons/obj/machines" @@ -567,6 +568,7 @@ #include "code\game\objects\items\devices\binoculars.dm" #include "code\game\objects\items\devices\chameleonproj.dm" #include "code\game\objects\items\devices\debugger.dm" +#include "code\game\objects\items\devices\door_bracer.dm" #include "code\game\objects\items\devices\flash.dm" #include "code\game\objects\items\devices\flashlight.dm" #include "code\game\objects\items\devices\isocube.dm" diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 696fb288..6da7f62f 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -1345,3 +1345,23 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "Pill Bottle Kit" access = access_medical group = "Medical / Science" + +/datum/supply_packs/doorbracers_engineering + name = "Engineering Doorbracer Crate" + contains = list(/obj/item/device/doorbrace/engineering, + /obj/item/device/doorbrace/engineering, + /obj/item/device/doorbrace/engineering) + cost = 30 + containertype = /obj/structure/closet/crate + containername = "engineering doorbracers" + group = "Engineering" + +/datum/supply_packs/doorbracers_security + name = "Security Doorbracer Crate" + contains = list(/obj/item/device/doorbrace/security, + /obj/item/device/doorbrace/security, + /obj/item/device/doorbrace/security) + cost = 30 + containertype = /obj/structure/closet/crate + containername = "security doorbracers" + group = "Security" diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 8b49259e..4712c727 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -51,6 +51,7 @@ var/door_sound='sound/machines/airlock.ogg' var/door_sound_distance=30 autoclose = 1 + var/obj/item/device/doorbrace/bracer = null /obj/machinery/door/airlock/command name = "Airlock" @@ -717,6 +718,15 @@ About the new airlock wires panel: set_frequency(ST.change_freq(frequency)) return + if (istype(C, /obj/item/device/doorbrace)) + if (bracer) + user << "There is already a [bracer] on [src]!" + return + + var/obj/item/device/doorbrace/newbracer = C + newbracer.attachto(src, user) + return + src.add_fingerprint(user) if((istype(C, /obj/item/weapon/weldingtool) && !( src.operating > 0 ) && src.density)) var/obj/item/weapon/weldingtool/W = C @@ -824,7 +834,10 @@ About the new airlock wires panel: playsound(src.loc, door_sound, door_sound_distance, 1) /obj/machinery/door/airlock/open(var/forced=0) - if( operating || welded || locked ) + if( operating || welded || locked) + return 0 + if (bracer) + visible_message("[src]'s actuators whirr, but the door does not open.") return 0 if(!forced) if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) ) @@ -915,7 +928,9 @@ About the new airlock wires panel: break /obj/machinery/door/airlock/proc/prison_open() + if (bracer) + return src.unlock() src.open() src.lock() - return \ No newline at end of file + return diff --git a/code/game/objects/items/devices/door_bracer.dm b/code/game/objects/items/devices/door_bracer.dm new file mode 100644 index 00000000..8c45f2cf --- /dev/null +++ b/code/game/objects/items/devices/door_bracer.dm @@ -0,0 +1,289 @@ +#define STATUS_INACTIVE 0 +#define STATUS_ACTIVE 1 +#define STATUS_BROKEN 2 + +#define LAYER_ATTACHED 3.2 +#define LAYER_NORMAL 3 + +/obj/item/device/doorbrace + name = "magnetic door lock" + desc = "A large, ID locked device used for completely locking down airlocks." + icon = 'icons/obj/door_braces/centcom.dmi' + icon_state = "inactive" + w_class = 3 + req_access = list(103) + health = 90 + + var/department = "CENTCOM" + var/status = 0 + var/constructionstate = 0 + var/obj/machinery/door/airlock/target = null + +/obj/item/device/doorbrace/security + icon = 'icons/obj/door_braces/security.dmi' + department = "Security" + req_access = list(1) + +/obj/item/device/doorbrace/engineering + icon = 'icons/obj/door_braces/engineering.dmi' + department = "Engineering" + req_access = null + req_one_access = list(11, 24) + +/obj/item/device/doorbrace/examine() + ..() + + if (status == STATUS_BROKEN) + usr << "It looks broken!" + else + usr << "\blue This device has [department] department markings on it." + +/obj/item/device/doorbrace/attack_hand(var/mob/user) + if (status == STATUS_ACTIVE) + ui_interact(user) + else + ..() + +/obj/item/device/doorbrace/bullet_act(var/obj/item/projectile/Proj) + takedamage(Proj.damage) + ..() + +/obj/item/device/doorbrace/attackby(var/obj/item/I, var/mob/user) + if (status == STATUS_BROKEN) + user << "[src] is broken beyond repair!" + return + + if (istype(I, /obj/item/weapon) && user.a_intent == "hurt") + if (I.force >= 8) + user.visible_message("[user] bashes [src] with [I]!", "You strike [src] with [I], damaging it!") + takedamage(I.force) + return + else + user.visible_message("[user] hits [src] with [I] to no visible effect.", "You hit [src] with [I], but it appears to have no effect.") + return + + switch (constructionstate) + if (0) + if (istype(I, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/emagcard = I + emagcard.uses-- + visible_message("[src] sparks and falls off the door!", "You emag [src], frying its circuitry[status == STATUS_ACTIVE ? " and making it drop onto the floor" : ""]!") + + setstatus(STATUS_BROKEN) + return + + if (status == STATUS_ACTIVE && istype(I, /obj/item/weapon/card/id)) + if (check_access(I) && !constructionstate) + user << "You swipe your [I] through [src], making it drop onto the floor with a thud." + setstatus(STATUS_INACTIVE) + return + else if (constructionstate) + user << "You cannot swipe your [I] through [src] with it partially dismantled!" + return + else + user << "A red light flashes on [src] as you swipe your [I] through it." + flick("deny",src) + return + + if (istype(I, /obj/item/weapon/screwdriver)) + user << "You unfasten and remove the plastic cover from [src], revealing a thick metal shell." + playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1) + setconstructionstate(1) + return + + if (1) + if (istype(I, /obj/item/weapon/screwdriver)) + user << "You put the metal cover of back onto [src], and screw it tight." + playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1) + setconstructionstate(0) + return + if (istype(I, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = I + if (WT.remove_fuel(1, user)) + user.visible_message("[user] starts welding through the metal shell of [src].", "You start welding through the metal covering of [src]") + playsound(loc, 'sound/items/Welder.ogg', 50, 1) + if (do_after(user, 25)) + user << "You are able to weld through the metal shell of [src]." + setconstructionstate(2) + return + if (2) + if (istype(I, /obj/item/weapon/crowbar)) + user << "You pry off the metal covering from [src]." + playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) + setconstructionstate(3) + return + if (3) + if (istype(I, /obj/item/weapon/wirecutters)) + user << "You cut the wires connecting the [src]'s magnets to their powersupply, [target ? "making the device fall off [target] and rendering it unusable." : "rendering the device unusable."]" + playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1) + setconstructionstate(4) + return + +/obj/item/device/doorbrace/proc/attachto(var/obj/machinery/door/airlock/newtarget, var/mob/user as mob) + if (status == STATUS_BROKEN) + user << "[src] is damaged beyond repair! It cannot be used!" + return + + if (!newtarget.density || newtarget.operating) + user << "[newtarget] must be closed before you can attach [src] to it!" + return + + if (newtarget.p_open) + user << "You must close [newtarget]'s maintenance panel before attaching [src] to it!" + return + + user.visible_message("[user] starts mounting [src] onto [newtarget].", "You begin mounting [src] onto [newtarget].") + if (do_after(user, 35, 1)) + if (status == STATUS_BROKEN) + user << "[src] is damaged beyond repair! It cannot be used!" + return + + if (!newtarget.density) + user << "[newtarget] must be closed before you can attach [src] to it!" + return + + if (newtarget.p_open) + user << "You must close [newtarget]'s maintenance panel before attaching [src] to it!" + return + + user.visible_message("[user] attached [src] onto [newtarget] and flicks it on. The magnetic lock now seals [newtarget].", "You attached [src] onto [newtarget] and switched on the magnetic lock.") + user.drop_item() + + setstatus(STATUS_ACTIVE, newtarget) + return + +/obj/item/device/doorbrace/proc/setstatus(var/newstatus, var/obj/machinery/door/airlock/newtarget as obj) + switch (newstatus) + if (STATUS_INACTIVE) + if (status != STATUS_ACTIVE) + return + if (!target) + return + + detach() + icon_state = "inactive" + status = newstatus + + if (STATUS_ACTIVE) + if (status != STATUS_INACTIVE) + return + if (!newtarget) + return + + attach(newtarget) + icon_state = "active" + status = newstatus + + if (STATUS_BROKEN) + spark() + + if (target) + var/playflick = 1 + if (constructionstate) + playflick = 0 + + detach(playflick) + + icon_state = "broken" + status = newstatus + +/obj/item/device/doorbrace/proc/setconstructionstate(var/newstate) + constructionstate = newstate + if (newstate == 0) + if (status == STATUS_ACTIVE) + icon_state = "active" + else + icon_state = "inactive" + else if (newstate == 2) + flick("deconstruct_2_anim", src) + else if (newstate == 4) + setstatus(STATUS_BROKEN) + else + icon_state = "deconstruct_[constructionstate]" + +/obj/item/device/doorbrace/proc/detach(var/playflick = 1) + if (target) + + if (playflick) + spawn(-15) flick("release", src) + + adjustsprite(null) + layer = LAYER_NORMAL + + target.bracer = null + + anchored = 0 + +/obj/item/device/doorbrace/proc/attach(var/obj/machinery/door/airlock/newtarget as obj) + adjustsprite(newtarget) + layer = LAYER_ATTACHED + flick("deploy", src) + + newtarget.bracer = src + target = newtarget + + anchored = 1 + +/obj/item/device/doorbrace/proc/adjustsprite(var/obj/target as obj) + if (target) + switch (get_dir(src, target)) + if (NORTH) + pixel_x = 0 + pixel_y = 32 + if (NORTHEAST) + pixel_x = 32 + pixel_y = 32 + if (EAST) + pixel_x = 32 + pixel_y = 0 + if (SOUTHEAST) + pixel_x = 32 + pixel_y = -32 + if (SOUTH) + pixel_x = 0 + pixel_y = -32 + if (SOUTHWEST) + pixel_x = -32 + pixel_y = -32 + if (WEST) + pixel_x = -32 + pixel_y = 0 + if (NORTHWEST) + pixel_x = -32 + pixel_y = 32 + else + pixel_x = 0 + pixel_y = 0 + +/obj/item/device/doorbrace/proc/takedamage(var/damage) + health -= damage + + if (damage >= 40 && prob(50)) + health = 0 + + if (health <= 0) + visible_message("[src] sparks[target ? " and falls off of \the [target]!" : "!"] It is now completely unusable!") + setstatus(STATUS_BROKEN) + return + + if (prob(50)) + spark() + +/obj/item/device/doorbrace/proc/spark() + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + + if (target) + s.set_up(5, 1, target) + else + s.set_up(5, 1, src) + + s.start() + spawn(5) + del(s) + +#undef STATUS_INACTIVE +#undef STATUS_ACTIVE +#undef STATUS_BROKEN + +#undef LAYER_ATTACHED +#undef LAYER_NORMAL diff --git a/icons/obj/door_braces/centcom.dmi b/icons/obj/door_braces/centcom.dmi new file mode 100644 index 00000000..97a97794 Binary files /dev/null and b/icons/obj/door_braces/centcom.dmi differ diff --git a/icons/obj/door_braces/engineering.dmi b/icons/obj/door_braces/engineering.dmi new file mode 100644 index 00000000..49323f4a Binary files /dev/null and b/icons/obj/door_braces/engineering.dmi differ diff --git a/icons/obj/door_braces/security.dmi b/icons/obj/door_braces/security.dmi new file mode 100644 index 00000000..00a820fb Binary files /dev/null and b/icons/obj/door_braces/security.dmi differ diff --git a/maps/tgstation2.dmm b/maps/tgstation2.dmm index af54753e..a954fa60 100644 --- a/maps/tgstation2.dmm +++ b/maps/tgstation2.dmm @@ -638,7 +638,7 @@ "amn" = (/obj/structure/rack,/obj/item/clothing/mask/gas{pixel_x = 3; pixel_y = 3},/obj/item/clothing/mask/gas{pixel_x = 3; pixel_y = 3},/obj/item/clothing/mask/gas,/obj/item/clothing/mask/gas,/obj/item/clothing/mask/gas{pixel_x = -3; pixel_y = -3},/obj/item/clothing/mask/gas{pixel_x = -3; pixel_y = -3},/obj/structure/window/reinforced{dir = 4},/obj/item/device/binoculars,/obj/item/device/binoculars,/turf/simulated/floor{icon_state = "bot"; dir = 1},/area/security/armoury) "amo" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/security/armoury) "amp" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/security/armoury) -"amq" = (/obj/machinery/light_switch{pixel_y = 28},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor,/area/security/armoury) +"amq" = (/obj/machinery/light_switch{pixel_y = 28},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/structure/rack,/obj/item/device/doorbrace/security{pixel_x = 5; pixel_y = -5},/obj/item/device/doorbrace/security,/obj/item/device/doorbrace/security{pixel_x = -5; pixel_y = 5},/turf/simulated/floor,/area/security/armoury) "amr" = (/obj/structure/dispenser{plasmatanks = 0},/obj/machinery/alarm{locked = 1; pixel_y = 23},/obj/machinery/atmospherics/unary/vent_pump/on{tag = "icon-map_vent_out (WEST)"; icon_state = "map_vent_out"; dir = 8},/obj/machinery/camera{dir = 8},/turf/simulated/floor{icon_state = "bot"},/area/security/armoury) "ams" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plating/airless,/area/solar/auxport) "amt" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plating/airless,/area/solar/auxport) @@ -6605,7 +6605,7 @@ "cxa" = (/obj/structure/stool,/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plating,/area/maintenance/aft) "cxb" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/turf/simulated/floor/plating,/area/maintenance/aft) "cxc" = (/turf/simulated/wall/r_wall,/area/engine/storage_hard) -"cxd" = (/obj/machinery/power/apc{dir = 8; name = "Engineering Storage APC"; pixel_x = -26; pixel_y = 3},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor,/area/engine/storage) +"cxd" = (/obj/machinery/power/apc{dir = 8; name = "Engineering Storage APC"; pixel_x = -26; pixel_y = 3},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/table/reinforced{icon_state = "table"},/obj/item/device/doorbrace/engineering{pixel_x = 5; pixel_y = -5},/obj/item/device/doorbrace/engineering,/obj/item/device/doorbrace/engineering{pixel_x = -5; pixel_y = 5},/turf/simulated/floor,/area/engine/storage) "cxe" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{tag = "icon-map-scrubbers (WEST)"; icon_state = "map-scrubbers"; dir = 8},/turf/simulated/floor,/area/engine/storage) "cxf" = (/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{tag = "icon-intact-scrubbers (EAST)"; icon_state = "intact-scrubbers"; dir = 4},/turf/simulated/floor,/area/engine/storage) "cxg" = (/obj/structure/table,/obj/item/weapon/airlock_electronics,/obj/item/weapon/airlock_electronics,/obj/item/weapon/cable_coil,/obj/item/weapon/cable_coil,/obj/item/clothing/glasses/welding,/obj/item/weapon/book/manual/supermatter_engine,/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/machinery/atmospherics/unary/vent_scrubber/on{tag = "icon-map_scrubber_on (WEST)"; icon_state = "map_scrubber_on"; dir = 8},/turf/simulated/floor,/area/engine/storage)