| 08-20-2007, 11:36 PM | #1 |
I'm working on a spell (My first using Handles). This one is meant to have 5 rotating wisps of light, which rotate outwards like a nova, and then back in. All of this works, except for the actual effects. Allied units inside the area should have a divine shield effect attached to them and become invulnerable. The problem is that they arent becoming vulnerable when they leave the radius, or when the spell ends, and they arent getting the divine shield effect. I believe there could be something wrong with lastgroup. JASS:function Spiral_Filter takes nothing returns boolean return GetWidgetLife(GetFilterUnit()) > 0 and IsUnitAlly(GetFilterUnit(),GetOwningPlayer(bj_ghoul[111])) endfunction function Spiral_Move takes nothing returns nothing local timer t = GetExpiredTimer() local unit u = GetHandleUnit(t,"TriggerUnit") local unit u2 = GetHandleUnit(t,"DummyUnit") local real Distance = (GetHandleReal(t,"Distance")) local real x = GetUnitX(u) local real y = GetUnitY(u) local real Dur = (GetHandleReal(t,"Dur") + 0.04) local real Angle = (GetHandleReal(t,"Angle") + 7.1) local real x2 local real y2 local unit u3 local group lastgroup = CreateGroup() local group currentgroup = CreateGroup() local group currentgroup2 = CreateGroup() set bj_ghoul[111] = u //================================== //=====PART THAT ISNT WORKING======= //================================== call GroupAddGroup(GetHandleGroup(t,"lastgroup"),lastgroup) call GroupEnumUnitsInRange(currentgroup,x,y,Distance,Filter(function Spiral_Filter)) call SetHandleHandle(t,"lastgroup",currentgroup) call GroupAddGroup(currentgroup,currentgroup2) loop set u3 = FirstOfGroup(currentgroup) exitwhen u3 == null if (IsUnitInGroup(u3,lastgroup) == false) then if GetHandleEffect(FirstOfGroup(currentgroup),"SpiralEffect") == null then call SetHandleHandle(FirstOfGroup(currentgroup),"SpiralEffect",AddSpecialEffectTarget("Abilities\\Spells\\Human\\DivineShield\\DivineShieldTarget.mdl",u3,"origin")) endif call SetUnitInvulnerable(u3,true) call GroupRemoveUnit(currentgroup,u3) endif endloop loop set u3 = FirstOfGroup(lastgroup) exitwhen u3 == null if (IsUnitInGroup(u3,currentgroup2) == false) then call DestroyEffect(GetHandleEffect(FirstOfGroup(lastgroup),"SpiralEffect")) call SetUnitInvulnerable(u3,false) call GroupRemoveUnit(lastgroup,u3) endif endloop call DestroyGroup(currentgroup) call DestroyGroup(currentgroup2) call DestroyGroup(lastgroup) set u3 = null //================================== //================================== //================================== if Distance < 400 and Dur < 4.00 then set Distance = Distance + 4.571 endif if Dur > 4.00 then set Distance = Distance - 4.571 endif set x2 = x + Distance * Cos(Angle * bj_DEGTORAD) set y2 = y + Distance * Sin(Angle * bj_DEGTORAD) call SetUnitX(u2,x2) call SetUnitY(u2,y2) call SetHandleReal(t,"Angle",Angle) call SetHandleReal(t,"Distance",Distance) call SetHandleReal(t,"Dur",Dur) if Dur >= 10.00 then call PauseTimer(t) call DestroyTimer(t) call KillUnit(u2) call FlushHandleLocals(t) endif set t = null set u = null set u2 = null endfunction function Spiral_Actions takes nothing returns nothing local timer array t local unit u = GetTriggerUnit() local unit array u2 local real x = GetUnitX(u) local real y = GetUnitY(u) local integer i = 0 local player p = GetOwningPlayer(u) local integer i2 = 5 local real dur = 0.0 local real array anglegetter loop set t[i] = CreateTimer() call SetHandleReal(t[i],"Dur",dur) call SetHandleInt(t[i],"Level",GetUnitAbilityLevel(u,'A000')) set anglegetter[i] = (360 / i2) * i call SetHandleReal(t[i],"Angle",anglegetter[i]) call SetHandleReal(t[i],"Distance",0) call SetHandleHandle(t[i],"TriggerUnit",u) call SetHandleHandle(t[i],"DummyUnit",(CreateUnit(p,'h000',x,y,GetRandomReal(1,360)))) call TimerStart(t[i],0.04,true,function Spiral_Move) set t[i] = null set u2[i] = null set i = i + 1 exitwhen i >= i2 endloop set u = null set p = null endfunction function SpiralConds takes nothing returns boolean return GetSpellAbilityId() == 'A000' endfunction function InitTrig_HolySpiral takes nothing returns nothing local trigger t = gg_trg_HolySpiral set t = CreateTrigger() call TriggerAddAction(t,function Spiral_Actions) call TriggerAddCondition(t,Condition(function SpiralConds)) call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT) set t = null endfunction |
| 08-21-2007, 12:47 AM | #2 |
i dont know a lotta jass but i didnt see any leaves area stuff so that could be the problem ;P |
| 08-21-2007, 01:24 AM | #3 |
Instead of using leaving area stuff, I'm using 2 unit groups. The units which were within range the last time, and this time. First i check if any units are in now and werent before. That part works. Second, I check if there are any units which were in before and arent now. That doesnt. |
| 08-21-2007, 02:23 AM | #4 |
JASS:call GroupAddGroup(GetHandleGroup(t,"lastgroup"),lastgroup) call GroupEnumUnitsInRange(currentgroup,x,y,Distance,Filter(function Spiral_Filter)) call SetHandle*Handle*(t,"lastgroup",currentgroup) call GroupAddGroup(currentgroup,currentgroup2) loop set u3 = FirstOfGroup(currentgroup) exitwhen u3 == null if (IsUnitInGroup(u3,lastgroup) == false) then if GetHandleEffect(FirstOfGroup(currentgroup),"SpiralEffect") == null then call SetHandle*Handle**(FirstOfGroup(currentgroup)*,"SpiralEffect",AddSpecialEffectTarget("Abilities\\Spells\\Human\\DivineShield\\DivineShieldTarget.mdl",u3,"origin")) endif call SetUnitInvulnerable(u3,true) call GroupRemoveUnit(currentgroup,u3) endif endloop loop set u3 = FirstOfGroup(lastgroup) exitwhen u3 == null if (IsUnitInGroup(u3,currentgroup2) == false) then call DestroyEffect(GetHandleEffect(FirstOfGroup(lastgroup),"SpiralEffect")) call SetUnitInvulnerable(u3,false) call GroupRemoveUnit(lastgroup,u3) endif endloop call DestroyGroup(currentgroup) call DestroyGroup(currentgroup2) call DestroyGroup(lastgroup) set u3 = null *Don't mock my limited programming knowledge.* Possible errors are caught between "*" Is the second "handle" required? The "(FirstofGroup(currentgroup)" might not be working because there isn't a second ")" to cover the not-covered "(". Possibly small errors like this with the others? Perhaps coding errors or logical errors? Am I right? ![]() |
| 08-21-2007, 02:34 AM | #5 |
It all checks out in JassCraft, so I know theres no simple errors. SetHandleHandle means your creating a handle which is a handle. Another example is SetHandleInteger- makes a handle which is an integer. |
| 08-21-2007, 12:31 PM | #6 |
Use. CSCache. This is all wrong: JASS:function InitTrig_HolySpiral takes nothing returns nothing local trigger t = gg_trg_HolySpiral set t = CreateTrigger() call TriggerAddAction(t,function Spiral_Actions) call TriggerAddCondition(t,Condition(function SpiralConds)) call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT) set t = null endfunction JASS:function InitTrig_HolySpiral takes nothing returns nothing call TriggerAddAction(gg_trg_HolySpiral,function Spiral_Actions) call TriggerAddCondition(gg_trg_HolySpiral,Condition(function SpiralConds)) call TriggerRegisterAnyUnitEventBJ(gg_trg_HolySpiral,EVENT_PLAYER_UNIT_SPELL_EFFECT) endfunction If you try to get a real/int that hasn't actually been stored (Using [ljass]SetHandleReal/Int[/ljas] it will return 0 anyway. It's pointless to store it as 0.00 when you know it hasn't already got a value as you've done: JASS:local real dur = 0.0 //... call SetHandleReal(t[i],"Dur",dur) //... call SetHandleReal(t[i],"Distance",0) set anglegetter[i] = (360 / i2) * i is a problem because the loop runs 6 times, but you're only using 5 increments for the angles (initializing i as 1 will fix this). When you do call SetHandleInt(t[i],"Level",GetUnitAbilityLevel(u,'A000')), you should store the level to a variable outside of the loop such that it doesn't need to get the level multiple times: JASS:local integer level = GetUnitAbilityLevel(u, 'A000') //... call SetHandleInt(t[i],"Level",level) I personally dislike starting at 0 when looping through things; I find it easier to start at 1 and then make my exitwhens at the top of the loop so that I can easily divide by the number of times the loop will run and stuff. Thus, I'd do this: JASS:local integer i = 0 //... local integer i2 = 5 //It will create 5 units; you were creating 6 //... loop set i = i+1 exitwhen i > i2 set t[i] = CreateTimer() call SetHandleReal(t[i],"Dur",dur) call SetHandleInt(t[i],"Level",GetUnitAbilityLevel(u,'A000')) set anglegetter[i] = (360 / i2) * i call SetHandleReal(t[i],"Angle",anglegetter[i]) call SetHandleReal(t[i],"Distance",0) call SetHandleHandle(t[i],"TriggerUnit",u) call SetHandleHandle(t[i],"DummyUnit",(CreateUnit(p,'h000',x,y,GetRandomReal(1,360)))) call TimerStart(t[i],0.04,true,function Spiral_Move) set t[i] = null set u2[i] = null endloop The way you do everything with arrays is both pointless and unnecessary. You can simply remove the arrays: JASS:loop set i = i+1 exitwhen i > i2 set t = CreateTimer() call SetHandleInt(t,"Level",level) call SetHandleReal(t,"Angle",(360 / i2) * i) //Note how this is inlined call SetHandleHandle(t,"TriggerUnit",u) call SetHandleHandle(t,"DummyUnit",(CreateUnit(p,'h000',x,y,GetRandomReal(1,360)))) call TimerStart(t,0.04,true,function Spiral_Move) endloop //I also removed the u2 array, as you never used it set t = null Finally, everything can be attached to 1 timer instead of using 5 different timers. Here's that function done correctly :D JASS:function Spiral_Actions takes nothing returns nothing local timer t = CreateTimer() local unit u = GetTriggerUnit() local real x = GetUnitX(u) local real y = GetUnitY(u) local integer i = 0 local player p = GetOwningPlayer(u) local integer i2 = 5 local integer level = GetUnitAbilityLevel(u, 'A000') loop set i = i+1 exitwhen i > i2 call SetHandleReal(t,"Angle "+I2S(i),(360 / i2) * i) call SetHandleHandle(t,"DummyUnit "+I2S(i),(CreateUnit(p,'h000',x,y,GetRandomReal(0,360)))) endloop call SetHandleInt(t,"Level",level) call SetHandleHandle(t,"TriggerUnit",u) call TimerStart(t,0.04,true,function Spiral_Move) set t = null set u = null set p = null endfunction As for the callback function, now you're going to have to modify everything to work with arrays... but let's assume that you're not going to do it for 5 units at once in the callback first. Here's how you'd go about fixin' it up: Pointless: JASS:local group lastgroup = CreateGroup() //... call GroupAddGroup(GetHandleGroup(t,"lastgroup"),lastgroup) You're attaching a special effect to a unit and then attaching it with handlevars. Bad idea. The best solution is to make an ability based off of the "life regeneration aura" ability that does nothing but add the Divine Shield SFX to the unit that has the ability. Then you'll simply remove it when the effect needs to go away: JASS:if GetHandleEffect(FirstOfGroup(currentgroup),"SpiralEffect") == null then call SetHandleHandle(FirstOfGroup(currentgroup),"SpiralEffect",AddSpecialEffectTarget("Abilities\\Spells\\Human\\DivineShield\\DivineShieldTarget.mdl",u3,"origin")) endif //Becomes this: if GetUnitAbilityLevel(u3, 'A001') == 0 then call UnitAddAbility(u3, 'A001') endif //And change this: call DestroyEffect(GetHandleEffect(FirstOfGroup(lastgroup),"SpiralEffect")) //To this: call UnitRemoveAbility(u3, 'A001') All of this: JASS:loop set u3 = FirstOfGroup(currentgroup) exitwhen u3 == null if (IsUnitInGroup(u3,lastgroup) == false) then if GetUnitAbilityLevel(u3, 'A001') == 0 then call UnitAddAbility(u3, 'A001') endif call SetUnitInvulnerable(u3,true) call GroupRemoveUnit(currentgroup,u3) endif endloop loop set u3 = FirstOfGroup(lastgroup) exitwhen u3 == null if (IsUnitInGroup(u3,currentgroup2) == false) then call UnitRemoveAbility(u3, 'A001') call SetUnitInvulnerable(u3,false) call GroupRemoveUnit(lastgroup,u3) endif endloop JASS:loop set u3 = FirstOfGroup(lastgroup) exitwhen u3 == null if not(IsUnitInGroup(u3,currentgroup2)) then //The "not" operator is useful call UnitRemoveAbility(u3, 'A001') //'A001' being the rawcode of the new spell call SetUnitInvulnerable(u3,false) endif call GroupRemoveUnit(currentgroup,u3) //Removing it from the other group so we don't have to check to see if the unit isn't in this one in the other loop call GroupRemoveUnit(lastgroup,u3) //Taking it out of the If/Then/Else prevents a possible thread crash with an infinite loop endloop //I think that was your problem loop set u3 = FirstOfGroup(currentgroup) exitwhen u3 == null if GetUnitAbilityLevel(u3, 'A001') == 0 then call UnitAddAbility(u3, 'A001') call SetUnitInvulnerable(u3,true) //You don't need to make it invulnerable every time if it already is endif call GroupRemoveUnit(currentgroup,u3) //Again, fixing the infinite loop problems endloop This is a mighty severe problem: JASS:call SetHandleHandle(t,"lastgroup",currentgroup) //... call DestroyGroup(currentgroup) set u3 = null is redundant because you're exiting the loop when the variable is null. JASS:if Distance < 400 and Dur < 4.00 then set Distance = Distance + 4.571 endif if Dur > 4.00 then set Distance = Distance - 4.571 endif JASS:if Distance < 400 and Dur < 4.00 then set Distance = Distance + 4.571 elseif Dur > 4.00 then set Distance = Distance - 4.571 endif JASS:call SetHandleReal(t,"Angle",Angle) call SetHandleReal(t,"Distance",Distance) call SetHandleReal(t,"Dur",Dur) if Dur >= 10.00 then call PauseTimer(t) call DestroyTimer(t) call KillUnit(u2) call FlushHandleLocals(t) endif JASS:if Dur >= 10.00 then call KillUnit(u2) call PauseTimer(t) call FlushHandleLocals(t) //You must do this before destroying the timer, else it's flushing a null category call DestroyTimer(t) else call SetHandleReal(t,"Angle",Angle) call SetHandleReal(t,"Distance",Distance) call SetHandleReal(t,"Dur",Dur) endif So, all put together it would be this: JASS:function Spiral_Move takes nothing returns nothing local timer t = GetExpiredTimer() local unit u = GetHandleUnit(t,"TriggerUnit") local unit u2 = GetHandleUnit(t,"DummyUnit") local real Distance = (GetHandleReal(t,"Distance")) local real x = GetUnitX(u) local real y = GetUnitY(u) local real Dur = (GetHandleReal(t,"Dur") + 0.04) local real Angle = (GetHandleReal(t,"Angle") + 7.1) local real x2 local real y2 local unit u3 local group lastgroup = local group lastgroup = GetHandleGroup(t,"lastgroup") local group currentgroup = CreateGroup() local group currentgroup2 = CreateGroup() set bj_ghoul[111] = u call GroupEnumUnitsInRange(currentgroup,x,y,Distance,Filter(function Spiral_Filter)) call SetHandleHandle(t,"lastgroup",currentgroup2) call GroupAddGroup(currentgroup,currentgroup2) loop set u3 = FirstOfGroup(lastgroup) exitwhen u3 == null if not(IsUnitInGroup(u3,currentgroup2)) then call UnitRemoveAbility(u3, 'A001') //'A001' being the rawcode of the new spell call SetUnitInvulnerable(u3,false) endif call GroupRemoveUnit(currentgroup,u3) call GroupRemoveUnit(lastgroup,u3) endloop loop set u3 = FirstOfGroup(currentgroup) exitwhen u3 == null if GetUnitAbilityLevel(u3, 'A001') == 0 then call UnitAddAbility(u3, 'A001') call SetUnitInvulnerable(u3,true) endif call GroupRemoveUnit(currentgroup,u3) endloop call DestroyGroup(currentgroup) call DestroyGroup(lastgroup) if Distance < 400 and Dur < 4.00 then set Distance = Distance + 4.571 elseif Dur > 4.00 then set Distance = Distance - 4.571 endif set x2 = x + Distance * Cos(Angle * bj_DEGTORAD) set y2 = y + Distance * Sin(Angle * bj_DEGTORAD) call SetUnitX(u2,x2) call SetUnitY(u2,y2) if Dur >= 10.00 then call KillUnit(u2) call PauseTimer(t) call FlushHandleLocals(t) call DestroyTimer(t) else call SetHandleReal(t,"Angle",Angle) call SetHandleReal(t,"Distance",Distance) call SetHandleReal(t,"Dur",Dur) endif set t = null set u = null set u2 = null endfunction Now, if you were controlling the movement of all projectiles from 1 single timer, you'd do this: JASS:function Spiral_Move takes nothing returns nothing local timer t = GetExpiredTimer() local unit u = GetHandleUnit(t,"TriggerUnit") local unit array u2 // = GetHandleUnit(t,"DummyUnit") local real Distance = (GetHandleReal(t,"Distance")) local real x = GetUnitX(u) local real y = GetUnitY(u) local real Dur = (GetHandleReal(t,"Dur") + 0.04) local real array Angle // = (GetHandleReal(t,"Angle") + 7.1) local real x2 local real y2 local unit u3 local integer i = 0 local integer i2 = 5 local group lastgroup = GetHandleGroup(t,"lastgroup") local group currentgroup = CreateGroup() local group currentgroup2 = CreateGroup() set bj_ghoul[111] = u call GroupEnumUnitsInRange(currentgroup,x,y,Distance,Filter(function Spiral_Filter)) call SetHandleHandle(t,"lastgroup",currentgroup2) call GroupAddGroup(currentgroup,currentgroup2) loop set u3 = FirstOfGroup(lastgroup) exitwhen u3 == null if not(IsUnitInGroup(u3,currentgroup2)) then call UnitRemoveAbility(u3, 'A001') call SetUnitInvulnerable(u3,false) endif call GroupRemoveUnit(currentgroup,u3) call GroupRemoveUnit(lastgroup,u3) endloop loop set u3 = FirstOfGroup(currentgroup) exitwhen u3 == null if GetUnitAbilityLevel(u3, 'A001') == 0 then call UnitAddAbility(u3, 'A001') call SetUnitInvulnerable(u3,true) endif call GroupRemoveUnit(currentgroup,u3) endloop call DestroyGroup(currentgroup) call DestroyGroup(lastgroup) if Distance < 400 and Dur < 4.00 then set Distance = Distance + 4.571 elseif Dur > 4.00 then set Distance = Distance - 4.571 endif loop set i = i+1 exitwhen i > i2 set u2[i] = GetHandleUnit(t, "DummyUnit "+I2S(i)) set Angle[i] = GetHandleReal(t, "Angle "+I2S(i))+7.1 set x2 = x + Distance * Cos(Angle[i] * bj_DEGTORAD) set y2 = y + Distance * Sin(Angle[i] * bj_DEGTORAD) call SetUnitX(u2[i],x2) call SetUnitY(u2[i],y2) endloop if Dur >= 10.00 then set i = 0 loop set i = i+1 exitwhen i > i2 call KillUnit(u2[i]) endloop call PauseTimer(t) call FlushHandleLocals(t) call DestroyTimer(t) else set i = 0 loop set i = i+1 exitwhen i > i2 call SetHandleReal(t,"Angle "+I2S(i),Angle[i]) endloop call SetHandleReal(t,"Distance",Distance) call SetHandleReal(t,"Dur",Dur) endif set t = null set u = null set i = 0 loop set i = i+1 exitwhen i > i2 set u2[i] = null endloop endfunction I apologize for any compile errors or typos there might be; I didn't thoroughly check this code. I hope it clears something up for you. |
| 08-21-2007, 03:46 PM | #7 |
Ooh, thanks. Ill work on implementing all these immediately. This should also help me get to start coding alot better (my first jass spell with handles and 2nd with timers). |
