/* FIRE ALARM */ #define FIRE_ALARM_FRAME 0 #define FIRE_ALARM_UNWIRED 1 #define FIRE_ALARM_READY 2 /obj/machinery/firealarm name = "fire alarm" desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever." icon = 'icons/obj/wallbumps/firealarm.dmi' icon_state = "firealarm_off" /// Whether or not the fire alarm will sound the alarm if its temperature rises above 200C var/detecting = TRUE var/working = TRUE var/time = 10.0 var/timing = 0.0 anchored = TRUE max_integrity = 250 integrity_failure = 100 armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 100, FIRE = 90, ACID = 30) idle_power_consumption = 2 active_power_consumption = 6 power_channel = PW_CHANNEL_ENVIRONMENT resistance_flags = FIRE_PROOF cares_about_temperature = TRUE light_power = LIGHTING_MINIMUM_POWER light_range = 7 light_color = "#ff3232" var/wiresexposed = FALSE var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone var/report_fire_alarms = TRUE // Should triggered fire alarms also trigger an actual alarm? var/show_alert_level = TRUE // Should fire alarms display the current alert level? var/last_time_pulled //used to prevent pulling spam by same persons /obj/machinery/firealarm/Initialize(mapload, direction, building) . = ..() if(building) buildstage = 0 wiresexposed = TRUE setDir(direction) set_pixel_offsets_from_dir(26, -26, 26, -26) var/area/our_area = get_area(src) LAZYADD(our_area.firealarms, src) if(is_station_contact(z)) RegisterSignal(SSsecurity_level, COMSIG_SECURITY_LEVEL_CHANGED, PROC_REF(on_security_level_update)) name = "fire alarm" set_light(1, LIGHTING_MINIMUM_POWER) //for emissives update_icon() /obj/machinery/firealarm/no_alarm report_fire_alarms = FALSE /obj/machinery/firealarm/syndicate report_fire_alarms = FALSE show_alert_level = FALSE /obj/machinery/firealarm/update_icon_state() if(wiresexposed) icon_state = "firealarm_b[buildstage]" return if(stat & BROKEN) icon_state = "firealarm_broken" return if(stat & NOPOWER) icon_state = "firealarm_off" return if(!detecting) icon_state = "firealarm_detect" return else icon_state = "firealarm_off" /obj/machinery/firealarm/update_overlays() . = ..() underlays.Cut() if(stat & (NOPOWER|BROKEN)) return if(is_station_contact(z) && show_alert_level) . += "overlay_[SSsecurity_level.get_current_level_as_text()]" underlays += emissive_appearance(icon, "firealarm_overlay_lightmask") if(!wiresexposed) underlays += emissive_appearance(icon, "firealarm_detect") var/area/area = get_area(src) if(area.fire) . += "firealarm_alarming" return /obj/machinery/firealarm/emag_act(mob/user) if(!emagged) emagged = TRUE if(user) user.visible_message(SPAN_WARNING("Sparks fly out of [src]!"), SPAN_NOTICE("You emag [src], disabling its thermal sensors.")) playsound(loc, 'sound/effects/sparks4.ogg', 50, TRUE) return TRUE /obj/machinery/firealarm/temperature_expose(exposed_temperature, exposed_volume) ..() if(!emagged && detecting && exposed_temperature > T0C + 200) alarm() // added check of detector status here /obj/machinery/firealarm/attack_ai(mob/user) add_hiddenprint(user) return attack_hand(user) /obj/machinery/firealarm/attack_ghost(mob/user) if(user.can_advanced_admin_interact()) toggle_alarm(user) /obj/machinery/firealarm/emp_act(severity) if(prob(50/severity)) alarm(rand(30/severity, 60/severity)) ..() /obj/machinery/firealarm/item_interaction(mob/living/user, obj/item/used, list/modifiers) add_fingerprint(user) if(!wiresexposed) return ..() if(buildstage == FIRE_ALARM_UNWIRED && istype(used, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/coil = used if(!coil.use(5)) to_chat(user, SPAN_WARNING("You need a total of five cables to wire [src]!")) return ITEM_INTERACT_COMPLETE buildstage = FIRE_ALARM_READY playsound(get_turf(src), used.usesound, 50, TRUE) to_chat(user, SPAN_NOTICE("You wire [src]!")) update_icon() return ITEM_INTERACT_COMPLETE if(buildstage == FIRE_ALARM_FRAME && istype(used, /obj/item/firealarm_electronics)) to_chat(user, SPAN_NOTICE("You insert the circuit!")) qdel(used) buildstage = FIRE_ALARM_UNWIRED update_icon() return ITEM_INTERACT_COMPLETE return ..() /obj/machinery/firealarm/crowbar_act(mob/user, obj/item/I) if(buildstage != FIRE_ALARM_UNWIRED) return . = TRUE if(!I.tool_use_check(user, 0)) return CROWBAR_ATTEMPT_PRY_CIRCUIT_MESSAGE if(!I.use_tool(src, user, 20, volume = I.tool_volume) || buildstage != FIRE_ALARM_UNWIRED) return new /obj/item/firealarm_electronics(drop_location()) buildstage = FIRE_ALARM_FRAME update_icon() CROWBAR_PRY_CIRCUIT_SUCCESS_MESSAGE /obj/machinery/firealarm/multitool_act(mob/user, obj/item/I) if(buildstage != FIRE_ALARM_READY) return . = TRUE if(!wiresexposed) to_chat(user, SPAN_WARNING("You need to expose the wires first!")) return if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return detecting = !detecting if(detecting) user.visible_message(SPAN_WARNING("[user] has reconnected [src]'s detecting unit!"), "You have reconnected [src]'s detecting unit.") else user.visible_message(SPAN_WARNING("[user] has disconnected [src]'s detecting unit!"), "You have disconnected [src]'s detecting unit.") /obj/machinery/firealarm/screwdriver_act(mob/user, obj/item/I) if(buildstage != FIRE_ALARM_READY) return . = TRUE if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return wiresexposed = !wiresexposed if(wiresexposed) SCREWDRIVER_OPEN_PANEL_MESSAGE else SCREWDRIVER_CLOSE_PANEL_MESSAGE update_icon() /obj/machinery/firealarm/wirecutter_act(mob/user, obj/item/I) if(buildstage != FIRE_ALARM_READY) return . = TRUE if(!wiresexposed) to_chat(user, SPAN_WARNING("You need to expose the wires first!")) return if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return update_icon() WIRECUTTER_SNIP_MESSAGE var/obj/item/stack/cable_coil/new_coil = new /obj/item/stack/cable_coil(drop_location()) new_coil.amount = 5 buildstage = FIRE_ALARM_UNWIRED /obj/machinery/firealarm/wrench_act(mob/user, obj/item/I) if(buildstage != FIRE_ALARM_FRAME) return . = TRUE if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return WRENCH_UNANCHOR_WALL_MESSAGE new /obj/item/mounted/frame/firealarm(get_turf(user)) qdel(src) /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 && !emagged) 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 & NODECONSTRUCT) && buildstage != 0) //can't break the electronics if there isn't any inside. stat |= BROKEN var/area/our_area = get_area(src) LAZYREMOVE(our_area.firealarms, src) update_icon() /obj/machinery/firealarm/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) new /obj/item/stack/sheet/metal(loc, 1) if(!(stat & BROKEN)) var/obj/item/I = new /obj/item/firealarm_electronics(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(stat & NOPOWER) set_light(0) return else if(SSsecurity_level.get_current_level_as_number() == SEC_LEVEL_EPSILON) set_light(2, 1, COLOR_WHITE) return else if(fire == !!light_power || fire == !!(light_power - 0.1)) return // do nothing if we're already active if(fire) set_light(l_power = 0.8) else set_light(l_power = LIGHTING_MINIMUM_POWER) /obj/machinery/firealarm/proc/update_fire_sound(fire) var/area/A = get_area(src) if(stat & NOPOWER) GLOB.firealarm_soundloop.stop(src, TRUE) else if(A.fire) GLOB.firealarm_soundloop.start(src) /obj/machinery/firealarm/proc/on_security_level_update(datum/source, previous_level_number, new_level_number) SIGNAL_HANDLER update_icon() update_fire_light() /obj/machinery/firealarm/power_change() if(!..()) return update_fire_light() update_icon() update_fire_sound() /obj/machinery/firealarm/attack_hand(mob/user) if(stat & (NOPOWER|BROKEN) || buildstage != 2) return 1 if(user.incapacitated()) return 1 if(fingerprintslast == user.ckey && world.time < last_time_pulled + 2 SECONDS) //no spamming >:C to_chat(user, SPAN_WARNING("[src] is still processing your earlier command.")) return toggle_alarm(user) /obj/machinery/firealarm/proc/toggle_alarm(mob/user) var/area/A = get_area(src) if(istype(A)) add_fingerprint(user) last_time_pulled = world.time if(A.fire) reset() else alarm() /obj/machinery/firealarm/examine(mob/user) . = ..() switch(buildstage) if(FIRE_ALARM_FRAME) . += SPAN_NOTICE("It's missing a circuit board and the bolts are exposed.") if(FIRE_ALARM_UNWIRED) . += SPAN_NOTICE("The control board needs wiring and can be pried out.") if(FIRE_ALARM_READY) if(wiresexposed) . += SPAN_NOTICE("The fire alarm's wires are exposed by the unscrewed panel.") . += SPAN_NOTICE("The detection circuitry can be turned [detecting ? "off" : "on"] by pulsing the board.") . += "It shows the alert level as: [capitalize(SSsecurity_level.get_current_level_as_text())]." /obj/machinery/firealarm/proc/reset() if(!working || !report_fire_alarms) return var/area/A = get_area(src) A.firereset(src) /obj/machinery/firealarm/proc/alarm() if(!working || !report_fire_alarms) return var/area/A = get_area(src) if(!A) return A.firealert(src) // Manually trigger alarms if the alarm isn't reported /obj/machinery/firealarm/Destroy() LAZYREMOVE(GLOB.firealarm_soundloop.output_atoms, src) var/area/our_area = get_area(src) LAZYREMOVE(our_area.firealarms, src) return ..() MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/firealarm, 32, 32) MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/firealarm/no_alarm, 32, 32) /* FIRE ALARM CIRCUIT Just a object used in constructing fire alarms */ /obj/item/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 = WEIGHT_CLASS_SMALL materials = list(MAT_METAL = 100, MAT_GLASS = 100) origin_tech = "engineering=2;programming=1" usesound = 'sound/items/deconstruct.ogg' #undef FIRE_ALARM_FRAME #undef FIRE_ALARM_UNWIRED #undef FIRE_ALARM_READY