forked from Mirrors/openclonk
clean up AI script
parent
80c07d34e4
commit
3fb539522d
|
@ -30,4 +30,27 @@ private func GetTargetYDir(object target, int prec)
|
|||
{
|
||||
var moving_target = GetTargetMovementObject(target);
|
||||
return moving_target->GetYDir(prec);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function: Convert target coordinates and projectile out speed to desired shooting angle. Because
|
||||
// http://en.wikipedia.org/wiki/Trajectory_of_a_projectile says so. No SimFlight checks to check upper
|
||||
// angle (as that is really easy to evade anyway) just always shoot the lower angle if sight is free.
|
||||
private func GetBallisticAngle(int dx, int dy, int v, int max_angle)
|
||||
{
|
||||
// The variable v is in 1/10 pix/frame.
|
||||
// The variable gravity is in 1/100 pix/frame^2.
|
||||
var g = GetGravity();
|
||||
// Correct vertical distance to account for integration error. Engine adds gravity after movement, so
|
||||
// targets fly higher than they should. Thus, we aim lower. we don't know the travel time yet, so we
|
||||
// assume some 90% of v is horizontal (it's ~2px correction for 200px shooting distance).
|
||||
dy += Abs(dx) * g * 10 / (v * 180);
|
||||
// The variable q is in 1/10000 (pix/frame)^4.
|
||||
var q = v**4 - g * (g * dx * dx - 2 * dy * v * v); // dy is negative up
|
||||
if (q < 0)
|
||||
return nil; // Out of range.
|
||||
var a = (Angle(0, 0, g * dx, Sqrt(q) - v * v, 10) + 1800) % 3600 - 1800;
|
||||
// Check bounds.
|
||||
if (!Inside(a, -10 * max_angle, 10 * max_angle))
|
||||
return nil;
|
||||
return a;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
|||
[DefCore]
|
||||
id=AI_Vehicles
|
||||
Version=6,0
|
||||
Category=C4D_StaticBack
|
||||
HideInCreator=true
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
AI Vehicles
|
||||
Functionality that helps the AI use vehicles.
|
||||
|
||||
@author Sven2, Maikel
|
||||
*/
|
||||
|
||||
|
||||
/*-- General Vehicle --*/
|
||||
|
||||
private func ExecuteVehicle(effect fx)
|
||||
{
|
||||
// Do we have a vehicle?
|
||||
if (!fx.vehicle)
|
||||
return false;
|
||||
|
||||
// Use the catapult.
|
||||
if (fx.vehicle->GetID() == Catapult)
|
||||
return ExecuteCatapult(fx);
|
||||
|
||||
// Don't know how to use this vehicle, so reset it.
|
||||
fx.vehicle = nil;
|
||||
return false;
|
||||
}
|
||||
|
||||
private func CheckVehicleAmmo(effect fx, object vehicle)
|
||||
{
|
||||
// Check for specific vehicle.
|
||||
if (vehicle->GetID() == Catapult)
|
||||
{
|
||||
if (CheckCatapultAmmo(fx, vehicle))
|
||||
return true;
|
||||
}
|
||||
// Vehicle out of ammo: Can't really be refilled. Stop using that weapon.
|
||||
fx.vehicle = nil;
|
||||
this->ObjectCommand("UnGrab");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*-- Catapult --*/
|
||||
|
||||
private func ExecuteCatapult(effect fx)
|
||||
{
|
||||
// Still pushing it?
|
||||
if (GetProcedure() != "PUSH" || GetActionTarget() != fx.vehicle)
|
||||
{
|
||||
if (!GetCommand() || !Random(4))
|
||||
SetCommand("Grab", fx.vehicle);
|
||||
return true;
|
||||
}
|
||||
// Target still in guard range?
|
||||
if (!fx.ai->CheckTargetInGuardRange(fx))
|
||||
return false;
|
||||
// Turn in correct direction.
|
||||
var x = GetX(), y = GetY(), tx = fx.target->GetX(), ty = fx.target->GetY() - 4;
|
||||
if (tx > x && !fx.vehicle.dir)
|
||||
{
|
||||
fx.vehicle->ControlRight(this);
|
||||
return true;
|
||||
}
|
||||
if (tx < x && fx.vehicle.dir)
|
||||
{
|
||||
fx.vehicle->ControlLeft(this);
|
||||
return true;
|
||||
}
|
||||
// Make sure we're aiming.
|
||||
if (!fx.aim_weapon)
|
||||
{
|
||||
if (!fx.vehicle->~ControlUseStart(this))
|
||||
return false;
|
||||
fx.aim_weapon = fx.vehicle;
|
||||
fx.aim_time = fx.time;
|
||||
return true;
|
||||
}
|
||||
// Update catapult animation.
|
||||
fx.vehicle->~ControlUseHolding(this, tx - x, ty - y);
|
||||
// Determine power needed to hit target.
|
||||
var dx = tx - x, dy = ty - y + 20;
|
||||
var power = Sqrt((GetGravity() * dx * dx) / Max(Abs(dx) + dy, 1));
|
||||
var dt = dx * 10 / power;
|
||||
tx += fx.ai->GetTargetXDir(fx.target, dt);
|
||||
ty += fx.ai->GetTargetYDir(fx.target, dt);
|
||||
if (!fx.target->GetContact(-1))
|
||||
dy += GetGravity() * dt * dt / 200;
|
||||
power = Sqrt((GetGravity() * dx * dx) / Max(Abs(dx) + dy, 1));
|
||||
power = power + Random(11) - 5;
|
||||
// Limits imposed by catapult.
|
||||
fx.projectile_speed = power = BoundBy(power, 20, 100);
|
||||
// Can shoot now?
|
||||
if (fx.time >= fx.aim_time + fx.aim_wait && PathFree(x, y - 20, x + dx, y + dy - 20))
|
||||
{
|
||||
fx.aim_weapon->~DoFire(this, power, 0);
|
||||
fx.aim_weapon = nil;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private func CheckCatapultAmmo(effect fx, object vehicle)
|
||||
{
|
||||
return vehicle->ContentsCount() > 0;
|
||||
}
|
Loading…
Reference in New Issue