mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-24 04:28:12 +01:00
Merge branch 'phaser-handbow' of https://github.com/TheDavestDave/VOREStation into phaser-handbow
This commit is contained in:
@@ -306,13 +306,9 @@
|
||||
var/output = {"<form><input type="hidden" name="src" value="\ref[src]"><ul class="sparse">"}
|
||||
if (inputtype == "checkbox" || inputtype == "radio")
|
||||
for (var/i in values)
|
||||
var/div_slider = slidecolor
|
||||
if(!i["allowed_edit"])
|
||||
div_slider = "locked"
|
||||
output += {"<li>
|
||||
<label class="switch">
|
||||
<input type="[inputtype]" value="1" name="[i["name"]]"[i["checked"] ? " checked" : ""][i["allowed_edit"] ? "" : " onclick='return false' onkeydown='return false'"]>
|
||||
<div class="slider [div_slider ? "[div_slider]" : ""]"></div>
|
||||
<input type="[inputtype]" value="1" name="[i["name"]]"[i["checked"] ? " checked" : ""][i["allowed_edit"] ? "" : " disabled onclick='return false' onkeydown='return false'"]>
|
||||
<span>[i["name"]]</span>
|
||||
</label>
|
||||
</li>"}
|
||||
|
||||
@@ -196,6 +196,9 @@ var/list/runechat_image_cache = list()
|
||||
message.maptext_y = message_loc.runechat_y_offset(msgwidth, mheight)
|
||||
message.maptext = complete_text
|
||||
|
||||
if(!owner)
|
||||
qdel(src)
|
||||
return
|
||||
if(owner.contains(target)) // Special case, holding an atom speaking (pAI, recorder...)
|
||||
message.plane = PLANE_PLAYER_HUD_ABOVE
|
||||
|
||||
|
||||
@@ -188,7 +188,11 @@
|
||||
var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types)
|
||||
for(var/sig_type in sig_types)
|
||||
if(!override && procs[target][sig_type])
|
||||
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
|
||||
var/trace_msg = "[sig_type] overridden. Use override = TRUE to suppress this warning."
|
||||
if(isatom(target))
|
||||
var/atom/A = target
|
||||
trace_msg += " [A.x],[A.y],[A.z]"
|
||||
stack_trace(trace_msg)
|
||||
|
||||
procs[target][sig_type] = proctype
|
||||
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
///For switchable lights, is it on and currently emitting light?
|
||||
#define LIGHTING_ON (1<<0)
|
||||
///Is the parent attached to something else, its loc? Then we need to keep an eye of this.
|
||||
#define LIGHTING_ATTACHED (1<<1)
|
||||
|
||||
#define GET_PARENT (parent_attached_to || parent)
|
||||
|
||||
#define GET_LIGHT_SOURCE (directional_atom || current_holder)
|
||||
|
||||
#define SHORT_CAST 2
|
||||
|
||||
/**
|
||||
* Movable atom overlay-based lighting component.
|
||||
*
|
||||
* * Component works by applying a visual object to the parent target.
|
||||
*
|
||||
* * The component tracks the parent's loc to determine the current_holder.
|
||||
* * The current_holder is either the parent or its loc, whichever is on a turf. If none, then the current_holder is null and the light is not visible.
|
||||
*
|
||||
* * Lighting works at its base by applying a dark overlay and "cutting" said darkness with light, adding (possibly colored) transparency.
|
||||
* * This component uses the visible_mask visual object to apply said light mask on the darkness.
|
||||
*
|
||||
* * The main limitation of this system is that it uses a limited number of pre-baked geometrical shapes, but for most uses it does the job.
|
||||
*
|
||||
* * Another limitation is for big lights: you only see the light if you see the object emiting it.
|
||||
* * For small objects this is good (you can't see them behind a wall), but for big ones this quickly becomes prety clumsy.
|
||||
*/
|
||||
/datum/component/overlay_lighting
|
||||
///How far the light reaches, float.
|
||||
var/range = 1
|
||||
///Ceiling of range, integer without decimal entries.
|
||||
var/lumcount_range = 0
|
||||
///How much this light affects the dynamic_lumcount of turfs.
|
||||
var/lum_power = 0.5
|
||||
///Transparency value.
|
||||
var/set_alpha = 0
|
||||
///For light sources that can be turned on and off.
|
||||
var/overlay_lighting_flags = NONE
|
||||
|
||||
///Cache of the possible light overlays, according to size.
|
||||
var/static/list/light_overlays = list(
|
||||
"32" = 'icons/effects/light_overlays/light_32.dmi',
|
||||
"64" = 'icons/effects/light_overlays/light_64.dmi',
|
||||
"96" = 'icons/effects/light_overlays/light_96.dmi',
|
||||
"128" = 'icons/effects/light_overlays/light_128.dmi',
|
||||
"160" = 'icons/effects/light_overlays/light_160.dmi',
|
||||
"192" = 'icons/effects/light_overlays/light_192.dmi',
|
||||
"224" = 'icons/effects/light_overlays/light_224.dmi',
|
||||
"256" = 'icons/effects/light_overlays/light_256.dmi',
|
||||
"288" = 'icons/effects/light_overlays/light_288.dmi',
|
||||
"320" = 'icons/effects/light_overlays/light_320.dmi',
|
||||
"352" = 'icons/effects/light_overlays/light_352.dmi',
|
||||
)
|
||||
|
||||
///Overlay effect to cut into the darkness and provide light.
|
||||
var/obj/effect/overlay/light_visible/visible_mask
|
||||
///Lazy list to track the turfs being affected by our light, to determine their visibility.
|
||||
var/list/turf/affected_turfs
|
||||
///Movable atom currently holding the light. Parent might be a flashlight, for example, but that might be held by a mob or something else.
|
||||
var/atom/movable/current_holder
|
||||
///Movable atom the parent is attached to. For example, a flashlight into a helmet or gun. We'll need to track the thing the parent is attached to as if it were the parent itself.
|
||||
var/atom/movable/parent_attached_to
|
||||
///Whether we're a directional light
|
||||
var/directional
|
||||
///Abstractional atom for directional light, we move this around to make the directional effect
|
||||
var/obj/effect/abstract/directional_lighting/directional_atom
|
||||
///A cone overlay for directional light, it's alpha and color are dependant on the light
|
||||
var/obj/effect/overlay/light_cone/cone
|
||||
///Current tracked direction for the directional cast behaviour
|
||||
var/current_direction
|
||||
///Cast range for the directional cast (how far away the atom is moved)
|
||||
var/cast_range = 2
|
||||
///Cone offset X hint from atom, used when facing south, inverted when facing north
|
||||
var/cone_hint_x
|
||||
///Cone offset Y hint from atom, when facing east/west, ignored for north/south (uses 16 in those cases)
|
||||
var/cone_hint_y
|
||||
|
||||
|
||||
/datum/component/overlay_lighting/Initialize(_range, _power, _color, starts_on, is_directional)
|
||||
if(!ismovable(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
var/atom/movable/movable_parent = parent
|
||||
if(movable_parent.light_system != MOVABLE_LIGHT && movable_parent.light_system != MOVABLE_LIGHT_DIRECTIONAL)
|
||||
stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT] or [MOVABLE_LIGHT_DIRECTIONAL] instead.")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
. = ..()
|
||||
|
||||
visible_mask = new()
|
||||
if(is_directional)
|
||||
directional = TRUE
|
||||
directional_atom = new()
|
||||
cone = new()
|
||||
cone_hint_x = movable_parent.light_cone_x_offset
|
||||
cone_hint_y = movable_parent.light_cone_y_offset
|
||||
cone.transform = cone.transform.Translate(-32, -32)
|
||||
set_direction(movable_parent.dir)
|
||||
if(!isnull(_range))
|
||||
movable_parent.set_light_range(_range)
|
||||
set_range(parent, movable_parent.light_range)
|
||||
if(!isnull(_power))
|
||||
movable_parent.set_light_power(_power)
|
||||
set_power(parent, movable_parent.light_power)
|
||||
if(!isnull(_color))
|
||||
movable_parent.set_light_color(_color)
|
||||
set_color(parent, movable_parent.light_color)
|
||||
if(!isnull(starts_on))
|
||||
movable_parent.set_light_on(starts_on)
|
||||
|
||||
|
||||
/datum/component/overlay_lighting/RegisterWithParent()
|
||||
. = ..()
|
||||
if(directional)
|
||||
RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, .proc/on_parent_dir_change)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/on_parent_moved)
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_RANGE, .proc/set_range)
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_POWER, .proc/set_power)
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_COLOR, .proc/set_color)
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_ON, .proc/on_toggle)
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, .proc/on_light_flags_change)
|
||||
RegisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT, .proc/on_parent_crafted)
|
||||
RegisterSignal(parent, COMSIG_LIGHT_EATER_QUEUE, .proc/on_light_eater)
|
||||
var/atom/movable/movable_parent = parent
|
||||
if(movable_parent.light_flags & LIGHT_ATTACHED)
|
||||
overlay_lighting_flags |= LIGHTING_ATTACHED
|
||||
set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null)
|
||||
check_holder()
|
||||
if(movable_parent.light_on)
|
||||
turn_on()
|
||||
|
||||
|
||||
/datum/component/overlay_lighting/UnregisterFromParent()
|
||||
overlay_lighting_flags &= ~LIGHTING_ATTACHED
|
||||
set_parent_attached_to(null)
|
||||
set_holder(null)
|
||||
clean_old_turfs()
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_MOVABLE_MOVED,
|
||||
COMSIG_ATOM_UPDATE_LIGHT_RANGE,
|
||||
COMSIG_ATOM_UPDATE_LIGHT_POWER,
|
||||
COMSIG_ATOM_UPDATE_LIGHT_COLOR,
|
||||
COMSIG_ATOM_UPDATE_LIGHT_ON,
|
||||
COMSIG_ATOM_UPDATE_LIGHT_FLAGS,
|
||||
COMSIG_ATOM_USED_IN_CRAFT,
|
||||
COMSIG_LIGHT_EATER_QUEUE,
|
||||
))
|
||||
if(directional)
|
||||
UnregisterSignal(parent, COMSIG_ATOM_DIR_CHANGE)
|
||||
if(overlay_lighting_flags & LIGHTING_ON)
|
||||
turn_off()
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/component/overlay_lighting/Destroy()
|
||||
set_parent_attached_to(null)
|
||||
set_holder(null)
|
||||
clean_old_turfs()
|
||||
|
||||
qdel(visible_mask, TRUE)
|
||||
visible_mask = null
|
||||
|
||||
if(directional)
|
||||
qdel(directional_atom, TRUE)
|
||||
directional_atom = null
|
||||
|
||||
qdel(cone, TRUE)
|
||||
cone = null
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
///Clears the affected_turfs lazylist, removing from its contents the effects of being near the light.
|
||||
/datum/component/overlay_lighting/proc/clean_old_turfs()
|
||||
for(var/t in affected_turfs)
|
||||
var/turf/lit_turf = t
|
||||
lit_turf.dynamic_lumcount -= lum_power
|
||||
affected_turfs = null
|
||||
|
||||
|
||||
///Populates the affected_turfs lazylist, adding to its contents the effects of being near the light.
|
||||
/datum/component/overlay_lighting/proc/get_new_turfs()
|
||||
if(!current_holder)
|
||||
return
|
||||
var/atom/movable/light_source = GET_LIGHT_SOURCE
|
||||
for(var/turf/lit_turf in view(lumcount_range, get_turf(light_source)))
|
||||
lit_turf.dynamic_lumcount += lum_power
|
||||
LAZYADD(affected_turfs, lit_turf)
|
||||
|
||||
|
||||
///Clears the old affected turfs and populates the new ones.
|
||||
/datum/component/overlay_lighting/proc/make_luminosity_update()
|
||||
clean_old_turfs()
|
||||
if(!isturf(current_holder?.loc))
|
||||
return
|
||||
if(directional)
|
||||
cast_directional_light()
|
||||
get_new_turfs()
|
||||
|
||||
|
||||
///Adds the luminosity and source for the afected movable atoms to keep track of their visibility.
|
||||
/datum/component/overlay_lighting/proc/add_dynamic_lumi()
|
||||
var/atom/movable/light_source = GET_LIGHT_SOURCE
|
||||
LAZYSET(light_source.affected_dynamic_lights, src, lumcount_range + 1)
|
||||
light_source.vis_contents += visible_mask
|
||||
light_source.update_dynamic_luminosity()
|
||||
if(directional)
|
||||
current_holder.vis_contents += cone
|
||||
|
||||
///Removes the luminosity and source for the afected movable atoms to keep track of their visibility.
|
||||
/datum/component/overlay_lighting/proc/remove_dynamic_lumi()
|
||||
var/atom/movable/light_source = GET_LIGHT_SOURCE
|
||||
LAZYREMOVE(light_source.affected_dynamic_lights, src)
|
||||
light_source.vis_contents -= visible_mask
|
||||
light_source.update_dynamic_luminosity()
|
||||
if(directional)
|
||||
current_holder.vis_contents -= cone
|
||||
directional_atom.moveToNullspace()
|
||||
|
||||
///Called to change the value of parent_attached_to.
|
||||
/datum/component/overlay_lighting/proc/set_parent_attached_to(atom/movable/new_parent_attached_to)
|
||||
if(new_parent_attached_to == parent_attached_to)
|
||||
return
|
||||
|
||||
. = parent_attached_to
|
||||
parent_attached_to = new_parent_attached_to
|
||||
if(.)
|
||||
var/atom/movable/old_parent_attached_to = .
|
||||
UnregisterSignal(old_parent_attached_to, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE))
|
||||
if(old_parent_attached_to == current_holder)
|
||||
RegisterSignal(old_parent_attached_to, COMSIG_PARENT_QDELETING, .proc/on_holder_qdel)
|
||||
RegisterSignal(old_parent_attached_to, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
|
||||
RegisterSignal(old_parent_attached_to, COMSIG_LIGHT_EATER_QUEUE, .proc/on_light_eater)
|
||||
if(parent_attached_to)
|
||||
if(parent_attached_to == current_holder)
|
||||
UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE))
|
||||
RegisterSignal(parent_attached_to, COMSIG_PARENT_QDELETING, .proc/on_parent_attached_to_qdel)
|
||||
RegisterSignal(parent_attached_to, COMSIG_MOVABLE_MOVED, .proc/on_parent_attached_to_moved)
|
||||
RegisterSignal(parent_attached_to, COMSIG_LIGHT_EATER_QUEUE, .proc/on_light_eater)
|
||||
check_holder()
|
||||
|
||||
|
||||
///Called to change the value of current_holder.
|
||||
/datum/component/overlay_lighting/proc/set_holder(atom/movable/new_holder)
|
||||
if(new_holder == current_holder)
|
||||
return
|
||||
if(current_holder)
|
||||
if(current_holder != parent && current_holder != parent_attached_to)
|
||||
UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE))
|
||||
if(directional)
|
||||
UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE)
|
||||
if(overlay_lighting_flags & LIGHTING_ON)
|
||||
remove_dynamic_lumi()
|
||||
current_holder = new_holder
|
||||
if(new_holder == null)
|
||||
clean_old_turfs()
|
||||
return
|
||||
if(new_holder != parent && new_holder != parent_attached_to)
|
||||
RegisterSignal(new_holder, COMSIG_PARENT_QDELETING, .proc/on_holder_qdel)
|
||||
RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
|
||||
RegisterSignal(new_holder, COMSIG_LIGHT_EATER_QUEUE, .proc/on_light_eater)
|
||||
if(directional)
|
||||
RegisterSignal(new_holder, COMSIG_ATOM_DIR_CHANGE, .proc/on_holder_dir_change)
|
||||
if(overlay_lighting_flags & LIGHTING_ON)
|
||||
make_luminosity_update()
|
||||
add_dynamic_lumi()
|
||||
|
||||
|
||||
///Used to determine the new valid current_holder from the parent's loc.
|
||||
/datum/component/overlay_lighting/proc/check_holder()
|
||||
var/atom/movable/movable_parent = GET_PARENT
|
||||
if(isturf(movable_parent.loc))
|
||||
set_holder(movable_parent)
|
||||
return
|
||||
var/atom/inside = movable_parent.loc //Parent's loc
|
||||
if(isnull(inside))
|
||||
set_holder(null)
|
||||
return
|
||||
if(isturf(inside.loc))
|
||||
set_holder(inside)
|
||||
return
|
||||
set_holder(null)
|
||||
|
||||
|
||||
///Called when the current_holder is qdeleted, to remove the light effect.
|
||||
/datum/component/overlay_lighting/proc/on_holder_qdel(atom/movable/source, force)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
|
||||
if(directional)
|
||||
UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE)
|
||||
set_holder(null)
|
||||
|
||||
|
||||
///Called when current_holder changes loc.
|
||||
/datum/component/overlay_lighting/proc/on_holder_moved(atom/movable/source, OldLoc, Dir, Forced)
|
||||
SIGNAL_HANDLER
|
||||
if(!(overlay_lighting_flags & LIGHTING_ON))
|
||||
return
|
||||
make_luminosity_update()
|
||||
|
||||
|
||||
///Called when parent changes loc.
|
||||
/datum/component/overlay_lighting/proc/on_parent_moved(atom/movable/source, OldLoc, Dir, Forced)
|
||||
SIGNAL_HANDLER
|
||||
var/atom/movable/movable_parent = parent
|
||||
if(overlay_lighting_flags & LIGHTING_ATTACHED)
|
||||
set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null)
|
||||
check_holder()
|
||||
if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder)
|
||||
return
|
||||
make_luminosity_update()
|
||||
|
||||
|
||||
///Called when the current_holder is qdeleted, to remove the light effect.
|
||||
/datum/component/overlay_lighting/proc/on_parent_attached_to_qdel(atom/movable/source, force)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(parent_attached_to, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
|
||||
if(directional)
|
||||
UnregisterSignal(parent_attached_to, COMSIG_ATOM_DIR_CHANGE)
|
||||
if(parent_attached_to == current_holder)
|
||||
set_holder(null)
|
||||
set_parent_attached_to(null)
|
||||
|
||||
|
||||
///Called when parent_attached_to changes loc.
|
||||
/datum/component/overlay_lighting/proc/on_parent_attached_to_moved(atom/movable/source, OldLoc, Dir, Forced)
|
||||
SIGNAL_HANDLER
|
||||
check_holder()
|
||||
if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder)
|
||||
return
|
||||
make_luminosity_update()
|
||||
|
||||
|
||||
///Changes the range which the light reaches. 0 means no light, 6 is the maximum value.
|
||||
/datum/component/overlay_lighting/proc/set_range(atom/source, old_range)
|
||||
SIGNAL_HANDLER
|
||||
var/new_range = source.light_range
|
||||
if(range == new_range)
|
||||
return
|
||||
if(range == 0)
|
||||
turn_off()
|
||||
range = clamp(CEILING(new_range, 0.5), 1, 6)
|
||||
var/pixel_bounds = ((range - 1) * 64) + 32
|
||||
lumcount_range = CEILING(range, 1)
|
||||
visible_mask.icon = light_overlays["[pixel_bounds]"]
|
||||
if(pixel_bounds == 32)
|
||||
visible_mask.transform = null
|
||||
return
|
||||
var/offset = (pixel_bounds - 32) * 0.5
|
||||
var/matrix/transform = new
|
||||
transform.Translate(-offset, -offset)
|
||||
visible_mask.transform = transform
|
||||
if(directional)
|
||||
cast_range = clamp(round(new_range * 0.5), 1, 3)
|
||||
if(overlay_lighting_flags & LIGHTING_ON)
|
||||
make_luminosity_update()
|
||||
|
||||
|
||||
///Changes the intensity/brightness of the light by altering the visual object's alpha.
|
||||
/datum/component/overlay_lighting/proc/set_power(atom/source, old_power)
|
||||
SIGNAL_HANDLER
|
||||
var/new_power = source.light_power
|
||||
set_lum_power(new_power >= 0 ? 0.5 : -0.5)
|
||||
set_alpha = min(230, (abs(new_power) * 120) + 30)
|
||||
visible_mask.alpha = set_alpha
|
||||
if(directional)
|
||||
cone.alpha = min(200, (abs(new_power) * 90)+20)
|
||||
|
||||
|
||||
///Changes the light's color, pretty straightforward.
|
||||
/datum/component/overlay_lighting/proc/set_color(atom/source, old_color)
|
||||
SIGNAL_HANDLER
|
||||
var/new_color = source.light_color
|
||||
visible_mask.color = new_color
|
||||
if(directional)
|
||||
cone.color = new_color
|
||||
|
||||
|
||||
///Toggles the light on and off.
|
||||
/datum/component/overlay_lighting/proc/on_toggle(atom/source, old_value)
|
||||
SIGNAL_HANDLER
|
||||
var/new_value = source.light_on
|
||||
if(new_value) //Truthy value input, turn on.
|
||||
turn_on()
|
||||
return
|
||||
turn_off() //Falsey value, turn off.
|
||||
|
||||
|
||||
///Triggered right after the parent light flags change.
|
||||
/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, old_flags)
|
||||
SIGNAL_HANDLER
|
||||
var/new_flags = source.light_flags
|
||||
var/atom/movable/movable_parent = parent
|
||||
if(!((new_flags ^ old_flags) & LIGHT_ATTACHED))
|
||||
return
|
||||
|
||||
if(new_flags & LIGHT_ATTACHED) // Gained the [LIGHT_ATTACHED] property
|
||||
overlay_lighting_flags |= LIGHTING_ATTACHED
|
||||
if(ismovable(movable_parent.loc))
|
||||
set_parent_attached_to(movable_parent.loc)
|
||||
else // Lost the [LIGHT_ATTACHED] property
|
||||
overlay_lighting_flags &= ~LIGHTING_ATTACHED
|
||||
set_parent_attached_to(null)
|
||||
|
||||
|
||||
///Toggles the light on.
|
||||
/datum/component/overlay_lighting/proc/turn_on()
|
||||
if(overlay_lighting_flags & LIGHTING_ON)
|
||||
return
|
||||
if(current_holder)
|
||||
if(directional)
|
||||
cast_directional_light()
|
||||
add_dynamic_lumi()
|
||||
overlay_lighting_flags |= LIGHTING_ON
|
||||
get_new_turfs()
|
||||
|
||||
|
||||
///Toggles the light off.
|
||||
/datum/component/overlay_lighting/proc/turn_off()
|
||||
if(!(overlay_lighting_flags & LIGHTING_ON))
|
||||
return
|
||||
if(current_holder)
|
||||
remove_dynamic_lumi()
|
||||
overlay_lighting_flags &= ~LIGHTING_ON
|
||||
clean_old_turfs()
|
||||
|
||||
|
||||
///Here we append the behavior associated to changing lum_power.
|
||||
/datum/component/overlay_lighting/proc/set_lum_power(new_lum_power)
|
||||
if(lum_power == new_lum_power)
|
||||
return
|
||||
. = lum_power
|
||||
lum_power = new_lum_power
|
||||
var/difference = . - lum_power
|
||||
for(var/t in affected_turfs)
|
||||
var/turf/lit_turf = t
|
||||
lit_turf.dynamic_lumcount -= difference
|
||||
|
||||
///Here we append the behavior associated to changing lum_power.
|
||||
/datum/component/overlay_lighting/proc/cast_directional_light()
|
||||
var/final_distance = cast_range
|
||||
//Lower the distance by 1 if we're not looking at a cardinal direction, and we're not a short cast
|
||||
if(final_distance > SHORT_CAST && !(ALL_CARDINALS & current_direction))
|
||||
final_distance -= 1
|
||||
var/turf/scanning = get_turf(current_holder)
|
||||
for(var/i in 1 to final_distance)
|
||||
var/turf/next_turf = get_step(scanning, current_direction)
|
||||
if(isnull(next_turf) || IS_OPAQUE_TURF(next_turf))
|
||||
break
|
||||
scanning = next_turf
|
||||
directional_atom.forceMove(scanning)
|
||||
|
||||
///Called when current_holder changes loc.
|
||||
/datum/component/overlay_lighting/proc/on_holder_dir_change(atom/movable/source, olddir, newdir)
|
||||
SIGNAL_HANDLER
|
||||
set_direction(newdir)
|
||||
|
||||
///Called when parent changes loc.
|
||||
/datum/component/overlay_lighting/proc/on_parent_dir_change(atom/movable/source, olddir, newdir)
|
||||
SIGNAL_HANDLER
|
||||
set_direction(newdir)
|
||||
|
||||
///Sets a new direction for the directional cast, then updates luminosity
|
||||
/datum/component/overlay_lighting/proc/set_direction(newdir)
|
||||
if(!newdir)
|
||||
return
|
||||
if(current_direction == newdir)
|
||||
return
|
||||
current_direction = newdir
|
||||
cone.set_dir(newdir)
|
||||
|
||||
if(newdir & NORTH)
|
||||
cone.pixel_y = 16
|
||||
else if(newdir & SOUTH)
|
||||
cone.pixel_y = -16
|
||||
else
|
||||
if(!isnull(cone_hint_y))
|
||||
cone.pixel_y = cone_hint_y
|
||||
else
|
||||
cone.pixel_y = 0
|
||||
|
||||
if(newdir & EAST)
|
||||
cone.pixel_x = 16
|
||||
else if(newdir & WEST)
|
||||
cone.pixel_x = -16
|
||||
else
|
||||
if(!isnull(cone_hint_x))
|
||||
if(newdir & NORTH)
|
||||
cone.pixel_x = -1*cone_hint_x
|
||||
else
|
||||
cone.pixel_x = cone_hint_x
|
||||
else
|
||||
cone.pixel_x = 0
|
||||
|
||||
if(overlay_lighting_flags & LIGHTING_ON)
|
||||
make_luminosity_update()
|
||||
|
||||
/datum/component/overlay_lighting/proc/on_parent_crafted(datum/source, atom/movable/new_craft)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!istype(new_craft))
|
||||
return
|
||||
|
||||
UnregisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT)
|
||||
RegisterSignal(new_craft, COMSIG_ATOM_USED_IN_CRAFT, .proc/on_parent_crafted)
|
||||
set_parent_attached_to(new_craft)
|
||||
|
||||
/// Handles putting the source for overlay lights into the light eater queue since we aren't tracked by [/atom/var/light_sources]
|
||||
/datum/component/overlay_lighting/proc/on_light_eater(datum/source, list/light_queue, datum/light_eater)
|
||||
SIGNAL_HANDLER
|
||||
light_queue[parent] = TRUE
|
||||
return NONE
|
||||
|
||||
#undef LIGHTING_ON
|
||||
#undef LIGHTING_ATTACHED
|
||||
#undef GET_PARENT
|
||||
#undef GET_LIGHT_SOURCE
|
||||
#undef SHORT_CAST
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* A holder for simple behaviour that can be attached to many different types
|
||||
*
|
||||
* Only one element of each type is instanced during game init.
|
||||
* Otherwise acts basically like a lightweight component.
|
||||
*/
|
||||
* A holder for simple behaviour that can be attached to many different types
|
||||
*
|
||||
* Only one element of each type is instanced during game init.
|
||||
* Otherwise acts basically like a lightweight component.
|
||||
*/
|
||||
/datum/element
|
||||
/// Option flags for element behaviour
|
||||
var/element_flags = NONE
|
||||
@@ -18,17 +18,23 @@
|
||||
|
||||
/// Activates the functionality defined by the element on the given target datum
|
||||
/datum/element/proc/Attach(datum/target)
|
||||
SHOULD_CALL_PARENT(1)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(type == /datum/element)
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
SEND_SIGNAL(target, COMSIG_ELEMENT_ATTACH, src)
|
||||
if(element_flags & ELEMENT_DETACH)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach, override = TRUE)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/OnTargetDelete, override = TRUE)
|
||||
|
||||
/datum/element/proc/OnTargetDelete(datum/source, force)
|
||||
SIGNAL_HANDLER
|
||||
Detach(source)
|
||||
|
||||
/// Deactivates the functionality defines by the element on the given datum
|
||||
/datum/element/proc/Detach(datum/source, force)
|
||||
/datum/element/proc/Detach(datum/source, ...)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
SEND_SIGNAL(source, COMSIG_ELEMENT_DETACH, src)
|
||||
SHOULD_CALL_PARENT(1)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
UnregisterSignal(source, COMSIG_PARENT_QDELETING)
|
||||
|
||||
/datum/element/Destroy(force)
|
||||
@@ -41,15 +47,21 @@
|
||||
|
||||
/// Finds the singleton for the element type given and attaches it to src
|
||||
/datum/proc/_AddElement(list/arguments)
|
||||
if(QDELING(src))
|
||||
CRASH("We just tried to add an element to a qdeleted datum, something is fucked")
|
||||
var/datum/element/ele = SSdcs.GetElement(arguments)
|
||||
arguments[1] = src
|
||||
if(ele.Attach(arglist(arguments)) == ELEMENT_INCOMPATIBLE)
|
||||
CRASH("Incompatible [arguments[1]] assigned to a [type]! args: [json_encode(args)]")
|
||||
|
||||
/**
|
||||
* Finds the singleton for the element type given and detaches it from src
|
||||
* You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE]
|
||||
*/
|
||||
* Finds the singleton for the element type given and detaches it from src
|
||||
* You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE]
|
||||
*/
|
||||
/datum/proc/_RemoveElement(list/arguments)
|
||||
var/datum/element/ele = SSdcs.GetElement(arguments)
|
||||
ele.Detach(src)
|
||||
if(ele.element_flags & ELEMENT_COMPLEX_DETACH)
|
||||
arguments[1] = src
|
||||
ele.Detach(arglist(arguments))
|
||||
else
|
||||
ele.Detach(src)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Attached to movable atoms with opacity. Listens to them move and updates their old and new turf loc's opacity accordingly.
|
||||
*/
|
||||
/datum/element/light_blocking
|
||||
element_flags = ELEMENT_DETACH
|
||||
|
||||
|
||||
/datum/element/light_blocking/Attach(datum/target)
|
||||
. = ..()
|
||||
if(!ismovable(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/on_target_move)
|
||||
var/atom/movable/movable_target = target
|
||||
if(isturf(movable_target.loc))
|
||||
var/turf/turf_loc = movable_target.loc
|
||||
turf_loc.add_opacity_source(target)
|
||||
|
||||
|
||||
/datum/element/light_blocking/Detach(atom/movable/target)
|
||||
. = ..()
|
||||
UnregisterSignal(target, list(COMSIG_MOVABLE_MOVED))
|
||||
var/atom/movable/movable_target = target
|
||||
if(isturf(movable_target.loc))
|
||||
var/turf/turf_loc = movable_target.loc
|
||||
turf_loc.remove_opacity_source(target)
|
||||
|
||||
|
||||
///Updates old and new turf loc opacities.
|
||||
/datum/element/light_blocking/proc/on_target_move(atom/movable/source, atom/OldLoc, Dir, Forced = FALSE)
|
||||
SIGNAL_HANDLER
|
||||
if(isturf(OldLoc))
|
||||
var/turf/old_turf = OldLoc
|
||||
old_turf.remove_opacity_source(source)
|
||||
if(isturf(source.loc))
|
||||
var/turf/new_turf = source.loc
|
||||
new_turf.add_opacity_source(source)
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
DO NOT USE THIS. THIS IS BEING DEPRECATED BY PROCESSING SUBSYSTEMS (controllers/subsystems/processing) AND TIMERS.
|
||||
*/
|
||||
|
||||
/*
|
||||
README:
|
||||
|
||||
The global_iterator datum is supposed to provide a simple and robust way to
|
||||
create some constantly "looping" processes with ability to stop and restart them at will.
|
||||
Generally, the only thing you want to play with (meaning, redefine) is the process() proc.
|
||||
It must contain all the things you want done.
|
||||
|
||||
Control functions:
|
||||
new - used to create datum. First argument (optional) - var list(to use in process() proc) as list,
|
||||
second (optional) - autostart control.
|
||||
If autostart == TRUE, the loop will be started immediately after datum creation.
|
||||
|
||||
start(list/arguments) - starts the loop. Takes arguments(optional) as a list, which is then used
|
||||
by process() proc. Returns null if datum already active, 1 if loop started succesfully and 0 if there's
|
||||
an error in supplied arguments (not list or empty list).
|
||||
|
||||
stop() - stops the loop. Returns null if datum is already inactive and 1 on success.
|
||||
|
||||
set_delay(new_delay) - sets the delay between iterations. Pretty selfexplanatory.
|
||||
Returns 0 on error(new_delay is not numerical), 1 otherwise.
|
||||
|
||||
set_process_args(list/arguments) - passes the supplied arguments to the process() proc.
|
||||
|
||||
active() - Returns 1 if datum is active, 0 otherwise.
|
||||
|
||||
toggle() - toggles datum state. Returns new datum state (see active()).
|
||||
|
||||
Misc functions:
|
||||
|
||||
get_last_exec_time() - Returns the time of last iteration.
|
||||
|
||||
get_last_exec_time_as_text() - Returns the time of last iteration as text
|
||||
|
||||
|
||||
Control vars:
|
||||
|
||||
delay - delay between iterations
|
||||
|
||||
check_for_null - if equals TRUE, on each iteration the supplied arguments will be checked for nulls.
|
||||
If some varible equals null (and null only), the loop is stopped.
|
||||
Usefull, if some var unexpectedly becomes null - due to object deletion, for example.
|
||||
Of course, you can also check the variables inside process() proc to prevent runtime errors.
|
||||
|
||||
Data storage vars:
|
||||
|
||||
result - stores the value returned by process() proc
|
||||
*/
|
||||
|
||||
/datum/global_iterator
|
||||
var/control_switch = 0
|
||||
var/delay = 10
|
||||
var/list/arg_list = new
|
||||
var/last_exec = null
|
||||
var/check_for_null = 1
|
||||
var/forbid_garbage = 0
|
||||
var/result
|
||||
var/state = 0
|
||||
|
||||
New(list/arguments=null,autostart=1)
|
||||
delay = delay>0?(delay):1
|
||||
if(forbid_garbage) //prevents garbage collection with tag != null
|
||||
tag = "\ref[src]"
|
||||
set_process_args(arguments)
|
||||
if(autostart)
|
||||
start()
|
||||
return
|
||||
|
||||
proc/main()
|
||||
state = 1
|
||||
while(src && control_switch)
|
||||
last_exec = world.timeofday
|
||||
if(check_for_null && has_null_args())
|
||||
stop()
|
||||
return 0
|
||||
result = process(arglist(arg_list))
|
||||
for(var/sleep_time=delay;sleep_time>0;sleep_time--) //uhh, this is ugly. But I see no other way to terminate sleeping proc. Such disgrace.
|
||||
if(!control_switch)
|
||||
return 0
|
||||
sleep(1)
|
||||
return 0
|
||||
|
||||
proc/start(list/arguments=null)
|
||||
if(active())
|
||||
return
|
||||
if(arguments)
|
||||
if(!set_process_args(arguments))
|
||||
return 0
|
||||
if(!state_check()) //the main loop is sleeping, wait for it to terminate.
|
||||
return
|
||||
control_switch = 1
|
||||
spawn()
|
||||
state = main()
|
||||
return 1
|
||||
|
||||
proc/stop()
|
||||
if(!active())
|
||||
return
|
||||
control_switch = 0
|
||||
spawn(-1) //report termination error but don't wait for state_check().
|
||||
state_check()
|
||||
return 1
|
||||
|
||||
proc/state_check()
|
||||
var/lag = 0
|
||||
while(state)
|
||||
sleep(1)
|
||||
if(++lag>10)
|
||||
CRASH("The global_iterator loop \ref[src] failed to terminate in designated timeframe. This may be caused by server lagging.")
|
||||
return 1
|
||||
|
||||
proc/active()
|
||||
return control_switch
|
||||
|
||||
proc/has_null_args()
|
||||
if(null in arg_list)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
proc/set_delay(new_delay)
|
||||
if(isnum(new_delay))
|
||||
delay = max(1, round(new_delay))
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
proc/get_last_exec_time()
|
||||
return (last_exec||0)
|
||||
|
||||
proc/get_last_exec_time_as_text()
|
||||
return (time2text(last_exec)||"Wasn't executed yet")
|
||||
|
||||
proc/set_process_args(list/arguments)
|
||||
if(arguments && istype(arguments, /list) && arguments.len)
|
||||
arg_list = arguments
|
||||
return 1
|
||||
else
|
||||
// to_world("<span class='danger'>Invalid arguments supplied for [src.type], ref = \ref[src]</span>")
|
||||
return 0
|
||||
|
||||
proc/toggle_null_checks()
|
||||
check_for_null = !check_for_null
|
||||
return check_for_null
|
||||
|
||||
proc/toggle()
|
||||
if(!stop())
|
||||
start()
|
||||
return active()
|
||||
|
||||
/datum/global_iterator/Destroy()
|
||||
tag = null
|
||||
arg_list.Cut()
|
||||
stop()
|
||||
return QDEL_HINT_LETMELIVE
|
||||
//Do not call ..()
|
||||
@@ -10,10 +10,13 @@
|
||||
plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE
|
||||
// And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
|
||||
|
||||
// Helper similar to image()
|
||||
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER)
|
||||
/// Helper similar to image()
|
||||
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE)
|
||||
var/mutable_appearance/MA = new()
|
||||
MA.icon = icon
|
||||
MA.icon_state = icon_state
|
||||
MA.layer = layer
|
||||
return MA
|
||||
MA.plane = plane
|
||||
MA.alpha = alpha
|
||||
MA.appearance_flags |= appearance_flags
|
||||
return MA
|
||||
|
||||
@@ -66,7 +66,8 @@
|
||||
/obj/item/weapon/surgical/bonegel,
|
||||
/obj/item/weapon/surgical/retractor,
|
||||
/obj/item/weapon/surgical/bonesetter,
|
||||
/obj/item/weapon/surgical/circular_saw
|
||||
/obj/item/weapon/surgical/circular_saw,
|
||||
/obj/item/weapon/surgical/bioregen
|
||||
)
|
||||
cost = 25
|
||||
containertype = /obj/structure/closet/crate/secure/veymed
|
||||
|
||||
Reference in New Issue
Block a user