+ Reply to Thread
Results 1 to 7 of 7

Thread: Determine Combat Begin and Combat End in a raid ?

  1. #1
    Prophet of Telara
    Join Date
    Sep 2010
    Posts
    1,008

    Default Determine Combat Begin and Combat End in a raid ?

    What is the best way to determine the combat begin and combat end in a raid ?
    Event.System.Secure.Enter seems only determine my personal combat begin but not the entire raid.
    I need this for encounters like Thalguur where the first ability (group damage) start exactly 17 seconds after combat begin.

  2. #2
    Prophet of Telara
    Join Date
    Sep 2010
    Posts
    1,008

    Default

    Probably my solution is too complicated and can be implemented much easier but it works. Unfortunately I have to use global variables for this solution, is there another way?

    For the start of the fight, I check if the status changes of a NPC.
    For the end of the fight, I check if the Boss HP reached 0 % or anyone casting Call of the Ascended (Raid rez) or anyone starts a ready check.

    Code:
    local function CombatBegin() -- Track Combat Begin in a raid only for Raid Mobs
        if rra_combatbegin == "out_of_combat" then
            local inspect = Inspect.Unit.Detail
            local list = Inspect.Unit.List()
            local format = tostring
            for k,v in pairs(list) do
                local detail = inspect(format(k))
                if detail and detail.relation == "hostile" and detail.healthMax > 20000000 and detail.health > detail.healthMax*0.98 then
                    print("Combat Begin -> ".. detail.name)
                    rra_combatbegin = detail.id
                end
            end
        end
    end
    
    
    local function CombatEnd()
        if rra_combatbegin ~= "out_of_combat" then
            print("Combat End")
            rra_combatbegin = "out_of_combat"
        end
    end
    
    
    local function CheckHP(units)
        if rra_combatbegin ~= "out_of_combat" then
            local detail = Inspect.Unit.Detail(rra_combatbegin)
            if detail ~= nil then
                if detail.health <= 1 then
                    print(detail.name .. " -> " .. "0 %")
                    CombatEnd()
                end
            end
        end
    end
    
    
    local function getAbilityName(event, units)
        if units then
            for id, value in pairs(units) do
                if value then
                    local details = Inspect.Unit.Detail(id)
                    local cast = Inspect.Unit.Castbar(id)
                    if cast.abilityNew ~= nill then
                        if cast.abilityNew == "A24FE01816BA3C9E7" then -- Call of the Ascended (Raid rez)
                            CombatEnd()
                        end
                    end
                end
            end
        end
    end
    
    
    rra_combatbegin = "out_of_combat"
    Command.Event.Attach(Event.Unit.Detail.Combat, CombatBegin, "CombatBegin")
    Command.Event.Attach(Event.Unit.Detail.Health, CheckHP, "CheckHP")
    Command.Event.Attach(Event.Unit.Castbar, getAbilityName, "AbilityName")
    Command.Event.Attach(Event.Unit.Detail.Ready, CombatEnd, "CombatEnd")

  3. #3
    General of Telara
    Join Date
    Mar 2014
    Posts
    967

    Default

    I can't really offer advice on encounter timing logic (other than looking how for example KBM does it), but you don't ever have to use global variables.

    You can define local variables outside of functions which then are valid for the whole Lua file.
    If you need it across different files of your addon, each addon also has its own table, which is passed as the second vararg, so you can just put this at the beginning of each file:
    Code:
    myAddonDetails, myAddonDataTable = ...
    or alternatively, if you're not interested in the addon details anyway
    Code:
    myAddonDataTable = select(2, ...)
    Also you should really start to use the data provided to event callbacks. If you parse each available unit for each unit update, you potentially create an O(n^2) scaling, i.e. for 10 units and one event each you have 100 unit inspects, for 50 you have 2500, for 100 you get 10k...or in other words, it gets really bad quickly, unless Rift is good at bundling events (which from my experience it isn't, at least for dimension editing)
    There is no point in inspecting Units unless their availability changed or the event you're interested in fires for it.
    Without testing it, it whould look something like this:
    Code:
    local rra_combatbegin = "not_initialized"
    
    local function CombatBegin(event, units)
        local unit_details = Inspect.Unit.Detail(units)
        for id, detail in pairs(unit_details) do
           -- do checks and update rra_combatbegin
        end
    end
    You must handle the Event.Unit.Availability.* events then though, because if you approach a unit that already is in combat, it won't trigger a combat start event. Though in case of a boss, if you're not in visibility range of the boss at encounter begin, your timer will most likely be messed up anyway.
    Dimension Addon 'Tinker Tools' is now available on Curse!
    Or grab the latest development code on GitHub.

  4. #4
    Prophet of Telara
    Join Date
    Sep 2010
    Posts
    1,008

    Default

    Quote Originally Posted by Lynx3d View Post
    Also you should really start to use the data provided to event callbacks. If you parse each available unit for each unit update, you potentially create an O(n^2) scaling, i.e. for 10 units and one event each you have 100 unit inspects, for 50 you have 2500, for 100 you get 10k...or in other words, it gets really bad quickly, unless Rift is good at bundling events (which from my experience it isn't, at least for dimension editing)
    There is no point in inspecting Units unless their availability changed or the event you're interested in fires for it.
    Now you mention it, my solution seems to me also very inefficient.
    I do not know what I was thinking

    I'll try your example so thanks for the input.

  5. #5
    Prophet of Telara
    Join Date
    Sep 2010
    Posts
    1,008

    Default

    Here is my new solution, but it does not work for me with a local variable.

    If i use local rra_boss_id = 0 it does not work.
    Code:
    local rra_boss_id = 0
    Command.Event.Attach(Event.Unit.Detail.Combat, CombatCheck, "CombatCheck")
    Command.Event.Attach(Event.Combat.Death, CombatCheck, "CombatDeathCheck")

    If i use rra_boss_id = 0 everything works.
    Code:
    rra_boss_id = 0
    Command.Event.Attach(Event.Unit.Detail.Combat, CombatCheck, "CombatCheck")
    Command.Event.Attach(Event.Combat.Death, CombatCheck, "CombatDeathCheck")

    Code:
    local function CombatCheck(event, units)
        if rra_boss_id == 0 then
            local unit_details = Inspect.Unit.Detail(units)
            for id, detail in pairs(unit_details) do
                if detail.relation == "hostile" and detail.health > 1 then
                    print("Combat Begin -> ".. detail.name)
                    rra_boss_id = detail.id
                    break
                end
            end
        else
            local unit_details = Inspect.Unit.Detail(units)
            for id, detail in pairs(unit_details) do
                if detail.id == rra_boss_id then
                    print("Combat End -> ".. detail.name)
                    rra_boss_id = 0
                end
            end
        end
    end
    
    rra_boss_id = 0
    Command.Event.Attach(Event.Unit.Detail.Combat, CombatCheck, "CombatCheck")
    Command.Event.Attach(Event.Combat.Death, CombatCheck, "CombatDeathCheck")

  6. #6
    General of Telara
    Join Date
    Mar 2014
    Posts
    967

    Default

    Hm I think you need to declar local variables before the function for it to be visible. From what I understand, each Lua file basically gets executed as the body of an anonymous function. So say you write

    Code:
    -- Main.lua
    local someFunc()
        some_var = 0
    end
    
    local some_var
    This effectively means to Rift:
    Code:
    local function executeLuaFile(...)
        local someFunc()
            some_var = 0  -- some_var not in local environment => becomes global assignment
        end
    
        local some_var  -- too late for beeing visible to someFunc()
    end
    
    executeLuaFile(addonInfo, addonData)
    Of course the actual process uses the C-API of the LuaJIT library, this is just an equivalent if it was all done in Lua.
    I hope I didn't say a lot of bullsh** though, I sometimes still get confused about Lua environments and other stuff myself ^^
    Last edited by Lynx3d; 06-28-2016 at 05:25 AM.
    Dimension Addon 'Tinker Tools' is now available on Curse!
    Or grab the latest development code on GitHub.

  7. #7
    Prophet of Telara
    Join Date
    Sep 2010
    Posts
    1,008

    Default

    Quote Originally Posted by Lynx3d View Post
    Hm I think you need to declar local variables before the function for it to be visible.
    Thanks that's it. Now it works

    Code:
    local rra_boss_id
    
    local function CombatCheck(event, units)
        if not rra_boss_id then
            local unit_details = Inspect.Unit.Detail(units)
            for id, detail in pairs(unit_details) do
                if detail.relation == "hostile" and detail.health > 1 then
                    print("Combat Begin -> ".. detail.name)
                    rra_boss_id = detail.id
                    break
                end
            end
        else
            local unit_details = Inspect.Unit.Detail(units)
            for id, detail in pairs(unit_details) do
                if detail.id == rra_boss_id then
                    print("Combat End -> ".. detail.name)
                    rra_boss_id = nil
                    break
                end
            end
        end
    end
    
    Command.Event.Attach(Event.Unit.Detail.Combat, CombatCheck, "CombatCheck")
    Command.Event.Attach(Event.Combat.Death, CombatCheck, "CombatCheck")

+ Reply to Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts