mikeyy

AIShopUtilities: FindBestBaseItem/FindBestCitadelUpgrade v2

Jun 18th, 2011
152
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function FindBestBaseItem( unit, aiBrain, action, sellItemData )
  2.     local bestValue = 0
  3.     local bestItems = {}
  4.     local shops = {}
  5.  
  6.     local asset = action.StrategicAsset
  7.     if not asset or not asset.ItemPriorities then
  8.         return false
  9.     end
  10.  
  11.     local inventoryOpen = {}
  12.     for invName,inv in unit.Inventory do
  13.         inventoryOpen[invName] = ValidateInventory.NumFreeSlots( inv )
  14.     end
  15.  
  16.     local highestPriority = false
  17.  
  18.     local maxCost = false
  19.  
  20.     --Mithy: New save-for logic that takes into account item cost mods
  21.     local savingForUpgrade, savingForCost = AIGlobals.SaveForUpgrade(unit, aiBrain)
  22.     local gold = aiBrain.mGold - (savingForCost or 0 * (unit.Sync.ItemCostMod) or 1)
  23.  
  24.     local syncData = Common.GetSyncData(unit)
  25.  
  26.     for _,itemData in asset.ItemPriorities do
  27.  
  28.         --this number can increase for stackable items
  29.         local purchaseQuantity = 1
  30.         local currentPriority = 0
  31.  
  32.         if itemData.Priority <= 0 then
  33.             continue
  34.         end
  35.  
  36.  
  37.  
  38.         --If we have a highest priority and this next item won't be higher; break the loop
  39.         if highestPriority and itemData.Priority < highestPriority then
  40.             continue
  41.         end
  42.  
  43.         --Store out each shop only once; this way we don't have to find shops more like crazy
  44.         if shops[itemData.ItemTable.ShopType] == nil then
  45.             local shop = aiBrain.GoalPlanner:GetFriendlyShop(itemData.ItemTable.ShopType, unit:GetPosition())
  46.             if shop then
  47.                 shops[itemData.ItemTable.ShopType] = shop
  48.             else
  49.                 shops[itemData.ItemTable.ShopType] = false
  50.             end
  51.  
  52.             --all shops of this time seem dead, continue to next item
  53.             if not shop then
  54.                 continue
  55.             end
  56.         end
  57.  
  58.  
  59.  
  60.         local nearby = shops[itemData.ItemTable.ShopType]
  61.         if not nearby then
  62.             continue
  63.         end
  64.  
  65.         local hasItem, numHeld = UnitHasItem( unit, itemData.ItemTable.ItemId, itemData.ItemTable.BaseShopType )
  66.         --Figure out if we can carry this item; We have two checks - one for non-stacked items and one for stacks
  67.         if itemData.ItemTable.StacksPerSlot > 1 then
  68.             if hasItem and numHeld >= itemData.ItemTable.StacksPerSlot then
  69.                 continue
  70.             end
  71.  
  72.             local maxPurchasable = itemData.ItemTable.StacksPerSlot - numHeld
  73.             --Already at max; this item is bankrupt
  74.             if maxPurchasable <= 0 then
  75.                 continue
  76.             end
  77.  
  78.             maxPurchasable = math.min( maxPurchasable, AIGlobals.ItemWeights[itemData.ItemTable.ItemId].MaxPurchase or 1 )
  79.  
  80.             --Mithy: Take into account item cost mult, and make sure we can actually afford one
  81.             local maxAffordable = math.floor( gold / (itemData.ItemTable.ItemCost * (unit.Sync.ItemCostMod or 1)) )
  82.             if maxAffordable < 1 then --was <= 0
  83.                 continue
  84.             end
  85.  
  86.             currentPriority = itemData.Priority
  87.  
  88.             --Make sure the new item is better than the old item
  89.             if sellItemData[itemData.ItemTable.InventoryType] then
  90.                 --[MOD] Fixed amount added to sell priority to ensure new item is greater than 5 priority better.  Prevents buy/sell loops
  91.                 if sellItemData[itemData.ItemTable.InventoryType].SellItemPriority + 5 > itemData.Priority then
  92.                     continue
  93.                 end
  94.             end
  95.  
  96.         else
  97.             --Handle non-stacked items here
  98.             if hasItem then
  99.                 continue
  100.             end
  101.  
  102. --0.26.40 - removed the code that placed a limitation on what items could be purchased at the start of the game
  103. --[[            # [MOD] TE   Buy more cheaper items at start
  104.             if GetGameTimeSeconds() < 30 and gold < 5000 and itemData.ItemTable.ItemCost >= 1750 then
  105.                 continue
  106.             elseif  GetGameTimeSeconds() < 30 and gold < 35000 and itemData.ItemTable.ItemCost > 10000 then
  107.                 continue
  108.             end
  109. --]]
  110.  
  111.             --Get our sell refund and make sure the new item is better than the old item
  112.             local addAmount = 0
  113.             if sellItemData[itemData.ItemTable.InventoryType] then
  114.                 addAmount = sellItemData[itemData.ItemTable.InventoryType].SellItemRefund
  115.  
  116.  
  117.                 --[MOD] Fixed amount added to sell priority to ensure new item is greater than 5 priority better.   Prevents buy/sell loops
  118.                 if sellItemData[itemData.ItemTable.InventoryType].SellItemPriority + 5 > itemData.Priority then
  119.                     continue
  120.                 end
  121.             end
  122.  
  123.             --Mithy: Factor item cost mult
  124.             if gold + (addAmount * (unit.Sync.ItemCostMod or 1)) < (itemData.ItemTable.ItemCost * (unit.Sync.ItemCostMod or 1)) then
  125.                 continue
  126.             end
  127.  
  128.             --[MOD] TE Check idol priority against current idol
  129.             if syncData.Inventory.Generals then
  130.                 local buyItem = true
  131.                 for slot, invData in syncData.Inventory.Generals.Slots do
  132.                     local invItemData = EntityData[invData[1]].Data  # [MOD] TE Refrence .Data so item def can get blueprint.
  133.                     local invItemDef = Items[invItemData.BlueprintId]
  134.                     if invItemDef then
  135.                         local idolInSlot = string.sub(invItemDef.Name, 1, -5)
  136.                         local idolInShop = string.sub(itemData.ItemTable.ItemId, 1, -5)
  137.                         if idolInSlot == idolInShop then
  138.                             local invPriority = 0
  139.                             for k,v in asset.ItemPriorities do
  140.                                 if v.ItemTable.ItemId == invItemDef.Name then
  141.                                     invPriority = v.Priority
  142.                                     break
  143.                                 end
  144.  
  145.                             end
  146.  
  147.  
  148.                             if invPriority + 5 > itemData.Priority then
  149.                                 --WARN( LOC(aiBrain.Nickname) ..' Current: '..invItemDef.Name ..' - ' .. invPriority + 5 .. ' | vs | ' .. itemData.ItemTable.ItemId .. ' - ' .. itemData.Priority )
  150.                                 buyItem = false
  151.                             else
  152.                                 buyItem = true
  153.                                 --WARN( LOC(aiBrain.Nickname) ..' Sell: '..invItemDef.Name ..' - ' .. invPriority .. ' | Buy: ' .. itemData.ItemTable.ItemId .. ' - ' .. itemData.Priority )
  154.                             end
  155.                         end
  156.                     end
  157.                 end
  158.                 if not buyItem then
  159.                     continue
  160.                 end
  161.             end
  162.  
  163.  
  164.             currentPriority = itemData.Priority
  165.         end
  166.  
  167.         --Make sure we'll have room for the item
  168.         if inventoryOpen[itemData.ItemTable.InventoryType] <= 0 and not sellItemData[itemData.ItemTable.InventoryType] then
  169.             continue
  170.         end
  171.  
  172.         --WARN('Items - ' ..  itemData.ItemTable.ItemId .. ' - Inventory Type - ' ..  inventoryOpen[itemData.ItemTable.InventoryType] )
  173.  
  174.  
  175.         --Do NOT allow rebuying of the same item
  176.         if sellItemData[itemData.ItemTable.InventoryType].SellItem == itemData.ItemTable.ItemId then
  177.             continue
  178.         end
  179.  
  180.         highestPriority = currentPriority
  181.  
  182.         --[[if (unit:GetArmy() == 1) then
  183.             WARN('*AI SHOP DEBUG: Find Best Item Army= ' .. unit:GetArmy() .. ' - Purchasing item= ' .. itemData.ItemTable.ItemId
  184.                 .. ' - Priority= ' .. highestPriority
  185.                 .. ' - Quantity= ' .. purchaseQuantity  )
  186.         end--]]
  187.  
  188.         table.insert( bestItems, { ItemName = itemData.ItemTable.ItemId, ShopType = itemData.ItemTable.ShopType,
  189.             Shop = nearby, ItemCost = itemData.ItemTable.ItemCost, ItemPriority = highestPriority, NumPurchase = purchaseQuantity,
  190.             InventoryType = itemData.ItemTable.InventoryType, BaseShopType = itemData.ItemTable.BaseShopType } )
  191.     end
  192.  
  193.     if table.getn( bestItems ) > 0 then
  194.         return bestItems[Random( 1, table.getn(bestItems) )]
  195.     end
  196.  
  197.     return false
  198. end
  199.  
  200.  
  201. ----------------
  202.  
  203.  
  204. function FindBestCitadelUpgrade(unit, aiBrain, action)
  205.     local bestValue = 0
  206.     local bestItems = {}
  207.     local shop = aiBrain:GetStronghold()
  208.  
  209.     local asset = action.StrategicAsset
  210.     if not asset or not asset.CitadelUpgradePriorities or not shop then
  211.         return false
  212.     end
  213.  
  214.     local highestPriority = false
  215.  
  216.     --Mithy: New save-for-upgrade method that only runs once per shopping check
  217.     local savingForUpgrade, savingForCost = AIGlobals.SaveForUpgrade(unit, aiBrain)
  218.  
  219.     for _,itemData in asset.CitadelUpgradePriorities do
  220.         local purchaseQuantity = 1
  221.         local currentPriority = 0
  222.  
  223.         if itemData.Priority <= 0 then
  224.             continue
  225.         end
  226.  
  227.         --If we have a highest priority and this next item won't be higher; break the loop
  228.         if highestPriority and (itemData.Priority) < highestPriority then
  229.             break
  230.         end
  231.  
  232.         if ValidateUpgrade.CanPickUpgrade(Upgrades.Tree, unit, aiBrain.Score.WarRank, itemData.ItemTable.ItemId) != true then
  233.             continue
  234.         end
  235.  
  236.         --Mithy: New save-for logic that runs after CanPickUpgrade and takes into account item cost mods
  237.         --Are we saving, and is this what we're saving for?
  238.         if savingForUpgrade and savingForUpgrade ~= itemData.ItemTable.ItemId then
  239.             --If saving, do we have enough excess gold to purchase this?
  240.             if aiBrain.mGold - (savingForCost * (unit.Sync.ItemCostMod or 1)) < (itemData.ItemTable.ItemCost * (unit.Sync.ItemCostMod or 1)) then
  241.                 continue
  242.             end
  243.         end
  244.  
  245.         highestPriority = itemData.Priority
  246.  
  247.         table.insert( bestItems, { ItemName = itemData.ItemTable.ItemId, ShopType = itemData.ItemTable.ShopType,
  248.             Shop = shop, ItemCost = itemData.ItemTable.ItemCost, ItemPriority = highestPriority } )
  249.     end
  250.  
  251.     if table.getn( bestItems ) > 0 then
  252.         return bestItems[ Random( 1, table.getn(bestItems) ) ]
  253.     end
  254.  
  255.     return false
  256. end
RAW Paste Data