CCrossbowBolt *CCrossbowBolt::BoltCreate( void ) { // Create a new entity with CCrossbowBolt private data CCrossbowBolt *pBolt = GetClassPtr( (CCrossbowBolt *)NULL ); pBolt->pev->classname = MAKE_STRING("bolt"); pBolt->Spawn(); return pBolt; }
CCrossbowBolt *CCrossbowBolt::BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, CBasePlayer *pentOwner ) { // Create a new entity with CCrossbowBolt private data CCrossbowBolt *pBolt = (CCrossbowBolt *)CreateEntityByName( "crossbow_bolt" ); UTIL_SetOrigin( pBolt, vecOrigin ); pBolt->SetAbsAngles( angAngles ); pBolt->Spawn(); pBolt->SetOwnerEntity( pentOwner ); return pBolt; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponCrossbow::FireBolt( void ) { if ( m_iClip1 <= 0 ) { if ( !m_bFireOnEmpty ) { Reload(); } else { WeaponSound( EMPTY ); m_flNextPrimaryAttack = 0.15; } return; } CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner == NULL ) return; #ifndef CLIENT_DLL Vector vecAiming = pOwner->GetAutoaimVector( 0 ); Vector vecSrc = pOwner->Weapon_ShootPosition(); QAngle angAiming; VectorAngles( vecAiming, angAiming ); CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate( vecSrc, angAiming, GetHL2MPWpnData().m_iPlayerDamage, pOwner ); if ( pOwner->GetWaterLevel() == 3 ) { pBolt->SetAbsVelocity( vecAiming * BOLT_WATER_VELOCITY ); } else { pBolt->SetAbsVelocity( vecAiming * BOLT_AIR_VELOCITY ); } #endif m_iClip1--; pOwner->ViewPunch( QAngle( -2, 0, 0 ) ); WeaponSound( SINGLE ); WeaponSound( SPECIAL2 ); SendWeaponAnim( ACT_VM_PRIMARYATTACK ); if ( !m_iClip1 && pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) { // HEV suit - indicate out of ammo condition pOwner->SetSuitUpdate("!HEV_AMO0", FALSE, 0); } m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + 0.75; DoLoadEffect(); SetChargerState( CHARGER_STATE_DISCHARGE ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponCrossbow::FireBolt() { if ( m_iClip1 <= 0 ) { if ( !m_bFireOnEmpty ) Reload(); else { WeaponSound( EMPTY ); m_flNextPrimaryAttack = 0.15; } return; } CBasePlayer *pOwner = ToBasePlayer(GetOwner()); if ( !pOwner ) return; #ifndef CLIENT_DLL pOwner->RumbleEffect(RUMBLE_357, 0, RUMBLE_FLAG_RESTART); Vector vecAiming = pOwner->GetAutoaimVector(0); Vector vecSrc = pOwner->Weapon_ShootPosition(); QAngle angAiming; VectorAngles( vecAiming, angAiming ); #if defined(HL2_EPISODIC) // !!!HACK - the other piece of the Alyx crossbow bolt hack for Outland_10 (see ::BoltTouch() for more detail) if( FStrEq(STRING(gpGlobals->mapname), "ep2_outland_10") ) { trace_t tr; UTIL_TraceLine( vecSrc, vecSrc + vecAiming * 24.0f, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); if( tr.m_pEnt != NULL && tr.m_pEnt->Classify() == CLASS_PLAYER_ALLY_VITAL ) { // If Alyx is right in front of the player, make sure the bolt starts outside of the player's BBOX, or the bolt // will instantly collide with the player after the owner of the bolt is switched to Alyx in ::BoltTouch(). We // avoid this altogether by making it impossible for the bolt to collide with the player. vecSrc += vecAiming * 24.0f; } } #endif CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate( vecSrc, angAiming, pOwner ); if ( pOwner->GetWaterLevel() == 3 ) pBolt->SetAbsVelocity(vecAiming * BOLT_WATER_VELOCITY); else pBolt->SetAbsVelocity(vecAiming * BOLT_AIR_VELOCITY); #endif m_iClip1--; pOwner->ViewPunch(QAngle( -2, 0, 0 )); WeaponSound(SINGLE); WeaponSound(SPECIAL2); #ifndef CLIENT_DLL CSoundEnt::InsertSound(SOUND_COMBAT, GetAbsOrigin(), 200, 0.2); #endif SendWeaponAnim(ACT_VM_PRIMARYATTACK); // HEV suit - indicate out of ammo condition if ( !m_iClip1 && pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) pOwner->SetSuitUpdate("!HEV_AMO0", FALSE, 0); m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + 0.75; DoLoadEffect(); SetChargerState(CHARGER_STATE_DISCHARGE); }
// this function only gets called in multiplayer void CCrossbow::FireSniperBolt() { m_flNextPrimaryAttack = gpGlobals->time + 0.75; if (m_iClip == 0) { PlayEmptySound( ); return; } TraceResult tr; m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; m_iClip--; // make twang sound EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/xbow_fire1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF)); if (m_iClip) { EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM, 0, 93 + RANDOM_LONG(0,0xF)); SendWeaponAnim( CROSSBOW_FIRE1 ); } else if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] == 0) { SendWeaponAnim( CROSSBOW_FIRE3 ); } // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); Vector anglesAim = m_pPlayer->pev->viewangles + m_pPlayer->pev->punchangle; UTIL_MakeVectors( anglesAim ); Vector vecSrc = m_pPlayer->GetGunPosition( ) - gpGlobals->v_up * 2; Vector vecDir = gpGlobals->v_forward; UTIL_TraceLine(vecSrc, vecSrc + vecDir * 8192, dont_ignore_monsters, m_pPlayer->edict(), &tr); if ( tr.pHit->v.takedamage ) { switch( RANDOM_LONG(0,1) ) { case 0: EMIT_SOUND( tr.pHit, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM); break; case 1: EMIT_SOUND( tr.pHit, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM); break; } ClearMultiDamage( ); CBaseEntity::Instance(tr.pHit)->TraceAttack(m_pPlayer->pev, 120, vecDir, &tr, DMG_BULLET | DMG_NEVERGIB ); ApplyMultiDamage( pev, m_pPlayer->pev ); } else { // create a bolt CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate(); pBolt->pev->origin = tr.vecEndPos - vecDir * 10; pBolt->pev->angles = UTIL_VecToAngles( vecDir ); pBolt->pev->solid = SOLID_NOT; pBolt->SetTouch( NULL ); pBolt->SetThink( SUB_Remove ); EMIT_SOUND( pBolt->edict(), CHAN_WEAPON, "weapons/xbow_hit1.wav", RANDOM_FLOAT(0.95, 1.0), ATTN_NORM ); if (UTIL_PointContents(tr.vecEndPos) != CONTENTS_WATER) { UTIL_Sparks( tr.vecEndPos ); } if ( FClassnameIs( tr.pHit, "worldspawn" ) ) { // let the bolt sit around for a while if it hit static architecture pBolt->pev->nextthink = gpGlobals->time + 5.0; } else { pBolt->pev->nextthink = gpGlobals->time; } } }