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;
}
Example #2
0
/** 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;
}