DayZ 1.27
DayZ Explorer by KGB
 
Загрузка...
Поиск...
Не найдено
ComponentEnergyManager.c
См. документацию.
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}
const int PLUG_ATTACHMENTS_INTO_THIS
Определения _constants.c:36
const int PLUG_THIS_INTO_ATTACHMENT
Определения _constants.c:35
const int PLUG_UNDEFINED
Определения _constants.c:23
const int PLUG_COMMON_APPLIANCE
Определения _constants.c:25
map
Определения ControlsXboxNew.c:4
proto string ToString()
override float Get()
Определения PlayerStatBase.c:134
proto bool ConfigGetChildName(string path, int index, out string name)
Get name of subclass 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 int GetTime()
returns mission time in milliseconds
ScriptModule GameScript
Определения Game.c:12
proto native int ConfigGetChildrenCount(string path)
Get count of subclasses in config class on path.
EntityAI m_ThisEntityAI
Определения Component.c:24
bool m_RestorePlugState
Определения ComponentEnergyManager.c:30
static const string SEL_CORD_FOLDED
Определения ComponentEnergyManager.c:66
ref Timer m_UpdateTimer
Определения ComponentEnergyManager.c:73
float GetEnergyAtSpawn()
Определения ComponentEnergyManager.c:1280
float m_LastUpdateTime
Определения ComponentEnergyManager.c:55
void SetElectricityIconVisibility(bool make_visible)
Energy manager: Sets visibility of the electricity icon (bolt).
Определения ComponentEnergyManager.c:686
void SwitchOn()
Energy manager: Switches ON the device so it starts doing its work if it has enough energy.
Определения ComponentEnergyManager.c:375
float GetEnergyMax()
Energy manager: Returns the maximum amount of energy this device can curently store....
Определения ComponentEnergyManager.c:1252
bool GetPreviousSwitchState()
Определения ComponentEnergyManager.c:860
void UnplugAllDevices()
Energy manager: Unplugs everything directly connected to this device.
Определения ComponentEnergyManager.c:506
void SetMySocketID(int slot_ID)
Определения ComponentEnergyManager.c:1721
static const string SOCKET_
Определения ComponentEnergyManager.c:62
float m_WetnessExposure
Определения ComponentEnergyManager.c:56
void InteractBranch(EntityAI originalCaller, Man player=null, int system=0)
Определения ComponentEnergyManager.c:1502
int m_EnergySourceStorageIDb3
Определения ComponentEnergyManager.c:42
float GetEnergyUsage()
Energy manager: Returns the number of energy this device needs to run itself (See its config >> energ...
Определения ComponentEnergyManager.c:1208
void OnInteractBranch(EntityAI originalCaller, Man player, int system)
Called when the player is interacting with an item containing this energy component,...
Определения ComponentEnergyManager.c:1520
void ComponentEnergyManager()
Определения ComponentEnergyManager.c:83
int GetEnergySourceNetworkIDLow()
Определения ComponentEnergyManager.c:1144
bool IsWorking()
Energy manager: Returns true if this device is working right now.
Определения ComponentEnergyManager.c:900
int m_EnergySourceStorageIDb2
Определения ComponentEnergyManager.c:41
void SetEnergyMaxPristine(float new_limit)
Energy manager: Changes the maximum amount of energy this device can store (when pristine).
Определения ComponentEnergyManager.c:630
Shape DrawArrow(vector from, vector to, float size=0.5, int color=0xFFFFFFFF, float flags=0)
Определения ComponentEnergyManager.c:150
static const string _AVAILABLE
Определения ComponentEnergyManager.c:64
bool m_ConvertEnergyToQuantity
Определения ComponentEnergyManager.c:36
void SetDebugPlugs(bool newVal)
Определения ComponentEnergyManager.c:362
void GetCompatiblePlugTypes(out TIntArray IDs)
Определения ComponentEnergyManager.c:615
float m_EnergyAtSpawn
Определения ComponentEnergyManager.c:50
void SetEnergy0To1(float energy01)
Energy manager: Sets stored energy for this device between 0 and MAX based on relative input value be...
Определения ComponentEnergyManager.c:541
bool HasFreeSocket(int socket_id=-1)
Energy manager: Returns true if this device has any free socket to receive a plug....
Определения ComponentEnergyManager.c:917
ref Timer m_UpdateQuantityTimer
Определения ComponentEnergyManager.c:74
float GetWetnessExposure()
Returns wetness exposure value defined in config.
Определения ComponentEnergyManager.c:1202
float m_UpdateInterval
Определения ComponentEnergyManager.c:57
bool m_HasElectricityIcon
Определения ComponentEnergyManager.c:33
void WakeUpWholeBranch(EntityAI original_caller)
Определения ComponentEnergyManager.c:1527
void UnplugDevice(EntityAI device_to_unplug)
Energy manager: Unplugs the given device from this one.
Определения ComponentEnergyManager.c:451
bool CheckWetness()
Energy manager: Checks if this device is being stopped from working by its wetness level....
Определения ComponentEnergyManager.c:843
static const string _PLUGGED
Определения ComponentEnergyManager.c:63
void SetUpdateInterval(float value)
Energy manager: Sets the interval of the OnWork(...) calls. Changing this value does not change the r...
Определения ComponentEnergyManager.c:723
void SetPassiveState(bool state=true)
Energy manager: Changes the status of this device. When it's passive (true), the main timer and OnWor...
Определения ComponentEnergyManager.c:441
static bool m_DebugPlugs
Определения ComponentEnergyManager.c:21
bool PlugInDevice(EntityAI device_to_plug, int socket_id=-1)
Определения ComponentEnergyManager.c:1619
void SetAttachmentAction(int new_action_type)
Определения ComponentEnergyManager.c:648
bool FindAndConsumeEnergy(EntityAI original_caller, float amount, bool ignore_switch_state=false)
Определения ComponentEnergyManager.c:1684
ref Timer m_DebugUpdate
Определения ComponentEnergyManager.c:75
void OnEnergyAdded()
Energy manager: Called when energy was added on this device.
Определения ComponentEnergyManager.c:1473
void UnplugCordFromSocket(int socket_to_unplug_ID)
Определения ComponentEnergyManager.c:1660
float AddEnergy(float added_energy)
Energy manager: Adds energy to this device and clamps it within its min/max storage limits....
Определения ComponentEnergyManager.c:1220
const float DEFAULT_UPDATE_INTERVAL
Определения ComponentEnergyManager.c:20
int GetEnergySourceStorageIDb4()
Определения ComponentEnergyManager.c:1138
void UnplugThis()
Energy manager: Unplugs this device from its power source.
Определения ComponentEnergyManager.c:494
float GetCurrentUpdateTime()
Определения ComponentEnergyManager.c:1741
int GetPluggedDevicesCount()
Energy manager: Returns the number of devices plugged into this one.
Определения ComponentEnergyManager.c:1156
void ClearLastUpdateTime()
Определения ComponentEnergyManager.c:1731
void SetCordLength(float new_length)
Energy manager: Changes the length of the virtual power cord.
Определения ComponentEnergyManager.c:636
void SetEnergySourceClient(EntityAI source)
Определения ComponentEnergyManager.c:673
void SetEnergySource(EntityAI source)
Определения ComponentEnergyManager.c:1596
EntityAI m_EnergySource
Определения ComponentEnergyManager.c:69
int m_EnergySourceNetworkIDLow
Определения ComponentEnergyManager.c:45
int GetEnergy0To100()
Energy manager: Returns % of stored energy this device has as integer (from 0 to 100)
Определения ComponentEnergyManager.c:1167
void ~ComponentEnergyManager()
Определения ComponentEnergyManager.c:91
void PlugCordIntoSocket(EntityAI device_to_plug, int socket_id=-1)
Определения ComponentEnergyManager.c:1550
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...
Определения ComponentEnergyManager.c:1031
void HandleMoveInsideCargo(EntityAI container)
Определения ComponentEnergyManager.c:711
float GetEnergy()
Energy manager: Returns the amount of stored energy this device has.
Определения ComponentEnergyManager.c:1214
int GetPlugType()
Energy manager: Returns plug type. Check \DZ\data\basicDefines.hpp OR \Scripts\Classes\Component_cons...
Определения ComponentEnergyManager.c:1108
bool CanBePluggedInto(EntityAI potential_energy_provider)
Energy manager: Returns true if this device can be plugged into the given energy source....
Определения ComponentEnergyManager.c:998
bool IsPlugged()
Energy manager: Returns true if this device is plugged into some other device (even if they are OFF o...
Определения ComponentEnergyManager.c:887
EntityAI GetEnergySource()
Energy manager: Returns the energy source this device is plugged into.
Определения ComponentEnergyManager.c:1292
ref array< EntityAI > m_PluggedDevices
Определения ComponentEnergyManager.c:70
void OnAttachmentRemoved(EntityAI elec_device)
Определения ComponentEnergyManager.c:1434
EntityAI GetThisEntityAI()
Определения ComponentEnergyManager.c:169
void OnWork(float consumed_energy)
Определения ComponentEnergyManager.c:1360
const int MAX_SOCKETS_COUNT
Определения ComponentEnergyManager.c:77
array< EntityAI > GetPluggedDevices()
Energy manager: Returns an array of devices which are plugged into this one.
Определения ComponentEnergyManager.c:1332
float m_ReduceMaxEnergyByDamageCoef
Определения ComponentEnergyManager.c:52
int GetEnergySourceNetworkIDHigh()
Определения ComponentEnergyManager.c:1150
bool IsPassive()
Energy manager: Returns true if this device is set to be passive. False if otherwise.
Определения ComponentEnergyManager.c:881
Shape m_DebugPlugArrow
Определения ComponentEnergyManager.c:22
bool HasConversionOfEnergyToQuantity()
Energy manager: Returns true if this item automatically converts its energy to quantity.
Определения ComponentEnergyManager.c:1010
void SetPowered(bool state)
Определения ComponentEnergyManager.c:1678
void SetPlugType(int new_type)
Определения ComponentEnergyManager.c:642
void StoreEnergySourceIDs(int b1, int b2, int b3, int b4)
Определения ComponentEnergyManager.c:621
int GetEnergySourceStorageIDb2()
Определения ComponentEnergyManager.c:1126
ref TIntArray m_CompatiblePlugTypes
Определения ComponentEnergyManager.c:68
void UpdatePlugState()
Energy manager: Unplugs this device when it's necesarry.
Определения ComponentEnergyManager.c:587
void OnAttachmentAdded(EntityAI elec_device)
Определения ComponentEnergyManager.c:1416
void OnIsPlugged(EntityAI source_device)
Определения ComponentEnergyManager.c:1366
EntityAI m_Sockets[MAX_SOCKETS_COUNT]
Определения ComponentEnergyManager.c:78
string GetCordTextureFile()
Energy manager: Returns path to the cord texture file.
Определения ComponentEnergyManager.c:1326
ref map< string, EntityAI > m_DeviceByPlugSelection
Определения ComponentEnergyManager.c:71
bool IsSelectionAPlug(string selection_to_test)
Energy manager: Returns true if this selection is a plug that's plugged into this device....
Определения ComponentEnergyManager.c:1078
void SetEnergy(float new_energy)
Energy manager: Sets stored energy for this device. It ignores the min/max limit!
Определения ComponentEnergyManager.c:525
void SetPlugOwner(string selection_name, EntityAI device)
Определения ComponentEnergyManager.c:1650
float GetCordLength()
Energy manager: Returns the length of the virtual power cord.
Определения ComponentEnergyManager.c:1286
EntityAI GetPlugOwner(string plug_selection_name)
Energy manager: Returns the device to which the given plug selection belongs to.
Определения ComponentEnergyManager.c:1304
int GetAttachmentAction()
Определения ComponentEnergyManager.c:1114
bool CanWork(float test_energy=-1)
Energy manager: Checks whenever this device can do work or not.
Определения ComponentEnergyManager.c:757
EntityAI GetPluggedDevice()
Energy manager: Returns a device which is plugged into this one. If there are more devices to choose ...
Определения ComponentEnergyManager.c:1315
void UpdateSelections()
Energy manager: Shows/Hides all selections this system works with. Call this if something is wrong wi...
Определения ComponentEnergyManager.c:547
void OnIsUnplugged(EntityAI last_energy_source)
Определения ComponentEnergyManager.c:1382
bool GetRestorePlugState()
Определения ComponentEnergyManager.c:729
bool HasVisibleSocketsInInventory()
Определения ComponentEnergyManager.c:1072
int m_AttachmentActionType
Определения ComponentEnergyManager.c:44
bool m_ShowSocketsInInventory
Определения ComponentEnergyManager.c:32
static const string SEL_CORD_PLUGGED
Определения ComponentEnergyManager.c:65
bool IsCordFolded()
Energy manager: Returns true if the cord of this device is folded. Returns false if it's plugged.
Определения ComponentEnergyManager.c:872
override int GetCompType()
Определения ComponentEnergyManager.c:316
void RestorePlugState(bool state)
Определения ComponentEnergyManager.c:519
int m_EnergySourceStorageIDb4
Определения ComponentEnergyManager.c:43
bool m_AutoSwitchOffWhenInCargo
Определения ComponentEnergyManager.c:34
float GetEnergy0To1()
Energy manager: Returns % of stored energy this device has as float (from 0.0 to 1....
Определения ComponentEnergyManager.c:1179
void SwitchOff()
Energy manager: Switches OFF the device.
Определения ComponentEnergyManager.c:406
void OnOwnSocketReleased(EntityAI device)
Определения ComponentEnergyManager.c:1402
array< EntityAI > GetPoweredDevices()
Energy manager: Returns an array of devices which are plugged into this one and are turned on.
Определения ComponentEnergyManager.c:1338
override void Event_OnAwake()
Определения ComponentEnergyManager.c:175
bool ConsumeEnergy(float amount)
Energy manager: Consumes the given amount of energy. If there is not enough of stored energy in this ...
Определения ComponentEnergyManager.c:894
float m_EnergyStorageMax
Определения ComponentEnergyManager.c:51
void RememberLastUpdateTime()
Определения ComponentEnergyManager.c:1736
bool CanSwitchOn()
Energy manager: Checks if the device can be switched ON.
Определения ComponentEnergyManager.c:741
void ResetEnergyUsage()
Energy manager: Resets energy usage to default (config) value.
Определения ComponentEnergyManager.c:660
int m_EnergySourceNetworkIDHigh
Определения ComponentEnergyManager.c:46
int GetEnergySourceStorageIDb1()
Определения ComponentEnergyManager.c:1120
bool IsPlugCompatible(int plug_ID)
Energy manager: Checks if the given plug is compatible with this device's socket. Used by CanReceiveP...
Определения ComponentEnergyManager.c:947
void SetEnergyUsage(float new_usage)
Energy manager: Changes the energy usage per second.
Определения ComponentEnergyManager.c:654
void OnEnergyConsumed()
Energy manager: Called when energy was consumed on this device.
Определения ComponentEnergyManager.c:1467
void SetCordTextureFile(string new_path)
Определения ComponentEnergyManager.c:667
override void Event_OnInit()
Определения ComponentEnergyManager.c:101
string m_CordTextureFile
Определения ComponentEnergyManager.c:59
bool CanSwitchOff()
Energy manager: Checks if the device can be switched OFF.
Определения ComponentEnergyManager.c:849
int GetSocketsCount()
Energy manager: Returns the count of power sockets (whenever used or not)
Определения ComponentEnergyManager.c:1102
void SetDeviceBySocketID(int id, EntityAI plugged_device)
Energy manager: Stores the device which is plugged into the given socket ID.
Определения ComponentEnergyManager.c:679
void UpdateSocketSelections(int socket_id, EntityAI device_to_plug)
Определения ComponentEnergyManager.c:1578
float GetUpdateInterval()
Energy manager: Returns the update interval of this device.
Определения ComponentEnergyManager.c:1190
bool m_IsSwichedOnPreviousState
Определения ComponentEnergyManager.c:25
bool HasElectricityIcon()
Energy manager: Returns true if the electricity icon (bolt) is supposed to be visible for this device...
Определения ComponentEnergyManager.c:1004
void OnOwnSocketTaken(EntityAI device)
Определения ComponentEnergyManager.c:1389
void OnDeviceDestroyed()
Определения ComponentEnergyManager.c:322
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...
Определения ComponentEnergyManager.c:735
int m_EnergySourceStorageIDb1
Определения ComponentEnergyManager.c:40
EntityAI GetDeviceBySocketID(int id)
Energy manager: Returns the device which is plugged into the given socket ID.
Определения ComponentEnergyManager.c:1298
float GetEnergyMaxPristine()
Energy manager: Returns the maximum amount of energy this device can store. It's damage is NOT taken ...
Определения ComponentEnergyManager.c:1275
bool IsSwitchedOn()
Energy manager: Returns state of the switch. Whenever the device is working or not does not matter....
Определения ComponentEnergyManager.c:866
int GetEnergySourceStorageIDb3()
Определения ComponentEnergyManager.c:1132
bool HasEnoughStoredEnergy()
Energy manager: Returns true if this device has enough of stored energy for its own use.
Определения ComponentEnergyManager.c:906
bool CanReceivePlugFrom(EntityAI device_to_plug)
Energy manager: Returns true if this device can receive power plug of the other device.
Определения ComponentEnergyManager.c:976
Определения Component.c:16
Wrapper class for managing sound through SEffectManager.
Определения EffectSound.c:5
Определения Building.c:6
Определения EnMath.c:7
Определения DayZPlayerImplement.c:63
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
static proto native float DistanceSq(vector v1, vector v2)
Returns the square distance between tips of two 3D vectors.
proto float Normalize()
Normalizes vector. Returns length.
static proto native float Distance(vector v1, vector v2)
Returns the distance between tips of two 3D vectors.
vector Perpend()
Returns perpendicular vector. Perpendicular vector is computed as cross product between input vector ...
Определения EnConvert.c:209
Определения EnConvert.c:106
proto native CGame GetGame()
const int COMP_TYPE_ENERGY_MANAGER
Определения Component.c:9
void Error(string err)
Messagebox with error message.
Определения 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
Определения EnScript.c:687
proto volatile int CallFunction(Class inst, string function, out void returnVal, void parm)
static proto float Lerp(float a, float b, float time)
Linearly interpolates between 'a' and 'b' given 'time'.
static proto float Min(float x, float y)
Returns smaller of two given values.
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'.
const int CALL_CATEGORY_SYSTEM
Определения tools.c:8