⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 weapon.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// ----------------------------------------------------------------------- //

DBOOL CWeapon::FiringTooClose(DVector *vFire, DFLOAT fDist, DVector *vNewPos)
{
	//***** Make sure the server and inventory systems are valid *****//
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE || !m_pViewModel) return DFALSE;

   	CPlayerObj	*pObj = (CPlayerObj*)pServerDE->HandleToObject(m_hOwner);
	DFLOAT fOffset = 0.0f;

	if(pObj)	fOffset = pObj->GetEyeLevel();

	DVector	vOffset;
	VEC_SET(vOffset, 0.0f, fOffset, 0.0f);

	// Setup the vectors for the intersect
	pServerDE->GetObjectPos(m_pViewModel->m_hObject, vNewPos);
	VEC_ADD(*vNewPos, *vNewPos, vOffset);

	VEC_NORM(*vFire);
	VEC_MULSCALAR(*vFire, *vFire, fDist);

	IntersectQuery	iq;
	IntersectInfo	ii;

	// Set the intersection query values
	iq.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY;
	iq.m_FilterFn = LiquidFilterFn;
	iq.m_pUserData = DNULL;

	VEC_COPY(iq.m_From, *vNewPos);
	VEC_ADD(iq.m_To, iq.m_From, *vFire);
	VEC_NORM(*vFire);

	if(pServerDE->IntersectSegment(&iq, &ii))
		return DTRUE;

	return DFALSE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::AlignFireVector
//
//	PURPOSE:	Trick to improve accuracy and keep the effect at the weapon end
//
// ----------------------------------------------------------------------- //

void CWeapon::AlignFireVector(DVector *vFire, DFLOAT fDist)
{
	//***** Make sure the server and inventory systems are valid *****//
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE || !m_hOwner) return;

   	CPlayerObj	*pObj = (CPlayerObj*)pServerDE->HandleToObject(m_hOwner);
	DFLOAT fOffset = 0.0f;

	if(pObj)	fOffset = pObj->GetEyeLevel();

	DVector	vPos, vOffset;
	VEC_SET(vOffset, 0.0f, fOffset, 0.0f);

	// Setup the vectors for the intersect
	pServerDE->GetObjectPos(m_hOwner, &vPos);
	VEC_ADD(vPos, vPos, vOffset);

	VEC_NORM(*vFire);
	VEC_MULSCALAR(*vFire, *vFire, fDist);

	IntersectQuery	iq;
	IntersectInfo	ii;

	// Set the intersection query values
	iq.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY;
	iq.m_FilterFn = LiquidFilterFn;
	iq.m_pUserData = DNULL;

	VEC_COPY(iq.m_From, vPos);
	VEC_ADD(iq.m_To, iq.m_From, *vFire);

	if(pServerDE->IntersectSegment(&iq, &ii))
	{
		VEC_SUB(*vFire, ii.m_Point, m_vPosition);
		VEC_NORM(*vFire);
	}
	else
	{
		VEC_SUB(*vFire, iq.m_To, m_vPosition);
		VEC_NORM(*vFire);
	}
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::SetFirePosRot
//
//	PURPOSE:	Update the firing state of the gun, keep track of muzzle
//				position & rotation (used by AIs)
//
// ----------------------------------------------------------------------- //

void CWeapon::SetFirePosRot(DVector *firedPos, DRotation *rotP, DBOOL bAltFire)
{
	VEC_COPY(m_vPosition, *firedPos);
	ROT_COPY(m_rRotation, *rotP);

	m_eState = bAltFire ? WS_ALT_FIRING : WS_FIRING;
}
	

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::GetHandModelPos
//
//	PURPOSE:	Returns the position of the hand gun model, if any.
//
// ----------------------------------------------------------------------- //

DBOOL CWeapon::GetHandModelPos(DVector *pvPos, DRotation *prRot)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE || !m_pHandModel || !m_pHandModel->m_hObject || !pvPos || !prRot) return DFALSE;


	pServerDE->GetObjectPos(m_pHandModel->m_hObject, pvPos);
	pServerDE->GetObjectRotation(m_pHandModel->m_hObject, prRot);
	return DTRUE;
}
	

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::UpdateFiringState
//
//	PURPOSE:	Update the firing state of the gun, keep track of muzzle
//				position & rotation (used by player objects)
//
// ----------------------------------------------------------------------- //

