DayZ 1.29
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 if (!m_ThisEntityAI)
104 return;
105
106 m_ThisEntityAI.m_EM = this;
107 g_Game.GameScript.CallFunction(m_ThisEntityAI, "OnInitEnergy", NULL, 0);
108 }
109
110 // Update debug arrows
112 {
113 if ( GetDebugPlugs() )
114 {
115 if ( g_Game.IsMultiplayer() && g_Game.IsServer() )
116 {
117 if (m_DebugUpdate)
118 m_DebugUpdate.Stop();
119
120 return;
121 }
122
124 {
125 m_DebugPlugArrow.Destroy();
126 m_DebugPlugArrow = NULL;
127 }
128
130 {
131 vector from = GetEnergySource().GetPosition() + "0 0.1 0";
132 vector to = m_ThisEntityAI.GetPosition() + "0 0.1 0";
133
134 //No need to draw an arrow in this situation as it would not be visible
135 if ( vector.DistanceSq(from, to) == 0 )
136 return;
137
138 if ( m_ThisEntityAI.GetType() == "BarbedWire" ) // Special case for debugging of electric fences. Temporal code until offsets in fences are fixed.
139 {
140 EntityAI BBB = m_ThisEntityAI.GetHierarchyParent();
141
142 if ( BBB && BBB.GetType() == "Fence" )
143 {
144 to = to + "0 -1.3 0";
145 }
146 }
147
148 m_DebugPlugArrow = DrawArrow( from, to );
149 }
150 }
151 }
152
153 Shape DrawArrow(vector from, vector to, float size = 0.5, int color = 0xFFFFFFFF, float flags = 0)
154 {
155 vector dir = to - from;
156 dir.Normalize();
157 vector dir1 = dir * size;
158 size = size * 0.5;
159
160 vector dir2 = dir.Perpend() * size;
161
162 vector pts[5];
163 pts[0] = from;
164 pts[1] = to;
165 pts[2] = to - dir1 - dir2;
166 pts[3] = to - dir1 + dir2;
167 pts[4] = to;
168
169 return Shape.CreateLines(color, flags, pts, 5);
170 }
171
173 {
174 return m_ThisEntityAI;
175 }
176
177 // Prepare everything
178 override void Event_OnAwake()
179 {
180 if (!m_ThisEntityAI)
181 return;
182
183 string cfg_item = "CfgVehicles " + m_ThisEntityAI.GetType();
184 string cfg_energy_manager = cfg_item + " EnergyManager ";
185
186 // Read all config parameters
187 m_EnergyUsage = g_Game.ConfigGetFloat(cfg_energy_manager + "energyUsagePerSecond");
188 bool switch_on = g_Game.ConfigGetFloat(cfg_energy_manager + "switchOnAtSpawn");
189 m_AutoSwitchOff = g_Game.ConfigGetFloat(cfg_energy_manager + "autoSwitchOff");
190 m_HasElectricityIcon = g_Game.ConfigGetFloat(cfg_energy_manager + "hasIcon");
191 m_AutoSwitchOffWhenInCargo = g_Game.ConfigGetFloat(cfg_energy_manager + "autoSwitchOffWhenInCargo");
192
193 m_EnergyAtSpawn = g_Game.ConfigGetFloat(cfg_energy_manager + "energyAtSpawn");
195 m_EnergyStorageMax = g_Game.ConfigGetFloat(cfg_energy_manager + "energyStorageMax");
196 m_ReduceMaxEnergyByDamageCoef = g_Game.ConfigGetFloat(cfg_energy_manager + "reduceMaxEnergyByDamageCoef");
197 m_SocketsCount = g_Game.ConfigGetFloat(cfg_energy_manager + "powerSocketsCount");
198
199 m_IsPassiveDevice = g_Game.ConfigGetFloat(cfg_energy_manager + "isPassiveDevice");
200 m_CordLength = g_Game.ConfigGetFloat(cfg_energy_manager + "cordLength");
201 m_PlugType = g_Game.ConfigGetFloat(cfg_energy_manager + "plugType");
202
203 m_AttachmentActionType = g_Game.ConfigGetFloat(cfg_energy_manager + "attachmentAction");
204 m_WetnessExposure = g_Game.ConfigGetFloat(cfg_energy_manager + "wetnessExposure");
205
206 float update_interval = g_Game.ConfigGetFloat(cfg_energy_manager + "updateInterval");
207
208 m_ConvertEnergyToQuantity = g_Game.ConfigGetFloat(cfg_energy_manager + "convertEnergyToQuantity");
209
210
211 // Check if energy->quantity converion is configured properly
212 float cfg_max_quantity = g_Game.ConfigGetFloat (cfg_item + " varQuantityMax");
213
214 if (m_ConvertEnergyToQuantity && cfg_max_quantity <= 0)
215 {
216 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!";
217 Error(error);
219 }
220 else
221 {
223 {
226
227 m_UpdateQuantityTimer.Run( 0.3 , this, "OnEnergyAdded", NULL, false);
228 }
229 }
230
231 // Set update interval
232 if ( update_interval <= 0 )
233 update_interval = DEFAULT_UPDATE_INTERVAL;
234
235 SetUpdateInterval( update_interval );
236
237 // If energyAtSpawn is present, then use its value for energyStorageMax if that cfg param is not present (for convenience's sake)
238 string cfg_check_energy_limit = cfg_energy_manager + "energyStorageMax";
239
240 if ( !g_Game.ConfigIsExisting (cfg_check_energy_limit) && m_Energy > 0 )
241 {
243 }
244
245 // Fill m_CompatiblePlugTypes
246 string cfg_check_plug_types = cfg_energy_manager + "compatiblePlugTypes";
247
248 if ( g_Game.ConfigIsExisting (cfg_check_plug_types) )
249 {
251 g_Game.ConfigGetIntArray(cfg_check_plug_types, m_CompatiblePlugTypes);
252 }
253
254 if (GetSocketsCount() > 0)
256
257 if ( m_CordLength < 0 )
258 {
259 m_CordLength = 0;
260 string error_message_cord = "Warning! " + m_ThisEntityAI.GetType() + ": config parameter 'cordLength' is less than 0! Cord length should not be negative!";
261 DPrint(error_message_cord);
262 }
263
264 if (GetSocketsCount() > 0)
265 {
267 // Prepare the m_DeviceByPlugSelection
268 string cfg_animation_sources = "cfgVehicles " + m_ThisEntityAI.GetType() + " " + "AnimationSources ";
269 int animation_sources_count = g_Game.ConfigGetChildrenCount(cfg_animation_sources);
270
271 for (int i_selection = 0; i_selection < animation_sources_count; i_selection++)
272 {
273 // TO DO: This could be optimized so not all selections on item are considered as plug/socket selections.
274 string selection;
275 g_Game.ConfigGetChildName(cfg_animation_sources, i_selection, selection);
276 m_DeviceByPlugSelection.Set(selection, NULL);
277 }
278 }
279
280
281
282 // Prepare sockets
284 {
286 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!";
287 DPrint(error_message_sockets);
288 }
289
290 m_Sockets[MAX_SOCKETS_COUNT]; // Handles selections for plugs in the sockets. Feel free to change the limit if needed.
291
292 g_Game.ConfigGetText(cfg_energy_manager + "cordTextureFile", m_CordTextureFile);
293
294 if ( switch_on )
295 {
296 SwitchOn();
297 }
298
299 for ( int i = 0; i <= GetSocketsCount(); ++i )
300 {
301 m_ThisEntityAI.HideSelection ( SOCKET_ + i.ToString() + _PLUGGED );
302 }
303
304 // Show/hide inventory sockets
306 if ( GetSocketsCount() > 0 && IsPlugCompatible(PLUG_COMMON_APPLIANCE) && m_ThisEntityAI.GetType() != "MetalWire" ) // metal wire filter is hopefully temporal.
307 {
309 }
310
312
313 m_ThisEntityAI.HideSelection( SEL_CORD_PLUGGED );
314
315
316 #ifdef DIAG_DEVELOPER
317 g_Game.m_EnergyManagerArray.Insert( this );
318 #endif
319 }
320
321 // Returns the type of this component
322 override int GetCompType()
323 {
325 }
326
327 // When the object is deleted
329 {
330 if (!m_ThisEntityAI)
331 return;
332
333 bool was_working = m_ThisEntityAI.GetCompEM().IsWorking();
334
335 SwitchOff();
337 UnplugThis();
338 SetPowered( false );
339
340 if ( was_working )
341 m_ThisEntityAI.OnWorkStop();
342 ;
343 }
344
345 //Restart the debug timer when relogging
347 {
348 if ( m_DebugPlugs )
349 {
350 if ( !m_DebugUpdate )
352
353 if ( !m_DebugUpdate.IsRunning() )
354 m_DebugUpdate.Run(0.01, this, "DebugUpdate", NULL, true);
355 }
356 else
357 {
358 if ( m_DebugPlugArrow )
359 {
360 m_DebugPlugArrow.Destroy();
361 m_DebugPlugArrow = NULL;
362 }
363 }
364 }
365
367 {
368 return m_DebugPlugs;
369 }
370
371 void SetDebugPlugs( bool newVal )
372 {
373 m_DebugPlugs = newVal;
374 RefreshDebug();
375 }
376
377 //======================================================================================
378 // PUBLIC FUNCTIONS
379 // Use these to control the Energy Manager
380 // Functions are in order of their return value: void, bool, int, float, string, array.
381 //======================================================================================
382
384 void SwitchOn()
385 {
387
388 if (g_Game.IsServer() || !g_Game.IsMultiplayer())
389 {
391 {
392 m_IsSwichedOn = true;
393 Synch();
394
395 DeviceUpdate(); // 'Wake up' this device now
396 StartUpdates();
397
398 // 'Wakes up' all connected devices
400
402
403 // Call event
404 g_Game.GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOn", NULL, 0);
405 }
406 }
407
408 if ( !g_Game.IsServer() && g_Game.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.)
409 {
410 g_Game.GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOn", NULL, 0);
411 }
412 }
413
416 {
418
419 if (g_Game.IsServer() || !g_Game.IsMultiplayer())
420 {
422 {
423 m_IsSwichedOn = false;
424 Synch();
425
426 if (IsWorking())
427 {
428 StopUpdates();
429 DeviceUpdate();
430 }
431
432 // 'Wakes up' all connected devices
434
436
437 // Call event
438 g_Game.GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOff", NULL, 0);
439 }
440 }
441
442 if ( !g_Game.IsServer() && g_Game.IsMultiplayer() )
443 {
444 m_IsSwichedOn = false;
445 g_Game.GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOff", NULL, 0);
446 }
447 }
448
450 void SetPassiveState(bool state = true)
451 {
452 m_IsPassiveDevice = state;
453 if ( !m_IsPassiveDevice )
454 {
455 DeviceUpdate();
456 }
457 }
458
460 void UnplugDevice(EntityAI device_to_unplug)
461 {
462 if (g_Game)
463 {
464 int indexStart = GetPluggedDevicesCount() - 1;
465 bool deviceFound = false;
466
467 for (int i = indexStart; i >= 0; --i)
468 {
469 EntityAI plugged_device = GetPluggedDevices().Get(i);
470
471 if (plugged_device == device_to_unplug)
472 {
473 GetPluggedDevices().Remove(i);
474 deviceFound = true;
475 break;
476 }
477 }
478
479 if (deviceFound && m_ThisEntityAI)
480 {
481 int socket_ID = device_to_unplug.GetCompEM().GetMySocketID();
482 UnplugCordFromSocket(socket_ID);
483 device_to_unplug.GetCompEM().SetEnergySource(null);
484 device_to_unplug.GetCompEM().DeviceUpdate();
485 device_to_unplug.GetCompEM().StartUpdates();
486 device_to_unplug.GetCompEM().WakeUpWholeBranch(m_ThisEntityAI);
487
489 {
490 m_DebugPlugArrow.Destroy();
491 m_DebugPlugArrow = null;
492 }
493
494 OnOwnSocketReleased(device_to_unplug);
495 device_to_unplug.GetCompEM().OnIsUnplugged(m_ThisEntityAI);
496 device_to_unplug.ShowSelection(SEL_CORD_FOLDED);
497 device_to_unplug.HideSelection(SEL_CORD_PLUGGED);
498 }
499 }
500 }
501
504 {
505 if (g_Game)
506 {
508 {
509 GetEnergySource().GetCompEM().UnplugDevice(m_ThisEntityAI);
510 }
511 }
512 }
513
516 {
517 if ( GetPluggedDevices() ) // This check is necesarry in case this function is called before initialization
518 {
519 int indexStart = GetPluggedDevicesCount() - 1;
520 for (int i = indexStart; i >= 0; --i)
521 {
523 }
524 }
525 }
526
527 // Used only for storing of the plug's state through server restart
528 void RestorePlugState(bool state)
529 {
530 m_RestorePlugState = state;
531 }
532
534 void SetEnergy(float new_energy)
535 {
536 if (m_ThisEntityAI && (g_Game.IsServer() || !g_Game.IsMultiplayer())) // Client can't change energy value.
537 {
538 m_ThisEntityAI.SetWeightDirty();
539 float old_energy = m_Energy;
540 m_Energy = new_energy;
541
542 if (old_energy - GetEnergyUsage() <= 0 || (old_energy != new_energy && Math.Min(old_energy,new_energy) <= 0))
543 {
545 }
546 }
547 }
548
550 void SetEnergy0To1(float energy01)
551 {
552 SetEnergy( Math.Lerp(0, GetEnergyMax(),energy01));
553 }
554
557 {
558 if (!m_ThisEntityAI)
559 return;
560
561 // Lets update sockets, if there are any
562 int slots_c = GetSocketsCount();
563
564 for (int i = 0; i < slots_c; ++i)
565 {
566 EntityAI plug_owner = GetDeviceBySocketID(i);
567
568 if (plug_owner)
569 {
570 string plugged_selection = SOCKET_ + (i+1).ToString() + _PLUGGED;
571 string available_selection = SOCKET_ + (i+1).ToString() + _AVAILABLE;
572 m_ThisEntityAI.ShowSelection(plugged_selection);
573 m_ThisEntityAI.HideSelection(available_selection);
574 string texture_path = plug_owner.GetCompEM().GetCordTextureFile();
575 int selection_index = m_ThisEntityAI.GetHiddenSelectionIndex(plugged_selection);
576 m_ThisEntityAI.SetObjectTexture(selection_index, texture_path);
577 }
578 else
579 {
580 m_ThisEntityAI.ShowSelection(SOCKET_ + (i+1).ToString() + _AVAILABLE);
581 m_ThisEntityAI.HideSelection(SOCKET_ + (i+1).ToString() + _PLUGGED);
582 }
583 }
584
585 // Now lets update the cord/plug state
586 if (GetEnergySource())
587 {
588 m_ThisEntityAI.ShowSelection(SEL_CORD_PLUGGED);
589 m_ThisEntityAI.HideSelection(SEL_CORD_FOLDED);
590 }
591 else
592 {
593 m_ThisEntityAI.ShowSelection(SEL_CORD_FOLDED);
594 m_ThisEntityAI.HideSelection(SEL_CORD_PLUGGED);
595 }
596 }
597
600 {
601 if (m_ThisEntityAI && m_ThisEntityAI.GetCompEM().GetEnergySource())
602 {
603 EntityAI player = m_ThisEntityAI.GetHierarchyRootPlayer();
604 // Check if the item is held in hands during advanced placement
605 if (player)
606 {
607 // Measure distance from the player
608 vector playerPosition = player.GetPosition();
609 if (!IsEnergySourceAtReach(playerPosition, 5))
610 UnplugThis();
611 }
612 else
613 {
614 // Measure distance from the device
615 vector itemPosition = m_ThisEntityAI.GetPosition();
616
617 if (m_ThisEntityAI.GetHierarchyParent())
618 itemPosition = m_ThisEntityAI.GetHierarchyParent().GetPosition();
619
620 if (!IsEnergySourceAtReach(itemPosition))
621 UnplugThis();
622 }
623 }
624 }
625
626 // Returns an array of plug types this device can accept
628 {
630 }
631
632 // Stores IDs of the energy source.
633 void StoreEnergySourceIDs(int b1, int b2, int b3, int b4)
634 {
639 }
640
642 void SetEnergyMaxPristine(float new_limit)
643 {
644 m_EnergyStorageMax = new_limit;
645 }
646
648 void SetCordLength( float new_length )
649 {
650 m_CordLength = new_length;
651 }
652
653 // Sets the plug type (for plug -> socket compatibility checks).
654 void SetPlugType( int new_type )
655 {
656 m_PlugType = new_type;
657 }
658
659 // Sets the new attachment action type.
660 void SetAttachmentAction( int new_action_type )
661 {
662 m_AttachmentActionType = new_action_type;
663 }
664
666 void SetEnergyUsage( float new_usage )
667 {
668 m_EnergyUsage = new_usage;
669 }
670
673 {
674 if (!m_ThisEntityAI)
675 return;
676
677 string cfg_energy_usage = "CfgVehicles " + m_ThisEntityAI.GetType() + " EnergyManager ";
678 m_EnergyUsage = g_Game.ConfigGetFloat (cfg_energy_usage + "energyUsagePerSecond");
679 }
680
681 // Sets path to the cord texture file.
682 void SetCordTextureFile( string new_path )
683 {
684 m_CordTextureFile = new_path;
685 }
686
687 // Sets energy source. Intended to be called only on client through RPC.
689 {
690 SetEnergySource(source);
691 }
692
694 void SetDeviceBySocketID(int id, EntityAI plugged_device)
695 {
696 m_Sockets[id] = plugged_device;
697 }
698
699
701 void SetElectricityIconVisibility( bool make_visible )
702 {
703 m_HasElectricityIcon = make_visible;
704 }
705
706 // 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.
708 {
709 if (g_Game.IsServer() || !g_Game.IsMultiplayer())
710 {
711 bool current_state = CanWork();
712 if (current_state != m_CanWork)
713 {
714 m_CanWork = current_state;
715
716 if (m_ThisEntityAI)
717 {
718 Synch();
719 if (m_ThisEntityAI.GetHierarchyParent() && m_ThisEntityAI.GetHierarchyParent().GetCompEM())
720 {
721 m_ThisEntityAI.GetHierarchyParent().GetCompEM().UpdateCanWork();
722 }
723 }
724 }
725 }
726 }
727
729 {
731 {
732 if (IsSwitchedOn())
733 {
734 SwitchOff();
735 }
736 }
737 }
738
740 void SetUpdateInterval( float value )
741 {
742 m_UpdateInterval = value;
743 }
744
745 // Returns true if this device was plugged into something at the end of previous session
747 {
748 return m_RestorePlugState;
749 }
750
752 bool PlugThisInto(EntityAI energy_source, int socket_id = -1)
753 {
754 if (m_ThisEntityAI)
755 {
756 return energy_source.GetCompEM().PlugInDevice(m_ThisEntityAI, socket_id);
757 }
758 else
759 {
760 return false;
761 }
762 }
763
766 {
767 if ( !IsSwitchedOn() )
768 {
769 return true;
770 }
771
772 return false;
773 }
774
775
781 bool CanWork( float test_energy = -1)
782 {
783 if ( g_Game.IsMultiplayer() && g_Game.IsClient() )
784 {
785 return m_CanWork;
786 }
787
788 if (!m_ThisEntityAI || m_ThisEntityAI.IsRuined())
789 {
790 return false;
791 }
792
793 // Check if the power source(s) (which can be serially connected) can provide needed energy.
794 float energy_usage = test_energy;
795 float gathered_energy = GetEnergy();
796 EntityAI energy_source = GetEnergySource();
797
798 if (energy_usage == -1)
799 {
800 energy_usage = GetEnergyUsage();
801 }
802
803 if ( !CheckWetness() )
804 {
805 return false;
806 }
807
808 if (gathered_energy <= 0 && energy_usage <= 0) //empty power source
809 {
810 return false;
811 }
812
813 int cycle_limit = 500; // Sanity check to definitely avoid infinite cycles
814
815 while ( gathered_energy < energy_usage ) // Look for energy source if we don't have enough stored energy
816 {
817 // Safetycheck!
818 if (cycle_limit > 0)
819 {
820 cycle_limit--;
821 }
822 else
823 {
824 DPrint("Energy Manager ERROR: The 'cycle_limit' safety break had to be activated to prevent possible game freeze. Dumping debug information...");
825 //Print(m_ThisEntityAI);
826 //Print(this);
827 //Print(energy_source);
828
829 if (energy_source.GetCompEM())
830 {
831 //Print(energy_source.GetCompEM());
832 }
833
834 //Print(gathered_energy);
835 //Print(energy_usage);
836
837 //Print(m_ThisEntityAI.GetPosition());
838
839 if (energy_source)
840 {
841 //Print(energy_source.GetPosition());
842 }
843
844 //Print("End of the 'cycle_limit' safety break ^ ");
845
846 return false;
847 }
848 // ^ Safetycheck!
849
850 if ( energy_source && energy_source != m_ThisEntityAI && !energy_source.IsRuined() && energy_source.GetCompEM() && energy_source.GetCompEM().IsSwitchedOn() && energy_source.GetCompEM().CheckWetness() )
851 {
852 gathered_energy = gathered_energy + energy_source.GetCompEM().GetEnergy();
853 energy_source = energy_source.GetCompEM().GetEnergySource();
854 }
855 else
856 {
857 // No power source, no energy.
858 return false;
859 }
860 }
861
862 // Enough energy was found
863 return true;
864 }
865
868 {
869 if (m_ThisEntityAI)
870 {
871 return (m_ThisEntityAI.GetWet() <= 1-m_WetnessExposure);
872 }
873 else
874 {
875 return false;
876 }
877 }
878
881 {
882 if ( IsPassive() )
883 {
884 return false;
885 }
886
887 return IsSwitchedOn();
888 }
889
890 // Returns previous state of the switch.
895
898 {
899 return m_IsSwichedOn;
900 }
901
904 {
905 if ( IsPlugged() )
906 return false;
907
908 return true;
909 }
910
913 {
914 return m_IsPassiveDevice;
915 }
916
919 {
920 return m_IsPlugged;
921 }
922
923
925 bool ConsumeEnergy(float amount)
926 {
927 if (m_ThisEntityAI)
928 {
929 return FindAndConsumeEnergy(m_ThisEntityAI, amount, true);
930 }
931 else
932 {
933 return false;
934 }
935 }
936
939 {
940 return m_IsWorking;
941 }
942
945 {
946 if ( GetEnergy() > GetEnergyUsage() )
947 {
948 return true;
949 }
950
951 return false;
952 }
953
955 bool HasFreeSocket( int socket_id = -1 )
956 {
957 if (socket_id == -1)
958 {
959 int plugged_devices = GetPluggedDevicesCount();
960 int plugged_devices_limit = GetSocketsCount();
961
962 if ( plugged_devices < plugged_devices_limit )
963 {
964 return true;
965 }
966
967 return false;
968 }
969 else
970 {
971 EntityAI device = GetDeviceBySocketID(socket_id);
972
973 if (device)
974 {
975 return false;
976 }
977 else
978 {
979 return true;
980 }
981 }
982 }
983
985 bool IsPlugCompatible(int plug_ID)
986 {
987 if ( plug_ID == PLUG_UNDEFINED )
988 {
989 return true; // When plugType is undefined in config then make it compatible.
990 }
991
993 {
994 int nCompatiblePlugTypes = m_CompatiblePlugTypes.Count();
995 for ( int i = 0; i < nCompatiblePlugTypes; ++i )
996 {
997 int plug_ID_to_Check = m_CompatiblePlugTypes.Get(i);
998
999 if ( plug_ID_to_Check == plug_ID )
1000 {
1001 return true;
1002 }
1003 }
1004 }
1005 else
1006 {
1007 // Since the config parameter compatiblePlugTypes is not present, then accept all plugs for simplicity's sake
1008 return true;
1009 }
1010
1011 return false;
1012 }
1013
1015 bool CanReceivePlugFrom( EntityAI device_to_plug )
1016 {
1017 // The following conditions are broken down for the sake of easier reading/debugging.
1018 if (m_ThisEntityAI && HasFreeSocket() && device_to_plug != m_ThisEntityAI)
1019 {
1020 if ( device_to_plug.GetCompEM().GetEnergySource() != m_ThisEntityAI)
1021 {
1022 if ( IsPlugCompatible(device_to_plug.GetCompEM().GetPlugType()) )
1023 {
1024 if ( device_to_plug.GetCompEM().IsEnergySourceAtReach( device_to_plug.GetPosition(), 0, m_ThisEntityAI.GetPosition() ) )
1025 {
1026 return true;
1027 }
1028 }
1029 }
1030 }
1031
1032 return false;
1033 }
1034
1036 bool CanBePluggedInto( EntityAI potential_energy_provider )
1037 {
1038 if (m_ThisEntityAI)
1039 {
1040 return potential_energy_provider.GetCompEM().CanReceivePlugFrom(m_ThisEntityAI);
1041 }
1042 else
1043 {
1044 return false;
1045 }
1046 }
1047
1050 {
1051 return m_HasElectricityIcon;
1052 }
1053
1059
1076 bool IsEnergySourceAtReach( vector from_position, float add_tolerance = 0, vector override_source_position = "-1 -1 -1" )
1077 {
1078 if ( !IsPlugged() && override_source_position == "-1 -1 -1" )
1079 {
1080 return false;
1081 }
1082
1083 if ( GetCordLength() == 0 ) // 0 is an exception, which means infinitely long cable.
1084 {
1085 return true;
1086 }
1087
1088 vector source_pos;
1089 float distance;
1090
1091 if ( override_source_position == "-1 -1 -1" )
1092 {
1093 EntityAI energy_source = GetEnergySource();
1094
1095 if (!energy_source)
1096 return false;
1097
1098 source_pos = energy_source.GetPosition();
1099 distance = vector.Distance( from_position, source_pos );
1100 }
1101 else
1102 {
1103 source_pos = override_source_position;
1104 distance = vector.Distance( from_position, source_pos );
1105 }
1106
1107 if (distance > GetCordLength() + add_tolerance)
1108 {
1109 return false;
1110 }
1111 else
1112 {
1113 return true;
1114 }
1115 }
1116
1121
1123 bool IsSelectionAPlug(string selection_to_test )
1124 {
1125 if ( GetPluggedDevices() )
1126 {
1127 int socket_count = GetSocketsCount();
1128
1129 for ( int i = socket_count; i >= 0; --i )
1130 {
1131 string real_selection = SOCKET_ + i.ToString() +_PLUGGED;
1132
1133 if ( selection_to_test == real_selection)
1134 {
1135 return true;
1136 }
1137 }
1138 }
1139
1140 return false;
1141 }
1142
1143
1144
1145
1148 {
1149 return m_SocketsCount;
1150 }
1151
1154 {
1155 return m_PlugType;
1156 }
1157
1158 // Returns the action ID which is supposed to be done upon receiving an attachment
1160 {
1162 }
1163
1164 // Returns persistent ID (block 1) of the energy source
1169
1170 // Returns persistent ID (block 2) of the energy source
1175
1176 // Returns persistent ID (block 3) of the energy source
1181
1182 // Returns persistent ID (block 4) of the energy source
1187
1188 // Returns network ID (low) of the energy source
1193
1194 // Returns network ID (high) of the energy source
1199
1202 {
1203 if ( GetPluggedDevices() )
1204 {
1205 return GetPluggedDevices().Count();
1206 }
1207
1208 return 0;
1209 }
1210
1213 {
1214 if ( m_EnergyStorageMax > 0 )
1215 {
1216 int coef = Math.Round( m_Energy / m_EnergyStorageMax * 100 );
1217 return coef;
1218 }
1219
1220 return 0;
1221 }
1222
1225 {
1226 if ( m_EnergyStorageMax > 0 )
1227 {
1229 }
1230
1231 return 0;
1232 }
1233
1236 {
1237 #ifdef DIAG_DEVELOPER
1238 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_CONSUMPTION) || (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_RECHARGE)))
1239 {
1240 return 1;//when modifying time accel, we might want to see things happen when they should, instead of waiting for the next tick
1241 }
1242 #endif
1243 return m_UpdateInterval;
1244 }
1245
1248 {
1249 return m_WetnessExposure;
1250 }
1251
1254 {
1255 return m_EnergyUsage;
1256 }
1257
1260 {
1261 return m_Energy;
1262 }
1263
1265 float AddEnergy(float added_energy)
1266 {
1267 if (added_energy != 0)
1268 {
1269 //Print("AddEnergy ---------> " + added_energy + " " + this + " " +m_ThisEntityAI.ClassName());
1270 #ifdef DIAG_DEVELOPER
1271 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_CONSUMPTION) && added_energy < 0)
1272 {
1273 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
1274 added_energy *= timeAccel;
1275 }
1276 #endif
1277
1278 bool energy_was_added = (added_energy > 0);
1279
1280 float energy_to_clamp = GetEnergy() + added_energy;
1281 float clamped_energy = Math.Clamp( energy_to_clamp, 0, GetEnergyMax() );
1282 SetEnergy(clamped_energy);
1283 StartUpdates();
1284
1285 if (energy_was_added)
1286 OnEnergyAdded();
1287 else
1289
1290 return energy_to_clamp - clamped_energy;
1291 }
1292
1293 return 0;
1294 }
1295
1298 {
1299 float max_health = 0;
1300
1301 if (m_ThisEntityAI && m_ThisEntityAI.HasDamageSystem())
1302 max_health = m_ThisEntityAI.GetMaxHealth("","");
1303 //else if ( m_ReduceMaxEnergyByDamageCoef != 0 )
1304 // Error("[ERROR] ReduceMaxEnergyByDamageCoef is setup but " + m_ThisEntityAI.GetType() + " does not have a Damage System");
1305
1306 if ( max_health == 0 || m_ReduceMaxEnergyByDamageCoef == 0 )
1307 return GetEnergyMaxPristine();
1308
1309 float health = 100;
1310
1311 if (m_ThisEntityAI && (g_Game.IsServer() || !g_Game.IsMultiplayer())) // TO DO: Remove this IF when method GetHealth can be called on client!
1312 health = m_ThisEntityAI.GetHealth("","");
1313
1314 float damage_coef = 1 - (health / max_health);
1315
1316 return GetEnergyMaxPristine() * (1 - ( damage_coef * m_ReduceMaxEnergyByDamageCoef ) );
1317 }
1318
1321 {
1322 return m_EnergyStorageMax;
1323 }
1324
1326 {
1327 return m_EnergyAtSpawn;
1328 }
1329
1332 {
1333 return m_CordLength;
1334 }
1335
1338 {
1339 return m_EnergySource;
1340 }
1341
1344 {
1345 return m_Sockets[id];
1346 }
1347
1349 EntityAI GetPlugOwner(string plug_selection_name)
1350 {
1351 if ( m_DeviceByPlugSelection && m_DeviceByPlugSelection.Contains(plug_selection_name) )
1352 {
1353 return m_DeviceByPlugSelection.Get(plug_selection_name);
1354 }
1355
1356 return NULL;
1357 }
1358
1361 {
1362 if ( GetPluggedDevicesCount() > 0 )
1363 {
1364 return GetPluggedDevices().Get(0);
1365 }
1366
1367 return NULL;
1368 }
1369
1372 {
1373 return m_CordTextureFile;
1374 }
1375
1381
1384 {
1385 array<EntityAI> return_array = new array<EntityAI>;
1386 int plugged_devices_c = GetPluggedDevicesCount();
1387 for ( int i = 0; i < plugged_devices_c; ++i )
1388 {
1389 EntityAI device = GetPluggedDevices().Get(i);
1390 if ( IsSwitchedOn() )
1391 {
1392 return_array.Insert(device);
1393 }
1394 }
1395
1396 return return_array;
1397 }
1398
1399
1400 /*===================================
1401 PUBLIC EVENTS
1402 ===================================*/
1403
1404 // Called every device update if its supposed to do some work. The update can be every second or at random, depending on its manipulation.
1405 void OnWork( float consumed_energy )
1406 {
1407 if (m_ThisEntityAI)
1408 m_ThisEntityAI.OnWork(consumed_energy);
1409 }
1410
1411 // Called when this device is plugged into some energy source
1412 void OnIsPlugged(EntityAI source_device)
1413 {
1414 if (m_DebugPlugs)
1415 {
1416 if (!m_DebugUpdate)
1418
1419 if (!m_DebugUpdate.IsRunning())
1420 m_DebugUpdate.Run(0.01, this, "DebugUpdate", NULL, true);
1421 }
1422
1423 UpdateCanWork();
1424 if (m_ThisEntityAI)
1425 m_ThisEntityAI.OnIsPlugged(source_device);
1426 }
1427
1428 // Called when this device is UNPLUGGED from the energy source
1429 void OnIsUnplugged( EntityAI last_energy_source )
1430 {
1431 UpdateCanWork();
1432 if (m_ThisEntityAI)
1433 m_ThisEntityAI.OnIsUnplugged( last_energy_source );
1434 }
1435
1436 // When something is plugged into this device
1438 {
1439 if (!m_ThisEntityAI)
1440 return;
1441
1442 //play sound
1443 if (device.GetCompEM().GetPlugType() == PLUG_COMMON_APPLIANCE && m_ThisEntityAI.IsInitialized())
1444 {
1445 EffectSound sound_plug;
1446 m_ThisEntityAI.PlaySoundSet(sound_plug, "cablereel_plugin_SoundSet", 0, 0);
1447 }
1448
1449 m_ThisEntityAI.OnOwnSocketTaken(device);
1450 }
1451
1452 // When something is UNPLUGGED from this device
1454 {
1455 if (!m_ThisEntityAI)
1456 return;
1457
1458 //play sound
1459 if ( device.GetCompEM().GetPlugType() == PLUG_COMMON_APPLIANCE && m_ThisEntityAI.IsInitialized() )
1460 {
1461 EffectSound sound_unplug;
1462 m_ThisEntityAI.PlaySoundSet( sound_unplug, "cablereel_unplug_SoundSet", 0, 0 );
1463 }
1464
1465 m_ThisEntityAI.OnOwnSocketReleased( device );
1466 }
1467
1468
1469 // Handles automatic attachment action
1470 void OnAttachmentAdded(EntityAI elec_device)
1471 {
1472 if (!m_ThisEntityAI)
1473 return;
1474
1475 int attachment_action_type = GetAttachmentAction();
1476
1477 if (attachment_action_type == PLUG_THIS_INTO_ATTACHMENT)
1478 {
1479 if (elec_device.GetCompEM().CanReceivePlugFrom(m_ThisEntityAI))
1480 {
1481 PlugThisInto(elec_device);
1482 }
1483 }
1484 else if (attachment_action_type == PLUG_ATTACHMENTS_INTO_THIS)
1485 {
1486 elec_device.GetCompEM().PlugThisInto(m_ThisEntityAI);
1487 }
1488 }
1489
1490 // Handles automatic detachment action
1492 {
1493 int attachment_action_type = GetAttachmentAction();
1494
1495 if ( attachment_action_type == PLUG_THIS_INTO_ATTACHMENT )
1496 {
1497 if ( elec_device == GetEnergySource() )
1498 {
1499 UnplugThis();
1500 }
1501 }
1502 else if ( attachment_action_type == PLUG_ATTACHMENTS_INTO_THIS )
1503 {
1504 elec_device.GetCompEM().UnplugThis();
1505 }
1506 }
1507
1508 // Starts the device's main cycle
1510 {
1511 if (!m_IsPassiveDevice)
1512 {
1513 if (!m_UpdateTimer)
1515
1516 if (!m_UpdateTimer.IsRunning()) // Makes sure the timer is NOT running already
1517 {
1518 m_UpdateTimer.Run(GetUpdateInterval(), this, "DeviceUpdate", null, true);
1519 }
1520 }
1521 }
1522
1525 {
1526 if (m_ThisEntityAI)
1527 m_ThisEntityAI.OnEnergyConsumed();
1528 }
1529
1532 {
1534 {
1535 m_UpdateQuantityTimer.Stop();
1536 m_UpdateQuantityTimer = NULL;
1537 }
1538
1539 if (m_ThisEntityAI)
1540 m_ThisEntityAI.OnEnergyAdded();
1541 }
1542
1543
1544 /*===================================
1545 PROTECTED FUNCTIONS
1546 ===================================*/
1547
1548 // Stops the device's main cycle
1549 protected void StopUpdates()
1550 {
1551 if (m_UpdateTimer)
1552 {
1553 m_UpdateTimer.Stop();
1554 m_UpdateTimer = NULL; // Delete timer from memory
1555 }
1556 }
1557
1561 void InteractBranch(EntityAI originalCaller, Man player = null, int system = 0)
1562 {
1563 OnInteractBranch(originalCaller, player, system);
1564 if ( GetSocketsCount() > 0 )
1565 {
1567
1568 foreach ( EntityAI device : devices)
1569 {
1570 if ( device != originalCaller ) // originalCaller check here prevents infinite loops
1571 {
1572 device.GetCompEM().InteractBranch( originalCaller, player, system );
1573 }
1574 }
1575 }
1576 }
1577
1579 protected void OnInteractBranch(EntityAI originalCaller, Man player, int system)
1580 {
1581 if (m_ThisEntityAI)
1582 m_ThisEntityAI.IncreaseLifetime();
1583
1584 }
1585
1586 // 'Wakes up' all devices down the network so they start working, if they have enough power, and are switched ON
1587 protected void WakeUpWholeBranch( EntityAI original_caller )
1588 {
1589 if ( GetSocketsCount() > 0 )
1590 {
1591 array<EntityAI> plugged_devices = GetPluggedDevices();
1592 int plugged_devices_c = plugged_devices.Count();
1593
1594 for ( int i = 0; i < plugged_devices_c; ++i )
1595 {
1596 EntityAI device = plugged_devices.Get(i);
1597 if ( device != original_caller ) // original_caller check here prevents infinite loops
1598 {
1599 device.GetCompEM().UpdateCanWork();
1600 device.GetCompEM().DeviceUpdate();
1601 device.GetCompEM().StartUpdates();
1602 device.GetCompEM().WakeUpWholeBranch( original_caller );
1603 }
1604 }
1605 }
1606 }
1607
1608 // Finds an available socket and plugs the given device into it.
1609 // This is mainly about visualisation.
1610 protected void PlugCordIntoSocket( EntityAI device_to_plug, int socket_id = -1 )
1611 {
1612 if (socket_id >= 0)
1613 {
1614 EntityAI plug_owner_by_socket = GetDeviceBySocketID(socket_id);
1615
1616 if (!plug_owner_by_socket)
1617 {
1618 UpdateSocketSelections(socket_id, device_to_plug);
1619 return;
1620 }
1621 }
1622
1623 int slots_c = GetSocketsCount();
1624
1625 for ( int i = 0; i < slots_c; ++i )
1626 {
1627 EntityAI plug_owner = GetDeviceBySocketID(i);
1628
1629 if ( !plug_owner ) // Check if this socket is available
1630 {
1631 UpdateSocketSelections(i, device_to_plug);
1632 break;
1633 }
1634 }
1635 }
1636
1637 // Updates socket selections (plugged/unplugged) of the given ID and sets color texture of the plug.
1638 protected void UpdateSocketSelections(int socket_id, EntityAI device_to_plug)
1639 {
1640 if (!m_ThisEntityAI)
1641 return;
1642
1643 SetDeviceBySocketID(socket_id, device_to_plug);
1644
1645 string plugged_selection = SOCKET_ + (socket_id+1).ToString() + _PLUGGED;
1646 SetPlugOwner( plugged_selection, device_to_plug );
1647 m_ThisEntityAI.ShowSelection ( plugged_selection );
1648
1649 string unplugged_selection = SOCKET_ + (socket_id+1).ToString() + _AVAILABLE;
1650 m_ThisEntityAI.HideSelection ( unplugged_selection );
1651 string texture_path = device_to_plug.GetCompEM().GetCordTextureFile();
1652 int selection_index = m_ThisEntityAI.GetHiddenSelectionIndex( plugged_selection );
1653 m_ThisEntityAI.SetObjectTexture( selection_index, texture_path );
1654 device_to_plug.GetCompEM().SetMySocketID(socket_id);
1655 }
1656
1657
1658 // Sets energy source for this device
1659 protected void SetEnergySource( EntityAI source )
1660 {
1661 m_EnergySource = source;
1662
1663 if (source)
1664 {
1665 m_IsPlugged = true;
1666 StartUpdates();
1667 }
1668 else
1669 {
1670 m_IsPlugged = false;
1673 }
1674
1675 if (m_EnergySource)
1677
1678 Synch();
1679 }
1680
1681 // Plugs the given device into this one
1682 protected bool PlugInDevice(EntityAI device_to_plug, int socket_id = -1)
1683 {
1684 if (m_ThisEntityAI && CanReceivePlugFrom(device_to_plug))
1685 {
1686 device_to_plug.IncreaseLifetime();
1688 if (device_to_plug.GetCompEM().IsPlugged())
1689 device_to_plug.GetCompEM().UnplugThis();
1690
1691 GetPluggedDevices().Insert(device_to_plug);
1692 device_to_plug.GetCompEM().SetEnergySource(m_ThisEntityAI);
1693
1694 PlugCordIntoSocket(device_to_plug, socket_id); // Visualisation
1695 OnOwnSocketTaken(device_to_plug);
1696
1697 device_to_plug.GetCompEM().OnIsPlugged(m_ThisEntityAI);
1699
1700 if (g_Game.IsServer() || !g_Game.IsMultiplayer())
1701 {
1702 device_to_plug.HideSelection(SEL_CORD_FOLDED);
1703 device_to_plug.ShowSelection(SEL_CORD_PLUGGED);
1704 }
1705
1706 return true;
1707 }
1708
1709 return false;
1710 }
1711
1712 // Sets the device to which the given plug selection belongs to
1713 protected void SetPlugOwner(string selection_name, EntityAI device)
1714 {
1715 if ( m_DeviceByPlugSelection.Contains(selection_name) )
1716 {
1717 m_DeviceByPlugSelection.Set(selection_name, device);
1718 }
1719 }
1720
1721 // Frees the given socket.
1722 // This is only about visualisation.
1723 protected void UnplugCordFromSocket( int socket_to_unplug_ID )
1724 {
1725 EntityAI plug_owner = GetDeviceBySocketID(socket_to_unplug_ID);
1726
1727 if (m_ThisEntityAI && plug_owner)
1728 {
1729 SetDeviceBySocketID(socket_to_unplug_ID, NULL);
1730 string unplugged_selection = SOCKET_ + (socket_to_unplug_ID+1).ToString() + _AVAILABLE;
1731 m_ThisEntityAI.ShowSelection ( unplugged_selection );
1732
1733 string plugged_selection = SOCKET_ + (socket_to_unplug_ID+1).ToString() + _PLUGGED;
1734 m_ThisEntityAI.HideSelection ( plugged_selection );
1735 SetPlugOwner( plugged_selection, NULL );
1736 plug_owner.GetCompEM().SetMySocketID(-1);
1737 }
1738 }
1739
1740 // Sets the state of the device
1741 protected void SetPowered( bool state )
1742 {
1743 m_IsWorking = state;
1744 }
1745
1746 // 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.
1747 protected bool FindAndConsumeEnergy(EntityAI original_caller, float amount, bool ignore_switch_state = false)
1748 {
1749 if ((ignore_switch_state || IsSwitchedOn()) && m_ThisEntityAI && !m_ThisEntityAI.IsRuined())
1750 {
1751 float available_energy = AddEnergy(-amount);
1752
1753 if (available_energy < 0 && IsPlugged())
1754 {
1755 // 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)
1756 EntityAI next_power_source = GetEnergySource();
1757
1758 if (next_power_source && next_power_source != original_caller) // Prevents infinite loop if the power source is the original caller itself
1759 {
1760 return next_power_source.GetCompEM().FindAndConsumeEnergy(original_caller, -available_energy);
1761 }
1762 }
1763
1764 if (available_energy >= 0)
1765 {
1766 return true;
1767 }
1768
1769 return false;
1770 }
1771 else
1772 {
1773 return false;
1774 }
1775 }
1776
1777 // Gets the socket ID this device is powered from.
1778 protected int GetMySocketID()
1779 {
1780 return m_MySocketID;
1781 }
1782
1783 // Sets the socket ID this device is plugged into.
1784 protected void SetMySocketID( int slot_ID )
1785 {
1786 m_MySocketID = slot_ID;
1787 }
1788
1789 void Synch()
1790 {
1791 if (m_ThisEntityAI && g_Game.IsServer())
1792 m_ThisEntityAI.SetSynchDirty();
1793 }
1794
1796 {
1797 m_LastUpdateTime = 0;
1798 }
1799
1804
1806 {
1807 return g_Game.GetTime();
1808 }
1809
1810 // Updates the device's state of power. This function is visualized in the diagram at DayZ Confluence >> Camping & Squatting >> Electricity >> Energy Manager functionalities
1812 {
1813 /*
1814 vector pos = m_ThisEntityAI.GetPosition();
1815 string debug_message = "Object " + m_ThisEntityAI.GetType() + " | Energy: " + GetEnergy() + " | IsAtReach: " + (IsEnergySourceAtReach(pos)).ToString();
1816 Print(debug_message);
1817 */
1818
1819 if ( !m_IsPassiveDevice )
1820 {
1821 // 'm_ThisEntityAI' and 'this' must be checked because this method is caled from a timer
1822 if (m_ThisEntityAI && this && IsSwitchedOn() && !m_ThisEntityAI.IsRuined() && CheckWetness() && m_CanWork && !g_Game.IsMissionMainMenu())
1823 {
1824 bool was_powered = IsWorking();
1825 float consumed_energy_coef;
1826 // Make sure to use only as much % of energy as needed since this function can be called at random.
1827
1828 if ( m_LastUpdateTime == 0 )
1829 {
1831 consumed_energy_coef = 1.0;
1832 }
1833 else
1834 {
1835 float updatetime = GetCurrentUpdateTime();
1836 float time = updatetime - m_LastUpdateTime;
1837 consumed_energy_coef = time / 1000;
1838 }
1839
1840 if (consumed_energy_coef > 0) // Prevents calling of OnWork events when no energy is consumed
1841 {
1843 float consume_energy = GetEnergyUsage() * consumed_energy_coef;
1844 bool has_consumed_enough = true;
1845
1846 if (g_Game.IsServer() || !g_Game.IsMultiplayer()) // single player or server side multiplayer
1847 has_consumed_enough = ConsumeEnergy( consume_energy );
1848
1849 SetPowered( has_consumed_enough );
1850
1851 if ( has_consumed_enough )
1852 {
1853 if ( !was_powered )
1854 {
1855 m_CanStopWork = true;
1857 g_Game.GameScript.CallFunction(m_ThisEntityAI, "OnWorkStart", NULL, 0);
1858 UpdateCanWork();
1859 }
1860
1861 OnWork( consume_energy );
1862 }
1863 else
1864 {
1865 if ( was_powered )
1866 {
1867 if (m_CanStopWork)
1868 {
1869 m_CanStopWork = false;
1871 g_Game.GameScript.CallFunction(m_ThisEntityAI, "OnWorkStop", NULL, 0); // This event is called only once when the device STOPS being powered
1872 UpdateCanWork();
1873
1874 if (m_AutoSwitchOff)
1875 {
1876 SwitchOff();
1877 }
1878 }
1879 }
1880
1881 StopUpdates();
1882 }
1883 }
1884 else
1885 {
1887 }
1888 }
1889 else if (this && m_ThisEntityAI)
1890 {
1891 SetPowered( false );
1892 StopUpdates();
1893
1894 if (m_CanStopWork)
1895 {
1896 m_CanStopWork = false;
1898 g_Game.GameScript.CallFunction(m_ThisEntityAI, "OnWorkStop", NULL, 0); // This event is called only once when the device STOPS being powered
1899 UpdateCanWork();
1900
1901 if (m_AutoSwitchOff)
1902 {
1903 SwitchOff();
1904 }
1905 }
1906 }
1907 }
1908 }
1909}
const int PLUG_ATTACHMENTS_INTO_THIS
const int PLUG_THIS_INTO_ATTACHMENT
const int PLUG_UNDEFINED
const int PLUG_COMMON_APPLIANCE
DayZGame g_Game
Определения DayZGame.c:3942
proto string ToString()
override float Get()
Определения PlayerStatBase.c:134
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:1325
float m_LastUpdateTime
Определения ComponentEnergyManager.c:55
void SetElectricityIconVisibility(bool make_visible)
Energy manager: Sets visibility of the electricity icon (bolt).
Определения ComponentEnergyManager.c:701
void SwitchOn()
Energy manager: Switches ON the device so it starts doing its work if it has enough energy.
Определения ComponentEnergyManager.c:384
float GetEnergyMax()
Energy manager: Returns the maximum amount of energy this device can curently store....
Определения ComponentEnergyManager.c:1297
bool GetPreviousSwitchState()
Определения ComponentEnergyManager.c:891
void UnplugAllDevices()
Energy manager: Unplugs everything directly connected to this device.
Определения ComponentEnergyManager.c:515
void SetMySocketID(int slot_ID)
Определения ComponentEnergyManager.c:1784
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:1561
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:1253
void OnInteractBranch(EntityAI originalCaller, Man player, int system)
Called when the player is interacting with an item containing this energy component,...
Определения ComponentEnergyManager.c:1579
void ComponentEnergyManager()
Определения ComponentEnergyManager.c:83
int GetEnergySourceNetworkIDLow()
Определения ComponentEnergyManager.c:1189
bool IsWorking()
Energy manager: Returns true if this device is working right now.
Определения ComponentEnergyManager.c:938
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:642
Shape DrawArrow(vector from, vector to, float size=0.5, int color=0xFFFFFFFF, float flags=0)
Определения ComponentEnergyManager.c:153
static const string _AVAILABLE
Определения ComponentEnergyManager.c:64
bool m_ConvertEnergyToQuantity
Определения ComponentEnergyManager.c:36
void SetDebugPlugs(bool newVal)
Определения ComponentEnergyManager.c:371
void GetCompatiblePlugTypes(out TIntArray IDs)
Определения ComponentEnergyManager.c:627
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:550
bool HasFreeSocket(int socket_id=-1)
Energy manager: Returns true if this device has any free socket to receive a plug....
Определения ComponentEnergyManager.c:955
ref Timer m_UpdateQuantityTimer
Определения ComponentEnergyManager.c:74
float GetWetnessExposure()
Returns wetness exposure value defined in config.
Определения ComponentEnergyManager.c:1247
float m_UpdateInterval
Определения ComponentEnergyManager.c:57
bool m_HasElectricityIcon
Определения ComponentEnergyManager.c:33
void WakeUpWholeBranch(EntityAI original_caller)
Определения ComponentEnergyManager.c:1587
void UnplugDevice(EntityAI device_to_unplug)
Energy manager: Unplugs the given device from this one.
Определения ComponentEnergyManager.c:460
bool CheckWetness()
Energy manager: Checks if this device is being stopped from working by its wetness level....
Определения ComponentEnergyManager.c:867
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:740
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:450
static bool m_DebugPlugs
Определения ComponentEnergyManager.c:21
bool PlugInDevice(EntityAI device_to_plug, int socket_id=-1)
Определения ComponentEnergyManager.c:1682
void SetAttachmentAction(int new_action_type)
Определения ComponentEnergyManager.c:660
bool FindAndConsumeEnergy(EntityAI original_caller, float amount, bool ignore_switch_state=false)
Определения ComponentEnergyManager.c:1747
ref Timer m_DebugUpdate
Определения ComponentEnergyManager.c:75
void OnEnergyAdded()
Energy manager: Called when energy was added on this device.
Определения ComponentEnergyManager.c:1531
void UnplugCordFromSocket(int socket_to_unplug_ID)
Определения ComponentEnergyManager.c:1723
float AddEnergy(float added_energy)
Energy manager: Adds energy to this device and clamps it within its min/max storage limits....
Определения ComponentEnergyManager.c:1265
const float DEFAULT_UPDATE_INTERVAL
Определения ComponentEnergyManager.c:20
int GetEnergySourceStorageIDb4()
Определения ComponentEnergyManager.c:1183
void UnplugThis()
Energy manager: Unplugs this device from its power source.
Определения ComponentEnergyManager.c:503
float GetCurrentUpdateTime()
Определения ComponentEnergyManager.c:1805
int GetPluggedDevicesCount()
Energy manager: Returns the number of devices plugged into this one.
Определения ComponentEnergyManager.c:1201
void ClearLastUpdateTime()
Определения ComponentEnergyManager.c:1795
void SetCordLength(float new_length)
Energy manager: Changes the length of the virtual power cord.
Определения ComponentEnergyManager.c:648
void SetEnergySourceClient(EntityAI source)
Определения ComponentEnergyManager.c:688
void SetEnergySource(EntityAI source)
Определения ComponentEnergyManager.c:1659
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:1212
void ~ComponentEnergyManager()
Определения ComponentEnergyManager.c:91
void PlugCordIntoSocket(EntityAI device_to_plug, int socket_id=-1)
Определения ComponentEnergyManager.c:1610
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:1076
void HandleMoveInsideCargo(EntityAI container)
Определения ComponentEnergyManager.c:728
float GetEnergy()
Energy manager: Returns the amount of stored energy this device has.
Определения ComponentEnergyManager.c:1259
int GetPlugType()
Energy manager: Returns plug type. Check \DZ\data\basicDefines.hpp OR \Scripts\Classes\Component_cons...
Определения ComponentEnergyManager.c:1153
bool CanBePluggedInto(EntityAI potential_energy_provider)
Energy manager: Returns true if this device can be plugged into the given energy source....
Определения ComponentEnergyManager.c:1036
bool IsPlugged()
Energy manager: Returns true if this device is plugged into some other device (even if they are OFF o...
Определения ComponentEnergyManager.c:918
EntityAI GetEnergySource()
Energy manager: Returns the energy source this device is plugged into.
Определения ComponentEnergyManager.c:1337
ref array< EntityAI > m_PluggedDevices
Определения ComponentEnergyManager.c:70
void OnAttachmentRemoved(EntityAI elec_device)
Определения ComponentEnergyManager.c:1491
EntityAI GetThisEntityAI()
Определения ComponentEnergyManager.c:172
void OnWork(float consumed_energy)
Определения ComponentEnergyManager.c:1405
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:1377
float m_ReduceMaxEnergyByDamageCoef
Определения ComponentEnergyManager.c:52
int GetEnergySourceNetworkIDHigh()
Определения ComponentEnergyManager.c:1195
bool IsPassive()
Energy manager: Returns true if this device is set to be passive. False if otherwise.
Определения ComponentEnergyManager.c:912
Shape m_DebugPlugArrow
Определения ComponentEnergyManager.c:22
bool HasConversionOfEnergyToQuantity()
Energy manager: Returns true if this item automatically converts its energy to quantity.
Определения ComponentEnergyManager.c:1055
void SetPowered(bool state)
Определения ComponentEnergyManager.c:1741
void SetPlugType(int new_type)
Определения ComponentEnergyManager.c:654
void StoreEnergySourceIDs(int b1, int b2, int b3, int b4)
Определения ComponentEnergyManager.c:633
int GetEnergySourceStorageIDb2()
Определения ComponentEnergyManager.c:1171
ref TIntArray m_CompatiblePlugTypes
Определения ComponentEnergyManager.c:68
void UpdatePlugState()
Energy manager: Unplugs this device when it's necesarry.
Определения ComponentEnergyManager.c:599
void OnAttachmentAdded(EntityAI elec_device)
Определения ComponentEnergyManager.c:1470
void OnIsPlugged(EntityAI source_device)
Определения ComponentEnergyManager.c:1412
EntityAI m_Sockets[MAX_SOCKETS_COUNT]
Определения ComponentEnergyManager.c:78
string GetCordTextureFile()
Energy manager: Returns path to the cord texture file.
Определения ComponentEnergyManager.c:1371
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:1123
void SetEnergy(float new_energy)
Energy manager: Sets stored energy for this device. It ignores the min/max limit!
Определения ComponentEnergyManager.c:534
void SetPlugOwner(string selection_name, EntityAI device)
Определения ComponentEnergyManager.c:1713
float GetCordLength()
Energy manager: Returns the length of the virtual power cord.
Определения ComponentEnergyManager.c:1331
EntityAI GetPlugOwner(string plug_selection_name)
Energy manager: Returns the device to which the given plug selection belongs to.
Определения ComponentEnergyManager.c:1349
int GetAttachmentAction()
Определения ComponentEnergyManager.c:1159
bool CanWork(float test_energy=-1)
Energy manager: Checks whenever this device can do work or not.
Определения ComponentEnergyManager.c:781
EntityAI GetPluggedDevice()
Energy manager: Returns a device which is plugged into this one. If there are more devices to choose ...
Определения ComponentEnergyManager.c:1360
void UpdateSelections()
Energy manager: Shows/Hides all selections this system works with. Call this if something is wrong wi...
Определения ComponentEnergyManager.c:556
void OnIsUnplugged(EntityAI last_energy_source)
Определения ComponentEnergyManager.c:1429
bool GetRestorePlugState()
Определения ComponentEnergyManager.c:746
bool HasVisibleSocketsInInventory()
Определения ComponentEnergyManager.c:1117
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:903
override int GetCompType()
Определения ComponentEnergyManager.c:322
void RestorePlugState(bool state)
Определения ComponentEnergyManager.c:528
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:1224
void SwitchOff()
Energy manager: Switches OFF the device.
Определения ComponentEnergyManager.c:415
void OnOwnSocketReleased(EntityAI device)
Определения ComponentEnergyManager.c:1453
array< EntityAI > GetPoweredDevices()
Energy manager: Returns an array of devices which are plugged into this one and are turned on.
Определения ComponentEnergyManager.c:1383
override void Event_OnAwake()
Определения ComponentEnergyManager.c:178
bool ConsumeEnergy(float amount)
Energy manager: Consumes the given amount of energy. If there is not enough of stored energy in this ...
Определения ComponentEnergyManager.c:925
float m_EnergyStorageMax
Определения ComponentEnergyManager.c:51
void RememberLastUpdateTime()
Определения ComponentEnergyManager.c:1800
bool CanSwitchOn()
Energy manager: Checks if the device can be switched ON.
Определения ComponentEnergyManager.c:765
void ResetEnergyUsage()
Energy manager: Resets energy usage to default (config) value.
Определения ComponentEnergyManager.c:672
int m_EnergySourceNetworkIDHigh
Определения ComponentEnergyManager.c:46
int GetEnergySourceStorageIDb1()
Определения ComponentEnergyManager.c:1165
bool IsPlugCompatible(int plug_ID)
Energy manager: Checks if the given plug is compatible with this device's socket. Used by CanReceiveP...
Определения ComponentEnergyManager.c:985
void SetEnergyUsage(float new_usage)
Energy manager: Changes the energy usage per second.
Определения ComponentEnergyManager.c:666
void OnEnergyConsumed()
Energy manager: Called when energy was consumed on this device.
Определения ComponentEnergyManager.c:1524
void SetCordTextureFile(string new_path)
Определения ComponentEnergyManager.c:682
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:880
int GetSocketsCount()
Energy manager: Returns the count of power sockets (whenever used or not)
Определения ComponentEnergyManager.c:1147
void SetDeviceBySocketID(int id, EntityAI plugged_device)
Energy manager: Stores the device which is plugged into the given socket ID.
Определения ComponentEnergyManager.c:694
void UpdateSocketSelections(int socket_id, EntityAI device_to_plug)
Определения ComponentEnergyManager.c:1638
float GetUpdateInterval()
Energy manager: Returns the update interval of this device.
Определения ComponentEnergyManager.c:1235
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:1049
void OnOwnSocketTaken(EntityAI device)
Определения ComponentEnergyManager.c:1437
void OnDeviceDestroyed()
Определения ComponentEnergyManager.c:328
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:752
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:1343
float GetEnergyMaxPristine()
Energy manager: Returns the maximum amount of energy this device can store. It's damage is NOT taken ...
Определения ComponentEnergyManager.c:1320
bool IsSwitchedOn()
Energy manager: Returns state of the switch. Whenever the device is working or not does not matter....
Определения ComponentEnergyManager.c:897
int GetEnergySourceStorageIDb3()
Определения ComponentEnergyManager.c:1177
bool HasEnoughStoredEnergy()
Energy manager: Returns true if this device has enough of stored energy for its own use.
Определения ComponentEnergyManager.c:944
bool CanReceivePlugFrom(EntityAI device_to_plug)
Energy manager: Returns true if this device can receive power plug of the other device.
Определения ComponentEnergyManager.c:1015
Определения Component.c:16
Wrapper class for managing sound through SEffectManager.
Определения EffectSound.c:5
Определения EnMath.c:7
Определения DayZPlayerImplement.c:39
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
Определения CachedEquipmentStorage.c:4
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:222
Определения EnConvert.c:119
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:714
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
Определения 3_Game/DayZ/tools/tools.c:8