70 lines
3.5 KiB
Lua
70 lines
3.5 KiB
Lua
-- Inspect actual inventory and equipment once per minute; normal NPC interactions only.
|
|
local snapshots,registry={},{}
|
|
-- WotLK 3.3.5 UpdateFields.h: OBJECT_END (6) + 0x36 / 0x37.
|
|
-- Read only; verified against this AzerothCore build's item update fields.
|
|
local ITEM_DURABILITY,ITEM_MAX_DURABILITY=0x003C,0x003D
|
|
local registryAt=0
|
|
local consumables={}
|
|
-- Match playerbots' own food/drink categories, without an incomplete item-ID list.
|
|
local q=WorldDBQuery('SELECT entry,spellcategory_1 FROM item_template WHERE class=0 AND subclass IN (0,5) AND spellcategory_1 IN (11,59)')
|
|
if q then repeat consumables[q:GetUInt32(0)]=q:GetUInt32(1) until not q:NextRow() end
|
|
local function managed(p)
|
|
local r=p and registry[p:GetGUIDLow()]
|
|
return r and p:IsPlayerbot() and r.name==p:GetName() and r.account==p:GetAccountId() and p:GetBotAI() and not p:GetBotAI():HasGameClientMaster()
|
|
end
|
|
local function safe(p)
|
|
if not managed(p) or p:IsDead() or p:IsInCombat() or p:IsCasting() or p:IsTaxi() then return false end
|
|
local g=p:GetGroup()
|
|
if g then
|
|
if g:IsRaidGroup() or #g:GetMembers()~=g:GetMembersCount() then return false end
|
|
for _,m in pairs(g:GetMembers()) do if not managed(m) then return false end end
|
|
end
|
|
return not (AzerothAISurvivalOverride and AzerothAISurvivalOverride(p))
|
|
end
|
|
function AzerothAIReadinessSnapshot(p)
|
|
local r=snapshots[p:GetGUIDLow()]
|
|
return r and r.name==p:GetName() and r.account==p:GetAccountId() and r.values or {}
|
|
end
|
|
local function inspect(p)
|
|
local ai=p:GetBotAI();local v={readinessAt=os.time(),brokenItems=0,freeTalents=p:GetFreeTalentPoints(),foodCount=0,drinkCount=0}
|
|
for slot=0,18 do
|
|
local item=p:GetItemByPos(255,slot)
|
|
if item then
|
|
if item:IsBroken() then v.brokenItems=v.brokenItems+1 end
|
|
local maximum=item:GetUInt32Value(ITEM_MAX_DURABILITY)
|
|
if maximum>0 then local pct=100*item:GetUInt32Value(ITEM_DURABILITY)/maximum;v.minDurabilityPct=math.min(v.minDurabilityPct or 100,pct) end
|
|
end
|
|
end
|
|
for _,item in pairs(ai:GetInventoryItems()) do
|
|
local category=consumables[item:GetEntry()]
|
|
if category and p:CanUseItem(item) then
|
|
if category==11 then v.foodCount=v.foodCount+item:GetCount() else v.drinkCount=v.drinkCount+item:GetCount() end
|
|
end
|
|
end
|
|
snapshots[p:GetGUIDLow()]={name=p:GetName(),account=p:GetAccountId(),values=v}
|
|
if not safe(p) then return end
|
|
if v.freeTalents>0 then ai:DoSpecificAction('auto talents',true) end
|
|
local supplies=v.foodCount<5 or p:GetPowerType()==0 and v.drinkCount<5
|
|
if (v.minDurabilityPct or 100)<30 or v.brokenItems>0 or supplies then
|
|
-- RPG handles finding an appropriate vendor and walking there. No spawned supplies.
|
|
ai:ChangeStrategy('+rpg',1)
|
|
if not ai:HasCheat(2) then
|
|
if (v.minDurabilityPct or 100)<30 or v.brokenItems>0 then ai:DoSpecificAction('repair',true) end
|
|
if supplies then ai:DoSpecificAction('rpg buy',true) end
|
|
end
|
|
end
|
|
end
|
|
CreateLuaEvent(function()
|
|
local now=os.time()
|
|
if now-registryAt>=60 then
|
|
local rows={};local result=AuthDBQuery("SELECT guid,name,account_id FROM azerothai_lifecycle WHERE state='active'")
|
|
if result then repeat rows[result:GetUInt32(0)]={name=result:GetString(1),account=result:GetUInt32(2)} until not result:NextRow() end
|
|
registry=rows;registryAt=now
|
|
end
|
|
for _,p in pairs(GetPlayersInWorld() or {}) do if managed(p) then
|
|
local old=snapshots[p:GetGUIDLow()]
|
|
if not old or now-old.values.readinessAt>=60 then local ok,err=pcall(inspect,p);if not ok then PrintError('[AzerothAI readiness] '..tostring(err)) end end
|
|
end end
|
|
for guid,r in pairs(snapshots) do if now-r.values.readinessAt>600 then snapshots[guid]=nil end end
|
|
end,10000,0)
|