void CWeapon::UpdateFiringState(DVector *firedPos, DRotation *rotP, DBOOL bFiring, DBOOL bAltFiring)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE || !m_pViewModel) return;

	VEC_COPY(m_vPosition, *firedPos);
	ROT_COPY(m_rRotation, *rotP);

	DFLOAT fTime = pServerDE->GetTime();
	DBOOL bAltFire = DFALSE;

	switch (m_eState)
	{
		case WS_IDLE:
			{
				if(!PlayAnimation(m_nIdleAnim))
				{	
					PlayAnimation(m_nRestAnim);
					m_eState = WS_REST;
					m_fIdleStartTime = fTime;
					m_fIdleDelay = pServerDE->Random(m_fMinIdleDelay, m_fMaxIdleDelay);

					pServerDE->SetModelLooping(m_pViewModel->m_hObject, m_bLoopStatic);
				}
			}

		case WS_REST:
			{
				DFLOAT fReloadTime;
				if (m_bLastFireAlt)
					fReloadTime = m_fAltReloadTime;
				else
					fReloadTime = m_fReloadTime;

				fReloadTime *= m_pInventoryMgr->GetFireRateMultiplier();

				// See if we should play an idle animation
				if((pServerDE->GetTime() - m_fIdleStartTime) > m_fIdleDelay)
				{
					pServerDE->SetModelLooping(m_pViewModel->m_hObject, DFALSE);

					PlayAnimation(m_nIdleAnim);
					m_eState = WS_IDLE;
				}

				// Make sure enough time has gone by to allow firing
				if(((fTime - m_fLastShotTime) > fReloadTime))
				{
					if (bFiring && (CheckAmmo(DFALSE) >= m_nAmmoUse))
					{
						m_fLastShotTime = fTime;
	
						m_eState = WS_START_FIRING;
						if (!PlayAnimation(m_nStartFireAnim))
						{
							pServerDE->SetModelLooping(m_pViewModel->m_hObject, m_bLoopAnim);

							PlayAnimation(m_nFireAnim);
							m_eState = WS_FIRING;
						}
					}
					else if (bAltFiring && !IsAltFireZoom() && (CheckAmmo(DTRUE) >= m_nAltAmmoUse))
					{
						m_fLastShotTime = fTime;

						m_eState = WS_START_ALT_FIRING;
						if (!PlayAnimation(m_nStartAltFireAnim))
						{
							pServerDE->SetModelLooping(m_pViewModel->m_hObject, m_bAltLoopAnim);

							PlayAnimation(m_nAltFireAnim);
							m_eState = WS_ALT_FIRING;
						}
					}
				}
			}
			break;

		case WS_DRAW:
			{
				if(!PlayAnimation(m_nDrawAnim))
				{	
					PlayAnimation(m_nRestAnim);
					m_eState = WS_REST;

					pServerDE->SetModelLooping(m_pViewModel->m_hObject, m_bLoopStatic);
					m_fIdleStartTime = fTime;
				}
			}
			break;

		case WS_HOLSTER:
			{
				if(!PlayAnimation(m_nHolsterAnim))
				{	
					m_eState = WS_HOLSTERED;

					pServerDE->SetModelLooping(m_pViewModel->m_hObject, DFALSE);
				}
			}
			break;

		case WS_START_ALT_FIRING:
		case WS_START_FIRING:
			{
				bAltFire = (m_eState == WS_START_ALT_FIRING);
				if (!PlayAnimation(bAltFire ? m_nStartAltFireAnim : m_nStartFireAnim))
				{
					if (bAltFire ? m_bAltLoopAnim : m_bLoopAnim)
						pServerDE->SetModelLooping(m_pViewModel->m_hObject, DTRUE);
					else
						pServerDE->SetModelLooping(m_pViewModel->m_hObject, DFALSE);

					PlayAnimation(bAltFire ? m_nAltFireAnim : m_nFireAnim);
					m_eState = bAltFire ? WS_ALT_FIRING : WS_FIRING;
				}
				m_fIdleStartTime = fTime;
			}
			break;

		case WS_ALT_FIRING:
		case WS_FIRING:
			{
				bAltFire = (m_eState == WS_ALT_FIRING);
				DBOOL bLoopAnim;
				DDWORD nFireAnim;
				DBOOL  bNowFiring;
				DFLOAT fReloadTime;
				WeaponState eNextState;

				if (bAltFire)
				{
					bLoopAnim	= m_bAltLoopAnim;
					nFireAnim	= m_nAltFireAnim;
					bNowFiring	= bAltFiring;
					fReloadTime = m_fAltReloadTime;
					eNextState	= WS_STOP_ALT_FIRING;
				}
				else
				{
					bLoopAnim	= m_bLoopAnim;
					nFireAnim	= m_nFireAnim;
					bNowFiring	= bFiring;
					fReloadTime = m_fReloadTime;
					eNextState	= WS_STOP_FIRING;
				}

				// No fire anim, so fire right away
				if (nFireAnim == INVALID_ANI && !bLoopAnim)
				{
					OnFireKey();
					m_eState = eNextState;
				}
				// Else looping anim, so fire based on rate of fire
				else if (bLoopAnim)
				{
					if (!bNowFiring || CheckAmmo(bAltFire) == 0.0f)
					{
						m_eState = eNextState;
						pServerDE->SetModelLooping(m_pViewModel->m_hObject, DFALSE);
					}
				}
				else if (m_bSemiAuto)
				{
					// Stopped firing
					if (!m_bLastFiring && bNowFiring)
					{
						pServerDE->ResetModelAnimation(m_pViewModel->m_hObject);
					}
					else if (!PlayAnimation(bAltFire ? m_nAltFireAnim : m_nFireAnim))
					{
						m_eState = eNextState;
					}
				}
				// Else just wait for the animation to stop
				else if (!PlayAnimation(bAltFire ? m_nAltFireAnim : m_nFireAnim))
				{
					m_eState = eNextState;
				}
				// check if there is a fire rate multiplier
				else if (m_pInventoryMgr->GetFireRateMultiplier() < 1.0f)
				{
					if (!m_bLastFiring && bNowFiring && (fTime - m_fLastShotTime) > fReloadTime * m_pInventoryMgr->GetFireRateMultiplier())
						pServerDE->ResetModelAnimation(m_pViewModel->m_hObject);
				}
				m_fIdleStartTime = fTime;
			}
			break;

		case WS_STOP_ALT_FIRING:
		case WS_STOP_FIRING:
			{
				bAltFire = (m_eState == WS_STOP_ALT_FIRING);
				if (!PlayAnimation(bAltFire ? m_nStopAltFireAnim : m_nStopFireAnim))
				{
					PlayAnimation(m_nRestAnim);
					m_eState = WS_REST;

					pServerDE->SetModelLooping(m_pViewModel->m_hObject, m_bLoopStatic);
				}
				m_fIdleStartTime = fTime;
			}
			break;

		default : break;
	}
	m_bLastFiring = bFiring | bAltFiring;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::CreateHandModel
