mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-15 12:11:45 +00:00
* Resonance cascade polishening, bugfixes and better logging * Update light.dm Co-authored-by: distributivgesetz <distributivgesetz93@gmail.com> Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
695 lines
22 KiB
Plaintext
695 lines
22 KiB
Plaintext
// the standard tube light fixture
|
|
/obj/machinery/light
|
|
name = "light fixture"
|
|
icon = 'icons/obj/lighting.dmi'
|
|
icon_state = "tube"
|
|
desc = "A lighting fixture."
|
|
layer = WALL_OBJ_LAYER
|
|
plane = GAME_PLANE_UPPER
|
|
max_integrity = 100
|
|
use_power = ACTIVE_POWER_USE
|
|
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.02
|
|
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.02
|
|
power_channel = AREA_USAGE_LIGHT //Lights are calc'd via area so they dont need to be in the machine list
|
|
always_area_sensitive = TRUE
|
|
///What overlay the light should use
|
|
var/overlay_icon = 'icons/obj/lighting_overlay.dmi'
|
|
///base description and icon_state
|
|
var/base_state = "tube"
|
|
///Is the light on?
|
|
var/on = FALSE
|
|
///Amount of power used
|
|
var/static_power_used = 0
|
|
///Luminosity when on, also used in power calculation
|
|
var/brightness = 8
|
|
///Basically the alpha of the emitted light source
|
|
var/bulb_power = 1
|
|
///Default colour of the light.
|
|
var/bulb_colour = "#f3fffa"
|
|
///LIGHT_OK, _EMPTY, _BURNED or _BROKEN
|
|
var/status = LIGHT_OK
|
|
///Should we flicker?
|
|
var/flickering = FALSE
|
|
///The type of light item
|
|
var/light_type = /obj/item/light/tube
|
|
///String of the light type, used in descriptions and in examine
|
|
var/fitting = "tube"
|
|
///Count of number of times switched on/off, this is used to calculate the probability the light burns out
|
|
var/switchcount = 0
|
|
///True if rigged to explode
|
|
var/rigged = FALSE
|
|
///Cell reference
|
|
var/obj/item/stock_parts/cell/cell
|
|
///If true, this fixture generates a very weak cell at roundstart
|
|
var/start_with_cell = TRUE
|
|
///Currently in night shift mode?
|
|
var/nightshift_enabled = FALSE
|
|
///Set to FALSE to never let this light get switched to night mode.
|
|
var/nightshift_allowed = TRUE
|
|
///Brightness of the nightshift light
|
|
var/nightshift_brightness = 8
|
|
///Alpha of the nightshift light
|
|
var/nightshift_light_power = 0.45
|
|
///Basecolor of the nightshift light
|
|
var/nightshift_light_color = "#FFDDCC"
|
|
///If true, the light is in low power mode
|
|
var/low_power_mode = FALSE
|
|
///If true, this light cannot ever be in low power mode
|
|
var/no_low_power = FALSE
|
|
///If true, overrides lights to use emergency lighting
|
|
var/major_emergency = FALSE
|
|
///Multiplier for this light's base brightness during a cascade
|
|
var/bulb_major_emergency_brightness_mul = 0.75
|
|
///Colour of the light when major emergency mode is on
|
|
var/bulb_emergency_colour = "#ff4e4e"
|
|
///Multiplier for this light's base brightness in low power power mode
|
|
var/bulb_low_power_brightness_mul = 0.25
|
|
///Determines the colour of the light while it's in low power mode
|
|
var/bulb_low_power_colour = "#FF3232"
|
|
///The multiplier for determining the light's power in low power mode
|
|
var/bulb_low_power_pow_mul = 0.75
|
|
///The minimum value for the light's power in low power mode
|
|
var/bulb_low_power_pow_min = 0.5
|
|
///Power usage - W per unit of luminosity
|
|
var/power_consumption_rate = 20
|
|
|
|
/obj/machinery/light/Move()
|
|
if(status != LIGHT_BROKEN)
|
|
break_light_tube(TRUE)
|
|
return ..()
|
|
|
|
// create a new lighting fixture
|
|
/obj/machinery/light/Initialize(mapload)
|
|
. = ..()
|
|
|
|
if(!mapload) //sync up nightshift lighting for player made lights
|
|
var/area/our_area = get_area(src)
|
|
var/obj/machinery/power/apc/temp_apc = our_area.apc
|
|
nightshift_enabled = temp_apc?.nightshift_lights
|
|
|
|
if(start_with_cell && !no_low_power)
|
|
cell = new/obj/item/stock_parts/cell/emergency_light(src)
|
|
|
|
RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, .proc/on_light_eater)
|
|
AddElement(/datum/element/atmos_sensitive, mapload)
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/machinery/light/LateInitialize()
|
|
. = ..()
|
|
switch(fitting)
|
|
if("tube")
|
|
if(prob(2))
|
|
break_light_tube(TRUE)
|
|
if("bulb")
|
|
if(prob(5))
|
|
break_light_tube(TRUE)
|
|
addtimer(CALLBACK(src, .proc/update, FALSE), 0.1 SECONDS)
|
|
|
|
/obj/machinery/light/Destroy()
|
|
var/area/local_area = get_area(src)
|
|
if(local_area)
|
|
on = FALSE
|
|
QDEL_NULL(cell)
|
|
return ..()
|
|
|
|
/obj/machinery/light/update_icon_state()
|
|
switch(status) // set icon_states
|
|
if(LIGHT_OK)
|
|
//var/area/local_area = get_area(src) SKYRAT EDIT REMOVAL
|
|
if(low_power_mode || major_emergency) // SKYRAT EDIT CHANGE
|
|
icon_state = "[base_state]_emergency"
|
|
else
|
|
icon_state = "[base_state]"
|
|
if(LIGHT_EMPTY)
|
|
icon_state = "[base_state]-empty"
|
|
if(LIGHT_BURNED)
|
|
icon_state = "[base_state]-burned"
|
|
if(LIGHT_BROKEN)
|
|
icon_state = "[base_state]-broken"
|
|
return ..()
|
|
|
|
/obj/machinery/light/update_overlays()
|
|
. = ..()
|
|
if(!on || status != LIGHT_OK)
|
|
return
|
|
|
|
/* SKYRAT EDIT START - ORIGINAL:
|
|
var/area/local_area = get_area(src)
|
|
if(emergency_mode || (local_area?.fire))
|
|
*/
|
|
if(low_power_mode || major_emergency) // SKYRAT EDIT END
|
|
. += mutable_appearance(overlay_icon, "[base_state]_emergency")
|
|
return
|
|
if(nightshift_enabled)
|
|
. += mutable_appearance(overlay_icon, "[base_state]_nightshift")
|
|
return
|
|
. += mutable_appearance(overlay_icon, base_state)
|
|
|
|
|
|
//SKYRAT EDIT ADDITION BEGIN - AESTHETICS
|
|
#define LIGHT_ON_DELAY_UPPER 3 SECONDS
|
|
#define LIGHT_ON_DELAY_LOWER 1 SECONDS
|
|
//SKYRAT EDIT END
|
|
|
|
// Area sensitivity is traditionally tied directly to power use, as an optimization
|
|
// But since we want it for fire reacting, we disregard that
|
|
/obj/machinery/light/setup_area_power_relationship()
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
var/area/our_area = get_area(src)
|
|
RegisterSignal(our_area, COMSIG_AREA_FIRE_CHANGED, .proc/handle_fire)
|
|
|
|
/obj/machinery/light/on_enter_area(datum/source, area/area_to_register)
|
|
..()
|
|
RegisterSignal(area_to_register, COMSIG_AREA_FIRE_CHANGED, .proc/handle_fire)
|
|
handle_fire(area_to_register, area_to_register.fire)
|
|
|
|
/obj/machinery/light/on_exit_area(datum/source, area/area_to_unregister)
|
|
..()
|
|
UnregisterSignal(area_to_unregister, COMSIG_AREA_FIRE_CHANGED)
|
|
|
|
/obj/machinery/light/proc/handle_fire(area/source, new_fire)
|
|
SIGNAL_HANDLER
|
|
update()
|
|
|
|
// update the icon_state and luminosity of the light depending on its state
|
|
/obj/machinery/light/proc/update(trigger = TRUE, instant = FALSE, play_sound = TRUE) //SKYRAT EDIT CHANGE
|
|
switch(status)
|
|
if(LIGHT_BROKEN,LIGHT_BURNED,LIGHT_EMPTY)
|
|
on = FALSE
|
|
low_power_mode = FALSE
|
|
if(on)
|
|
/* SKYRAT EDIT ORIGINAL
|
|
var/brightness_set = brightness
|
|
var/power_set = bulb_power
|
|
var/color_set = bulb_colour
|
|
if(color)
|
|
color_set = color
|
|
var/area/local_area = get_area(src)
|
|
if (local_area?.fire)
|
|
color_set = bulb_low_power_colour
|
|
else if (nightshift_enabled)
|
|
brightness_set = nightshift_brightness
|
|
power_set = nightshift_light_power
|
|
if(!color)
|
|
color_set = nightshift_light_color
|
|
else if (major_emergency)
|
|
color_set = bulb_low_power_colour
|
|
brightness_set = brightness * bulb_major_emergency_brightness_mul
|
|
var/matching = light && brightness_set == light.light_range && power_set == light.light_power && color_set == light.light_color
|
|
if(!matching)
|
|
switchcount++
|
|
if(rigged)
|
|
if(status == LIGHT_OK && trigger)
|
|
explode()
|
|
else if( prob( min(60, (switchcount**2)*0.01) ) )
|
|
if(trigger)
|
|
burn_out()
|
|
else
|
|
use_power = ACTIVE_POWER_USE
|
|
set_light(
|
|
l_range = brightness_set,
|
|
l_power = power_set,
|
|
l_color = color_set
|
|
)
|
|
*/
|
|
//SKYRAT EDIT CHANGE BEGIN - AESTHETICS
|
|
if(instant)
|
|
turn_on(trigger, play_sound)
|
|
else if(maploaded)
|
|
turn_on(trigger, play_sound)
|
|
maploaded = FALSE
|
|
else if(!turning_on)
|
|
turning_on = TRUE
|
|
addtimer(CALLBACK(src, .proc/turn_on, trigger, play_sound), rand(LIGHT_ON_DELAY_LOWER, LIGHT_ON_DELAY_UPPER))
|
|
//SKYRAT EDIT END
|
|
else if(has_emergency_power(LIGHT_EMERGENCY_POWER_USE) && !turned_off())
|
|
use_power = IDLE_POWER_USE
|
|
low_power_mode = TRUE
|
|
START_PROCESSING(SSmachines, src)
|
|
else
|
|
use_power = IDLE_POWER_USE
|
|
set_light(l_range = 0)
|
|
update_appearance()
|
|
update_current_power_usage()
|
|
broken_sparks(start_only=TRUE)
|
|
|
|
|
|
//SKYRAT EDIT ADDITION BEGIN - AESTHETICS
|
|
#undef LIGHT_ON_DELAY_UPPER
|
|
#undef LIGHT_ON_DELAY_LOWER
|
|
//SKYRAT EDIT END
|
|
|
|
/obj/machinery/light/update_current_power_usage()
|
|
if(!on && static_power_used > 0) //Light is off but still powered
|
|
removeStaticPower(static_power_used, AREA_USAGE_STATIC_LIGHT)
|
|
static_power_used = 0
|
|
else if(on) //Light is on, just recalculate usage
|
|
var/static_power_used_new = 0
|
|
var/area/local_area = get_area(src)
|
|
if (nightshift_enabled && !local_area?.fire)
|
|
static_power_used_new = nightshift_brightness * nightshift_light_power * power_consumption_rate
|
|
else
|
|
static_power_used_new = brightness * bulb_power * power_consumption_rate
|
|
if(static_power_used != static_power_used_new) //Consumption changed - update
|
|
removeStaticPower(static_power_used, AREA_USAGE_STATIC_LIGHT)
|
|
static_power_used = static_power_used_new
|
|
addStaticPower(static_power_used, AREA_USAGE_STATIC_LIGHT)
|
|
|
|
/obj/machinery/light/update_atom_colour()
|
|
..()
|
|
update()
|
|
|
|
/obj/machinery/light/proc/broken_sparks(start_only=FALSE)
|
|
if(!QDELETED(src) && status == LIGHT_BROKEN && has_power() && MC_RUNNING())
|
|
if(!start_only)
|
|
do_sparks(3, TRUE, src)
|
|
var/delay = rand(BROKEN_SPARKS_MIN, BROKEN_SPARKS_MAX)
|
|
addtimer(CALLBACK(src, .proc/broken_sparks), delay, TIMER_UNIQUE | TIMER_NO_HASH_WAIT)
|
|
|
|
/obj/machinery/light/process()
|
|
if (!cell)
|
|
return PROCESS_KILL
|
|
if(has_power())
|
|
if (cell.charge == cell.maxcharge)
|
|
return PROCESS_KILL
|
|
cell.charge = min(cell.maxcharge, cell.charge + LIGHT_EMERGENCY_POWER_USE) //Recharge emergency power automatically while not using it
|
|
if(low_power_mode && !use_emergency_power(LIGHT_EMERGENCY_POWER_USE))
|
|
update(FALSE) //Disables emergency mode and sets the color to normal
|
|
|
|
/obj/machinery/light/proc/burn_out()
|
|
if(status == LIGHT_OK)
|
|
status = LIGHT_BURNED
|
|
icon_state = "[base_state]-burned"
|
|
on = FALSE
|
|
set_light(l_range = 0)
|
|
|
|
// attempt to set the light's on/off status
|
|
// will not switch on if broken/burned/empty
|
|
/obj/machinery/light/proc/set_on(turn_on)
|
|
on = (turn_on && status == LIGHT_OK)
|
|
update()
|
|
|
|
/obj/machinery/light/get_cell()
|
|
return cell
|
|
|
|
// examine verb
|
|
/obj/machinery/light/examine(mob/user)
|
|
. = ..()
|
|
switch(status)
|
|
if(LIGHT_OK)
|
|
. += "It is turned [on? "on" : "off"]."
|
|
if(LIGHT_EMPTY)
|
|
. += "The [fitting] has been removed."
|
|
if(LIGHT_BURNED)
|
|
. += "The [fitting] is burnt out."
|
|
if(LIGHT_BROKEN)
|
|
. += "The [fitting] has been smashed."
|
|
if(cell)
|
|
. += "Its backup power charge meter reads [round((cell.charge / cell.maxcharge) * 100, 0.1)]%."
|
|
//SKYRAT EDIT ADDITION
|
|
if(constant_flickering)
|
|
. += span_danger("The lighting ballast appears to be damaged, this could be fixed with a multitool.")
|
|
//SKYRAT EDIT END
|
|
|
|
|
|
|
|
// attack with item - insert light (if right type), otherwise try to break the light
|
|
|
|
/obj/machinery/light/attackby(obj/item/tool, mob/living/user, params)
|
|
|
|
//Light replacer code
|
|
if(istype(tool, /obj/item/lightreplacer))
|
|
var/obj/item/lightreplacer/replacer = tool
|
|
replacer.ReplaceLight(src, user)
|
|
return
|
|
|
|
//SKYRAT EDIT ADDITION
|
|
if(istype(tool, /obj/item/multitool) && constant_flickering)
|
|
to_chat(user, span_notice("You start repairing the ballast of [src] with [tool]."))
|
|
if(do_after(user, 2 SECONDS, src))
|
|
stop_flickering()
|
|
to_chat(user, span_notice("You repair the ballast of [src]!"))
|
|
return
|
|
|
|
//SKYRAT EDTI END
|
|
|
|
// attempt to insert light
|
|
if(istype(tool, /obj/item/light))
|
|
if(status == LIGHT_OK)
|
|
to_chat(user, span_warning("There is a [fitting] already inserted!"))
|
|
return
|
|
add_fingerprint(user)
|
|
var/obj/item/light/light_object = tool
|
|
if(!istype(light_object, light_type))
|
|
to_chat(user, span_warning("This type of light requires a [fitting]!"))
|
|
return
|
|
if(!user.temporarilyRemoveItemFromInventory(light_object))
|
|
return
|
|
|
|
add_fingerprint(user)
|
|
if(status != LIGHT_EMPTY)
|
|
drop_light_tube(user)
|
|
to_chat(user, span_notice("You replace [light_object]."))
|
|
else
|
|
to_chat(user, span_notice("You insert [light_object]."))
|
|
status = light_object.status
|
|
switchcount = light_object.switchcount
|
|
rigged = light_object.rigged
|
|
brightness = light_object.brightness
|
|
on = has_power()
|
|
update()
|
|
|
|
qdel(light_object)
|
|
|
|
if(on && rigged)
|
|
explode()
|
|
return
|
|
|
|
// attempt to stick weapon into light socket
|
|
if(status != LIGHT_EMPTY)
|
|
return ..()
|
|
if(tool.tool_behaviour == TOOL_SCREWDRIVER) //If it's a screwdriver open it.
|
|
tool.play_tool_sound(src, 75)
|
|
user.visible_message(span_notice("[user.name] opens [src]'s casing."), \
|
|
span_notice("You open [src]'s casing."), span_hear("You hear a noise."))
|
|
deconstruct()
|
|
return
|
|
to_chat(user, span_userdanger("You stick \the [tool] into the light socket!"))
|
|
if(has_power() && (tool.flags_1 & CONDUCT_1))
|
|
do_sparks(3, TRUE, src)
|
|
if (prob(75))
|
|
electrocute_mob(user, get_area(src), src, (rand(7,10) * 0.1), TRUE)
|
|
|
|
/obj/machinery/light/deconstruct(disassembled = TRUE)
|
|
if(flags_1 & NODECONSTRUCT_1)
|
|
qdel(src)
|
|
return
|
|
var/obj/structure/light_construct/new_light = null
|
|
var/current_stage = 2
|
|
if(!disassembled)
|
|
current_stage = 1
|
|
switch(fitting)
|
|
if("tube")
|
|
new_light = new /obj/structure/light_construct(loc)
|
|
new_light.icon_state = "tube-construct-stage[current_stage]"
|
|
|
|
if("bulb")
|
|
new_light = new /obj/structure/light_construct/small(loc)
|
|
new_light.icon_state = "bulb-construct-stage[current_stage]"
|
|
new_light.setDir(dir)
|
|
new_light.stage = current_stage
|
|
if(!disassembled)
|
|
new_light.take_damage(new_light.max_integrity * 0.5, sound_effect=FALSE)
|
|
if(status != LIGHT_BROKEN)
|
|
break_light_tube()
|
|
if(status != LIGHT_EMPTY)
|
|
drop_light_tube()
|
|
new /obj/item/stack/cable_coil(loc, 1, "red")
|
|
transfer_fingerprints_to(new_light)
|
|
if(!QDELETED(cell))
|
|
new_light.cell = cell
|
|
cell.forceMove(new_light)
|
|
cell = null
|
|
qdel(src)
|
|
|
|
/obj/machinery/light/attacked_by(obj/item/attacking_object, mob/living/user)
|
|
..()
|
|
if(status != LIGHT_BROKEN && status != LIGHT_EMPTY)
|
|
return
|
|
if(!on || !(attacking_object.flags_1 & CONDUCT_1))
|
|
return
|
|
if(prob(12))
|
|
electrocute_mob(user, get_area(src), src, 0.3, TRUE)
|
|
|
|
/obj/machinery/light/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
|
|
. = ..()
|
|
if(. && !QDELETED(src))
|
|
if(prob(damage_amount * 5))
|
|
break_light_tube()
|
|
|
|
/obj/machinery/light/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
|
switch(damage_type)
|
|
if(BRUTE)
|
|
switch(status)
|
|
if(LIGHT_EMPTY)
|
|
playsound(loc, 'sound/weapons/smash.ogg', 50, TRUE)
|
|
if(LIGHT_BROKEN)
|
|
playsound(loc, 'sound/effects/hit_on_shattered_glass.ogg', 90, TRUE)
|
|
else
|
|
playsound(loc, 'sound/effects/glasshit.ogg', 90, TRUE)
|
|
if(BURN)
|
|
playsound(loc, 'sound/items/welder.ogg', 100, TRUE)
|
|
|
|
// 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/local_area = get_area(src)
|
|
return !local_area.lightswitch && local_area.power_light || flickering || constant_flickering //SKYRAT EDIT CHANGE
|
|
|
|
// returns whether this light has power
|
|
// true if area has power and lightswitch is on
|
|
/obj/machinery/light/proc/has_power()
|
|
var/area/local_area = get_area(src)
|
|
//SKYRAT EDIT ADDITION BEGIN
|
|
if(isnull(local_area))
|
|
return FALSE
|
|
//SKYRAT EDIT END
|
|
return local_area.lightswitch && local_area.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(power_usage_amount)
|
|
if(no_low_power || !cell)
|
|
return FALSE
|
|
if(power_usage_amount ? cell.charge >= power_usage_amount : 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(power_usage_amount = LIGHT_EMERGENCY_POWER_USE)
|
|
if(!has_emergency_power(power_usage_amount))
|
|
return FALSE
|
|
if(cell.charge > 300) //it's meant to handle 120 W, ya doofus
|
|
visible_message(span_warning("[src] short-circuits from too powerful of a power cell!"))
|
|
burn_out()
|
|
return FALSE
|
|
cell.use(power_usage_amount)
|
|
set_light(
|
|
l_range = brightness * bulb_low_power_brightness_mul,
|
|
l_power = max(bulb_low_power_pow_min, bulb_low_power_pow_mul * (cell.charge / cell.maxcharge)),
|
|
l_color = bulb_low_power_colour
|
|
)
|
|
return TRUE
|
|
|
|
|
|
/obj/machinery/light/proc/flicker(amount = rand(10, 20))
|
|
set waitfor = FALSE
|
|
if(flickering)
|
|
return
|
|
flickering = TRUE
|
|
if(on && status == LIGHT_OK)
|
|
for(var/i in 1 to amount)
|
|
if(status != LIGHT_OK)
|
|
break
|
|
on = !on
|
|
update(FALSE, TRUE) //SKYRAT EDIT CHANGE
|
|
sleep(rand(5, 15))
|
|
on = (status == LIGHT_OK)
|
|
update(FALSE, TRUE) //SKYRAT EDIT CHANGE
|
|
. = TRUE //did we actually flicker?
|
|
flickering = FALSE
|
|
|
|
// ai attack - make lights flicker, because why not
|
|
|
|
/obj/machinery/light/attack_ai(mob/user)
|
|
no_low_power = !no_low_power
|
|
to_chat(user, span_notice("Emergency lights for this fixture have been [no_low_power ? "disabled" : "enabled"]."))
|
|
update(FALSE)
|
|
return
|
|
|
|
// attack with hand - remove tube/bulb
|
|
// if hands aren't protected and the light is on, burn the player
|
|
|
|
/obj/machinery/light/attack_hand(mob/living/carbon/human/user, list/modifiers)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
add_fingerprint(user)
|
|
|
|
if(status == LIGHT_EMPTY)
|
|
to_chat(user, span_warning("There is no [fitting] in this light!"))
|
|
return
|
|
|
|
// make it burn hands unless you're wearing heat insulated gloves or have the RESISTHEAT/RESISTHEATHANDS traits
|
|
if(!on)
|
|
to_chat(user, span_notice("You remove the light [fitting]."))
|
|
// create a light tube/bulb item and put it in the user's hand
|
|
drop_light_tube(user)
|
|
return
|
|
var/protection_amount = 0
|
|
var/mob/living/carbon/human/electrician = user
|
|
|
|
if(istype(electrician))
|
|
var/obj/item/organ/internal/stomach/maybe_stomach = electrician.getorganslot(ORGAN_SLOT_STOMACH)
|
|
if(istype(maybe_stomach, /obj/item/organ/internal/stomach/ethereal))
|
|
var/obj/item/organ/internal/stomach/ethereal/stomach = maybe_stomach
|
|
if(stomach.drain_time > world.time)
|
|
return
|
|
to_chat(electrician, span_notice("You start channeling some power through the [fitting] into your body."))
|
|
stomach.drain_time = world.time + LIGHT_DRAIN_TIME
|
|
while(do_after(user, LIGHT_DRAIN_TIME, target = src))
|
|
stomach.drain_time = world.time + LIGHT_DRAIN_TIME
|
|
if(istype(stomach))
|
|
to_chat(electrician, span_notice("You receive some charge from the [fitting]."))
|
|
stomach.adjust_charge(LIGHT_POWER_GAIN)
|
|
else
|
|
to_chat(electrician, span_warning("You can't receive charge from the [fitting]!"))
|
|
return
|
|
|
|
if(electrician.gloves)
|
|
var/obj/item/clothing/gloves/electrician_gloves = electrician.gloves
|
|
if(electrician_gloves.max_heat_protection_temperature)
|
|
protection_amount = (electrician_gloves.max_heat_protection_temperature > 360)
|
|
else
|
|
protection_amount = 1
|
|
|
|
if(protection_amount > 0 || HAS_TRAIT(user, TRAIT_RESISTHEAT) || HAS_TRAIT(user, TRAIT_RESISTHEATHANDS))
|
|
to_chat(user, span_notice("You remove the light [fitting]."))
|
|
else if(istype(user) && user.dna.check_mutation(/datum/mutation/human/telekinesis))
|
|
to_chat(user, span_notice("You telekinetically remove the light [fitting]."))
|
|
else
|
|
var/obj/item/bodypart/affecting = electrician.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm")
|
|
if(affecting?.receive_damage( 0, 5 )) // 5 burn damage
|
|
electrician.update_damage_overlays()
|
|
if(HAS_TRAIT(user, TRAIT_LIGHTBULB_REMOVER))
|
|
to_chat(user, span_notice("You feel like you're burning, but you can push through."))
|
|
if(!do_after(user, 5 SECONDS, target = src))
|
|
return
|
|
if(affecting?.receive_damage( 0, 10 )) // 10 more burn damage
|
|
electrician.update_damage_overlays()
|
|
to_chat(user, span_notice("You manage to remove the light [fitting], shattering it in process."))
|
|
break_light_tube()
|
|
else
|
|
to_chat(user, span_warning("You try to remove the light [fitting], but you burn your hand on it!"))
|
|
return
|
|
// create a light tube/bulb item and put it in the user's hand
|
|
drop_light_tube(user)
|
|
|
|
/obj/machinery/light/proc/set_major_emergency_light()
|
|
major_emergency = TRUE
|
|
update()
|
|
|
|
/obj/machinery/light/proc/unset_major_emergency_light()
|
|
major_emergency = FALSE
|
|
update()
|
|
|
|
/obj/machinery/light/proc/drop_light_tube(mob/user)
|
|
var/obj/item/light/light_object = new light_type()
|
|
light_object.status = status
|
|
light_object.rigged = rigged
|
|
light_object.brightness = brightness
|
|
|
|
// light item inherits the switchcount, then zero it
|
|
light_object.switchcount = switchcount
|
|
switchcount = 0
|
|
|
|
light_object.update()
|
|
light_object.forceMove(loc)
|
|
|
|
if(user) //puts it in our active hand
|
|
light_object.add_fingerprint(user)
|
|
user.put_in_active_hand(light_object)
|
|
|
|
status = LIGHT_EMPTY
|
|
update()
|
|
return light_object
|
|
|
|
/obj/machinery/light/attack_tk(mob/user)
|
|
if(status == LIGHT_EMPTY)
|
|
to_chat(user, span_warning("There is no [fitting] in this light!"))
|
|
return
|
|
|
|
to_chat(user, span_notice("You telekinetically remove the light [fitting]."))
|
|
// create a light tube/bulb item and put it in the user's hand
|
|
var/obj/item/light/light_tube = drop_light_tube()
|
|
return light_tube.attack_tk(user)
|
|
|
|
// break the light and make sparks if was on
|
|
/obj/machinery/light/proc/break_light_tube(skip_sound_and_sparks = FALSE)
|
|
if(status == LIGHT_EMPTY || status == LIGHT_BROKEN)
|
|
return
|
|
|
|
if(!skip_sound_and_sparks)
|
|
if(status == LIGHT_OK || status == LIGHT_BURNED)
|
|
playsound(loc, 'sound/effects/glasshit.ogg', 75, TRUE)
|
|
if(on)
|
|
do_sparks(3, TRUE, src)
|
|
status = LIGHT_BROKEN
|
|
update()
|
|
|
|
/obj/machinery/light/proc/fix()
|
|
if(status == LIGHT_OK)
|
|
return
|
|
status = LIGHT_OK
|
|
brightness = initial(brightness)
|
|
on = TRUE
|
|
update()
|
|
|
|
/obj/machinery/light/zap_act(power, zap_flags)
|
|
var/explosive = zap_flags & ZAP_MACHINE_EXPLOSIVE
|
|
zap_flags &= ~(ZAP_MACHINE_EXPLOSIVE | ZAP_OBJ_DAMAGE)
|
|
. = ..()
|
|
if(explosive)
|
|
explosion(src, flame_range = 5, adminlog = FALSE)
|
|
qdel(src)
|
|
|
|
// called when area power state changes
|
|
/obj/machinery/light/power_change()
|
|
SHOULD_CALL_PARENT(FALSE)
|
|
var/area/local_area = get_area(src)
|
|
set_on(local_area.lightswitch && local_area.power_light)
|
|
|
|
// called when heated
|
|
|
|
/obj/machinery/light/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
|
|
return exposed_temperature > 673
|
|
|
|
/obj/machinery/light/atmos_expose(datum/gas_mixture/air, exposed_temperature)
|
|
if(prob(max(0, exposed_temperature - 673))) //0% at <400C, 100% at >500C
|
|
break_light_tube()
|
|
|
|
// explode the light
|
|
|
|
/obj/machinery/light/proc/explode()
|
|
set waitfor = 0
|
|
break_light_tube() // break it first to give a warning
|
|
sleep(2)
|
|
explosion(src, light_impact_range = 2, flash_range = -1)
|
|
sleep(1)
|
|
qdel(src)
|
|
|
|
/obj/machinery/light/proc/on_light_eater(obj/machinery/light/source, datum/light_eater)
|
|
SIGNAL_HANDLER
|
|
. = COMPONENT_BLOCK_LIGHT_EATER
|
|
if(status == LIGHT_EMPTY)
|
|
return
|
|
var/obj/item/light/tube = drop_light_tube()
|
|
tube?.burn()
|
|
return
|
|
|
|
|
|
|
|
|
|
/obj/machinery/light/floor
|
|
name = "floor light"
|
|
icon = 'icons/obj/lighting.dmi'
|
|
base_state = "floor" // base description and icon_state
|
|
icon_state = "floor"
|
|
brightness = 4
|
|
layer = LOW_OBJ_LAYER
|
|
plane = FLOOR_PLANE
|
|
light_type = /obj/item/light/bulb
|
|
fitting = "bulb"
|