- Joined
- Nov 4, 2007
- Messages
- 337
peq - jass-Code #1327 //***************************************************************************************************************
I have seen many knockback systems yet.
But almost all GUI-Triggerers complained about them,
because they are too complicated.
Also the other ones have bugs.
Units can slide into water.
So I created a new Knockback System;
The safest Knockback-System.
The easiest one to implement.
And the easiest one to make it fit your needs.
So here my System and its propertie;
* ================================ *
* P R O S A N D C O N T R A S *
* ================================ *
compared to other knockback-systems
[+]
1. This knockback system is very userfriendly. You cant make any other knockback-system fit your
needs as easily as with this.
2. This knockback system is also very userfriendly for only GUI-users, because there are unique options
which make it easy with GUI-triggers to knockback units.
You dont need any custom scripts.
3. This system has a great performance.
It uses structs, clears them up, uses coordinates, rects to kill trees, nulls local variables,
creates only two dummies and keeps them, uses fast Attachment Systems (3 systems choosable.
All made by me) and so on.
4. The implemantion is very easy, because of the used libraries.
5. This system is clear of bugs.
When units hit trees, the trees get killed.
When units hit water, the knockback stops.
Units cant slide out of the map.
6. This systems has the most parameters.
Other Systems have a constant speed and friction and
you can just choose how long you want to knockback them
(range). With this system you can also chose the speed and
friction.
[-]
1. You have to create two dummy-units to use the knockback-system
2. There are faster systems
=======================================================
Help for non-JASSers
==== E N G L I S H ====
I prepared some GUI-functions for people who dont understand JASS.
These GUI-functions are found beneath 'Additional Service'.
In the trigger 'Global Knockback Parameters' there is a list with units.
If you want a unit to knockback another unit, you can put that unit
that shall knockback in the list and set Speed, Range and Friction
to the values you want.
Alternatively you can declare the variables with the prefix Glob
and run the trigger 'GlobalKnockBack' then.
==== D E U T S C H ====
Für Diejenigen, die kein JASS können, habe ich einige GUI-Funktionen
vorbereitet, welche unter 'Additional Service' gefunden werden können.
In dem Auslöser 'Global Knockback Parameters' befindet sich eine Liste mit
Einheiten. Wenn du willst, dass eine Einheit eine andere zurückschleudert,
kannst du diese Einheit in die dortige Liste eintragen, inklusive der Daten
'Speed', 'Range' und 'Friction'.
Alternativ kannst du auch die Variablen mit dem Präfix Glob bestimmen
und den Auslöser 'GlobalKnockBack' starten.
==== You should check the header* of the map and configure the Knockback_System ====
==== Du solltest unbedingt in den Header* der map schauen und das System konfigurieren ====
*header is the little scroll on top of all trigger folders with the name of your map.
*Der Header ist die kleine Rolle über allen Auslöser-Ordnern und hat den Namen deiner Map.
PLEASE GIVE CREDITS WHEN YOU USE THIS KNOCKBACK SYSTEM
BITTE GIB MIR CREDITS, WENN DU DIESES SYSTEM BENUTZT.
=================================================
And now the code:
Important!
The example map:
http://www.speedyshare.com/700977292.html
I have seen many knockback systems yet.
But almost all GUI-Triggerers complained about them,
because they are too complicated.
Also the other ones have bugs.
Units can slide into water.
So I created a new Knockback System;
The safest Knockback-System.
The easiest one to implement.
And the easiest one to make it fit your needs.
So here my System and its propertie;
* ================================ *
* P R O S A N D C O N T R A S *
* ================================ *
compared to other knockback-systems
[+]
1. This knockback system is very userfriendly. You cant make any other knockback-system fit your
needs as easily as with this.
2. This knockback system is also very userfriendly for only GUI-users, because there are unique options
which make it easy with GUI-triggers to knockback units.
You dont need any custom scripts.
3. This system has a great performance.
It uses structs, clears them up, uses coordinates, rects to kill trees, nulls local variables,
creates only two dummies and keeps them, uses fast Attachment Systems (3 systems choosable.
All made by me) and so on.
4. The implemantion is very easy, because of the used libraries.
5. This system is clear of bugs.
When units hit trees, the trees get killed.
When units hit water, the knockback stops.
Units cant slide out of the map.
6. This systems has the most parameters.
Other Systems have a constant speed and friction and
you can just choose how long you want to knockback them
(range). With this system you can also chose the speed and
friction.
[-]
1. You have to create two dummy-units to use the knockback-system
2. There are faster systems
=======================================================
Help for non-JASSers
==== E N G L I S H ====
I prepared some GUI-functions for people who dont understand JASS.
These GUI-functions are found beneath 'Additional Service'.
In the trigger 'Global Knockback Parameters' there is a list with units.
If you want a unit to knockback another unit, you can put that unit
that shall knockback in the list and set Speed, Range and Friction
to the values you want.
Alternatively you can declare the variables with the prefix Glob
and run the trigger 'GlobalKnockBack' then.
==== D E U T S C H ====
Für Diejenigen, die kein JASS können, habe ich einige GUI-Funktionen
vorbereitet, welche unter 'Additional Service' gefunden werden können.
In dem Auslöser 'Global Knockback Parameters' befindet sich eine Liste mit
Einheiten. Wenn du willst, dass eine Einheit eine andere zurückschleudert,
kannst du diese Einheit in die dortige Liste eintragen, inklusive der Daten
'Speed', 'Range' und 'Friction'.
Alternativ kannst du auch die Variablen mit dem Präfix Glob bestimmen
und den Auslöser 'GlobalKnockBack' starten.
==== You should check the header* of the map and configure the Knockback_System ====
==== Du solltest unbedingt in den Header* der map schauen und das System konfigurieren ====
*header is the little scroll on top of all trigger folders with the name of your map.
*Der Header ist die kleine Rolle über allen Auslöser-Ordnern und hat den Namen deiner Map.
PLEASE GIVE CREDITS WHEN YOU USE THIS KNOCKBACK SYSTEM
BITTE GIB MIR CREDITS, WENN DU DIESES SYSTEM BENUTZT.
=================================================
And now the code:
JASS:
//***************************************************************************************************************
//* *
//* K N O C K B A C K *
//* Actual Code *
//* v1.27 *
//* *
//* By: Mr.Malte *
//* *
//***************************************************************************************************************
// ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//¤ Requires JassNewGenPack Editor!
//¤ Knockback System v1.27
//¤ Requires swimming dummy
//¤ Requires non-swimming dummy
//¤
//¤¤ USED SYSTEMS:
//¤
//¤ - My TSA System; Timer Struct Attachment.
//¤ - My HA System; Handle Attachment.
//¤ - My GCSA System; Game Cache Struct Attachment.
//¤ SPECIAL THANKS TO:
//¤
//¤ - Vexorian for JassNewGenPack
//¤ - Mueslirocker for SetUnitXY function
// ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//! Note!
// If you want one of my systems, TimerStructAttachment or HandleAttachment, give credits!
//! GIVE CREDITS WHEN YOU USE THE KNOCKBACK SYSTEM!
// If you want to edit the knockback System, change the values of the section
// "Configurable Data".
function GlobalKnockBack takes nothing returns nothing
call Knockback(udg_GlobOpfer, udg_GlobAtk, udg_GlobSpeed, udg_GlobDistanz, udg_GlobFriction, udg_GlobShowEffects)
endfunction
library KnockBackFunctions initializer KnockBackInit
globals
// * ================================== *
// * C O N F I G U R A B L E D A T A *
// * ================================== *
//! ====TIMER_INTERVAL====
// A higher number will increase the performance
// A lower number will make the knockback smoother
// !Note!- if you increase the speed of the timer, the units wont slide faster.
// The speed will be kept.
//! ====DUST_DENSITY====
// Every TIMER_INTERVAL * DUST_DENSITY seconds a dust effect is shown.
// Decrease DUST_DENSITY to create more densitive dust (recommended for fast-speed-knockbacks)
// Increase DUST_DENSITY to increase the performance ( recommended, when many units at the same time are knocked back)
//! ====DUST_MODEL====
// This Model is the dust that is shown. If you want to know the string of another model, go
// to the object-editor, chose your model somewhere and press ok.
// If you click on your model-field again, the string of the model is shown
// at 'Own'.
// Important: You must replace '\' in the string with '\\'
//! ====DUMMY_TYPE[1]=====
// If RETQUIRES_UNBLOCKED is true, you need two dummy units;
// DUMMY_TYPE[1] must be able to swim.
// DUMMY_TYPE[2] mustn't be able to swim.
// DUMMY_TYPE[3] must be like a normal unit; It must have collision and needs movetype walking.
//! ====DUMMY_TYPE[2]=====
// If RETQUIRES_UNBLOCKED is true, you need two dummy units;
// DUMMY_TYPE[1] must be able to swim.
// DUMMY_TYPE[2] mustn't be able to swim.
// DUMMY_TYPE[3] must be like a normal unit; It must have collision and needs movetype walking.
//! ====DUMMY_TYPE[3]=====
// If RETQUIRES_UNBLOCKED is true, you need two dummy units;
// DUMMY_TYPE[1] must be able to swim.
// DUMMY_TYPE[2] mustn't be able to swim.
// DUMMY_TYPE[3] must be like a normal unit; It must have collision and needs movetype walking.
//! ====ATTACHMENT_SYSTEM=====
//! JUST FOR FUNCTIOM 'PRECISE_KNOCKBACK'
// This is the system which is used to attach the parameters
// of the knockback to the timer that works with them.
// Possible options;
// "TimerStructAttachment"
// "HandleAttachment"
// "Game Cache"
// If ATTACHMENT_SYSTEM is "TimerStructAttachment",
// the Knockback-System is not as fast as with "HandleAttachment", but you can run 500 knockbacks (configurable)
// at the same time without any bugs.
// If ATTACHMENT_SYSTEM is "HandleAttachment",
// the system is faster, that means less lag, but if
// your map contains a lot of units and timers and blablabla. Handles.
// Then bugs could appear.
// Actually this system is the best choice, because of the speed.
// But if the system says "HandleAttachment System is too full." somewhen,
// you should swap to the TimerStructAttachment or Game Cache
// If ATTACHMENT_SYSTEM is "Game Cache",
// you use the savest, but also the slowest Attachment System.
// You should only use this, if both systems, TSA and HA give error
// messages.
//! ====KILLTREE_RADIUS=====
// Units destroy trees in this radius.
// You can also use the function Precise_Knockback to make an individual KILLTRE_RADIUS for each knockback.
//! ====PERCENTAGE_KNOCKBACK=====
// This number should be 1.00
// 1.00 means, that the speed and friction of all Knockbacks is
// Speed*1.00 and Friction*1.00
//! =====MOVEBACK=====
// If a unit hits water, it gets moved back by this amount.
// Choose a higher number if units stuck in water often.
//! =====UNBLOCK_FACTOR=====
// If this is 0, units slide through everything and kill trees.
// If this is 1, units don't slide through water
// If this is 2 or higher, units can't do anything while
// They are knocked back, and the knockback stops if a unit
// can't stand on the new point. That means the Knockback is stopped
// by: Cliffs, units, water, doodads. By everything.
// If the UNBLOCK_FACTOR is higher than 0 and the unit is not moved, the knockback
// stops instantly.
//! =====DISPLAYCREDITS_AFTER=====
// After this real the game tells you that the Knockbacksystem was made by me.
private constant real TIMER_INTERVAL = 0.033
private constant integer DUST_DENSITY = 11
private constant string DUST_MODEL = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
private constant boolean REQUIRES_UNBLOCKED = true
private constant integer DUMMY_TYPE1 = 'e000'
private constant integer DUMMY_TYPE2 = 'e001'
private constant integer DUMMY_TYPE3 = 'e002'
private constant real KILLTREE_RADIUS = 110.
private real PERCENTAGE_KNOCKBACK = 2.00
private constant real MOVEBACK = 30.
private constant integer UNBLOCK_FACTOR = 1
private constant string AUTHOR = "Mr.Malte"
endglobals
private function h2i takes handle h returns integer
return h
return 0
endfunction
private function Debug takes string s returns nothing
call DisplayTextToForce(GetPlayersAll(),s)
endfunction
// End of Handle Attachment System
public struct KB
boolean bool
integer kbi
integer up
real speed
real distanz
real friction
real slidet
real killtreerange
real sin
real cos
unit atk
unit opfer
endstruct
globals
private real minx
private real maxx
private real miny
private real maxy
private integer CC
private unit array Converted
private integer Total = 0
private KB array Knockbackdata
private boolexpr Treekillcondition = null
private timer KnockbackTimer = CreateTimer()
private boolean IsTimerRunning = false
private integer up = 0
private boolean showdust = false
private boolean Knock_GoOn = true
private unit IsWalkableDummy = null
private boolean IsStolen = false
endglobals
function SetUnitXY takes unit u, real x, real y returns boolean
if x < minx then
set u = null
return false
elseif x > maxx then
set u = null
return false
else
call SetUnitX(u, x)
endif
if y < miny then
set u = null
return false
elseif y > maxy then
set u = null
return false
else
call SetUnitY (u, y)
endif
set u = null
return false
endfunction
function IsPointWalkable takes real newx, real newy returns boolean
// SetUnitPosition setzt eine Einheit auf eine Stelle, wenn diese
// für die Einheit begehbar ist.
// Die Einheit wird also auf die neuen Koordinaten mit der Funktion
// gesetzt. Wenn die Koordinaten der Einheit nach SetUnitPosition
// newx und newy entsrpechen, kann die Einheit dort stehen.
call SetUnitPosition(IsWalkableDummy,newx,newy)
if ( GetUnitX(IsWalkableDummy) == newx and GetUnitY(IsWalkableDummy) == newy ) then
return true
endif
return false
endfunction
private function IsWaterLoc takes real x, real y returns boolean
call SetUnitPosition(udg_Knockback_Dummy1,x,y)
call SetUnitPosition(udg_Knockback_Dummy2,x,y)
if ( GetUnitX(udg_Knockback_Dummy1) == GetUnitX(udg_Knockback_Dummy2) and GetUnitY(udg_Knockback_Dummy1) == GetUnitY(udg_Knockback_Dummy2)) then
return false
endif
return true
endfunction
public function TreeFilter takes nothing returns boolean
local integer d = GetDestructableTypeId(GetFilterDestructable())
return d == 'ATtr' or d == 'BTtw' or d == 'KTtw' or d == 'YTft' or d == 'JTct' or d == 'YTst' or d == 'YTct' or d == 'YTwt' or d == 'JTwt' or d == 'JTwt' or d == 'FTtw' or d == 'CTtr' or d == 'ITtw' or d == 'NTtw' or d == 'OTtw' or d == 'ZTtw' or d == 'WTst' or d == 'LTlt' or d == 'GTsh' or d == 'Xtlt' or d == 'WTtw' or d == 'Attc' or d == 'BTtc' or d == 'CTtc' or d == 'ITtc' or d == 'NTtc' or d == 'ZTtc'
endfunction
function UpdateTotal takes nothing returns nothing
local integer i = 201
loop
exitwhen i == 0
set i = i - 1
if ( Knockbackdata[i] != null ) then
set Total = i
set i = 200
return
endif
endloop
endfunction
private function KillTree takes nothing returns nothing
call KillDestructable(GetEnumDestructable())
endfunction
// STRUCT FUNCTIONS
function PushUp_Structs takes integer fromwhere returns nothing
local integer i = fromwhere
loop
set i = i + 1
exitwhen i > Total
set Knockbackdata[i-1] = Knockbackdata[i]
endloop
set Total = Total - 1
endfunction
function FreePlace_Structs takes integer ib returns nothing
set Knockbackdata[ib] = Knockbackdata[Total]
set Total = Total - 1
endfunction
// ENDSTRUCT FUNCTIONS
private function KnockbackCreate takes nothing returns nothing
//local timer expired = GetExpiredTimer() // Used for the system - means not important for you
local integer structNR
local KB knock
local integer ib = 0 // Used for the system
local real x = 0. // Used for the system
local real y = 0. // Used for the system
local real newx = 0. // Used for the system
local real newy = 0. // Used for the system
local effect e = null // Used for the system
local real angle = 0. // Used for the system
local real speed //= knock.speed // The speed the target slides with
local real distanz //= knock.distanz // Distance the target unit slides
local boolean bool //= knock.bool // Show effects? True and the effect is shown.
local rect killtrees
if ( IsStolen == true ) then
return
endif
if (up == DUST_DENSITY) then // up is used to count up an integer. When the integer hits the constant integer DUST_DENSITY (basic 7), the dust is shown - to decrease lagg
set up = 0
set showdust = true
endif
loop
set ib = ib + 1
exitwhen ib > Total
set Knock_GoOn = true
set knock = Knockbackdata[ib]
set speed = knock.speed
set distanz = knock.distanz
set bool = knock.bool
set x = GetUnitX(knock.opfer)
set y = GetUnitY(knock.opfer)
set angle = Atan2(y - GetUnitY(knock.atk), x - GetUnitX(knock.atk))
set killtrees = Rect(x - knock.killtreerange, y - knock.killtreerange, x + knock.killtreerange, y + knock.killtreerange)
set speed = speed - knock.friction
set knock.speed = speed
set knock.slidet = knock.slidet + speed
set newx = x + speed * knock.cos
set newy = y + speed * knock.sin
call EnumDestructablesInRect(killtrees, Treekillcondition, function KillTree)
call RemoveRect(killtrees)
// Stop Knockback when unit hits water
if ( UNBLOCK_FACTOR == 1 ) then
if ( IsWaterLoc(newx,newy) ) then
set newx = x - MOVEBACK * knock.cos
set newy = y - MOVEBACK * knock.sin
call SetUnitXY(knock.opfer, newx, newy)
call PauseUnit(knock.opfer,false)
call RemoveRect(killtrees)
//set Knockbackdata[Total] = Knockbackdata[ib]
//set Total = Total - 1
set killtrees = null
call knock.destroy()
//set Total = Total - 1
call FreePlace_Structs(ib)
//call PushUp_Structs(ib)
set Knock_GoOn = false
//set expired = null
endif
endif
if ( UNBLOCK_FACTOR == 2 ) then
if ( IsPointWalkable(newx,newy) == false ) then
call PauseUnit(knock.opfer,false)
call RemoveRect(killtrees)
set killtrees = null
call knock.destroy()
call FreePlace_Structs(ib)
//call PushUp_Structs(ib)
//set Total = Total - 1
set Knock_GoOn = false
endif
endif
// Change coordinates
if ( Knock_GoOn == true ) then
call SetUnitXY(knock.opfer, newx, newy)
call RemoveRect(killtrees)
set killtrees = null
// Show dust
if ( showdust ) then
if ( knock.bool == true ) then
call DestroyEffect(AddSpecialEffect(DUST_MODEL, x, y))
endif
endif
// End knockback?
if ( speed < 0.1 ) then
call PauseUnit(knock.opfer,false)
call knock.destroy()
call FreePlace_Structs(ib)
//call PushUp_Structs(ib)
//set Total = Total - 1
endif
if ( knock.slidet > distanz ) then
call PauseUnit(knock.opfer,false)
call knock.destroy()
call FreePlace_Structs(ib)
//call PushUp_Structs(ib)
//set Total = Total - 1
endif
endif
endloop
if ( Total == 0 ) then
call PauseTimer(KnockbackTimer)
set IsTimerRunning = false
endif
set up = up + 1
set showdust = false
endfunction
function Knockback takes unit opfer, unit atk, real speed, real distanz, real friction, boolean b returns nothing
local KB knock = KB.create()
local real angle
set speed = (speed * (TIMER_INTERVAL*25)) * PERCENTAGE_KNOCKBACK
set friction = (friction * (TIMER_INTERVAL*25)) * PERCENTAGE_KNOCKBACK
set knock.opfer = opfer
set knock.atk = atk
set knock.speed = speed
set knock.distanz = distanz
set knock.slidet = 10.
set knock.friction = friction
set knock.bool = b
set knock.killtreerange = KILLTREE_RADIUS
set Total = Total + 1
set angle = Atan2(GetUnitY(opfer) - GetUnitY(atk), GetUnitX(opfer) - GetUnitX(atk))
set knock.cos = Cos(angle)
set knock.sin = Sin(angle)
if ( Total > 200 ) then
call UpdateTotal()
endif
set Knockbackdata[Total] = knock
if ( IsTimerRunning == false ) then
call TimerStart(KnockbackTimer, TIMER_INTERVAL, true, function KnockbackCreate)
set IsTimerRunning = true
endif
set opfer = null
set b = false
endfunction
function SetKnockbackFactor takes real newPercentage returns nothing
set PERCENTAGE_KNOCKBACK = newPercentage
endfunction
private function KnockBackInit takes nothing returns nothing
local location temppoint = null
set minx = GetRectMinX(bj_mapInitialPlayableArea)
set maxx = GetRectMaxX(bj_mapInitialPlayableArea)
set miny = GetRectMinY(bj_mapInitialPlayableArea)
set maxy = GetRectMaxY(bj_mapInitialPlayableArea)
if ( 0 == 0 ) then
set temppoint = GetRectCenter(GetPlayableMapRect())
call CreateUnitAtLoc(Player(15),DUMMY_TYPE1,temppoint,270.)
set udg_Knockback_Dummy1 = GetLastCreatedUnit()
call CreateUnitAtLoc(Player(15),DUMMY_TYPE2,temppoint,270.)
set udg_Knockback_Dummy2 = GetLastCreatedUnit()
//set IsWalkableDummy = CreateUnitAtLoc(Player(15),DUMMY_TYPE3,temppoint,270.)
call RemoveLocation(temppoint)
endif
set Treekillcondition = Filter(function TreeFilter)
endfunction
function Trig_Knockback_Init_Dummies_Func002A takes nothing returns nothing
set udg_Knockback_Dummy2 = GetEnumUnit()
endfunction
function Trig_Knockback_Init_Dummies_Func003A takes nothing returns nothing
set udg_Knockback_Dummy1 = GetEnumUnit()
endfunction
function Knockback_Init takes nothing returns nothing
call ForGroupBJ( GetUnitsOfTypeIdAll(DUMMY_TYPE2), function Trig_Knockback_Init_Dummies_Func002A )
call ForGroupBJ( GetUnitsOfTypeIdAll(DUMMY_TYPE1), function Trig_Knockback_Init_Dummies_Func003A )
endfunction
function ConvertToUnitArray takes nothing returns nothing
set CC = CC + 1
set Converted[CC] = GetEnumUnit()
endfunction
function KnockbackGroup takes group g, unit atk, real speed, real distanz, real friction, boolean b returns nothing
local integer i = 0
call ForGroup(g, function CovertToUnitArray)
loop
set i = i + 1
exitwhen i > CC
call Knockback(Converted[i],atk,speed,distanz,friction,b)
set Converted[i] = null
endloop
endfunction
endlibrary
// End of Knockback System by Mr.Malte
Important!
The example map:
http://www.speedyshare.com/700977292.html
Last edited: