Skip to content

Commit

Permalink
fix #6118
Browse files Browse the repository at this point in the history
make auto-targeting take linear time
  • Loading branch information
rt committed Jan 15, 2019
1 parent 8a452bc commit b54c668
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 38 deletions.
2 changes: 1 addition & 1 deletion rts/Game/GameHelper.cpp
Expand Up @@ -478,7 +478,7 @@ namespace {
Enemy_InLos(nullptr, at), cai(cai) {}

bool Unit(const CUnit* u) {
return Enemy_InLos::Unit(u) && cai->IsValidTarget(u);
return Enemy_InLos::Unit(u) && cai->IsValidTarget(u, nullptr);
}
};

Expand Down
1 change: 0 additions & 1 deletion rts/Sim/MoveTypes/GroundMoveType.cpp
Expand Up @@ -1311,7 +1311,6 @@ void CGroundMoveType::ReRequestPath(bool forceRequest) {
}

wantRepath = true;
return;
}


Expand Down
42 changes: 19 additions & 23 deletions rts/Sim/Units/CommandAI/AirCAI.cpp
Expand Up @@ -238,13 +238,12 @@ bool CAirCAI::AirAutoGenerateTarget(AAirMoveType* myPlane) {
tgt = CGameHelper::GetClosestValidTarget(owner->pos + owner->speed * 20.0f, searchRadius, owner->allyteam, this);
}

if (!IsValidTarget(tgt))
if (!IsValidTarget(tgt, const_cast<CWeapon*>(wpn)))
return false;
if (!eventHandler.AllowWeaponTarget(owner->id, tgt->id, wpn->weaponNum, wpn->weaponDef->id, nullptr))
return false;

Command nc(CMD_ATTACK, INTERNAL_ORDER, tgt->id);
commandQue.push_front(nc);
commandQue.push_front(Command(CMD_ATTACK, INTERNAL_ORDER, tgt->id));
inCommand = false;
return true;
}
Expand Down Expand Up @@ -314,8 +313,7 @@ void CAirCAI::ExecuteFight(Command& c)
goalPos = ClosestPointOnLine(commandPos1, commandPos2, owner->pos);

