Merge pull request #4198 from Citadel-Station-13/upstream-merge-33213

[MIRROR] Adds emergency lights, built into light fixtures
This commit is contained in:
deathride58
2017-12-04 22:14:15 +00:00
committed by GitHub
11 changed files with 272 additions and 101 deletions
+82 -82
View File
@@ -1,82 +1,82 @@
//Speech verbs.
/mob/verb/say_verb(message as text)
set name = "Say"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
usr.say(message)
/mob/verb/whisper_verb(message as text)
set name = "Whisper"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
whisper(message)
/mob/proc/whisper(message, datum/language/language=null)
say(message, language) //only living mobs actually whisper, everything else just talks
/mob/verb/me_verb(message as text)
set name = "Me"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
usr.emote("me",1,message)
/mob/proc/say_dead(var/message)
var/name = real_name
var/alt_name = ""
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
if(jobban_isbanned(src, "OOC"))
to_chat(src, "<span class='danger'>You have been banned from deadchat.</span>")
return
if (src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='danger'>You cannot talk in deadchat (muted).</span>")
return
if(src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
return
var/mob/dead/observer/O = src
if(isobserver(src) && O.deadchat_name)
name = "[O.deadchat_name]"
else
if(mind && mind.name)
name = "[mind.name]"
else
name = real_name
if(name != real_name)
alt_name = " (died as [real_name])"
var/K
if(key)
K = src.key
message = src.say_quote(message, get_spans())
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[name]</span>[alt_name] <span class='message'>[message]</span></span>"
deadchat_broadcast(rendered, follow_target = src, speaker_key = K)
/mob/proc/emote(var/act)
return
/mob/proc/hivecheck()
return 0
/mob/proc/lingcheck()
return LINGHIVE_NONE
//Speech verbs.
/mob/verb/say_verb(message as text)
set name = "Say"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
usr.say(message)
/mob/verb/whisper_verb(message as text)
set name = "Whisper"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
whisper(message)
/mob/proc/whisper(message, datum/language/language=null)
say(message, language) //only living mobs actually whisper, everything else just talks
/mob/verb/me_verb(message as text)
set name = "Me"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
usr.emote("me",1,message)
/mob/proc/say_dead(var/message)
var/name = real_name
var/alt_name = ""
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
if(jobban_isbanned(src, "OOC"))
to_chat(src, "<span class='danger'>You have been banned from deadchat.</span>")
return
if (src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='danger'>You cannot talk in deadchat (muted).</span>")
return
if(src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
return
var/mob/dead/observer/O = src
if(isobserver(src) && O.deadchat_name)
name = "[O.deadchat_name]"
else
if(mind && mind.name)
name = "[mind.name]"
else
name = real_name
if(name != real_name)
alt_name = " (died as [real_name])"
var/K
if(key)
K = src.key
message = src.say_quote(message, get_spans())
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[name]</span>[alt_name] <span class='message'>[message]</span></span>"
deadchat_broadcast(rendered, follow_target = src, speaker_key = K)
/mob/proc/emote(var/act)
return
/mob/proc/hivecheck()
return 0
/mob/proc/lingcheck()
return LINGHIVE_NONE
+10
View File
@@ -89,6 +89,7 @@
var/auto_name = 0
var/failure_timer = 0
var/force_update = 0
var/emergency_lights = FALSE
var/update_state = -1
var/update_overlay = -1
var/icon_update_needed = FALSE
@@ -760,6 +761,7 @@
"coverLocked" = coverlocked,
"siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console(),
"malfStatus" = get_malf_status(user),
"emergencyLights" = !emergency_lights,
"powerChannels" = list(
list(
@@ -899,6 +901,14 @@
failure_timer = 0
update_icon()
update()
if("emergency_lighting")
emergency_lights = !emergency_lights
for(var/area/A in area.related)
for(var/obj/machinery/light/L in A)
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
return 1
/obj/machinery/power/apc/proc/toggle_breaker()
+14
View File
@@ -343,3 +343,17 @@
/obj/item/stock_parts/cell/beam_rifle/emp_act(severity)
charge = Clamp((charge-(10000/severity)),0,maxcharge)
/obj/item/stock_parts/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
materials = list(MAT_GLASS = 20)
rating = 1
w_class = WEIGHT_CLASS_TINY
/obj/item/stock_parts/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
+112 -9
View File
@@ -49,12 +49,22 @@
var/fixture_type = "tube"
var/sheets_refunded = 2
var/obj/machinery/light/newlight = null
var/obj/item/stock_parts/cell/cell
/obj/structure/light_construct/New(loc, ndir, building)
..()
var/cell_connectors = TRUE
/obj/structure/light_construct/Initialize(mapload, ndir, building)
. = ..()
if(building)
setDir(ndir)
/obj/structure/light_construct/Destroy()
QDEL_NULL(cell)
return ..()
/obj/structure/light_construct/get_cell()
return cell
/obj/structure/light_construct/examine(mob/user)
..()
switch(src.stage)
@@ -64,9 +74,38 @@
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>")
return
/obj/structure/light_construct/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
if(istype(W, /obj/item/stock_parts/cell))
if(!cell_connectors)
to_chat(user, "<span class='warning'>This [name] can't support a power cell!</span>")
return
if(W.flags_1 & NODROP_1)
to_chat(user, "<span class='warning'>[W] is stuck to your hand!</span>")
return
user.dropItemToGround(W)
if(cell)
user.visible_message("<span class='notice'>[user] swaps [W] out for [src]'s cell.</span>", \
"<span class='notice'>You swap [src]'s power cells.</span>")
cell.forceMove(drop_location())
user.put_in_hands(cell)
else
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
switch(stage)
if(1)
if(istype(W, /obj/item/wrench))
@@ -124,6 +163,10 @@
newlight = new /obj/machinery/light/small/built(loc)
newlight.setDir(dir)
transfer_fingerprints_to(newlight)
if(cell)
newlight.cell = cell
cell.forceMove(newlight)
cell = null
qdel(src)
return
return ..()
@@ -173,6 +216,11 @@
var/rigged = 0 // true if rigged to explode
var/obj/item/stock_parts/cell/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
// the smaller bulb light fixture
/obj/machinery/light/small
@@ -192,8 +240,10 @@
/obj/machinery/light/built
icon_state = "tube-empty"
start_with_cell = FALSE
/obj/machinery/light/built/New()
/obj/machinery/light/built/Initialize()
. = ..()
status = LIGHT_EMPTY
update(0)
..()
@@ -208,8 +258,10 @@
// create a new lighting fixture
/obj/machinery/light/New()
..()
/obj/machinery/light/Initialize()
. = ..()
if(start_with_cell && !no_emergency)
cell = new/obj/item/stock_parts/cell/emergency_light(src)
spawn(2)
switch(fitting)
if("tube")
@@ -228,13 +280,17 @@
if(A)
on = FALSE
// A.update_lights()
QDEL_NULL(cell)
return ..()
/obj/machinery/light/update_icon()
switch(status) // set icon_states
if(LIGHT_OK)
icon_state = "[base_state][on]"
if(emergency_mode)
icon_state = "[base_state]_emergency"
else
icon_state = "[base_state][on]"
if(LIGHT_EMPTY)
icon_state = "[base_state]-empty"
on = FALSE
@@ -249,7 +305,7 @@
// update the icon_state and luminosity of the light depending on its state
/obj/machinery/light/proc/update(trigger = 1)
update_icon()
emergency_mode = FALSE
if(on)
if(!light || light.light_range != brightness)
switchcount++
@@ -261,10 +317,14 @@
burn_out()
else
use_power = ACTIVE_POWER_USE
set_light(brightness)
set_light(brightness, 1, "#FFFFFF")
else if(has_emergency_power() && !turned_off())
use_power = IDLE_POWER_USE
emergency_mode = TRUE
else
use_power = IDLE_POWER_USE
set_light(0)
update_icon()
active_power_usage = (brightness * 10)
if(on != on_gs)
@@ -276,6 +336,12 @@
removeStaticPower(static_power_used, STATIC_LIGHT)
/obj/machinery/light/process()
if(has_power() && cell)
cell.charge = min(cell.maxcharge, cell.charge + 0.2) //Recharge emergency power automatically while not using it
if(emergency_mode && !use_emergency_power(0.2))
update(FALSE) //Disables emergency mode and sets the color to normal
/obj/machinery/light/proc/burn_out()
if(status == LIGHT_OK)
status = LIGHT_BURNED
@@ -289,6 +355,9 @@
on = (s && status == LIGHT_OK)
update()
/obj/machinery/light/get_cell()
return cell
// examine verb
/obj/machinery/light/examine(mob/user)
..()
@@ -301,6 +370,8 @@
to_chat(user, "The [fitting] is burnt out.")
if(LIGHT_BROKEN)
to_chat(user, "The [fitting] has been smashed.")
if(cell)
to_chat(user, "Its backup power charge meter reads [(cell.charge / cell.maxcharge) * 100]%.")
@@ -384,6 +455,10 @@
drop_light_tube()
new /obj/item/stack/cable_coil(loc, 1, "red")
transfer_fingerprints_to(newlight)
if(cell)
newlight.cell = cell
cell.forceMove(newlight)
cell = null
qdel(src)
/obj/machinery/light/attacked_by(obj/item/I, mob/living/user)
@@ -415,6 +490,11 @@
if(BURN)
playsound(src.loc, 'sound/items/welder.ogg', 100, 1)
// 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
// returns whether this light has power
// true if area has power and lightswitch is on
@@ -422,6 +502,27 @@
var/area/A = get_area(src)
return A.lightswitch && 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 = 0.2)
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>")
burn_out()
return FALSE
cell.use(pwr)
set_light(brightness * 0.25, max(0.5, 0.75 * (cell.charge / cell.maxcharge)), "#FF3232") //RGB: 255, 50, 50
return TRUE
/obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
set waitfor = 0
if(flickering)
@@ -441,7 +542,9 @@
// ai attack - make lights flicker, because why not
/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
// attack with hand - remove tube/bulb
@@ -800,6 +800,14 @@
build_path = /obj/item/device/slime_scanner
category = list("initial", "Misc")
/datum/design/miniature_power_cell
name = "Light Fixture Battery"
id = "miniature_power_cell"
build_type = AUTOLATHE
materials = list(MAT_GLASS = 20)
build_path = /obj/item/stock_parts/cell/emergency_light
category = list("initial", "Electronics")
/datum/design/holodisk
name = "Holodisk"
id = "holodisk"