Skip to content

Commit

Permalink
fix #5630
Browse files Browse the repository at this point in the history
  • Loading branch information
rt committed Jul 7, 2017
1 parent 066e39f commit 0cd2098
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 45 deletions.
2 changes: 1 addition & 1 deletion rts/Game/FPSUnitController.cpp
Expand Up @@ -50,7 +50,7 @@ void FPSUnitController::Update() {
CFeature* hitFeature = nullptr;

// SYNCED, do NOT use GuiTraceRay which also checks gu->spectatingFullView
float hitDist = TraceRay::TraceRay(absPos, viewDir, controllee->maxRange, Collision::NONOTINLOS, controllee, hitUnit, hitFeature);
float hitDist = TraceRay::TraceRay(absPos, viewDir, controllee->maxRange, ~Collision::NONOTINLOS, controllee, hitUnit, hitFeature);

if (hitUnit != nullptr) {
targetUnit = hitUnit;
Expand Down
73 changes: 39 additions & 34 deletions rts/Game/TraceRay.cpp
Expand Up @@ -173,30 +173,34 @@ float TraceRay(
const float3& pos,
const float3& dir,
float traceLength,
int avoidFlags,
int traceFlags,
int allyTeam,
const CUnit* owner,
CUnit*& hitUnit,
CFeature*& hitFeature,
CollisionQuery* hitColQuery
) {
const bool noEnemies = ((avoidFlags & Collision::NOENEMIES ) != 0);
const bool noAllies = ((avoidFlags & Collision::NOFRIENDLIES) != 0);
const bool noFeatures = ((avoidFlags & Collision::NOFEATURES ) != 0);
const bool noNeutrals = ((avoidFlags & Collision::NONEUTRALS ) != 0);
const bool noGround = ((avoidFlags & Collision::NOGROUND ) != 0);
const bool noCloaked = ((avoidFlags & Collision::NOCLOAKED ) != 0);
const bool noNotInLOS = ((avoidFlags & Collision::NONOTINLOS ) != 0);

const bool noUnits = noEnemies && noAllies && noNeutrals;
// NOTE:
// the bits here and in Test*Cone are interpreted as "do not scan for {enemy,friendly,...}
// objects in quads" rather than "return false if ray hits an {enemy,friendly,...} object"
// consequently a weapon with (e.g.) avoidFriendly=true that wants to check whether it has
// a free line of fire should *not* set the NOFRIENDLIES bit in its trace-flags, etc
const bool scanForEnemies = ((traceFlags & Collision::NOENEMIES ) == 0);
const bool scanForAllies = ((traceFlags & Collision::NOFRIENDLIES) == 0);
const bool scanForFeatures = ((traceFlags & Collision::NOFEATURES ) == 0);
const bool scanForNeutrals = ((traceFlags & Collision::NONEUTRALS ) == 0);
const bool scanForGround = ((traceFlags & Collision::NOGROUND ) == 0);
const bool scanForCloaked = ((traceFlags & Collision::NOCLOAKED ) == 0);
const bool scanForNotInLOS = ((traceFlags & Collision::NONOTINLOS ) == 0);
const bool scanForAnyUnits = scanForEnemies || scanForAllies || scanForNeutrals || scanForCloaked || scanForNotInLOS;

hitFeature = nullptr;
hitUnit = nullptr;

if (dir == ZeroVector)
return -1.0f;

if (!noFeatures || !noUnits) {
if (scanForFeatures || scanForAnyUnits) {
CollisionQuery cq;

const auto& quads = quadField->GetQuadsOnRay(pos, dir, traceLength);
Expand All @@ -207,7 +211,7 @@ float TraceRay(
hitColQuery = &cq;

// feature intersection
if (!noFeatures) {
if (scanForFeatures) {
for (const int quadIdx: quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

Expand All @@ -218,7 +222,7 @@ float TraceRay(
if (!f->HasCollidableStateBit(CSolidObject::CSTATE_BIT_QUADMAPRAYS))
continue;

if (noNotInLOS && !f->IsInLosForAllyTeam(allyTeam))
if (scanForNotInLOS && !f->IsInLosForAllyTeam(allyTeam))
continue;

if (CCollisionHandler::DetectHit(f, f->GetTransformMatrix(true), pos, pos + dir * traceLength, &cq, true)) {
Expand All @@ -237,7 +241,7 @@ float TraceRay(
}

// unit intersection
if (!noUnits) {
if (scanForAnyUnits) {
for (const int quadIdx: quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

Expand All @@ -246,15 +250,15 @@ float TraceRay(
continue;
if (!u->HasCollidableStateBit(CSolidObject::CSTATE_BIT_QUADMAPRAYS))
continue;
if (noAllies && u->allyteam == owner->allyteam)
if (scanForAllies && u->allyteam == owner->allyteam)
continue;
if (noEnemies && u->allyteam != owner->allyteam)
if (scanForEnemies && u->allyteam != owner->allyteam)
continue;
if (noNeutrals && u->IsNeutral())
if (scanForNeutrals && u->IsNeutral())
continue;
if (noCloaked && u->IsCloaked())
if (scanForCloaked && u->IsCloaked())
continue;
if (noNotInLOS && (u->losStatus[allyTeam] & LOS_INLOS) == 0)
if (scanForNotInLOS && (u->losStatus[allyTeam] & LOS_INLOS) == 0)
continue;

if (CCollisionHandler::DetectHit(u, u->GetTransformMatrix(true), pos, pos + dir * traceLength, &cq, true)) {
Expand All @@ -277,7 +281,7 @@ float TraceRay(
}
}

if (!noGround) {
if (scanForGround) {
// ground intersection
const float groundLength = CGround::LineGroundCol(pos, pos + dir * traceLength);

Expand Down Expand Up @@ -467,22 +471,22 @@ bool TestCone(
float length,
float spread,
int allyteam,
int avoidFlags,
int traceFlags,
CUnit* owner
) {
const auto& quads = quadField->GetQuadsOnRay(from, dir, length);

if (quads.empty())
return true;

const bool noAllies = ((avoidFlags & Collision::NOFRIENDLIES) != 0);
const bool noNeutrals = ((avoidFlags & Collision::NONEUTRALS ) != 0);
const bool noFeatures = ((avoidFlags & Collision::NOFEATURES ) != 0);
const bool scanForAllies = ((traceFlags & Collision::NOFRIENDLIES) == 0);
const bool scanForNeutrals = ((traceFlags & Collision::NONEUTRALS ) == 0);
const bool scanForFeatures = ((traceFlags & Collision::NOFEATURES ) == 0);

for (const int quadIdx: quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

if (!noAllies) {
if (scanForAllies) {
for (const CUnit* u: quad.teamUnits[allyteam]) {
if (u == owner)
continue;
Expand All @@ -494,7 +498,7 @@ bool TestCone(
}
}

if (!noNeutrals) {
if (scanForNeutrals) {
for (const CUnit* u: quad.units) {
if (!u->IsNeutral())
continue;
Expand All @@ -508,7 +512,7 @@ bool TestCone(
}
}

if (!noFeatures) {
if (scanForFeatures) {
for (const CFeature* f: quad.features) {
if (!f->HasCollidableStateBit(CSolidObject::CSTATE_BIT_QUADMAPRAYS))
continue;
Expand All @@ -532,22 +536,23 @@ bool TestTrajectoryCone(
float quadratic,
float spread,
int allyteam,
int avoidFlags,
int traceFlags,
CUnit* owner
) {
const auto& quads = quadField->GetQuadsOnRay(from, dir, length);

if (quads.empty())
return true;

const bool noAllies = ((avoidFlags & Collision::NOFRIENDLIES) != 0);
const bool noNeutrals = ((avoidFlags & Collision::NONEUTRALS ) != 0);
const bool noFeatures = ((avoidFlags & Collision::NOFEATURES ) != 0);
const bool scanForAllies = ((traceFlags & Collision::NOFRIENDLIES) == 0);
const bool scanForNeutrals = ((traceFlags & Collision::NONEUTRALS ) == 0);
const bool scanForFeatures = ((traceFlags & Collision::NOFEATURES ) == 0);

for (const int quadIdx: quads) {
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

// friendly units in this quad
if (!noAllies) {
if (scanForAllies) {
for (const CUnit* u: quad.teamUnits[allyteam]) {
if (u == owner)
continue;
Expand All @@ -561,7 +566,7 @@ bool TestTrajectoryCone(
}

// neutral units in this quad
if (!noNeutrals) {
if (scanForNeutrals) {
for (const CUnit* u: quad.units) {
if (!u->IsNeutral())
continue;
Expand All @@ -576,7 +581,7 @@ bool TestTrajectoryCone(
}

// features in this quad
if (!noFeatures) {
if (scanForFeatures) {
for (const CFeature* f: quad.features) {
if (!f->HasCollidableStateBit(CSolidObject::CSTATE_BIT_QUADMAPRAYS))
continue;
Expand Down
8 changes: 4 additions & 4 deletions rts/Game/TraceRay.h
Expand Up @@ -37,7 +37,7 @@ namespace TraceRay {
const float3& pos,
const float3& dir,
float traceLength,
int avoidFlags,
int traceFlags,
const CUnit* owner,
CUnit*& hitUnit,
CFeature*& hitFeature,
Expand All @@ -47,7 +47,7 @@ namespace TraceRay {
const float3& pos,
const float3& dir,
float traceLength,
int avoidFlags,
int traceFlags,
int allyTeam,
const CUnit* owner,
CUnit*& hitUnit,
Expand Down Expand Up @@ -85,7 +85,7 @@ namespace TraceRay {
float length,
float spread,
int allyteam,
int avoidFlags,
int traceFlags,
CUnit* owner);

/**
Expand All @@ -100,7 +100,7 @@ namespace TraceRay {
float quadratic,
float spread,
int allyteam,
int avoidFlags,
int traceFlags,
CUnit* owner);
}

Expand Down
10 changes: 8 additions & 2 deletions rts/Sim/Weapons/BeamLaser.cpp
Expand Up @@ -316,7 +316,7 @@ void CBeamLaser::FireInternal(float3 curDir)
for (int tries = 0; tries < 5 && tryAgain; ++tries) {
float beamLength = TraceRay::TraceRay(curPos, curDir, maxLength - curLength, collisionFlags, owner, hitUnit, hitFeature, &hitColQuery);

if (hitUnit != NULL && teamHandler->AlliedTeams(hitUnit->team, owner->team)) {
if (hitUnit != nullptr && teamHandler->AlliedTeams(hitUnit->team, owner->team)) {
if (sweepFireState.IsSweepFiring() && !sweepFireState.DamageAllies()) {
doDamage = false; break;
}
Expand All @@ -326,6 +326,7 @@ void CBeamLaser::FireInternal(float3 curDir)
// terminate beam at water surface if necessary
if ((curDir.y < 0.0f) && ((curPos.y + curDir.y * beamLength) <= 0.0f)) {
beamLength = curPos.y / -curDir.y;

hitUnit = nullptr;
hitFeature = nullptr;
}
Expand All @@ -341,6 +342,7 @@ void CBeamLaser::FireInternal(float3 curDir)
for (const TraceRay::SShieldDist& sd: hitShields) {
if (sd.dist < beamLength && sd.rep->IncomingBeam(this, curPos, curPos + (curDir * sd.dist), salvoDamageMult)) {
beamLength = sd.dist;

hitUnit = nullptr;
hitFeature = nullptr;
hitShield = sd.rep;
Expand All @@ -350,9 +352,13 @@ void CBeamLaser::FireInternal(float3 curDir)

// same as hitColQuery.GetHitPos() if no water or shield in way
hitPos = curPos + curDir * beamLength;

if (hitShield != nullptr && hitShield->weaponDef->shieldRepulser) {
// reflect
const float3 normal = (hitPos - hitShield->weaponMuzzlePos).Normalize();
newDir = curDir - normal * normal.dot(curDir) * 2;
const float3 prjDir = normal * normal.dot(curDir) * 2.0f;

newDir = curDir - prjDir;
tryAgain = true;
} else {
tryAgain = false;
Expand Down
5 changes: 1 addition & 4 deletions rts/Sim/Weapons/Weapon.cpp
Expand Up @@ -980,10 +980,7 @@ bool CWeapon::HaveFreeLineOfFire(const float3 srcPos, const float3 tgtPos, const
}

// friendly, neutral & feature check
if (TraceRay::TestCone(srcPos, tgtDir, length, spread, owner->allyteam, avoidFlags, owner))
return false;

return true;
return (!TraceRay::TestCone(srcPos, tgtDir, length, spread, owner->allyteam, avoidFlags, owner));
}


Expand Down

0 comments on commit 0cd2098

Please sign in to comment.