diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm index c394d003d8..c93f1b2435 100644 --- a/code/__DEFINES/construction.dm +++ b/code/__DEFINES/construction.dm @@ -110,4 +110,7 @@ #define RCD_DECONSTRUCT 3 #define RCD_WINDOWGRILLE 4 #define RCD_MACHINE 8 -#define RCD_COMPUTER 16 \ No newline at end of file +#define RCD_COMPUTER 16 + +#define RCD_UPGRADE_FRAMES 1 +#define RCD_UPGRADE_SIMPLE_CIRCUITS 2 \ No newline at end of file diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 03c1bb3bc8..3e88223037 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1408,6 +1408,9 @@ /obj/machinery/door/airlock/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) switch(the_rcd.mode) if(RCD_DECONSTRUCT) + if(security_level != AIRLOCK_SECURITY_NONE && the_rcd.canRturf != TRUE) + to_chat(user, "[src]'s reinforcement needs to be removed first.") + return FALSE return list("mode" = RCD_DECONSTRUCT, "delay" = 50, "cost" = 32) return FALSE diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index dec41b0a59..39b6c8da1d 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -450,6 +450,21 @@ return return ..() +/obj/structure/firelock_frame/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if((constructionStep == CONSTRUCTION_NOCIRCUIT) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS)) + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + return FALSE + +/obj/structure/firelock_frame/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a firelock circuit and slot it into the assembly.") + constructionStep = CONSTRUCTION_GUTTED + update_icon() + return TRUE + return FALSE + /obj/structure/firelock_frame/heavy name = "heavy firelock frame" reinforced = TRUE diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 8f7fce8e3e..1ef3fc0a74 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -1,325 +1,340 @@ -#define FIREALARM_COOLDOWN 67 // Chosen fairly arbitrarily, it is the length of the audio in FireAlarm.ogg. The actual track length is 7 seconds 8ms but but the audio stops at 6s 700ms - -/obj/item/electronics/firealarm - name = "fire alarm electronics" - desc = "A fire alarm circuit. Can handle heat levels up to 40 degrees celsius." - -/obj/item/wallframe/firealarm - name = "fire alarm frame" - desc = "Used for building fire alarms." - icon = 'icons/obj/monitors.dmi' - icon_state = "fire_bitem" - result_path = /obj/machinery/firealarm - -/obj/machinery/firealarm - name = "fire alarm" - desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever." - icon = 'icons/obj/monitors.dmi' - icon_state = "fire0" - max_integrity = 250 - integrity_failure = 100 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30) - use_power = IDLE_POWER_USE - idle_power_usage = 2 - active_power_usage = 6 - power_channel = ENVIRON - resistance_flags = FIRE_PROOF - - light_power = 0 - light_range = 7 - light_color = "#ff3232" - - var/detecting = 1 - var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone - var/last_alarm = 0 - var/area/myarea = null - -/obj/machinery/firealarm/Initialize(mapload, dir, building) - . = ..() - if(dir) - src.setDir(dir) - if(building) - buildstage = 0 - panel_open = TRUE - pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) - pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 - update_icon() - myarea = get_area(src) - LAZYADD(myarea.firealarms, src) - -/obj/machinery/firealarm/Destroy() - LAZYREMOVE(myarea.firealarms, src) - return ..() - -/obj/machinery/firealarm/power_change() - ..() - update_icon() - -/obj/machinery/firealarm/update_icon() - cut_overlays() - SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) - - if(panel_open) - icon_state = "fire_b[buildstage]" - return - - if(stat & BROKEN) - icon_state = "firex" - return - - icon_state = "fire0" - - if(stat & NOPOWER) - return - - add_overlay("fire_overlay") - - if(is_station_level(z)) - add_overlay("fire_[GLOB.security_level]") - SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) - else - add_overlay("fire_[SEC_LEVEL_GREEN]") - SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) - - var/area/A = src.loc - A = A.loc - - if(!detecting || !A.fire) - add_overlay("fire_off") - SSvis_overlays.add_vis_overlay(src, icon, "fire_off", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) - else if(obj_flags & EMAGGED) - add_overlay("fire_emagged") - SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) - else - add_overlay("fire_on") - SSvis_overlays.add_vis_overlay(src, icon, "fire_on", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) - -/obj/machinery/firealarm/emp_act(severity) - . = ..() - - if (. & EMP_PROTECT_SELF) - return - - if(prob(50 / severity)) - alarm() - -/obj/machinery/firealarm/emag_act(mob/user) - . = ..() - if(obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - update_icon() - if(user) - user.visible_message("Sparks fly out of [src]!", - "You emag [src], disabling its thermal sensors.") - playsound(src, "sparks", 50, 1) - return TRUE - -/obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume) - if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !(obj_flags & EMAGGED) && detecting && !stat) - alarm() - ..() - -/obj/machinery/firealarm/proc/alarm(mob/user) - if(!is_operational() || (last_alarm+FIREALARM_COOLDOWN > world.time)) - return - last_alarm = world.time - var/area/A = get_area(src) - A.firealert(src) - playsound(loc, 'goon/sound/machinery/FireAlarm.ogg', 75) - if(user) - log_game("[user] triggered a fire alarm at [COORD(src)]") - -/obj/machinery/firealarm/proc/reset(mob/user) - if(!is_operational()) - return - var/area/A = get_area(src) - A.firereset(src) - if(user) - log_game("[user] reset a fire alarm at [COORD(src)]") - -/obj/machinery/firealarm/attack_hand(mob/user) - if(buildstage != 2) - return ..() - add_fingerprint(user) - var/area/A = get_area(src) - if(A.fire) - reset(user) - else - alarm(user) - -/obj/machinery/firealarm/attack_ai(mob/user) - return attack_hand(user) - -/obj/machinery/firealarm/attack_robot(mob/user) - return attack_hand(user) - -/obj/machinery/firealarm/attackby(obj/item/W, mob/user, params) - add_fingerprint(user) - - if(istype(W, /obj/item/screwdriver) && buildstage == 2) - W.play_tool_sound(src) - panel_open = !panel_open - to_chat(user, "The wires have been [panel_open ? "exposed" : "unexposed"].") - update_icon() - return - - if(panel_open) - - if(istype(W, /obj/item/weldingtool) && user.a_intent == INTENT_HELP) - if(obj_integrity < max_integrity) - if(!W.tool_start_check(user, amount=0)) - return - - to_chat(user, "You begin repairing [src]...") - if(W.use_tool(src, user, 40, volume=50)) - obj_integrity = max_integrity - to_chat(user, "You repair [src].") - else - to_chat(user, "[src] is already in good condition!") - return - - switch(buildstage) - if(2) - if(istype(W, /obj/item/multitool)) - detecting = !detecting - if (src.detecting) - user.visible_message("[user] has reconnected [src]'s detecting unit!", "You reconnect [src]'s detecting unit.") - else - user.visible_message("[user] has disconnected [src]'s detecting unit!", "You disconnect [src]'s detecting unit.") - return - - else if (istype(W, /obj/item/wirecutters)) - buildstage = 1 - W.play_tool_sound(src) - new /obj/item/stack/cable_coil(user.loc, 5) - to_chat(user, "You cut the wires from \the [src].") - update_icon() - return - else if(W.force) //hit and turn it on - ..() - var/area/A = get_area(src) - if(!A.fire) - alarm() - return - if(1) - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W - if(coil.get_amount() < 5) - to_chat(user, "You need more cable for this!") - else - coil.use(5) - buildstage = 2 - to_chat(user, "You wire \the [src].") - update_icon() - return - - else if(istype(W, /obj/item/crowbar)) - user.visible_message("[user.name] removes the electronics from [src.name].", \ - "You start prying out the circuit...") - if(W.use_tool(src, user, 20, volume=50)) - if(buildstage == 1) - if(stat & BROKEN) - to_chat(user, "You remove the destroyed circuit.") - stat &= ~BROKEN - else - to_chat(user, "You pry out the circuit.") - new /obj/item/electronics/firealarm(user.loc) - buildstage = 0 - update_icon() - return - if(0) - if(istype(W, /obj/item/electronics/firealarm)) - to_chat(user, "You insert the circuit.") - qdel(W) - buildstage = 1 - update_icon() - return - - else if(istype(W, /obj/item/electroadaptive_pseudocircuit)) - var/obj/item/electroadaptive_pseudocircuit/P = W - if(!P.adapt_circuit(user, 15)) - return - user.visible_message("[user] fabricates a circuit and places it into [src].", \ - "You adapt a fire alarm circuit and slot it into the assembly.") - buildstage = 1 - update_icon() - return - - else if(istype(W, /obj/item/wrench)) - user.visible_message("[user] removes the fire alarm assembly from the wall.", \ - "You remove the fire alarm assembly from the wall.") - var/obj/item/wallframe/firealarm/frame = new /obj/item/wallframe/firealarm() - frame.forceMove(user.drop_location()) - W.play_tool_sound(src) - qdel(src) - return - return ..() - -/obj/machinery/firealarm/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) - . = ..() - if(.) //damage received - if(obj_integrity > 0 && !(stat & BROKEN) && buildstage != 0) - if(prob(33)) - alarm() - -/obj/machinery/firealarm/singularity_pull(S, current_size) - if (current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects, the fire alarm experiences integrity failure - deconstruct() - ..() - -/obj/machinery/firealarm/obj_break(damage_flag) - if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1) && buildstage != 0) //can't break the electronics if there isn't any inside. - LAZYREMOVE(myarea.firealarms, src) - stat |= BROKEN - update_icon() - -/obj/machinery/firealarm/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - new /obj/item/stack/sheet/metal(loc, 1) - if(!(stat & BROKEN)) - var/obj/item/I = new /obj/item/electronics/firealarm(loc) - if(!disassembled) - I.obj_integrity = I.max_integrity * 0.5 - new /obj/item/stack/cable_coil(loc, 3) - qdel(src) - -/obj/machinery/firealarm/proc/update_fire_light(fire) - if(fire == !!light_power) - return // do nothing if we're already active - if(fire) - set_light(l_power = 0.8) - else - set_light(l_power = 0) - -/* - * Return of Party button - */ - -/area - var/party = FALSE - -/obj/machinery/firealarm/partyalarm - name = "\improper PARTY BUTTON" - desc = "Cuban Pete is in the house!" - var/static/party_overlay - -/obj/machinery/firealarm/partyalarm/reset() - if (stat & (NOPOWER|BROKEN)) - return - var/area/A = get_area(src) - if (!A || !A.party) - return - A.party = FALSE - A.cut_overlay(party_overlay) - -/obj/machinery/firealarm/partyalarm/alarm() - if (stat & (NOPOWER|BROKEN)) - return - var/area/A = get_area(src) - if (!A || A.party || A.name == "Space") - return - A.party = TRUE - if (!party_overlay) - party_overlay = iconstate2appearance('icons/turf/areas.dmi', "party") - A.add_overlay(party_overlay) +#define FIREALARM_COOLDOWN 67 // Chosen fairly arbitrarily, it is the length of the audio in FireAlarm.ogg. The actual track length is 7 seconds 8ms but but the audio stops at 6s 700ms + +/obj/item/electronics/firealarm + name = "fire alarm electronics" + desc = "A fire alarm circuit. Can handle heat levels up to 40 degrees celsius." + +/obj/item/wallframe/firealarm + name = "fire alarm frame" + desc = "Used for building fire alarms." + icon = 'icons/obj/monitors.dmi' + icon_state = "fire_bitem" + result_path = /obj/machinery/firealarm + +/obj/machinery/firealarm + name = "fire alarm" + desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever." + icon = 'icons/obj/monitors.dmi' + icon_state = "fire0" + max_integrity = 250 + integrity_failure = 100 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30) + use_power = IDLE_POWER_USE + idle_power_usage = 2 + active_power_usage = 6 + power_channel = ENVIRON + resistance_flags = FIRE_PROOF + + light_power = 0 + light_range = 7 + light_color = "#ff3232" + + var/detecting = 1 + var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone + var/last_alarm = 0 + var/area/myarea = null + +/obj/machinery/firealarm/Initialize(mapload, dir, building) + . = ..() + if(dir) + src.setDir(dir) + if(building) + buildstage = 0 + panel_open = TRUE + pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) + pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 + update_icon() + myarea = get_area(src) + LAZYADD(myarea.firealarms, src) + +/obj/machinery/firealarm/Destroy() + LAZYREMOVE(myarea.firealarms, src) + return ..() + +/obj/machinery/firealarm/power_change() + ..() + update_icon() + +/obj/machinery/firealarm/update_icon() + cut_overlays() + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) + + if(panel_open) + icon_state = "fire_b[buildstage]" + return + + if(stat & BROKEN) + icon_state = "firex" + return + + icon_state = "fire0" + + if(stat & NOPOWER) + return + + add_overlay("fire_overlay") + + if(is_station_level(z)) + add_overlay("fire_[GLOB.security_level]") + SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) + else + add_overlay("fire_[SEC_LEVEL_GREEN]") + SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) + + var/area/A = src.loc + A = A.loc + + if(!detecting || !A.fire) + add_overlay("fire_off") + SSvis_overlays.add_vis_overlay(src, icon, "fire_off", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) + else if(obj_flags & EMAGGED) + add_overlay("fire_emagged") + SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) + else + add_overlay("fire_on") + SSvis_overlays.add_vis_overlay(src, icon, "fire_on", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) + +/obj/machinery/firealarm/emp_act(severity) + . = ..() + + if (. & EMP_PROTECT_SELF) + return + + if(prob(50 / severity)) + alarm() + +/obj/machinery/firealarm/emag_act(mob/user) + . = ..() + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + update_icon() + if(user) + user.visible_message("Sparks fly out of [src]!", + "You emag [src], disabling its thermal sensors.") + playsound(src, "sparks", 50, 1) + return TRUE + +/obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume) + if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !(obj_flags & EMAGGED) && detecting && !stat) + alarm() + ..() + +/obj/machinery/firealarm/proc/alarm(mob/user) + if(!is_operational() || (last_alarm+FIREALARM_COOLDOWN > world.time)) + return + last_alarm = world.time + var/area/A = get_area(src) + A.firealert(src) + playsound(loc, 'goon/sound/machinery/FireAlarm.ogg', 75) + if(user) + log_game("[user] triggered a fire alarm at [COORD(src)]") + +/obj/machinery/firealarm/proc/reset(mob/user) + if(!is_operational()) + return + var/area/A = get_area(src) + A.firereset(src) + if(user) + log_game("[user] reset a fire alarm at [COORD(src)]") + +/obj/machinery/firealarm/attack_hand(mob/user) + if(buildstage != 2) + return ..() + add_fingerprint(user) + var/area/A = get_area(src) + if(A.fire) + reset(user) + else + alarm(user) + +/obj/machinery/firealarm/attack_ai(mob/user) + return attack_hand(user) + +/obj/machinery/firealarm/attack_robot(mob/user) + return attack_hand(user) + +/obj/machinery/firealarm/attackby(obj/item/W, mob/user, params) + add_fingerprint(user) + + if(istype(W, /obj/item/screwdriver) && buildstage == 2) + W.play_tool_sound(src) + panel_open = !panel_open + to_chat(user, "The wires have been [panel_open ? "exposed" : "unexposed"].") + update_icon() + return + + if(panel_open) + + if(istype(W, /obj/item/weldingtool) && user.a_intent == INTENT_HELP) + if(obj_integrity < max_integrity) + if(!W.tool_start_check(user, amount=0)) + return + + to_chat(user, "You begin repairing [src]...") + if(W.use_tool(src, user, 40, volume=50)) + obj_integrity = max_integrity + to_chat(user, "You repair [src].") + else + to_chat(user, "[src] is already in good condition!") + return + + switch(buildstage) + if(2) + if(istype(W, /obj/item/multitool)) + detecting = !detecting + if (src.detecting) + user.visible_message("[user] has reconnected [src]'s detecting unit!", "You reconnect [src]'s detecting unit.") + else + user.visible_message("[user] has disconnected [src]'s detecting unit!", "You disconnect [src]'s detecting unit.") + return + + else if (istype(W, /obj/item/wirecutters)) + buildstage = 1 + W.play_tool_sound(src) + new /obj/item/stack/cable_coil(user.loc, 5) + to_chat(user, "You cut the wires from \the [src].") + update_icon() + return + else if(W.force) //hit and turn it on + ..() + var/area/A = get_area(src) + if(!A.fire) + alarm() + return + if(1) + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = W + if(coil.get_amount() < 5) + to_chat(user, "You need more cable for this!") + else + coil.use(5) + buildstage = 2 + to_chat(user, "You wire \the [src].") + update_icon() + return + + else if(istype(W, /obj/item/crowbar)) + user.visible_message("[user.name] removes the electronics from [src.name].", \ + "You start prying out the circuit...") + if(W.use_tool(src, user, 20, volume=50)) + if(buildstage == 1) + if(stat & BROKEN) + to_chat(user, "You remove the destroyed circuit.") + stat &= ~BROKEN + else + to_chat(user, "You pry out the circuit.") + new /obj/item/electronics/firealarm(user.loc) + buildstage = 0 + update_icon() + return + if(0) + if(istype(W, /obj/item/electronics/firealarm)) + to_chat(user, "You insert the circuit.") + qdel(W) + buildstage = 1 + update_icon() + return + + else if(istype(W, /obj/item/electroadaptive_pseudocircuit)) + var/obj/item/electroadaptive_pseudocircuit/P = W + if(!P.adapt_circuit(user, 15)) + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a fire alarm circuit and slot it into the assembly.") + buildstage = 1 + update_icon() + return + + else if(istype(W, /obj/item/wrench)) + user.visible_message("[user] removes the fire alarm assembly from the wall.", \ + "You remove the fire alarm assembly from the wall.") + var/obj/item/wallframe/firealarm/frame = new /obj/item/wallframe/firealarm() + frame.forceMove(user.drop_location()) + W.play_tool_sound(src) + qdel(src) + return + return ..() + +/obj/machinery/firealarm/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if((buildstage == 0) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS)) + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + return FALSE + +/obj/machinery/firealarm/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a fire alarm circuit and slot it into the assembly.") + buildstage = 1 + update_icon() + return TRUE + return FALSE + +/obj/machinery/firealarm/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) + . = ..() + if(.) //damage received + if(obj_integrity > 0 && !(stat & BROKEN) && buildstage != 0) + if(prob(33)) + alarm() + +/obj/machinery/firealarm/singularity_pull(S, current_size) + if (current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects, the fire alarm experiences integrity failure + deconstruct() + ..() + +/obj/machinery/firealarm/obj_break(damage_flag) + if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1) && buildstage != 0) //can't break the electronics if there isn't any inside. + LAZYREMOVE(myarea.firealarms, src) + stat |= BROKEN + update_icon() + +/obj/machinery/firealarm/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + new /obj/item/stack/sheet/metal(loc, 1) + if(!(stat & BROKEN)) + var/obj/item/I = new /obj/item/electronics/firealarm(loc) + if(!disassembled) + I.obj_integrity = I.max_integrity * 0.5 + new /obj/item/stack/cable_coil(loc, 3) + qdel(src) + +/obj/machinery/firealarm/proc/update_fire_light(fire) + if(fire == !!light_power) + return // do nothing if we're already active + if(fire) + set_light(l_power = 0.8) + else + set_light(l_power = 0) + +/* + * Return of Party button + */ + +/area + var/party = FALSE + +/obj/machinery/firealarm/partyalarm + name = "\improper PARTY BUTTON" + desc = "Cuban Pete is in the house!" + var/static/party_overlay + +/obj/machinery/firealarm/partyalarm/reset() + if (stat & (NOPOWER|BROKEN)) + return + var/area/A = get_area(src) + if (!A || !A.party) + return + A.party = FALSE + A.cut_overlay(party_overlay) + +/obj/machinery/firealarm/partyalarm/alarm() + if (stat & (NOPOWER|BROKEN)) + return + var/area/A = get_area(src) + if (!A || A.party || A.name == "Space") + return + A.party = TRUE + if (!party_overlay) + party_overlay = iconstate2appearance('icons/turf/areas.dmi', "party") + A.add_overlay(party_overlay) diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 1b85a41f7c..cdf6b77a76 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -452,4 +452,45 @@ icon_state = "slugboom" randomdir = FALSE duration = 30 - pixel_x = -24 \ No newline at end of file + pixel_x = -24 + +/obj/effect/constructing_effect + icon = 'icons/effects/effects_rcd.dmi' + icon_state = "" + layer = ABOVE_ALL_MOB_LAYER + anchored = TRUE + var/status = 0 + var/delay = 0 + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + +/obj/effect/constructing_effect/Initialize(mapload, rcd_delay, rcd_status) + . = ..() + status = rcd_status + delay = rcd_delay + if (status == RCD_DECONSTRUCT) + addtimer(CALLBACK(src, /atom/.proc/update_icon), 11) + delay -= 11 + icon_state = "rcd_end_reverse" + else + update_icon() + +/obj/effect/constructing_effect/update_icon() + icon_state = "rcd" + if (delay < 10) + icon_state += "_shortest" + else if (delay < 20) + icon_state += "_shorter" + else if (delay < 37) + icon_state += "_short" + if (status == RCD_DECONSTRUCT) + icon_state += "_reverse" + +/obj/effect/constructing_effect/proc/end_animation() + if (status == RCD_DECONSTRUCT) + qdel(src) + else + icon_state = "rcd_end" + addtimer(CALLBACK(src, .proc/end), 15) + +/obj/effect/constructing_effect/proc/end() + qdel(src) \ No newline at end of file diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 24c241aabc..e151450d8a 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -47,7 +47,11 @@ RLD /obj/item/construction/examine(mob/user) . = ..() - . += "\A [src]. It currently holds [matter]/[max_matter] matter-units." + . += "It currently holds [matter]/[max_matter] matter-units." + if(upgrade & RCD_UPGRADE_FRAMES) + . += "It contains the design for machine frames, computer frames and deconstruction." + if(upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS) + . += "It contains the design for firelock, air alarm, fire alarm, apc circuits and crap power cells." /obj/item/construction/Destroy() QDEL_NULL(spark_system) @@ -85,9 +89,11 @@ RLD to_chat(user, "[src] now holds [matter]/[max_matter] matter-units.") else if(istype(W, /obj/item/rcd_upgrade)) to_chat(user, "You upgrade the RCD with the [W]!") - upgrade = TRUE - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - qdel(W) + var/obj/item/rcd_upgrade/rcd_up = W + if(!(upgrade & rcd_up.upgrade)) + upgrade |= rcd_up.upgrade + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + qdel(W) else return ..() update_icon() //ensures that ammo counters (if present) get updated @@ -116,10 +122,10 @@ RLD if(matter < amount) if(user) to_chat(user, no_ammo_message) - return 0 + return FALSE matter -= amount update_icon() - return 1 + return TRUE /obj/item/construction/proc/checkResource(amount, mob/user) . = matter >= amount @@ -439,18 +445,22 @@ RLD var/list/rcd_results = A.rcd_vals(user, src) if(!rcd_results) return FALSE + var/delay = rcd_results["delay"] * delay_mod + var/obj/effect/constructing_effect/rcd_effect = new(get_turf(A), delay, src.mode) var/turf/the_turf = get_turf(A) var/turf_coords = "[COORD(the_turf)]" investigate_log("[user] is attempting to use [src] on [A] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD) - if(do_after(user, rcd_results["delay"] * delay_mod, target = A)) + if(do_after(user, delay, target = A)) if(checkResource(rcd_results["cost"], user)) var/atom/cached = A if(A.rcd_act(user, src, rcd_results["mode"])) + rcd_effect.end_animation() useResource(rcd_results["cost"], user) activate() investigate_log("[user] used [src] on [cached] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD) playsound(src, 'sound/machines/click.ogg', 50, 1) return TRUE + qdel(rcd_effect) /obj/item/construction/rcd/Initialize() . = ..() @@ -467,7 +477,7 @@ RLD "Grilles & Windows" = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow"), "Floors & Walls" = image(icon = 'icons/mob/radial.dmi', icon_state = "wallfloor") ) - if(upgrade) + if(upgrade & RCD_UPGRADE_FRAMES) choices += list( "Deconstruct" = image(icon= 'icons/mob/radial.dmi', icon_state = "delete"), "Machine Frames" = image(icon = 'icons/mob/radial.dmi', icon_state = "machine"), @@ -593,6 +603,7 @@ RLD energyfactor = 66 /obj/item/construction/rcd/loaded + materials = list(MAT_METAL=48000, MAT_GLASS=32000) matter = 160 /obj/item/construction/rcd/loaded/upgraded @@ -825,9 +836,18 @@ RLD /obj/item/rcd_upgrade name = "RCD advanced design disk" - desc = "It contains the design for machine frames, computer frames, and deconstruction." + desc = "It seems to be empty." icon = 'icons/obj/module.dmi' icon_state = "datadisk3" + var/upgrade + +/obj/item/rcd_upgrade/frames + desc = "It contains the design for machine frames, computer frames and deconstruction." + upgrade = RCD_UPGRADE_FRAMES + +/obj/item/rcd_upgrade/simple_circuits + desc = "It contains the design for firelock, air alarm, fire alarm, apc circuits and crap power cells." + upgrade = RCD_UPGRADE_SIMPLE_CIRCUITS #undef GLOW_MODE #undef LIGHT_MODE diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index f9153ff8bf..720490942a 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -263,7 +263,7 @@ A.autoclose = TRUE return TRUE if(RCD_DECONSTRUCT) - if(ScrapeAway(flags = CHANGETURF_INHERIT_AIR) == src) + if(!ScrapeAway(flags = CHANGETURF_INHERIT_AIR)) return FALSE to_chat(user, "You deconstruct [src].") return TRUE diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index cbbfc05f39..e49368016b 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -822,6 +822,21 @@ return ..() +/obj/machinery/airalarm/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if((buildstage == 0) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS)) + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + return FALSE + +/obj/machinery/airalarm/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt an air alarm circuit and slot it into the assembly.") + buildstage = 1 + update_icon() + return TRUE + return FALSE + /obj/machinery/airalarm/AltClick(mob/user) . = ..() if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 2652026a11..0ad2983b91 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -701,6 +701,52 @@ else return ..() +/obj/machinery/power/apc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if(the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS) + if(!has_electronics) + if(stat & BROKEN) + to_chat(user, "[src]'s frame is too damaged to support a circuit.") + return FALSE + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + else if(!cell) + if(stat & MAINT) + to_chat(user, "There's no connector for a power cell.") + return FALSE + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 50, "cost" = 10) //16 for a wall + else + to_chat(user, "[src] has both electronics and a cell.") + return FALSE + return FALSE + +/obj/machinery/power/apc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + if(!has_electronics) + if(stat & BROKEN) + to_chat(user, "[src]'s frame is too damaged to support a circuit.") + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a power control board and click it into place in [src]'s guts.") + has_electronics = TRUE + locked = TRUE + return TRUE + else if(!cell) + if(stat & MAINT) + to_chat(user, "There's no connector for a power cell.") + return FALSE + var/obj/item/stock_parts/cell/crap/empty/C = new(src) + C.forceMove(src) + cell = C + chargecount = 0 + user.visible_message("[user] fabricates a weak power cell and places it into [src].", \ + "Your [the_rcd.name] whirrs with strain as you create a weak power cell and place it into [src]!") + update_icon() + return TRUE + else + to_chat(user, "[src] has both electronics and a cell.") + return FALSE + return FALSE + /obj/machinery/power/apc/AltClick(mob/user) . = ..() if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 302ac345b7..b18db566af 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -389,13 +389,23 @@ ////////////Tools////////////// /////////////////////////////// -/datum/design/rcd_upgrade - name = "Advanced RCD designs upgrade" +/datum/design/rcd_upgrade/frames + name = "RCD frames designs upgrade" desc = "Adds the computer frame and machine frame to the RCD." - id = "rcd_upgrade" + id = "rcd_upgrade_frames" build_type = PROTOLATHE materials = list(MAT_METAL = 5000, MAT_GLASS = 2500, MAT_SILVER = 1500, MAT_TITANIUM = 2000) - build_path = /obj/item/rcd_upgrade + build_path = /obj/item/rcd_upgrade/frames + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/rcd_upgrade/simple_circuits + name = "RCD simple circuits designs upgrade" + desc = "Adds the simple circuits to the RCD." + id = "rcd_upgrade_simple_circuits" + build_type = PROTOLATHE + materials = list(MAT_METAL = 5000, MAT_GLASS = 2500, MAT_SILVER = 1500, MAT_TITANIUM = 2000) + build_path = /obj/item/rcd_upgrade/simple_circuits category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING @@ -429,6 +439,26 @@ category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING +/datum/design/rcd_loaded + name = "Rapid Construction Device" + desc = "A tool that can construct and deconstruct walls, airlocks and floors on the fly." + id = "rcd_loaded" + build_type = PROTOLATHE + materials = list(MAT_METAL = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT) // costs more than what it did in the autolathe, this one comes loaded. + build_path = /obj/item/construction/rcd/loaded + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/rpd + name = "Rapid Pipe Dispenser" + desc = "A tool that can construct and deconstruct pipes on the fly." + id = "rpd" + build_type = PROTOLATHE + materials = list(MAT_METAL = 75000, MAT_GLASS = 37500) + build_path = /obj/item/pipe_dispenser + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + /datum/design/alienwrench name = "Alien Wrench" desc = "An advanced wrench obtained through Abductor technology." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index f1151d6988..b6a1105cf4 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -200,7 +200,7 @@ display_name = "Advanced Engineering" description = "Pushing the boundaries of physics, one chainsaw-fist at a time." prereq_ids = list("engineering", "emp_basic") - design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade") + design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask" , "rcd_loaded", "rpd", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade_frames", "rcd_upgrade_simple_circuits") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) export_price = 5000 diff --git a/icons/effects/effects_rcd.dmi b/icons/effects/effects_rcd.dmi new file mode 100644 index 0000000000..efb13bfb11 Binary files /dev/null and b/icons/effects/effects_rcd.dmi differ