void CASW_Drone_Movement::CategorizePosition() { Vector point, bumpOrigin; trace_t pm; point = bumpOrigin = mv->GetAbsOrigin(); point.z -= 2; bumpOrigin.z += 2; // Shooting up really fast. Definitely not on ground. if ( mv->m_vecVelocity[2] > 140 || ( mv->m_vecVelocity[2] > 0.0f && m_pNPC->GetMoveType() == MOVETYPE_LADDER ) ) { SetGroundEntity( (CBaseEntity *)NULL ); } else { // Try and move down. UTIL_TraceEntity( m_pNPC, bumpOrigin, point, MASK_NPCSOLID, &pm ); //TraceBBox( bumpOrigin, point, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), pm ); // Moving up two units got us stuck in something, start tracing down exactly at our // current origin (since CheckStuck allowed us to get here, that pos is valid) if ( pm.startsolid ) { bumpOrigin = mv->GetAbsOrigin(); UTIL_TraceEntity( m_pNPC, bumpOrigin, point, MASK_NPCSOLID, &pm ); //TraceBBox( bumpOrigin, point, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), pm ); } // If we hit a steep plane, we are not on ground if ( pm.plane.normal[2] < 0.7) { SetGroundEntity( (CBaseEntity *)NULL ); // too steep // probably want to add a check for a +z velocity too! if ( ( mv->m_vecVelocity.z > 0.0f ) && ( m_pNPC->GetMoveType() != MOVETYPE_NOCLIP ) ) { m_surfaceFriction = 0.25f; } } else { SetGroundEntity( pm.m_pEnt ); // Otherwise, point to index of ent under us. } // If we are on something... if (m_pNPC->GetGroundEntity() != NULL) { // If we could make the move, drop us down that 1 pixel if (!pm.startsolid && !pm.allsolid ) { if( pm.fraction ) { mv->SetAbsOrigin( pm.endpos ); } } } } }
//----------------------------------------------------------------------------- // Drops an entity onto the floor //----------------------------------------------------------------------------- int UTIL_DropToFloor( CBaseEntity *pEntity, unsigned int mask, CBaseEntity *pIgnore) { // Assume no ground //pEntity->SetGroundEntity( NULL ); Assert( pEntity ); trace_t trace; // HACK: is this really the only sure way to detect crossing a terrain boundry? UTIL_TraceEntity( pEntity, VFuncs::GetAbsOrigin(pEntity), VFuncs::GetAbsOrigin(pEntity), mask, pIgnore, VFuncs::GetCollisionGroup(pEntity), &trace ); if (trace.fraction == 0.0) return -1; UTIL_TraceEntity( pEntity, VFuncs::GetAbsOrigin(pEntity), VFuncs::GetAbsOrigin(pEntity) - Vector(0,0,256), mask, pIgnore, VFuncs::GetCollisionGroup(pEntity), &trace ); if (trace.allsolid) return -1; if (trace.fraction == 1) return 0; VFuncs::Teleport(pEntity, &trace.endpos, NULL, NULL); //pEntity->SetAbsOrigin( trace.endpos ); //pEntity->SetGroundEntity( trace.m_pEnt ); return 1; }
void TerrainMod_Add( TerrainModType type, const CTerrainModParams ¶ms ) { if ( IsXbox() ) { return; } // Move players out of the way so they don't get stuck on the terrain. float playerStartHeights[MAX_PLAYERS]; int i; int nPlayers = MIN( MAX_PLAYERS, gpGlobals->maxClients ); for( i=0; i < nPlayers; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i+1 ); if( !pPlayer ) continue; playerStartHeights[i] = pPlayer->GetAbsOrigin().z; // Cast a ray upwards to see if we can move the player out of the way. trace_t trace; UTIL_TraceEntity( pPlayer, pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin() + Vector( 0, 0, params.m_flRadius*2 ), MASK_SOLID, &trace ); pPlayer->SetLocalOrigin( trace.endpos ); } // Apply the mod. engine->ApplyTerrainMod( type, params ); // Move players back down. for( i=0; i < nPlayers; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i+1 ); if( !pPlayer ) continue; // Cast a ray upwards to see if we can move the player out of the way. trace_t trace; UTIL_TraceEntity( pPlayer, pPlayer->GetAbsOrigin(), Vector( pPlayer->GetAbsOrigin().x, pPlayer->GetAbsOrigin().y, playerStartHeights[i] ), MASK_SOLID, &trace ); pPlayer->SetLocalOrigin( trace.endpos ); } }
static void RestoreEntityTo( CBaseEntity *pEntity, const Vector &vWantedPos ) { int nMask = pEntity->IsPlayer() ? MASK_PLAYERSOLID : MASK_NPCSOLID; int nCollisionGroup = pEntity->IsPlayer() ? COLLISION_GROUP_PLAYER_MOVEMENT : COLLISION_GROUP_NPC; // Try to move to the wanted position from our current position. trace_t tr; VPROF_BUDGET( "RestorePlayerTo", "CTFLagCompensationManager" ); UTIL_TraceEntity( pEntity, vWantedPos, vWantedPos, nMask, pEntity, nCollisionGroup, &tr ); if ( tr.startsolid || tr.allsolid ) { if ( sv_unlag_debug.GetBool() ) { CBasePlayer *pPlayer = ToBasePlayer( pEntity ); if ( pPlayer ) { DevMsg( "RestorePlayerTo() could not restore player position for client \"%s\" ( %.1f %.1f %.1f )\n", pPlayer->GetPlayerName(), vWantedPos.x, vWantedPos.y, vWantedPos.z ); } else { DevMsg( "RestoreEntityTo() could not restore entity position for %s ( %.1f %.1f %.1f )\n", pEntity->GetClassname(), vWantedPos.x, vWantedPos.y, vWantedPos.z ); } } UTIL_TraceEntity( pEntity, pEntity->GetLocalOrigin(), vWantedPos, nMask, pEntity, nCollisionGroup, &tr ); if ( tr.startsolid || tr.allsolid ) { // In this case, the guy got stuck back wherever we lag compensated him to. Nasty. if ( sv_unlag_debug.GetBool() ) DevMsg( " restore failed entirely\n" ); } else { // We can get to a valid place, but not all the way back to where we were. Vector vPos; VectorLerp( pEntity->GetLocalOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos ); UTIL_SetOrigin( pEntity, vPos, true ); if ( sv_unlag_debug.GetBool() ) DevMsg( " restore got most of the way\n" ); } } else { // Cool, the player can go back to whence he came. UTIL_SetOrigin( pEntity, tr.endpos, true ); } }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ Vector CAI_BasePhysicsFlyingBot::VelocityToAvoidObstacles(float flInterval) { // -------------------------------- // Avoid banging into stuff // -------------------------------- trace_t tr; Vector vTravelDir = m_vCurrentVelocity*flInterval; Vector endPos = GetAbsOrigin() + vTravelDir; UTIL_TraceEntity( this, GetAbsOrigin(), endPos, MASK_NPCSOLID|CONTENTS_WATER, &tr); if (tr.fraction != 1.0) { // Bounce off in normal Vector vBounce = tr.plane.normal * 0.5 * m_vCurrentVelocity.Length(); return (vBounce); } // -------------------------------- // Try to remain above the ground. // -------------------------------- float flMinGroundDist = MinGroundDist(); UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -flMinGroundDist), MASK_NPCSOLID_BRUSHONLY|CONTENTS_WATER, BaseEntity(), COLLISION_GROUP_NONE, &tr); if (tr.fraction < 1) { // Clamp veloctiy if (tr.fraction < 0.1) { tr.fraction = 0.1; } return Vector(0, 0, 50/tr.fraction); } return vec3_origin; }
void CASW_Drone_Movement::FinishGravity( void ) { /* float ent_gravity; if ( m_pNPC->GetGravity() ) ent_gravity = m_pNPC->GetGravity(); else ent_gravity = 1.0; ent_gravity = 3.0; // Get the correct velocity for the end of the dt mv->m_vecVelocity[2] -= (ent_gravity * sv_gravity.GetFloat() * m_flInterval * 0.5); */ // push the drone down by gravity Vector dest = mv->GetAbsOrigin(); dest[2] = mv->GetAbsOrigin()[2] + mv->m_vecVelocity.z * m_flInterval; trace_t pm; UTIL_TraceEntity( m_pNPC, mv->GetAbsOrigin(), dest, MASK_NPCSOLID, &pm ); if (!pm.startsolid && !pm.allsolid) { dest[2] = mv->GetAbsOrigin()[2] + mv->m_vecVelocity.z * m_flInterval * pm.fraction; mv->SetAbsOrigin( dest ); } }
// Overridden for Gargantua because his swing starts lower as // a percentage of his height (otherwise he swings over the // players head) //========================================================= CBaseEntity* CNPC_Gargantua::GargantuaCheckTraceHullAttack(float flDist, int iDamage, int iDmgType) { trace_t tr; Vector vForward, vUp; AngleVectors( GetAbsAngles(), &vForward, NULL, &vUp ); Vector vecStart = GetAbsOrigin(); vecStart.z += 64; Vector vecEnd = vecStart + ( vForward * flDist) - ( vUp * flDist * 0.3); //UTIL_TraceHull( vecStart, vecEnd, dont_ignore_monsters, head_hull, ENT(pev), &tr ); UTIL_TraceEntity( this, GetAbsOrigin(), vecEnd, MASK_SOLID, &tr ); if ( tr.m_pEnt ) { CBaseEntity *pEntity = tr.m_pEnt; if ( iDamage > 0 ) { CTakeDamageInfo info( this, this, iDamage, iDmgType ); CalculateMeleeDamageForce( &info, vForward, tr.endpos ); pEntity->TakeDamage( info ); } return pEntity; } return NULL; }
void CSatchelCharge::SatchelThink( void ) { // If attached resize so player can pick up off wall if (m_bIsAttached) { UTIL_SetSize(this, Vector( -2, -2, -6), Vector(2, 2, 6)); } // See if I can lose my owner (has dropper moved out of way?) // Want do this so owner can shoot the satchel charge if (GetOwnerEntity()) { trace_t tr; Vector vUpABit = GetAbsOrigin(); vUpABit.z += 5.0; CBaseEntity* saveOwner = GetOwnerEntity(); SetOwnerEntity( NULL ); UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); if ( tr.startsolid || tr.fraction != 1.0 ) { SetOwnerEntity( saveOwner ); } } // Bounce movement code gets this think stuck occasionally so check if I've // succeeded in moving, otherwise kill my motions. else if ((GetAbsOrigin() - m_vLastPosition).LengthSqr()<1) { SetAbsVelocity( vec3_origin ); QAngle angVel = GetLocalAngularVelocity(); angVel.y = 0; SetLocalAngularVelocity( angVel ); // Clear think function SetThink(NULL); return; } m_vLastPosition= GetAbsOrigin(); StudioFrameAdvance( ); SetNextThink( gpGlobals->curtime + 0.1f ); if (!IsInWorld()) { UTIL_Remove( this ); return; } // Is it attached to a wall? if (m_bIsAttached) { return; } }
void CTripmineGrenade::BeamBreakThink( void ) { // See if I can go solid yet (has dropper moved out of way?) if (IsSolidFlagSet( FSOLID_NOT_SOLID )) { trace_t tr; Vector vUpBit = GetAbsOrigin(); vUpBit.z += 5.0; UTIL_TraceEntity( this, GetAbsOrigin(), vUpBit, MASK_SHOT, &tr ); if ( !tr.startsolid && (tr.fraction == 1.0) ) { RemoveSolidFlags( FSOLID_NOT_SOLID ); } } trace_t tr; // NOT MASK_SHOT because we want only simple hit boxes UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); // ALERT( at_console, "%f : %f\n", tr.flFraction, m_flBeamLength ); // respawn detect. if ( !m_pBeam ) { MakeBeam( ); if ( tr.m_pEnt ) m_hOwner = tr.m_pEnt; // reset owner too } CBaseEntity *pEntity = tr.m_pEnt; CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); bool bAttachMoved = false; if ( m_bAttached && m_hAttachEntity.Get() != NULL ) { if ( m_hAttachEntity.Get()->GetAbsOrigin() != m_vAttachedPosition ) bAttachMoved = true; } // Also blow up if the attached entity goes away, ie: a crate if (pBCC || fabs( m_flBeamLength - tr.fraction ) > 0.001 || ( m_bAttached && m_hAttachEntity.Get() == NULL) || bAttachMoved ) { m_iHealth = 0; if (m_pConstraint) m_pConstraint->Deactivate(); Event_Killed( CTakeDamageInfo( (CBaseEntity*)m_hOwner, this, 100, GIB_NORMAL ) ); return; } SetNextThink( gpGlobals->curtime + 0.05f ); }
//========================================================= // RunTask //========================================================= void CNPC_HAssassin::RunTask ( const Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_ASSASSIN_FALL_TO_GROUND: GetMotor()->SetIdealYawAndUpdate( GetEnemyLKP() ); if ( IsSequenceFinished() ) { if ( GetAbsVelocity().z > 0) { SetActivity( ACT_ASSASSIN_FLY_UP ); } else if ( HasCondition ( COND_SEE_ENEMY )) { SetActivity( ACT_ASSASSIN_FLY_ATTACK ); SetCycle( 0 ); } else { SetActivity( ACT_ASSASSIN_FLY_DOWN ); SetCycle( 0 ); } ResetSequenceInfo( ); } if ( GetFlags() & FL_ONGROUND) { TaskComplete( ); } else if( gpGlobals->curtime > m_flWaitFinished || GetAbsVelocity().z == 0.0 ) { // I've waited two seconds and haven't hit the ground. Try to force it. trace_t trace; UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 1 ), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &trace ); if( trace.DidHitWorld() ) { SetGroundEntity( trace.m_pEnt ); } else { // Try again in a couple of seconds. m_flWaitFinished = gpGlobals->curtime + 2.0f; } } break; default: BaseClass::RunTask ( pTask ); break; } }
void CTripwireGrenade::RopeBreakThink( void ) { // See if I can go solid yet (has dropper moved out of way?) if (IsSolidFlagSet(FSOLID_NOT_SOLID)) { trace_t tr; Vector vUpBit = GetAbsOrigin(); vUpBit.z += 5.0; UTIL_TraceEntity( this, GetAbsOrigin(), vUpBit, MASK_SHOT, &tr ); if ( !tr.startsolid && (tr.fraction == 1.0) ) { RemoveSolidFlags( FSOLID_NOT_SOLID ); } } // Check if rope had gotten beyond it's max length float flRopeLength = (GetAbsOrigin()-m_pHook->GetAbsOrigin()).Length(); if (flRopeLength > TGRENADE_MAX_ROPE_LEN) { // Shoot missiles at hook m_iHealth = 0; BreakRope(); m_vTargetPos = m_pHook->GetAbsOrigin(); CrossProduct ( m_vecDir, Vector(0,0,1), m_vTargetOffset ); m_vTargetOffset *=TGRENADE_MISSILE_OFFSET; SetThink(FireThink); FireThink(); } // Check to see if can see hook // NOT MASK_SHOT because we want only simple hit boxes trace_t tr; UTIL_TraceLine( GetAbsOrigin(), m_pHook->GetAbsOrigin(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); // If can't see hook CBaseEntity *pEntity = tr.m_pEnt; if (tr.fraction != 1.0 && pEntity != m_pHook) { // Shoot missiles at place where rope was intersected m_iHealth = 0; BreakRope(); m_vTargetPos = tr.endpos; CrossProduct ( m_vecDir, Vector(0,0,1), m_vTargetOffset ); m_vTargetOffset *=TGRENADE_MISSILE_OFFSET; SetThink(FireThink); FireThink(); return; } SetNextThink( gpGlobals->curtime + 0.1f ); }
static void RestoreEntityTo( CAI_BaseNPC *pEntity, const Vector &vWantedPos ) { // Try to move to the wanted position from our current position. trace_t tr; VPROF_BUDGET( "RestoreEntityTo", "CLagCompensationManager" ); UTIL_TraceEntity( pEntity, vWantedPos, vWantedPos, MASK_NPCSOLID, pEntity, COLLISION_GROUP_NPC, &tr ); if ( tr.startsolid || tr.allsolid ) { if ( sv_unlag_debug.GetBool() ) { DevMsg( "RestorepEntityTo() could not restore entity position for %s ( %.1f %.1f %.1f )\n", pEntity->GetClassname(), vWantedPos.x, vWantedPos.y, vWantedPos.z ); } UTIL_TraceEntity( pEntity, pEntity->GetLocalOrigin(), vWantedPos, MASK_NPCSOLID, pEntity, COLLISION_GROUP_NPC, &tr ); if ( tr.startsolid || tr.allsolid ) { // In this case, the guy got stuck back wherever we lag compensated him to. Nasty. if ( sv_unlag_debug.GetBool() ) DevMsg( " restore failed entirely\n" ); } else { // We can get to a valid place, but not all the way back to where we were. Vector vPos; VectorLerp( pEntity->GetLocalOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos ); UTIL_SetOrigin( pEntity, vPos, true ); if ( sv_unlag_debug.GetBool() ) DevMsg( " restore got most of the way\n" ); } } else { // Cool, the entity can go back to whence he came. UTIL_SetOrigin( pEntity, tr.endpos, true ); } }
void CTripmineGrenade::BeamBreakThink( void ) { // See if I can go solid yet (has dropper moved out of way?) if (IsSolidFlagSet( FSOLID_NOT_SOLID )) { trace_t tr; Vector vUpBit = GetAbsOrigin(); vUpBit.z += 5.0; UTIL_TraceEntity( this, GetAbsOrigin(), vUpBit, MASK_SHOT, &tr ); if ( !tr.startsolid && (tr.fraction == 1.0) ) { RemoveSolidFlags( FSOLID_NOT_SOLID ); } } trace_t tr; // NOT MASK_SHOT because we want only simple hit boxes UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); // ALERT( at_console, "%f : %f\n", tr.flFraction, m_flBeamLength ); // respawn detect. if ( !m_pBeam ) { MakeBeam( ); if ( tr.m_pEnt ) m_hOwner = tr.m_pEnt; // reset owner too } CBaseEntity *pEntity = tr.m_pEnt; CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); if (pBCC && pBCC->GetTeamNumber() != m_nTeam && pBCC->m_floatCloakFactor < 1.0f) //if (pBCC || fabs( m_flBeamLength - tr.fraction ) > 0.001) { m_iHealth = 0; Event_Killed( CTakeDamageInfo( (CBaseEntity*)m_hOwner, this, 100, GIB_NORMAL ) ); return; } SetNextThink( gpGlobals->curtime + 0.05f ); }
//========================================================= // Spawn //========================================================= void CGenericNPC::Spawn() { Precache(); SetModel( STRING( GetModelName() ) ); /* if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) ) UTIL_SetSize(this, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); else UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); */ if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) || FStrEq( STRING( GetModelName() ), "models/holo.mdl" ) ) UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); else UTIL_SetSize(this, NAI_Hull::Mins(HULL_HUMAN), NAI_Hull::Maxs(HULL_HUMAN)); SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_NOT_STANDABLE ); SetMoveType( MOVETYPE_STEP ); m_bloodColor = BLOOD_COLOR_RED; m_iHealth = 8; m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) m_NPCState = NPC_STATE_NONE; CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS ); NPCInit(); if ( !HasSpawnFlags(SF_GENERICNPC_NOTSOLID) ) { trace_t tr; UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), MASK_SOLID, &tr ); if ( tr.startsolid ) { Msg("Placed npc_generic in solid!!! (%s)\n", STRING(GetModelName()) ); m_spawnflags |= SF_GENERICNPC_NOTSOLID; } } if ( HasSpawnFlags(SF_GENERICNPC_NOTSOLID) ) { AddSolidFlags( FSOLID_NOT_SOLID ); m_takedamage = DAMAGE_NO; VPhysicsDestroyObject(); } }
bool CASW_Parasite::HasHeadroom() { trace_t tr; UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, 1 ), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); #if 0 if( tr.fraction == 1.0f ) { Msg("Headroom\n"); } else { Msg("NO Headroom\n"); } #endif return (tr.fraction == 1.0); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CAI_RappelBehavior::BeginRappel() { // Send the message to begin rappeling! SetCondition( COND_BEGIN_RAPPEL ); m_vecRopeAnchor = GetOuter()->GetAbsOrigin(); trace_t tr; UTIL_TraceEntity( GetOuter(), GetAbsOrigin(), GetAbsOrigin()-Vector(0,0,4096), MASK_SHOT, GetOuter(), COLLISION_GROUP_NONE, &tr ); if( tr.m_pEnt != NULL && tr.m_pEnt->IsNPC() ) { Vector forward; GetOuter()->GetVectors( &forward, NULL, NULL ); CSoundEnt::InsertSound( SOUND_DANGER, tr.m_pEnt->EarPosition() - forward * 12.0f, 32, 0.2f, GetOuter() ); } }
//------------------------------------------------------------------------------ // Searches along the direction ray in steps of "step" to see if // the entity position is passible. // Used for putting the player in valid space when toggling off noclip mode. //------------------------------------------------------------------------------ int FindPassableSpace( CBaseEntity *pPlayer, const Vector& direction, float step, Vector& oldorigin ) { int i; for ( i = 0; i < 100; i++ ) { Vector origin = VFuncs::GetAbsOrigin(pPlayer); VectorMA( origin, step, direction, origin ); VFuncs::SetAbsOrigin(pPlayer, origin ); trace_t trace; UTIL_TraceEntity( pPlayer, VFuncs::GetAbsOrigin(pPlayer), VFuncs::GetAbsOrigin(pPlayer), MASK_PLAYERSOLID, &trace ); if ( trace.startsolid == 0) { VectorCopy( VFuncs::GetAbsOrigin(pPlayer), oldorigin ); return 1; } } return 0; }
void CASW_Drone_Movement::WalkMove() { // Add in any base velocity to the current velocity. VectorAdd (mv->m_vecVelocity, m_pNPC->GetBaseVelocity(), mv->m_vecVelocity ); // if we're barely moving, then zero the velocity and stop float spd = VectorLength( mv->m_vecVelocity ); if ( spd < 1.0f || m_flInterval <= 0) { mv->m_vecVelocity.Init(); // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) VectorSubtract( mv->m_vecVelocity, m_pNPC->GetBaseVelocity(), mv->m_vecVelocity ); return; } // first try just moving to the destination Vector dest; dest[0] = mv->GetAbsOrigin()[0] + mv->m_vecVelocity[0]*m_flInterval; dest[1] = mv->GetAbsOrigin()[1] + mv->m_vecVelocity[1]*m_flInterval; dest[2] = mv->GetAbsOrigin()[2]; trace_t pm; UTIL_TraceEntity( m_pNPC, mv->GetAbsOrigin(), dest, MASK_NPCSOLID, &pm ); //TraceBBox( mv->GetAbsOrigin(), dest, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), pm ); // if we made it all the way there, then set that as our new origin and return if ( pm.fraction == 1 ) { mv->SetAbsOrigin( pm.endpos ); m_pNPC->PhysicsTouchTriggers(); // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) VectorSubtract( mv->m_vecVelocity, m_pNPC->GetBaseVelocity(), mv->m_vecVelocity ); return; } // if NPC started the move on the ground, then try to move up/down steps if ( m_pNPC->GetGroundEntity() != NULL ) { StepMove( dest, pm ); } // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) VectorSubtract( mv->m_vecVelocity, m_pNPC->GetBaseVelocity(), mv->m_vecVelocity ); }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void CGrenade_Molotov::MolotovThink( void ) { // See if I can lose my owner (has dropper moved out of way?) // Want do this so owner can throw the brickbat if (GetOwnerEntity()) { trace_t tr; Vector vUpABit = GetAbsOrigin(); vUpABit.z += 5.0; CBaseEntity* saveOwner = GetOwnerEntity(); SetOwnerEntity( NULL ); UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); if ( tr.startsolid || tr.fraction != 1.0 ) { SetOwnerEntity( saveOwner ); } } SetNextThink( gpGlobals->curtime + 0.1f ); }
void CPlayerPickupController::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if ( ToBasePlayer(pActivator) == m_pPlayer ) { CBaseEntity *pAttached = m_grabController.GetAttached(); if ( !pAttached || useType == USE_OFF || m_grabController.ComputeError() > 12 || (m_pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2)) ) { Shutdown(); return; } else if ( useType == USE_SET ) { // update position matrix3x4_t tmp; ComputePlayerMatrix( tmp ); Vector position; QAngle angles; VectorTransform( m_positionPlayerSpace, tmp, position ); angles = TransformAnglesToWorldSpace( m_anglesPlayerSpace, tmp ); CheckObjectPosition( position, angles, pAttached->GetAbsOrigin() ); // check to see if object is still sitting on something trace_t tr; Vector down = Vector( 0, 0, -6 ); UTIL_TraceEntity( pAttached, position, position + down, MASK_SOLID, &tr ); // if trace made it then there's nothing left to sit on, break the tie if ( tr.fraction == 1 ) { Shutdown(); return; } else { m_grabController.SetTargetPosition( position, angles ); } } } }
//----------------------------------------------------------------------------- // Purpose: Check that the selected position is buildable //----------------------------------------------------------------------------- bool CBaseObject::IsPlacementPosValid( void ) { bool bValid = CalculatePlacementPos(); if ( !bValid ) { return false; } CTFPlayer *pPlayer = GetOwner(); if ( !pPlayer ) { return false; } #ifndef CLIENT_DLL if ( !EstimateValidBuildPos() ) return false; #endif // Verify that the entire object can fit here // Important! here we want to collide with players and other buildings, but not dropped weapons trace_t tr; UTIL_TraceEntity( this, m_vecBuildOrigin, m_vecBuildOrigin, MASK_SOLID, NULL, COLLISION_GROUP_PLAYER, &tr ); if ( tr.fraction < 1.0f ) return false; // Make sure we can see the final position UTIL_TraceLine( pPlayer->EyePosition(), m_vecBuildOrigin + Vector(0,0,m_vecBuildMaxs[2] * 0.5), MASK_PLAYERSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction < 1.0 ) { return false; } return true; }
//----------------------------------------------------------------------------- // trace line rules //----------------------------------------------------------------------------- float CGameRules::WeaponTraceEntity( CBaseEntity *pEntity, const Vector &vecStart, const Vector &vecEnd, unsigned int mask, trace_t *ptr ) { UTIL_TraceEntity( pEntity, vecStart, vecEnd, mask, ptr ); return 1.0f; }
int CASW_Drone_Movement::TryMove( Vector *pFirstDest, trace_t *pFirstTrace ) { int bumpcount, numbumps; Vector dir; float d; int numplanes; Vector planes[MAX_CLIP_PLANES]; Vector primal_velocity, original_velocity; Vector new_velocity; int i, j; trace_t pm; Vector end; float time_left, allFraction; int blocked; numbumps = 4; // Bump up to four times blocked = 0; // Assume not blocked numplanes = 0; // and not sliding along any planes VectorCopy (mv->m_vecVelocity, original_velocity); // Store original velocity VectorCopy (mv->m_vecVelocity, primal_velocity); allFraction = 0; time_left = m_flInterval; // Total time for this movement operation. new_velocity.Init(); // set the last wall normal z high, so any planes found are 'more upright' m_LastHitWallNormal.z = 2.0f; for (bumpcount=0 ; bumpcount < numbumps; bumpcount++) { if ( mv->m_vecVelocity.Length() == 0.0 ) break; // Assume we can move all the way from the current origin to the // end point. VectorMA( mv->GetAbsOrigin(), time_left, mv->m_vecVelocity, end ); // See if we can make it from origin to end point. if ( g_bMovementOptimizations ) { // If their velocity Z is 0, then we can avoid an extra trace here during WalkMove. if ( pFirstDest && end == *pFirstDest ) pm = *pFirstTrace; else UTIL_TraceEntity( m_pNPC, mv->GetAbsOrigin(), end, MASK_NPCSOLID, &pm ); //TraceBBox( mv->GetAbsOrigin(), end, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), pm ); } else { UTIL_TraceEntity( m_pNPC, mv->GetAbsOrigin(), end, MASK_NPCSOLID, &pm ); //TraceBBox( mv->GetAbsOrigin(), end, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), pm ); } allFraction += pm.fraction; // If we started in a solid object, or we were in solid space // the whole way, zero out our velocity and return that we // are blocked by floor and wall. if (pm.allsolid) { // entity is trapped in another solid VectorCopy (vec3_origin, mv->m_vecVelocity); return 4; } if (pm.fraction < 1.0f) // we've hit something, store the most wall-ish normal { // store the most upright plane if (m_LastHitWallNormal.z > pm.plane.normal.z) VectorCopy(pm.plane.normal, m_LastHitWallNormal); } // If we moved some portion of the total distance, then // copy the end position into the pmove.origin and // zero the plane counter. if( pm.fraction > 0 ) { // actually covered some distance mv->SetAbsOrigin(pm.endpos); VectorCopy (mv->m_vecVelocity, original_velocity); numplanes = 0; } // If we covered the entire distance, we are done // and can return. if (pm.fraction == 1) { break; // moved the entire distance } // Save entity that blocked us (since fraction was < 1.0) // for contact // Add it if it's not already in the list!!! //MoveHelper( )->AddToTouched( pm, mv->m_vecVelocity ); // If the plane we hit has a high z component in the normal, then // it's probably a floor if (pm.plane.normal[2] > 0.7) { blocked |= 1; // floor } // If the plane has a zero z component in the normal, then it's a // step or wall if (!pm.plane.normal[2]) { blocked |= 2; // step / wall } // Reduce amount of m_flFrameTime left by total time left * fraction // that we covered. time_left -= time_left * pm.fraction; // Did we run out of planes to clip against? if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen // Stop our movement if so. VectorCopy (vec3_origin, mv->m_vecVelocity); //Con_DPrintf("Too many planes 4\n"); break; } // Set up next clipping plane VectorCopy (pm.plane.normal, planes[numplanes]); numplanes++; // modify original_velocity so it parallels all of the clip planes // // relfect npc velocity // Only give this a try for first impact plane because you can get yourself stuck in an acute corner by jumping in place // and pressing forward and nobody was really using this bounce/reflection feature anyway... if ( numplanes == 1 && m_pNPC->GetMoveType() == MOVETYPE_WALK && m_pNPC->GetGroundEntity() == NULL ) { for ( i = 0; i < numplanes; i++ ) { if ( planes[i][2] > 0.7 ) { // floor or slope ClipVelocity( original_velocity, planes[i], new_velocity, 1 ); VectorCopy( new_velocity, original_velocity ); } else { ClipVelocity( original_velocity, planes[i], new_velocity, 1.0 + sv_bounce.GetFloat() * (1 - m_surfaceFriction) ); } } VectorCopy( new_velocity, mv->m_vecVelocity ); VectorCopy( new_velocity, original_velocity ); } else { for (i=0 ; i < numplanes ; i++) { ClipVelocity ( original_velocity, planes[i], mv->m_vecVelocity, 1); for (j=0 ; j<numplanes ; j++) if (j != i) { // Are we now moving against this plane? if (mv->m_vecVelocity.Dot(planes[j]) < 0) break; // not ok } if (j == numplanes) // Didn't have to clip, so we're ok break; } // Did we go all the way through plane set if (i != numplanes) { // go along this plane // pmove.velocity is set in clipping call, no need to set again. ; } else { // go along the crease if (numplanes != 2) { VectorCopy (vec3_origin, mv->m_vecVelocity); break; } CrossProduct (planes[0], planes[1], dir); d = dir.Dot(mv->m_vecVelocity); VectorScale (dir, d, mv->m_vecVelocity ); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // d = mv->m_vecVelocity.Dot(primal_velocity); if (d <= 0) { //Con_DPrintf("Back\n"); VectorCopy (vec3_origin, mv->m_vecVelocity); break; } } } if ( allFraction == 0 ) { VectorCopy (vec3_origin, mv->m_vecVelocity); } return blocked; }
//----------------------------------------------------------------------------- // Purpose: Does the basic move attempting to climb up step heights. It uses // the mv->m_vecAbsOrigin and mv->m_vecVelocity. It returns a new // new mv->m_vecAbsOrigin, mv->m_vecVelocity, and mv->m_outStepHeight. //----------------------------------------------------------------------------- void CASW_Drone_Movement::StepMove( Vector &vecDestination, trace_t &trace ) { // CheckStuck(); Vector vecEndPos; VectorCopy( vecDestination, vecEndPos ); // Try sliding forward both on ground and up 16 pixels // take the move that goes farthest Vector vecPos, vecVel; VectorCopy( mv->GetAbsOrigin(), vecPos ); VectorCopy( mv->m_vecVelocity, vecVel ); // Slide move down. Vector downWallNormal; TryMove( &vecEndPos, &trace ); downWallNormal = m_LastHitWallNormal; // Down results. Vector vecDownPos, vecDownVel; VectorCopy( mv->GetAbsOrigin(), vecDownPos ); VectorCopy( mv->m_vecVelocity, vecDownVel ); // Reset original values. mv->SetAbsOrigin( vecPos ); VectorCopy( vecVel, mv->m_vecVelocity ); // Move up a stair height. VectorCopy( mv->GetAbsOrigin(), vecEndPos ); vecEndPos.z += STEP_SIZE; UTIL_TraceEntity( m_pNPC, mv->GetAbsOrigin(), vecEndPos, MASK_NPCSOLID, &trace ); //TraceBBox( mv->GetAbsOrigin(), vecEndPos, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), trace ); if ( !trace.startsolid && !trace.allsolid ) { mv->SetAbsOrigin( trace.endpos ); } // Slide move up. Vector upWallNormal; TryMove(NULL, NULL); upWallNormal = m_LastHitWallNormal; // Move down a stair (attempt to). VectorCopy( mv->GetAbsOrigin(), vecEndPos ); vecEndPos.z -= STEP_SIZE; UTIL_TraceEntity( m_pNPC, mv->GetAbsOrigin(), vecEndPos, MASK_NPCSOLID, &trace ); //TraceBBox( mv->GetAbsOrigin(), vecEndPos, MASK_NPCSOLID, m_pNPC->GetCollisionGroup(), trace ); // If we are not on the ground any more then use the original movement attempt. if ( trace.plane.normal[2] < 0.7 ) { mv->SetAbsOrigin( vecDownPos ); VectorCopy( vecDownVel, mv->m_vecVelocity ); VectorCopy( downWallNormal, m_LastHitWallNormal ); float flStepDist = mv->GetAbsOrigin().z - vecPos.z; if ( flStepDist > 0.0f ) { mv->m_outStepHeight += flStepDist; } return; } // If the trace ended up in empty space, copy the end over to the origin. if ( !trace.startsolid && !trace.allsolid ) { mv->SetAbsOrigin( trace.endpos ); } // Copy this origin to up. Vector vecUpPos; VectorCopy( mv->GetAbsOrigin(), vecUpPos ); VectorCopy( upWallNormal, m_LastHitWallNormal); // decide which one went farther float flDownDist = ( vecDownPos.x - vecPos.x ) * ( vecDownPos.x - vecPos.x ) + ( vecDownPos.y - vecPos.y ) * ( vecDownPos.y - vecPos.y ); float flUpDist = ( vecUpPos.x - vecPos.x ) * ( vecUpPos.x - vecPos.x ) + ( vecUpPos.y - vecPos.y ) * ( vecUpPos.y - vecPos.y ); if ( flDownDist > flUpDist ) { mv->SetAbsOrigin( vecDownPos ); VectorCopy( vecDownVel, mv->m_vecVelocity ); VectorCopy( downWallNormal, m_LastHitWallNormal); } else { // copy z value from slide move mv->m_vecVelocity.z = vecDownVel.z; } float flStepDist = mv->GetAbsOrigin().z - vecPos.z; if ( flStepDist > 0 ) { mv->m_outStepHeight += flStepDist; } }
void CLagCompensationManager::BacktrackEntity( CAI_BaseNPC *pEntity, float flTargetTime ) { Vector org, mins, maxs; QAngle ang; VPROF_BUDGET( "BacktrackEntity", "CLagCompensationManager" ); // get track history of this entity int index = pEntity->GetAIIndex(); CUtlFixedLinkedList< LagRecord > *track = &m_EntityTrack[ index ]; // check if we have at leat one entry if ( track->Count() <= 0 ) return; int curr = track->Head(); LagRecord *prevRecord = NULL; LagRecord *record = NULL; Vector prevOrg = pEntity->GetLocalOrigin(); // Walk context looking for any invalidating event while( track->IsValidIndex(curr) ) { // remember last record prevRecord = record; // get next record record = &track->Element( curr ); if ( !(record->m_fFlags & LC_ALIVE) ) { // entity must be alive, lost track return; } Vector delta = record->m_vecOrigin - prevOrg; if ( delta.LengthSqr() > LAG_COMPENSATION_TELEPORTED_DISTANCE_SQR ) { // lost track, moved too far (may have teleported) return; } // did we find a context smaller than target time ? if ( record->m_flSimulationTime <= flTargetTime ) break; // hurra, stop prevOrg = record->m_vecOrigin; // go one step back in time curr = track->Next( curr ); } Assert( record ); if ( !record ) { if ( sv_unlag_debug.GetBool() ) { DevMsg( "No valid positions in history for BacktrackEntity ( %s )\n", pEntity->GetClassname() ); } return; // that should never happen } float frac = 0.0f; if ( prevRecord && (record->m_flSimulationTime < flTargetTime) && (record->m_flSimulationTime < prevRecord->m_flSimulationTime) ) { // we didn't find the exact time but have a valid previous record // so interpolate between these two records; Assert( prevRecord->m_flSimulationTime > record->m_flSimulationTime ); Assert( flTargetTime < prevRecord->m_flSimulationTime ); // calc fraction between both records frac = ( flTargetTime - record->m_flSimulationTime ) / ( prevRecord->m_flSimulationTime - record->m_flSimulationTime ); Assert( frac > 0 && frac < 1 ); // should never extrapolate ang = Lerp( frac, record->m_vecAngles, prevRecord->m_vecAngles ); org = Lerp( frac, record->m_vecOrigin, prevRecord->m_vecOrigin ); mins = Lerp( frac, record->m_vecMins, prevRecord->m_vecMins ); maxs = Lerp( frac, record->m_vecMaxs, prevRecord->m_vecMaxs ); } else { // we found the exact record or no other record to interpolate with // just copy these values since they are the best we have ang = record->m_vecAngles; org = record->m_vecOrigin; mins = record->m_vecMins; maxs = record->m_vecMaxs; } // See if this is still a valid position for us to teleport to if ( sv_unlag_fixstuck.GetBool() ) { // Try to move to the wanted position from our current position. trace_t tr; UTIL_TraceEntity( pEntity, org, org, MASK_NPCSOLID, &tr ); if ( tr.startsolid || tr.allsolid ) { if ( sv_unlag_debug.GetBool() ) DevMsg( "WARNING: BackupEntity trying to back entity into a bad position - %s\n", pEntity->GetClassname() ); CBasePlayer *pHitPlayer = dynamic_cast<CBasePlayer *>( tr.m_pEnt ); // don't lag compensate the current player if ( pHitPlayer && ( pHitPlayer != m_pCurrentPlayer ) ) { // If we haven't backtracked this player, do it now // this deliberately ignores WantsLagCompensationOnEntity. if ( !m_RestorePlayer.Get( pHitPlayer->entindex() - 1 ) ) { // prevent recursion - save a copy of m_RestorePlayer, // pretend that this player is off-limits int pl_index = pEntity->entindex() - 1; // Temp turn this flag on m_RestorePlayer.Set( pl_index ); BacktrackPlayer( pHitPlayer, flTargetTime ); // Remove the temp flag m_RestorePlayer.Clear( pl_index ); } } else { CAI_BaseNPC *pHitEntity = dynamic_cast<CAI_BaseNPC *>( tr.m_pEnt ); if ( pHitEntity ) { CAI_BaseNPC *pNPC = NULL; CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); int nAIs = g_AI_Manager.NumAIs(); for ( int i = 0; i < nAIs; i++ ) // we'll have to find this entity's index though :( { pNPC = ppAIs[i]; if ( pNPC == pHitEntity ) break; } // If we haven't backtracked this player, do it now // this deliberately ignores WantsLagCompensationOnEntity. if ( pNPC && !m_RestoreEntity.Get( pNPC->GetAIIndex() ) ) { // prevent recursion - save a copy of m_RestoreEntity, // pretend that this player is off-limits // Temp turn this flag on m_RestoreEntity.Set( pNPC->GetAIIndex() ); BacktrackEntity( pHitEntity, flTargetTime ); // Remove the temp flag m_RestoreEntity.Clear( pNPC->GetAIIndex() ); } } } // now trace us back as far as we can go UTIL_TraceEntity( pEntity, pEntity->GetLocalOrigin(), org, MASK_NPCSOLID, &tr ); if ( tr.startsolid || tr.allsolid ) { // Our starting position is bogus if ( sv_unlag_debug.GetBool() ) DevMsg( "Backtrack failed completely, bad starting position\n" ); } else { // We can get to a valid place, but not all the way to the target Vector vPos; VectorLerp( pEntity->GetLocalOrigin(), org, tr.fraction * g_flFractionScale, vPos ); // This is as close as we're going to get org = vPos; if ( sv_unlag_debug.GetBool() ) DevMsg( "Backtrack got most of the way\n" ); } } } // See if this represents a change for the entity int flags = 0; LagRecord *restore = &m_EntityRestoreData[ index ]; LagRecord *change = &m_EntityChangeData[ index ]; QAngle angdiff = pEntity->GetLocalAngles() - ang; Vector orgdiff = pEntity->GetLocalOrigin() - org; // Always remember the pristine simulation time in case we need to restore it. restore->m_flSimulationTime = pEntity->GetSimulationTime(); if ( angdiff.LengthSqr() > LAG_COMPENSATION_EPS_SQR ) { flags |= LC_ANGLES_CHANGED; restore->m_vecAngles = pEntity->GetLocalAngles(); pEntity->SetLocalAngles( ang ); change->m_vecAngles = ang; } // Use absolute equality here if ( ( mins != pEntity->WorldAlignMins() ) || ( maxs != pEntity->WorldAlignMaxs() ) ) { flags |= LC_SIZE_CHANGED; restore->m_vecMins = pEntity->WorldAlignMins() ; restore->m_vecMaxs = pEntity->WorldAlignMaxs(); pEntity->SetSize( mins, maxs ); change->m_vecMins = mins; change->m_vecMaxs = maxs; } // Note, do origin at end since it causes a relink into the k/d tree if ( orgdiff.LengthSqr() > LAG_COMPENSATION_EPS_SQR ) { flags |= LC_ORIGIN_CHANGED; restore->m_vecOrigin = pEntity->GetLocalOrigin(); pEntity->SetLocalOrigin( org ); change->m_vecOrigin = org; } // Sorry for the loss of the optimization for the case of people // standing still, but you breathe even on the server. // This is quicker than actually comparing all bazillion floats. flags |= LC_ANIMATION_CHANGED; restore->m_masterSequence = pEntity->GetSequence(); restore->m_masterCycle = pEntity->GetCycle(); bool interpolationAllowed = false; if( prevRecord && (record->m_masterSequence == prevRecord->m_masterSequence) ) { // If the master state changes, all layers will be invalid too, so don't interp (ya know, interp barely ever happens anyway) interpolationAllowed = true; } //////////////////////// // First do the master settings bool interpolatedMasters = false; if( frac > 0.0f && interpolationAllowed ) { interpolatedMasters = true; pEntity->SetSequence( Lerp( frac, record->m_masterSequence, prevRecord->m_masterSequence ) ); pEntity->SetCycle( Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle ) ); if( record->m_masterCycle > prevRecord->m_masterCycle ) { // the older record is higher in frame than the newer, it must have wrapped around from 1 back to 0 // add one to the newer so it is lerping from .9 to 1.1 instead of .9 to .1, for example. float newCycle = Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle + 1 ); pEntity->SetCycle(newCycle < 1 ? newCycle : newCycle - 1 );// and make sure .9 to 1.2 does not end up 1.05 } else { pEntity->SetCycle( Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle ) ); } } if( !interpolatedMasters ) { pEntity->SetSequence(record->m_masterSequence); pEntity->SetCycle(record->m_masterCycle); } //////////////////////// // Now do all the layers int layerCount = pEntity->GetNumAnimOverlays(); for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) { CAnimationLayer *currentLayer = pEntity->GetAnimOverlay(layerIndex); if( currentLayer ) { restore->m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle; restore->m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder; restore->m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence; restore->m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight; bool interpolated = false; if( (frac > 0.0f) && interpolationAllowed ) { LayerRecord &recordsLayerRecord = record->m_layerRecords[layerIndex]; LayerRecord &prevRecordsLayerRecord = prevRecord->m_layerRecords[layerIndex]; if( (recordsLayerRecord.m_order == prevRecordsLayerRecord.m_order) && (recordsLayerRecord.m_sequence == prevRecordsLayerRecord.m_sequence) ) { // We can't interpolate across a sequence or order change interpolated = true; if( recordsLayerRecord.m_cycle > prevRecordsLayerRecord.m_cycle ) { // the older record is higher in frame than the newer, it must have wrapped around from 1 back to 0 // add one to the newer so it is lerping from .9 to 1.1 instead of .9 to .1, for example. float newCycle = Lerp( frac, recordsLayerRecord.m_cycle, prevRecordsLayerRecord.m_cycle + 1 ); currentLayer->m_flCycle = newCycle < 1 ? newCycle : newCycle - 1;// and make sure .9 to 1.2 does not end up 1.05 } else { currentLayer->m_flCycle = Lerp( frac, recordsLayerRecord.m_cycle, prevRecordsLayerRecord.m_cycle ); } currentLayer->m_nOrder = recordsLayerRecord.m_order; currentLayer->m_nSequence = recordsLayerRecord.m_sequence; currentLayer->m_flWeight = Lerp( frac, recordsLayerRecord.m_weight, prevRecordsLayerRecord.m_weight ); } } if( !interpolated ) { //Either no interp, or interp failed. Just use record. currentLayer->m_flCycle = record->m_layerRecords[layerIndex].m_cycle; currentLayer->m_nOrder = record->m_layerRecords[layerIndex].m_order; currentLayer->m_nSequence = record->m_layerRecords[layerIndex].m_sequence; currentLayer->m_flWeight = record->m_layerRecords[layerIndex].m_weight; } } } if ( !flags ) return; // we didn't change anything if ( sv_lagflushbonecache.GetBool() ) pEntity->InvalidateBoneCache(); /*char text[256]; Q_snprintf( text, sizeof(text), "time %.2f", flTargetTime ); pEntity->DrawServerHitboxes( 10 ); NDebugOverlay::Text( org, text, false, 10 ); NDebugOverlay::EntityBounds( pEntity, 255, 0, 0, 32, 10 ); */ m_RestoreEntity.Set( index ); //remember that we changed this entity m_bNeedToRestore = true; // we changed at least one player / entity restore->m_fFlags = flags; // we need to restore these flags change->m_fFlags = flags; // we have changed these flags if( sv_showlagcompensation.GetInt() == 1 ) { pEntity->DrawServerHitboxes(4, true); } }
void CC4::PrimaryAttack() { bool PlaceBomb = false; CCSPlayer *pPlayer = GetPlayerOwner(); if ( !pPlayer ) return; int onGround = FBitSet( pPlayer->GetFlags(), FL_ONGROUND ); CBaseEntity *groundEntity = (onGround) ? pPlayer->GetGroundEntity() : NULL; if ( groundEntity ) { // Don't let us stand on players, breakables, or pushaway physics objects to plant if ( groundEntity->IsPlayer() || IsPushableEntity( groundEntity ) || #ifndef CLIENT_DLL IsBreakableEntity( groundEntity ) || #endif // !CLIENT_DLL IsPushAwayEntity( groundEntity ) ) { onGround = false; } } if( m_bStartedArming == false && m_bBombPlanted == false ) { if( pPlayer->m_bInBombZone && onGround ) { m_bStartedArming = true; m_fArmedTime = gpGlobals->curtime + WEAPON_C4_ARM_TIME; m_bBombPlacedAnimation = false; #if !defined( CLIENT_DLL ) // init the beep flags int i; for( i=0;i<NUM_BEEPS;i++ ) m_bPlayedArmingBeeps[i] = false; // freeze the player in place while planting pPlayer->SetMaxSpeed( 1 ); // player "arming bomb" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); pPlayer->SetNextAttack( gpGlobals->curtime ); IGameEvent * event = gameeventmanager->CreateEvent( "bomb_beginplant" ); if( event ) { event->SetInt("userid", pPlayer->GetUserID() ); event->SetInt("site", pPlayer->m_iBombSiteIndex ); event->SetInt( "priority", 8 ); gameeventmanager->FireEvent( event ); } #endif SendWeaponAnim( ACT_VM_PRIMARYATTACK ); FX_PlantBomb( pPlayer->entindex(), pPlayer->Weapon_ShootPosition() ); } else { if ( !pPlayer->m_bInBombZone ) { ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_At_Bomb_Spot"); } else { ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground"); } m_flNextPrimaryAttack = gpGlobals->curtime + 1.0; return; } } else { if ( !onGround || !pPlayer->m_bInBombZone ) { if( !pPlayer->m_bInBombZone ) { ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Arming_Cancelled" ); } else { ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground" ); } m_flNextPrimaryAttack = gpGlobals->curtime + 1.5; m_bStartedArming = false; #if !defined( CLIENT_DLL ) // release the player from being frozen, we've somehow left the bomb zone pPlayer->ResetMaxSpeed(); pPlayer->SetProgressBarTime( 0 ); //pPlayer->SetAnimation( PLAYER_HOLDBOMB ); IGameEvent * event = gameeventmanager->CreateEvent( "bomb_abortplant" ); if( event ) { event->SetInt("userid", pPlayer->GetUserID() ); event->SetInt("site", pPlayer->m_iBombSiteIndex ); event->SetInt( "priority", 8 ); gameeventmanager->FireEvent( event ); } #endif if(m_bBombPlacedAnimation == true) //this means the placement animation is canceled { SendWeaponAnim( ACT_VM_DRAW ); } else { SendWeaponAnim( ACT_VM_IDLE ); } return; } else { #ifndef CLIENT_DLL PlayArmingBeeps(); #endif if( gpGlobals->curtime >= m_fArmedTime ) //the c4 is ready to be armed { //check to make sure the player is still in the bomb target area PlaceBomb = true; } else if( ( gpGlobals->curtime >= (m_fArmedTime - 0.75) ) && ( !m_bBombPlacedAnimation ) ) { //call the c4 Placement animation m_bBombPlacedAnimation = true; SendWeaponAnim( ACT_VM_SECONDARYATTACK ); #if !defined( CLIENT_DLL ) // player "place" animation //pPlayer->SetAnimation( PLAYER_HOLDBOMB ); #endif } } } if ( PlaceBomb && m_bStartedArming ) { m_bStartedArming = false; m_fArmedTime = 0; if( pPlayer->m_bInBombZone ) { #if !defined( CLIENT_DLL ) CPlantedC4 *pC4 = CPlantedC4::ShootSatchelCharge( pPlayer, pPlayer->GetAbsOrigin(), pPlayer->GetAbsAngles() ); if ( pC4 ) { pC4->SetBombSiteIndex( pPlayer->m_iBombSiteIndex ); trace_t tr; UTIL_TraceEntity( pC4, GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,-200), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); pC4->SetAbsOrigin( tr.endpos ); CBombTarget *pBombTarget = (CBombTarget*)UTIL_EntityByIndex( pPlayer->m_iBombSiteIndex ); if ( pBombTarget ) { CBaseEntity *pAttachPoint = gEntList.FindEntityByName( NULL, pBombTarget->GetBombMountTarget() ); if ( pAttachPoint ) { pC4->SetAbsOrigin( pAttachPoint->GetAbsOrigin() ); pC4->SetAbsAngles( pAttachPoint->GetAbsAngles() ); pC4->SetParent( pAttachPoint ); } variant_t emptyVariant; pBombTarget->AcceptInput( "BombPlanted", pC4, pC4, emptyVariant, 0 ); } } IGameEvent * event = gameeventmanager->CreateEvent( "bomb_planted" ); if( event ) { event->SetInt("userid", pPlayer->GetUserID() ); event->SetInt("site", pPlayer->m_iBombSiteIndex ); event->SetInt("posx", pPlayer->GetAbsOrigin().x ); event->SetInt("posy", pPlayer->GetAbsOrigin().y ); event->SetInt( "priority", 8 ); gameeventmanager->FireEvent( event ); } // Fire a beep event also so the bots have a chance to hear the bomb event = gameeventmanager->CreateEvent( "bomb_beep" ); if ( event ) { event->SetInt( "entindex", entindex() ); gameeventmanager->FireEvent( event ); } pPlayer->SetProgressBarTime( 0 ); CSGameRules()->m_bBombDropped = false; CSGameRules()->m_bBombPlanted = true; // Play the plant sound. Vector plantPosition = pPlayer->GetAbsOrigin() + Vector( 0, 0, 5 ); CPASAttenuationFilter filter( plantPosition ); EmitSound( filter, entindex(), "c4.plant" ); // release the player from being frozen pPlayer->ResetMaxSpeed(); // No more c4! pPlayer->Weapon_Drop( this, NULL, NULL ); UTIL_Remove( this ); #endif //don't allow the planting to start over again next frame. m_bBombPlanted = true; return; } else { ClientPrint( pPlayer, HUD_PRINTCENTER, "#C4_Activated_At_Bomb_Spot" ); #if !defined( CLIENT_DLL ) //pPlayer->SetAnimation( PLAYER_HOLDBOMB ); // release the player from being frozen pPlayer->ResetMaxSpeed(); IGameEvent * event = gameeventmanager->CreateEvent( "bomb_abortplant" ); if( event ) { event->SetInt("userid", pPlayer->GetUserID() ); event->SetInt("site", pPlayer->m_iBombSiteIndex ); event->SetInt( "priority", 8 ); gameeventmanager->FireEvent( event ); } #endif m_flNextPrimaryAttack = gpGlobals->curtime + 1.0; return; } } m_flNextPrimaryAttack = gpGlobals->curtime + 0.3; SetWeaponIdleTime( gpGlobals->curtime + SharedRandomFloat("C4IdleTime", 10, 15 ) ); }
//----------------------------------------------------------------------------- // Purpose: // Input : *pTask - //----------------------------------------------------------------------------- void CNPC_Bug_Builder::StartTask( const Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_BBUG_GET_PATH_TO_FLEE: { // Always tell our bughole that we're under attack if ( m_hMyBugHole ) { m_hMyBugHole->IncomingFleeingBug( this ); } // If we have no squad, or we couldn't get a path to our squadmate, move to our bughole if ( m_hMyBugHole ) { SetTarget( m_hMyBugHole ); AI_NavGoal_t goal( GOALTYPE_TARGETENT, vec3_origin, ACT_RUN ); if ( GetNavigator()->SetGoal( goal ) ) { TaskComplete(); return; } } TaskComplete(); } break; case TASK_BBUG_GET_PATH_TO_BUGHOLE: { // Get a path back to my bughole // If we have no squad, or we couldn't get a path to our squadmate, look for a bughole if ( m_hMyBugHole ) { SetTarget( m_hMyBugHole ); AI_NavGoal_t goal( GOALTYPE_TARGETENT, vec3_origin, ACT_RUN ); if ( GetNavigator()->SetGoal( goal ) ) { TaskComplete(); return; } } TaskFail( "Couldn't get to bughole." ); } break; case TASK_BBUG_HOLE_REMOVE: { TaskComplete(); // Crawl inside the bughole and remove myself AddEffects( EF_NODRAW ); AddSolidFlags( FSOLID_NOT_SOLID ); Event_Killed( CTakeDamageInfo( this, this, 200, DMG_CRUSH ) ); // Tell the bughole if ( m_hMyBugHole ) { m_hMyBugHole->BugReturned(); } } break; case TASK_BBUG_GET_PATH_TO_DAWDLE: { // Get a dawdle point ahead of us Vector vecForward, vecTarget; AngleVectors( GetAbsAngles(), &vecForward ); VectorMA( GetAbsOrigin(), random->RandomFloat( DAWDLE_MIN_DIST, DAWDLE_MAX_DIST ), vecForward, vecTarget ); // See how far we could move ahead trace_t tr; UTIL_TraceEntity( this, GetAbsOrigin(), vecTarget, MASK_SOLID, &tr); float flDistance = tr.fraction * (vecTarget - GetAbsOrigin()).Length(); if ( flDistance >= DAWDLE_MIN_DIST ) { AI_NavGoal_t goal( tr.endpos ); GetNavigator()->SetGoal( goal ); } TaskComplete(); } break; case TASK_BBUG_FACE_DAWDLE: { // Turn a random amount to the right float flYaw = GetMotor()->GetIdealYaw(); flYaw = flYaw + random->RandomFloat( 45, 135 ); GetMotor()->SetIdealYaw( UTIL_AngleMod(flYaw) ); SetTurnActivity(); break; } break; default: BaseClass::StartTask( pTask ); break; } }
//SecobMod__Information On a player touching this, portalize them! //------------------------------------------------------------------------------ // A small wrapper around SV_Move that never clips against the supplied entity. //------------------------------------------------------------------------------ static bool TestEntityPosition ( CBaseEntity *pOther ) { trace_t trace; UTIL_TraceEntity( pOther, pOther->GetAbsOrigin(), pOther->GetAbsOrigin(), MASK_PLAYERSOLID, &trace ); return (trace.startsolid == 0); }
bool CNPC_Controller::OverrideMove( float flInterval ) { if (m_flGroundSpeed == 0) { m_flGroundSpeed = 100; } // ---------------------------------------------- // Select move target // ---------------------------------------------- CBaseEntity *pMoveTarget = NULL; if (GetTarget() != NULL ) { pMoveTarget = GetTarget(); } else if (GetEnemy() != NULL ) { pMoveTarget = GetEnemy(); } // ---------------------------------------------- // Select move target position // ---------------------------------------------- Vector vMoveTargetPos(0,0,0); if (GetTarget()) { vMoveTargetPos = GetTarget()->GetAbsOrigin(); } else if (GetEnemy() != NULL) { vMoveTargetPos = GetEnemy()->GetAbsOrigin(); } // ----------------------------------------- // See if we can fly there directly // ----------------------------------------- if (pMoveTarget /*|| HaveInspectTarget()*/) { trace_t tr; if (pMoveTarget) { UTIL_TraceEntity( this, GetAbsOrigin(), vMoveTargetPos, MASK_NPCSOLID_BRUSHONLY, pMoveTarget, GetCollisionGroup(), &tr); } else { UTIL_TraceEntity( this, GetAbsOrigin(), vMoveTargetPos, MASK_NPCSOLID_BRUSHONLY, &tr); } /* float fTargetDist = (1-tr.fraction)*(GetAbsOrigin() - vMoveTargetPos).Length(); if (fTargetDist > 50) { //SetCondition( COND_SCANNER_FLY_BLOCKED ); } else { //SetCondition( COND_SCANNER_FLY_CLEAR ); } */ } // ----------------------------------------------------------------- // If I have a route, keep it updated and move toward target // ------------------------------------------------------------------ if (GetNavigator()->IsGoalActive()) { if ( OverridePathMove( flInterval ) ) return true; } else { //do nothing Stop(); TaskComplete(); } return true; }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void CGrenade_Brickbat::BrickbatThink( void ) { // ----------------------------------------------------------- // Might be physically simulated so get my velocity manually // ----------------------------------------------------------- Vector vVelocity; AngularImpulse vAngVel; GetVelocity(&vVelocity,&vAngVel); // See if I can lose my owner (has dropper moved out of way?) // Want do this so owner can throw the brickbat if (GetOwnerEntity()) { trace_t tr; Vector vUpABit = GetAbsOrigin(); vUpABit.z += 5.0; CBaseEntity* saveOwner = GetOwnerEntity(); SetOwnerEntity( NULL ); UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); if ( tr.startsolid || tr.fraction != 1.0 ) { SetOwnerEntity( saveOwner ); } } // --------------------------------------------------------------- // Make sure we're not resting on a living thing's bounding box // --------------------------------------------------------------- if (vVelocity.Length() < 0.01) { trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction < 1.0 && tr.m_pEnt) { CBaseEntity *pEntity = tr.m_pEnt; if (pEntity->GetFlags() & (FL_CLIENT | FL_NPC)) { // -------------------- // Bounce me off // -------------------- Vector vNewVel; vNewVel.y = 100; vNewVel.x = random->RandomInt(-100,100); vNewVel.z = random->RandomInt(-100,100); // If physically simulated IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->AddVelocity( &vNewVel, &vAngVel ); } // Otherwise else { SetAbsVelocity( vNewVel ); } } } } if (vVelocity.Length() < 0.01) { SpawnBrickbatWeapon(); } SetNextThink( gpGlobals->curtime + 0.1f ); }