Guest User

alchemyManager.ws

a guest
Aug 28th, 2018
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.97 KB | None | 0 0
  1. /***********************************************************************/
  2. /**     © 2015 CD PROJEKT S.A. All rights reserved.
  3. /**     THE WITCHER® is a trademark of CD PROJEKT S. A.
  4. /**     The Witcher game is based on the prose of Andrzej Sapkowski.
  5. /***********************************************************************/
  6.  
  7.  
  8.  
  9.  
  10. class W3AlchemyManager
  11. {
  12.     private var recipes : array<SAlchemyRecipe>;                                   
  13.     private var isPlayerMounted  : bool;
  14.     private var isPlayerInCombat : bool;
  15.    
  16.    
  17.     public function Init(optional alchemyRecipes : array<name>)
  18.     {
  19.         if(alchemyRecipes.Size() > 0)
  20.         {
  21.             LoadRecipesCustomXMLData( alchemyRecipes );
  22.         }
  23.         else
  24.         {
  25.             LoadRecipesCustomXMLData( GetWitcherPlayer().GetAlchemyRecipes() );
  26.         }
  27.        
  28.         isPlayerMounted = thePlayer.GetUsedVehicle();
  29.         isPlayerInCombat = thePlayer.IsInCombat();
  30.     }
  31.    
  32.    
  33.     public function GetRecipe(recipeName : name, out ret : SAlchemyRecipe) : bool
  34.     {
  35.         var i : int;
  36.        
  37.         for(i=0; i<recipes.Size(); i+=1)
  38.         {
  39.             if(recipes[i].recipeName == recipeName)
  40.             {
  41.                 ret = recipes[i];
  42.                 return true;
  43.             }
  44.         }
  45.        
  46.         return false;
  47.     }
  48.    
  49.    
  50.     private function LoadRecipesCustomXMLData(recipesNames : array<name>)
  51.     {
  52.         var dm : CDefinitionsManagerAccessor;
  53.         var main, ingredients : SCustomNode;
  54.         var tmpBool : bool;
  55.         var tmpName : name;
  56.         var tmpString : string;
  57.         var tmpInt : int;
  58.         var rec : SAlchemyRecipe;
  59.         var i, k, readRecipes : int;
  60.         var ing : SItemParts;
  61.        
  62.         dm = theGame.GetDefinitionsManager();
  63.         main = dm.GetCustomDefinition('alchemy_recipes');
  64.         readRecipes = 0;
  65.        
  66.         for(i=0; i<main.subNodes.Size(); i+=1)
  67.         {
  68.            
  69.             if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'name_name', tmpName) && IsNameValid(tmpName) && recipesNames.Contains(tmpName))
  70.             {
  71.                 rec.recipeName = tmpName;
  72.                
  73.                 if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'cookedItem_name', tmpName))
  74.                     rec.cookedItemName = tmpName;
  75.                 else
  76.                     rec.cookedItemName = '';
  77.                    
  78.                 if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'type_name', tmpName))
  79.                     rec.typeName = tmpName;
  80.                 else
  81.                     rec.typeName = '';
  82.                
  83.                 if(dm.GetCustomNodeAttributeValueInt(main.subNodes[i], 'level', tmpInt))
  84.                     rec.level = tmpInt;
  85.                 else
  86.                     rec.level = -1;
  87.                    
  88.                 if(dm.GetCustomNodeAttributeValueString(main.subNodes[i], 'cookedItemType', tmpString))
  89.                     rec.cookedItemType = AlchemyCookedItemTypeStringToEnum(tmpString);
  90.                 else
  91.                     rec.cookedItemType = EACIT_Undefined;
  92.                    
  93.                 if(dm.GetCustomNodeAttributeValueInt(main.subNodes[i], 'cookedItemQuantity', tmpInt))
  94.                     rec.cookedItemQuantity = tmpInt;
  95.                 else
  96.                     rec.cookedItemQuantity = -1;
  97.                
  98.                
  99.                 ingredients = dm.GetCustomDefinitionSubNode(main.subNodes[i],'ingredients');
  100.                 rec.requiredIngredients.Clear();                   
  101.                 for(k=0; k<ingredients.subNodes.Size(); k+=1)
  102.                 {      
  103.                     if(dm.GetCustomNodeAttributeValueName(ingredients.subNodes[k], 'item_name', tmpName))                      
  104.                         ing.itemName = tmpName;
  105.                     else
  106.                         ing.itemName = '';
  107.                        
  108.                     if(dm.GetCustomNodeAttributeValueInt(ingredients.subNodes[k], 'quantity', tmpInt))
  109.                         ing.quantity = tmpInt;
  110.                     else
  111.                         ing.quantity = -1;
  112.                        
  113.                     rec.requiredIngredients.PushBack(ing);                     
  114.                 }
  115.                
  116.                
  117.                
  118.                 rec.cookedItemIconPath          = dm.GetItemIconPath( rec.cookedItemName );
  119.                
  120.                
  121.                 rec.recipeIconPath              = dm.GetItemIconPath( rec.recipeName );
  122.  
  123.                 recipes.PushBack(rec);
  124.                
  125.                
  126.                 readRecipes += 1;
  127.                 if(readRecipes >= recipesNames.Size())
  128.                     break;
  129.             }
  130.         }
  131.     }
  132.    
  133.     private final function GetItemNameWithoutLevelAsString(itemName : name) : string
  134.     {
  135.         var itemStr : string;
  136.        
  137.         itemStr = NameToString(itemName);
  138.         if(StrEndsWith(itemStr, " 1") || StrEndsWith(itemStr, " 2") || StrEndsWith(itemStr, " 3"))
  139.             return StrLeft(itemStr, StrLen(itemStr)-2);
  140.        
  141.         return itemStr;
  142.     }
  143.    
  144.    
  145.     public function CanCookRecipe(recipeName : name, optional ignorePlayerState:bool) : EAlchemyExceptions
  146.     {
  147.         var i, cnt, itemLevel : int;
  148.         var recipe : SAlchemyRecipe;
  149.         var items  : array<SItemUniqueId>;
  150.         var itemType : string;
  151.         var itemName : name;
  152.         var dm : CDefinitionsManagerAccessor;
  153.        
  154.         if(!GetRecipe(recipeName, recipe))
  155.             return EAE_NoRecipe;
  156.        
  157.         if (!ignorePlayerState)
  158.         {
  159.             if (isPlayerMounted) return EAE_Mounted;
  160.             if (isPlayerInCombat) return EAE_InCombat;
  161.         }
  162.        
  163.        
  164.         itemType = GetItemNameWithoutLevelAsString(recipe.cookedItemName);
  165.        
  166.         if( theGame.GetDefinitionsManager().IsItemSingletonItem(recipe.cookedItemName) )
  167.         {
  168.             thePlayer.inv.GetAllItems(items);  
  169.             for(i=0; i<items.Size(); i+=1)
  170.             {
  171.                 itemName = thePlayer.inv.GetItemName(items[i]);
  172.                
  173.                
  174.                 if(itemName == recipe.cookedItemName)
  175.                     return EAE_CannotCookMore;
  176.                    
  177.                
  178.                 if(StrStartsWith(NameToString(itemName), itemType))
  179.                 {
  180.                     itemLevel = (int)CalculateAttributeValue(thePlayer.inv.GetItemAttributeValue(items[i], 'level'));
  181.                     if(itemLevel >= recipe.level)
  182.                         return EAE_CannotCookMore;
  183.                 }
  184.             }
  185.         }
  186.        
  187.         dm = theGame.GetDefinitionsManager();
  188.        
  189.        
  190.         for(i=0; i<recipe.requiredIngredients.Size(); i+=1)
  191.         {
  192.             itemName = recipe.requiredIngredients[i].itemName;
  193.            
  194.             if (dm.ItemHasTag( itemName, 'MutagenIngredient' ))
  195.             {
  196.                 cnt = thePlayer.inv.GetUnusedMutagensCount(itemName);
  197.             }
  198.             else
  199.             {
  200.                 cnt = thePlayer.inv.GetItemQuantityByName(itemName);
  201.             }
  202.            
  203.             if(cnt < recipe.requiredIngredients[i].quantity)
  204.             {
  205.                 return EAE_NotEnoughIngredients;
  206.             }          
  207.         }
  208.         return EAE_NoException;
  209.     }
  210.        
  211.    
  212.     public function CookItem(recipeName : name)
  213.     {
  214.         var i, j, quantity, removedIngQuantity, maxAmmo : int;
  215.         var recipe : SAlchemyRecipe;
  216.         var dm : CDefinitionsManagerAccessor;
  217.         var crossbowID : SItemUniqueId;
  218.         var min, max : SAbilityAttributeValue;
  219.         var uiStateAlchemy : W3TutorialManagerUIHandlerStateAlchemy;
  220.         var uiStateAlchemyMutagens : W3TutorialManagerUIHandlerStateAlchemyMutagens;
  221.         var ids : array<SItemUniqueId>;
  222.         var items, alchIngs  : array<SItemUniqueId>;
  223.         var isPotion, isSingletonItem : bool;
  224.         var witcher : W3PlayerWitcher;
  225.         var equippedOnSlot : EEquipmentSlots;
  226.         var itemName:name;
  227.        
  228.         GetRecipe(recipeName, recipe);
  229.        
  230.        
  231.         equippedOnSlot = EES_InvalidSlot;
  232.         dm = theGame.GetDefinitionsManager();
  233.         dm.GetItemAttributeValueNoRandom(recipe.cookedItemName, true, 'ammo', min, max);
  234.         quantity = (int)CalculateAttributeValue(GetAttributeRandomizedValue(min, max));
  235.        
  236.         if(recipe.cookedItemType == EACIT_Bomb && GetWitcherPlayer().CanUseSkill(S_Alchemy_s08))
  237.             quantity += GetWitcherPlayer().GetSkillLevel(S_Alchemy_s08);
  238.        
  239.        
  240.         isSingletonItem = dm.IsItemSingletonItem(recipe.cookedItemName);
  241.         if(isSingletonItem && thePlayer.inv.GetItemQuantityByName(recipe.cookedItemName) > 0 )
  242.         {
  243.             items = thePlayer.inv.GetItemsByName(recipe.cookedItemName);
  244.            
  245.             if (items.Size() == 1 && thePlayer.inv.ItemHasTag(items[0], 'NoShow'))
  246.             {
  247.                 thePlayer.inv.RemoveItemTag(items[i], 'NoShow');
  248.             }
  249.         }
  250.         else
  251.         {
  252.             ids = thePlayer.inv.AddAnItem(recipe.cookedItemName, quantity);
  253.             if(isSingletonItem)
  254.             {
  255.                 maxAmmo = thePlayer.inv.SingletonItemGetMaxAmmo(ids[0]);
  256.                 for(i=0; i<ids.Size(); i+=1)
  257.                     thePlayer.inv.SingletonItemSetAmmo(ids[i], maxAmmo);
  258.             }
  259.         }
  260.        
  261.        
  262.         for(i=0; i<recipe.requiredIngredients.Size(); i+=1)
  263.         {
  264.             itemName = recipe.requiredIngredients[i].itemName;
  265.            
  266.            
  267.            
  268.             if( dm.ItemHasTag( itemName, 'MutagenIngredient' ) )
  269.             {
  270.                 thePlayer.inv.RemoveUnusedMutagensCount( itemName, recipe.requiredIngredients[i].quantity);
  271.             }
  272.             else if( dm.IsItemAlchemyItem( itemName ))
  273.             {
  274.                 removedIngQuantity = 0;
  275.                 alchIngs = thePlayer.inv.GetItemsByName(itemName);
  276.                 witcher = GetWitcherPlayer();
  277.                
  278.                 for(j=0; j<alchIngs.Size(); j+=1)
  279.                 {
  280.                     equippedOnSlot = witcher.GetItemSlot(alchIngs[j]);
  281.                    
  282.                     if(equippedOnSlot != EES_InvalidSlot)
  283.                     {
  284.                         witcher.UnequipItem(alchIngs[j]);
  285.                     }
  286.                    
  287.                     removedIngQuantity += 1;
  288.                     witcher.inv.RemoveItem(alchIngs[j], 1);
  289.                    
  290.                     if(removedIngQuantity >= recipe.requiredIngredients[i].quantity)
  291.                         break;
  292.                 }
  293.             }
  294.             else
  295.             {
  296.                
  297.                 thePlayer.inv.RemoveItemByName(itemName, recipe.requiredIngredients[i].quantity);
  298.             }
  299.         }
  300.        
  301.         RemoveLowerLevelItems(recipe);
  302.        
  303.         if( ids.Size() > 0  && thePlayer.inv.IsItemPotion( ids[0] ) )
  304.         {
  305.             isPotion = true;
  306.         }
  307.         else if( items.Size() > 0  && thePlayer.inv.IsItemPotion( items[0] ) )
  308.         {
  309.             isPotion = true;
  310.         }
  311.         else
  312.         {
  313.             isPotion = false;
  314.         }
  315.        
  316.         if( isPotion )
  317.         {
  318.             theTelemetry.LogWithLabelAndValue( TE_ITEM_COOKED, recipe.cookedItemName, 1 );
  319.         }
  320.         else
  321.         {
  322.             theTelemetry.LogWithLabelAndValue( TE_ITEM_COOKED, recipe.cookedItemName, 0 );
  323.         }
  324.        
  325.        
  326.         if(equippedOnSlot != EES_InvalidSlot)
  327.         {
  328.             witcher.EquipItemInGivenSlot(ids[0], equippedOnSlot, false);
  329.         }
  330.        
  331.         LogAlchemy("Item <<" + recipe.cookedItemName + ">> cooked x" + recipe.cookedItemQuantity);
  332.        
  333.        
  334.         if(ShouldProcessTutorial('TutorialAlchemyCook'))
  335.         {
  336.             uiStateAlchemy = (W3TutorialManagerUIHandlerStateAlchemy)theGame.GetTutorialSystem().uiHandler.GetCurrentState();
  337.             if(uiStateAlchemy)
  338.             {
  339.                 uiStateAlchemy.CookedItem(recipeName);
  340.             }
  341.             else
  342.             {
  343.                 uiStateAlchemyMutagens = (W3TutorialManagerUIHandlerStateAlchemyMutagens)theGame.GetTutorialSystem().uiHandler.GetCurrentState();
  344.                 if(uiStateAlchemyMutagens)
  345.                     uiStateAlchemyMutagens.CookedItem(recipeName);
  346.             }
  347.         }
  348.     }
  349.    
  350.    
  351.     private function RemoveLowerLevelItems(recipe : SAlchemyRecipe)
  352.     {
  353.         var i, j : int;
  354.         var items : array<SItemUniqueId>;
  355.         var witcher : W3PlayerWitcher;
  356.        
  357.         witcher = GetWitcherPlayer();
  358.         for(i=0; i<recipes.Size(); i+=1)
  359.         {
  360.             if(recipes[i].typeName == recipe.typeName && recipes[i].level < recipe.level)
  361.             {
  362.                 items = thePlayer.inv.GetItemsByName(recipes[i].cookedItemName);
  363.                 for(j=0; j<items.Size(); j+=1)
  364.                 {
  365.                     if(witcher.IsItemEquipped(items[j]))
  366.                         witcher.UnequipItem(items[j]);
  367.                        
  368.                     witcher.inv.RemoveItem(items[j]);
  369.                 }
  370.             }
  371.         }
  372.     }
  373.            
  374.    
  375.     public function GetRecipes(forceAll : bool) : array<SAlchemyRecipe>
  376.     {
  377.         var ret : array<SAlchemyRecipe>;
  378.         var i, j, cnt : int;
  379.         var checkedRecipe, testedRecipe : string;
  380.         var deletedCheckted : bool;
  381.         var alchemyItems : array<SItemUniqueId>;
  382.         var itemName : name;
  383.        
  384.        
  385.         forceAll = true;
  386.        
  387.        
  388.         if(forceAll)
  389.             return recipes;
  390.        
  391.         alchemyItems = thePlayer.inv.GetAlchemyCraftableItems();
  392.        
  393.        
  394.        
  395.        
  396.         ret.Resize(recipes.Size());
  397.         for(i=0; i<recipes.Size(); i+=1)
  398.         {
  399.             ret[i] = recipes[i];
  400.         }
  401.        
  402.         i=0;
  403.         while(i < ret.Size())
  404.         {
  405.             j=i+1;
  406.             deletedCheckted = false;
  407.            
  408.            
  409.             checkedRecipe = NameToString(ret[i].cookedItemName);
  410.             checkedRecipe = StrLeft(checkedRecipe, StrLen(checkedRecipe)-2);
  411.                        
  412.             while(j<ret.Size())
  413.             {
  414.                
  415.                 testedRecipe = NameToString(ret[j].cookedItemName);
  416.                 testedRecipe = StrLeft(testedRecipe, StrLen(testedRecipe)-2);
  417.                
  418.                
  419.                 if(checkedRecipe == testedRecipe)
  420.                 {              
  421.                     if(ret[i].level < ret[j].level)
  422.                     {
  423.                         if(ShouldRemoveRecipe(ret[i].cookedItemName, ret[i].level, alchemyItems))
  424.                         {
  425.                            
  426.                             ret.EraseFast(i);
  427.                             deletedCheckted = true;
  428.                             break;
  429.                         }
  430.                     }
  431.                     else
  432.                     {
  433.                         if(ShouldRemoveRecipe(ret[j].cookedItemName, ret[j].level, alchemyItems))
  434.                         {
  435.                            
  436.                             ret.EraseFast(j);
  437.                             continue;
  438.                         }
  439.                     }
  440.                 }
  441.                
  442.                
  443.                 j+=1;
  444.             }
  445.            
  446.            
  447.             if(!deletedCheckted)
  448.                 i+=1;
  449.         }
  450.        
  451.        
  452.         for(i=ret.Size()-1; i>=0; i-=1)
  453.         {
  454.             itemName = ret[i].cookedItemName;
  455.             cnt = thePlayer.inv.GetItemQuantityByName(itemName);
  456.            
  457.             if(cnt <= 0)
  458.                 continue;
  459.                
  460.            
  461.             if(ret[i].cookedItemType == EACIT_Potion && StrStartsWith(NameToString(ret[i].typeName), "Mutagen"))
  462.             {
  463.                 ret.EraseFast(i);
  464.                 continue;
  465.             }
  466.            
  467.            
  468.             if(ret[i].level == 3)
  469.             {
  470.                 ret.EraseFast(i);
  471.                 continue;
  472.             }
  473.            
  474.            
  475.             if(itemName == 'Killer Whale 1' || itemName == 'Trial Potion Kit' || itemName == 'Pops Antidote' || itemName == 'mh107_czart_lure' || StrContains(NameToString(itemName), "Pheromone"))
  476.             {
  477.                 ret.EraseFast(i);
  478.                 continue;
  479.             }
  480.         }
  481.        
  482.         return ret;
  483.     }
  484.    
  485.    
  486.     private final function ShouldRemoveRecipe(itemName : name, itemLevel : int, alchemyItems : array<SItemUniqueId>) : bool
  487.     {
  488.         var recipeItemType, checkedItemType : string;
  489.         var i : int;
  490.        
  491.         recipeItemType = NameToString(itemName);
  492.         recipeItemType = StrLeft(recipeItemType, StrLen(recipeItemType)-2);
  493.        
  494.         for(i=0; i<alchemyItems.Size(); i+=1)
  495.         {
  496.             checkedItemType = NameToString(thePlayer.inv.GetItemName(alchemyItems[i]));
  497.             checkedItemType = StrLeft(checkedItemType, StrLen(checkedItemType)-2);
  498.            
  499.             if(recipeItemType == checkedItemType)
  500.             {
  501.                 if( CalculateAttributeValue(thePlayer.inv.GetItemAttributeValue(alchemyItems[i], 'level')) >= itemLevel )
  502.                     return true;
  503.             }
  504.         }
  505.        
  506.         return false;
  507.     }
  508.    
  509.     public function GetRequiredIngredients(recipeName : name) : array<SItemParts>
  510.     {
  511.         var rec : SAlchemyRecipe;
  512.         var null : array<SItemParts>;
  513.    
  514.         if(GetRecipe(recipeName, rec))
  515.             return rec.requiredIngredients;
  516.            
  517.         return null;
  518.     }  
  519. }
  520.  
  521. function getAlchemyRecipeFromName(recipeName : name):SAlchemyRecipe
  522. {
  523.     var dm : CDefinitionsManagerAccessor;
  524.     var main, ingredients : SCustomNode;
  525.     var tmpBool : bool;
  526.     var tmpName : name;
  527.     var tmpString : string;
  528.     var tmpInt : int;
  529.     var ing : SItemParts;
  530.     var i,k : int;
  531.     var rec : SAlchemyRecipe;
  532.    
  533.     dm = theGame.GetDefinitionsManager();
  534.     main = dm.GetCustomDefinition('alchemy_recipes');
  535.    
  536.     for(i=0; i<main.subNodes.Size(); i+=1)
  537.     {
  538.         dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'name_name', tmpName);
  539.        
  540.         if (tmpName == recipeName)
  541.         {
  542.             if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'cookedItem_name', tmpName))
  543.                 rec.cookedItemName = tmpName;
  544.             if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'type_name', tmpName))
  545.                 rec.typeName = tmpName;
  546.             if(dm.GetCustomNodeAttributeValueInt(main.subNodes[i], 'level', tmpInt))
  547.                 rec.level = tmpInt;
  548.             if(dm.GetCustomNodeAttributeValueString(main.subNodes[i], 'cookedItemType', tmpString))
  549.                 rec.cookedItemType = AlchemyCookedItemTypeStringToEnum(tmpString);
  550.             if(dm.GetCustomNodeAttributeValueInt(main.subNodes[i], 'cookedItemQuantity', tmpInt))
  551.                 rec.cookedItemQuantity = tmpInt;
  552.            
  553.            
  554.             ingredients = dm.GetCustomDefinitionSubNode(main.subNodes[i],'ingredients');                   
  555.             for(k=0; k<ingredients.subNodes.Size(); k+=1)
  556.             {      
  557.                 ing.itemName = '';
  558.                 ing.quantity = -1;
  559.            
  560.                 if(dm.GetCustomNodeAttributeValueName(ingredients.subNodes[k], 'item_name', tmpName))                      
  561.                     ing.itemName = tmpName;
  562.                 if(dm.GetCustomNodeAttributeValueInt(ingredients.subNodes[k], 'quantity', tmpInt))
  563.                     ing.quantity = tmpInt;
  564.                    
  565.                 rec.requiredIngredients.PushBack(ing);                     
  566.             }
  567.            
  568.             rec.recipeName = recipeName;
  569.            
  570.            
  571.             rec.cookedItemIconPath          = dm.GetItemIconPath( rec.cookedItemName );
  572.             rec.recipeIconPath              = dm.GetItemIconPath( rec.recipeName );
  573.             break;
  574.         }
  575.     }
  576.    
  577.     return rec;
  578. }
Advertisement
Add Comment
Please, Sign In to add comment