DayZ Scripts
v1.21.156300 ยท Jun 20, 2023
 
Loading...
Searching...
No Matches
ComponentEnergyManager.c
Go to the documentation of this file.
1//-----------------------------
2// ENERGY MANAGER
3//-----------------------------
4/*
5Author: Boris Vacula
6
7Documentation can be found at DayZ Confluence >> Camping & Squatting >> Electricity >> Energy Manager functionalities
8
9This system controls storage, spending and sharing of energy between instances.
10
11Every EntityAI object which uses this API gains these functions:
12 -It can store some amout of energy
13 -It can use this amount of energy for any kind of functionality
14 -It can share this energy with other devices plugged into it
15 -It will have an ON/OFF switch
16*/
17
19{
20 protected const float DEFAULT_UPDATE_INTERVAL = 15;
21 protected static bool m_DebugPlugs = false; //true; // Use this to toggle visualisation of plug connections
23
24 protected bool m_IsSwichedOn;
25 protected bool m_IsSwichedOnPreviousState; // Necesarry due to synchronization of m_IsSwichedOn
26 protected bool m_IsPassiveDevice;
27 protected bool m_IsWorking;
28 protected bool m_CanWork;
29 protected bool m_CanStopWork;
30 protected bool m_RestorePlugState; // After server restart, this value reports if this device was plugged into something or not at the end of last session.
31 protected bool m_AutoSwitchOff;
33 protected bool m_HasElectricityIcon; // Electricity icon over the item in inventory
35 protected bool m_IsPlugged; // Synchronized variable
37
38 protected int m_MySocketID = -1;
39 protected int m_PlugType;
40 protected int m_EnergySourceStorageIDb1; // Storage persistence ID
41 protected int m_EnergySourceStorageIDb2; // Storage persistence ID
42 protected int m_EnergySourceStorageIDb3; // Storage persistence ID
43 protected int m_EnergySourceStorageIDb4; // Storage persistence ID
45 protected int m_EnergySourceNetworkIDLow = -1; // Network ID
46 protected int m_EnergySourceNetworkIDHigh = -1; // Network ID
47
48 protected float m_EnergyUsage;
49 protected float m_Energy;
50 protected float m_EnergyStorageMax;
52 protected float m_SocketsCount;
53 protected float m_CordLength;
54 protected float m_LastUpdateTime;
55 protected float m_WetnessExposure;
56 protected float m_UpdateInterval; // Interval of OnWork(...) calls and device updates.
57
58 protected string m_CordTextureFile;
59
60 // Concatenated strings for p3d selections
61 protected static const string SOCKET_ = "socket_";
62 protected static const string _PLUGGED = "_plugged";
63 protected static const string _AVAILABLE = "_available";
64 static const string SEL_CORD_PLUGGED = "cord_plugged";
65 static const string SEL_CORD_FOLDED = "cord_folded";
66
68 EntityAI m_EnergySource; // Energy source can be any EntityAI object
71
75
76 const int MAX_SOCKETS_COUNT = 4;
78
79
80
81 // Constructor
83 {
84 // Disable debug arrows on public release, so that they don't use their timers.
85 #ifndef DEVELOPER
86 m_DebugPlugs = false;
87 #endif
88 }
89
91 {
93 {
94 m_DebugPlugArrow.Destroy();
95 m_DebugPlugArrow = NULL;
96 }
97 }
98
99 // Initialization. Energy Manager is ready.
100 override void Event_OnInit()
101 {
102 m_ThisEntityAI.m_EM = this;
103 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnInitEnergy", NULL, 0);
104 }
105
106 // Update debug arrows
108 {
109 if ( GetDebugPlugs() )
110 {
111 if ( GetGame().IsMultiplayer() && GetGame().IsServer() )
112 {
113 if (m_DebugUpdate)
115
116 return;
117 }
118
120 {
121 m_DebugPlugArrow.Destroy();
122 m_DebugPlugArrow = NULL;
123 }
124
125 if ( GetEnergySource() )
126 {
127 vector from = GetEnergySource().GetPosition() + "0 0.1 0";
128 vector to = m_ThisEntityAI.GetPosition() + "0 0.1 0";
129
130 //No need to draw an arrow in this situation as it would not be visible
131 if ( vector.DistanceSq(from, to) == 0 )
132 return;
133
134 if ( m_ThisEntityAI.GetType() == "BarbedWire" ) // Special case for debugging of electric fences. Temporal code until offsets in fences are fixed.
135 {
136 EntityAI BBB = m_ThisEntityAI.GetHierarchyParent();
137
138 if ( BBB && BBB.GetType() == "Fence" )
139 {
140 to = to + "0 -1.3 0";
141 }
142 }
143
144 m_DebugPlugArrow = DrawArrow( from, to );
145 }
146 }
147 }
148
149 Shape DrawArrow(vector from, vector to, float size = 0.5, int color = 0xFFFFFFFF, float flags = 0)
150 {
151 vector dir = to - from;
152 dir.Normalize();
153 vector dir1 = dir * size;
154 size = size * 0.5;
155
156 vector dir2 = dir.Perpend() * size;
157
158 vector pts[5];
159 pts[0] = from;
160 pts[1] = to;
161 pts[2] = to - dir1 - dir2;
162 pts[3] = to - dir1 + dir2;
163 pts[4] = to;
164
165 return Shape.CreateLines(color, flags, pts, 5);
166 }
167
169 {
170 return m_ThisEntityAI;
171 }
172
173 // Prepare everything
174 override void Event_OnAwake()
175 {
176 string cfg_item = "CfgVehicles " + m_ThisEntityAI.GetType();
177 string cfg_energy_manager = cfg_item + " EnergyManager ";
178
179 // Read all config parameters
180 m_EnergyUsage = GetGame().ConfigGetFloat(cfg_energy_manager + "energyUsagePerSecond");
181 bool switch_on = GetGame().ConfigGetFloat(cfg_energy_manager + "switchOnAtSpawn");
182 m_AutoSwitchOff = GetGame().ConfigGetFloat(cfg_energy_manager + "autoSwitchOff");
183 m_HasElectricityIcon = GetGame().ConfigGetFloat(cfg_energy_manager + "hasIcon");
184 m_AutoSwitchOffWhenInCargo = GetGame().ConfigGetFloat(cfg_energy_manager + "autoSwitchOffWhenInCargo");
185
186 m_Energy = GetGame().ConfigGetFloat(cfg_energy_manager + "energyAtSpawn");
187 m_EnergyStorageMax = GetGame().ConfigGetFloat(cfg_energy_manager + "energyStorageMax");
188 m_ReduceMaxEnergyByDamageCoef = GetGame().ConfigGetFloat(cfg_energy_manager + "reduceMaxEnergyByDamageCoef");
189 m_SocketsCount = GetGame().ConfigGetFloat(cfg_energy_manager + "powerSocketsCount");
190
191 m_IsPassiveDevice = GetGame().ConfigGetFloat(cfg_energy_manager + "isPassiveDevice");
192 m_CordLength = GetGame().ConfigGetFloat(cfg_energy_manager + "cordLength");
193 m_PlugType = GetGame().ConfigGetFloat(cfg_energy_manager + "plugType");
194
195 m_AttachmentActionType = GetGame().ConfigGetFloat(cfg_energy_manager + "attachmentAction");
196 m_WetnessExposure = GetGame().ConfigGetFloat(cfg_energy_manager + "wetnessExposure");
197
198 float update_interval = GetGame().ConfigGetFloat(cfg_energy_manager + "updateInterval");
199
200 m_ConvertEnergyToQuantity = GetGame().ConfigGetFloat(cfg_energy_manager + "convertEnergyToQuantity");
201
202
203 // Check if energy->quantity converion is configured properly
204 float cfg_max_quantity = GetGame().ConfigGetFloat (cfg_item + " varQuantityMax");
205
206 if (m_ConvertEnergyToQuantity && cfg_max_quantity <= 0)
207 {
208 string error = "Error! Item " + m_ThisEntityAI.GetType() + " has invalid configuration of the energy->quantity conversion feature. To fix this, add 'varQuantityMax' parameter with value higher than 0 to the item's config. Then make sure to re-build the PBO containing this item!";
209 Error(error);
211 }
212 else
213 {
215 {
218
219 m_UpdateQuantityTimer.Run( 0.3 , this, "OnEnergyAdded", NULL, false);
220 }
221 }
222
223 // Set update interval
224 if ( update_interval <= 0 )
225 update_interval = DEFAULT_UPDATE_INTERVAL;
226
227 SetUpdateInterval( update_interval );
228
229 // If energyAtSpawn is present, then use its value for energyStorageMax if that cfg param is not present (for convenience's sake)
230 string cfg_check_energy_limit = cfg_energy_manager + "energyStorageMax";
231
232 if ( !GetGame().ConfigIsExisting (cfg_check_energy_limit) && m_Energy > 0 )
233 {
235 }
236
237 // Fill m_CompatiblePlugTypes
238 string cfg_check_plug_types = cfg_energy_manager + "compatiblePlugTypes";
239
240 if ( GetGame().ConfigIsExisting (cfg_check_plug_types) )
241 {
243 GetGame().ConfigGetIntArray(cfg_check_plug_types, m_CompatiblePlugTypes);
244 }
245
246 if (GetSocketsCount() > 0)
248
249 if ( m_CordLength < 0 )
250 {
251 m_CordLength = 0;
252 string error_message_cord = "Warning! " + m_ThisEntityAI.GetType() + ": config parameter 'cordLength' is less than 0! Cord length should not be negative!";
253 DPrint(error_message_cord);
254 }
255
256 if (GetSocketsCount() > 0)
257 {
259 // Prepare the m_DeviceByPlugSelection
260 string cfg_animation_sources = "cfgVehicles " + m_ThisEntityAI.GetType() + " " + "AnimationSources ";
261 int animation_sources_count = GetGame().ConfigGetChildrenCount(cfg_animation_sources);
262
263 for (int i_selection = 0; i_selection < animation_sources_count; i_selection++)
264 {
265 // TO DO: This could be optimized so not all selections on item are considered as plug/socket selections.
266 string selection;
267 GetGame().ConfigGetChildName(cfg_animation_sources, i_selection, selection);
268 m_DeviceByPlugSelection.Set(selection, NULL);
269 }
270 }
271
272
273
274 // Prepare sockets
276 {
278 string error_message_sockets = "Error! " + m_ThisEntityAI.GetType() + ": config parameter 'powerSocketsCount' is higher than the current limit (" + MAX_SOCKETS_COUNT.ToString() + ")! Raise the limit (constant MAX_SOCKETS_COUNT) or decrease the powerSocketsCount parameter for this device!";
279 DPrint(error_message_sockets);
280 }
281
282 m_Sockets[MAX_SOCKETS_COUNT]; // Handles selections for plugs in the sockets. Feel free to change the limit if needed.
283
284 GetGame().ConfigGetText(cfg_energy_manager + "cordTextureFile", m_CordTextureFile);
285
286 if ( switch_on )
287 {
288 SwitchOn();
289 }
290
291 for ( int i = 0; i <= GetSocketsCount(); ++i )
292 {
293 m_ThisEntityAI.HideSelection ( SOCKET_ + i.ToString() + _PLUGGED );
294 }
295
296 // Show/hide inventory sockets
298 if ( GetSocketsCount() > 0 && IsPlugCompatible(PLUG_COMMON_APPLIANCE) && m_ThisEntityAI.GetType() != "MetalWire" ) // metal wire filter is hopefully temporal.
299 {
301 }
302
304
305 m_ThisEntityAI.HideSelection( SEL_CORD_PLUGGED );
306
307
308 #ifdef DIAG_DEVELOPER
309 GetGame().m_EnergyManagerArray.Insert( this );
310 #endif
311 }
312
313 // Returns the type of this component
314 override int GetCompType()
315 {
317 }
318
319 // When the object is deleted
321 {
322 bool was_working = m_ThisEntityAI.GetCompEM().IsWorking();
323
324 SwitchOff();
326 UnplugThis();
327 SetPowered( false );
328
329 if ( was_working )
330 m_ThisEntityAI.OnWorkStop();
331 ;
332 }
333
334 //Restart the debug timer when relogging
336 {
337 if ( m_DebugPlugs )
338 {
339 if ( !m_DebugUpdate )
341
342 if ( !m_DebugUpdate.IsRunning() )
343 m_DebugUpdate.Run(0.01, this, "DebugUpdate", NULL, true);
344 }
345 else
346 {
347 if ( m_DebugPlugArrow )
348 {
349 m_DebugPlugArrow.Destroy();
350 m_DebugPlugArrow = NULL;
351 }
352 }
353 }
354
356 {
357 return m_DebugPlugs;
358 }
359
360 void SetDebugPlugs( bool newVal )
361 {
362 m_DebugPlugs = newVal;
363 RefreshDebug();
364 }
365
366 //======================================================================================
367 // PUBLIC FUNCTIONS
368 // Use these to control the Energy Manager
369 // Functions are in order of their return value: void, bool, int, float, string, array.
370 //======================================================================================
371
373 void SwitchOn()
374 {
376
377 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
378 {
379 if ( CanSwitchOn() )
380 {
381 m_IsSwichedOn = true;
382 Synch();
383
384 DeviceUpdate(); // 'Wake up' this device now
385 StartUpdates();
386
387 // 'Wakes up' all connected devices
389
391
392 // Call event
393 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOn", NULL, 0);
394 }
395 }
396
397 if ( !GetGame().IsServer() && GetGame().IsMultiplayer()/* && CanSwitchOn() */) // I want the CanSwitchOn() check, but when it's here, the OnSwitchOn() event is never called on client-side due to engine's synchronization system changing the m_IsSwichedOn to true without any specific event beign called. (Yes there is OnVariablesSynchronized() but that is called also when m_CanWork is synchronized, so I need to write a method of knowing when was this specific value changed.)
398 {
399 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOn", NULL, 0);
400 }
401 }
402
405 {
407
408 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
409 {
410 if ( CanSwitchOff() )
411 {
412 m_IsSwichedOn = false;
413 Synch();
414
415 if ( IsWorking() )
416 {
417 StopUpdates();
418 DeviceUpdate();
419 }
420
421 // 'Wakes up' all connected devices
423
425
426 // Call event
427 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOff", NULL, 0);
428 }
429 }
430
431 if ( !GetGame().IsServer() && GetGame().IsMultiplayer() )
432 {
433 m_IsSwichedOn = false;
434 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOff", NULL, 0);
435 }
436 }
437
439 void SetPassiveState(bool state = true)
440 {
441 m_IsPassiveDevice = state;
442 if ( !m_IsPassiveDevice )
443 {
444 DeviceUpdate();
445 }
446 }
447
449 void UnplugDevice(EntityAI device_to_unplug)
450 {
451 if ( GetGame() )
452 {
453 int index_start = GetPluggedDevicesCount() - 1;
454 bool device_found = false;
455
456 for ( int i = index_start; i >= 0; --i )
457 {
458 EntityAI plugged_device = GetPluggedDevices().Get(i);
459
460 if (plugged_device == device_to_unplug)
461 {
462 GetPluggedDevices().Remove(i);
463 device_found = true;
464 break;
465 }
466 }
467
468 if (device_found)
469 {
470 int socket_ID = device_to_unplug.GetCompEM().GetMySocketID();
471 UnplugCordFromSocket( socket_ID );
472 device_to_unplug.GetCompEM().SetEnergySource(NULL);
473 device_to_unplug.GetCompEM().DeviceUpdate();
474 device_to_unplug.GetCompEM().StartUpdates();
475 device_to_unplug.GetCompEM().WakeUpWholeBranch( m_ThisEntityAI );
476
478 {
479 m_DebugPlugArrow.Destroy();
480 m_DebugPlugArrow = NULL;
481 }
482
483 OnOwnSocketReleased(device_to_unplug);
484 device_to_unplug.GetCompEM().OnIsUnplugged( m_ThisEntityAI );
485 device_to_unplug.ShowSelection ( SEL_CORD_FOLDED );
486 device_to_unplug.HideSelection ( SEL_CORD_PLUGGED );
487 }
488 }
489 }
490
493 {
494 if ( GetGame() )
495 {
496 if ( GetEnergySource() )
497 {
498 GetEnergySource().GetCompEM().UnplugDevice(m_ThisEntityAI);
499 }
500 }
501 }
502
505 {
506 if ( GetPluggedDevices() ) // This check is necesarry in case this function is called before initialization
507 {
508 int index_start = GetPluggedDevicesCount() - 1;
509 for ( int i = index_start; i >= 0; --i )
510 {
512 }
513 }
514 }
515
516 // Used only for storing of the plug's state through server restart
517 void RestorePlugState(bool state)
518 {
519 m_RestorePlugState = state;
520 }
521
523 void SetEnergy(float new_energy)
524 {
525 if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // Client can't change energy value.
526 {
527 m_ThisEntityAI.SetWeightDirty();
528 float old_energy = m_Energy;
529 m_Energy = new_energy;
530
531 if ( old_energy - GetEnergyUsage() <= 0 || (old_energy != new_energy && Math.Min(old_energy,new_energy) <= 0) )
532 {
534 }
535 }
536 }
537
539 void SetEnergy0To1(float energy01)
540 {
541 if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // Client can't change energy value.
542 {
543 SetEnergy( Math.Lerp(0, GetEnergyMax(),energy01));
544 }
545 }
546
549 {
550 // Lets update sockets, if there are any
551 int slots_c = GetSocketsCount();
552
553 for ( int i = 0; i < slots_c; ++i )
554 {
555 EntityAI plug_owner = GetDeviceBySocketID(i);
556
557 if ( plug_owner )
558 {
559 string plugged_selection = SOCKET_ + (i+1).ToString() + _PLUGGED;
560 string available_selection = SOCKET_ + (i+1).ToString() + _AVAILABLE;
561 m_ThisEntityAI.ShowSelection ( plugged_selection );
562 m_ThisEntityAI.HideSelection ( available_selection );
563 string texture_path = plug_owner.GetCompEM().GetCordTextureFile();
564 int selection_index = m_ThisEntityAI.GetHiddenSelectionIndex( plugged_selection );
565 m_ThisEntityAI.SetObjectTexture(selection_index, texture_path );
566 }
567 else
568 {
569 m_ThisEntityAI.ShowSelection ( SOCKET_ + (i+1).ToString() + _AVAILABLE );
570 m_ThisEntityAI.HideSelection ( SOCKET_ + (i+1).ToString() + _PLUGGED );
571 }
572 }
573
574 // Now lets update the cord/plug state
575 if ( GetEnergySource() )
576 {
577 m_ThisEntityAI.ShowSelection ( SEL_CORD_PLUGGED );
578 m_ThisEntityAI.HideSelection ( SEL_CORD_FOLDED );
579 }
580 else
581 {
582 m_ThisEntityAI.ShowSelection ( SEL_CORD_FOLDED );
583 m_ThisEntityAI.HideSelection ( SEL_CORD_PLUGGED );
584 }
585 }
586
589 {
590 // Check if the item is held in hands during advanced placement
591 if ( m_ThisEntityAI.GetHierarchyRootPlayer() && m_ThisEntityAI.GetHierarchyRootPlayer().IsKindOf("SurvivorBase") )
592 {
593 // Yes it is in player's hands
594 EntityAI player = m_ThisEntityAI.GetHierarchyRootPlayer();
595
596 // Measure distance from the player
597 vector pos_player = player.GetPosition();
598 if ( ! IsEnergySourceAtReach( pos_player , 5 ) )
599 {
600 UnplugThis();
601 }
602 }
603 else
604 {
605 // No it is not in player's hands.
606 // Measure distance from the device
607 vector pos_item = m_ThisEntityAI.GetPosition();
608
609 if ( m_ThisEntityAI.GetHierarchyParent() )
610 {
611 pos_item = m_ThisEntityAI.GetHierarchyParent().GetPosition();
612 }
613
614 if ( ! IsEnergySourceAtReach( pos_item ) )
615 {
616 UnplugThis();
617 }
618 }
619 }
620
621 // Returns an array of plug types this device can accept
623 {
625 }
626
627 // Stores IDs of the energy source.
628 void StoreEnergySourceIDs(int b1, int b2, int b3, int b4)
629 {
634 }
635
637 void SetEnergyMaxPristine(float new_limit)
638 {
639 m_EnergyStorageMax = new_limit;
640 }
641
643 void SetCordLength( float new_length )
644 {
645 m_CordLength = new_length;
646 }
647
648 // Sets the plug type (for plug -> socket compatibility checks).
649 void SetPlugType( int new_type )
650 {
651 m_PlugType = new_type;
652 }
653
654 // Sets the new attachment action type.
655 void SetAttachmentAction( int new_action_type )
656 {
657 m_AttachmentActionType = new_action_type;
658 }
659
661 void SetEnergyUsage( float new_usage )
662 {
663 m_EnergyUsage = new_usage;
664 }
665
668 {
669 string cfg_energy_usage = "CfgVehicles " + m_ThisEntityAI.GetType() + " EnergyManager ";
670 m_EnergyUsage = GetGame().ConfigGetFloat (cfg_energy_usage + "energyUsagePerSecond");
671 }
672
673 // Sets path to the cord texture file.
674 void SetCordTextureFile( string new_path )
675 {
676 m_CordTextureFile = new_path;
677 }
678
679 // Sets energy source. Intended to be called only on client through RPC.
681 {
682 SetEnergySource(source);
683 }
684
686 void SetDeviceBySocketID(int id, EntityAI plugged_device)
687 {
688 m_Sockets[id] = plugged_device;
689 }
690
691
693 void SetElectricityIconVisibility( bool make_visible )
694 {
695 m_HasElectricityIcon = make_visible;
696 }
697
698 // Checks whenever this device can work or not and updates this information on all clients. Can be called many times per frame because synchronization happens only once if a change has occured.
700 {
701 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
702 {
703 bool current_state = CanWork();
704
705 if (current_state != m_CanWork)
706 {
707 m_CanWork = current_state;
708 Synch();
709
710 if ( m_ThisEntityAI && m_ThisEntityAI.GetHierarchyParent() && m_ThisEntityAI.GetHierarchyParent().GetCompEM() )
711 {
712 m_ThisEntityAI.GetHierarchyParent().GetCompEM().UpdateCanWork();
713 }
714 }
715 }
716 }
717
719 {
721 {
722 if (IsSwitchedOn())
723 {
724 SwitchOff();
725 }
726 }
727 }
728
730 void SetUpdateInterval( float value )
731 {
732 m_UpdateInterval = value;
733 }
734
735 // Returns true if this device was plugged into something at the end of previous session
737 {
738 return m_RestorePlugState;
739 }
740
742 bool PlugThisInto(EntityAI energy_source, int socket_id = -1)
743 {
744 return energy_source.GetCompEM().PlugInDevice(m_ThisEntityAI, socket_id);
745 }
746
749 {
750 if ( !IsSwitchedOn() )
751 {
752 return true;
753 }
754
755 return false;
756 }
757
758
764 bool CanWork( float test_energy = -1)
765 {
766 if ( GetGame().IsMultiplayer() && GetGame().IsClient() )
767 {
768 return m_CanWork;
769 }
770
771 if (m_ThisEntityAI && m_ThisEntityAI.IsRuined())
772 {
773 return false;
774 }
775
776 // Check if the power source(s) (which can be serially connected) can provide needed energy.
777 float energy_usage = test_energy;
778 float gathered_energy = GetEnergy();
779 EntityAI energy_source = GetEnergySource();
780
781 if (energy_usage == -1)
782 {
783 energy_usage = GetEnergyUsage();
784 }
785
786 if ( !CheckWetness() )
787 {
788 return false;
789 }
790
791 if (gathered_energy <= 0 && energy_usage <= 0) //empty power source
792 {
793 return false;
794 }
795
796 int cycle_limit = 500; // Sanity check to definitely avoid infinite cycles
797
798 while ( gathered_energy < energy_usage ) // Look for energy source if we don't have enough stored energy
799 {
800 // Safetycheck!
801 if (cycle_limit > 0)
802 {
803 cycle_limit--;
804 }
805 else
806 {
807 DPrint("Energy Manager ERROR: The 'cycle_limit' safety break had to be activated to prevent possible game freeze. Dumping debug information...");
808 //Print(m_ThisEntityAI);
809 //Print(this);
810 //Print(energy_source);
811
812 if (energy_source.GetCompEM())
813 {
814 //Print(energy_source.GetCompEM());
815 }
816
817 //Print(gathered_energy);
818 //Print(energy_usage);
819
820 //Print(m_ThisEntityAI.GetPosition());
821
822 if (energy_source)
823 {
824 //Print(energy_source.GetPosition());
825 }
826
827 //Print("End of the 'cycle_limit' safety break ^ ");
828
829 return false;
830 }
831 // ^ Safetycheck!
832
833 if ( energy_source && energy_source != m_ThisEntityAI && !energy_source.IsRuined() && energy_source.GetCompEM() && energy_source.GetCompEM().IsSwitchedOn() && energy_source.GetCompEM().CheckWetness() )
834 {
835 gathered_energy = gathered_energy + energy_source.GetCompEM().GetEnergy();
836 energy_source = energy_source.GetCompEM().GetEnergySource();
837 }
838 else
839 {
840 // No power source, no energy.
841 return false;
842 }
843 }
844
845 // Enough energy was found
846 return true;
847 }
848
851 {
852 return (m_ThisEntityAI.GetWet() <= 1-m_WetnessExposure);
853 }
854
857 {
858 if ( IsPassive() )
859 {
860 return false;
861 }
862
863 return IsSwitchedOn();
864 }
865
866 // Returns previous state of the switch.
868 {
870 }
871
874 {
875 return m_IsSwichedOn;
876 }
877
880 {
881 if ( IsPlugged() )
882 return false;
883
884 return true;
885 }
886
889 {
890 return m_IsPassiveDevice;
891 }
892
895 {
896 return m_IsPlugged;
897 }
898
899
901 bool ConsumeEnergy(float amount)
902 {
903 return FindAndConsumeEnergy(m_ThisEntityAI, amount, true);
904 }
905
908 {
909 return m_IsWorking;
910 }
911
914 {
915 if ( GetEnergy() > GetEnergyUsage() )
916 {
917 return true;
918 }
919
920 return false;
921 }
922
924 bool HasFreeSocket( int socket_id = -1 )
925 {
926 if (socket_id == -1)
927 {
928 int plugged_devices = GetPluggedDevicesCount();
929 int plugged_devices_limit = GetSocketsCount();
930
931 if ( plugged_devices < plugged_devices_limit )
932 {
933 return true;
934 }
935
936 return false;
937 }
938 else
939 {
940 EntityAI device = GetDeviceBySocketID(socket_id);
941
942 if (device)
943 {
944 return false;
945 }
946 else
947 {
948 return true;
949 }
950 }
951 }
952
954 bool IsPlugCompatible(int plug_ID)
955 {
956 if ( plug_ID == PLUG_UNDEFINED )
957 {
958 return true; // When plugType is undefined in config then make it compatible.
959 }
960
962 {
963 for ( int i = 0; i < m_CompatiblePlugTypes.Count(); i++ )
964 {
965 int plug_ID_to_Check = m_CompatiblePlugTypes.Get(i);
966
967 if ( plug_ID_to_Check == plug_ID )
968 {
969 return true;
970 }
971 }
972 }
973 else
974 {
975 // Since the config parameter compatiblePlugTypes is not present, then accept all plugs for simplicity's sake
976 return true;
977 }
978
979 return false;
980 }
981
983 bool CanReceivePlugFrom( EntityAI device_to_plug )
984 {
985 // The following conditions are broken down for the sake of easier reading/debugging.
986
987 if ( HasFreeSocket() && device_to_plug != m_ThisEntityAI)
988 {
989 if ( device_to_plug.GetCompEM().GetEnergySource() != m_ThisEntityAI)
990 {
991 if ( IsPlugCompatible(device_to_plug.GetCompEM().GetPlugType()) )
992 {
993 if ( device_to_plug.GetCompEM().IsEnergySourceAtReach( device_to_plug.GetPosition(), 0, m_ThisEntityAI.GetPosition() ) )
994 {
995 return true;
996 }
997 }
998 }
999 }
1000
1001 return false;
1002 }
1003
1005 bool CanBePluggedInto( EntityAI potential_energy_provider )
1006 {
1007 return potential_energy_provider.GetCompEM().CanReceivePlugFrom( m_ThisEntityAI );
1008 }
1009
1012 {
1013 return m_HasElectricityIcon;
1014 }
1015
1018 {
1020 }
1021
1038 bool IsEnergySourceAtReach( vector from_position, float add_tolerance = 0, vector override_source_position = "-1 -1 -1" )
1039 {
1040 if ( !IsPlugged() && override_source_position == "-1 -1 -1" )
1041 {
1042 return false;
1043 }
1044
1045 if ( GetCordLength() == 0 ) // 0 is an exception, which means infinitely long cable.
1046 {
1047 return true;
1048 }
1049
1050 vector source_pos;
1051 float distance;
1052
1053 if ( override_source_position == "-1 -1 -1" )
1054 {
1055 EntityAI energy_source = GetEnergySource();
1056
1057 if (!energy_source)
1058 return false;
1059
1060 source_pos = energy_source.GetPosition();
1061 distance = vector.Distance( from_position, source_pos );
1062 }
1063 else
1064 {
1065 source_pos = override_source_position;
1066 distance = vector.Distance( from_position, source_pos );
1067 }
1068
1069 if ( distance > GetCordLength() + add_tolerance )
1070 {
1071 return false;
1072 }
1073 else
1074 {
1075 return true;
1076 }
1077 }
1078
1080 {
1082 }
1083
1085 bool IsSelectionAPlug(string selection_to_test )
1086 {
1087 if ( GetPluggedDevices() )
1088 {
1089 int socket_count = GetSocketsCount();
1090
1091 for ( int i = socket_count; i >= 0; --i )
1092 {
1093 string real_selection = SOCKET_ + i.ToString() +_PLUGGED;
1094
1095 if ( selection_to_test == real_selection)
1096 {
1097 return true;
1098 }
1099 }
1100 }
1101
1102 return false;
1103 }
1104
1105
1106
1107
1110 {
1111 return m_SocketsCount;
1112 }
1113
1116 {
1117 return m_PlugType;
1118 }
1119
1120 // Returns the action ID which is supposed to be done upon receiving an attachment
1122 {
1124 }
1125
1126 // Returns persistent ID (block 1) of the energy source
1128 {
1130 }
1131
1132 // Returns persistent ID (block 2) of the energy source
1134 {
1136 }
1137
1138 // Returns persistent ID (block 3) of the energy source
1140 {
1142 }
1143
1144 // Returns persistent ID (block 4) of the energy source
1146 {
1148 }
1149
1150 // Returns network ID (low) of the energy source
1152 {
1154 }
1155
1156 // Returns network ID (high) of the energy source
1158 {
1160 }
1161
1164 {
1165 if ( GetPluggedDevices() )
1166 {
1167 return GetPluggedDevices().Count();
1168 }
1169
1170 return 0;
1171 }
1172
1175 {
1176 if ( m_EnergyStorageMax > 0 )
1177 {
1178 int coef = Math.Round( m_Energy / m_EnergyStorageMax * 100 );
1179 return coef;
1180 }
1181
1182 return 0;
1183 }
1184
1187 {
1188 if ( m_EnergyStorageMax > 0 )
1189 {
1191 }
1192
1193 return 0;
1194 }
1195
1198 {
1199 #ifdef DIAG_DEVELOPER
1200 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_CONSUMPTION) || (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_RECHARGE)))
1201 {
1202 return 1;//when modifying time accel, we might want to see things happen when they should, instead of waiting for the next tick
1203 }
1204 #endif
1205 return m_UpdateInterval;
1206 }
1207
1210 {
1211 return m_WetnessExposure;
1212 }
1213
1216 {
1217 return m_EnergyUsage;
1218 }
1219
1222 {
1223 return m_Energy;
1224 }
1225
1227 float AddEnergy(float added_energy)
1228 {
1229 if (added_energy != 0)
1230 {
1231 //Print("AddEnergy ---------> " + added_energy + " " + this + " " +m_ThisEntityAI.ClassName());
1232 #ifdef DIAG_DEVELOPER
1233 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_CONSUMPTION) && added_energy < 0)
1234 {
1235 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
1236 added_energy *= timeAccel;
1237 }
1238 #endif
1239
1240 bool energy_was_added = (added_energy > 0);
1241
1242 float energy_to_clamp = GetEnergy() + added_energy;
1243 float clamped_energy = Math.Clamp( energy_to_clamp, 0, GetEnergyMax() );
1244 SetEnergy(clamped_energy);
1245 StartUpdates();
1246
1247 if (energy_was_added)
1248 OnEnergyAdded();
1249 else
1251
1252 return energy_to_clamp - clamped_energy;
1253 }
1254
1255 return 0;
1256 }
1257
1260 {
1261 float max_health = 0;
1262
1263 if ( m_ThisEntityAI.HasDamageSystem() )
1264 max_health = m_ThisEntityAI.GetMaxHealth("","");
1265 //else if ( m_ReduceMaxEnergyByDamageCoef != 0 )
1266 // Error("[ERROR] ReduceMaxEnergyByDamageCoef is setup but " + m_ThisEntityAI.GetType() + " does not have a Damage System");
1267
1268 if ( max_health == 0 || m_ReduceMaxEnergyByDamageCoef == 0 )
1269 return GetEnergyMaxPristine();
1270
1271 float health = 100;
1272
1273 if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // TO DO: Remove this IF when method GetHealth can be called on client!
1274 health = m_ThisEntityAI.GetHealth("","");
1275
1276 float damage_coef = 1 - (health / max_health);
1277
1278 return GetEnergyMaxPristine() * (1 - ( damage_coef * m_ReduceMaxEnergyByDamageCoef ) );
1279 }
1280
1283 {
1284 return m_EnergyStorageMax;
1285 }
1286
1289 {
1290 return m_CordLength;
1291 }
1292
1295 {
1296 return m_EnergySource;
1297 }
1298
1301 {
1302 return m_Sockets[id];
1303 }
1304
1306 EntityAI GetPlugOwner(string plug_selection_name)
1307 {
1308 if ( m_DeviceByPlugSelection.Contains(plug_selection_name) )
1309 {
1310 return m_DeviceByPlugSelection.Get(plug_selection_name);
1311 }
1312
1313 return NULL;
1314 }
1315
1318 {
1319 if ( GetPluggedDevicesCount() > 0 )
1320 {
1321 return GetPluggedDevices().Get(0);
1322 }
1323
1324 return NULL;
1325 }
1326
1329 {
1330 return m_CordTextureFile;
1331 }
1332
1335 {
1336 return m_PluggedDevices;
1337 }
1338
1341 {
1342 array<EntityAI> return_array = new array<EntityAI>;
1343 int plugged_devices_c = GetPluggedDevicesCount();
1344 for ( int i = 0; i < plugged_devices_c; ++i )
1345 {
1346 EntityAI device = GetPluggedDevices().Get(i);
1347 if ( IsSwitchedOn() )
1348 {
1349 return_array.Insert(device);
1350 }
1351 }
1352
1353 return return_array;
1354 }
1355
1356
1357 /*===================================
1358 PUBLIC EVENTS
1359 ===================================*/
1360
1361 // Called every device update if its supposed to do some work. The update can be every second or at random, depending on its manipulation.
1362 void OnWork( float consumed_energy )
1363 {
1364 m_ThisEntityAI.OnWork(consumed_energy);
1365 }
1366
1367 // Called when this device is plugged into some energy source
1368 void OnIsPlugged(EntityAI source_device)
1369 {
1370 if (m_DebugPlugs)
1371 {
1372 if (!m_DebugUpdate)
1374
1375 if (!m_DebugUpdate.IsRunning())
1376 m_DebugUpdate.Run(0.01, this, "DebugUpdate", NULL, true);
1377 }
1378
1379 UpdateCanWork();
1380 m_ThisEntityAI.OnIsPlugged(source_device);
1381 }
1382
1383 // Called when this device is UNPLUGGED from the energy source
1384 void OnIsUnplugged( EntityAI last_energy_source )
1385 {
1386 UpdateCanWork();
1387 m_ThisEntityAI.OnIsUnplugged( last_energy_source );
1388 }
1389
1390 // When something is plugged into this device
1392 {
1393 //play sound
1394 if ( device.GetCompEM().GetPlugType() == PLUG_COMMON_APPLIANCE && m_ThisEntityAI.IsInitialized() )
1395 {
1396 EffectSound sound_plug;
1397 m_ThisEntityAI.PlaySoundSet( sound_plug, "cablereel_plugin_SoundSet", 0, 0 );
1398 }
1399
1400 m_ThisEntityAI.OnOwnSocketTaken(device);
1401 }
1402
1403 // When something is UNPLUGGED from this device
1405 {
1406 //play sound
1407 if ( device.GetCompEM().GetPlugType() == PLUG_COMMON_APPLIANCE && m_ThisEntityAI.IsInitialized() )
1408 {
1409 EffectSound sound_unplug;
1410 m_ThisEntityAI.PlaySoundSet( sound_unplug, "cablereel_unplug_SoundSet", 0, 0 );
1411 }
1412
1413 m_ThisEntityAI.OnOwnSocketReleased( device );
1414 }
1415
1416
1417 // Handles automatic attachment action
1418 void OnAttachmentAdded(EntityAI elec_device)
1419 {
1420 int attachment_action_type = GetAttachmentAction();
1421
1422 if ( attachment_action_type == PLUG_THIS_INTO_ATTACHMENT )
1423 {
1424 if ( elec_device.GetCompEM().CanReceivePlugFrom( m_ThisEntityAI ) )
1425 {
1426 PlugThisInto(elec_device);
1427 }
1428 }
1429 else if ( attachment_action_type == PLUG_ATTACHMENTS_INTO_THIS )
1430 {
1431 elec_device.GetCompEM().PlugThisInto(m_ThisEntityAI);
1432 }
1433 }
1434
1435 // Handles automatic detachment action
1437 {
1438 int attachment_action_type = GetAttachmentAction();
1439
1440 if ( attachment_action_type == PLUG_THIS_INTO_ATTACHMENT )
1441 {
1442 if ( elec_device == GetEnergySource() )
1443 {
1444 UnplugThis();
1445 }
1446 }
1447 else if ( attachment_action_type == PLUG_ATTACHMENTS_INTO_THIS )
1448 {
1449 elec_device.GetCompEM().UnplugThis();
1450 }
1451 }
1452
1453 // Starts the device's main cycle
1455 {
1456 if ( !m_IsPassiveDevice )
1457 {
1458 if (!m_UpdateTimer)
1460
1461 if ( !m_UpdateTimer.IsRunning() ) // Makes sure the timer is NOT running already
1462 {
1463 m_UpdateTimer.Run( GetUpdateInterval() , this, "DeviceUpdate", NULL, true);
1464 }
1465 }
1466 }
1467
1470 {
1471 m_ThisEntityAI.OnEnergyConsumed();
1472 }
1473
1476 {
1478 {
1480 m_UpdateQuantityTimer = NULL;
1481 }
1482
1483 m_ThisEntityAI.OnEnergyAdded();
1484 }
1485
1486
1487 /*===================================
1488 PROTECTED FUNCTIONS
1489 ===================================*/
1490
1491 // Stops the device's main cycle
1492 protected void StopUpdates()
1493 {
1494 if (m_UpdateTimer)
1495 {
1497 m_UpdateTimer = NULL; // Delete timer from memory
1498 }
1499 }
1500
1504 void InteractBranch(EntityAI originalCaller, Man player = null, int system = 0)
1505 {
1506 OnInteractBranch(originalCaller, player, system);
1507 if ( GetSocketsCount() > 0 )
1508 {
1510
1511 foreach ( EntityAI device : devices)
1512 {
1513 if ( device != originalCaller ) // originalCaller check here prevents infinite loops
1514 {
1515 device.GetCompEM().InteractBranch( originalCaller, player, system );
1516 }
1517 }
1518 }
1519 }
1520
1522 protected void OnInteractBranch(EntityAI originalCaller, Man player, int system)
1523 {
1524 m_ThisEntityAI.IncreaseLifetime();
1525
1526 }
1527
1528 // 'Wakes up' all devices down the network so they start working, if they have enough power, and are switched ON
1529 protected void WakeUpWholeBranch( EntityAI original_caller )
1530 {
1531 if ( GetSocketsCount() > 0 )
1532 {
1533 array<EntityAI> plugged_devices = GetPluggedDevices();
1534 int plugged_devices_c = plugged_devices.Count();
1535
1536 for ( int i = 0; i < plugged_devices_c; ++i )
1537 {
1538 EntityAI device = plugged_devices.Get(i);
1539 if ( device != original_caller ) // original_caller check here prevents infinite loops
1540 {
1541 device.GetCompEM().UpdateCanWork();
1542 device.GetCompEM().DeviceUpdate();
1543 device.GetCompEM().StartUpdates();
1544 device.GetCompEM().WakeUpWholeBranch( original_caller );
1545 }
1546 }
1547 }
1548 }
1549
1550 // Finds an available socket and plugs the given device into it.
1551 // This is mainly about visualisation.
1552 protected void PlugCordIntoSocket( EntityAI device_to_plug, int socket_id = -1 )
1553 {
1554 if (socket_id >= 0)
1555 {
1556 EntityAI plug_owner_by_socket = GetDeviceBySocketID(socket_id);
1557
1558 if (!plug_owner_by_socket)
1559 {
1560 UpdateSocketSelections(socket_id, device_to_plug);
1561 return;
1562 }
1563 }
1564
1565 int slots_c = GetSocketsCount();
1566
1567 for ( int i = 0; i < slots_c; ++i )
1568 {
1569 EntityAI plug_owner = GetDeviceBySocketID(i);
1570
1571 if ( !plug_owner ) // Check if this socket is available
1572 {
1573 UpdateSocketSelections(i, device_to_plug);
1574 break;
1575 }
1576 }
1577 }
1578
1579 // Updates socket selections (plugged/unplugged) of the given ID and sets color texture of the plug.
1580 protected void UpdateSocketSelections(int socket_id, EntityAI device_to_plug)
1581 {
1582 SetDeviceBySocketID(socket_id, device_to_plug);
1583
1584 string plugged_selection = SOCKET_ + (socket_id+1).ToString() + _PLUGGED;
1585 SetPlugOwner( plugged_selection, device_to_plug );
1586 m_ThisEntityAI.ShowSelection ( plugged_selection );
1587
1588 string unplugged_selection = SOCKET_ + (socket_id+1).ToString() + _AVAILABLE;
1589 m_ThisEntityAI.HideSelection ( unplugged_selection );
1590 string texture_path = device_to_plug.GetCompEM().GetCordTextureFile();
1591 int selection_index = m_ThisEntityAI.GetHiddenSelectionIndex( plugged_selection );
1592 m_ThisEntityAI.SetObjectTexture( selection_index, texture_path );
1593 device_to_plug.GetCompEM().SetMySocketID(socket_id);
1594 }
1595
1596
1597 // Sets energy source for this device
1598 protected void SetEnergySource( EntityAI source )
1599 {
1600 m_EnergySource = source;
1601
1602 if (source)
1603 {
1604 m_IsPlugged = true;
1605 StartUpdates();
1606 }
1607 else
1608 {
1609 m_IsPlugged = false;
1612 }
1613
1614 if (m_EnergySource)
1615 {
1617
1618 //Print(m_EnergySource);
1619 //Print(m_EnergySourceNetworkIDLow);
1620 //Print(m_EnergySourceNetworkIDHigh);
1621 }
1622
1623 Synch();
1624 }
1625
1626 // Plugs the given device into this one
1627 protected bool PlugInDevice(EntityAI device_to_plug, int socket_id = -1)
1628 {
1629 if ( CanReceivePlugFrom(device_to_plug) )
1630 {
1631 device_to_plug.IncreaseLifetime();
1633 if ( device_to_plug.GetCompEM().IsPlugged() )
1634 device_to_plug.GetCompEM().UnplugThis();
1635
1636 GetPluggedDevices().Insert( device_to_plug );
1637 device_to_plug.GetCompEM().SetEnergySource(m_ThisEntityAI);
1638
1639 PlugCordIntoSocket( device_to_plug, socket_id ); // Visualisation
1640 OnOwnSocketTaken( device_to_plug );
1641
1642 device_to_plug.GetCompEM().OnIsPlugged(m_ThisEntityAI);
1644
1645 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
1646 {
1647 device_to_plug.HideSelection( SEL_CORD_FOLDED );
1648 device_to_plug.ShowSelection( SEL_CORD_PLUGGED );
1649 }
1650
1651 return true;
1652 }
1653
1654 return false;
1655 }
1656
1657 // Sets the device to which the given plug selection belongs to
1658 protected void SetPlugOwner(string selection_name, EntityAI device)
1659 {
1660 if ( m_DeviceByPlugSelection.Contains(selection_name) )
1661 {
1662 m_DeviceByPlugSelection.Set(selection_name, device);
1663 }
1664 }
1665
1666 // Frees the given socket.
1667 // This is only about visualisation.
1668 protected void UnplugCordFromSocket( int socket_to_unplug_ID )
1669 {
1670 EntityAI plug_owner = GetDeviceBySocketID(socket_to_unplug_ID);
1671
1672 if ( plug_owner )
1673 {
1674 SetDeviceBySocketID(socket_to_unplug_ID, NULL);
1675 string unplugged_selection = SOCKET_ + (socket_to_unplug_ID+1).ToString() + _AVAILABLE;
1676 m_ThisEntityAI.ShowSelection ( unplugged_selection );
1677
1678 string plugged_selection = SOCKET_ + (socket_to_unplug_ID+1).ToString() + _PLUGGED;
1679 m_ThisEntityAI.HideSelection ( plugged_selection );
1680 SetPlugOwner( plugged_selection, NULL );
1681 plug_owner.GetCompEM().SetMySocketID(-1);
1682 }
1683 }
1684
1685 // Sets the state of the device
1686 protected void SetPowered( bool state )
1687 {
1688 m_IsWorking = state;
1689 }
1690
1691 // Tries to consume the given amount of energy. If there is none in this device, then it tries to take it from some power source.
1692 protected bool FindAndConsumeEnergy(EntityAI original_caller, float amount, bool ignore_switch_state = false)
1693 {
1694 if ( (ignore_switch_state || IsSwitchedOn()) && !m_ThisEntityAI.IsRuined() )
1695 {
1696 float available_energy = AddEnergy(-amount);
1697
1698 if ( available_energy < 0 && IsPlugged() )
1699 {
1700 // This devices does not has enough of stored energy, therefore it will take it from its power source (which can be a chain of cable reels)
1701 EntityAI next_power_source = GetEnergySource();
1702
1703 if (next_power_source && next_power_source != original_caller) // Prevents infinite loop if the power source is the original caller itself
1704 {
1705 return next_power_source.GetCompEM().FindAndConsumeEnergy( original_caller, -available_energy );
1706 }
1707 }
1708
1709 if ( available_energy >= 0)
1710 {
1711 return true;
1712 }
1713
1714 return false;
1715 }
1716 else
1717 {
1718 return false;
1719 }
1720 }
1721
1722 // Gets the socket ID this device is powered from.
1723 protected int GetMySocketID()
1724 {
1725 return m_MySocketID;
1726 }
1727
1728 // Sets the socket ID this device is plugged into.
1729 protected void SetMySocketID( int slot_ID )
1730 {
1731 m_MySocketID = slot_ID;
1732 }
1733
1734 void Synch()
1735 {
1736 m_ThisEntityAI.SetSynchDirty();
1737 }
1738
1740 {
1741 m_LastUpdateTime = 0;
1742 }
1743
1745 {
1747 }
1748
1750 {
1751 return GetGame().GetTime();
1752 }
1753
1754 // Updates the device's state of power. This function is visualized in the diagram at DayZ Confluence >> Camping & Squatting >> Electricity >> Energy Manager functionalities
1756 {
1757 /*
1758 vector pos = m_ThisEntityAI.GetPosition();
1759 string debug_message = "Object " + m_ThisEntityAI.GetType() + " | Energy: " + GetEnergy() + " | IsAtReach: " + (IsEnergySourceAtReach(pos)).ToString();
1760 Print(debug_message);
1761 */
1762
1763 if ( !m_IsPassiveDevice )
1764 {
1765 // 'm_ThisEntityAI' and 'this' must be checked because this method is caled from a timer
1766 if ( m_ThisEntityAI && this && IsSwitchedOn() && !m_ThisEntityAI.IsRuined() && CheckWetness() && m_CanWork && !GetGame().IsMissionMainMenu() )
1767 {
1768 bool was_powered = IsWorking();
1769 float consumed_energy_coef;
1770 // Make sure to use only as much % of energy as needed since this function can be called at random.
1771
1772 if ( m_LastUpdateTime == 0 )
1773 {
1775 consumed_energy_coef = 1.0;
1776 }
1777 else
1778 {
1779 float updatetime = GetCurrentUpdateTime();
1780 float time = updatetime - m_LastUpdateTime;
1781 consumed_energy_coef = time / 1000;
1782 }
1783
1784 if (consumed_energy_coef > 0) // Prevents calling of OnWork events when no energy is consumed
1785 {
1787 float consume_energy = GetEnergyUsage() * consumed_energy_coef;
1788 bool has_consumed_enough = true;
1789
1790 if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // single player or server side multiplayer
1791 has_consumed_enough = ConsumeEnergy( consume_energy );
1792
1793 SetPowered( has_consumed_enough );
1794
1795 if ( has_consumed_enough )
1796 {
1797 if ( !was_powered )
1798 {
1799 m_CanStopWork = true;
1801 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStart", NULL, 0);
1802 UpdateCanWork();
1803 }
1804
1805 OnWork( consume_energy );
1806 }
1807 else
1808 {
1809 if ( was_powered )
1810 {
1811 if (m_CanStopWork)
1812 {
1813 m_CanStopWork = false;
1815 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStop", NULL, 0); // This event is called only once when the device STOPS being powered
1816 UpdateCanWork();
1817
1818 if (m_AutoSwitchOff)
1819 {
1820 SwitchOff();
1821 }
1822 }
1823 }
1824
1825 StopUpdates();
1826 }
1827 }
1828 else
1829 {
1831 }
1832 }
1833 else if (this && m_ThisEntityAI)
1834 {
1835 SetPowered( false );
1836 StopUpdates();
1837
1838 if (m_CanStopWork)
1839 {
1840 m_CanStopWork = false;
1842 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStop", NULL, 0); // This event is called only once when the device STOPS being powered
1843 UpdateCanWork();
1844
1845 if (m_AutoSwitchOff)
1846 {
1847 SwitchOff();
1848 }
1849 }
1850 }
1851 }
1852 }
1853}
const int PLUG_ATTACHMENTS_INTO_THIS
Definition _constants.c:36
const int PLUG_THIS_INTO_ATTACHMENT
Definition _constants.c:35
const int PLUG_UNDEFINED
Definition _constants.c:23
const int PLUG_COMMON_APPLIANCE
Definition _constants.c:25
proto string ToString()
array< ref PlayerStatBase > Get()
proto native int ConfigGetChildrenCount(string path)
Get count of subclasses in config class on path.
proto native float ConfigGetFloat(string path)
Get float value from config on path.
proto native void ConfigGetIntArray(string path, out TIntArray values)
Get array of integers from config on path.
proto bool ConfigGetText(string path, out string value)
Get string value from config on path.
proto bool ConfigGetChildName(string path, int index, out string name)
Get name of subclass in config class on path.
proto int GetTime()
returns mission time in milliseconds
ScriptModule GameScript
Definition Game.c:12
protected bool m_ShowSocketsInInventory
void StoreEnergySourceIDs(int b1, int b2, int b3, int b4)
float AddEnergy(float added_energy)
Energy manager: Adds energy to this device and clamps it within its min/max storage limits....
static protected const string SOCKET_
protected void SetPowered(bool state)
void SetUpdateInterval(float value)
Energy manager: Sets the interval of the OnWork(...) calls. Changing this value does not change the r...
void SwitchOff()
Energy manager: Switches OFF the device.
ref array< EntityAI > m_PluggedDevices
void SetCordLength(float new_length)
Energy manager: Changes the length of the virtual power cord.
EntityAI m_Sockets[MAX_SOCKETS_COUNT]
static protected const string _AVAILABLE
bool IsPlugged()
Energy manager: Returns true if this device is plugged into some other device (even if they are OFF o...
bool CanWork(float test_energy=-1)
Energy manager: Checks whenever this device can do work or not.
bool IsEnergySourceAtReach(vector from_position, float add_tolerance=0, vector override_source_position="-1 -1 -1")
Energy manager: Returns true if this device's virtual power cord can reach its energy source at the g...
protected void SetEnergySource(EntityAI source)
bool HasElectricityIcon()
Energy manager: Returns true if the electricity icon (bolt) is supposed to be visible for this device...
void SetAttachmentAction(int new_action_type)
protected bool FindAndConsumeEnergy(EntityAI original_caller, float amount, bool ignore_switch_state=false)
void SetDeviceBySocketID(int id, EntityAI plugged_device)
Energy manager: Stores the device which is plugged into the given socket ID.
float GetEnergy()
Energy manager: Returns the amount of stored energy this device has.
array< EntityAI > GetPoweredDevices()
Energy manager: Returns an array of devices which are plugged into this one and are turned on.
EntityAI GetEnergySource()
Energy manager: Returns the energy source this device is plugged into.
void OnAttachmentAdded(EntityAI elec_device)
array< EntityAI > GetPluggedDevices()
Energy manager: Returns an array of devices which are plugged into this one.
void UnplugThis()
Energy manager: Unplugs this device from its power source.
void SwitchOn()
Energy manager: Switches ON the device so it starts doing its work if it has enough energy.
bool CanSwitchOn()
Energy manager: Checks if the device can be switched ON.
void UpdatePlugState()
Energy manager: Unplugs this device when it's necesarry.
void SetEnergy(float new_energy)
Energy manager: Sets stored energy for this device. It ignores the min/max limit!
float GetEnergy0To1()
Energy manager: Returns % of stored energy this device has as float (from 0.0 to 1....
bool CheckWetness()
Energy manager: Checks if this device is being stopped from working by its wetness level....
protected bool m_IsSwichedOnPreviousState
protected const float DEFAULT_UPDATE_INTERVAL
protected float m_ReduceMaxEnergyByDamageCoef
void HandleMoveInsideCargo(EntityAI container)
void OnEnergyConsumed()
Energy manager: Called when energy was consumed on this device.
int GetEnergy0To100()
Energy manager: Returns % of stored energy this device has as integer (from 0 to 100)
Shape DrawArrow(vector from, vector to, float size=0.5, int color=0xFFFFFFFF, float flags=0)
protected bool m_AutoSwitchOffWhenInCargo
void InteractBranch(EntityAI originalCaller, Man player=null, int system=0)
static const string SEL_CORD_FOLDED
void GetCompatiblePlugTypes(out TIntArray IDs)
void OnOwnSocketTaken(EntityAI device)
void SetEnergyUsage(float new_usage)
Energy manager: Changes the energy usage per second.
protected void UpdateSocketSelections(int socket_id, EntityAI device_to_plug)
protected bool PlugInDevice(EntityAI device_to_plug, int socket_id=-1)
void SetElectricityIconVisibility(bool make_visible)
Energy manager: Sets visibility of the electricity icon (bolt).
bool IsWorking()
Energy manager: Returns true if this device is working right now.
void SetCordTextureFile(string new_path)
ref map< string, EntityAI > m_DeviceByPlugSelection
bool HasEnoughStoredEnergy()
Energy manager: Returns true if this device has enough of stored energy for its own use.
void ResetEnergyUsage()
Energy manager: Resets energy usage to default (config) value.
void OnWork(float consumed_energy)
protected void PlugCordIntoSocket(EntityAI device_to_plug, int socket_id=-1)
void SetEnergy0To1(float energy01)
Energy manager: Sets stored energy for this device between 0 and MAX based on relative input value be...
protected bool m_ConvertEnergyToQuantity
void UpdateSelections()
Energy manager: Shows/Hides all selections this system works with. Call this if something is wrong wi...
void OnIsPlugged(EntityAI source_device)
protected void OnInteractBranch(EntityAI originalCaller, Man player, int system)
Called when the player is interacting with an item containing this energy component,...
float GetEnergyMax()
Energy manager: Returns the maximum amount of energy this device can curently store....
void UnplugAllDevices()
Energy manager: Unplugs everything directly connected to this device.
void OnAttachmentRemoved(EntityAI elec_device)
bool PlugThisInto(EntityAI energy_source, int socket_id=-1)
Energy manager: Attempts to plug this device into the energy_source. Returns true if the action was s...
float GetCordLength()
Energy manager: Returns the length of the virtual power cord.
static protected bool m_DebugPlugs
protected void SetPlugOwner(string selection_name, EntityAI device)
static protected const string _PLUGGED
protected void UnplugCordFromSocket(int socket_to_unplug_ID)
void SetEnergyMaxPristine(float new_limit)
Energy manager: Changes the maximum amount of energy this device can store (when pristine).
bool HasFreeSocket(int socket_id=-1)
Energy manager: Returns true if this device has any free socket to receive a plug....
float GetWetnessExposure()
Returns wetness exposure value defined in config.
bool IsSelectionAPlug(string selection_to_test)
Energy manager: Returns true if this selection is a plug that's plugged into this device....
int GetSocketsCount()
Energy manager: Returns the count of power sockets (whenever used or not)
bool ConsumeEnergy(float amount)
Energy manager: Consumes the given amount of energy. If there is not enough of stored energy in this ...
protected void SetMySocketID(int slot_ID)
float GetUpdateInterval()
Energy manager: Returns the update interval of this device.
void SetEnergySourceClient(EntityAI source)
void OnEnergyAdded()
Energy manager: Called when energy was added on this device.
EntityAI GetPlugOwner(string plug_selection_name)
Energy manager: Returns the device to which the given plug selection belongs to.
bool IsCordFolded()
Energy manager: Returns true if the cord of this device is folded. Returns false if it's plugged.
float GetEnergyMaxPristine()
Energy manager: Returns the maximum amount of energy this device can store. It's damage is NOT taken ...
bool CanReceivePlugFrom(EntityAI device_to_plug)
Energy manager: Returns true if this device can receive power plug of the other device.
string GetCordTextureFile()
Energy manager: Returns path to the cord texture file.
void OnOwnSocketReleased(EntityAI device)
EntityAI GetPluggedDevice()
Energy manager: Returns a device which is plugged into this one. If there are more devices to choose ...
float GetEnergyUsage()
Energy manager: Returns the number of energy this device needs to run itself (See its config >> energ...
void UnplugDevice(EntityAI device_to_unplug)
Energy manager: Unplugs the given device from this one.
void SetPassiveState(bool state=true)
Energy manager: Changes the status of this device. When it's passive (true), the main timer and OnWor...
bool HasConversionOfEnergyToQuantity()
Energy manager: Returns true if this item automatically converts its energy to quantity.
protected int m_EnergySourceNetworkIDHigh
protected ref TIntArray m_CompatiblePlugTypes
bool IsPassive()
Energy manager: Returns true if this device is set to be passive. False if otherwise.
bool CanSwitchOff()
Energy manager: Checks if the device can be switched OFF.
static const string SEL_CORD_PLUGGED
int GetPluggedDevicesCount()
Energy manager: Returns the number of devices plugged into this one.
bool CanBePluggedInto(EntityAI potential_energy_provider)
Energy manager: Returns true if this device can be plugged into the given energy source....
int GetPlugType()
Energy manager: Returns plug type. Check \DZ\data\basicDefines.hpp OR \Scripts\Classes\Component_cons...
void OnIsUnplugged(EntityAI last_energy_source)
EntityAI GetDeviceBySocketID(int id)
Energy manager: Returns the device which is plugged into the given socket ID.
bool IsPlugCompatible(int plug_ID)
Energy manager: Checks if the given plug is compatible with this device's socket. Used by CanReceiveP...
protected void WakeUpWholeBranch(EntityAI original_caller)
bool IsSwitchedOn()
Energy manager: Returns state of the switch. Whenever the device is working or not does not matter....
protected EntityAI m_ThisEntityAI
Definition Component.c:24
Wrapper class for managing sound through SEffectManager.
Definition EffectSound.c:5
Definition EnMath.c:7
override void Stop()
static proto native float Distance(vector v1, vector v2)
Returns the distance between tips of two 3D vectors.
proto float Normalize()
Normalizes vector. Returns length.
vector Perpend()
Returns perpendicular vector. Perpendicular vector is computed as cross product between input vector ...
Definition EnConvert.c:209
static proto native float DistanceSq(vector v1, vector v2)
Returns the square distance between tips of two 3D vectors.
proto native CGame GetGame()
const int COMP_TYPE_ENERGY_MANAGER
Definition Component.c:9
void Error(string err)
Messagebox with error message.
Definition EnDebug.c:90
proto void DPrint(string var)
Prints content of variable to console/log. Should be used for critical messages so it will appear in ...
class DiagMenu Shape
don't call destructor directly. Use Destroy() instead
proto volatile int CallFunction(Class inst, string function, out void returnVal, void parm)
array< int > TIntArray
Definition EnScript.c:687
static proto float Round(float f)
Returns mathematical round of value.
static proto float Clamp(float value, float min, float max)
Clamps 'value' to 'min' if it is lower than 'min', or to 'max' if it is higher than 'max'.
static proto float Min(float x, float y)
Returns smaller of two given values.
static proto float Lerp(float a, float b, float time)
Linearly interpolates between 'a' and 'b' given 'time'.
static proto string ToString(void var, bool type=false, bool name=false, bool quotes=true)
Return string representation of variable.
const int CALL_CATEGORY_SYSTEM
Definition tools.c:8