Skip to content

Commit

Permalink
Added a feature which should create a overall segment after a dungeon…
Browse files Browse the repository at this point in the history
… heroic and mythic0 run
  • Loading branch information
Tercioo committed Sep 15, 2024
1 parent 3787860 commit f899fd3
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 6 deletions.
16 changes: 15 additions & 1 deletion Definitions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@
---@field training_dummy boolean if true, the combat is against a training dummy
---@field playerTalents table<actorname, string> [playerName] = "talent string"
---@field bossName string? the name of the boss, if the combat has no unitId "boss1", this value is nil
---@field
---@field context string? for the context manager
---@field
---@field __call table
---@field __index table
Expand Down Expand Up @@ -284,6 +284,7 @@
---@field player_last_events table<string, table[]> record the latest events of each player, latter used to build the death log
---@field
---@field LockActivityTime fun(self: combat)
---@field AddCombat fun(self: combat, givingCombat: combat, bSetStartDate:boolean?, bSetEndDate:boolean?)
---@field CutDeathEventsByTime fun(self: combat, time: number?) remove death events by time, default 10 seconds
---@field GetTotal fun(self: combat, attribute: number, subAttribute: number?, onlyGroup: boolean?) : number return the total amount of the requested attribute
---@field GetCurrentPhase fun(self: combat) : number return the current phase of the combat or the phase where the combat ended
Expand Down Expand Up @@ -826,9 +827,22 @@
---@field StopTime fun(actor: actor) stop the time of the actor
---@field SetOrGetPauseState fun(actor: actor, bPause: boolean|nil) : boolean|nil set or get the pause state of the actor, if bPause is nil, then it will return the current pause state

---@class instancedifficulty : table
---@field DungeonNormal number
---@field DungeonHeroic number
---@field DungeonMythic number
---@field DungeonMythicPlus number
---@field RaidLFR number
---@field RaidNormal number
---@field RaidHeroic number
---@field RaidMythic number


---@class details222 : table
---@field TimeMachine timemachine
---@field PetContainer petcontainer
---@field InstanceDifficulty instancedifficulty
---@field ContextManager contextmanager

---@class profile_breakdown_settings : table
---@field font_size number
Expand Down
253 changes: 253 additions & 0 deletions boot.lua
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,257 @@
--aura scanner
Details222.AuraScan = {}

---@type instancedifficulty
Details222.InstanceDifficulty = {
["DungeonNormal"] = 1,
["DungeonHeroic"] = 2,
["DungeonMythic"] = 23,
["DungeonMythicPlus"] = 8,
["RaidLFR"] = 17,
["RaidNormal"] = 14,
["RaidHeroic"] = 15,
["RaidMythic"] = 16,
}

local emptyFunction = function()end
local emptyTable = {}

---context manager is a system that evaluates where the player is and create a set of extra rules that fit the content the player is doing
---@class contextmanager : table
---@field instanceType string
---@field instanceName string
---@field instanceId number
---@field instanceDifficulty number
---@field lastInstanceType string
---@field lastInstanceName string
---@field lastInstanceDifficulty number
---@field contextId string
---@field bContextStarted boolean
---@field bContextFinished boolean
---@field bHasContext boolean
---@field fHasLostInterest function
---@field fOnContextFinished function
---@field fOnCombatFinished function
---@field eventFrame frame
---@field DetailsEventListener table
---@field contextEventTable table
---@field StartContext function
---@field CheckContextInterest function
---@field FinishContext function
---@field GetContext function

