Example #1
0
/*
================
FireBullets

Go to the trouble of combining multiple pellets into a single damage call.

This version is used by Monsters.
================
*/
void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int inDamageType)
{
	static int tracerCount;
	int tracer;
	TraceResult tr;
	Vector vecRight = gpGlobals->v_right;
	Vector vecUp = gpGlobals->v_up;

	if ( pevAttacker == NULL )
		pevAttacker = pev;  // the default attacker is ourselves

	ClearMultiDamage();
	gMultiDamage.type = inDamageType;

	for (ULONG iShot = 1; iShot <= cShots; iShot++)
	{
		// get circular gaussian spread
		float x, y, z;
		do {
			x = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5);
			y = RANDOM_FLOAT(-0.5,0.5) + RANDOM_FLOAT(-0.5,0.5);
			z = x*x+y*y;
		} while (z > 1);

		Vector vecDir = vecDirShooting +
						x * vecSpread.x * vecRight +
						y * vecSpread.y * vecUp;
		Vector vecEnd;

		vecEnd = vecSrc + vecDir * flDistance;
		//UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev)/*pentIgnore*/, &tr);
		bool theProtected = false;
		AvHSUServerTraceBullets(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), tr, theProtected);
		CBaseEntity* theEntityHit = CBaseEntity::Instance(tr.pHit);

		if(theProtected && theEntityHit)
		{	
			// joev: experiment
			EMIT_SOUND(theEntityHit->edict(), CHAN_AUTO, kUmbraBlockedSound, 1.0f, ATTN_NORM);
			// :joev
		}
		else
		{
			tracer = 0;
			if (iTracerFreq != 0 && (tracerCount++ % iTracerFreq) == 0)
			{
				Vector vecTracerSrc;
			
				if ( IsPlayer() )
				{// adjust tracer position for player
					vecTracerSrc = vecSrc + Vector ( 0 , 0 , -4 ) + gpGlobals->v_right * 2 + gpGlobals->v_forward * 16;
				}
				else
				{
					vecTracerSrc = vecSrc;
				}
				
				if ( iTracerFreq != 1 )		// guns that always trace also always decal
					tracer = 1;
				switch( iBulletType )
				{
				case BULLET_MONSTER_MP5:
				case BULLET_MONSTER_9MM:
				case BULLET_MONSTER_12MM:
				default:
					MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, vecTracerSrc );
						WRITE_BYTE( TE_TRACER );
						WRITE_COORD( vecTracerSrc.x );
						WRITE_COORD( vecTracerSrc.y );
						WRITE_COORD( vecTracerSrc.z );
						WRITE_COORD( tr.vecEndPos.x );
						WRITE_COORD( tr.vecEndPos.y );
						WRITE_COORD( tr.vecEndPos.z );
					MESSAGE_END();
					break;
				}
			}
			// do damage, paint decals
			if (tr.flFraction != 1.0)
			{
				float theScalar = 1.0f;
				if(theEntityHit && GetGameRules()->CanEntityDoDamageTo(this, theEntityHit, &theScalar))
				{
					// Multiply damage by scalar for tourny mode, etc.
					iDamage *= theScalar;

					if ( iDamage )
					{
						theEntityHit->TraceAttack(pevAttacker, iDamage, vecDir, &tr, DMG_BULLET | ((iDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) );
						
						TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
						DecalGunshot( &tr, iBulletType );
						//DecalGunshot( &tr, 0 );
					} 
					else switch(iBulletType)
					{
					default:
					case BULLET_MONSTER_9MM:
						theEntityHit->TraceAttack(pevAttacker, gSkillData.monDmg9MM, vecDir, &tr, DMG_BULLET);
						
						TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
						DecalGunshot( &tr, iBulletType );
					
						break;
					
					case BULLET_MONSTER_MP5:
						theEntityHit->TraceAttack(pevAttacker, gSkillData.monDmgMP5, vecDir, &tr, DMG_BULLET);
						
						TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
						DecalGunshot( &tr, iBulletType );
					
						break;
					
					case BULLET_MONSTER_12MM:		
						theEntityHit->TraceAttack(pevAttacker, gSkillData.monDmg12MM, vecDir, &tr, DMG_BULLET); 
						if ( !tracer )
						{
							TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
							DecalGunshot( &tr, iBulletType );
						}
						break;
					
					case BULLET_NONE: // FIX 
						theEntityHit->TraceAttack(pevAttacker, 50, vecDir, &tr, DMG_CLUB);
						TEXTURETYPE_PlaySound(&tr, vecSrc, vecEnd, iBulletType);
						// only decal glass
						if ( !FNullEnt(tr.pHit) && VARS(tr.pHit)->rendermode != 0)
						{
							UTIL_DecalTrace( &tr, DECAL_GLASSBREAK1 + RANDOM_LONG(0,2) );
						}
					
						break;
					}
				}
			}
			// make bullet trails
			UTIL_BubbleTrail( vecSrc, tr.vecEndPos, (flDistance * tr.flFraction) / 64.0 );
		}
	}
	ApplyMultiDamage(pev, pevAttacker);
}
Example #2
0
/*
================
FireBullets

Go to the trouble of combining multiple pellets into a single damage call.
 
This version is used by Players, uses the random seed generator to sync client and server side shots.
================
*/
Vector CBaseEntity::FireBulletsPlayer ( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int shared_rand )
{
	static int tracerCount;
	TraceResult tr;
	Vector vecRight = gpGlobals->v_right;
	Vector vecUp = gpGlobals->v_up;
	entvars_t* theInflictor = this->pev;
	//float x, y, z;
	
	if ( pevAttacker == NULL )
		pevAttacker = pev;  // the default attacker is ourselves
	
	int theDamageType = DMG_BULLET;
	bool isShotgun=false;
	AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(this);
	if(thePlayer && thePlayer->m_pActiveItem)
	{
		AvHBasePlayerWeapon* theBasePlayerWeapon = dynamic_cast<AvHBasePlayerWeapon*>(thePlayer->m_pActiveItem);
		if(theBasePlayerWeapon)
		{
			theDamageType = theBasePlayerWeapon->GetDamageType();
			theInflictor = theBasePlayerWeapon->pev;
		}
		AvHSonicGun* theSonicGun = dynamic_cast<AvHSonicGun*>(thePlayer->m_pActiveItem);
		if ( theSonicGun ) 
		{
			isShotgun=true;
		}
	}	
	else
	{
		AvHTurret* theTurret = dynamic_cast<AvHTurret*>(this);
		if(theTurret)
		{
			theDamageType = theTurret->GetDamageType();
		}
	}

	ClearMultiDamage();
	gMultiDamage.type = theDamageType;

	for ( ULONG iShot = 1; iShot <= cShots; iShot++ )
	{
		//Use player's random seed.
		// get circular gaussian spread
		//x = UTIL_SharedRandomFloat( shared_rand + iShot, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 1 + iShot ) , -0.5, 0.5 );
		//y = UTIL_SharedRandomFloat( shared_rand + ( 2 + iShot ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 3 + iShot ), -0.5, 0.5 );
		//z = x * x + y * y;
		//
		//Vector vecDir = vecDirShooting +
		//				x * vecSpread.x * vecRight +
		//				y * vecSpread.y * vecUp;

		Vector vecDir = UTIL_GetRandomSpreadDir(shared_rand, iShot, vecDirShooting, vecRight, vecUp, vecSpread);
		Vector vecEnd;

		vecEnd = vecSrc + vecDir * flDistance;
		//UTIL_TraceLine(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev)/*pentIgnore*/, &tr);
		bool theProtected = false;
		AvHSUServerTraceBullets(vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), tr, theProtected);
		CBaseEntity* theEntityHit = CBaseEntity::Instance(tr.pHit);

		if(theProtected)
		{
			// joev: experiment
			EMIT_SOUND(theEntityHit->edict(), CHAN_AUTO, kUmbraBlockedSound, 1.0f, ATTN_NORM);
			// :joev
		}
		else
		{
		
			// do damage, paint decals
			if (tr.flFraction != 1.0)
			{
				float theScalar = 1.0f;
				if(GetGameRules()->CanEntityDoDamageTo(thePlayer, theEntityHit, &theScalar))
				{
					int theAdjustedDamage = iDamage*theScalar;

					if(theAdjustedDamage) {
						theEntityHit->TraceAttack(pevAttacker, theAdjustedDamage, vecDir, &tr, theDamageType | ((theAdjustedDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB) );
					} 
				}
			}
			// make bullet trails
			UTIL_BubbleTrail( vecSrc, tr.vecEndPos, (flDistance * tr.flFraction) / 64.0 );
		}
	}
	ApplyMultiDamage(theInflictor, pevAttacker);

	//return Vector( (float)(x * vecSpread.x), (float)(y * vecSpread.y), 0.0f );
	return vecSpread;
}
Example #3
0
//=========================================================
// CheckTraceHullAttack - expects a length to trace, amount 
// of damage to do, and damage type. Returns a pointer to
// the damaged entity in case the monster wishes to do
// other stuff to the victim (punchangle, etc)
//
// Used for many contact-range melee attacks. Bites, claws, etc.
//=========================================================
CBaseEntity* CBaseMonster :: CheckTraceHullAttack( float flDist, float& ioDamage, int iDmgType )
{
	Vector vecStart = pev->origin;
	
	if(this->IsPlayer())
	{
		// Melee attacks always originate where the view is
		vecStart.x += this->pev->view_ofs.x;
		vecStart.y += this->pev->view_ofs.y;
		vecStart.z += this->pev->view_ofs.z;
	}
	
	if (IsPlayer())
		UTIL_MakeVectors( pev->v_angle );
	else
		UTIL_MakeAimVectors( pev->angles );
	
	//AvHSUPlayParticleEvent("JetpackEffect", this->edict(), vecStart);

	// First do a tracehull.  If that misses, try three tracelines (dead-on center, then randomly left and randomly right).
	bool theHitTarget = false;
	for(int i = 0; (i < 4) && !theHitTarget; i++)
	{
		const float kAmount = 0.4f;
		float theXAmount = 0.0f;
		
		if(i == 2)
		{
			theXAmount = kAmount;
		}
		else if(i == 3)
		{
			theXAmount = -kAmount;
		}

		Vector vecDir = gpGlobals->v_forward + theXAmount*gpGlobals->v_right;
		vecDir.Normalize();

		Vector vecEnd = vecStart + (vecDir * flDist );
		TraceResult tr;

		if(i == 0)
		{
			int theOurHull = this->GetHull();
			int theHull = AvHSUGetValveHull(theOurHull);
			UTIL_TraceHull(vecStart, vecEnd, dont_ignore_monsters, theHull, this->edict(), &tr);
		}
		else
		{
			//AvHSUPlayParticleEvent("JetpackEffect", this->edict(), vecEnd);

			UTIL_TraceLine(vecStart, vecEnd, dont_ignore_monsters, dont_ignore_glass, ENT(this->pev), &tr);
		}
		
		if ( tr.pHit )
		{
			CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit );
			
			if ( ioDamage > 0 )
			{
				float theScalar = 1.0f;
				if(GetGameRules()->CanEntityDoDamageTo(this, pEntity, &theScalar))
				{
					theHitTarget = true;

					// Multiply damage by scalar for tourny mode, etc.
					ioDamage *= theScalar;
					
					entvars_t* theInflictor = this->pev;
					AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(this);
					if(thePlayer)
					{
						AvHBasePlayerWeapon* theBasePlayerWeapon = dynamic_cast<AvHBasePlayerWeapon*>(thePlayer->m_pActiveItem);
						if(theBasePlayerWeapon)
						{
							theInflictor = theBasePlayerWeapon->pev;
						}
					}
					
					pEntity->TakeDamage(theInflictor, pev, ioDamage, iDmgType );

					// Spawn blood
					if(ioDamage > 0.0f)
					{
						// a little surface blood.
						SpawnBlood(tr.vecEndPos, pEntity->BloodColor(), ioDamage);

						// on the wall/floor (don't play because blood decal is green)
						//TraceBleed(ioDamage, vecDir, &tr, iDmgType);
					}
		
					return pEntity;
				}
			}
		}
	}

	return NULL;
}
Example #4
0
void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float inDamage, float flRadius, int iClassIgnore, int bitsDamageType )
{
	CBaseEntity *pEntity = NULL;
	TraceResult	tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;

	if ( flRadius )
		falloff = inDamage / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER);

	vecSrc.z += 1;// in case grenade is lying on the ground

	if ( !pevAttacker )
		pevAttacker = pevInflictor;

	// iterate on all entities in the vicinity.
	while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
	{
		// NOTE: Should this be inflictor or attacker?
		CBaseEntity* theInflictingEntity = CBaseEntity::Instance(pevInflictor);
		CBaseEntity* theAttackingEntity = CBaseEntity::Instance(pevAttacker);
		float theScalar = 1.0f;
		bool aCanDamage=GetGameRules()->CanEntityDoDamageTo(theAttackingEntity, pEntity, &theScalar) || theInflictingEntity->pev->classname == MAKE_STRING(kwsDeployedMine);;
		bool iCanDamage=GetGameRules()->CanEntityDoDamageTo(theInflictingEntity, pEntity, &theScalar);

		if(pEntity && ( aCanDamage && iCanDamage ))
		{
			// Multiply damage by scalar for tourny mode, etc.
			float theDamage = inDamage*theScalar;

			if ( pEntity->pev->takedamage != DAMAGE_NO )
			{

				// UNDONE: this should check a damage mask, not an ignore
				if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
				{// houndeyes don't hurt other houndeyes with their attack
					continue;
				}
			
				// blast's don't tavel into or out of water
				if (bInWater && pEntity->pev->waterlevel == 0)
					continue;
				if (!bInWater && pEntity->pev->waterlevel == 3)
					continue;
			
				vecSpot = pEntity->BodyTarget( vecSrc );

				// Clear pevInflictor's owner temporarily so it can apply damage to it
				edict_t* theInflictorOwner = pevInflictor->owner;
				pevInflictor->owner = NULL;
				
				UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pevInflictor), &tr );

				// Restore owner
				pevInflictor->owner = theInflictorOwner;
				
                if (tr.flFraction == 1.0 || tr.pHit == pEntity->edict() )
				{// the explosion can 'see' this entity, so hurt them!
					if (tr.fStartSolid)
					{
						// if we're stuck inside them, fixup the position and distance
						tr.vecEndPos = vecSrc;
						tr.flFraction = 0.0;
					}
					
					// decrease damage for an ent that's farther from the bomb.
					flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length() * falloff;
					flAdjustedDamage = theDamage - flAdjustedDamage;
				
					if ( flAdjustedDamage > 0 )
					{
						pEntity->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
					}
				}
			}
		}
	}
}
Example #5
0
//=========================================================
//=========================================================
void CBasePlayer::CheatImpulseCommands( int iImpulse )
{
	if( !UTIL_CheatsAllowed() )
	{
		return;
	}

	switch( iImpulse )
	{
	case 76:
		{
			if( !g_bPrecacheGrunt )
			{
				g_bPrecacheGrunt = true;
				ALERT( at_console, "You must now restart to use Grunt-o-matic.\n" );
			}
			else
			{
				UTIL_MakeVectors( Vector( 0, GetViewAngle().y, 0 ) );
				Create( "monster_human_grunt", GetAbsOrigin() + gpGlobals->v_forward * 128, GetAbsAngles() );
			}
			break;
		}

	case 101:
		{
			gEvilImpulse101 = true;
			GiveNamedItem( "item_suit" );
			GiveNamedItem( "item_battery" );
			GiveNamedItem( "weapon_crowbar" );
			GiveNamedItem( "weapon_9mmhandgun" );
			GiveNamedItem( "ammo_9mmclip" );
			GiveNamedItem( "weapon_shotgun" );
			GiveNamedItem( "ammo_buckshot" );
			GiveNamedItem( "weapon_9mmAR" );
			GiveNamedItem( "ammo_9mmAR" );
			GiveNamedItem( "ammo_ARgrenades" );
			GiveNamedItem( "weapon_handgrenade" );
			GiveNamedItem( "weapon_tripmine" );

			GiveNamedItem( "weapon_357" );
			GiveNamedItem( "ammo_357" );
			GiveNamedItem( "weapon_crossbow" );
			GiveNamedItem( "ammo_crossbow" );
			GiveNamedItem( "weapon_egon" );
			GiveNamedItem( "weapon_gauss" );
			GiveNamedItem( "ammo_gaussclip" );
			GiveNamedItem( "weapon_rpg" );
			GiveNamedItem( "ammo_rpgclip" );
			GiveNamedItem( "weapon_satchel" );
			GiveNamedItem( "weapon_snark" );
			GiveNamedItem( "weapon_hornetgun" );

#if USE_OPFOR
			GiveNamedItem( "weapon_knife" );
			GiveNamedItem( "weapon_pipewrench" );
			GiveNamedItem( "weapon_grapple" );
			GiveNamedItem( "weapon_eagle" );
			GiveNamedItem( "weapon_m249" );
			GiveNamedItem( "weapon_displacer" );
			GiveNamedItem( "weapon_sniperrifle" );
			GiveNamedItem( "weapon_sporelauncher" );
			GiveNamedItem( "weapon_shockrifle" );
			GiveNamedItem( "ammo_556" );
			GiveNamedItem( "ammo_762" );
#endif

			gEvilImpulse101 = false;
			break;
		}

	case 102:
		{
			// Gibbage!!!
			CGib::SpawnRandomGibs( this, 1, 1 );
			break;
		}

	case 103:
		{
			// What the hell are you doing?
			auto pEntity = UTIL_FindEntityForward( this );
			if( pEntity )
			{
				CBaseMonster *pMonster = pEntity->MyMonsterPointer();
				if( pMonster )
					pMonster->ReportAIState();
			}
			break;
		}

	case 104:
		{
			// Dump all of the global state varaibles (and global entity names)
			gGlobalState.DumpGlobals();
			break;
		}

	case	105:// player makes no sound for monsters to hear.
		{
			if( m_fNoPlayerSound )
			{
				ALERT( at_console, "Player is audible\n" );
				m_fNoPlayerSound = false;
			}
			else
			{
				ALERT( at_console, "Player is silent\n" );
				m_fNoPlayerSound = true;
			}
			break;
		}

	case 106:
		{
			// Give me the classname and targetname of this entity.
			auto pEntity = UTIL_FindEntityForward( this );
			if( pEntity )
			{
				ALERT( at_console, "Classname: %s", pEntity->GetClassname() );

				if( pEntity->HasTargetname() )
				{
					ALERT( at_console, " - Targetname: %s\n", pEntity->GetTargetname() );
				}
				else
				{
					ALERT( at_console, " - TargetName: No Targetname\n" );
				}

				ALERT( at_console, "Model: %s\n", pEntity->GetModelName() );
				if( HasGlobalName() )
					ALERT( at_console, "Globalname: %s\n", pEntity->GetGlobalName() );
			}

			break;
		}

	case 107:
		{
			TraceResult tr;

			CBaseEntity* pWorld = CWorld::GetInstance();

			Vector start = GetAbsOrigin() + GetViewOffset();
			Vector end = start + gpGlobals->v_forward * 1024;
			UTIL_TraceLine( start, end, ignore_monsters, edict(), &tr );
			if( tr.pHit )
				pWorld = CBaseEntity::Instance( tr.pHit );
			const texture_t* pTexture = UTIL_TraceTexture( pWorld, start, end );
			if( pTexture )
				ALERT( at_console, "Texture: %s\n", pTexture->name );
			break;
		}

	case	195:// show shortest paths for entire level to nearest node
		{
			Create( "node_viewer_fly", GetAbsOrigin(), GetAbsAngles() );
			break;
		}

	case	196:// show shortest paths for entire level to nearest node
		{
			Create( "node_viewer_large", GetAbsOrigin(), GetAbsAngles() );
			break;
		}

	case	197:// show shortest paths for entire level to nearest node
		{
			Create( "node_viewer_human", GetAbsOrigin(), GetAbsAngles() );
			break;
		}

	case	199:// show nearest node and all connections
		{
			ALERT( at_console, "%d\n", WorldGraph.FindNearestNode( GetAbsOrigin(), bits_NODE_GROUP_REALM ) );
			WorldGraph.ShowNodeConnections( WorldGraph.FindNearestNode( GetAbsOrigin(), bits_NODE_GROUP_REALM ) );

			break;
		}
		
	case	202:// Random blood splatter
		{
			UTIL_MakeVectors( GetViewAngle() );
			TraceResult tr;
			UTIL_TraceLine( GetAbsOrigin() + GetViewOffset(), GetAbsOrigin() + GetViewOffset() + gpGlobals->v_forward * 128, ignore_monsters, ENT( pev ), &tr );

			if( tr.flFraction != 1.0 )
			{// line hit something, so paint a decal
				auto pBlood = static_cast< CBloodSplat* >( UTIL_CreateNamedEntity( "blood_splat" ) );
				pBlood->CreateSplat( this );
			}
			break;
		}

	case	203:// remove creature.
		{
			auto pEntity = UTIL_FindEntityForward( this );
			if( pEntity )
			{
				if( pEntity->GetTakeDamageMode() != DAMAGE_NO )
					pEntity->SetThink( &CBaseEntity::SUB_Remove );
			}
			break;
		}
	}
}
Example #6
0
/*
============
ImpulseCommands
============
*/
void CBasePlayer::ImpulseCommands()
{
	TraceResult	tr;// UNDONE: kill me! This is temporary for PreAlpha CDs

				   // Handle use events
	PlayerUse();

	int iImpulse = GetImpulse();
	switch( iImpulse )
	{
	case 99:
		{

			bool bOn;

			if( !gmsgLogo )
			{
				bOn = true;
				//TODO: figure out why this is done here. - Solokiller
				gmsgLogo = REG_USER_MSG( "Logo", 1 );
			}
			else
			{
				bOn = false;
			}

			ASSERT( gmsgLogo > 0 );
			// send "health" update message
			MESSAGE_BEGIN( MSG_ONE, gmsgLogo, NULL, this );
			WRITE_BYTE( bOn );
			MESSAGE_END();

			if( !bOn )
				gmsgLogo = 0;
			break;
		}
	case 100:
		// temporary flashlight for level designers
		if( FlashlightIsOn() )
		{
			FlashlightTurnOff();
		}
		else
		{
			FlashlightTurnOn();
		}
		break;

	case	201:// paint decal

		if( gpGlobals->time < m_flNextDecalTime )
		{
			// too early!
			break;
		}

		UTIL_MakeVectors( GetViewAngle() );
		UTIL_TraceLine( GetAbsOrigin() + GetViewOffset(), GetAbsOrigin() + GetViewOffset() + gpGlobals->v_forward * 128, ignore_monsters, ENT( pev ), &tr );

		if( tr.flFraction != 1.0 )
		{// line hit something, so paint a decal
			m_flNextDecalTime = gpGlobals->time + decalfrequency.value;
			auto pCan = static_cast<CSprayCan*>( UTIL_CreateNamedEntity( "spray_can" ) );
			pCan->CreateSprayCan( this );
		}

		break;

	default:
		// check all of the cheat impulse commands now
		CheatImpulseCommands( iImpulse );
		break;
	}

	SetImpulse( 0 );
}
Example #7
0
void CBasePlayer::PreThink()
{
	const int buttonsChanged = ( m_afButtonLast ^ GetButtons().Get() );	// These buttons have changed this frame

	// Debounced button codes for pressed/released
	// UNDONE: Do we need auto-repeat?
	m_afButtonPressed = buttonsChanged & GetButtons().Get();		// The changed ones still down are "pressed"
	m_afButtonReleased = buttonsChanged & ( ~GetButtons().Get() );	// The ones not down are "released"

	g_pGameRules->PlayerThink( this );

	bool bCheckVehicles = true;

#if USE_ANGELSCRIPT
	uint32_t uiFlags = PreThinkFlag::NONE;

	CallGlobalEvent( g_PlayerPreThinkEvent, CallFlag::NONE, this, &uiFlags );

	bCheckVehicles = !( uiFlags & PreThinkFlag::SKIP_VEHICLES );
#endif

	if( g_fGameOver )
		return;         // intermission or finale

	UTIL_MakeVectors( GetViewAngle() );             // is this still used?

	ItemPreFrame();
	WaterMove();

	if( g_pGameRules && g_pGameRules->FAllowFlashlight() )
		m_iHideHUD &= ~HIDEHUD_FLASHLIGHT;
	else
		m_iHideHUD |= HIDEHUD_FLASHLIGHT;


	// JOHN: checks if new client data (for HUD and view control) needs to be sent to the client
	UpdateClientData();

	CheckTimeBasedDamage();

	CheckSuitUpdate();

	// Observer Button Handling
	if( IsObserver() )
	{
		Observer_HandleButtons();
		Observer_CheckTarget();
		Observer_CheckProperties();
		SetImpulse( 0 );
		return;
	}

	if( GetDeadFlag() >= DEAD_DYING )
	{
		PlayerDeathThink();
		return;
	}

	// So the correct flags get sent to client asap.
	//
	if( m_afPhysicsFlags & PFLAG_ONTRAIN )
		GetFlags() |= FL_ONTRAIN;
	else
		GetFlags().ClearFlags( FL_ONTRAIN );

	if( bCheckVehicles )
	{
#if USE_OPFOR
	//We're on a rope. - Solokiller
	if( m_afPhysicsFlags & PFLAG_ONROPE && m_pRope )
	{
		SetAbsVelocity( g_vecZero );

		const Vector vecAttachPos = m_pRope->GetAttachedObjectsPosition();

		SetAbsOrigin( vecAttachPos );

		Vector vecForce;

		/*
		//TODO: This causes sideways acceleration that doesn't occur in Op4. - Solokiller
		//TODO: should be IN_MOVERIGHT and IN_MOVELEFT - Solokiller
		if( GetButtons().Any( IN_DUCK ) )
		{
			vecForce.x = gpGlobals->v_right.x;
			vecForce.y = gpGlobals->v_right.y;
			vecForce.z = 0;
			
			m_pRope->ApplyForceFromPlayer( vecForce );
		}

		if( GetButtons().Any( IN_JUMP ) )
		{
			vecForce.x = -gpGlobals->v_right.x;
			vecForce.y = -gpGlobals->v_right.y;
			vecForce.z = 0;
			m_pRope->ApplyForceFromPlayer( vecForce );
		}
		*/

		//Determine if any force should be applied to the rope, or if we should move around. - Solokiller
		if( GetButtons().Any( IN_BACK | IN_FORWARD ) )
		{
			if( ( gpGlobals->v_forward.x * gpGlobals->v_forward.x + 
				gpGlobals->v_forward.y * gpGlobals->v_forward.y - 
				gpGlobals->v_forward.z * gpGlobals->v_forward.z ) <= 0.0 )
			{
				if( m_bIsClimbing )
				{
					const float flDelta = gpGlobals->time - m_flLastClimbTime;
					m_flLastClimbTime = gpGlobals->time;
					if( GetButtons().Any( IN_FORWARD ) )
					{
						if( gpGlobals->v_forward.z < 0.0 )
						{
							if( !m_pRope->MoveDown( flDelta ) )
							{
								//Let go of the rope, detach. - Solokiller
								SetMoveType( MOVETYPE_WALK );
								SetSolidType( SOLID_SLIDEBOX );

								m_afPhysicsFlags &= ~PFLAG_ONROPE;
								m_pRope->DetachObject();
								m_pRope = nullptr;
								m_bIsClimbing = false;
							}
						}
						else
						{
							m_pRope->MoveUp( flDelta );
						}
					}
					if( GetButtons().Any( IN_BACK ) )
					{
						if( gpGlobals->v_forward.z < 0.0 )
						{
							m_pRope->MoveUp( flDelta );
						}
						else if( !m_pRope->MoveDown( flDelta ) )
						{
							//Let go of the rope, detach. - Solokiller
							SetMoveType( MOVETYPE_WALK );
							SetSolidType( SOLID_SLIDEBOX );
							m_afPhysicsFlags &= ~PFLAG_ONROPE;
							m_pRope->DetachObject();
							m_pRope = nullptr;
							m_bIsClimbing = false;
						}
					}
				}
				else
				{
					m_bIsClimbing = true;
					m_flLastClimbTime = gpGlobals->time;
				}
			}
			else
			{
				vecForce.x = gpGlobals->v_forward.x;
				vecForce.y = gpGlobals->v_forward.y;
				vecForce.z = 0.0;
				if( GetButtons().Any( IN_BACK ) )
				{
					vecForce.x = -gpGlobals->v_forward.x;
					vecForce.y = -gpGlobals->v_forward.y;
					vecForce.z = 0;
				}
				m_pRope->ApplyForceFromPlayer( vecForce );
				m_bIsClimbing = false;
			}
		}
		else
		{
			m_bIsClimbing = false;
		}

		if( m_afButtonPressed & IN_JUMP )
		{
			//We've jumped off the rope, give us some momentum - Solokiller
			SetMoveType( MOVETYPE_WALK );
			SetSolidType( SOLID_SLIDEBOX );
			this->m_afPhysicsFlags &= ~PFLAG_ONROPE;

			Vector vecDir = gpGlobals->v_up * 165.0 + gpGlobals->v_forward * 150.0;

			Vector vecVelocity = m_pRope->GetAttachedObjectsVelocity() * 2;

			vecVelocity.NormalizeInPlace();

			vecVelocity = vecVelocity * 200;

			SetAbsVelocity( vecVelocity + vecDir );

			m_pRope->DetachObject();
			m_pRope = nullptr;
			m_bIsClimbing = false;
		}
		return;
	}
#endif

		// Train speed control
		if( m_afPhysicsFlags & PFLAG_ONTRAIN )
		{
			CBaseEntity *pTrain = GetGroundEntity();

			//To match original behavior, Instance returns the world if entity is null - Solokiller
			if( !pTrain )
				pTrain = CWorld::GetInstance();

			float vel;

			if( !pTrain )
			{
				TraceResult trainTrace;
				// Maybe this is on the other side of a level transition
				UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -38 ), ignore_monsters, ENT( pev ), &trainTrace );

				// HACKHACK - Just look for the func_tracktrain classname
				if( trainTrace.flFraction != 1.0 && trainTrace.pHit )
					pTrain = CBaseEntity::Instance( trainTrace.pHit );


				if( !pTrain || !( pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE ) || !pTrain->OnControls( this ) )
				{
					//ALERT( at_error, "In train mode with no train!\n" );
					m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
					m_iTrain = TRAIN_NEW | TRAIN_OFF;
					return;
				}
			}
			else if( !GetFlags().Any( FL_ONGROUND ) || pTrain->GetSpawnFlags().Any( SF_TRACKTRAIN_NOCONTROL ) || ( GetButtons().Any( IN_MOVELEFT | IN_MOVERIGHT ) ) )
			{
				// Turn off the train if you jump, strafe, or the train controls go dead
				m_afPhysicsFlags &= ~PFLAG_ONTRAIN;
				m_iTrain = TRAIN_NEW | TRAIN_OFF;
				return;
			}

			SetAbsVelocity( g_vecZero );
			vel = 0;
			if( m_afButtonPressed & IN_FORWARD )
			{
				vel = 1;
				pTrain->Use( this, this, USE_SET, ( float ) vel );
			}
			else if( m_afButtonPressed & IN_BACK )
			{
				vel = -1;
				pTrain->Use( this, this, USE_SET, ( float ) vel );
			}

			if( vel )
			{
				m_iTrain = TrainSpeed( pTrain->GetSpeed(), pTrain->GetImpulse() );
				m_iTrain |= TRAIN_ACTIVE | TRAIN_NEW;
			}

		}
		else if( m_iTrain & TRAIN_ACTIVE )
			m_iTrain = TRAIN_NEW; // turn off train
	}

	if( GetButtons().Any( IN_JUMP ) )
	{
		// If on a ladder, jump off the ladder
		// else Jump
		Jump();
	}


	// If trying to duck, already ducked, or in the process of ducking
	if( GetButtons().Any( IN_DUCK ) || GetFlags().Any( FL_DUCKING ) || ( m_afPhysicsFlags & PFLAG_DUCKING ) )
		Duck();

	if( !GetFlags().Any( FL_ONGROUND ) )
	{
		m_flFallVelocity = -GetAbsVelocity().z;
	}

	// StudioFrameAdvance( );//!!!HACKHACK!!! Can't be hit by traceline when not animating?

	// Clear out ladder pointer
	m_hEnemy = NULL;

	if( m_afPhysicsFlags & PFLAG_ONBARNACLE )
	{
		SetAbsVelocity( g_vecZero );
	}
}