improve enemy finding for defense AI

The path finder seems quite slow if a lot of AI enemies are around and can't find a path...
install-platforms
Maikel de Vries 2018-01-23 11:35:47 +01:00
parent 26fe0d089a
commit 65c279233e
6 changed files with 47 additions and 12 deletions

View File

@ -12,6 +12,15 @@
local AltTargetDistance = 400; // Use the scenario given target if normal AI target is further away than this distance.
// Special settings for the defense AI.
public func AddAI(object clonk, id type)
{
var fx_ai = inherited(clonk, type, ...);
// Make AI aggressive.
fx_ai.is_aggressive = true;
return fx_ai;
}
// Alternative target finding for defense scenarios: partially controlled by the scenario script.
public func FindTarget(effect fx)
{
@ -27,8 +36,8 @@ public func FindTarget(effect fx)
// If target can't be attacked just take normal target again.
if (!this->HasWeaponForTarget(fx, target))
target = _inherited(fx, ...);
if (!target)
this->LogAI_Info(fx, Format("No target found by DefenseAI for %v.", fx.Target));
this->LogAI_Info(fx, Format("Defense AI %v found %v as a target to attack.", fx.Target, target));
this->LogAI_CallStack(fx);
return target;
}
@ -80,9 +89,16 @@ public func ExecuteBomber(effect fx)
// Still carrying the bomb?
if (fx.weapon->Contained() != fx.Target)
{
this->LogAI_Info(fx, Format("ExecuteBomber %v lost its bomb.", fx.Target));
fx.weapon = nil;
return false;
}
// Find a different target at random times, because the current target could not be the optimal any more.
if (!Random(40) && !PathFree(fx.Target->GetX(), fx.Target->GetY(), fx.target->GetX(), fx.target->GetY()))
{
fx.target = this->FindTarget(fx);
return true;
}
// Are we in range?
if (fx.Target->ObjectDistance(fx.target) < 16 || Distance(fx.Target->GetX(), fx.Target->GetY(), fx.target->GetX(), fx.target->GetY() + fx.target->GetBottom()) < 16)
{

View File

@ -317,7 +317,7 @@ local Spearman = new DefaultEnemy
local Grenadier = new DefaultEnemy
{
Name = "$EnemyGrenadier$",
Inventory = [GrenadeLauncher, IronBomb, IronBomb, IronBomb, IronBomb, IronBomb],
Inventory = [GrenadeLauncher, [IronBomb, 8]],
Energy = 25,
Bounty = 5,
Color = 0xffa0a0ff,
@ -380,7 +380,7 @@ local Bomber = new DefaultEnemy
local AirshipPilot = new DefaultEnemy
{
Name = "$EnemyAirshipPilot$",
Inventory = [Rock, Rock, Rock, Rock, Rock],
Inventory = [[Rock, 5]],
Energy = 35,
Bounty = 15,
Color = 0xffff00ff,

View File

@ -8,7 +8,7 @@ global func GetRandomAttackTarget(object attacker)
return target;
// Attack structures owned by the enemy of the attacker.
var controller = attacker->GetController();
for (var target in attacker->FindObjects(Find_Category(C4D_Structure), Find_Hostile(controller), Sort_Distance()))
for (var target in attacker->FindObjects(Find_Category(C4D_Structure), Find_Hostile(controller), attacker->Sort_Distance()))
if (target && PathFree(attacker->GetX(), attacker->GetY(), target->GetX(), target->GetY()))
return target;
// Otherwise return random enemy structure.
@ -23,9 +23,9 @@ global func GetRandomSiegeTarget(object attacker)
return target;
// Attack structures owned by the enemy of the attacker.
var controller = attacker->GetController();
for (var target in attacker->FindObjects(Find_Category(C4D_Structure), Find_Hostile(controller), Sort_Distance()))
for (var target in attacker->FindObjects(Find_Category(C4D_Structure), Find_Hostile(controller), attacker->Sort_Distance()))
if (target && PathFree(attacker->GetX(), attacker->GetY(), target->GetX(), target->GetY()))
return target;
// Otherwise return random enemy structure.
return FindObject(Find_Category(C4D_Structure), Find_Hostile(controller), Sort_Random());
return attacker->FindObject(Find_Category(C4D_Structure), Find_Hostile(controller), Sort_Random());
}

View File

@ -5,14 +5,15 @@
@author Maikel
*/
// Callback from the Definition()-call
// Callback from the Definition()-call.
public func OnDefineAI(proplist def)
{
_inherited(def);
def->GetControlEffect().DebugLoggingOn = false; // Whether or not debug logging is turned on.
// Whether or not debug logging is turned on.
def->GetControlEffect().DebugLoggingOn = false;
}
// Logs AI warnings.
public func LogAI_Warning(effect fx, string message)
{
if (fx.DebugLoggingOn)
@ -20,10 +21,21 @@ public func LogAI_Warning(effect fx, string message)
return;
}
// Logs AI info
// Logs AI info.
public func LogAI_Info(proplist fx, string message)
{
if (fx.DebugLoggingOn)
Log("[%d] AI INFO (%v): %s", FrameCounter(), fx.Target, message);
return;
}
// Logs the call stack.
public func LogAI_CallStack(proplist fx)
{
if (fx.DebugLoggingOn)
{
Log("[%d] AI CALLSTACK", FrameCounter());
LogCallStack();
}
return;
}

View File

@ -110,8 +110,10 @@ private func ExecuteRanged(effect fx)
return true;
}
}
// Path not free or out of range. Just wait for enemy to come...
// Path not free or out of range. Just wait for enemy to come or move to it if in agressive mode.
fx.aim_weapon->ControlUseHolding(fx.Target, tx - x, ty - y);
if (fx.is_aggressive && d > 40)
fx.Target->SetCommand("MoveTo", nil, fx.target->GetX(), fx.target->GetY());
// Might also change target if current is unreachable.
var new_target;
if (!Random(3))

View File

@ -253,6 +253,11 @@ public func OnRelaunchCreation()
CreateContents(IronBomb);
}
public func IsExplosive()
{
return !!FindObject(Find_Container(this), Find_Func("IsExplosive"));
}
func Definition(def)
{
def.PictureTransformation = Trans_Mul(Trans_Translate(-3000, 1000, 1500),Trans_Rotate(170,0,1,0),Trans_Rotate(30,0,0,1));