DayZ Scripts
v1.21.156300 ยท Jun 20, 2023
 
Loading...
Searching...
No Matches
PlayerStomach.c
Go to the documentation of this file.
2{
4 float m_Amount;
6 //bool m_IsLiquid;
7 string m_ClassName;
9
10 void StomachItem(string class_name, float amount, NutritionalProfile profile,int foodstage, int agents)
11 {
12 m_Amount = amount;
13 m_Profile = profile;
14 //m_IsLiquid = is_liquid;
15 m_FoodStage = foodstage;
17 m_Agents = agents;
18 }
19
20 string GetClassName()
21 {
22 return m_ClassName;
23 }
24
25 /*
26 void SetLiquid(bool is_liquid)
27 {
28 m_IsLiquid = is_liquid;
29 }
30
31 bool IsLiquid()
32 {
33 return m_IsLiquid;
34 }*/
35
36
37
39 {
40 return m_FoodStage;
41 }
42
43 void SetFoodStage(int food_stage)
44 {
45 m_FoodStage = food_stage;
46 }
47
48 // returns grams or ml's of this item/liquid
49 float GetAmount()
50 {
51 return m_Amount;
52 }
53
54 // adds grams or ml's of this item/liquid
55 void AddAmount(float amount)
56 {
57 m_Amount += amount;
58 }
59
60 void AddAgents(int agents)
61 {
62 m_Agents = m_Agents | agents;
63 }
64
65
66 // "digests" given amount, "outs" nutritional components, and returns 'true' if leads to complete item digestion(no amount left)
67 bool ProcessDigestion(float digestion_points, out float water, out float energy, out float toxicity, out float volume, out int agents, out float consumed_amount)
68 {
69 agents = m_Agents;
70 consumed_amount = GetNutritions(digestion_points, m_Profile, water, energy, toxicity );
71 m_Amount -= consumed_amount;
73 return( m_Amount < 0.001 );
74 }
75
76 float GetNutritions( float digestion_points, NutritionalProfile profile, out float water, out float energy, out float toxicity )
77 {
78 float energy_per_unit = profile.GetEnergy() / 100;
79 float water_per_unit = profile.GetWaterContent() / 100;
80 float toxicity_per_unit = profile.GetToxicity();
81 float digestability = profile.GetDigestibility();
82
83 if(digestability == 0)//if undefined
84 {
85 digestability = 1;
86 }
87
88 float consumed_quantity = digestion_points * digestability;
89
90 if( m_Amount < consumed_quantity )
91 {
92 consumed_quantity = m_Amount;
93 }
94 if ( consumed_quantity > 0 )
95 {
96 water = consumed_quantity * water_per_unit;
97 energy = consumed_quantity * energy_per_unit;
98 toxicity = consumed_quantity * toxicity_per_unit;
99 }
100 return consumed_quantity;
101 }
102}
103
104class PlayerStomach
105{
106 const int DIGESTING_WATER = 1;
107 const int DIGESTING_ENERGY = 2;
108
109 const int quantity_bit_offset = 16;
110 const int id_bit_offset = 4;//based on food stage count(+1 for safe measure)
111 static int CHECKSUM;
113 const int ACCEPTABLE_QUANTITY_MAX = 32768;
117 static const bool m_InitData = PlayerStomach.InitData();
119 int m_AgentTransferFilter;//bit mask that prevents agents set in the mask from passing to the player
124 const int STORAGE_VERSION = 106;
125
126
128 {
129 m_Player = player;
130 }
131
133 {
134
135 }
136
137
139 {
140 return m_StomachVolume;
141 }
142
144 {
145 m_StomachContents.Clear();
146 m_StomachVolume = 0.0;
147 }
148
149 void SetAgentTransferFilter(int filter_agents)
150 {
152 }
153
155 {
157 }
158
159 static void RegisterItem(string classname, int id)
160 {
161 int hash = classname.Hash();
162 CHECKSUM = CHECKSUM^hash; //xor hash vs current checksum
163// Print(classname);
164// Print(CHECKSUM);
165 m_NamesToIDs.Insert(classname, id);
166 m_IDsToNames.Insert(id, classname);
167 }
168
169 static string GetClassnameFromID(int id)
170 {
171 return m_IDsToNames.Get(id);
172 }
173
174 static int GetIDFromClassname(string name)
175 {
176 if(!m_NamesToIDs.Contains(name))
177 return -1;
178 return m_NamesToIDs.Get(name);
179 }
180
181 static bool InitData()
182 {
183 TStringArray all_paths = new TStringArray;
184
185 all_paths.Insert("CfgVehicles");
186 all_paths.Insert("cfgLiquidDefinitions");
187
188 string config_path;
189 string child_name;
190 int scope;
191 string path;
192 int consumable_count;
193 for(int i = 0; i < all_paths.Count(); i++)
194 {
195 config_path = all_paths.Get(i);
196 int children_count = GetGame().ConfigGetChildrenCount(config_path);
197
198 for(int x = 0; x < children_count; x++)
199 {
200 GetGame().ConfigGetChildName(config_path, x, child_name);
201 path = config_path + " " + child_name;
202 scope = GetGame().ConfigGetInt( config_path + " " + child_name + " scope" );
203 bool should_check = 1;
204 if( config_path == "CfgVehicles" && scope == 0)
205 {
206 should_check = 0;
207 }
208
209 if ( should_check )
210 {
211 bool has_nutrition = GetGame().ConfigIsExisting(path + " Nutrition");
212 bool has_stages = GetGame().ConfigIsExisting(path + " Food");
213
214 if(has_nutrition || has_stages)
215 {
216 //Print("child name:" + child_name);
217 RegisterItem(child_name, consumable_count);//consumable_count value serves as an unique ID for each item
218 consumable_count++;
219 }
220 }
221 }
222 }
223 //Print("consumable_count " + consumable_count);
224 return true;
225 }
226
228 {
229 return STORAGE_VERSION;
230 }
231
233 {
234 return (m_DigestingType != 0);
235 }
236
238 {
239 return m_DigestingType;
240 }
241
242
243 void Update(float delta_time)
244 {
245 ProcessNutrients(delta_time);
246 }
247
248 void ProcessNutrients(float delta_time)
249 {
250 StomachItem item;
251 int stomach_items_count = m_StomachContents.Count();
252 m_DigestingType = 0;
253 if(stomach_items_count == 0)
254 return;
255
256 float digestion_points_per_item = (DIGESTION_POINTS / stomach_items_count) * delta_time;
257 m_StomachVolume = 0;//reset, it's accumulated with each pass
258 for(int i = 0; i < m_StomachContents.Count(); i ++)
259 {
260 item = m_StomachContents.Get(i);
261 float water, energy, toxicity, volume, consumed_amount;
262 int agents;
263 if(item.ProcessDigestion( digestion_points_per_item, water, energy, toxicity, volume, agents, consumed_amount ))
264 {
265 m_StomachContents.Remove(i);
266 i--;
267 }
268 m_StomachVolume += volume;
269 m_Player.GetStatEnergy().Add(energy);
270 m_Player.GetStatWater().Add(water);
271
272 if(energy > 0)
273 {
275 }
276
277 if(water > 0)
278 {
280 }
281
282 DigestAgents(agents, consumed_amount);
283 }
284 }
285
286
287 void DigestAgents(int agents, float quantity)
288 {
289 if(!agents)
290 return;
291 agents = agents & (~m_AgentTransferFilter);//filter against the agent filter mask
292 int highest_bit = Math.Log2(agents) + 1;
293 for(int i = 0; i < highest_bit;i++)
294 {
295 int agent = (1 << i)& agents;
296 if( agent )
297 {
298 m_Player.m_AgentPool.DigestAgent(agent, quantity);
299 }
300 }
301 }
302
304 {
305 Print("================================");
306 for(int i = 0; i < m_StomachContents.Count(); i++)
307 {
308 string itemname = m_StomachContents.Get(i).m_ClassName;
309 float amount = m_StomachContents.Get(i).GetAmount();
310 int food_stage = m_StomachContents.Get(i).GetFoodStage();
311 int agents = m_StomachContents.Get(i).m_Agents;
312 Print(">");
313 Print("itemname:" + itemname);
314 Print("amount:" + amount);
315 Print("food_stage:" + food_stage);
316 Print("agents:" + agents);
317 Print(">");
318 }
319 Print("m_StomachVolume:" + m_StomachVolume);
320 Print("================================");
321 }
322
323 void AddToStomach(string class_name, float amount, int food_stage = 0, int agents = 0)
324 {
326 return;
327 bool is_liquid;
328
330 if(profile)
331 {
332 is_liquid = true;
333 }
334 else
335 {
336 profile = Edible_Base.GetNutritionalProfile(null,class_name, food_stage);
337 }
338
339 if(profile)
340 {
341 // sanity checks start
342 if(amount > ACCEPTABLE_QUANTITY_MAX || amount < 0)
343 {
344 amount = 0;
345 }
346 if (food_stage < 0 || food_stage > ACCEPTABLE_FOODSTAGE_MAX)
347 {
348 food_stage = FoodStageType.RAW;
349 }
350 // sanity checks end
351
352 agents = agents | profile.GetAgents();
353 bool found = false;
354 for(int i = 0; i < m_StomachContents.Count(); i++)
355 {
356 StomachItem stomach_item = m_StomachContents.Get(i);
357 if(stomach_item.GetClassName() == class_name )
358 {
359 if (is_liquid || stomach_item.GetFoodStage() == food_stage)
360 {
361 stomach_item.AddAmount(amount);
362 stomach_item.AddAgents(agents);
363 found = true;
364 }
365 }
366 }
367
368 if(!found)
369 {
370 m_StomachContents.Insert(new StomachItem(class_name, amount, profile, food_stage, agents));
371 }
372 }
373 }
374
376 {
377 ctx.Write( PlayerStomach.CHECKSUM );
378 ctx.Write( m_StomachContents.Count() );
379 StomachItem stomach_item;
380 for(int i = 0; i < m_StomachContents.Count();i++)
381 {
382 stomach_item = m_StomachContents.Get(i);
383 int id = PlayerStomach.GetIDFromClassname(stomach_item.m_ClassName);
384 //Print("SAVE id:" + id);
385 //Print("SAVE id_bit_offset:" + id_bit_offset);
386
387 int write_result = stomach_item.m_FoodStage | ( id << id_bit_offset );
388 write_result = write_result | ((int)stomach_item.m_Amount << quantity_bit_offset);
389 ctx.Write( write_result );
390 ctx.Write( stomach_item.m_Agents );
391 //Print("SAVE write_result:" + write_result);
392 }
393 //Print("SAVE CHECKSUM:" + PlayerStomach.CHECKSUM);
394 }
395
396 bool OnStoreLoad(ParamsReadContext ctx, int version)
397 {
398 int checksum, count;
399 if(!ctx.Read(checksum))
400 {
401 return false;
402 }
403
404 if(!ctx.Read(count))
405 {
406 return false;
407 }
408 for(int i = 0; i < count; i++)
409 {
410 int value, agents;
411 if(!ctx.Read(value) )
412 {
413 return false;
414 }
415 if(!ctx.Read(agents) )
416 {
417 return false;
418 }
419 if(checksum == CHECKSUM)//if checksum matches, add to stomach, otherwise throw the data away but go through the de-serialization to keep the stream intact
420 {
421 int amount = value >> quantity_bit_offset;//isolate amount bits
422 int id_mask = Math.Pow(2, quantity_bit_offset) - 1;
423 int id = (id_mask & value) >> id_bit_offset;//isolate id bits
424 int food_mask = Math.Pow(2, id_bit_offset) - 1;
425 int food_stage = value & food_mask;
426 //Print("LOAD value:" + value);
427 //Print("LOAD id:" + id);
428 //Print("LOAD id_bit_offset:" + id_bit_offset);
429 //Print("LOAD food_stage:" + food_stage);
430 string classname = GetClassnameFromID(id);
431 AddToStomach(classname, amount, food_stage, agents);
432 }
433 }
434 //Print("LOAD checksum:" + checksum);
435 if(checksum != CHECKSUM)
436 {
437 Print("Stomach checksum fail");
438 }
439 return true;
440 }
441
443 {
444 int count = m_StomachContents.Count();
445 for(int i = 0; i < m_StomachContents.Count();i++)
446 {
447 int id = PlayerStomach.GetIDFromClassname(m_StomachContents.Get(i).m_ClassName);
448 int food_stage = m_StomachContents.Get(i).m_FoodStage;
449 int agents = m_StomachContents.Get(i).m_Agents;
450 float amount = m_StomachContents.Get(i).m_Amount;
451 Param4<int,int,int,float> p4 = new Param4<int,int,int,float>(id, food_stage, agents, amount);
452 object_out.Insert(p4);
453 }
454 Param1<float> p1 = new Param1<float>(m_StomachVolume);
455 object_out.Insert(p1);
456 return count;
457
458 }
459}
class RecipeCacheData int
FoodStageType
Definition FoodStage.c:2
DayZPlayer m_Player
Definition Hand_Events.c:42
Icon x
void OnStoreSave(ParamsWriteContext ctx)
int GetStorageVersion()
const int STORAGE_VERSION
bool OnStoreLoad(ParamsReadContext ctx, int version)
class OptionSelectorMultistate extends OptionSelector class_name
int m_DigestingType
void PrintUpdate()
void AddToStomach(string class_name, float amount, int food_stage=0, int agents=0)
void ClearContents()
const int ACCEPTABLE_QUANTITY_MAX
const int ACCEPTABLE_FOODSTAGE_MAX
int GetAgentTransferFilter()
bool IsDigesting()
static ref map< int, string > m_IDsToNames
static int CHECKSUM
const float DIGESTION_POINTS
class StomachItem DIGESTING_WATER
const int quantity_bit_offset
void DigestAgents(int agents, float quantity)
int GetDebugObject(array< ref Param > object_out)
const int DIGESTING_ENERGY
bool m_Digesting
void ProcessNutrients(float delta_time)
static void RegisterItem(string classname, int id)
int GetDigestingType()
static string GetClassnameFromID(int id)
float GetStomachVolume()
void SetAgentTransferFilter(int filter_agents)
ref array< ref StomachItem > m_StomachContents
static bool InitData()
static const bool m_InitData
const int id_bit_offset
void ~PlayerStomach()
float m_StomachVolume
static int GetIDFromClassname(string name)
int m_AgentTransferFilter
static ref map< string, int > m_NamesToIDs
void PlayerStomach(PlayerBase player)
string name
proto native int ConfigGetChildrenCount(string path)
Get count of subclasses in config class on path.
proto native int ConfigGetInt(string path)
Get int value from config on path.
proto native bool ConfigIsExisting(string path)
proto bool ConfigGetChildName(string path, int index, out string name)
Get name of subclass in config class on path.
Definition Liquid.c:2
static NutritionalProfile GetNutritionalProfileByName(string class_name)
Definition Liquid.c:222
Definition EnMath.c:7
static const float DIGESTION_SPEED
Serialization general interface. Serializer API works with:
Definition Serializer.c:56
proto bool Write(void value_out)
proto bool Read(void value_in)
void AddAgents(int agents)
void SetFoodStage(int food_stage)
float GetAmount()
bool ProcessDigestion(float digestion_points, out float water, out float energy, out float toxicity, out float volume, out int agents, out float consumed_amount)
string GetClassName()
void StomachItem(string class_name, float amount, NutritionalProfile profile, int foodstage, int agents)
int GetFoodStage()
string m_ClassName
float GetNutritions(float digestion_points, NutritionalProfile profile, out float water, out float energy, out float toxicity)
void AddAmount(float amount)
ref NutritionalProfile m_Profile
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
proto native CGame GetGame()
proto void Print(void var)
Prints content of variable to console/log.
array< string > TStringArray
Definition EnScript.c:685
static proto float Log2(float x)
Returns the binary (base-2) logarithm of x.
static proto float Pow(float v, float power)
Return power of v ^ power.
proto native int Hash()
Returns hash of string.
proto native volatile void Update()