mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-24 20:47:43 +01:00
Merge pull request #6943 from VOREStation/upstream-merge-6820
[MIRROR] Emergency lighting
This commit is contained in:
@@ -105,6 +105,7 @@
|
||||
var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment
|
||||
var/longtermpower = 10
|
||||
var/datum/wires/apc/wires = null
|
||||
var/emergency_lights = FALSE
|
||||
var/update_state = -1
|
||||
var/update_overlay = -1
|
||||
var/is_critical = 0
|
||||
@@ -795,6 +796,7 @@
|
||||
"gridCheck" = grid_check,
|
||||
"coverLocked" = coverlocked,
|
||||
"siliconUser" = issilicon(user) || isobserver(user), //I add observer here so admins can have more control, even if it makes 'siliconUser' seem inaccurate.
|
||||
"emergencyLights" = !emergency_lights,
|
||||
|
||||
"powerChannels" = list(
|
||||
list(
|
||||
@@ -835,7 +837,7 @@
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "apc.tmpl", "[area.name] - APC", 520, data["siliconUser"] ? 465 : 440)
|
||||
ui = new(user, src, ui_key, "apc.tmpl", "[area.name] - APC", 520, data["siliconUser"] ? 490 : 465)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
@@ -932,6 +934,14 @@
|
||||
update_icon()
|
||||
update()
|
||||
|
||||
else if (href_list["emergency_lighting"])
|
||||
emergency_lights = !emergency_lights
|
||||
for(var/obj/machinery/light/L in area)
|
||||
if(!initial(L.no_emergency)) //If there was an override set on creation, keep that override
|
||||
L.no_emergency = emergency_lights
|
||||
INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE)
|
||||
CHECK_TICK
|
||||
|
||||
else if (href_list["breaker"])
|
||||
toggle_breaker()
|
||||
|
||||
|
||||
@@ -132,3 +132,16 @@
|
||||
overlays.Cut()
|
||||
target.nutrition += amount
|
||||
user.custom_emote(message = "connects \the [src] to [user == target ? "their" : "[target]'s"] charging port, expending it.")
|
||||
|
||||
/obj/item/weapon/cell/emergency_light
|
||||
name = "miniature power cell"
|
||||
desc = "A tiny power cell with a very low power capacity. Used in light fixtures to power them in the event of an outage."
|
||||
maxcharge = 120 //Emergency lights use 0.2 W per tick, meaning ~10 minutes of emergency power from a cell
|
||||
matter = list("glass" = 20)
|
||||
w_class = ITEMSIZE_TINY
|
||||
|
||||
/obj/item/weapon/cell/emergency_light/Initialize()
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
if(!A.lightswitch || !A.light_power)
|
||||
charge = 0 //For naturally depowered areas, we start with no power
|
||||
@@ -10,6 +10,7 @@
|
||||
#define LIGHT_BURNED 3
|
||||
#define LIGHT_BULB_TEMPERATURE 400 //K - used value for a 60W bulb
|
||||
#define LIGHTING_POWER_FACTOR 2 //5W per luminosity * range //VOREStation Edit: why the fuck are lights eating so much power, 2W per thing
|
||||
#define LIGHT_EMERGENCY_POWER_USE 0.2 //How much power emergency lights will consume per tick
|
||||
|
||||
var/global/list/light_type_cache = list()
|
||||
/proc/get_light_type_instance(var/light_type)
|
||||
@@ -29,6 +30,10 @@ var/global/list/light_type_cache = list()
|
||||
var/stage = 1
|
||||
var/fixture_type = /obj/machinery/light
|
||||
var/sheets_refunded = 2
|
||||
var/obj/machinery/light/newlight = null
|
||||
var/obj/item/weapon/cell/cell = null
|
||||
|
||||
var/cell_connectors = TRUE
|
||||
|
||||
/obj/machinery/light_construct/New(var/atom/newloc, var/newdir, var/building = 0, var/datum/frame/frame_types/frame_type, var/obj/machinery/light/fixture = null)
|
||||
..(newloc)
|
||||
@@ -61,9 +66,44 @@ var/global/list/light_type_cache = list()
|
||||
to_chat(user, "It's wired.")
|
||||
if(3)
|
||||
to_chat(user, "The casing is closed.")
|
||||
if(cell_connectors)
|
||||
if(cell)
|
||||
to_chat(user, "You see [cell] inside the casing.")
|
||||
else
|
||||
to_chat(user, "The casing has no power cell for backup power.")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>This casing doesn't support power cells for backup power.</span>")
|
||||
|
||||
/obj/machinery/light_construct/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return . // obj/machinery/attack_hand returns 1 if user can't use the machine
|
||||
if(cell)
|
||||
user.visible_message("[user] removes [cell] from [src]!","<span class='notice'>You remove [cell].</span>")
|
||||
user.put_in_hands(cell)
|
||||
cell.update_icon()
|
||||
cell = null
|
||||
|
||||
/obj/machinery/light_construct/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
if(istype(W, /obj/item/weapon/cell/emergency_light))
|
||||
if(!cell_connectors)
|
||||
to_chat(user, "<span class='warning'>This [name] can't support a power cell!</span>")
|
||||
return
|
||||
if(!user.unEquip(W))
|
||||
to_chat(user, "<span class='warning'>[W] is stuck to your hand!</span>")
|
||||
return
|
||||
if(cell)
|
||||
to_chat(user, "<span class='warning'>There is a power cell already installed!</span>")
|
||||
else if(user.drop_from_inventory(W))
|
||||
user.visible_message("<span class='notice'>[user] hooks up [W] to [src].</span>", \
|
||||
"<span class='notice'>You add [W] to [src].</span>")
|
||||
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
|
||||
W.forceMove(src)
|
||||
cell = W
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
if (W.is_wrench())
|
||||
if (src.stage == 1)
|
||||
playsound(src, W.usesound, 75, 1)
|
||||
@@ -114,6 +154,10 @@ var/global/list/light_type_cache = list()
|
||||
var/obj/machinery/light/newlight = new fixture_type(src.loc, src)
|
||||
newlight.set_dir(src.dir)
|
||||
src.transfer_fingerprints_to(newlight)
|
||||
if(cell)
|
||||
newlight.cell = cell
|
||||
cell.forceMove(newlight)
|
||||
cell = null
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
@@ -192,6 +236,16 @@ var/global/list/light_type_cache = list()
|
||||
|
||||
var/auto_flicker = FALSE // If true, will constantly flicker, so long as someone is around to see it (otherwise its a waste of CPU).
|
||||
|
||||
var/obj/item/weapon/cell/emergency_light/cell
|
||||
var/start_with_cell = TRUE // if true, this fixture generates a very weak cell at roundstart
|
||||
|
||||
var/emergency_mode = FALSE // if true, the light is in emergency mode
|
||||
var/no_emergency = FALSE // if true, this light cannot ever have an emergency mode
|
||||
var/bulb_emergency_brightness_mul = 0.25 // multiplier for this light's base brightness in emergency power mode
|
||||
var/bulb_emergency_colour = "#FF3232" // determines the colour of the light while it's in emergency mode
|
||||
var/bulb_emergency_pow_mul = 0.75 // the multiplier for determining the light's power in emergency mode
|
||||
var/bulb_emergency_pow_min = 0.5 // the minimum value for the light's power in emergency mode
|
||||
|
||||
/obj/machinery/light/flicker
|
||||
auto_flicker = TRUE
|
||||
|
||||
@@ -208,6 +262,12 @@ var/global/list/light_type_cache = list()
|
||||
/obj/machinery/light/small/flicker
|
||||
auto_flicker = TRUE
|
||||
|
||||
/obj/machinery/light/poi
|
||||
start_with_cell = FALSE
|
||||
|
||||
/obj/machinery/light/small/poi
|
||||
start_with_cell = FALSE
|
||||
|
||||
/obj/machinery/light/flamp
|
||||
icon = 'icons/obj/lighting.dmi' //VOREStation Edit
|
||||
icon_state = "flamp1"
|
||||
@@ -222,10 +282,14 @@ var/global/list/light_type_cache = list()
|
||||
|
||||
/obj/machinery/light/flamp/New(atom/newloc, obj/machinery/light_construct/construct = null)
|
||||
..(newloc, construct)
|
||||
|
||||
if(construct)
|
||||
start_with_cell = FALSE
|
||||
lamp_shade = 0
|
||||
update_icon()
|
||||
else
|
||||
if(start_with_cell && !no_emergency)
|
||||
cell = new/obj/item/weapon/cell/emergency_light(src)
|
||||
|
||||
|
||||
/obj/machinery/light/flamp/flicker
|
||||
auto_flicker = TRUE
|
||||
@@ -256,11 +320,14 @@ var/global/list/light_type_cache = list()
|
||||
..(newloc)
|
||||
|
||||
if(construct)
|
||||
start_with_cell = FALSE
|
||||
status = LIGHT_EMPTY
|
||||
construct_type = construct.type
|
||||
construct.transfer_fingerprints_to(src)
|
||||
set_dir(construct.dir)
|
||||
else
|
||||
if(start_with_cell && !no_emergency)
|
||||
cell = new/obj/item/weapon/cell/emergency_light(src)
|
||||
var/obj/item/weapon/light/L = get_light_type_instance(light_type)
|
||||
update_from_bulb(L)
|
||||
if(prob(L.broken_chance))
|
||||
@@ -274,6 +341,7 @@ var/global/list/light_type_cache = list()
|
||||
if(A)
|
||||
on = 0
|
||||
// A.update_lights()
|
||||
QDEL_NULL(cell)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/light/update_icon()
|
||||
@@ -369,6 +437,10 @@ var/global/list/light_type_cache = list()
|
||||
else
|
||||
use_power = 2
|
||||
set_light(brightness_range, brightness_power, brightness_color)
|
||||
else if(has_emergency_power(LIGHT_EMERGENCY_POWER_USE) && !turned_off())
|
||||
use_power = 1
|
||||
emergency_mode = TRUE
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
use_power = 1
|
||||
set_light(0)
|
||||
@@ -408,6 +480,9 @@ var/global/list/light_type_cache = list()
|
||||
on = (s && status == LIGHT_OK)
|
||||
update()
|
||||
|
||||
/obj/machinery/light/get_cell()
|
||||
return cell
|
||||
|
||||
// examine verb
|
||||
/obj/machinery/light/examine(mob/user)
|
||||
var/fitting = get_fitting_name()
|
||||
@@ -420,6 +495,8 @@ var/global/list/light_type_cache = list()
|
||||
to_chat(user, "[desc] The [fitting] is burnt out.")
|
||||
if(LIGHT_BROKEN)
|
||||
to_chat(user, "[desc] The [fitting] has been smashed.")
|
||||
if(cell)
|
||||
to_chat(user, "Its backup power charge meter reads [round((cell.charge / cell.maxcharge) * 100, 0.1)]%.")
|
||||
|
||||
/obj/machinery/light/proc/get_fitting_name()
|
||||
var/obj/item/weapon/light/L = light_type
|
||||
@@ -545,6 +622,12 @@ var/global/list/light_type_cache = list()
|
||||
|
||||
..()
|
||||
|
||||
// returns if the light has power /but/ is manually turned off
|
||||
// if a light is turned off, it won't activate emergency power
|
||||
/obj/machinery/light/proc/turned_off()
|
||||
var/area/A = get_area(src)
|
||||
return !A.lightswitch && A.power_light || flickering
|
||||
|
||||
// returns whether this light has power
|
||||
// true if area has power and lightswitch is on
|
||||
/obj/machinery/light/proc/has_power()
|
||||
@@ -558,6 +641,28 @@ var/global/list/light_type_cache = list()
|
||||
else
|
||||
return A && A.lightswitch && (!A.requires_power || A.power_light)
|
||||
|
||||
// returns whether this light has emergency power
|
||||
// can also return if it has access to a certain amount of that power
|
||||
/obj/machinery/light/proc/has_emergency_power(pwr)
|
||||
if(no_emergency || !cell)
|
||||
return FALSE
|
||||
if(pwr ? cell.charge >= pwr : cell.charge)
|
||||
return status == LIGHT_OK
|
||||
|
||||
// attempts to use power from the installed emergency cell, returns true if it does and false if it doesn't
|
||||
/obj/machinery/light/proc/use_emergency_power(pwr = LIGHT_EMERGENCY_POWER_USE)
|
||||
if(turned_off())
|
||||
return FALSE
|
||||
if(!has_emergency_power(pwr))
|
||||
return FALSE
|
||||
if(cell.charge > 300) //it's meant to handle 120 W, ya doofus
|
||||
visible_message("<span class='warning'>[src] short-circuits from too powerful of a power cell!</span>")
|
||||
status = LIGHT_BURNED
|
||||
return FALSE
|
||||
cell.use(pwr)
|
||||
set_light(brightness_range * bulb_emergency_brightness_mul, max(bulb_emergency_pow_min, bulb_emergency_pow_mul * (cell.charge / cell.maxcharge)), bulb_emergency_colour)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
|
||||
if(flickering) return
|
||||
flickering = 1
|
||||
@@ -572,12 +677,17 @@ var/global/list/light_type_cache = list()
|
||||
update(0)
|
||||
flickering = 0
|
||||
|
||||
// ai attack - make lights flicker, because why not
|
||||
|
||||
// ai attack - turn on/off emergency lighting for a specific fixture
|
||||
/obj/machinery/light/attack_ai(mob/user)
|
||||
src.flicker(1)
|
||||
no_emergency = !no_emergency
|
||||
to_chat(user, "<span class='notice'>Emergency lights for this fixture have been [no_emergency ? "disabled" : "enabled"].</span>")
|
||||
update(FALSE)
|
||||
return
|
||||
|
||||
// ai alt click - Make light flicker. Very important for atmosphere.
|
||||
/obj/machinery/light/AIAltClick(mob/user)
|
||||
flicker(1)
|
||||
|
||||
/obj/machinery/light/flamp/attack_ai(mob/user)
|
||||
attack_hand()
|
||||
return
|
||||
@@ -700,6 +810,17 @@ var/global/list/light_type_cache = list()
|
||||
// use power
|
||||
|
||||
/obj/machinery/light/process()
|
||||
if(!cell)
|
||||
return PROCESS_KILL
|
||||
if(has_power())
|
||||
emergency_mode = FALSE
|
||||
update(FALSE)
|
||||
if(cell.charge == cell.maxcharge)
|
||||
return PROCESS_KILL
|
||||
cell.charge = min(cell.maxcharge, cell.charge + LIGHT_EMERGENCY_POWER_USE*2) //Recharge emergency power automatically while not using it
|
||||
if(emergency_mode && !use_emergency_power(LIGHT_EMERGENCY_POWER_USE))
|
||||
update(FALSE) //Disables emergency mode and sets the color to normal
|
||||
|
||||
if(auto_flicker && !flickering)
|
||||
if(check_for_player_proximity(src, radius = 12, ignore_ghosts = FALSE, ignore_afk = TRUE))
|
||||
seton(TRUE) // Lights must be on to flicker.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
################################
|
||||
# Example Changelog File
|
||||
#
|
||||
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
|
||||
#
|
||||
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
|
||||
# When it is, any changes listed below will disappear.
|
||||
#
|
||||
# Valid Prefixes:
|
||||
# bugfix
|
||||
# wip (For works in progress)
|
||||
# tweak
|
||||
# soundadd
|
||||
# sounddel
|
||||
# rscadd (general adding of nice things)
|
||||
# rscdel (general deleting of nice things)
|
||||
# imageadd
|
||||
# imagedel
|
||||
# maptweak
|
||||
# spellcheck (typo fixes)
|
||||
# experiment
|
||||
#################################
|
||||
|
||||
# Your name.
|
||||
author: Shadow-Quill
|
||||
|
||||
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||
delete-after: True
|
||||
|
||||
# Any changes you've made. See valid prefix list above.
|
||||
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||
# SCREW THIS UP AND IT WON'T WORK.
|
||||
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- rscadd: "Adds emergency backup cells to most light fixtures"
|
||||
- tweak: "AIs can turn emergency lighting on and off by clicking light fixtures. Flickering the lights has been moved to alt-click.
|
||||
@@ -188,6 +188,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<div class="itemLabel">
|
||||
Emergency Lighting:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
{{if data.locked && !data.siliconUser}}
|
||||
{{:data.emergencyLights ? "<span class='good'>Enabled</span>" : "<span class='bad'>Disabled</span>"}}
|
||||
{{else}}
|
||||
{{:helper.link(data.emergencyLights ? 'Enabled' : 'Disabled', data.emergencyLights ? 'power' : 'close', {'emergency_lighting' : 1}, null)}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if data.siliconUser}}
|
||||
<h3>System Overrides</h3>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user