bleedingsourcesmanagerserver.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. class BleedingSourcesManagerServer extends BleedingSourcesManagerBase
  2. {
  3. const float TICK_INTERVAL_SEC = 3;
  4. float m_Tick;
  5. bool m_DisableBloodLoss = false;
  6. ref array<int> m_DeleteList = new array<int>;
  7. protected bool m_ProcessSourcesRemoval = false; //to avoid constant array counting
  8. const int STORAGE_VERSION = 103;
  9. protected BleedingSourceZone GetBleedingSourceZone(int bit)
  10. {
  11. return m_BleedingSourceZone.Get(GetSelectionNameFromBit(bit));
  12. }
  13. int GetStorageVersion()
  14. {
  15. return STORAGE_VERSION;
  16. }
  17. void RequestDeletion(int bit)
  18. {
  19. if (m_DeleteList.Find(bit) == -1) //avoids multiple removal of the same bit/source
  20. {
  21. m_DeleteList.Insert(bit);
  22. m_ProcessSourcesRemoval = true;
  23. }
  24. }
  25. override protected void AddBleedingSource(int bit)
  26. {
  27. #ifdef DEVELOPER
  28. if (m_Player && !m_Player.GetAllowDamage())//full invincibility prevents bleeding source creation
  29. return;
  30. #endif
  31. m_Player.SetBleedingBits(m_Player.GetBleedingBits() | bit);
  32. super.AddBleedingSource(bit);
  33. m_Player.OnBleedingSourceAdded();
  34. }
  35. override protected bool RemoveBleedingSource(int bit)
  36. {
  37. if (super.RemoveBleedingSource(bit))
  38. {
  39. m_Player.OnBleedingSourceRemovedEx(m_Item);
  40. float chanceToInfect;
  41. if (m_Item)
  42. {
  43. chanceToInfect = m_Item.GetInfectionChance(0, CachedObjectsParams.PARAM1_BOOL);
  44. }
  45. else
  46. {
  47. chanceToInfect = PlayerConstants.BLEEDING_SOURCE_CLOSE_INFECTION_CHANCE;
  48. }
  49. float diceRoll = Math.RandomFloat01();
  50. if (diceRoll < chanceToInfect)
  51. {
  52. m_Player.InsertAgent(eAgents.WOUND_AGENT);
  53. }
  54. }
  55. else
  56. {
  57. ErrorEx("Failed to remove bleeding source:" + bit,ErrorExSeverity.INFO);
  58. }
  59. int inverse_bit_mask = ~bit;
  60. m_Player.SetBleedingBits(m_Player.GetBleedingBits() & inverse_bit_mask);
  61. m_Item = null;//reset, so that next call, if induced by self-healing, will have no item
  62. return true;
  63. }
  64. void RemoveAnyBleedingSource()
  65. {
  66. int bleeding_sources_bits = m_Player.GetBleedingBits();
  67. int rightmost_bit = bleeding_sources_bits & (-bleeding_sources_bits);
  68. RemoveBleedingSource(rightmost_bit);
  69. }
  70. void RemoveMostSignificantBleedingSource()
  71. {
  72. int bit = GetMostSignificantBleedingSource();
  73. if (bit != 0)
  74. RemoveBleedingSource(bit);
  75. }
  76. void RemoveMostSignificantBleedingSourceEx(ItemBase item)
  77. {
  78. SetItem(item);
  79. RemoveMostSignificantBleedingSource();
  80. }
  81. int GetMostSignificantBleedingSource()
  82. {
  83. int bleeding_sources_bits = m_Player.GetBleedingBits();
  84. float highest_flow;
  85. int highest_flow_bit;
  86. int bit_offset;
  87. for (int i = 0; i < BIT_INT_SIZE; ++i)
  88. {
  89. int bit = 1 << bit_offset;
  90. if ((bit & bleeding_sources_bits) != 0)
  91. {
  92. BleedingSourceZone meta = GetBleedingSourceMeta(bit);
  93. if (meta)
  94. {
  95. if (meta.GetFlowModifier() > highest_flow)
  96. {
  97. highest_flow = meta.GetFlowModifier();
  98. highest_flow_bit = bit;
  99. //Print(meta.GetSelectionName());
  100. }
  101. }
  102. }
  103. bit_offset++;
  104. }
  105. return highest_flow_bit;
  106. }
  107. void OnTick(float delta_time)
  108. {
  109. m_Tick += delta_time;
  110. if (m_ProcessSourcesRemoval)
  111. {
  112. while (m_DeleteList.Count() > 0)
  113. {
  114. RemoveBleedingSource(m_DeleteList.Get(0));
  115. m_DeleteList.Remove(0);
  116. }
  117. m_ProcessSourcesRemoval = false;
  118. }
  119. if (m_Tick > TICK_INTERVAL_SEC)
  120. {
  121. float blood_scale = Math.InverseLerp(PlayerConstants.BLOOD_THRESHOLD_FATAL, PlayerConstants.BLEEDING_LOW_PRESSURE_BLOOD, m_Player.GetHealth("GlobalHealth", "Blood"));
  122. blood_scale = Math.Clamp(blood_scale, PlayerConstants.BLEEDING_LOW_PRESSURE_MIN_MOD, 1);
  123. for (int i = 0; i < m_BleedingSources.Count(); ++i)
  124. {
  125. m_BleedingSources.GetElement(i).OnUpdateServer(m_Tick, blood_scale, m_DisableBloodLoss);
  126. }
  127. m_Tick = 0;
  128. }
  129. }
  130. void ActivateAllBS()
  131. {
  132. for (int i = 0; i < m_BleedingSourceZone.Count(); ++i)
  133. {
  134. int bit = m_BleedingSourceZone.GetElement(i).GetBit();
  135. if (CanAddBleedingSource(bit))
  136. {
  137. AddBleedingSource(bit);
  138. }
  139. }
  140. }
  141. //damage must be to "Blood" healthType
  142. void ProcessHit(float damage, EntityAI source, int component, string zone, string ammo, vector modelPos)
  143. {
  144. float dmg_max = m_Player.GetMaxHealth(zone, "Blood");
  145. float bleed_threshold = GetGame().ConfigGetFloat("CfgAmmo " + ammo + " DamageApplied bleedThreshold");
  146. string damageTypeString = GetGame().ConfigGetTextOut("CfgAmmo " + ammo + " DamageApplied type");
  147. bleed_threshold = Math.Clamp(bleed_threshold,0,1);
  148. float bleedingChance;
  149. bool createBleedingSource = false;
  150. // 'true' only when the damageTypeString is handled there
  151. if (BleedChanceData.CalculateBleedChance(damageTypeString, damage, bleed_threshold,bleedingChance))
  152. {
  153. float roll = Math.RandomFloat01();
  154. createBleedingSource = bleedingChance != 0 && bleedingChance >= roll;
  155. #ifdef ENABLE_LOGGING
  156. if (LogManager.IsBleedingChancesLogEnable())
  157. {
  158. Debug.BleedingChancesLog(roll.ToString(), "BleedingSourcesManagerServer" , "n/a", "bleeding random roll:");
  159. }
  160. #endif
  161. }
  162. else if (source && source.IsZombie())
  163. {
  164. int chance = Math.RandomInt(0,100);
  165. if (chance <= damage)
  166. {
  167. createBleedingSource = true;
  168. }
  169. }
  170. else if (damage > (dmg_max * (1 - bleed_threshold)))
  171. {
  172. createBleedingSource = true;
  173. }
  174. if (createBleedingSource)
  175. {
  176. #ifdef ENABLE_LOGGING
  177. if (LogManager.IsBleedingChancesLogEnable())
  178. {
  179. Debug.BleedingChancesLog("true", "BleedingSourcesManagerServer" , "n/a", "Attempting to create bleeding source");
  180. }
  181. #endif
  182. AttemptAddBleedingSource(component);
  183. }
  184. }
  185. void DebugActivateBleedingSource(int source)
  186. {
  187. RemoveAllSources();
  188. if (source >= m_BleedingSourceZone.Count() || !m_BleedingSourceZone.GetElement(source)) return;
  189. int bit = m_BleedingSourceZone.GetElement(source).GetBit();
  190. if (bit && CanAddBleedingSource(bit))
  191. {
  192. AddBleedingSource(bit);
  193. }
  194. }
  195. void SetBloodLoss(bool status)
  196. {
  197. m_DisableBloodLoss = status;
  198. }
  199. void OnStoreSave(ParamsWriteContext ctx)
  200. {
  201. //int count = m_BleedingSources.Count();
  202. int active_bits = m_Player.GetBleedingBits();
  203. ctx.Write(active_bits);
  204. int bit_offset = 0;
  205. for (int i = 0; i < BIT_INT_SIZE; ++i)
  206. {
  207. int bit = 1 << bit_offset;
  208. if ((bit & active_bits) != 0)
  209. {
  210. int active_time = GetBleedingSourceActiveTime(bit);
  211. eBleedingSourceType type = GetBleedingSourceType(bit);
  212. ctx.Write(active_time);
  213. ctx.Write(type);
  214. }
  215. bit_offset++;
  216. }
  217. }
  218. bool OnStoreLoad(ParamsReadContext ctx, int version)
  219. {
  220. int active_bits;
  221. if (!ctx.Read(active_bits))
  222. {
  223. return false;
  224. }
  225. int bit_offset = 0;
  226. for (int i = 0; i < BIT_INT_SIZE; ++i)
  227. {
  228. int bit = 1 << bit_offset;
  229. if ((bit & active_bits) != 0 && CanAddBleedingSource(bit))
  230. {
  231. AddBleedingSource(bit);
  232. int active_time = 0;
  233. if (!ctx.Read(active_time))
  234. {
  235. return false;
  236. }
  237. else
  238. {
  239. SetBleedingSourceActiveTime(bit,active_time);
  240. }
  241. if (version >= 121)//type was added in this version
  242. {
  243. eBleedingSourceType type = eBleedingSourceType.NORMAL;
  244. if (!ctx.Read(type))
  245. {
  246. return false;
  247. }
  248. else
  249. {
  250. SetBleedingSourceType(bit,type);
  251. }
  252. }
  253. }
  254. bit_offset++;
  255. }
  256. return true;
  257. }
  258. void ~BleedingSourcesManagerServer()
  259. {
  260. if (m_Player && !m_Player.IsAlive())
  261. RemoveAllSources();
  262. }
  263. }