• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Lua] Invoking 2 units that check nearby units together makes the game freezes

Status
Not open for further replies.
Level 24
Joined
Jun 26, 2020
Messages
1,852
Hello, I made this ability to create a rock that slows nearby enemy units, but when 2 of this units are place together, the game lags and then freezes, I don't know what is wrong:

Lua:
OnInit(function ()
    Require "BossFightUtils"

    local SPELL = FourCC('A02F')
    local AREA = 300.
    local DURATION = 14.
    local ROCK_ID = FourCC('o063')

    RegisterSpellEffectEvent(SPELL, function ()
        local caster = GetSpellAbilityUnit()
        local owner = GetOwningPlayer(caster)
        local rock = CreateUnit(owner, ROCK_ID, GetSpellTargetX(), GetSpellTargetY(), 0)
        SetUnitAnimation(rock, "death")
        local eff = AddSpecialEffect("Abilities\\Spells\\Orc\\EarthQuake\\EarthQuakeTarget.mdl", GetSpellTargetX(), GetSpellTargetY())
        Timed.echo(1., DURATION, function ()
            SetUnitAnimation(rock, "stand")
            local x, y = GetUnitX(rock), GetUnitY(rock)
            ForUnitsInRange(x, y, AREA, function (u)
                if GetUnitTypeId(u) ~= ROCK_ID then
                    -- Change its target
                    if math.random(100) <= 50 then
                        ForUnitsInRange(x, y, 4*AREA, function (u2)
                            if GetUnitTypeId(u2) ~= ROCK_ID then
                                IssueTargetOrderById(rock, Orders.smart, u2)
                            end
                        end)
                    end
                    -- Slow
                    if not UnitHasBuffBJ(u, FourCC('Bchd')) then
                        DummyCast(
                            owner,
                            x, y,
                            SLOW_SPELL,
                            SLOW_ORDER,
                            1,
                            CastType.TARGET,
                            u
                        )
                    end
                end
            end)
            BlzSetSpecialEffectPosition(eff, x, y, BlzGetLocalSpecialEffectZ(eff))
        end, function ()
            DestroyEffect(eff)
            KillUnit(rock)
        end)
    end)

end)
 
