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