| 06-23-2008, 01:52 PM | #1 |
Sorry for the bad topic, but i just didnt know how to call this here. At first, what does the following spell do? Pretty easy: 20 Missiles created 800 distance around the Target Point fly towards it, and in the very inner when they meet all units in an AoE of X get damaged and an effect is shown. So, the problem is, when spamming this spell quickly, the missile dummys are removed or killed before they reach the center point. Why? If i cast this spell just once and wait until its finished, everything works fine, but shouldnt it with spamming, too? If i remove the KillUnit and RemoveUnitTimed (Removes a unit after a certain time) functions then the dummys sometimes just stop moving at half of their way, while timer is running out and the final effect is still shown. Any help? Here we go with the code: JASS:function Trig_Soul_Valley_Conditions takes nothing returns boolean return GetSpellAbilityId() == 'A001' endfunction struct SoulValleyData unit caster unit array dummys[20] real centerx real centery integer executions method onDestroy takes nothing returns nothing local integer i = 0 loop exitwhen .dummys[i] == null if .dummys[i] == null then call BJDebugMsg("DUMMY IS NULL") endif call KillUnit(.dummys[i]) call RemoveUnitTimed(.dummys[i],2.) set i = i +1 endloop set .caster = null endmethod endstruct function SoulValley_Final takes real centerx, real centery, unit caster returns nothing local group g = CreateGroup() local unit u local real dmg = 200. call DestroyEffect(AddSpecialEffect(GetAbilityEffectById('A001',EFFECT_TYPE_AREA_EFFECT,0),centerx,centery)) call GroupEnumUnitsInRange(g,centerx,centery,350.,null) loop set u = FirstOfGroup(g) exitwhen u == null if IsUnitEnemy(u,GetOwningPlayer(caster)) then call UnitDamageTarget(caster,u,dmg,true,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_NORMAL,null) endif call GroupRemoveUnit(g,u) endloop call DestroyGroup(g) set g = null set u = null set caster = null endfunction function SoulValley_callback takes nothing returns nothing local timer t = GetExpiredTimer() local SoulValleyData a = GetAttachedInt(t,"data") local integer i = 0 local real angle local real nx local real ny local real ux local real uy loop exitwhen i > 19 set ux = GetUnitX(a.dummys[i]) set uy = GetUnitY(a.dummys[i]) set angle = Atan2(a.centery - uy, a.centerx-ux) set nx = ux + 30 * Cos(angle) set ny = uy + 30 * Sin(angle) call SetUnitX(a.dummys[i],nx) call SetUnitY(a.dummys[i],ny) set i = i +1 endloop set a.executions = a.executions -1 call AttachInt(t,"data",a) if a.executions <=0 then call SoulValley_Final(a.centerx,a.centery,a.caster) call a.destroy() call CleanAttachedVars(t) call ReleaseTimer(t) endif endfunction function Trig_Soul_Valley_Actions takes nothing returns nothing local SoulValleyData a = SoulValleyData.create() local timer t = NewTimer() local location tp = GetSpellTargetLoc() local integer i = 0 local real angle local real nx local real ny set a.caster = GetTriggerUnit() set a.centerx = GetLocationX(tp) set a.centery = GetLocationY(tp) set a.executions = 800/30 loop exitwhen i > 19 set angle = bj_DEGTORAD*360/20*i set nx = a.centerx + 800 *Cos(angle) set ny = a.centery + 800 *Sin(angle) set a.dummys[i] = CreateUnit(GetOwningPlayer(a.caster),'h001',nx,ny,270.) call SetUnitX(a.dummys[i],nx) call SetUnitY(a.dummys[i],ny) set i = i +1 endloop call AttachInt(t,"data",a) call TimerStart(t,0.03,true,function SoulValley_callback) endfunction //=========================================================================== function InitTrig_Soul_Valley takes nothing returns nothing set gg_trg_Soul_Valley = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_Soul_Valley, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition( gg_trg_Soul_Valley, Condition( function Trig_Soul_Valley_Conditions ) ) call TriggerAddAction( gg_trg_Soul_Valley, function Trig_Soul_Valley_Actions ) endfunction Edit: Okay, if i change the code to the oldsql way of transferring data with timers, everything works properly. where is the mistake now? JASS:function Trig_Soul_Valley_Conditions takes nothing returns boolean return GetSpellAbilityId() == 'A001' endfunction struct SoulValleyData unit caster unit array dummys[20] real centerx real centery integer executions method onDestroy takes nothing returns nothing local integer i = 0 local unit u call BJDebugMsg("DESTROY") loop exitwhen .dummys[i] == null if .dummys[i] == null then call BJDebugMsg("DUMMY IS NULL") endif // call KillUnit(.dummys[i]) set u = .dummys[i] call RemoveUnitTimed(u,2.) call KillUnit(u) set i = i +1 endloop set .caster = null endmethod endstruct function SoulValley_Final takes real centerx, real centery, unit caster returns nothing local group g = CreateGroup() local unit u local real dmg = 200. call DestroyEffect(AddSpecialEffect(GetAbilityEffectById('A001',EFFECT_TYPE_AREA_EFFECT,0),centerx,centery)) call GroupEnumUnitsInRange(g,centerx,centery,350.,null) loop set u = FirstOfGroup(g) exitwhen u == null if IsUnitEnemy(u,GetOwningPlayer(caster)) then call UnitDamageTarget(caster,u,dmg,true,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_NORMAL,null) endif call GroupRemoveUnit(g,u) endloop call DestroyGroup(g) set g = null set u = null set caster = null endfunction function SoulValley_callback takes nothing returns nothing local timer t = GetExpiredTimer() local unit caster = GetAttachedUnit(t,"caster") local real centerx = GetAttachedReal(t,"centerx") local real centery = GetAttachedReal(t,"centery") local integer executions = GetAttachedInt(t,"executions") local unit dummy local integer i = 0 local real angle local real nx local real ny local real ux local real uy loop exitwhen i > 19 set dummy = GetAttachedUnit(t,"dummys"+I2S(i)) set ux = GetUnitX(dummy) set uy = GetUnitY(dummy) set angle = Atan2(centery - uy, centerx-ux) set nx = ux + 30 * Cos(angle) set ny = uy + 30 * Sin(angle) call SetUnitX(dummy,nx) call SetUnitY(dummy,ny) set i = i +1 endloop set executions = executions -1 call AttachInt(t,"executions",executions) if executions <=0 then set i = 0 loop exitwhen i > 19 call KillUnit(GetAttachedUnit(t,"dummys"+I2S(i))) set i = i +1 endloop call BJDebugMsg("EXECUTIONS NULL") call SoulValley_Final(centerx,centery,caster) call CleanAttachedVars(t) call ReleaseTimer(t) endif endfunction function Trig_Soul_Valley_Actions takes nothing returns nothing local unit caster = GetTriggerUnit() local unit array dummys [20] local timer t = NewTimer() local location tp = GetSpellTargetLoc() local integer i = 0 local real angle local real nx local real ny local real centerx = GetLocationX(tp) local real centery = GetLocationY(tp) local integer executions = 800/30 loop exitwhen i > 19 set angle = bj_DEGTORAD*360/20*i set nx = centerx + 800 *Cos(angle) set ny = centery + 800 *Sin(angle) set dummys[i] = CreateUnit(GetOwningPlayer(caster),'h001',nx,ny,270.) call SetUnitX(dummys[i],nx) call SetUnitY(dummys[i],ny) call AttachObject(t,"dummys"+I2S(i),dummys[i]) set i = i +1 endloop call AttachObject(t,"caster",caster) call AttachReal(t,"centerx",centerx) call AttachReal(t,"centery",centery) call AttachInt(t,"executions",executions) call TimerStart(t,0.03,true,function SoulValley_callback) endfunction //=========================================================================== function InitTrig_Soul_Valley_Copy takes nothing returns nothing set gg_trg_Soul_Valley_Copy = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_Soul_Valley_Copy, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition( gg_trg_Soul_Valley_Copy, Condition( function Trig_Soul_Valley_Conditions ) ) call TriggerAddAction( gg_trg_Soul_Valley_Copy, function Trig_Soul_Valley_Actions ) endfunction Edit2: It seems to have something to do with the unit array definitely, but as i tested a.executions never gets 0 immediately, its always reduced by 1 until it hits 0 and struct is destroyed. There seems to be a conflict with multiple structs used in this spell at the same time. |
| 06-23-2008, 08:25 PM | #2 | |
JASS:exitwhen .dummys[i] == null Try changing that to exitwhen i>=20. Might work.
__________________________________________________________________ You code pretty well, if you used some more spaces/tabs (intendation) I would be more than happy, but that's probably just a matter of personal taste. In the looping part, you do not have to re-set the int. JASS:set a.executions = a.executions -1 call AttachInt(t,"data",a) Also, you have forgotten set t=null. In the Final-part, you do not need to null caster, since it's an argument for the function. set caster = null |
| 06-23-2008, 08:57 PM | #3 |
Ty very much! +rep |
