local NanamiDPS = NanamiDPS local DataStore = {} NanamiDPS.DataStore = DataStore local function CreateEmptySegmentData() return { damage = {}, healing = {}, damageTaken = {}, deaths = {}, dispels = {}, interrupts = {}, threat = {}, activity = {}, classes = {}, } end local function CreateSegment(name) return { name = name or "Unknown", startTime = GetTime(), endTime = 0, duration = 0, data = CreateEmptySegmentData(), } end DataStore.total = CreateSegment("Total") DataStore.current = CreateSegment("Current") DataStore.history = {} DataStore.inCombat = false function DataStore:GetSegment(index) if index == 0 then return self.total elseif index == 1 then return self.current elseif index and self.history[index - 1] then return self.history[index - 1] end return self.current end function DataStore:GetSegmentList() local list = {} table.insert(list, { index = 0, name = NanamiDPS.L["Total"] }) table.insert(list, { index = 1, name = NanamiDPS.L["Current"] }) for i, seg in ipairs(self.history) do table.insert(list, { index = i + 1, name = seg.name }) end return list end function DataStore:StartCombat() if self.inCombat then return end self.inCombat = true self.current = CreateSegment("Current") self.current.startTime = GetTime() NanamiDPS:FireCallback("COMBAT_START") end function DataStore:StopCombat() if not self.inCombat then return end self.inCombat = false self.current.endTime = GetTime() self.current.duration = self.current.endTime - self.current.startTime local hasData = false for _ in pairs(self.current.data.damage) do hasData = true; break end if not hasData then for _ in pairs(self.current.data.healing) do hasData = true; break end end if hasData and self.current.duration >= 2 then local segName = date("%H:%M:%S") self.current.name = segName table.insert(self.history, 1, self.current) local maxSegs = (NanamiDPS.config and NanamiDPS.config.maxSegments) or 10 while table.getn(self.history) > maxSegs do table.remove(self.history) end end self.current = CreateSegment("Current") NanamiDPS:FireCallback("COMBAT_STOP") NanamiDPS:FireCallback("refresh") end function DataStore:AddDamage(source, spell, target, amount, school) if not source or not amount then return end amount = tonumber(amount) if not amount or amount <= 0 then return end local segs = { self.current, self.total } for _, seg in ipairs(segs) do local d = seg.data.damage if not d[source] then d[source] = { _sum = 0, _ctime = 1, _tick = 0, spells = {} } end d[source]._sum = d[source]._sum + amount d[source].spells[spell] = (d[source].spells[spell] or 0) + amount self:UpdateCombatTime(d[source]) end end function DataStore:AddDamageTaken(target, spell, source, amount, school) if not target or not amount then return end amount = tonumber(amount) if not amount or amount <= 0 then return end local segs = { self.current, self.total } for _, seg in ipairs(segs) do local d = seg.data.damageTaken if not d[target] then d[target] = { _sum = 0, _ctime = 1, _tick = 0, spells = {} } end d[target]._sum = d[target]._sum + amount d[target].spells[spell] = (d[target].spells[spell] or 0) + amount self:UpdateCombatTime(d[target]) end end function DataStore:AddHealing(source, spell, target, amount, effective) if not source or not amount then return end amount = tonumber(amount) effective = tonumber(effective) or amount if not amount or amount <= 0 then return end local segs = { self.current, self.total } for _, seg in ipairs(segs) do local d = seg.data.healing if not d[source] then d[source] = { _sum = 0, _esum = 0, _ctime = 1, _tick = 0, spells = {}, effective = {} } end d[source]._sum = d[source]._sum + amount d[source]._esum = d[source]._esum + effective d[source].spells[spell] = (d[source].spells[spell] or 0) + amount d[source].effective[spell] = (d[source].effective[spell] or 0) + effective self:UpdateCombatTime(d[source]) end end function DataStore:AddDeath(playerName, deathLog) local segs = { self.current, self.total } for _, seg in ipairs(segs) do local d = seg.data.deaths if not d[playerName] then d[playerName] = { _sum = 0, events = {} } end d[playerName]._sum = d[playerName]._sum + 1 table.insert(d[playerName].events, deathLog) end end function DataStore:AddDispel(source, spell, target, aura) if not source then return end local segs = { self.current, self.total } for _, seg in ipairs(segs) do local d = seg.data.dispels if not d[source] then d[source] = { _sum = 0, spells = {} } end d[source]._sum = d[source]._sum + 1 d[source].spells[spell] = (d[source].spells[spell] or 0) + 1 end end function DataStore:AddInterrupt(source, spell, target, interrupted) if not source then return end local segs = { self.current, self.total } for _, seg in ipairs(segs) do local d = seg.data.interrupts if not d[source] then d[source] = { _sum = 0, spells = {} } end d[source]._sum = d[source]._sum + 1 d[source].spells[spell] = (d[source].spells[spell] or 0) + 1 end end function DataStore:AddThreat(source, amount) if not source or not amount then return end local segs = { self.current, self.total } for _, seg in ipairs(segs) do local d = seg.data.threat if not d[source] then d[source] = { _sum = 0 } end d[source]._sum = d[source]._sum + amount if d[source]._sum < 0 then d[source]._sum = 0 end end end function DataStore:GetPlayerThreat(source) if not source then return 0 end local d = self.current.data.threat[source] return d and d._sum or 0 end function DataStore:UpdateActivity(source, timestamp) if not source then return end local segs = { self.current, self.total } for _, seg in ipairs(segs) do local d = seg.data.activity if not d[source] then d[source] = { _firstAction = timestamp, _lastAction = timestamp, _activeTime = 0, _tick = 0 } end local entry = d[source] if entry._tick > 0 and (timestamp - entry._tick) < 5 then entry._activeTime = entry._activeTime + (timestamp - entry._tick) end entry._tick = timestamp entry._lastAction = timestamp end end function DataStore:SetClass(name, class) self.current.data.classes[name] = class self.total.data.classes[name] = class end function DataStore:GetClass(name) return self.current.data.classes[name] or self.total.data.classes[name] end function DataStore:UpdateCombatTime(entry) if not entry._tick then entry._tick = 0 end local now = GetTime() if entry._tick == 0 then entry._tick = now return end local diff = now - entry._tick if diff >= 5 then entry._ctime = entry._ctime + 5 else entry._ctime = entry._ctime + diff end entry._tick = now end function DataStore:ResetAll() self.total = CreateSegment("Total") self.current = CreateSegment("Current") self.history = {} NanamiDPS:FireCallback("refresh") end