Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
pluginrecipesmanager.c
Go to the documentation of this file.
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 map<typename, bool>;
16
17
18 ref Timer m_TestTimer;
19 const int MAX_NUMBER_OF_RECIPES = GetMaxNumberOfRecipes();
20 const int MAX_CONCURENT_RECIPES = 128;
21 const int MAX_INGREDIENTS = 5;
22
23 int m_RegRecipeIndex;
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
33 ItemBase m_ingredient1[MAX_CONCURENT_RECIPES];
34 ItemBase m_ingredient2[MAX_CONCURENT_RECIPES];
35 ItemBase m_ingredient3[MAX_CONCURENT_RECIPES];
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
45 ref Timer myTimer1;
46
47 static int GetMaxNumberOfRecipes()
48 {
49 return 2048;
50 }
51
52 void PluginRecipesManager()
53 {
54
57
58 myTimer1 = new Timer();
59 }
60
61 void ~PluginRecipesManager()
62 {
63 }
64
65
66 bool IsEnableDebugCrafting()
67 {
68 return m_EnableDebugCrafting;
69 }
70
71 void SetEnableDebugCrafting(bool enable)
72 {
73 m_EnableDebugCrafting = enable;
74 }
75
76 string GetRecipeName(int recipe_id)
77 {
78 if (m_RecipeList[recipe_id])
79 return m_RecipeList[recipe_id].GetName();
80
81 return "";
82 }
83
84
85 //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
86 int GetValidRecipes(ItemBase item1, ItemBase item2, array<int> ids, PlayerBase player)
87 {
88 if ( item1 == NULL || item2 == NULL )
89 {
90 if (ids) ids.Clear();
91 return 0;
92 }
93
94 if ( ( item1.GetInventory().IsAttachment() && item1.GetHierarchyParent().DisassembleOnLastDetach() ) || ( item2.GetInventory().IsAttachment() && item2.GetHierarchyParent().DisassembleOnLastDetach() ) )
95 {
96 if (ids) ids.Clear();
97 return 0;
98 }
99 m_Ingredients[0] = item1;
100 m_Ingredients[1] = item2;
101
102 return GetValidRecipesProper(2,m_Ingredients, ids, player);
103 }
104
105 int GetValidRecipesProper(int num_of_items, ItemBase items[], array<int> ids, PlayerBase player)
106 {
107 if (ids) ids.Clear();
108 GetRecipeIntersection(num_of_items,items);
109 int numOfRecipes = SortIngredients(num_of_items,items,m_ResolvedRecipes);
110 //will return number of cached recipes for the 2 items being considered,
111 //and save their indexes in m_ResolvedRecipes, please note the m_ResolvedRecipes is a static array,
112 //and does not clear up with each query, so the number of recipes returned is critical to make sure we don't accidentally
113 //mix in some other indexes from previous queries(and obviously loop only as far as we have to)
114 //this also saves the ingredients in the correct assignment as ingredient 1/2 into m_ingredient1/m_ingredient2 arrays, these 3 arrays
115 //therefore provide you with information per each index with: recipeid,ingredient1,ingredient2
116 if ( numOfRecipes == 0 ) return 0;
117 int found = 0;
118 RecipeBase p_recipe = NULL;
119 for (int i = 0; i < numOfRecipes; i++)
120 {
121 p_recipe = m_RecipeList[m_ResolvedRecipes[i]];
122
123 if ( p_recipe.CheckRecipe(m_ingredient1[i],m_ingredient2[i], player) == true )
124 {
125 if (ids) ids.Insert( p_recipe.GetID() );
126 found++;
127 }
128 }
129 return found;
130 }
131
132
133 float GetRecipeLengthInSecs(int recipe_id)
134 {
135 if ( m_RecipeList[recipe_id] ) return m_RecipeList[recipe_id].GetLengthInSecs();
136 return 0;
137 }
138
139 float GetRecipeSpecialty(int recipe_id)
140 {
141 if ( m_RecipeList[recipe_id] ) return m_RecipeList[recipe_id].GetSpecialty();
142 return 0;
143 }
144
145 bool GetIsInstaRecipe(int recipe_id)
146 {
147 if ( m_RecipeList[recipe_id] ) return m_RecipeList[recipe_id].IsInstaRecipe();
148 else return false;
149 }
150
151 bool GetIsRepeatable(int recipe_id)
152 {
153 if ( m_RecipeList[recipe_id] ) return m_RecipeList[recipe_id].IsRepeatable();
154 return false;
155 }
156
157 override void OnInit()
158 {
159 super.OnInit();
160 //ReadCacheFromFile(PATH_CACHE_FILE);//read the cache from a file
161 //GenerateHumanReadableRecipeList();
162 }
163
164
165 void CallbackGenerateCache()
166 {
167 Debug.Log("CallbackGenerateCache","recipes");
169 //SaveCacheToFile(PATH_CACHE_FILE);//generate the cache and save it to a file
170 //ReadCacheFromFile(PATH_CACHE_FILE);
171 }
172
173 protected void GenerateRecipeCache()
174 {
175 GetGame().ProfilerStart("m_RecipeCache");
176
177 //m_CacheBasesMap.Clear();
178 m_CachedItems.Clear();
179 PluginRecipesManager.m_RecipeCache.Clear();
180
181 TStringArray all_config_paths = new TStringArray;
182
183 all_config_paths.Insert(CFG_VEHICLESPATH);
184 all_config_paths.Insert(CFG_WEAPONSPATH);
185 all_config_paths.Insert(CFG_MAGAZINESPATH);
186 //Debug.Log("Got here 0","caching");
187 string config_path;
188 string child_name;
189 int scope;
190 TStringArray full_path = new TStringArray;
191 WalkRecipes();
192 for (int i = 0; i < all_config_paths.Count(); i++)
193 {
194 config_path = all_config_paths.Get(i);
195 int children_count = GetGame().ConfigGetChildrenCount(config_path);
196
197 for (int x = 0; x < children_count; x++)
198 {
199 GetGame().ConfigGetChildName(config_path, x, child_name);
200 scope = GetGame().ConfigGetInt( config_path + " " + child_name + " scope" );
201
202 if ( scope == 2 )
203 {
204 GetGame().ConfigGetFullPath(config_path +" "+ child_name,/*out*/ full_path);
205 MatchItems(full_path);
206 }
207 }
208 }
209 GetGame().ProfilerStop("m_RecipeCache");
210 }
211
213 {
214 //Print("------------- WalkRecipes --------------");
215 for (int c = 0; c < m_RecipeList.Count(); c++)
216 {
217 RecipeBase recipe = m_RecipeList.Get(c);
218 if (recipe)
219 {
220 //Print(recipe.ClassName());
221 int recipe_id = recipe.GetID();
222 for (int i = 0; i < MAX_NUMBER_OF_INGREDIENTS; i++)
223 {
224 array<string> list = recipe.m_Ingredients[i];
225
226 for (int x = 0; x < list.Count(); x++)
227 {
228 string ingredient = list.Get(x);
229 int mask = Math.Pow(2,i);
230 CacheObject co = m_RecipeCache.Get(ingredient);
231
232 if (!co)
233 {
234 co = new CacheObject;
235 m_RecipeCache.Insert(ingredient,co);
236 }
237 co.AddRecipe(recipe_id, mask);
238 }
239 }
240 }
241 }
242 }
243
244
245 // moved outside method to speed things up
254
255 //this will take the item class name and resolve it against all processed recipes
256 protected void MatchItems(TStringArray full_path)
257 {
258 m_ItemName = full_path.Get(0);
259 m_CoItem = m_RecipeCache.Get(m_ItemName);
260 //Print(m_ItemName);
261 if ( !m_CoItem )
262 {
263 m_CoItem = new CacheObject;
264 m_RecipeCache.Insert(m_ItemName,m_CoItem);
265 }
266 for (int i = 1; i < full_path.Count(); i++)
267 {
268 m_BaseName = full_path.Get(i);
269 m_CoBase = m_RecipeCache.Get(m_BaseName);
270 if ( m_CoBase )//resolve new base classes
271 {
272 m_RcpsArray = m_RecipeCache.Get(m_BaseName).GetRecipes();
273
274 for ( int x = 0; x < m_RcpsArray.Count(); x++ )//base recipes
275 {
276 m_RecipeID = m_RcpsArray.Get(x);
277
278 //item_mask = m_CoItem.GetMaskByRecipeID(m_RecipeID);
279 m_BaseMask = m_CoBase.GetMaskByRecipeID(m_RecipeID);
280
281 m_CoItem.AddRecipe(m_RecipeID,m_BaseMask);
282 }
283 }
284 }
285
286
287 }
288
289 bool IsRecipePossibleToPerform(int id, ItemBase itemA, ItemBase itemB, PlayerBase player)
290 {
291 if ( !itemA || !itemB )
292 {
293 return false;
294 }
295
296 m_Ingredients[0] = itemA;
297 m_Ingredients[1] = itemB;
298
299 SortIngredientsInRecipe(id, 2, m_Ingredients, m_sortedIngredients);
300
301 bool result = CheckRecipe(id, m_sortedIngredients[0], m_sortedIngredients[1], player);
302 if (result)
303 {
304 result = RecipeSanityCheck(2, m_sortedIngredients, player);
305 }
306
307 return result;
308 }
309
310 void PerformRecipeServer(int id, ItemBase item_a,ItemBase item_b ,PlayerBase player)
311 {
312 m_Ingredients[0] = item_a;
313 m_Ingredients[1] = item_b;
314
315 if ( !item_a || !item_b )
316 {
317 Error("PerformRecipeServer - one of the items null !!");
318 return;
319 }
320
321 SortIngredientsInRecipe(id, 2,m_Ingredients, m_sortedIngredients);
322
323 bool is_recipe_valid = CheckRecipe(id,m_sortedIngredients[0],m_sortedIngredients[1],player);
324 bool passed_sanity_check = RecipeSanityCheck(2,m_sortedIngredients,player);
325
326 if ( !is_recipe_valid )
327 {
328 Error("PerformRecipeServer - recipe not valid !!");
329 return;
330 }
331 if ( !passed_sanity_check )
332 {
333 Error("PerformRecipeServer - recipe failed to pass sanity check !!");
334 return;
335 }
336 RecipeBase ptrRecipe = m_RecipeList[id];
337 ptrRecipe.PerformRecipe(m_sortedIngredients[0],m_sortedIngredients[1],player);
338 //player.RequestCraftingDisable();
339
340 }
341
343 {
344 set<string> testset = new set<string>;
345
346 FileHandle file = OpenFile("$profile:RecipeDump.txt", FileMode.WRITE);
347 if ( file == 0 )
348 {
349 //error message
350 PrintString("failed to open file RecipeDump");
351 return;
352 }
353 array<int> recipes = new array<int>;
354 for (int i = 0; i < PluginRecipesManager.m_RecipeCache.Count(); i++)
355 {
356 string key = PluginRecipesManager.m_RecipeCache.GetKey(i);
357 CacheObject value = PluginRecipesManager.m_RecipeCache.GetElement(i);
358
359 string line = key;
360 recipes.Clear();
361 recipes.InsertAll( value.GetRecipes() );
362
363 //PrintString("Item: " + key);
364
365 for (int x = 0; x < recipes.Count(); x++)
366 {
367 int recipe_id = recipes.Get(x);
368 string recipe_name = Widget.TranslateString(GetRecipeName(recipe_id));
369 testset.Insert(recipe_name);
370
371 line += "," +recipe_name;
372 }
373 FPrintln(file, line);
374
375 }
376
377 // generate localized list of recipe names
378 foreach ( string st : testset)
379 {
380 FPrintln(file, st);
381 }
382
383 CloseFile(file);
384 }
385
387 {
388 CacheObject co = PluginRecipesManager.m_RecipeCache.Get(itemName);
389 array<int> ids = co.GetRecipes();
390
391 array<RecipeBase> recipes = new array<RecipeBase>();
392 foreach (int recipeID : ids)
393 {
394 recipes.Insert(m_RecipeList[recipeID]);
395 }
396
397 return recipes;
398 }
399
400 protected bool RecipeSanityCheck(int num_of_ingredients, InventoryItemBase items[], PlayerBase player)
401 {
402 int check_results[MAX_INGREDIENTS];
403
404 for (int i = 0; i < num_of_ingredients;i++)
405 {
406 ItemBase item = items[i];
407 Man item_owner_player = item.GetHierarchyRootPlayer();
408 vector item_pos = item.GetPosition();
409 vector player_pos = player.GetPosition();
410
411 if (item_owner_player == player)
412 {
413 check_results[i] = check_results[i] | ERecipeSanityCheck.IS_IN_PLAYER_INVENTORY;
414 }
415
416 if ( item_owner_player == NULL || item_owner_player == player || !item_owner_player.IsAlive() )
417 {
418 check_results[i] = check_results[i] | ERecipeSanityCheck.NOT_OWNED_BY_ANOTHER_LIVE_PLAYER;
419 }
420
421 if ( vector.Distance(item_pos, player_pos ) < ACCEPTABLE_DISTANCE )
422 {
423 check_results[i] = check_results[i] | ERecipeSanityCheck.CLOSE_ENOUGH;
424 }
425 }
426 for (i = 0; i < num_of_ingredients;i++)
427 {
429 {
430 return false;
431 }
432 }
433 return true;
434 }
435
436 override protected void RegisterRecipe(RecipeBase recipe)
437 {
438
439 if ( m_RegRecipeIndex >= MAX_NUMBER_OF_RECIPES )
440 {
441 Error("Exceeded max. number of recipes, max set to: "+MAX_NUMBER_OF_RECIPES.ToString());
442 }
443
444 m_RegRecipeIndex = m_RecipeList.Insert(recipe);
445 recipe.SetID(m_RegRecipeIndex);
446 m_RecipeNamesList.Insert(recipe.ClassName(), m_RegRecipeIndex);
447 //Print("RegisterRecipe: " +recipe.ClassName() + ", "+ m_RegRecipeIndex.ToString());
448 }
449
450 override protected void UnregisterRecipe(string clasname)
451 {
452 int recipe_id = RecipeIDFromClassname(clasname);
453 //Print("UnregisterRecipe: " + recipe_id.ToString());
454 if (recipe_id != -1)
455 {
456 m_RecipeNamesList.Remove(clasname);
457 //Print(m_RecipeList[recipe_id]);
458 m_RecipeList[recipe_id] = null;
459 //Print(m_RecipeList[recipe_id]);
460 }
461 }
462
463 static int RecipeIDFromClassname(string classname)
464 {
465 if (m_RecipeNamesList.Contains(classname))
466 return m_RecipeNamesList.Get(classname);
467 return -1;
468 }
469
470 protected bool CheckRecipe(int id, ItemBase item1, ItemBase item2, PlayerBase player)//requires ordered items
471 {
472 RecipeBase p_recipe = m_RecipeList[id];
473 return p_recipe.CheckRecipe(item1,item2, player);
474 }
475
476 protected void PrintCache()
477 {
478 for (int i = 0; i < PluginRecipesManager.m_RecipeCache.Count(); i++)
479 {
480 string key = PluginRecipesManager.m_RecipeCache.GetKey(i);
481 CacheObject co = PluginRecipesManager.m_RecipeCache.GetElement(i);
482
483 PrintString("Item: " + key);
484 co.DebugPrint();
485 PrintString("----------------");
486 }
487 }
489 protected bool SortIngredientsInRecipe(int id, int num_of_ingredients, ItemBase ingredients_unsorted[], ItemBase ingredients_sorted[] )
490 {
491 ClearResults();
492
493 for (int i = 0; i < num_of_ingredients; i++)
494 {
495 CacheObject co_item = PluginRecipesManager.m_RecipeCache.Get( ingredients_unsorted[i].GetType() );
496 m_IngredientBitMask[i] = co_item.GetMaskByRecipeID(id);
497 m_IngredientBitMaskSize[i] = co_item.GetBitCountByRecipeID(id);
498 }
499
500 bool result = ResolveIngredients(num_of_ingredients);
501
502 if (result)
503 {
504 for (i = 0; i < num_of_ingredients; i++)
505 {
506 int index = Math.Log2( m_BitsResults[i]);
507 ingredients_sorted[index] = ingredients_unsorted[ i ];
508 }
509 }
510 //PrintResultMasks(num_of_ingredients);
511 return result;
512 }
513
514 protected void ClearResults()
515 {
516 for (int i = 0; i < MAX_INGREDIENTS; i++)
517 {
518 m_BitsResults[i] = 0;
519 }
520
521 }
522
523 protected bool ResolveIngredients(int num_of_ingredients, int passes = 0)
524 {
525 int rightmost_bit;
526 int smallest = 99999;
527 int smallest_index = 0;
528
529 for (int i = 0; i < num_of_ingredients; i++)
530 {
531 int count = m_IngredientBitMaskSize[i];
532 if ( count != 0 && count < smallest)
533 {
534 smallest = m_IngredientBitMaskSize[i];
535 smallest_index = i;
536 }
537 }
538
539 rightmost_bit = m_IngredientBitMask[smallest_index] & (-m_IngredientBitMask[smallest_index]);
540 m_BitsResults[smallest_index] = m_BitsResults[smallest_index] | rightmost_bit;
541
542 for (int x = 0; x < num_of_ingredients; x++)
543 {
544 m_IngredientBitMask[x] = ~rightmost_bit & m_IngredientBitMask[x];
545 m_IngredientBitMask[smallest_index] = 0;
546 m_IngredientBitMaskSize[smallest_index] = 0;
547 }
548
549 // check validity
550 int check_sum_vertical = 0;
551
552 for (int z = 0; z < num_of_ingredients; z++)
553 {
554 check_sum_vertical = check_sum_vertical | m_IngredientBitMask[z];//vertical sum
555 check_sum_vertical = check_sum_vertical | m_BitsResults[z];//vertical sum
556 if ((m_IngredientBitMask[z] | m_BitsResults[z]) == 0)
557 {
558 return false;//horizontal check
559 }
560 }
561
562 if ( check_sum_vertical != (Math.Pow(2, num_of_ingredients) - 1)) return false;//vertical check
563
564 passes++;
565
566 if (passes < num_of_ingredients)
567 {
568 if ( !ResolveIngredients(num_of_ingredients, passes) ) return false;
569 }
570 return true;
571 }
572
573
574 protected void PrintResultMasks(int num)
575 {
576 for (int i = 0; i < num; i++)
577 {
578 Debug.Log("results mask("+i.ToString()+") = " +m_BitsResults[i].ToString() );
579 }
580 }
581
583 protected int GetRecipeIntersection(int num_of_ingredients, ItemBase items[])
584 {
585 int count = 0;
586 int smallest = 9999;
587 int smallest_index = 0;
588 m_RecipesMatched.Clear();
589
590 /*
591 m_Ingredients[0] = item_a;
592 m_Ingredients[1] = item_b;
593 */
594 //find the item with smallest number of recipes
595 CacheObject co_least_recipes;
596
597 for (int i = 0; i < num_of_ingredients; i++)
598 {
599 CacheObject cobject = PluginRecipesManager.m_RecipeCache.Get( items[i].GetType() );
600 if (!cobject)
601 {
602 return 0;
603 }
604 if (cobject.GetNumberOfRecipes() < smallest)
605 {
606 smallest = cobject.GetNumberOfRecipes();
607 smallest_index = i;
608 co_least_recipes = cobject;
609 }
610 }
611
612 //look for matches
613 array<int> recipes = co_least_recipes.GetRecipes();
614 for (int x = 0; x < recipes.Count(); x++)
615 {
616 int id = recipes.Get(x);
617 for (int z = 0; z < num_of_ingredients; z++)
618 {
619 if ( z!= smallest_index)
620 {
621 CacheObject cobject2 = PluginRecipesManager.m_RecipeCache.Get( items[z].GetType() );
622 if ( cobject2.IsContainRecipe(id) )
623 {
624 m_RecipesMatched.Insert(id);
625 count++;
626 }
627 }
628 }
629 }
630 return count;
631 }
632
633 protected int SortIngredients(int num_of_ingredients, ItemBase items_unsorted[], int resolved_recipes[])
634 {
635 int count = 0;
636 for (int i = 0; i < m_RecipesMatched.Count() && i < MAX_CONCURENT_RECIPES; i++)
637 {
638 int recipe_id = m_RecipesMatched.Get(i);
639
640 if (SortIngredientsInRecipe(recipe_id, num_of_ingredients, items_unsorted, m_sortedIngredients))//...and now we need to determine which item will be which ingredient number
641 {
642 resolved_recipes[count] = recipe_id;
643 m_ingredient1[count] = m_sortedIngredients[0];
644 m_ingredient2[count] = m_sortedIngredients[1];
645 //m_ingredient3[count] = m_sortedIngredients[2];
646 count++;
647 }
648 }
649 return count;
650 }
651
652
653 protected void CreateAllRecipes()
654 {
656 }
657
658
659 string GetSoundCategory(int recipeID, ItemBase item1, ItemBase item2)
660 {
661 ItemBase unsorted[2];
662 ItemBase sorted[2];
663
664 unsorted[0] = item1;
665 unsorted[1] = item2;
666
667 SortIngredientsInRecipe(recipeID, 2,unsorted, sorted);
668
669 RecipeBase recipe = m_RecipeList[recipeID];
670 string soundCat = recipe.GetSoundCategory(0,sorted[0]);
671
672 if (!soundCat)
673 {
674 soundCat = recipe.GetSoundCategory(1,sorted[1]);
675 }
676
677 return soundCat;
678 }
679
680
682 {
683 return m_RecipeList[recipeID].GetRecipeAnimationInfo(player, mainItem, target);
684 }
685
686 int GetAnimationCommandUID(int recipeID) //obsolete
687 {
688 return m_RecipeList[recipeID].GetAnimationCommandUID();
689 }
690
691}
eBleedingSourceType GetType()
DetachActionData m_ItemName
WorldCraftActionReciveData m_RecipeID
void CacheObject()
Definition cacheobject.c:35
Definition debug.c:2
override bool DisassembleOnLastDetach()
Definition kitbase.c:34
Definition enmath.c:7
static int RecipeIDFromClassname(string classname)
void RegisterRecipe(RecipeBase recipe)
bool IsRecipePossibleToPerform(int id, ItemBase itemA, ItemBase itemB, PlayerBase player)
void UnregisterRecipe(string clasname)
bool ResolveIngredients(int num_of_ingredients, int passes=0)
void PerformRecipeServer(int id, ItemBase item_a, ItemBase item_b, PlayerBase player)
int GetAnimationCommandUID(int recipeID)
int GetRecipeIntersection(int num_of_ingredients, ItemBase items[])
fills an array with recipe IDs which 'item_a' and 'item_b' share
array< RecipeBase > GetRecipesForItem(string itemName)
bool CheckRecipe(int id, ItemBase item1, ItemBase item2, PlayerBase player)
bool RecipeSanityCheck(int num_of_ingredients, InventoryItemBase items[], PlayerBase player)
RecipeAnimationInfo GetRecipeAnimationInfo(int recipeID, PlayerBase player, ItemBase mainItem, ItemBase target)
string GetSoundCategory(int recipeID, ItemBase item1, ItemBase item2)
void MatchItems(TStringArray full_path)
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
int SortIngredients(int num_of_ingredients, ItemBase items_unsorted[], int resolved_recipes[])
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
proto native CGame GetGame()
void Error(string err)
Messagebox with error message.
Definition endebug.c:90
array< string > TStringArray
Definition enscript.c:709
class array< Class T > PrintString
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.
const string CFG_VEHICLESPATH
Definition constants.c:220
const string CFG_WEAPONSPATH
Definition constants.c:221
const string CFG_MAGAZINESPATH
Definition constants.c:222
void OnInit()
Callback for user defined initialization. Called for all suites during TestHarness....
Definition freezestate.c:81
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.
ref array< string > m_Ingredients[MAX_NUMBER_OF_INGREDIENTS]
Definition recipebase.c:24
const int MAX_NUMBER_OF_INGREDIENTS
Definition recipebase.c:1