Skip to content

Commit

Permalink
Try making good unit behavior when walls block a target.
Browse files Browse the repository at this point in the history
Rough attempt to get units to stop firing through walls while
also trying to path towards their target without an obstructed view
of them.

Fixes #271
  • Loading branch information
KJeff01 committed May 9, 2019
1 parent 4ed887e commit 5cbe6b9
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 13 deletions.
82 changes: 75 additions & 7 deletions src/action.cpp
Expand Up @@ -632,6 +632,8 @@ void actionUpdateDroid(DROID *psDroid)
bool targetVisibile[MAX_WEAPONS] = { false };
bool bHasTarget = false;
bool bDirect = false;
STRUCTURE *blockingWall = nullptr;
bool wallBlocked = false;

CHECK_DROID(psDroid);

Expand Down Expand Up @@ -819,6 +821,7 @@ void actionUpdateDroid(DROID *psDroid)
for (unsigned i = 0; i < psDroid->numWeaps; ++i)
{
bDirect = proj_Direct(asWeaponStats + psDroid->asWeaps[i].nStat);
blockingWall = nullptr;
// Does this weapon have a target?
if (psDroid->psActionTarget[i] != nullptr)
{
Expand All @@ -832,6 +835,11 @@ void actionUpdateDroid(DROID *psDroid)
{
setDroidActionTarget(psDroid, nullptr, i);
}
// Is target blocked by a wall?
else if (bDirect && visGetBlockingWall(psDroid, psDroid->psActionTarget[i]))
{
setDroidActionTarget(psDroid, nullptr, i);
}
// I have a target!
else
{
Expand All @@ -850,8 +858,7 @@ void actionUpdateDroid(DROID *psDroid)
}
}
// If we have a target for the weapon: is it visible?
if (psDroid->psActionTarget[i] != nullptr
&& visibleObject(psDroid, psDroid->psActionTarget[i], false))
if (psDroid->psActionTarget[i] != nullptr && visibleObject(psDroid, psDroid->psActionTarget[i], false))
{
hasVisibleTarget = true; // droid have a visible target to shoot
targetVisibile[i] = true;// it is at least visible for this weapon
Expand All @@ -863,15 +870,41 @@ void actionUpdateDroid(DROID *psDroid)
// loop through weapons
for (unsigned i = 0; i < psDroid->numWeaps; ++i)
{
const unsigned compIndex = psDroid->asWeaps[i].nStat;
const WEAPON_STATS *psStats = asWeaponStats + compIndex;
wallBlocked = false;

// has weapon a target? is target valid?
if (psDroid->psActionTarget[i] != nullptr && validTarget(psDroid, psDroid->psActionTarget[i], i))
{
// is target visible and weapon is not a Nullweapon?
if (targetVisibile[i] && nonNullWeapon[i]) //to fix a AA-weapon attack ground unit exploit
{
BASE_OBJECT *psActionTarget = psDroid->psActionTarget[i];
BASE_OBJECT *psActionTarget = nullptr;
blockingWall = visGetBlockingWall(psDroid, psDroid->psActionTarget[i]);

if (proj_Direct(psStats) && blockingWall)
{
WEAPON_EFFECT weapEffect = psStats->weaponEffect;

if (!aiCheckAlliances(psDroid->player, blockingWall->player)
&& asStructStrengthModifier[weapEffect][blockingWall->pStructureType->strength] >= 100)
{
psActionTarget = blockingWall;
setDroidActionTarget(psDroid, psActionTarget, i); // attack enemy wall
}
else
{
wallBlocked = true;
}
}
else
{
psActionTarget = psDroid->psActionTarget[i];
}

// is the turret aligned with the target?
if (actionTargetTurret(psDroid, psActionTarget, &psDroid->asWeaps[i]))
if (!wallBlocked && actionTargetTurret(psDroid, psActionTarget, &psDroid->asWeaps[i]))
{
// In range - fire !!!
combFire(&psDroid->asWeaps[i], psDroid, psActionTarget, i);
Expand Down Expand Up @@ -924,6 +957,7 @@ void actionUpdateDroid(DROID *psDroid)
}

bHasTarget = false;
wallBlocked = false;
for (unsigned i = 0; i < psDroid->numWeaps; ++i)
{
BASE_OBJECT *psActionTarget;
Expand Down Expand Up @@ -963,8 +997,28 @@ void actionUpdateDroid(DROID *psDroid)
&& actionInRange(psDroid, psActionTarget, i))
{
WEAPON_STATS *const psWeapStats = &asWeaponStats[psDroid->asWeaps[i].nStat];
WEAPON_EFFECT weapEffect = psWeapStats->weaponEffect;
blockingWall = visGetBlockingWall(psDroid, psActionTarget);

// if a wall is inbetween us and the target, try firing at the wall if our
// weapon is good enough
if (proj_Direct(psWeapStats) && blockingWall)
{
if (!aiCheckAlliances(psDroid->player, blockingWall->player)
&& asStructStrengthModifier[weapEffect][blockingWall->pStructureType->strength] >= 100)
{
psActionTarget = (BASE_OBJECT *)blockingWall;
setDroidActionTarget(psDroid, psActionTarget, i);
}
else
{
wallBlocked = true;
}
}

bHasTarget = true;
if (validTarget(psDroid, psActionTarget, i))

if (validTarget(psDroid, psActionTarget, i) && !wallBlocked)
{
int dirDiff = 0;

Expand Down Expand Up @@ -1011,7 +1065,7 @@ void actionUpdateDroid(DROID *psDroid)
}
}

if (!bHasTarget)
if (!bHasTarget || wallBlocked)
{
BASE_OBJECT *psTarget;
bool supportsSensorTower = !isVtolDroid(psDroid) && (psTarget = orderStateObj(psDroid, DORDER_FIRESUPPORT)) && psTarget->type == OBJ_STRUCTURE;
Expand Down Expand Up @@ -1208,7 +1262,21 @@ void actionUpdateDroid(DROID *psDroid)
else if (actionInRange(psDroid, psDroid->psActionTarget[0], i))
{
// fire while closing range
combFire(&psDroid->asWeaps[i], psDroid, psDroid->psActionTarget[0], i);
if ((blockingWall = visGetBlockingWall(psDroid, psDroid->psActionTarget[0])) && proj_Direct(psWeapStats))
{
WEAPON_EFFECT weapEffect = psWeapStats->weaponEffect;

if (!aiCheckAlliances(psDroid->player, blockingWall->player)
&& asStructStrengthModifier[weapEffect][blockingWall->pStructureType->strength] >= 100)
{
//Shoot at wall if the weapon is good enough against them
combFire(&psDroid->asWeaps[i], psDroid, (BASE_OBJECT *)blockingWall, i);
}
}
else
{
combFire(&psDroid->asWeaps[i], psDroid, psDroid->psActionTarget[0], i);
}
}
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/ai.cpp
Expand Up @@ -690,16 +690,18 @@ int aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, i
if (bestTarget)
{
ASSERT(!bestTarget->died, "AI gave us a target that is already dead.");
targetStructure = visGetBlockingWall((BASE_OBJECT *)psDroid, bestTarget);
targetStructure = visGetBlockingWall(psDroid, bestTarget);

/* See if target is blocked by a wall; only affects direct weapons */
// See if target is blocked by a wall; only affects direct weapons
// Ignore friendly walls here
if (proj_Direct(asWeaponStats + psDroid->asWeaps[weapon_slot].nStat)
&& targetStructure)
&& targetStructure
&& !aiCheckAlliances(psDroid->player, targetStructure->player))
{
//are we any good against walls?
if (asStructStrengthModifier[weaponEffect][targetStructure->pStructureType->strength] >= 100) //can attack atleast with default strength
if (asStructStrengthModifier[weaponEffect][targetStructure->pStructureType->strength] >= 100) //can attack atleast with default strength
{
bestTarget = (BASE_OBJECT *)targetStructure; //attack wall
bestTarget = (BASE_OBJECT *)targetStructure; //attack wall
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/order.cpp
Expand Up @@ -749,7 +749,7 @@ void orderUpdateDroid(DROID *psDroid)
&& psDroid->order.psObj == psDroid->psActionTarget[0]
&& actionInRange(psDroid, psDroid->order.psObj, 0)
&& (psWall = visGetBlockingWall(psDroid, psDroid->order.psObj))
&& psWall->player != psDroid->player)
&& !aiCheckAlliances(psWall->player, psDroid->player))
{
// there is a wall in the way - attack that
actionDroid(psDroid, DACTION_ATTACK, psWall);
Expand Down

0 comments on commit 5cbe6b9

Please sign in to comment.