| 09-07-2009, 10:51 PM | #1 |
Hi, I have made a spell in my map that creates two tornadoes that circles around my hero from 0 degrees to 360 degrees (even if the hero is moving), the first tornado circles around the caster using some math formulas, while the other tornado depends on the first tornado, so that they will be opposite to each other no matter what. The tornadoes have slow revolution rate, now the problem is, when my caster moves to the east, the tornadoes stop circling around when they are about to reach the north and south part, and when my caster tends to face backwards (0 degrees to 180 degrees), the tornadoes quickly circles around, when my caster stops, it circles normally like I wanted. Looks like the tornadoes depend on the caster's facing angle, that is why it sometimes fuck up. How do I make this work? The code (there are some function calls from other libraries, so please ignore them, for I believe that they do nothing about the circling part) JASS:scope EyeStorm initializer init globals private constant integer spell = 'A02S' private constant string light = "CHIM" private constant string hit = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl" private constant integer dumid = 'e009' endglobals private struct data unit c unit t1 unit t2 timer d1 timer d2 timer s integer l real elapsed //Circling Part static method dum1 takes nothing returns boolean local timer t = GetExpiredTimer() local data d = GetTimerData(t) local real x = GetUnitX(d.c) local real y = GetUnitY(d.c) local real a = 57.29582 * Atan3(x,y,GetUnitX(d.t1),GetUnitY(d.t1)) local real px = x + 200 * Cos((a+2) * bj_DEGTORAD) local real py = y + 200 * Sin((a+2) * bj_DEGTORAD) call SetUnitX(d.t1,px) call SetUnitY(d.t1,py) set t = null return true endmethod static method dum2 takes nothing returns boolean local timer t = GetExpiredTimer() local data d = GetTimerData(t) local real x = GetUnitX(d.t1) local real y = GetUnitY(d.t1) local real a = Atan3(x,y,GetUnitX(d.c),GetUnitY(d.c)) local real px = x + 400 * Cos(a) local real py = y + 400 * Sin(a) call SetUnitX(d.t2,px) call SetUnitY(d.t2,py) set t = null return true endmethod //End of Circling part static method strike takes nothing returns boolean local timer t = GetExpiredTimer() local data d = GetTimerData(t) local group g = NewGroup() local unit u local xedamage xe = xedamage.create() local real x = GetUnitX(d.t1) local real y = GetUnitY(d.t1) local real ux local real uy local real a set xe.dtype = DTWATER call xe.useSpecialEffect(hit,"origin") set xe.exception = UNIT_TYPE_STRUCTURE call GroupEnumUnitsInRange(g,x,y,250.0,BOOLEXPR_TRUE) loop set u = FirstOfGroup(g) exitwhen u == null if IsUnitEnemy(u, GetOwningPlayer(d.c)) and GetWidgetLife(u) > 0.405 and not IsUnitType(u,UNIT_TYPE_STRUCTURE) and not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) then call LightningUnitTarget(d.t1,I2R(GetRandomInt(400,500)),u,0.0,light,0.6,1.0,1.0,1.0) call xe.damageTarget(d.c,u,20*d.l+60) call DestroyEffect(AddSpecialEffectTarget(hit,u,"origin")) if not IsUnitType(u,UNIT_TYPE_HERO) and not (GetUnitTypeId(u) == 'n004' or GetUnitTypeId(u) == 'n009') then set ux = GetUnitX(u) set uy = GetUnitY(u) set a = 57.29582 * Atan3(x,y,ux,uy) call KnockbackTarget(d.c,u,a,800.0,800.0,false,false,false) endif endif call GroupRemoveUnit(g,u) endloop call ReleaseGroup(g) set u = null set g = null set g = NewGroup() set x = GetUnitX(d.t2) set y = GetUnitY(d.t2) call GroupEnumUnitsInRange(g,x,y,250.0,BOOLEXPR_TRUE) loop set u = FirstOfGroup(g) exitwhen u == null if IsUnitEnemy(u, GetOwningPlayer(d.c)) and GetWidgetLife(u) > 0.405 and not IsUnitType(u,UNIT_TYPE_STRUCTURE) and not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) then call LightningUnitTarget(d.t2,I2R(GetRandomInt(400,500)),u,0.0,light,0.6,1.0,1.0,1.0) call xe.damageTarget(d.c,u,20*d.l+60) call DestroyEffect(AddSpecialEffectTarget(hit,u,"origin")) if not IsUnitType(u,UNIT_TYPE_HERO) and not (GetUnitTypeId(u) == 'n004' or GetUnitTypeId(u) == 'n009') then set ux = GetUnitX(u) set uy = GetUnitY(u) set a = 57.29582 * Atan3(x,y,ux,uy) call KnockbackTarget(d.c,u,a,800.0,800.0,false,false,false) endif endif call GroupRemoveUnit(g,u) endloop call ReleaseGroup(g) call xe.destroy() set u = null set g = null set t = null return true endmethod static method tDestroy takes nothing returns boolean local timer t = GetExpiredTimer() local data d = GetTimerData(t) set d.elapsed = d.elapsed + 0.035 if d.elapsed >= 20.0 or GetWidgetLife(d.c) <= 0.405 then set d.elapsed = 0.0 call KillUnit(d.t1) call KillUnit(d.t2) call ReleaseTimer(d.d1) call ReleaseTimer(d.d2) call ReleaseTimer(d.s) call ReleaseTimer(t) call d.destroy() endif set t = null return true endmethod static method create takes unit c, integer l returns data local data d = data.allocate() local timer t = NewTimer() local real px1 = GetUnitX(c) + 200 * Cos(57.29582 * 0) local real py1 = GetUnitY(c) + 200 * Sin(57.29582 * 0) local real px2 = GetUnitX(c) + 200 * Cos(57.29582 * 180) local real py2 = GetUnitY(c) + 200 * Sin(57.29582 * 180) set d.c = c set d.l = l set d.t1 = CreateUnit(GetOwningPlayer(d.c),dumid,px1,py1,0.0) set d.t2 = CreateUnit(GetOwningPlayer(d.c),dumid,px2,py2,0.0) set d.d1 = NewTimer() set d.d2 = NewTimer() set d.s = NewTimer() call UnitApplyTimedLife(d.t1,'BTLF',20.0) call UnitApplyTimedLife(d.t2,'BTLF',20.0) call TimerStart(d.d1,0.035,true,function data.dum1) call TimerStart(d.d2,0.035,true,function data.dum2) call TimerStart(d.s,0.75,true,function data.strike) call TimerStart(t,0.035,true,function data.tDestroy) call SetTimerData(d.d1,d) call SetTimerData(d.d2,d) call SetTimerData(d.s,d) call SetTimerData(t,d) set t = null return d endmethod endstruct private function act takes nothing returns nothing local data d = data.create(SpellEvent.CastingUnit,GetUnitAbilityLevel(SpellEvent.CastingUnit,spell)) call shake() endfunction private function init takes nothing returns nothing call RegisterSpellEffectResponse(spell,act) endfunction endscope Thank you. |
