1- IncludeScript (" light_bridge_lights/helper.nut" )
2-
3- // sv_init.nut runs before entities have spawned + on every game load. wait until entities are ready before running
4- function scriptStart () {
5- local initTimer = CreateEntityByName (" logic_timer" , { // check every tick if entities have actually spawned in yet
6- targetname = " lightbridgelights_canstarttimer"
7- RefireTime = 0.01
8- })
1+ if (! (" Entities" in this )) return
92
10- initTimer. ConnectOutput (" OnTimer" , " scriptInit" )
11- EntFire (" lightbridgelights_canstarttimer" , " Enable" )
12- }
13- function scriptInit () { // if player exists, other entities exist
14- local player = GetPlayer ()
15- if (player != null ) {
16- EntFire (" lightbridgelights_canstarttimer" , " Kill" ) // prevent further inits
3+ IncludeScript (" light_bridge_lights/helper.nut" )
174
18- Setup ()
19- if (GetDeveloperLevel () > 0 ) Dev. msgDeveloper (" Script initialised." )
5+ function LBL_scriptInit () {
6+ if (GetPlayer () != null ) {
7+ LBL_Setup ()
8+ if (GetDeveloperLevel () > 0 ) LBL_Dev. msgDeveloper (" Script initialised." )
9+ } else {
10+ printl (" [LIGHT BRIDGE LIGHTS - ERROR] Player entity not found!" )
2011 }
2112}
2213
23- ::LIGHT_COLOUR <- Vector(63 , 196 , 252 ) // RGB colour values - light blue
24- const LIGHT_BRIGHTNESS = 40
25- const LIGHT_D50 = 50
26- const LIGHT_D0 = 300
27- const LIGHT_SHADOWSIZE = - 1 // DONT CHANGE THIS FROM -1, it just instantly overwhelms the shadow atlas (-1 = no shadows)
14+ LBL_LIGHT_COLOUR <- Vector(63 , 196 , 252 ) // RGB colour values - light blue
15+ const LBL_LIGHT_BRIGHTNESS = 40
16+ const LBL_LIGHT_D50 = 50
17+ const LBL_LIGHT_D0 = 300
18+ const LBL_LIGHT_SHADOWSIZE = - 1 // DONT CHANGE THIS FROM -1, it just instantly overwhelms the shadow atlas (-1 = no shadows)
19+
20+ const LBL_LIGHT_SPACING = 20 // distance between lights in units, less spacing means more lights but a higher performance cost
21+ const LBL_LIGHT_MAXCOUNT = 128 // maximum number of lights per bridge to prevent performance issues
2822
29- const LIGHT_SPACING = 20 // distance between lights in units, less spacing means more lights but a higher performance cost
23+ const LBL_LIGHT_SPECIFIC_HEALTH = 27852 // used to identify lights created by this script
3024
31- bridgesCached <- [] // stores bridge handles and their entindexes
32- bridgeLightCountPrevious <- {}
33- bridgesCacheMarkedForReset <- false
34- const CACHE_REFRESH_TIME = 0.01
25+ LBL_bridgesCached <- [] // stores bridge handles and their entindexes
26+ LBL_bridgeLightCountPrevious <- {}
27+ LBL_bridgesCacheMarkedForReset <- false
28+ const LBL_CACHE_REFRESH_TIME = 0.01
3529
3630// traces used for calculating bridge length
37- const TRACE_DISTANCE = 8192
38- TRACE_MASK <- MASK_SOLID | MASK_WATER | MASK_BLOCKLOS
39- TRACE_COLLISION_GROUP <- COLLISION_GROUP_NONE
40- TRACE_BOUNDS_MIN <- Vector(- 12 , - 12 , - 12 )
41- TRACE_BOUNDS_MAX <- Vector(12 , 12 , 12 )
42-
43- function Setup () {
44- Dev. msgDeveloper (" Creating cache refresh timer..." )
31+ const LBL_TRACE_DISTANCE = 8192
32+ LBL_TRACE_MASK <- MASK_SOLID | MASK_WATER | MASK_BLOCKLOS
33+ LBL_TRACE_COLLISION_GROUP <- COLLISION_GROUP_NONE
34+ LBL_TRACE_BOUNDS_MIN <- Vector(- 12 , - 12 , - 12 )
35+ LBL_TRACE_BOUNDS_MAX <- Vector(12 , 12 , 12 )
36+
37+ function LBL_Setup () {
38+ if (Entities. FindByName (null , " lightbridgelights_setupdone" ) != null ) {
39+ LBL_Dev. msgDeveloper (" Setup has already been completed, skipping..." )
40+ return
41+ }
42+
43+ LBL_Dev. msgDeveloper (" Creating cache refresh timer..." )
4544 local loopTimer = CreateEntityByName (" logic_timer" , { // cache refresh timer
46- RefireTime = CACHE_REFRESH_TIME
45+ RefireTime = LBL_CACHE_REFRESH_TIME
46+ })
47+ loopTimer. ConnectOutput (" OnTimer" , " LBL_bridgeCacheRefresh" )
48+ LBL_bridgeCacheRefresh () // initial cache
49+
50+ local loadAuto = CreateEntityByName (" logic_auto" , {}) // handle loading of saves
51+ loadAuto. ConnectOutput (" OnLoadGame" , " LBL_OnLoadGame" )
52+
53+ local hasBeenSetupEntity = CreateEntityByName (" info_target" , { // dummy entity to check against to prevent multiple setups
54+ targetname = " lightbridgelights_setupdone"
4755 })
48- loopTimer. ConnectOutput (" OnTimer" , " bridgeCacheRefresh" )
49- bridgeCacheRefresh () // initial cache
5056}
5157
52- function bridgeCacheRefresh () {
53- if (bridgesCacheMarkedForReset) {
54- foreach (idx, data in bridgesCached) {
55- local bridgeIndex = data. index
56- lightRemoveAtBridge (bridgeIndex) // prevent duplicate lights
58+ function LBL_OnLoadGame () {
59+ LBL_Dev. msgDeveloper (" Load game detected, resetting lights..." )
5760
58- bridgesCached. remove (idx) // dont attempt to remove lights at this bridge again
59- }
60- bridgeCacheReset ()
61- bridgesCacheMarkedForReset = false
61+ // entindexs get messed up on load, meaning all lights need to be reset
62+ LBL_bridgesCacheMarkedForReset = true
63+ LBL_lightRemoveAll ()
64+ }
65+
66+ function LBL_bridgeCacheRefresh () {
67+ if (LBL_bridgesCacheMarkedForReset) {
68+ LBL_bridgeCacheReset ()
69+ LBL_bridgesCacheMarkedForReset = false
6270 }
6371
64- foreach (data in bridgesCached ) {
72+ foreach (data in LBL_bridgesCached ) {
6573 local bridge = data. bridge
6674 local bridgeIndex = data. index
6775
6876 // reset the cache if any cached bridges are invalid
6977 // one small problem with this is it causes all lights to respawn (hence a small flicker), but it's better than crashing
7078
7179 if (! bridge. IsValid ()) {
72- lightRemoveAtBridge (bridgeIndex)
73- bridgesCacheMarkedForReset = true // wait until next tick to prevent crashes
80+ LBL_lightRemoveAtBridge (bridgeIndex)
81+ LBL_bridgesCacheMarkedForReset = true // wait until next tick to prevent crashes
7482 break
7583 }
7684
77- local lightCountNew = bridgeGetLightCount (bridge)
85+ local lightCountNew = LBL_bridgeGetLightCount (bridge)
7886
7987 // get old light count, or use new light count if not found
80- local lightCountOld = (bridgeIndex in bridgeLightCountPrevious ) ? bridgeLightCountPrevious [bridgeIndex] : lightCountNew
88+ local lightCountOld = (bridgeIndex in LBL_bridgeLightCountPrevious ) ? LBL_bridgeLightCountPrevious [bridgeIndex] : lightCountNew
8189
8290 // check if light count has changed
8391 if (lightCountNew != lightCountOld) {
84- if (lightCountNew < lightCountOld) lightRemoveAtBridge (bridgeIndex, lightCountNew) // remove lights if bridge has shrunk
85- if (lightCountNew > lightCountOld) lightSpawnAtBridge (bridge, lightCountOld) // spawn additional lights
86- bridgeLightCountPrevious [bridgeIndex] <- lightCountNew
92+ if (lightCountNew < lightCountOld) LBL_lightRemoveAtBridge (bridgeIndex, lightCountNew) // remove lights if bridge has shrunk
93+ if (lightCountNew > lightCountOld) LBL_lightSpawnAtBridge (bridge, lightCountOld) // spawn additional lights
94+ LBL_bridgeLightCountPrevious [bridgeIndex] <- lightCountNew
8795 }
8896 }
8997
9098 for (local bridge = null ; bridge = Entities. FindByClassname (bridge, " projected_wall_entity" );) {
91- if (bridgeIsCached (bridge) || ! bridge. IsValid ()) continue // skip cached bridges or invalid bridges
99+ if (LBL_bridgeIsCached (bridge) || ! bridge. IsValid ()) continue // skip cached bridges or invalid bridges
92100
93101 // update cache with new bridge
94102
95103 local bridgeIndex = bridge. entindex ()
96104
97- bridgesCached . append ({
105+ LBL_bridgesCached . append ({
98106 bridge = bridge,
99107 index = bridgeIndex
100108 })
101109
102- local bridgeLightCount = bridgeGetLightCount (bridge)
103- bridgeLightCountPrevious [bridgeIndex] <- bridgeLightCount // store initial lightcount in a table based on entindex() for comparison later
110+ local bridgeLightCount = LBL_bridgeGetLightCount (bridge)
111+ LBL_bridgeLightCountPrevious [bridgeIndex] <- bridgeLightCount // store initial lightcount in a table based on entindex() for comparison later
104112
105- lightSpawnAtBridge (bridge)
113+ LBL_lightSpawnAtBridge (bridge)
106114 }
107115}
108116
109- function bridgeIsCached (bridge) {
110- foreach (data in bridgesCached ) {
117+ function LBL_bridgeIsCached (bridge) {
118+ foreach (data in LBL_bridgesCached ) {
111119 if (data. bridge == bridge) return true
112120 }
113121 return false
114122}
115123
116- function bridgeCacheReset () {
117- Dev. msgDeveloper (" Resetting bridge cache..." )
118- bridgesCached <- []
119- bridgeLightCountPrevious <- {}
124+ function LBL_bridgeCacheReset () {
125+ LBL_Dev. msgDeveloper (" Resetting bridge cache..." )
126+
127+ foreach (idx, data in LBL_bridgesCached) {
128+ local bridgeIndex = data. index
129+ LBL_lightRemoveAtBridge (bridgeIndex) // prevent duplicate lights
130+
131+ LBL_bridgesCached. remove (idx) // dont attempt to remove lights at this bridge again
132+ }
133+
134+ LBL_bridgesCached <- []
135+ LBL_bridgeLightCountPrevious <- {}
120136}
121137
122- function bridgeCalculateLength (bridge) {
138+ function LBL_bridgeCalculateLength (bridge) {
123139 local pos = bridge. GetOrigin ()
124140 local forward = bridge. GetForwardVector ()
125- local ray = TraceHull (pos, pos + (forward * TRACE_DISTANCE ), TRACE_BOUNDS_MIN, TRACE_BOUNDS_MAX, TRACE_MASK , bridge, TRACE_COLLISION_GROUP )
141+ local ray = TraceHull (pos, pos + (forward * LBL_TRACE_DISTANCE ), LBL_TRACE_BOUNDS_MIN, LBL_TRACE_BOUNDS_MAX, LBL_TRACE_MASK , bridge, LBL_TRACE_COLLISION_GROUP )
126142
127- return Dev . distance (pos, ray. GetEndPos ())
143+ return LBL_Dev . distance (pos, ray. GetEndPos ())
128144}
129145
130- function bridgeGetLightCount (bridge) {
131- local bridgeLength = bridgeCalculateLength (bridge)
146+ function LBL_bridgeGetLightCount (bridge) {
147+ local bridgeLength = LBL_bridgeCalculateLength (bridge)
132148
133- return floor (bridgeLength / LIGHT_SPACING ) + 1
149+ return floor (bridgeLength / LBL_LIGHT_SPACING ) + 1
134150}
135151
136- function lightSpawnAtBridge (bridge, currentLightCount = 0 ) {
137- local bridgeLength = bridgeCalculateLength (bridge)
138- local lightCount = bridgeGetLightCount (bridge)
152+ function LBL_lightSpawnAtBridge (bridge, currentLightCount = 0 ) {
153+ local bridgeLength = LBL_bridgeCalculateLength (bridge)
154+
155+ local lightCount = LBL_bridgeGetLightCount (bridge)
156+ if (lightCount > LBL_LIGHT_MAXCOUNT) lightCount = LBL_LIGHT_MAXCOUNT // cap light count to prevent performance issues
157+
139158 local bridgeIndex = bridge. entindex ()
140159
141- Dev . msgDeveloper (" Spawning " + (lightCount - currentLightCount) + " lights." )
160+ LBL_Dev . msgDeveloper (" Spawning " + (lightCount - currentLightCount) + " lights." )
142161
143162 for (local i = currentLightCount; i < lightCount; i++ ) { // spawn lights from currentLightCount onwards
144- local distance = (i * LIGHT_SPACING < bridgeLength) ? i * LIGHT_SPACING : bridgeLength // prevent overshoot on last light
145- local light = lightCreate (bridge. GetOrigin () + (bridge. GetForwardVector () * distance))
163+ local distance = (i * LBL_LIGHT_SPACING < bridgeLength) ? i * LBL_LIGHT_SPACING : bridgeLength // prevent overshoot on last light
164+ local light = LBL_lightCreate (bridge. GetOrigin () + (bridge. GetForwardVector () * distance))
146165
147166 light. SetParent (bridge)
148167 light. __KeyValueFromString (" targetname" , bridgeIndex + " _light" + i)
149168 }
150169}
151170
152- function lightCreate (pos) { // returns light handle
171+ function LBL_lightCreate (pos) { // returns light handle
153172 local light = null
154173
155174 light = CreateEntityByName (" light_rt" , {
156175 _lightmode = 3 ,
157176 spawnflags = 2
158177 })
159- light. SetLightColor (LIGHT_COLOUR, LIGHT_BRIGHTNESS )
160- light. SetLightFalloffD50D0 (LIGHT_D50, LIGHT_D0 )
161- light. SetShadowSize (LIGHT_SHADOWSIZE )
178+ light. SetLightColor (LBL_LIGHT_COLOUR, LBL_LIGHT_BRIGHTNESS )
179+ light. SetLightFalloffD50D0 (LBL_LIGHT_D50, LBL_LIGHT_D0 )
180+ light. SetShadowSize (LBL_LIGHT_SHADOWSIZE )
162181
163182 light. Spawn ()
164183 light. SetOrigin (pos)
165184
185+ light. __KeyValueFromInt (" max_health" , LBL_LIGHT_SPECIFIC_HEALTH) // needed to detect light entities later
186+
166187 return light
167188}
168189
169- function lightRemoveAtBridge (bridgeIndex, numLightsToKeep = 0 ) {
170- Dev . msgDeveloper (" Removing lights from bridgeIndex " + bridgeIndex + " starting at light index " + numLightsToKeep + " ." )
190+ function LBL_lightRemoveAtBridge (bridgeIndex, numLightsToKeep = 0 ) {
191+ LBL_Dev . msgDeveloper (" Removing lights from bridgeIndex " + bridgeIndex + " starting at light index " + numLightsToKeep + " ." )
171192
172193 // how many lights could ever exist on this bridge given the current settings
173- local numLightsPotential = (TRACE_DISTANCE / LIGHT_SPACING )
194+ local numLightsPotential = (LBL_TRACE_DISTANCE / LBL_LIGHT_SPACING )
174195
175196 for (local i = numLightsToKeep; i < numLightsToKeep + numLightsPotential; i++ ) { // remove all lights from index numLightsToKeep onwards
176197 local light = Entities. FindByName (null , bridgeIndex + " _light" + i)
177- if (light != null ) Dev . EntFireByHandleCompressed (light, " Kill" )
198+ if (light != null ) LBL_Dev . EntFireByHandleCompressed (light, " Kill" )
178199 }
179200}
180201
181- scriptStart ()
202+ function LBL_lightRemoveAll () {
203+ LBL_Dev. msgDeveloper (" Removing all bridge lights..." )
204+
205+ for (local light = null ; light = Entities. FindByClassname (light, " light_rt" );) {
206+ if (light. GetMaxHealth () == LBL_LIGHT_SPECIFIC_HEALTH) { // only remove lights created by this script
207+ LBL_Dev. EntFireByHandleCompressed (light, " Kill" )
208+ }
209+ }
210+
211+ LBL_bridgeCacheReset ()
212+ }
213+
214+ LBL_auto <- CreateEntityByName(" logic_auto" , {spawnflags = 1 })
215+ LBL_auto. ConnectOutput (" OnNewGame" , " LBL_scriptInit" )
0 commit comments