pluginrecipesmanager.c 18 KB

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