123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845 |
- //-----------------------------
- // ENERGY MANAGER
- //-----------------------------
- /*
- Author: Boris Vacula
- Documentation can be found at DayZ Confluence >> Camping & Squatting >> Electricity >> Energy Manager functionalities
- This system controls storage, spending and sharing of energy between instances.
- Every EntityAI object which uses this API gains these functions:
- -It can store some amout of energy
- -It can use this amount of energy for any kind of functionality
- -It can share this energy with other devices plugged into it
- -It will have an ON/OFF switch
- */
- class ComponentEnergyManager : Component
- {
- protected const float DEFAULT_UPDATE_INTERVAL = 15;
- protected static bool m_DebugPlugs = false; //true; // Use this to toggle visualisation of plug connections
- protected Shape m_DebugPlugArrow;
-
- protected bool m_IsSwichedOn;
- protected bool m_IsSwichedOnPreviousState; // Necesarry due to synchronization of m_IsSwichedOn
- protected bool m_IsPassiveDevice;
- protected bool m_IsWorking;
- protected bool m_CanWork;
- protected bool m_CanStopWork;
- 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.
- protected bool m_AutoSwitchOff;
- protected bool m_ShowSocketsInInventory;
- protected bool m_HasElectricityIcon; // Electricity icon over the item in inventory
- protected bool m_AutoSwitchOffWhenInCargo;
- protected bool m_IsPlugged; // Synchronized variable
- protected bool m_ConvertEnergyToQuantity;
-
- protected int m_MySocketID = -1;
- protected int m_PlugType;
- protected int m_EnergySourceStorageIDb1; // Storage persistence ID
- protected int m_EnergySourceStorageIDb2; // Storage persistence ID
- protected int m_EnergySourceStorageIDb3; // Storage persistence ID
- protected int m_EnergySourceStorageIDb4; // Storage persistence ID
- protected int m_AttachmentActionType;
- protected int m_EnergySourceNetworkIDLow = -1; // Network ID
- protected int m_EnergySourceNetworkIDHigh = -1; // Network ID
-
- protected float m_EnergyUsage;
- protected float m_Energy;
- protected float m_EnergyAtSpawn;
- protected float m_EnergyStorageMax;
- protected float m_ReduceMaxEnergyByDamageCoef;
- protected float m_SocketsCount;
- protected float m_CordLength;
- protected float m_LastUpdateTime;
- protected float m_WetnessExposure;
- protected float m_UpdateInterval; // Interval of OnWork(...) calls and device updates.
-
- protected string m_CordTextureFile;
-
- // Concatenated strings for p3d selections
- protected static const string SOCKET_ = "socket_";
- protected static const string _PLUGGED = "_plugged";
- protected static const string _AVAILABLE = "_available";
- static const string SEL_CORD_PLUGGED = "cord_plugged";
- static const string SEL_CORD_FOLDED = "cord_folded";
-
- protected ref TIntArray m_CompatiblePlugTypes;
- EntityAI m_EnergySource; // Energy source can be any EntityAI object
- ref array<EntityAI> m_PluggedDevices;
- ref map<string,EntityAI> m_DeviceByPlugSelection;
-
- ref Timer m_UpdateTimer;
- ref Timer m_UpdateQuantityTimer;
- ref Timer m_DebugUpdate;
-
- const int MAX_SOCKETS_COUNT = 4;
- EntityAI m_Sockets[MAX_SOCKETS_COUNT];
-
-
- // Constructor
- void ComponentEnergyManager()
- {
- // Disable debug arrows on public release, so that they don't use their timers.
- #ifndef DEVELOPER
- m_DebugPlugs = false;
- #endif
- }
-
- void ~ComponentEnergyManager()
- {
- if (m_DebugPlugArrow)
- {
- m_DebugPlugArrow.Destroy();
- m_DebugPlugArrow = NULL;
- }
- }
- // Initialization. Energy Manager is ready.
- override void Event_OnInit()
- {
- m_ThisEntityAI.m_EM = this;
- GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnInitEnergy", NULL, 0);
- }
-
- // Update debug arrows
- void DebugUpdate()
- {
- if ( GetDebugPlugs() )
- {
- if ( GetGame().IsMultiplayer() && GetGame().IsServer() )
- {
- if (m_DebugUpdate)
- m_DebugUpdate.Stop();
-
- return;
- }
-
- if (m_DebugPlugArrow)
- {
- m_DebugPlugArrow.Destroy();
- m_DebugPlugArrow = NULL;
- }
-
- if ( GetEnergySource() )
- {
- vector from = GetEnergySource().GetPosition() + "0 0.1 0";
- vector to = m_ThisEntityAI.GetPosition() + "0 0.1 0";
-
- //No need to draw an arrow in this situation as it would not be visible
- if ( vector.DistanceSq(from, to) == 0 )
- return;
-
- if ( m_ThisEntityAI.GetType() == "BarbedWire" ) // Special case for debugging of electric fences. Temporal code until offsets in fences are fixed.
- {
- EntityAI BBB = m_ThisEntityAI.GetHierarchyParent();
-
- if ( BBB && BBB.GetType() == "Fence" )
- {
- to = to + "0 -1.3 0";
- }
- }
-
- m_DebugPlugArrow = DrawArrow( from, to );
- }
- }
- }
-
- Shape DrawArrow(vector from, vector to, float size = 0.5, int color = 0xFFFFFFFF, float flags = 0)
- {
- vector dir = to - from;
- dir.Normalize();
- vector dir1 = dir * size;
- size = size * 0.5;
-
- vector dir2 = dir.Perpend() * size;
-
- vector pts[5];
- pts[0] = from;
- pts[1] = to;
- pts[2] = to - dir1 - dir2;
- pts[3] = to - dir1 + dir2;
- pts[4] = to;
-
- return Shape.CreateLines(color, flags, pts, 5);
- }
- EntityAI GetThisEntityAI()
- {
- return m_ThisEntityAI;
- }
-
- // Prepare everything
- override void Event_OnAwake()
- {
- string cfg_item = "CfgVehicles " + m_ThisEntityAI.GetType();
- string cfg_energy_manager = cfg_item + " EnergyManager ";
-
- // Read all config parameters
- m_EnergyUsage = GetGame().ConfigGetFloat(cfg_energy_manager + "energyUsagePerSecond");
- bool switch_on = GetGame().ConfigGetFloat(cfg_energy_manager + "switchOnAtSpawn");
- m_AutoSwitchOff = GetGame().ConfigGetFloat(cfg_energy_manager + "autoSwitchOff");
- m_HasElectricityIcon = GetGame().ConfigGetFloat(cfg_energy_manager + "hasIcon");
- m_AutoSwitchOffWhenInCargo = GetGame().ConfigGetFloat(cfg_energy_manager + "autoSwitchOffWhenInCargo");
-
- m_EnergyAtSpawn = GetGame().ConfigGetFloat(cfg_energy_manager + "energyAtSpawn");
- m_Energy = m_EnergyAtSpawn;
- m_EnergyStorageMax = GetGame().ConfigGetFloat(cfg_energy_manager + "energyStorageMax");
- m_ReduceMaxEnergyByDamageCoef = GetGame().ConfigGetFloat(cfg_energy_manager + "reduceMaxEnergyByDamageCoef");
- m_SocketsCount = GetGame().ConfigGetFloat(cfg_energy_manager + "powerSocketsCount");
-
- m_IsPassiveDevice = GetGame().ConfigGetFloat(cfg_energy_manager + "isPassiveDevice");
- m_CordLength = GetGame().ConfigGetFloat(cfg_energy_manager + "cordLength");
- m_PlugType = GetGame().ConfigGetFloat(cfg_energy_manager + "plugType");
-
- m_AttachmentActionType = GetGame().ConfigGetFloat(cfg_energy_manager + "attachmentAction");
- m_WetnessExposure = GetGame().ConfigGetFloat(cfg_energy_manager + "wetnessExposure");
-
- float update_interval = GetGame().ConfigGetFloat(cfg_energy_manager + "updateInterval");
-
- m_ConvertEnergyToQuantity = GetGame().ConfigGetFloat(cfg_energy_manager + "convertEnergyToQuantity");
-
-
- // Check if energy->quantity converion is configured properly
- float cfg_max_quantity = GetGame().ConfigGetFloat (cfg_item + " varQuantityMax");
-
- if (m_ConvertEnergyToQuantity && cfg_max_quantity <= 0)
- {
- 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!";
- Error(error);
- m_ConvertEnergyToQuantity = false;
- }
- else
- {
- if (m_ConvertEnergyToQuantity)
- {
- if (!m_UpdateQuantityTimer)
- m_UpdateQuantityTimer = new Timer( CALL_CATEGORY_SYSTEM );
-
- m_UpdateQuantityTimer.Run( 0.3 , this, "OnEnergyAdded", NULL, false);
- }
- }
-
- // Set update interval
- if ( update_interval <= 0 )
- update_interval = DEFAULT_UPDATE_INTERVAL;
-
- SetUpdateInterval( update_interval );
-
- // If energyAtSpawn is present, then use its value for energyStorageMax if that cfg param is not present (for convenience's sake)
- string cfg_check_energy_limit = cfg_energy_manager + "energyStorageMax";
-
- if ( !GetGame().ConfigIsExisting (cfg_check_energy_limit) && m_Energy > 0 )
- {
- m_EnergyStorageMax = m_Energy;
- }
-
- // Fill m_CompatiblePlugTypes
- string cfg_check_plug_types = cfg_energy_manager + "compatiblePlugTypes";
-
- if ( GetGame().ConfigIsExisting (cfg_check_plug_types) )
- {
- m_CompatiblePlugTypes = new TIntArray;
- GetGame().ConfigGetIntArray(cfg_check_plug_types, m_CompatiblePlugTypes);
- }
-
- if (GetSocketsCount() > 0)
- m_PluggedDevices = new array<EntityAI>;
-
- if ( m_CordLength < 0 )
- {
- m_CordLength = 0;
- string error_message_cord = "Warning! " + m_ThisEntityAI.GetType() + ": config parameter 'cordLength' is less than 0! Cord length should not be negative!";
- DPrint(error_message_cord);
- }
-
- if (GetSocketsCount() > 0)
- {
- m_DeviceByPlugSelection = new map<string,EntityAI>;
- // Prepare the m_DeviceByPlugSelection
- string cfg_animation_sources = "cfgVehicles " + m_ThisEntityAI.GetType() + " " + "AnimationSources ";
- int animation_sources_count = GetGame().ConfigGetChildrenCount(cfg_animation_sources);
-
- for (int i_selection = 0; i_selection < animation_sources_count; i_selection++)
- {
- // TO DO: This could be optimized so not all selections on item are considered as plug/socket selections.
- string selection;
- GetGame().ConfigGetChildName(cfg_animation_sources, i_selection, selection);
- m_DeviceByPlugSelection.Set(selection, NULL);
- }
- }
-
-
-
- // Prepare sockets
- if ( m_SocketsCount > MAX_SOCKETS_COUNT )
- {
- m_SocketsCount = MAX_SOCKETS_COUNT;
- 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!";
- DPrint(error_message_sockets);
- }
-
- m_Sockets[MAX_SOCKETS_COUNT]; // Handles selections for plugs in the sockets. Feel free to change the limit if needed.
-
- GetGame().ConfigGetText(cfg_energy_manager + "cordTextureFile", m_CordTextureFile);
-
- if ( switch_on )
- {
- SwitchOn();
- }
-
- for ( int i = 0; i <= GetSocketsCount(); ++i )
- {
- m_ThisEntityAI.HideSelection ( SOCKET_ + i.ToString() + _PLUGGED );
- }
-
- // Show/hide inventory sockets
- m_ShowSocketsInInventory = false;
- if ( GetSocketsCount() > 0 && IsPlugCompatible(PLUG_COMMON_APPLIANCE) && m_ThisEntityAI.GetType() != "MetalWire" ) // metal wire filter is hopefully temporal.
- {
- m_ShowSocketsInInventory = true;
- }
-
- m_CanWork = HasEnoughStoredEnergy();
-
- m_ThisEntityAI.HideSelection( SEL_CORD_PLUGGED );
-
-
- #ifdef DIAG_DEVELOPER
- GetGame().m_EnergyManagerArray.Insert( this );
- #endif
- }
- // Returns the type of this component
- override int GetCompType()
- {
- return COMP_TYPE_ENERGY_MANAGER;
- }
-
- // When the object is deleted
- void OnDeviceDestroyed()
- {
- bool was_working = m_ThisEntityAI.GetCompEM().IsWorking();
-
- SwitchOff();
- UnplugAllDevices();
- UnplugThis();
- SetPowered( false );
-
- if ( was_working )
- m_ThisEntityAI.OnWorkStop();
- ;
- }
-
- //Restart the debug timer when relogging
- void RefreshDebug()
- {
- if ( m_DebugPlugs )
- {
- if ( !m_DebugUpdate )
- m_DebugUpdate = new Timer( CALL_CATEGORY_SYSTEM );
-
- if ( !m_DebugUpdate.IsRunning() )
- m_DebugUpdate.Run(0.01, this, "DebugUpdate", NULL, true);
- }
- else
- {
- if ( m_DebugPlugArrow )
- {
- m_DebugPlugArrow.Destroy();
- m_DebugPlugArrow = NULL;
- }
- }
- }
-
- bool GetDebugPlugs()
- {
- return m_DebugPlugs;
- }
-
- void SetDebugPlugs( bool newVal )
- {
- m_DebugPlugs = newVal;
- RefreshDebug();
- }
- //======================================================================================
- // PUBLIC FUNCTIONS
- // Use these to control the Energy Manager
- // Functions are in order of their return value: void, bool, int, float, string, array.
- //======================================================================================
- //! Energy manager: Switches ON the device so it starts doing its work if it has enough energy.
- void SwitchOn()
- {
- m_IsSwichedOnPreviousState = m_IsSwichedOn;
-
- if (GetGame().IsServer() || !GetGame().IsMultiplayer())
- {
- if ( CanSwitchOn() )
- {
- m_IsSwichedOn = true;
- Synch();
-
- DeviceUpdate(); // 'Wake up' this device now
- StartUpdates();
-
- // 'Wakes up' all connected devices
- WakeUpWholeBranch( m_ThisEntityAI );
-
- UpdateCanWork();
-
- // Call event
- GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOn", NULL, 0);
- }
- }
-
- 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.)
- {
- GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOn", NULL, 0);
- }
- }
- //! Energy manager: Switches OFF the device.
- void SwitchOff()
- {
- m_IsSwichedOnPreviousState = m_IsSwichedOn;
-
- if (GetGame().IsServer() || !GetGame().IsMultiplayer())
- {
- if ( CanSwitchOff() )
- {
- m_IsSwichedOn = false;
- Synch();
-
- if ( IsWorking() )
- {
- StopUpdates();
- DeviceUpdate();
- }
-
- // 'Wakes up' all connected devices
- WakeUpWholeBranch( m_ThisEntityAI );
- UpdateCanWork();
-
- // Call event
- GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOff", NULL, 0);
- }
- }
-
- if ( !GetGame().IsServer() && GetGame().IsMultiplayer() )
- {
- m_IsSwichedOn = false;
- GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnSwitchOff", NULL, 0);
- }
- }
- //! Energy manager: Changes the status of this device. When it's passive (true), the main timer and OnWork events are not used.
- void SetPassiveState(bool state = true)
- {
- m_IsPassiveDevice = state;
- if ( !m_IsPassiveDevice )
- {
- DeviceUpdate();
- }
- }
- //! Energy manager: Unplugs the given device from this one.
- void UnplugDevice(EntityAI device_to_unplug)
- {
- if ( GetGame() )
- {
- int indexStart = GetPluggedDevicesCount() - 1;
- bool deviceFound = false;
-
- for (int i = indexStart; i >= 0; --i)
- {
- EntityAI plugged_device = GetPluggedDevices().Get(i);
-
- if (plugged_device == device_to_unplug)
- {
- GetPluggedDevices().Remove(i);
- deviceFound = true;
- break;
- }
- }
-
- if (deviceFound)
- {
- int socket_ID = device_to_unplug.GetCompEM().GetMySocketID();
- UnplugCordFromSocket(socket_ID);
- device_to_unplug.GetCompEM().SetEnergySource(null);
- device_to_unplug.GetCompEM().DeviceUpdate();
- device_to_unplug.GetCompEM().StartUpdates();
- device_to_unplug.GetCompEM().WakeUpWholeBranch(m_ThisEntityAI);
-
- if (m_DebugPlugs && m_DebugPlugArrow)
- {
- m_DebugPlugArrow.Destroy();
- m_DebugPlugArrow = null;
- }
-
- OnOwnSocketReleased(device_to_unplug);
- device_to_unplug.GetCompEM().OnIsUnplugged(m_ThisEntityAI);
- device_to_unplug.ShowSelection(SEL_CORD_FOLDED);
- device_to_unplug.HideSelection(SEL_CORD_PLUGGED);
- }
- }
- }
- //! Energy manager: Unplugs this device from its power source
- void UnplugThis()
- {
- if (GetGame())
- {
- if (GetEnergySource())
- {
- GetEnergySource().GetCompEM().UnplugDevice(m_ThisEntityAI);
- }
- }
- }
-
- //! Energy manager: Unplugs everything directly connected to this device
- void UnplugAllDevices()
- {
- if ( GetPluggedDevices() ) // This check is necesarry in case this function is called before initialization
- {
- int indexStart = GetPluggedDevicesCount() - 1;
- for (int i = indexStart; i >= 0; --i)
- {
- UnplugDevice(GetPluggedDevices().Get(i));
- }
- }
- }
-
- // Used only for storing of the plug's state through server restart
- void RestorePlugState(bool state)
- {
- m_RestorePlugState = state;
- }
- //! Energy manager: Sets stored energy for this device. It ignores the min/max limit!
- void SetEnergy(float new_energy)
- {
- if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // Client can't change energy value.
- {
- m_ThisEntityAI.SetWeightDirty();
- float old_energy = m_Energy;
- m_Energy = new_energy;
-
- if ( old_energy - GetEnergyUsage() <= 0 || (old_energy != new_energy && Math.Min(old_energy,new_energy) <= 0) )
- {
- UpdateCanWork();
- }
- }
- }
-
- //! Energy manager: Sets stored energy for this device between 0 and MAX based on relative input value between 0 and 1
- void SetEnergy0To1(float energy01)
- {
- SetEnergy( Math.Lerp(0, GetEnergyMax(),energy01));
- }
- //! Energy manager: Shows/Hides all selections this system works with. Call this if something is wrong with selections (like during Init and Restore event in config)
- void UpdateSelections()
- {
- // Lets update sockets, if there are any
- int slots_c = GetSocketsCount();
-
- for ( int i = 0; i < slots_c; ++i )
- {
- EntityAI plug_owner = GetDeviceBySocketID(i);
-
- if ( plug_owner )
- {
- string plugged_selection = SOCKET_ + (i+1).ToString() + _PLUGGED;
- string available_selection = SOCKET_ + (i+1).ToString() + _AVAILABLE;
- m_ThisEntityAI.ShowSelection ( plugged_selection );
- m_ThisEntityAI.HideSelection ( available_selection );
- string texture_path = plug_owner.GetCompEM().GetCordTextureFile();
- int selection_index = m_ThisEntityAI.GetHiddenSelectionIndex( plugged_selection );
- m_ThisEntityAI.SetObjectTexture(selection_index, texture_path );
- }
- else
- {
- m_ThisEntityAI.ShowSelection ( SOCKET_ + (i+1).ToString() + _AVAILABLE );
- m_ThisEntityAI.HideSelection ( SOCKET_ + (i+1).ToString() + _PLUGGED );
- }
- }
-
- // Now lets update the cord/plug state
- if ( GetEnergySource() )
- {
- m_ThisEntityAI.ShowSelection ( SEL_CORD_PLUGGED );
- m_ThisEntityAI.HideSelection ( SEL_CORD_FOLDED );
- }
- else
- {
- m_ThisEntityAI.ShowSelection ( SEL_CORD_FOLDED );
- m_ThisEntityAI.HideSelection ( SEL_CORD_PLUGGED );
- }
- }
- //! Energy manager: Unplugs this device when it's necesarry
- void UpdatePlugState()
- {
- if (m_ThisEntityAI.GetCompEM().GetEnergySource())
- {
- EntityAI player = m_ThisEntityAI.GetHierarchyRootPlayer();
- // Check if the item is held in hands during advanced placement
- if (player)
- {
- // Measure distance from the player
- vector playerPosition = player.GetPosition();
- if (!IsEnergySourceAtReach(playerPosition, 5))
- UnplugThis();
- }
- else
- {
- // Measure distance from the device
- vector itemPosition = m_ThisEntityAI.GetPosition();
-
- if (m_ThisEntityAI.GetHierarchyParent())
- itemPosition = m_ThisEntityAI.GetHierarchyParent().GetPosition();
-
- if (!IsEnergySourceAtReach(itemPosition))
- UnplugThis();
- }
- }
- }
- // Returns an array of plug types this device can accept
- void GetCompatiblePlugTypes(out TIntArray IDs)
- {
- IDs = m_CompatiblePlugTypes;
- }
- // Stores IDs of the energy source.
- void StoreEnergySourceIDs(int b1, int b2, int b3, int b4)
- {
- m_EnergySourceStorageIDb1 = b1;
- m_EnergySourceStorageIDb2 = b2;
- m_EnergySourceStorageIDb3 = b3;
- m_EnergySourceStorageIDb4 = b4;
- }
-
- //! Energy manager: Changes the maximum amount of energy this device can store (when pristine).
- void SetEnergyMaxPristine(float new_limit)
- {
- m_EnergyStorageMax = new_limit;
- }
-
- //! Energy manager: Changes the length of the virtual power cord.
- void SetCordLength( float new_length )
- {
- m_CordLength = new_length;
- }
-
- // Sets the plug type (for plug -> socket compatibility checks).
- void SetPlugType( int new_type )
- {
- m_PlugType = new_type;
- }
-
- // Sets the new attachment action type.
- void SetAttachmentAction( int new_action_type )
- {
- m_AttachmentActionType = new_action_type;
- }
-
- //! Energy manager: Changes the energy usage per second.
- void SetEnergyUsage( float new_usage )
- {
- m_EnergyUsage = new_usage;
- }
-
- //! Energy manager: Resets energy usage to default (config) value.
- void ResetEnergyUsage()
- {
- string cfg_energy_usage = "CfgVehicles " + m_ThisEntityAI.GetType() + " EnergyManager ";
- m_EnergyUsage = GetGame().ConfigGetFloat (cfg_energy_usage + "energyUsagePerSecond");
- }
-
- // Sets path to the cord texture file.
- void SetCordTextureFile( string new_path )
- {
- m_CordTextureFile = new_path;
- }
-
- // Sets energy source. Intended to be called only on client through RPC.
- void SetEnergySourceClient( EntityAI source )
- {
- SetEnergySource(source);
- }
-
- //! Energy manager: Stores the device which is plugged into the given socket ID.
- void SetDeviceBySocketID(int id, EntityAI plugged_device)
- {
- m_Sockets[id] = plugged_device;
- }
-
-
- //! Energy manager: Sets visibility of the electricity icon (bolt).
- void SetElectricityIconVisibility( bool make_visible )
- {
- m_HasElectricityIcon = make_visible;
- }
-
- // 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.
- void UpdateCanWork()
- {
- if (GetGame().IsServer() || !GetGame().IsMultiplayer())
- {
- bool current_state = CanWork();
-
- if (current_state != m_CanWork)
- {
- m_CanWork = current_state;
- Synch();
-
- if ( m_ThisEntityAI && m_ThisEntityAI.GetHierarchyParent() && m_ThisEntityAI.GetHierarchyParent().GetCompEM() )
- {
- m_ThisEntityAI.GetHierarchyParent().GetCompEM().UpdateCanWork();
- }
- }
- }
- }
-
- void HandleMoveInsideCargo(EntityAI container)
- {
- if ( m_AutoSwitchOffWhenInCargo )
- {
- if (IsSwitchedOn())
- {
- SwitchOff();
- }
- }
- }
-
- //! Energy manager: Sets the interval of the OnWork(...) calls. Changing this value does not change the rate of energy consumption.
- void SetUpdateInterval( float value )
- {
- m_UpdateInterval = value;
- }
-
- // Returns true if this device was plugged into something at the end of previous session
- bool GetRestorePlugState()
- {
- return m_RestorePlugState;
- }
-
- //! Energy manager: Attempts to plug this device into the energy_source. Returns true if the action was successfull, or false if not (due to plug incompatibility or no free socket on the receiver). The ID of the power socket is chosen automatically unless optional parameter socket_id is used (starting from 0). If the given ID is not free then a free socket is found.
- bool PlugThisInto(EntityAI energy_source, int socket_id = -1)
- {
- return energy_source.GetCompEM().PlugInDevice(m_ThisEntityAI, socket_id);
- }
-
- //! Energy manager: Checks if the device can be switched ON
- bool CanSwitchOn()
- {
- if ( !IsSwitchedOn() )
- {
- return true;
- }
-
- return false;
- }
-
- /**
- \brief Energy manager: Checks whenever this device can do work or not.
- \param test_energy \p float optional parameter will overwite the default energy consumption value of this device.
- \return \p bool Returns true if this device will work when it's switched on. Otherwise it returns false.
- */
- bool CanWork( float test_energy = -1)
- {
- if ( GetGame().IsMultiplayer() && GetGame().IsClient() )
- {
- return m_CanWork;
- }
-
- if (m_ThisEntityAI && m_ThisEntityAI.IsRuined())
- {
- return false;
- }
-
- // Check if the power source(s) (which can be serially connected) can provide needed energy.
- float energy_usage = test_energy;
- float gathered_energy = GetEnergy();
- EntityAI energy_source = GetEnergySource();
-
- if (energy_usage == -1)
- {
- energy_usage = GetEnergyUsage();
- }
-
- if ( !CheckWetness() )
- {
- return false;
- }
-
- if (gathered_energy <= 0 && energy_usage <= 0) //empty power source
- {
- return false;
- }
-
- int cycle_limit = 500; // Sanity check to definitely avoid infinite cycles
-
- while ( gathered_energy < energy_usage ) // Look for energy source if we don't have enough stored energy
- {
- // Safetycheck!
- if (cycle_limit > 0)
- {
- cycle_limit--;
- }
- else
- {
- DPrint("Energy Manager ERROR: The 'cycle_limit' safety break had to be activated to prevent possible game freeze. Dumping debug information...");
- //Print(m_ThisEntityAI);
- //Print(this);
- //Print(energy_source);
-
- if (energy_source.GetCompEM())
- {
- //Print(energy_source.GetCompEM());
- }
-
- //Print(gathered_energy);
- //Print(energy_usage);
-
- //Print(m_ThisEntityAI.GetPosition());
-
- if (energy_source)
- {
- //Print(energy_source.GetPosition());
- }
-
- //Print("End of the 'cycle_limit' safety break ^ ");
-
- return false;
- }
- // ^ Safetycheck!
-
- if ( energy_source && energy_source != m_ThisEntityAI && !energy_source.IsRuined() && energy_source.GetCompEM() && energy_source.GetCompEM().IsSwitchedOn() && energy_source.GetCompEM().CheckWetness() )
- {
- gathered_energy = gathered_energy + energy_source.GetCompEM().GetEnergy();
- energy_source = energy_source.GetCompEM().GetEnergySource();
- }
- else
- {
- // No power source, no energy.
- return false;
- }
- }
-
- // Enough energy was found
- return true;
- }
- //! Energy manager: Checks if this device is being stopped from working by its wetness level. Returns true when its wetness is not blocking it, false when its to owet to work.
- bool CheckWetness()
- {
- return (m_ThisEntityAI.GetWet() <= 1-m_WetnessExposure);
- }
-
- //! Energy manager: Checks if the device can be switched OFF
- bool CanSwitchOff()
- {
- if ( IsPassive() )
- {
- return false;
- }
-
- return IsSwitchedOn();
- }
- // Returns previous state of the switch.
- bool GetPreviousSwitchState()
- {
- return m_IsSwichedOnPreviousState;
- }
-
- //! Energy manager: Returns state of the switch. Whenever the device is working or not does not matter. Use IsWorking() to account for that as well.
- bool IsSwitchedOn()
- {
- return m_IsSwichedOn;
- }
- //! Energy manager: Returns true if the cord of this device is folded. Returns false if it's plugged.
- bool IsCordFolded()
- {
- if ( IsPlugged() )
- return false;
-
- return true;
- }
-
- //! Energy manager: Returns true if this device is set to be passive. False if otherwise.
- bool IsPassive()
- {
- return m_IsPassiveDevice;
- }
- //! Energy manager: Returns true if this device is plugged into some other device (even if they are OFF or ruined). Otherwise it returns false.
- bool IsPlugged()
- {
- return m_IsPlugged;
- }
-
-
- //! Energy manager: Consumes the given amount of energy. If there is not enough of stored energy in this device, then it tries to take it from its power source, if any exists. Returns true if the requested amount of energy was consumed. Otherwise it returns false.
- bool ConsumeEnergy(float amount)
- {
- return FindAndConsumeEnergy(m_ThisEntityAI, amount, true);
- }
- //! Energy manager: Returns true if this device is working right now.
- bool IsWorking()
- {
- return m_IsWorking;
- }
- //! Energy manager: Returns true if this device has enough of stored energy for its own use.
- bool HasEnoughStoredEnergy()
- {
- if ( GetEnergy() > GetEnergyUsage() )
- {
- return true;
- }
-
- return false;
- }
- //! Energy manager: Returns true if this device has any free socket to receive a plug. If optional parameter socket_id is provided then only that socket ID is checked.
- bool HasFreeSocket( int socket_id = -1 )
- {
- if (socket_id == -1)
- {
- int plugged_devices = GetPluggedDevicesCount();
- int plugged_devices_limit = GetSocketsCount();
-
- if ( plugged_devices < plugged_devices_limit )
- {
- return true;
- }
-
- return false;
- }
- else
- {
- EntityAI device = GetDeviceBySocketID(socket_id);
-
- if (device)
- {
- return false;
- }
- else
- {
- return true;
- }
- }
- }
- //! Energy manager: Checks if the given plug is compatible with this device's socket. Used by CanReceivePlugFrom() method.
- bool IsPlugCompatible(int plug_ID)
- {
- if ( plug_ID == PLUG_UNDEFINED )
- {
- return true; // When plugType is undefined in config then make it compatible.
- }
-
- if ( m_CompatiblePlugTypes )
- {
- for ( int i = 0; i < m_CompatiblePlugTypes.Count(); i++ )
- {
- int plug_ID_to_Check = m_CompatiblePlugTypes.Get(i);
-
- if ( plug_ID_to_Check == plug_ID )
- {
- return true;
- }
- }
- }
- else
- {
- // Since the config parameter compatiblePlugTypes is not present, then accept all plugs for simplicity's sake
- return true;
- }
-
- return false;
- }
-
- //! Energy manager: Returns true if this device can receive power plug of the other device.
- bool CanReceivePlugFrom( EntityAI device_to_plug )
- {
- // The following conditions are broken down for the sake of easier reading/debugging.
-
- if ( HasFreeSocket() && device_to_plug != m_ThisEntityAI)
- {
- if ( device_to_plug.GetCompEM().GetEnergySource() != m_ThisEntityAI)
- {
- if ( IsPlugCompatible(device_to_plug.GetCompEM().GetPlugType()) )
- {
- if ( device_to_plug.GetCompEM().IsEnergySourceAtReach( device_to_plug.GetPosition(), 0, m_ThisEntityAI.GetPosition() ) )
- {
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
- //! Energy manager: Returns true if this device can be plugged into the given energy source. Otherwise returns false.
- bool CanBePluggedInto( EntityAI potential_energy_provider )
- {
- return potential_energy_provider.GetCompEM().CanReceivePlugFrom( m_ThisEntityAI );
- }
-
- //! Energy manager: Returns true if the electricity icon (bolt) is supposed to be visible for this device. False if not.
- bool HasElectricityIcon()
- {
- return m_HasElectricityIcon;
- }
-
- //! Energy manager: Returns true if this item automatically converts its energy to quantity
- bool HasConversionOfEnergyToQuantity()
- {
- return m_ConvertEnergyToQuantity;
- }
- /**
- \brief Energy manager: Returns true if this device's virtual power cord can reach its energy source at the given position, depending on its cordLength config parameter. Otherwise returns false.
- \param from_position \p vector position from where the measurement will be taken
- \param add_tolerance \p float parameter will add to the cord's length in meters (optional)
- \return \p bool True if the power source will be at reach for the plug, or if config param cordLength is absent or 0. False if not, or is not plugged, or this device lacks Energy Manager component.
- @code
- vector position_player = GetGame().GetPlayer().GetPosition();
-
- if ( my_device.GetCompEM().IsEnergySourceAtReach( position_player ) )
- {
- Print("Power source is at reach!");
- }else{
- Print("Power source is NOT at reach!");
- }
- @endcode
- */
- bool IsEnergySourceAtReach( vector from_position, float add_tolerance = 0, vector override_source_position = "-1 -1 -1" )
- {
- if ( !IsPlugged() && override_source_position == "-1 -1 -1" )
- {
- return false;
- }
-
- if ( GetCordLength() == 0 ) // 0 is an exception, which means infinitely long cable.
- {
- return true;
- }
-
- vector source_pos;
- float distance;
-
- if ( override_source_position == "-1 -1 -1" )
- {
- EntityAI energy_source = GetEnergySource();
-
- if (!energy_source)
- return false;
-
- source_pos = energy_source.GetPosition();
- distance = vector.Distance( from_position, source_pos );
- }
- else
- {
- source_pos = override_source_position;
- distance = vector.Distance( from_position, source_pos );
- }
-
- if (distance > GetCordLength() + add_tolerance)
- {
- return false;
- }
- else
- {
- return true;
- }
- }
-
- bool HasVisibleSocketsInInventory()
- {
- return m_ShowSocketsInInventory;
- }
-
- //! Energy manager: Returns true if this selection is a plug that's plugged into this device. Otherwise returns false.
- bool IsSelectionAPlug(string selection_to_test )
- {
- if ( GetPluggedDevices() )
- {
- int socket_count = GetSocketsCount();
-
- for ( int i = socket_count; i >= 0; --i )
- {
- string real_selection = SOCKET_ + i.ToString() +_PLUGGED;
-
- if ( selection_to_test == real_selection)
- {
- return true;
- }
- }
- }
-
- return false;
- }
-
-
-
-
- //! Energy manager: Returns the count of power sockets (whenever used or not)
- int GetSocketsCount()
- {
- return m_SocketsCount;
- }
- //! Energy manager: Returns plug type. Check \DZ\data\basicDefines.hpp OR \Scripts\Classes\Component\_constants.h files for types of plugs
- int GetPlugType()
- {
- return m_PlugType;
- }
- // Returns the action ID which is supposed to be done upon receiving an attachment
- int GetAttachmentAction()
- {
- return m_AttachmentActionType;
- }
- // Returns persistent ID (block 1) of the energy source
- int GetEnergySourceStorageIDb1()
- {
- return m_EnergySourceStorageIDb1;
- }
- // Returns persistent ID (block 2) of the energy source
- int GetEnergySourceStorageIDb2()
- {
- return m_EnergySourceStorageIDb2;
- }
-
- // Returns persistent ID (block 3) of the energy source
- int GetEnergySourceStorageIDb3()
- {
- return m_EnergySourceStorageIDb3;
- }
-
- // Returns persistent ID (block 4) of the energy source
- int GetEnergySourceStorageIDb4()
- {
- return m_EnergySourceStorageIDb4;
- }
-
- // Returns network ID (low) of the energy source
- int GetEnergySourceNetworkIDLow()
- {
- return m_EnergySourceNetworkIDLow;
- }
- // Returns network ID (high) of the energy source
- int GetEnergySourceNetworkIDHigh()
- {
- return m_EnergySourceNetworkIDHigh;
- }
-
- //! Energy manager: Returns the number of devices plugged into this one.
- int GetPluggedDevicesCount()
- {
- if ( GetPluggedDevices() )
- {
- return GetPluggedDevices().Count();
- }
-
- return 0;
- }
-
- //! Energy manager: Returns % of stored energy this device has as integer (from 0 to 100)
- int GetEnergy0To100()
- {
- if ( m_EnergyStorageMax > 0 )
- {
- int coef = Math.Round( m_Energy / m_EnergyStorageMax * 100 );
- return coef;
- }
-
- return 0;
- }
-
- //! Energy manager: Returns % of stored energy this device has as float (from 0.0 to 1.0)
- float GetEnergy0To1()
- {
- if ( m_EnergyStorageMax > 0 )
- {
- return m_Energy / m_EnergyStorageMax;
- }
-
- return 0;
- }
-
- //! Energy manager: Returns the update interval of this device.
- float GetUpdateInterval()
- {
- #ifdef DIAG_DEVELOPER
- if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_CONSUMPTION) || (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_RECHARGE)))
- {
- return 1;//when modifying time accel, we might want to see things happen when they should, instead of waiting for the next tick
- }
- #endif
- return m_UpdateInterval;
- }
-
- //! Returns wetness exposure value defined in config
- float GetWetnessExposure()
- {
- return m_WetnessExposure;
- }
-
- //! Energy manager: Returns the number of energy this device needs to run itself (See its config >> energyUsagePerSecond)
- float GetEnergyUsage()
- {
- return m_EnergyUsage;
- }
- //! Energy manager: Returns the amount of stored energy this device has
- float GetEnergy()
- {
- return m_Energy;
- }
- //! Energy manager: Adds energy to this device and clamps it within its min/max storage limits. Returns the amount of energy that was clamped. Negative value is supported, but you should still use ConsumeEnergy(...) for propper substraction of energy.
- float AddEnergy(float added_energy)
- {
- if (added_energy != 0)
- {
- //Print("AddEnergy ---------> " + added_energy + " " + this + " " +m_ThisEntityAI.ClassName());
- #ifdef DIAG_DEVELOPER
- if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.ENERGY_CONSUMPTION) && added_energy < 0)
- {
- float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
- added_energy *= timeAccel;
- }
- #endif
-
- bool energy_was_added = (added_energy > 0);
-
- float energy_to_clamp = GetEnergy() + added_energy;
- float clamped_energy = Math.Clamp( energy_to_clamp, 0, GetEnergyMax() );
- SetEnergy(clamped_energy);
- StartUpdates();
-
- if (energy_was_added)
- OnEnergyAdded();
- else
- OnEnergyConsumed();
-
- return energy_to_clamp - clamped_energy;
- }
-
- return 0;
- }
-
- //! Energy manager: Returns the maximum amount of energy this device can curently store. If parameter 'reduceMaxEnergyByDamageCoef' is used in the config of this device then the returned value will be reduced by damage.
- float GetEnergyMax()
- {
- float max_health = 0;
-
- if ( m_ThisEntityAI.HasDamageSystem() )
- max_health = m_ThisEntityAI.GetMaxHealth("","");
- //else if ( m_ReduceMaxEnergyByDamageCoef != 0 )
- // Error("[ERROR] ReduceMaxEnergyByDamageCoef is setup but " + m_ThisEntityAI.GetType() + " does not have a Damage System");
-
- if ( max_health == 0 || m_ReduceMaxEnergyByDamageCoef == 0 )
- return GetEnergyMaxPristine();
-
- float health = 100;
-
- if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // TO DO: Remove this IF when method GetHealth can be called on client!
- health = m_ThisEntityAI.GetHealth("","");
-
- float damage_coef = 1 - (health / max_health);
-
- return GetEnergyMaxPristine() * (1 - ( damage_coef * m_ReduceMaxEnergyByDamageCoef ) );
- }
-
- //! Energy manager: Returns the maximum amount of energy this device can store. It's damage is NOT taken into account.
- float GetEnergyMaxPristine()
- {
- return m_EnergyStorageMax;
- }
-
- float GetEnergyAtSpawn()
- {
- return m_EnergyAtSpawn;
- }
-
- //! Energy manager: Returns the length of the virtual power cord.
- float GetCordLength()
- {
- return m_CordLength;
- }
- //! Energy manager: Returns the energy source this device is plugged into
- EntityAI GetEnergySource()
- {
- return m_EnergySource;
- }
-
- //! Energy manager: Returns the device which is plugged into the given socket ID.
- EntityAI GetDeviceBySocketID(int id)
- {
- return m_Sockets[id];
- }
- //! Energy manager: Returns the device to which the given plug selection belongs to
- EntityAI GetPlugOwner(string plug_selection_name)
- {
- if ( m_DeviceByPlugSelection && m_DeviceByPlugSelection.Contains(plug_selection_name) )
- {
- return m_DeviceByPlugSelection.Get(plug_selection_name);
- }
-
- return NULL;
- }
-
- //! Energy manager: Returns a device which is plugged into this one. If there are more devices to choose from then it returns the first one that is found.
- EntityAI GetPluggedDevice()
- {
- if ( GetPluggedDevicesCount() > 0 )
- {
- return GetPluggedDevices().Get(0);
- }
-
- return NULL;
- }
-
- //! Energy manager: Returns path to the cord texture file.
- string GetCordTextureFile()
- {
- return m_CordTextureFile;
- }
- //! Energy manager: Returns an array of devices which are plugged into this one
- array<EntityAI> GetPluggedDevices()
- {
- return m_PluggedDevices;
- }
- //! Energy manager: Returns an array of devices which are plugged into this one and are turned on
- array<EntityAI> GetPoweredDevices()
- {
- array<EntityAI> return_array = new array<EntityAI>;
- int plugged_devices_c = GetPluggedDevicesCount();
- for ( int i = 0; i < plugged_devices_c; ++i )
- {
- EntityAI device = GetPluggedDevices().Get(i);
- if ( IsSwitchedOn() )
- {
- return_array.Insert(device);
- }
- }
-
- return return_array;
- }
-
-
- /*===================================
- PUBLIC EVENTS
- ===================================*/
- // Called every device update if its supposed to do some work. The update can be every second or at random, depending on its manipulation.
- void OnWork( float consumed_energy )
- {
- m_ThisEntityAI.OnWork(consumed_energy);
- }
- // Called when this device is plugged into some energy source
- void OnIsPlugged(EntityAI source_device)
- {
- if (m_DebugPlugs)
- {
- if (!m_DebugUpdate)
- m_DebugUpdate = new Timer( CALL_CATEGORY_SYSTEM );
-
- if (!m_DebugUpdate.IsRunning())
- m_DebugUpdate.Run(0.01, this, "DebugUpdate", NULL, true);
- }
-
- UpdateCanWork();
- m_ThisEntityAI.OnIsPlugged(source_device);
- }
- // Called when this device is UNPLUGGED from the energy source
- void OnIsUnplugged( EntityAI last_energy_source )
- {
- UpdateCanWork();
- m_ThisEntityAI.OnIsUnplugged( last_energy_source );
- }
- // When something is plugged into this device
- void OnOwnSocketTaken( EntityAI device )
- {
- //play sound
- if ( device.GetCompEM().GetPlugType() == PLUG_COMMON_APPLIANCE && m_ThisEntityAI.IsInitialized() )
- {
- EffectSound sound_plug;
- m_ThisEntityAI.PlaySoundSet( sound_plug, "cablereel_plugin_SoundSet", 0, 0 );
- }
-
- m_ThisEntityAI.OnOwnSocketTaken(device);
- }
- // When something is UNPLUGGED from this device
- void OnOwnSocketReleased( EntityAI device )
- {
- //play sound
- if ( device.GetCompEM().GetPlugType() == PLUG_COMMON_APPLIANCE && m_ThisEntityAI.IsInitialized() )
- {
- EffectSound sound_unplug;
- m_ThisEntityAI.PlaySoundSet( sound_unplug, "cablereel_unplug_SoundSet", 0, 0 );
- }
-
- m_ThisEntityAI.OnOwnSocketReleased( device );
- }
-
-
- // Handles automatic attachment action
- void OnAttachmentAdded(EntityAI elec_device)
- {
- int attachment_action_type = GetAttachmentAction();
-
- if ( attachment_action_type == PLUG_THIS_INTO_ATTACHMENT )
- {
- if ( elec_device.GetCompEM().CanReceivePlugFrom( m_ThisEntityAI ) )
- {
- PlugThisInto(elec_device);
- }
- }
- else if ( attachment_action_type == PLUG_ATTACHMENTS_INTO_THIS )
- {
- elec_device.GetCompEM().PlugThisInto(m_ThisEntityAI);
- }
- }
- // Handles automatic detachment action
- void OnAttachmentRemoved(EntityAI elec_device)
- {
- int attachment_action_type = GetAttachmentAction();
-
- if ( attachment_action_type == PLUG_THIS_INTO_ATTACHMENT )
- {
- if ( elec_device == GetEnergySource() )
- {
- UnplugThis();
- }
- }
- else if ( attachment_action_type == PLUG_ATTACHMENTS_INTO_THIS )
- {
- elec_device.GetCompEM().UnplugThis();
- }
- }
- // Starts the device's main cycle
- void StartUpdates()
- {
- if (!m_IsPassiveDevice)
- {
- if (!m_UpdateTimer)
- m_UpdateTimer = new Timer(CALL_CATEGORY_SYSTEM);
-
- if (!m_UpdateTimer.IsRunning()) // Makes sure the timer is NOT running already
- {
- m_UpdateTimer.Run(GetUpdateInterval(), this, "DeviceUpdate", null, true);
- }
- }
- }
-
- //! Energy manager: Called when energy was consumed on this device
- void OnEnergyConsumed()
- {
- m_ThisEntityAI.OnEnergyConsumed();
- }
-
- //! Energy manager: Called when energy was added on this device
- void OnEnergyAdded()
- {
- if (m_UpdateQuantityTimer)
- {
- m_UpdateQuantityTimer.Stop();
- m_UpdateQuantityTimer = NULL;
- }
-
- m_ThisEntityAI.OnEnergyAdded();
- }
- /*===================================
- PROTECTED FUNCTIONS
- ===================================*/
- // Stops the device's main cycle
- protected void StopUpdates()
- {
- if (m_UpdateTimer)
- {
- m_UpdateTimer.Stop();
- m_UpdateTimer = NULL; // Delete timer from memory
- }
- }
- //! Gets called originally when the player is interacting with an item containing this energy component, then recursively following the branches of connection from the original item to the peripheries
- //! External calling of this function is not automatic for all item interactions and may need to be implemented on case by case bases
- //! Avoid using for gameplay logic, use 'OnInteractBranch' instead
- void InteractBranch(EntityAI originalCaller, Man player = null, int system = 0)
- {
- OnInteractBranch(originalCaller, player, system);
- if ( GetSocketsCount() > 0 )
- {
- array<EntityAI> devices = GetPluggedDevices();
-
- foreach ( EntityAI device : devices)
- {
- if ( device != originalCaller ) // originalCaller check here prevents infinite loops
- {
- device.GetCompEM().InteractBranch( originalCaller, player, system );
- }
- }
- }
- }
-
- //! Called when the player is interacting with an item containing this energy component, or when interacting with an item this device is connected to
- protected void OnInteractBranch(EntityAI originalCaller, Man player, int system)
- {
- m_ThisEntityAI.IncreaseLifetime();
-
- }
-
- // 'Wakes up' all devices down the network so they start working, if they have enough power, and are switched ON
- protected void WakeUpWholeBranch( EntityAI original_caller )
- {
- if ( GetSocketsCount() > 0 )
- {
- array<EntityAI> plugged_devices = GetPluggedDevices();
- int plugged_devices_c = plugged_devices.Count();
-
- for ( int i = 0; i < plugged_devices_c; ++i )
- {
- EntityAI device = plugged_devices.Get(i);
- if ( device != original_caller ) // original_caller check here prevents infinite loops
- {
- device.GetCompEM().UpdateCanWork();
- device.GetCompEM().DeviceUpdate();
- device.GetCompEM().StartUpdates();
- device.GetCompEM().WakeUpWholeBranch( original_caller );
- }
- }
- }
- }
- // Finds an available socket and plugs the given device into it.
- // This is mainly about visualisation.
- protected void PlugCordIntoSocket( EntityAI device_to_plug, int socket_id = -1 )
- {
- if (socket_id >= 0)
- {
- EntityAI plug_owner_by_socket = GetDeviceBySocketID(socket_id);
-
- if (!plug_owner_by_socket)
- {
- UpdateSocketSelections(socket_id, device_to_plug);
- return;
- }
- }
- int slots_c = GetSocketsCount();
-
- for ( int i = 0; i < slots_c; ++i )
- {
- EntityAI plug_owner = GetDeviceBySocketID(i);
-
- if ( !plug_owner ) // Check if this socket is available
- {
- UpdateSocketSelections(i, device_to_plug);
- break;
- }
- }
- }
-
- // Updates socket selections (plugged/unplugged) of the given ID and sets color texture of the plug.
- protected void UpdateSocketSelections(int socket_id, EntityAI device_to_plug)
- {
- SetDeviceBySocketID(socket_id, device_to_plug);
-
- string plugged_selection = SOCKET_ + (socket_id+1).ToString() + _PLUGGED;
- SetPlugOwner( plugged_selection, device_to_plug );
- m_ThisEntityAI.ShowSelection ( plugged_selection );
-
- string unplugged_selection = SOCKET_ + (socket_id+1).ToString() + _AVAILABLE;
- m_ThisEntityAI.HideSelection ( unplugged_selection );
- string texture_path = device_to_plug.GetCompEM().GetCordTextureFile();
- int selection_index = m_ThisEntityAI.GetHiddenSelectionIndex( plugged_selection );
- m_ThisEntityAI.SetObjectTexture( selection_index, texture_path );
- device_to_plug.GetCompEM().SetMySocketID(socket_id);
- }
-
-
- // Sets energy source for this device
- protected void SetEnergySource( EntityAI source )
- {
- m_EnergySource = source;
-
- if (source)
- {
- m_IsPlugged = true;
- StartUpdates();
- }
- else
- {
- m_IsPlugged = false;
- m_EnergySourceNetworkIDLow = -1;
- m_EnergySourceNetworkIDHigh = -1;
- }
-
- if (m_EnergySource)
- m_EnergySource.GetNetworkID(m_EnergySourceNetworkIDLow, m_EnergySourceNetworkIDHigh);
-
- Synch();
- }
- // Plugs the given device into this one
- protected bool PlugInDevice(EntityAI device_to_plug, int socket_id = -1)
- {
- if (CanReceivePlugFrom(device_to_plug))
- {
- device_to_plug.IncreaseLifetime();
- InteractBranch(m_ThisEntityAI);
- if (device_to_plug.GetCompEM().IsPlugged())
- device_to_plug.GetCompEM().UnplugThis();
-
- GetPluggedDevices().Insert(device_to_plug);
- device_to_plug.GetCompEM().SetEnergySource(m_ThisEntityAI);
-
- PlugCordIntoSocket(device_to_plug, socket_id); // Visualisation
- OnOwnSocketTaken(device_to_plug);
-
- device_to_plug.GetCompEM().OnIsPlugged(m_ThisEntityAI);
- WakeUpWholeBranch( m_ThisEntityAI );
-
- if (GetGame().IsServer() || !GetGame().IsMultiplayer())
- {
- device_to_plug.HideSelection(SEL_CORD_FOLDED);
- device_to_plug.ShowSelection(SEL_CORD_PLUGGED);
- }
-
- return true;
- }
-
- return false;
- }
- // Sets the device to which the given plug selection belongs to
- protected void SetPlugOwner(string selection_name, EntityAI device)
- {
- if ( m_DeviceByPlugSelection.Contains(selection_name) )
- {
- m_DeviceByPlugSelection.Set(selection_name, device);
- }
- }
-
- // Frees the given socket.
- // This is only about visualisation.
- protected void UnplugCordFromSocket( int socket_to_unplug_ID )
- {
- EntityAI plug_owner = GetDeviceBySocketID(socket_to_unplug_ID);
-
- if ( plug_owner )
- {
- SetDeviceBySocketID(socket_to_unplug_ID, NULL);
- string unplugged_selection = SOCKET_ + (socket_to_unplug_ID+1).ToString() + _AVAILABLE;
- m_ThisEntityAI.ShowSelection ( unplugged_selection );
-
- string plugged_selection = SOCKET_ + (socket_to_unplug_ID+1).ToString() + _PLUGGED;
- m_ThisEntityAI.HideSelection ( plugged_selection );
- SetPlugOwner( plugged_selection, NULL );
- plug_owner.GetCompEM().SetMySocketID(-1);
- }
- }
- // Sets the state of the device
- protected void SetPowered( bool state )
- {
- m_IsWorking = state;
- }
-
- // 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.
- protected bool FindAndConsumeEnergy(EntityAI original_caller, float amount, bool ignore_switch_state = false)
- {
- if ( (ignore_switch_state || IsSwitchedOn()) && !m_ThisEntityAI.IsRuined() )
- {
- float available_energy = AddEnergy(-amount);
-
- if ( available_energy < 0 && IsPlugged() )
- {
- // 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)
- EntityAI next_power_source = GetEnergySource();
-
- if (next_power_source && next_power_source != original_caller) // Prevents infinite loop if the power source is the original caller itself
- {
- return next_power_source.GetCompEM().FindAndConsumeEnergy( original_caller, -available_energy );
- }
- }
-
- if ( available_energy >= 0)
- {
- return true;
- }
-
- return false;
- }
- else
- {
- return false;
- }
- }
-
- // Gets the socket ID this device is powered from.
- protected int GetMySocketID()
- {
- return m_MySocketID;
- }
-
- // Sets the socket ID this device is plugged into.
- protected void SetMySocketID( int slot_ID )
- {
- m_MySocketID = slot_ID;
- }
- void Synch()
- {
- m_ThisEntityAI.SetSynchDirty();
- }
-
- void ClearLastUpdateTime()
- {
- m_LastUpdateTime = 0;
- }
-
- void RememberLastUpdateTime()
- {
- m_LastUpdateTime = GetCurrentUpdateTime();
- }
-
- float GetCurrentUpdateTime()
- {
- return GetGame().GetTime();
- }
-
- // Updates the device's state of power. This function is visualized in the diagram at DayZ Confluence >> Camping & Squatting >> Electricity >> Energy Manager functionalities
- void DeviceUpdate()
- {
- /*
- vector pos = m_ThisEntityAI.GetPosition();
- string debug_message = "Object " + m_ThisEntityAI.GetType() + " | Energy: " + GetEnergy() + " | IsAtReach: " + (IsEnergySourceAtReach(pos)).ToString();
- Print(debug_message);
- */
-
- if ( !m_IsPassiveDevice )
- {
- // 'm_ThisEntityAI' and 'this' must be checked because this method is caled from a timer
- if ( m_ThisEntityAI && this && IsSwitchedOn() && !m_ThisEntityAI.IsRuined() && CheckWetness() && m_CanWork && !GetGame().IsMissionMainMenu() )
- {
- bool was_powered = IsWorking();
- float consumed_energy_coef;
- // Make sure to use only as much % of energy as needed since this function can be called at random.
-
- if ( m_LastUpdateTime == 0 )
- {
- RememberLastUpdateTime();
- consumed_energy_coef = 1.0;
- }
- else
- {
- float updatetime = GetCurrentUpdateTime();
- float time = updatetime - m_LastUpdateTime;
- consumed_energy_coef = time / 1000;
- }
-
- if (consumed_energy_coef > 0) // Prevents calling of OnWork events when no energy is consumed
- {
- m_LastUpdateTime = GetCurrentUpdateTime();
- float consume_energy = GetEnergyUsage() * consumed_energy_coef;
- bool has_consumed_enough = true;
-
- if (GetGame().IsServer() || !GetGame().IsMultiplayer()) // single player or server side multiplayer
- has_consumed_enough = ConsumeEnergy( consume_energy );
-
- SetPowered( has_consumed_enough );
-
- if ( has_consumed_enough )
- {
- if ( !was_powered )
- {
- m_CanStopWork = true;
- WakeUpWholeBranch(m_ThisEntityAI);
- GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStart", NULL, 0);
- UpdateCanWork();
- }
-
- OnWork( consume_energy );
- }
- else
- {
- if ( was_powered )
- {
- if (m_CanStopWork)
- {
- m_CanStopWork = false;
- ClearLastUpdateTime();
- GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStop", NULL, 0); // This event is called only once when the device STOPS being powered
- UpdateCanWork();
-
- if (m_AutoSwitchOff)
- {
- SwitchOff();
- }
- }
- }
-
- StopUpdates();
- }
- }
- else
- {
- ClearLastUpdateTime();
- }
- }
- else if (this && m_ThisEntityAI)
- {
- SetPowered( false );
- StopUpdates();
-
- if (m_CanStopWork)
- {
- m_CanStopWork = false;
- ClearLastUpdateTime();
- GetGame().GameScript.CallFunction(m_ThisEntityAI, "OnWorkStop", NULL, 0); // This event is called only once when the device STOPS being powered
- UpdateCanWork();
-
- if (m_AutoSwitchOff)
- {
- SwitchOff();
- }
- }
- }
- }
- }
- }
|