- Joined
- May 4, 2007
- Messages
- 2,260
HI guys, i was making a map to compete with ciebron, but unfortunatly i found a bug with no solution (or so I think).
The problem is that I add an ability to an unit, but then i can not remove it.
This code uses vJASS and ABC (i know it is old, but is is easy as well) and so i really would like to know what it wrong =S
The code looks complex but it is very simple actually.
It is a channeling spell. When i start casting it i use 3 timers and a unit group(among other things).
1 timer is to create thunders, 2 timer is to pick allied units around the caster according to a condition and then it adds them to buffer group, finally the 3 timer ... well, it should kill unit is group buffer, but that does not happen !! whyy !!!
When the spell ends, i kill all timers and remove all units from group buffer, I also destroy the group. At least this part works perfectly...
Can some1 please help me out here ?? Why isn't the 3rd timer working ?? Is the problem on the timer ??
The problem is that I add an ability to an unit, but then i can not remove it.
This code uses vJASS and ABC (i know it is old, but is is easy as well) and so i really would like to know what it wrong =S
JASS:
struct Mystruct
unit caster = GetTriggerUnit()
timer repeator = CreateTimer()
timer picker = CreateTimer()
timer remover = CreateTimer()
group buffer = CreateGroup()
trigger end = CreateTrigger()
triggeraction endAction
triggercondition endCondition
endstruct
//==========================================================================
function End_Conds takes nothing returns boolean
return GetSpellAbilityId() == 'A000'
endfunction
//==========================================================================
function End_Acts takes nothing returns nothing
//catches the trigger and runs this function
local Mystruct data = GetTriggerStructB(GetTriggeringTrigger())
local unit targ
//Cleans all units from data.buffer and destroys it
loop
set targ = FirstOfGroup(data.buffer)
exitwhen(targ == null)
call UnitRemoveAbility(targ, 'A00A')
call UnitRemoveAbility(targ, 'A00B')
call UnitRemoveAbility(targ, 'A003')
call GroupRemoveUnit(data.buffer, targ)
endloop
call DestroyGroup(data.buffer)
//removes the created trigger in the Code_acts function
call TriggerRemoveCondition(data.end,data.endCondition)
call TriggerRemoveAction(data.end,data.endAction)
call DestroyTrigger(data.end)
call ClearTriggerStructB(data.end)
//stops the repeator timer and ends the spell once and for all
call PauseTimer(data.repeator)
call DestroyTimer(data.repeator)
call PauseTimer(data.picker)
call DestroyTimer(data.picker)
call PauseTimer(data.remover)
call DestroyTimer(data.remover)
call ClearTimerStructA(data.repeator)
call ClearTimerStructB(data.picker)
call ClearTimerStructC(data.remover)
endfunction
//==========================================================================
function Remover takes nothing returns nothing
local Mystruct data = GetTimerStructC(GetExpiredTimer())
local unit targ
//THE BUG IS HERE !! THE UNITS DO NOT DIE !! HELP PLEASE !! WHYYYYY!!!
//here I check all units in data.buffer to see if they are inside range
loop
set targ = FirstOfGroup(data.buffer)
exitwhen(targ == null)
// call BJDebugMsg("loop")
call KillUnit(targ)
// if (IsUnitInRange(data.caster, targ, 900) == false) then
// call UnitRemoveAbility(targ, 'A003')
// call UnitRemoveAbility(targ, 'A00A')
// call UnitRemoveAbility(targ, 'A00B')
// call GroupRemoveUnit(data.buffer, targ)
// endif
endloop
endfunction
//==========================================================================
function Picker takes nothing returns nothing
local Mystruct data = GetTimerStructB(GetExpiredTimer())
local group g = CreateGroup()
local unit targ
local player p = GetOwningPlayer(data.caster)
local integer level = GetUnitAbilityLevel(data.caster, 'A000')
//here i select friendly units, give them new ability, and add them to data.buffer
call GroupEnumUnitsInRange( g, GetUnitX( data.caster ), GetUnitY( data.caster ), 900, Filter(null))
loop
set targ = FirstOfGroup( g )
exitwhen (targ == null)
if IsUnitAlly(targ, p) then
if IsUnitType(targ, UNIT_TYPE_HERO) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0) and ((targ == data.caster)== false) then
//spell book for hero atatckers
call UnitAddAbility(targ, 'A003') //add book
call SetUnitAbilityLevel(targ, 'A003', level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,'A001', level)//sets lv of Ability to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), 'A003', false )
call GroupAddUnit(data.buffer, targ)
elseif IsUnitType(targ, UNIT_TYPE_MELEE_ATTACKER) and (IsUnitType(targ, UNIT_TYPE_HERO) == false) and (IsUnitType(targ, UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0) then
//spell book for melee atatcker units
call UnitAddAbility(targ, 'A00B') //add book
call SetUnitAbilityLevel(targ, 'A00B', level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,'A005', level)//sets lv of Melee to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), 'A00B', false )
call GroupAddUnit(data.buffer, targ)
elseif IsUnitType(targ, UNIT_TYPE_RANGED_ATTACKER) and (IsUnitType(targ, UNIT_TYPE_HERO) == false) and (IsUnitType(targ, UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0) then
//spell book for ranged atatckers
call UnitAddAbility(targ, 'A00A') //add book
call SetUnitAbilityLevel(targ, 'A00A', level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,'A006', level)//sets lv of ranged to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), 'A00A', false )
call GroupAddUnit(data.buffer, targ)
endif
endif
call GroupRemoveUnit(g,targ)
endloop
call DestroyGroup(g)
set g = null
endfunction
//==========================================================================
function LightningInvocation takes nothing returns nothing
//catches the expired timer and runs this function
local Mystruct data = GetTimerStructA(GetExpiredTimer())
//This uses polar projection. Formula: Center + r * trigfunction(angle teta);
//where Center is the center coordinate X or Y
//r is the distance (in the case rabdom between 300 and 600)
//trigfunction is Sin if using Y and Cos if using X
//angle teta is the angle formed between r and the axis (in this case random, can be all circle)
local real randomX
local real randomY
local unit dummy
local integer exit = GetUnitAbilityLevel(data.caster, 'A000')
local integer counter = 0
loop
exitwhen(counter >= exit)
set randomX = GetUnitX(data.caster) + GetRandomReal(100.00, 900.00) * Cos(GetRandomReal(0.0, 360.0) * bj_DEGTORAD)
set randomY = GetUnitY(data.caster) + GetRandomReal(100.00, 900.00) * Sin(GetRandomReal(0.0, 360.0) * bj_DEGTORAD)
set dummy = CreateUnit(GetOwningPlayer(data.caster), 'h000', randomX, randomY, 0)
call UnitAddAbility(dummy, 'A002')
call IssueImmediateOrder( dummy, "thunderclap" )
call UnitApplyTimedLife(dummy, 'BTLF', 2.00)
set counter = counter + 1
endloop
set dummy = null
endfunction
//==========================================================================
function LightningInvocation_Conds takes nothing returns boolean
return GetSpellAbilityId() == 'A000'
endfunction
//==========================================================================
function LightningInvocation_Acts takes nothing returns nothing
local Mystruct data = Mystruct.create()
//starts the effect of the spell, thunders start falling from sky
call SetTimerStructA(data.repeator, data)
call TimerStart(data.repeator, 3 / GetUnitAbilityLevel(data.caster, 'A000'), true, function LightningInvocation)
//creates the timer that picks units arround the hero to give them abilities
call SetTimerStructB(data.picker, data)
call TimerStart(data.picker, 1, true, function Picker)
//This timer checks every 0.2 secs if a unit is outside range, to remove the buffs
call SetTimerStructC(data.remover, data)
call TimerStart(data.remover, 0.2, true, function Remover)
//creates the trigger that will end the spell when the hero stops channeling
call SetTriggerStructB(data.end, data)
call TriggerRegisterAnyUnitEventBJ( data.end, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
set data.endCondition = TriggerAddCondition( data.end, Condition( function End_Conds ) )
set data.endAction = TriggerAddAction( data.end, function End_Acts )
endfunction
//===========================================================================
function InitTrig_Lightning_Invocation takes nothing returns nothing
set gg_trg_Lightning_Invocation = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Lightning_Invocation, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
call TriggerAddCondition( gg_trg_Lightning_Invocation, Condition( function LightningInvocation_Conds ) )
call TriggerAddAction( gg_trg_Lightning_Invocation, function LightningInvocation_Acts )
endfunction
The code looks complex but it is very simple actually.
It is a channeling spell. When i start casting it i use 3 timers and a unit group(among other things).
1 timer is to create thunders, 2 timer is to pick allied units around the caster according to a condition and then it adds them to buffer group, finally the 3 timer ... well, it should kill unit is group buffer, but that does not happen !! whyy !!!
When the spell ends, i kill all timers and remove all units from group buffer, I also destroy the group. At least this part works perfectly...
Can some1 please help me out here ?? Why isn't the 3rd timer working ?? Is the problem on the timer ??