mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-21 15:46:39 +01:00
313 lines
6.7 KiB
Plaintext
313 lines
6.7 KiB
Plaintext
/obj/item/assembly/infra
|
|
name = "infrared emitter"
|
|
desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted."
|
|
icon_state = "infrared"
|
|
origin_tech = list(TECH_MAGNET = 2)
|
|
materials_base = list(MAT_STEEL = 1000, MAT_GLASS = 500)
|
|
|
|
wires = WIRE_PULSE
|
|
|
|
secured = FALSE
|
|
|
|
/// on or off?
|
|
var/on = FALSE
|
|
/// visible beam?
|
|
var/visible = FALSE
|
|
/// head of beam
|
|
var/obj/effect/beam/i_beam/head
|
|
/// range of beam - capped to 100
|
|
var/range = 8
|
|
/// requires rebuild?
|
|
var/dirty = FALSE
|
|
/// current atom listening to
|
|
var/atom/movable/listening
|
|
var/hearing_range = 3
|
|
|
|
/obj/item/assembly/infra/activate()
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
if(on)
|
|
turn_off()
|
|
else
|
|
turn_on()
|
|
|
|
/obj/item/assembly/infra/toggle_secure()
|
|
secured = !secured
|
|
if(!secured)
|
|
turn_off()
|
|
return secured
|
|
|
|
/obj/item/assembly/infra/proc/turn_on()
|
|
if(!secured)
|
|
turn_off()
|
|
return
|
|
if(on)
|
|
return
|
|
on = TRUE
|
|
Rebuild()
|
|
update_icon()
|
|
START_PROCESSING(SSprocess_5fps, src)
|
|
|
|
/obj/item/assembly/infra/proc/turn_off()
|
|
if(!on)
|
|
return
|
|
if(listening)
|
|
UnregisterSignal(listening, COMSIG_MOVABLE_MOVED)
|
|
listening = null
|
|
on = FALSE
|
|
Rebuild()
|
|
update_icon()
|
|
STOP_PROCESSING(SSprocess_5fps, src)
|
|
|
|
/obj/item/assembly/infra/update_icon()
|
|
cut_overlays()
|
|
attached_overlays = list()
|
|
if(on)
|
|
add_overlay("infrared_on")
|
|
attached_overlays += "infrared_on" // TODO: Investigate???
|
|
if(holder)
|
|
holder.update_icon()
|
|
|
|
/obj/item/assembly/infra/proc/toggle_visible()
|
|
visible = !visible
|
|
head?.SetVisible(visible)
|
|
|
|
/obj/item/assembly/infra/setDir()
|
|
var/old = dir
|
|
. = ..()
|
|
if(old == dir)
|
|
return
|
|
Queue()
|
|
|
|
/obj/item/assembly/infra/proc/Queue()
|
|
dirty = TRUE
|
|
|
|
/obj/item/assembly/infra/proc/Rebuild()
|
|
if(head)
|
|
if(!QDELETED(head))
|
|
QDEL_NULL(head)
|
|
head = null
|
|
if(!on || QDELETED(src))
|
|
return
|
|
if(!loc)
|
|
return
|
|
if(ismovable(loc)) // register listener
|
|
if(listening)
|
|
UnregisterSignal(listening, COMSIG_MOVABLE_MOVED)
|
|
listening = loc
|
|
RegisterSignal(loc, COMSIG_MOVABLE_MOVED, PROC_REF(Queue))
|
|
if(!isturf(loc) && !isturf(loc.loc)) // only allow nesting 1 deep
|
|
return
|
|
// spread
|
|
var/obj/effect/beam/i_beam/I = new(loc, src, range - 1, visible, null)
|
|
I.density = TRUE
|
|
I.setDir(dir)
|
|
step(I, I.dir)
|
|
// did it work?
|
|
if(QDELETED(I))
|
|
// nope
|
|
return
|
|
else
|
|
head = I
|
|
head.density = FALSE
|
|
head.Propagate()
|
|
dirty = FALSE
|
|
|
|
/obj/item/assembly/infra/process(delta_time)
|
|
if(!on || QDELETED(src))
|
|
Rebuild()
|
|
return PROCESS_KILL
|
|
if(QDELETED(head) || dirty)
|
|
Rebuild()
|
|
return
|
|
head.Refresh()
|
|
|
|
/obj/item/assembly/infra/Move()
|
|
var/old_dir = dir
|
|
. = ..()
|
|
setDir(old_dir)
|
|
Queue()
|
|
|
|
/obj/item/assembly/infra/doMove()
|
|
. = ..()
|
|
Queue()
|
|
|
|
/obj/item/assembly/infra/holder_movement()
|
|
if(!holder)
|
|
return FALSE
|
|
setDir(holder.dir)
|
|
Queue()
|
|
return TRUE
|
|
|
|
/obj/item/assembly/infra/Moved(atom/oldloc)
|
|
. = ..()
|
|
if(listening)
|
|
UnregisterSignal(listening, COMSIG_MOVABLE_MOVED)
|
|
if(on && ismovable(loc))
|
|
RegisterSignal(loc, COMSIG_MOVABLE_MOVED, PROC_REF(Queue))
|
|
listening = loc
|
|
|
|
/obj/item/assembly/infra/proc/trigger_beam()
|
|
if((!secured)||(!on)||(cooldown > 0))
|
|
return FALSE
|
|
pulse(0)
|
|
if(!holder)
|
|
audible_message(SPAN_INFOPLAIN("[icon2html(src, hearers(src))] *beep* *beep* *beep*"), null, hearing_range)
|
|
for(var/mob/hearing_mob in get_hearers_in_view(hearing_range, src))
|
|
hearing_mob.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
|
cooldown = 2
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/assembly, process_cooldown)), 10)
|
|
|
|
/obj/item/assembly/infra/ui_interact(mob/user, datum/tgui/ui)
|
|
if(!secured)
|
|
to_chat(user, SPAN_WARNING("[src] is unsecured!"))
|
|
return FALSE
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "AssemblyInfrared", name)
|
|
ui.open()
|
|
|
|
/obj/item/assembly/infra/ui_data(mob/user, datum/tgui/ui)
|
|
var/list/data = ..()
|
|
|
|
data["on"] = on
|
|
data["visible"] = visible
|
|
|
|
return data
|
|
|
|
/obj/item/assembly/infra/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state, datum/event_args/actor/actor)
|
|
if(..())
|
|
return TRUE
|
|
|
|
switch(action)
|
|
if("state")
|
|
activate()
|
|
return TRUE
|
|
if("visible")
|
|
visible = !visible
|
|
for(var/ibeam in head)
|
|
var/obj/effect/beam/i_beam/I = ibeam
|
|
I.visible = visible
|
|
CHECK_TICK
|
|
return TRUE
|
|
|
|
/obj/item/assembly/infra/verb/rotate_clockwise()
|
|
set name = "Rotate Infrared Laser Clockwise"
|
|
set category = VERB_CATEGORY_OBJECT
|
|
set src in usr
|
|
|
|
setDir(turn(dir, 90))
|
|
|
|
/***************************IBeam*********************************/
|
|
|
|
/obj/effect/beam/i_beam
|
|
name = "i beam"
|
|
icon = 'icons/obj/projectiles.dmi'
|
|
icon_state = "ibeam"
|
|
anchored = TRUE
|
|
pass_flags = ATOM_PASS_TABLE|ATOM_PASS_GLASS|ATOM_PASS_GRILLE
|
|
/// the next beam
|
|
var/obj/effect/beam/i_beam/next
|
|
/// the previous beam
|
|
var/obj/effect/beam/i_beam/prev
|
|
/// master assembly
|
|
var/obj/item/assembly/infra/master
|
|
/// are we visible?
|
|
var/visible = FALSE
|
|
/// beam segments left, excluding this one
|
|
var/propagate = 0
|
|
|
|
/obj/effect/beam/i_beam/Initialize(mapload, _master, _propagate, _visible, _prev)
|
|
. = ..()
|
|
if(_propagate)
|
|
src.propagate = min(100, _propagate)
|
|
if(_master)
|
|
src.master = _master
|
|
if(_visible)
|
|
visible = _visible
|
|
if(_prev)
|
|
prev = _prev
|
|
invisibility = visible? 0 : 101
|
|
|
|
/obj/effect/beam/i_beam/Destroy()
|
|
master = null
|
|
if(next)
|
|
if(!QDELETED(next))
|
|
qdel(next)
|
|
next = null
|
|
if(prev)
|
|
if(prev.next == src)
|
|
prev.next = null
|
|
return ..()
|
|
|
|
/**
|
|
* Both handles beam propagation, and triggering if the beam suddenly finds itself on an dense atom.
|
|
*/
|
|
/obj/effect/beam/i_beam/proc/Propagate()
|
|
propagate = min(100, propagate)
|
|
if(next)
|
|
if(!QDELETED(next))
|
|
qdel(next)
|
|
next = null
|
|
if(!loc || !master)
|
|
if(!QDELETED(src))
|
|
qdel(src)
|
|
return
|
|
if(propagate <= 0)
|
|
return
|
|
if(!next)
|
|
// spread
|
|
var/obj/effect/beam/i_beam/I = new type(loc, master, propagate - 1, visible, src)
|
|
I.density = TRUE
|
|
I.setDir(dir)
|
|
step(I, I.dir)
|
|
// did it work?
|
|
if(QDELETED(I))
|
|
// nope
|
|
return
|
|
else
|
|
next = I
|
|
next.density = FALSE
|
|
next.Propagate()
|
|
|
|
/obj/effect/beam/i_beam/proc/Refresh()
|
|
if(!next)
|
|
if(propagate > 0)
|
|
Propagate()
|
|
return
|
|
// propagate vis and force rest to checks
|
|
invisibility = visible? 0 : 101
|
|
if(next)
|
|
next.visible = visible
|
|
next.Refresh()
|
|
|
|
/obj/effect/beam/i_beam/proc/SetVisible(new_vis)
|
|
visible = new_vis
|
|
Refresh()
|
|
|
|
/obj/effect/beam/i_beam/proc/Trigger(atom/A)
|
|
if(master)
|
|
master.trigger_beam()
|
|
qdel(src)
|
|
|
|
/obj/effect/beam/i_beam/Bump(atom/movable/AM)
|
|
. = ..()
|
|
qdel(src)
|
|
|
|
// only useful during Propagate() since density is TRUE there.
|
|
/obj/effect/beam/i_beam/Bumped(atom/movable/AM)
|
|
. = ..()
|
|
Trigger(AM)
|
|
|
|
// we need to refactor this at some point holy shit, infrared grids are so awful right now.
|
|
/obj/effect/beam/i_beam/Crossed(atom/movable/AM)
|
|
. = ..()
|
|
if(AM.is_incorporeal())
|
|
return
|
|
if(istype(AM, /obj/effect/beam))
|
|
return
|
|
if(isobserver(AM))
|
|
return
|
|
Trigger(AM)
|