123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- //! Manages all bleeding indicators and their updates
- class GameplayEffectsDataBleeding extends GameplayEffectsData
- {
- protected bool m_Initialized; //tied to initialization of 'BleedingSourcesManagerBase' on player object, skips updates until ready, even when formally active
- protected bool m_Visible; //overall visibility
- protected ref map<int,ref BleedingIndicator> m_RegisteredInstances;
- protected ref array<int> m_CleanupQueue;
- protected ref array<int> m_RunningIndicators;
- protected int m_LastDropIdx;
- protected int m_ImageWidgetCount; //number of available blood drop image widgets
- protected ref map<int,ref array<float>> m_ProbabilityMap;
- protected ref array<Widget> m_PositioningFramesArray;
- protected Widget m_BloodDropsFrame;
-
- protected int m_LastPositionFrameUsed;
-
- void GameplayEffectsDataBleeding(array<ref Widget> input, int type, int user_override = -1)
- {
- m_RegisteredInstances = new map<int,ref BleedingIndicator>;
- m_CleanupQueue = new array<int>;
- m_RunningIndicators = new array<int>;
- m_Initialized = false;
- }
-
- override void Init(array<ref Widget> input, int type, Widget layout_root, int user_override = -1)
- {
- super.Init(input, type, layout_root, user_override);
-
- m_WidgetArray.ShuffleArray(); //shuffles order of the widgets on every init
- m_ImageWidgetCount = m_WidgetArray.Count();
- m_BloodDropsFrame = m_LayoutRoot.FindAnyWidgetById(EffectWidgetsTypes.BLEEDING_LAYER);
- m_Visible = g_Game.GetProfileOption(EDayZProfilesOptions.BLEEDINGINDICATION);
- m_BloodDropsFrame.Show(m_Visible);
- m_LastDropIdx = -1;
- m_LastPositionFrameUsed = -1;
-
- BuildProbabilityData(BleedingIndicationConstants.INDICATOR_SEVERITY_LOW,BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_LOW);
- BuildProbabilityData(BleedingIndicationConstants.INDICATOR_SEVERITY_MEDIUM,BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_MEDIUM);
- BuildProbabilityData(BleedingIndicationConstants.INDICATOR_SEVERITY_HIGH,BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_HIGH);
- BuildPositioningData();
- }
-
- override bool HasDefinedHandle()
- {
- return true;
- }
-
- override bool DataInitialized()
- {
- return m_Initialized;
- }
-
- override void RegisterData(Param p)
- {
- if (m_Initialized)
- {
- #ifdef DEVELOPER
- ErrorEx("" + this + " is already initialized, further registration not possible!");
- #else
- Debug.Log("ERROR: " + this + " is already initialized, further registration not possible!");
- #endif
- return;
- }
-
- //<finish registration,bit,flow_modifier>
- Param3<bool,int,float> par;
- if (Class.CastTo(par,p))
- {
- if (par.param1 == true) //finish registration
- {
- m_Initialized = true;
- return;
- }
-
- RegisterBleedingIndicatorInstance(par.param2,par.param3);
- }
- }
-
- void RegisterBleedingIndicatorInstance(int bit, float flow_modifier)
- {
- int severity = CalculateSeverity(flow_modifier);
- BleedingIndicator indicator = new BleedingIndicator(bit,severity,this); //source_ID == bit for the purpose of pairing
- m_RegisteredInstances.Set(bit,indicator);
- }
-
- void SpawnBleedingIndicator(int source_ID, vector position)
- {
- if (m_RunningIndicators.Find(source_ID) != -1)
- {
- return;
- }
- BleedingIndicator indicator = m_RegisteredInstances.Get(source_ID);
- //indicator.InitIndicator(position); //would be nice if we could pair the indicator position to the hit position that caused the bleeding, wouldn't it
- indicator.InitIndicator(GenerateSequenceRandomPosition());
- m_RunningIndicators.Insert(source_ID);
- }
-
- int CalculateSeverity(float flow_modifier)
- {
- switch (flow_modifier)
- {
- case PlayerConstants.BLEEDING_SOURCE_FLOW_MODIFIER_LOW:
- return BleedingIndicationConstants.INDICATOR_SEVERITY_LOW;
-
- case PlayerConstants.BLEEDING_SOURCE_FLOW_MODIFIER_MEDIUM:
- return BleedingIndicationConstants.INDICATOR_SEVERITY_MEDIUM;
-
- case PlayerConstants.BLEEDING_SOURCE_FLOW_MODIFIER_HIGH:
- return BleedingIndicationConstants.INDICATOR_SEVERITY_HIGH;
- }
- return BleedingIndicationConstants.INDICATOR_SEVERITY_LOW;
- }
-
- ImageWidget GetNextDropImage()
- {
- m_LastDropIdx++;
- if (m_LastDropIdx > (m_ImageWidgetCount - 1))
- {
- m_LastDropIdx = 0;
- }
-
- return ImageWidget.Cast(m_WidgetArray[m_LastDropIdx]);
- }
-
- void StopBleedingIndicator(int source_ID, bool instant = false)
- {
- m_RegisteredInstances.Get(source_ID).StopIndicator(instant); //stop queued, evaluated on update!
- }
-
- void UpdateBleedingIndicators(float timeSlice)
- {
- BleedingIndicator bib;
- for (int i = 0; i < m_RunningIndicators.Count(); i++)
- {
- bib = m_RegisteredInstances.Get(m_RunningIndicators[i]);
- bib.Update(timeSlice);
- if ( bib.GetEndNow() )
- {
- m_CleanupQueue.Insert(m_RunningIndicators[i]);
- }
- }
- }
-
- void CleanupBleedingIndicators()
- {
- for (int i = 0; i < m_CleanupQueue.Count(); i++)
- {
- m_RunningIndicators.RemoveItem(m_CleanupQueue[i]);
- }
- m_CleanupQueue.Clear();
- }
-
- override void Update(float timeSlice = 0, Param p = null, int handle = -1)
- {
- //starts or ends a bleeding indicator
- if (p)
- {
- //start/stop of the indicator
- //<state,bit,position,immediate>
- Param4<bool,int,vector,bool> par;
-
- //hide/show of bleeding effect visuals
- //<state>
- Param1<bool> parShow;
-
- if (Class.CastTo(par,p))
- {
- bool state = par.param1;
- if (state) //queue add indicator
- {
- SpawnBleedingIndicator(par.param2,par.param3);
- }
- else //queue stop indicator
- {
- StopBleedingIndicator(par.param2,par.param4);
- }
- }
- else if (Class.CastTo(parShow,p) && m_Visible != parShow.param1)
- {
- m_Visible = parShow.param1;
- m_BloodDropsFrame.Show(m_Visible);
- }
- }
-
- //updates bleeding indicators
- UpdateBleedingIndicators(timeSlice);
- CleanupBleedingIndicators();
-
- if (m_RunningIndicators.Count() <= 0)
- {
- GetGame().GetMission().GetEffectWidgets().RemoveActiveEffects({EffectWidgetsTypes.BLEEDING_LAYER});
- m_WidgetArray.ShuffleArray();
- }
- }
-
- override void UpdateVisibility(bool state)
- {
- m_Visible = g_Game.GetProfileOption(EDayZProfilesOptions.BLEEDINGINDICATION); //ugh
- //manage layout visibility
- Widget w = m_BloodDropsFrame;
- while (w && w != m_LayoutRoot && m_Visible == state && w.IsVisibleHierarchy() != state)
- {
- w.Show(state);
- w = w.GetParent();
- }
- }
-
- //! stops and re-sets indicators and images even out of sequence. Should still be tied to the 'player' update, though!
- override void ForceStop()
- {
- super.ForceStop();
-
- foreach (int i: m_RunningIndicators)
- {
- m_RegisteredInstances.Get(i).StopIndicator(true);
- }
- Update();
- }
-
- void BuildProbabilityData(int severity, float frequency)
- {
- if (!m_ProbabilityMap)
- {
- m_ProbabilityMap = new map<int,ref array<float>>;
- }
-
- array<float> probabilities = new array<float>;
-
- for (int i = 0; i < BleedingIndicationConstants.SEQUENCE_STEPS; i++)
- {
- probabilities.Insert(Math.Poisson(frequency,i));
- }
-
- m_ProbabilityMap.Insert(severity,probabilities);
- }
-
- array<float> GetProbabilities(int severity)
- {
- array<float> ret = m_ProbabilityMap.Get(severity);
- if (!ret)
- {
- ErrorEx("No defined data for the selected severity!");
- }
- return ret;
- }
-
- void BuildPositioningData()
- {
- Widget frameParent = m_LayoutRoot.FindAnyWidget("PoisitioningFrames");
- if (frameParent)
- {
- if (!m_PositioningFramesArray)
- {
- m_PositioningFramesArray = new array<Widget>;
- }
-
- Widget frame = frameParent.GetChildren();
- while (frame)
- {
- m_PositioningFramesArray.Insert(frame);
- frame = frame.GetSibling();
- }
- }
- }
-
- vector GenerateSequenceRandomPosition()
- {
- if (m_PositioningFramesArray)
- {
- int arrayCount = m_PositioningFramesArray.Count();
- int index = Math.RandomInt(0,arrayCount);
- if (index == m_LastPositionFrameUsed)
- {
- index++;
- if (index >= arrayCount)
- {
- index = 0;
- }
- }
-
- Widget frame = m_PositioningFramesArray[index];
- m_LastPositionFrameUsed = index;
-
- if (frame)
- {
- int screenX,screenY;
- float x,y,x_size,y_size;
- frame.GetScreenPos(x,y);
- frame.GetScreenSize(x_size,y_size);
-
- x = Math.RandomFloatInclusive(x,x+x_size);
- y = Math.RandomFloatInclusive(y,y+y_size);
-
- return Vector(x,y,0);
- }
- }
- return vector.Zero;
- }
- }
|