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. 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. // Alternative target finding for defense scenarios: partially controlled by the scenario script.
public func FindTarget(effect fx) 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 target can't be attacked just take normal target again.
if (!this->HasWeaponForTarget(fx, target)) if (!this->HasWeaponForTarget(fx, target))
target = _inherited(fx, ...); target = _inherited(fx, ...);
if (!target) this->LogAI_Info(fx, Format("Defense AI %v found %v as a target to attack.", fx.Target, target));
this->LogAI_Info(fx, Format("No target found by DefenseAI for %v.", fx.Target)); this->LogAI_CallStack(fx);
return target; return target;
} }
@ -80,9 +89,16 @@ public func ExecuteBomber(effect fx)
// Still carrying the bomb? // Still carrying the bomb?
if (fx.weapon->Contained() != fx.Target) if (fx.weapon->Contained() != fx.Target)
{ {
this->LogAI_Info(fx, Format("ExecuteBomber %v lost its bomb.", fx.Target));
fx.weapon = nil; fx.weapon = nil;
return false; 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? // 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) 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 local Grenadier = new DefaultEnemy
{ {
Name = "$EnemyGrenadier$", Name = "$EnemyGrenadier$",
Inventory = [GrenadeLauncher, IronBomb, IronBomb, IronBomb, IronBomb, IronBomb], Inventory = [GrenadeLauncher, [IronBomb, 8]],
Energy = 25, Energy = 25,
Bounty = 5, Bounty = 5,
Color = 0xffa0a0ff, Color = 0xffa0a0ff,
@ -380,7 +380,7 @@ local Bomber = new DefaultEnemy
local AirshipPilot = new DefaultEnemy local AirshipPilot = new DefaultEnemy
{ {
Name = "$EnemyAirshipPilot$", Name = "$EnemyAirshipPilot$",
Inventory = [Rock, Rock, Rock, Rock, Rock], Inventory = [[Rock, 5]],
Energy = 35, Energy = 35,
Bounty = 15, Bounty = 15,
Color = 0xffff00ff, Color = 0xffff00ff,

View File

@ -8,7 +8,7 @@ global func GetRandomAttackTarget(object attacker)
return target; return target;
// Attack structures owned by the enemy of the attacker. // Attack structures owned by the enemy of the attacker.
var controller = attacker->GetController(); 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())) if (target && PathFree(attacker->GetX(), attacker->GetY(), target->GetX(), target->GetY()))
return target; return target;
// Otherwise return random enemy structure. // Otherwise return random enemy structure.
@ -23,9 +23,9 @@ global func GetRandomSiegeTarget(object attacker)
return target; return target;
// Attack structures owned by the enemy of the attacker. // Attack structures owned by the enemy of the attacker.
var controller = attacker->GetController(); 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())) if (target && PathFree(attacker->GetX(), attacker->GetY(), target->GetX(), target->GetY()))
return target; return target;
// Otherwise return random enemy structure. // 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 @author Maikel
*/ */
// Callback from the Definition()-call // Callback from the Definition()-call.
public func OnDefineAI(proplist def) public func OnDefineAI(proplist def)
{ {
_inherited(def); _inherited(def);
// Whether or not debug logging is turned on.
def->GetControlEffect().DebugLoggingOn = false; // Whether or not debug logging is turned on. def->GetControlEffect().DebugLoggingOn = false;
} }
// Logs AI warnings.
public func LogAI_Warning(effect fx, string message) public func LogAI_Warning(effect fx, string message)
{ {
if (fx.DebugLoggingOn) if (fx.DebugLoggingOn)
@ -20,10 +21,21 @@ public func LogAI_Warning(effect fx, string message)
return; return;
} }
// Logs AI info // Logs AI info.
public func LogAI_Info(proplist fx, string message) public func LogAI_Info(proplist fx, string message)
{ {
if (fx.DebugLoggingOn) if (fx.DebugLoggingOn)
Log("[%d] AI INFO (%v): %s", FrameCounter(), fx.Target, message); Log("[%d] AI INFO (%v): %s", FrameCounter(), fx.Target, message);
return; 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; 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); 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. // Might also change target if current is unreachable.
var new_target; var new_target;
if (!Random(3)) if (!Random(3))

View File

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