mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
540 lines
16 KiB
Plaintext
540 lines
16 KiB
Plaintext
/*
|
|
* Contains:
|
|
* Flashlights
|
|
* Lamps
|
|
* Flares
|
|
* Chemlights
|
|
* Slime Extract
|
|
*/
|
|
|
|
/*
|
|
* Flashlights
|
|
*/
|
|
|
|
/obj/item/flashlight
|
|
name = "flashlight"
|
|
desc = "A hand-held emergency light."
|
|
icon = 'icons/obj/lighting.dmi'
|
|
icon_state = "flashlight"
|
|
w_class = ITEMSIZE_SMALL
|
|
slot_flags = SLOT_BELT
|
|
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
|
|
actions_types = list(/datum/action/item_action/toggle_flashlight)
|
|
|
|
light_system = MOVABLE_LIGHT_DIRECTIONAL
|
|
light_range = 4 //luminosity when on
|
|
light_power = 0.8 //lighting power when on
|
|
light_color = "#FFFFFF" //LIGHT_COLOR_INCANDESCENT_FLASHLIGHT //lighting colour when on
|
|
light_cone_y_offset = -7
|
|
|
|
var/on = 0
|
|
|
|
var/obj/item/cell/cell
|
|
var/cell_type = /obj/item/cell/device
|
|
var/power_usage = 1
|
|
var/power_use = 1
|
|
var/flickering = FALSE
|
|
pickup_sound = 'sound/items/pickup/device.ogg'
|
|
drop_sound = 'sound/items/drop/device.ogg'
|
|
|
|
/obj/item/flashlight/Initialize(mapload)
|
|
. = ..()
|
|
|
|
if(power_use && cell_type)
|
|
cell = new cell_type(src)
|
|
|
|
update_brightness()
|
|
|
|
/obj/item/flashlight/Destroy()
|
|
STOP_PROCESSING(SSobj, src)
|
|
QDEL_NULL(cell)
|
|
return ..()
|
|
|
|
/obj/item/flashlight/get_cell()
|
|
return cell
|
|
|
|
/obj/item/flashlight/process()
|
|
if(!on || !cell)
|
|
return PROCESS_KILL
|
|
|
|
if(power_usage)
|
|
if(cell.use(power_usage) != power_usage) // we weren't able to use our full power_usage amount!
|
|
visible_message(span_warning("\The [src] flickers before going dull."))
|
|
playsound(src, 'sound/effects/sparks3.ogg', 10, 1, -3) //Small cue that your light went dull in your pocket. //VOREStation Edit
|
|
on = 0
|
|
update_brightness()
|
|
return PROCESS_KILL
|
|
|
|
/obj/item/flashlight/proc/update_brightness()
|
|
if(on)
|
|
icon_state = "[initial(icon_state)]-on"
|
|
else
|
|
icon_state = initial(icon_state)
|
|
set_light_on(on)
|
|
if(light_system == STATIC_LIGHT)
|
|
update_light()
|
|
|
|
/obj/item/flashlight/examine(mob/user)
|
|
. = ..()
|
|
if(power_use && cell)
|
|
. += "\The [src] has a \the [cell] attached."
|
|
|
|
if(cell.charge <= cell.maxcharge*0.25)
|
|
. += "It appears to have a low amount of power remaining."
|
|
else if(cell.charge > cell.maxcharge*0.25 && cell.charge <= cell.maxcharge*0.5)
|
|
. += "It appears to have an average amount of power remaining."
|
|
else if(cell.charge > cell.maxcharge*0.5 && cell.charge <= cell.maxcharge*0.75)
|
|
. += "It appears to have an above average amount of power remaining."
|
|
else if(cell.charge > cell.maxcharge*0.75 && cell.charge <= cell.maxcharge)
|
|
. += "It appears to have a high amount of power remaining."
|
|
|
|
/obj/item/flashlight/attack_self(mob/user)
|
|
if(flickering)
|
|
to_chat(user, "The light is currently malfunctioning and you're unable to adjust it!") //To prevent some lighting anomalities.
|
|
return
|
|
if(power_use)
|
|
if(!isturf(user.loc))
|
|
to_chat(user, "You cannot turn the light on while in this [user.loc].") //To prevent some lighting anomalities.
|
|
return 0
|
|
if(!cell || cell.charge == 0)
|
|
to_chat(user, "You flick the switch on [src], but nothing happens.")
|
|
return 0
|
|
on = !on
|
|
if(on && power_use)
|
|
START_PROCESSING(SSobj, src)
|
|
else if(power_use)
|
|
STOP_PROCESSING(SSobj, src)
|
|
playsound(src, 'sound/weapons/empty.ogg', 15, 1, -3) // VOREStation Edit
|
|
update_brightness()
|
|
user.update_mob_action_buttons()
|
|
return 1
|
|
|
|
/obj/item/flashlight/attack(mob/living/M as mob, mob/living/user as mob)
|
|
add_fingerprint(user)
|
|
if(on && user.zone_sel.selecting == O_EYES)
|
|
|
|
if((CLUMSY in user.mutations) && prob(50)) //too dumb to use flashlight properly
|
|
return ..() //just hit them in the head
|
|
|
|
var/mob/living/carbon/human/H = M //mob has protective eyewear
|
|
if(istype(H))
|
|
for(var/obj/item/clothing/C in list(H.head,H.wear_mask,H.glasses))
|
|
if(istype(C) && (C.body_parts_covered & EYES))
|
|
to_chat(user, span_warning("You're going to need to remove [C.name] first."))
|
|
return
|
|
|
|
var/obj/item/organ/vision
|
|
if(H.species.vision_organ)
|
|
vision = H.internal_organs_by_name[H.species.vision_organ]
|
|
if(!vision)
|
|
user.visible_message(span_infoplain(span_bold("\The [user]") + " directs [src] at [M]'s face."), \
|
|
span_notice("You direct [src] at [M]'s face."))
|
|
to_chat(user, span_warning("You can't find any [H.species.vision_organ ? H.species.vision_organ : "eyes"] on [H]!"))
|
|
user.setClickCooldown(user.get_attack_speed(src))
|
|
return
|
|
|
|
user.visible_message(span_infoplain(span_bold("\The [user]") + " directs [src] to [M]'s eyes."), \
|
|
span_notice("You direct [src] to [M]'s eyes."))
|
|
if(H != user) //can't look into your own eyes buster
|
|
if(M.stat == DEAD || M.blinded) //mob is dead or fully blind
|
|
to_chat(user, span_warning("\The [M]'s pupils do not react to the light!"))
|
|
return
|
|
if(XRAY in M.mutations)
|
|
to_chat(user, span_notice("\The [M] pupils give an eerie glow!"))
|
|
if(vision.is_bruised())
|
|
to_chat(user, span_warning("There's visible damage to [M]'s [vision.name]!"))
|
|
else if(M.eye_blurry)
|
|
to_chat(user, span_notice("\The [M]'s pupils react slower than normally."))
|
|
if(M.getBrainLoss() > 15)
|
|
to_chat(user, span_notice("There's visible lag between left and right pupils' reactions."))
|
|
|
|
var/list/pinpoint = list(REAGENT_ID_OXYCODONE=1,REAGENT_ID_TRAMADOL=5)
|
|
var/list/dilating = list(REAGENT_ID_BLISS=5,REAGENT_ID_AMBROSIAEXTRACT=5,REAGENT_ID_MINDBREAKER=1)
|
|
if(M.reagents.has_any_reagent(pinpoint) || H.ingested.has_any_reagent(pinpoint))
|
|
to_chat(user, span_notice("\The [M]'s pupils are already pinpoint and cannot narrow any more."))
|
|
else if(M.reagents.has_any_reagent(dilating) || H.ingested.has_any_reagent(dilating))
|
|
to_chat(user, span_notice("\The [M]'s pupils narrow slightly, but are still very dilated."))
|
|
else
|
|
to_chat(user, span_notice("\The [M]'s pupils narrow."))
|
|
|
|
user.setClickCooldown(user.get_attack_speed(src)) //can be used offensively
|
|
M.flash_eyes()
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/flashlight/attack_hand(mob/user as mob)
|
|
if(user.get_inactive_hand() == src)
|
|
if(cell)
|
|
cell.update_icon()
|
|
user.put_in_hands(cell)
|
|
cell = null
|
|
to_chat(user, span_notice("You remove the cell from the [src]."))
|
|
playsound(src, 'sound/machines/button.ogg', 30, 1, 0)
|
|
on = 0
|
|
update_brightness()
|
|
return
|
|
..()
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/flashlight/MouseDrop(obj/over_object as obj)
|
|
if(!canremove)
|
|
return
|
|
|
|
if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
|
|
|
|
if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
|
|
return
|
|
|
|
if (!( istype(over_object, /atom/movable/screen) ))
|
|
return ..()
|
|
|
|
//makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
|
|
//there's got to be a better way of doing this.
|
|
if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
|
|
return
|
|
|
|
if (( usr.restrained() ) || ( usr.stat ))
|
|
return
|
|
|
|
if ((src.loc == usr) && !(istype(over_object, /atom/movable/screen)) && !usr.unEquip(src))
|
|
return
|
|
|
|
switch(over_object.name)
|
|
if("r_hand")
|
|
usr.u_equip(src)
|
|
usr.put_in_r_hand(src)
|
|
if("l_hand")
|
|
usr.u_equip(src)
|
|
usr.put_in_l_hand(src)
|
|
src.add_fingerprint(usr)
|
|
|
|
/obj/item/flashlight/attackby(obj/item/W, mob/user as mob)
|
|
if(power_use)
|
|
if(istype(W, /obj/item/cell))
|
|
if(istype(W, /obj/item/cell/device))
|
|
if(!cell)
|
|
user.drop_item()
|
|
W.loc = src
|
|
cell = W
|
|
to_chat(user, span_notice("You install a cell in \the [src]."))
|
|
playsound(src, 'sound/machines/button.ogg', 30, 1, 0)
|
|
update_brightness()
|
|
else
|
|
to_chat(user, span_notice("\The [src] already has a cell."))
|
|
else
|
|
to_chat(user, span_notice("\The [src] cannot use that type of cell."))
|
|
|
|
else
|
|
..()
|
|
|
|
/obj/item/flashlight/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
|
. = ..()
|
|
if(!on)
|
|
return
|
|
if(light_system == MOVABLE_LIGHT_DIRECTIONAL)
|
|
var/datum/component/overlay_lighting/OL = GetComponent(/datum/component/overlay_lighting)
|
|
if(!OL)
|
|
return
|
|
var/turf/T = get_turf(target)
|
|
OL.place_directional_light(T)
|
|
|
|
/obj/item/flashlight/proc/flicker(var/amount = rand(10, 20), var/flicker_color, var/forced)
|
|
if(flickering)
|
|
return
|
|
if(!flicker_color)
|
|
flicker_color = light_color //If we don't have a flicker color, use our current light color.
|
|
if((!power_use && !forced) || (!power_usage && !forced))
|
|
return //We don't use power / have no power, so we're probably a flare or dead.
|
|
flickering = TRUE
|
|
var/original_color = light_color
|
|
var/original_on = on
|
|
var/datum/component/overlay_lighting/OL = GetComponent(/datum/component/overlay_lighting) //BEWARE, ESOTERIC BULLSHIT HERE.
|
|
if(flicker_color && light_color != flicker_color)
|
|
set_light_color(flicker_color)
|
|
OL.directional_atom.color = flicker_color
|
|
do_flicker(amount, flicker_color, original_color, original_on, OL, 1)
|
|
|
|
|
|
/// Args:
|
|
/// amount is how many timer to flicker.
|
|
/// flicker_color is what to set the flashlight to when we flicker.
|
|
/// original_color is what our original color was prior to flickering
|
|
/// original_on is if we were originally on or not.
|
|
/// OL is our overlay for lighting.
|
|
/// ticker is how many times we have flickered so far.
|
|
/obj/item/flashlight/proc/do_flicker(var/amount = rand(10, 20), var/flicker_color, var/original_color, var/original_on, var/datum/component/overlay_lighting/OL, var/ticker)
|
|
if(ticker >= amount) //We have flickered enough times. Terminate the cycle.
|
|
finish_flicker(original_color, original_on, OL)
|
|
return
|
|
on = !on
|
|
update_brightness()
|
|
if(!on) // Only play when the light turns off.
|
|
playsound(src, 'sound/effects/light_flicker.ogg', 50, 1)
|
|
addtimer(CALLBACK(src, PROC_REF(do_flicker), amount, flicker_color, original_color, original_on, OL, ++ticker), rand(5,15), TIMER_DELETE_ME)
|
|
|
|
/obj/item/flashlight/proc/finish_flicker(var/original_color, var/original_on, var/datum/component/overlay_lighting/OL)
|
|
set_light_color(original_color)
|
|
OL.directional_atom.color = original_color
|
|
on = original_on
|
|
flickering = FALSE
|
|
update_brightness()
|
|
|
|
|
|
/obj/item/flashlight/pen
|
|
name = "penlight"
|
|
desc = "A pen-sized light, used by medical staff."
|
|
icon_state = "penlight"
|
|
item_state = "pen"
|
|
drop_sound = 'sound/items/drop/accessory.ogg'
|
|
pickup_sound = 'sound/items/pickup/accessory.ogg'
|
|
slot_flags = SLOT_EARS
|
|
light_range = 2
|
|
w_class = ITEMSIZE_TINY
|
|
power_use = 0
|
|
|
|
/obj/item/flashlight/color //Default color is blue
|
|
name = "blue flashlight"
|
|
desc = "A small flashlight. This one is blue."
|
|
icon_state = "flashlight_blue"
|
|
|
|
/obj/item/flashlight/color/green
|
|
name = "green flashlight"
|
|
desc = "A small flashlight. This one is green."
|
|
icon_state = "flashlight_green"
|
|
|
|
/obj/item/flashlight/color/purple
|
|
name = "purple flashlight"
|
|
desc = "A small flashlight. This one is purple."
|
|
icon_state = "flashlight_purple"
|
|
|
|
/obj/item/flashlight/color/red
|
|
name = "red flashlight"
|
|
desc = "A small flashlight. This one is red."
|
|
icon_state = "flashlight_red"
|
|
|
|
/obj/item/flashlight/color/orange
|
|
name = "orange flashlight"
|
|
desc = "A small flashlight. This one is orange."
|
|
icon_state = "flashlight_orange"
|
|
|
|
/obj/item/flashlight/color/yellow
|
|
name = "yellow flashlight"
|
|
desc = "A small flashlight. This one is yellow."
|
|
icon_state = "flashlight_yellow"
|
|
|
|
/obj/item/flashlight/maglight
|
|
name = "maglight"
|
|
desc = "A very, very heavy duty flashlight."
|
|
icon_state = "maglight"
|
|
light_color = LIGHT_COLOR_FLUORESCENT_FLASHLIGHT
|
|
force = 10
|
|
slot_flags = SLOT_BELT
|
|
w_class = ITEMSIZE_SMALL
|
|
attack_verb = list ("smacked", "thwacked", "thunked")
|
|
matter = list(MAT_STEEL = 200,MAT_GLASS = 50)
|
|
hitsound = "swing_hit"
|
|
|
|
/obj/item/flashlight/drone
|
|
name = "low-power flashlight"
|
|
desc = "A miniature lamp, that might be used by small robots."
|
|
icon_state = "penlight"
|
|
item_state = null
|
|
light_range = 2
|
|
w_class = ITEMSIZE_TINY
|
|
power_use = 0
|
|
|
|
/*
|
|
* Lamps
|
|
*/
|
|
|
|
// pixar desk lamp
|
|
/obj/item/flashlight/lamp
|
|
name = "desk lamp"
|
|
desc = "A desk lamp with an adjustable mount."
|
|
icon_state = "lamp"
|
|
force = 10
|
|
center_of_mass_x = 13
|
|
center_of_mass_y = 11
|
|
light_range = 5
|
|
w_class = ITEMSIZE_LARGE
|
|
power_use = 0
|
|
on = 1
|
|
light_system = STATIC_LIGHT
|
|
|
|
/obj/item/flashlight/lamp/verb/toggle_light()
|
|
set name = "Toggle light"
|
|
set category = "Object"
|
|
set src in oview(1)
|
|
|
|
if(!usr.stat)
|
|
attack_self(usr)
|
|
|
|
// green-shaded desk lamp
|
|
/obj/item/flashlight/lamp/green
|
|
desc = "A classic green-shaded desk lamp."
|
|
icon_state = "lampgreen"
|
|
center_of_mass_x = 15
|
|
center_of_mass_y = 11
|
|
light_color = "#FFC58F"
|
|
|
|
// clown lamp
|
|
/obj/item/flashlight/lamp/clown
|
|
desc = "A whacky banana peel shaped lamp."
|
|
icon_state = "bananalamp"
|
|
center_of_mass_x = 15
|
|
center_of_mass_y = 11
|
|
|
|
|
|
/*
|
|
* Flares
|
|
*/
|
|
|
|
/obj/item/flashlight/flare
|
|
name = "flare"
|
|
desc = "A red standard-issue flare. There are instructions on the side reading 'pull cord, make light'."
|
|
w_class = ITEMSIZE_TINY // CHOMPedit: These can fit in more places.
|
|
light_range = 8 // Pretty bright.
|
|
light_power = 0.8
|
|
light_color = LIGHT_COLOR_FLARE
|
|
icon_state = "flare"
|
|
item_state = "flare"
|
|
actions_types = list() //just pull it manually, neckbeard.
|
|
var/fuel = 0
|
|
var/on_damage = 7
|
|
var/produce_heat = 1500
|
|
power_use = 0
|
|
drop_sound = 'sound/items/drop/gloves.ogg'
|
|
pickup_sound = 'sound/items/pickup/gloves.ogg'
|
|
light_system = MOVABLE_LIGHT
|
|
|
|
/obj/item/flashlight/flare/Initialize(mapload)
|
|
fuel = rand(800, 1000) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds.
|
|
. = ..()
|
|
|
|
/obj/item/flashlight/flare/process()
|
|
var/turf/pos = get_turf(src)
|
|
if(pos)
|
|
pos.hotspot_expose(produce_heat, 5)
|
|
fuel = max(fuel - 1, 0)
|
|
if(!fuel || !on)
|
|
turn_off()
|
|
if(!fuel)
|
|
src.icon_state = "[initial(icon_state)]-empty"
|
|
STOP_PROCESSING(SSobj, src)
|
|
|
|
/obj/item/flashlight/flare/proc/turn_off()
|
|
on = 0
|
|
src.force = initial(src.force)
|
|
src.damtype = initial(src.damtype)
|
|
update_brightness()
|
|
|
|
/obj/item/flashlight/flare/attack_self(mob/user)
|
|
|
|
// Usual checks
|
|
if(!fuel)
|
|
to_chat(user, span_notice("It's out of fuel."))
|
|
return
|
|
if(on)
|
|
return
|
|
|
|
. = ..()
|
|
// All good, turn it on.
|
|
if(.)
|
|
user.visible_message(span_notice("[user] activates the flare."), span_notice("You pull the cord on the flare, activating it!"))
|
|
src.force = on_damage
|
|
src.damtype = BURN
|
|
START_PROCESSING(SSobj, src)
|
|
|
|
/obj/item/flashlight/flare/proc/ignite() //Used for flare launchers.
|
|
on = !on
|
|
update_brightness()
|
|
force = on_damage
|
|
damtype = BURN
|
|
START_PROCESSING(SSobj, src)
|
|
return 1
|
|
|
|
/*
|
|
* Chemlights
|
|
*/
|
|
|
|
/obj/item/flashlight/glowstick
|
|
name = "green glowstick"
|
|
desc = "A green military-grade chemical light."
|
|
w_class = ITEMSIZE_TINY // CHOMPedit: These can fit in more places.
|
|
light_system = MOVABLE_LIGHT
|
|
light_range = 4
|
|
light_power = 0.9
|
|
light_color = "#49F37C"
|
|
icon_state = "glowstick_green"
|
|
item_state = "glowstick_green"
|
|
var/fuel = 0
|
|
power_use = 0
|
|
|
|
/obj/item/flashlight/glowstick/Initialize(mapload)
|
|
fuel = rand(1600, 2000)
|
|
. = ..()
|
|
|
|
/obj/item/flashlight/glowstick/process()
|
|
fuel = max(fuel - 1, 0)
|
|
if(!fuel || !on)
|
|
turn_off()
|
|
if(!fuel)
|
|
src.icon_state = "[initial(icon_state)]-empty"
|
|
STOP_PROCESSING(SSobj, src)
|
|
|
|
/obj/item/flashlight/glowstick/proc/turn_off()
|
|
on = 0
|
|
update_brightness()
|
|
|
|
/obj/item/flashlight/glowstick/attack_self(mob/user)
|
|
|
|
if(!fuel)
|
|
to_chat(user, span_notice("The glowstick has already been turned on."))
|
|
return
|
|
if(on)
|
|
return
|
|
|
|
. = ..()
|
|
if(.)
|
|
user.visible_message(span_notice("[user] cracks and shakes \the [name]."), span_notice("You crack and shake \the [src], turning it on!"))
|
|
START_PROCESSING(SSobj, src)
|
|
|
|
/obj/item/flashlight/glowstick/red
|
|
name = "red glowstick"
|
|
desc = "A red military-grade chemical light."
|
|
light_color = "#FC0F29"
|
|
icon_state = "glowstick_red"
|
|
item_state = "glowstick_red"
|
|
|
|
/obj/item/flashlight/glowstick/blue
|
|
name = "blue glowstick"
|
|
desc = "A blue military-grade chemical light."
|
|
light_color = "#599DFF"
|
|
icon_state = "glowstick_blue"
|
|
item_state = "glowstick_blue"
|
|
|
|
/obj/item/flashlight/glowstick/orange
|
|
name = "orange glowstick"
|
|
desc = "A orange military-grade chemical light."
|
|
light_color = "#FA7C0B"
|
|
icon_state = "glowstick_orange"
|
|
item_state = "glowstick_orange"
|
|
|
|
/obj/item/flashlight/glowstick/yellow
|
|
name = "yellow glowstick"
|
|
desc = "A yellow military-grade chemical light."
|
|
light_color = "#FEF923"
|
|
icon_state = "glowstick_yellow"
|
|
item_state = "glowstick_yellow"
|
|
|
|
/obj/item/flashlight/glowstick/radioisotope
|
|
name = "radioisotope glowstick"
|
|
desc = "A radioisotope powered chemical light. Escaping particles light up the area far brighter on similar levels to flares and for longer"
|
|
icon_state = "glowstick_isotope"
|
|
item_state = "glowstick_isotope"
|
|
|
|
light_range = 8
|
|
light_power = 0.1
|
|
light_color = "#49F37C"
|