DayZ 1.24
Loading...
Searching...
No Matches
ScriptedLightBase.c
Go to the documentation of this file.
1/*
2 Please remember that:
3 -Lights work only on client side!
4 -Lights with Brightness or Radius of 0 (or less) are automatically deleted
5 -Lights are very performance heavy. Especially if they cast shadows. Use them carefully!
6
7 Script author: Boris Vacula
8*/
9
11{
13 float m_LifetimeEnd = -1; // -1 makes this light permanent
14 float m_FadeOutTime = -1;
15 float m_FadeInTime = -1;
16 float m_Radius;
19 float m_BrightnessPulse; // flicker effect
24 float m_BrightnessSpeedOfChange = 1;
25 float m_RadiusSpeedOfChange = 1;
26 float m_OptimizeShadowsRadius = 0; // Within this range between the light source and camera the shadows will be automatically disabled to save on performance
27
30
32
33 bool m_IsDebugEnabled = false;
34
35 Object m_Parent; // Attachment parent
36 vector m_LocalPos; // Local position to my attachment parent
37 vector m_LocalOri; // Local orientation to my attachment parent
39
41
42 static ref set<ScriptedLightBase> m_NightTimeOnlyLights = new set<ScriptedLightBase>();
43
46 {
47 m_LifetimeStart = GetGame().GetTime();
48 SetEnabled(true);
49 SetEventMask(EntityEvent.FRAME);
50 SetEventMask(EntityEvent.INIT);
51 }
52
54 {
55 if (m_NightTimeOnlyLights)
56 {
57 int index = m_NightTimeOnlyLights.Find(this);
58 if (index != -1)
59 m_NightTimeOnlyLights.Remove(index);
60 }
61 }
62
63 override void EOnInit(IEntity other, int extra)
64 {
65 if (!IsVisibleDuringDaylight())
66 {
68 if (player && player.m_UndergroundPresence)
69 SetVisibleDuringDaylight(true);
70 m_NightTimeOnlyLights.Insert(this);
71 }
72 }
73
74 override bool IsScriptedLight()
75 {
76 return true;
77 }
78
80 {
82 if (item)
83 {
85 item.GetInventory().GetCurrentInventoryLocation(il);
86 string slotName;
87 if (il.GetType() == InventoryLocationType.GROUND)
88 slotName = "Ground";
89 else if (il.GetSlot() != -1)
91 UpdateLightMode(slotName);
92 }
93 }
94
95 private void UpdateLightMode(string slotName);
96
98 private void DeleteLightWithDelay()
99 {
100 DetachFromParent(); // This is the reason for the delay
101
102 if (GetGame())
103 {
104 if (!m_DeleteTimer)
106
107 m_DeleteTimer.Run(0.03, this, "DeleteLightNow", NULL, true);
108 }
109
110 }
111
112 // Deletes light now. Do not call this directly. Call Destroy() instead. Otherwise you might get errors related to hierarchy.
113 private void DeleteLightNow()
114 {
115 GetGame().ObjectDelete(this);
116 }
117
119 void AttachOnObject(Object parent, vector local_pos = "0 0 0", vector local_ori = "0 0 0")
120 {
121 if (!parent)
122 {
123 if (m_Parent)
124 m_Parent.RemoveChild(this);
125
126 return;
127 }
128 else
129 {
130 if (m_Parent)
131 m_Parent.RemoveChild(this);
132 }
133
134 m_Parent = parent;
137 SetOrientation(local_ori);
139 parent.AddChild(this, -1);
140 parent.Update();
141 }
142
145 {
146 return m_Parent;
147 }
148
151 {
152 if (parent.MemoryPointExists(memory_point_start))
153 {
154 m_LocalPos = parent.GetMemoryPointPos(memory_point_start);
156
157 if (memory_point_target != "")
158 {
159 if (parent.MemoryPointExists(memory_point_target))
160 {
161 vector target_pos = parent.GetSelectionPositionLS(memory_point_target);
163 local_ori = target_pos.VectorToAngles();
164 }
165 else
166 ErrorEx("memory point 'memory_point_target' not found when attaching light");
167 }
168 AttachOnObject(parent, m_LocalPos, local_ori);
169 UpdateMode();
170 }
171 else
172 ErrorEx("memory point 'memory_point_start' not found when attaching light");
173 }
174
177 {
178 if (!m_Parent)
179 m_Parent = Object.Cast(GetParent());
180
181 if (m_Parent)
182 {
183 if (!m_Parent.ToDelete() && !ToDelete())
184 m_Parent.RemoveChild(this);
185 }
186
187 m_Parent = null;
188 m_LocalPos = Vector(0, 0, 0);
189 m_LocalOri = Vector(0, 0, 0);
190 }
191
193 {
195 if (target.MemoryPointExists(memory_point_start))
196 {
198 light.AttachOnMemoryPoint(target, memory_point_start, memory_point_target);
199 }
200 return light;
201 }
202
205 {
207
208 if (!GetGame().IsServer() || !GetGame().IsMultiplayer()) // Client side
209 {
210 light_instance = ScriptedLightBase.Cast(GetGame().CreateObject(name.ToString(), global_pos, true));
211
212 if (!light_instance)
213 {
214 Error("Error! Light entity of name " + name.ToString() + " cannot be spawned! This name is incorrect or not inherited from ScriptedLightBase.");
215 return null;
216 }
217
218 if (fade_in_time_in_s != 0)
220 }
221 else // Server side
222 {
223 if (GetGame().IsDebug())
224 Error("An instance of ScriptedLightBase was attempted to spawn on server side! Lights are CLIENT SIDE ONLY!");
225 }
226
227 return light_instance;
228 }
229
232 {
233 m_Brightness = value;
234 m_BrightnessTarget = value;
235 SetBrightness(m_Brightness * m_BrightnessPulse);
236 CorrectLightPulseDuringDaylight();
237 }
238
241 {
242 if (m_Brightness < 100)
243 {
244 float v = m_Brightness * 0.01;
245
246 if (v > 0)
247 {
248 float brightness_compesation = 1 / v;
249 float compenset_brightness = (m_Brightness * m_BrightnessPulse) * brightness_compesation;
250 SetBrightness(compenset_brightness);
251 SetPulseCoef(v);
252 }
253 }
254 else
255 SetPulseCoef(1);
256 }
257
260 {
261 m_BrightnessTarget = value;
262
263 if (time_in_s == 0)
264 m_BrightnessSpeedOfChange = 9999;
265 else
266 m_BrightnessSpeedOfChange = Math.AbsFloat(m_Brightness - m_BrightnessTarget) / time_in_s;
267 }
268
270 void SetRadiusTo(float value)
271 {
272 m_Radius = value;
273 m_RadiusTarget = value;
274 SetRadius(m_Radius);
275 }
276
278 void FadeRadiusTo(float value, float time_in_s)
279 {
280 m_RadiusTarget = value;
281
282 if (time_in_s == 0)
283 m_RadiusSpeedOfChange = 9999;
284 else
285 m_RadiusSpeedOfChange = Math.AbsFloat(m_Radius - m_RadiusTarget) / time_in_s;
286 }
287
289 void Destroy()
290 {
291 ClearEventMask(EntityEvent.FRAME);
292 SetEnabled(false);
293 if (m_Parent)
294 DeleteLightWithDelay();
295 else
296 DeleteLightNow();
297 }
298
301 {
302 if (GetGame())
303 m_LifetimeEnd = GetGame().GetTime() + life_in_s * 1000;
304 }
305
308 {
309 m_FadeOutTime = time_in_s * 1000;
310 }
311
313 void FadeOut(float time_in_s = -1)
314 {
315 float time_in_ms = time_in_s * 1000;
316
317 if (time_in_s == -1)
318 {
319 float kill_time_in_s = m_FadeOutTime * 0.001;
320
321 FadeBrightnessTo(0, kill_time_in_s);
322 FadeRadiusTo(0, kill_time_in_s);
323 SetLifetime(kill_time_in_s);
324 }
325 else
326 {
327 FadeBrightnessTo(0, time_in_s);
328 FadeRadiusTo(0, time_in_s);
329 SetLifetime(time_in_s);
330 }
331 }
332
334 void FadeIn(float time_in_s)
335 {
336 float brightness = m_Brightness;
337 SetBrightnessTo(0);
338 FadeBrightnessTo(brightness, time_in_s);
339 }
340
343 {
344 m_LifetimeEnd += life_in_s * 1000;
345 }
346
349 {
350 // ...
351 }
352
354 override void EOnFrame(IEntity other, float timeSlice)
355 {
356 // Control lifetime of the light
357 int current_time = GetGame().GetTime();
358
359 if (CheckLifetime(current_time))
360 SetRadius(m_Radius);
361 else
362 return;
363
364 HandleFlickering(current_time - m_LifetimeStart, timeSlice);
365 HandleDancingShadows(current_time - m_LifetimeStart, timeSlice);
366 CheckFadeOut(current_time);
367 HandleBrightnessFadeing(timeSlice);
368 HandleRadiusFadeing(timeSlice);
369
370 CheckIfParentIsInCargo();
371 TryShadowOptimization();
372 OnFrameLightSource(other, timeSlice);
373
374 HandleBlinking(current_time);
375 }
376
379 {
380 m_DancingShadowsAmplitude = Math.AbsFloat(max_deviation_in_meters);
381 }
382
388
391 {
392 return m_DancingShadowsAmplitude;
393 }
394
397 {
398 return m_DancingShadowsSpeed;
399 }
400
403 {
404 m_IsDebugEnabled = state;
405 }
406
407 // Handles subtle movement of the light point to create the effect of dancing shadows
409 {
410 if (m_DancingShadowsAmplitude > 0)
411 {
412 for (int i = 0; i < 3; i++)
413 {
414 m_DancingShadowsLocalPos[i] = m_DancingShadowsLocalPos[i] + (Math.RandomFloat(-m_DancingShadowsSpeed, m_DancingShadowsSpeed) * timeSlice) ;
415
416 if (m_DancingShadowsLocalPos[i] > m_DancingShadowsAmplitude)
417 m_DancingShadowsLocalPos[i] = m_DancingShadowsAmplitude;
418
419 if (m_DancingShadowsLocalPos[i] < -m_DancingShadowsAmplitude)
420 m_DancingShadowsLocalPos[i] = -m_DancingShadowsAmplitude;
421
422 }
423
424 if (m_Parent && !m_Parent.ToDelete())
425 {
426 // In order to move with the light, it must be detached from its parent first
427
428 m_Parent.RemoveChild(this);
429 SetPosition(m_LocalPos + m_DancingShadowsLocalPos);
430
431 m_Parent.AddChild(this, -1);
432 m_Parent.Update();
433 }
434
435 if (m_IsDebugEnabled)
436 {
437 Particle p = ParticleManager.GetInstance().PlayInWorld(ParticleList.DEBUG_DOT, GetPosition());
438 p.SetParticleParam(EmitorParam.SIZE, 0.01);
439 }
440 }
441 else
442 m_DancingShadowsLocalPos = Vector(0, 0, 0);
443 }
444
445 // Updates flickering light
446 void HandleFlickering(float time, float timeSlice)
447 {
448 if (m_BrightnessPulseAmplitudeMax > 0)
449 {
450 m_BrightnessPulse += (Math.RandomFloat(-m_BrightnessPulseSpeed, m_BrightnessPulseSpeed)) * timeSlice;
451
452 if (m_BrightnessPulse < m_BrightnessPulseAmplitudeMin + 1)
453 m_BrightnessPulse = m_BrightnessPulseAmplitudeMin + 1;
454
455 if (m_BrightnessPulse > m_BrightnessPulseAmplitudeMax + 1)
456 m_BrightnessPulse = m_BrightnessPulseAmplitudeMax + 1;
457
458 }
459 else
460 m_BrightnessPulse = 1;
461 }
462
464 void SetFlickerSpeed(float speed)
465 {
466 m_BrightnessPulseSpeed = speed;
467 }
468
470 void SetFlickerAmplitude(float coef)
471 {
472 m_BrightnessPulseAmplitudeMax = Math.AbsFloat(coef);
473 m_BrightnessPulseAmplitudeMin = -Math.AbsFloat(coef);
474 }
475
476 void SetFlickerAmplitudeMax(float coef)
477 {
478 m_BrightnessPulseAmplitudeMax = coef;
479 }
480
481 void SetFlickerAmplitudeMin(float coef)
482 {
483 m_BrightnessPulseAmplitudeMin = coef;
484 }
485
488 {
489 return m_BrightnessPulseSpeed;
490 }
491
494 {
495 return m_BrightnessPulseAmplitudeMax;
496 }
497
500 {
501 return m_BrightnessPulseAmplitudeMin;
502 }
503
506 {
507 if (m_OptimizeShadowsRadius > 0)
508 {
509 float distance_to_camera = vector.Distance(GetPosition(), GetGame().GetCurrentCameraPosition());
510
511 if (distance_to_camera < m_OptimizeShadowsRadius)
512 SetCastShadow(false);
513 else
514 SetCastShadow(true);
515 }
516 }
517
520 {
521 m_OptimizeShadowsRadius = radius_in_m;
522 }
523
526 {
527 return m_OptimizeShadowsRadius;
528 }
529
531 {
532 // TO DO: OPTIMIZE AND REFACTOR! THIS MUST BE HANDLED IN AN EVENT, NOT PER FRAME!
533
534 if (m_Parent)
535 {
537
538 if (parent_EAI) // Check if the Cast was successfull
539 {
540 GameInventory GI = parent_EAI.GetInventory();
541
542 if (GI) // Prevents handling of light on the parent item when it's projected in inventory as the item in inventory character's hands.
543 {
544 bool is_in_cargo = GI.IsInCargo();
545
546 if (!is_in_cargo)
547 {
548 EntityAI parent2 = parent_EAI.GetHierarchyParent();
549
550 if (parent2 && parent2.GetInventory())
551 is_in_cargo = parent2.GetInventory().IsInCargo();
552 }
553
554 if (is_in_cargo)
555 SetEnabled(false);
556 else
557 SetEnabled(true);
558 }
559 }
560 }
561 }
562
563 // Destroys this light if it's past it lifetime
564 private bool CheckLifetime(int current_time)
565 {
566 if (current_time > m_LifetimeEnd && m_LifetimeEnd != -1)
567 {
568 Destroy();
569 return false;
570 }
571
572 return true;
573 }
574
575 // Handles fade out effect at the end of lifetime
576 private void CheckFadeOut(int current_time)
577 {
578 // Control fade out of the light
579 if (m_FadeOutTime != -1 && m_LifetimeEnd != -1 && current_time > m_LifetimeEnd - m_FadeOutTime)
580 {
581 m_FadeOutTime = -1;
582 m_FadeInTime = -1; // Stop fade in process
583 float time_left_in_s = (m_LifetimeEnd - current_time) * 0.001;
584 FadeBrightnessTo(0, time_left_in_s);
585 FadeRadiusTo(0, time_left_in_s);
586 }
587 }
588
589 // handles fading of brightness
591 {
592 if (m_Brightness != m_BrightnessTarget)
593 {
594 float brightness_difference = m_Brightness - m_BrightnessTarget;
595
596 if (brightness_difference > m_BrightnessSpeedOfChange * timeSlice)
597 brightness_difference = m_BrightnessSpeedOfChange * timeSlice;
598
599 if (brightness_difference < -m_BrightnessSpeedOfChange * timeSlice)
600 brightness_difference = -m_BrightnessSpeedOfChange * timeSlice;
601
602 m_Brightness -= brightness_difference;
603
604 if (m_Brightness > 0 || m_BrightnessTarget > 0)
605 {
606 SetBrightness(m_Brightness * m_BrightnessPulse);
607 CorrectLightPulseDuringDaylight();
608 }
609 else
610 {
611 Destroy();
612 return;
613 }
614 }
615 else
616 {
617 SetBrightness(m_Brightness * m_BrightnessPulse);
618 CorrectLightPulseDuringDaylight();
619 }
620 }
621
622 // handles fading of radius
623 private void HandleRadiusFadeing(float timeSlice)
624 {
625 if (m_Radius != m_RadiusTarget)
626 {
627 float radius_difference = m_Radius - m_RadiusTarget;
628
629 if (radius_difference > m_RadiusSpeedOfChange * timeSlice)
630 radius_difference = m_RadiusSpeedOfChange * timeSlice;
631
632 if (radius_difference < -m_RadiusSpeedOfChange * timeSlice)
633 radius_difference = -m_RadiusSpeedOfChange * timeSlice;
634
636
637 if (m_Radius > 0 || m_RadiusTarget > 0)
638 SetRadius(m_Radius);
639 else
640 {
641 Destroy();
642 return;
643 }
644 }
645 else
646 SetRadius(m_Radius);
647 }
648
651 {
652 m_BlinkingSpeed = _speed;
653 }
654
657 {
658 return m_BlinkingSpeed;
659 }
660
661 // handles blinking. Turns light on and off on regular intervals
662 private void HandleBlinking(float time)
663 {
664 if (m_BlinkingSpeed <= 0)
665 return;
666
667 float multiplier;
668
669 multiplier = Math.Sin(time * 0.001 * m_BlinkingSpeed); // Oscillate the multiplier overtime (time normalized to sec)
670 multiplier = (multiplier + 1) / 2; // Normalized the value to 0-1
671
672 multiplier = Math.Round(multiplier); // Rounding to 0 or 1 to make it blink instantly
673 SetBrightness(m_Brightness * multiplier);
674 }
675};
float m_Radius
PlayerSpawnPresetDiscreteItemSetSlotData name
one set for cargo
PlayerSpawnPreset slotName
vector m_LocalPos
Cached local pos.
Definition Effect.c:60
vector m_LocalOri
Local orientation set by SetAttachedLocalOri, only used by EffectParticle.
Definition Effect.c:62
ref Timer m_DeleteTimer
void CreateLight()
InventoryLocationType
types of Inventory Location
PlayerBase GetPlayer()
void ParticleManager(ParticleManagerSettings settings)
Constructor (ctor)
Widget m_Parent
Definition SizeToChild.c:86
void SetEnabled()
prevents insider adding in the wrong position, HOTFIX
class JsonUndergroundAreaTriggerData GetPosition
void HandleBrightnessFadeing(float timeSlice)
Object GetAttachmentParent()
Returns attachment parent.
void HandleBlinking(float time)
void SetLifetime(float life_in_s)
Makes the light destroy itself after the given time in seconds. The light will fade out if it's set t...
void FadeIn(float time_in_s)
Makes the light fade into existence. Works only at the moment the light is created....
void SetFadeOutTime(float time_in_s)
Sets the fade out time in seconds. Fade out begins automatically as the light nears the end of its li...
override void EOnFrame(IEntity other, float timeSlice)
On frame event. If you want to control your light within your own rules then override the event OnFra...
void TryShadowOptimization()
Optimizes shadows by disabling them on this light source while it's within the given radius around th...
void HandleRadiusFadeing(float timeSlice)
void SetBrightnessTo(float value)
Sets the brightness of the light.
void DeleteLightWithDelay()
Correct way of deleting light from memory. It is necesarry to have this delay due to hierarchy.
static ScriptedLightBase CreateLightAtObjMemoryPoint(typename name, notnull Object target, string memory_point_start, string memory_point_target="", vector global_pos="0 0 0", float fade_in_time_in_s=0)
static ScriptedLightBase CreateLight(typename name, vector global_pos="0 0 0", float fade_in_time_in_s=0)
Creates an instance of light on the given position. Optionally, use fade_in_time_in_s parameter to ma...
override bool IsScriptedLight()
void SetDancingShadowsMovementSpeed(float speed_in_meters_per_frame)
Sets the maximum speed of the point light within the dancing shadows effect.
float GetDisableShadowsWithinRadius()
Returns the range you put inside SetDisableShadowsWithinRadius(...)
float GetBlinkingSpeed()
Returns the speed of blinks.
void HandleDancingShadows(float time, float timeSlice)
void SetBlinkingSpeed(float _speed)
Sets blinking speed (no blinking if speed <= 0)
void AddLifetime(float life_in_s)
Prolongs the lifetime of the light in seconds. Use negative number to shorten its lifetime.
void Destroy()
Switches off the light and deletes it from memory.
void SetDancingShadowsAmplitude(float max_deviation_in_meters)
Sets the maximum range of the point light within the dancing shadows effect.
void DetachFromParent()
Detaches this light from its parent entity.
void ScriptedLightBase()
Constructor. Everything here is executed before the constructor of all children.
float GetFlickerAmplitudeCoefMin()
Returns flicker amplitude minimum.
void SetFlickerSpeed(float speed)
Sets speed of light flickering (random brightness coefficient change per second)
void SetFlickerAmplitudeMax(float coef)
override void EOnInit(IEntity other, int extra)
float GetDancingShadowsAmplitude()
Returns max movement range of pointlight within the dancing shadow effect.
void AttachOnMemoryPoint(Object parent, string memory_point_start, string memory_point_target="")
Attaches this light on the parent entity's memory point, with optional direction target memory point.
float GetDancingShadowsMovementSpeed()
Returns max movement speed of pointlight within the dancing shadow effect.
void AttachOnObject(Object parent, vector local_pos="0 0 0", vector local_ori="0 0 0")
Attaches this light on the parent entity, with optional position and orientation offset.
float GetFlickerSpeed()
Returns flicker speed.
void CorrectLightPulseDuringDaylight()
Call this after using SetBrightness(...) to fix light's intensity during daytime.
void SetFlickerAmplitude(float coef)
Sets the change coefficient of flickering light. (0.0 - 1.0 values, result of greater values are peri...
float GetFlickerAmplitudeCoefMax()
Returns flicker amplitude maximum.
void HandleFlickering(float time, float timeSlice)
void SetRadiusTo(float value)
Sets the radius of the light.
void FadeOut(float time_in_s=-1)
Starts the fade out process and destroys the light when its done. Optional parameter allows you to se...
void FadeBrightnessTo(float value, float time_in_s)
Fades the brightness of the light to the given value.
void SetFlickerAmplitudeMin(float coef)
void SetDisableShadowsWithinRadius(float radius_in_m)
When the light source gets within this radius (radius_in_m) around the camera, then it's shadows are ...
void OnFrameLightSource(IEntity other, float timeSlice)
Override this for custom functionality.
void FadeRadiusTo(float value, float time_in_s)
Fades the radius of the light to the given value.
void EnableDebug(bool state)
Enables some debug functionality of this light.
void CheckFadeOut(int current_time)
void UpdateLightMode(string slotName)
bool CheckLifetime(int current_time)
script counterpart to engine's class Inventory
Definition Inventory.c:79
InventoryLocation.
provides access to slot configuration
static proto native owned string GetSlotName(int id)
converts slot_id to string
Definition EnMath.c:7
Legacy way of using particles in the game.
Definition Particle.c:7
static const int DEBUG_DOT
static vector Direction(vector p1, vector p2)
Returns direction vector from point p1 to point p2.
Definition EnConvert.c:220
static proto native float Distance(vector v1, vector v2)
Returns the distance between tips of two 3D vectors.
proto native CGame GetGame()
void Error(string err)
Messagebox with error message.
Definition EnDebug.c:90
enum ShapeType ErrorEx
proto native void SetPosition(vector position)
Set the world position of the Effect.
Definition Effect.c:420
proto native void Destroy()
Cleans up the Effect, including unregistering if needed.
Definition Effect.c:207
EntityEvent
Entity events for event-mask, or throwing event from code.
Definition EnEntity.c:44
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
static proto float Round(float f)
Returns mathematical round of value.
static proto float RandomFloat(float min, float max)
Returns a random float number between and min[inclusive] and max[exclusive].
static proto float Sin(float angle)
Returns sinus of angle in radians.
static proto float AbsFloat(float f)
Returns absolute value.
EmitorParam
Definition EnVisual.c:114
const int CALL_CATEGORY_SYSTEM
Definition tools.c:8
proto native Widget GetParent()
Get parent of the Effect.
Definition Effect.c:389