diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 8d30dd0343a..aa2578347df 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -53,18 +53,10 @@ return 0 return 1 - -//Magic constants obtained by using linear regression on right-angled triangles of sides 0=dy) return (k1*dx) + (k2*dy) //No sqrt or powers :) - else return (k2*dx) + (k1*dy) -#undef k1 -#undef k2 +//We used to use linear regression to approximate the answer, but Mloc realized this was actually faster. +//And lo and behold, it is, and it's more accurate to boot. +/proc/cheap_hypotenuse(Ax,Ay,Bx,By) + return sqrt(abs(Ax - Bx)**2 + abs(Ay - By)**2) //A squared + B squared = C squared /proc/circlerange(center=usr,radius=3) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 168024d0702..51f52265cde 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -828,8 +828,6 @@ Turf and target are seperate in case you want to teleport some distance from a t //else populates the list first before returning it /proc/SortAreas() for(var/area/A in world) - if(A.lighting_subarea) - continue sortedAreas.Add(A) sortTim(sortedAreas, /proc/cmp_name_asc) @@ -888,152 +886,6 @@ Turf and target are seperate in case you want to teleport some distance from a t var/y_pos = null var/z_pos = null -/area/proc/move_contents_to(var/area/A, var/turftoleave=null, var/direction = null) - //Takes: Area. Optional: turf type to leave behind. - //Returns: Nothing. - //Notes: Attempts to move the contents of one area to another area. - // Movement based on lower left corner. Tiles that do not fit - // into the new area will not be moved. - - if(!A || !src) return 0 - - var/list/turfs_src = get_area_turfs(src.type) - var/list/turfs_trg = get_area_turfs(A.type) - - var/src_min_x = 0 - var/src_min_y = 0 - for (var/turf/T in turfs_src) - if(T.x < src_min_x || !src_min_x) src_min_x = T.x - if(T.y < src_min_y || !src_min_y) src_min_y = T.y - - var/trg_min_x = 0 - var/trg_min_y = 0 - for (var/turf/T in turfs_trg) - if(T.x < trg_min_x || !trg_min_x) trg_min_x = T.x - if(T.y < trg_min_y || !trg_min_y) trg_min_y = T.y - - var/list/refined_src = new/list() - for(var/turf/T in turfs_src) - refined_src += T - refined_src[T] = new/datum/coords - var/datum/coords/C = refined_src[T] - C.x_pos = (T.x - src_min_x) - C.y_pos = (T.y - src_min_y) - - var/list/refined_trg = new/list() - for(var/turf/T in turfs_trg) - refined_trg += T - refined_trg[T] = new/datum/coords - var/datum/coords/C = refined_trg[T] - C.x_pos = (T.x - trg_min_x) - C.y_pos = (T.y - trg_min_y) - - var/list/fromupdate = new/list() - var/list/toupdate = new/list() - - moving: - for (var/turf/T in refined_src) - var/datum/coords/C_src = refined_src[T] - for (var/turf/B in refined_trg) - var/datum/coords/C_trg = refined_trg[B] - if(C_src.x_pos == C_trg.x_pos && C_src.y_pos == C_trg.y_pos) - - var/old_dir1 = T.dir - var/old_icon_state1 = T.icon_state - var/old_icon1 = T.icon - - var/turf/X = new T.type(B) - X.dir = old_dir1 - X.icon_state = old_icon_state1 - X.icon = old_icon1 //Shuttle floors are in shuttle.dmi while the defaults are floors.dmi - - - // Give the new turf our air, if simulated - if(istype(X, /turf/simulated) && istype(T, /turf/simulated)) - var/turf/simulated/sim = X - sim.copy_air_with_tile(T) - - /* Quick visual fix for some weird shuttle corner artefacts when on transit space tiles */ - if(direction && findtext(X.icon_state, "swall_s")) - - // Spawn a new shuttle corner object - var/obj/corner = new() - corner.loc = X - corner.density = 1 - corner.anchored = 1 - corner.icon = X.icon - corner.icon_state = replacetext(X.icon_state, "_s", "_f") - corner.tag = "delete me" - corner.name = "wall" - - // Find a new turf to take on the property of - var/turf/nextturf = get_step(corner, direction) - if(!nextturf || !istype(nextturf, /turf/space)) - nextturf = get_step(corner, turn(direction, 180)) - - - // Take on the icon of a neighboring scrolling space icon - X.icon = nextturf.icon - X.icon_state = nextturf.icon_state - - - for(var/obj/O in T) - - // Reset the shuttle corners - if(O.tag == "delete me") - X.icon = 'icons/turf/shuttle.dmi' - X.icon_state = replacetext(O.icon_state, "_f", "_s") // revert the turf to the old icon_state - X.name = "wall" - qdel(O) // prevents multiple shuttle corners from stacking - continue - if(!istype(O,/obj)) continue - O.loc = X - for(var/mob/M in T) - if(!M.move_on_shuttle) - continue - M.loc = X - -// var/area/AR = X.loc - -// if(AR.lighting_use_dynamic) //TODO: rewrite this code so it's not messed by lighting ~Carn -// X.opacity = !X.opacity -// X.SetOpacity(!X.opacity) - - toupdate += X - - if(turftoleave) - var/turf/ttl = new turftoleave(T) - -// var/area/AR2 = ttl.loc - -// if(AR2.lighting_use_dynamic) //TODO: rewrite this code so it's not messed by lighting ~Carn -// ttl.opacity = !ttl.opacity -// ttl.sd_SetOpacity(!ttl.opacity) - - fromupdate += ttl - - else - T.ChangeTurf(/turf/space) - - refined_src -= T - refined_trg -= B - continue moving - - - if(toupdate.len) - for(var/turf/simulated/T1 in toupdate) - SSair.remove_from_active(T1) - T1.CalculateAdjacentTurfs() - SSair.add_to_active(T1,1) - - if(fromupdate.len) - for(var/turf/simulated/T2 in fromupdate) - SSair.remove_from_active(T2) - T2.CalculateAdjacentTurfs() - SSair.add_to_active(T2,1) - - - /proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0) if(!original) return null diff --git a/code/controllers/_DynamicAreaLighting_TG.dm b/code/controllers/_DynamicAreaLighting_TG.dm deleted file mode 100644 index ea1b76b1ce2..00000000000 --- a/code/controllers/_DynamicAreaLighting_TG.dm +++ /dev/null @@ -1,308 +0,0 @@ -/* - Modified DynamicAreaLighting for TGstation - Coded by Carnwennan - - This is TG's 'new' lighting system. It's basically a heavily modified combination of Forum_Account's and - ShadowDarke's respective lighting libraries. Credits, where due, to them. - - Like sd_DAL (what we used to use), it changes the shading overlays of areas by splitting each type of area into sub-areas - by using the var/tag variable and moving turfs into the contents list of the correct sub-area. This method is - much less costly than using overlays or objects. - - Unlike sd_DAL however it uses a queueing system. Everytime we call a change to opacity or luminosity - (through SetOpacity() or SetLuminosity()) we are simply updating variables and scheduling certain lights/turfs for an - update. Actual updates are handled periodically by the SSlighting subsystem. This carries additional overheads, however it - means that each thing is changed only once per SSlighting.wait deciseconds. Allowing for greater control - over how much priority we'd like lighting updates to have. - - UPDATE: we no longer postpone lighting updates by editting variables, there is now a subsystem/proc/postpone() procedure. - So you would do SSlighting.postpone() - - Unlike our old system there are hardcoded maximum luminositys (different for certain atoms). - This is to cap the cost of creating lighting effects. - (without this, an atom with luminosity of 20 would have to update 41^2 turfs!) :s - - Also, in order for the queueing system to work, each light remembers the effect it casts on each turf. This is going to - have larger memory requirements than our previous system but it's easily worth the hassle for the greater control we - gain. It also reduces cost of removing lighting effects by a lot! - - Known Issues/TODO: - Shuttles still do not have support for dynamic lighting (I hope to fix this at some point) - No directional lighting support. (prototype looked ugly) -*/ - -#define USE_CIRCULAR_LIGHTING //comment this out to use old square lighting effects. - -/datum/light_source - var/atom/owner - var/changed = 1 - var/list/effect = list() - var/__x = 0 //x coordinate at last update - var/__y = 0 //y coordinate at last update - - -/datum/light_source/New(atom/A) - if(!istype(A)) - CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.") - ..() - owner = A - __x = owner.x - __y = owner.y - // the lighting object maintains a list of all light sources - SSlighting.lights += src - - -//Check a light to see if its effect needs reprocessing. If it does, remove any old effect and create a new one -/datum/light_source/proc/check() - if(!owner) - remove_effect() - return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it. - - // check to see if we've moved since last update - if(owner.x != __x || owner.y != __y) - __x = owner.x - __y = owner.y - changed = 1 - - if(changed) - changed = 0 - remove_effect() - return add_effect() - return 0 - - -/datum/light_source/proc/remove_effect() - // before we apply the effect we remove the light's current effect. - for(var/turf/T in effect) // negate the effect of this light source - T.update_lumcount(-effect[T]) - - if(T.affecting_lights && T.affecting_lights.len) - T.affecting_lights -= src - else - T.affecting_lights = null - - effect.Cut() // clear the effect list - -/datum/light_source/proc/add_effect() - // only do this if the light is turned on and is on the map - if(owner.loc && owner.luminosity > 0) - effect = list() - var/turf/To = get_turf(owner) - var/range = owner.get_light_range() - - for(var/turf/T in view(range, To)) - var/delta_lumcount = T.lumen(src) - if(delta_lumcount > 0) - effect[T] = delta_lumcount - T.update_lumcount(delta_lumcount) - - if(!T.affecting_lights) - T.affecting_lights = list() - T.affecting_lights += src - - return 0 - else - owner.light = null - return 1 //cause the light to be removed from the lights list and garbage collected once it's no - //longer referenced by the queue - -/turf/proc/lumen(datum/light_source/L) - . = L.owner.luminosity -#ifdef USE_CIRCULAR_LIGHTING - . -= cheap_hypotenuse(x, y, L.__x, L.__y) -#else - . -= max(abs(x - L.__x), abs(y - L.__y)) -#endif - return . - -/turf/space/lumen() - return 0 - - -/atom - var/datum/light_source/light - - -//Turfs with opacity when they are constructed will trigger nearby lights to update -//Turfs and atoms with luminosity when they are constructed will create a light_source automatically -/turf/New() - ..() - if(luminosity) - if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.") - light = new(src) - -//Movable atoms with opacity when they are constructed will trigger nearby lights to update -//Movable atoms with luminosity when they are constructed will create a light_source automatically -/atom/movable/New() - ..() - if(opacity) - UpdateAffectingLights() - if(luminosity) - if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.") - light = new(src) - -//Objects with opacity will trigger nearby lights to update at next lighting process. -/atom/movable/Destroy() - if(opacity) - UpdateAffectingLights() - return ..() - -//Sets our luminosity. -//If we have no light it will create one. -//If we are setting luminosity to 0 the light will be cleaned up by the controller and garbage collected once all its -//queues are complete. -//if we have a light already it is merely updated, rather than making a new one. -/atom/proc/SetLuminosity(new_luminosity) - if(new_luminosity < 0) - new_luminosity = 0 - if(light) - if(luminosity != new_luminosity) //non-luminous lights are removed from the lights list in add_effect() - light.changed = 1 - else - if(new_luminosity) - light = new(src) - luminosity = new_luminosity - -/atom/proc/AddLuminosity(delta_luminosity) - SetLuminosity(luminosity + delta_luminosity) - -/area/SetLuminosity(new_luminosity) //we don't want dynamic lighting for areas - luminosity = !!new_luminosity - - -//change our opacity (defaults to toggle), and then update all lights that affect us. -/atom/proc/SetOpacity(new_opacity) - if(new_opacity == null) - new_opacity = !opacity //default = toggle opacity - else if(opacity == new_opacity) - return 0 //opacity hasn't changed! don't bother doing anything - opacity = new_opacity //update opacity, the below procs now call light updates. - UpdateAffectingLights() - - -/turf - var/lighting_lumcount = 0 - var/lighting_changed = 0 - var/list/affecting_lights //not initialised until used (even empty lists reserve a fair bit of memory) - -/turf/space - lighting_lumcount = 4 //starlight - -/turf/proc/update_lumcount(amount) - lighting_lumcount += amount - if(!lighting_changed) - SSlighting.changed_turfs += src - lighting_changed = 1 - -/area/proc/lighting_tag(level) - return tagbase + "sd_L[level]" - -/area/proc/build_lighting_area(tag, level) - var/area/A = locate(tag) // find an appropriate area - if(A) - return A - A = new type() // create area if it wasn't found - // replicate vars - for(var/V in vars) - switch(V) - if("contents","last_light","overlays") continue - else - if(issaved(vars[V])) A.vars[V] = vars[V] - - A.tag = tag - A.lighting_subarea = 1 - A.lighting_space = 0 // in case it was copied from a space subarea - A.SetLightLevel(level) - - related += A - return A - -/turf/proc/shift_to_subarea() - lighting_changed = 0 - var/area/Area = loc - - if(!istype(Area) || !Area.lighting_use_dynamic) return - - var/level = min(max(round(lighting_lumcount,1),0),SSlighting.lighting_images.len) - var/new_tag = Area.lighting_tag(level) - if(Area.tag!=new_tag) //skip if already in this area - var/area/A = Area.build_lighting_area(new_tag,level) - A.contents += src // move the turf into the area - -/area - var/lighting_use_dynamic = 1 //Turn this flag off to prevent sd_DynamicAreaLighting from affecting this area - var/last_light //tracks the last light level set for this area (used for removing previously applied lighting overlays) - var/lighting_subarea = 0 //tracks whether we're a lighting sub-area - var/lighting_space = 0 // true for space-only lighting subareas - var/tagbase - -/area/proc/SetLightLevel(light) - if(!src) return - if(light <= 1) - light = 1 - luminosity = 0 - else - if(light > SSlighting.lighting_images.len) - light = SSlighting.lighting_images.len - luminosity = 1 - - if(last_light != light) - if(last_light) - overlays -= SSlighting.lighting_images[last_light] - overlays += SSlighting.lighting_images[light] - last_light = light - -/area/proc/SetDynamicLighting() - lighting_use_dynamic = 1 - for(var/turf/T in contents) - T.update_lumcount(0) - -/area/proc/InitializeLighting() //TODO: could probably improve this bit ~Carn - tagbase = "[type]" - if(!tag) tag = tagbase - if(!lighting_use_dynamic) - if(!lighting_subarea) // see if this is a lighting subarea already - //show the dark overlay so areas, not yet in a lighting subarea, won't be bright as day and look silly. - SetLightLevel(4) - -#undef USE_CIRCULAR_LIGHTING - -//set the changed status of all lights which could have possibly lit this atom. -//We don't need to worry about lights which lit us but moved away, since they will have change status set already -//This proc can cause lots of lights to be updated. :( -/atom/proc/UpdateAffectingLights() - -/atom/movable/UpdateAffectingLights() - if(isturf(loc)) - loc.UpdateAffectingLights() - -/turf/UpdateAffectingLights() - if(affecting_lights) - for(var/thing in affecting_lights) - thing:changed = 1 //force it to update at next process() - - -#define LIGHTING_MAX_LUMINOSITY_STATIC 8 //Maximum luminosity to reduce lag. -#define LIGHTING_MAX_LUMINOSITY_MOBILE 5 //Moving objects have a lower max luminosity since these update more often. (lag reduction) -#define LIGHTING_MAX_LUMINOSITY_MOB 5 -#define LIGHTING_MAX_LUMINOSITY_TURF 1 //turfs have a severely shortened range to protect from inevitable floor-lighttile spam. - -//caps luminosity effects max-range based on what type the light's owner is. -/atom/proc/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC) - -/atom/movable/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_MOBILE) - -/mob/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_MOB) - -/obj/machinery/light/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC) - -/turf/get_light_range() - return min(luminosity, LIGHTING_MAX_LUMINOSITY_TURF) - -#undef LIGHTING_MAX_LUMINOSITY_STATIC -#undef LIGHTING_MAX_LUMINOSITY_MOBILE -#undef LIGHTING_MAX_LUMINOSITY_MOB -#undef LIGHTING_MAX_LUMINOSITY_TURF diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 3a329379f97..6ebee701170 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -82,7 +82,8 @@ var/datum/subsystem/garbage_collector/SSgarbage // Return true if the the GC controller should allow the object to continue existing. (Useful if pooling objects.) /datum/proc/Destroy() //del(src) - return + tag = null + return 0 /datum/var/gc_destroyed //Time when this object was destroyed. diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index 0754b284c67..0aacf50f5b6 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -1,56 +1,50 @@ var/datum/subsystem/lighting/SSlighting #define MC_AVERAGE(average, current) (0.8*(average) + 0.2*(current)) -#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha6.dmi' -#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays /datum/subsystem/lighting name = "Lighting" wait = 5 priority = 1 - var/list/lighting_images = list() //replaces lighting_states (use lighting_images.len) ~carn - var/list/lights = list() //list of all datum/light_source - var/lights_workload = 0 //stats on the largest number of lights (max lights.len) - var/list/changed_turfs = list() //list of all turfs which need moving to a new lighting subarea + var/list/changed_lights = list() //list of all datum/light_source that need updating + var/changed_lights_workload = 0 //stats on the largest number of lights (max changed_lights.len) + var/list/changed_turfs = list() //list of all turfs which may have a different light level var/changed_turfs_workload = 0 //stats on the largest number of turfs changed (max changed_turfs.len) /datum/subsystem/lighting/New() NEW_SS_GLOBAL(SSlighting) - //cache lighting images - if(!lighting_images.len) - for(var/icon_state in icon_states(LIGHTING_ICON)) - lighting_images += image(LIGHTING_ICON, null, icon_state, LIGHTING_LAYER) - return ..() /datum/subsystem/lighting/stat_entry() - stat(name, "[round(cost,0.001)]ds (CPU:[round(cpu,1)]%) L:[round(lights_workload,1)]/T:[round(changed_turfs_workload,1)]") + stat(name, "[round(cost,0.001)]ds (CPU:[round(cpu,1)]%) L:[round(changed_lights_workload,1)]/T:[round(changed_turfs_workload,1)]") -//Workhorse of lighting. It cycles through each light to see which ones need their effects updating. It updates their -//effects and then processes every turf in the queue, moving the turfs to the corresponing lighting sub-area. -//All queue lists prune themselves, which will cause lights with no luminosity to be garbage collected (cheaper and safer -//than deleting them). +//Workhorse of lighting. It cycles through each light that needs updating. It updates their +//effects and then processes every turf in the queue, updating their lighting object's appearance +//Any light that returns 1 in check() deletes itself //By using queues we are ensuring we don't perform more updates than are necessary /datum/subsystem/lighting/fire() - lights_workload = MC_AVERAGE(lights_workload, lights.len) - var/i=1 - for(var/thing in lights) - if(thing && !thing:check()) //yes, cry that I'm using the : operator, it's much faster looping like this. And this gets called a lot. Dealwithit. - ++i - continue - lights.Cut(i, i+1) + changed_lights_workload = MC_AVERAGE(changed_lights_workload, changed_lights.len) + +// for(var/area/A in sortedAreas) +// A.luminosity = 1 + + for(var/datum/light_source/thing in changed_lights) + thing.check() + changed_lights.Cut() changed_turfs_workload = MC_AVERAGE(changed_turfs_workload, changed_turfs.len) - for(var/thing in changed_turfs) - if(thing && thing:lighting_changed) - thing:shift_to_subarea() + for(var/turf/thing in changed_turfs) + if(thing && thing.lighting_changed) + thing.redraw_lighting() changed_turfs.Cut() +// for(var/area/A in sortedAreas) +// A.luminosity = !A.lighting_use_dynamic //same as above except it attempts to shift ALL turfs in the world regardless of lighting_changed status //Does not loop. Should be run prior to process() being called for the first time. @@ -58,12 +52,13 @@ var/datum/subsystem/lighting/SSlighting //z-levels with the z_level argument /datum/subsystem/lighting/Initialize(timeofday, z_level) - var/i=1 - for(var/thing in lights) - if(thing && !thing:check()) - ++i - continue - lights.Cut(i, i+1) +// for(var/area/A in sortedAreas) +// A.luminosity = 1 + + for(var/datum/light_source/thing in changed_lights) + thing.add_effect() + thing.changed = 0 + changed_lights.Cut() var/z_start = 1 var/z_finish = world.maxz @@ -72,28 +67,24 @@ var/datum/subsystem/lighting/SSlighting z_start = z_level z_finish = z_level - for(var/z=z_start, z<=z_finish, ++z) - for(var/x=1, x<=world.maxx, ++x) - for(var/y=1, y<=world.maxy, ++y) - var/turf/T = locate(x,y,z) - if(T) - T.shift_to_subarea() + var/list/turfs_to_init = block(locate(1, 1, z_start), locate(world.maxx, world.maxy, z_finish)) + + for(var/turf/T in turfs_to_init) + T.init_lighting() if(z_level) //we need to loop through to clear only shifted turfs from the list. or we will cause errors - i=1 - for(var/thing in changed_turfs) - if(thing && thing:z < z_start && z_finish < thing:z) + var/i=1 + for(var/turf/thing in changed_turfs) + if(thing && thing.z < z_start && z_finish < thing.z) ++i continue changed_turfs.Cut(i, i+1) else changed_turfs.Cut() - if(config.starlight) - set background = 1 - for(var/turf/space/S in world) - S.update_starlight() +// for(var/area/A in sortedAreas) +// A.luminosity = !A.lighting_use_dynamic ..() @@ -103,21 +94,20 @@ var/datum/subsystem/lighting/SSlighting /datum/subsystem/lighting/Recover() if(!istype(SSlighting.changed_turfs)) SSlighting.changed_turfs = list() - if(!istype(SSlighting.lights)) - SSlighting.lights = list() + if(!istype(SSlighting.changed_lights)) + SSlighting.changed_lights = list() - if(istype(SSlighting.lighting_images)) - lighting_images = SSlighting.lighting_images +// for(var/area/A in sortedAreas) +// A.luminosity = 1 - for(var/datum/light_source/L in SSlighting.lights) + for(var/datum/light_source/L in SSlighting.changed_lights) spawn(-1) //so we don't crash the loop (inefficient) L.check() - lights += L //If we didn't runtime then this will get transferred over for(var/turf/T in changed_turfs) if(T.lighting_changed) spawn(-1) - T.shift_to_subarea() + T.redraw_lighting() var/msg = "## DEBUG: [time2text(world.timeofday)] [name] subsystem restarted. Reports:\n" for(var/varname in SSlighting.vars) @@ -132,5 +122,5 @@ var/datum/subsystem/lighting/SSlighting msg += "\t [varname] = [varval1] -> [varval2]\n" world.log << msg -#undef LIGHTING_ICON -#undef LIGHTING_LAYER \ No newline at end of file +// for(var/area/A in sortedAreas) +// A.luminosity = !A.lighting_use_dynamic \ No newline at end of file diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index fb9b8f856d3..d9b12400f19 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -194,8 +194,7 @@ proc/process_ghost_teleport_locs() /area/asteroid/artifactroom/New() ..() - lighting_use_dynamic = 1 - InitializeLighting() + SetDynamicLighting() /area/planet/clown name = "\improper Clown Planet" diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 86520169a27..f33d876c73b 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -43,7 +43,6 @@ ..() power_change() // all machines set to current power level, also updates lighting icon - InitializeLighting() blend_mode = BLEND_MULTIPLY // Putting this in the constructure so that it stops the icons being screwed up in the map editor. @@ -223,7 +222,7 @@ return /area/proc/updateicon() - if ((fire || eject || party) && (!requires_power||power_environ) && !lighting_space)//If it doesn't require power, can still activate this proc. + if ((fire || eject || party) && (!requires_power||power_environ))//If it doesn't require power, can still activate this proc. if(fire && !eject && !party) icon_state = "blue" /*else if(atmosalm && !fire && !eject && !party) @@ -238,6 +237,8 @@ // new lighting behaviour with obj lights icon_state = null +/area/space/updateicon() + icon_state = null /* #define EQUIP 1 @@ -251,8 +252,6 @@ return 1 if(master.always_unpowered) return 0 - if(src.lighting_space) - return 0 // Nope sorry switch(chan) if(EQUIP) return master.power_equip @@ -263,6 +262,9 @@ return 0 +/area/space/powered(chan) //Nope.avi + return 0 + // called when power status changes /area/proc/power_change() diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index a0eaf523e16..c0db11eedd5 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -46,11 +46,13 @@ else if (step(src, WEST)) . = step(src, SOUTH) - if(!loc || (loc == oldloc && oldloc != newloc)) last_move = 0 return + if(.) + Moved(oldloc, direct) + last_move = direct spawn(5) // Causes space drifting. /tg/station has no concept of speed, we just use 5 @@ -58,6 +60,10 @@ if(loc == newloc) //Remove this check and people can accelerate. Not opening that can of worms just yet. newtonian_move(last_move) +//Called after a successful Move(). By this point, we've already moved +/atom/movable/proc/Moved(atom/OldLoc, Dir) + return 1 + /atom/movable/Del() if(isnull(gc_destroyed) && loc) testing("GC: -- [type] was deleted via del() rather than qdel() --") @@ -68,14 +74,13 @@ ..() /atom/movable/Destroy() + . = ..() if(reagents) qdel(reagents) for(var/atom/movable/AM in contents) qdel(AM) - tag = null loc = null invisibility = 101 - // Do not call ..() // Previously known as HasEntered() // This is automatically called when something enters your square @@ -96,12 +101,15 @@ /atom/movable/proc/forceMove(atom/destination) if(destination) - if(loc) - loc.Exited(src) + var/atom/oldloc = loc + if(oldloc) + oldloc.Exited(src, destination) loc = destination - loc.Entered(src) - for(var/atom/movable/AM in loc) + destination.Entered(src, oldloc) + for(var/atom/movable/AM in destination) + if(AM == src) continue AM.Crossed(src) + Moved(oldloc, 0) return 1 return 0 diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index 736fa2e7df9..9d6de20b142 100644 --- a/code/game/gamemodes/blob/blob_report.dm +++ b/code/game/gamemodes/blob/blob_report.dm @@ -57,9 +57,7 @@ /datum/station_state/proc/count() - for(var/turf/T in world) - if(T.z != ZLEVEL_STATION) - continue + for(var/turf/T in block(locate(1,1,1), locate(world.maxx,world.maxy,1))) if(istype(T,/turf/simulated/floor)) if(!(T:burnt)) @@ -79,19 +77,16 @@ else src.r_wall += 1 - for(var/obj/O in world) - if(O.z != ZLEVEL_STATION) - continue - if(istype(O, /obj/structure/window)) - src.window += 1 - else if(istype(O, /obj/structure/grille) && (!O:destroyed)) - src.grille += 1 - else if(istype(O, /obj/machinery/door)) - src.door += 1 - else if(istype(O, /obj/machinery)) - src.mach += 1 - return + for(var/obj/O in T.contents) + if(istype(O, /obj/structure/window)) + src.window += 1 + else if(istype(O, /obj/structure/grille) && (!O:destroyed)) + src.grille += 1 + else if(istype(O, /obj/machinery/door)) + src.door += 1 + else if(istype(O, /obj/machinery)) + src.mach += 1 /datum/station_state/proc/score(var/datum/station_state/result) diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 9e51ce6bcf3..21a4ba0fff2 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -42,15 +42,15 @@ pixel_y = ((src.dir & 3)? (src.dir ==1 ? 24 : -32) : (0)) spawn(20) - for(var/obj/machinery/door/window/brigdoor/M in world) + for(var/obj/machinery/door/window/brigdoor/M in range(20, src)) if (M.id == src.id) targets += M - for(var/obj/machinery/flasher/F in world) + for(var/obj/machinery/flasher/F in range(20, src)) if(F.id == src.id) targets += F - for(var/obj/structure/closet/secure_closet/brig/C in world) + for(var/obj/structure/closet/secure_closet/brig/C in range(20, src)) if(C.id == src.id) targets += C diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 00d896cc6c0..1ba38ab9140 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -181,7 +181,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() if (Console.department == department) Console.newmessagepriority = 0 Console.update_icon() - Console.luminosity = 1 + Console.SetLuminosity(1) newmessagepriority = 0 update_icon() var/messageComposite = "" @@ -317,7 +317,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() else // Normal priority Console.createmessage(src, "Message from [department]", sending, 1, 1) screen = 6 - Console.luminosity = 2 + Console.SetLuminosity(2) switch(priority) if(2) @@ -431,7 +431,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() var/obj/item/weapon/paper/slip = new /obj/item/weapon/paper(src.loc) slip.info = "From: [unlinkedsender]
[message]" slip.name = "Message - [unlinkedsender]" - src.luminosity = 2 + SetLuminosity(2) /obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob, params) if (istype(O, /obj/item/weapon/crowbar)) diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index 0c5002a60f5..d8389f36327 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -148,7 +148,6 @@ return var/area/A = new A.name = str - A.tagbase="[A.type]_[md5(str)]" // without this dynamic light system ruin everithing //var/ma //ma = A.master ? "[A.master]" : "(null)" //world << "DEBUG: create_area:
A.name=[A.name]
A.tag=[A.tag]
A.master=[ma]" diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 46d41aff01f..e383f8633dc 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -195,6 +195,7 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/ai icon_state = "NONE" ttone = "data" + fon = 0 mode = 5 noreturn = 1 detonate = 0 @@ -223,6 +224,12 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/New() ..() + if(fon) + if(!isturf(loc)) + loc.AddLuminosity(f_lum) + SetLuminosity(0) + else + SetLuminosity(f_lum) PDAs += src if(default_cartridge) cartridge = new default_cartridge(src) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 66019ef52b5..061a8db5665 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -126,8 +126,7 @@ /turf/proc/ChangeTurf(var/path) if(!path) return if(path == type) return src - var/old_lumcount = lighting_lumcount - initial(lighting_lumcount) - var/old_opacity = opacity + SSair.remove_from_active(src) var/turf/W = new path(src) @@ -136,18 +135,6 @@ W:Assimilate_Air() W.RemoveLattice() - W.lighting_lumcount += old_lumcount - if(old_lumcount != W.lighting_lumcount) //light levels of the turf have changed. We need to shift it to another lighting-subarea - W.lighting_changed = 1 - SSlighting.changed_turfs += W - - if(old_opacity != W.opacity) //opacity has changed. Need to update surrounding lights - if(W.lighting_lumcount) //unless we're being illuminated, don't bother (may be buggy, hard to test) - W.UpdateAffectingLights() - - for(var/turf/space/S in range(W,1)) - S.update_starlight() - W.levelupdate() W.CalculateAdjacentTurfs() return W diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 75f860eb5f0..e4ec5e8fd5a 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -137,7 +137,7 @@ /datum/spacevine_mutation/light/on_grow(obj/effect/spacevine/holder) if(prob(10*severity)) - holder.luminosity = 4 + holder.SetLuminosity(4) /datum/spacevine_mutation/toxicity name = "toxic" diff --git a/code/modules/lighting/lighting_system.dm b/code/modules/lighting/lighting_system.dm new file mode 100644 index 00000000000..d1a24a9a9bc --- /dev/null +++ b/code/modules/lighting/lighting_system.dm @@ -0,0 +1,379 @@ +/* + This is /tg/'s 'newer' lighting system. It's basically a combination of Forum_Account's and ShadowDarke's + respective lighting libraries heavily modified by Carnwennan for /tg/station with further edits by + MrPerson. Credits, where due, to them. + + Originally, like all other lighting libraries on BYOND, we used areas to render different hard-coded light levels. + The idea was that this was cheaper than using objects. Well as it turns out, the cost of the system is primarily from the + massive loops the system has to run, not from the areas or objects actually doing any work. Thus the newer system uses objects + so we can have more lighting states and smooth transitions between them. + + This is a queueing system. Everytime we call a change to opacity or luminosity throwgh SetOpacity() or SetLuminosity(), + we are simply updating variables and scheduling certain lights/turfs for an update. Actual updates are handled + periodically by the SSlighting subsystem. Specifically, it runs check() on every light datum that ran changed(). + Then it runs redraw_lighting() on every turf that ran update_lumcount(). + + Unlike our older system, there are hardcoded maximum luminosities (different for certain atoms). + This is to cap the cost of creating lighting effects. + (without this, an atom with luminosity of 20 would have to update 41^2 turfs!) :s + + Each light remembers the effect it casts on each turf. It reduces cost of removing lighting effects by a lot! + + Known Issues/TODO: + Shuttles still do not have support for dynamic lighting (I hope to fix this at some point) -probably trivial now + No directional lighting support. (prototype looked ugly) + Allow lights to be weaker than 'cap' radius + Colored lights +*/ + +#define LIGHTING_CIRCULAR 1 //comment this out to use old square lighting effects. +#define LIGHTING_LAYER 15 //Drawing layer for lighting +#define LIGHTING_CAP 10 //The lumcount level at which alpha is 0 and we're fully lit. +#define LIGHTING_CAP_FRAC (255/LIGHTING_CAP) //A precal'd variable we'll use in turf/redraw_lighting() +#define LIGHTING_ICON 'icons/effects/alphacolors.dmi' +#define LIGHTING_ICON_STATE "white" +#define LIGHTING_TIME 1.2 //Time to do any lighting change. Actual number pulled out of my ass +#define LIGHTING_DARKEST_VISIBLE_ALPHA 230 //Anything darker than this is so dark, we'll just consider the whole tile unlit + +/datum/light_source + var/atom/owner + var/radius = 0 + var/changed = 1 + var/list/effect = list() + var/__x = 0 //x coordinate at last update + var/__y = 0 //y coordinate at last update + +/datum/light_source/New(atom/A) + if(!istype(A)) + CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.") + ..() + owner = A + radius = A.luminosity + __x = owner.x + __y = owner.y + SSlighting.changed_lights |= src + +/datum/light_source/Destroy() + if(owner && owner.light == src) + remove_effect() + owner.light = null + owner = null + return ..() + +//Check a light to see if its effect needs reprocessing. If it does, remove any old effect and create a new one +/datum/light_source/proc/check() + if(!owner) + remove_effect() + return 0 + + if(changed) + changed = 0 + remove_effect() + return add_effect() + + return 1 + +//Tell the lighting subsystem to check() next fire +/datum/light_source/proc/changed() + if(owner) + __x = owner.x + __y = owner.y + if(!changed) + changed = 1 + SSlighting.changed_lights |= src + +//Remove current effect +/datum/light_source/proc/remove_effect(). + for(var/turf/T in effect) + T.update_lumcount(-effect[T]) + + if(T.affecting_lights && T.affecting_lights.len) + T.affecting_lights -= src + + effect.Cut() + +//Apply a new effect +/datum/light_source/proc/add_effect() + // only do this if the light is turned on and is on the map + if(owner && owner.loc && radius > 0) + effect = list() + var/turf/To = get_turf(owner) + var/range = owner.get_light_range(radius) + for(var/atom/movable/AM in To) + if(AM == owner) + continue + if(AM.opacity) + range = 0 + break + + for(var/turf/T in view(range, To)) + var/delta_lumcount = T.lumen(src) + if(delta_lumcount > 0) + effect[T] = delta_lumcount + T.update_lumcount(delta_lumcount) + + if(!T.affecting_lights) + T.affecting_lights = list() + T.affecting_lights |= src + + return 1 + else + return 0 + +//How much light light_source L should apply to src +/turf/proc/lumen(datum/light_source/L) + var/distance = 0 +#ifdef LIGHTING_CIRCULAR + distance = cheap_hypotenuse(x, y, L.__x, L.__y) +#else + distance = max(abs(x - L.__x), abs(y - L.__y)) +#endif + return LIGHTING_CAP * (L.radius - distance) / L.radius +//LIGHTING_CAP == strength for now + + +/atom + var/datum/light_source/light + + +//Turfs with opacity when they are constructed will trigger nearby lights to update +//Turfs and atoms with luminosity when they are constructed will create a light_source automatically +/turf/New() + ..() + if(luminosity) + light = new(src) +// luminosity = 0 + +//Movable atoms with opacity when they are constructed will trigger nearby lights to update +//Movable atoms with luminosity when they are constructed will create a light_source automatically +/atom/movable/New() + ..() + if(opacity) + UpdateAffectingLights() + if(luminosity) + light = new(src) +// luminosity = 0 + +//Objects with opacity will trigger nearby lights to update at next SSlighting fire +/atom/movable/Destroy() + qdel(light) + if(opacity) + UpdateAffectingLights() + return ..() + +//Objects with opacity will trigger nearby lights of the old location to update at next SSlighting fire +/atom/movable/Moved(atom/OldLoc, Dir) + if(isturf(loc)) + if(opacity) + OldLoc.UpdateAffectingLights() + else + if(light) + light.changed() + return ..() + +//Sets our luminosity. +//If we have no light it will create one. +//If we are setting luminosity to 0 the light will be cleaned up by the controller and garbage collected once all its +//queues are complete. +//if we have a light already it is merely updated, rather than making a new one. +/atom/proc/SetLuminosity(new_luminosity) + if(new_luminosity < 0) + new_luminosity = 0 + + if(!light) + if(!new_luminosity) + return + light = new(src) + else + if(light.radius == new_luminosity) + return + light.radius = new_luminosity + luminosity = new_luminosity + light.changed() + +/atom/proc/AddLuminosity(delta_luminosity) + if(light) + SetLuminosity(light.radius + delta_luminosity) + else + SetLuminosity(delta_luminosity) + +/area/SetLuminosity(new_luminosity) //we don't want dynamic lighting for areas + luminosity = !!new_luminosity + + +//change our opacity (defaults to toggle), and then update all lights that affect us. +/atom/proc/SetOpacity(new_opacity) + if(new_opacity == null) + new_opacity = !opacity //default = toggle opacity + else if(opacity == new_opacity) + return 0 //opacity hasn't changed! don't bother doing anything + opacity = new_opacity //update opacity, the below procs now call light updates. + UpdateAffectingLights() + return 1 + +/atom/movable/light + icon = LIGHTING_ICON + icon_state = LIGHTING_ICON_STATE + layer = LIGHTING_LAYER + mouse_opacity = 0 + blend_mode = BLEND_OVERLAY + invisibility = INVISIBILITY_LIGHTING + color = "#000" + luminosity = 0 + infra_luminosity = 1 + anchored = 1 + +/atom/movable/light/Destroy() + return 1 + +/atom/movable/light/Move() + return 0 + +/turf + var/lighting_lumcount = 0 + var/lighting_changed = 0 + var/atom/movable/light/lighting_object //Will be null for space turfs and anything in a static lighting area + var/list/affecting_lights //not initialised until used (even empty lists reserve a fair bit of memory) + +/turf/ChangeTurf(var/path) + if(!path || path == type) //Sucks this is here but it would cause problems otherwise. + return ..() + + if(light) + qdel(light) + + var/old_lumcount = lighting_lumcount - initial(lighting_lumcount) + + var/list/our_lights //reset affecting_lights if needed + if(opacity != initial(path:opacity) && old_lumcount) + UpdateAffectingLights() + + if(affecting_lights) + our_lights = affecting_lights.Copy() + + . = ..() //At this point the turf has changed + + affecting_lights = our_lights + + lighting_changed = 1 //Don't add ourself to SSlighting.changed_turfs + update_lumcount(old_lumcount) + lighting_object = locate() in src + init_lighting() + + for(var/turf/space/S in orange(src,1)) + S.update_starlight() + +/turf/proc/update_lumcount(amount) + lighting_lumcount += amount + if(!lighting_changed) + SSlighting.changed_turfs += src + lighting_changed = 1 + +/turf/space/update_lumcount(amount) //Keep track in case the turf becomes a floor at some point, but don't process. + lighting_lumcount += amount + +/turf/proc/init_lighting() + var/area/A = loc + if(!A.lighting_use_dynamic || istype(src, /turf/space)) + lighting_changed = 0 + if(lighting_object) + lighting_object.alpha = 0 + lighting_object = null + else + if(!lighting_object) + lighting_object = new (src) + redraw_lighting(1) + +/turf/space/init_lighting() + . = ..() + if(config.starlight) + update_starlight() + +/turf/proc/redraw_lighting(var/instantly = 0) + if(lighting_object) + var/newalpha + if(lighting_lumcount <= 0) + newalpha = 255 + else + lighting_object.luminosity = 1 + if(lighting_lumcount < LIGHTING_CAP) + var/num = Clamp(lighting_lumcount * LIGHTING_CAP_FRAC, 0, 255) + newalpha = 255-num + else //if(lighting_lumcount >= LIGHTING_CAP) + newalpha = 0 + + if(lighting_object.alpha != newalpha) + var/change_time = LIGHTING_TIME + if(instantly) + change_time = 0 + animate(lighting_object, alpha = newalpha, time = change_time) + if(newalpha >= LIGHTING_DARKEST_VISIBLE_ALPHA) //Doesn't actually make it darker or anything, just tells byond you can't see the tile + animate(luminosity = 0, time = 0) + + lighting_changed = 0 + +/area + var/lighting_use_dynamic = 1 //Turn this flag off to make the area fullbright + +/area/New() + . = ..() + if(!lighting_use_dynamic) + luminosity = 1 + +/area/proc/SetDynamicLighting() + lighting_use_dynamic = 1 + luminosity = 0 + for(var/turf/T in src.contents) + T.init_lighting() + T.update_lumcount(0) + +#undef LIGHTING_LAYER +#undef LIGHTING_CIRCULAR +#undef LIGHTING_ICON +#undef LIGHTING_ICON_STATE +#undef LIGHTING_TIME +#undef LIGHTING_CAP +#undef LIGHTING_CAP_FRAC +#undef LIGHTING_DARKEST_VISIBLE_ALPHA + + +//set the changed status of all lights which could have possibly lit this atom. +//We don't need to worry about lights which lit us but moved away, since they will have change status set already +//This proc can cause lots of lights to be updated. :( +/atom/proc/UpdateAffectingLights() + +/atom/movable/UpdateAffectingLights() + if(isturf(loc)) + loc.UpdateAffectingLights() + +/turf/UpdateAffectingLights() + if(affecting_lights) + for(var/datum/light_source/thing in affecting_lights) + thing.changed() //force it to update at next process() + + +#define LIGHTING_MAX_LUMINOSITY_STATIC 8 //Maximum luminosity to reduce lag. +#define LIGHTING_MAX_LUMINOSITY_MOBILE 5 //Moving objects have a lower max luminosity since these update more often. (lag reduction) +#define LIGHTING_MAX_LUMINOSITY_MOB 5 +#define LIGHTING_MAX_LUMINOSITY_TURF 8 //turfs are static too, why was this 1?! + +//caps luminosity effects max-range based on what type the light's owner is. +/atom/proc/get_light_range(radius) + return min(radius, LIGHTING_MAX_LUMINOSITY_STATIC) + +/atom/movable/get_light_range(radius) + return min(radius, LIGHTING_MAX_LUMINOSITY_MOBILE) + +/mob/get_light_range(radius) + return min(radius, LIGHTING_MAX_LUMINOSITY_MOB) + +/obj/machinery/light/get_light_range(radius) + return min(radius, LIGHTING_MAX_LUMINOSITY_STATIC) + +/turf/get_light_range(radius) + return min(radius, LIGHTING_MAX_LUMINOSITY_TURF) + +#undef LIGHTING_MAX_LUMINOSITY_STATIC +#undef LIGHTING_MAX_LUMINOSITY_MOBILE +#undef LIGHTING_MAX_LUMINOSITY_MOB +#undef LIGHTING_MAX_LUMINOSITY_TURF diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 31e2944aa96..89642e29838 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -277,7 +277,7 @@ update_icon() if(on) - if(luminosity != brightness) + if(!light || light.radius != brightness) switchcount++ if(rigged) if(status == LIGHT_OK && trigger) @@ -295,11 +295,11 @@ use_power = 1 SetLuminosity(0) - active_power_usage = (luminosity * 10) + active_power_usage = (brightness * 10) if(on != on_gs) on_gs = on if(on) - static_power_used = luminosity * 20 //20W per unit luminosity + static_power_used = brightness * 20 //20W per unit luminosity addStaticPower(static_power_used, STATIC_LIGHT) else removeStaticPower(static_power_used, STATIC_LIGHT) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 846f7e28c14..204b94477e7 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -321,6 +321,8 @@ for(var/obj/O in T0) if(O.invisibility >= 101) continue + if(O == T0.lighting_object) + continue O.loc = T1 //close open doors @@ -350,13 +352,13 @@ //air system updates for(var/turf/T1 in L1) - T1.shift_to_subarea() + T1.redraw_lighting() SSair.remove_from_active(T1) T1.CalculateAdjacentTurfs() SSair.add_to_active(T1,1) for(var/turf/T0 in L0) - T0.shift_to_subarea() + T0.redraw_lighting() SSair.remove_from_active(T0) T0.CalculateAdjacentTurfs() SSair.add_to_active(T0,1) diff --git a/html/changelogs/MrPerson.yml b/html/changelogs/MrPerson.yml index 6378584f30e..642ce9a49f5 100644 --- a/html/changelogs/MrPerson.yml +++ b/html/changelogs/MrPerson.yml @@ -1,2 +1,3 @@ author: MrPerson -changes: [] +changes: + - experiment: "New lighting system! Lighting now smoothly transfers from one lighting level to the next." diff --git a/icons/effects/alphacolors.dmi b/icons/effects/alphacolors.dmi index 02316fbf64d..74452b58dcf 100644 Binary files a/icons/effects/alphacolors.dmi and b/icons/effects/alphacolors.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 65785814dc7..6255ad3a698 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -118,7 +118,6 @@ #include "code\ATMOSPHERICS\pipes\simple.dm" #include "code\ATMOSPHERICS\pipes\tank.dm" #include "code\ATMOSPHERICS\pipes\vent.dm" -#include "code\controllers\_DynamicAreaLighting_TG.dm" #include "code\controllers\configuration.dm" #include "code\controllers\failsafe.dm" #include "code\controllers\master_controller.dm" @@ -1014,6 +1013,7 @@ #include "code\modules\library\lib_items.dm" #include "code\modules\library\lib_machines.dm" #include "code\modules\library\lib_readme.dm" +#include "code\modules\lighting\lighting_system.dm" #include "code\modules\mining\equipment_locker.dm" #include "code\modules\mining\machine_input_output_plates.dm" #include "code\modules\mining\machine_processing.dm"