liquid.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. //extendable!
  2. class LiquidInfo
  3. {
  4. string m_LiquidClassName;
  5. string m_LiquidDisplayName;
  6. int m_LiquidType;
  7. float m_TemperatureLiquidFreezeThreshold = float.LOWEST;
  8. float m_TemperatureLiquidThawThreshold = float.LOWEST;
  9. float m_TemperatureLiquidBoilThreshold = Cooking.LIQUID_BOILING_POINT;
  10. float m_Flammability;
  11. ref NutritionalProfile m_NutriProfile;
  12. void LiquidInfo(string className, NutritionalProfile profile)
  13. {
  14. m_NutriProfile = profile;
  15. Init(className);
  16. }
  17. protected void Init(string className)
  18. {
  19. string path = "cfgLiquidDefinitions " + className;
  20. m_LiquidClassName = className;
  21. GetGame().ConfigGetTextRaw(string.Format("%1 displayName", path), m_LiquidDisplayName);
  22. GetGame().FormatRawConfigStringKeys(m_LiquidDisplayName);
  23. m_LiquidType = GetGame().ConfigGetInt(string.Format("%1 type", path));
  24. if (GetGame().ConfigIsExisting(string.Format("%1 liquidFreezeThreshold", path)))
  25. m_TemperatureLiquidFreezeThreshold = GetGame().ConfigGetFloat(string.Format("%1 liquidFreezeThreshold", path));
  26. if (GetGame().ConfigIsExisting(string.Format("%1 liquidThawThreshold", path)))
  27. m_TemperatureLiquidThawThreshold = GetGame().ConfigGetFloat(string.Format("%1 liquidThawThreshold", path));
  28. if (GetGame().ConfigIsExisting(string.Format("%1 liquidBoilingThreshold", path)))
  29. m_TemperatureLiquidBoilThreshold = GetGame().ConfigGetFloat(string.Format("%1 liquidBoilingThreshold", path));
  30. m_Flammability = GetGame().ConfigGetFloat(string.Format("%1 flammability", path));
  31. }
  32. }
  33. class Liquid
  34. {
  35. static ref map<int, ref NutritionalProfile> m_AllLiquidsByType = new map<int, ref NutritionalProfile>; //DEPRECATED!
  36. static ref map<string, ref NutritionalProfile> m_AllLiquidsByName = new map<string, ref NutritionalProfile>; //DEPRECATED!
  37. static ref map<int, ref LiquidInfo> m_LiquidInfosByType = new map<int, ref LiquidInfo>;
  38. static ref map<string, ref LiquidInfo> m_LiquidInfosByName = new map<string, ref LiquidInfo>;
  39. static bool m_Init = InitAllLiquids();
  40. static string GetLiquidClassname(int liquid_type)
  41. {
  42. LiquidInfo info = m_LiquidInfosByType.Get(liquid_type);
  43. if (info)
  44. {
  45. return info.m_LiquidClassName;
  46. }
  47. return "";
  48. }
  49. static bool InitAllLiquids()
  50. {
  51. string cfg_classname = "cfgLiquidDefinitions";
  52. string property_value = "NULL_PROPERTY";
  53. int cfg_item_count = g_Game.ConfigGetChildrenCount(cfg_classname);
  54. for (int i = 0; i < cfg_item_count; i++)
  55. {
  56. string liquid_class_name;
  57. GetGame().ConfigGetChildName(cfg_classname, i, liquid_class_name);
  58. string liquid_full_path = string.Format("%1 %2",cfg_classname, liquid_class_name);
  59. int config_liquid_type = GetGame().ConfigGetInt(string.Format("%1 type", liquid_full_path));
  60. NutritionalProfile profile = SetUpNutritionalProfile(config_liquid_type, liquid_class_name);
  61. LiquidInfo info = new LiquidInfo(liquid_class_name, profile);
  62. m_LiquidInfosByType.Insert(config_liquid_type, info);
  63. m_LiquidInfosByName.Insert(liquid_class_name, info);
  64. //legacy stuff
  65. m_AllLiquidsByType.Insert(config_liquid_type, profile);
  66. m_AllLiquidsByName.Insert(liquid_class_name, profile);
  67. }
  68. return true;
  69. }
  70. //---------------------------------------------------------------------------------------------------------
  71. static void Transfer(ItemBase source_ent, ItemBase target_ent, float quantity = -1)
  72. {
  73. if (!Liquid.CanTransfer(source_ent, target_ent))
  74. return;
  75. float source_quantity = source_ent.GetQuantity();
  76. float target_quantity = target_ent.GetQuantity();
  77. float targetCfgWeight = target_ent.m_ConfigWeight;
  78. int source_liquid_type = source_ent.GetLiquidType();
  79. float available_capacity = target_ent.GetQuantityMax() - target_quantity;
  80. float quantity_to_transfer;
  81. //transfers all
  82. if (quantity == -1)
  83. {
  84. quantity_to_transfer = Math.Clamp(source_quantity,0,available_capacity);
  85. }
  86. //transfers exact ammount
  87. else
  88. {
  89. quantity_to_transfer = Math.Clamp(Math.Min(source_quantity,quantity),0,available_capacity);
  90. }
  91. PluginTransmissionAgents m_mta = PluginTransmissionAgents.Cast(GetPlugin(PluginTransmissionAgents));
  92. m_mta.TransmitAgents(source_ent, target_ent, AGT_TRANSFER_COPY);
  93. source_ent.AddQuantity(-quantity_to_transfer);
  94. float retultTemp = (source_ent.GetTemperature() * quantity_to_transfer + target_ent.GetTemperature() * (targetCfgWeight + target_quantity)) / (targetCfgWeight + target_quantity + quantity_to_transfer);
  95. target_ent.SetTemperature(retultTemp);
  96. Liquid.FillContainer(target_ent,source_liquid_type,quantity_to_transfer);
  97. }
  98. static bool CanTransfer(ItemBase source_ent, ItemBase target_ent)
  99. {
  100. if (!source_ent || !target_ent)
  101. return false;
  102. Barrel_ColorBase barrelTarget = Barrel_ColorBase.Cast(target_ent);
  103. Barrel_ColorBase barrelSource = Barrel_ColorBase.Cast(source_ent);
  104. if ((barrelTarget && !barrelTarget.IsOpen()) || (barrelSource && !barrelSource.IsOpen()))
  105. {
  106. return false;
  107. }
  108. if (source_ent.GetIsFrozen())
  109. {
  110. return false;
  111. }
  112. float source_quantity = source_ent.GetQuantity();
  113. if (source_quantity <= 0)
  114. {
  115. //Debug.Log("source has no quantity", "LiquidTransfer");
  116. return false;//if there is nothing to transfer
  117. }
  118. int source_liquid_type = source_ent.GetLiquidType();
  119. if (source_liquid_type < 1)
  120. {
  121. //Debug.Log("source has some quantity, but does not have a valid liquidType set, liquidType = "+ToString(source_liquid_type), "LiquidTransfer");
  122. return false;//if source is not a container
  123. }
  124. if (!CanFillContainer(target_ent,source_liquid_type))
  125. {
  126. return false;
  127. }
  128. return true;
  129. }
  130. static void FillContainer(ItemBase container, int liquid_type, float amount)
  131. {
  132. if (!CanFillContainer(container,liquid_type))
  133. {
  134. return;
  135. }
  136. //filling
  137. container.SetLiquidType(liquid_type);
  138. container.AddQuantity(amount);
  139. }
  140. static void FillContainerEnviro(ItemBase container, int liquid_type, float amount, bool inject_agents = true)
  141. {
  142. float containerCfgWeight = container.m_ConfigWeight;
  143. float retultTemp = (GetLiquidTypeEnviroTemperature(liquid_type) * amount + container.GetTemperature() * (containerCfgWeight + container.GetQuantity())) / (container.GetQuantity() + containerCfgWeight + amount);
  144. container.SetTemperature(retultTemp);
  145. AffectContainerOnFill(container,liquid_type,amount);
  146. FillContainer(container, TranslateLiquidType(liquid_type), amount);
  147. if (inject_agents)
  148. {
  149. PluginTransmissionAgents plugin = PluginTransmissionAgents.Cast(GetPlugin(PluginTransmissionAgents));
  150. int agtSource;
  151. switch (liquid_type)
  152. {
  153. case LIQUID_FRESHWATER:
  154. case LIQUID_RIVERWATER:
  155. case LIQUID_STILLWATER:
  156. agtSource = AGT_WATER_POND;
  157. break;
  158. case LIQUID_SNOW:
  159. agtSource = AGT_SNOW;
  160. break;
  161. case LIQUID_HOTWATER:
  162. agtSource = AGT_WATER_HOT_SPRING;
  163. break;
  164. default:
  165. agtSource = AGT_NONE;
  166. break;
  167. }
  168. plugin.TransmitAgents(NULL, container, agtSource, amount);
  169. }
  170. }
  171. static void AffectContainerOnFill(ItemBase container, int liquid_type, float amount)
  172. {
  173. container.AffectLiquidContainerOnFill(liquid_type,amount);
  174. }
  175. static bool IsLiquidDrinkWater(int liquidType)
  176. {
  177. if (liquidType & (LIQUID_GROUP_DRINKWATER))
  178. return true;
  179. return false;
  180. }
  181. //! Translates 'administrative' liquid types into liquid types with valid config class
  182. static int TranslateLiquidType(int liquidType)
  183. {
  184. if (IsLiquidDrinkWater(liquidType))
  185. return LIQUID_WATER;
  186. else
  187. return liquidType;
  188. }
  189. static bool CanFillContainer(ItemBase container, int liquid_type, bool ignore_fullness_check = false)
  190. {
  191. if (!container)
  192. return false;
  193. bool is_container_full = container.IsFullQuantity();
  194. if (is_container_full && !ignore_fullness_check)
  195. {
  196. //Debug.Log("container is full", "LiquidTransfer");
  197. return false;
  198. }
  199. int container_mask = container.GetLiquidContainerMask();
  200. if (container_mask == 0)
  201. {
  202. //Debug.Log("target is not a container", "LiquidTransfer");
  203. return false;//if the target liquidContainerType is set to 0
  204. }
  205. if ((liquid_type & container_mask) == 0)
  206. {
  207. //Debug.Log("target liquidContainerType does not support this liquid type", "LiquidTransfer");
  208. return false;
  209. }
  210. float container_quantity = container.GetQuantity();
  211. int container_liquid_type = container.GetLiquidType();
  212. if (container_quantity > 0 && container_liquid_type != liquid_type)
  213. {
  214. //Debug.Log("target is not empty AND is of different liquid type than liquid_type added in", "LiquidTransfer");
  215. return false;
  216. }
  217. return true;
  218. }
  219. //! Gets liquid temperature from the enviroment
  220. /*!
  221. \param[in] liquidType Type of liquid.
  222. */
  223. static float GetLiquidTypeEnviroTemperature(int liquidType)
  224. {
  225. float ret = GetGame().GetMission().GetWorldData().GetLiquidTypeEnviroTemperature(liquidType);
  226. //ret = Math.Max(ret,GetLiquidFreezeThreshold(liquidType));
  227. return ret;
  228. }
  229. private static string GetLiquidConfigProperty(int liquid_type, string property_name, bool is_nutrition_property = false)
  230. {
  231. string cfg_classname = "cfgLiquidDefinitions";
  232. string property_value = "NULL_PROPERTY";
  233. int cfg_item_count = g_Game.ConfigGetChildrenCount(cfg_classname);
  234. for (int i = 0; i < cfg_item_count; i++)
  235. {
  236. string liquid_class_name;
  237. GetGame().ConfigGetChildName(cfg_classname, i, liquid_class_name);
  238. string liquid_full_path = string.Format("%1 %2", cfg_classname, liquid_class_name);
  239. int config_liquid_type = GetGame().ConfigGetInt(string.Format("%1 type", liquid_full_path));
  240. if (config_liquid_type == liquid_type)// found the specific class, now lets extract the values
  241. {
  242. if (!is_nutrition_property)
  243. {
  244. GetGame().ConfigGetText(string.Format("%1 %2", liquid_full_path, property_name), property_value);
  245. return property_value;
  246. }
  247. else
  248. {
  249. GetGame().ConfigGetText(string.Format("%1 Nutrition %2", liquid_full_path, property_name), property_value);
  250. return property_value;
  251. }
  252. }
  253. }
  254. return property_value;
  255. }
  256. static NutritionalProfile GetNutritionalProfileByType(int liquid_type)
  257. {
  258. LiquidInfo info = m_LiquidInfosByType.Get(liquid_type);
  259. if (info && info.m_NutriProfile)
  260. return info.m_NutriProfile;
  261. return null;
  262. }
  263. static NutritionalProfile GetNutritionalProfileByName(string class_name)
  264. {
  265. LiquidInfo info = m_LiquidInfosByName.Get(class_name);
  266. if (info && info.m_NutriProfile)
  267. return info.m_NutriProfile;
  268. return null;
  269. }
  270. static NutritionalProfile SetUpNutritionalProfile(int liquid_type, string liquid_class_name)
  271. {
  272. float energy = Liquid.GetLiquidConfigProperty(liquid_type, "energy", true).ToFloat();
  273. float nutritional_index = Liquid.GetLiquidConfigProperty(liquid_type, "nutritionalIndex", true).ToFloat();
  274. float volume = Liquid.GetLiquidConfigProperty(liquid_type, "fullnessIndex", true).ToFloat();
  275. float water_content = Liquid.GetLiquidConfigProperty(liquid_type, "water", true).ToFloat();
  276. float toxicity = Liquid.GetLiquidConfigProperty(liquid_type, "toxicity", true).ToFloat();
  277. int agents = Liquid.GetLiquidConfigProperty(liquid_type, "agents", true).ToInt();
  278. float digest = Liquid.GetLiquidConfigProperty(liquid_type, "digestibility", true).ToFloat();
  279. NutritionalProfile profile = new NutritionalProfile(energy, water_content, nutritional_index, volume, toxicity, agents, digest);
  280. profile.MarkAsLiquid(liquid_type, liquid_class_name);
  281. return profile;
  282. }
  283. static int GetAgents(int liquid_type)
  284. {
  285. return m_LiquidInfosByType.Get(liquid_type).m_NutriProfile.GetAgents();
  286. }
  287. static float GetToxicity(int liquid_type)
  288. {
  289. return m_LiquidInfosByType.Get(liquid_type).m_NutriProfile.GetToxicity();
  290. }
  291. static float GetWaterContent(int liquid_type)
  292. {
  293. return m_LiquidInfosByType.Get(liquid_type).m_NutriProfile.GetWaterContent();
  294. }
  295. static float GetEnergy(int liquid_type)
  296. {
  297. return m_LiquidInfosByType.Get(liquid_type).m_NutriProfile.GetEnergy();
  298. }
  299. static float GetNutritionalIndex(int liquid_type)
  300. {
  301. return m_LiquidInfosByType.Get(liquid_type).m_NutriProfile.GetNutritionalIndex();
  302. }
  303. static string GetDisplayName(int liquid_type)
  304. {
  305. return m_LiquidInfosByType.Get(liquid_type).m_LiquidDisplayName;
  306. }
  307. static float GetFlammability(int liquid_type)
  308. {
  309. return m_LiquidInfosByType.Get(liquid_type).m_Flammability;
  310. }
  311. static float GetFullness(int liquid_type)
  312. {
  313. return m_LiquidInfosByType.Get(liquid_type).m_NutriProfile.GetFullnessIndex();
  314. }
  315. static float GetDigestibility(int liquid_type)
  316. {
  317. return m_LiquidInfosByType.Get(liquid_type).m_NutriProfile.GetDigestibility();
  318. }
  319. static float GetFreezeThreshold(int liquid_type)
  320. {
  321. return m_LiquidInfosByType.Get(liquid_type).m_TemperatureLiquidFreezeThreshold;
  322. }
  323. static float GetThawThreshold(int liquid_type)
  324. {
  325. return m_LiquidInfosByType.Get(liquid_type).m_TemperatureLiquidThawThreshold;
  326. }
  327. static float GetBoilThreshold(int liquid_type)
  328. {
  329. return m_LiquidInfosByType.Get(liquid_type).m_TemperatureLiquidBoilThreshold;
  330. }
  331. ///////////////////////////
  332. //deprecated methods below
  333. ///////////////////////////
  334. static string GetName(int liquid_type)
  335. {
  336. return Liquid.GetLiquidConfigProperty(liquid_type, "name");
  337. }
  338. };