| 03-17-2009, 04:04 AM | #1 |
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. |
| 03-18-2009, 02:37 AM | #2 |
Bump, code update 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.50 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 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 target != GetFilterUnit() 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 set d.hit = NewGroup() 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 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) call ReleaseGroup(this.hit) 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 set sx = GetUnitX(u) set sy = GetUnitY(u) set source = d.source set target = d.target call GroupEnumUnitsInRange(ENUM_GROUP,sx,sy,CHAINRADIUS,ChainFilter) loop set t = FirstOfGroup(ENUM_GROUP) 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 call BJDebugMsg("working now") endif call GroupRemoveUnit(ENUM_GROUP, 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 set t = 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 |
| 03-19-2009, 04:55 AM | #3 |
Bump. |
| 03-19-2009, 01:57 PM | #4 |
I am quite sure people read your thread the first time. It's very hard to fix code when the problem is not described... I am not even sure what the code is supposed to do... If I read the code correctly, you use this chain group to avoid adding a unit twice, however, in another part of the code, you are emptying the chain group, that's probably not a good idea. |
| 03-19-2009, 02:55 PM | #5 |
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!!!! // //****************************************************************************** //* Formula to calculate the distance * //* - 1 * V * V / ( 2 * A / Interval) * //* Variable V = The amount of speed the knockedback unit has * //* Variable A = The amount of speed reduced per Interval * //* Variable Interval = Located at the top of the Knockback System * //* * //* Some things to note about them * //* Variable A must be a positive number * //* Variable B must be a negative number * //* * //* * //* * //* * //****************************************************************************** library Knockback initializer Init requires BoundSentinel, DestructableLib, IsTerrainWalkable, GroupUtils globals private constant real TIME = 0.03 private constant real CHAINRADIUS = 100 private constant real SPEEDFACTOR = 0.90 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 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 target != GetFilterUnit() 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 set d.hit = NewGroup() 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 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) call ReleaseGroup(this.hit) 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 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 mode = d.EffectMode set x = GetUnitX(u) set y = GetUnitY(u) 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 else set x = x + d.speed * d.cos set y = y + d.speed * d.sin set d.EffectMode = d.TerrainCheck(d) if d.AllowMove == true then call SetUnitX(u,x) call SetUnitY(u,y) else call SetUnitPosition(u,x,y) endif if d.Trees == true then call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS) call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees) endif 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 set d.speed = d.speed - d.decrement if d.chain == true then set source = d.source set target = d.target call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter) loop set t = FirstOfGroup(ENUM_GROUP) 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(y-cy,x-cx),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 call BJDebugMsg("working now") endif call GroupRemoveUnit(ENUM_GROUP, t) endloop endif endif set i = i - 1 endloop set u = null set t = 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 Updated code. It mysteriously doesn't freeze much after I moved this JASS:set d.speed = d.speed - d.decrement above the chain code. Right now, the units that are getting chain knockedback , aren't moving much at all, they just move like 50 distance only. Sometimes when it hits about 8 units at once , it will lag for about 2 seconds. |
