📄 viewweapon.cpp
字号:
//----------------------------------------------------------
//
// 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 + -