forked from Mirrors/openclonk
Tutorial 4: Improved aiming for bow and spear AIs
parent
4a1a9cc2b0
commit
f51a1f4d68
|
@ -7,8 +7,11 @@ public func AI_IsLoaded() { return !!FindObject(Find_Container(this), Find_ID(Ar
|
|||
public func AI_CommandString() { return "AI_BowAttack"; }
|
||||
public func AI_TargetHittable(object target)
|
||||
{
|
||||
var x = ObjectDistance(target, Contained());
|
||||
return Max(0, - x * (x - 200) / 100);
|
||||
var xDist = target->GetX() - Contained()->GetX();
|
||||
var yDist = target->GetY() - Contained()->GetY();
|
||||
// (vel*vel*vel*vel - g*(g*x*x + 2*y*vel*vel)) <see: AI_BowFirePos()>
|
||||
// vel = 100, g = 20
|
||||
return Max(1, 100000000 - (400*xDist*xDist + yDist*400000));
|
||||
}
|
||||
|
||||
protected func AI_BowAttack(object clonk, int x, int y, object target)
|
||||
|
@ -22,7 +25,6 @@ protected func AI_BowAttack(object clonk, int x, int y, object target)
|
|||
clonk->AddCommand("Acquire", nil, nil, nil, nil, nil, Arrow);
|
||||
return;
|
||||
}
|
||||
// Shoot an arrow. Todo: aim better.
|
||||
AddEffect("AI_BowAim", clonk, 100, 1, this, nil, target);
|
||||
|
||||
clonk->AppendCommand("Wait", nil, 50, nil, nil, nil, 50);
|
||||
|
@ -37,9 +39,15 @@ protected func FxAI_BowAimStart(object clonk, int num, int temporary, object tar
|
|||
EffectVar(0, clonk, num) = target;
|
||||
var dx = target->GetX() - clonk->GetX();
|
||||
var dy = target->GetY() - clonk->GetY();
|
||||
var dist = Distance(0, 0, dx, dy);
|
||||
dy -= dist / 10;
|
||||
ControlUseStart(clonk, dx, dy);
|
||||
//var dist = Distance(0, 0, dx, dy);
|
||||
//dy -= dist / 10;
|
||||
//ControlUseStart(clonk, dx, dy);
|
||||
var aimVector = AI_AimPos(dx, dy, 100, 5);
|
||||
if(aimVector == -1) {
|
||||
ControlUseCancel(clonk,nil,nil);
|
||||
}else{
|
||||
ControlUseStart(clonk, aimVector[0], aimVector[1]);
|
||||
}
|
||||
}
|
||||
|
||||
protected func FxAI_BowAimTimer(object clonk, int num, int time)
|
||||
|
@ -49,10 +57,16 @@ protected func FxAI_BowAimTimer(object clonk, int num, int time)
|
|||
var target = EffectVar(0, clonk, num);
|
||||
var dx = target->GetX() - clonk->GetX();
|
||||
var dy = target->GetY() - clonk->GetY();
|
||||
var dist = Distance(0, 0, dx, dy);
|
||||
dy -= dist / 10;
|
||||
ControlUseHolding(clonk, dx, dy);
|
||||
return 1;
|
||||
//var dist = Distance(0, 0, dx, dy);
|
||||
//dy -= dist / 10;
|
||||
//ControlUseHolding(clonk, dx, dy);
|
||||
var aimVector = AI_AimPos(dx, dy, 100, 5);
|
||||
if(aimVector == -1) {
|
||||
ControlUseCancel(clonk,nil,nil);
|
||||
}else{
|
||||
ControlUseHolding(clonk, aimVector[0], aimVector[1]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected func FxAI_BowAimStop(object clonk, int num, int reason, bool temporary)
|
||||
|
@ -60,37 +74,27 @@ protected func FxAI_BowAimStop(object clonk, int num, int reason, bool temporary
|
|||
var target = EffectVar(0, clonk, num);
|
||||
var dx = target->GetX() - clonk->GetX();
|
||||
var dy = target->GetY() - clonk->GetY();
|
||||
var dist = Distance(0, 0, dx, dy);
|
||||
dy -= dist / 10;
|
||||
ControlUseStop(clonk, dx, dy);
|
||||
return 1;
|
||||
//var dist = Distance(0, 0, dx, dy);
|
||||
//dy -= dist / 10;
|
||||
//ControlUseStop(clonk, dx, dy);
|
||||
var aimVector = AI_AimPos(dx, dy, 100, 5);
|
||||
if(aimVector == -1) {
|
||||
ControlUseCancel(clonk,nil,nil);
|
||||
}else{
|
||||
ControlUseStop(clonk, aimVector[0], aimVector[1]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private func AI_BowFirePos(x, y)
|
||||
//vel = "muzzle velocity" (speed at which the projectile is launched)
|
||||
//spread = variation in aim
|
||||
private func AI_AimPos(int x, int y, int vel, int spread)
|
||||
{
|
||||
var v = 10, // 10 px / tick
|
||||
f = 200, // Fixpunktfaktor
|
||||
g = -GetGravity() * f * f / 1000 / v, // 0,2 px / tick˛
|
||||
x = x * f / v,
|
||||
y = -y * f / v /* Korrektur: */ - Abs(x) * GetGravity() / 2000,
|
||||
d = y * y + x * x,
|
||||
k = y + f * f * f / 2 / g,
|
||||
w = k * k - d;
|
||||
if (w < 0)
|
||||
return;
|
||||
var t1 = Sqrt( (k + Sqrt(w)) * (f * f * f / g) ),
|
||||
t2 = Sqrt( (k - Sqrt(w)) * (f * f * f / g) ),
|
||||
phi1 = ArcCos(x, t1),
|
||||
phi2 = ArcCos(x, t2);
|
||||
if(y < g * t1 / f * t1 / f / f) phi1 = -phi1;
|
||||
if(y < g * t2 / f * t2 / f / f) phi2 = -phi2;
|
||||
// Winkel umrechnen
|
||||
phi1 = (270 - phi1) % 360 - 180;
|
||||
phi2 = 90 - phi2;
|
||||
|
||||
var angle = phi1;
|
||||
if(t2 < t1 * 3)
|
||||
angle = phi2;
|
||||
|
||||
return [Sin(angle, 100), Cos(angle, 100)];
|
||||
y = -y;
|
||||
var g = GetGravity()/5; //FnGetGravity() multiplies actual gravity by 500
|
||||
var root = (vel*vel*vel*vel - g*(g*x*x + 2*y*vel*vel));
|
||||
if(root < 0)
|
||||
return -1;
|
||||
var angle = Angle(0,0,(g*x),vel*vel-Sqrt(root));
|
||||
return [Sin(angle, 100)+Random(2*spread)-spread, Cos(angle, 100)+Random(2*spread)-spread];
|
||||
}
|
|
@ -28,10 +28,16 @@ protected func FxAI_JavelinAimStart(object clonk, int num, int temporary, object
|
|||
return;
|
||||
EffectVar(0, clonk, num) = target;
|
||||
var dx = target->GetX() - clonk->GetX();
|
||||
var dy = target->GetY() - clonk->GetY();
|
||||
var dist = Distance(0, 0, dx, dy);
|
||||
dy -= dist / 10;
|
||||
ControlUseStart(clonk, dx, dy);
|
||||
var dy = target->GetY() - (clonk->GetY()-5);
|
||||
//var dist = Distance(0, 0, dx, dy);
|
||||
//dy -= dist / 10;
|
||||
//ControlUseStart(clonk, dx, dy);
|
||||
var aimVector = AI_AimPos(dx, dy, clonk->GetPhysical("Throw") / 800, 0);
|
||||
if(aimVector == -1) {
|
||||
ControlUseCancel(clonk,nil,nil);
|
||||
}else{
|
||||
ControlUseStart(clonk, aimVector[0], aimVector[1]);
|
||||
}
|
||||
}
|
||||
|
||||
protected func FxAI_JavelinAimTimer(object clonk, int num, int time)
|
||||
|
@ -40,10 +46,16 @@ protected func FxAI_JavelinAimTimer(object clonk, int num, int time)
|
|||
return -1;
|
||||
var target = EffectVar(0, clonk, num);
|
||||
var dx = target->GetX() - clonk->GetX();
|
||||
var dy = target->GetY() - clonk->GetY();
|
||||
var dist = Distance(0, 0, dx, dy);
|
||||
dy -= dist / 10;
|
||||
ControlUseHolding(clonk, dx, dy);
|
||||
var dy = target->GetY() - (clonk->GetY()-5);
|
||||
//var dist = Distance(0, 0, dx, dy);
|
||||
//dy -= dist / 10;
|
||||
//ControlUseHolding(clonk, dx, dy);
|
||||
var aimVector = AI_AimPos(dx, dy, clonk->GetPhysical("Throw") / 800, 0);
|
||||
if(aimVector == -1) {
|
||||
ControlUseCancel(clonk,nil,nil);
|
||||
}else{
|
||||
ControlUseHolding(clonk, aimVector[0], aimVector[1]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -51,9 +63,28 @@ protected func FxAI_JavelinAimStop(object clonk, int num, int reason, bool tempo
|
|||
{
|
||||
var target = EffectVar(0, clonk, num);
|
||||
var dx = target->GetX() - clonk->GetX();
|
||||
var dy = target->GetY() - clonk->GetY();
|
||||
var dist = Distance(0, 0, dx, dy);
|
||||
dy -= dist / 10;
|
||||
ControlUseStop(clonk, dx, dy);
|
||||
var dy = target->GetY() - (clonk->GetY()-5);
|
||||
//var dist = Distance(0, 0, dx, dy);
|
||||
//dy -= dist / 10;
|
||||
//ControlUseStop(clonk, dx, dy);
|
||||
var aimVector = AI_AimPos(dx, dy, clonk->GetPhysical("Throw") / 800, 0);
|
||||
if(aimVector == -1) {
|
||||
ControlUseCancel(clonk,nil,nil);
|
||||
}else{
|
||||
ControlUseStop(clonk, aimVector[0], aimVector[1]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//vel = "muzzle velocity" (speed at which the projectile is launched)
|
||||
//spread = variation in aim
|
||||
private func AI_AimPos(int x, int y, int vel, int spread)
|
||||
{
|
||||
y = -y;
|
||||
var g = GetGravity()/5; //FnGetGravity() multiplies actual gravity by 500
|
||||
var root = (vel*vel*vel*vel - g*(g*x*x + 2*y*vel*vel));
|
||||
if(root < 0)
|
||||
return -1;
|
||||
var angle = Angle(0,0,(g*x),vel*vel-Sqrt(root));
|
||||
return [Sin(angle, 100)+Random(2*spread)-spread, Cos(angle, 100)+Random(2*spread)-spread];
|
||||
}
|
|
@ -7,7 +7,7 @@ protected func AI_RangedAttack(object clonk, int x, int y, object target)
|
|||
clonk->AI_LogCommandStack();
|
||||
clonk->AI_Log("Ranged attack on %v", target);
|
||||
// target in range?
|
||||
if (ObjectDistance(clonk, target) > 400 || target->Contained())
|
||||
if (ObjectDistance(clonk, target) > 1000 || target->Contained())
|
||||
return clonk->AI_Log("Target %v out of range", target);
|
||||
|
||||
// target still alive?
|
||||
|
|
Loading…
Reference in New Issue