コード例 #1
0
ファイル: Projectile.cpp プロジェクト: Arc0re/lithtech
void CProjectile::Explode()
{
	if (!g_pServerDE) return;

	DVector vPos;
	g_pServerDE->GetObjectPos(m_hObject, &vPos);

	AddImpact(vPos, vPos, m_hHitObject);

	if(m_nRadius) 
	{
		DamageObjectsWithinRadius();
	} 
	else if (m_hHitObject)
	{
		// Send damage message to object...
		DamageObject(m_hFiredFrom, this, m_hHitObject, m_fDamage, m_vDir, vPos, m_nDamageType); 
	}
	
	if (m_hHitObject)
	{
		g_pServerDE->BreakInterObjectLink(m_hObject, m_hHitObject);
		m_hHitObject = DFALSE;
	}
}
コード例 #2
0
LTBOOL CProjectile::TestInsideObject(HOBJECT hTestObj, AmmoType eAmmoType)
{
    if (!hTestObj) return LTFALSE;

	// TO DO???
	// NOTE:  This code may need to be updated to use test the dims
	// of the CharacterHitBox instead of the dims of the object...
	// TO DO???

	// See if we are inside the test object...

    LTVector vTestPos, vTestDims;
    g_pLTServer->GetObjectPos(hTestObj, &vTestPos);
    g_pLTServer->GetObjectDims(hTestObj, &vTestDims);

	if (m_vFirePos.x < vTestPos.x - vTestDims.x ||
		m_vFirePos.x > vTestPos.x + vTestDims.x ||
		m_vFirePos.y < vTestPos.y - vTestDims.y ||
		m_vFirePos.y > vTestPos.y + vTestDims.y ||
		m_vFirePos.z < vTestPos.z - vTestDims.z ||
		m_vFirePos.z > vTestPos.z + vTestDims.z)
	{
        return LTFALSE;
	}


	// We're inside the object, so we automatically hit the object...

	if (eAmmoType == PROJECTILE)
	{
		Detonate(hTestObj);
	}
	else
	{
		if (eAmmoType == VECTOR)
		{
			if (IsCharacter(hTestObj))
			{
                CCharacter *pChar = (CCharacter*) g_pLTServer->HandleToObject(hTestObj);
                if (!pChar) return LTFALSE;

				ModelNode eModelNode = g_pModelButeMgr->GetSkeletonDefaultHitNode(pChar->GetModelSkeleton());

				pChar->SetModelNodeLastHit(eModelNode);

				m_fInstDamage *= pChar->ComputeDamageModifier(eModelNode);
			}

			ImpactDamageObject(m_hFiredFrom, hTestObj);
		}

        LTVector vNormal(0, 1, 0);
		AddImpact(hTestObj, m_vFlashPos, vTestPos, vNormal, GetSurfaceType(hTestObj));
	}

	RemoveObject();

    return LTTRUE;
}
コード例 #3
0
void CProjectile::Detonate(HOBJECT hObj)
{
	if (m_bDetonated) return;

	// Make sure we don't detonate if a cinematic is playing (i.e.,
	// make sure the user doesn't disrupt the cinematic)...

	if (Camera::IsActive())
	{
		RemoveObject();
		return;
	}


    m_bDetonated = LTTRUE;

	SurfaceType eType = ST_UNKNOWN;

    LTVector vPos;
    g_pLTServer->GetObjectPos(m_hObject, &vPos);

	// Determine the normal of the surface we are impacting on...

    LTVector vNormal(0.0f, 1.0f, 0.0f);

	if (hObj)
	{
        if (IsMainWorld(hObj) || g_pLTServer->GetObjectType(hObj) == OT_WORLDMODEL)
		{
			CollisionInfo info;
            g_pLTServer->GetLastCollision(&info);

			if (info.m_hPoly)
			{
				eType = GetSurfaceType(info.m_hPoly);
			}

			LTPlane plane = info.m_Plane;
			vNormal = plane.m_Normal;

			// Calculate where we really hit the plane...

            LTVector vVel, vP0, vP1, vDir;
            g_pLTServer->GetVelocity(m_hObject, &vVel);
			vDir = vVel;
			vDir.Norm();

			vP1 = vPos;
            vVel *= g_pLTServer->GetFrameTime();
			vP0 = vP1 - vVel;
			vP1 += vVel;

			// Make sure we don't tunnel through an object...

			IntersectInfo iInfo;
			IntersectQuery qInfo;

			qInfo.m_Flags = INTERSECT_HPOLY | INTERSECT_OBJECTS | IGNORE_NONSOLID;

			qInfo.m_From	  = vP0;
			qInfo.m_To		  = vPos;
			qInfo.m_FilterFn  = SpecificObjectFilterFn;
			qInfo.m_pUserData = m_hObject;

			if (g_pLTServer->IntersectSegment(&qInfo, &iInfo))
			{
				vPos    = iInfo.m_Point - vDir;
				eType   = GetSurfaceType(iInfo);
				vNormal = iInfo.m_Plane.m_Normal;
			}
			else
			{

				//g_pLTServer->CPrint("P0  = %.2f, %.2f, %.2f", VEC_EXPAND(vP0));
				//g_pLTServer->CPrint("P1  = %.2f, %.2f, %.2f", VEC_EXPAND(vP1));
				//LTVector vDist = vP1 - vP0;
				//g_pLTServer->CPrint("Distance from P0 to P1: %.2f", vDist.Mag());

				LTFLOAT fDot1 = VEC_DOT(vNormal, vP0) - info.m_Plane.m_Dist;
				LTFLOAT fDot2 = VEC_DOT(vNormal, vP1) - info.m_Plane.m_Dist;

				if (fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f)
				{
					vPos = vP1;
				}
				else
				{
					LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1);
					//g_pLTServer->CPrint("Percent: %.2f", fPercent);
					VEC_LERP(vPos, vP0, vP1, fPercent);
				}
			}

            LTRotation rRot;
            g_pLTServer->AlignRotation(&rRot, &vNormal, LTNULL);
            g_pLTServer->SetObjectRotation(m_hObject, &rRot);

			// g_pLTServer->CPrint("Pos = %.2f, %.2f, %.2f", VEC_EXPAND(vPos));
		}
	}
	else
	{
		// Since hObj was null, this means the projectile's lifetime was up,
		// so we just blew-up in the air.

		eType = ST_AIR;
	}


	if (eType == ST_UNKNOWN)
	{
		eType = GetSurfaceType(hObj);
	}


	AddImpact(hObj, m_vFlashPos, vPos, vNormal, eType);


	// Handle impact damage...

	if (hObj)
	{
		HOBJECT hDamager = m_hFiredFrom ? m_hFiredFrom : m_hObject;
		ImpactDamageObject(hDamager, hObj);
	}


    //g_pLTServer->CPrint("Server end pos (%.2f, %.2f, %.2f)", vPos.x, vPos.y, vPos.z);
    //g_pLTServer->CPrint("Server fly time %.2f", g_pLTServer->GetTime() - m_fStartTime);

	// Remove projectile from world...

	RemoveObject();
}
コード例 #4
0
LTBOOL CProjectile::HandleVectorImpact(IntersectInfo & iInfo, LTVector & vFrom,
                                     LTVector & vTo)
{
	// Get the surface type...

	SurfaceType eSurfType = GetSurfaceType(iInfo);


	// See if we hit an invisible surface...

	if (eSurfType == ST_INVISIBLE)
	{
		if (!CalcInvisibleImpact(iInfo, eSurfType))
		{
			SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurfType);
            if (!pSurf) return LTTRUE;

			return UpdateDoVectorValues(*pSurf, 0, iInfo.m_Point, vFrom, vTo);
		}
	}


	// See if we hit an object that should be damaged...

    LTBOOL bHitWorld = IsMainWorld(iInfo.m_hObject);

	if (!bHitWorld && eSurfType != ST_LIQUID)
	{
		ImpactDamageObject(m_hFiredFrom, iInfo.m_hObject);
	}


	// If the fire position is the initial fire position, use the flash
	// position when building the impact special fx...

    LTVector vFirePos = (vFrom.Equals(m_vFirePos) ? m_vFlashPos : vFrom);

	AddImpact(iInfo.m_hObject, vFirePos, iInfo.m_Point, iInfo.m_Plane.m_Normal, eSurfType);


	// See if we can shoot through the surface...

	SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurfType);
    if (!pSurf) return LTTRUE;  // Done.

	if (pSurf->bCanShootThrough)
	{
		int nMaxThickness = pSurf->nMaxShootThroughThickness;
		if (nMaxThickness == 0)
		{
			// Special case of always being able to shoot through surface...

			// Calculate new values for next DoVector iteration...

			return UpdateDoVectorValues(*pSurf, 0, iInfo.m_Point, vFrom, vTo);
		}

		// Test if object/wall intersected is thin enough to be shot
		// through...

		// Test object case first...

		if (!bHitWorld && iInfo.m_hObject)
		{
			// Test to see if we can shoot through the object...

            LTVector vDims;
            g_pLTServer->GetObjectDims(iInfo.m_hObject, &vDims);

			if (vDims.x*2.0f >= nMaxThickness &&  vDims.y*2.0f >= nMaxThickness &&
				vDims.z*2.0f >= nMaxThickness)
			{
				// Can't shoot through this object...
                return LTTRUE;
			}
		}

		// Determine if we shot through the wall/object...

		IntersectInfo iTestInfo;
		IntersectQuery qTestInfo;

        qTestInfo.m_From = iInfo.m_Point + (m_vDir * (LTFLOAT)(nMaxThickness + 1));
		qTestInfo.m_To   = iInfo.m_Point - m_vDir;

		qTestInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY;

		qTestInfo.m_FilterFn  = DoVectorFilterFn;
		qTestInfo.m_pUserData = m_hFiredFrom;

        if (g_pLTServer->IntersectSegment(&qTestInfo, &iTestInfo))
		{
			// Calculate new values for next DoVector iteration...

            LTVector vThickness = iTestInfo.m_Point - iInfo.m_Point;
			return UpdateDoVectorValues(*pSurf, vThickness.Mag(), iTestInfo.m_Point, vFrom, vTo);
		}
	}

    return LTTRUE;
}
コード例 #5
0
void CProjectile::DoVector()
{
	IntersectInfo iInfo;
	IntersectQuery qInfo;

    LTVector vTo, vFrom, vOriginalFrom;
	vFrom = m_vFirePos;
	vTo	= vFrom + (m_vDir * m_fRange);

	qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY;

    LTBOOL bHitSomething = LTFALSE;
    LTBOOL bDone         = LTFALSE;

	int nLoopCount = 0; // No infinite loops thanks.

	HOBJECT hLastHitbox = LTNULL;

	while (!bDone)
	{
		qInfo.m_PolyFilterFn = DoVectorPolyFilterFn;
		qInfo.m_FilterFn	 = DoVectorFilterFn;
		qInfo.m_pUserData	 = m_hFiredFrom;

		qInfo.m_From = vFrom;
		qInfo.m_To   = vTo;

        if (g_pLTServer->IntersectSegment(&qInfo, &iInfo))
		{
            HCLASS hClass = g_pLTServer->GetObjectClass(iInfo.m_hObject);

			if ( iInfo.m_hObject == hLastHitbox )
			{
				_ASSERT(LTFALSE);
				g_pLTServer->CPrint("ERROR: vector intersected character hitbox twice");
				bDone = LTTRUE;
				continue;
			}

			if (IsCharacterHitBox(iInfo.m_hObject))
			{
				hLastHitbox = iInfo.m_hObject;

				vOriginalFrom = vFrom;

				if (HandlePotentialHitBoxImpact(iInfo, vFrom))
				{
					HandleVectorImpact(iInfo, vOriginalFrom, vTo);
					return;
				}
			}
			else
			{
				if (HandleVectorImpact(iInfo, vFrom, vTo))
				{
					return;
				}
			}
		}
		else // Didn't hit anything...
		{
            bDone = LTTRUE;
		}


		// Melee weapons can't shoot through objects...

		if (m_pAmmoData->eInstDamageType == DT_MELEE)
		{
			bDone = LTTRUE;
		}


		// Make sure we don't loop forever...

		if (++nLoopCount > MAX_VECTOR_LOOP)
		{
            g_pLTServer->CPrint("ERROR in CProjectile::DoVector() - Infinite loop encountered!!!");
            bDone = LTTRUE;
		}
	}


	// Didn't hit anything so just impact at the end pos...

    LTVector vUp(0.0f, 1.0f, 0.0f);
    AddImpact(LTNULL, m_vFlashPos, vTo, vUp, ST_SKY);


	// Okay, we're all done now...bye, bye...

	RemoveObject();
}