//----------------------------------------------------------------------------- // Purpose: // Input : *pPlayer - //----------------------------------------------------------------------------- void CWeaponFrag::ThrowGrenade( CBasePlayer *pPlayer, bool Invis /*= false*/ ) { #ifndef CLIENT_DLL Vector vecEye = pPlayer->EyePosition(); Vector vForward, vRight; pPlayer->EyeVectors( &vForward, &vRight, NULL ); Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f; CheckThrowPosition( pPlayer, vecEye, vecSrc ); // vForward[0] += 0.1f; vForward[2] += 0.1f; Vector vecThrow; pPlayer->GetVelocity( &vecThrow, NULL ); //DHL - We're just gonna set the grenade off at vecSrc if it goes off "in their hand", so don't worry about velocity if ( !Invis ) vecThrow += vForward * 1200; //DHL: Added conditional to last arg, to allow priming... //If we haven't hit the time we should explode yet, use the remaining time as the clock for the grenade //Otherwise (we're due to explode) throw (will be forced in the PostFrame function) and go off near immediately CBaseGrenade *pGrenade = Fraggrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, ( (flExplodeTime > gpGlobals->curtime) ? (flExplodeTime - gpGlobals->curtime) : 0.01f ), false ); if ( pGrenade ) { if ( pPlayer && pPlayer->m_lifeState != LIFE_ALIVE ) { pPlayer->GetVelocity( &vecThrow, NULL ); IPhysicsObject *pPhysicsObject = pGrenade->VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->SetVelocity( &vecThrow, NULL ); } } pGrenade->SetDamage( GetHL2MPWpnData().m_iPlayerDamage ); pGrenade->SetDamageRadius( GRENADE_DAMAGE_RADIUS ); if ( Invis ) //DHL - Don't always want to be able to see the grenade { pGrenade->AddEffects( EF_NODRAW ); pGrenade->SetMoveType( MOVETYPE_NONE ); CUtlVector<CBaseEntity *> childrenList; GetAllChildren( pGrenade, childrenList ); if ( childrenList.Count() ) // If there's any children in the list... { for ( int i = childrenList.Count()-1; i >= 0; --i ) { UTIL_Remove( childrenList[i] ); //Remove them all } } pGrenade->SetAbsVelocity( vec3_origin ); pGrenade->SetAbsOrigin( vecSrc ); //Put the grenade right back in their hand incase it's moved pGrenade->Detonate(); } } #endif m_bRedraw = true; WeaponSound( SINGLE ); // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); }
void CNPC_Zombine::HandleAnimEvent( animevent_t *pEvent ) { if ( pEvent->event == AE_ZOMBINE_PULLPIN ) { Vector vecStart; QAngle angles; GetAttachment( "grenade_attachment", vecStart, angles ); CBaseGrenade *pGrenade = Fraggrenade_Create( vecStart, vec3_angle, vec3_origin, AngularImpulse( 0, 0, 0 ), this, 3.5f, true ); if ( pGrenade ) { // Move physobject to shadow IPhysicsObject *pPhysicsObject = pGrenade->VPhysicsGetObject(); if ( pPhysicsObject ) { pGrenade->VPhysicsDestroyObject(); int iAttachment = LookupAttachment( "grenade_attachment"); pGrenade->SetMoveType( MOVETYPE_NONE ); pGrenade->SetSolid( SOLID_NONE ); pGrenade->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); pGrenade->SetAbsOrigin( vecStart ); pGrenade->SetAbsAngles( angles ); pGrenade->SetParent( this, iAttachment ); pGrenade->SetDamage( 200.0f ); m_hGrenade = pGrenade; EmitSound( "Zombine.ReadyGrenade" ); // Tell player allies nearby to regard me! CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); CAI_BaseNPC *pNPC; for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) { pNPC = ppAIs[i]; if( pNPC->Classify() == CLASS_PLAYER_ALLY || pNPC->Classify() == CLASS_PLAYER_ALLY_VITAL && pNPC->FVisible(this) ) { int priority; Disposition_t disposition; priority = pNPC->IRelationPriority(this); disposition = pNPC->IRelationType(this); pNPC->AddEntityRelationship( this, disposition, priority + 1 ); } } } m_iGrenadeCount--; } return; } if ( pEvent->event == AE_NPC_ATTACK_BROADCAST ) { if ( HasGrenade() ) return; } BaseClass::HandleAnimEvent( pEvent ); }