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

📄 weapon.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//----------------------------------------------------------
//
// MODULE  : Weapon.cpp
//
// PURPOSE : General purpose weapon parent
//
// CREATED : 9/20/97
//
//----------------------------------------------------------

// Includes....
#include <stdio.h>
#include "InventoryMgr.h"
#include "BaseCharacter.h"
#include "generic_msg_de.h"
#include "GameProjectiles.h"
#include "PlayerObj.h"
#include "SFXMsgIds.h"
#include "ViewWeaponModel.h"
#include "ClientSparksSFX.h"
#include "ClientMarkSFX.h"
#include "Impacts.h"
//#include "ShellCasing.h"
#include "ObjectUtilities.h"
#include "VolumeBrushTypes.h"
#include "ClientSplashSFX.h"
#include "ClientExplosionSFX.h"
#include "corpse.h"
#include "ai_mgr.h"
#include "DestructableBrush.h"
#include "WeaponDefs.h"
#include "Door.h"
#include "BloodServerShell.h"

void BPrint(char*);


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::CWeapon()
//
//	PURPOSE:	constructor
//
// ----------------------------------------------------------------------- //

CWeapon::CWeapon(DBYTE dbWeapType)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();

	m_hOwner				= DNULL;
	m_hClient				= DNULL;
	m_pInventoryMgr			= DNULL;
	m_bInitialized			= DFALSE;
	m_bClientNotified		= DFALSE;
	m_nType					= dbWeapType;
	m_eState				= WS_HOLSTERED;

	m_pViewModel			= DNULL;

	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_pHandModelFilename	= wd->m_szHandModelFilename;
	m_pHandModelSkinname	= wd->m_szHandModelSkin;
	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_vHandModelOffset, wd->m_vHandModelOffset)
	VEC_COPY(m_vViewModelOffset, wd->m_vViewModelOffset)
	VEC_COPY(m_vMuzzleOffset, wd->m_vMuzzleOffset)
	VEC_COPY(m_vRecoil, wd->m_vRecoil)
	VEC_COPY(m_vFlash, wd->m_vFlash)
	m_fEjectInterval		= wd->m_fEjectInterval;
	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_hFlash				= DNULL;
	m_pViewModel			= DNULL;
	m_pHandModel			= DNULL;
	m_hHandAttachment		= DNULL;

	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_nFlags				= DNULL;

	m_szPic					= DNULL;
	m_szPicH				= DNULL;

	m_bAccuracyCheck		= DTRUE;
	m_bMultiDamageBoost		= DFALSE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::~CWeapon()
//
//	PURPOSE:	destructor
//
// ----------------------------------------------------------------------- //

CWeapon::~CWeapon()
{
	Term();
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::Init()
//
//	PURPOSE:	Initializes the weapon
//
// ----------------------------------------------------------------------- //

void CWeapon::Init(HOBJECT hOwner, CInventoryMgr* pInventoryMgr, DBOOL bLeftHand, HOBJECT hMuzzleFlash)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!hOwner || !pInventoryMgr) return;

	m_hOwner = hOwner;
	m_pInventoryMgr = pInventoryMgr;
	m_bLeftHand = bLeftHand;

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

	m_hFlash = hMuzzleFlash;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::SetClient()
//
//	PURPOSE:	Sets the client for the weapon, and initializes a player view model.
//
// ----------------------------------------------------------------------- //

