diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index a270af2df90..c1626ab99a4 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1320,4 +1320,48 @@ proc/is_hot(obj/item/W as obj) istype(W, /obj/item/weapon/reagent_containers/syringe) || \ istype(W, /obj/item/weapon/kitchen/utensil/fork) && W.icon_state != "forkloaded" || \ istype(W, /obj/item/weapon/twohanded/fireaxe) \ - ) \ No newline at end of file + ) + +/* +Checks if that loc and dir has a item on the wall +*/ +var/list/WALLITEMS = list( + "/obj/machinery/power/apc", "/obj/machinery/alarm", "/obj/item/device/radio/intercom", + "/obj/structure/extinguisher_cabinet", "/obj/structure/reagent_dispensers/peppertank", + "/obj/machinery/status_display", "/obj/machinery/requests_console", "/obj/machinery/light_switch", "/obj/effect/sign", + "/obj/machinery/newscaster", "/obj/machinery/firealarm", "/obj/structure/noticeboard", "/obj/machinery/door_control", + "/obj/machinery/computer/security/telescreen", "/obj/machinery/embedded_controller/radio/simple_vent_controller", + "/obj/item/weapon/secstorage/ssafe", "/obj/machinery/door_timer", "/obj/machinery/flasher", "/obj/machinery/keycard_auth", + "/obj/structure/mirror", "/obj/structure/closet/fireaxecabinet", "/obj/machinery/computer/security/telescreen/entertainment" + ) +/proc/gotwallitem(loc, dir) + for(var/obj/O in loc) + for(var/item in WALLITEMS) + if(istype(O, text2path(item))) + //Direction works sometimes + if(O.dir == dir) + return 1 + + //Some stuff doesn't use dir properly, so we need to check pixel instead + switch(dir) + if(SOUTH) + if(O.pixel_y > 10) + return 1 + if(NORTH) + if(O.pixel_y < -10) + return 1 + if(WEST) + if(O.pixel_x > 10) + return 1 + if(EAST) + if(O.pixel_x < -10) + return 1 + + + //Some stuff is placed directly on the wallturf (signs) + for(var/obj/O in get_step(loc, dir)) + for(var/item in WALLITEMS) + if(istype(O, text2path(item))) + if(O.pixel_x == 0 && O.pixel_y == 0) + return 1 + return 0 diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 2884f1a4701..fb672949131 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -71,6 +71,7 @@ var/aidisabled = 0 var/AAlarmwires = 31 var/shorted = 0 + var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone // Uses code from apc.dm @@ -142,8 +143,20 @@ var/list/air_vent_info var/list/air_scrub_info -/obj/machinery/alarm/New() +/obj/machinery/alarm/New(nloc, ndir, nbuild) ..() + if(nloc) + loc = nloc + + if(ndir) + dir = ndir + + if(nbuild) + buildstage = 0 + wiresexposed = 1 + pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) + pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 + alarm_area = get_area(loc) if (alarm_area.master) alarm_area = alarm_area.master @@ -151,6 +164,8 @@ if (name == "alarm") name = "[alarm_area.name] Air Alarm" + update_icon() + /obj/machinery/alarm/initialize() set_frequency(frequency) if (!master_is_operating()) @@ -268,6 +283,7 @@ //world << "AAlarm Wire Cut" src.updateDialog() + update_icon() return @@ -298,6 +314,7 @@ // if(AALARM_WIRE_AALARM) //world << "AAlarm Wire mended" + update_icon() src.updateDialog() return @@ -869,8 +886,18 @@ table tr:first-child th:first-child { border: none;} /obj/machinery/alarm/update_icon() if(wiresexposed) - icon_state = "alarmx" + switch(buildstage) + if(2) + if(src.AAlarmwires == 0) // All wires cut + icon_state = "alarm_b2" + else + icon_state = "alarmx" + if(1) + icon_state = "alarm_b2" + if(0) + icon_state = "alarm_b1" return + if((stat & (NOPOWER|BROKEN)) || shorted) icon_state = "alarmp" return @@ -968,36 +995,81 @@ table tr:first-child th:first-child { border: none;} update_icon() /obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob) -/* if (istype(W, /obj/item/weapon/wirecutters)) - stat ^= BROKEN - src.add_fingerprint(user) - for(var/mob/O in viewers(user, null)) - O.show_message(text("\red [] has []activated []!", user, (stat&BROKEN) ? "de" : "re", src), 1) - update_icon() - return -*/ - if(istype(W, /obj/item/weapon/screwdriver)) // Opening that Air Alarm up. - //user << "You pop the Air Alarm's maintence panel open." - wiresexposed = !wiresexposed - user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]" - update_icon() - return + switch(buildstage) + if(2) + if(istype(W, /obj/item/weapon/wirecutters) && AAlarmwires == 0) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) + user << "You cut the final wires." + var/obj/item/weapon/cable_coil/cable = new /obj/item/weapon/cable_coil( src.loc ) + cable.amount = 5 + buildstage = 1 + update_icon() + return - if (wiresexposed && ((istype(W, /obj/item/device/multitool) || istype(W, /obj/item/weapon/wirecutters)))) - return src.attack_hand(user) + if(istype(W, /obj/item/weapon/screwdriver)) // Opening that Air Alarm up. + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + wiresexposed = !wiresexposed + user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]" + update_icon() + return + if (wiresexposed && ((istype(W, /obj/item/device/multitool) || istype(W, /obj/item/weapon/wirecutters)))) + return src.attack_hand(user) + else if (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card + if(stat & (NOPOWER|BROKEN)) + user << "It does nothing" + else + if(src.allowed(usr) && !isWireCut(AALARM_WIRE_IDSCAN)) + locked = !locked + user << "\blue You [ locked ? "lock" : "unlock"] the Air Alarm interface." + src.updateUsrDialog() + else + user << "\red Access denied." + return + if(1) + if(istype(W, /obj/item/weapon/crowbar) && AAlarmwires == 0) + user << "You pry out the circuit." + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + spawn(20) + new /obj/item/weapon/airalarm_electronics( src.loc ) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + buildstage = 0 + update_icon() + return + + if(istype(W, /obj/item/weapon/cable_coil)) + var/obj/item/weapon/cable_coil/cable = W + if(cable.amount < 5) + user << "You need more cable!" + return + + user << "You start wiring the air alarm!" + spawn(20) + cable.amount -= 5 + if(!cable.amount) + del(cable) + + user << "You wire the air alarm!" + src.AAlarmwires = 31 + buildstage = 2 + update_icon() + return + if(0) + if(istype(W, /obj/item/weapon/airalarm_electronics)) + user << "You insert the circuit!" + buildstage = 1 + update_icon() + user.drop_item() + del(W) + return + + if(istype(W, /obj/item/weapon/wrench)) + user << "You detach \the [src] from the wall!" + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + new /obj/item/alarm_frame( user.loc ) + del(src) + return - else if (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card - if(stat & (NOPOWER|BROKEN)) - user << "It does nothing" - else - if(src.allowed(usr) && !isWireCut(AALARM_WIRE_IDSCAN)) - locked = !locked - user << "\blue You [ locked ? "lock" : "unlock"] the Air Alarm interface." - src.updateUsrDialog() - else - user << "\red Access denied." - return return ..() /obj/machinery/alarm/power_change() @@ -1008,8 +1080,94 @@ table tr:first-child th:first-child { border: none;} spawn(rand(0,15)) update_icon() +/* +AIR ALARM CIRCUIT +Just a object used in constructing air alarms +*/ +/obj/item/weapon/airalarm_electronics + name = "air alarm electronics" + icon = 'icons/obj/doors/door_assembly.dmi' + icon_state = "door_electronics" + desc = "Looks like a circuit. Probably is." + w_class = 2.0 + m_amt = 50 + g_amt = 50 + + +/* +AIR ALARM ITEM +Handheld air alarm frame, for placing on walls +Code shamelessly copied from apc_frame +*/ +/obj/item/alarm_frame + name = "air alarm frame" + desc = "Used for building Air Alarms" + icon = 'icons/obj/monitors.dmi' + icon_state = "alarm_bitem" + flags = FPRINT | TABLEPASS| CONDUCT + +/obj/item/alarm_frame/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/metal( get_turf(src.loc), 2 ) + del(src) + return + ..() + +/obj/item/alarm_frame/proc/try_build(turf/on_wall) + if (get_dist(on_wall,usr)>1) + return + + var/ndir = get_dir(on_wall,usr) + if (!(ndir in cardinal)) + return + + var/turf/loc = get_turf_loc(usr) + var/area/A = loc.loc + if (!istype(loc, /turf/simulated/floor)) + usr << "\red Air Alarm cannot be placed on this spot." + return + if (A.requires_power == 0 || A.name == "Space") + usr << "\red Air Alarm cannot be placed in this area." + return + + if(gotwallitem(loc, ndir)) + usr << "\red There's already an item on this wall!" + return + + new /obj/machinery/alarm(loc, ndir, 1) + + del(src) + + +/* +FIRE ALARM +*/ /obj/machinery/firealarm var/last_process = 0 + var/wiresexposed = 0 + var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone + +/obj/machinery/firealarm/update_icon() + + if(wiresexposed) + switch(buildstage) + if(2) + icon_state="fire_b2" + if(1) + icon_state="fire_b1" + if(0) + icon_state="fire_b0" + + return + + if(stat & BROKEN) + icon_state = "firex" + else if(stat & NOPOWER) + icon_state = "firep" + else if(!src.detecting) + icon_state = "fire1" + else + icon_state = "fire0" /obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume) if(src.detecting) @@ -1030,30 +1188,77 @@ table tr:first-child th:first-child { border: none;} if(prob(50/severity)) alarm() ..() -/obj/machinery/firealarm/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (istype(W, /obj/item/weapon/wirecutters)) - src.detecting = !( src.detecting ) - if (src.detecting) - user.visible_message("\red [user] has reconnected [src]'s detecting unit!", "You have reconnected [src]'s detecting unit.") - else - user.visible_message("\red [user] has disconnected [src]'s detecting unit!", "You have disconnected [src]'s detecting unit.") - else - src.alarm() +/obj/machinery/firealarm/attackby(obj/item/W as obj, mob/user as mob) src.add_fingerprint(user) + + if (istype(W, /obj/item/weapon/screwdriver) && buildstage == 2) + wiresexposed = !wiresexposed + update_icon() + return + + if(wiresexposed) + switch(buildstage) + if(2) + if (istype(W, /obj/item/device/multitool)) + src.detecting = !( src.detecting ) + if (src.detecting) + user.visible_message("\red [user] has reconnected [src]'s detecting unit!", "You have reconnected [src]'s detecting unit.") + else + user.visible_message("\red [user] has disconnected [src]'s detecting unit!", "You have disconnected [src]'s detecting unit.") + + else if (istype(W, /obj/item/weapon/wirecutters)) + buildstage = 1 + playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) + var/obj/item/weapon/cable_coil/coil = new /obj/item/weapon/cable_coil() + coil.amount = 5 + coil.loc = user.loc + user << "You cut the wires from \the [src]" + update_icon() + if(1) + if(istype(W, /obj/item/weapon/cable_coil)) + var/obj/item/weapon/cable_coil/coil = W + if(coil.amount < 5) + user << "You need more cable for this!" + return + + coil.amount -= 5 + if(!coil.amount) + del(coil) + + buildstage = 2 + user << "You wire \the [src]!" + update_icon() + + else if(istype(W, /obj/item/weapon/crowbar)) + user << "You pry out the circuit!" + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + spawn(20) + var/obj/item/weapon/firealarm_electronics/circuit = new /obj/item/weapon/firealarm_electronics() + circuit.loc = user.loc + buildstage = 0 + update_icon() + if(0) + if(istype(W, /obj/item/weapon/firealarm_electronics)) + user << "You insert the circuit!" + del(W) + buildstage = 1 + update_icon() + + else if(istype(W, /obj/item/weapon/wrench)) + user << "You remove the fire alarm assembly from the wall!" + var/obj/item/firealarm_frame/frame = new /obj/item/firealarm_frame() + frame.loc = user.loc + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + del(src) + return + + src.alarm() return /obj/machinery/firealarm/process()//Note: this processing was mostly phased out due to other code, and only runs when needed if(stat & (NOPOWER|BROKEN)) return -// var/area/A = src.loc -// A = A.loc - -// if(A.fire) -// src.icon_state = "fire1" -// else -// src.icon_state = "fire0" - if(src.timing) if(src.time > 0) src.time = src.time - ((world.timeofday - last_process)/10) @@ -1069,16 +1274,19 @@ table tr:first-child th:first-child { border: none;} /obj/machinery/firealarm/power_change() if(powered(ENVIRON)) stat &= ~NOPOWER - icon_state = "fire0" + update_icon() else spawn(rand(0,15)) stat |= NOPOWER - icon_state = "firep" + update_icon() /obj/machinery/firealarm/attack_hand(mob/user as mob) if(user.stat || stat & (NOPOWER|BROKEN)) return + if (buildstage != 2) + return + user.set_machine(src) var/area/A = src.loc var/d1 @@ -1120,23 +1328,25 @@ table tr:first-child th:first-child { border: none;} ..() if (usr.stat || stat & (BROKEN|NOPOWER)) return + + if (buildstage != 2) + return + if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) usr.set_machine(src) if (href_list["reset"]) src.reset() - else - if (href_list["alarm"]) - src.alarm() - else - if (href_list["time"]) - src.timing = text2num(href_list["time"]) - last_process = world.timeofday - processing_objects.Add(src) - else - if (href_list["tp"]) - var/tp = text2num(href_list["tp"]) - src.time += tp - src.time = min(max(round(src.time), 0), 120) + else if (href_list["alarm"]) + src.alarm() + else if (href_list["time"]) + src.timing = text2num(href_list["time"]) + last_process = world.timeofday + processing_objects.Add(src) + else if (href_list["tp"]) + var/tp = text2num(href_list["tp"]) + src.time += tp + src.time = min(max(round(src.time), 0), 120) + src.updateUsrDialog() src.add_fingerprint(usr) @@ -1154,6 +1364,7 @@ table tr:first-child th:first-child { border: none;} return for(var/area/RA in A.related) RA.firereset() + update_icon() return /obj/machinery/firealarm/proc/alarm() @@ -1165,9 +1376,85 @@ table tr:first-child th:first-child { border: none;} return for(var/area/RA in A.related) RA.firealert() + update_icon() //playsound(src.loc, 'sound/ambience/signal.ogg', 75, 0) return +/obj/machinery/firealarm/New(loc, dir, building) + ..() + + if(loc) + src.loc = loc + + if(dir) + src.dir = dir + + if(building) + buildstage = 0 + wiresexposed = 1 + pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) + pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 + + update_icon() + +/* +FIRE ALARM CIRCUIT +Just a object used in constructing fire alarms +*/ +/obj/item/weapon/firealarm_electronics + name = "fire alarm electronics" + icon = 'icons/obj/doors/door_assembly.dmi' + icon_state = "door_electronics" + desc = "A circuit. It has a label on it, it says \"Can handle heat levels up to 40 degrees celsius!\"" + w_class = 2.0 + m_amt = 50 + g_amt = 50 + + +/* +FIRE ALARM ITEM +Handheld fire alarm frame, for placing on walls +Code shamelessly copied from apc_frame +*/ +/obj/item/firealarm_frame + name = "fire alarm frame" + desc = "Used for building Fire Alarms" + icon = 'icons/obj/monitors.dmi' + icon_state = "fire_bitem" + flags = FPRINT | TABLEPASS| CONDUCT + +/obj/item/firealarm_frame/attackby(obj/item/weapon/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/metal( get_turf(src.loc), 2 ) + del(src) + return + ..() + +/obj/item/firealarm_frame/proc/try_build(turf/on_wall) + if (get_dist(on_wall,usr)>1) + return + + var/ndir = get_dir(on_wall,usr) + if (!(ndir in cardinal)) + return + + var/turf/loc = get_turf_loc(usr) + var/area/A = loc.loc + if (!istype(loc, /turf/simulated/floor)) + usr << "\red Fire Alarm cannot be placed on this spot." + return + if (A.requires_power == 0 || A.name == "Space") + usr << "\red Fire Alarm cannot be placed in this area." + return + + if(gotwallitem(loc, ndir)) + usr << "\red There's already an item on this wall!" + return + + new /obj/machinery/firealarm(loc, ndir, 1) + + del(src) + /obj/machinery/partyalarm/attack_paw(mob/user as mob) return src.attack_hand(user) /obj/machinery/partyalarm/attack_hand(mob/user as mob) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 5d31104e11f..5af03b9219d 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -15,6 +15,8 @@ var/global/list/autolathe_recipes = list( \ new /obj/item/clothing/head/welding(), \ new /obj/item/weapon/stock_parts/console_screen(), \ new /obj/item/weapon/airlock_electronics(), \ + new /obj/item/weapon/airalarm_electronics(), \ + new /obj/item/weapon/firealarm_electronics(), \ new /obj/item/stack/sheet/metal(), \ new /obj/item/stack/sheet/glass(), \ new /obj/item/stack/sheet/rglass(), \ diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 69d6ebd82b1..111a9dfe73d 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -32,11 +32,14 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \ new/datum/stack_recipe("machine frame", /obj/machinery/constructable_frame/machine_frame, 5, time = 25, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1), \ null, \ - new/datum/stack_recipe("apc frame", /obj/item/apc_frame, 2), \ new/datum/stack_recipe("grenade casing", /obj/item/weapon/grenade/chem_grenade), \ new/datum/stack_recipe("light fixture frame", /obj/item/light_fixture_frame, 2), \ new/datum/stack_recipe("small light fixture frame", /obj/item/light_fixture_frame/small, 1), \ null, \ + new/datum/stack_recipe("apc frame", /obj/item/apc_frame, 2), \ + new/datum/stack_recipe("air alarm frame", /obj/item/alarm_frame, 2), \ + new/datum/stack_recipe("fire alarm frame", /obj/item/firealarm_frame, 2), \ + null, \ new/datum/stack_recipe("iron door", /obj/structure/mineral_door/iron, 20, one_per_turf = 1, on_floor = 1), \ ) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 5b4740a0665..0d53e2a51a6 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -245,6 +245,16 @@ AH.try_build(src) return + else if(istype(W,/obj/item/alarm_frame)) + var/obj/item/alarm_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/firealarm_frame)) + var/obj/item/firealarm_frame/AH = W + AH.try_build(src) + return + else if(istype(W,/obj/item/light_fixture_frame)) var/obj/item/light_fixture_frame/AH = W AH.try_build(src) diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index da596295113..5cd0a29d5c3 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -253,6 +253,15 @@ var/obj/item/apc_frame/AH = W AH.try_build(src) + else if( istype(W,/obj/item/alarm_frame) ) + var/obj/item/alarm_frame/AH = W + AH.try_build(src) + + else if(istype(W,/obj/item/firealarm_frame)) + var/obj/item/firealarm_frame/AH = W + AH.try_build(src) + return + else if(istype(W,/obj/item/light_fixture_frame)) var/obj/item/light_fixture_frame/AH = W AH.try_build(src) diff --git a/html/changelog.html b/html/changelog.html index 13974318b7f..6317264bd4c 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -48,6 +48,14 @@ Stuff which is in development and not yet visible to players or just code relate should be listed in the changelog upon commit tho. Thanks. --> +