Level 39
Joined
Feb 27, 2007
Messages
5,016
Something in this section causes an infinite loop but I don't see what it could be.
Lua:
        Timed.echo(1., DURATION, function ()
            SetUnitAnimation(rock, "stand")
            local x, y = GetUnitX(rock), GetUnitY(rock)
            ForUnitsInRange(x, y, AREA, function (u)
                if GetUnitTypeId(u) ~= ROCK_ID then
                    -- Change its target
                    if math.random(100) <= 50 then
                        ForUnitsInRange(x, y, 4*AREA, function (u2)
                            if GetUnitTypeId(u2) ~= ROCK_ID then
                                IssueTargetOrderById(rock, Orders.smart, u2)
                            end
                        end)
                    end
                    -- Slow
                    if not UnitHasBuffBJ(u, FourCC('Bchd')) then
                        DummyCast(
                            owner,
                            x, y,
                            SLOW_SPELL,
                            SLOW_ORDER,
                            1,
                            CastType.TARGET,
                            u
                        )
                    end
                end
            end)
            BlzSetSpecialEffectPosition(eff, x, y, BlzGetLocalSpecialEffectZ(eff))
        end,
I think there is also an error in the first half, or it's not clear what you're trying to do with ordering the rock to 'smart'. The way it currently proceeds is as follows:
  • Enum units within AREA of (x,y)
  • If the enum unit (u) is a rock then do nothing, otherwise...
    • If a 50% chance occurs (chance computed for each value of u), then also enum all units within 4*AREA of (x,y)
      • If the interior enum unit (u2) is not a rock, then order the rock to smart to u2
      • This repeats for all u2s picked, so the rock will only ever start the smart order on the last u2 of the group that passes the 50% chance
    • If the unit does not have the debuff, apply it
Each time a u passes the 50% chance it then does the interior enum where the rock is ordered to smart every non-rock unit within 4*AREA of its current position, but since they're all sequential all but the final order gets overwritten. Then, for any other u that passes the chance it will overwrite that 'last' order with another interior enum order chain.

Need more context about what you're trying to do.
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
Something in this section causes an infinite loop but I don't see what it could be.
Lua:
        Timed.echo(1., DURATION, function ()
            SetUnitAnimation(rock, "stand")
            local x, y = GetUnitX(rock), GetUnitY(rock)
            ForUnitsInRange(x, y, AREA, function (u)
                if GetUnitTypeId(u) ~= ROCK_ID then
                    -- Change its target
                    if math.random(100) <= 50 then
                        ForUnitsInRange(x, y, 4*AREA, function (u2)
                            if GetUnitTypeId(u2) ~= ROCK_ID then
                                IssueTargetOrderById(rock, Orders.smart, u2)
                            end
                        end)
                    end
                    -- Slow
                    if not UnitHasBuffBJ(u, FourCC('Bchd')) then
                        DummyCast(
                            owner,
                            x, y,
                            SLOW_SPELL,
                            SLOW_ORDER,
                            1,
                            CastType.TARGET,
                            u
                        )
                    end
                end
            end)
            BlzSetSpecialEffectPosition(eff, x, y, BlzGetLocalSpecialEffectZ(eff))
        end,
I think there is also an error in the first half, or it's not clear what you're trying to do with ordering the rock to 'smart'. The way it currently proceeds is as follows:
  • Enum units within AREA of (x,y)
  • If the enum unit (u) is a rock then do nothing, otherwise...
    • If a 50% chance occurs (chance computed for each value of u), then also enum all units within 4*AREA of (x,y)
      • If the interior enum unit (u2) is not a rock, then order the rock to smart to u2
      • This repeats for all u2s picked, so the rock will only ever start the smart order on the last u2 of the group that passes the 50% chance
    • If the unit does not have the debuff, apply it
Each time a u passes the 50% chance it then does the interior enum where the rock is ordered to smart every non-rock unit within 4*AREA of its current position, but since they're all sequential all but the final order gets overwritten. Then, for any other u that passes the chance it will overwrite that 'last' order with another interior enum order chain.

Need more context about what you're trying to do.
The rock follows a nearby unit, but not the same to take more advantage of the ability.
 
Level 39
Joined
Feb 27, 2007
Messages
5,016
I replied but the database backup didn't catch it so my response was lost the wind. Basically it said:

That's not currently what happens with the rock. What "not the same"-ness are you trying to do? Not same target twice in a row, no two rocks with the same target, not the same target twice ever, change to new target if initial is too far away, etc.?
 
Last edited:
Level 24
Joined
Jun 26, 2020
Messages
1,852
I replied but the database backup didn't catch it so my response was lost the wind. Basically it said:

That's not what happens with the rock. What "not the same"-ness are you trying to do? Not same target twice in a row, no two rocks with the same target, not the same target twice ever, change to new target if initial is too far away, etc.?
Now is when I'm realizing that I should make it only target 1 unit.
We also have no idea how ForUnitsInRange works, it's not a blizzard native at all.
For some reason I suspect that's the issue.
Is a function that I created:

Lua:
local ENUM_GROUP = CreateGroup()
local LOCUST_ID = FourCC('Aloc')

local callbacks = {} ---@type fun(u: unit)[]
local filter = Filter(function () callbacks[#callbacks](GetFilterUnit())  end)

---@param x number
---@param y number
---@param radius number
---@param callback fun(u:unit)
---@param includeLocust? boolean
function ForUnitsInRange(x, y, radius, callback, includeLocust)
    table.insert(callbacks, function (u)
        if not includeLocust or GetUnitAbilityLevel(u, LOCUST_ID) > 0 then
            callback(u)
        end
    end)
    GroupEnumUnitsInRange(ENUM_GROUP, x, y, radius, filter)
    table.remove(callbacks)
end
 
Status
Not open for further replies.
Top