bool CGameHelper::TestTrajectoryCone(const float3 &from, const float3 &flatdir,float length, float linear, float quadratic, float spread, float baseSize, int allyteam,CUnit* owner) { int quads[1000]; int* endQuad = quads; qf->GetQuadsOnRay(from,flatdir,length,endQuad); for(int* qi=quads;qi!=endQuad;++qi){ CQuadField::Quad& quad = qf->baseQuads[*qi]; for(list<CUnit*>::iterator ui=quad.teamUnits[allyteam].begin();ui!=quad.teamUnits[allyteam].end();++ui){ if((*ui)==owner) continue; CUnit* u=*ui; float3 dif=u->midPos-from; float3 flatdif(dif.x,0,dif.z); float closeFlatLength=flatdif.dot(flatdir); if(closeFlatLength<=0) continue;//closeLength=0; if(closeFlatLength>length) closeFlatLength=length; /* float3 newfrom=from+flatdir*closeFlatLength; newfrom.y+=(linear+quadratic*closeFlatLength)*closeFlatLength; geometricObjects->AddLine(newfrom-UpVector*(spread*closeFlatLength+baseSize),newfrom+UpVector*(spread*closeFlatLength+baseSize),3,0,16); /**/ if(fabs(linear-quadratic*closeFlatLength)<0.15f){ //relativly flat region -> use approximation dif.y-=(linear+quadratic*closeFlatLength)*closeFlatLength; float3 closeVect=dif-flatdir*closeFlatLength; float r=u->radius+spread*closeFlatLength+baseSize; if(closeVect.SqLength() < r*r){ return true; } } else { float3 newfrom=from+flatdir*closeFlatLength; newfrom.y+=(linear+quadratic*closeFlatLength)*closeFlatLength; float3 dir=flatdir; dir.y=linear+quadratic*closeFlatLength; dir.Normalize(); dif=u->midPos-newfrom; float closeLength=dif.dot(dir); float3 closeVect=dif-dir*closeLength; float r=u->radius+spread*closeFlatLength+baseSize; if(closeVect.SqLength() < r*r){ return true; } } } } return false; }
/** helper for TestTrajectoryAllyCone and TestTrajectoryNeutralCone @return true if the unit u is in the firing trajectory, false otherwise */ bool CGameHelper::TestTrajectoryConeHelper(const float3& from, const float3& flatdir, float length, float linear, float quadratic, float spread, float baseSize, const CUnit* u) { const CollisionVolume* cv = u->collisionVolume; float3 dif = (u->midPos + cv->GetOffsets()) - from; float3 flatdif(dif.x, 0, dif.z); float closeFlatLength = flatdif.dot(flatdir); if (closeFlatLength <= 0) return false; if (closeFlatLength > length) closeFlatLength = length; if (fabs(linear - quadratic * closeFlatLength) < 0.15f) { // relatively flat region -> use approximation dif.y -= (linear + quadratic * closeFlatLength) * closeFlatLength; // NOTE: overly conservative for non-spherical volumes float3 closeVect = dif - flatdir * closeFlatLength; float r = cv->GetBoundingRadius() + spread * closeFlatLength + baseSize; if (closeVect.SqLength() < r * r) { return true; } } else { float3 newfrom = from + flatdir * closeFlatLength; newfrom.y += (linear + quadratic * closeFlatLength) * closeFlatLength; float3 dir = flatdir; dir.y = linear + quadratic * closeFlatLength; dir.Normalize(); dif = (u->midPos + cv->GetOffsets()) - newfrom; float closeLength = dif.dot(dir); // NOTE: overly conservative for non-spherical volumes float3 closeVect = dif - dir * closeLength; float r = cv->GetBoundingRadius() + spread * closeFlatLength + baseSize; if (closeVect.SqLength() < r * r) { return true; } } return false; }