//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBasePlayer::SetStepSoundTime( stepsoundtimes_t iStepSoundTime, bool bWalking ) { switch ( iStepSoundTime ) { case STEPSOUNDTIME_NORMAL: case STEPSOUNDTIME_WATER_FOOT: m_flStepSoundTime = bWalking ? 600 : 300; break; case STEPSOUNDTIME_ON_LADDER: m_flStepSoundTime = 500; break; case STEPSOUNDTIME_WATER_KNEE: m_flStepSoundTime = 600; break; default: Assert(0); break; } // UNDONE: need defined numbers for run, walk, crouch, crouch run velocities!!!! if ( ( GetFlags() & FL_DUCKING) || ( GetMoveType() == MOVETYPE_LADDER ) ) { m_flStepSoundTime += 100; } }
bool CSDKPlayer::CanAttack( void ) { #if defined ( SDK_USE_SPRINTING ) #if !defined ( SDK_SHOOT_WHILE_SPRINTING ) if ( IsSprinting() ) return false; #endif // SDK_SHOOT_WHILE_SPRINTING #endif // SDK_USE_SPRINTING #if !defined ( SDK_SHOOT_ON_LADDERS ) if ( GetMoveType() == MOVETYPE_LADDER ) return false; #endif //SDK_SHOOT_ON_LADDERS #if !defined ( SDK_SHOOT_WHILE_JUMPING ) if ( m_Shared.IsJumping() ) return false; #endif //SDK_SHOOT_WHILE_JUMPING #if defined ( SDK_USE_PRONE ) // cannot attack while prone moving. if ( m_Shared.IsProne() && GetAbsVelocity().LengthSqr() > 1 ) { return false; } if( m_Shared.IsGoingProne() || m_Shared.IsGettingUpFromProne() ) { return false; } #endif // SDK_USE_PRONE return true; }
void CSDKPlayer::GetStepSoundVelocities( float *velwalk, float *velrun ) { BaseClass::GetStepSoundVelocities(velwalk, velrun); if (!( ( GetFlags() & FL_DUCKING) || ( GetMoveType() == MOVETYPE_LADDER ) )) *velwalk = 110; }
int CHL2MP_Player::OnTakeDamage( const CTakeDamageInfo &inputInfo ) { #ifndef GE_DLL //return here if the player is in the respawn grace period vs. slams. if ( gpGlobals->curtime < m_flSlamProtectTime && (inputInfo.GetDamageType() == DMG_BLAST ) ) return 0; m_vecTotalBulletForce += inputInfo.GetDamageForce(); gamestats->Event_PlayerDamage( this, inputInfo ); #else CBaseEntity *attacker = inputInfo.GetAttacker(); Vector force = inputInfo.GetDamageForce(); if ( force == vec3_origin && attacker ) { Vector vecDir = vec3_origin; if ( inputInfo.GetInflictor() && GetMoveType() == MOVETYPE_WALK && !attacker->IsSolidFlagSet(FSOLID_TRIGGER) ) { vecDir = inputInfo.GetInflictor()->WorldSpaceCenter() - Vector ( 0, 0, 10 ) - WorldSpaceCenter(); VectorNormalize( vecDir ); force = vecDir * -DamageForce( WorldAlignSize(), inputInfo.GetBaseDamage() ); } } m_vecTotalBulletForce += force; #endif return BaseClass::OnTakeDamage( inputInfo ); }
//========================================================= // WaitTillLand - in order to emit their meaty scent from // the proper location, gibs should wait until they stop // bouncing to emit their scent. That's what this function // does. //========================================================= void CGib::WaitTillLand ( void ) { if (!IsInWorld()) { UTIL_Remove( this ); return; } if ( GetAbsVelocity() == vec3_origin ) { SetRenderAlpha( 255 ); m_nRenderMode = kRenderTransTexture; if ( GetMoveType() != MOVETYPE_VPHYSICS ) { AddSolidFlags( FSOLID_NOT_SOLID ); } SetLocalAngularVelocity( vec3_angle ); SetNextThink( gpGlobals->curtime + m_lifeTime ); SetThink ( &CGib::SUB_FadeOut ); if ( GetSprite() ) { CSprite *pSprite = dynamic_cast<CSprite*>( GetSprite() ); if ( pSprite ) { //Adrian - Why am I doing this? Check InitPointGib for the answer! if ( m_lifeTime == 0 ) m_lifeTime = random->RandomFloat( 1, 3 ); pSprite->FadeAndDie( m_lifeTime ); } } if ( GetFlame() ) { CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() ); if ( pFlame ) { pFlame->SetLifetime( 1.0f ); } } // If you bleed, you stink! if ( m_bloodColor != DONT_BLEED ) { // ok, start stinkin! // FIXME: It's too easy to fill up the sound queue with all these meat sounds // CSoundEnt::InsertSound ( SOUND_MEAT, GetAbsOrigin(), 384, 25 ); } } else { // wait and check again in another half second. SetNextThink( gpGlobals->curtime + 0.5f ); } }
//----------------------------------------------------------------------------- // Purpose: Determine view roll, including data kick //----------------------------------------------------------------------------- void CBasePlayer::CalcViewRoll( QAngle& eyeAngles ) { if ( GetMoveType() == MOVETYPE_NOCLIP ) return; float side = CalcRoll( GetAbsAngles(), GetAbsVelocity(), sv_rollangle.GetFloat(), sv_rollspeed.GetFloat() ); eyeAngles[ROLL] += side; }
//----------------------------------------------------------------------------- // Purpose: Helper to remove from ladder //----------------------------------------------------------------------------- void C_BaseHLPlayer::ExitLadder() { if ( MOVETYPE_LADDER != GetMoveType() ) return; SetMoveType( MOVETYPE_WALK ); SetMoveCollide( MOVECOLLIDE_DEFAULT ); // Remove from ladder m_HL2Local.m_hLadder = NULL; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_Eli::PrescheduleThink( void ) { BaseClass::PrescheduleThink(); // Figure out if Eli has just been removed from his parent if ( GetMoveType() == MOVETYPE_NONE && !GetMoveParent() ) { SetupWithoutParent(); SetupVPhysicsHull(); } }
void CStickyBomb::Touch( CBaseEntity *pOther ) { // Don't stick if already stuck if ( GetMoveType() == MOVETYPE_FLYGRAVITY ) { trace_t tr = GetTouchTrace(); // stickies don't stick to each other or sky if ( FClassnameIs(pOther, "grenade_stickybomb") || (tr.surface.flags & SURF_SKY) ) { // bounce Vector vecNewVelocity; PhysicsClipVelocity( GetAbsVelocity(), tr.plane.normal, vecNewVelocity, 1.0 ); SetAbsVelocity( vecNewVelocity ); } else { SetAbsVelocity( vec3_origin ); SetMoveType( MOVETYPE_NONE ); if ( pOther->entindex() != 0 ) { // set up notification if the parent is deleted before we explode g_pNotify->AddEntity( this, pOther ); if ( (tr.surface.flags & SURF_HITBOX) && modelinfo->GetModelType( pOther->GetModel() ) == mod_studio ) { CBaseAnimating *pOtherAnim = dynamic_cast<CBaseAnimating *>(pOther); if ( pOtherAnim ) { matrix3x4_t bombWorldSpace; MatrixCopy( EntityToWorldTransform(), bombWorldSpace ); // get the bone info so we can follow the bone FollowEntity( pOther ); SetOwnerEntity( pOther ); m_boneIndexAttached = pOtherAnim->GetHitboxBone( tr.hitbox ); matrix3x4_t boneToWorld; pOtherAnim->GetBoneTransform( m_boneIndexAttached, boneToWorld ); // transform my current position/orientation into the hit bone's space // UNDONE: Eventually we need to intersect with the mesh here // REVISIT: maybe do something like the decal code to find a spot on // the mesh. matrix3x4_t worldToBone, localMatrix; MatrixInvert( boneToWorld, worldToBone ); ConcatTransforms( worldToBone, bombWorldSpace, localMatrix ); MatrixAngles( localMatrix, m_boneAngles.GetForModify(), m_bonePosition.GetForModify() ); return; } } SetParent( pOther ); } } } }
BOOL KMovableObject::UnFix() { BOOL bResult = false; KGLOG_PROCESS_ERROR(GetMoveType() == mosFixed); TurnToMoveType(mosFree); bResult = true; Exit0: return bResult; }
void CTFBaseRocket::Simulate( void ) { // Make sure the rocket is facing movement direction. if ( GetMoveType() == MOVETYPE_FLYGRAVITY ) { QAngle angForward; VectorAngles( GetAbsVelocity(), angForward ); SetAbsAngles( angForward ); } BaseClass::Simulate(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBasePlayer::GetStepSoundVelocities( float *velwalk, float *velrun ) { // UNDONE: need defined numbers for run, walk, crouch, crouch run velocities!!!! if ( ( GetFlags() & FL_DUCKING) || ( GetMoveType() == MOVETYPE_LADDER ) ) { *velwalk = 60; // These constants should be based on cl_movespeedkey * cl_forwardspeed somehow *velrun = 80; } else { *velwalk = 90; *velrun = 220; } }
void Monai::GetPositionMon(float time){ //GetMoveType(time); if(!g_bChangePattern){ GetMoveType(time); } if(!g_bChangeThread){ Type(pMon->GetmType(),time); }else{ pCheckResult->StartSorting(); g_bChangeThread = FALSE; g_bChangePattern = FALSE; } /* if(!bNaton&&time - g_fNormalAttack>5.0f){ vLength = pMon->GetPosition()-pCha->GetPosition(); if(D3DXVec3Length(&vLength)<MON_REAL_SIZE+MON_ATTACK_RANGE){ g_bNormalAttack = FALSE; } if(!g_bNormalAttack){ pAniModel->SetCurrentAnimation(0); fAniMotionTime = 0.01f; g_fNormalAttackStart = time; g_bNormalAttack = TRUE; bNaton = TRUE; }else{ if(time - g_fNormalAttackStart>2.0f){ pCha->SetLife(-1); }else{ g_bNormalAttack = FALSE; bNaton = FALSE; } } } *///if(!g_bChangeThread){ // Type(pMon->GetmType(),time); //}else{ // if(g_bChangePattern){ // pCheckResult->start(); // g_bChangePattern = FALSE; // }else{ // if(pCheckResult->NowChange()){ // pCheckResult->SetChange(FALSE); // g_bChangeThread = FALSE; // } // } //} }
void CBaseGolem::UpdateAI() { switch(GetMoveType()) { case RAND_MOVE: { CAI_Handler::GetInstance()->RandomMove(this); } break; case TARGET_MOVE: { CAI_Handler::GetInstance()->MoveToPos(this); } break; } }
bool CDODPlayer::CanAttack( void ) { if ( IsSprinting() ) return false; if ( GetMoveType() == MOVETYPE_LADDER ) return false; if ( m_Shared.IsJumping() ) return false; if ( m_Shared.IsDefusing() ) return false; // cannot attack while prone moving. except if you have a bazooka if ( m_Shared.IsProne() && GetAbsVelocity().LengthSqr() > 1 ) { return false; } if( m_Shared.IsGoingProne() || m_Shared.IsGettingUpFromProne() ) { return false; } CDODGameRules *rules = DODGameRules(); Assert( rules ); DODRoundState state = rules->State_Get(); if ( dod_bonusround.GetBool() ) { if ( GetTeamNumber() == TEAM_ALLIES ) { return ( state == STATE_RND_RUNNING || state == STATE_ALLIES_WIN ); } else { return ( state == STATE_RND_RUNNING || state == STATE_AXIS_WIN ); } } else return ( state == STATE_RND_RUNNING ); }
void CBasePlayer::AvoidPhysicsProps( CUserCmd *pCmd ) { #ifndef _XBOX // Don't avoid if noclipping or in movetype none switch ( GetMoveType() ) { case MOVETYPE_NOCLIP: case MOVETYPE_NONE: return; default: break; } if ( !IsObserver() ) return; AvoidPushawayProps( this, pCmd ); #endif }
std::string GetMoveUci(const Move move) { std::string result; result += GetSquareSAN(GetFrom(move)); result += GetSquareSAN(GetTo(move)); if (GetMoveType(move) == MoveTypePromotion) { switch (GetPromotionMoveType(move)) { case KNIGHT: result += "n"; break; case BISHOP: result += "b"; break; case ROOK: result += "r"; break; case QUEEN: result += "q"; break; } } return result; }
void CSDKPlayer::State_PreThink_DEATH_ANIM() { // If the anim is done playing, go to the next state (waiting for a keypress to // either respawn the guy or put him into observer mode). if ( GetFlags() & FL_ONGROUND ) { float flForward = GetAbsVelocity().Length() - 20; if (flForward <= 0) { SetAbsVelocity( vec3_origin ); } else { Vector vAbsVel = GetAbsVelocity(); VectorNormalize( vAbsVel ); vAbsVel *= flForward; SetAbsVelocity( vAbsVel ); } } if ( gpGlobals->curtime >= (m_flDeathTime + SDK_PLAYER_DEATH_TIME ) ) // let the death cam stay going up to min spawn time. { m_lifeState = LIFE_DEAD; StopAnimation(); AddEffects( EF_NOINTERP ); if ( GetMoveType() != MOVETYPE_NONE && (GetFlags() & FL_ONGROUND) ) SetMoveType( MOVETYPE_NONE ); } //Tony; if we're now dead, and not changing classes, spawn if ( m_lifeState == LIFE_DEAD ) { #if defined ( SDK_USE_PLAYERCLASSES ) //Tony; if the class menu is open, don't respawn them, wait till they're done. if (IsClassMenuOpen()) return; #endif State_Transition( STATE_ACTIVE ); } }
//------------------------------------------------------------------------------ // Purpose : Override to return correct velocity // Input : // Output : //------------------------------------------------------------------------------ void CAI_BasePhysicsFlyingBot::GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity) { Assert( GetMoveType() == MOVETYPE_VPHYSICS ); if ( VPhysicsGetObject() ) { VPhysicsGetObject()->GetVelocity( vVelocity, vAngVelocity ); } else { if ( vVelocity ) { vVelocity->Init(); } if ( vAngVelocity ) { vAngVelocity->Init(); } } }
bool CBliinkPlayer::CanAttack( void ) { #if defined ( SDK_USE_SPRINTING ) #if !defined ( SDK_SHOOT_WHILE_SPRINTING ) if ( IsSprinting() ) return false; #endif // SDK_SHOOT_WHILE_SPRINTING #endif // SDK_USE_SPRINTING #if !defined ( SDK_SHOOT_ON_LADDERS ) if ( GetMoveType() == MOVETYPE_LADDER ) return false; #endif //SDK_SHOOT_ON_LADDERS #if !defined ( SDK_SHOOT_WHILE_JUMPING ) if ( m_Shared.IsJumping() ) return false; #endif //SDK_SHOOT_WHILE_JUMPING return true; }
void CDHLProjectile::ReceiveMessage( int classID, bf_read &msg ) { if ( classID != GetClientClass()->m_ClassID ) { // message is for subclass BaseClass::ReceiveMessage( classID, msg ); return; } int iType = msg.ReadByte(); //Server is letting us know that we're about to be deleted if ( iType == MSG_NOTIFY_REMOVAL ) { if ( !m_bCollided ) { Vector vecDir = vec3_origin; if ( GetAbsVelocity() != vec3_origin ) vecDir = GetAbsVelocity(); else vecDir = m_vecProjectileVelocity; VectorNormalize( vecDir ); Vector vecStartPos = GetMoveType() == MOVETYPE_CUSTOM ? GetLocalOrigin() : m_vecProjectileOrigin; //Try to plant a decal trace_t decaltr; UTIL_TraceLine( vecStartPos, vecStartPos + (vecDir * 120.0), MASK_SHOT, this, //Pretty long distance, but seems necessary in practice COLLISION_GROUP_NONE, &decaltr ); //DebugDrawLine( decaltr.startpos, decaltr.endpos, 255, 0, 0, false, 3.0f ); if ( decaltr.DidHit() ) { OnTouch( decaltr, true ); } m_bCollided = true; } } }
void CUnitBase::PhysicsSimulate( void ) { #ifdef CLIENT_DLL if (ShouldPredict()) { m_nSimulationTick = gpGlobals->tickcount; return; } #else //NDebugOverlay::Box( GetAbsOrigin(), Vector(-16, -16, -16), Vector(16, 24, 16), 0, 255, 0, 255, 0.1f); #endif // CLIENT_DLL if( GetMoveType() != MOVETYPE_WALK ) { BaseClass::PhysicsSimulate(); return; } // Run all but the base think function PhysicsRunThink( THINK_FIRE_ALL_BUT_BASE ); PhysicsRunThink( THINK_FIRE_BASE_ONLY ); }
//------------------------------------------------------------------------------ // If we hit water, then stop //------------------------------------------------------------------------------ void CQUAGrenadeHelicopter::PhysicsSimulate( void ) { Vector vecPrevPosition = GetAbsOrigin(); BaseClass::PhysicsSimulate(); if (!m_bActivated && (GetMoveType() != MOVETYPE_VPHYSICS)) { if ( GetWaterLevel() > 1 ) { SetAbsVelocity( vec3_origin ); SetMoveType( MOVETYPE_NONE ); BecomeActive(); } // Stuck condition, can happen pretty often if ( vecPrevPosition == GetAbsOrigin() ) { SetAbsVelocity( vec3_origin ); SetMoveType( MOVETYPE_NONE ); BecomeActive(); } } }
void CSnark::HuntThink( void ) { if (!IsInWorld()) { SetTouch( NULL ); UTIL_Remove( this ); return; } StudioFrameAdvance( ); SetNextThink( gpGlobals->curtime + 0.1f ); // explode when ready if ( gpGlobals->curtime >= m_flDie ) { g_vecAttackDir = GetAbsVelocity(); VectorNormalize( g_vecAttackDir ); m_iHealth = -1; CTakeDamageInfo info( this, this, 1, DMG_GENERIC ); Event_Killed( info ); return; } // float if ( GetWaterLevel() != 0) { if ( GetMoveType() == MOVETYPE_FLYGRAVITY ) { SetMoveType( MOVETYPE_FLY, MOVECOLLIDE_FLY_BOUNCE ); } Vector vecVel = GetAbsVelocity(); vecVel *= 0.9; vecVel.z += 8.0; SetAbsVelocity( vecVel ); } else if ( GetMoveType() == MOVETYPE_FLY ) { SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); } // return if not time to hunt if ( m_flNextHunt > gpGlobals->curtime ) return; m_flNextHunt = gpGlobals->curtime + 2.0; Vector vecFlat = GetAbsVelocity(); vecFlat.z = 0; VectorNormalize( vecFlat ); if ( GetEnemy() == NULL || !GetEnemy()->IsAlive() ) { // find target, bounce a bit towards it. GetSenses()->Look( 512 ); SetEnemy( BestEnemy() ); } // squeek if it's about time blow up if ( (m_flDie - gpGlobals->curtime <= 0.5) && (m_flDie - gpGlobals->curtime >= 0.3) ) { CPASAttenuationFilter filter( this ); enginesound->EmitSound( filter, entindex(), CHAN_VOICE, "squeek/sqk_die1.wav", 1, ATTN_NORM, 0, 100 + random->RandomInt( 0, 0x3F ) ); CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 256, 0.25 ); } // higher pitch as squeeker gets closer to detonation time float flpitch = 155.0 - 60.0 * ( (m_flDie - gpGlobals->curtime) / SQUEEK_DETONATE_DELAY ); if ( flpitch < 80 ) flpitch = 80; if ( GetEnemy() != NULL ) { if ( FVisible( GetEnemy() ) ) { m_vecTarget = GetEnemy()->EyePosition() - GetAbsOrigin(); VectorNormalize( m_vecTarget ); } float flVel = GetAbsVelocity().Length(); float flAdj = 50.0 / ( flVel + 10.0 ); if ( flAdj > 1.2 ) flAdj = 1.2; // ALERT( at_console, "think : enemy\n"); // ALERT( at_console, "%.0f %.2f %.2f %.2f\n", flVel, m_vecTarget.x, m_vecTarget.y, m_vecTarget.z ); SetAbsVelocity( GetAbsVelocity() * flAdj + (m_vecTarget * 300) ); } if ( GetFlags() & FL_ONGROUND ) { SetLocalAngularVelocity( QAngle( 0, 0, 0 ) ); } else { QAngle angVel = GetLocalAngularVelocity(); if ( angVel == QAngle( 0, 0, 0 ) ) { angVel.x = random->RandomFloat( -100, 100 ); angVel.z = random->RandomFloat( -100, 100 ); SetLocalAngularVelocity( angVel ); } } if ( ( GetAbsOrigin() - m_posPrev ).Length() < 1.0 ) { Vector vecVel = GetAbsVelocity(); vecVel.x = random->RandomFloat( -100, 100 ); vecVel.y = random->RandomFloat( -100, 100 ); SetAbsVelocity( vecVel ); } m_posPrev = GetAbsOrigin(); QAngle angles; VectorAngles( GetAbsVelocity(), angles ); angles.z = 0; angles.x = 0; SetAbsAngles( angles ); }
//----------------------------------------------------------------------------- // Client-side obstacle avoidance //----------------------------------------------------------------------------- void C_BaseHLPlayer::PerformClientSideObstacleAvoidance( float flFrameTime, CUserCmd *pCmd ) { // Don't avoid if noclipping or in movetype none switch ( GetMoveType() ) { case MOVETYPE_NOCLIP: case MOVETYPE_NONE: case MOVETYPE_OBSERVER: return; default: break; } // Try to steer away from any objects/players we might interpenetrate Vector size = WorldAlignSize(); float radius = 0.7f * sqrt( size.x * size.x + size.y * size.y ); float curspeed = GetLocalVelocity().Length2D(); //int slot = 1; //engine->Con_NPrintf( slot++, "speed %f\n", curspeed ); //engine->Con_NPrintf( slot++, "radius %f\n", radius ); // If running, use a larger radius float factor = 1.0f; if ( curspeed > 150.0f ) { curspeed = MIN( 2048.0f, curspeed ); factor = ( 1.0f + ( curspeed - 150.0f ) / 150.0f ); //engine->Con_NPrintf( slot++, "scaleup (%f) to radius %f\n", factor, radius * factor ); radius = radius * factor; } Vector currentdir; Vector rightdir; QAngle vAngles = pCmd->viewangles; vAngles.x = 0; AngleVectors( vAngles, ¤tdir, &rightdir, NULL ); bool istryingtomove = false; bool ismovingforward = false; if ( fabs( pCmd->forwardmove ) > 0.0f || fabs( pCmd->sidemove ) > 0.0f ) { istryingtomove = true; if ( pCmd->forwardmove > 1.0f ) { ismovingforward = true; } } if ( istryingtomove == true ) radius *= 1.3f; CPlayerAndObjectEnumerator avoid( radius ); partition->EnumerateElementsInSphere( PARTITION_CLIENT_SOLID_EDICTS, GetAbsOrigin(), radius, false, &avoid ); // Okay, decide how to avoid if there's anything close by int c = avoid.GetObjectCount(); if ( c <= 0 ) return; //engine->Con_NPrintf( slot++, "moving %s forward %s\n", istryingtomove ? "true" : "false", ismovingforward ? "true" : "false" ); float adjustforwardmove = 0.0f; float adjustsidemove = 0.0f; for ( int i = 0; i < c; i++ ) { C_AI_BaseNPC *obj = dynamic_cast< C_AI_BaseNPC *>(avoid.GetObject( i )); if( !obj ) continue; Vector vecToObject = obj->GetAbsOrigin() - GetAbsOrigin(); float flDist = vecToObject.Length2D(); // Figure out a 2D radius for the object Vector vecWorldMins, vecWorldMaxs; obj->CollisionProp()->WorldSpaceAABB( &vecWorldMins, &vecWorldMaxs ); Vector objSize = vecWorldMaxs - vecWorldMins; float objectradius = 0.5f * sqrt( objSize.x * objSize.x + objSize.y * objSize.y ); //Don't run this code if the NPC is not moving UNLESS we are in stuck inside of them. if ( !obj->IsMoving() && flDist > objectradius ) continue; if ( flDist > objectradius && obj->IsEffectActive( EF_NODRAW ) ) { obj->RemoveEffects( EF_NODRAW ); } Vector vecNPCVelocity; obj->EstimateAbsVelocity( vecNPCVelocity ); float flNPCSpeed = VectorNormalize( vecNPCVelocity ); Vector vPlayerVel = GetAbsVelocity(); VectorNormalize( vPlayerVel ); float flHit1, flHit2; Vector vRayDir = vecToObject; VectorNormalize( vRayDir ); float flVelProduct = DotProduct( vecNPCVelocity, vPlayerVel ); float flDirProduct = DotProduct( vRayDir, vPlayerVel ); if ( !IntersectInfiniteRayWithSphere( GetAbsOrigin(), vRayDir, obj->GetAbsOrigin(), radius, &flHit1, &flHit2 ) ) continue; Vector dirToObject = -vecToObject; VectorNormalize( dirToObject ); float fwd = 0; float rt = 0; float sidescale = 2.0f; float forwardscale = 1.0f; bool foundResult = false; Vector vMoveDir = vecNPCVelocity; if ( flNPCSpeed > 0.001f ) { // This NPC is moving. First try deflecting the player left or right relative to the NPC's velocity. // Start with whatever side they're on relative to the NPC's velocity. Vector vecNPCTrajectoryRight = CrossProduct( vecNPCVelocity, Vector( 0, 0, 1) ); int iDirection = ( vecNPCTrajectoryRight.Dot( dirToObject ) > 0 ) ? 1 : -1; for ( int nTries = 0; nTries < 2; nTries++ ) { Vector vecTryMove = vecNPCTrajectoryRight * iDirection; VectorNormalize( vecTryMove ); Vector vTestPosition = GetAbsOrigin() + vecTryMove * radius * 2; if ( TestMove( vTestPosition, size.z * 2, radius * 2, obj->GetAbsOrigin(), vMoveDir ) ) { fwd = currentdir.Dot( vecTryMove ); rt = rightdir.Dot( vecTryMove ); //Msg( "PUSH DEFLECT fwd=%f, rt=%f\n", fwd, rt ); foundResult = true; break; } else { // Try the other direction. iDirection *= -1; } } } else { // the object isn't moving, so try moving opposite the way it's facing Vector vecNPCForward; obj->GetVectors( &vecNPCForward, NULL, NULL ); Vector vTestPosition = GetAbsOrigin() - vecNPCForward * radius * 2; if ( TestMove( vTestPosition, size.z * 2, radius * 2, obj->GetAbsOrigin(), vMoveDir ) ) { fwd = currentdir.Dot( -vecNPCForward ); rt = rightdir.Dot( -vecNPCForward ); if ( flDist < objectradius ) { obj->AddEffects( EF_NODRAW ); } //Msg( "PUSH AWAY FACE fwd=%f, rt=%f\n", fwd, rt ); foundResult = true; } } if ( !foundResult ) { // test if we can move in the direction the object is moving Vector vTestPosition = GetAbsOrigin() + vMoveDir * radius * 2; if ( TestMove( vTestPosition, size.z * 2, radius * 2, obj->GetAbsOrigin(), vMoveDir ) ) { fwd = currentdir.Dot( vMoveDir ); rt = rightdir.Dot( vMoveDir ); if ( flDist < objectradius ) { obj->AddEffects( EF_NODRAW ); } //Msg( "PUSH ALONG fwd=%f, rt=%f\n", fwd, rt ); foundResult = true; } else { // try moving directly away from the object Vector vTestPosition = GetAbsOrigin() - dirToObject * radius * 2; if ( TestMove( vTestPosition, size.z * 2, radius * 2, obj->GetAbsOrigin(), vMoveDir ) ) { fwd = currentdir.Dot( -dirToObject ); rt = rightdir.Dot( -dirToObject ); foundResult = true; //Msg( "PUSH AWAY fwd=%f, rt=%f\n", fwd, rt ); } } } if ( !foundResult ) { // test if we can move through the object Vector vTestPosition = GetAbsOrigin() - vMoveDir * radius * 2; fwd = currentdir.Dot( -vMoveDir ); rt = rightdir.Dot( -vMoveDir ); if ( flDist < objectradius ) { obj->AddEffects( EF_NODRAW ); } //Msg( "PUSH THROUGH fwd=%f, rt=%f\n", fwd, rt ); foundResult = true; } // If running, then do a lot more sideways veer since we're not going to do anything to // forward velocity if ( istryingtomove ) { sidescale = 6.0f; } if ( flVelProduct > 0.0f && flDirProduct > 0.0f ) { sidescale = 0.1f; } float force = 1.0f; float forward = forwardscale * fwd * force * AVOID_SPEED; float side = sidescale * rt * force * AVOID_SPEED; adjustforwardmove += forward; adjustsidemove += side; } pCmd->forwardmove += adjustforwardmove; pCmd->sidemove += adjustsidemove; // Clamp the move to within legal limits, preserving direction. This is a little // complicated because we have different limits for forward, back, and side //Msg( "PRECLAMP: forwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove ); float flForwardScale = 1.0f; if ( pCmd->forwardmove > fabs( cl_forwardspeed.GetFloat() ) ) { flForwardScale = fabs( cl_forwardspeed.GetFloat() ) / pCmd->forwardmove; } else if ( pCmd->forwardmove < -fabs( cl_backspeed.GetFloat() ) ) { flForwardScale = fabs( cl_backspeed.GetFloat() ) / fabs( pCmd->forwardmove ); } float flSideScale = 1.0f; if ( fabs( pCmd->sidemove ) > fabs( cl_sidespeed.GetFloat() ) ) { flSideScale = fabs( cl_sidespeed.GetFloat() ) / fabs( pCmd->sidemove ); } float flScale = MIN( flForwardScale, flSideScale ); pCmd->forwardmove *= flScale; pCmd->sidemove *= flScale; //Msg( "POSTCLAMP: forwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove ); }
//----------------------------------------------------------------------------- // Purpose: Give the buster a slight attraction to striders. // Ported back from the magnade. //----------------------------------------------------------------------------- void CWeaponStriderBuster::BusterFlyThink() { if (IsAttachedToStrider()) return; // early out. Think no more. // If we're nosediving, forget about magnetism. if ( m_bNoseDiving ) { if ( VPhysicsGetObject() ) VPhysicsGetObject()->ApplyForceCenter( Vector( 0, 0, striderbuster_dive_force.GetFloat() ) ); SetNextThink(gpGlobals->curtime + 0.01f); return; } // seek? const float magradius = 38.0 * sk_striderbuster_magnet_multiplier.GetFloat(); // radius of strider hull times multiplier if (magradius > 0 && GetMoveType() == MOVETYPE_VPHYSICS && VPhysicsGetObject() ) { // find the nearest enemy. CBaseEntity *pList[16]; Vector origin = GetAbsOrigin(); // do a find in box ( a little faster than sphere ) int count; { Vector mins,maxs; mins = origin; mins -= magradius; maxs = origin; maxs += magradius; count = UTIL_EntitiesInBox(pList, 16, mins, maxs, FL_NPC); } float magradiusSq = Square( magradius ); float nearestDistSq = magradiusSq + 1; int bestFit = -1; Vector toTarget; // will be garbage unless something good is found CNPC_Strider *pBestStrider = NULL; for ( int ii = 0 ; ii < count ; ++ii ) { CNPC_Strider *pStrider = dynamic_cast<CNPC_Strider *>(pList[ii]); if ( pStrider && !pStrider->CarriedByDropship() ) // ShouldStickToEntity() doesn't work because the strider NPC isn't what we glue to { // get distance squared VectorSubtract( pStrider->GetAdjustedOrigin(), GetAbsOrigin(), toTarget ); //NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + toTarget, 128, 0, 128, false, 0.1 ); float dSq = toTarget.LengthSqr(); if (dSq < nearestDistSq) { bestFit = ii; nearestDistSq = dSq; pBestStrider = pStrider; } } } if (bestFit >= 0) // we found something and should attract towards it. (hysterisis later?) { if ( striderbuster_debugseek.GetBool() ) { NDebugOverlay::Circle( GetAbsOrigin() + toTarget, magradius, 255, 255, 255, 255, true, .1 ); NDebugOverlay::Cross3D( GetAbsOrigin() + toTarget, magradius, 255, 255, 255, true, .1 ); } // force magnitude. float magnitude = GetMass() * striderbuster_magnetic_force_strider.GetFloat(); int falloff = striderbuster_falloff_power.GetInt(); switch (falloff) { case 1: VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / nearestDistSq) ); // dividing through by distance squared normalizes toTarget and gives a linear falloff break; case 2: VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / (nearestDistSq * sqrtf(nearestDistSq))) ); // dividing through by distance cubed normalizes toTarget and gives a quadratic falloff break; case 3: VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / (nearestDistSq * nearestDistSq)) ); // dividing through by distance fourth normalizes toTarget and gives a cubic falloff break; case 4: { Vector toTarget; pBestStrider->GetAttachment( "buster_target", toTarget ); if ( striderbuster_debugseek.GetBool() ) { NDebugOverlay::Cross3D( toTarget, magradius, 255, 0, 255, true, .1 ); NDebugOverlay::Cross3D( toTarget, magradius, 255, 0, 255, true, .1 ); } toTarget -= GetAbsOrigin(); toTarget.NormalizeInPlace(); VPhysicsGetObject()->ApplyForceCenter( toTarget * magnitude ); } break; default: // arbitrary powers VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude * powf(nearestDistSq,(falloff+1.0f)/2)) ); // square root for distance instead of squared, add one to normalize toTarget break; } } SetNextThink(gpGlobals->curtime + 0.01f); } }
void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) { bool bWalking; float fvol; Vector knee; Vector feet; float height; float speed; float velrun; float velwalk; int fLadder; if ( m_flStepSoundTime > 0 ) { m_flStepSoundTime -= 1000.0f * gpGlobals->frametime; if ( m_flStepSoundTime < 0 ) { m_flStepSoundTime = 0; } } if ( m_flStepSoundTime > 0 ) return; if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) return; if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) return; if ( !sv_footsteps.GetFloat() ) return; speed = VectorLength( vecVelocity ); float groundspeed = Vector2DLength( vecVelocity.AsVector2D() ); // determine if we are on a ladder fLadder = ( GetMoveType() == MOVETYPE_LADDER ); GetStepSoundVelocities( &velwalk, &velrun ); bool onground = ( GetFlags() & FL_ONGROUND ); bool movingalongground = ( groundspeed > 0.0001f ); bool moving_fast_enough = ( speed >= velwalk ); #ifdef PORTAL // In Portal we MUST play footstep sounds even when the player is moving very slowly // This is used to count the number of footsteps they take in the challenge mode // -Jeep moving_fast_enough = true; #endif // To hear step sounds you must be either on a ladder or moving along the ground AND // You must be moving fast enough if ( !moving_fast_enough || !(fLadder || ( onground && movingalongground )) ) return; // MoveHelper()->PlayerSetAnimation( PLAYER_WALK ); bWalking = speed < velrun; VectorCopy( vecOrigin, knee ); VectorCopy( vecOrigin, feet ); height = GetPlayerMaxs()[ 2 ] - GetPlayerMins()[ 2 ]; knee[2] = vecOrigin[2] + 0.2 * height; // find out what we're stepping in or on... if ( fLadder ) { psurface = GetLadderSurface(vecOrigin); fvol = 0.5; SetStepSoundTime( STEPSOUNDTIME_ON_LADDER, bWalking ); } else if ( GetWaterLevel() == WL_Waist ) { static int iSkipStep = 0; if ( iSkipStep == 0 ) { iSkipStep++; return; } if ( iSkipStep++ == 3 ) { iSkipStep = 0; } psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) ); fvol = 0.65; SetStepSoundTime( STEPSOUNDTIME_WATER_KNEE, bWalking ); } else if ( GetWaterLevel() == WL_Feet ) { psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) ); fvol = bWalking ? 0.2 : 0.5; SetStepSoundTime( STEPSOUNDTIME_WATER_FOOT, bWalking ); } else { if ( !psurface ) return; SetStepSoundTime( STEPSOUNDTIME_NORMAL, bWalking ); switch ( psurface->game.material ) { default: case CHAR_TEX_CONCRETE: fvol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_METAL: fvol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_DIRT: fvol = bWalking ? 0.25 : 0.55; break; case CHAR_TEX_VENT: fvol = bWalking ? 0.4 : 0.7; break; case CHAR_TEX_GRATE: fvol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_TILE: fvol = bWalking ? 0.2 : 0.5; break; case CHAR_TEX_SLOSH: fvol = bWalking ? 0.2 : 0.5; break; } } // play the sound // 65% volume if ducking if ( GetFlags() & FL_DUCKING ) { fvol *= 0.65; } PlayStepSound( feet, psurface, fvol, false ); }
void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) { int fWalking; float fvol; Vector knee; Vector feet; float height; float speed; float velrun; float velwalk; float flduck; int fLadder; if ( m_flStepSoundTime > 0 ) { m_flStepSoundTime -= 1000.0f * gpGlobals->frametime; if ( m_flStepSoundTime < 0 ) { m_flStepSoundTime = 0; } } if ( m_flStepSoundTime > 0 ) return; if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) return; if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) return; if ( !sv_footsteps.GetFloat() ) return; speed = VectorLength( vecVelocity ); float groundspeed = Vector2DLength( vecVelocity.AsVector2D() ); // determine if we are on a ladder fLadder = ( GetMoveType() == MOVETYPE_LADDER ); // UNDONE: need defined numbers for run, walk, crouch, crouch run velocities!!!! if ( ( GetFlags() & FL_DUCKING) || fLadder ) { velwalk = 60; // These constants should be based on cl_movespeedkey * cl_forwardspeed somehow velrun = 80; flduck = 100; } else { velwalk = 90; velrun = 220; flduck = 0; } bool onground = ( GetFlags() & FL_ONGROUND ); bool movingalongground = ( groundspeed > 0.0f ); bool moving_fast_enough = ( speed >= velwalk ); // To hear step sounds you must be either on a ladder or moving along the ground AND // You must be moving fast enough if ( !moving_fast_enough || !(fLadder || ( onground && movingalongground )) ) return; // MoveHelper()->PlayerSetAnimation( PLAYER_WALK ); fWalking = speed < velrun; VectorCopy( vecOrigin, knee ); VectorCopy( vecOrigin, feet ); height = GetPlayerMaxs()[ 2 ] - GetPlayerMins()[ 2 ]; knee[2] = vecOrigin[2] + 0.2 * height; // find out what we're stepping in or on... if ( fLadder ) { #ifdef CLIENT_DLL psurface = GetFootstepSurface( vecOrigin, "ladder" ); #else psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "ladder" ) ); #endif fvol = 0.5; m_flStepSoundTime = 350; } else if ( enginetrace->GetPointContents( knee ) & MASK_WATER ) { static int iSkipStep = 0; if ( iSkipStep == 0 ) { iSkipStep++; return; } if ( iSkipStep++ == 3 ) { iSkipStep = 0; } psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) ); fvol = 0.65; m_flStepSoundTime = 600; } else if ( enginetrace->GetPointContents( feet ) & MASK_WATER ) { psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) ); fvol = fWalking ? 0.2 : 0.5; m_flStepSoundTime = fWalking ? 400 : 300; } else { if ( !psurface ) return; m_flStepSoundTime = fWalking ? 400 : 300; switch ( psurface->game.material ) { default: case CHAR_TEX_CONCRETE: fvol = fWalking ? 0.2 : 0.5; break; case CHAR_TEX_METAL: fvol = fWalking ? 0.2 : 0.5; break; case CHAR_TEX_DIRT: fvol = fWalking ? 0.25 : 0.55; break; case CHAR_TEX_VENT: fvol = fWalking ? 0.4 : 0.7; break; case CHAR_TEX_GRATE: fvol = fWalking ? 0.2 : 0.5; break; case CHAR_TEX_TILE: fvol = fWalking ? 0.2 : 0.5; break; case CHAR_TEX_SLOSH: fvol = fWalking ? 0.2 : 0.5; break; } } m_flStepSoundTime += flduck; // slower step time if ducking // play the sound // 65% volume if ducking if ( GetFlags() & FL_DUCKING ) { fvol *= 0.65; } PlayStepSound( feet, psurface, fvol, false ); }
std::string GetMoveSAN(Position &position, const Move move) { const Square from = GetFrom(move); const Square to = GetTo(move); const Move moveType = GetMoveType(move); std::string result; if (moveType == MoveTypeCastle) { if (GetColumn(to) > FILE_E) { result = "O-O"; } else { result = "O-O-O"; } } else { // Piece that is moving const PieceType fromPieceType = GetPieceType(position.Board[from]); switch (fromPieceType) { case PAWN: break; case KNIGHT: result += "N"; break; case BISHOP: result += "B"; break; case ROOK: result += "R"; break; case QUEEN: result += "Q"; break; case KING: result += "K"; break; } Move legalMoves[256]; int legalMoveCount = GenerateLegalMoves(position, legalMoves); // Do we need to disambiguate? bool dupe = false, rowDiff = true, columnDiff = true; for (int i = 0; i < legalMoveCount; i++) { if (GetFrom(legalMoves[i]) != from && GetTo(legalMoves[i]) == to && GetPieceType(position.Board[GetFrom(legalMoves[i])]) == fromPieceType) { dupe = true; if (GetRow(GetFrom(legalMoves[i])) == GetRow(from)) { rowDiff = false; } if (GetColumn(GetFrom(legalMoves[i])) == GetColumn(from)) { columnDiff = false; } } } if (dupe) { if (columnDiff) { result += GetSquareSAN(from)[0]; } else if (rowDiff) { result += GetSquareSAN(from)[1]; } else { result += GetSquareSAN(from); } } else if (fromPieceType == PAWN && position.Board[to] != PIECE_NONE) { // Pawn captures need a row result += GetSquareSAN(from)[0]; } // Capture? if (position.Board[to] != PIECE_NONE || moveType == MoveTypeEnPassent) { result += "x"; } // Target square result += GetSquareSAN(to); } if (moveType == MoveTypePromotion) { switch (GetPromotionMoveType(move)) { case KNIGHT: result += "=N"; break; case BISHOP: result += "=B"; break; case ROOK: result += "=R"; break; case QUEEN: result += "=Q"; break; } } MoveUndo moveUndo; position.MakeMove(move, moveUndo); if (position.IsInCheck()) { Move checkEscapes[64]; result += GenerateCheckEscapeMoves(position, checkEscapes) == 0 ? "#" : "+"; } position.UnmakeMove(move, moveUndo); return result; }
//----------------------------------------------------------------------------- // Purpose: // Input : flInterval - // - // *pTraceResult - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CAI_BaseNPC::AutoMovement( float flInterval, CBaseEntity *pTarget, AIMoveTrace_t *pTraceResult ) { bool ignored; Vector newPos; QAngle newAngles; if (flInterval <= 0.0) return true; m_ScheduleState.bTaskRanAutomovement = true; if (GetIntervalMovement( flInterval, ignored, newPos, newAngles )) { // DevMsg( "%.2f : (%.1f) %.1f %.1f %.1f\n", gpGlobals->curtime, (newPos - GetLocalOrigin()).Length(), newPos.x, newPos.y, newAngles.y ); if ( m_hCine ) { m_hCine->ModifyScriptedAutoMovement( &newPos ); } if (GetMoveType() == MOVETYPE_STEP) { if (!(GetFlags() & FL_FLY)) { if ( !pTarget ) { pTarget = GetNavTargetEntity(); } // allow NPCs to adjust the automatic movement if ( ModifyAutoMovement( newPos ) ) { // Set our motor's speed here Vector vecOriginalPosition = GetAbsOrigin(); bool bResult = false; if (!TaskIsComplete()) { bResult = ( GetMotor()->MoveGroundStep( newPos, pTarget, newAngles.y, false, true, pTraceResult ) == AIM_SUCCESS ); } Vector change = GetAbsOrigin() - vecOriginalPosition; if (flInterval != 0) { change /= flInterval; } GetMotor()->SetMoveVel(change); return bResult; } return ( GetMotor()->MoveGroundStep( newPos, pTarget, newAngles.y, false, true, pTraceResult ) == AIM_SUCCESS ); } else { // FIXME: here's no direct interface to a fly motor, plus this needs to support a state where going through the world is okay. // FIXME: add callbacks into the script system for validation // FIXME: add function on scripts to force only legal movements // FIXME: GetIntervalMovement deals in Local space, nor global. Currently now way to communicate that through these interfaces. SetLocalOrigin( newPos ); SetLocalAngles( newAngles ); return true; } } else if (GetMoveType() == MOVETYPE_FLY) { Vector dist = newPos - GetLocalOrigin(); VectorScale( dist, 1.0 / flInterval, dist ); SetLocalVelocity( dist ); return true; } } return false; }