void CWeapon::SetClient(HCLIENT hClient, CViewWeaponModel *pViewModel)
{
	m_hClient = hClient;

	// Create the view weapon model if it's a Player object
	m_pViewModel = pViewModel;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::Term()
//
//	PURPOSE:	Terminates this weapon
//
// ----------------------------------------------------------------------- //

void CWeapon::Term()
{
	CServerDE* pServerDE = BaseClass::GetServerDE();

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

	if (m_pHandModel)
	{
		pServerDE->RemoveObject(m_pHandModel->m_hObject);
		m_pHandModel->SetWeaponOwner( NULL );
		m_pHandModel = DNULL;
	}

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

	KillSounds();
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::IsIdle()
//
//	PURPOSE:	Terminates this weapon
//
// ----------------------------------------------------------------------- //

DBOOL CWeapon::IsChanging()
{
	if(IsOwnerAPlayer())
	{
		if((m_eState == WS_DRAW) || (m_eState == WS_HOLSTER))
			return	DTRUE;
	}
	return	DFALSE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::Draw()
//
//	PURPOSE:	draws the weapon, sets filenames
//
// ----------------------------------------------------------------------- //

void CWeapon::Draw()
{ 
	m_eState = WS_DRAW; 
	
	SetupMuzzleFlash();

	if (m_hClient)
	{
		SetupViewModel();
	}
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::CheckAmmo()
//
//	PURPOSE:	returns amount of ammo available to this weapon
//
// ----------------------------------------------------------------------- //

DFLOAT CWeapon::CheckAmmo(DBOOL bAltFire)
{
    // If the No Ammo is required for the Weapon then return 1
    if (GetAmmoType(bAltFire) == AMMO_NONE)
    {
        return 1.0f;
    }        

	if (m_pInventoryMgr)
		return m_pInventoryMgr->GetAmmoCount(GetAmmoType(bAltFire));
	else
		return 0.0f;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::CheckDamageMultiplier()
//
//	PURPOSE:	returns the owner's damage multiplier
//
// ----------------------------------------------------------------------- //

DFLOAT CWeapon::GetDamageMultiplier()
{
	if (m_pInventoryMgr)
		return m_pInventoryMgr->GetDamageMultiplier();
	else
		return 0.0f;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::ShowHandModel()
//
//	PURPOSE:	Creates and shows or destroys and hides the hand model.
//
// ----------------------------------------------------------------------- //

void CWeapon::ShowHandModel(DBOOL bShow)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();

	if (bShow)	// Create it.
	{
		if (!m_pHandModel)
		{
			CreateHandModel();
		}
	}
	else	// Remove it.
	{
		if (m_hHandAttachment)
		{
			pServerDE->RemoveAttachment(m_hHandAttachment);
			m_hHandAttachment = DNULL;
		}

		if (m_pHandModel && m_pHandModel->m_hObject)
		{
			pServerDE->RemoveObject(m_pHandModel->m_hObject);
			m_pHandModel->SetWeaponOwner( NULL );
			m_pHandModel = DNULL;
		}
	}
}



// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::Update()
//
//	PURPOSE:	Updates this weapon's position
//
// ----------------------------------------------------------------------- //

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

	// This flag shows that the weapon has had an update, so it's now ok to 
	// send the view object to the client.
	if (!m_bInitialized)
	{
		m_bInitialized = DTRUE;
	}

	// Kill the sound if it's played long enough
	for(int i = 0; i < MAX_FIRE_SOUNDS; i++)
	{
		DBOOL bSoundDone = DFALSE;

		if (m_hCurFireSounds[i] && pServerDE->IsSoundDone(m_hCurFireSounds[i], &bSoundDone) == LT_OK && bSoundDone)
		{
			pServerDE->KillSound(m_hCurFireSounds[i]);
			m_hCurFireSounds[i] = DNULL;
		}	
	}

	// Update muzzle flash
	if (m_bFlashShowing)
	{
		UpdateMuzzleFlash();
	}

	// Set color to match the owner (stealth pu..)
	if (m_hOwner && m_pHandModel && m_pHandModel->m_hObject)
	{
		DVector vColor;
		DFLOAT fAlpha;

		pServerDE->GetObjectColor(m_hOwner, &vColor.x, &vColor.y, &vColor.z, &fAlpha);
		pServerDE->SetObjectColor(m_pHandModel->m_hObject, vColor.x, vColor.y, vColor.z, fAlpha);
	}
}



// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeapon::PlayFireSound()
//
//	PURPOSE:	Plays the firing sound
//
// ----------------------------------------------------------------------- //

void CWeapon::PlayFireSound(DBOOL bAltFire)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	HSOUNDDE hSound = DNULL;

	char *sound;
	DBOOL bLoop = DFALSE;

	if (bAltFire)
	{
		sound = m_szAltFireSound;
	}
	else
	{
		sound = m_szFireSound;
	}

	if (sound && _mbstrlen(sound) > 0)
	{
		DFLOAT Radius = 2000.0f;
		DBYTE sndtype = IsOwnerAPlayer() ? SOUNDPRIORITYBASE_PLAYER : SOUNDPRIORITYBASE_AI;

		hSound = PlaySoundFromObject(m_hOwner, sound, Radius, sndtype + SOUNDPRIORITYMOD_HIGH, bLoop, DTRUE, DTRUE);

		SendSoundTrigger(m_hOwner, SOUND_GUNFIRE, m_vPosition, Radius);
	}

	int		soundToKill = 0;

	if (hSound)
	{
		// See if there is an available sound slot, if not, kill the sound with the least time remaining.

		int nIndex = -1;
		for (int i=0; i < MAX_FIRE_SOUNDS; i++)
		{
			if (!m_hCurFireSounds[i]) 
			{
				nIndex = i;
				break;	// A match!
			}
			else if (nIndex == -1 || m_fCurFireSoundsEndTime[i] < m_fCurFireSoundsEndTime[nIndex])
			{
				nIndex = i;
			}
		}

		if (nIndex != -1)	// This should ALWAYS be the case.
		{
			DFLOAT fTime;
			pServerDE->GetSoundDuration(hSound, &fTime);
			fTime += pServerDE->GetTime();

			if (m_hCurFireSounds[nIndex])
				pServerDE->KillSound(m_hCurFireSounds[nIndex]);

			m_hCurFireSounds[nIndex] = hSound;
			m_fCurFireSoundsEndTime[nIndex] = fTime;

		}
		else
		{
			pServerDE->KillSound(hSound);
			hSound = DNULL;
		}
	}
}


// ----------------------------------------------------------------------- //

⌨️ 快捷键说明

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