// CMD_FIGHT is pretty useless if !canAttack, but we try to honour the modders wishes anyway...
if ((owner->fireState >= FIRESTATE_FIREATWILL) && (owner->moveState != MOVESTATE_HOLDPOS) && (owner->maxRange > 0.0f) && ownerDef->canAttack)
{
if ((owner->fireState >= FIRESTATE_FIREATWILL) && (owner->moveState != MOVESTATE_HOLDPOS) && (owner->maxRange > 0.0f) && ownerDef->canAttack) {
CUnit* enemy = nullptr;

if (ownerDef->IsFighterAirUnit()) {
Expand All @@ -324,9 +322,8 @@ void CAirCAI::ExecuteFight(Command& c)

enemy = CGameHelper::GetClosestEnemyAircraft(nullptr, pos, 1000.0f * owner->moveState, owner->allyteam);
}
if (IsValidTarget(enemy) && (owner->moveState != MOVESTATE_MANEUVER
|| LinePointDist(commandPos1, commandPos2, enemy->pos) < 1000))
{

if (IsValidTarget(enemy, nullptr) && (owner->moveState != MOVESTATE_MANEUVER || LinePointDist(commandPos1, commandPos2, enemy->pos) < 1000)) {
// make the attack-command inherit <c>'s options
// (if <c> is internal, then so are the attacks)
//
Expand All @@ -335,8 +332,7 @@ void CAirCAI::ExecuteFight(Command& c)
// noAutoTarget set (although the <enemy> CUnit*
// is technically not a user-target, we treat it
// as such) even when explicitly told to fight
Command nc(CMD_ATTACK, c.GetOpts(), enemy->id);
commandQue.push_front(nc);
commandQue.push_front(Command(CMD_ATTACK, c.GetOpts(), enemy->id));

tempOrder = true;
inCommand = false;
Expand All @@ -347,18 +343,17 @@ void CAirCAI::ExecuteFight(Command& c)
}

return;
} else {
}

{
const float3 ofs = owner->speed * 20.0f;
const float3 pos = ClosestPointOnLine(commandPos1, commandPos2, owner->pos + ofs);

enemy = CGameHelper::GetClosestValidTarget(pos, 500.0f * owner->moveState, owner->allyteam, this);

if (enemy != nullptr) {
if ((enemy = CGameHelper::GetClosestValidTarget(pos, 500.0f * owner->moveState, owner->allyteam, this)) != nullptr) {
PushOrUpdateReturnFight();

// make the attack-command inherit <c>'s options
Command nc(CMD_ATTACK, c.GetOpts(), enemy->id);
commandQue.push_front(nc);
commandQue.push_front(Command(CMD_ATTACK, c.GetOpts(), enemy->id));

tempOrder = true;
inCommand = false;
Expand Down Expand Up @@ -496,11 +491,10 @@ void CAirCAI::ExecuteGuard(Command& c)
(owner->maxRange > 0.0f) &&
owner->unitDef->canAttack &&
((guardee->lastAttackFrame + 40) < gs->frameNum) &&
IsValidTarget(guardee->lastAttacker);
IsValidTarget(guardee->lastAttacker, nullptr);

if (pushAttackCommand) {
Command nc(CMD_ATTACK, c.GetOpts() | INTERNAL_ORDER, guardee->lastAttacker->id);
commandQue.push_front(nc);
commandQue.push_front(Command(CMD_ATTACK, c.GetOpts() | INTERNAL_ORDER, guardee->lastAttacker->id));
SlowUpdate();
} else {
Command c2(CMD_MOVE, c.GetOpts() | INTERNAL_ORDER);
Expand All @@ -518,7 +512,7 @@ void CAirCAI::ExecuteGuard(Command& c)

int CAirCAI::GetDefaultCmd(const CUnit* pointed, const CFeature* feature)
{
if (pointed) {
if (pointed != nullptr) {
if (!teamHandler.Ally(gu->myAllyTeam, pointed->allyteam)) {
if (owner->unitDef->canAttack)
return CMD_ATTACK;
Expand All @@ -532,9 +526,11 @@ int CAirCAI::GetDefaultCmd(const CUnit* pointed, const CFeature* feature)
return CMD_MOVE;
}

bool CAirCAI::IsValidTarget(const CUnit* enemy) const {
if (!CMobileCAI::IsValidTarget(enemy)) return false;
if (enemy->IsCrashing()) return false;
bool CAirCAI::IsValidTarget(const CUnit* enemy, CWeapon* weapon) const {
if (!CMobileCAI::IsValidTarget(enemy, weapon))
return false;
if (enemy->IsCrashing())
return false;
return (GetStrafeAirMoveType(owner)->isFighter || !enemy->unitDef->canfly);
}

Expand Down
2 changes: 1 addition & 1 deletion rts/Sim/Units/CommandAI/AirCAI.h
Expand Up @@ -32,7 +32,7 @@ class CAirCAI : public CMobileCAI
void ExecuteFight(Command& c);
void ExecuteMove(Command& c);

bool IsValidTarget(const CUnit* enemy) const;
bool IsValidTarget(const CUnit* enemy, CWeapon* weapon) const override;

private:
bool AirAutoGenerateTarget(AAirMoveType*);
Expand Down
25 changes: 14 additions & 11 deletions rts/Sim/Units/CommandAI/MobileCAI.cpp
Expand Up @@ -556,7 +556,7 @@ void CMobileCAI::ExecuteFight(Command& c)
ExecuteMove(c);
}

bool CMobileCAI::IsValidTarget(const CUnit* enemy) const {
bool CMobileCAI::IsValidTarget(const CUnit* enemy, CWeapon* weapon) const {
if (enemy == nullptr)
return false;

Expand All @@ -570,15 +570,18 @@ bool CMobileCAI::IsValidTarget(const CUnit* enemy) const {
if (enemy->IsNeutral())
return false;

// test if given weapon belonging to owner can target
// the enemy unit; indicates an auto-targeting context
if (weapon != nullptr)
return (weapon->TestTarget(enemy->pos, {enemy}) && (owner->moveState != MOVESTATE_HOLDPOS || weapon->TryTargetRotate(enemy, false, false)));

// test if any of owner's weapons can target the enemy unit
if (owner->weapons.empty())
return false;

// test if any weapon can target the enemy unit
for (CWeapon* w: owner->weapons) {
if (w->TestTarget(enemy->pos, SWeaponTarget(enemy)) &&
(owner->moveState != MOVESTATE_HOLDPOS || w->TryTargetRotate(enemy, false, false))) {
if (w->TestTarget(enemy->pos, SWeaponTarget(enemy)) && (owner->moveState != MOVESTATE_HOLDPOS || w->TryTargetRotate(enemy, false, false)))
return true;
}
}

return false;
Expand Down Expand Up @@ -610,7 +613,7 @@ void CMobileCAI::ExecuteGuard(Command& c)
const bool pushAttackCommand =
owner->unitDef->canAttack &&
(guardee->lastAttackFrame + 40 < gs->frameNum) &&
IsValidTarget(guardee->lastAttacker);
IsValidTarget(guardee->lastAttacker, nullptr);

if (pushAttackCommand) {
commandQue.push_front(Command(CMD_ATTACK, c.GetOpts(), guardee->lastAttacker->id));
Expand Down Expand Up @@ -1156,13 +1159,13 @@ bool CMobileCAI::GenerateAttackCmd()
for (CWeapon* w: owner->weapons) {
const SWeaponTarget& wTgt = w->GetCurrentTarget();

if (w->HaveTarget() && !eventHandler.AllowWeaponTarget(owner->id, wTgt.unit->id, w->weaponNum, w->weaponDef->id, nullptr))
continue;

// no current target, and nothing to auto-target
if (!w->HaveTarget() && !w->AutoTarget())
continue;

if (wTgt.type != Target_Unit || !IsValidTarget(wTgt.unit))
// maybe a current target, but invalid type or category etc
if (wTgt.type != Target_Unit || !IsValidTarget(wTgt.unit, w))
continue;
if (!eventHandler.AllowWeaponTarget(owner->id, wTgt.unit->id, w->weaponNum, w->weaponDef->id, nullptr))
continue;

newAttackTargetId = wTgt.unit->id;
Expand Down
2 changes: 1 addition & 1 deletion rts/Sim/Units/CommandAI/MobileCAI.h
Expand Up @@ -54,7 +54,7 @@ class CMobileCAI : public CCommandAI

int GetCancelDistance() { return cancelDistance; }

virtual bool IsValidTarget(const CUnit* enemy) const;
virtual bool IsValidTarget(const CUnit* enemy, CWeapon* weapon) const;
virtual bool CanWeaponAutoTarget(const CWeapon* weapon) const override;

void SetTransportee(CUnit* unit);
Expand Down

0 comments on commit b54c668

Please sign in to comment.