Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/pr-changelogs/3348.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* fixed attack queues stalling or skipping the next target when the current target is made neutral.
* attack orders now skip crashing aircraft when the `fireAtDead.fireAtCrashing` modrule is disabled. Fighters also respect this modrule when selecting targets automatically.
2 changes: 1 addition & 1 deletion rts/Game/GameHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ namespace {
{
EnemyAircraft(const CUnit* exclUnit, int allyTeam) : Enemy_InLos(exclUnit, allyTeam) {}
bool Unit(const CUnit* u) {
return (u->unitDef->canfly && !u->IsCrashing() && Enemy_InLos::Unit(u));
return (u->unitDef->canfly && (modInfo.fireAtCrashing || !u->IsCrashing()) && Enemy_InLos::Unit(u));
}
};

Expand Down
8 changes: 6 additions & 2 deletions rts/Sim/Units/CommandAI/AirCAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ void CAirCAI::ExecuteAttack(Command& c)
return;
}
if (orderTarget != nullptr) {
if (orderTarget->unitDef->canfly && orderTarget->IsCrashing()) {
if (SkipCrashingTarget(orderTarget)) {
owner->DropCurrentAttackTarget();
StopMoveAndFinishCommand();
return;
Expand Down Expand Up @@ -431,6 +431,10 @@ void CAirCAI::ExecuteAttack(Command& c)
StopMoveAndFinishCommand();
return;
}
if (SkipCrashingTarget(targetUnit)) {
StopMoveAndFinishCommand();
return;
}

SetGoal(targetUnit->pos, owner->pos, cancelDistance);
SetOrderTarget(targetUnit);
Expand Down Expand Up @@ -539,7 +543,7 @@ int CAirCAI::GetDefaultCmd(const CUnit* pointed, const CFeature* feature)
bool CAirCAI::IsValidTarget(const CUnit* enemy, CWeapon* weapon) const {
if (!CMobileCAI::IsValidTarget(enemy, weapon))
return false;
if (enemy->IsCrashing())
if (SkipCrashingTarget(enemy))
return false;
return (GetStrafeAirMoveType(owner)->isFighter || !enemy->unitDef->canfly);
}
Expand Down
25 changes: 25 additions & 0 deletions rts/Sim/Units/CommandAI/CommandAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,11 @@ void CCommandAI::ExecuteAttack(Command& c)
FinishCommand();
return;
}
if (SkipCrashingTarget(orderTarget)) {
owner->DropCurrentAttackTarget();
FinishCommand();
return;
}
if (!(c.GetOpts() & ALT_KEY) && SkipParalyzeTarget(orderTarget)) {
FinishCommand();
return;
Expand All @@ -1517,6 +1522,10 @@ void CCommandAI::ExecuteAttack(Command& c)
FinishCommand();
return;
}
if (SkipCrashingTarget(targetUnit)) {
FinishCommand();
return;
}

SetOrderTarget(targetUnit);
owner->AttackUnit(targetUnit, !c.IsInternalOrder(), c.GetID() == CMD_MANUALFIRE);
Expand Down Expand Up @@ -1832,6 +1841,11 @@ bool CCommandAI::HasMoreMoveCommands(bool skipFirstCmd) const


bool CCommandAI::CanChangeFireState() const { return (owner->unitDef->CanChangeFireState()); }
bool CCommandAI::SkipCrashingTarget(const CUnit* target) const
{
return (target != nullptr && !modInfo.fireAtCrashing && target->IsCrashing());
}

bool CCommandAI::SkipParalyzeTarget(const CUnit* target) const
{
RECOIL_DETAILED_TRACY_ZONE;
Expand All @@ -1854,7 +1868,18 @@ void CCommandAI::StopAttackingTargetIf(const std::function<bool(const CUnit*)>&
const auto hasTarget = [&](const Command& c) { return (c.GetNumParams() == 1 && (c.GetID() == CMD_FIGHT || c.GetID() == CMD_ATTACK)); };
const auto removeCmd = [&](const Command& c) { return (hasTarget(c) && pred(unitHandler.GetUnit(c.GetParam(0)))); };

const bool frontRemoved = (!commandQue.empty() && removeCmd(commandQue.front()));

commandQue.erase(std::remove_if(commandQue.begin(), commandQue.end(), removeCmd), commandQue.end());

// the order being executed was erased without FinishCommand; clear its
// execution state so the next queued order starts fresh instead of being
// judged against the old target (or never initialised at all)
if (frontRemoved) {
inCommand = CMD_STOP;
targetDied = false;
SetOrderTarget(nullptr);
}
}

void CCommandAI::StopAttackingAllyTeam(int ally)
Expand Down
6 changes: 2 additions & 4 deletions rts/Sim/Units/CommandAI/CommandAI.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef _COMMAND_AI_H
#define _COMMAND_AI_H
#pragma once

#include <functional>
#include <vector>
Expand Down Expand Up @@ -139,6 +138,7 @@ class CCommandAI : public CObject
virtual bool SelectNewAreaAttackTargetOrPos(const Command& ac) { return true; }

bool IsAttackCapable() const;
bool SkipCrashingTarget(const CUnit* target) const;
bool SkipParalyzeTarget(const CUnit* target) const;

void GiveAllowedCommand(const Command& c, bool fromSynced = true);
Expand Down Expand Up @@ -176,5 +176,3 @@ inline void CCommandAI::SetOrderTarget(CUnit* o) {
AddDeathDependence(reinterpret_cast<CObject*>(orderTarget), DEPENDENCE_ORDERTARGET);
}
}

#endif // _COMMAND_AI_H
9 changes: 9 additions & 0 deletions rts/Sim/Units/CommandAI/MobileCAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,10 @@ void CMobileCAI::ExecuteAttack(Command& c)
StopMoveAndFinishCommand();
return;
}
if (SkipCrashingTarget(targetUnit)) {
StopMoveAndFinishCommand();
return;
}

const float3 tgtErrPos = targetUnit->GetErrorPos(owner->allyteam, false);
const float3 tgtPosDir = (tgtErrPos - owner->pos).Normalize();
Expand Down Expand Up @@ -953,6 +957,11 @@ void CMobileCAI::ExecuteAttack(Command& c)
StopMoveAndFinishCommand();
return;
}
if (SkipCrashingTarget(orderTarget)) {
owner->DropCurrentAttackTarget();
StopMoveAndFinishCommand();
return;
}


// user clicked on enemy unit; either stop and attack or turn/move toward it
Expand Down