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

📄 viewweapon.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//----------------------------------------------------------
//
// MODULE  : ViewWeapon.cpp
//
// PURPOSE : Handles client side weapons.
//
// CREATED : 9/22/97
//
//----------------------------------------------------------

// Includes...

#include <crtdbg.h>
#include <mbstring.h>
#include "ViewWeapon.h"
#include "SFXMsgIds.h"
#include "ClientUtilities.h"
#include "BloodClientShell.h"
#include "SoundTypes.h"


DBYTE g_byRandomWeaponSeed;


// Defines....

#define ANIM_GUN_NONE		0
#define ANIM_GUN_FIRING		1
#define ANIM_GUN_FIRING2	2

#define LOWER_SPEED			2
#define LOWER_AMOUNT		(PI/4)

#define WEAPON_KEY_FIRE			"FIRE_KEY"
#define WEAPON_KEY_SOUND		"SOUND_KEY"
#define WEAPON_KEY_SOUNDLOOP	"SOUNDLOOP_KEY"
#define WEAPON_KEY_SOUNDSTOP	"SOUNDSTOP_KEY"
#define WEAPON_KEY_HIDE			"HIDE_KEY"
#define WEAPON_KEY_SHOW			"SHOW_KEY"

#define INVALID_ANI		((DDWORD)-1)


DRotation g_rotGun;
HLOCALOBJ g_hWeaponModel;


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::CViewWeapon()
//
//	PURPOSE:	Constructor
//
// --------------------------------------------------------------------------- //

CViewWeapon::CViewWeapon()
{
	m_nType				= WEAP_NONE;
	VEC_INIT(m_vViewModelOffset);
	VEC_INIT(m_vFlashPos);
	VEC_INIT(m_vAdjFlashPos);
	m_fViewKick			= 0;
	m_bCumulativeKick	= DFALSE;
	m_bLeftHand			= DFALSE;
	
	m_fBobHeight		= 0.0f;
	m_fBobWidth			= 0.0f;
	m_fLastEjectedTime	= 0.0f;
	m_bOkToFire			= DTRUE;
	m_nFiredType		= 0;
	m_pClientDE			= NULL;
	m_hFlashSprite		= NULL;
	m_hAltFlashSprite	= NULL;
	m_fFlashDuration	= 0.0f;
	m_nFlashVisible		= 0;
	m_nIgnoreFX			= 0;
	m_hLoopSound		= DNULL;

	m_nFlags			= FLAG_ENVIRONMENTMAP;
	m_fChromeValue		= 0.5f;

	m_hObject			= DNULL;
}


