- Joined
- Nov 10, 2006
- Messages
- 181
JASS:
Chain knockback[/b]
[code=jass]//Formula to calculate Distance = -1 * V * V / (2 * A / Interval) Where variable V is speed and A is decrement.//
// Note! V must be positive and A must be negative!!!! //
library Knockback initializer Init requires BoundSentinel, DestructableLib, IsTerrainWalkable
globals
private constant real TIME = 0.03
private constant real CHAINRADIUS = 100
private constant real SPEEDFACTOR = 0.75
private constant string GROUND = "MDX\\Dust.mdx"
private constant string WATER = "MDX\\SlideWater.mdx"
private constant string COLLISION = "MDX\\DustAndRocks.mdx"
private constant string ATTACHPOINT = "origin"
private constant integer Invulnerable = 'Avul'
private constant real RADIUS = 180
private timer Timer = CreateTimer()
private group chain = CreateGroup()
private integer Count = 0
private integer array Knocker
private rect TreeRect
private boolexpr TreeCheck
private boolexpr ChainFilter
private unit source
private unit target
endglobals
private function CheckTrees takes nothing returns boolean
if IsDestructableTree(GetFilterDestructable()) then
return true
endif
return false
endfunction
private function Trees takes nothing returns nothing
call KillDestructable(GetEnumDestructable())
endfunction
private function ChainCheck takes nothing returns boolean
return true
//return target != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(source)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) and GetWidgetLife(GetFilterUnit()) > 0.405 and GetUnitAbilityLevel(GetFilterUnit(), Invulnerable) <= 0
endfunction
private struct Knock
unit source
unit target
integer EffectMode
group hit
real x
real y
real cos
real sin
real speed
real decrement
effect effects
boolean Terrain
boolean Trees
boolean AllowMove
boolean constantspeed
boolean chain
public method TerrainCheck takes Knock d returns integer
local real x = GetUnitX(d.target)
local real y = GetUnitY(d.target)
if IsTerrainWalkable(x + 50.00 * d.cos,y + 50.00 * d.sin) == false then
return 3
else
if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
return 1
elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
return 2
endif
endif
return 0
endmethod
static method create takes unit source, unit target, real angle,real speed, real decrement, boolean KillTree, boolean Allowmove, boolean ConstantSpeed,boolean Chain returns Knock
local Knock d = Knock.allocate()
local real x
local real y
set d.source = source
set d.target = target
set d.Trees = KillTree
set d.constantspeed = ConstantSpeed
set d.AllowMove = Allowmove
set d.chain = Chain
if d.chain == true then
set d.hit = CreateGroup()
endif
set x = GetUnitX(d.target)
set y = GetUnitY(d.target)
set d.speed = speed * TIME
set d.decrement = decrement * TIME
set d.sin = Sin(angle)
set d.cos = Cos(angle)
set d.EffectMode = d.TerrainCheck(d)
if chain == null then
set chain = CreateGroup()
endif
if d.EffectMode == 1 then
set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
endif
if d.EffectMode == 2 then
set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
endif
if d.EffectMode == 3 then
set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
endif
return d
endmethod
method onDestroy takes nothing returns nothing
call DestroyEffect(this.effects)
endmethod
endstruct
private function Update takes nothing returns nothing
local Knock d = 0
local Knock c = 0
local unit u
local unit t
local real sx
local real sy
local real x
local real y
local real cx
local real cy
local integer i = Count - 1
local integer mode = 0
loop
exitwhen i < 0
set d = Knocker[i]
set u = d.target
set sx = GetUnitX(u)
set sy = GetUnitY(u)
set x = sx + d.speed * d.cos
set y = sy + d.speed * d.sin
if d.speed <= 0 then
call d.destroy()
set Count = Count - 1
if Count < 0 then
call PauseTimer(Timer)
set Count = 0
else
set Knocker[i] = Knocker[Count]
endif
endif
set mode = d.EffectMode
if d.AllowMove == true then
call SetUnitX(d.target,x)
call SetUnitY(d.target,y)
else
call SetUnitPosition(u,x,y)
endif
if d.Trees == true then
call SetRect(TreeRect,sx-RADIUS,sy-RADIUS,sx+RADIUS,sy+RADIUS)
call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
endif
set d.EffectMode = d.TerrainCheck(d)
if d.EffectMode == 1 and (mode == 2 or mode == 3) then
call DestroyEffect(d.effects)
set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
elseif d.EffectMode == 2 and (mode == 1 or mode == 3) then
call DestroyEffect(d.effects)
set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
elseif d.EffectMode == 3 and (mode == 1 or mode == 2) then
call DestroyEffect(d.effects)
set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
endif
if d.chain == true then
call BJDebugMsg("Working!")
set sx = GetUnitX(u)
set sy = GetUnitY(u)
set source = d.source
set target = d.target
call GroupEnumUnitsInRange(chain,sx,sy,CHAINRADIUS,ChainFilter)
loop
set t = FirstOfGroup(chain)
exitwhen t == null
if not IsUnitInGroup(t,d.hit) then
set cx = GetUnitX(t)
set cy = GetUnitY(t)
call GroupAddUnit(d.hit,t)
set c = Knock.create(d.source,t, Atan2(cy-sy,cx-sx), d.speed*SPEEDFACTOR, d.decrement, d.Trees,d.AllowMove,d.constantspeed,d.chain)
call GroupAddUnit(c.hit, u)
set Knocker[Count] = c
set Count = Count + 1
endif
call GroupRemoveUnit(chain, t)
endloop
endif
if d.constantspeed == true then
else
set d.speed = d.speed - d.decrement
endif
set i = i - 1
endloop
set u = null
endfunction
function KnockbackStop takes unit target returns boolean
local integer i = Count - 1
local Knock d = 0
local boolean b = false
loop
exitwhen i < 0
set d = Knocker[i]
if d.target == target then
call d.destroy()
set Count = Count - 1
if Count < 0 then
call PauseTimer(Timer)
set Count = 0
else
set Knocker[i] = Knocker[Count]
endif
set b = true
endif
set i = i - 1
endloop
return b
endfunction
function IsKnockedBack takes unit target returns boolean
local integer i = Count - 1
local Knock d = 0
loop
exitwhen i < 0
set d = Knocker[i]
if d.target == target then
return true
endif
set i = i - 1
endloop
return false
endfunction
function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement,boolean KillTree, boolean AllowMove, boolean ConstantSpeed,boolean Chain returns boolean
local Knock d = 0
if target == null or source == null or speed == null or decrement == null then
call BJDebugMsg("Invalid Values!")
return false
endif
set d = Knock.create(source,target,angle,speed,decrement,KillTree,AllowMove,ConstantSpeed,Chain)
if Count == 0 then
call TimerStart(Timer,TIME,true,function Update)
endif
set Knocker[Count] = d
set Count = Count + 1
return true
endfunction
private function Init takes nothing returns nothing
set TreeRect = Rect(0,0,1,1)
set TreeCheck = Filter(function CheckTrees)
set ChainFilter = Filter(function ChainCheck)
endfunction
endlibrary
JASS:
scope KnockTest initializer Init
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'TEST'
endfunction
private function Actions takes nothing returns nothing
local unit u = GetSpellTargetUnit()
local unit t = GetTriggerUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real tx = GetUnitX(t)
local real ty = GetUnitY(t)
local real a = Atan2(y-ty,x-tx)
call KnockbackTarget(t,u,a,1000,15,true,false,false,true)
set u = null
set t = null
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( t, function Actions )
call TriggerAddCondition(t,Condition(function Conditions))
endfunction
endscope
I included the Test spell in there too , it is a single target unit spell.
EDIT : Alright, made it have no conditions and guess what happened when a unit comes near? The effects gets created and never destroyed and the unit gets stuck at the location forever and cannot hit people. After 3 unit got this bug , the warcraft hanged so I used windows task manager, I assumed that there was a infinite loop.
Last edited: