void CProjectile::ImpactDamageObject(HOBJECT hDamager, HOBJECT hObj)
{
	DamageStruct damage;

	damage.hDamager = hDamager;
	damage.vDir		= m_vDir;

	// Do Instant damage...

	if (m_fInstDamage > 0.0f)
	{
		damage.eType	= m_eInstDamageType;
		damage.fDamage	= m_fInstDamage;

		damage.DoDamage(this, hObj);
	}

	// Do Progressive damage...(if the progressive damage is supposed to
	// happen over time, it will be done in the explosion object)....

	if (m_fProgDamage > 0.0f && m_pAmmoData->fProgDamageLifetime <= 0.0f)
	{
		damage.eType	 = m_eProgDamageType;
		damage.fDamage	 = m_fProgDamage;
		damage.fDuration = m_pAmmoData->fProgDamageDuration;

		damage.DoDamage(this, hObj);
	}



	// Update player summary info...

	CPlayerObj* pPlayer;
	if (IsPlayer(hDamager) && IsCharacter(hObj) && IsAccuracyType(m_eInstDamageType))
	{
        CCharacter* pChar = (CCharacter*) g_pLTServer->HandleToObject(hObj);
        pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(hDamager);
		if (pPlayer)
		{
			ModelNode eModelNode = pChar->GetModelNodeLastHit();

			if (eModelNode != eModelNodeInvalid)
			{
				HitLocation eLoc = g_pModelButeMgr->GetSkeletonNodeLocation(pChar->GetModelSkeleton(),eModelNode);
				pPlayer->GetPlayerSummaryMgr()->IncNumHits(eLoc);
			}
			else
			{
				pPlayer->GetPlayerSummaryMgr()->IncNumHits(HL_UNKNOWN);
			}
		}
	}

	if (IsPlayer(hObj))
	{
        pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(hObj);
		if (pPlayer)
		{
			pPlayer->GetPlayerSummaryMgr()->IncNumTimesHit();
		}
	}
}
Ejemplo n.º 2
0
void CSpear::HandleImpact(HOBJECT hObj)
{
	if (!g_vtSpearStickPercentage.IsInitted())
	{
        g_vtSpearStickPercentage.Init(g_pLTServer, "SpearStickPercent", LTNULL, 0.9f);
	}

	if (!m_pAmmoData || !m_pAmmoData->pProjectileFX)
	{
		CProjectile::HandleImpact(hObj);
		return;
	}


	CollisionInfo info;
    g_pLTServer->GetLastCollision(&info);

    LTVector vPos, vVel, vCurVel, vP0, vP1;
    g_pLTServer->GetObjectPos(m_hObject, &vPos);

    LTRotation rRot;
    g_pLTServer->GetObjectRotation(m_hObject, &rRot);


	// Should we break the spear?

	enum SpearAction
	{
		eSpearActionBreak,
		eSpearActionStickWorld,
		eSpearActionStickAI,
		eSpearActionStickPlayer,
		eSpearActionStickBody
	};

	SpearAction eSpearAction = eSpearActionBreak;

	// Randomly break even if we could sometimes stick...

	if (GetRandom(0.0, 1.0f) > g_vtSpearStickPercentage.GetFloat())
	{
		eSpearAction = eSpearActionBreak;
	}
	else if (IsMainWorld(hObj))
	{
 		// Calculate where we really hit the world...

		g_pLTServer->GetVelocity(m_hObject, &vVel);

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

        LTFLOAT fDot1 = VEC_DOT(info.m_Plane.m_Normal, vP0) - info.m_Plane.m_Dist;
        LTFLOAT fDot2 = VEC_DOT(info.m_Plane.m_Normal, 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);
			VEC_LERP(vPos, vP0, vP1, fPercent);
		}

		// Set our new "real" pos...

        g_pLTServer->SetObjectPos(m_hObject, &vPos);

		eSpearAction = eSpearActionStickWorld;
	}
	else if (IsMoveable(hObj))
	{
		if (IsAI(hObj))
		{
			// Attach to a AI
			eSpearAction = eSpearActionStickAI;
		}
		else if (IsPlayer(hObj))
		{
			// Attach to a Player
			eSpearAction = eSpearActionStickPlayer;
		}
		else if (IsBody(hObj))
		{
			// Attach to a body
 			eSpearAction = eSpearActionStickBody;
		}
		else
		{
			// Could probably come up with a way to attach to moveable
			// non-character objects (like doors), but it is much easier
			// to just break it ;)...

            eSpearAction = eSpearActionBreak;
		}
	}

	// If the surface is too hard, the spear will just break when
	// it hits it...

	SurfaceType eSurf = GetSurfaceType(info);
	SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurf);
	if ((eSpearActionBreak == eSpearAction) || ((eSpearActionStickWorld == eSpearAction) && pSurf && pSurf->fHardness > 0.5))
	{
		// Create spear debris...

		DEBRIS* pDebris = g_pDebrisMgr->GetDebris(m_pAmmoData->szName);
		if (pDebris)
		{
			vVel.Norm();
            LTVector vNegVel = -vVel;
            CreatePropDebris(vPos, vNegVel, pDebris->nId);
		}

		CProjectile::HandleImpact(hObj);
		return;
	}

	// Create the Spear powerup...

	char szSpawn[512];
	sprintf(szSpawn, "AmmoBox AmmoType1 %s;AmmoCount1 1;Filename %s;Skin %s",
		m_pAmmoData->szName, m_pAmmoData->pProjectileFX->szModel,
		m_pAmmoData->pProjectileFX->szSkin);

	LTVector vScale = m_pAmmoData->pProjectileFX->vModelScale;

	// Make sure the spear sticks out a little ways...

	vVel.Norm();
	vPos -= (vVel * vScale.z/2.0f);

	if (eSpearActionStickWorld == eSpearAction)
	{
		g_pLTServer->AlignRotation(&rRot, &vVel, LTNULL);
	}

	BaseClass* pClass = SpawnObject(szSpawn, LTVector(-10000,-10000,-10000), rRot);

	if (pClass)
	{
		g_pLTServer->ScaleObject(pClass->m_hObject, &vScale);

		LTVector vDims;
		g_pLTServer->GetObjectDims(pClass->m_hObject, &vDims);
		vDims.x *= vScale.x;
		vDims.y *= vScale.y;
		vDims.z *= vScale.z;

		g_pLTServer->SetObjectDims(pClass->m_hObject, &vDims);

		// We don't want other projectiles to impact on us...

		//uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(pClass->m_hObject);
		//dwUsrFlags |= USRFLG_IGNORE_PROJECTILES;
		//g_pLTServer->SetObjectUserFlags(pClass->m_hObject, dwUsrFlags);


		if ( eSpearActionStickAI == eSpearAction || eSpearActionStickPlayer == eSpearAction )
		{
			g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW);
			g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY);

			if ( eSpearActionStickPlayer == eSpearAction )
			{
				g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) | USRFLG_ATTACH_HIDE1SHOW3);
			}

			// Attach it to the character

			CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hObj);
			pCharacter->AddSpear(pClass->m_hObject, pCharacter->GetModelNodeLastHit(), rRot);
		}
		else if ( eSpearActionStickBody == eSpearAction )
		{
			g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW);
			g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY);

			// Attach it to the body

			Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj);
			pBody->AddSpear(pClass->m_hObject, rRot);
		}
		else // ( eSpearActionStickWorld == eSpearAction )
		{
			// Move it to the right position in the world
			g_pLTServer->SetObjectPos(pClass->m_hObject, &vPos);
		}
	}

	CProjectile::HandleImpact(hObj);
}