Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
Hey there. So basically, I need help creating a trigger; this is basically what the trigger has to do:
1. Select every allied unit around the enemy unit that the allied units are attacking.
2. Calculate the distance between wherever the allied unit is and the predetermined never-changing point that all the allied units are supposed to be knockbacked too. This distance will be divided by 5.
3. Move the allied units every 1 second for 5 seconds, until they reach the predetermined - point.
I've looked over every knockback spell guide on here, and they are all either focusing on only one target or have no predetermined point in which the knockbacked units have to reach.
i kinda had this same sort of problem, all the knockback scripts i tried to use didnt seem to work etc. but i posted and aznricepuff showed me one that i really do like.
if you have vJASS/NewGen World Editor this will work, if not then you will need to find other means or wait for another response.
Put both of these into your "header" (click the map at the top when looking at triggers, and paste it in custom scripts)
JASS:
library Geometry
struct Point
real x
real y
static method create takes real x, real y returns Point
local Point p = Point.allocate()
set p.x = x
set p.y = y
return p
endmethod
method getDistanceToPoint takes Point p returns real
local real dx = p.x - .x
local real dy = p.y - .y
return SquareRoot( dx * dx + dy * dy )
endmethod
method getAngletoPoint takes Point p returns real
local real dx = p.x - .x
local real dy = p.y - .y
return Atan2( dy, dx )
endmethod
method calculateDisplacement takes real distance, real angle returns Point
return Point.create( .x + distance * Cos( angle ), .y + distance * Sin( angle ) )
endmethod
static method getDistanceBetweenPoints takes Point p1, Point p2 returns real
local real dx = p2.x - p1.x
local real dy = p2.y - p1.y
return SquareRoot( dx * dx + dy * dy )
endmethod
static method getAngleBetweenPoints takes Point p1, Point p2 returns real
local real dx = p2.x - p1.x
local real dy = p2.y - p1.y
return Atan2( dy, dx )
endmethod
static method pointFromLoc takes location loc returns Point
return Point.create( GetLocationX( loc ), GetLocationY( loc ) )
endmethod
static method pointFromUnit takes unit u returns Point
return Point.create( GetUnitX( u ), GetUnitY( u ) )
endmethod
endstruct
endlibrary
JASS:
library Knockback initializer init requires Geometry
globals
private constant real TIMEOUT = 0.035
private Knockback array knockbackArray
private integer knockbackArraySize = 0
private timer t
endglobals
struct Knockback
unit target //unit being knocked back
real angle //angle (equal to theta in 3D polar coords) of movement direction in radians
real increment //distance to move unit with each loop of timer
real distance //total distance to knock back
real distanceRemaining //distance remaining to knock back
boolean toDestroy = false //whether or not struct needs to be destroyed
//whenever you need to knock back a unit, just call this method
//unit target: unit being knocked back
//real angle: angle (theta) in radians of the direction of the knockback
//real speed: speed (wc3 distance units/second) of knockback
//real distance: distance to knock back
static method create takes unit target, real angle, real speed, real distance returns Knockback
local Knockback temp = Knockback.allocate()
set temp.target = target
set temp.angle = angle
set temp.increment = TIMEOUT * speed
set temp.distance = distance
set temp.distanceRemaining = distance
set knockbackArray[knockbackArraySize] = temp
set knockbackArraySize = knockbackArraySize + 1
if ( knockbackArraySize == 1 ) then
call TimerStart( t, TIMEOUT, true, function Knockback.executeKnockback )
endif
return temp
endmethod
private static method executeKnockback takes nothing returns nothing
local Knockback data
local Point p
local integer i = 0
loop
exitwhen ( i >= knockbackArraySize )
set data = knockbackArray[i]
if ( data.toDestroy ) then //struct needs to be destroyed
set knockbackArray[i] = knockbackArray[knockbackArraySize - 1] //we copy the struct at the last index of the array to the current index
set knockbackArraySize = knockbackArraySize - 1 //decrease size of array by one (technically just decreasing the maximum index of the array that this loop will read
set i = i - 1 //since we decreased the array size by one, we need to decrease i by one otherwise that struct that we copied would not get read by this loop (loop would stop one short of the index for that struct), but since we COPIED that struct to the current index, by decreasing i by one, the next iteration of this loop would result in the loop reading the same index as this iteration, and now that index contains the copied struct
call data.destroy() //destroy the struct to free up memory
else
set p = Point.pointFromUnit( data.target ) //get location of the unit being knocked back
set p = p.calculateDisplacement( data.angle, data.increment ) //calculate the point with a displacement from p equal to the given angle and distance (think of it as a vector in polar form), and save that point in p
call SetUnitPosition( data.target, p.x, p.y ) //set unit position
set data.distanceRemaining = data.distanceRemaining - data.increment //update the distance remaining to knockback
call p.destroy() //destroy the point struct to free up memory
if ( data.distanceRemaining <= 0 ) then //unit has been knocked back far enough
set data.toDestroy = true //slate struct for destruction on next iteration of the timer
endif
endif
set i = i + 1
endloop
if ( knockbackArraySize == 0 ) then
call PauseTimer( t )
endif
endmethod
endstruct
private function init takes nothing returns nothing
set t = CreateTimer()
endfunction
endlibrary
and without testing, i believe the code used would be:
Knockback to Point
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to <Your Ability>
Actions
Set AAA_Point = (Center of Your_Region <gen>)
Unit Group - Pick every unit in (Units within 600.00 of (Position of (Triggering unit)) matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)) and do (Actions)
Loop - Actions
Custom script: local unit picked_unit = GetEnumUnit()
Set AAA_Real_Distance = ((Distance between AAA_Point and (Position of (Picked unit))) / 5.00)
Set AAA_Real_Angle = (Angle from (Position of (Picked unit)) to AAA_Point)
take note anything that usually leaks does in this case.... i cleaned up the local unit that was made, but the rest leaks. unit group and 3 points i believe.
Set AAA_Real_Distance = ((Distance between AAA_Point and (Position of (Picked unit))) / 5.00)
Set AAA_Real_Angle = (Angle from (Position of (Picked unit)) to AAA_Point)
2 leaks of the same position... just set a variable with position of picked unit and use it... then (inside the unit group) clear it by using call RemoveLocation(udg_YOURPOINTVARIABLE)
i kinda had this same sort of problem, all the knockback scripts i tried to use didnt seem to work etc. but i posted and aznricepuff showed me one that i really do like.
if you have vJASS/NewGen World Editor this will work, if not then you will need to find other means or wait for another response.
Put both of these into your "header" (click the map at the top when looking at triggers, and paste it in custom scripts)
JASS:
library Geometry
struct Point
real x
real y
static method create takes real x, real y returns Point
local Point p = Point.allocate()
set p.x = x
set p.y = y
return p
endmethod
method getDistanceToPoint takes Point p returns real
local real dx = p.x - .x
local real dy = p.y - .y
return SquareRoot( dx * dx + dy * dy )
endmethod
method getAngletoPoint takes Point p returns real
local real dx = p.x - .x
local real dy = p.y - .y
return Atan2( dy, dx )
endmethod
method calculateDisplacement takes real distance, real angle returns Point
return Point.create( .x + distance * Cos( angle ), .y + distance * Sin( angle ) )
endmethod
static method getDistanceBetweenPoints takes Point p1, Point p2 returns real
local real dx = p2.x - p1.x
local real dy = p2.y - p1.y
return SquareRoot( dx * dx + dy * dy )
endmethod
static method getAngleBetweenPoints takes Point p1, Point p2 returns real
local real dx = p2.x - p1.x
local real dy = p2.y - p1.y
return Atan2( dy, dx )
endmethod
static method pointFromLoc takes location loc returns Point
return Point.create( GetLocationX( loc ), GetLocationY( loc ) )
endmethod
static method pointFromUnit takes unit u returns Point
return Point.create( GetUnitX( u ), GetUnitY( u ) )
endmethod
endstruct
endlibrary
JASS:
library Knockback initializer init requires Geometry
globals
private constant real TIMEOUT = 0.035
private Knockback array knockbackArray
private integer knockbackArraySize = 0
private timer t
endglobals
struct Knockback
unit target //unit being knocked back
real angle //angle (equal to theta in 3D polar coords) of movement direction in radians
real increment //distance to move unit with each loop of timer
real distance //total distance to knock back
real distanceRemaining //distance remaining to knock back
boolean toDestroy = false //whether or not struct needs to be destroyed
//whenever you need to knock back a unit, just call this method
//unit target: unit being knocked back
//real angle: angle (theta) in radians of the direction of the knockback
//real speed: speed (wc3 distance units/second) of knockback
//real distance: distance to knock back
static method create takes unit target, real angle, real speed, real distance returns Knockback
local Knockback temp = Knockback.allocate()
set temp.target = target
set temp.angle = angle
set temp.increment = TIMEOUT * speed
set temp.distance = distance
set temp.distanceRemaining = distance
set knockbackArray[knockbackArraySize] = temp
set knockbackArraySize = knockbackArraySize + 1
if ( knockbackArraySize == 1 ) then
call TimerStart( t, TIMEOUT, true, function Knockback.executeKnockback )
endif
return temp
endmethod
private static method executeKnockback takes nothing returns nothing
local Knockback data
local Point p
local integer i = 0
loop
exitwhen ( i >= knockbackArraySize )
set data = knockbackArray[i]
if ( data.toDestroy ) then //struct needs to be destroyed
set knockbackArray[i] = knockbackArray[knockbackArraySize - 1] //we copy the struct at the last index of the array to the current index
set knockbackArraySize = knockbackArraySize - 1 //decrease size of array by one (technically just decreasing the maximum index of the array that this loop will read
set i = i - 1 //since we decreased the array size by one, we need to decrease i by one otherwise that struct that we copied would not get read by this loop (loop would stop one short of the index for that struct), but since we COPIED that struct to the current index, by decreasing i by one, the next iteration of this loop would result in the loop reading the same index as this iteration, and now that index contains the copied struct
call data.destroy() //destroy the struct to free up memory
else
set p = Point.pointFromUnit( data.target ) //get location of the unit being knocked back
set p = p.calculateDisplacement( data.angle, data.increment ) //calculate the point with a displacement from p equal to the given angle and distance (think of it as a vector in polar form), and save that point in p
call SetUnitPosition( data.target, p.x, p.y ) //set unit position
set data.distanceRemaining = data.distanceRemaining - data.increment //update the distance remaining to knockback
call p.destroy() //destroy the point struct to free up memory
if ( data.distanceRemaining <= 0 ) then //unit has been knocked back far enough
set data.toDestroy = true //slate struct for destruction on next iteration of the timer
endif
endif
set i = i + 1
endloop
if ( knockbackArraySize == 0 ) then
call PauseTimer( t )
endif
endmethod
endstruct
private function init takes nothing returns nothing
set t = CreateTimer()
endfunction
endlibrary
and without testing, i believe the code used would be:
Knockback to Point
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to <Your Ability>
Actions
Set AAA_Point = (Center of Your_Region <gen>)
Unit Group - Pick every unit in (Units within 600.00 of (Position of (Triggering unit)) matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)) and do (Actions)
Loop - Actions
Custom script: local unit picked_unit = GetEnumUnit()
Set AAA_Real_Distance = ((Distance between AAA_Point and (Position of (Picked unit))) / 5.00)
Set AAA_Real_Angle = (Angle from (Position of (Picked unit)) to AAA_Point)
take note anything that usually leaks does in this case.... i cleaned up the local unit that was made, but the rest leaks. unit group and 3 points i believe.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.