forked from Mirrors/openclonk
ai: airship gets new pilot if old one is lost
parent
7b26e1fa13
commit
0dbfa2dd91
|
@ -3,10 +3,15 @@
|
|||
Functionality that helps the AI use vehicles. Handles:
|
||||
* Catapult
|
||||
|
||||
@author Sven2, Maikel
|
||||
@author Sven2, Clonkonaut, Maikel
|
||||
*/
|
||||
|
||||
|
||||
// AI Settings.
|
||||
local AirshipBoardDistance = 100; // How near must an airship be to the target to dispatch its troops.
|
||||
local AirshipLostDistance = 50; // How far the pilot must be away from an airship for it to find a new pilot.
|
||||
|
||||
|
||||
/*-- General Vehicle --*/
|
||||
|
||||
private func ExecuteVehicle(effect fx)
|
||||
|
@ -52,7 +57,7 @@ private func ExecuteCatapult(effect fx)
|
|||
{
|
||||
// Still pushing it?
|
||||
if (fx.Target->GetProcedure() != "PUSH" || fx.Target->GetActionTarget() != fx.vehicle)
|
||||
{
|
||||
{
|
||||
if (!fx.Target->GetCommand() || !Random(4))
|
||||
fx.Target->SetCommand("Grab", fx.vehicle);
|
||||
return true;
|
||||
|
@ -117,6 +122,15 @@ public func ExecuteAirship(effect fx)
|
|||
// Still steering the airship?
|
||||
if (fx.Target->GetProcedure() != "PUSH" || fx.Target->GetActionTarget() != fx.vehicle)
|
||||
{
|
||||
// Try to find a new pilot if the current pilot lost the airship.
|
||||
if (fx.Target->ObjectDistance(fx.vehicle) > fx.control.AirshipLostDistance)
|
||||
{
|
||||
this->PromoteNewAirshipCaptain(fx);
|
||||
fx.strategy = nil;
|
||||
fx.weapon = nil;
|
||||
fx.vehicle = nil;
|
||||
return true;
|
||||
}
|
||||
if (!fx.Target->GetCommand())
|
||||
fx.Target->SetCommand("Grab", fx.vehicle);
|
||||
return true;
|
||||
|
@ -125,14 +139,16 @@ public func ExecuteAirship(effect fx)
|
|||
// Move the airship to the target. Check if no command or is making contact, this means a new control needs to be issued.
|
||||
if (!fx.vehicle->GetCommand() || fx.vehicle->GetContact(-1))
|
||||
{
|
||||
// If close enough (also in y-coordinates) release the crew.
|
||||
if (fx.vehicle->ObjectDistance(fx.target) < 100 && Inside(fx.vehicle->GetY() - fx.target->GetY(), -40, 0))
|
||||
// If close enough (also in y-coordinates, must be above target) release the crew.
|
||||
if (fx.vehicle->ObjectDistance(fx.target) < fx.control.AirshipBoardDistance && Inside(fx.vehicle->GetY() - fx.target->GetY(), -fx.control.AirshipBoardDistance / 2, 0))
|
||||
{
|
||||
// Unboard the crew and let go of airship.
|
||||
for (var clonk in this->GetAirshipCrew(fx))
|
||||
for (var clonk in this->GetCommanderCrew(fx))
|
||||
{
|
||||
var clonk_ai = clonk->GetAI();
|
||||
clonk_ai.commander = nil;
|
||||
if (clonk->GetProcedure() == "PUSH")
|
||||
clonk->SetAction("Walk");
|
||||
clonk_ai.target = fx.target;
|
||||
}
|
||||
fx.vehicle = nil;
|
||||
|
@ -200,15 +216,29 @@ public func GetAirshipBoardingPoint(effect fx)
|
|||
|
||||
public func PromoteNewAirshipCaptain(effect fx)
|
||||
{
|
||||
var crew = RandomElement(this->GetAirshipCrew(fx));
|
||||
if (!crew)
|
||||
var crew_members = fx.vehicle->GetCrewMembers();
|
||||
if (!GetLength(crew_members))
|
||||
return false;
|
||||
return;
|
||||
var new_pilot = RandomElement(crew_members);
|
||||
var fx_ai = new_pilot->~GetAI();
|
||||
if (!fx_ai)
|
||||
return false;
|
||||
// Make this crew the new pilot.
|
||||
fx_ai.commander = nil;
|
||||
fx_ai.weapon = fx.vehicle;
|
||||
fx_ai.vehicle = fx.vehicle;
|
||||
fx_ai.strategy = this.ExecuteVehicle;
|
||||
// Set new commander for remaining crew members.
|
||||
for (var crew in crew_members)
|
||||
if (crew != new_pilot)
|
||||
if (crew->~GetAI())
|
||||
crew->~GetAI().commander = new_pilot;
|
||||
return true;
|
||||
}
|
||||
|
||||
public func GetAirshipCrew(effect fx)
|
||||
// Find all crew members with this AI as their commander.
|
||||
public func GetCommanderCrew(effect fx)
|
||||
{
|
||||
// Find all crew members with this commander.
|
||||
var crew = [];
|
||||
for (var clonk in fx.Target->FindObjects(Find_OCF(OCF_CrewMember), Find_Owner(fx.Target->GetOwner())))
|
||||
if (clonk->~GetAI() && clonk->GetAI().commander == fx.Target)
|
||||
|
|
|
@ -88,7 +88,7 @@ public func GetTurnAngle()
|
|||
public func FxIntAirshipMovementTimer(object target, proplist effect, int time)
|
||||
{
|
||||
// Is the engine running?
|
||||
if (GetComDir() != COMD_Stop && AirshipPilot())
|
||||
if (GetComDir() != COMD_Stop && HasAirshipPilot())
|
||||
{
|
||||
//Turn the propeller
|
||||
AnimationForward();
|
||||
|
@ -131,7 +131,7 @@ public func FxIntAirshipMovementTimer(object target, proplist effect, int time)
|
|||
/* TODO: Implement */;
|
||||
|
||||
// Fall down if there no pilot and ground.
|
||||
if (!AirshipPilot())
|
||||
if (!HasAirshipPilot())
|
||||
{
|
||||
if (GetContact(-1) & CNAT_Bottom)
|
||||
SetComDir(COMD_Stop);
|
||||
|
@ -282,12 +282,28 @@ func ControlStop(object clonk, int control)
|
|||
return true;
|
||||
}
|
||||
|
||||
private func AirshipPilot()
|
||||
|
||||
/*-- Pilot & Crew --*/
|
||||
|
||||
private func HasAirshipPilot()
|
||||
{
|
||||
// Looks for a clonk within the gondola.
|
||||
return FindObject(Find_ID(Clonk), Find_OCF(OCF_Alive), Find_InRect(gondola[0], gondola[1], gondola[2], gondola[3]));
|
||||
return !!FindObject(Find_ID(Clonk), Find_OCF(OCF_Alive), Find_InRect(gondola[0], gondola[1], gondola[2], gondola[3]));
|
||||
}
|
||||
|
||||
public func IsInsideGondola(object clonk)
|
||||
{
|
||||
if (!clonk)
|
||||
return false;
|
||||
return Inside(clonk->GetX() - GetX(), this.gondola[0], this.gondola[2]) && Inside(clonk->GetY() - GetY(), this.gondola[1], this.gondola[3]);
|
||||
}
|
||||
|
||||
public func GetCrewMembers()
|
||||
{
|
||||
return FindObjects(Find_InRect(this.gondola[0], this.gondola[1], this.gondola[2], this.gondola[3]), Find_Owner(GetOwner()), Find_OCF(OCF_Alive));
|
||||
}
|
||||
|
||||
|
||||
/*-- Projectile Target --*/
|
||||
|
||||
// Only is a projectile target if the projectile hits the balloon part of the airship.
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#appendto Airship
|
||||
|
||||
private func AirshipPilot()
|
||||
private func HasAirshipPilot()
|
||||
{
|
||||
// Looks for a clonk within the gondola.
|
||||
return FindObject(Find_ID(Clonk), Find_OCF(OCF_Alive), Find_InRect(gondola[0], gondola[1], gondola[2], gondola[3]), Find_AnyLayer());
|
||||
return !!FindObject(Find_ID(Clonk), Find_OCF(OCF_Alive), Find_InRect(gondola[0], gondola[1], gondola[2], gondola[3]), Find_AnyLayer());
|
||||
}
|
Loading…
Reference in New Issue