//
//	PURPOSE:	Create the hand-model associated with the weapon.
//
// ----------------------------------------------------------------------- //

void CWeapon::CreateHandModel()
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE || !m_pHandModelFilename || !m_pHandModelSkinname) return;

	HCLASS hOwnerClass = pServerDE->GetObjectClass(m_hOwner);

	DVector vPos;
	DRotation rRot;
	char* szNode = m_bLeftHand ? "l_gun" : "r_gun";

	pServerDE->GetObjectPos(m_hOwner, &vPos);

	// Create the hand view model
	ObjectCreateStruct ocStruct;
	INIT_OBJECTCREATESTRUCT(ocStruct);

	ocStruct.m_ObjectType = OT_MODEL; 
	ocStruct.m_Flags = FLAG_VISIBLE | FLAG_FORCECLIENTUPDATE;
	VEC_COPY(ocStruct.m_Pos, vPos);

	if(m_hClient)
	{
		ocStruct.m_UserData = pServerDE->GetClientID(m_hClient);
		if(m_bLeftHand)
			ocStruct.m_NextUpdate = 0.02f;
	}
	else
		ocStruct.m_UserData = 0;

	_mbscpy((unsigned char*)ocStruct.m_Filename, (const unsigned char*)m_pHandModelFilename);
	_mbscpy((unsigned char*)ocStruct.m_SkinName, (const unsigned char*)m_pHandModelSkinname);

	HCLASS hClass = pServerDE->GetClass("CHandWeaponModel");
	m_pHandModel = (CHandWeaponModel*)pServerDE->CreateObject(hClass, &ocStruct);

	if (m_pHandModel && m_pHandModel->m_hObject)
	{
		// Set to the animation with the proper origin offset
		DDWORD dwAnim = pServerDE->GetAnimIndex(m_pHandModel->m_hObject, "handheld");
		if (dwAnim != INVALID_ANI)
			pServerDE->SetModelAnimation(m_pHandModel->m_hObject, dwAnim);

		m_pHandModel->SetType(m_nType);
		m_pHandModel->SetPlayerOwned( IsPlayer( m_hOwner ));
		m_pHandModel->SetWeaponOwner( this );

		if (m_hClient)
			m_pHandModel->SetClient(m_hClient, m_bLeftHand);

		DVector vOffset;
		DRotation rRotOffset;
		VEC_INIT(vOffset);
		ROT_INIT(rRotOffset);

		// Create an attachment and show the model if there is a node
		if (pServerDE->GetModelNodeTransform(m_hOwner, szNode, &vPos, &rRot))
		{
			pServerDE->CreateAttachment(m_hOwner, m_pHandModel->m_hObject, szNode, &vOffset, &rRotOffset, &m_hHandAttachment);
			m_pHandModel->SetVisible(DTRUE);
		}
		else
		{	// hide it
			pServerDE->CreateAttachment(m_hOwner, m_pHandModel->m_hObject, DNULL, &vOffset, &rRotOffset, &m_hHandAttachment);
			m_pHandModel->SetVisible(DFALSE);
		}
	}
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::DropHandModel
//
//	PURPOSE:	Drops the hand model
//
// ----------------------------------------------------------------------- //

