• 🏆 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 spell help (Thunderclap ish)

Level 4
Joined
Jun 6, 2015
Messages
77
So, I am trying this LUA stuff. The spell is simple, it deals damage to enemies around the caster. It deals most damage to those within 150 range, less damage to those between 150 and 225 range and the least damage to those between 225 and 300. Including some special effects to spice it up.

The spell works perfectly. But it only works 3-5 times. After the spell has been used 3-5 times, if the unit uses it again, nothing happens. I know this way of doing it is probably very stupid etc and that's fine (I'm just learning). I'm just very curious on why the spell only works 3-5 times.

Any gifted souls who can point out why, and possibly explain? The spell is based on Thunder Clap. I just also tried to use the Berserk spell.


Lua:
-- Function to check the distance between two points
local function DistanceBetweenPoints(x1, y1, x2, y2)
    local dx = x2 - x1
    local dy = y2 - y1
    return math.sqrt(dx * dx + dy * dy)
end

-- Function to destroy effects after a delay
local function DestroyEffects(effects, timer)
    for _, effect in ipairs(effects) do
        DestroyEffect(effect)
    end
    DestroyTimer(timer)  -- Destroy the timer to prevent leaks
end


-- Function to deal damage to enemies based on range
local function DealDamageInRange(x, y, castingUnit, maxRange)
    local group = CreateGroup()
    GroupEnumUnitsInRange(group, x, y, maxRange, nil)
    while true do
        local unit = FirstOfGroup(group)
        if not unit then break end
        local distance = DistanceBetweenPoints(x, y, GetUnitX(unit), GetUnitY(unit))
        local damage = 0
        if distance <= 150 then
            damage = 300 -- Most damage
        elseif distance <= 225 then
            damage = 225 -- Medium damage
        else
            damage = 150 -- Least damage
        end
        if GetOwningPlayer(unit) ~= GetOwningPlayer(castingUnit) and IsPlayerEnemy(GetOwningPlayer(castingUnit), GetOwningPlayer(unit)) then
            UnitDamageTarget(castingUnit, unit, damage, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
        end
        GroupRemoveUnit(group, unit)
    end
    DestroyGroup(group)
end


function SpellCastTrigger()
    local event = CreateTrigger()
    TriggerRegisterAnyUnitEventBJ(event, EVENT_PLAYER_UNIT_SPELL_CAST)
    TriggerAddAction(event, function()
        local castingUnit = GetTriggerUnit()
        local spellId = GetSpellAbilityId()
        if spellId == FourCC('A001') then
            local x = GetUnitX(castingUnit) -- X coordinate of the caster
            local y = GetUnitY(castingUnit) -- Y coordinate of the caster
            local maxRange = 300
            local intervals = {150, 225, 300} -- Array of ranges
            local angleInterval = 30 -- Interval in degrees to place effects
            local effects = {} -- Store effect handles
            -- Loop to create effects around the caster for each range
            for _, range in ipairs(intervals) do
                for angle = 0, 360, angleInterval do
                    local radian = angle * (math.pi / 180) -- Convert angle to radians
                    local effectX = x + range * math.cos(radian) -- X coordinate for effect
                    local effectY = y + range * math.sin(radian) -- Y coordinate for effect
                    -- Create the blink effect and store its handle
                    local effect = AddSpecialEffect("Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl", effectX, effectY)
                    table.insert(effects, effect)
                end
            end
        
            -- Call the function to deal damage
            DealDamageInRange(x, y, castingUnit, maxRange)
            -- Set a timer to destroy the effects after 2 seconds
            local timer = CreateTimer()
            TimerStart(timer, 2.0, false, function() DestroyEffects(effects, timer) end)
        end
    end)
end

SpellCastTrigger()
 
Level 4
Joined
Jun 6, 2015
Messages
77
Ah, really. Thanks mate. Don't mind the code in general btw. I am sure this could have been done very differently. I'm currently studying artificial intelligence and we have been learning mainly Python and some C/C++ for half a year. Thought I could start having some fun with Lua on the side in wc3.
I am using chatGPT in the learning process although it usually provides code that does not work at all without modifications.

Added a timer pause:

Lua:
-- Function to destroy effects after a delay
local function DestroyEffects(effects, timer)
    for _, effect in ipairs(effects) do
        DestroyEffect(effect)
    end
    PauseTimer(timer)    -- Pause the timer before destroying it (To prevent a specific bug)
    DestroyTimer(timer)  -- Destroy the timer to prevent leaks
end

...
...
...

-- Set a timer to destroy the effects after 2 seconds
            local timer = CreateTimer()
            TimerStart(timer, 2.0, false, function() DestroyEffects(effects, timer) end)
 
Top