void HapticsDamage(CBasePlayer* pPlayer, const CTakeDamageInfo &info) { #if !defined(TF_DLL) && !defined(CSTRIKE_DLL) if(!pPlayer->HasHaptics()) return;// do not send to non haptic users. Vector DamageDirection(0,0,0); CBaseEntity *eInflictor = info.GetInflictor(); // Pat: nuero toxix crash fix if(!eInflictor) { return; } // Player Data Vector playerPosition = pPlayer->GetLocalOrigin(); Vector inflictorPosition = eInflictor->GetLocalOrigin(); Vector posWithDir = playerPosition + (playerPosition - inflictorPosition); pPlayer->WorldToEntitySpace(posWithDir, &DamageDirection); QAngle dir(0,0,0); VectorAngles(DamageDirection, dir); float yawAngle = dir[YAW]; float pitchAngle = dir[PITCH]; int bitDamageType = info.GetDamageType(); if(bitDamageType & DMG_FALL) { pitchAngle = ((float)-90.0); // coming from beneath } else if(bitDamageType & DMG_BURN && (bitDamageType & ~DMG_BURN)==0) { // just burn, use the z axis here. pitchAngle = 0.0; } #ifdef TERROR else if( (bitDamageType & ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ) ) && (bitDamageType & ~( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ) )==0 ) { // it is time based. and should not really do a punch. return; } #endif float sendDamage = info.GetDamage(); if(sendDamage>0.0f) { HapticMsg_HapDmg( pPlayer, pitchAngle, -yawAngle, sendDamage, bitDamageType ); } #endif }
bool CAI_LeadBehavior::SetGoal( const AI_LeadArgs_t &args ) { CBaseEntity *pGoalEnt; pGoalEnt = gEntList.FindEntityByName( NULL, args.pszGoal ); if ( !pGoalEnt ) return false; m_args = args; // @Q (toml 08-13-02): need to copy string? m_goal = pGoalEnt->GetLocalOrigin(); m_goalyaw = (args.flags & AILF_USE_GOAL_FACING) ? pGoalEnt->GetLocalAngles().y : -1; m_waitpoint = vec3_origin; m_waitdistance = args.flWaitDistance; m_leaddistance = args.flLeadDistance ? args.flLeadDistance : 64; m_retrievedistance = args.flRetrieveDistance ? args.flRetrieveDistance : (m_leaddistance + LEAD_MIN_RETRIEVEDIST_OFFSET); m_successdistance = args.flSuccessDistance ? args.flSuccessDistance : 0; m_run = args.bRun; m_gagleader = args.bGagLeader; m_hasspokenstart = args.bDontSpeakStart; m_hasspokenarrival = false; m_hasPausedScenes = false; m_flSpeakNextNagTime = 0; m_flWeaponSafetyTimeOut = 0; m_flNextLeadIdle = gpGlobals->curtime + 10; m_bInitialAheadTest = true; if ( args.pszWaitPoint && args.pszWaitPoint[0] ) { CBaseEntity *pWaitPoint = gEntList.FindEntityByName( NULL, args.pszWaitPoint ); if ( pWaitPoint ) { m_waitpoint = pWaitPoint->GetLocalOrigin(); } } return true; }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ void CBaseHelicopter::UpdatePlayerDopplerShift( ) { // ----------------------------- // make rotor, engine sounds // ----------------------------- if (m_iSoundState == 0) { // Sound startup. InitializeRotorSound(); } else { CBaseEntity *pPlayer = NULL; // UNDONE: this needs to send different sounds to every player for multiplayer. // FIXME: this isn't the correct way to find a player!!! pPlayer = gEntList.FindEntityByName( NULL, "!player", this ); if (pPlayer) { Vector dir = pPlayer->GetLocalOrigin() - GetLocalOrigin(); VectorNormalize(dir); #if 1 float velReceiver = -DotProduct( pPlayer->GetAbsVelocity(), dir ); float velTransmitter = -DotProduct( GetAbsVelocity(), dir ); // speed of sound == 13049in/s int iPitch = 100 * ((1 - velReceiver / 13049) / (1 + velTransmitter / 13049)); #else // This is a bogus doppler shift, but I like it better float relV = DotProduct( GetAbsVelocity() - pPlayer->GetAbsVelocity(), dir ); int iPitch = (int)(100 + relV / 50.0); #endif // clamp pitch shifts if (iPitch > 250) iPitch = 250; if (iPitch < 50) iPitch = 50; UpdateRotorSoundPitch( iPitch ); // Msg( "Pitch:%d\n", iPitch ); } else { Msg( "Chopper didn't find a player!\n" ); } } }
void CGunTarget::Next( void ) { SetThink( NULL ); m_hTargetEnt = GetNextTarget(); CBaseEntity *pTarget = m_hTargetEnt; if ( !pTarget ) { Stop(); return; } SetMoveDone( &CGunTarget::Wait ); LinearMove( pTarget->GetLocalOrigin(), m_flSpeed ); }
void CInfoIntermission::Think ( void ) { CBaseEntity *pTarget; // find my target pTarget = gEntList.FindEntityByName( NULL, m_target ); if ( pTarget ) { Vector dir = pTarget->GetLocalOrigin() - GetLocalOrigin(); VectorNormalize( dir ); QAngle angles; VectorAngles( dir, angles ); SetLocalAngles( angles ); } }
//----------------------------------------------------------------------------- // Purpose: For create nodes in wc edit mode // Input : // Output : //----------------------------------------------------------------------------- void NWCEdit::CreateAINode( CBasePlayer *pPlayer ) { // ------------------------------------------------------------- // Check that WC is running with the right map version // ------------------------------------------------------------- if ( !IsWCVersionValid() || !pPlayer ) return; pPlayer->AddSolidFlags( FSOLID_NOT_SOLID ); int hullType = g_pAINetworkManager->GetEditOps()->m_iHullDrawNum; // ----------------------------------- // Get position of node to create // ----------------------------------- Vector vNewNodePos = vec3_origin; bool bPositionValid = false; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { vNewNodePos = NWCEdit::AirNodePlacementPosition(); // Make sure we can see the node trace_t tr; UTIL_TraceLine(pPlayer->EyePosition(), vNewNodePos, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); if (tr.fraction == 1.0) { bPositionValid = true; } } else { // Place node by where the player is looking Vector forward; pPlayer->EyeVectors( &forward ); Vector startTrace = pPlayer->EyePosition(); Vector endTrace = pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH; trace_t tr; UTIL_TraceLine(startTrace,endTrace,MASK_NPCSOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction != 1.0) { // Raise the end position up off the floor, place the node and drop him down tr.endpos.z += 48; vNewNodePos = tr.endpos; bPositionValid = true; } } // ------------------------------------------------------------------------------- // Now check that this is a valid location for the new node bu using test hull // ------------------------------------------------------------------------------- if (bPositionValid) { CBaseEntity *testHull = (CBaseEntity*)CAI_TestHull::GetTestHull(); // Set the size of the test hull UTIL_SetSize(testHull, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType)); // Set origin of test hull testHull->SetLocalOrigin( vNewNodePos ); // ----------------------------------------------------------------------- // If a ground node, drop to floor and make sure can stand at test postion // ----------------------------------------------------------------------- if (!g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { UTIL_DropToFloor( testHull, MASK_NPCSOLID ); vNewNodePos = testHull->GetAbsOrigin(); CTraceFilterSimple traceFilter( testHull, COLLISION_GROUP_NONE ); if (!UTIL_CheckBottom(testHull, &traceFilter, sv_stepsize.GetFloat())) { CAI_TestHull::ReturnTestHull(); bPositionValid = false; goto DoneCreate; } } // ----------------------------------------------------------------------- // Make sure hull fits at location by seeing if it can move up a fraction // ----------------------------------------------------------------------- Vector vUpBit = testHull->GetAbsOrigin(); vUpBit.z += 1; trace_t tr; UTIL_TraceHull( testHull->GetAbsOrigin(), vUpBit, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType), MASK_NPCSOLID, testHull, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid || tr.fraction != 1.0) { CAI_TestHull::ReturnTestHull(); bPositionValid = false; goto DoneCreate; } // <<TEMP>> Round position till DS fixed WC bug testHull->SetLocalOrigin( Vector( floor(testHull->GetAbsOrigin().x), floor(testHull->GetAbsOrigin().y ), floor(testHull->GetAbsOrigin().z) ) ); // --------------------------------------- // Send new node to WC // --------------------------------------- int status; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { status = Editor_CreateNode("info_node_air", g_pAINetworkManager->GetEditOps()->m_nNextWCIndex, testHull->GetLocalOrigin().x, testHull->GetLocalOrigin().y, testHull->GetLocalOrigin().z, false); } else { // Create slightly higher in WC so it can be dropped when its loaded again Vector origin = testHull->GetLocalOrigin(); origin.z += 24.0; testHull->SetLocalOrigin( origin ); status = Editor_CreateNode("info_node", g_pAINetworkManager->GetEditOps()->m_nNextWCIndex, testHull->GetLocalOrigin().x, testHull->GetLocalOrigin().y, testHull->GetLocalOrigin().z, false); } if (status == Editor_BadCommand) { Msg( "Worldcraft failed on creation...\n" ); CAI_TestHull::ReturnTestHull(); } else if (status == Editor_OK) { // ----------------------- // Create a new ai node // ----------------------- CNodeEnt *pNodeEnt; if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) { pNodeEnt = (CNodeEnt*)CreateEntityByName("info_node_air"); } else { pNodeEnt = (CNodeEnt*)CreateEntityByName("info_node"); } // Note this is a new entity being created as part of wc editing pNodeEnt->SetLocalOrigin( testHull->GetLocalOrigin() ); CAI_TestHull::ReturnTestHull(); pNodeEnt->m_NodeData.nWCNodeID = g_pAINetworkManager->GetEditOps()->m_nNextWCIndex; pNodeEnt->m_debugOverlays |= OVERLAY_WC_CHANGE_ENTITY; pNodeEnt->Spawn(); } } DoneCreate: // ---------------------------------------------------------- // Flash a red box as a warning that the hull won't fit here // ---------------------------------------------------------- if (!bPositionValid) { NDebugOverlay::Box(vNewNodePos, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType), 255,0,0,0,0.1); } // Restore player collidability pPlayer->SetSolid( SOLID_BBOX ); }
//----------------------------------------------------------------------------- // Purpose: Find a point on my path near to the target and move toward it //----------------------------------------------------------------------------- void CTankTrainAI::Think( void ) { CFuncTrackTrain *pTrain = m_hTrain; if ( !pTrain || pTrain->m_lifeState != LIFE_ALIVE ) { SoundShutdown(); if ( pTrain ) UTIL_RemoveHierarchy( pTrain ); UTIL_Remove( this ); return; } int desired = 0; CBaseEntity *pTarget = m_hTargetEntity; if ( pTarget ) { desired = PathFindDirection( pTrain->m_ppath, pTrain->GetLocalOrigin(), pTarget->GetLocalOrigin() ); } // If the train wants to stop, figure out throttle // otherwise, just throttle in the indicated direction and let the train logic // clip the speed if ( !desired ) { if ( pTrain->m_flSpeed > 0 ) { desired = -1; } else if ( pTrain->m_flSpeed < 0 ) { desired = 1; } } // UNDONE: Align the think time with arrival, and bump this up to a few seconds SetNextThink( gpGlobals->curtime + 0.5f ); if ( desired != 0 ) { int wasMoving = (pTrain->m_flSpeed == 0) ? false : true; // chaser wants train to move, send message pTrain->SetSpeed( desired ); int isMoving = (pTrain->m_flSpeed == 0) ? false : true; if ( !isMoving && wasMoving ) { SoundEngineStop(); } else if ( isMoving ) { if ( !wasMoving ) { SoundEngineStart(); } } } else { SoundEngineStop(); // UNDONE: Align the think time with arrival, and bump this up to a few seconds SetNextThink( gpGlobals->curtime + 1.0f ); } }
CBaseEntity* CHL2MP_Player::EntSelectSpawnPoint( void ) { CBaseEntity *pSpot = NULL; CBaseEntity *pLastSpawnPoint = g_pLastSpawn; edict_t *player = edict(); const char *pSpawnpointName = "info_player_deathmatch"; if ( HL2MPRules()->IsTeamplay() == true ) { if ( GetTeamNumber() == TEAM_COMBINE ) { pSpawnpointName = "info_player_combine"; pLastSpawnPoint = g_pLastCombineSpawn; } else if ( GetTeamNumber() == TEAM_REBELS ) { pSpawnpointName = "info_player_rebel"; pLastSpawnPoint = g_pLastRebelSpawn; } if ( gEntList.FindEntityByClassname( NULL, pSpawnpointName ) == NULL ) { pSpawnpointName = "info_player_deathmatch"; pLastSpawnPoint = g_pLastSpawn; } } pSpot = pLastSpawnPoint; // Randomize the start spot for ( int i = random->RandomInt(1,5); i > 0; i-- ) pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); if ( !pSpot ) // skip over the null point pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); CBaseEntity *pFirstSpot = pSpot; do { if ( pSpot ) { // check if pSpot is valid if ( g_pGameRules->IsSpawnPointValid( pSpot, this ) ) { if ( pSpot->GetLocalOrigin() == vec3_origin ) { pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); continue; } // if so, go to pSpot goto ReturnSpot; } } // increment pSpot pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); } while ( pSpot != pFirstSpot ); // loop if we're not back to the start // we haven't found a place to spawn yet, so kill any guy at the first spawn point and spawn there if ( pSpot ) { CBaseEntity *ent = NULL; for ( CEntitySphereQuery sphere( pSpot->GetAbsOrigin(), 128 ); (ent = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) { // if ent is a client, kill em (unless they are ourselves) if ( ent->IsPlayer() && !(ent->edict() == player) ) ent->TakeDamage( CTakeDamageInfo( GetContainingEntity(INDEXENT(0)), GetContainingEntity(INDEXENT(0)), 300, DMG_GENERIC ) ); } goto ReturnSpot; } if ( !pSpot ) { pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_start" ); if ( pSpot ) goto ReturnSpot; } ReturnSpot: if ( HL2MPRules()->IsTeamplay() == true ) { if ( GetTeamNumber() == TEAM_COMBINE ) { g_pLastCombineSpawn = pSpot; } else if ( GetTeamNumber() == TEAM_REBELS ) { g_pLastRebelSpawn = pSpot; } } g_pLastSpawn = pSpot; m_flSlamProtectTime = gpGlobals->curtime + 0.5; return pSpot; }
CBaseEntity* CHL2MP_Player::EntSelectSpawnPoint( void ) { CBaseEntity *pSpot = NULL; CBaseEntity *pLastSpawnPoint = g_pLastSpawn; edict_t *player = edict(); const char *pSpawnpointName = "info_player_deathmatch"; pSpot = pLastSpawnPoint; // Randomize the start spot for ( int i = random->RandomInt(1,5); i > 0; i-- ) pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); if ( !pSpot ) // skip over the null point pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); CBaseEntity *pFirstSpot = pSpot; do { if ( pSpot ) { // check if pSpot is valid if ( g_pGameRules->IsSpawnPointValid( pSpot, this ) ) { if ( pSpot->GetLocalOrigin() == vec3_origin ) { pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); continue; } // if so, go to pSpot goto ReturnSpot; } } // increment pSpot pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); } while ( pSpot != pFirstSpot ); // loop if we're not back to the start // we haven't found a place to spawn yet, so kill any guy at the first spawn point and spawn there if ( pSpot ) { CBaseEntity *ent = NULL; for ( CEntitySphereQuery sphere( pSpot->GetAbsOrigin(), 128 ); (ent = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) { // if ent is a client, kill em (unless they are ourselves) if ( ent->IsPlayer() && !(ent->edict() == player) ) ent->TakeDamage( CTakeDamageInfo( GetContainingEntity(INDEXENT(0)), GetContainingEntity(INDEXENT(0)), 300, DMG_GENERIC ) ); } goto ReturnSpot; } if ( !pSpot ) { char szMapName[256]; Q_strncpy(szMapName, STRING(gpGlobals->mapname), sizeof(szMapName)); Q_strlower(szMapName); //TDT - Information: Although we don't support official maps for gaming, they are useful for testing and these maps for whatever reason spawn you in the wrong location. As such this // code is here to force players to spawn at the beginning of the selected maps. Custom maps won't require this as they will have deathmatch/class based player starts. if (!Q_strnicmp(szMapName, "d1_canals_01a", 13) || !Q_strnicmp(szMapName, "d1_canals_03", 12) || !Q_strnicmp(szMapName, "d1_canals_13", 12) || !Q_strnicmp(szMapName, "d1_town_01", 10) || !Q_strnicmp(szMapName, "d1_town_01a", 11) || !Q_strnicmp(szMapName, "d1_town_02", 10) || !Q_strnicmp(szMapName, "d1_town_02a", 11) || !Q_strnicmp(szMapName, "d1_town_03", 10) || !Q_strnicmp(szMapName, "d1_town_04", 10) || !Q_strnicmp(szMapName, "d1_town_05", 10) || !Q_strnicmp(szMapName, "d2_coast_03", 11) || !Q_strnicmp(szMapName, "d2_coast_08", 11) || !Q_strnicmp(szMapName, "d2_coast_11", 11) || !Q_strnicmp(szMapName, "d2_prison_01", 12) || !Q_strnicmp(szMapName, "d2_prison_02", 12) || !Q_strnicmp(szMapName, "d2_prison_03", 12) || !Q_strnicmp(szMapName, "d2_prison_04", 12) || !Q_strnicmp(szMapName, "d2_prison_05", 12) || !Q_strnicmp(szMapName, "d2_prison_06", 12) || !Q_strnicmp(szMapName, "d2_prison_07", 12) || !Q_strnicmp(szMapName, "d2_prison_08", 12) || !Q_strnicmp(szMapName, "d3_c17_08", 9) || !Q_strnicmp(szMapName, "d3_citadel_01", 13) || !Q_strnicmp(szMapName, "d3_citadel_02", 13) || !Q_strnicmp(szMapName, "d3_citadel_03", 13) || !Q_strnicmp(szMapName, "d3_citadel_04", 13) || !Q_strnicmp(szMapName, "d3_citadel_05", 13) || !Q_strnicmp(szMapName, "d3_breen_01", 11) || !Q_strnicmp(szMapName, "ep1_c17_00", 10) || !Q_strnicmp(szMapName, "ep1_c17_00a", 11) || !Q_strnicmp(szMapName, "ep1_c17_02b", 11) || !Q_strnicmp(szMapName, "ep1_c17_05", 10) || !Q_strnicmp(szMapName, "ep2_outland_01a", 15) || !Q_strnicmp(szMapName, "ep2_outland_03", 14) || !Q_strnicmp(szMapName, "ep2_outland_08", 14) || !Q_strnicmp(szMapName, "ep2_outland_06", 14) ) { CBaseEntity *pEntity = NULL; CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); Vector vecOrigin = pPlayer->GetAbsOrigin(); pEntity = gEntList.FindEntityByClassnameNearest("item_suit", vecOrigin, 0); if (pEntity != NULL) { vecOrigin = pEntity->GetAbsOrigin(); pEntity = gEntList.FindEntityByClassnameNearest("info_player_start", vecOrigin, 0); pSpot = pEntity; pSpawnpointName = "info_player_start"; goto ReturnSpot; } else { pSpot = gEntList.FindEntityByClassname(pSpot, "info_player_start"); } } else if (!Q_strnicmp(szMapName, "d1_trainstation_05", 18)) { CBaseEntity *pEntity = NULL; CBasePlayer *pPlayer = UTIL_GetNearestPlayer(GetAbsOrigin()); Vector vecOrigin = pPlayer->GetAbsOrigin(); pEntity = gEntList.FindEntityByClassnameNearest("npc_alyx", vecOrigin, 0); if (pEntity != NULL) { vecOrigin = pEntity->GetAbsOrigin(); pEntity = gEntList.FindEntityByClassnameNearest("info_player_start", vecOrigin, 0); pSpot = pEntity; pSpawnpointName = "info_player_start"; goto ReturnSpot; } else { pSpot = gEntList.FindEntityByClassname(pSpot, "info_player_start"); } } else { pSpot = gEntList.FindEntityByClassname(pSpot, "info_player_start"); } if ( pSpot ) goto ReturnSpot; } ReturnSpot: g_pLastSpawn = pSpot; m_flSlamProtectTime = gpGlobals->curtime + 0.5; return pSpot; }
void CWeaponGravityGun::EffectUpdate( void ) { Vector start, angles, forward, right; trace_t tr; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !pOwner ) return; m_viewModelIndex = pOwner->entindex(); // Make sure I've got a view model CBaseViewModel *vm = pOwner->GetViewModel(); if ( vm ) { m_viewModelIndex = vm->entindex(); } pOwner->EyeVectors( &forward, &right, NULL ); start = pOwner->Weapon_ShootPosition(); Vector end = start + forward * 4096; UTIL_TraceLine( start, end, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); end = tr.endpos; float distance = tr.fraction * 4096; if ( tr.fraction != 1 ) { // too close to the player, drop the object if ( distance < 36 ) { DetachObject(); return; } } if ( m_hObject == NULL && tr.DidHitNonWorldEntity() ) { CBaseEntity *pEntity = tr.m_pEnt; // inform the object what was hit ClearMultiDamage(); pEntity->DispatchTraceAttack( CTakeDamageInfo( pOwner, pOwner, 0, DMG_PHYSGUN ), forward, &tr ); ApplyMultiDamage(); AttachObject( pEntity, start, tr.endpos, distance ); m_lastYaw = pOwner->EyeAngles().y; } // Add the incremental player yaw to the target transform matrix3x4_t curMatrix, incMatrix, nextMatrix; QAngle ang(0.0f, pOwner->EyeAngles().y - m_lastYaw, 0.0f); AngleMatrix( m_gravCallback.m_targetRotation, curMatrix ); AngleMatrix( ang, incMatrix ); ConcatTransforms( incMatrix, curMatrix, nextMatrix ); MatrixAngles( nextMatrix, m_gravCallback.m_targetRotation ); m_lastYaw = pOwner->EyeAngles().y; CBaseEntity *pObject = m_hObject; if ( pObject ) { if ( m_useDown ) { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = false; } } else { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = true; } } if ( m_useDown ) { pOwner->SetPhysicsFlag( PFLAG_DIROVERRIDE, true ); if ( pOwner->m_nButtons & IN_FORWARD ) { m_distance = UTIL_Approach( 1024, m_distance, gpGlobals->frametime * 100 ); } if ( pOwner->m_nButtons & IN_BACK ) { m_distance = UTIL_Approach( 40, m_distance, gpGlobals->frametime * 100 ); } } if ( pOwner->m_nButtons & IN_WEAPON1 ) { m_distance = UTIL_Approach( 1024, m_distance, m_distance * 0.1 ); } if ( pOwner->m_nButtons & IN_WEAPON2 ) { m_distance = UTIL_Approach( 40, m_distance, m_distance * 0.1 ); } // Send the object a physics damage message (0 damage). Some objects interpret this // as something else being in control of their physics temporarily. pObject->TakeDamage( CTakeDamageInfo( this, pOwner, 0, DMG_PHYSGUN ) ); Vector newPosition = start + forward * m_distance; // 24 is a little larger than 16 * sqrt(2) (extent of player bbox) // HACKHACK: We do this so we can "ignore" the player and the object we're manipulating // If we had a filter for tracelines, we could simply filter both ents and start from "start" Vector awayfromPlayer = start + forward * 24; UTIL_TraceLine( start, awayfromPlayer, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction == 1 ) { UTIL_TraceLine( awayfromPlayer, newPosition, MASK_SOLID, pObject, COLLISION_GROUP_NONE, &tr ); Vector dir = tr.endpos - newPosition; float distance = VectorNormalize(dir); float maxDist = m_gravCallback.m_maxVel * gpGlobals->frametime; if ( distance > maxDist ) { newPosition += dir * maxDist; } else { newPosition = tr.endpos; } } else { newPosition = tr.endpos; } CreatePelletAttraction( phys_gunglueradius.GetFloat(), pObject ); // If I'm looking more than 20 degrees away from the glue point, then give up // This lets the player "gesture" for the glue to let go. Vector pelletDir = m_gravCallback.m_worldPosition - start; VectorNormalize(pelletDir); if ( DotProduct( pelletDir, forward ) < 0.939 ) // 0.939 ~= cos(20deg) { // lose attach for 2 seconds if you're too far away m_glueTime = gpGlobals->curtime + 1; } if ( m_pelletHeld >= 0 && gpGlobals->curtime > m_glueTime ) { CGravityPellet *pPelletAttract = m_activePellets[m_pelletAttract].pellet; g_pEffects->Sparks( pPelletAttract->GetAbsOrigin() ); } m_gravCallback.SetTargetPosition( newPosition ); Vector dir = (newPosition - pObject->GetLocalOrigin()); m_movementLength = dir.Length(); } else { m_gravCallback.SetTargetPosition( end ); } if ( m_pelletHeld >= 0 && gpGlobals->curtime > m_glueTime ) { Vector worldNormal, worldPos; GetPelletWorldCoords( m_pelletAttract, &worldPos, &worldNormal ); m_gravCallback.SetAutoAlign( m_activePellets[m_pelletHeld].localNormal, m_activePellets[m_pelletHeld].pellet->GetLocalOrigin(), worldNormal, worldPos ); } else { m_gravCallback.ClearAutoAlign(); } }
void CWeaponGravityGun::EffectUpdate( void ) { Vector start, forward, right; trace_t tr; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !pOwner ) return; pOwner->EyeVectors( &forward, &right, NULL ); start = pOwner->Weapon_ShootPosition(); TraceLine( &tr ); Vector end = tr.endpos; float distance = tr.fraction * 4096; if ( m_hObject == NULL && tr.DidHitNonWorldEntity() ) { CBaseEntity *pEntity = tr.m_pEnt; AttachObject( pEntity, GetPhysObjFromPhysicsBone( pEntity, tr.physicsbone ), tr.physicsbone, start, tr.endpos, distance ); } // Add the incremental player yaw to the target transform QAngle angles = m_gravCallback.TransformAnglesFromPlayerSpace( m_gravCallback.m_targetRotation, pOwner ); CBaseEntity *pObject = m_hObject; if ( pObject ) { if ( m_useDown ) { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = false; } } else { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = true; } } if ( m_useDown ) { #ifndef CLIENT_DLL pOwner->SetPhysicsFlag( PFLAG_DIROVERRIDE, true ); #endif if ( pOwner->m_nButtons & IN_FORWARD ) { m_distance = Approach( 1024, m_distance, gpGlobals->frametime * 100 ); } if ( pOwner->m_nButtons & IN_BACK ) { m_distance = Approach( 40, m_distance, gpGlobals->frametime * 100 ); } } if ( pOwner->m_nButtons & IN_WEAPON1 ) { m_distance = Approach( 1024, m_distance, m_distance * 0.1 ); } if ( pOwner->m_nButtons & IN_WEAPON2 ) { m_distance = Approach( 40, m_distance, m_distance * 0.1 ); } IPhysicsObject *pPhys = GetPhysObjFromPhysicsBone( pObject, m_physicsBone ); if ( pPhys ) { if ( pPhys->IsAsleep() ) { // on the odd chance that it's gone to sleep while under anti-gravity pPhys->Wake(); } Vector newPosition = start + forward * m_distance; Vector offset; pPhys->LocalToWorld( &offset, m_worldPosition ); Vector vecOrigin; pPhys->GetPosition( &vecOrigin, NULL ); m_gravCallback.SetTargetPosition( newPosition + (vecOrigin - offset), angles ); Vector dir = (newPosition - pObject->GetLocalOrigin()); m_movementLength = dir.Length(); } } else { m_targetPosition = end; //m_gravCallback.SetTargetPosition( end, m_gravCallback.m_targetRotation ); } }
void CWeaponGravityGun::EffectUpdate( void ) { Vector start, forward, right; trace_t tr; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !pOwner ) return; pOwner->EyeVectors( &forward, &right, NULL ); start = pOwner->Weapon_ShootPosition(); TraceLine( &tr ); Vector end = tr.endpos; float distance = tr.fraction * 4096; if ( tr.fraction != 1 ) { // too close to the player, drop the object if ( distance < 36 ) { DetachObject(); return; } } if ( m_hObject == NULL && tr.DidHitNonWorldEntity() ) { CBaseEntity *pEntity = tr.m_pEnt; AttachObject( pEntity, start, tr.endpos, distance ); m_lastYaw = pOwner->EyeAngles().y; } // Add the incremental player yaw to the target transform matrix3x4_t curMatrix, incMatrix, nextMatrix; AngleMatrix( m_gravCallback.m_targetRotation, curMatrix ); AngleMatrix( QAngle(0,pOwner->EyeAngles().y - m_lastYaw,0), incMatrix ); ConcatTransforms( incMatrix, curMatrix, nextMatrix ); MatrixAngles( nextMatrix, m_gravCallback.m_targetRotation ); m_lastYaw = pOwner->EyeAngles().y; CBaseEntity *pObject = m_hObject; if ( pObject ) { if ( m_useDown ) { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = false; } } else { if ( pOwner->m_afButtonPressed & IN_USE ) { m_useDown = true; } } if ( m_useDown ) { #ifndef CLIENT_DLL pOwner->SetPhysicsFlag( PFLAG_DIROVERRIDE, true ); #endif if ( pOwner->m_nButtons & IN_FORWARD ) { m_distance = Approach( 1024, m_distance, gpGlobals->frametime * 100 ); } if ( pOwner->m_nButtons & IN_BACK ) { m_distance = Approach( 40, m_distance, gpGlobals->frametime * 100 ); } } if ( pOwner->m_nButtons & IN_WEAPON1 ) { m_distance = Approach( 1024, m_distance, m_distance * 0.1 ); #ifdef CLIENT_DLL if ( gpGlobals->maxClients > 1 ) { gHUD.m_bSkipClear = false; } #endif } if ( pOwner->m_nButtons & IN_WEAPON2 ) { m_distance = Approach( 40, m_distance, m_distance * 0.1 ); #ifdef CLIENT_DLL if ( gpGlobals->maxClients > 1 ) { gHUD.m_bSkipClear = false; } #endif } IPhysicsObject *pPhys = pObject->VPhysicsGetObject(); if ( pPhys && pPhys->IsAsleep() ) { // on the odd chance that it's gone to sleep while under anti-gravity pPhys->Wake(); } Vector newPosition = start + forward * m_distance; Vector offset; pObject->EntityToWorldSpace( m_worldPosition, &offset ); m_gravCallback.SetTargetPosition( newPosition + (pObject->GetAbsOrigin() - offset), m_gravCallback.m_targetRotation ); Vector dir = (newPosition - pObject->GetLocalOrigin()); m_movementLength = dir.Length(); } else { m_targetPosition = end; //m_gravCallback.SetTargetPosition( end, m_gravCallback.m_targetRotation ); } }
Vector QUA_helicopter::CalcDamageForceVector( const CTakeDamageInfo &info ) { // Already have a damage force in the data, use that. if (info.GetDamageForce() != vec3_origin || (info.GetDamageType() & /*DMG_NO_PHYSICS_FORCE*/DMG_BLAST)) { //if( info.GetDamageType() & DMG_BLAST ) //{ // Fudge blast forces a little bit, so that each // victim gets a slightly different trajectory. // This simulates features that usually vary from // person-to-person variables such as bodyweight, // which are all indentical for characters using the same model. float scale = random->RandomFloat( 0.85, 1.15 ); Vector force = info.GetDamageForce(); force.x *= scale; force.y *= scale; // Try to always exaggerate the upward force because we've got pretty harsh gravity force.z *= (force.z > 0) ? 1.15 : scale; return force; //} return info.GetDamageForce(); } CBaseEntity *pForce = info.GetInflictor(); if ( !pForce ) { pForce = info.GetAttacker(); } if ( pForce ) { // Calculate an impulse large enough to push a 75kg man 4 in/sec per point of damage float forceScale = info.GetDamage() * 75 * 4; Vector forceVector; // If the damage is a blast, point the force vector higher than usual, this gives // the ragdolls a bodacious "really got blowed up" look. if( info.GetDamageType() & DMG_BLAST ) { // exaggerate the force from explosions a little (37.5%) forceVector = (GetLocalOrigin() + Vector(0, 0, WorldAlignSize().z) ) - pForce->GetLocalOrigin(); VectorNormalize(forceVector); forceVector *= 1.375f; } else { // taking damage from self? Take a little random force, but still try to collapse on the spot. if ( this == pForce ) { forceVector.x = random->RandomFloat( -1.0f, 1.0f ); forceVector.y = random->RandomFloat( -1.0f, 1.0f ); forceVector.z = 0.0; forceScale = random->RandomFloat( 1000.0f, 2000.0f ); } else { // UNDONE: Collision forces are baked in to CTakeDamageInfo now // UNDONE: Is this MOVETYPE_VPHYSICS code still necessary? if ( pForce->GetMoveType() == MOVETYPE_VPHYSICS ) { // killed by a physics object IPhysicsObject *pPhysics = VPhysicsGetObject(); if ( !pPhysics ) { pPhysics = pForce->VPhysicsGetObject(); } pPhysics->GetVelocity( &forceVector, NULL ); forceScale = pPhysics->GetMass(); } else { forceVector = GetLocalOrigin() - pForce->GetLocalOrigin(); VectorNormalize(forceVector); } } } return forceVector * forceScale; } return vec3_origin; }
Vector CASW_Simple_Alien::CalcDeathForceVector( const CTakeDamageInfo &info ) { // Already have a damage force in the data, use that. if ( info.GetDamageForce() != vec3_origin || (g_pGameRules->Damage_NoPhysicsForce(info.GetDamageType()))) { if( info.GetDamageType() & DMG_BLAST ) { float scale = random->RandomFloat( 0.85, 1.15 ); Vector force = info.GetDamageForce(); force.x *= scale; force.y *= scale; // Try to always exaggerate the upward force because we've got pretty harsh gravity force.z *= (force.z > 0) ? 1.15 : scale; return force; } return info.GetDamageForce(); } CBaseEntity *pForce = info.GetInflictor(); if ( !pForce ) { pForce = info.GetAttacker(); } if ( pForce ) { // Calculate an impulse large enough to push a 75kg man 4 in/sec per point of damage float forceScale = info.GetDamage() * 75 * 4; Vector forceVector; // If the damage is a blast, point the force vector higher than usual, this gives // the ragdolls a bodacious "really got blowed up" look. if( info.GetDamageType() & DMG_BLAST ) { // exaggerate the force from explosions a little (37.5%) forceVector = (GetLocalOrigin() + Vector(0, 0, WorldAlignSize().z) ) - pForce->GetLocalOrigin(); VectorNormalize(forceVector); forceVector *= 1.375f; } else { // taking damage from self? Take a little random force, but still try to collapse on the spot. if ( this == pForce ) { forceVector.x = random->RandomFloat( -1.0f, 1.0f ); forceVector.y = random->RandomFloat( -1.0f, 1.0f ); forceVector.z = 0.0; forceScale = random->RandomFloat( 1000.0f, 2000.0f ); } else { // UNDONE: Collision forces are baked in to CTakeDamageInfo now // UNDONE: Is this MOVETYPE_VPHYSICS code still necessary? if ( pForce->GetMoveType() == MOVETYPE_VPHYSICS ) { // killed by a physics object IPhysicsObject *pPhysics = VPhysicsGetObject(); if ( !pPhysics ) { pPhysics = pForce->VPhysicsGetObject(); } pPhysics->GetVelocity( &forceVector, NULL ); forceScale = pPhysics->GetMass(); } else { forceVector = GetLocalOrigin() - pForce->GetLocalOrigin(); VectorNormalize(forceVector); } } } return forceVector * forceScale; } return vec3_origin; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CFastZombie::StartTask( const Task_t *pTask ) { switch( pTask->iTask ) { case TASK_FASTZOMBIE_VERIFY_ATTACK: // Simply ensure that the zombie still has a valid melee attack if( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) { TaskComplete(); } else { TaskFail(""); } break; case TASK_FASTZOMBIE_JUMP_BACK: { SetActivity( ACT_IDLE ); RemoveFlag( FL_ONGROUND ); BeginAttackJump(); Vector forward; AngleVectors( GetLocalAngles(), &forward ); // // Take him off ground so engine doesn't instantly reset FL_ONGROUND. // UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); ApplyAbsVelocityImpulse( forward * -200 + Vector( 0, 0, 200 ) ); } break; case TASK_FASTZOMBIE_UNSTICK_JUMP: { RemoveFlag( FL_ONGROUND ); // Call begin attack jump. A little bit later if we fail to pathfind, we check // this value to see if we just jumped. If so, we assume we've jumped // to someplace that's not pathing friendly, and so must jump again to get out. BeginAttackJump(); // // Take him off ground so engine doesn't instantly reset FL_ONGROUND. // UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); CBaseEntity *pEnemy = GetEnemy(); Vector vecJumpDir; if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN ) { // Jump off the pipe backwards! Vector forward; GetVectors( &forward, NULL, NULL ); ApplyAbsVelocityImpulse( forward * -200 ); } else if( pEnemy ) { vecJumpDir = pEnemy->GetLocalOrigin() - GetLocalOrigin(); VectorNormalize( vecJumpDir ); vecJumpDir.z = 0; ApplyAbsVelocityImpulse( vecJumpDir * 300 + Vector( 0, 0, 200 ) ); } else { Msg("UNHANDLED CASE! Stuck Fast Zombie with no enemy!\n"); } } break; case TASK_WAIT_FOR_MOVEMENT: // If we're waiting for movement, that means that pathfinding succeeded, and // we're about to be moving. So we aren't stuck. So clear this flag. m_fJustJumped = false; BaseClass::StartTask( pTask ); break; case TASK_FACE_ENEMY: { // We don't use the base class implementation of this, because GetTurnActivity // stomps our landing scrabble animations (sjb) Vector flEnemyLKP = GetEnemyLKP(); GetMotor()->SetIdealYawToTarget( flEnemyLKP ); } break; case TASK_FASTZOMBIE_LAND_RECOVER: { // Set the ideal yaw Vector flEnemyLKP = GetEnemyLKP(); GetMotor()->SetIdealYawToTarget( flEnemyLKP ); // figure out which way to turn. float flDeltaYaw = GetMotor()->DeltaIdealYaw(); if( flDeltaYaw < 0 ) { SetIdealActivity( (Activity)ACT_FASTZOMBIE_LAND_RIGHT ); } else { SetIdealActivity( (Activity)ACT_FASTZOMBIE_LAND_LEFT ); } TaskComplete(); } break; case TASK_RANGE_ATTACK1: // Make melee attacks impossible until we land! m_flNextMeleeAttack = gpGlobals->curtime + 60; SetTouch( LeapAttackTouch ); break; case TASK_FASTZOMBIE_DO_ATTACK: SetActivity( (Activity)ACT_FASTZOMBIE_LEAP_SOAR ); break; default: BaseClass::StartTask( pTask ); break; } }
//========================================================= // FindNearestFriend // Scan for nearest, visible friend. If fPlayer is true, look for // nearest player //========================================================= CBaseEntity *CAI_PlayerAlly::FindNearestFriend(bool fPlayer) { CBaseEntity *pFriend = NULL; CBaseEntity *pNearest = NULL; float range = 10000000.0; trace_t tr; Vector vecStart = GetAbsOrigin(); Vector vecCheck; int i; const char *pszFriend; int cfriends; vecStart.z = GetAbsMaxs().z; if (fPlayer) cfriends = 1; else cfriends = TLK_CFRIENDS; // for each type of friend... for (i = cfriends-1; i > -1; i--) { if (fPlayer) { CBaseEntity *pPlayer = UTIL_PlayerByIndex(1); if ( pPlayer ) { pszFriend = STRING(pPlayer->m_iClassname); } else { pszFriend = "player"; } } else pszFriend = m_szFriends[FriendNumber(i)]; if (!pszFriend) continue; // for each friend in this bsp... while (pFriend = gEntList.FindEntityByClassname( pFriend, pszFriend )) { if (pFriend == this || !pFriend->IsAlive()) // don't talk to self or dead people continue; CAI_BaseNPC *pNPC = pFriend->MyNPCPointer(); // If not a NPC for some reason, or in a script. if ( pNPC && (pNPC->m_NPCState == NPC_STATE_SCRIPT || pNPC->m_NPCState == NPC_STATE_PRONE)) continue; if( pNPC && pNPC->IsSelected() ) { // Don't bother people that are awaiting orders. return false; } vecCheck = pFriend->GetLocalOrigin(); vecCheck.z = pFriend->GetAbsMaxs().z; // if closer than previous friend, and in range, see if he's visible if (range > (vecStart - vecCheck).Length()) { UTIL_TraceLine(vecStart, vecCheck, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); if (tr.fraction == 1.0) { // visible and in range, this is the new nearest scientist if ((vecStart - vecCheck).Length() < TALKRANGE_MIN) { pNearest = pFriend; range = (vecStart - vecCheck).Length(); } } } } } return pNearest; }