void CWeapon::DropHandModel()
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE || !m_pHandModel || !m_pHandModel->m_hObject) return;

	// Reset the color in case owner had stealth or something.
	pServerDE->SetObjectColor(m_pHandModel->m_hObject, 0.0f, 0.0f, 0.0f, 1.0f);

	if (m_hHandAttachment)
	{
		pServerDE->RemoveAttachment(m_hHandAttachment);
		m_hHandAttachment = DNULL;
	}

	DVector vPos;
	DRotation rRot;

	pServerDE->GetObjectPos(m_hOwner, &vPos);
	pServerDE->GetObjectRotation(m_hOwner, &rRot);

	pServerDE->SetObjectPos(m_pHandModel->m_hObject, &vPos);
	pServerDE->SetObjectRotation(m_pHandModel->m_hObject, &rRot);

	m_pHandModel->Drop();
	m_pHandModel->SetWeaponOwner( NULL );
	m_pHandModel = DNULL;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::SetupViewModel
//
//	PURPOSE:	Sets the model filenames and animations.
//
// ----------------------------------------------------------------------- //

void CWeapon::SetupViewModel()
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE || !m_pViewModel) return;

	HCLASS hOwnerClass = pServerDE->GetObjectClass(m_hOwner);

	// Choose the right or lefthanded model
	char	*pModelFilename;
	if(m_bLeftHand)		pModelFilename = m_pLeftViewModelFilename;
		else			pModelFilename = m_pViewModelFilename;

	if(pModelFilename && m_pViewModelSkinname)
	{
		char	model[128];
		char	skin[128];
		char	firstChar;
		char	start[] = "C_";
		char	*change = DNULL;

		// Get the character to use for the skin

#ifdef _ADDON
		DBOOL bEnemyChar = DFALSE;
#endif

   		CPlayerObj	*pObj = (CPlayerObj*)pServerDE->HandleToObject(m_hOwner);
		if(pObj)
		{
			switch(pObj->GetCharacter())
			{
				case	CHARACTER_CALEB:		firstChar = 'C'; break;
				case	CHARACTER_OPHELIA:		firstChar = 'O'; break;
				case	CHARACTER_ISHMAEL:		firstChar = 'I'; break;
				case	CHARACTER_GABREILLA:	firstChar = 'G'; break;

#ifdef _ADDON
				case	CHARACTER_M_CULTIST:	firstChar = 'C'; break;
				case	CHARACTER_F_CULTIST:	firstChar = 'O'; break;
				case	CHARACTER_SOULDRUDGE:	firstChar = 'C'; break;
				case	CHARACTER_PROPHET:		firstChar = 'I'; break;
#endif

			}

#ifdef _ADDON
			if (pObj->GetCharacter() >= CHARACTER_M_CULTIST)
			{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -