Name | Type | is_array | initial_value |
//TESH.scrollpos=0
//TESH.alwaysfold=0
//! zinc
library ArrowKnockback{
// CHANGEABLE
// This is the Timer Time
constant real LoopTime = 0.0325;
// This is the AoE where it picks up Units for the Knockback
constant real PickUpAoE = 140;
// This is the Range how much the Knockbacked Units get moved (Multiplied by Level)
constant real kRange = 100;
// This is the Range how mucbh the Arrow will move (Multiplied by Level)
constant real aRange = 750;
// This is the Speed of the Arrow (per Second)
constant real aSpeed = 750;
// This is the Speed of the Knockbacked Units (per Second)
constant real kSpeed = 300;
// This is the Damage a Unit gets when hitted (Multiplied by Level)
constant real kDamage = 150;
// This is the Effect
constant string speEffect = "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl";
// This is the Spell ID
constant integer aID = 'A000';
// This is the Dummy ID
constant integer dID = 'h000';
// How often should the Effect come (every LoopTime +1)
constant integer speTime = 12;
// NONCHANGEABLE
integer aLevel;
location aPos;
constant integer Angle = 1;
constant integer Level = 2;
constant integer Range = 3;
constant integer Unit = 4;
constant integer Time = 5;
constant integer Effect = 6;
group NoStack = CreateGroup();
unit Arrow;
hashtable AKHash = InitHashtable();
function IsAbility() -> boolean{if ( GetSpellAbilityId() == aID ){return true;}else{return false;}}
function GroupCon() -> boolean {
if ( IsUnitAliveBJ(GetFilterUnit()) == true && IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(Arrow)) == true && IsUnitInGroup(GetFilterUnit(), NoStack) == false && IsUnitAliveBJ(Arrow) == true ){
return true;} else { return false; }
}
function KnockbackLoop(){
handle q = GetExpiredTimer();
integer h = GetHandleId(q);
real angle = LoadReal( AKHash, h, Angle);
real range = LoadReal( AKHash, h, Range);
unit u = LoadUnitHandle( AKHash, h, Unit);
integer i = LoadInteger( AKHash, h, Effect);
real speed = kSpeed*LoopTime;
real x = GetUnitX(u) + (speed) * Cos(angle * bj_DEGTORAD);
real y = GetUnitY(u) + (speed) * Sin(angle * bj_DEGTORAD);
if ( IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) == true) {
angle = 0 - angle;
x = GetUnitX(u) + (speed) * Cos(angle * bj_DEGTORAD);
y = GetUnitY(u) + (speed) * Sin(angle * bj_DEGTORAD);
if ( IsTerrainPathable( x, y, PATHING_TYPE_WALKABILITY) == true) {
angle = angle -180;
x = GetUnitX(u) + (speed) * Cos(angle * bj_DEGTORAD);
y = GetUnitY(u) + (speed) * Sin(angle * bj_DEGTORAD);
}
}
if ( i >= speTime ){ DestroyEffect(AddSpecialEffect( speEffect, x, y)); i = 0;}
SetUnitPosition( u, x, y);
range = range - speed;
SaveReal( AKHash, h, Range, range);
SaveReal( AKHash, h, Angle, angle);
SaveInteger( AKHash, h, Effect, i + 1);
if (range <= 0){
DestroyTimer(GetExpiredTimer());
SetUnitPathing( u, true );
GroupRemoveUnit( NoStack, u);
} else if ( GetUnitState( u, UNIT_STATE_LIFE) <= 0 ) { DestroyTimer(GetExpiredTimer()); GroupRemoveUnit( NoStack, u); SetUnitPathing( u, true );}
}
function Knockback(){
unit u = GetEnumUnit();
real x = GetUnitX(u);
real y = GetUnitY(u);
timer t = CreateTimer();
handle q = t;
integer h = GetHandleId(q);
real angle = AngleBetweenPoints( aPos, Location(x, y));
DestroyEffect(AddSpecialEffect( speEffect, x, y));
SaveReal( AKHash, h, Range, aLevel * kRange);
SaveReal( AKHash, h, Angle, angle);
SaveUnitHandle( AKHash, h, Unit, u);
UnitDamageTarget( Arrow, u, kDamage * aLevel, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
GroupAddUnit( NoStack, u);
SetUnitPathing( u, false );
TimerStart(t, LoopTime, true, function KnockbackLoop);
}
function Loop(){
handle q = GetExpiredTimer();
integer h = GetHandleId(q);
real angle = LoadReal( AKHash, h, Angle);
integer level = LoadInteger( AKHash, h, Level);
real range = LoadReal( AKHash, h, Range);
unit u = LoadUnitHandle( AKHash, h, Unit);
real speed = aSpeed*LoopTime;
real x = GetUnitX(u) + (speed) * Cos(angle * bj_DEGTORAD);
real y = GetUnitY(u) + (speed) * Sin(angle * bj_DEGTORAD);
group g = CreateGroup();
if ( IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) == true) {
angle = 0 - angle;
x = GetUnitX(u) + (speed) * Cos(angle * bj_DEGTORAD);
y = GetUnitY(u) + (speed) * Sin(angle * bj_DEGTORAD);
if ( IsTerrainPathable( x, y, PATHING_TYPE_WALKABILITY) == true) {
angle = angle -180;
x = GetUnitX(u) + (speed) * Cos(angle * bj_DEGTORAD);
y = GetUnitY(u) + (speed) * Sin(angle * bj_DEGTORAD);
}
}
Arrow = u;
aLevel = level;
aPos = Location(GetUnitX(u), GetUnitY(u));
GroupEnumUnitsInRange( g, x, y, PickUpAoE, Condition(function GroupCon));
ForGroup( g, function Knockback);
SetUnitFacing( u, angle);
SetUnitPosition( u, x, y);
range = range - speed;
SaveReal( AKHash, h, Range, range);
SaveReal( AKHash, h, Angle, angle);
if (range <= 0){
DestroyTimer(GetExpiredTimer());
RemoveUnit( u);
}
DestroyGroup(g);
}
function Cast(){
unit u = GetTriggerUnit();
real x = GetUnitX(u);
real y = GetUnitY(u);
timer t = CreateTimer();
handle q = t;
location p = GetSpellTargetLoc();
real angle = AngleBetweenPoints(Location(x, y), p);
unit dummy = CreateUnit ( Player(GetPlayerId(GetOwningPlayer(u))), dID, x, y, angle);
integer h = GetHandleId(q);
integer level = GetUnitAbilityLevel( u, aID);
SaveReal( AKHash, h, Angle, angle);
SaveInteger( AKHash, h, Level, level);
SaveReal( AKHash, h, Range, level * aRange);
SaveUnitHandle( AKHash, h, Unit, dummy);
RemoveLocation(p);
TimerStart(t, LoopTime, true, function Loop);
}
function onInit(){
trigger t = CreateTrigger( );
TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT );
TriggerAddCondition( t, Condition( function IsAbility ) );
TriggerAddAction( t, function Cast );
}
}
//! endzinc