- Joined
- Sep 29, 2006

- Messages
- 447

Okay so I'm creating a spell called rage that causes a unit to run at a target location and knockback and damage all units it comes into contact with.

Hero goes through doodads

Also, bear in mind that I'm working off of a Mac and do not have ANY third party programs. Everything must be done with the vanilla editor.

Here's the spell:

And here are some function declared in the header that I used in this spell:

Extra Info, from the comments section of the Trigger:

Thanks for any help.

*Current Problems:*Hero goes through doodads

Also, bear in mind that I'm working off of a Mac and do not have ANY third party programs. Everything must be done with the vanilla editor.

Here's the spell:

JASS:

```
function RageConditions takes nothing returns boolean
return GetSpellAbilityId() == 'A001'
endfunction
function RageGroupSlide takes nothing returns nothing
local unit target = GetEnumUnit()
local integer targetID = GetHandleId(target)
local real angle = LoadReal(udg_hash, targetID, 0)
local real kbCount = LoadReal(udg_hash, targetID, 1)
local timer kbTimer = LoadTimerHandle(udg_hash, targetID, 2)
local real dist = 20.00
local real kbTotalDist = 350.00
if (kbCount < kbTotalDist) then
call SaveReal(udg_hash, targetID, 1, kbCount + dist)
call Slide(target, dist, angle, "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl")
else
call PauseTimer(kbTimer)
call PauseUnit(target, false)
call DestroyTimer(kbTimer)
call GroupRemoveUnit(udg_rageDamaged, target)
call FlushChildHashtable(udg_hash, targetID)
endif
set kbTimer = null
set target = null
endfunction
function RageKnockback takes nothing returns nothing
call ForGroup(udg_rageDamaged, function RageGroupSlide)
endfunction
function RageGroupFilter takes nothing returns boolean
local unit caster = udg_globalCaster
local player owner = GetOwningPlayer(caster)
local unit target = GetFilterUnit()
local integer targetID
local real damageAmount = 100 + ((I2R(GetUnitAbilityLevel(caster, 'A001')) - 1.00) * 50)
local real angle
local real angle2
local real kbCount = 0
local timer targetTimer = CreateTimer()
if (GetUnitState(target, UNIT_STATE_LIFE) > 0 and IsUnitType(target, UNIT_TYPE_GROUND) == true and IsUnitEnemy(target, owner) == true and IsUnitInGroup(target, udg_rageDamaged) == false) then
call GroupAddUnit(udg_rageDamaged, target)
call UnitDamageTarget(caster, target, damageAmount, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
set targetID = GetHandleId(target)
set angle = GetAngle(GetUnitX(caster), GetUnitY(caster), GetUnitX(target), GetUnitY(target))
if angle < 0 then
set angle = angle + 360.
endif
set angle2 = GetUnitFacing(caster)
if angle2 > angle then
set angle = angle2 - 45.
elseif angle2 < angle then
set angle = angle2 + 45.
endif
call SaveReal(udg_hash, targetID, 0, angle)
call SaveReal(udg_hash, targetID, 1, kbCount)
call SaveTimerHandle(udg_hash, targetID, 2, targetTimer)
call PauseUnit(target, true)
call TimerStart(targetTimer, .05, true, function RageKnockback)
endif
set caster = null
set target = null
return false
endfunction
function RageCallback takes nothing returns nothing
local timer rageTimer = GetExpiredTimer()
local integer timerID = GetHandleId(rageTimer)
local unit caster = LoadUnitHandle(udg_hash, timerID, 0)
local real angle = LoadReal(udg_hash, timerID, 1)
local real count = LoadReal(udg_hash, timerID, 2)
local real totalDist = LoadReal(udg_hash, timerID, 3)
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real dist = 45.00
local group targetGroup = CreateGroup()
set udg_globalCaster = caster
if (count < totalDist) then
call SaveReal(udg_hash, timerID, 2, count + dist)
call GroupEnumUnitsInRange(targetGroup, x, y, 175.00, Filter(function RageGroupFilter))
call SlideKeepOrder(caster, dist, angle, "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl")
else
call PauseTimer(rageTimer)
call DestroyTimer(rageTimer)
call PauseUnit(caster, false)
call FlushChildHashtable(udg_hash, timerID)
endif
set rageTimer = null
set caster = null
call DestroyGroup(targetGroup)
set targetGroup = null
endfunction
function RageActions takes nothing returns nothing
local unit caster = GetTriggerUnit()
local real x1 = GetUnitX(caster)
local real y1 = GetUnitY(caster)
local real x2 = GetSpellTargetX()
local real y2 = GetSpellTargetY()
local real angle = GetAngle(x1, y1, x2, y2)
local real totalDist = Distance(x1, y1, x2, y2)
local real count = 0.00
local timer rageTimer = CreateTimer()
local integer timerID = GetHandleId(rageTimer)
call SaveUnitHandle(udg_hash, timerID, 0, caster)
call SaveReal(udg_hash, timerID, 1, angle)
call SaveReal(udg_hash, timerID, 2, count)
call SaveReal(udg_hash, timerID, 3, totalDist)
call PauseUnit(caster, true)
call TimerStart(rageTimer, 0.03, true, function RageCallback)
set caster = null
set rageTimer = null
endfunction
//===========================================================================
function InitTrig_Rage takes nothing returns nothing
local trigger trigRage = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(trigRage, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trigRage, Condition(function RageConditions))
call TriggerAddAction(trigRage, function RageActions)
endfunction
```

And here are some function declared in the header that I used in this spell:

JASS:

```
//================================================================
function PolarProjectX takes real x, real dist, real angle returns real
return x + dist * Cos(angle * bj_DEGTORAD)
endfunction
function PolarProjectY takes real y, real dist, real angle returns real
return y + dist * Sin(angle * bj_DEGTORAD)
endfunction
function GetAngle takes real x1, real y1, real x2, real y2 returns real
return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
endfunction
function Distance takes real x1, real y1, real x2, real y2 returns real
local real dx = x2 - x1
local real dy = y2 - y1
return SquareRoot(dx * dx + dy * dy)
endfunction
//================================================================
function SafeX takes real x returns real
if (x > udg_maxX) then
return udg_maxX
elseif (x < udg_minX) then
return udg_minX
else
return x
endif
endfunction
function SafeY takes real y returns real
if (y > udg_maxY) then
return udg_maxY
elseif (y < udg_minY) then
return udg_minY
else
return y
endif
endfunction
//================================================================
function SlideKeepOrder takes unit target, real dist, real angle, string fx returns nothing
local real x = GetUnitX(target)
local real y = GetUnitY(target)
local real x2 = SafeX(PolarProjectX(x, dist, angle))
local real y2 = SafeY(PolarProjectY(y, dist, angle))
call DestroyEffect(AddSpecialEffect(fx, x, y))
call SetUnitX(target, x2)
call SetUnitY(target, y2)
endfunction
//================================================================
function Slide takes unit target, real dist, real angle, string fx returns nothing
local real x = GetUnitX(target)
local real y = GetUnitY(target)
local real x2 = SafeX(PolarProjectX(x, dist, angle))
local real y2 = SafeY(PolarProjectY(y, dist, angle))
call DestroyEffect(AddSpecialEffect(fx, x, y))
call SetUnitPosition(target, x2, y2)
endfunction
//================================================================
```

Extra Info, from the comments section of the Trigger:

Code:

```
Hashtable info: Hashtable = udg_hash
Index (timerID,0) reserved for unit "caster"
Index (timerID,1) reserved for real "angle"
Index (timerID,2) reserved for real "count"
Index (timerID,3) reserved for real "totalDist"
Hashtable info: Hashtable = udg_hash
Index (targetID,0) reserved for real "angle"
Index (targetID,1) reserved for real "kbcount"
Index (targetID,2) reserved for timer "kbTimer"
```

Thanks for any help.

Last edited: