| 12-26-2008, 11:51 PM | #1 |
I'm creating a spell that is a half sphere and then it implodes but now I have an extremely weird bug. When I cast it once then it fucks up totally, when that instance finish and I casts it again then it fucks up but in another way, BUT if I first cast it and it fucks up and then casts it again while the other is still running then it works. How I can see the bug: If the instance is fucked up then the units moves totally randomly. JASS:library OtherSummon initializer Init requires HSAS globals private constant integer SPELL_ID = 'A002' private constant integer DUMMY_ID = 'o001' private constant real RADIUS = 400 private constant integer UNITS_PER_LAYER = 16 private constant real TIMER_PERIOD = 0.025 private constant real DECREASE_TIME = 4 endglobals //! runtextmacro HSAS_Static("Other", "8190", "private") private struct otherdata real x real y group g unit u player p real array xyspeeds[200] real array heightspeeds[200] integer iterator static method create takes unit u, real x, real y returns otherdata local otherdata d = .allocate() set d.x = x set d.y = y set d.u = u set d.g = CreateGroup() set d.p = GetOwningPlayer(u) set d.iterator = 0 return d endmethod endstruct globals private otherdata dddddd endglobals private function CallbackForgroup takes nothing returns nothing local unit u = GetEnumUnit() local real x = GetUnitX(u) local real y = GetUnitY(u) local otherdata d = dddddd local real angle = (Atan2(y - d.y, x - d.x)) local real height = GetUnitFlyHeight(u) local real distance = SquareRoot((x - d.x) * (x - d.x) + (y - d.y) * (y - d.y)) if distance == 0 then set distance = 1 endif if distance >= 20 then call SetUnitX(u, d.x + (distance - d.xyspeeds[d.iterator]) * Cos(angle)) call SetUnitY(u, d.y + (distance - d.xyspeeds[d.iterator]) * Sin(angle)) endif if height > 10 then call SetUnitFlyHeight(u, height - d.heightspeeds[d.iterator], 0 ) endif if distance < 20 and height <= 10 then call GroupRemoveUnit(d.g, u) endif set d.iterator = d.iterator + 1 endfunction private function Callback takes nothing returns nothing local otherdata d = GetAttachedStructOther(GetExpiredTimer()) set dddddd = d if FirstOfGroup(d.g) == null then call d.destroy() call PauseTimer(GetExpiredTimer()) call DestroyTimer(GetExpiredTimer()) else call ForGroup(d.g , function CallbackForgroup) endif set d.iterator = 0 endfunction private function Act takes nothing returns nothing local location loc = GetSpellTargetLoc() local unit u = GetTriggerUnit() local otherdata d = otherdata.create(u, GetLocationX(loc), GetLocationY(loc)) local integer i = 0 local real angleBetween = (360/UNITS_PER_LAYER) // The amount of units on the height = this/2 local real angleDone = 0 local real angleDoneHeight = 0 local real cz = 1 local timer t = CreateTimer() local real dist loop exitwhen cz < 0 loop exitwhen angleDone >= 360. or cz < 0 set cz = RADIUS * Cos(angleDoneHeight*bj_DEGTORAD) set u = CreateUnit(d.p, DUMMY_ID, d.x + RADIUS * Sin(angleDoneHeight*bj_DEGTORAD) * Cos(angleDone*bj_DEGTORAD) , d.y + RADIUS * Sin(angleDoneHeight*bj_DEGTORAD) * Sin(angleDone*bj_DEGTORAD) , 270) call UnitApplyTimedLife( u, 'BTLF', 6) call SetUnitFlyHeight(u, cz + 10, 0) call GroupAddUnit(d.g, u) set angleDone = angleDone + angleBetween set dist = SquareRoot((GetUnitX(u) - d.x) * (GetUnitX(u) - d.x) + (GetUnitY(u) - d.y) * (GetUnitY(u) - d.y)) set d.xyspeeds[i] = (dist * TIMER_PERIOD) / DECREASE_TIME set d.heightspeeds[i] = (GetUnitFlyHeight(u) * TIMER_PERIOD) / DECREASE_TIME set u = null set i = i + 1 endloop set angleDone = 0 set angleDoneHeight = angleDoneHeight+angleBetween endloop call AttachStructOther(t, d) call TimerStart(t, TIMER_PERIOD, true, function Callback) endfunction private function Cond takes nothing returns boolean return GetSpellAbilityId() == SPELL_ID endfunction private function Init takes nothing returns nothing local trigger Trig = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(Trig, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(Trig, Condition(function Cond)) call TriggerAddAction(Trig, function Act) endfunction endlibrary Edit - I know that it leaks but there's no leaks in the periodic stuff :) |
| 12-27-2008, 05:28 AM | #2 |
Perhaps it's an error with HSAS? Have you tried with a different attachment system? I don't see anything that would do stuff like that besides attaching getting fucked up. |
| 12-27-2008, 03:38 PM | #3 |
Ok, made it use ABC instead but there was no improvment. |
| 12-27-2008, 10:42 PM | #4 |
I don't think it is the attachment system that is making problems here. (but I do think you should use TT for spells like this) Post a demo map with this spell, that is the fastest way to get help with problems like this. |
| 12-27-2008, 11:16 PM | #5 |
> (but I do think you should use TT for spells like this) Easily changed, add return boolean and some returns + TT calls :P > Post a demo map with this spell, that is the fastest way to get help with problems like this. Posted a demo map |
| 12-28-2008, 08:54 AM | #6 |
JASS:library OtherSummon initializer Init requires TT globals private constant integer SPELL_ID = 'A002' private constant integer DUMMY_ID = 'o001' private constant integer MAX_DUMMIES = 200 private constant real RADIUS = 400 private constant integer UNITS_PER_LAYER = 16 private constant real DECREASE_TIME = 4 endglobals private struct Data real x real y //group g unit u player p integer N // unit counter unit array U[MAX_DUMMIES] // using array instead of group boolean array active[MAX_DUMMIES] // <-----<< real array coss[MAX_DUMMIES] // Optimize ffs real array sins[MAX_DUMMIES] real array xyspeeds[MAX_DUMMIES] real array heightspeeds[MAX_DUMMIES] //integer iterator static method create takes unit u, real x, real y returns Data local Data d = .allocate() set d.x = x set d.y = y set d.u = u //set d.g = CreateGroup() set d.N = 0 set d.p = GetOwningPlayer(u) //set d.iterator = 0 return d endmethod endstruct //=========================================================================== private function MoveUnit takes Data d, integer i returns nothing //local unit u = GetEnumUnit() local real x = GetUnitX(d.U[i]) local real y = GetUnitY(d.U[i]) //local real angle = (Atan2(y - d.y, x - d.x)) local real height = GetUnitFlyHeight(d.U[i]) local real distance = SquareRoot((x - d.x) * (x - d.x) + (y - d.y) * (y - d.y)) if distance == 0 then set distance = 1 endif if distance >= 20 then call SetUnitX(d.U[i], d.x + (distance - d.xyspeeds[i]) * d.coss[i]) call SetUnitY(d.U[i], d.y + (distance - d.xyspeeds[i]) * d.sins[i]) endif if height > 10 then call SetUnitFlyHeight(d.U[i], height - d.heightspeeds[i], 0 ) endif if distance < 20 and height <= 10 then //call GroupRemoveUnit(d.g, d.U[i]) set d.active[i] = false endif endfunction private function Callback takes nothing returns boolean //local Data d = GetAttachedStructOther(GetExpiredTimer()) local Data d = TT_GetData() local integer i //if FirstOfGroup(d.g) == null then if d.N <= 0 then call d.destroy() return true //call ClearTimerStructA(GetExpiredTimer()) //call PauseTimer(GetExpiredTimer()) //call DestroyTimer(GetExpiredTimer()) else set i = 0 loop exitwhen i >= d.N if d.active[i] then call MoveUnit(d, i) endif set i = i + 1 endloop return false endif endfunction private function Act takes nothing returns nothing local location temp = GetSpellTargetLoc() local unit u = GetTriggerUnit() local Data d = Data.create(u, GetLocationX(temp), GetLocationY(temp)) local integer i = 0 local real angleBetween = (360/UNITS_PER_LAYER) // The amount of units on the height = this/2 local real angleDone = 0 local real angleDoneHeight = 0 local real angle local real cz = 1 //local timer t = CreateTimer() local real dist call RemoveLocation(temp) // <-----<< shame on you set temp = null loop exitwhen cz < 0 loop exitwhen angleDone >= 360. or cz < 0 set cz = RADIUS * Cos(angleDoneHeight*bj_DEGTORAD) set u = CreateUnit(d.p, DUMMY_ID, d.x + RADIUS * Sin(angleDoneHeight*bj_DEGTORAD) * Cos(angleDone*bj_DEGTORAD) , d.y + RADIUS * Sin(angleDoneHeight*bj_DEGTORAD) * Sin(angleDone*bj_DEGTORAD) , 270) call UnitApplyTimedLife( u, 'BTLF', 6) call SetUnitFlyHeight(u, cz + 10, 0) //call GroupAddUnit(d.g, u) set angleDone = angleDone + angleBetween set dist = SquareRoot((GetUnitX(u) - d.x) * (GetUnitX(u) - d.x) + (GetUnitY(u) - d.y) * (GetUnitY(u) - d.y)) set d.xyspeeds[i] = (dist * TT_PERIOD) / DECREASE_TIME set d.heightspeeds[i] = (GetUnitFlyHeight(u) * TT_PERIOD) / DECREASE_TIME set angle = Atan2(GetUnitY(u) - d.y, GetUnitX(u) - d.x) // <-----<< set d.coss[i] = Cos(angle) set d.sins[i] = Sin(angle) set d.U[i] = u // <-----<< set d.active[i] = true // <-----<< set d.N = d.N + 1 set u = null set i = i + 1 endloop set angleDone = 0 set angleDoneHeight = angleDoneHeight+angleBetween endloop //call SetTimerStructA(t , d) call TT_Start(function Callback, d) endfunction private function Cond takes nothing returns boolean return GetSpellAbilityId() == SPELL_ID endfunction private function Init takes nothing returns nothing local trigger Trig = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(Trig, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(Trig, Condition(function Cond)) call TriggerAddAction(Trig, function Act) endfunction endlibrary The problem with spell was that you used both groups and iteration, so when unit was removed from group it fucked up iteration counter. I recoded the spell to use iteration only. Replaced attachment systems with TT (not really important) and finally optimized Cos and Sin usage. PS: I saw in demo map a HandleCounter with period of 0.001, that is stupid, first because it lags and second because dialog display works on 1.0 period and even if it was not human eye cannot detect 0.001 changes in number display. |
| 12-28-2008, 05:25 PM | #7 |
Lol.. the bug was pretty obvious when you saw it... And the Handle Counter is only a CnP of the Handle Counter "system" that's posted on Th.net. Thanks for the help :) |
