gameplayeffectwidgets.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*
  2. TODO - doxygen formating
  3. */
  4. //! grouped gameplay effect widgets and their handling
  5. class GameplayEffectWidgets extends GameplayEffectWidgets_base
  6. {
  7. protected ref Widget m_Root; //dummy parent node
  8. protected ref map<int,ref Widget> m_Layouts;
  9. protected ref set<ref Widget> m_UniqueLayouts;
  10. protected ref GameplayEffectDataMap m_WidgetDataMap;
  11. protected ref set<int> m_RunningEffects;
  12. protected ref set<int> m_RunningEffectsPrevious;
  13. protected ref array<int> m_UpdatingEffects;
  14. protected ref array<ref Widget> m_UpdatedWidgetsCheck; //to make sure widgets are not updated over and over (case of multiple IDs sharing same widget set)
  15. protected ref array<int> m_UpdatedWidgetSetsCheck; //to make sure sets are not updated over and over (case of multiple IDs sharing same widget set)
  16. protected ref set<int> m_SuspendRequests;
  17. protected ref map<int,typename> m_IDToTypeMap;
  18. protected float m_TimeProgBreath;
  19. protected float m_BreathMultStamina;
  20. protected float m_BreathResidue;
  21. //UserID's for widget containers that use something different from 'EffectWidgetsTypes' defaults
  22. protected const int WIDGETSET_BREATH = 100;
  23. //effect values
  24. protected int m_BreathColor;
  25. protected float m_BreathAlphaVal;
  26. protected float m_FlashbangCoverAlphaVal;
  27. void GameplayEffectWidgets()
  28. {
  29. m_Root = GetGame().GetWorkspace().CreateWidget(FrameWidgetTypeID,0,0,1.0,1.0,WidgetFlags.VISIBLE | WidgetFlags.HEXACTPOS | WidgetFlags.VEXACTPOS, 0xffffffff, 0);
  30. m_Layouts = new map<int,ref Widget>;
  31. m_UniqueLayouts = new set<ref Widget>;
  32. m_WidgetDataMap = new GameplayEffectDataMap;
  33. m_RunningEffects = new set<int>;
  34. m_RunningEffectsPrevious = new set<int>;
  35. m_UpdatingEffects = new array<int>;
  36. m_UpdatedWidgetsCheck = new array<ref Widget>;
  37. m_UpdatedWidgetSetsCheck = new array<int>;
  38. m_SuspendRequests = new set<int>;
  39. m_IDToTypeMap = new map<int,typename>;
  40. m_TimeProgBreath = 0.0;
  41. m_BreathMultStamina = 1.0;
  42. PairIDToTypes();
  43. RegisterLayouts("gui/layouts/gameplay/CameraEffects.layout",CompileEffectListing());
  44. RegisterLayouts("gui/layouts/gameplay/BleedingEffects.layout",{EffectWidgetsTypes.BLEEDING_LAYER});
  45. InitWidgetSet(EffectWidgetsTypes.MASK_BREATH,true,WIDGETSET_BREATH);
  46. InitWidgetSet(EffectWidgetsTypes.HELMET_BREATH,true,WIDGETSET_BREATH);
  47. InitWidgetSet(EffectWidgetsTypes.MOTO_BREATH,true,WIDGETSET_BREATH);
  48. InitWidgetSet(EffectWidgetsTypes.MASK_OCCLUDER,false,EffectWidgetsTypes.MASK_OCCLUDER);
  49. InitWidgetSet(EffectWidgetsTypes.HELMET_OCCLUDER);
  50. InitWidgetSet(EffectWidgetsTypes.HELMET2_OCCLUDER);
  51. InitWidgetSet(EffectWidgetsTypes.MOTO_OCCLUDER);
  52. InitWidgetSet(EffectWidgetsTypes.NVG_OCCLUDER,false,EffectWidgetsTypes.NVG_OCCLUDER);
  53. InitWidgetSet(EffectWidgetsTypes.PUMPKIN_OCCLUDER,false,EffectWidgetsTypes.NVG_OCCLUDER);
  54. InitWidgetSet(EffectWidgetsTypes.EYEPATCH_OCCLUDER);
  55. InitWidgetSet(EffectWidgetsTypes.COVER_FLASHBANG);
  56. InitWidgetSet(EffectWidgetsTypes.BLEEDING_LAYER,true);
  57. UpdateVisibility();
  58. }
  59. void ~GameplayEffectWidgets()
  60. {
  61. for (int i = 0; i < m_Layouts.Count(); i++)
  62. {
  63. if (m_Layouts.GetElement(i))
  64. m_Layouts.GetElement(i).Unlink();
  65. }
  66. }
  67. /**
  68. \brief Registers new layout and ties effect IDs to it
  69. \note Order of layout creation matters, they get layered on top of each other. Within a single layout, widget priorities govern the widget order.
  70. */
  71. protected void RegisterLayouts(string path, array<int> types)
  72. {
  73. Widget w = GetGame().GetWorkspace().CreateWidgets(path,m_Root,false);
  74. m_UniqueLayouts.Insert(w);
  75. w.Show(false);
  76. foreach (int i : types)
  77. {
  78. m_Layouts.Set(i,w);
  79. }
  80. }
  81. protected void PairIDToTypes()
  82. {
  83. m_IDToTypeMap.Insert(EffectWidgetsTypes.BLEEDING_LAYER,GameplayEffectsDataBleeding);
  84. }
  85. protected typename TranslateIDToType(int typeID)
  86. {
  87. return m_IDToTypeMap.Get(typeID);
  88. }
  89. override void RegisterGameplayEffectData(int id, Param p)
  90. {
  91. if (!m_WidgetDataMap.Get(id).DataInitialized())
  92. {
  93. m_WidgetDataMap.Get(id).RegisterData(p);
  94. }
  95. }
  96. /**
  97. \brief InitWidgetSet
  98. \param type \p int ID of effect widget type
  99. \param updating \p bool Marks widgets for 'PlayerBase.EOnFrame' updating
  100. \param user_id_override \p int UserID of a widget to be used instead (allows multiple types to use single widget)
  101. @code
  102. InitWidgetSet(EffectWidgetsTypes.MASK_BREATH,true,BREATH);
  103. @endcode
  104. \note All child widgets MUST be of the same type if special functionality is required (ImageWidget etc.)
  105. */
  106. protected void InitWidgetSet(int type, bool updating = false, int user_id_override = -1)
  107. {
  108. Widget parent = null;
  109. if (user_id_override != -1)
  110. {
  111. parent = m_Layouts.Get(type).FindAnyWidgetById(user_id_override);
  112. }
  113. else
  114. {
  115. parent = m_Layouts.Get(type).FindAnyWidgetById(type);
  116. }
  117. if (!parent)
  118. {
  119. Print("InitWidgetSet | type: " + type + " - parent not found!");
  120. return;
  121. }
  122. array<ref Widget> output;
  123. Widget w = parent.GetChildren();
  124. if (w)
  125. {
  126. output = new array<ref Widget>;
  127. while (w)
  128. {
  129. w.Update();
  130. w.Show(false,true);
  131. output.Insert(w);
  132. w = w.GetSibling();
  133. }
  134. if (parent.GetChildren())
  135. {
  136. typename handled_type = TranslateIDToType(type);
  137. if ( handled_type )
  138. {
  139. CreateHandledClass(handled_type,output,type,user_id_override);
  140. }
  141. else
  142. {
  143. if (ImageWidget.Cast(parent.GetChildren()))
  144. {
  145. m_WidgetDataMap.Set(type, new GameplayEffectsDataImage(output,type,user_id_override) );
  146. }
  147. else
  148. {
  149. m_WidgetDataMap.Set(type, new GameplayEffectsData(output,type,user_id_override) );
  150. }
  151. }
  152. }
  153. if (updating)
  154. m_UpdatingEffects.Insert(type);
  155. }
  156. }
  157. bool CreateHandledClass(typename handled_type, array<ref Widget> input, int type, int user_override)
  158. {
  159. if (handled_type)
  160. {
  161. GameplayEffectsData data = GameplayEffectsData.Cast(handled_type.Spawn());
  162. data.Init(input,type,m_Layouts.Get(type),user_override);
  163. m_WidgetDataMap.Set(type, data);
  164. return true;
  165. }
  166. return false;
  167. }
  168. //! returns all vanilla effects, nested in a vanilla layout. If using different layouts for custom effects, please register and link separately
  169. array<int> CompileEffectListing()
  170. {
  171. array<int> ret = new array<int>;
  172. ret.Insert(EffectWidgetsTypes.MASK_OCCLUDER);
  173. ret.Insert(EffectWidgetsTypes.MASK_BREATH);
  174. ret.Insert(EffectWidgetsTypes.HELMET_OCCLUDER);
  175. ret.Insert(EffectWidgetsTypes.HELMET_BREATH);
  176. ret.Insert(EffectWidgetsTypes.MOTO_OCCLUDER);
  177. ret.Insert(EffectWidgetsTypes.MOTO_BREATH);
  178. ret.Insert(EffectWidgetsTypes.COVER_FLASHBANG);
  179. ret.Insert(EffectWidgetsTypes.NVG_OCCLUDER);
  180. ret.Insert(EffectWidgetsTypes.PUMPKIN_OCCLUDER);
  181. ret.Insert(EffectWidgetsTypes.EYEPATCH_OCCLUDER);
  182. ret.Insert(EffectWidgetsTypes.HELMET2_OCCLUDER);
  183. return ret;
  184. }
  185. protected void UpdateVisibility()
  186. {
  187. Widget w;
  188. //Hide diff
  189. int value;
  190. int runningEffectCount = m_RunningEffects.Count();
  191. bool runningEffectsPresent = runningEffectCount > 0;
  192. GameplayEffectsData dta;
  193. for (int i = 0; i < m_RunningEffectsPrevious.Count(); i++)
  194. {
  195. value = m_RunningEffectsPrevious.Get(i);
  196. dta = m_WidgetDataMap.Get(value);
  197. if (runningEffectCount < 1 || m_RunningEffects.Find(value) == -1)
  198. {
  199. if (dta.HasDefinedHandle())
  200. {
  201. dta.UpdateVisibility(false);
  202. }
  203. else
  204. {
  205. for (int j = 0; j < m_WidgetDataMap.Get(value).GetWidgetSet().Count(); j++)
  206. {
  207. w = m_WidgetDataMap.Get(value).GetWidgetSet().Get(j);
  208. w.Show(false);
  209. }
  210. w.GetParent().Show(false);
  211. }
  212. }
  213. }
  214. //Show running effects
  215. if (runningEffectsPresent)
  216. {
  217. value = 0;
  218. for (i = 0; i < runningEffectCount; i++)
  219. {
  220. value = m_RunningEffects.Get(i);
  221. dta = m_WidgetDataMap.Get(value);
  222. if (dta.HasDefinedHandle())
  223. {
  224. dta.m_LayoutRoot.Show(true);
  225. dta.UpdateVisibility(true);
  226. }
  227. else
  228. {
  229. for (j = 0; j < m_WidgetDataMap.Get(value).GetWidgetSet().Count(); j++)
  230. {
  231. w = m_WidgetDataMap.Get(value).GetWidgetSet().Get(j);
  232. w.Update();
  233. w.Show(true);
  234. }
  235. while (w) //dumb but necessary because of uncertain "visible" setting of the layout
  236. {
  237. w = w.GetParent();
  238. if (w)
  239. {
  240. w.Show(true);
  241. }
  242. }
  243. }
  244. }
  245. }
  246. m_Root.Show(runningEffectsPresent && m_SuspendRequests.Count() < 1);
  247. m_RunningEffectsPrevious.Clear();
  248. }
  249. override void AddActiveEffects(array<int> effects)
  250. {
  251. if (effects && effects.Count() > 0)
  252. {
  253. m_RunningEffectsPrevious.Copy(m_RunningEffects);
  254. int value;
  255. for (int i = 0; i < effects.Count(); i++)
  256. {
  257. value = effects.Get(i);
  258. m_RunningEffects.Insert(value);
  259. }
  260. if (m_RunningEffectsPrevious.Count() != m_RunningEffects.Count())
  261. {
  262. UpdateVisibility();
  263. }
  264. }
  265. }
  266. override void RemoveActiveEffects(array<int> effects)
  267. {
  268. if (effects && effects.Count() > 0)
  269. {
  270. m_RunningEffectsPrevious.Copy(m_RunningEffects);
  271. int value;
  272. int idx;
  273. for (int i = 0; i < effects.Count(); i++)
  274. {
  275. value = effects.Get(i);
  276. idx = m_RunningEffects.Find(value);
  277. if (idx != -1)
  278. {
  279. m_RunningEffects.Remove(idx);
  280. }
  281. }
  282. if (m_RunningEffectsPrevious.Count() != m_RunningEffects.Count())
  283. {
  284. UpdateVisibility();
  285. }
  286. }
  287. }
  288. override void StopAllEffects()
  289. {
  290. m_Root.Show(false); //to avoid visual 'peeling'
  291. if (IsAnyEffectRunning())
  292. {
  293. int count = m_RunningEffects.Count();
  294. GameplayEffectsData data;
  295. for (int i = 0; i < count; i++) //iterates over running metadata, in case anything requires its own stop handling
  296. {
  297. data = m_WidgetDataMap.Get(m_RunningEffects[i]);
  298. data.ForceStop();
  299. }
  300. }
  301. m_RunningEffectsPrevious.Copy(m_RunningEffects);
  302. m_RunningEffects.Clear();
  303. UpdateVisibility();
  304. }
  305. override bool IsAnyEffectRunning()
  306. {
  307. return m_RunningEffects && m_RunningEffects.Count() > 0;
  308. }
  309. override void AddSuspendRequest(int request_id)
  310. {
  311. m_SuspendRequests.Insert(request_id);
  312. UpdateVisibility();
  313. }
  314. override void RemoveSuspendRequest(int request_id)
  315. {
  316. int idx = m_SuspendRequests.Find(request_id);
  317. if (idx != -1)
  318. {
  319. m_SuspendRequests.Remove(idx);
  320. }
  321. UpdateVisibility();
  322. }
  323. override void ClearSuspendRequests()
  324. {
  325. m_SuspendRequests.Clear();
  326. UpdateVisibility();
  327. }
  328. override int GetSuspendRequestCount()
  329. {
  330. return m_SuspendRequests.Count();
  331. }
  332. //! Usually called in course of an OnFrame update, can be manually called from elsewhere with parameters
  333. override void UpdateWidgets(int type = -1, float timeSlice = 0, Param p = null, int handle = -1)
  334. {
  335. GameplayEffectsData dta;
  336. array<ref Widget> widget_set;
  337. if (type == EffectWidgetsTypes.ROOT)
  338. {
  339. HandleWidgetRoot(timeSlice,p,handle);
  340. }
  341. else if (type == -1) //update stuff from the m_UpdatingEffects
  342. {
  343. int type_widgetset = 0;
  344. for (int i = 0; i < m_UpdatingEffects.Count(); i++)
  345. {
  346. if (m_RunningEffects.Find(m_UpdatingEffects.Get(i)) != -1)
  347. {
  348. type_widgetset = m_UpdatingEffects.Get(i);
  349. dta = m_WidgetDataMap.Get(type_widgetset);
  350. if (dta.HasDefinedHandle() && dta.DataInitialized())
  351. {
  352. dta.Update(timeSlice,p,handle); //calculate and apply
  353. }
  354. else
  355. {
  356. CalculateValues(type_widgetset,timeSlice,p,handle);
  357. widget_set = dta.GetWidgetSet();
  358. foreach (Widget w : widget_set)
  359. {
  360. if (w.IsVisibleHierarchy() && m_UpdatedWidgetsCheck.Find(w) == -1)
  361. {
  362. m_UpdatedWidgetsCheck.Insert(w);
  363. ProcessWidgetUpdate(w,type_widgetset,timeSlice,p,handle);
  364. }
  365. }
  366. }
  367. }
  368. }
  369. }
  370. else //update specific widget set
  371. {
  372. if (m_RunningEffects.Find(type) != -1) //only do if the effect is running (FPS stonks!)
  373. {
  374. dta = m_WidgetDataMap.Get(type);
  375. if (dta.HasDefinedHandle() && dta.DataInitialized())
  376. {
  377. dta.Update(timeSlice,p,handle); //calculate and apply
  378. }
  379. else
  380. {
  381. CalculateValues(type,timeSlice,p,handle);
  382. widget_set = dta.GetWidgetSet();
  383. foreach (Widget w2 : widget_set)
  384. {
  385. if (w2.IsVisibleHierarchy() && m_UpdatedWidgetsCheck.Find(w2) == -1)
  386. {
  387. m_UpdatedWidgetsCheck.Insert(w2);
  388. ProcessWidgetUpdate(w2,type,timeSlice,p,handle);
  389. }
  390. }
  391. }
  392. }
  393. }
  394. m_UpdatedWidgetsCheck.Clear();
  395. m_UpdatedWidgetSetsCheck.Clear();
  396. }
  397. //! Only one calculation per unique WidgetSet
  398. protected void CalculateValues(int type = -1, float timeSlice = 0, Param p = null, int handle = -1)
  399. {
  400. if (m_UpdatedWidgetSetsCheck.Find(m_WidgetDataMap.Get(type).GetWidgetSetID()) != -1)
  401. {
  402. //Print("skipped updating set ID " + m_WidgetDataMap.Get(type).GetWidgetSetID() + " | effect: " + type);
  403. return;
  404. }
  405. switch (type)
  406. {
  407. case EffectWidgetsTypes.MOTO_BREATH:
  408. case EffectWidgetsTypes.HELMET_BREATH:
  409. case EffectWidgetsTypes.MASK_BREATH:
  410. {
  411. CalculateBreathEffect(timeSlice);
  412. }
  413. break;
  414. case EffectWidgetsTypes.MOTO_OCCLUDER:
  415. case EffectWidgetsTypes.EYEPATCH_OCCLUDER:
  416. case EffectWidgetsTypes.HELMET_OCCLUDER:
  417. case EffectWidgetsTypes.HELMET2_OCCLUDER:
  418. case EffectWidgetsTypes.MASK_OCCLUDER:
  419. {
  420. CalculateOccluderEffect(type,timeSlice,p,handle);
  421. }
  422. break;
  423. case EffectWidgetsTypes.COVER_FLASHBANG:
  424. {
  425. CalculateFlashbangEffect(type,timeSlice,p,handle);
  426. }
  427. break;
  428. default:
  429. return; //no need to calculate anything
  430. break;
  431. }
  432. m_UpdatedWidgetSetsCheck.Insert(m_WidgetDataMap.Get(type).GetWidgetSetID());
  433. }
  434. protected void ProcessWidgetUpdate(Widget w, int type, float timeSlice = 0, Param p = null, int handle = -1)
  435. {
  436. switch (type)
  437. {
  438. case EffectWidgetsTypes.MOTO_BREATH:
  439. case EffectWidgetsTypes.HELMET_BREATH:
  440. case EffectWidgetsTypes.MASK_BREATH:
  441. {
  442. UpdateBreathEffect(ImageWidget.Cast(w));
  443. }
  444. break;
  445. case EffectWidgetsTypes.MOTO_OCCLUDER:
  446. case EffectWidgetsTypes.EYEPATCH_OCCLUDER:
  447. case EffectWidgetsTypes.HELMET_OCCLUDER:
  448. case EffectWidgetsTypes.HELMET2_OCCLUDER:
  449. case EffectWidgetsTypes.MASK_OCCLUDER:
  450. {
  451. UpdateOccluderEffect(ImageWidget.Cast(w),type,timeSlice,p,handle);
  452. }
  453. break;
  454. case EffectWidgetsTypes.COVER_FLASHBANG:
  455. {
  456. UpdateFlashbangEffect(ImageWidget.Cast(w));
  457. }
  458. break;
  459. default:
  460. //Print("---invalid widget type to update---");
  461. break;
  462. }
  463. }
  464. //-----------------------------------------
  465. //specific widget 'handlers'
  466. const float BREATH_HDR_MIN = 0.005; //dusk?
  467. const float BREATH_HDR_MAX = 1.0; //dark?
  468. const float BREATH_COLOR_MULT_MIN = 0.5;
  469. const float BREATH_COLOR_MULT_MAX = 0.8;
  470. //-----------------------------------------
  471. //Breath
  472. //-----------------------------------------
  473. protected void CalculateBreathEffect(float timeSlice = 0, int type = -1, Param p = null)
  474. {
  475. float modifier = Math.Lerp(0.25, 0.5, m_BreathResidue);
  476. float speed = timeSlice * modifier;
  477. m_BreathResidue -= speed;
  478. m_BreathResidue = Math.Clamp(m_BreathResidue,0,1);
  479. float residue_final = Math.Lerp(0, 0.7, m_BreathResidue);
  480. float hdr_mult;
  481. hdr_mult = GetSceneHDRMul(0);
  482. hdr_mult = Math.Clamp(hdr_mult,BREATH_HDR_MIN,BREATH_HDR_MAX);
  483. hdr_mult = Math.InverseLerp(BREATH_HDR_MIN,BREATH_HDR_MAX,hdr_mult);
  484. hdr_mult = Math.Lerp(BREATH_COLOR_MULT_MAX,BREATH_COLOR_MULT_MIN,hdr_mult);
  485. m_BreathColor = ARGBF(0.0,1.0 * hdr_mult,1.0 * hdr_mult,1.0 * hdr_mult); //grayscaling of the image
  486. m_BreathAlphaVal = Math.Lerp(m_BreathAlphaVal, residue_final, timeSlice);
  487. }
  488. protected void UpdateBreathEffect(ImageWidget w)
  489. {
  490. w.SetColor(m_BreathColor);
  491. w.SetAlpha(m_BreathAlphaVal);
  492. }
  493. //-----------------------------------------
  494. //Occluders
  495. //-----------------------------------------
  496. protected void CalculateOccluderEffect(int type, float timeSlice, Param p, int handle)
  497. {
  498. }
  499. protected void UpdateOccluderEffect(ImageWidget w, int type, float timeSlice, Param p, int handle)
  500. {
  501. }
  502. //-----------------------------------------
  503. //Flashbang
  504. //-----------------------------------------
  505. protected void CalculateFlashbangEffect(int type, float timeSlice, Param p, int handle)
  506. {
  507. Param1<float> par = Param1<float>.Cast(p);
  508. m_FlashbangCoverAlphaVal = par.param1;
  509. /*if (m_FlashbangCoverAlphaVal <= 0.0)
  510. {
  511. RemoveActiveEffects({EffectWidgetsTypes.COVER_FLASHBANG});
  512. return;
  513. }*/
  514. }
  515. protected void UpdateFlashbangEffect(ImageWidget w)
  516. {
  517. w.SetAlpha(1 - m_FlashbangCoverAlphaVal);
  518. }
  519. //-----------------------------------------
  520. //root handling (generic 'Widget', so mainly alpha and hiding?)
  521. //-----------------------------------------
  522. protected void HandleWidgetRoot(float timeSlice = 0, Param p = null, int handle = -1)
  523. {
  524. switch (handle)
  525. {
  526. default:
  527. {
  528. Param1<float> par = Param1<float>.Cast(p);
  529. if (par)
  530. {
  531. float alpha_mod = Math.Clamp(par.param1,0.0,1.0);
  532. //Print(alpha_mod);
  533. m_Root.SetAlpha(alpha_mod);
  534. }
  535. }
  536. break;
  537. }
  538. }
  539. //-----------------------------------------
  540. //! Generic update, called on frame from the player
  541. override void Update(float timeSlice)
  542. {
  543. if (m_SuspendRequests.Count() > 0)
  544. {
  545. return;
  546. }
  547. UpdateWidgets(-1,timeSlice);
  548. }
  549. /*
  550. override void SetBreathIntensityStamina(float stamina_cap, float stamina_current)
  551. {
  552. float stamina_normalized = Math.InverseLerp(0, stamina_cap, stamina_current);
  553. stamina_normalized = Math.Clamp(stamina_normalized,0,1);
  554. if ( stamina_normalized < STAMINA_SOUND_TR2 )
  555. {
  556. m_BreathMultStamina = 2.0;
  557. }
  558. else if ( stamina_normalized < STAMINA_SOUND_TR1 )
  559. {
  560. m_BreathMultStamina = 1.5;
  561. }
  562. else
  563. {
  564. m_BreathMultStamina = 1.0;
  565. }
  566. }
  567. */
  568. override void OnVoiceEvent(float breathing_resistance01)
  569. {
  570. m_BreathResidue += Math.Lerp(0,0.35,breathing_resistance01);
  571. m_BreathResidue = Math.Clamp(m_BreathResidue,0,1);
  572. }
  573. }