struct bash {
private {
unit b, s;
real dist, mxdist;
real dx, dy;
real dmg;
p_real vec;
integer p;
@ ADDED @
real z;
real vz;
real az;
real zprev;
@ END @
}
/// ----------------------------------------------------------------
// ***
static method create(integer castplayer, unit bashingUnit, unit whichUnit, integer lvl, real distance, real radians, real damage, @real vertAccel, real height@) -> bash {
bash this = allocate();
s = bashingUnit;
b = whichUnit;
dist = distance;
mxdist = SquareRoot(BashPushDistance(lvl));
dx = Cos(radians);
dy = Sin(radians);
vec = pVector(GetUnitX(b), GetUnitY(b), I2R(lvl));
p = castplayer;
dmg = damage;
@ ADDED @
zprev = GetUnitFlyHeight(b);
z = zprev;
az = vertAccel; //added 2 arguments to this method, see above; will have to change arguments to all .create() calls
vz = 2*az*height; //knematics bro
UnitAddAbility(b, 'Amrf');
UnitRemoveAbility(b, 'Amrf');
@ END @
DDSet(b, UNIT_BASH_KEY, 1);
SetUnitTimeScale(b, UNIT_ANIM_SPEED*.01);
if (!IsUnitType(b, UNIT_TYPE_DEAD)) {
SetUnitAnimation(b, UNIT_ANIM_NAME);
QueueUnitAnimation(b, "stand");
}
return this;
}
// ***
method destroy() {
DDSet(b, UNIT_BASH_KEY, 0);
SetUnitTimeScale(b, 1.);
@ SetUnitFlyHeight(b, zprev, 0.00); @
vec.destroy();
s = null;
b = null;
deallocate();
}
method Launch() {
DDStartTim(DD_INTERVAL, true, this, static method() {
bash this = bash( DDTimData() );
integer tick = DDTimTick();
real speed = DD_INTERVAL * (PUSH_SPEED_END + ( (PUSH_SPEED_START-PUSH_SPEED_END)/mxdist )*SquareRoot(dist));
// basic formula for speed: y = a*sqrt(x) + b
// ----------------------------------
// *** Position calcs
dist -= speed;
vec[0] += speed * dx;
vec[1] += speed * dy;
@ vz = vz-az; @
@ z = z+vz; @
// ----------------------------------
// *** Motion
SetUnitX(b, vec[0]);
SetUnitY(b, vec[1]);
@ SetUnitFlyHeight(b, z, 0.00); @
// ----------------------------------
// *** Push Effects
if (ModuloReal(tick*DD_INTERVAL, PUSH_EFFECT_INTERVAL) < DD_INTERVAL)
static if (USE_WATER_FILE)
if (IsTerrainPathable(vec[0], vec[1], PATHING_TYPE_FLOATABILITY))
DestroyEffect(AddSpecialEffect(PUSH_MODEL_FILE, vec[0], vec[1]));
else
DestroyEffect(AddSpecialEffect(PUSH_MODEL_WATER_FILE, vec[0], vec[1]));
else
DestroyEffect(AddSpecialEffect(PUSH_MODEL_FILE, vec[0], vec[1]));
// ----------------------------------------
// *** Check if trees are in the way
static if (DESTROY_TREES)
if (ModuloReal(tick*DD_INTERVAL, CLEAR_TREES_INTERVAL) < DD_INTERVAL) {
DDEnumDestsInRange(vec, CLEAR_TREES_RADIUS, null, function() {
if (DDIsDestructableTree(GetEnumDestructable()))
KillDestructable(GetEnumDestructable());
});
}
// ---------------------------------------------------------
// *** Check for bounce/collision with unpathable points
if (ModuloReal(tick*DD_INTERVAL, CLEAR_TREES_INTERVAL) < DD_INTERVAL) {
if (IsTerrainPathable(vec[0]+BOUNCE_DETECT_RANGE*dx, vec[1], PATHING_TYPE_WALKABILITY))
dx = -dx;
else if (IsTerrainPathable(vec[0], vec[1]+BOUNCE_DETECT_RANGE*dy, PATHING_TYPE_WALKABILITY))
dy = -dy;
}
// ----------------------------------------
// *** Check if there are any units to be splash bashed
static if (ENABLE_SPLASH_BASH)
if (speed > SPLASH_BASH_NEED_SPEED*DD_INTERVAL && ModuloReal(tick*DD_INTERVAL, SPLASH_BASH_INTERVAL) < DD_INTERVAL)
TryDoSplashBash();
// ----------------------------------
// *** Check to quit push
@ if ((dist <= 0.) and (z <= zprev)) { @ //Now we check to make sure the vertical displacement is done too.
PauseUnit(b, false);
destroy();
DDQuitTim();
}
});
}