• 🏆 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!

[vJASS] Using a cooldown for "on hit" abilities

Status
Not open for further replies.
Level 4
Joined
Sep 25, 2005
Messages
71
FIXED: Including the cooldown/add ability inside the loop of the execution function worked:

JASS:
globals
    timer C2ConeCDTimer = CreateTimer()
    integer activeC2ConeCD = 0
    Chance2ConeData array C2ConeCDArray
endglobals

struct Chance2ConeData
    real cooldown
    unit attacker
endstruct

function ConeCooldown takes nothing returns nothing
    local Chance2ConeData localC2Cone
    local integer i = 0
    
    loop
        exitwhen i >= activeC2ConeCD
        
        set localC2Cone = C2ConeCDArray[i]
        set localC2Cone.cooldown = localC2Cone.cooldown - .01       
        if localC2Cone.cooldown == 0 then
            call UnitAddAbility(localC2Cone.attacker, 'A00D')
            set activeC2ConeCD = activeC2ConeCD - 1
            set C2ConeCDArray[i] = C2ConeCDArray[activeC2ConeCD]
        
            call localC2Cone.destroy()
        endif
        set i = i + 1
    endloop
    
    if activeC2ConeCD == 0 then
        call PauseTimer(C2ConeCDTimer)
    endif
    
endfunction

function checkChance2Cone takes nothing returns boolean
    local unit caster
    local real x = GetUnitX(GetTriggerUnit())
    local real y = GetUnitY(GetTriggerUnit())
    local Chance2ConeData localC2Cone = Chance2ConeData.create()
    if IsUnitAlly(GetAttacker(), GetOwningPlayer(GetTriggerUnit())) == false /*
    */and GetUnitAbilityLevel(GetAttacker(), 'A00D') >= 1 /*
    */and ValidGroundTarget(GetTriggerUnit(), GetAttacker()) == true then
        set caster = CreateUnit(GetOwningPlayer(GetAttacker()), 'o006', GetUnitX(GetAttacker()), GetUnitY(GetAttacker()), GetUnitFacing(GetAttacker()))
        call IssuePointOrder(caster, "flamestrike", x, y)
        call UnitApplyTimedLife(caster, 'B001', 2.)
        call UnitRemoveAbility(GetAttacker(), 'A00D')
        set localC2Cone.cooldown = 3.
        set localC2Cone.attacker = GetAttacker()
        set C2ConeCDArray[activeC2ConeCD]=localC2Cone
        if activeC2ConeCD <= 0 then
            call TimerStart(C2ConeCDTimer, .01, true, function ConeCooldown)
        endif
        set activeC2ConeCD = activeC2ConeCD + 1
    endif
    set caster = null
    return false
endfunction

function InitTrig_Chance2Cone takes nothing returns nothing
    local trigger localTrigVar = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( localTrigVar, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( localTrigVar, Condition( function checkChance2Cone ) )
    set localTrigVar = null
endfunction

I found a resolution for an ability I was trying to make, which would cause an ability on attack. I know the popular route is to go by using a "chance on hit," but I'd rather simply set the abilities to a set cooldown.

I'm having a problem with instancing - again. In this case, it's possible for units to use the first hit - every time. The cooldown goes on. However, that's where things get wonky: for some reason, if one unit finishes cooldown first, the others get their cooldowns skipped. This results in - until all units are finished, only one will be able to use the ability.

The behavior I'm going for is if -any- unit, or any number of units hit a valid target while having the ability, that unit will lose the ability, and regain it in five.

Should the if cooldown is over be in the loop to solve this?

JASS:
globals
    timer C2ConeCDTimer = CreateTimer()
    integer activeC2ConeCD = 0
    Chance2ConeData array C2ConeCDArray
endglobals

struct Chance2ConeData
    integer cooldown
    unit attacker
endstruct

function ConeCooldown takes nothing returns nothing
    local Chance2ConeData localC2Cone
    local integer i = 0
    
    loop
        exitwhen i >= activeC2ConeCD
        
        set localC2Cone = C2ConeCDArray[i]
        set localC2Cone.cooldown = localC2Cone.cooldown - 1
        set i = i + 1
    endloop
    
    if localC2Cone.cooldown == 0 then
        call UnitAddAbility(localC2Cone.attacker, 'A00D')
        set activeC2ConeCD = activeC2ConeCD - 1
        set C2ConeCDArray[i] = C2ConeCDArray[activeC2ConeCD]
        
        call localC2Cone.destroy()
    endif
    
    if activeC2ConeCD == 0 then
        call PauseTimer(C2ConeCDTimer)
    endif
    
endfunction

function checkChance2Cone takes nothing returns boolean
    local unit caster
    local real x = GetUnitX(GetTriggerUnit())
    local real y = GetUnitY(GetTriggerUnit())
    local Chance2ConeData localC2Cone = Chance2ConeData.create()
    if IsUnitAlly(GetAttacker(), GetOwningPlayer(GetTriggerUnit())) == false /*
    */and GetUnitAbilityLevel(GetAttacker(), 'A00D') >= 1 /*
    */and ValidGroundTarget(GetTriggerUnit(), GetAttacker()) == true then
        set caster = CreateUnit(GetOwningPlayer(GetAttacker()), 'o006', GetUnitX(GetAttacker()), GetUnitY(GetAttacker()), GetUnitFacing(GetAttacker()))
        call IssuePointOrder(caster, "flamestrike", x, y)
        call UnitApplyTimedLife(caster, 'B001', 2.)
        call UnitRemoveAbility(GetAttacker(), 'A00D')
        set localC2Cone.cooldown = 5
        set localC2Cone.attacker = GetAttacker()
        set C2ConeCDArray[activeC2ConeCD]=localC2Cone
        if activeC2ConeCD <= 0 then
            call TimerStart(C2ConeCDTimer, 1, true, function ConeCooldown)
        endif
        set activeC2ConeCD = activeC2ConeCD + 1
    endif
    set caster = null
    return false
endfunction

function InitTrig_Chance2Cone takes nothing returns nothing
    local trigger localTrigVar = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( localTrigVar, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( localTrigVar, Condition( function checkChance2Cone ) )
    set localTrigVar = null
endfunction
 
Status
Not open for further replies.
Top