diff --git a/code/datums/chat_message.dm b/code/datums/chat_message.dm
index a625d0cd58..ae17f21e2d 100644
--- a/code/datums/chat_message.dm
+++ b/code/datums/chat_message.dm
@@ -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
diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm
new file mode 100644
index 0000000000..a037e7fab1
--- /dev/null
+++ b/code/datums/components/overlay_lighting.dm
@@ -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
diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm
index 5958f79d00..387adcd6c8 100644
--- a/code/game/objects/effects/misc.dm
+++ b/code/game/objects/effects/misc.dm
@@ -61,4 +61,92 @@
/obj/effect/temporary_effect/lightning_strike/Initialize()
icon_state += "[rand(1,2)]" // To have two variants of lightning sprites.
animate(src, alpha = 0, time = time_to_die - 1)
- . = ..()
\ No newline at end of file
+<<<<<<< HEAD
+ . = ..()
+||||||| parent of e749537a98... Merge pull request #10683 from VOREStation/Arokha/runtimes
+ . = ..()
+
+/obj/effect/dummy/lighting_obj
+ name = "lighting fx obj"
+ desc = "Tell a coder if you're seeing this."
+ icon_state = "nothing"
+ light_system = MOVABLE_LIGHT
+ light_range = MINIMUM_USEFUL_LIGHT_RANGE
+ light_color = COLOR_WHITE
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ light_on = TRUE
+ blocks_emissive = FALSE
+
+/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration)
+ . = ..()
+ if(!isnull(_range))
+ set_light_range(_range)
+ if(!isnull(_power))
+ set_light_power(_power)
+ if(!isnull(_color))
+ set_light_color(_color)
+ if(_duration)
+ QDEL_IN(src, _duration)
+
+/obj/effect/dummy/lighting_obj/moblight
+ name = "mob lighting fx"
+
+/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration)
+ . = ..()
+ if(!ismob(loc))
+ return INITIALIZE_HINT_QDEL
+
+/obj/effect/dummy/lighting_obj/moblight/fire
+ name = "fire"
+ light_color = LIGHT_COLOR_FIRE
+ light_range = LIGHT_RANGE_FIRE
+
+/obj/effect/abstract/directional_lighting
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+=======
+ . = ..()
+
+/obj/effect/dummy/lighting_obj
+ name = "lighting fx obj"
+ desc = "Tell a coder if you're seeing this."
+ icon_state = "nothing"
+ light_system = MOVABLE_LIGHT
+ light_range = MINIMUM_USEFUL_LIGHT_RANGE
+ light_color = COLOR_WHITE
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ light_on = TRUE
+ blocks_emissive = FALSE
+
+/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration)
+ . = ..()
+ if(!isnull(_range))
+ set_light_range(_range)
+ if(!isnull(_power))
+ set_light_power(_power)
+ if(!isnull(_color))
+ set_light_color(_color)
+ if(_duration)
+ QDEL_IN(src, _duration)
+
+/obj/effect/dummy/lighting_obj/moblight
+ name = "mob lighting fx"
+
+/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration)
+ . = ..()
+ if(!ismob(loc))
+ return INITIALIZE_HINT_QDEL
+
+/obj/effect/dummy/lighting_obj/moblight/fire
+ name = "fire"
+ light_color = LIGHT_COLOR_FIRE
+ light_range = LIGHT_RANGE_FIRE
+
+/obj/effect/abstract/directional_lighting
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+
+/obj/effect/abstract/directional_lighting/Destroy(force)
+ if(!force)
+ stack_trace("Directional light atom deleted, but not by our component")
+ return QDEL_HINT_LETMELIVE
+ return ..()
+>>>>>>> e749537a98... Merge pull request #10683 from VOREStation/Arokha/runtimes
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index b1c00bb79a..146ddebd3b 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -111,3 +111,108 @@
plane = PLANE_LIGHTING_ABOVE
pixel_x = -32
pixel_y = -32
+<<<<<<< HEAD
+||||||| parent of e749537a98... Merge pull request #10683 from VOREStation/Arokha/runtimes
+
+/obj/effect/overlay/vis
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ anchored = TRUE
+ vis_flags = VIS_INHERIT_DIR
+ ///When detected to be unused it gets set to world.time, after a while it gets removed
+ var/unused = 0
+ ///overlays which go unused for this amount of time get cleaned up
+ var/cache_expiration = 2 MINUTES
+
+/*
+/obj/effect/overlay/atmos_excited
+ name = "excited group"
+ icon = null
+ icon_state = null
+ anchored = TRUE // should only appear in vis_contents, but to be safe
+ appearance_flags = RESET_TRANSFORM | TILE_BOUND
+ invisibility = INVISIBILITY_ABSTRACT
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+
+ plane = ATMOS_GROUP_PLANE
+*/
+
+/obj/effect/overlay/light_visible
+ name = ""
+ icon = 'icons/effects/light_overlays/light_32.dmi'
+ icon_state = "light"
+ plane = PLANE_O_LIGHTING_VISUAL
+ appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ alpha = 0
+ vis_flags = NONE
+ blocks_emissive = FALSE
+
+/obj/effect/overlay/light_cone
+ name = ""
+ icon = 'icons/effects/light_overlays/light_cone.dmi'
+ icon_state = "light"
+ plane = PLANE_O_LIGHTING_VISUAL
+ appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ vis_flags = NONE
+ alpha = 110
+ blocks_emissive = FALSE
+
+=======
+
+/obj/effect/overlay/vis
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ anchored = TRUE
+ vis_flags = VIS_INHERIT_DIR
+ ///When detected to be unused it gets set to world.time, after a while it gets removed
+ var/unused = 0
+ ///overlays which go unused for this amount of time get cleaned up
+ var/cache_expiration = 2 MINUTES
+
+/*
+/obj/effect/overlay/atmos_excited
+ name = "excited group"
+ icon = null
+ icon_state = null
+ anchored = TRUE // should only appear in vis_contents, but to be safe
+ appearance_flags = RESET_TRANSFORM | TILE_BOUND
+ invisibility = INVISIBILITY_ABSTRACT
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+
+ plane = ATMOS_GROUP_PLANE
+*/
+
+/obj/effect/overlay/light_visible
+ name = ""
+ icon = 'icons/effects/light_overlays/light_32.dmi'
+ icon_state = "light"
+ plane = PLANE_O_LIGHTING_VISUAL
+ appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ alpha = 0
+ vis_flags = NONE
+ blocks_emissive = FALSE
+
+/obj/effect/overlay/light_visible/Destroy(force)
+ if(!force)
+ stack_trace("Movable light visible mask deleted, but not by our component")
+ return QDEL_HINT_LETMELIVE
+ return ..()
+
+/obj/effect/overlay/light_cone
+ name = ""
+ icon = 'icons/effects/light_overlays/light_cone.dmi'
+ icon_state = "light"
+ plane = PLANE_O_LIGHTING_VISUAL
+ appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ vis_flags = NONE
+ alpha = 110
+ blocks_emissive = FALSE
+
+/obj/effect/overlay/light_cone/Destroy(force)
+ if(!force)
+ stack_trace("Directional light cone deleted, but not by our component")
+ return QDEL_HINT_LETMELIVE
+ return ..()
+>>>>>>> e749537a98... Merge pull request #10683 from VOREStation/Arokha/runtimes
diff --git a/code/modules/artifice/telecube.dm b/code/modules/artifice/telecube.dm
index 581b1791f8..6e7db1ebfe 100644
--- a/code/modules/artifice/telecube.dm
+++ b/code/modules/artifice/telecube.dm
@@ -129,7 +129,7 @@
/obj/item/weapon/telecube/proc/teleport_to_mate(var/atom/movable/A, var/areaporting = FALSE)
. = FALSE
- if(!A)
+ if(!istype(A))
return .
if(A == src || A == mate)
diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm
index 22ae47b4c4..6c4ab1db13 100644
--- a/code/modules/awaymissions/gateway.dm
+++ b/code/modules/awaymissions/gateway.dm
@@ -148,6 +148,114 @@ obj/machinery/gateway/centerstation/process()
if(dest)
M.forceMove(dest.loc)
M.set_dir(SOUTH)
+<<<<<<< HEAD
+||||||| parent of e749537a98... Merge pull request #10683 from VOREStation/Arokha/runtimes
+ //VOREStation Addition Start: Mcguffin time!
+ if(istype(M, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = M
+ if(!H.client)
+ awaygate.entrydetect()
+ //VOREStation Addition End: Mcguffin time!
+
+ //VOREStation Addition Start: Abduction!
+ if(istype(M, /mob/living) && dest.abductor)
+ var/mob/living/L = M
+ //Situations to get the mob out of
+ if(L.buckled)
+ L.buckled.unbuckle_mob()
+ if(istype(L.loc,/obj/mecha))
+ var/obj/mecha/ME = L.loc
+ ME.go_out()
+ else if(istype(L.loc,/obj/machinery/sleeper))
+ var/obj/machinery/sleeper/SL = L.loc
+ SL.go_out()
+ else if(istype(L.loc,/obj/machinery/recharge_station))
+ var/obj/machinery/recharge_station/RS = L.loc
+ RS.go_out()
+ if(!issilicon(L)) //Don't drop borg modules...
+ var/list/mob_contents = list() //Things which are actually drained as a result of the above not being null.
+ mob_contents |= L // The recursive check below does not add the object being checked to its list.
+ mob_contents |= recursive_content_check(L, mob_contents, recursion_limit = 3, client_check = 0, sight_check = 0, include_mobs = 1, include_objects = 1, ignore_show_messages = 1)
+ for(var/obj/item/weapon/holder/I in mob_contents)
+ var/obj/item/weapon/holder/H = I
+ var/mob/living/MI = H.held_mob
+ MI.forceMove(get_turf(H))
+ if(!issilicon(MI)) //Don't drop borg modules...
+ for(var/obj/item/II in MI)
+ if(istype(II,/obj/item/weapon/implant) || istype(II,/obj/item/device/nif))
+ continue
+ MI.drop_from_inventory(II, dest.loc)
+ var/obj/effect/landmark/finaldest = pick(awayabductors)
+ MI.forceMove(finaldest.loc)
+ sleep(1)
+ MI.Paralyse(10)
+ MI << 'sound/effects/bamf.ogg'
+ to_chat(MI,"You're starting to come to. You feel like you've been out for a few minutes, at least...")
+ for(var/obj/item/I in L)
+ if(istype(I,/obj/item/weapon/implant) || istype(I,/obj/item/device/nif))
+ continue
+ L.drop_from_inventory(I, dest.loc)
+ var/obj/effect/landmark/finaldest = pick(awayabductors)
+ L.forceMove(finaldest.loc)
+ sleep(1)
+ L.Paralyse(10)
+ L << 'sound/effects/bamf.ogg'
+ to_chat(L,"You're starting to come to. You feel like you've been out for a few minutes, at least...")
+ //VOREStation Addition End
+=======
+ //VOREStation Addition Start: Mcguffin time!
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(H.client)
+ awaygate.entrydetect()
+ //VOREStation Addition End: Mcguffin time!
+
+ //VOREStation Addition Start: Abduction!
+ if(istype(M, /mob/living) && dest.abductor)
+ var/mob/living/L = M
+ //Situations to get the mob out of
+ if(L.buckled)
+ L.buckled.unbuckle_mob()
+ if(istype(L.loc,/obj/mecha))
+ var/obj/mecha/ME = L.loc
+ ME.go_out()
+ else if(istype(L.loc,/obj/machinery/sleeper))
+ var/obj/machinery/sleeper/SL = L.loc
+ SL.go_out()
+ else if(istype(L.loc,/obj/machinery/recharge_station))
+ var/obj/machinery/recharge_station/RS = L.loc
+ RS.go_out()
+ if(!issilicon(L)) //Don't drop borg modules...
+ var/list/mob_contents = list() //Things which are actually drained as a result of the above not being null.
+ mob_contents |= L // The recursive check below does not add the object being checked to its list.
+ mob_contents |= recursive_content_check(L, mob_contents, recursion_limit = 3, client_check = 0, sight_check = 0, include_mobs = 1, include_objects = 1, ignore_show_messages = 1)
+ for(var/obj/item/weapon/holder/I in mob_contents)
+ var/obj/item/weapon/holder/H = I
+ var/mob/living/MI = H.held_mob
+ MI.forceMove(get_turf(H))
+ if(!issilicon(MI)) //Don't drop borg modules...
+ for(var/obj/item/II in MI)
+ if(istype(II,/obj/item/weapon/implant) || istype(II,/obj/item/device/nif))
+ continue
+ MI.drop_from_inventory(II, dest.loc)
+ var/obj/effect/landmark/finaldest = pick(awayabductors)
+ MI.forceMove(finaldest.loc)
+ sleep(1)
+ MI.Paralyse(10)
+ MI << 'sound/effects/bamf.ogg'
+ to_chat(MI,"You're starting to come to. You feel like you've been out for a few minutes, at least...")
+ for(var/obj/item/I in L)
+ if(istype(I,/obj/item/weapon/implant) || istype(I,/obj/item/device/nif))
+ continue
+ L.drop_from_inventory(I, dest.loc)
+ var/obj/effect/landmark/finaldest = pick(awayabductors)
+ L.forceMove(finaldest.loc)
+ sleep(1)
+ L.Paralyse(10)
+ L << 'sound/effects/bamf.ogg'
+ to_chat(L,"You're starting to come to. You feel like you've been out for a few minutes, at least...")
+ //VOREStation Addition End
+>>>>>>> e749537a98... Merge pull request #10683 from VOREStation/Arokha/runtimes
return
/obj/machinery/gateway/centerstation/attackby(obj/item/device/W as obj, mob/user as mob)
diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm
index 5c2c55cf98..059905c36e 100644
--- a/code/modules/clothing/spacesuits/rig/rig.dm
+++ b/code/modules/clothing/spacesuits/rig/rig.dm
@@ -731,8 +731,8 @@
to_chat(H, "Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.")
playsound(src, 'sound/machines/rig/rigservo.ogg', 10, FALSE)
- if(piece == "helmet" && helmet)
- helmet.update_light(H)
+ if(piece == "helmet" && helmet?.light_system == STATIC_LIGHT)
+ helmet.update_light()
/obj/item/weapon/rig/proc/deploy(mob/M,var/sealed)
diff --git a/code/modules/clothing/spacesuits/void/void.dm b/code/modules/clothing/spacesuits/void/void.dm
index 81ba938ff9..a7480034ff 100644
--- a/code/modules/clothing/spacesuits/void/void.dm
+++ b/code/modules/clothing/spacesuits/void/void.dm
@@ -184,7 +184,9 @@
helmet.pickup(H)
helmet.canremove = 0
to_chat(H, "You deploy your suit helmet, sealing you off from the world.")
- helmet.update_light(H)
+
+ if(helmet.light_system == STATIC_LIGHT)
+ helmet.update_light()
/obj/item/clothing/suit/space/void/verb/eject_tank()
diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm
index 954b299b08..1733072284 100644
--- a/code/modules/food/food/snacks.dm
+++ b/code/modules/food/food/snacks.dm
@@ -6470,14 +6470,14 @@
nutriment_amt = 6
bitesize = 1
-/obj/item/weapon/reagent_containers/food/snacks/squid //ADDITION 04/11/2021
+/obj/item/weapon/reagent_containers/food/snacks/squid
name = "\improper Calamari Crisps"
icon = 'icons/obj/food_snacks.dmi'
icon_state = "squid"
desc = "Space squid tentacles, Carefully removed (from the squid) then dried into strips of delicious rubbery goodness!"
trash = /obj/item/trash/squid
filling_color = "#c0a9d7"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("fish" = 1, "salt" = 1)
nutriment_amt = 2
bitesize = 1
@@ -6486,26 +6486,26 @@
. = ..()
reagents.add_reagent("protein", 4)
-/obj/item/weapon/reagent_containers/food/snacks/croutons //ADDITION 04/11/2021
+/obj/item/weapon/reagent_containers/food/snacks/croutons
name = "\improper Suhariki"
icon = 'icons/obj/food_snacks.dmi'
icon_state = "croutons"
desc = "Fried bread cubes. Popular in Terran territories."
trash = /obj/item/trash/croutons
filling_color = "#c6b17f"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("bread" = 1, "salt" = 1)
nutriment_amt = 3
bitesize = 1
-/obj/item/weapon/reagent_containers/food/snacks/salo //ADDITION 04/11/2021
+/obj/item/weapon/reagent_containers/food/snacks/salo
name = "\improper Salo"
icon = 'icons/obj/food_snacks.dmi'
icon_state = "pigfat"
desc = "Pig fat. Salted. Just as good as it sounds."
trash = /obj/item/trash/salo
filling_color = "#e0bcbc"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("fat" = 1, "salt" = 1)
nutriment_amt = 2
bitesize = 2
@@ -6514,14 +6514,14 @@
. = ..()
reagents.add_reagent("protein", 8)
-/obj/item/weapon/reagent_containers/food/snacks/driedfish //ADDITION 04/11/2021
+/obj/item/weapon/reagent_containers/food/snacks/driedfish
name = "\improper Vobla"
icon = 'icons/obj/food_snacks.dmi'
icon_state = "driedfish"
desc = "Dried salted beer snack fish."
trash = /obj/item/trash/driedfish
filling_color = "#c8a5bb"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("fish" = 1, "salt" = 1)
nutriment_amt = 2
bitesize = 1
@@ -6602,7 +6602,7 @@
desc = "Contains over 9000% of your daily recommended intake of salt."
trash = /obj/item/trash/tidegobs
filling_color = "#2556b0"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("salt" = 4, "seagull?" = 1)
nutriment_amt = 5
bitesize = 2
@@ -6614,7 +6614,7 @@
desc = "A peanut flavored snack that looks like the rings of Saturn!"
trash = /obj/item/trash/saturno
filling_color = "#dca319"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("salt" = 4, "peanut" = 2, "wood?" = 1)
nutriment_amt = 5
bitesize = 2
@@ -6626,7 +6626,7 @@
desc = "By Joove! It's some kind of gel."
trash = /obj/item/trash/jupiter
filling_color = "#dc1919"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("sweetness" = 4, "vanilla" = 1)
nutriment_amt = 5
bitesize = 2
@@ -6638,7 +6638,7 @@
desc = "Baseless tasteless nutrithick rods to get you through the day. Now even less rash inducing!"
trash = /obj/item/trash/pluto
filling_color = "#ffffff"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("chalk" = 4, "sadness" = 1)
nutriment_amt = 5
bitesize = 2
@@ -6650,7 +6650,7 @@
desc = "A steaming self-heated bowl of sweet eggs and taters!"
trash = /obj/item/trash/mars
filling_color = "#d2c63f"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("eggs" = 4, "potato" = 4, "mustard" = 2)
nutriment_amt = 8
bitesize = 2
@@ -6662,7 +6662,7 @@
desc = "Hot takes on hot cakes, a timeless classic now finally fit for human consumption!"
trash = /obj/item/trash/venus
filling_color = "#d2c63f"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("heat" = 4, "burning!" = 1)
nutriment_amt = 5
bitesize = 2
@@ -6678,7 +6678,7 @@
desc = "A Sol favorite, Sun Snax! Sun dried corn chips coated in a super spicy seasoning!"
trash = /obj/item/trash/sun_snax
filling_color = "#d2c63f"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("heat" = 3, "burning!" = 2)
nutriment_amt = 3
bitesize = 1
@@ -6694,7 +6694,7 @@
desc = "Pop rocks themed on the outermost reaches of the Sol system, new formula guarantees fewer shrapnel induced oral injuries."
trash = /obj/item/trash/oort
filling_color = "#3f7dd2"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("fizz" = 4, "sweetness" = 1)
nutriment_amt = 5
bitesize = 2
@@ -6710,7 +6710,7 @@
trash = /obj/item/trash/pretzel
desc = "A tasty bread like snack that is seasoned with what tastes like salt... but you're not so sure it's actually salt."
filling_color = "#916E36"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("salt" = 2, "pretzel" = 3)
nutriment_amt = 3
bitesize = 1
@@ -6723,7 +6723,7 @@
desc = "Fermented space shark, like chewing a urine soaked mattress."
description_fluff = "A form of fermented shark that originated on Earth as far back as the 17th century. Modern Hakarl is made from vat-made fermented shark and is distributed across the galaxy as a delicacy. However, few are able to stand the smell or taste of the meat."
filling_color = "#916E36"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("fish" = 2, "salt" = 2, "ammonia" = 1)
nutriment_amt = 4
bitesize = 1
@@ -6835,7 +6835,7 @@
/obj/item/weapon/reagent_containers/food/snacks/old
name = "master old-food"
desc = "they're all inedible and potentially dangerous items"
- center_of_mass = "x=15;y=12"
+ center_of_mass = list("x"=15,"y"=12)
nutriment_desc = list("rot" = 5, "mold" = 5)
nutriment_amt = 10
bitesize = 3
@@ -6920,7 +6920,7 @@
desc = "A can of premium preserved vat-grown holstein beef. Now 99.9% bone free!"
trash = /obj/item/trash/beef
filling_color = "#663300"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("beef" = 1)
bitesize = 2
@@ -6935,7 +6935,7 @@
desc = "Luna Colony beans. Carefully synthethized from soy."
trash = /obj/item/trash/beans
filling_color = "#ff6633"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("beans" = 1, "tomato sauce" = 1)
nutriment_amt = 10
bitesize = 2
@@ -6950,7 +6950,7 @@
// desc = "Plain old unseasoned tomato soup. This can has no use-by date."
// trash = "/obj/item/trash/tomato"
// filling_color = "#ae0000"
-// center_of_mass = "x=15;y=9"
+// center_of_mass = list("x"=15, "y"=9)
// nutriment_desc = list("tomato" = 1)
// bitesize = 3
// eat_sound = 'sound/items/drink.ogg'
@@ -6969,7 +6969,7 @@
desc = "Wup-Az! Brand canned spinach. Notably has less iron in it than a watermelon."
trash = /obj/item/trash/spinach
filling_color = "#003300"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("soggy" = 1, "vegetable" = 1)
bitesize = 5
@@ -6988,7 +6988,7 @@
desc = "Terran caviar, or space carp eggs. Carefully faked using alginate, artificial flavoring and salt. Skrell approved!"
trash = /obj/item/trash/fishegg
filling_color = "#000000"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("fish" = 1, "salt" = 1)
nutriment_amt = 6
bitesize = 1
@@ -7003,7 +7003,7 @@
desc = "Terran caviar, or space carp eggs. Banned by the Vir Food Health Administration for exceeding the legally set amount of carpotoxins in food stuffs."
trash = /obj/item/trash/carpegg
filling_color = "#330066"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("fish" = 1, "salt" = 1, "a numbing sensation" = 1)
nutriment_amt = 6
bitesize = 1
@@ -7019,7 +7019,7 @@
desc = "A re-branding of a classic Terran snack! Contains mostly edible ingredients."
trash = /obj/item/trash/maps
filling_color = "#330066"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("meat" = 1, "salt" = 1)
nutriment_amt = 8
bitesize = 2
@@ -7035,7 +7035,7 @@
desc = "A classic snack favored by Sol astronauts. Made from dried apple-hybidized berries grown on the lunar colonies."
trash = /obj/item/trash/appleberry
filling_color = "#FFFFFF"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("apple" = 1, "sweetness" = 1)
nutriment_amt = 8
bitesize = 2
@@ -7085,7 +7085,7 @@
desc = "Now with 20% less lawsuit enabling rhegolith!"
//trash = /obj/item/trash/lunacakewrap //need to add code that drops trash but keeps -open state
filling_color = "#ffffff"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("sweetness" = 4, "vanilla" = 1)
bitesize = 2
@@ -7099,7 +7099,7 @@
desc = "Explore the dark side! May contain trace amounts of reconstituted cocoa."
//trash = /obj/item/trash/mooncakewrap //need to add code that drops trash but keeps -open state
filling_color = "#ffffff"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("sweetness" = 4, "chocolate" = 1)
bitesize = 2
@@ -7113,7 +7113,7 @@
desc = "Konnichiwa! Many go lucky rice cakes in future!"
//trash = /obj/item/trash/mochicakewrap //need to add code that drops trash but keeps -open state
filling_color = "#ffffff"
- center_of_mass = "x=15;y=9"
+ center_of_mass = list("x"=15, "y"=9)
nutriment_desc = list("sweetness" = 4, "rice" = 1)
bitesize = 2