DayZ Scripts
v1.21.156300 ยท Jun 20, 2023
 
Loading...
Searching...
No Matches
PluginRecipesManager.c
Go to the documentation of this file.
2{
6}
7
8const float ACCEPTABLE_DISTANCE = 5;
9
10const int SANITY_CHECK_ACCEPTABLE_RESULT = ERecipeSanityCheck.NOT_OWNED_BY_ANOTHER_LIVE_PLAYER | ERecipeSanityCheck.CLOSE_ENOUGH;
11
12class PluginRecipesManager extends PluginRecipesManagerBase
13{
15 static ref map<typename, bool> m_RecipesInitializedItem = new ref map<typename, bool>;
16
17
19 const int MAX_NUMBER_OF_RECIPES = GetMaxNumberOfRecipes();
20 const int MAX_CONCURENT_RECIPES = 128;
21 const int MAX_INGREDIENTS = 5;
22
24 int m_ResolvedRecipes[MAX_CONCURENT_RECIPES];
25
26 bool m_EnableDebugCrafting = false;
27 ItemBase m_Ingredients[MAX_INGREDIENTS];
28 int m_IngredientBitMask[MAX_INGREDIENTS];
29 int m_IngredientBitMaskSize[MAX_INGREDIENTS];
30
31 int m_BitsResults[MAX_INGREDIENTS];
32
36
37 ItemBase m_sortedIngredients[MAX_NUMBER_OF_INGREDIENTS];
38
39 ref array<int> m_RecipesMatched = new array<int>;
40 ref array<string> m_CachedItems = new array<string>;
41
42 ref array<ref RecipeBase> m_RecipeList = new array<ref RecipeBase>;//all recipes
43 static ref map<string, int> m_RecipeNamesList = new map<string, int>;//all recipes
44
46
48 {
49 return 2048;
50 }
51
53 {
54
57
58 myTimer1 = new Timer();
59 }
60
62 {
63 }
64
65
67 {
69 }
70
71 void SetEnableDebugCrafting(bool enable)
72 {
73 m_EnableDebugCrafting = enable;
74 }
75
76
77 string GetRecipeName(int recipe_id)
78 {
79 if ( m_RecipeList[recipe_id] ) return m_RecipeList[recipe_id].GetName();
80 return "";
81 }
82
83
84 //will fill the map 'ids' with valid recipes for the 'item1' and 'item2' items, where the key is the recipe ID, and the value is the recipe name
85 int GetValidRecipes(ItemBase item1, ItemBase item2, array<int> ids, PlayerBase player)
86 {
87 if ( item1 == NULL || item2 == NULL )
88 {
89 if (ids) ids.Clear();
90 return 0;
91 }
92
93 if ( ( item1.GetInventory().IsAttachment() && item1.GetHierarchyParent().DisassembleOnLastDetach() ) || ( item2.GetInventory().IsAttachment() && item2.GetHierarchyParent().DisassembleOnLastDetach() ) )
94 {
95 if (ids) ids.Clear();
96 return 0;
97 }
98 m_Ingredients[0] = item1;
99 m_Ingredients[1] = item2;
100
101 return GetValidRecipesProper(2,m_Ingredients, ids, player);
102 }
103
104 int GetValidRecipesProper(int num_of_items, ItemBase items[], array<int> ids, PlayerBase player)
105 {
106 if (ids) ids.Clear();
107 GetRecipeIntersection(num_of_items,items);
108 int numOfRecipes = SortIngredients(num_of_items,items,m_ResolvedRecipes);
109 //will return number of cached recipes for the 2 items being considered,
110 //and save their indexes in m_ResolvedRecipes, please note the m_ResolvedRecipes is a static array,
111 //and does not clear up with each query, so the number of recipes returned is critical to make sure we don't accidentally
112 //mix in some other indexes from previous queries(and obviously loop only as far as we have to)
113 //this also saves the ingredients in the correct assignment as ingredient 1/2 into m_ingredient1/m_ingredient2 arrays, these 3 arrays
114 //therefore provide you with information per each index with: recipeid,ingredient1,ingredient2
115 if ( numOfRecipes == 0 ) return 0;
116 int found = 0;
117 RecipeBase p_recipe = NULL;
118 for (int i = 0; i < numOfRecipes; i++)
119 {
120 p_recipe = m_RecipeList[m_ResolvedRecipes[i]];
121
122 if ( p_recipe.CheckRecipe(m_ingredient1[i],m_ingredient2[i], player) == true )
123 {
124 if (ids) ids.Insert( p_recipe.GetID() );
125 found++;
126 }
127 }
128 return found;
129 }
130
131
132 float GetRecipeLengthInSecs(int recipe_id)
133 {
134 if ( m_RecipeList[recipe_id] ) return m_RecipeList[recipe_id].GetLengthInSecs();
135 return 0;
136 }
137
138 float GetRecipeSpecialty(int recipe_id)
139 {
140 if ( m_RecipeList[recipe_id] ) return m_RecipeList[recipe_id].GetSpecialty();
141 return 0;
142 }
143
144 bool GetIsInstaRecipe(int recipe_id)
145 {
146 if ( m_RecipeList[recipe_id] ) return m_RecipeList[recipe_id].IsInstaRecipe();
147 else return false;
148 }
149
150 override void OnInit()
151 {
152 super.OnInit();
153 //ReadCacheFromFile(PATH_CACHE_FILE);//read the cache from a file
154 //GenerateHumanReadableRecipeList();
155 }
156
157
159 {
160 Debug.Log("CallbackGenerateCache","recipes");
162 //SaveCacheToFile(PATH_CACHE_FILE);//generate the cache and save it to a file
163 //ReadCacheFromFile(PATH_CACHE_FILE);
164 }
165
166 protected void GenerateRecipeCache()
167 {
168 GetGame().ProfilerStart("m_RecipeCache");
169
170 //m_CacheBasesMap.Clear();
171 m_CachedItems.Clear();
172 PluginRecipesManager.m_RecipeCache.Clear();
173
174 TStringArray all_config_paths = new TStringArray;
175
176 all_config_paths.Insert(CFG_VEHICLESPATH);
177 all_config_paths.Insert(CFG_WEAPONSPATH);
178 all_config_paths.Insert(CFG_MAGAZINESPATH);
179 //Debug.Log("Got here 0","caching");
180 string config_path;
181 string child_name;
182 int scope;
183 TStringArray full_path = new TStringArray;
184 WalkRecipes();
185 for (int i = 0; i < all_config_paths.Count(); i++)
186 {
187 config_path = all_config_paths.Get(i);
188 int children_count = GetGame().ConfigGetChildrenCount(config_path);
189
190 for (int x = 0; x < children_count; x++)
191 {
192 GetGame().ConfigGetChildName(config_path, x, child_name);
193 scope = GetGame().ConfigGetInt( config_path + " " + child_name + " scope" );
194
195 if ( scope == 2 )
196 {
197 GetGame().ConfigGetFullPath(config_path +" "+ child_name,/*out*/ full_path);
198 MatchItems(full_path);
199 }
200 }
201 }
202 GetGame().ProfilerStop("m_RecipeCache");
203 }
204
206 {
207 //Print("------------- WalkRecipes --------------");
208 for (int c = 0; c < m_RecipeList.Count(); c++)
209 {
210 RecipeBase recipe = m_RecipeList.Get(c);
211 if (recipe)
212 {
213 //Print(recipe.ClassName());
214 int recipe_id = recipe.GetID();
215 for (int i = 0; i < MAX_NUMBER_OF_INGREDIENTS; i++)
216 {
217 array<string> list = recipe.m_Ingredients[i];
218
219 for (int x = 0; x < list.Count(); x++)
220 {
221 string ingredient = list.Get(x);
222 int mask = Math.Pow(2,i);
223 CacheObject co = m_RecipeCache.Get(ingredient);
224
225 if (!co)
226 {
227 co = new CacheObject;
228 m_RecipeCache.Insert(ingredient,co);
229 }
230 co.AddRecipe(recipe_id, mask);
231 }
232 }
233 }
234 }
235 }
236
237
238 // moved outside method to speed things up
247
248 //this will take the item class name and resolve it against all processed recipes
249 protected void MatchItems(TStringArray full_path)
250 {
251 m_ItemName = full_path.Get(0);
252 m_CoItem = m_RecipeCache.Get(m_ItemName);
253 //Print(m_ItemName);
254 if ( !m_CoItem )
255 {
256 m_CoItem = new CacheObject;
257 m_RecipeCache.Insert(m_ItemName,m_CoItem);
258 }
259 for (int i = 1; i < full_path.Count(); i++)
260 {
261 m_BaseName = full_path.Get(i);
262 m_CoBase = m_RecipeCache.Get(m_BaseName);
263 if ( m_CoBase )//resolve new base classes
264 {
265 m_RcpsArray = m_RecipeCache.Get(m_BaseName).GetRecipes();
266
267 for ( int x = 0; x < m_RcpsArray.Count(); x++ )//base recipes
268 {
269 m_RecipeID = m_RcpsArray.Get(x);
270
271 //item_mask = m_CoItem.GetMaskByRecipeID(m_RecipeID);
272 m_BaseMask = m_CoBase.GetMaskByRecipeID(m_RecipeID);
273
274 m_CoItem.AddRecipe(m_RecipeID,m_BaseMask);
275 }
276 }
277 }
278
279
280 }
281
282 void PerformRecipeServer(int id, ItemBase item_a,ItemBase item_b ,PlayerBase player)
283 {
284 m_Ingredients[0] = item_a;
285 m_Ingredients[1] = item_b;
286
287 if ( !item_a || !item_b )
288 {
289 Error("PerformRecipeServer - one of the items null !!");
290 return;
291 }
292
293 SortIngredientsInRecipe(id, 2,m_Ingredients, m_sortedIngredients);
294
295 bool is_recipe_valid = CheckRecipe(id,m_sortedIngredients[0],m_sortedIngredients[1],player);
296 bool passed_sanity_check = RecipeSanityCheck(2,m_sortedIngredients,player);
297
298 if ( !is_recipe_valid )
299 {
300 Error("PerformRecipeServer - recipe not valid !!");
301 return;
302 }
303 if ( !passed_sanity_check )
304 {
305 Error("PerformRecipeServer - recipe failed to pass sanity check !!");
306 return;
307 }
308 RecipeBase ptrRecipe = m_RecipeList[id];
309 ptrRecipe.PerformRecipe(m_sortedIngredients[0],m_sortedIngredients[1],player);
310 //player.RequestCraftingDisable();
311
312 }
313
315 {
316 FileHandle file = OpenFile("$profile:RecipeDump.txt", FileMode.WRITE);
317 if ( file == 0 )
318 {
319 //error message
320 PrintString("failed to open file RecipeDump");
321 return;
322 }
323 array<int> recipes = new array<int>;
324 for (int i = 0; i < PluginRecipesManager.m_RecipeCache.Count(); i++)
325 {
326 string key = PluginRecipesManager.m_RecipeCache.GetKey(i);
327 CacheObject value = PluginRecipesManager.m_RecipeCache.GetElement(i);
328
329 string line = key;
330 recipes.Clear();
331 recipes.InsertAll( value.GetRecipes() );
332
333 //PrintString("Item: " + key);
334
335 for (int x = 0; x < recipes.Count(); x++)
336 {
337 int recipe_id = recipes.Get(x);
338 string recipe_name = GetRecipeName(recipe_id);
339 line += "," +recipe_name;
340 }
341 FPrintln(file, line);
342 }
343 CloseFile(file);
344 }
345
346 protected bool RecipeSanityCheck(int num_of_ingredients, InventoryItemBase items[], PlayerBase player)
347 {
348 int check_results[MAX_INGREDIENTS];
349
350 for (int i = 0; i < num_of_ingredients;i++)
351 {
352 ItemBase item = items[i];
353 Man item_owner_player = item.GetHierarchyRootPlayer();
354 vector item_pos = item.GetPosition();
355 vector player_pos = player.GetPosition();
356
357 if (item_owner_player == player)
358 {
359 check_results[i] = check_results[i] | ERecipeSanityCheck.IS_IN_PLAYER_INVENTORY;
360 }
361
362 if ( item_owner_player == NULL || item_owner_player == player || !item_owner_player.IsAlive() )
363 {
364 check_results[i] = check_results[i] | ERecipeSanityCheck.NOT_OWNED_BY_ANOTHER_LIVE_PLAYER;
365 }
366
367 if ( vector.Distance(item_pos, player_pos ) < ACCEPTABLE_DISTANCE )
368 {
369 check_results[i] = check_results[i] | ERecipeSanityCheck.CLOSE_ENOUGH;
370 }
371 }
372 for (i = 0; i < num_of_ingredients;i++)
373 {
375 {
376 return false;
377 }
378 }
379 return true;
380 }
381
382 override protected void RegisterRecipe(RecipeBase recipe)
383 {
384
385 if ( m_RegRecipeIndex >= MAX_NUMBER_OF_RECIPES )
386 {
387 Error("Exceeded max. number of recipes, max set to: "+MAX_NUMBER_OF_RECIPES.ToString());
388 }
389
390 m_RegRecipeIndex = m_RecipeList.Insert(recipe);
391 recipe.SetID(m_RegRecipeIndex);
392 m_RecipeNamesList.Insert(recipe.ClassName(), m_RegRecipeIndex);
393 //Print("RegisterRecipe: " +recipe.ClassName() + ", "+ m_RegRecipeIndex.ToString());
394 }
395
396 override protected void UnregisterRecipe(string clasname)
397 {
398 int recipe_id = RecipeIDFromClassname(clasname);
399 //Print("UnregisterRecipe: " + recipe_id.ToString());
400 if (recipe_id != -1)
401 {
402 m_RecipeNamesList.Remove(clasname);
403 //Print(m_RecipeList[recipe_id]);
404 m_RecipeList[recipe_id] = null;
405 //Print(m_RecipeList[recipe_id]);
406 }
407 }
408
409 static int RecipeIDFromClassname(string classname)
410 {
411 if (m_RecipeNamesList.Contains(classname))
412 return m_RecipeNamesList.Get(classname);
413 return -1;
414 }
415
416 protected bool CheckRecipe(int id, ItemBase item1, ItemBase item2, PlayerBase player)//requires ordered items
417 {
418 RecipeBase p_recipe = m_RecipeList[id];
419 return p_recipe.CheckRecipe(item1,item2, player);
420 }
421
422 protected void PrintCache()
423 {
424 for (int i = 0; i < PluginRecipesManager.m_RecipeCache.Count(); i++)
425 {
426 string key = PluginRecipesManager.m_RecipeCache.GetKey(i);
427 CacheObject co = PluginRecipesManager.m_RecipeCache.GetElement(i);
428
429 PrintString("Item: " + key);
430 co.DebugPrint();
431 PrintString("----------------");
432 }
433 }
435 protected bool SortIngredientsInRecipe(int id, int num_of_ingredients, ItemBase ingredients_unsorted[], ItemBase ingredients_sorted[] )
436 {
437 ClearResults();
438
439 for (int i = 0; i < num_of_ingredients; i++)
440 {
441 CacheObject co_item = PluginRecipesManager.m_RecipeCache.Get( ingredients_unsorted[i].GetType() );
442 m_IngredientBitMask[i] = co_item.GetMaskByRecipeID(id);
443 m_IngredientBitMaskSize[i] = co_item.GetBitCountByRecipeID(id);
444 }
445
446 bool result = ResolveIngredients(num_of_ingredients);
447
448 if (result)
449 {
450 for (i = 0; i < num_of_ingredients; i++)
451 {
452 int index = Math.Log2( m_BitsResults[i]);
453 ingredients_sorted[index] = ingredients_unsorted[ i ];
454 }
455 }
456 //PrintResultMasks(num_of_ingredients);
457 return result;
458 }
459
460 protected void ClearResults()
461 {
462 for (int i = 0; i < MAX_INGREDIENTS; i++)
463 {
464 m_BitsResults[i] = 0;
465 }
466
467 }
468
469 protected bool ResolveIngredients(int num_of_ingredients, int passes = 0)
470 {
471 int rightmost_bit;
472 int smallest = 99999;
473 int smallest_index = 0;
474
475 for (int i = 0; i < num_of_ingredients; i++)
476 {
477 int count = m_IngredientBitMaskSize[i];
478 if ( count != 0 && count < smallest)
479 {
480 smallest = m_IngredientBitMaskSize[i];
481 smallest_index = i;
482 }
483 }
484
485 rightmost_bit = m_IngredientBitMask[smallest_index] & (-m_IngredientBitMask[smallest_index]);
486 m_BitsResults[smallest_index] = m_BitsResults[smallest_index] | rightmost_bit;
487
488 for (int x = 0; x < num_of_ingredients; x++)
489 {
490 m_IngredientBitMask[x] = ~rightmost_bit & m_IngredientBitMask[x];
491 m_IngredientBitMask[smallest_index] = 0;
492 m_IngredientBitMaskSize[smallest_index] = 0;
493 }
494
495 // check validity
496 int check_sum_vertical = 0;
497
498 for (int z = 0; z < num_of_ingredients; z++)
499 {
500 check_sum_vertical = check_sum_vertical | m_IngredientBitMask[z];//vertical sum
501 check_sum_vertical = check_sum_vertical | m_BitsResults[z];//vertical sum
502 if ((m_IngredientBitMask[z] | m_BitsResults[z]) == 0)
503 {
504 return false;//horizontal check
505 }
506 }
507
508 if ( check_sum_vertical != (Math.Pow(2, num_of_ingredients) - 1)) return false;//vertical check
509
510 passes++;
511
512 if (passes < num_of_ingredients)
513 {
514 if ( !ResolveIngredients(num_of_ingredients, passes) ) return false;
515 }
516 return true;
517 }
518
519
520 protected void PrintResultMasks(int num)
521 {
522 for (int i = 0; i < num; i++)
523 {
524 Debug.Log("results mask("+i.ToString()+") = " +m_BitsResults[i].ToString() );
525 }
526 }
527
529 protected int GetRecipeIntersection(int num_of_ingredients, ItemBase items[])
530 {
531 int count = 0;
532 int smallest = 9999;
533 int smallest_index = 0;
534 m_RecipesMatched.Clear();
535
536 /*
537 m_Ingredients[0] = item_a;
538 m_Ingredients[1] = item_b;
539 */
540 //find the item with smallest number of recipes
541 CacheObject co_least_recipes;
542
543 for (int i = 0; i < num_of_ingredients; i++)
544 {
545 CacheObject cobject = PluginRecipesManager.m_RecipeCache.Get( items[i].GetType() );
546 if (!cobject)
547 {
548 return 0;
549 }
550 if (cobject.GetNumberOfRecipes() < smallest)
551 {
552 smallest = cobject.GetNumberOfRecipes();
553 smallest_index = i;
554 co_least_recipes = cobject;
555 }
556 }
557
558 //look for matches
559 array<int> recipes = co_least_recipes.GetRecipes();
560 for (int x = 0; x < recipes.Count(); x++)
561 {
562 int id = recipes.Get(x);
563 for (int z = 0; z < num_of_ingredients; z++)
564 {
565 if ( z!= smallest_index)
566 {
567 CacheObject cobject2 = PluginRecipesManager.m_RecipeCache.Get( items[z].GetType() );
568 if ( cobject2.IsContainRecipe(id) )
569 {
570 m_RecipesMatched.Insert(id);
571 count++;
572 }
573 }
574 }
575 }
576 return count;
577 }
578
579 protected int SortIngredients(int num_of_ingredients, ItemBase items_unsorted[], int resolved_recipes[])
580 {
581 int count = 0;
582 for (int i = 0; i < m_RecipesMatched.Count() && i < MAX_CONCURENT_RECIPES; i++)
583 {
584 int recipe_id = m_RecipesMatched.Get(i);
585
586 if (SortIngredientsInRecipe(recipe_id, num_of_ingredients, items_unsorted, m_sortedIngredients))//...and now we need to determine which item will be which ingredient number
587 {
588 resolved_recipes[count] = recipe_id;
589 m_ingredient1[count] = m_sortedIngredients[0];
590 m_ingredient2[count] = m_sortedIngredients[1];
591 //m_ingredient3[count] = m_sortedIngredients[2];
592 count++;
593 }
594 }
595 return count;
596 }
597
598
599 protected void CreateAllRecipes()
600 {
602 }
603
604
605 string GetSoundCategory(int recipeID, ItemBase item1, ItemBase item2)
606 {
607 ItemBase unsorted[2];
608 ItemBase sorted[2];
609
610 unsorted[0] = item1;
611 unsorted[1] = item2;
612
613 SortIngredientsInRecipe(recipeID, 2,unsorted, sorted);
614
615 RecipeBase recipe = m_RecipeList[recipeID];
616 string soundCat = recipe.GetSoundCategory(0,sorted[0]);
617
618 if (!soundCat)
619 {
620 soundCat = recipe.GetSoundCategory(1,sorted[1]);
621 }
622
623 return soundCat;
624 }
625
626
627
628}
eBleedingSourceType GetType()
DetachActionData m_ItemName
WorldCraftActionReciveData m_RecipeID
void CacheObject()
Definition CacheObject.c:35
Icon x
ref Timer myTimer1
const int SANITY_CHECK_ACCEPTABLE_RESULT
ERecipeSanityCheck
@ CLOSE_ENOUGH
@ IS_IN_PLAYER_INVENTORY
@ NOT_OWNED_BY_ANOTHER_LIVE_PLAYER
enum ERecipeSanityCheck ACCEPTABLE_DISTANCE
void RegisterRecipies()
Please do not delete commented recipes, they are usually commented out for a reason.
const int MAX_NUMBER_OF_INGREDIENTS
Definition RecipeBase.c:1
proto native int ConfigGetChildrenCount(string path)
Get count of subclasses in config class on path.
proto native void ProfilerStop(string name)
Use for profiling code from start to stop, they must match have same name, look wiki pages for more i...
proto native void ProfilerStart(string name)
Use for profiling code from start to stop, they must match have same name, look wiki pages for more i...
proto native int ConfigGetInt(string path)
Get int value from config on path.
proto bool ConfigGetChildName(string path, int index, out string name)
Get name of subclass in config class on path.
proto native void ConfigGetFullPath(string path, out TStringArray full_path)
Definition Debug.c:14
static void Log(string message=LOG_DEFAULT, string plugin=LOG_DEFAULT, string author=LOG_DEFAULT, string label=LOG_DEFAULT, string entity=LOG_DEFAULT)
Prints debug message with normal prio.
Definition Debug.c:133
override bool DisassembleOnLastDetach()
Definition KitBase.c:63
Definition EnMath.c:7
int GetValidRecipes(ItemBase item1, ItemBase item2, array< int > ids, PlayerBase player)
protected bool RecipeSanityCheck(int num_of_ingredients, InventoryItemBase items[], PlayerBase player)
int GetValidRecipesProper(int num_of_items, ItemBase items[], array< int > ids, PlayerBase player)
protected void PrintResultMasks(int num)
override protected void RegisterRecipe(RecipeBase recipe)
protected bool SortIngredientsInRecipe(int id, int num_of_ingredients, ItemBase ingredients_unsorted[], ItemBase ingredients_sorted[])
sorts ingredients correctly as either first or second ingredient based on their masks
override protected void UnregisterRecipe(string clasname)
protected int GetRecipeIntersection(int num_of_ingredients, ItemBase items[])
fills an array with recipe IDs which 'item_a' and 'item_b' share
void PerformRecipeServer(int id, ItemBase item_a, ItemBase item_b, PlayerBase player)
float GetRecipeSpecialty(int recipe_id)
protected bool CheckRecipe(int id, ItemBase item1, ItemBase item2, PlayerBase player)
static int RecipeIDFromClassname(string classname)
string GetRecipeName(int recipe_id)
protected void MatchItems(TStringArray full_path)
void SetEnableDebugCrafting(bool enable)
protected bool ResolveIngredients(int num_of_ingredients, int passes=0)
protected int SortIngredients(int num_of_ingredients, ItemBase items_unsorted[], int resolved_recipes[])
string GetSoundCategory(int recipeID, ItemBase item1, ItemBase item2)
bool GetIsInstaRecipe(int recipe_id)
float GetRecipeLengthInSecs(int recipe_id)
bool CheckRecipe(ItemBase item1, ItemBase item2, PlayerBase player)
Definition RecipeBase.c:483
string GetSoundCategory(int ingredientIndex, ItemBase item)
Definition RecipeBase.c:608
int GetID()
Definition RecipeBase.c:584
ref array< string > m_Ingredients[MAX_NUMBER_OF_INGREDIENTS]
Definition RecipeBase.c:7
void PerformRecipe(ItemBase item1, ItemBase item2, PlayerBase player)
Definition RecipeBase.c:525
void SetID(int id)
Definition RecipeBase.c:590
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
static proto native float Distance(vector v1, vector v2)
Returns the distance between tips of two 3D vectors.
proto native CGame GetGame()
void Error(string err)
Messagebox with error message.
Definition EnDebug.c:90
array< string > TStringArray
Definition EnScript.c:685
void PrintString(string s)
Helper for printing out string expression. Example: PrintString("Hello " + var);.
Definition EnScript.c:345
FileMode
Definition EnSystem.c:383
proto void CloseFile(FileHandle file)
Close the File.
proto FileHandle OpenFile(string name, FileMode mode)
Opens File.
int[] FileHandle
Definition EnSystem.c:390
proto void FPrintln(FileHandle file, void var)
Write to file and add new line.
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.
const string CFG_VEHICLESPATH
Definition constants.c:195
const string CFG_WEAPONSPATH
Definition constants.c:196
const string CFG_MAGAZINESPATH
Definition constants.c:197