gewidgetsmetadatableeding.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. //! Manages all bleeding indicators and their updates
  2. class GameplayEffectsDataBleeding extends GameplayEffectsData
  3. {
  4. protected bool m_Initialized; //tied to initialization of 'BleedingSourcesManagerBase' on player object, skips updates until ready, even when formally active
  5. protected bool m_Visible; //overall visibility
  6. protected ref map<int,ref BleedingIndicator> m_RegisteredInstances;
  7. protected ref array<int> m_CleanupQueue;
  8. protected ref array<int> m_RunningIndicators;
  9. protected int m_LastDropIdx;
  10. protected int m_ImageWidgetCount; //number of available blood drop image widgets
  11. protected ref map<int,ref array<float>> m_ProbabilityMap;
  12. protected ref array<Widget> m_PositioningFramesArray;
  13. protected Widget m_BloodDropsFrame;
  14. protected int m_LastPositionFrameUsed;
  15. void GameplayEffectsDataBleeding(array<ref Widget> input, int type, int user_override = -1)
  16. {
  17. m_RegisteredInstances = new map<int,ref BleedingIndicator>;
  18. m_CleanupQueue = new array<int>;
  19. m_RunningIndicators = new array<int>;
  20. m_Initialized = false;
  21. }
  22. override void Init(array<ref Widget> input, int type, Widget layout_root, int user_override = -1)
  23. {
  24. super.Init(input, type, layout_root, user_override);
  25. m_WidgetArray.ShuffleArray(); //shuffles order of the widgets on every init
  26. m_ImageWidgetCount = m_WidgetArray.Count();
  27. m_BloodDropsFrame = m_LayoutRoot.FindAnyWidgetById(EffectWidgetsTypes.BLEEDING_LAYER);
  28. m_Visible = g_Game.GetProfileOption(EDayZProfilesOptions.BLEEDINGINDICATION);
  29. m_BloodDropsFrame.Show(m_Visible);
  30. m_LastDropIdx = -1;
  31. m_LastPositionFrameUsed = -1;
  32. BuildProbabilityData(BleedingIndicationConstants.INDICATOR_SEVERITY_LOW,BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_LOW);
  33. BuildProbabilityData(BleedingIndicationConstants.INDICATOR_SEVERITY_MEDIUM,BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_MEDIUM);
  34. BuildProbabilityData(BleedingIndicationConstants.INDICATOR_SEVERITY_HIGH,BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_HIGH);
  35. BuildPositioningData();
  36. }
  37. override bool HasDefinedHandle()
  38. {
  39. return true;
  40. }
  41. override bool DataInitialized()
  42. {
  43. return m_Initialized;
  44. }
  45. override void RegisterData(Param p)
  46. {
  47. if (m_Initialized)
  48. {
  49. #ifdef DEVELOPER
  50. ErrorEx("" + this + " is already initialized, further registration not possible!");
  51. #else
  52. Debug.Log("ERROR: " + this + " is already initialized, further registration not possible!");
  53. #endif
  54. return;
  55. }
  56. //<finish registration,bit,flow_modifier>
  57. Param3<bool,int,float> par;
  58. if (Class.CastTo(par,p))
  59. {
  60. if (par.param1 == true) //finish registration
  61. {
  62. m_Initialized = true;
  63. return;
  64. }
  65. RegisterBleedingIndicatorInstance(par.param2,par.param3);
  66. }
  67. }
  68. void RegisterBleedingIndicatorInstance(int bit, float flow_modifier)
  69. {
  70. int severity = CalculateSeverity(flow_modifier);
  71. BleedingIndicator indicator = new BleedingIndicator(bit,severity,this); //source_ID == bit for the purpose of pairing
  72. m_RegisteredInstances.Set(bit,indicator);
  73. }
  74. void SpawnBleedingIndicator(int source_ID, vector position)
  75. {
  76. if (m_RunningIndicators.Find(source_ID) != -1)
  77. {
  78. return;
  79. }
  80. BleedingIndicator indicator = m_RegisteredInstances.Get(source_ID);
  81. //indicator.InitIndicator(position); //would be nice if we could pair the indicator position to the hit position that caused the bleeding, wouldn't it
  82. indicator.InitIndicator(GenerateSequenceRandomPosition());
  83. m_RunningIndicators.Insert(source_ID);
  84. }
  85. int CalculateSeverity(float flow_modifier)
  86. {
  87. switch (flow_modifier)
  88. {
  89. case PlayerConstants.BLEEDING_SOURCE_FLOW_MODIFIER_LOW:
  90. return BleedingIndicationConstants.INDICATOR_SEVERITY_LOW;
  91. case PlayerConstants.BLEEDING_SOURCE_FLOW_MODIFIER_MEDIUM:
  92. return BleedingIndicationConstants.INDICATOR_SEVERITY_MEDIUM;
  93. case PlayerConstants.BLEEDING_SOURCE_FLOW_MODIFIER_HIGH:
  94. return BleedingIndicationConstants.INDICATOR_SEVERITY_HIGH;
  95. }
  96. return BleedingIndicationConstants.INDICATOR_SEVERITY_LOW;
  97. }
  98. ImageWidget GetNextDropImage()
  99. {
  100. m_LastDropIdx++;
  101. if (m_LastDropIdx > (m_ImageWidgetCount - 1))
  102. {
  103. m_LastDropIdx = 0;
  104. }
  105. return ImageWidget.Cast(m_WidgetArray[m_LastDropIdx]);
  106. }
  107. void StopBleedingIndicator(int source_ID, bool instant = false)
  108. {
  109. m_RegisteredInstances.Get(source_ID).StopIndicator(instant); //stop queued, evaluated on update!
  110. }
  111. void UpdateBleedingIndicators(float timeSlice)
  112. {
  113. BleedingIndicator bib;
  114. for (int i = 0; i < m_RunningIndicators.Count(); i++)
  115. {
  116. bib = m_RegisteredInstances.Get(m_RunningIndicators[i]);
  117. bib.Update(timeSlice);
  118. if ( bib.GetEndNow() )
  119. {
  120. m_CleanupQueue.Insert(m_RunningIndicators[i]);
  121. }
  122. }
  123. }
  124. void CleanupBleedingIndicators()
  125. {
  126. for (int i = 0; i < m_CleanupQueue.Count(); i++)
  127. {
  128. m_RunningIndicators.RemoveItem(m_CleanupQueue[i]);
  129. }
  130. m_CleanupQueue.Clear();
  131. }
  132. override void Update(float timeSlice = 0, Param p = null, int handle = -1)
  133. {
  134. //starts or ends a bleeding indicator
  135. if (p)
  136. {
  137. //start/stop of the indicator
  138. //<state,bit,position,immediate>
  139. Param4<bool,int,vector,bool> par;
  140. //hide/show of bleeding effect visuals
  141. //<state>
  142. Param1<bool> parShow;
  143. if (Class.CastTo(par,p))
  144. {
  145. bool state = par.param1;
  146. if (state) //queue add indicator
  147. {
  148. SpawnBleedingIndicator(par.param2,par.param3);
  149. }
  150. else //queue stop indicator
  151. {
  152. StopBleedingIndicator(par.param2,par.param4);
  153. }
  154. }
  155. else if (Class.CastTo(parShow,p) && m_Visible != parShow.param1)
  156. {
  157. m_Visible = parShow.param1;
  158. m_BloodDropsFrame.Show(m_Visible);
  159. }
  160. }
  161. //updates bleeding indicators
  162. UpdateBleedingIndicators(timeSlice);
  163. CleanupBleedingIndicators();
  164. if (m_RunningIndicators.Count() <= 0)
  165. {
  166. GetGame().GetMission().GetEffectWidgets().RemoveActiveEffects({EffectWidgetsTypes.BLEEDING_LAYER});
  167. m_WidgetArray.ShuffleArray();
  168. }
  169. }
  170. override void UpdateVisibility(bool state)
  171. {
  172. m_Visible = g_Game.GetProfileOption(EDayZProfilesOptions.BLEEDINGINDICATION); //ugh
  173. //manage layout visibility
  174. Widget w = m_BloodDropsFrame;
  175. while (w && w != m_LayoutRoot && m_Visible == state && w.IsVisibleHierarchy() != state)
  176. {
  177. w.Show(state);
  178. w = w.GetParent();
  179. }
  180. }
  181. //! stops and re-sets indicators and images even out of sequence. Should still be tied to the 'player' update, though!
  182. override void ForceStop()
  183. {
  184. super.ForceStop();
  185. foreach (int i: m_RunningIndicators)
  186. {
  187. m_RegisteredInstances.Get(i).StopIndicator(true);
  188. }
  189. Update();
  190. }
  191. void BuildProbabilityData(int severity, float frequency)
  192. {
  193. if (!m_ProbabilityMap)
  194. {
  195. m_ProbabilityMap = new map<int,ref array<float>>;
  196. }
  197. array<float> probabilities = new array<float>;
  198. for (int i = 0; i < BleedingIndicationConstants.SEQUENCE_STEPS; i++)
  199. {
  200. probabilities.Insert(Math.Poisson(frequency,i));
  201. }
  202. m_ProbabilityMap.Insert(severity,probabilities);
  203. }
  204. array<float> GetProbabilities(int severity)
  205. {
  206. array<float> ret = m_ProbabilityMap.Get(severity);
  207. if (!ret)
  208. {
  209. ErrorEx("No defined data for the selected severity!");
  210. }
  211. return ret;
  212. }
  213. void BuildPositioningData()
  214. {
  215. Widget frameParent = m_LayoutRoot.FindAnyWidget("PoisitioningFrames");
  216. if (frameParent)
  217. {
  218. if (!m_PositioningFramesArray)
  219. {
  220. m_PositioningFramesArray = new array<Widget>;
  221. }
  222. Widget frame = frameParent.GetChildren();
  223. while (frame)
  224. {
  225. m_PositioningFramesArray.Insert(frame);
  226. frame = frame.GetSibling();
  227. }
  228. }
  229. }
  230. vector GenerateSequenceRandomPosition()
  231. {
  232. if (m_PositioningFramesArray)
  233. {
  234. int arrayCount = m_PositioningFramesArray.Count();
  235. int index = Math.RandomInt(0,arrayCount);
  236. if (index == m_LastPositionFrameUsed)
  237. {
  238. index++;
  239. if (index >= arrayCount)
  240. {
  241. index = 0;
  242. }
  243. }
  244. Widget frame = m_PositioningFramesArray[index];
  245. m_LastPositionFrameUsed = index;
  246. if (frame)
  247. {
  248. int screenX,screenY;
  249. float x,y,x_size,y_size;
  250. frame.GetScreenPos(x,y);
  251. frame.GetScreenSize(x_size,y_size);
  252. x = Math.RandomFloatInclusive(x,x+x_size);
  253. y = Math.RandomFloatInclusive(y,y+y_size);
  254. return Vector(x,y,0);
  255. }
  256. }
  257. return vector.Zero;
  258. }
  259. }