--tells what is the activity the player is doing
Details222.ContextManager = {
instanceType = "INIT",
instanceName = "INIT",
instanceDifficulty = 0,
lastInstanceType = "INIT",
lastInstanceName = "INIT",
lastInstanceDifficulty = 0,
contextId = "INIT",
bContextStarted = false,
bContextFinished = false,
bHasContext = false,
fOnContextFinished = emptyFunction,
fHasLostInterest = emptyFunction,
fOnCombatFinished = emptyFunction,
contextEventTable = emptyTable,

eventFrame = CreateFrame("frame"),

---start a new context, this is called from the CheckContextInterest() function
---@param self contextmanager
---@param instanceId number
---@param instanceName string
---@param instanceType string
---@param difficultyId number
---@param contextEventTable table
---@param fOnCombatFinished function run when details! finishes a combat
---@param fOnContextFinished function run when the context is finished
---@param fHasLostInterest function run when CheckContextInterest() fails to find a context
StartContext = function(self, instanceId, instanceName, instanceType, difficultyId, contextEventTable, fOnCombatFinished, fOnContextFinished, fHasLostInterest)
self.instanceType = instanceType
self.instanceName = instanceName
self.instanceId = instanceId
self.instanceDifficulty = difficultyId
self.bContextStarted = true
self.bContextFinished = false
self.bHasContext = true
self.fOnContextFinished = fOnContextFinished
self.fHasLostInterest = fHasLostInterest
self.fOnCombatFinished = fOnCombatFinished
self.contextEventTable = contextEventTable

--create an event listener to grab the event when Details! finishes a combat
if (not self.DetailsEventListener) then
self.DetailsEventListener = Details:CreateEventListener()
end
self.DetailsEventListener:UnregisterEvent("COMBAT_PLAYER_LEAVE")
--register the onFinishCombat for the context
self.DetailsEventListener:RegisterEvent("COMBAT_PLAYER_LEAVE", fOnCombatFinished)

--unregister all events
self.eventFrame:UnregisterAllEvents()

--register the events that the context require
for i = 1, #contextEventTable.events do
self.eventFrame:RegisterEvent(contextEventTable.events[i])
end

--if the callback function returns true, the context is finished
self.eventFrame:SetScript("OnEvent", function(eventFrame, event, ...)
if (contextEventTable.callback(event, ...)) then
Details222.DebugMsg("context manager event", event)
--context completed
Details222.DebugMsg("Context Completed!")
C_Timer.After(1, fOnContextFinished)
C_Timer.After(1.1, function() self:FinishContext() end)
end
end)

Details222.DebugMsg("a new context has been set.")
end,

---check if the player is in a context of interest
---@param self contextmanager
---@param instanceId number
---@param instanceName string
---@param instanceType string
---@param difficultyId number
CheckContextInterest = function(self, instanceId, instanceName, instanceType, difficultyId)
Details222.DebugMsg("Checking for new context:", instanceId, instanceName, instanceType, difficultyId)
--normal, heroic and mythic0 dungeons on Retail
local diffTable = Details222.InstanceDifficulty
if (difficultyId == diffTable.DungeonNormal or difficultyId == diffTable.DungeonHeroic or difficultyId == diffTable.DungeonMythic) then
if (DetailsFramework.IsDragonflightAndBeyond()) then
--check if the player is in the same context
if (self.bHasContext and self.instanceId == instanceId and self.instanceType == instanceType and self.instanceName == instanceName and self.instanceDifficulty == difficultyId) then
return
end

--if a context is found, finishes it before a new one is created
if (self.bHasContext) then
--discard the context
Details222.DebugMsg("had an active context, finishing it.")
self:FinishContext()
end

--set a new context where at the end of the dungeon it creates an overall segment for the run
--function to verify if context is finished, in this case if all objectives of the dungeon has been completed by listening to the SCENARIO_COMPLETED event
local contextEventTable = {
events = {"SCENARIO_COMPLETED"},
callback = function(...)
--when a context return true, the context is finished and will trigger a call on the fOnContextFinished function
return true
end
}

--create a contextId to tag combats that are part of the same context
self.contextId = instanceName .. tostring(time())

--called when a combat finishes and this context is still active
local fOnCombatFinished = function()
local currentCombat = Details:GetCurrentCombat()
currentCombat.context = self.contextId
end

---this function evaluates if this context has lost its interest and should be discarded, return true if the context is no longer valid
local fHasLostInterest = function(instanceId, instanceName, instanceType, difficultyId)
--check if the player is still in the same context
if (self.instanceId ~= instanceId or self.instanceType ~= instanceType or self.instanceName ~= instanceName or self.instanceDifficulty ~= difficultyId) then
return true
end
end

--will ba called when the context finishes, in this case when the SCENARIO_COMPLETED event is triggered
local fOnContextFinished = function()
---@type combat[]
local interestCombats = {}
--get all segments
local segments = Details:GetCombatSegments()
for i = 1, #segments do
local segment = segments[i]
if (segment.context == self.contextId) then
interestCombats[#interestCombats+1] = segment
end
end

if (#interestCombats > 0) then
--start a new combat
Details222.StartCombat()

Details222.DebugMsg("merging", #interestCombats, "combats into a single combat.")

---@type combat
local currentCombat = Details:GetCurrentCombat()

--iterate over all interest combats
for i = 1, #interestCombats do
local interestCombat = interestCombats[i]
--add the combat to the new combat
currentCombat:AddCombat(interestCombat, i == 1, i == #interestCombats)
end

Details222.DebugMsg("combat time:", currentCombat:GetCombatTime())

--finish the new combat
Details:EndCombat()
end

Details222.DebugMsg("overall segment has been created.")
end

self:StartContext(instanceId, instanceName, instanceType, difficultyId, contextEventTable, fOnCombatFinished, fOnContextFinished, fHasLostInterest)

return
end
else
--if no context is found, check if there is a current context and check if it lost its interest
if (self.bHasContext) then
if (self.fHasLostInterest(self, instanceId, instanceName, instanceType, difficultyId)) then
Details222.DebugMsg("no context found, but context is active, finishing the current context.")
--discard the context
self:FinishContext()
end
end
end
end,

---finish the current context
---@param self contextmanager
FinishContext = function(self)
if (not self.bHasContext or not self.bContextStarted or self.bContextFinished) then
return
end

--mark this context as finished
self.bContextFinished = true

--reset context
self.instanceType = "INIT"
self.instanceName = "INIT"
self.contextId = "INIT"
self.instanceId = -1
self.instanceDifficulty = 0
self.bContextStarted = false
self.bHasContext = false
self.fOnContextFinished = emptyFunction
self.fHasLostInterest = emptyFunction
self.fOnCombatFinished = emptyFunction
self.contextEventTable = emptyTable
end,

---return the current contextIndex
---@param self contextmanager
---@return number|boolean, string?, string?, number?
GetContext = function(self)
if (self.bHasContext) then
return self.instanceId, self.instanceName, self.instanceType, self.instanceDifficulty
end
return false
end,
}

local GetSpellInfo = C_Spell and C_Spell.GetSpellInfo or GetSpellInfo
Details222.GetSpellInfo = GetSpellInfo

Expand Down Expand Up @@ -623,6 +874,8 @@ Made Details! survive for another expansion (Details! Team).
_detalhes.debug_chr = false
_detalhes.opened_windows = 0
_detalhes.last_combat_time = 0
_detalhes.last_zone_type = "INIT"
_detalhes.last_zone_id = -1

--store functions to create options frame
Details.optionsSection = {}
Expand Down
31 changes: 31 additions & 0 deletions classes/class_combat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,37 @@ local segmentTypeToString = {
end
end

---@param self combat
---@param givingCombat combat
---@param bSetStartDate boolean if true, the start date of the receiving combat will be set to the start date of the giving combat
---@param bSetEndDate boolean if true, the end date of the receiving combat will be set to the end date of the giving combat
---@return combat
function classCombat:AddCombat(givingCombat, bSetStartDate, bSetEndDate)
local receivingCombat = self

local timeInCombat = 0

receivingCombat:CopyDeathsFrom(givingCombat, false)
timeInCombat = timeInCombat + givingCombat:GetCombatTime()

receivingCombat = receivingCombat + givingCombat

local startDate, endDate = givingCombat:GetDate()
local startTime, endTime = givingCombat:GetStartTime(), givingCombat:GetEndTime()
if (bSetStartDate) then
receivingCombat:SetDate(startDate, endDate)
receivingCombat:SetStartTime(startTime)
receivingCombat:SetEndTime(endTime)
else
if (bSetEndDate) then
receivingCombat:SetDate(false, endDate)
receivingCombat:SetEndTime(endTime)
end
end

return receivingCombat
end

--return the total of a specific attribute
local power_table = {0, 1, 3, 6, 0, "alternatepower"}

Expand Down
3 changes: 1 addition & 2 deletions classes/container_actors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -789,10 +789,9 @@ unitNameTitles[#unitNameTitles+1] = unitNameTitles[1]:gsub(PET_TYPE_PET, PET_TYP
else
--anything else that isn't a player or a pet
actorObject.displayName = actorName

local npcID = Details:GetNpcIdFromGuid(actorSerial)
if (npcID) then
if (npcID == 210759 or npcID == 216287) then
if (npcID == 210759 or npcID == 216287) then --210759 --flag 0x2111
actorObject.grupo = true
end
end
Expand Down
2 changes: 1 addition & 1 deletion core/control.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1524,7 +1524,7 @@
if (instance.rows_showing == 0 and instance:GetSegment() == -1) then -- -1 overall data
if (not instance:IsShowingOverallDataWarning()) then
local tutorial = Details:GetTutorialCVar("OVERALLDATA_WARNING1") or 0
if ((type(tutorial) == "number") and (tutorial < 60)) then
if ((type(tutorial) == "number") and (tutorial < 10)) then
Details:SetTutorialCVar ("OVERALLDATA_WARNING1", tutorial + 1)
instance:ShowOverallDataWarning (true)
end
Expand Down
8 changes: 7 additions & 1 deletion core/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5327,18 +5327,24 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1
end
end

function Details.parser_functions:SCENARIO_COMPLETED(...)

end

function Details.parser_functions:ZONE_CHANGED_NEW_AREA(...)
return Details.Schedules.After(1, Details.Check_ZONE_CHANGED_NEW_AREA)
end

--~zone ~area
function Details:Check_ZONE_CHANGED_NEW_AREA()
local zoneName, zoneType, _, _, _, _, _, zoneMapID = GetInstanceInfo()
local zoneName, zoneType, difficultyID, difficultyName, _, _, _, zoneMapID = GetInstanceInfo()

Details.zone_type = zoneType
Details.zone_id = zoneMapID
Details.zone_name = zoneName

Details222.ContextManager:CheckContextInterest(zoneMapID, zoneName, zoneType, difficultyID)

_in_resting_zone = IsResting()

if (_in_resting_zone) then
Expand Down
Loading

0 comments on commit f899fd3

Please sign in to comment.