Vector CASW_Rocket::IntegrateRocketThrust( const Vector &vTargetDir, ///< direction of target float flDist ) ///< distance to target const { Vector vNewVelocity; const float flSimulateScale = IsSimulatingOnAlternateTicks() ? 2 : 1 ; // apply thrust in our desired direction Vector vecThrust = vTargetDir * ASW_ROCKET_ACCELERATION * flSimulateScale; if (asw_rocket_debug.GetInt() == 2) { Msg("vecThrust = %s\n", VecToString(vecThrust)); } vNewVelocity = GetAbsVelocity() + vecThrust; // apply drag float fDrag = ASW_ROCKET_DRAG - (0.1f * GetLifeFraction()); // increase drag as lifetime goes on (to help stop rockets spinning around their target) if (flDist < 300.0f && flDist > 0) fDrag -= (1.0f - (flDist / 300.0f)) * 0.1f; // reduce drag further as we get close vNewVelocity *= ASW_ROCKET_DRAG; // cap velocity to our min/max float speed = vNewVelocity.Length(); if ((speed > ASW_ROCKET_MAX_SPEED || speed < ASW_ROCKET_MIN_SPEED) && speed > 0) { vNewVelocity *= (ASW_ROCKET_MAX_SPEED / speed); } // thrust away from the ground if we get too low trace_t tr; UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, ROCKET_HOVER_HEIGHT ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0f ) { if ( vNewVelocity.z < 0 ) { vNewVelocity.z += tr.fraction * ASW_ROCKET_HOVER_THRUST; if ( asw_rocket_debug.GetBool() ) Msg( "Rocket[%d] hover thrusting %f vel.z is now %f\n", entindex(), tr.fraction * ASW_ROCKET_HOVER_THRUST, vNewVelocity.z ); if ( vNewVelocity.z > 0 ) { vNewVelocity.z = 0; } } } return vNewVelocity; }
//----------------------------------------------------------------------------- // Purpose: Draw any text overlays // Input : Previous text offset from the top // Output : Current text offset from the top //----------------------------------------------------------------------------- int CAI_LeadBehavior::DrawDebugTextOverlays( int text_offset ) { char tempstr[ 512 ]; int offset; offset = BaseClass::DrawDebugTextOverlays( text_offset ); if ( GetOuter()->m_debugOverlays & OVERLAY_TEXT_BIT ) { if ( HasGoal() ) { Q_snprintf( tempstr, sizeof(tempstr), "Goal: %s %s", m_args.pszGoal, VecToString( m_goal ) ); GetOuter()->EntityText( offset, tempstr, 0 ); offset++; } else { Q_snprintf( tempstr, sizeof(tempstr), "Goal: None" ); GetOuter()->EntityText( offset, tempstr, 0 ); offset++; } } return offset; }
CASW_Rocket * CASW_Rocket::Create( float fDamage, const Vector &vecOrigin, const QAngle &vecAngles, CBaseCombatCharacter *pentOwner /*= NULL */, CBaseEntity * pCreatorWeapon /*= NULL*/, const char *className /*= "asw_rocket" */ ) { CASW_Rocket *pMissile = (CASW_Rocket *) CBaseEntity::Create( className, vecOrigin, vecAngles, pentOwner ); pMissile->SetDamage( fDamage ); pMissile->ChangeFaction( pentOwner->GetFaction() ); pMissile->Activate(); if (asw_rocket_debug.GetBool()) { Msg("Rocket ang=%s\n", VecToString(vecAngles)); pMissile->m_debugOverlays |= OVERLAY_TEXT_BIT; } Vector vecForward; AngleVectors( vecAngles, &vecForward ); pMissile->SetAbsVelocity( vecForward * ASW_ROCKET_MIN_SPEED ); // + Vector( 0,0, 128 ) pMissile->m_hCreatorWeapon.Set( pCreatorWeapon ); if( pCreatorWeapon ) pMissile->m_CreatorWeaponClass = pCreatorWeapon->Classify(); return pMissile; }
/* ================== MakeTreePortals_r ================== */ void MakeTreePortals_r (node_t *node) { int i; CalcNodeBounds (node); if (node->mins[0] >= node->maxs[0]) { Warning("WARNING: node without a volume\n"); } for (i=0 ; i<3 ; i++) { if (node->mins[i] < (MIN_COORD_INTEGER-SIDESPACE) || node->maxs[i] > (MAX_COORD_INTEGER+SIDESPACE)) { const char *pMatName = "<NO BRUSH>"; // split by brush side if ( node->side ) { texinfo_t *pTexInfo = &texinfo[node->side->texinfo]; dtexdata_t *pTexData = GetTexData( pTexInfo->texdata ); pMatName = TexDataStringTable_GetString( pTexData->nameStringTableID ); } Vector point = node->portals->winding->p[0]; Warning("WARNING: BSP node with unbounded volume (material: %s, near %s)\n", pMatName, VecToString(point) ); break; } } if (node->planenum == PLANENUM_LEAF) return; MakeNodePortal (node); SplitNodePortals (node); MakeTreePortals_r (node->children[0]); MakeTreePortals_r (node->children[1]); }
void CPhysicsSystem::PhysicsSimulate() { CMiniProfilerGuard mpg(&g_mp_PhysicsSimulate); VPROF_BUDGET( "CPhysicsSystem::PhysicsSimulate", VPROF_BUDGETGROUP_PHYSICS ); float frametime = gpGlobals->frametime; if ( physenv ) { g_Collisions.BufferTouchEvents( true ); #ifdef _DEBUG physenv->DebugCheckContacts(); #endif frametime *= cl_phys_timescale.GetFloat(); int maxTicks = cl_phys_maxticks.GetInt(); if ( maxTicks ) { float maxFrameTime = physenv->GetDeltaFrameTime( maxTicks ) - 1e-4f; frametime = clamp( frametime, 0, maxFrameTime ); } physenv->Simulate( frametime ); int activeCount = physenv->GetActiveObjectCount(); g_mp_active_object_count.Add(activeCount); IPhysicsObject **pActiveList = NULL; if ( activeCount ) { PHYS_PROFILE(aUpdateActiveObjects) pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); physenv->GetActiveObjects( pActiveList ); for ( int i = 0; i < activeCount; i++ ) { C_BaseEntity *pEntity = reinterpret_cast<C_BaseEntity *>(pActiveList[i]->GetGameData()); if ( pEntity ) { //const CCollisionProperty *collProp = pEntity->CollisionProp(); //debugoverlay->AddBoxOverlay( collProp->GetCollisionOrigin(), collProp->OBBMins(), collProp->OBBMaxs(), collProp->GetCollisionAngles(), 190, 190, 0, 0, 0.01 ); if ( pEntity->CollisionProp()->DoesVPhysicsInvalidateSurroundingBox() ) { pEntity->CollisionProp()->MarkSurroundingBoundsDirty(); } pEntity->VPhysicsUpdate( pActiveList[i] ); IPhysicsShadowController *pShadow = pActiveList[i]->GetShadowController(); if ( pShadow ) { // active shadow object, check for error Vector pos, targetPos; QAngle rot, targetAngles; pShadow->GetTargetPosition( &targetPos, &targetAngles ); pActiveList[i]->GetPosition( &pos, &rot ); Vector delta = targetPos - pos; float dist = VectorNormalize(delta); bool bBlocked = false; if ( dist > cl_phys_block_dist.GetFloat() ) { Vector vel; pActiveList[i]->GetImplicitVelocity( &vel, NULL ); float proj = DotProduct(vel, delta); if ( proj < dist * cl_phys_block_fraction.GetFloat() ) { bBlocked = true; //Msg("%s was blocked %.3f (%.3f proj)!\n", pEntity->GetClassname(), dist, proj ); } } Vector targetAxis; float deltaTargetAngle; RotationDeltaAxisAngle( rot, targetAngles, targetAxis, deltaTargetAngle ); if ( fabsf(deltaTargetAngle) > 0.5f ) { AngularImpulse angVel; pActiveList[i]->GetImplicitVelocity( NULL, &angVel ); float proj = DotProduct( angVel, targetAxis ) * Sign(deltaTargetAngle); if ( proj < (fabsf(deltaTargetAngle) * cl_phys_block_fraction.GetFloat()) ) { bBlocked = true; //Msg("%s was rot blocked %.3f proj %.3f!\n", pEntity->GetClassname(), deltaTargetAngle, proj ); } } if ( bBlocked ) { C_BaseEntity *pBlocker = FindPhysicsBlocker( pActiveList[i] ); if ( pBlocker ) { if ( IsBlockedShouldDisableCollisions( pEntity ) ) { PhysDisableEntityCollisions( pEntity, pBlocker ); pActiveList[i]->RecheckContactPoints(); // GetClassname returns a pointer to the same buffer always! //Msg("%s blocked !", pEntity->GetClassname() ); Msg("by %s\n", pBlocker->GetClassname() ); } } } } } } } #if 0 if ( cl_visualize_physics_shadows.GetBool() ) { int entityCount = NUM_ENT_ENTRIES; for ( int i = 0; i < entityCount; i++ ) { IClientEntity *pClientEnt = cl_entitylist->GetClientEntity(i); if ( !pClientEnt ) continue; C_BaseEntity *pEntity = pClientEnt->GetBaseEntity(); if ( !pEntity ) continue; Vector pos; QAngle angle; IPhysicsObject *pObj = pEntity->VPhysicsGetObject(); if ( !pObj || !pObj->GetShadowController() ) continue; pObj->GetShadowPosition( &pos, &angle ); debugoverlay->AddBoxOverlay( pos, pEntity->CollisionProp()->OBBMins(), pEntity->CollisionProp()->OBBMaxs(), angle, 255, 255, 0, 32, 0 ); char tmp[256]; V_snprintf( tmp, sizeof(tmp),"%s, (%s)\n", pEntity->GetClassname(), VecToString(angle) ); debugoverlay->AddTextOverlay( pos, 0, tmp ); } } #endif g_Collisions.BufferTouchEvents( false ); g_Collisions.FrameUpdate(); } physicssound::PlayImpactSounds( m_impactSounds ); }
//----------------------------------------------------------------------------- // Purpose: Draw any text overlays // Input : Previous text offset from the top // Output : Current text offset from the top //----------------------------------------------------------------------------- int CAI_AssaultBehavior::DrawDebugTextOverlays( int text_offset ) { char tempstr[ 512 ]; int offset; offset = BaseClass::DrawDebugTextOverlays( text_offset ); if ( GetOuter()->m_debugOverlays & OVERLAY_TEXT_BIT ) { Q_snprintf( tempstr, sizeof(tempstr), "Assault Point: %s %s", STRING( m_AssaultPointName ), VecToString( m_hAssaultPoint->GetAbsOrigin() ) ); GetOuter()->EntityText( offset, tempstr, 0 ); offset++; } return offset; }
void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll ) { SetCollisionGroup( collisionGroup ); // Make sure it's interactive debris for at most 5 seconds if ( collisionGroup == COLLISION_GROUP_INTERACTIVE_DEBRIS ) { SetContextThink( &CRagdollProp::SetDebrisThink, gpGlobals->curtime + 5, s_pDebrisContext ); } SetMoveType( MOVETYPE_VPHYSICS ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); m_takedamage = DAMAGE_EVENTS_ONLY; ragdollparams_t params; params.pGameData = static_cast<void *>( static_cast<CBaseEntity *>(this) ); params.modelIndex = GetModelIndex(); params.pCollide = modelinfo->GetVCollide( params.modelIndex ); params.pStudioHdr = GetModelPtr(); params.forceVector = forceVector; params.forceBoneIndex = forceBone; params.forcePosition = forcePos; params.pPrevBones = pPrevBones; params.pCurrentBones = pBoneToWorld; params.boneDt = dt; params.jointFrictionScale = 1.0; RagdollCreate( m_ragdoll, params, physenv ); if ( m_anglesOverrideString != NULL_STRING && Q_strlen(m_anglesOverrideString.ToCStr()) > 0 ) { char szToken[2048]; const char *pStr = nexttoken(szToken, STRING(m_anglesOverrideString), ','); // anglesOverride is index,angles,index,angles (e.g. "1, 22.5 123.0 0.0, 2, 0 0 0, 3, 0 0 180.0") while ( szToken[0] != 0 ) { int objectIndex = atoi(szToken); // sanity check to make sure this token is an integer Assert( atof(szToken) == ((float)objectIndex) ); pStr = nexttoken(szToken, pStr, ','); Assert( szToken[0] ); if ( objectIndex >= m_ragdoll.listCount ) { Warning("Bad ragdoll pose in entity %s, model (%s) at %s, model changed?\n", GetDebugName(), GetModelName().ToCStr(), VecToString(GetAbsOrigin()) ); } else if ( szToken[0] != 0 ) { QAngle angles; Assert( objectIndex >= 0 && objectIndex < RAGDOLL_MAX_ELEMENTS ); UTIL_StringToVector( angles.Base(), szToken ); int boneIndex = m_ragdoll.boneIndex[objectIndex]; AngleMatrix( angles, pBoneToWorld[boneIndex] ); const ragdollelement_t &element = m_ragdoll.list[objectIndex]; Vector out; if ( element.parentIndex >= 0 ) { int parentBoneIndex = m_ragdoll.boneIndex[element.parentIndex]; VectorTransform( element.originParentSpace, pBoneToWorld[parentBoneIndex], out ); } else { out = GetAbsOrigin(); } MatrixSetColumn( out, 3, pBoneToWorld[boneIndex] ); element.pObject->SetPositionMatrix( pBoneToWorld[boneIndex], true ); } pStr = nexttoken(szToken, pStr, ','); } } if ( activateRagdoll ) { MEM_ALLOC_CREDIT(); RagdollActivate( m_ragdoll, params.pCollide, GetModelIndex() ); } for ( int i = 0; i < m_ragdoll.listCount; i++ ) { UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i ); g_pPhysSaveRestoreManager->AssociateModel( m_ragdoll.list[i].pObject, GetModelIndex() ); physcollision->CollideGetAABB( m_ragdollMins[i], m_ragdollMaxs[i], m_ragdoll.list[i].pObject->GetCollide(), vec3_origin, vec3_angle ); } VPhysicsSetObject( m_ragdoll.list[0].pObject ); CalcRagdollSize(); }