| 01-13-2009, 10:56 PM | #1 |
I've just spent all my free time today on this spell, trying to figure out why the hell it won't work. Well, ok, I've watched South Park .Anyway, the spell should attract enemies a bit closer to the caster. It's simple, and I thought it would be perfect to practice using structs. Please, any help would be appreciated. JASS:scope PositiveAttraction initializer Init globals private constant integer SPELLID = 'A002' private constant real RANGE = 600.0 private constant real DISTANCEBASE = 150.0 private constant real DISTANCEINCREASE = 75.0 private constant real MOVEEACHTIME = 25.0 private constant string EFFECT = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl" //Struct required private group Group = CreateGroup() private integer Counter = 0 private timer Timer = CreateTimer() private constant real TimerPeriod = 0.04 private integer array Move endglobals private constant function Distance takes integer level returns real return (DISTANCEBASE-DISTANCEINCREASE)+(DISTANCEINCREASE*level) endfunction private function Check takes nothing returns boolean return GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_ANCIENT) endfunction //=========================================================================== private function Conditions takes nothing returns boolean return GetSpellAbilityId()==SPELLID endfunction private struct move integer Level real X real Y unit U integer Repeat static method create takes integer level, real x, real y, unit u returns move local move m = move.allocate() set m.Level = level set m.X = x set m.Y = y set m.U = u set m.Repeat = R2I(Distance(level) / MOVEEACHTIME) return m endmethod endstruct private function Loop takes nothing returns nothing local move m = 0 local unit v local unit u local integer i = Counter - 1 local integer lvl local real x local real y local integer level local real angle local player p loop exitwhen i < Counter set m = Move[i] set x = m.X set y = m.Y set level = m.Level set u = m.U set p = GetOwningPlayer(u) if m.Repeat<0 then call m.destroy() set Counter = Counter - 1 if Counter < 0 then call PauseTimer(Timer) set Counter = 0 else set Move[i] = Move[Counter] endif else loop set v = FirstOfGroup(Group) exitwhen v == null call GroupRemoveUnit(Group, v) if IsUnitEnemy(v, p) then set angle = bj_RADTODEG*Atan2(y-GetUnitY(v), x-GetUnitX(v)) call SetUnitPosition(v, GetUnitX(v)+CosBJ(angle)*MOVEEACHTIME, GetUnitY(v)+SinBJ(angle)*MOVEEACHTIME) call DestroyEffect(AddSpecialEffect(EFFECT, GetUnitX(v), GetUnitY(v))) endif endloop set p = null set u = null endif set i = i-1 endloop set m.Repeat = m.Repeat-1 endfunction function Actions takes nothing returns nothing local unit caster = GetTriggerUnit() local move m = 0 local integer level = GetUnitAbilityLevel(caster, SPELLID) local real x = GetUnitX(caster) local real y = GetUnitY(caster) local integer n local player p = GetOwningPlayer(caster) call GroupEnumUnitsInRange(Group, x, y, RANGE, Condition(function Check)) set m = m.create(level, x, y, caster) if Counter == 0 then call TimerStart(Timer, TimerPeriod, true, function Loop) endif set Move[Counter] = m set Counter = Counter + 1 set caster = null endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger t = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(t, Condition(function Conditions)) call TriggerAddAction(t, function Actions ) endfunction endscope |
| 01-14-2009, 12:14 AM | #2 |
Hm, I believe you are modifying the "Group" variable directly, and therefore it stops after 1 execution. To fix it, create a new local variable in the "Loop" function and add the "Group" variable to it with GroupAddGroup(Group, newvar), then modify that one in your loop. Also make sure you clean up the "v" and "u" unit variables. |
| 01-14-2009, 01:15 AM | #3 |
I'd use radians, the funny thing about JASS is you really don't need to understand using radians, only use a different set of natives and bj_RADTODEG to convert to degrees for unit facing. And store X Speed and Y Speed as struct members ( X Speed would be calculated on creation, Move offset * Cos(angle)) or at least the cosine and sine ratios of the angle at which the unit is projected, you do not need to recalculate the angle or the cos/sin if the unit is projected at a constant angle. |
| 01-14-2009, 01:36 AM | #4 |
You know, I would not be surprised if this: JASS:local real a=.a local real x=Cos(a) local real y=Sin(a) JASS:local real x=.x local real y=.y |
| 01-14-2009, 04:51 AM | #5 |
I fixed it. As usual, it was an idiot's problem. First I didn't declared the struct properly, then some minor calculations were wrong, and finally group was cleared after the first loop, so it moved only for one period distance instead of total. Thanks for helping, your suggestions made me look in the right way. |