// --------------------------------------------------------------------------- //
//	ROUTINE:	CViewWeapon::~CViewWeapon()
//	PURPOSE:	Deletes this weapon object.
// --------------------------------------------------------------------------- //
CViewWeapon::~CViewWeapon()
{
	Term();
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::Create()
//
//	PURPOSE:	Sets up the weapon info, creates the model.
//
// --------------------------------------------------------------------------- //
DBOOL CViewWeapon::Create(CClientDE* pClientDE, DBYTE byWeaponID, DBOOL bLeftHand)
{
	m_pClientDE			= pClientDE;

	m_bLeftHand			= bLeftHand;

	m_fBobHeight		= 0.0f;
	m_fBobWidth			= 0.0f;
	m_fLastEjectedTime	= 0.0f;
	m_bOkToFire			= DTRUE;
	m_nFiredType		= 0;

	m_fLowerOffset		= 0;

	m_nType					= byWeaponID;
	m_eState				= WS_DRAW;

	WeaponData *wd			= &g_WeaponDefaults[m_nType-1];

	m_nFireType				= wd->m_nFireType;
	m_pViewModelFilename	= wd->m_szViewModelFilename;
	m_pLeftViewModelFilename = wd->m_szLeftViewModelFilename;
	m_pViewModelSkinname	= wd->m_szViewModelSkin;
	m_nAmmoType				= wd->m_nAmmoType;
	m_nAmmoUse				= wd->m_nAmmoUse;
	m_nAltAmmoUse			= wd->m_nAltAmmoUse;
	m_fDamage				= 0;
	m_fMinDamage			= wd->m_fMinDamage;
	m_fMaxDamage			= wd->m_fMaxDamage;
	m_fMinAltDamage			= wd->m_fMinAltDamage;
	m_fMaxAltDamage			= wd->m_fMaxAltDamage;
	m_fReloadTime			= wd->m_fReloadTime;
	m_fAltReloadTime		= wd->m_fAltReloadTime;
	m_Spread				= wd->m_Spread;
	m_AltSpread				= wd->m_AltSpread;
	m_fProjVelocity			= wd->m_fProjVelocity;
	m_fAltProjVelocity		= wd->m_fAltProjVelocity;
	m_fRange				= wd->m_fRange;
	m_fAltRange				= wd->m_fAltRange;
	m_dwShotsPerFire		= wd->m_dwShotsPerFire;
	m_dwAltShotsPerFire		= wd->m_dwAltShotsPerFire;
	m_dwStrengthReq			= wd->m_dwStrengthReq;
	m_dwTwoHandStrengthReq	= wd->m_dwTwoHandStrengthReq;
	m_bDualHanded = (m_dwTwoHandStrengthReq > 0);
	m_nDamageRadius			= wd->m_nDamageRadius;
	m_nAltDamageRadius		= wd->m_nAltDamageRadius;
	m_bAltFireZoom			= wd->m_bAltFireZoom;
	m_bSemiAuto				= wd->m_bSemiAuto;

	m_szFireSound			= wd->m_szFireSound;
	m_szAltFireSound		= wd->m_szAltFireSound;
	m_szEmptyWeaponSound	= wd->m_szEmptyWeaponSound;
	m_szAltEmptyWeaponSound	= wd->m_szAltEmptyWeaponSound;
	m_szProjectileClass		= wd->m_szProjectileClass;
	m_szAltProjectileClass	= wd->m_szAltProjectileClass;
	m_szWeaponName			= wd->m_szWeaponName;
	m_nWeaponNameID			= wd->m_nWeaponNameID;
	m_szFlashSprite			= wd->m_szFlashSprite;
	m_szAltFlashSprite		= wd->m_szAltFlashSprite;
	m_fFlashDuration		= wd->m_fFlashDuration;
	m_fFlashScale			= wd->m_fFlashScale;
	VEC_COPY(m_vViewModelOffset, wd->m_vViewModelOffset)
	VEC_COPY(m_vMuzzleOffset, wd->m_vMuzzleOffset)
	VEC_COPY(m_vFlashPos, wd->m_vFlash)
	m_fViewKick				= wd->m_fViewKick;				// Amount to adjust view when firing.
	m_bCumulativeKick		= wd->m_bCumulativeKick;		// Kick is Cumulative
	m_bLoopAnim				= wd->m_bLoopAnim;
	m_bAltLoopAnim			= wd->m_bAltLoopAnim;
	m_bLoopStatic			= DFALSE;

	m_fLastShotTime			= 0;
	m_fFireTime				= 0;
	m_bLastFireAlt			= DFALSE;

	if (m_nAmmoType == AMMO_BULLET || m_nAmmoType == AMMO_SHELL)
	{
		m_bEjectShell = DTRUE;
	}
	else
	{
		m_bEjectShell = DFALSE;
	}

	m_fIdleStartTime		= 0.0f;
	m_fIdleDelay			= 0.0f;
	m_fMinIdleDelay			= 20.0f;
	m_fMaxIdleDelay			= 60.0f;

	// Create a muzzle flash
	m_bFlashShowing			= DFALSE;

	m_nRestAnim				= INVALID_ANI;
	m_nIdleAnim				= INVALID_ANI;
	m_nDrawAnim				= INVALID_ANI;
	m_nDrawDuelAnim			= INVALID_ANI;
	m_nHolsterAnim			= INVALID_ANI;
	m_nHolsterDuelAnim		= INVALID_ANI;
	m_nStartFireAnim		= INVALID_ANI;
	m_nFireAnim				= INVALID_ANI;
	m_nStopFireAnim			= INVALID_ANI;
	m_nStartAltFireAnim		= INVALID_ANI;
	m_nAltFireAnim			= INVALID_ANI;
	m_nStopAltFireAnim		= INVALID_ANI;

	m_nDamageType			= DAMAGE_TYPE_NORMAL;

	for (int i=0; i < MAX_FIRE_SOUNDS; i++)
	{
		m_hCurFireSounds[i] = DNULL;
		m_fCurFireSoundsEndTime[i] = 0.0f;
	}

	m_nUpdateWait = 10;

	m_szPic					= DNULL;
	m_szPicH				= DNULL;

	m_bAccuracyCheck		= DTRUE;
	
	if ((m_szFlashSprite[0] != '\0') || (m_szAltFlashSprite[0] != '\0'))
		CreateFlash(wd->m_fFlashScale);


	if (m_bLeftHand)
	{
		m_vViewModelOffset.x = -m_vViewModelOffset.x;
		m_vFlashPos.x = -m_vFlashPos.x;
		m_vMuzzleOffset.x = -m_vMuzzleOffset.x;
	}

	SetupViewModel();

	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::CreateFlash
//
//	PURPOSE:	Create the muzzle flash
//
// ----------------------------------------------------------------------- //

void CViewWeapon::CreateFlash(DFLOAT fScale)
{
	if (!m_pClientDE) return;

	ObjectCreateStruct createStruct;
	INIT_OBJECTCREATESTRUCT(createStruct);
	
	DVector vFlashScale;
	VEC_SET(vFlashScale, fScale, fScale, fScale);

	if (m_szFlashSprite[0] != '\0')
	{
		createStruct.m_ObjectType = OT_SPRITE;
		_mbscpy((unsigned char*)createStruct.m_Filename, (const unsigned char*)m_szFlashSprite);
		createStruct.m_Flags	  = 0;

		m_hFlashSprite = m_pClientDE->CreateObject(&createStruct);
		m_pClientDE->SetObjectScale(m_hFlashSprite, &vFlashScale);
	}

	if (!_mbscmp((const unsigned char*)m_szFlashSprite, (const unsigned char*)m_szAltFlashSprite))
	{
		m_hAltFlashSprite = m_hFlashSprite;
	}
	else if (m_szAltFlashSprite[0] != '\0')
	{
		createStruct.m_ObjectType = OT_SPRITE;
		_mbscpy((unsigned char*)createStruct.m_Filename, (const unsigned char*)m_szAltFlashSprite);
		createStruct.m_Flags	  = 0;

		m_hAltFlashSprite = m_pClientDE->CreateObject(&createStruct);
		m_pClientDE->SetObjectScale(m_hAltFlashSprite, &vFlashScale);
	}
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::Term()
//
//	PURPOSE:	
//
// --------------------------------------------------------------------------- //

void CViewWeapon::Term()
{
	SendSoundMsg(DNULL, 0x02);

	if (m_hAltFlashSprite && (m_hAltFlashSprite != m_hFlashSprite))
	{
		m_pClientDE->DeleteObject(m_hAltFlashSprite);
		m_hAltFlashSprite = DNULL;
	}

	if (m_hFlashSprite)
	{
		m_pClientDE->DeleteObject(m_hFlashSprite);
		m_hFlashSprite = DNULL;
		m_hAltFlashSprite = DNULL;
	}

	if( m_szPic )
	{
		m_pClientDE->FreeString( m_szPic );
		m_szPic = DNULL;
	}
	if( m_szPicH )
	{
		m_pClientDE->FreeString( m_szPicH );
		m_szPicH = DNULL;
	}

	if (m_hObject)
	{
		m_pClientDE->DeleteObject(m_hObject);
		m_hObject = DNULL;
	}
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::AdjustAngleAndSetPos()
//
//	PURPOSE:	
//
// --------------------------------------------------------------------------- //

void CViewWeapon::AdjustAngleAndSetPos(DFLOAT fPitch, DFLOAT fYaw, DVector *pos)
{
	DRotation rotGun;
	DVector vR;
	DVector vU;
	DVector vF;
	DVector myPos;

	if (!m_hObject) return;

	// Compute offset for gun &
	// Move gun to correct position
	m_pClientDE->SetupEuler(&rotGun, fPitch, fYaw, (float)0);
	m_pClientDE->SetObjectRotation(m_hObject, &rotGun);
	ROT_COPY(g_rotGun, rotGun);

	m_pClientDE->GetRotationVectors(&rotGun, &vU, &vR, &vF);

	VEC_COPY(myPos, *pos)
	VEC_MULSCALAR(vU, vU, (m_vViewModelOffset.y + m_fBobHeight));
	VEC_MULSCALAR(vR, vR, (m_vViewModelOffset.x + m_fBobWidth));
	VEC_MULSCALAR(vF, vF, m_vViewModelOffset.z);

	VEC_ADD(myPos, myPos, vU);
	VEC_ADD(myPos, myPos, vR);
	VEC_ADD(myPos, myPos, vF);

	m_pClientDE->SetObjectPos(m_hObject, &myPos);
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::Update()
//
//	PURPOSE:	Updates the gun's position and animation state.
//
// --------------------------------------------------------------------------- //

void CViewWeapon::Update(DFLOAT fPitch, DFLOAT fYaw, DVector *pos)
{
	DFLOAT cTime = m_pClientDE->GetTime();
	DRotation rot;
	DVector vR;
	DVector vU;
	DVector vF;
	DVector myPos;
	static DFLOAT fFireAnimLength;

	if (!m_hObject) return;

	//******************************************************************
	// Place the flash at the muzzle of the gun if that node exists
	DVector		tempPos;
	DRotation	tempRot;

	ROT_INIT(tempRot);
	VEC_INIT(tempPos);

	m_pClientDE->SetObjectRotation(m_hObject, &tempRot);
	m_pClientDE->SetObjectPos(m_hObject, &tempPos);

	if(m_pClientDE->GetModelNodeTransform(m_hObject, "muzzle", &tempPos, &tempRot))
	{
		VEC_ADD(m_vFlashPos, tempPos, m_vViewModelOffset);
		VEC_MULSCALAR(m_vFlashPos, m_vFlashPos, 10.0f);
	}
	//******************************************************************

	// Compute offset for gun & move gun to correct position
	m_fLowerOffset = 0;
	AdjustAngleAndSetPos(fPitch, fYaw, pos);

	// Now figure out the muzzle position for the flash.
	m_pClientDE->GetObjectPos(m_hObject, &myPos);
	m_pClientDE->SetupEuler(&rot, fPitch, fYaw, (float)0);
	m_pClientDE->GetRotationVectors(&rot, &vU, &vR, &vF);

	VEC_COPY(m_vAdjFlashPos, myPos)
	VEC_MULSCALAR(vU, vU, (m_vFlashPos.y + m_fBobHeight));
	VEC_MULSCALAR(vR, vR, (m_vFlashPos.x + m_fBobWidth));
	VEC_MULSCALAR(vF, vF, m_vFlashPos.z );

	VEC_ADD(m_vAdjFlashPos, m_vAdjFlashPos, vU);
	VEC_ADD(m_vAdjFlashPos, m_vAdjFlashPos, vR);
	VEC_ADD(m_vAdjFlashPos, m_vAdjFlashPos, vF);

	VEC_COPY(m_vMuzzleOffset, m_vAdjFlashPos);

	if (m_nFlashVisible)
		UpdateFlash(m_vAdjFlashPos);

	// Set the object's alpha the same as the client object
	DFLOAT fR, fG, fB, fA;
	m_pClientDE->GetObjectColor(m_pClientDE->GetClientObject(), &fR, &fG, &fB, &fA);
	m_pClientDE->SetObjectColor(m_hObject, 0, 0, 0, fA);
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::UpdateBob()
//
//	PURPOSE:	Sets the weapon bob width and height values.
//
// --------------------------------------------------------------------------- //

void CViewWeapon::UpdateBob(DFLOAT fHeight, DFLOAT fWidth)
{
	m_fBobHeight = fHeight;
	m_fBobWidth  = fWidth;
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::UpdateFlash()
//
//	PURPOSE:	Updates the muzzle flash sprite position and visibility.
//
// --------------------------------------------------------------------------- //

void CViewWeapon::UpdateFlash(DVector vFlashPos)
{
	if (!m_pClientDE) return;

	DFLOAT fCurTime = m_pClientDE->GetTime();

	if ((fCurTime >= m_fFlashStartTime + m_fFlashDuration) && (fCurTime >= m_fFlashStartTime + m_pClientDE->GetFrameTime() + 0.05))
	{
		m_pClientDE->SetObjectFlags(m_hFlashSprite, 0);
		m_pClientDE->SetObjectFlags(m_hAltFlashSprite, 0);
		m_nFlashVisible = 0;
	}	
	else
	{
		if (m_nFlashVisible == 1)
		{
			m_pClientDE->SetObjectFlags(m_hFlashSprite, FLAG_VISIBLE | FLAG_SPRITEBIAS | FLAG_NOLIGHT);
			m_pClientDE->SetObjectPos(m_hFlashSprite, &vFlashPos);
		}
		else if (m_nFlashVisible == 2)
		{
			m_pClientDE->SetObjectFlags(m_hAltFlashSprite, FLAG_VISIBLE | FLAG_SPRITEBIAS | FLAG_NOLIGHT);
			m_pClientDE->SetObjectPos(m_hAltFlashSprite, &vFlashPos);
		}
	}
}



// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::Hide()
//
//	PURPOSE:	Turn off FLAG_VISIBLE for this weapon.
//
// --------------------------------------------------------------------------- //

void CViewWeapon::Hide()
{
	if (!m_hObject) return;
	
	DDWORD dwFlags = m_pClientDE->GetObjectFlags(m_hObject);
	m_pClientDE->SetObjectFlags(m_hObject, (dwFlags & ~FLAG_VISIBLE));

	if (m_nFlashVisible && m_hFlashSprite && m_hAltFlashSprite)
	{
		m_pClientDE->SetObjectFlags(m_hFlashSprite, 0);
		m_pClientDE->SetObjectFlags(m_hAltFlashSprite, 0);
		m_nFlashVisible = 0;
	}
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CViewWeapon::Show()
//
//	PURPOSE:	Turn on FLAG_VISIBLE for this weapon.
//
// --------------------------------------------------------------------------- //

void CViewWeapon::Show()
{
	if (!m_hObject) return;

⌨️ 快捷键说明

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