Dayz Explorer 1.28.160049
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_EnergyAtSpawn;
51 protected float m_EnergyStorageMax;
53 protected float m_SocketsCount;
54 protected float m_CordLength;
55 protected float m_LastUpdateTime;
56 protected float m_WetnessExposure;
57 protected float m_UpdateInterval; // Interval of OnWork(...) calls and device updates.
58
59 protected string m_CordTextureFile;
60
61 // Concatenated strings for p3d selections
62 protected static const string SOCKET_ = "socket_";
63 protected static const string _PLUGGED = "_plugged";
64 protected static const string _AVAILABLE = "_available";
65 static const string SEL_CORD_PLUGGED = "cord_plugged";
66 static const string SEL_CORD_FOLDED = "cord_folded";
67
69 EntityAI m_EnergySource; // Energy source can be any EntityAI object
72
76
77 const int MAX_SOCKETS_COUNT = 4;
79
80
81
82 // Constructor
84 {
85 // Disable debug arrows on public release, so that they don't use their timers.
86 #ifndef DEVELOPER
87 m_DebugPlugs = false;
88 #endif
89 }
90
92 {
94 {
95 m_DebugPlugArrow.Destroy();
96 m_DebugPlugArrow = NULL;
97 }
98 }
99
100 // Initialization. Energy Manager is ready.
101 override void Event_OnInit()
102 {
103 m_ThisEntityAI.m_EM = this;
104 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnInitEnergy", NULL, 0);
105 }
106
107 // Update debug arrows
109 {
110 if ( GetDebugPlugs() )
111 {
112 if ( GetGame().IsMultiplayer() && GetGame().IsServer() )
113 {
114 if (m_DebugUpdate)
115 m_DebugUpdate.Stop();
116
117 return;
118 }
119
121 {
122 m_DebugPlugArrow.Destroy();
123 m_DebugPlugArrow = NULL;
124 }
125
126 if ( GetEnergySource() )
127 {
128 vector from = GetEnergySource().GetPosition() + "0 0.1 0";
129 vector to = m_ThisEntityAI.GetPosition() + "0 0.1 0";
130
131 //No need to draw an arrow in this situation as it would not be visible
132 if ( vector.DistanceSq(from, to) == 0 )
133 return;
134
135 if ( m_ThisEntityAI.GetType() == "BarbedWire" ) // Special case for debugging of electric fences. Temporal code until offsets in fences are fixed.
136 {
137 EntityAI BBB = m_ThisEntityAI.GetHierarchyParent();
138
139 if ( BBB && BBB.GetType() == "Fence" )
140 {
141 to = to + "0 -1.3 0";
142 }
143 }
144
145 m_DebugPlugArrow = DrawArrow( from, to );
146 }
147 }
148 }
149
150 Shape DrawArrow(vector from, vector to, float size = 0.5, int color = 0xFFFFFFFF, float flags = 0)
151 {
152 vector dir = to - from;
153 dir.Normalize();
154 vector dir1 = dir * size;
155 size = size * 0.5;
156
157 vector dir2 = dir.Perpend() * size;
158
159 vector pts[5];
160 pts[0] = from;
161 pts[1] = to;
162 pts[2] = to - dir1 - dir2;
163 pts[3] = to - dir1 + dir2;
164 pts[4] = to;
165
166 return Shape.CreateLines(color, flags, pts, 5);
167 }
168
170 {
171 return m_ThisEntityAI;
172 }
173
174 // Prepare everything
175 override void Event_OnAwake()
176 {
177 string cfg_item = "CfgVehicles " + m_ThisEntityAI.GetType();
178 string cfg_energy_manager = cfg_item + " EnergyManager ";
179
180 // Read all config parameters
181 m_EnergyUsage = GetGame().ConfigGetFloat(cfg_energy_manager + "energyUsagePerSecond");
182 bool switch_on = GetGame().ConfigGetFloat(cfg_energy_manager + "switchOnAtSpawn");
183 m_AutoSwitchOff = GetGame().ConfigGetFloat(cfg_energy_manager + "autoSwitchOff");
184 m_HasElectricityIcon = GetGame().ConfigGetFloat(cfg_energy_manager + "hasIcon");
185 m_AutoSwitchOffWhenInCargo = GetGame().ConfigGetFloat(cfg_energy_manager + "autoSwitchOffWhenInCargo");
186
187 m_EnergyAtSpawn = GetGame().ConfigGetFloat(cfg_energy_manager + "energyAtSpawn");
189 m_EnergyStorageMax = GetGame().ConfigGetFloat(cfg_energy_manager + "energyStorageMax");
190 m_ReduceMaxEnergyByDamageCoef = GetGame().ConfigGetFloat(cfg_energy_manager + "reduceMaxEnergyByDamageCoef");
191 m_SocketsCount = GetGame().ConfigGetFloat(cfg_energy_manager + "powerSocketsCount");
192
193 m_IsPassiveDevice = GetGame().ConfigGetFloat(cfg_energy_manager + "isPassiveDevice");
194 m_CordLength = GetGame().ConfigGetFloat(cfg_energy_manager + "cordLength");
195 m_PlugType = GetGame().ConfigGetFloat(cfg_energy_manager + "plugType");
196
197 m_AttachmentActionType = GetGame().ConfigGetFloat(cfg_energy_manager + "attachmentAction");
198 m_WetnessExposure = GetGame().ConfigGetFloat(cfg_energy_manager + "wetnessExposure");
199
200 float update_interval = GetGame().ConfigGetFloat(cfg_energy_manager + "updateInterval");
201
202 m_ConvertEnergyToQuantity = GetGame().ConfigGetFloat(cfg_energy_manager + "convertEnergyToQuantity");
203
204
205 // Check if energy->quantity converion is configured properly
206 float cfg_max_quantity = GetGame().ConfigGetFloat (cfg_item + " varQuantityMax");
207
208 if (m_ConvertEnergyToQuantity && cfg_max_quantity <= 0)
209 {
210 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!";
211 Error(error);
213 }
214 else
215 {
217 {
220
221 m_UpdateQuantityTimer.Run( 0.3 , this, "OnEnergyAdded", NULL, false);
222 }
223 }
224
225 // Set update interval
226 if ( update_interval <= 0 )
227 update_interval = DEFAULT_UPDATE_INTERVAL;
228
229 SetUpdateInterval( update_interval );
230
231 // If energyAtSpawn is present, then use its value for energyStorageMax if that cfg param is not present (for convenience's sake)
232 string cfg_check_energy_limit = cfg_energy_manager + "energyStorageMax";
233
234 if ( !GetGame().ConfigIsExisting (cfg_check_energy_limit) && m_Energy > 0 )
235 {
237 }
238
239 // Fill m_CompatiblePlugTypes
240 string cfg_check_plug_types = cfg_energy_manager + "compatiblePlugTypes";
241
242 if ( GetGame().ConfigIsExisting (cfg_check_plug_types) )
243 {
245 GetGame().ConfigGetIntArray(cfg_check_plug_types, m_CompatiblePlugTypes);
246 }
247
248 if (GetSocketsCount() > 0)
250
251 if ( m_CordLength < 0 )
252 {
253 m_CordLength = 0;
254 string error_message_cord = "Warning! " + m_ThisEntityAI.GetType() + ": config parameter 'cordLength' is less than 0! Cord length should not be negative!";
255 DPrint(error_message_cord);
256 }
257
258 if (GetSocketsCount() > 0)
259 {
261 // Prepare the m_DeviceByPlugSelection
262 string cfg_animation_sources = "cfgVehicles " + m_ThisEntityAI.GetType() + " " + "AnimationSources ";
263 int animation_sources_count = GetGame().ConfigGetChildrenCount(cfg_animation_sources);
264
265 for (int i_selection = 0; i_selection < animation_sources_count; i_selection++)
266 {
267 // TO DO: This could be optimized so not all selections on item are considered as plug/socket selections.
268 string selection;
269 GetGame().ConfigGetChildName(cfg_animation_sources, i_selection, selection);
270 m_DeviceByPlugSelection.Set(selection, NULL);
271 }
272 }
273
274
275
276 // Prepare sockets
278 {
280 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!";
281 DPrint(error_message_sockets);
282 }
283
284 m_Sockets[MAX_SOCKETS_COUNT]; // Handles selections for plugs in the sockets. Feel free to change the limit if needed.
285
286 GetGame().ConfigGetText(cfg_energy_manager + "cordTextureFile", m_CordTextureFile);
287
288 if ( switch_on )
289 {
290 SwitchOn();
291 }
292
293 for ( int i = 0; i <= GetSocketsCount(); ++i )
294 {
295 m_ThisEntityAI.HideSelection ( SOCKET_ + i.ToString() + _PLUGGED );
296 }
297
298 // Show/hide inventory sockets
300 if ( GetSocketsCount() > 0 && IsPlugCompatible(PLUG_COMMON_APPLIANCE) && m_ThisEntityAI.GetType() != "MetalWire" ) // metal wire filter is hopefully temporal.
301 {
303 }
304
306
307 m_ThisEntityAI.HideSelection( SEL_CORD_PLUGGED );
308
309
310 #ifdef DIAG_DEVELOPER
311 GetGame().m_EnergyManagerArray.Insert( this );
312 #endif
313 }
314
315 // Returns the type of this component
316 override int GetCompType()
317 {
319 }
320
321 // When the object is deleted
323 {
324 bool was_working = m_ThisEntityAI.GetCompEM().IsWorking();
325
326 SwitchOff();
328 UnplugThis();
329 SetPowered( false );
330
331 if ( was_working )
332 m_ThisEntityAI.OnWorkStop();
333 ;
334 }
335
336 //Restart the debug timer when relogging
338 {
339 if ( m_DebugPlugs )
340 {
341 if ( !m_DebugUpdate )
343
344 if ( !m_DebugUpdate.IsRunning() )
345 m_DebugUpdate.Run(0.01, this, "DebugUpdate", NULL, true);
346 }
347 else
348 {
349 if ( m_DebugPlugArrow )
350 {
351 m_DebugPlugArrow.Destroy();
352 m_DebugPlugArrow = NULL;
353 }
354 }
355 }
356
358 {
359 return m_DebugPlugs;
360 }
361
362 void SetDebugPlugs( bool newVal )
363 {
364 m_DebugPlugs = newVal;
365 RefreshDebug();
366 }
367
368 //======================================================================================
369 // PUBLIC FUNCTIONS
370 // Use these to control the Energy Manager
371 // Functions are in order of their return value: void, bool, int, float, string, array.
372 //======================================================================================
373
375 void SwitchOn()
376 {
378
379 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
380 {
381 if ( CanSwitchOn() )
382 {
383 m_IsSwichedOn = true;
384 Synch();
385
386 DeviceUpdate(); // 'Wake up' this device now
387 StartUpdates();
388
389 // 'Wakes up' all connected devices
391
393
394 // Call event
395 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOn", NULL, 0);
396 }
397 }
398
399 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.)
400 {
401 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOn", NULL, 0);
402 }
403 }
404
407 {
409
410 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
411 {
412 if ( CanSwitchOff() )
413 {
414 m_IsSwichedOn = false;
415 Synch();
416
417 if ( IsWorking() )
418 {
419 StopUpdates();
420 DeviceUpdate();
421 }
422
423 // 'Wakes up' all connected devices
425
427
428 // Call event
429 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOff", NULL, 0);
430 }
431 }
432
433 if ( !GetGame().IsServer() && GetGame().IsMultiplayer() )
434 {
435 m_IsSwichedOn = false;
436 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOff", NULL, 0);
437 }
438 }
439
441 void SetPassiveState(bool state = true)
442 {
443 m_IsPassiveDevice = state;
444 if ( !m_IsPassiveDevice )
445 {
446 DeviceUpdate();
447 }
448 }
449
451 void UnplugDevice(EntityAI device_to_unplug)
452 {
453 if ( GetGame() )
454 {
455 int indexStart = GetPluggedDevicesCount() - 1;
456 bool deviceFound = false;
457
458 for (int i = indexStart; i >= 0; --i)
459 {
460 EntityAI plugged_device = GetPluggedDevices().Get(i);
461
462 if (plugged_device == device_to_unplug)
463 {
464 GetPluggedDevices().Remove(i);
465 deviceFound = true;
466 break;
467 }
468 }
469
470 if (deviceFound)
471 {
472 int socket_ID = device_to_unplug.GetCompEM().GetMySocketID();
473 UnplugCordFromSocket(socket_ID);
474 device_to_unplug.GetCompEM().SetEnergySource(null);
475 device_to_unplug.GetCompEM().DeviceUpdate();
476 device_to_unplug.GetCompEM().StartUpdates();
477 device_to_unplug.GetCompEM().WakeUpWholeBranch(m_ThisEntityAI);
478
480 {
481 m_DebugPlugArrow.Destroy();
482 m_DebugPlugArrow = null;
483 }
484
485 OnOwnSocketReleased(device_to_unplug);
486 device_to_unplug.GetCompEM().OnIsUnplugged(m_ThisEntityAI);
487 device_to_unplug.ShowSelection(SEL_CORD_FOLDED);
488 device_to_unplug.HideSelection(SEL_CORD_PLUGGED);
489 }
490 }
491 }
492
495 {
496 if (GetGame())
497 {
498 if (GetEnergySource())
499 {
500 GetEnergySource().GetCompEM().UnplugDevice(m_ThisEntityAI);
501 }
502 }
503 }
504
507 {
508 if ( GetPluggedDevices() ) // This check is necesarry in case this function is called before initialization
509 {
510 int indexStart = GetPluggedDevicesCount() - 1;
511 for (int i = indexStart; i >= 0; --i)
512 {
514 }
515 }
516 }
517
518 // Used only for storing of the plug's state through server restart
519 void RestorePlugState(bool state)
520 {
521 m_RestorePlugState = state;
522 }
523
525 void SetEnergy(float new_energy)
526 {
527 if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // Client can't change energy value.
528 {
529 m_ThisEntityAI.SetWeightDirty();
530 float old_energy = m_Energy;
531 m_Energy = new_energy;
532
533 if ( old_energy - GetEnergyUsage() <= 0 || (old_energy != new_energy && Math.Min(old_energy,new_energy) <= 0) )
534 {
536 }
537 }
538 }
539
541 void SetEnergy0To1(float energy01)
542 {
543 SetEnergy( Math.Lerp(0, GetEnergyMax(),energy01));
544 }
545
548 {
549 // Lets update sockets, if there are any
550 int slots_c = GetSocketsCount();
551
552 for ( int i = 0; i < slots_c; ++i )
553 {
554 EntityAI plug_owner = GetDeviceBySocketID(i);
555
556 if ( plug_owner )
557 {
558 string plugged_selection = SOCKET_ + (i+1).ToString() + _PLUGGED;
559 string available_selection = SOCKET_ + (i+1).ToString() + _AVAILABLE;
560 m_ThisEntityAI.ShowSelection ( plugged_selection );
561 m_ThisEntityAI.HideSelection ( available_selection );
562 string texture_path = plug_owner.GetCompEM().GetCordTextureFile();
563 int selection_index = m_ThisEntityAI.GetHiddenSelectionIndex( plugged_selection );
564 m_ThisEntityAI.SetObjectTexture(selection_index, texture_path );
565 }
566 else
567 {
568 m_ThisEntityAI.ShowSelection ( SOCKET_ + (i+1).ToString() + _AVAILABLE );
569 m_ThisEntityAI.HideSelection ( SOCKET_ + (i+1).ToString() + _PLUGGED );
570 }
571 }
572
573 // Now lets update the cord/plug state
574 if ( GetEnergySource() )
575 {
576 m_ThisEntityAI.ShowSelection ( SEL_CORD_PLUGGED );
577 m_ThisEntityAI.HideSelection ( SEL_CORD_FOLDED );
578 }
579 else
580 {
581 m_ThisEntityAI.ShowSelection ( SEL_CORD_FOLDED );
582 m_ThisEntityAI.HideSelection ( SEL_CORD_PLUGGED );
583 }
584 }
585
588 {
589 if (m_ThisEntityAI.GetCompEM().GetEnergySource())
590 {
591 EntityAI player = m_ThisEntityAI.GetHierarchyRootPlayer();
592 // Check if the item is held in hands during advanced placement
593 if (player)
594 {
595 // Measure distance from the player
596 vector playerPosition = player.GetPosition();
597 if (!IsEnergySourceAtReach(playerPosition, 5))
598 UnplugThis();
599 }
600 else
601 {
602 // Measure distance from the device
603 vector itemPosition = m_ThisEntityAI.GetPosition();
604
605 if (m_ThisEntityAI.GetHierarchyParent())
606 itemPosition = m_ThisEntityAI.GetHierarchyParent().GetPosition();
607
608 if (!IsEnergySourceAtReach(itemPosition))
609 UnplugThis();
610 }
611 }
612 }
613
614 // Returns an array of plug types this device can accept
616 {
618 }
619
620 // Stores IDs of the energy source.
621 void StoreEnergySourceIDs(int b1, int b2, int b3, int b4)
622 {
627 }
628
630 void SetEnergyMaxPristine(float new_limit)
631 {
632 m_EnergyStorageMax = new_limit;
633 }
634
636 void SetCordLength( float new_length )
637 {
638 m_CordLength = new_length;
639 }
640
641 // Sets the plug type (for plug -> socket compatibility checks).
642 void SetPlugType( int new_type )
643 {
644 m_PlugType = new_type;
645 }
646
647 // Sets the new attachment action type.
648 void SetAttachmentAction( int new_action_type )
649 {
650 m_AttachmentActionType = new_action_type;
651 }
652
654 void SetEnergyUsage( float new_usage )
655 {
656 m_EnergyUsage = new_usage;
657 }
658
661 {
662 string cfg_energy_usage = "CfgVehicles " + m_ThisEntityAI.GetType() + " EnergyManager ";
663 m_EnergyUsage = GetGame().ConfigGetFloat (cfg_energy_usage + "energyUsagePerSecond");
664 }
665
666 // Sets path to the cord texture file.
667 void SetCordTextureFile( string new_path )
668 {
669 m_CordTextureFile = new_path;
670 }
671
672 // Sets energy source. Intended to be called only on client through RPC.
674 {
675 SetEnergySource(source);
676 }
677
679 void SetDeviceBySocketID(int id, EntityAI plugged_device)
680 {
681 m_Sockets[id] = plugged_device;
682 }
683
684
686 void SetElectricityIconVisibility( bool make_visible )
687 {
688 m_HasElectricityIcon = make_visible;
689 }
690
691 // 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.
693 {
694 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
695 {
696 bool current_state = CanWork();
697
698 if (current_state != m_CanWork)
699 {
700 m_CanWork = current_state;
701 Synch();
702
703 if ( m_ThisEntityAI && m_ThisEntityAI.GetHierarchyParent() && m_ThisEntityAI.GetHierarchyParent().GetCompEM() )
704 {
705 m_ThisEntityAI.GetHierarchyParent().GetCompEM().UpdateCanWork();
706 }
707 }
708 }
709 }
710
712 {
714 {
715 if (IsSwitchedOn())
716 {
717 SwitchOff();
718 }
719 }
720 }
721
723 void SetUpdateInterval( float value )
724 {
725 m_UpdateInterval = value;
726 }
727
728 // Returns true if this device was plugged into something at the end of previous session
730 {
731 return m_RestorePlugState;
732 }
733
735 bool PlugThisInto(EntityAI energy_source, int socket_id = -1)
736 {
737 return energy_source.GetCompEM().PlugInDevice(m_ThisEntityAI, socket_id);
738 }
739
742 {
743 if ( !IsSwitchedOn() )
744 {
745 return true;
746 }
747
748 return false;
749 }
750
751
757 bool CanWork( float test_energy = -1)
758 {
759 if ( GetGame().IsMultiplayer() && GetGame().IsClient() )
760 {
761 return m_CanWork;
762 }
763
764 if (!m_ThisEntityAI || m_ThisEntityAI.IsRuined())
765 {
766 return false;
767 }
768
769 // Check if the power source(s) (which can be serially connected) can provide needed energy.
770 float energy_usage = test_energy;
771 float gathered_energy = GetEnergy();
772 EntityAI energy_source = GetEnergySource();
773
774 if (energy_usage == -1)
775 {
776 energy_usage = GetEnergyUsage();
777 }
778
779 if ( !CheckWetness() )
780 {
781 return false;
782 }
783
784 if (gathered_energy <= 0 && energy_usage <= 0) //empty power source
785 {
786 return false;
787 }
788
789 int cycle_limit = 500; // Sanity check to definitely avoid infinite cycles
790
791 while ( gathered_energy < energy_usage ) // Look for energy source if we don't have enough stored energy
792 {
793 // Safetycheck!
794 if (cycle_limit > 0)
795 {
796 cycle_limit--;
797 }
798 else
799 {
800 DPrint("Energy Manager ERROR: The 'cycle_limit' safety break had to be activated to prevent possible game freeze. Dumping debug information...");
801 //Print(m_ThisEntityAI);
802 //Print(this);
803 //Print(energy_source);
804
805 if (energy_source.GetCompEM())
806 {
807 //Print(energy_source.GetCompEM());
808 }
809
810 //Print(gathered_energy);
811 //Print(energy_usage);
812
813 //Print(m_ThisEntityAI.GetPosition());
814
815 if (energy_source)
816 {
817 //Print(energy_source.GetPosition());
818 }
819
820 //Print("End of the 'cycle_limit' safety break ^ ");
821
822 return false;
823 }
824 // ^ Safetycheck!
825
826 if ( energy_source && energy_source != m_ThisEntityAI && !energy_source.IsRuined() && energy_source.GetCompEM() && energy_source.GetCompEM().IsSwitchedOn() && energy_source.GetCompEM().CheckWetness() )
827 {
828 gathered_energy = gathered_energy + energy_source.GetCompEM().GetEnergy();
829 energy_source = energy_source.GetCompEM().GetEnergySource();
830 }
831 else
832 {
833 // No power source, no energy.
834 return false;
835 }
836 }
837
838 // Enough energy was found
839 return true;
840 }
841
844 {
845 return (m_ThisEntityAI.GetWet() <= 1-m_WetnessExposure);
846 }
847
850 {
851 if ( IsPassive() )
852 {
853 return false;
854 }
855
856 return IsSwitchedOn();
857 }
858
859 // Returns previous state of the switch.
864
867 {
868 return m_IsSwichedOn;
869 }
870
873 {
874 if ( IsPlugged() )
875 return false;
876
877 return true;
878 }
879
882 {
883 return m_IsPassiveDevice;
884 }
885
888 {
889 return m_IsPlugged;
890 }
891
892
894 bool ConsumeEnergy(float amount)
895 {
896 return FindAndConsumeEnergy(m_ThisEntityAI, amount, true);
897 }
898
901 {
902 return m_IsWorking;
903 }
904
907 {
908 if ( GetEnergy() > GetEnergyUsage() )
909 {
910 return true;
911 }
912
913 return false;
914 }
915
917 bool HasFreeSocket( int socket_id = -1 )
918 {
919 if (socket_id == -1)
920 {
921 int plugged_devices = GetPluggedDevicesCount();
922 int plugged_devices_limit = GetSocketsCount();
923
924 if ( plugged_devices < plugged_devices_limit )
925 {
926 return true;
927 }
928
929 return false;
930 }
931 else
932 {
933 EntityAI device = GetDeviceBySocketID(socket_id);
934
935 if (device)
936 {
937 return false;
938 }
939 else
940 {
941 return true;
942 }
943 }
944 }
945
947 bool IsPlugCompatible(int plug_ID)
948 {
949 if ( plug_ID == PLUG_UNDEFINED )
950 {
951 return true; // When plugType is undefined in config then make it compatible.
952 }
953
955 {
956 for ( int i = 0; i < m_CompatiblePlugTypes.Count(); i++ )
957 {
958 int plug_ID_to_Check = m_CompatiblePlugTypes.Get(i);
959
960 if ( plug_ID_to_Check == plug_ID )
961 {
962 return true;
963 }
964 }
965 }
966 else
967 {
968 // Since the config parameter compatiblePlugTypes is not present, then accept all plugs for simplicity's sake
969 return true;
970 }
971
972 return false;
973 }
974
976 bool CanReceivePlugFrom( EntityAI device_to_plug )
977 {
978 // The following conditions are broken down for the sake of easier reading/debugging.
979
980 if ( HasFreeSocket() && device_to_plug != m_ThisEntityAI)
981 {
982 if ( device_to_plug.GetCompEM().GetEnergySource() != m_ThisEntityAI)
983 {
984 if ( IsPlugCompatible(device_to_plug.GetCompEM().GetPlugType()) )
985 {
986 if ( device_to_plug.GetCompEM().IsEnergySourceAtReach( device_to_plug.GetPosition(), 0, m_ThisEntityAI.GetPosition() ) )
987 {
988 return true;
989 }
990 }
991 }
992 }
993
994 return false;
995 }
996
998 bool CanBePluggedInto( EntityAI potential_energy_provider )
999 {
1000 return potential_energy_provider.GetCompEM().CanReceivePlugFrom( m_ThisEntityAI );
1001 }
1002
1005 {
1006 return m_HasElectricityIcon;
1007 }
1008
1014
1031 bool IsEnergySourceAtReach( vector from_position, float add_tolerance = 0, vector override_source_position = "-1 -1 -1" )
1032 {
1033 if ( !IsPlugged() && override_source_position == "-1 -1 -1" )
1034 {
1035 return false;
1036 }
1037
1038 if ( GetCordLength() == 0 ) // 0 is an exception, which means infinitely long cable.
1039 {
1040 return true;
1041 }
1042
1043 vector source_pos;
1044 float distance;
1045
1046 if ( override_source_position == "-1 -1 -1" )
1047 {
1048 EntityAI energy_source = GetEnergySource();
1049
1050 if (!energy_source)
1051 return false;
1052
1053 source_pos = energy_source.GetPosition();
1054 distance = vector.Distance( from_position, source_pos );
1055 }
1056 else
1057 {
1058 source_pos = override_source_position;
1059 distance = vector.Distance( from_position, source_pos );
1060 }
1061
1062 if (distance > GetCordLength() + add_tolerance)
1063 {
1064 return false;
1065 }
1066 else
1067 {
1068 return true;
1069 }
1070 }
1071
1076
1078 bool IsSelectionAPlug(string selection_to_test )
1079 {
1080 if ( GetPluggedDevices() )
1081 {
1082 int socket_count = GetSocketsCount();
1083
1084 for ( int i = socket_count; i >= 0; --i )
1085 {
1086 string real_selection = SOCKET_ + i.ToString() +_PLUGGED;
1087
1088 if ( selection_to_test == real_selection)
1089 {
1090 return true;
1091 }
1092 }
1093 }
1094
1095 return false;
1096 }
1097
1098
1099
1100
1103 {
1104 return m_SocketsCount;
1105 }
1106
1109 {
1110 return m_PlugType;
1111 }
1112
1113 // Returns the action ID which is supposed to be done upon receiving an attachment
1115 {
1117 }
1118
1119 // Returns persistent ID (block 1) of the energy source
1124
1125 // Returns persistent ID (block 2) of the energy source
1130
1131 // Returns persistent ID (block 3) of the energy source
1136
1137 // Returns persistent ID (block 4) of the energy source
1142
1143 // Returns network ID (low) of the energy source
1148
1149 // Returns network ID (high) of the energy source
1154
1157 {
1158 if ( GetPluggedDevices() )
1159 {
1160 return GetPluggedDevices().Count();
1161 }
1162
1163 return 0;
1164 }
1165
1168 {
1169 if ( m_EnergyStorageMax > 0 )
1170 {
1171 int coef = Math.Round( m_Energy / m_EnergyStorageMax * 100 );
1172 return coef;
1173 }
1174
1175 return 0;
1176 }
1177
1180 {
1181 if ( m_EnergyStorageMax > 0 )
1182 {
1184 }
1185
1186 return 0;
1187 }
1188
1191 {
1192 #ifdef DIAG_DEVELOPER
1193 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_CONSUMPTION) || (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_RECHARGE)))
1194 {
1195 return 1;//when modifying time accel, we might want to see things happen when they should, instead of waiting for the next tick
1196 }
1197 #endif
1198 return m_UpdateInterval;
1199 }
1200
1203 {
1204 return m_WetnessExposure;
1205 }
1206
1209 {
1210 return m_EnergyUsage;
1211 }
1212
1215 {
1216 return m_Energy;
1217 }
1218
1220 float AddEnergy(float added_energy)
1221 {
1222 if (added_energy != 0)
1223 {
1224 //Print("AddEnergy ---------> " + added_energy + " " + this + " " +m_ThisEntityAI.ClassName());
1225 #ifdef DIAG_DEVELOPER
1226 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_CONSUMPTION) && added_energy < 0)
1227 {
1228 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
1229 added_energy *= timeAccel;
1230 }
1231 #endif
1232
1233 bool energy_was_added = (added_energy > 0);
1234
1235 float energy_to_clamp = GetEnergy() + added_energy;
1236 float clamped_energy = Math.Clamp( energy_to_clamp, 0, GetEnergyMax() );
1237 SetEnergy(clamped_energy);
1238 StartUpdates();
1239
1240 if (energy_was_added)
1241 OnEnergyAdded();
1242 else
1244
1245 return energy_to_clamp - clamped_energy;
1246 }
1247
1248 return 0;
1249 }
1250
1253 {
1254 float max_health = 0;
1255
1256 if ( m_ThisEntityAI.HasDamageSystem() )
1257 max_health = m_ThisEntityAI.GetMaxHealth("","");
1258 //else if ( m_ReduceMaxEnergyByDamageCoef != 0 )
1259 // Error("[ERROR] ReduceMaxEnergyByDamageCoef is setup but " + m_ThisEntityAI.GetType() + " does not have a Damage System");
1260
1261 if ( max_health == 0 || m_ReduceMaxEnergyByDamageCoef == 0 )
1262 return GetEnergyMaxPristine();
1263
1264 float health = 100;
1265
1266 if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // TO DO: Remove this IF when method GetHealth can be called on client!
1267 health = m_ThisEntityAI.GetHealth("","");
1268
1269 float damage_coef = 1 - (health / max_health);
1270
1271 return GetEnergyMaxPristine() * (1 - ( damage_coef * m_ReduceMaxEnergyByDamageCoef ) );
1272 }
1273
1276 {
1277 return m_EnergyStorageMax;
1278 }
1279
1281 {
1282 return m_EnergyAtSpawn;
1283 }
1284
1287 {
1288 return m_CordLength;
1289 }
1290
1293 {
1294 return m_EnergySource;
1295 }
1296
1299 {
1300 return m_Sockets[id];
1301 }
1302
1304 EntityAI GetPlugOwner(string plug_selection_name)
1305 {
1306 if ( m_DeviceByPlugSelection && m_DeviceByPlugSelection.Contains(plug_selection_name) )
1307 {
1308 return m_DeviceByPlugSelection.Get(plug_selection_name);
1309 }
1310
1311 return NULL;
1312 }
1313
1316 {
1317 if ( GetPluggedDevicesCount() > 0 )
1318 {
1319 return GetPluggedDevices().Get(0);
1320 }
1321
1322 return NULL;
1323 }
1324
1327 {
1328 return m_CordTextureFile;
1329 }
1330
1336
1339 {
1340 array<EntityAI> return_array = new array<EntityAI>;
1341 int plugged_devices_c = GetPluggedDevicesCount();
1342 for ( int i = 0; i < plugged_devices_c; ++i )
1343 {
1344 EntityAI device = GetPluggedDevices().Get(i);
1345 if ( IsSwitchedOn() )
1346 {
1347 return_array.Insert(device);
1348 }
1349 }
1350
1351 return return_array;
1352 }
1353
1354
1355 /*===================================
1356 PUBLIC EVENTS
1357 ===================================*/
1358
1359 // Called every device update if its supposed to do some work. The update can be every second or at random, depending on its manipulation.
1360 void OnWork( float consumed_energy )
1361 {
1362 m_ThisEntityAI.OnWork(consumed_energy);
1363 }
1364
1365 // Called when this device is plugged into some energy source
1366 void OnIsPlugged(EntityAI source_device)
1367 {
1368 if (m_DebugPlugs)
1369 {
1370 if (!m_DebugUpdate)
1372
1373 if (!m_DebugUpdate.IsRunning())
1374 m_DebugUpdate.Run(0.01, this, "DebugUpdate", NULL, true);
1375 }
1376
1377 UpdateCanWork();
1378 m_ThisEntityAI.OnIsPlugged(source_device);
1379 }
1380
1381 // Called when this device is UNPLUGGED from the energy source
1382 void OnIsUnplugged( EntityAI last_energy_source )
1383 {
1384 UpdateCanWork();
1385 m_ThisEntityAI.OnIsUnplugged( last_energy_source );
1386 }
1387
1388 // When something is plugged into this device
1390 {
1391 //play sound
1392 if ( device.GetCompEM().GetPlugType() == PLUG_COMMON_APPLIANCE && m_ThisEntityAI.IsInitialized() )
1393 {
1394 EffectSound sound_plug;
1395 m_ThisEntityAI.PlaySoundSet( sound_plug, "cablereel_plugin_SoundSet", 0, 0 );
1396 }
1397
1398 m_ThisEntityAI.OnOwnSocketTaken(device);
1399 }
1400
1401 // When something is UNPLUGGED from this device
1403 {
1404 //play sound
1405 if ( device.GetCompEM().GetPlugType() == PLUG_COMMON_APPLIANCE && m_ThisEntityAI.IsInitialized() )
1406 {
1407 EffectSound sound_unplug;
1408 m_ThisEntityAI.PlaySoundSet( sound_unplug, "cablereel_unplug_SoundSet", 0, 0 );
1409 }
1410
1411 m_ThisEntityAI.OnOwnSocketReleased( device );
1412 }
1413
1414
1415 // Handles automatic attachment action
1416 void OnAttachmentAdded(EntityAI elec_device)
1417 {
1418 int attachment_action_type = GetAttachmentAction();
1419
1420 if ( attachment_action_type == PLUG_THIS_INTO_ATTACHMENT )
1421 {
1422 if ( elec_device.GetCompEM().CanReceivePlugFrom( m_ThisEntityAI ) )
1423 {
1424 PlugThisInto(elec_device);
1425 }
1426 }
1427 else if ( attachment_action_type == PLUG_ATTACHMENTS_INTO_THIS )
1428 {
1429 elec_device.GetCompEM().PlugThisInto(m_ThisEntityAI);
1430 }
1431 }
1432
1433 // Handles automatic detachment action
1435 {
1436 int attachment_action_type = GetAttachmentAction();
1437
1438 if ( attachment_action_type == PLUG_THIS_INTO_ATTACHMENT )
1439 {
1440 if ( elec_device == GetEnergySource() )
1441 {
1442 UnplugThis();
1443 }
1444 }
1445 else if ( attachment_action_type == PLUG_ATTACHMENTS_INTO_THIS )
1446 {
1447 elec_device.GetCompEM().UnplugThis();
1448 }
1449 }
1450
1451 // Starts the device's main cycle
1453 {
1454 if (!m_IsPassiveDevice)
1455 {
1456 if (!m_UpdateTimer)
1458
1459 if (!m_UpdateTimer.IsRunning()) // Makes sure the timer is NOT running already
1460 {
1461 m_UpdateTimer.Run(GetUpdateInterval(), this, "DeviceUpdate", null, true);
1462 }
1463 }
1464 }
1465
1468 {
1469 m_ThisEntityAI.OnEnergyConsumed();
1470 }
1471
1474 {
1476 {
1477 m_UpdateQuantityTimer.Stop();
1478 m_UpdateQuantityTimer = NULL;
1479 }
1480
1481 m_ThisEntityAI.OnEnergyAdded();
1482 }
1483
1484
1485 /*===================================
1486 PROTECTED FUNCTIONS
1487 ===================================*/
1488
1489 // Stops the device's main cycle
1490 protected void StopUpdates()
1491 {
1492 if (m_UpdateTimer)
1493 {
1494 m_UpdateTimer.Stop();
1495 m_UpdateTimer = NULL; // Delete timer from memory
1496 }
1497 }
1498
1502 void InteractBranch(EntityAI originalCaller, Man player = null, int system = 0)
1503 {
1504 OnInteractBranch(originalCaller, player, system);
1505 if ( GetSocketsCount() > 0 )
1506 {
1508
1509 foreach ( EntityAI device : devices)
1510 {
1511 if ( device != originalCaller ) // originalCaller check here prevents infinite loops
1512 {
1513 device.GetCompEM().InteractBranch( originalCaller, player, system );
1514 }
1515 }
1516 }
1517 }
1518
1520 protected void OnInteractBranch(EntityAI originalCaller, Man player, int system)
1521 {
1522 m_ThisEntityAI.IncreaseLifetime();
1523
1524 }
1525
1526 // 'Wakes up' all devices down the network so they start working, if they have enough power, and are switched ON
1527 protected void WakeUpWholeBranch( EntityAI original_caller )
1528 {
1529 if ( GetSocketsCount() > 0 )
1530 {
1531 array<EntityAI> plugged_devices = GetPluggedDevices();
1532 int plugged_devices_c = plugged_devices.Count();
1533
1534 for ( int i = 0; i < plugged_devices_c; ++i )
1535 {
1536 EntityAI device = plugged_devices.Get(i);
1537 if ( device != original_caller ) // original_caller check here prevents infinite loops
1538 {
1539 device.GetCompEM().UpdateCanWork();
1540 device.GetCompEM().DeviceUpdate();
1541 device.GetCompEM().StartUpdates();
1542 device.GetCompEM().WakeUpWholeBranch( original_caller );
1543 }
1544 }
1545 }
1546 }
1547
1548 // Finds an available socket and plugs the given device into it.
1549 // This is mainly about visualisation.
1550 protected void PlugCordIntoSocket( EntityAI device_to_plug, int socket_id = -1 )
1551 {
1552 if (socket_id >= 0)
1553 {
1554 EntityAI plug_owner_by_socket = GetDeviceBySocketID(socket_id);
1555
1556 if (!plug_owner_by_socket)
1557 {
1558 UpdateSocketSelections(socket_id, device_to_plug);
1559 return;
1560 }
1561 }
1562
1563 int slots_c = GetSocketsCount();
1564
1565 for ( int i = 0; i < slots_c; ++i )
1566 {
1567 EntityAI plug_owner = GetDeviceBySocketID(i);
1568
1569 if ( !plug_owner ) // Check if this socket is available
1570 {
1571 UpdateSocketSelections(i, device_to_plug);
1572 break;
1573 }
1574 }
1575 }
1576
1577 // Updates socket selections (plugged/unplugged) of the given ID and sets color texture of the plug.
1578 protected void UpdateSocketSelections(int socket_id, EntityAI device_to_plug)
1579 {
1580 SetDeviceBySocketID(socket_id, device_to_plug);
1581
1582 string plugged_selection = SOCKET_ + (socket_id+1).ToString() + _PLUGGED;
1583 SetPlugOwner( plugged_selection, device_to_plug );
1584 m_ThisEntityAI.ShowSelection ( plugged_selection );
1585
1586 string unplugged_selection = SOCKET_ + (socket_id+1).ToString() + _AVAILABLE;
1587 m_ThisEntityAI.HideSelection ( unplugged_selection );
1588 string texture_path = device_to_plug.GetCompEM().GetCordTextureFile();
1589 int selection_index = m_ThisEntityAI.GetHiddenSelectionIndex( plugged_selection );
1590 m_ThisEntityAI.SetObjectTexture( selection_index, texture_path );
1591 device_to_plug.GetCompEM().SetMySocketID(socket_id);
1592 }
1593
1594
1595 // Sets energy source for this device
1596 protected void SetEnergySource( EntityAI source )
1597 {
1598 m_EnergySource = source;
1599
1600 if (source)
1601 {
1602 m_IsPlugged = true;
1603 StartUpdates();
1604 }
1605 else
1606 {
1607 m_IsPlugged = false;
1610 }
1611
1612 if (m_EnergySource)
1614
1615 Synch();
1616 }
1617
1618 // Plugs the given device into this one
1619 protected bool PlugInDevice(EntityAI device_to_plug, int socket_id = -1)
1620 {
1621 if (CanReceivePlugFrom(device_to_plug))
1622 {
1623 device_to_plug.IncreaseLifetime();
1625 if (device_to_plug.GetCompEM().IsPlugged())
1626 device_to_plug.GetCompEM().UnplugThis();
1627
1628 GetPluggedDevices().Insert(device_to_plug);
1629 device_to_plug.GetCompEM().SetEnergySource(m_ThisEntityAI);
1630
1631 PlugCordIntoSocket(device_to_plug, socket_id); // Visualisation
1632 OnOwnSocketTaken(device_to_plug);
1633
1634 device_to_plug.GetCompEM().OnIsPlugged(m_ThisEntityAI);
1636
1637 if (GetGame().IsServer() || !GetGame().IsMultiplayer())
1638 {
1639 device_to_plug.HideSelection(SEL_CORD_FOLDED);
1640 device_to_plug.ShowSelection(SEL_CORD_PLUGGED);
1641 }
1642
1643 return true;
1644 }
1645
1646 return false;
1647 }
1648
1649 // Sets the device to which the given plug selection belongs to
1650 protected void SetPlugOwner(string selection_name, EntityAI device)
1651 {
1652 if ( m_DeviceByPlugSelection.Contains(selection_name) )
1653 {
1654 m_DeviceByPlugSelection.Set(selection_name, device);
1655 }
1656 }
1657
1658 // Frees the given socket.
1659 // This is only about visualisation.
1660 protected void UnplugCordFromSocket( int socket_to_unplug_ID )
1661 {
1662 EntityAI plug_owner = GetDeviceBySocketID(socket_to_unplug_ID);
1663
1664 if ( plug_owner )
1665 {
1666 SetDeviceBySocketID(socket_to_unplug_ID, NULL);
1667 string unplugged_selection = SOCKET_ + (socket_to_unplug_ID+1).ToString() + _AVAILABLE;
1668 m_ThisEntityAI.ShowSelection ( unplugged_selection );
1669
1670 string plugged_selection = SOCKET_ + (socket_to_unplug_ID+1).ToString() + _PLUGGED;
1671 m_ThisEntityAI.HideSelection ( plugged_selection );
1672 SetPlugOwner( plugged_selection, NULL );
1673 plug_owner.GetCompEM().SetMySocketID(-1);
1674 }
1675 }
1676
1677 // Sets the state of the device
1678 protected void SetPowered( bool state )
1679 {
1680 m_IsWorking = state;
1681 }
1682
1683 // 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.
1684 protected bool FindAndConsumeEnergy(EntityAI original_caller, float amount, bool ignore_switch_state = false)
1685 {
1686 if ( (ignore_switch_state || IsSwitchedOn()) && !m_ThisEntityAI.IsRuined() )
1687 {
1688 float available_energy = AddEnergy(-amount);
1689
1690 if ( available_energy < 0 && IsPlugged() )
1691 {
1692 // 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)
1693 EntityAI next_power_source = GetEnergySource();
1694
1695 if (next_power_source && next_power_source != original_caller) // Prevents infinite loop if the power source is the original caller itself
1696 {
1697 return next_power_source.GetCompEM().FindAndConsumeEnergy( original_caller, -available_energy );
1698 }
1699 }
1700
1701 if ( available_energy >= 0)
1702 {
1703 return true;
1704 }
1705
1706 return false;
1707 }
1708 else
1709 {
1710 return false;
1711 }
1712 }
1713
1714 // Gets the socket ID this device is powered from.
1715 protected int GetMySocketID()
1716 {
1717 return m_MySocketID;
1718 }
1719
1720 // Sets the socket ID this device is plugged into.
1721 protected void SetMySocketID( int slot_ID )
1722 {
1723 m_MySocketID = slot_ID;
1724 }
1725
1726 void Synch()
1727 {
1728 m_ThisEntityAI.SetSynchDirty();
1729 }
1730
1732 {
1733 m_LastUpdateTime = 0;
1734 }
1735
1740
1742 {
1743 return GetGame().GetTime();
1744 }
1745
1746 // Updates the device's state of power. This function is visualized in the diagram at DayZ Confluence >> Camping & Squatting >> Electricity >> Energy Manager functionalities
1748 {
1749 /*
1750 vector pos = m_ThisEntityAI.GetPosition();
1751 string debug_message = "Object " + m_ThisEntityAI.GetType() + " | Energy: " + GetEnergy() + " | IsAtReach: " + (IsEnergySourceAtReach(pos)).ToString();
1752 Print(debug_message);
1753 */
1754
1755 if ( !m_IsPassiveDevice )
1756 {
1757 // 'm_ThisEntityAI' and 'this' must be checked because this method is caled from a timer
1758 if ( m_ThisEntityAI && this && IsSwitchedOn() && !m_ThisEntityAI.IsRuined() && CheckWetness() && m_CanWork && !GetGame().IsMissionMainMenu() )
1759 {
1760 bool was_powered = IsWorking();
1761 float consumed_energy_coef;
1762 // Make sure to use only as much % of energy as needed since this function can be called at random.
1763
1764 if ( m_LastUpdateTime == 0 )
1765 {
1767 consumed_energy_coef = 1.0;
1768 }
1769 else
1770 {
1771 float updatetime = GetCurrentUpdateTime();
1772 float time = updatetime - m_LastUpdateTime;
1773 consumed_energy_coef = time / 1000;
1774 }
1775
1776 if (consumed_energy_coef > 0) // Prevents calling of OnWork events when no energy is consumed
1777 {
1779 float consume_energy = GetEnergyUsage() * consumed_energy_coef;
1780 bool has_consumed_enough = true;
1781
1782 if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // single player or server side multiplayer
1783 has_consumed_enough = ConsumeEnergy( consume_energy );
1784
1785 SetPowered( has_consumed_enough );
1786
1787 if ( has_consumed_enough )
1788 {
1789 if ( !was_powered )
1790 {
1791 m_CanStopWork = true;
1793 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStart", NULL, 0);
1794 UpdateCanWork();
1795 }
1796
1797 OnWork( consume_energy );
1798 }
1799 else
1800 {
1801 if ( was_powered )
1802 {
1803 if (m_CanStopWork)
1804 {
1805 m_CanStopWork = false;
1807 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStop", NULL, 0); // This event is called only once when the device STOPS being powered
1808 UpdateCanWork();
1809
1810 if (m_AutoSwitchOff)
1811 {
1812 SwitchOff();
1813 }
1814 }
1815 }
1816
1817 StopUpdates();
1818 }
1819 }
1820 else
1821 {
1823 }
1824 }
1825 else if (this && m_ThisEntityAI)
1826 {
1827 SetPowered( false );
1828 StopUpdates();
1829
1830 if (m_CanStopWork)
1831 {
1832 m_CanStopWork = false;
1834 GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStop", NULL, 0); // This event is called only once when the device STOPS being powered
1835 UpdateCanWork();
1836
1837 if (m_AutoSwitchOff)
1838 {
1839 SwitchOff();
1840 }
1841 }
1842 }
1843 }
1844 }
1845}
#define PLUG_UNDEFINED
#define PLUG_THIS_INTO_ATTACHMENT
#define PLUG_COMMON_APPLIANCE
#define PLUG_ATTACHMENTS_INTO_THIS
proto int GetTime()
returns mission time in milliseconds
static const string SEL_CORD_FOLDED
void SetElectricityIconVisibility(bool make_visible)
Energy manager: Sets visibility of the electricity icon (bolt).
void SwitchOn()
Energy manager: Switches ON the device so it starts doing its work if it has enough energy.
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 InteractBranch(EntityAI originalCaller, Man player=null, int system=0)
float GetEnergyUsage()
Energy manager: Returns the number of energy this device needs to run itself (See its config >> energ...
void OnInteractBranch(EntityAI originalCaller, Man player, int system)
Called when the player is interacting with an item containing this energy component,...
bool IsWorking()
Energy manager: Returns true if this device is working right now.
void SetEnergyMaxPristine(float new_limit)
Energy manager: Changes the maximum amount of energy this device can store (when pristine).
Shape DrawArrow(vector from, vector to, float size=0.5, int color=0xFFFFFFFF, float flags=0)
static const string _AVAILABLE
void GetCompatiblePlugTypes(out TIntArray IDs)
void SetEnergy0To1(float energy01)
Energy manager: Sets stored energy for this device between 0 and MAX based on relative input value be...
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.
void WakeUpWholeBranch(EntityAI original_caller)
void UnplugDevice(EntityAI device_to_unplug)
Energy manager: Unplugs the given device from this one.
bool CheckWetness()
Energy manager: Checks if this device is being stopped from working by its wetness level....
void SetUpdateInterval(float value)
Energy manager: Sets the interval of the OnWork(...) calls. Changing this value does not change the r...
void SetPassiveState(bool state=true)
Energy manager: Changes the status of this device. When it's passive (true), the main timer and OnWor...
bool PlugInDevice(EntityAI device_to_plug, int socket_id=-1)
void SetAttachmentAction(int new_action_type)
bool FindAndConsumeEnergy(EntityAI original_caller, float amount, bool ignore_switch_state=false)
void OnEnergyAdded()
Energy manager: Called when energy was added on this device.
void UnplugCordFromSocket(int socket_to_unplug_ID)
float AddEnergy(float added_energy)
Energy manager: Adds energy to this device and clamps it within its min/max storage limits....
void UnplugThis()
Energy manager: Unplugs this device from its power source.
int GetPluggedDevicesCount()
Energy manager: Returns the number of devices plugged into this one.
void SetCordLength(float new_length)
Energy manager: Changes the length of the virtual power cord.
void SetEnergySourceClient(EntityAI source)
void SetEnergySource(EntityAI source)
int GetEnergy0To100()
Energy manager: Returns % of stored energy this device has as integer (from 0 to 100)
void PlugCordIntoSocket(EntityAI device_to_plug, int socket_id=-1)
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...
void HandleMoveInsideCargo(EntityAI container)
float GetEnergy()
Energy manager: Returns the amount of stored energy this device has.
int GetPlugType()
Energy manager: Returns plug type. Check \DZ\data\basicDefines.hpp OR \Scripts\Classes\Component_cons...
bool CanBePluggedInto(EntityAI potential_energy_provider)
Energy manager: Returns true if this device can be plugged into the given energy source....
bool IsPlugged()
Energy manager: Returns true if this device is plugged into some other device (even if they are OFF o...
EntityAI GetEnergySource()
Energy manager: Returns the energy source this device is plugged into.
ref array< EntityAI > m_PluggedDevices
void OnAttachmentRemoved(EntityAI elec_device)
void OnWork(float consumed_energy)
array< EntityAI > GetPluggedDevices()
Energy manager: Returns an array of devices which are plugged into this one.
bool IsPassive()
Energy manager: Returns true if this device is set to be passive. False if otherwise.
bool HasConversionOfEnergyToQuantity()
Energy manager: Returns true if this item automatically converts its energy to quantity.
void StoreEnergySourceIDs(int b1, int b2, int b3, int b4)
void UpdatePlugState()
Energy manager: Unplugs this device when it's necesarry.
void OnAttachmentAdded(EntityAI elec_device)
void OnIsPlugged(EntityAI source_device)
EntityAI m_Sockets[MAX_SOCKETS_COUNT]
string GetCordTextureFile()
Energy manager: Returns path to the cord texture file.
ref map< string, EntityAI > m_DeviceByPlugSelection
bool IsSelectionAPlug(string selection_to_test)
Energy manager: Returns true if this selection is a plug that's plugged into this device....
void SetEnergy(float new_energy)
Energy manager: Sets stored energy for this device. It ignores the min/max limit!
void SetPlugOwner(string selection_name, EntityAI device)
float GetCordLength()
Energy manager: Returns the length of the virtual power cord.
EntityAI GetPlugOwner(string plug_selection_name)
Energy manager: Returns the device to which the given plug selection belongs to.
bool CanWork(float test_energy=-1)
Energy manager: Checks whenever this device can do work or not.
EntityAI GetPluggedDevice()
Energy manager: Returns a device which is plugged into this one. If there are more devices to choose ...
void UpdateSelections()
Energy manager: Shows/Hides all selections this system works with. Call this if something is wrong wi...
void OnIsUnplugged(EntityAI last_energy_source)
static const string SEL_CORD_PLUGGED
bool IsCordFolded()
Energy manager: Returns true if the cord of this device is folded. Returns false if it's plugged.
float GetEnergy0To1()
Energy manager: Returns % of stored energy this device has as float (from 0.0 to 1....
void SwitchOff()
Energy manager: Switches OFF the device.
void OnOwnSocketReleased(EntityAI device)
array< EntityAI > GetPoweredDevices()
Energy manager: Returns an array of devices which are plugged into this one and are turned on.
bool ConsumeEnergy(float amount)
Energy manager: Consumes the given amount of energy. If there is not enough of stored energy in this ...
bool CanSwitchOn()
Energy manager: Checks if the device can be switched ON.
void ResetEnergyUsage()
Energy manager: Resets energy usage to default (config) value.
bool IsPlugCompatible(int plug_ID)
Energy manager: Checks if the given plug is compatible with this device's socket. Used by CanReceiveP...
void SetEnergyUsage(float new_usage)
Energy manager: Changes the energy usage per second.
void OnEnergyConsumed()
Energy manager: Called when energy was consumed on this device.
void SetCordTextureFile(string new_path)
bool CanSwitchOff()
Energy manager: Checks if the device can be switched OFF.
int GetSocketsCount()
Energy manager: Returns the count of power sockets (whenever used or not)
void SetDeviceBySocketID(int id, EntityAI plugged_device)
Energy manager: Stores the device which is plugged into the given socket ID.
void UpdateSocketSelections(int socket_id, EntityAI device_to_plug)
float GetUpdateInterval()
Energy manager: Returns the update interval of this device.
bool HasElectricityIcon()
Energy manager: Returns true if the electricity icon (bolt) is supposed to be visible for this device...
void OnOwnSocketTaken(EntityAI 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...
EntityAI GetDeviceBySocketID(int id)
Energy manager: Returns the device which is plugged into the given socket ID.
float GetEnergyMaxPristine()
Energy manager: Returns the maximum amount of energy this device can store. It's damage is NOT taken ...
bool IsSwitchedOn()
Energy manager: Returns state of the switch. Whenever the device is working or not does not matter....
bool HasEnoughStoredEnergy()
Energy manager: Returns true if this device has enough of stored energy for its own use.
bool CanReceivePlugFrom(EntityAI device_to_plug)
Energy manager: Returns true if this device can receive power plug of the other device.
EntityAI m_ThisEntityAI
Definition component.c:24
Wrapper class for managing sound through SEffectManager.
Definition effectsound.c:5
Definition enmath.c:7
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
proto string ToString()
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
array< int > TIntArray
Definition enscript.c:711
const int CALL_CATEGORY_SYSTEM
Definition tools.c:8
override float Get()