📄 weapon_brickbat.cpp
字号:
// Output :
//-----------------------------------------------------------------------------
int CWeaponBrickbat::WeaponRangeAttack1Condition( float flDot, float flDist )
{
// If things haven't changed too much since last time
// just return that previously calculated value
if (gpGlobals->curtime < m_fNextThrowCheck )
{
return m_iThrowBits;
}
if ( flDist < m_fMinRange1)
{
m_iThrowBits = COND_TOO_CLOSE_TO_ATTACK;
}
else if (flDist > m_fMaxRange1)
{
m_iThrowBits = COND_TOO_FAR_TO_ATTACK;
}
else if (flDot < 0.5)
{
m_iThrowBits = COND_NOT_FACING_ATTACK;
}
// If moving, can't throw.
else if ( m_flGroundSpeed != 0 )
{
m_iThrowBits = COND_NONE;
}
else
{
// Ok we should check again as some time has passed
// This function is only used by NPC's so we can cast to a Base Monster
CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer();
CBaseEntity *pEnemy = pNPC->GetEnemy();
if (!pEnemy)
{
return COND_NONE;
}
// Get Enemy Position
Vector vecTarget = Vector( pEnemy->GetAbsOrigin().x,
pEnemy->GetAbsOrigin().y,
pEnemy->GetAbsMins().z );
// Get Toss Vector
Vector throwStart = pNPC->Weapon_ShootPosition();
Vector vecToss;
CBaseEntity* pBlocker = NULL;
float throwDist = (throwStart - vecTarget).Length();
float fGravity = sv_gravity.GetFloat();
float throwLimit = pNPC->ThrowLimit(throwStart, vecTarget, fGravity, 35, WorldAlignMins(), WorldAlignMaxs(), pEnemy, &vecToss, &pBlocker);
// If I can make the throw (or most of the throw)
if (!throwLimit || (throwLimit != throwDist && throwLimit > 0.8*throwDist))
{
m_vecTossVelocity = vecToss;
m_iThrowBits = COND_CAN_RANGE_ATTACK1;
}
else
{
m_iThrowBits = COND_NONE;
}
}
// don't check again for a while.
m_fNextThrowCheck = gpGlobals->curtime + 0.33; // 1/3 second.
return m_iThrowBits;
}
//-----------------------------------------------------------------------------
// Purpose:
//
//
//-----------------------------------------------------------------------------
void CWeaponBrickbat::ThrowBrickbat( Vector vecSrc, Vector vecVelocity, float damage)
{
CGrenade_Brickbat *pBrickbat = (CGrenade_Brickbat*)Create( BrickBatAmmoArray[m_iCurrentAmmoType].m_sClassName, vecSrc, vec3_angle, GetOwner() );
if (!pBrickbat)
{
Msg("Brickbat type (%s) not defined!\n",BrickBatAmmoArray[m_iCurrentAmmoType].m_sClassName);
return;
}
AngularImpulse vecAngVel;
// Tumble through the air
vecAngVel.x = random->RandomFloat ( -100, -500 );
vecAngVel.z = random->RandomFloat ( -100, -500 );
vecAngVel.y = random->RandomFloat ( -100, -500 );
// If physically simulated
IPhysicsObject *pPhysicsObject = pBrickbat->VPhysicsGetObject();
if ( pPhysicsObject )
{
pPhysicsObject->AddVelocity( &vecVelocity, &vecAngVel );
}
// Otherwise
else
{
pBrickbat->SetAbsVelocity( vecVelocity );
QAngle angVel;
AngularImpulseToQAngle( vecAngVel, angVel );
pBrickbat->SetLocalAngularVelocity( angVel );
}
pBrickbat->SetOwner( GetOwner() );
pBrickbat->SetOwnerEntity( ((CBaseEntity*)GetOwner()) );
pBrickbat->SetDamage(damage);
m_nAmmoCount[m_iCurrentAmmoType]--;
m_bNeedThrow = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//
//
//-----------------------------------------------------------------------------
void CWeaponBrickbat::PrimaryAttack( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if (!pPlayer)
{
return;
}
SendWeaponAnim(ACT_VM_PULLBACK);
// Don't fire again until fire animation has completed
float flSequenceEndTime = gpGlobals->curtime + SequenceDuration();
pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime;
m_bNeedThrow = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//
//
//-----------------------------------------------------------------------------
void CWeaponBrickbat::Throw( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if (!pPlayer)
{
return;
}
Vector vecSrc = pPlayer->WorldSpaceCenter();
Vector vecFacing = pPlayer->BodyDirection3D( );
vecSrc = vecSrc + vecFacing * 18.0;
vecSrc.z += 24.0f;
// Player may have turned to face a wall during the throw anim in which case
// we don't want to throw the SLAM into the wall
if (ObjectInWay())
{
vecSrc = pPlayer->WorldSpaceCenter() + vecFacing * 5.0;
}
Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
vecAiming.z += 0.20; // Raise up so passes through reticle
ThrowBrickbat(vecSrc, vecAiming*800, sk_plr_dmg_brickbat.GetFloat());
pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
SendWeaponAnim(ACT_VM_THROW);
// Don't fire again until fire animation has completed
float flSequenceEndTime = gpGlobals->curtime + SequenceDuration();
pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime;
m_bNeedThrow = false;
m_bNeedDraw = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//
//
//-----------------------------------------------------------------------------
void CWeaponBrickbat::SecondaryAttack( void )
{
int counter = 0;
while (counter < NUM_BRICKBAT_AMMO_TYPES)
{
m_iCurrentAmmoType = ((++m_iCurrentAmmoType)%NUM_BRICKBAT_AMMO_TYPES);
// If I've found a category with ammo stop looking
if (m_nAmmoCount[m_iCurrentAmmoType] > 0)
{
DrawAmmo();
return;
}
counter++;
}
// I'm out of all ammo types
}
//-----------------------------------------------------------------------------
// Purpose:
//
//
//-----------------------------------------------------------------------------
void CWeaponBrickbat::DrawAmmo( void )
{
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
// -------------------------------------------
// Make sure I have ammo of the current type
// -------------------------------------------
int counter = 0;
while (m_nAmmoCount[m_iCurrentAmmoType] <=0)
{
m_iCurrentAmmoType = ((++m_iCurrentAmmoType)%NUM_BRICKBAT_AMMO_TYPES);
counter++;
// ----------------------------------------------------
// No ammo of any types so drop the weapon and destroy
// ----------------------------------------------------
if (counter >= NUM_BRICKBAT_AMMO_TYPES)
{
pOwner->Weapon_Drop( this, NULL, NULL );
UTIL_Remove(this);
return;
}
}
SetModel( BrickBatAmmoArray[m_iCurrentAmmoType].m_sViewModel);
CBaseViewModel *vm = pOwner->GetViewModel();
if ( vm )
{
vm->SetModel( BrickBatAmmoArray[m_iCurrentAmmoType].m_sViewModel );
}
//Msg("Drawing %s...\n",BrickBatAmmoArray[m_iCurrentAmmoType].m_sClassName);
m_bNeedDraw = false;
SendWeaponAnim(ACT_VM_DRAW);
// Don't fire again until fire animation has completed
float flSequenceEndTime = gpGlobals->curtime + SequenceDuration();
pOwner->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime;
}
//-----------------------------------------------------------------------------
// Purpose: Override so shotgun can do mulitple reloads in a row
// Input :
// Output :
//-----------------------------------------------------------------------------
void CWeaponBrickbat::ItemPostFrame( void )
{
/* HANDY FOR DEBUG
for (int i=0;i<NUM_BRICKBAT_AMMO_TYPES;i++)
{
Msg("%i %s",m_nAmmoCount[i],BrickBatAmmoArray[i].m_sClassName);
if (i==m_iCurrentAmmoType)
{
Msg("**");
}
Msg("\n");
}
*/
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if (!pOwner)
{
return;
}
if (m_bNeedThrow)
{
Throw();
}
else if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
{
SecondaryAttack();
}
else if ((pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime))
{
// Uses secondary ammo only
if (pOwner->GetAmmoCount(m_iPrimaryAmmoType))
{
PrimaryAttack();
}
}
else if (m_bNeedDraw)
{
DrawAmmo();
}
else
{
SendWeaponAnim( ACT_VM_IDLE );
//pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration();
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CWeaponBrickbat::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr )
{
if ( info.GetDamageType() & DMG_BULLET)
{
if (BrickBatAmmoArray[m_iCurrentAmmoType].m_nAmmoType == BRICKBAT_CREMATORHEAD ||
BrickBatAmmoArray[m_iCurrentAmmoType].m_nAmmoType == BRICKBAT_ROCK )
{
g_pEffects->Ricochet(ptr->endpos,ptr->plane.normal);
}
}
BaseClass::TraceAttack( info, vecDir, ptr );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CWeaponBrickbat::CWeaponBrickbat( void )
{
#ifdef _DEBUG
m_vecTossVelocity.Init();
#endif
m_fMinRange1 = 200;
m_fMaxRange1 = 1000;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -