mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
385 lines
9.6 KiB
Plaintext
385 lines
9.6 KiB
Plaintext
//UltraLight system, by Sukasa
|
|
|
|
|
|
#define UL_I_FALLOFF_SQUARE 0
|
|
#define UL_I_FALLOFF_ROUND 1
|
|
|
|
#define UL_I_LIT 0
|
|
#define UL_I_EXTINGUISHED 1
|
|
#define UL_I_ONZERO 2
|
|
#define UL_I_CHANGING 3
|
|
|
|
#define ul_LightingEnabled 1
|
|
//#define ul_LightingResolution 2
|
|
//Uncomment if you want maybe slightly smoother lighting
|
|
#define ul_Steps 7
|
|
#define ul_FalloffStyle UL_I_FALLOFF_ROUND // Sets the lighting falloff to be either squared or circular.
|
|
#define ul_Layer 10
|
|
#define ul_TopLuminosity 12 //Maximum brightness an object can have.
|
|
|
|
//#define ul_LightLevelChangedUpdates
|
|
//Uncomment if you have code that you want triggered when the light level on an atom changes.
|
|
|
|
|
|
#define ul_Clamp(Value) min(max(Value, 0), ul_Steps)
|
|
#define ul_IsLuminous(A) (A.ul_Red || A.ul_Green || A.ul_Blue)
|
|
#define ul_Luminosity(A) max(A.ul_Red, A.ul_Green, A.ul_Blue)
|
|
|
|
|
|
#ifdef ul_LightingResolution
|
|
var/ul_LightingResolutionSqrt = sqrt(ul_LightingResolution)
|
|
#endif
|
|
var/ul_SuppressLightLevelChanges = 0
|
|
|
|
|
|
var/list/ul_FastRoot = list(0, 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)
|
|
|
|
var/list/ul_IconCache = list()
|
|
|
|
|
|
proc/ul_UnblankLocal(var/list/ReApply = view(ul_TopLuminosity, src))
|
|
for(var/atom/Light in ReApply)
|
|
if(ul_IsLuminous(Light))
|
|
Light.ul_Illuminate()
|
|
return
|
|
|
|
atom/var/ul_Red = 0
|
|
atom/var/ul_Green = 0
|
|
atom/var/ul_Blue = 0
|
|
atom/var/turf/ul_LastIlluminated
|
|
|
|
atom/var/ul_Extinguished = UL_I_ONZERO
|
|
|
|
atom/proc/ul_SetLuminosity(var/Red = 0, var/Green = Red, var/Blue = Red)
|
|
|
|
if(ul_Extinguished == UL_I_CHANGING) //Changing state, just supress any changes, to prevent glitches.
|
|
return
|
|
|
|
if(ul_Red == min(Red, ul_TopLuminosity) && ul_Green == min(Green, ul_TopLuminosity) && ul_Blue == min(Blue, ul_TopLuminosity))
|
|
return //No point doing all that work if it won't have any effect anyways...
|
|
|
|
if (ul_Extinguished == UL_I_EXTINGUISHED)
|
|
ul_Red = min(Red,ul_TopLuminosity)
|
|
ul_Green = min(Green,ul_TopLuminosity)
|
|
ul_Blue = min(Blue,ul_TopLuminosity)
|
|
|
|
return
|
|
|
|
if (ul_IsLuminous(src))
|
|
ul_Extinguish()
|
|
|
|
ul_Red = min(Red,ul_TopLuminosity)
|
|
ul_Green = min(Green,ul_TopLuminosity)
|
|
ul_Blue = min(Blue,ul_TopLuminosity)
|
|
|
|
ul_Extinguished = UL_I_ONZERO
|
|
|
|
if (ul_IsLuminous(src))
|
|
ul_Illuminate()
|
|
|
|
return
|
|
|
|
atom/proc/ul_Illuminate()
|
|
if (ul_Extinguished == UL_I_LIT)
|
|
return
|
|
|
|
ul_Extinguished = UL_I_CHANGING
|
|
|
|
luminosity = ul_Luminosity(src)
|
|
|
|
for(var/turf/Affected in view(luminosity, src))
|
|
var/Falloff = ul_FalloffAmount(Affected)
|
|
|
|
var/DeltaRed = ul_Red - Falloff
|
|
var/DeltaGreen = ul_Green - Falloff
|
|
var/DeltaBlue = ul_Blue - Falloff
|
|
|
|
if(DeltaRed > 0 || DeltaGreen > 0 || DeltaBlue > 0)
|
|
|
|
if(DeltaRed > 0)
|
|
if(!Affected.MaxRed)
|
|
Affected.MaxRed = list()
|
|
Affected.MaxRed += DeltaRed
|
|
|
|
if(DeltaGreen > 0)
|
|
if(!Affected.MaxGreen)
|
|
Affected.MaxGreen = list()
|
|
Affected.MaxGreen += DeltaGreen
|
|
|
|
if(DeltaBlue > 0)
|
|
if(!Affected.MaxBlue)
|
|
Affected.MaxBlue = list()
|
|
Affected.MaxBlue += DeltaBlue
|
|
|
|
Affected.ul_UpdateLight()
|
|
|
|
#ifdef ul_LightLevelChangedUpdates
|
|
if (ul_SuppressLightLevelChanges == 0)
|
|
Affected.ul_LightLevelChanged()
|
|
|
|
for(var/atom/AffectedAtom in Affected)
|
|
AffectedAtom.ul_LightLevelChanged()
|
|
#endif
|
|
|
|
ul_LastIlluminated = get_turf(src)
|
|
ul_Extinguished = UL_I_LIT
|
|
|
|
return
|
|
|
|
atom/proc/ul_Extinguish()
|
|
|
|
if (ul_Extinguished != UL_I_LIT)
|
|
return
|
|
|
|
ul_Extinguished = UL_I_CHANGING
|
|
|
|
for(var/turf/Affected in view(ul_Luminosity(src), ul_LastIlluminated))
|
|
|
|
var/Falloff = ul_LastIlluminated.ul_FalloffAmount(Affected)
|
|
|
|
var/DeltaRed = ul_Red - Falloff
|
|
var/DeltaGreen = ul_Green - Falloff
|
|
var/DeltaBlue = ul_Blue - Falloff
|
|
|
|
if(DeltaRed > 0 || DeltaGreen > 0 || DeltaBlue > 0)
|
|
|
|
if(DeltaRed > 0)
|
|
if(Affected.MaxRed)
|
|
var/removed_light_source = Affected.MaxRed.Find(DeltaRed)
|
|
if(removed_light_source)
|
|
Affected.MaxRed.Cut(removed_light_source, removed_light_source+1)
|
|
if(!Affected.MaxRed.len)
|
|
del Affected.MaxRed
|
|
|
|
if(DeltaGreen > 0)
|
|
if(Affected.MaxGreen)
|
|
var/removed_light_source = Affected.MaxGreen.Find(DeltaGreen)
|
|
if(removed_light_source)
|
|
Affected.MaxGreen.Cut(removed_light_source, removed_light_source+1)
|
|
if(!Affected.MaxGreen.len)
|
|
del Affected.MaxGreen
|
|
|
|
if(DeltaBlue > 0)
|
|
if(Affected.MaxBlue)
|
|
var/removed_light_source = Affected.MaxBlue.Find(DeltaBlue)
|
|
if(removed_light_source)
|
|
Affected.MaxBlue.Cut(removed_light_source, removed_light_source+1)
|
|
if(!Affected.MaxBlue.len)
|
|
del Affected.MaxBlue
|
|
|
|
Affected.ul_UpdateLight()
|
|
|
|
#ifdef ul_LightLevelChangedUpdates
|
|
if (ul_SuppressLightLevelChanges == 0)
|
|
Affected.ul_LightLevelChanged()
|
|
|
|
for(var/atom/AffectedAtom in Affected)
|
|
AffectedAtom.ul_LightLevelChanged()
|
|
#endif
|
|
|
|
ul_Extinguished = UL_I_EXTINGUISHED
|
|
luminosity = 0
|
|
ul_LastIlluminated = null
|
|
|
|
return
|
|
|
|
|
|
/*
|
|
Calculates the correct lighting falloff value (used to calculate what brightness to set the turf to) to use,
|
|
when called on a luminous atom and passed an atom in the turf to be lit.
|
|
|
|
Supports multiple configurations, BS12 uses the circular falloff setting. This setting uses an array lookup
|
|
to avoid the cost of the square root function.
|
|
*/
|
|
atom/proc/ul_FalloffAmount(var/atom/ref)
|
|
if (ul_FalloffStyle == UL_I_FALLOFF_ROUND)
|
|
var/delta_x = (ref.x - src.x)
|
|
var/delta_y = (ref.y - src.y)
|
|
|
|
#ifdef ul_LightingResolution
|
|
if (round((delta_x*delta_x + delta_y*delta_y)*ul_LightingResolutionSqrt,1) > ul_FastRoot.len)
|
|
for(var/i = ul_FastRoot.len, i <= round(delta_x*delta_x+delta_y*delta_y*ul_LightingResolutionSqrt,1), i++)
|
|
ul_FastRoot += round(sqrt(i))
|
|
return ul_FastRoot[round((delta_x*delta_x + delta_y*delta_y)*ul_LightingResolutionSqrt, 1) + 1]/ul_LightingResolution
|
|
|
|
#else
|
|
if ((delta_x*delta_x + delta_y*delta_y) > ul_FastRoot.len)
|
|
for(var/i = ul_FastRoot.len, i <= delta_x*delta_x+delta_y*delta_y, i++)
|
|
ul_FastRoot += round(sqrt(i))
|
|
return ul_FastRoot[delta_x*delta_x + delta_y*delta_y + 1]
|
|
|
|
#endif
|
|
|
|
else if (ul_FalloffStyle == UL_I_FALLOFF_SQUARE)
|
|
return get_dist(src, ref)
|
|
|
|
return 0
|
|
|
|
atom/proc/ul_SetOpacity(var/NewOpacity)
|
|
if(opacity != NewOpacity)
|
|
|
|
var/list/Blanked = ul_BlankLocal()
|
|
|
|
opacity = NewOpacity
|
|
|
|
ul_UnblankLocal(Blanked)
|
|
|
|
return
|
|
|
|
atom/proc/ul_BlankLocal()
|
|
var/list/Blanked = list( )
|
|
var/TurfAdjust = isturf(src) ? 1 : 0
|
|
|
|
for(var/atom/Affected in view(ul_TopLuminosity, src))
|
|
if(ul_IsLuminous(Affected) && Affected.ul_Extinguished == UL_I_LIT && (ul_FalloffAmount(Affected) <= ul_Luminosity(Affected) + TurfAdjust))
|
|
Affected.ul_Extinguish()
|
|
Blanked += Affected
|
|
|
|
return Blanked
|
|
|
|
atom/proc/ul_LightLevelChanged()
|
|
//Designed for client projects to use. Called on items when the turf they are in has its light level changed
|
|
return
|
|
|
|
atom/New()
|
|
. = ..()
|
|
if(ul_IsLuminous(src))
|
|
spawn(5)
|
|
ul_Illuminate()
|
|
|
|
atom/Del()
|
|
if(ul_IsLuminous(src))
|
|
ul_Extinguish()
|
|
. = ..()
|
|
|
|
atom/movable/Move()
|
|
if(ul_IsLuminous(src))
|
|
ul_Extinguish()
|
|
. = ..()
|
|
ul_Illuminate()
|
|
else
|
|
return ..()
|
|
|
|
|
|
turf/var/list/MaxRed
|
|
turf/var/list/MaxGreen
|
|
turf/var/list/MaxBlue
|
|
|
|
turf/proc/ul_GetRed()
|
|
if(MaxRed)
|
|
return ul_Clamp(max(MaxRed))
|
|
return 0
|
|
turf/proc/ul_GetGreen()
|
|
if(MaxGreen)
|
|
return ul_Clamp(max(MaxGreen))
|
|
return 0
|
|
turf/proc/ul_GetBlue()
|
|
if(MaxBlue)
|
|
return ul_Clamp(max(MaxBlue))
|
|
return 0
|
|
|
|
turf/proc/ul_UpdateLight()
|
|
var/area/CurrentArea = loc
|
|
|
|
if(!isarea(CurrentArea) || !CurrentArea.ul_Lighting)
|
|
return
|
|
|
|
var/LightingTag = copytext(CurrentArea.tag, 1, findtext(CurrentArea.tag, ":UL")) + ":UL[ul_GetRed()]_[ul_GetGreen()]_[ul_GetBlue()]"
|
|
|
|
if(CurrentArea.tag != LightingTag)
|
|
var/area/NewArea = locate(LightingTag)
|
|
|
|
if(!NewArea)
|
|
NewArea = new CurrentArea.type()
|
|
NewArea.tag = LightingTag
|
|
|
|
for(var/V in CurrentArea.vars - "contents")
|
|
if(issaved(CurrentArea.vars[V]))
|
|
NewArea.vars[V] = CurrentArea.vars[V]
|
|
|
|
NewArea.tag = LightingTag
|
|
|
|
NewArea.ul_Light(ul_GetRed(), ul_GetGreen(), ul_GetBlue())
|
|
|
|
|
|
NewArea.contents += src
|
|
|
|
return
|
|
|
|
turf/proc/ul_Recalculate()
|
|
|
|
ul_SuppressLightLevelChanges++
|
|
|
|
var/list/Lights = ul_BlankLocal()
|
|
|
|
ul_UnblankLocal(Lights)
|
|
|
|
ul_SuppressLightLevelChanges--
|
|
|
|
return
|
|
|
|
area/var/ul_Overlay = null
|
|
area/var/ul_Lighting = 1
|
|
|
|
area/var/LightLevelRed = 0
|
|
area/var/LightLevelGreen = 0
|
|
area/var/LightLevelBlue = 0
|
|
area/var/list/LightLevels
|
|
|
|
area/proc/ul_Light(var/Red = LightLevelRed, var/Green = LightLevelGreen, var/Blue = LightLevelBlue)
|
|
|
|
if(!src || !src.ul_Lighting)
|
|
return
|
|
|
|
overlays -= ul_Overlay
|
|
if(LightLevels)
|
|
if(Red < LightLevels["Red"])
|
|
Red = LightLevels["Red"]
|
|
if(Green < LightLevels["Green"])
|
|
Green = LightLevels["Green"]
|
|
if(Blue < LightLevels["Blue"])
|
|
Blue = LightLevels["Blue"]
|
|
|
|
LightLevelRed = Red
|
|
LightLevelGreen = Green
|
|
LightLevelBlue = Blue
|
|
|
|
luminosity = LightLevelRed || LightLevelGreen || LightLevelBlue
|
|
|
|
var/ul_CachedOverlay = ul_IconCache["[LightLevelRed]-[LightLevelGreen]-[LightLevelBlue]"]
|
|
if(ul_CachedOverlay)
|
|
ul_Overlay = ul_CachedOverlay
|
|
else
|
|
ul_IconCache["[LightLevelRed]-[LightLevelGreen]-[LightLevelBlue]"] = image('icons/effects/ULIcons.dmi', , "[LightLevelRed]-[LightLevelGreen]-[LightLevelBlue]", ul_Layer)
|
|
ul_Overlay = ul_IconCache["[LightLevelRed]-[LightLevelGreen]-[LightLevelBlue]"]
|
|
|
|
overlays += ul_Overlay
|
|
|
|
return
|
|
|
|
area/proc/ul_Prep()
|
|
|
|
if(!tag)
|
|
tag = "[type]"
|
|
if(ul_Lighting)
|
|
if(!findtext(tag,":UL"))
|
|
ul_Light()
|
|
//world.log << tag
|
|
|
|
return
|
|
|
|
#undef UL_I_FALLOFF_SQUARE
|
|
#undef UL_I_FALLOFF_ROUND
|
|
#undef UL_I_LIT
|
|
#undef UL_I_EXTINGUISHED
|
|
#undef UL_I_ONZERO
|
|
#undef ul_LightingEnabled
|
|
#undef ul_LightingResolution
|
|
#undef ul_Steps
|
|
#undef ul_FalloffStyle
|
|
#undef ul_Layer
|
|
#undef ul_TopLuminosity
|
|
#undef ul_Clamp
|
|
#undef ul_LightLevelChangedUpdates |