Files
AzerothAI/ale/azerothai_experience.lua
2026-09-24 08:05:16 +12:00

49 lines
3.3 KiB
Lua

-- Bounded durable encounter memory. No changes to health, resurrection or stats.
local cache={}
local function quote(s)return "UNHEX('"..string.gsub(tostring(s),'.',function(c)return string.format('%02X',string.byte(c))end).."')" end
-- Synchronous DDL: the next snapshot may query immediately after ALE reload.
AuthDBQuery([[CREATE TABLE IF NOT EXISTS azerothai_death_experience (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,guid INT UNSIGNED,account_id INT UNSIGNED,
name VARCHAR(64),at BIGINT UNSIGNED,killer VARCHAR(100),entry INT UNSIGNED,
map INT UNSIGNED,x FLOAT,y FLOAT,level INT UNSIGNED,INDEX resident(guid,at))]])
local function identity(p)
if not p or not p:IsPlayerbot() or not p:GetBotAI() or p:GetBotAI():HasGameClientMaster() then return false end
local q=AuthDBQuery("SELECT name,account_id FROM azerothai_lifecycle WHERE state='active' AND guid="..p:GetGUIDLow())
return q and q:GetString(0)==p:GetName() and q:GetUInt32(1)==p:GetAccountId()
end
local function memories(p)
local guid,now=p:GetGUIDLow(),os.time();local c=cache[guid]
if c and c.account==p:GetAccountId() and c.name==p:GetName() and now-c.loaded<60 then return c.rows end
local rows={}
local q=AuthDBQuery('SELECT id,at,killer,entry,map,x,y,level FROM azerothai_death_experience WHERE guid='..guid..' AND account_id='..p:GetAccountId()..' AND name='..quote(p:GetName())..' AND at>'..(now-30*86400)..' ORDER BY id DESC LIMIT 32')
if q then repeat rows[#rows+1]={id=q:GetUInt32(0),at=q:GetUInt32(1),killer=q:GetString(2),entry=q:GetUInt32(3),map=q:GetUInt32(4),x=q:GetFloat(5),y=q:GetFloat(6),level=q:GetUInt32(7)} until not q:NextRow() end
cache[guid]={loaded=now,account=p:GetAccountId(),name=p:GetName(),rows=rows};return rows
end
function AzerothAILearnedDanger(p,target)
local creature=target and target:ToCreature();if not creature then return false end
for _,m in ipairs(memories(p)) do
-- Reassess after three levels or three days. Avoid this creature type near the fatal encounter.
if m.entry==creature:GetEntry() and m.map==p:GetMapId() and os.time()-m.at<3*86400 and p:GetLevel()<m.level+3 and (target:GetX()-m.x)^2+(target:GetY()-m.y)^2<=10000 then return true end
end
return false
end
function AzerothAIExperienceSnapshot(p)
local m=memories(p)[1]
if m then return {deathMemoryId=m.id,deathMemoryAt=m.at,deathMemoryKiller=m.killer,deathMemoryMap=m.map,deathMemoryX=m.x,deathMemoryY=m.y,deathMemoryLevel=m.level} end
return {}
end
local function died(_,killer,p)
if not identity(p) then return end
local now=os.time();local c=cache[p:GetGUIDLow()]
if c and c.recorded==now then return end
local creature=killer and killer:ToCreature()
AuthDBExecute('INSERT INTO azerothai_death_experience(guid,account_id,name,at,killer,entry,map,x,y,level) VALUES ('..p:GetGUIDLow()..','..p:GetAccountId()..','..quote(p:GetName())..','..now..','..quote(killer and killer:GetName() or 'Unknown')..','..(creature and creature:GetEntry() or 0)..','..p:GetMapId()..','..p:GetX()..','..p:GetY()..','..p:GetLevel()..')')
cache[p:GetGUIDLow()]={loaded=0,recorded=now,rows={}}
end
RegisterPlayerEvent(8,died)
RegisterPlayerEvent(6,died)
CreateLuaEvent(function()
AuthDBExecute('DELETE FROM azerothai_death_experience WHERE at<'..(os.time()-30*86400)..' LIMIT 2000')
for guid,c in pairs(cache) do if os.time()-c.loaded>600 then cache[guid]=nil end end
end,3600000,0)