mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-17 21:24:01 +00:00
* [MDB IGNORE] Angled Lights & Lighting Prototyping Tool (#74365) ## About The Pull Request Hello friends, I've been on a bit of a lighting kick recently, and I decided I clearly do not have enough things to work on as it is. This pr adds angle support to static lights, and a concepting/debug tool for playing with lights on a map. Let's start from first principles yeah? ### Why Angled Lights? Mappers, since they can't actually see a light's effect in editor, tend to go off gut. That gut is based more off what "makes sense" then how things actually work This means they'll overplace light sources, and also they tend to treat lights, particularly light "bars" (the bigger ones) as directional. So you'll have two lights on either sides of a pillar, lights inside a room with lights outside pointing out, etc.  This has annoying side effects. A lot of our map is overlit, to the point that knocking out a light does.... pretty much nothing. I find this sad, and would like to work to prevent it. I think dark and dim, while it does not suit the normal game, is amazing for vibes, and I want it to be easier to see that. Angled lights bring how lights work more in line with how mappers expect lights work, and avoids bleedover into rooms that shouldn't be bled into, working towards that goal of mine. ### How Angled Lights? This is more complex then you'd first think so we'll go step by step  Oh before we start, some catchup from the last time I touched lighting code. Instead of doing a lighting falloff calculation for each lighting corner (a block that represents the resolution of our lights) in view we instead generate cached lightsheets. These precalculate and store all possible falloffs for x and y distances from a source. This is very useful for angle work, since it makes it almost totally free. Atoms get 2 new values. light_angle and light_dir Light angle is the angle the light uses, and light_dir is a cardinal direction it displays in We take these values, and inside sheetbuilding do some optional angle work. getting the center angle, the angle of a pair of coords, and then the delta between them. This is then multiplied against the standard falloff formula, and job done. We do need some extra fenangling to make this all work nicely tho. We currently use a pixel turf var stored on the light source to do distance calculations. This is the turf we pretend the light source is on for visuals, most often used to make wall lights work nice. The trouble is it's not very granular, and doesn't always have the effect you might want. So, instead of generating and storing a pixel turf to do our distance calculations against, we store x and y offset variables. We use them to expand our working range and sheet size to ensure things visually make sense, and then offset any positions by them. I've added a way for sources to have opinions on their offsets too, and am using them for wall lights. This ensures the angle calculations don't make the wall behind a light fulldark, which would be silly. ### Debug Tool? In the interest of helping with that core problem, lights being complex to display, I've added a prototyping tool to the game. It's locked behind mapping verbs, and works about like this. Once the verb is activated, it iterates over all the sources in the world (except turfs because those are kinda silly), outlining and "freezing" them, preventing any future changes. Then, it adds 3 buttons to the owners of a light source.  The first button toggles the light on and off, as desired. The third allows you to move the source around, with a little targeting icon replacing your mouse The second tho, that's more interesting. The second button opens a debug menu for that light  There's a lot here, let's go through it. Bit on the left is a list of templates, which allow you to sample existing light types (No I have no idea why the background is fullwhite, need to work on that pre merge) You can choose one by clicking it, and hitting the upload button. This replaces your existing lighting values with the template's, alongside replacing its icon and icon state so it looks right. There are three types as of now, mostly for categorization. Bar, which are the larger typically stronger lights, Bulb, which are well, bulbs, and Misc which could be expanded, but currently just contains floor lights. Alongside that you can manually edit the power, range, color and angle of the focused light. I also have support for changing the direction of the light source, since anything that uses directional lighting would also tie light dir to it. This isn't *always* done tho, so I should maybe find a way to edit light dir too. My hope is this tool will allow for better concepting of a room's lights, and easier changing of individual object's light values to suit the right visuals. ### Lemon No Why What Ok so I applied angle lights to bars and bulbs, which means I am changing the lighting of pretty much every map in the codebase. I'm gonna uh, go check my work. Alongside this I intend to give lighting some depth. So if there's room to make a space warmer, or highlight light colors from other sources, I will do that. (Images as examples)  I also want to work on that other goal of mine, making breaking lights matter. So I'll be doing what I can to ensure you only need to break one light to make a meaningful change in the scene. This is semi complicated by one light source not ever actually reaching fullbright on its own, but we do what we must because we can.  I'm as I hope you know biased towards darker spaces, I think contrast has vibes. In particular I do not think strong lights really suit maintenance. Most of what is used there are bulbs, so I'm planning on replacing most uses with low power bulbs, to keep light impacts to rooms, alongside reducing the amount of lights placed in the main tunnels  **If you take issue with this methodology please do so NOW**, I don't want to have to do another pass over things. Oh also I'm saving station maps for last since ruins are less likely to get touched in mapping march and all. ### Misc + Finishing Thoughts Light templates support mirroring vars off typepaths using a subtype, which means all the templates added here do not require updating if the source type changes somehow. I'd like to expand the template list at some point, perhaps in future. I've opened this as a draft to make my intentions to make my changes to lights known, and to serve as motivation for all the map changes I need to do. ### Farish Future I'm unhappy with how we currently configure lights. I would like a system that more directly matches the idea of drawing falloff curves, along with allowing for different falloffs for different colors, alongside extending the idea to angle falloff. This would make out of engine lighting easier, allow for nicer looking lights (red to pink, blue to purple, etc), and improve accessibility by artists. This is slightly far off, because I have other obligations and it's kinda complicated, but I'd like to mention it cause it's one of my many pipedreams. ## Changelog 🆑 add: Added angle lighting, applies it to most wall lights! add: Adds a lighting prototyping tool, mappers go try it out (it's locked behind the mapping verb) /🆑 --------- Co-authored-by: MMMiracles <lolaccount1@ hotmail.com> * [MDB IGNORE] Angled Lights & Lighting Prototyping Tool * Update north_star.dmm * Revert "Update north_star.dmm" This reverts commit bb5b8b5a549f7edc3e23a369a147ed96bab41991. * Updatepaths * Update nukie_base.dmm * Newer version of northstar with the penguins * Update northstar_cryo.dmm --------- Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: MMMiracles <lolaccount1@ hotmail.com> Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com> Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com>
420 lines
14 KiB
Plaintext
420 lines
14 KiB
Plaintext
|
|
/proc/debug_sources()
|
|
GLOB.light_debug_enabled = TRUE
|
|
var/list/sum = list()
|
|
var/total = 0
|
|
for(var/datum/light_source/source)
|
|
if(!source.source_atom)
|
|
continue
|
|
source.source_atom.debug()
|
|
sum[source.source_atom.type] += 1
|
|
total += 1
|
|
|
|
sum = sortTim(sum, /proc/cmp_numeric_asc, TRUE)
|
|
var/text = ""
|
|
for(var/type in sum)
|
|
text += "[type] = [sum[type]]\n"
|
|
text += "total iterated: [total]"
|
|
|
|
for(var/client/lad in GLOB.admins)
|
|
var/datum/action/spawn_light/let_there_be = new (lad.mob.mind || lad.mob)
|
|
let_there_be.Grant(lad.mob)
|
|
|
|
// I am sorry
|
|
SSdcs.RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_CONNECT, TYPE_PROC_REF(/datum/controller/subsystem/processing/dcs, on_client_connect))
|
|
message_admins(text)
|
|
|
|
/datum/controller/subsystem/processing/dcs/proc/on_client_connect(datum/source, client/new_lad)
|
|
SIGNAL_HANDLER
|
|
var/datum/action/spawn_light/let_there_be = new (new_lad.mob.mind || new_lad.mob)
|
|
let_there_be.Grant(new_lad.mob)
|
|
|
|
/proc/undebug_sources()
|
|
GLOB.light_debug_enabled = FALSE
|
|
for(var/datum/weakref/button_ref as anything in GLOB.light_debugged_atoms)
|
|
var/atom/button = button_ref.resolve()
|
|
if(!button)
|
|
GLOB.light_debugged_atoms -= button_ref
|
|
continue
|
|
button.undebug()
|
|
|
|
SEND_GLOBAL_SIGNAL(COMSIG_LIGHT_DEBUG_DISABLED)
|
|
SSdcs.UnregisterSignal(SSdcs, COMSIG_GLOB_CLIENT_CONNECT)
|
|
|
|
GLOBAL_LIST_EMPTY(light_debugged_atoms)
|
|
/// Sets up this light source to be debugged, setting up in world buttons to control and move it
|
|
/// Also freezes it, so it can't change in future
|
|
/atom/proc/debug()
|
|
if(isturf(src) || HAS_TRAIT(src, TRAIT_LIGHTING_DEBUGGED))
|
|
return
|
|
ADD_TRAIT(src, TRAIT_LIGHTING_DEBUGGED, LIGHT_DEBUG_TRAIT)
|
|
GLOB.light_debugged_atoms += WEAKREF(src)
|
|
add_filter("debug_light", 0, outline_filter(2, COLOR_CENTCOM_BLUE))
|
|
var/static/uid = 0
|
|
if(!render_target)
|
|
render_target = "light_debug_[uid]"
|
|
uid++
|
|
var/atom/movable/render_step/color/above_light = new(null, src, "#ffffff23")
|
|
SET_PLANE_EXPLICIT(above_light, ABOVE_LIGHTING_PLANE, src)
|
|
add_overlay(above_light)
|
|
QDEL_NULL(above_light)
|
|
// Freeze our light would you please
|
|
light_flags |= LIGHT_FROZEN
|
|
new /atom/movable/screen/light_button/toggle(src)
|
|
new /atom/movable/screen/light_button/edit(src)
|
|
new /atom/movable/screen/light_button/move(src)
|
|
|
|
/// Disables light debugging, so you can let a scene fall to what it visually should be, or just fix admin fuckups
|
|
/atom/proc/undebug()
|
|
// I don't really want to undebug a light if it's off rn
|
|
// Loses control if we turn it back on again
|
|
if(isturf(src) || !HAS_TRAIT(src, TRAIT_LIGHTING_DEBUGGED) || !light)
|
|
return
|
|
REMOVE_TRAIT(src, TRAIT_LIGHTING_DEBUGGED, LIGHT_DEBUG_TRAIT)
|
|
GLOB.light_debugged_atoms -= WEAKREF(src)
|
|
remove_filter("debug_light")
|
|
// Removes the glow overlay via stupid, sorry
|
|
var/atom/movable/render_step/color/above_light = new(null, src, "#ffffff23")
|
|
SET_PLANE_EXPLICIT(above_light, ABOVE_LIGHTING_PLANE, src)
|
|
cut_overlay(above_light)
|
|
QDEL_NULL(above_light)
|
|
var/atom/movable/lie_to_areas = src
|
|
// Freeze our light would you please
|
|
light_flags &= ~LIGHT_FROZEN
|
|
for(var/atom/movable/screen/light_button/button in lie_to_areas.vis_contents)
|
|
qdel(button)
|
|
|
|
/atom/movable/screen/light_button
|
|
icon = 'icons/testing/lighting_debug.dmi'
|
|
plane = BALLOON_CHAT_PLANE // We hijack runechat because we can get multiz niceness without making a new PM
|
|
layer = ABOVE_ALL_MOB_LAYER
|
|
alpha = 100
|
|
var/datum/weakref/last_hovored_ref
|
|
|
|
/atom/movable/screen/light_button/Initialize(mapload)
|
|
. = ..()
|
|
attach_to(loc)
|
|
|
|
/atom/movable/screen/light_button/proc/attach_to(atom/new_owner)
|
|
if(loc)
|
|
UnregisterSignal(loc, COMSIG_QDELETING)
|
|
var/atom/movable/mislead_areas = loc
|
|
mislead_areas.vis_contents -= src
|
|
forceMove(new_owner)
|
|
layer = loc.layer
|
|
RegisterSignal(loc, COMSIG_QDELETING, PROC_REF(delete_self))
|
|
var/atom/movable/lie_to_areas = loc
|
|
lie_to_areas.vis_contents += src
|
|
|
|
/atom/movable/screen/light_button/proc/delete_self(datum/source)
|
|
SIGNAL_HANDLER
|
|
qdel(src)
|
|
|
|
// Entered and Exited won't fire while you're dragging something, because you're still "holding" it
|
|
// Very much byond logic, but I want nice for my highlighting, so we fake it with drag
|
|
// Copypasta from action buttons
|
|
/atom/movable/screen/light_button/MouseDrag(atom/over_object, src_location, over_location, src_control, over_control, params)
|
|
. = ..()
|
|
if(IS_WEAKREF_OF(over_object, last_hovored_ref))
|
|
return
|
|
var/atom/old_object
|
|
if(last_hovored_ref)
|
|
old_object = last_hovored_ref?.resolve()
|
|
else // If there's no current ref, we assume it was us. We also treat this as our "first go" location
|
|
old_object = src
|
|
|
|
if(old_object)
|
|
old_object.MouseExited(over_location, over_control, params)
|
|
|
|
last_hovored_ref = WEAKREF(over_object)
|
|
over_object.MouseEntered(over_location, over_control, params)
|
|
|
|
/atom/movable/screen/light_button/MouseDrop(over_object)
|
|
. = ..()
|
|
last_hovored_ref = null
|
|
|
|
/atom/movable/screen/light_button/MouseEntered(location, control, params)
|
|
. = ..()
|
|
animate(src, alpha = 255, time = 2)
|
|
|
|
/atom/movable/screen/light_button/MouseExited(location, control, params)
|
|
. = ..()
|
|
animate(src, alpha = initial(alpha), time = 2)
|
|
|
|
/atom/movable/screen/light_button/toggle
|
|
name = "Toggle Light"
|
|
desc = "Click to turn the light on/off"
|
|
icon_state = "light_enable"
|
|
|
|
/atom/movable/screen/light_button/toggle/attach_to(atom/new_owner)
|
|
if(loc)
|
|
UnregisterSignal(loc, COMSIG_ATOM_UPDATE_LIGHT_ON)
|
|
. = ..()
|
|
RegisterSignal(loc, COMSIG_ATOM_UPDATE_LIGHT_ON, PROC_REF(on_changed))
|
|
update_appearance()
|
|
|
|
/atom/movable/screen/light_button/toggle/Click(location, control, params)
|
|
. = ..()
|
|
if(!check_rights_for(usr.client, R_DEBUG))
|
|
return
|
|
var/atom/movable/parent = loc
|
|
parent.light_flags &= ~LIGHT_FROZEN
|
|
loc.set_light(l_on = !loc.light_on)
|
|
parent.light_flags |= LIGHT_FROZEN
|
|
|
|
/atom/movable/screen/light_button/toggle/proc/on_changed()
|
|
SIGNAL_HANDLER
|
|
update_appearance()
|
|
|
|
/atom/movable/screen/light_button/toggle/update_icon_state()
|
|
. = ..()
|
|
if(loc.light_on)
|
|
icon_state = "light_enable"
|
|
else
|
|
icon_state = "light_disable"
|
|
|
|
/atom/movable/screen/light_button/edit
|
|
name = "Edit Light"
|
|
desc = "Click to open an editing menu for the light"
|
|
icon_state = "light_focus"
|
|
|
|
/atom/movable/screen/light_button/edit/attach_to(atom/new_owner)
|
|
. = ..()
|
|
SStgui.try_update_ui(usr, src, null)
|
|
|
|
/atom/movable/screen/light_button/edit/Click(location, control, params)
|
|
. = ..()
|
|
ui_interact(usr)
|
|
|
|
/atom/movable/screen/light_button/edit/ui_state(mob/user)
|
|
return GLOB.debug_state
|
|
|
|
/atom/movable/screen/light_button/edit/can_interact()
|
|
return TRUE
|
|
|
|
/atom/movable/screen/light_button/edit/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "LightController")
|
|
ui.open()
|
|
|
|
/atom/movable/screen/light_button/edit/ui_assets(mob/user)
|
|
return list(get_asset_datum(/datum/asset/spritesheet/lights))
|
|
|
|
/atom/movable/screen/light_button/edit/ui_data()
|
|
var/list/data = list()
|
|
|
|
var/atom/parent = loc
|
|
var/list/light_info = list()
|
|
light_info["name"] = full_capitalize(parent.name)
|
|
light_info["on"] = parent.light_on
|
|
light_info["power"] = parent.light_power
|
|
light_info["range"] = parent.light_range
|
|
light_info["color"] = parent.light_color
|
|
light_info["angle"] = parent.light_angle
|
|
data["light_info"] = light_info
|
|
data["on"] = parent.light_on
|
|
data["direction"] = parent.dir
|
|
|
|
return data
|
|
|
|
/atom/movable/screen/light_button/edit/ui_static_data(mob/user)
|
|
. = ..()
|
|
var/list/data = list()
|
|
data["templates"] = list()
|
|
data["category_ids"] = list()
|
|
for(var/id in GLOB.light_types)
|
|
var/datum/light_template/template = GLOB.light_types[id]
|
|
var/list/insert = list()
|
|
var/list/light_info = list()
|
|
light_info["name"] = template.name
|
|
light_info["power"] = template.power
|
|
light_info["range"] = template.range
|
|
light_info["color"] = template.color
|
|
light_info["angle"] = template.angle
|
|
insert["light_info"] = light_info
|
|
insert["description"] = template.desc
|
|
insert["id"] = template.id
|
|
insert["category"] = template.category
|
|
if(!data["category_ids"][template.category])
|
|
data["category_ids"][template.category] = list()
|
|
data["category_ids"][template.category] += id
|
|
data["templates"][template.id] = insert
|
|
|
|
var/datum/light_template/first_template = GLOB.light_types[GLOB.light_types[1]]
|
|
data["default_id"] = first_template.id
|
|
data["default_category"] = first_template.category
|
|
return data
|
|
|
|
/atom/movable/screen/light_button/edit/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
var/atom/parent = loc
|
|
parent.light_flags &= ~LIGHT_FROZEN
|
|
switch(action)
|
|
if("set_on")
|
|
parent.set_light(l_on = params["value"])
|
|
if("change_color")
|
|
var/chosen_color = input(ui.user, "Pick new color", "[parent]", parent.light_color) as color|null
|
|
if(chosen_color)
|
|
parent.set_light(l_color = chosen_color)
|
|
if("set_power")
|
|
parent.set_light(l_power = params["value"])
|
|
if("set_range")
|
|
parent.set_light(l_range = params["value"])
|
|
if("set_angle")
|
|
// We use dir instead of light dir because anything directional should have its lightdir tied
|
|
// And this way we can update the sprite too
|
|
parent.set_light(l_angle = params["value"])
|
|
if("set_dir")
|
|
parent.setDir(params["value"])
|
|
if("mirror_template")
|
|
var/datum/light_template/template = GLOB.light_types[params["id"]]
|
|
var/atom/new_light = template.create(parent.loc, parent.dir)
|
|
var/atom/movable/lies_to_children = parent
|
|
for(var/atom/movable/screen/light_button/button in lies_to_children.vis_contents)
|
|
button.attach_to(new_light)
|
|
|
|
qdel(parent)
|
|
if("isolate")
|
|
isolate_light(parent)
|
|
|
|
parent.light_flags |= LIGHT_FROZEN
|
|
return TRUE
|
|
|
|
/// Hides all the lights around a source temporarially, for the sake of figuring out how bad a light bleeds
|
|
/// (Except for turf lights, because they're a part of the "scene" and rarely modified)
|
|
/proc/isolate_light(atom/source, delay = 7 SECONDS)
|
|
var/list/datum/lighting_corner/interesting_corners = source.light?.effect_str
|
|
|
|
var/list/atom/sources = list()
|
|
for(var/datum/lighting_corner/corner as anything in interesting_corners)
|
|
for(var/datum/light_source/target_spotted as anything in corner.affecting)
|
|
if(isturf(target_spotted.source_atom))
|
|
continue
|
|
sources[target_spotted.source_atom] = TRUE
|
|
|
|
sources -= source // Please don't disable yourself
|
|
if(!length(sources))
|
|
return
|
|
|
|
// Now that we have all the lights (and a bit more), let's get rid of em
|
|
for(var/atom/light_source as anything in sources)
|
|
light_source.light_flags &= ~LIGHT_FROZEN
|
|
light_source.set_light(l_on = FALSE)
|
|
light_source.light_flags |= LIGHT_FROZEN
|
|
|
|
// Now we sleep until the lighting system has processed them
|
|
var/current_tick = SSlighting.times_fired
|
|
|
|
UNTIL(SSlighting.times_fired > current_tick || QDELETED(source) || !source.light)
|
|
|
|
if(QDELETED(source) || !source.light)
|
|
repopulate_lights(sources)
|
|
return
|
|
|
|
// And finally, wait the allotted time, and reawake em
|
|
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(repopulate_lights), sources), delay)
|
|
|
|
/proc/repopulate_lights(list/atom/sources)
|
|
for(var/atom/light_source as anything in sources)
|
|
light_source.light_flags &= ~LIGHT_FROZEN
|
|
light_source.set_light(l_on = TRUE)
|
|
light_source.light_flags |= LIGHT_FROZEN
|
|
|
|
/atom/movable/screen/light_button/move
|
|
name = "Move Light"
|
|
desc = "Drag to move the light around"
|
|
icon_state = "light_move"
|
|
mouse_drag_pointer = 'icons/effects/mouse_pointers/light_drag.dmi'
|
|
|
|
/atom/movable/screen/light_button/move/MouseDrop(over_object)
|
|
. = ..()
|
|
if(!ismovable(loc))
|
|
return
|
|
var/atom/movable/movable_owner = loc
|
|
movable_owner.forceMove(get_turf(over_object))
|
|
|
|
/datum/action/spawn_light
|
|
name = "Spawn Light"
|
|
desc = "Create a light from a template"
|
|
button_icon = 'icons/mob/actions/actions_construction.dmi'
|
|
button_icon_state = "light_spawn"
|
|
|
|
/datum/action/spawn_light/New(Target)
|
|
. = ..()
|
|
RegisterSignal(SSdcs, COMSIG_LIGHT_DEBUG_DISABLED, PROC_REF(debug_disabled))
|
|
|
|
/datum/action/spawn_light/proc/debug_disabled()
|
|
SIGNAL_HANDLER
|
|
qdel(src)
|
|
|
|
/datum/action/spawn_light/Grant(mob/grant_to)
|
|
. = ..()
|
|
RegisterSignal(grant_to.client, COMSIG_CLIENT_MOB_LOGIN, PROC_REF(move_action), override = TRUE)
|
|
|
|
/datum/action/spawn_light/proc/move_action(client/source, mob/new_mob)
|
|
SIGNAL_HANDLER
|
|
Grant(new_mob)
|
|
|
|
/datum/action/spawn_light/Trigger(trigger_flags)
|
|
. = ..()
|
|
ui_interact(usr)
|
|
|
|
/datum/action/spawn_light/ui_state(mob/user)
|
|
return GLOB.debug_state
|
|
|
|
/datum/action/spawn_light/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "LightSpawn")
|
|
ui.open()
|
|
|
|
/datum/action/spawn_light/ui_assets(mob/user)
|
|
return list(get_asset_datum(/datum/asset/spritesheet/lights))
|
|
|
|
/datum/action/spawn_light/ui_data()
|
|
var/list/data = list()
|
|
return data
|
|
|
|
/datum/action/spawn_light/ui_static_data(mob/user)
|
|
. = ..()
|
|
var/list/data = list()
|
|
data["templates"] = list()
|
|
data["category_ids"] = list()
|
|
for(var/id in GLOB.light_types)
|
|
var/datum/light_template/template = GLOB.light_types[id]
|
|
var/list/insert = list()
|
|
var/list/light_info = list()
|
|
light_info["name"] = template.name
|
|
light_info["power"] = template.power
|
|
light_info["range"] = template.range
|
|
light_info["color"] = template.color
|
|
light_info["angle"] = template.angle
|
|
insert["light_info"] = light_info
|
|
insert["description"] = template.desc
|
|
insert["id"] = template.id
|
|
insert["category"] = template.category
|
|
if(!data["category_ids"][template.category])
|
|
data["category_ids"][template.category] = list()
|
|
data["category_ids"][template.category] += id
|
|
data["templates"][template.id] = insert
|
|
|
|
var/datum/light_template/first_template = GLOB.light_types[GLOB.light_types[1]]
|
|
data["default_id"] = first_template.id
|
|
data["default_category"] = first_template.category
|
|
return data
|
|
|
|
/datum/action/spawn_light/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
switch(action)
|
|
if("spawn_template")
|
|
var/datum/light_template/template = GLOB.light_types[params["id"]]
|
|
template.create(get_turf(owner), params["dir"])
|
|
return TRUE
|