mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
Got vgstation13 colored lights rewrite working here.
This commit is contained in:
@@ -366,3 +366,35 @@ datum/projectile_data
|
|||||||
var/dest_y = src_y + distance*cos(rotation);
|
var/dest_y = src_y + distance*cos(rotation);
|
||||||
|
|
||||||
return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
|
return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
|
||||||
|
|
||||||
|
/proc/GetRedPart(const/hexa)
|
||||||
|
var/hex = uppertext(hexa)
|
||||||
|
var/hi = text2ascii(hex, 2)
|
||||||
|
var/lo = text2ascii(hex, 3)
|
||||||
|
return (((hi >= 65 ? hi - 55 : hi - 48) << 4) | (lo >= 65 ? lo - 55 : lo - 48))
|
||||||
|
|
||||||
|
/proc/GetGreenPart(const/hexa)
|
||||||
|
var/hex = uppertext(hexa)
|
||||||
|
var/hi = text2ascii(hex, 4)
|
||||||
|
var/lo = text2ascii(hex, 5)
|
||||||
|
return (((hi >= 65 ? hi - 55 : hi - 48) << 4) | (lo >= 65 ? lo - 55 : lo - 48))
|
||||||
|
|
||||||
|
/proc/GetBluePart(const/hexa)
|
||||||
|
var/hex = uppertext(hexa)
|
||||||
|
var/hi = text2ascii(hex, 6)
|
||||||
|
var/lo = text2ascii(hex, 7)
|
||||||
|
return (((hi >= 65 ? hi - 55 : hi - 48) << 4) | (lo >= 65 ? lo - 55 : lo - 48))
|
||||||
|
|
||||||
|
/proc/GetHexColors(const/hexa)
|
||||||
|
var/hex = uppertext(hexa)
|
||||||
|
var/hi1 = text2ascii(hex, 2)
|
||||||
|
var/lo1 = text2ascii(hex, 3)
|
||||||
|
var/hi2 = text2ascii(hex, 4)
|
||||||
|
var/lo2 = text2ascii(hex, 5)
|
||||||
|
var/hi3 = text2ascii(hex, 6)
|
||||||
|
var/lo3 = text2ascii(hex, 7)
|
||||||
|
return list(
|
||||||
|
((hi1 >= 65 ? hi1 - 55 : hi1 - 48) << 4) | (lo1 >= 65 ? lo1 - 55 : lo1 - 48),
|
||||||
|
((hi2 >= 65 ? hi2 - 55 : hi2 - 48) << 4) | (lo2 >= 65 ? lo2 - 55 : lo2 - 48),
|
||||||
|
((hi3 >= 65 ? hi3 - 55 : hi3 - 48) << 4) | (lo3 >= 65 ? lo3 - 55 : lo3 - 48)
|
||||||
|
)
|
||||||
|
|||||||
@@ -6,11 +6,12 @@
|
|||||||
// in the logs. ascii character 13 = CR
|
// in the logs. ascii character 13 = CR
|
||||||
|
|
||||||
/var/global/log_end= world.system_type == UNIX ? ascii2text(13) : ""
|
/var/global/log_end= world.system_type == UNIX ? ascii2text(13) : ""
|
||||||
|
|
||||||
|
|
||||||
/proc/error(msg)
|
/proc/error(msg)
|
||||||
world.log << "## ERROR: [msg][log_end]"
|
world.log << "## ERROR: [msg][log_end]"
|
||||||
|
|
||||||
|
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].")
|
||||||
//print a warning message to world.log
|
//print a warning message to world.log
|
||||||
/proc/warning(msg)
|
/proc/warning(msg)
|
||||||
world.log << "## WARNING: [msg][log_end]"
|
world.log << "## WARNING: [msg][log_end]"
|
||||||
@@ -79,4 +80,4 @@
|
|||||||
diary << "\[[time_stamp()]]PDA: [text][log_end]"
|
diary << "\[[time_stamp()]]PDA: [text][log_end]"
|
||||||
|
|
||||||
/proc/log_misc(text)
|
/proc/log_misc(text)
|
||||||
diary << "\[[time_stamp()]]MISC: [text][log_end]"
|
diary << "\[[time_stamp()]]MISC: [text][log_end]"
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
var/const/E = 2.71828183
|
var/const/E = 2.71828183
|
||||||
var/const/Sqrt2 = 1.41421356
|
var/const/Sqrt2 = 1.41421356
|
||||||
|
|
||||||
|
// List of square roots for the numbers 1-100.
|
||||||
|
var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10)
|
||||||
|
|
||||||
/proc/Atan2(x, y)
|
/proc/Atan2(x, y)
|
||||||
if(!x && !y) return 0
|
if(!x && !y) return 0
|
||||||
|
|||||||
@@ -5,9 +5,10 @@
|
|||||||
ShadowDarke's respective lighting libraries. Credits, where due, to them.
|
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
|
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.
|
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
|
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
|
(through SetOpacity() or SetLuminosity()) we are simply updating variables and scheduling certain lights/turfs for an
|
||||||
update. Actual updates are handled periodically by the lighting_controller. This carries additional overheads, however it
|
update. Actual updates are handled periodically by the lighting_controller. This carries additional overheads, however it
|
||||||
means that each thing is changed only once per lighting_controller.processing_interval ticks. Allowing for greater control
|
means that each thing is changed only once per lighting_controller.processing_interval ticks. Allowing for greater control
|
||||||
@@ -15,50 +16,40 @@
|
|||||||
setting lighting_controller.processing = 0 at say, the start of a large explosion, waiting for it to finish, and then
|
setting lighting_controller.processing = 0 at say, the start of a large explosion, waiting for it to finish, and then
|
||||||
turning it back on with lighting_controller.processing = 1.
|
turning it back on with lighting_controller.processing = 1.
|
||||||
|
|
||||||
Unlike our old system there is a hardcoded maximum luminosity. This is to discourage coders using large luminosity values
|
Unlike our old system there are hardcoded maximum luminositys (different for certain atoms).
|
||||||
for dynamic lighting, as the cost of lighting grows rapidly at large luminosity levels (especially when changing opacity
|
This is to cap the cost of creating lighting effects.
|
||||||
at runtime)
|
(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
|
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 hopefully it's worth the hassle for the greater control we
|
have larger memory requirements than our previous system but it's easily worth the hassle for the greater control we
|
||||||
gain. Besides, there are far far worse uses of needless lists in the game, it'd be worth pruning some of them to offset
|
gain. It also reduces cost of removing lighting effects by a lot!
|
||||||
costs.
|
|
||||||
|
|
||||||
Known Issues/TODO:
|
Known Issues/TODO:
|
||||||
admin-spawned turfs will have broken lumcounts. Not willing to fix it at this moment
|
|
||||||
mob luminosity will be lower than expected when one of multiple light sources is dropped after exceeding the maximum luminosity
|
|
||||||
Shuttles still do not have support for dynamic lighting (I hope to fix this at some point)
|
Shuttles still do not have support for dynamic lighting (I hope to fix this at some point)
|
||||||
No directional lighting support. Fairly easy to add this and the code is ready.
|
No directional lighting support. (prototype looked ugly)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LIGHTING_MAX_LUMINOSITY 12 //Hard maximum luminosity to prevet lag which could be caused by coders making mini-suns
|
#define LIGHTING_CIRCULAR 1 //comment this out to use old square lighting effects.
|
||||||
#define LIGHTING_MAX_LUMINOSITY_MOB 7 //Mobs get their own max because 60-odd human suns running around would be pretty silly
|
#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays
|
||||||
#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays
|
#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha6.dmi' //Icon used for lighting shading effects
|
||||||
#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha7.dmi' //Icon used for lighting shading effects
|
|
||||||
|
|
||||||
datum/light_source
|
datum/light_source
|
||||||
var/atom/owner
|
var/atom/owner
|
||||||
var/changed = 1
|
var/changed = 1
|
||||||
var/mobile = 1
|
|
||||||
var/list/effect = list()
|
var/list/effect = list()
|
||||||
|
|
||||||
var/__x = 0 //x coordinate at last update
|
var/__x = 0 //x coordinate at last update
|
||||||
var/__y = 0 //y coordinate at last update
|
var/__y = 0 //y coordinate at last update
|
||||||
|
var/l_color
|
||||||
|
|
||||||
|
|
||||||
New(atom/A)
|
New(atom/A)
|
||||||
if(!istype(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.")
|
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
|
owner = A
|
||||||
|
l_color = owner.l_color
|
||||||
if(istype(owner, /atom/movable)) mobile = 1 //apparantly this is faster than type-checking
|
|
||||||
else mobile = 0 //Perhaps removing support for luminous turfs would be a good idea.
|
|
||||||
|
|
||||||
__x = owner.x
|
__x = owner.x
|
||||||
__y = owner.y
|
__y = owner.y
|
||||||
|
|
||||||
// the lighting object maintains a list of all light sources
|
// the lighting object maintains a list of all light sources
|
||||||
lighting_controller.lights += src
|
lighting_controller.lights += src
|
||||||
|
|
||||||
@@ -69,12 +60,14 @@ datum/light_source
|
|||||||
remove_effect()
|
remove_effect()
|
||||||
return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it.
|
return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it.
|
||||||
|
|
||||||
if(mobile)
|
// check to see if we've moved since last update
|
||||||
// check to see if we've moved since last update
|
if(owner.x != __x || owner.y != __y)
|
||||||
if(owner.x != __x || owner.y != __y)
|
__x = owner.x
|
||||||
__x = owner.x
|
__y = owner.y
|
||||||
__y = owner.y
|
changed = 1
|
||||||
changed = 1
|
|
||||||
|
if (owner.l_color != l_color)
|
||||||
|
changed = 1
|
||||||
|
|
||||||
if(changed)
|
if(changed)
|
||||||
changed = 0
|
changed = 0
|
||||||
@@ -85,197 +78,282 @@ datum/light_source
|
|||||||
|
|
||||||
proc/remove_effect()
|
proc/remove_effect()
|
||||||
// before we apply the effect we remove the light's current effect.
|
// before we apply the effect we remove the light's current effect.
|
||||||
if(effect.len)
|
for(var/turf/T in effect) // negate the effect of this light source
|
||||||
for(var/turf in effect) // negate the effect of this light source
|
T.update_lumcount(-effect[T], l_color, 1)
|
||||||
var/turf/T = turf
|
effect.Cut() // clear the effect list
|
||||||
T.update_lumcount(-effect[T])
|
|
||||||
effect.Cut() // clear the effect list
|
|
||||||
|
|
||||||
proc/add_effect()
|
proc/add_effect()
|
||||||
// only do this if the light is turned on and is on the map
|
// only do this if the light is turned on and is on the map
|
||||||
if(owner.loc && owner.luminosity > 0)
|
if(owner.loc && owner.luminosity > 0)
|
||||||
effect = new_effect() // identify the effects of this light source
|
l_color = owner.l_color
|
||||||
for(var/turf in effect)
|
effect = list()
|
||||||
var/turf/T = turf
|
for(var/turf/T in view(owner.get_light_range(),owner))
|
||||||
T.update_lumcount(effect[T]) // apply the effect
|
var/delta_lumen = lum(T)
|
||||||
|
if(delta_lumen > 0)
|
||||||
|
effect[T] = delta_lumen
|
||||||
|
T.update_lumcount(delta_lumen, l_color, 0)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
owner.light = null
|
owner.light = null
|
||||||
return 1 //cause the light to be removed from the lights list and garbage collected once it's no
|
return 1 //cause the light to be removed from the lights list and garbage collected once it's no
|
||||||
//longer referenced by the queue
|
//longer referenced by the queue
|
||||||
|
|
||||||
proc/new_effect()
|
|
||||||
. = list()
|
|
||||||
|
|
||||||
for(var/turf/T in view(owner.luminosity, owner))
|
|
||||||
// var/area/A = T.loc
|
|
||||||
// if(!A) continue
|
|
||||||
var/change_in_lumcount = lum(T)
|
|
||||||
if(change_in_lumcount > 0)
|
|
||||||
.[T] = change_in_lumcount
|
|
||||||
|
|
||||||
return .
|
|
||||||
|
|
||||||
|
|
||||||
proc/lum(turf/A)
|
proc/lum(turf/A)
|
||||||
return owner.luminosity - max(abs(A.x-__x),abs(A.y-__y))
|
if (owner.trueLuminosity < 1)
|
||||||
// var/dist = cheap_hypotenuse(A.x,A.y,__x,__y) //fetches the pythagorean distance between A and the light
|
return 0
|
||||||
// if(owner.luminosity < dist) //if the turf is outside the radius the light doesn't illuminate it
|
var/dist
|
||||||
// return 0
|
if(!A)
|
||||||
// return round(owner.luminosity - (dist/2),0.1)
|
dist = 0
|
||||||
|
else
|
||||||
|
#ifdef LIGHTING_CIRCULAR
|
||||||
|
dist = cheap_hypotenuse(A.x, A.y, __x, __y)
|
||||||
|
#else
|
||||||
|
dist = max(abs(A.x - __x), abs(A.y - __y))
|
||||||
|
#endif
|
||||||
|
if (owner.trueLuminosity > 100) // This will never happen... right?
|
||||||
|
return sqrt(owner.trueLuminosity) - dist
|
||||||
|
else
|
||||||
|
return sqrtTable[owner.trueLuminosity] - dist
|
||||||
|
|
||||||
atom
|
atom
|
||||||
var/datum/light_source/light
|
var/datum/light_source/light
|
||||||
|
var/trueLuminosity = 0 // Typically 'luminosity' squared. The builtin luminosity must remain linear.
|
||||||
|
// We may read it, but NEVER set it directly.
|
||||||
|
var/l_color
|
||||||
|
|
||||||
//Turfs with opacity when they are constructed will trigger nearby lights to update
|
//Turfs with opacity when they are constructed will trigger nearby lights to update
|
||||||
//Turfs atoms with luminosity when they are constructed will create a light_source automatically
|
//Turfs and atoms with luminosity when they are constructed will create a light_source automatically
|
||||||
//TODO: lag reduction
|
|
||||||
turf/New()
|
turf/New()
|
||||||
..()
|
..()
|
||||||
if(opacity)
|
|
||||||
UpdateAffectingLights()
|
|
||||||
if(luminosity)
|
if(luminosity)
|
||||||
world.log << "[type] has luminosity at New()"
|
if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.")
|
||||||
if(light) world.log << "## WARNING: [type] - Don't set lights up manually during New(), We do it automatically."
|
trueLuminosity = luminosity * luminosity
|
||||||
light = new(src)
|
light = new(src)
|
||||||
|
|
||||||
//Movable atoms with opacity when they are constructed will trigger nearby lights to update
|
//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
|
//Movable atoms with luminosity when they are constructed will create a light_source automatically
|
||||||
//TODO: lag reduction
|
|
||||||
atom/movable/New()
|
atom/movable/New()
|
||||||
..()
|
..()
|
||||||
if(opacity)
|
if(opacity)
|
||||||
UpdateAffectingLights()
|
if(isturf(loc))
|
||||||
|
if(loc:lighting_lumcount > 1)
|
||||||
|
UpdateAffectingLights()
|
||||||
if(luminosity)
|
if(luminosity)
|
||||||
if(light) world.log << "## WARNING: [type] - Don't set lights up manually during New(), We do it automatically."
|
if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.")
|
||||||
|
trueLuminosity = luminosity * luminosity
|
||||||
light = new(src)
|
light = new(src)
|
||||||
|
|
||||||
//Turfs with opacity will trigger nearby lights to update at next lighting process.
|
|
||||||
//TODO: is this really necessary? Removing it could help reduce lag during singulo-mayhem somewhat
|
|
||||||
turf/Del()
|
|
||||||
if(opacity)
|
|
||||||
UpdateAffectingLights()
|
|
||||||
..()
|
|
||||||
|
|
||||||
//Objects with opacity will trigger nearby lights to update at next lighting process.
|
//Objects with opacity will trigger nearby lights to update at next lighting process.
|
||||||
atom/movable/Del()
|
atom/movable/Del()
|
||||||
if(opacity)
|
if(opacity)
|
||||||
UpdateAffectingLights()
|
if(isturf(loc))
|
||||||
|
if(loc:lighting_lumcount > 1)
|
||||||
|
UpdateAffectingLights()
|
||||||
|
|
||||||
..()
|
..()
|
||||||
|
|
||||||
//Sets our luminosity. Enforces a hardcoded maximum luminosity by default. This maximum can be overridden but it is extremely
|
//Sets our luminosity.
|
||||||
//unwise to do so.
|
|
||||||
//If we have no light it will create one.
|
//If we have no light it will create one.
|
||||||
//If we are setting luminosity to 0 the light will be cleaned up and delted once all its queues are complete
|
//If we are setting luminosity to 0 the light will be cleaned up by the controller and garbage collected once all its
|
||||||
//if we have a light already it is merely updated
|
//queues are complete.
|
||||||
atom/proc/SetLuminosity(new_luminosity, max_luminosity = LIGHTING_MAX_LUMINOSITY)
|
//if we have a light already it is merely updated, rather than making a new one.
|
||||||
|
atom/proc/SetLuminosity(new_luminosity, trueLum = FALSE)
|
||||||
if(new_luminosity < 0)
|
if(new_luminosity < 0)
|
||||||
new_luminosity = 0
|
new_luminosity = 0
|
||||||
// world.log << "## WARNING: [type] - luminosity cannot be negative"
|
if(!trueLum)
|
||||||
else if(max_luminosity < new_luminosity)
|
new_luminosity *= new_luminosity
|
||||||
new_luminosity = max_luminosity
|
if(light)
|
||||||
// if(luminosity != new_luminosity)
|
if(trueLuminosity != new_luminosity) //non-luminous lights are removed from the lights list in add_effect()
|
||||||
// world.log << "## WARNING: [type] - LIGHT_MAX_LUMINOSITY exceeded"
|
light.changed = 1
|
||||||
|
else
|
||||||
|
if(new_luminosity)
|
||||||
|
light = new(src)
|
||||||
|
trueLuminosity = new_luminosity
|
||||||
|
if (trueLuminosity < 1)
|
||||||
|
luminosity = 0
|
||||||
|
else if (trueLuminosity <= 100)
|
||||||
|
luminosity = sqrtTable[trueLuminosity]
|
||||||
|
else
|
||||||
|
luminosity = sqrt(trueLuminosity)
|
||||||
|
|
||||||
if(isturf(loc))
|
atom/proc/AddLuminosity(delta_luminosity)
|
||||||
if(light)
|
if(delta_luminosity > 0)
|
||||||
if(luminosity != new_luminosity) //TODO: remove lights from the light list when they're not luminous? DONE in add_effect
|
SetLuminosity(trueLuminosity + delta_luminosity*delta_luminosity, TRUE)
|
||||||
light.changed = 1
|
else if(delta_luminosity < 0)
|
||||||
else
|
SetLuminosity(trueLuminosity - delta_luminosity*delta_luminosity, TRUE)
|
||||||
if(new_luminosity)
|
|
||||||
light = new(src)
|
|
||||||
|
|
||||||
luminosity = new_luminosity
|
area/SetLuminosity(new_luminosity) //we don't want dynamic lighting for areas
|
||||||
|
luminosity = !!new_luminosity
|
||||||
|
trueLuminosity = luminosity
|
||||||
|
|
||||||
//Snowflake code to prevent mobs becoming suns (lag-prevention)
|
|
||||||
mob/SetLuminosity(new_luminosity)
|
|
||||||
..(new_luminosity,LIGHTING_MAX_LUMINOSITY_MOB)
|
|
||||||
|
|
||||||
//change our opacity (defaults to toggle), and then update all lights that affect us.
|
//change our opacity (defaults to toggle), and then update all lights that affect us.
|
||||||
atom/proc/SetOpacity(var/new_opacity)
|
atom/proc/SetOpacity(new_opacity)
|
||||||
if(new_opacity == null) new_opacity = !opacity
|
if(new_opacity == null)
|
||||||
else if(opacity == new_opacity) return
|
new_opacity = !opacity //default = toggle opacity
|
||||||
opacity = new_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.
|
||||||
|
return 1
|
||||||
|
|
||||||
UpdateAffectingLights()
|
turf/SetOpacity(new_opacity)
|
||||||
|
if(..()==1) //only bother if opacity changed
|
||||||
|
if(lighting_lumcount) //only bother with an update if our turf is currently affected by a light
|
||||||
|
UpdateAffectingLights()
|
||||||
|
|
||||||
//set the changed status of all lights which could have possibly lit this atom.
|
/atom/movable/SetOpacity(new_opacity)
|
||||||
//We don't need to worry about lights which lit us but moved away, since they will have change status set already
|
if(..()==1) //only bother if opacity changed
|
||||||
atom/proc/UpdateAffectingLights()
|
if(isturf(loc)) //only bother with an update if we're on a turf
|
||||||
var/turf/T = src
|
var/turf/T = loc
|
||||||
if(!isturf(T))
|
if(T.lighting_lumcount) //only bother with an update if our turf is currently affected by a light
|
||||||
T = loc
|
UpdateAffectingLights()
|
||||||
if(!isturf(T)) return
|
|
||||||
for(var/atom in range(LIGHTING_MAX_LUMINOSITY,T)) //TODO: this will probably not work very well :(
|
|
||||||
var/atom/A = atom
|
|
||||||
if(A.light && A.luminosity)
|
|
||||||
A.light.changed = 1 //force it to update at next process()
|
|
||||||
|
|
||||||
// for(var/light in lighting_controller.lights) //TODO: this will probably laaaaaag
|
|
||||||
// var/datum/light_source/L = light
|
|
||||||
// if(L.changed) continue
|
|
||||||
// if(!L.owner) continue
|
|
||||||
// if(!L.owner.luminosity) continue
|
|
||||||
// if(src in L.effect)
|
|
||||||
// L.changed = 1
|
|
||||||
|
|
||||||
turf
|
turf
|
||||||
var/lighting_lumcount = 0
|
var/lighting_lumcount = 0
|
||||||
var/lighting_changed = 0
|
var/lighting_changed = 0
|
||||||
|
var/color_lighting_lumcount = 0
|
||||||
|
var/list/colors = list()
|
||||||
|
|
||||||
turf/space
|
turf/space
|
||||||
lighting_lumcount = 4 //starlight
|
lighting_lumcount = 4 //starlight
|
||||||
|
|
||||||
turf/proc/update_lumcount(amount)
|
turf/proc/update_lumcount(amount, _lcolor, removing = 0)
|
||||||
lighting_lumcount += amount
|
lighting_lumcount += amount
|
||||||
// if(lighting_lumcount < 0 || lighting_lumcount > 100)
|
var/blended
|
||||||
// world.log << "## WARNING: [type] ([src]) lighting_lumcount = [lighting_lumcount]"
|
|
||||||
|
if (_lcolor)
|
||||||
|
if (l_color && _lcolor && l_color != _lcolor && !removing) // Blend colors.
|
||||||
|
var/redblend = min((GetRedPart(l_color)) + (GetRedPart(_lcolor)), 255)
|
||||||
|
var/greenblend = min((GetGreenPart(l_color)) + (GetGreenPart(_lcolor)), 255)
|
||||||
|
var/blueblend = min((GetBluePart(l_color)) + (GetBluePart(_lcolor)), 255)
|
||||||
|
blended = "#[add_zero2(num2hex(redblend), 2)][add_zero2(num2hex(greenblend),2)][add_zero2(num2hex(blueblend),2)]"
|
||||||
|
|
||||||
|
if (removing)
|
||||||
|
colors.Remove(_lcolor) // Remove the color that's leaving us from our list.
|
||||||
|
|
||||||
|
if (colors && !colors.len)
|
||||||
|
l_color = null // All our color is gone, no color for us.
|
||||||
|
else if (colors && colors.len > 1)
|
||||||
|
var/maxdepth = 3 // Will blend 3 colors, anymore than that and it looks bad or we will get lag on every tile update.
|
||||||
|
var/currentblended
|
||||||
|
|
||||||
|
for (var/i = 0, ++i <= colors.len)
|
||||||
|
if (i > maxdepth)
|
||||||
|
//world << "Maxdepth reached, breaking loop."
|
||||||
|
break
|
||||||
|
|
||||||
|
if (!currentblended)
|
||||||
|
//world << "First iteration, currentblended = [colors[i]]."
|
||||||
|
currentblended = colors[i] // Start with the first of the remaining colors.
|
||||||
|
continue
|
||||||
|
|
||||||
|
var/redblend = min((GetRedPart(currentblended)) + (GetRedPart(colors[i])), 255)
|
||||||
|
var/greenblend = min((GetGreenPart(currentblended)) + (GetGreenPart(colors[i])), 255)
|
||||||
|
var/blueblend = min((GetBluePart(currentblended)) + (GetBluePart(colors[i])), 255)
|
||||||
|
currentblended = "#[add_zero2(num2hex(redblend), 2)][add_zero2(num2hex(greenblend), 2)][add_zero2(num2hex(blueblend), 2)]"
|
||||||
|
//world << "Finished [i] [currentblended]."
|
||||||
|
|
||||||
|
if (currentblended)
|
||||||
|
//world << "Ended up with [currentblended]"
|
||||||
|
l_color = currentblended // blended the remaining colors so apply it.
|
||||||
|
else
|
||||||
|
l_color = null // Something went wrong, no color for you.
|
||||||
|
else
|
||||||
|
l_color = colors[colors.len]
|
||||||
|
else // we added a color.
|
||||||
|
colors.Add(_lcolor) // Add the base color to the list.
|
||||||
|
|
||||||
|
if (blended)
|
||||||
|
l_color = blended // If we had a blended color, this is what we get otherwise.
|
||||||
|
else
|
||||||
|
l_color = _lcolor // Basecolor is our color.
|
||||||
|
|
||||||
|
// if ((l_color != LIGHT_WHITE && l_color != "#FFF") || removing)
|
||||||
|
color_lighting_lumcount = max(color_lighting_lumcount + amount, 0) // Minimum of 0.
|
||||||
|
|
||||||
if(!lighting_changed)
|
if(!lighting_changed)
|
||||||
lighting_controller.changed_turfs += src
|
lighting_controller.changed_turfs += src
|
||||||
lighting_changed = 1
|
lighting_changed = 1
|
||||||
|
|
||||||
|
turf/proc/lighting_tag(const/level)
|
||||||
|
var/area/A = loc
|
||||||
|
return A.tagbase + "sd_L[level]"
|
||||||
|
|
||||||
|
turf/proc/build_lighting_area(const/tag, const/level, const/color_light)
|
||||||
|
var/area/Area = loc
|
||||||
|
var/area/A = new Area.type() // create area if it wasn't found
|
||||||
|
// replicate vars
|
||||||
|
for(var/V in Area.vars)
|
||||||
|
switch(V)
|
||||||
|
if ("contents","lighting_overlay", "color_overlay", "overlays")
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
if(issaved(Area.vars[V])) A.vars[V] = Area.vars[V]
|
||||||
|
|
||||||
|
A.tag = tag
|
||||||
|
A.lighting_subarea = 1
|
||||||
|
A.lighting_space = 0 // in case it was copied from a space subarea
|
||||||
|
|
||||||
|
if (l_color != A.l_color)
|
||||||
|
A.l_color = l_color
|
||||||
|
//color_light = min(max(round(color_lighting_lumcount, 1), 0), lighting_controller.lighting_states)
|
||||||
|
//world << "[color_light] [color_lighting_lumcount]"
|
||||||
|
|
||||||
|
A.SetLightLevel(level, color_light)
|
||||||
|
Area.related += A
|
||||||
|
return A
|
||||||
|
|
||||||
turf/proc/shift_to_subarea()
|
turf/proc/shift_to_subarea()
|
||||||
lighting_changed = 0
|
lighting_changed = 0
|
||||||
var/area/Area = loc
|
var/area/Area = loc
|
||||||
|
|
||||||
if(!istype(Area) || !Area.lighting_use_dynamic) return
|
if(!istype(Area) || !Area.lighting_use_dynamic) return
|
||||||
|
|
||||||
// change the turf's area depending on its brightness
|
var/level = min(max(round(lighting_lumcount,1),0),lighting_controller.lighting_states)
|
||||||
// restrict light to valid levels
|
var/new_tag = lighting_tag(level)
|
||||||
var/light = min(max(round(lighting_lumcount,1),0),lighting_controller.lighting_states)
|
|
||||||
|
|
||||||
var/find = findtextEx(Area.tag, "sd_L")
|
// pomf - If we have a lighting color that is not null, apply the new tag to seperate the areas.
|
||||||
var/new_tag = copytext(Area.tag, 1, find)
|
if (l_color)
|
||||||
new_tag += "sd_L[light]"
|
new_tag += "[l_color][color_lighting_lumcount]" // pomf - We append the color lighting lumcount so we can have colored lights.
|
||||||
|
|
||||||
if(Area.tag!=new_tag) //skip if already in this area
|
if(Area.tag!=new_tag) //skip if already in this area
|
||||||
|
|
||||||
var/area/A = locate(new_tag) // find an appropriate area
|
var/area/A = locate(new_tag) // find an appropriate area
|
||||||
|
var/color_light = min(max(round(color_lighting_lumcount,1),0),lighting_controller.lighting_states)
|
||||||
|
|
||||||
if(!A)
|
if (!A)
|
||||||
|
A = build_lighting_area(new_tag, level, color_light)
|
||||||
A = new Area.type() // create area if it wasn't found
|
else if (l_color != A.l_color)
|
||||||
// replicate vars
|
A.l_color = l_color
|
||||||
for(var/V in Area.vars)
|
//color_light = min(max(round(color_lighting_lumcount, 1), 0), lighting_controller.lighting_states)
|
||||||
switch(V)
|
A.SetLightLevel(level, color_light)
|
||||||
if("contents","lighting_overlay","overlays") continue
|
|
||||||
else
|
|
||||||
if(issaved(Area.vars[V])) A.vars[V] = Area.vars[V]
|
|
||||||
|
|
||||||
A.tag = new_tag
|
|
||||||
A.lighting_subarea = 1
|
|
||||||
A.SetLightLevel(light)
|
|
||||||
|
|
||||||
Area.related += A
|
|
||||||
|
|
||||||
A.contents += src // move the turf into the area
|
A.contents += src // move the turf into the area
|
||||||
|
|
||||||
|
// Dedicated lighting sublevel for space turfs
|
||||||
|
// helps us depower things in space, remove space fire alarms,
|
||||||
|
// and evens out space lighting
|
||||||
|
turf/space/lighting_tag(var/level)
|
||||||
|
var/area/A = loc
|
||||||
|
return A.tagbase + "sd_L_space"
|
||||||
|
turf/space/build_lighting_area(var/tag,var/level)
|
||||||
|
var/area/A = ..(tag,4)
|
||||||
|
A.lighting_space = 1
|
||||||
|
A.SetLightLevel(4)
|
||||||
|
A.icon_state = null
|
||||||
|
return A
|
||||||
|
|
||||||
|
|
||||||
area
|
area
|
||||||
var/lighting_use_dynamic = 1 //Turn this flag off to prevent sd_DynamicAreaLighting from affecting this area
|
var/lighting_use_dynamic = 1 //Turn this flag off to prevent sd_DynamicAreaLighting from affecting this area
|
||||||
var/image/lighting_overlay //tracks the darkness image of the area for easy removal
|
var/image/lighting_overlay //tracks the darkness image of the area for easy removal
|
||||||
var/lighting_subarea = 0 //tracks whether we're a lighting sub-area
|
var/lighting_subarea = 0 //tracks whether we're a lighting sub-area
|
||||||
|
var/lighting_space = 0 // true for space-only lighting subareas
|
||||||
|
var/tagbase
|
||||||
|
var/image/color_overlay //Tracks the color image.
|
||||||
|
|
||||||
proc/SetLightLevel(light)
|
proc/SetLightLevel(light, color_light = 0)
|
||||||
if(!src) return
|
if(!src) return
|
||||||
if(light <= 0)
|
if(light <= 0)
|
||||||
light = 0
|
light = 0
|
||||||
@@ -291,17 +369,113 @@ area
|
|||||||
else
|
else
|
||||||
lighting_overlay = image(LIGHTING_ICON,,num2text(light),LIGHTING_LAYER)
|
lighting_overlay = image(LIGHTING_ICON,,num2text(light),LIGHTING_LAYER)
|
||||||
|
|
||||||
overlays += lighting_overlay
|
if (color_overlay)
|
||||||
|
overlays.Remove(color_overlay)
|
||||||
|
color_overlay.icon_state = "white"
|
||||||
|
else
|
||||||
|
if (l_color)
|
||||||
|
color_overlay = image('icons/effects/effects.dmi', ,"white", 10.1)
|
||||||
|
|
||||||
|
if (istype(color_overlay))
|
||||||
|
color_overlay.color = l_color
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (light < 6)
|
||||||
|
switch (level)
|
||||||
|
if (6)
|
||||||
|
color_overlay.alpha = 140
|
||||||
|
if (5)
|
||||||
|
color_overlay.alpha = 120
|
||||||
|
if (4)
|
||||||
|
color_overlay.alpha = 100
|
||||||
|
if (3)
|
||||||
|
color_overlay.alpha = 80
|
||||||
|
if (2)
|
||||||
|
color_overlay.alpha = 60
|
||||||
|
if (1)
|
||||||
|
color_overlay.alpha = 40
|
||||||
|
if (-INFINITY to 0)
|
||||||
|
//world << "Zero or below, [color_light]."
|
||||||
|
color_overlay.alpha = 0
|
||||||
|
else
|
||||||
|
//world << "Setting the alpha to max... color_light [color_light]."
|
||||||
|
color_overlay.alpha = 140
|
||||||
|
|
||||||
|
color_overlay.blend_mode = BLEND_MULTIPLY
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (1)
|
||||||
|
switch (color_light)
|
||||||
|
if (6)
|
||||||
|
color_overlay.alpha = 140
|
||||||
|
if (5)
|
||||||
|
color_overlay.alpha = 120
|
||||||
|
if (4)
|
||||||
|
color_overlay.alpha = 100
|
||||||
|
if (3)
|
||||||
|
color_overlay.alpha = 80
|
||||||
|
if (2)
|
||||||
|
color_overlay.alpha = 60
|
||||||
|
if (1)
|
||||||
|
color_overlay.alpha = 20
|
||||||
|
if (-INFINITY to 0)
|
||||||
|
//world << "Zero or below, [color_light]."
|
||||||
|
color_overlay.alpha = 0
|
||||||
|
else
|
||||||
|
//world << "Setting the alpha to max... color_light [color_light]."
|
||||||
|
color_overlay.alpha = 180
|
||||||
|
color_overlay.blend_mode = BLEND_MULTIPLY
|
||||||
|
if (color_overlay.color)
|
||||||
|
overlays.Add(color_overlay)
|
||||||
|
|
||||||
|
if (isnull(color_overlay))
|
||||||
|
overlays.Add(lighting_overlay)
|
||||||
|
else if (light < 6)
|
||||||
|
overlays.Add(lighting_overlay)
|
||||||
|
|
||||||
|
proc/SetDynamicLighting()
|
||||||
|
|
||||||
|
src.lighting_use_dynamic = 1
|
||||||
|
for(var/turf/T in src.contents)
|
||||||
|
T.update_lumcount(0)
|
||||||
|
|
||||||
proc/InitializeLighting() //TODO: could probably improve this bit ~Carn
|
proc/InitializeLighting() //TODO: could probably improve this bit ~Carn
|
||||||
if(!tag) tag = "[type]"
|
tagbase = "[type]"
|
||||||
|
if(!tag) tag = tagbase
|
||||||
if(!lighting_use_dynamic)
|
if(!lighting_use_dynamic)
|
||||||
if(!lighting_subarea) // see if this is a lighting subarea already
|
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.
|
//show the dark overlay so areas, not yet in a lighting subarea, won't be bright as day and look silly.
|
||||||
SetLightLevel(4)
|
SetLightLevel(4)
|
||||||
|
|
||||||
|
//#undef LIGHTING_LAYER
|
||||||
|
#undef LIGHTING_CIRCULAR
|
||||||
|
//#undef LIGHTING_ICON
|
||||||
|
|
||||||
#undef LIGHTING_MAX_LUMINOSITY
|
#define LIGHTING_MAX_LUMINOSITY_STATIC 8 //Maximum luminosity to reduce lag.
|
||||||
#undef LIGHTING_MAX_LUMINOSITY_MOB
|
#define LIGHTING_MAX_LUMINOSITY_MOBILE 5 //Moving objects have a lower max luminosity since these update more often. (lag reduction)
|
||||||
#undef LIGHTING_LAYER
|
#define LIGHTING_MAX_LUMINOSITY_TURF 1 //turfs have a severely shortened range to protect from inevitable floor-lighttile spam.
|
||||||
//#undef LIGHTING_ICON
|
|
||||||
|
//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()
|
||||||
|
for(var/atom/A in oview(LIGHTING_MAX_LUMINOSITY_STATIC-1,src))
|
||||||
|
if(A.light)
|
||||||
|
A.light.changed = 1 //force it to update at next process()
|
||||||
|
|
||||||
|
//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)
|
||||||
|
|
||||||
|
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_TURF
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 195 KiB |
Reference in New Issue
Block a user