void CSDKPlayer::CheckBallShield(const Vector &oldPos, Vector &newPos, const Vector &oldVel, Vector &newVel, const QAngle &oldAng, QAngle &newAng) { bool stopPlayer = false; const float border = (GetFlags() & FL_SHIELD_KEEP_IN) ? -mp_shield_border.GetInt() : mp_shield_border.GetInt(); int forward; #ifdef CLIENT_DLL forward = GetPlayersTeam(this)->m_nForward; #else forward = GetTeam()->m_nForward; #endif if (SDKGameRules()->m_nShieldType != SHIELD_NONE) { if (SDKGameRules()->m_nShieldType == SHIELD_GOALKICK || SDKGameRules()->m_nShieldType == SHIELD_PENALTY || SDKGameRules()->m_nShieldType == SHIELD_FREEKICK || (SDKGameRules()->m_nShieldType == SHIELD_KICKOFF && !SDKGameRules()->IsIntermissionState()) || SDKGameRules()->m_nShieldType == SHIELD_CORNER) { const float radius = mp_shield_ball_radius.GetFloat(); Vector dir = newPos - SDKGameRules()->m_vShieldPos; if (dir.Length2DSqr() < pow(radius, 2)) { dir.z = 0; dir.NormalizeInPlace(); newPos = SDKGameRules()->m_vShieldPos + dir * radius; stopPlayer = true; } } if (SDKGameRules()->m_nShieldType == SHIELD_GOALKICK || SDKGameRules()->m_nShieldType == SHIELD_PENALTY || SDKGameRules()->m_nShieldType == SHIELD_KEEPERHANDS) { int side = (SDKGameRules()->m_nShieldType == SHIELD_PENALTY ? GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->GetOppTeamNumber() : SDKGameRules()->m_nShieldTeam); Vector min = GetGlobalTeam(side)->m_vPenBoxMin - border; Vector max = GetGlobalTeam(side)->m_vPenBoxMax + border; if (GetFlags() & FL_SHIELD_KEEP_OUT || SDKGameRules()->m_nShieldType == SHIELD_PENALTY) { if (SDKGameRules()->m_vKickOff.GetY() > min.y) min.y -= 500; else max.y += 500; } bool isInsideBox = newPos.x > min.x && newPos.y > min.y && newPos.x < max.x && newPos.y < max.y; Vector boxCenter = (min + max) / 2; if (GetFlags() & FL_SHIELD_KEEP_OUT && isInsideBox) { bool oldPosInBox = true; if (newPos.x > min.x && oldPos.x <= min.x && newPos.x < boxCenter.x) { newPos.x = min.x; oldPosInBox = false; } else if (newPos.x < max.x && oldPos.x >= max.x && newPos.x > boxCenter.x) { newPos.x = max.x; oldPosInBox = false; } if (newPos.y > min.y && oldPos.y <= min.y && newPos.y < boxCenter.y) { newPos.y = min.y; oldPosInBox = false; } else if (newPos.y < max.y && oldPos.y >= max.y && newPos.y > boxCenter.y) { newPos.y = max.y; oldPosInBox = false; } stopPlayer = true; if (SDKGameRules()->m_nShieldType == SHIELD_KEEPERHANDS && oldPosInBox) { Vector goalCenter = GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->m_vGoalCenter; goalCenter.y -= GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->m_nForward * 500; if ((goalCenter - newPos).Length2DSqr() < (goalCenter - oldPos).Length2DSqr()) { newPos.x = oldPos.x; newPos.y = oldPos.y; stopPlayer = true; } else stopPlayer = false; } } else if (GetFlags() & FL_SHIELD_KEEP_IN && !isInsideBox) { if (newPos.x < min.x) newPos.x = min.x; else if (newPos.x > max.x) newPos.x = max.x; if (newPos.y < min.y) newPos.y = min.y; else if (newPos.y > max.y) newPos.y = max.y; stopPlayer = true; } } if (SDKGameRules()->m_nShieldType == SHIELD_THROWIN && GetFlags() & FL_SHIELD_KEEP_OUT || SDKGameRules()->m_nShieldType == SHIELD_FREEKICK || SDKGameRules()->m_nShieldType == SHIELD_CORNER || SDKGameRules()->m_nShieldType == SHIELD_KICKOFF || SDKGameRules()->m_nShieldType == SHIELD_PENALTY && (GetFlags() & FL_SHIELD_KEEP_OUT)) { float radius = SDKGameRules()->GetShieldRadius(GetTeamNumber(), GetFlags() & FL_SHIELD_KEEP_IN) + border; Vector dir = newPos - SDKGameRules()->m_vShieldPos; if (!SDKGameRules()->IsIntermissionState() && ((GetFlags() & FL_SHIELD_KEEP_OUT) && dir.Length2D() < radius || (GetFlags() & FL_SHIELD_KEEP_IN) && dir.Length2D() > radius)) { dir.z = 0; dir.NormalizeInPlace(); newPos = SDKGameRules()->m_vShieldPos + dir * radius; stopPlayer = true; } if (SDKGameRules()->m_nShieldType == SHIELD_KICKOFF && (GetFlags() & FL_SHIELD_KEEP_OUT) && (!SDKGameRules()->IsIntermissionState() || SDKGameRules()->State_Get() == MATCH_PERIOD_WARMUP && mp_shield_block_opponent_half.GetBool())) { int forward; #ifdef CLIENT_DLL forward = GetPlayersTeam(this)->m_nForward; #else forward = GetTeam()->m_nForward; #endif float yBorder = SDKGameRules()->m_vKickOff.GetY() - abs(border) * forward; if (ZeroSign(newPos.y - yBorder) == forward) { newPos.y = yBorder; stopPlayer = true; } } if (SDKGameRules()->m_nShieldType == SHIELD_FREEKICK && mp_shield_block_sixyardbox.GetBool()) { int teamPosType; #ifdef CLIENT_DLL teamPosType = GameResources()->GetTeamPosType(entindex()); #else teamPosType = GetTeamPosType(); #endif if (teamPosType != POS_GK || GetTeamNumber() != GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->GetOppTeamNumber()) { int side = GetGlobalTeam(SDKGameRules()->m_nShieldTeam)->GetOppTeamNumber(); Vector min = GetGlobalTeam(side)->m_vSixYardBoxMin - border; Vector max = GetGlobalTeam(side)->m_vSixYardBoxMax + border; if (GetGlobalTeam(side)->m_nForward == 1) min.y -= 500; else max.y += 500; bool isInsideBox = newPos.x > min.x && newPos.y > min.y && newPos.x < max.x && newPos.y < max.y; Vector boxCenter = (min + max) / 2; if (isInsideBox) { if (newPos.x > min.x && oldPos.x <= min.x && newPos.x < boxCenter.x) newPos.x = min.x; else if (newPos.x < max.x && oldPos.x >= max.x && newPos.x > boxCenter.x) newPos.x = max.x; if (newPos.y > min.y && oldPos.y <= min.y && newPos.y < boxCenter.y) newPos.y = min.y; else if (newPos.y < max.y && oldPos.y >= max.y && newPos.y > boxCenter.y) newPos.y = max.y; stopPlayer = true; } } } } if (SDKGameRules()->m_nShieldType == SHIELD_THROWIN && GetFlags() & FL_SHIELD_KEEP_IN) { const int xLength = mp_shield_throwin_movement_x.GetInt(); const int yLength = mp_shield_throwin_movement_y.GetInt(); Vector xSign = SDKGameRules()->m_vShieldPos.GetX() > SDKGameRules()->m_vKickOff.GetX() ? 1 : -1; Vector min = SDKGameRules()->m_vShieldPos + Vector(xSign == -1 ? -xLength : 0, -yLength / 2, 0); Vector max = SDKGameRules()->m_vShieldPos + Vector(xSign == -1 ? 0 : xLength, yLength / 2, 0); bool isInsideBox = newPos.x > min.x && newPos.y > min.y && newPos.x < max.x && newPos.y < max.y; if (!isInsideBox) { if (newPos.x < min.x) newPos.x = min.x; else if (newPos.x > max.x) newPos.x = max.x; if (newPos.y < min.y) newPos.y = min.y; else if (newPos.y > max.y) newPos.y = max.y; stopPlayer = true; } } } if (!SDKGameRules()->IsIntermissionState() && mp_field_padding_enabled.GetBool()) { float border = mp_field_padding.GetInt(); Vector min = SDKGameRules()->m_vFieldMin - border; Vector max = SDKGameRules()->m_vFieldMax + border; if (newPos.x < min.x || newPos.y < min.y || newPos.x > max.x || newPos.y > max.y) { if (newPos.x < min.x) newPos.x = min.x; else if (newPos.x > max.x) newPos.x = max.x; if (newPos.y < min.y) newPos.y = min.y; else if (newPos.y > max.y) newPos.y = max.y; stopPlayer = true; } } if (stopPlayer) { //newVel = oldVel; trace_t trace; UTIL_TraceHull(newPos, newPos, GetPlayerMins(), GetPlayerMaxs(), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER, &trace); if (trace.startsolid) { // Stay at the old pos since the new pos is taken newPos = oldPos; } Vector dir = newPos - oldPos; dir.z = 0; float speed = dir.NormalizeInPlace(); newVel = dir * min(speed * 100, mp_runspeed.GetInt()); //newVel.x = (newPos - oldPos).x * 100; //newVel.y = (newPos - oldPos).y * 100; //newPos = pos; } }
//----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CObjectTeleporter::TeleporterThink( void ) { SetContextThink( &CObjectTeleporter::TeleporterThink, gpGlobals->curtime + BUILD_TELEPORTER_NEXT_THINK, TELEPORTER_THINK_CONTEXT ); // At any point, if our match is not ready, revert to IDLE if ( IsDisabled() || IsRedeploying() || IsMatchingTeleporterReady() == false ) { ShowDirectionArrow( false ); if ( GetState() != TELEPORTER_STATE_IDLE && !IsUpgrading() ) { SetState( TELEPORTER_STATE_IDLE ); CObjectTeleporter *pMatch = GetMatchingTeleporter(); if ( !pMatch ) { // The other end has been destroyed. Revert back to L1. m_iUpgradeLevel = 1; // We need to adjust for any damage received if we downgraded float flHealthPercentage = GetHealth() / GetMaxHealthForCurrentLevel(); SetMaxHealth( GetMaxHealthForCurrentLevel() ); SetHealth( (int)( GetMaxHealthForCurrentLevel() * flHealthPercentage ) ); m_iUpgradeMetal = 0; } } return; } if ( m_flMyNextThink && m_flMyNextThink > gpGlobals->curtime ) return; // pMatch is not NULL and is not building CObjectTeleporter *pMatch = GetMatchingTeleporter(); Assert( pMatch ); Assert( pMatch->m_iState != TELEPORTER_STATE_BUILDING ); switch ( m_iState ) { // Teleporter is not yet active, do nothing case TELEPORTER_STATE_BUILDING: case TELEPORTER_STATE_UPGRADING: ShowDirectionArrow( false ); break; default: case TELEPORTER_STATE_IDLE: // Do we have a match that is active? // Make sure both ends wait through full recharge time in case they get upgraded while recharging. if ( IsMatchingTeleporterReady() && !IsUpgrading() && gpGlobals->curtime > m_flRechargeTime ) { SetState( TELEPORTER_STATE_READY ); EmitSound( "Building_Teleporter.Ready" ); if ( GetObjectMode() == TELEPORTER_TYPE_ENTRANCE ) { ShowDirectionArrow( true ); } } break; case TELEPORTER_STATE_READY: break; case TELEPORTER_STATE_SENDING: { pMatch->TeleporterReceive( m_hTeleportingPlayer, 1.0 ); m_flRechargeTime = gpGlobals->curtime + ( BUILD_TELEPORTER_FADEOUT_TIME + BUILD_TELEPORTER_FADEIN_TIME + g_flTeleporterRechargeTimes[ GetUpgradeLevel() - 1] ); // change state to recharging... SetState( TELEPORTER_STATE_RECHARGING ); } break; case TELEPORTER_STATE_RECEIVING: { // get the position we'll move the player to Vector newPosition = GetAbsOrigin(); newPosition.z += TELEPORTER_MAXS.z + 1; // Telefrag anyone in the way CBaseEntity *pEnts[256]; Vector mins, maxs; Vector expand( 4, 4, 4 ); mins = newPosition + VEC_HULL_MIN - expand; maxs = newPosition + VEC_HULL_MAX + expand; CTFPlayer *pTeleportingPlayer = m_hTeleportingPlayer.Get(); // move the player if ( pTeleportingPlayer ) { CUtlVector<CBaseEntity*> hPlayersToKill; bool bClear = true; // Telefrag any players in the way int numEnts = UTIL_EntitiesInBox( pEnts, 256, mins, maxs, 0 ); if ( numEnts ) { //Iterate through the list and check the results for ( int i = 0; i < numEnts && bClear; i++ ) { if ( pEnts[i] == NULL ) continue; if ( pEnts[i] == this ) continue; // kill players if ( pEnts[i]->IsPlayer() ) { if ( !pTeleportingPlayer->InSameTeam(pEnts[i]) ) { hPlayersToKill.AddToTail( pEnts[i] ); } continue; } if ( pEnts[i]->IsBaseObject() ) continue; // Solid entities will prevent a teleport if ( pEnts[i]->IsSolid() && pEnts[i]->ShouldCollide( pTeleportingPlayer->GetCollisionGroup(), MASK_ALL ) && g_pGameRules->ShouldCollide( pTeleportingPlayer->GetCollisionGroup(), pEnts[i]->GetCollisionGroup() ) ) { // We're going to teleport into something solid. Abort & destroy this exit. bClear = false; } } } if ( bClear ) { // Telefrag all enemy players we've found for ( int player = 0; player < hPlayersToKill.Count(); player++ ) { CTakeDamageInfo info( this, pTeleportingPlayer, 1000, DMG_CRUSH, TF_DMG_TELEFRAG ); hPlayersToKill[player]->TakeDamage( info ); } pTeleportingPlayer->Teleport( &newPosition, &(GetAbsAngles()), &vec3_origin ); // Unzoom if we are a sniper zoomed! if ( ( pTeleportingPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_SNIPER ) && pTeleportingPlayer->m_Shared.InCond( TF_COND_AIMING ) ) { CTFWeaponBase *pWpn = pTeleportingPlayer->GetActiveTFWeapon(); if ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_SNIPERRIFLE ) { CTFSniperRifle *pRifle = static_cast<CTFSniperRifle*>( pWpn ); pRifle->ToggleZoom(); } } pTeleportingPlayer->SetFOV( pTeleportingPlayer, 0, tf_teleporter_fov_time.GetFloat(), tf_teleporter_fov_start.GetInt() ); color32 fadeColor = {255,255,255,100}; UTIL_ScreenFade( pTeleportingPlayer, fadeColor, 0.25, 0.4, FFADE_IN ); } else { DetonateObject(); } } SetState( TELEPORTER_STATE_RECEIVING_RELEASE ); m_flMyNextThink = gpGlobals->curtime + ( BUILD_TELEPORTER_FADEIN_TIME ); } break; case TELEPORTER_STATE_RECEIVING_RELEASE: { CTFPlayer *pTeleportingPlayer = m_hTeleportingPlayer.Get(); if ( pTeleportingPlayer ) { int iTeam = GetBuilder() ? GetBuilder()->GetTeamNumber() : GetTeamNumber(); pTeleportingPlayer->m_Shared.SetTeleporterEffectColor( iTeam ); pTeleportingPlayer->TeleportEffect(); pTeleportingPlayer->m_Shared.RemoveCond( TF_COND_SELECTED_TO_TELEPORT ); if ( !m_bWasMapPlaced && GetBuilder() ) CTF_GameStats.Event_PlayerUsedTeleport( GetBuilder(), pTeleportingPlayer ); IGameEvent * event = gameeventmanager->CreateEvent( "player_teleported" ); if ( event ) { event->SetInt( "userid", pTeleportingPlayer->GetUserID() ); if ( GetBuilder() ) event->SetInt( "builderid", GetBuilder()->GetUserID() ); Vector vecOrigin = GetAbsOrigin(); Vector vecDestinationOrigin = GetMatchingTeleporter()->GetAbsOrigin(); Vector vecDifference = Vector( vecOrigin.x - vecDestinationOrigin.x, vecOrigin.y - vecDestinationOrigin.y, vecOrigin.z - vecDestinationOrigin.z ); float flDist = sqrtf( pow( vecDifference.x, 2 ) + pow( vecDifference.y, 2 ) + pow( vecDifference.z, 2 ) ); event->SetFloat( "dist", flDist ); gameeventmanager->FireEvent( event, true ); } // Don't thank ourselves. if ( pTeleportingPlayer != GetBuilder() ) pTeleportingPlayer->SpeakConceptIfAllowed( MP_CONCEPT_TELEPORTED ); } // reset the pointers to the player now that we're done teleporting SetTeleportingPlayer( NULL ); pMatch->SetTeleportingPlayer( NULL ); SetState( TELEPORTER_STATE_RECHARGING ); m_flMyNextThink = gpGlobals->curtime + ( g_flTeleporterRechargeTimes[ GetUpgradeLevel() - 1 ] ); } break; case TELEPORTER_STATE_RECHARGING: // If we are finished recharging, go active if ( gpGlobals->curtime > m_flRechargeTime ) { SetState( TELEPORTER_STATE_READY ); EmitSound( "Building_Teleporter.Ready" ); } break; } }
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; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFBaseRocket::Explode( trace_t *pTrace, CBaseEntity *pOther ) { // Save this entity as enemy, they will take 100% damage. m_hEnemy = pOther; // Invisible. SetModelName( NULL_STRING ); AddSolidFlags( FSOLID_NOT_SOLID ); m_takedamage = DAMAGE_NO; // Figure out Econ ID. int iItemID = -1; if ( m_hLauncher.Get() ) { CTFWeaponBase *pWeapon = dynamic_cast<CTFWeaponBase *>( m_hLauncher.Get() ); if ( pWeapon ) { iItemID = pWeapon->GetItemID(); } } // Pull out a bit. if ( pTrace->fraction != 1.0 ) { SetAbsOrigin( pTrace->endpos + ( pTrace->plane.normal * 1.0f ) ); } CBaseEntity *pAttacker = GetOwnerEntity(); IScorer *pScorerInterface = dynamic_cast<IScorer*>( pAttacker ); if ( pScorerInterface ) { pAttacker = pScorerInterface->GetScorer(); } // Play explosion sound and effect. Vector vecOrigin = GetAbsOrigin(); CPVSFilter filter( vecOrigin ); bool bCrit = ( GetDamageType() & DMG_CRITICAL ) != 0; TE_TFExplosion( filter, 0.0f, vecOrigin, pTrace->plane.normal, GetWeaponID(), pOther->entindex(), ToBasePlayer( pAttacker ), GetTeamNumber(), bCrit, iItemID ); CSoundEnt::InsertSound( SOUND_COMBAT, vecOrigin, 1024, 3.0 ); // Damage. float flRadius = GetRadius(); CTFRadiusDamageInfo radiusInfo; radiusInfo.info.Set( this, pAttacker, m_hLauncher, vec3_origin, vecOrigin, GetDamage(), GetDamageType() ); radiusInfo.m_vecSrc = vecOrigin; radiusInfo.m_flRadius = flRadius; radiusInfo.m_flSelfDamageRadius = 121.0f; // Original rocket radius? TFGameRules()->RadiusDamage( radiusInfo ); // Debug! if ( tf_rocket_show_radius.GetBool() ) { DrawRadius( flRadius ); } // Don't decal players with scorch. if ( !pOther->IsPlayer() ) { UTIL_DecalTrace( pTrace, "Scorch" ); } // Remove the rocket. UTIL_Remove( this ); }
void CSDKPlayer::FireBullet( Vector vecSrc, // shooting postion const QAngle &shootAngles, //shooting angle float vecSpread, // spread vector SDKWeaponID eWeaponID, // weapon that fired this shot int iDamage, // base damage int iBulletType, // ammo type CBaseEntity *pevAttacker, // shooter bool bDoEffects, // create impact effect ? float x, // spread x factor float y // spread y factor ) { float flCurrentDistance = 0.0; //distance that the bullet has traveled so far Vector vecDirShooting, vecRight, vecUp; AngleVectors( shootAngles, &vecDirShooting, &vecRight, &vecUp ); if ( !pevAttacker ) pevAttacker = this; // the default attacker is ourselves // add the spray Vector vecDir = vecDirShooting + x * vecSpread * vecRight + y * vecSpread * vecUp; VectorNormalize( vecDir ); float flMaxRange = 8000; Vector vecEnd = vecSrc + vecDir * flMaxRange; // max bullet range is 10000 units CBaseEntity* pIgnore = this; // initialize these before the penetration loop, we'll need them to make our tracer after Vector vecTracerSrc = vecSrc; trace_t tr; // main enter bullet trace for (size_t i = 0; i < 5; i++) { CTraceFilterSimpleList tf(COLLISION_GROUP_NONE); tf.AddEntityToIgnore(this); tf.AddEntityToIgnore(pIgnore); UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &tf, &tr ); if ( tr.fraction == 1.0f ) break; // we didn't hit anything, stop tracing shoot if ( sv_showimpacts.GetBool() ) { #ifdef CLIENT_DLL // draw red client impact markers debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawClientHitboxes( 4, true ); } #else // draw blue server impact markers NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawServerHitboxes( 4, true ); } #endif } weapontype_t eWeaponType = WT_NONE; CSDKWeaponInfo *pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo(eWeaponID); Assert(pWeaponInfo); if (pWeaponInfo) eWeaponType = pWeaponInfo->m_eWeaponType; float flDamageMultiplier = 1; float flMaxRange = 3000; // Power formula works like so: // pow( x, distance/y ) // The damage will be at 1 when the distance is 0 units, and at // x% when the distance is y units, with a gradual decay approaching zero switch (eWeaponType) { case WT_RIFLE: flDamageMultiplier = 0.75f; flMaxRange = 3000; break; case WT_SHOTGUN: flDamageMultiplier = 0.40f; flMaxRange = 500; break; case WT_SMG: flDamageMultiplier = 0.50f; flMaxRange = 1000; break; case WT_PISTOL: default: flDamageMultiplier = 0.55f; flMaxRange = 1500; break; } //calculate the damage based on the distance the bullet travelled. flCurrentDistance += tr.fraction * flMaxRange; // First 500 units, no decrease in damage. if (eWeaponType == WT_SHOTGUN) flCurrentDistance -= 350; else flCurrentDistance -= 500; if (flCurrentDistance < 0) flCurrentDistance = 0; if (flCurrentDistance > flMaxRange) flCurrentDistance = flMaxRange; float flDistanceMultiplier = pow(flDamageMultiplier, (flCurrentDistance / flMaxRange)); int iDamageType = DMG_BULLET | DMG_NEVERGIB | GetAmmoDef()->DamageType(iBulletType); if (i == 0) iDamageType |= DMG_DIRECT; if( bDoEffects ) { // See if the bullet ended up underwater + started out of the water if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) { trace_t waterTrace; UTIL_TraceLine( vecSrc, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), pIgnore, COLLISION_GROUP_NONE, &waterTrace ); if( waterTrace.allsolid != 1 ) { CEffectData data; data.m_vOrigin = waterTrace.endpos; data.m_vNormal = waterTrace.plane.normal; data.m_flScale = random->RandomFloat( 8, 12 ); if ( waterTrace.contents & CONTENTS_SLIME ) { data.m_fFlags |= FX_WATER_IN_SLIME; } DispatchEffect( "gunshotsplash", data ); } } else { //Do Regular hit effects // Don't decal nodraw surfaces if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) { CBaseEntity *pEntity = tr.m_pEnt; //Tony; only while using teams do we check for friendly fire. if ( pEntity && pEntity->IsPlayer() && (pEntity->GetBaseAnimating() && !pEntity->GetBaseAnimating()->IsRagdoll()) ) { #if defined ( SDK_USE_TEAMS ) if ( pEntity->GetTeamNumber() == GetTeamNumber() ) { if ( !friendlyfire.GetBool() ) UTIL_ImpactTrace( &tr, iDamageType ); } #else UTIL_ImpactTrace( &tr, iDamageType ); #endif } //Tony; non player, just go nuts, else { UTIL_ImpactTrace( &tr, iDamageType ); } } } } // bDoEffects // add damage to entity that we hit #ifdef GAME_DLL float flBulletDamage = iDamage * flDistanceMultiplier / (i+1); // Each iteration the bullet drops in strength ClearMultiDamage(); CTakeDamageInfo info( pevAttacker, pevAttacker, flBulletDamage, iDamageType ); CalculateBulletDamageForce( &info, iBulletType, vecDir, tr.endpos ); tr.m_pEnt->DispatchTraceAttack( info, vecDir, &tr ); TraceAttackToTriggers( info, tr.startpos, tr.endpos, vecDir ); ApplyMultiDamage(); #else flDistanceMultiplier = flDistanceMultiplier; // Silence warning. #endif pIgnore = tr.m_pEnt; float flPenetrationDistance; switch (eWeaponType) { case WT_RIFLE: flPenetrationDistance = 25; break; case WT_SHOTGUN: flPenetrationDistance = 5; break; case WT_SMG: flPenetrationDistance = 15; break; case WT_PISTOL: default: flPenetrationDistance = 15; break; } Vector vecBackwards = tr.endpos + vecDir * flPenetrationDistance; if (tr.m_pEnt->IsBSPModel()) UTIL_TraceLine( vecBackwards, tr.endpos, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr ); else UTIL_TraceLine( vecBackwards, tr.endpos, CONTENTS_HITBOX, NULL, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid) break; if (tr.m_pEnt) { // let's have a bullet exit effect if we penetrated a solid surface if (tr.m_pEnt->IsBSPModel()) UTIL_ImpactTrace( &tr, iDamageType ); // ignore the entity we just hit for the next trace to avoid weird impact behaviors pIgnore = tr.m_pEnt; } // Set up the next trace. vecSrc = tr.endpos + vecDir; // One unit in the direction of fire so that we firmly embed ourselves in whatever solid was hit. } // the bullet's done penetrating, let's spawn our particle system if (bDoEffects && (pevAttacker == this)) MakeTracer( vecTracerSrc, tr, TRACER_TYPE_DEFAULT ); }
//----------------------------------------------------------------------------- // Purpose: Checks to see if it's time to change controllers //----------------------------------------------------------------------------- void CControlZone::ReevaluateControllingTeam( void ) { // Count the number of players in each team int i; memset( m_iPlayersInZone, 0, sizeof( m_iPlayersInZone ) ); for ( i = 0; i < m_ZonePlayerList.Size(); i++ ) { if ( m_ZonePlayerList[i] != NULL && (m_ZonePlayerList[i]->GetTeamNumber() > 0) ) { m_iPlayersInZone[ m_ZonePlayerList[i]->GetTeamNumber() ] += 1; } } // Abort immediately if we're not using touches to changes teams if ( HasSpawnFlags( CZF_DONT_USE_TOUCHES ) ) return; // if we're locked in place, no changes can occur to controlling team except through an explicit map ResetTeam if ( m_iLocked ) return; bool foundAnyTeam = false; int teamFound = 0; // check to see if any teams have no players for ( i = 1; i <= GetNumberOfTeams(); i++ ) { if ( m_iPlayersInZone[i] ) { if ( foundAnyTeam ) { // we've already found a team, so it's being contested; teamFound = ZONE_CONTESTED; break; } foundAnyTeam = true; teamFound = i; } } // no one in the area! if ( teamFound == 0 ) { // just leave it as it is, let it continue to change team // exception: if the zone state is contested, and there aren't any players in the zone, // just return to the team who used to own the zone. if ( GetTeamNumber() == ZONE_CONTESTED ) { ChangeTeam(m_iDefendingTeam); SetControllingTeam( this, m_iDefendingTeam ); } return; } // if it's the same controlling team, don't worry about it if ( teamFound == GetTeamNumber() ) { // the right team is in control, don't even think of switching m_iTryingToChangeToTeam = 0; SetNextThink( TICK_NEVER_THINK ); return; } // Find out if the zone isn't owned by anyone at all (hasn't been touched since the map started, and it started un-owned) bool bHasBeenOwned = true; if ( m_iDefendingTeam == 0 && GetTeamNumber() == 0 ) bHasBeenOwned = false; // if it's not contested, always go to contested mode if ( GetTeamNumber() != ZONE_CONTESTED && teamFound != GetTeamNumber() ) { // Unowned zones are captured immediately (no contesting stage) if ( bHasBeenOwned ) teamFound = ZONE_CONTESTED; } // if it's the team we're trying to change to, don't worry about it if ( teamFound == m_iTryingToChangeToTeam ) return; // set up the time to change to the new team soon m_iTryingToChangeToTeam = teamFound; // changing from contested->uncontested and visa-versa have different delays if ( m_iTryingToChangeToTeam != ZONE_CONTESTED ) { if ( !bHasBeenOwned ) { DevMsg( 1, "trigger_controlzone: (%s) changing team to %d NOW\n", GetDebugName(), m_iTryingToChangeToTeam ); SetNextThink( gpGlobals->curtime + 0.1f ); } else { DevMsg( 1, "trigger_controlzone: (%s) changing team to %d in %.2f seconds\n", GetDebugName(), m_iTryingToChangeToTeam, m_flTimeTillCaptured ); SetNextThink( gpGlobals->curtime + m_flTimeTillCaptured ); } } else { DevMsg( 1, "trigger_controlzone: (%s) changing to contested in %f seconds\n", GetDebugName(), m_flTimeTillContested ); SetNextThink( gpGlobals->curtime + m_flTimeTillContested ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CObjectSentrygun::ValidTargetPlayer( CTFPlayer *pPlayer, const Vector &vecStart, const Vector &vecEnd ) { // Keep shooting at spies that go invisible after we acquire them as a target. if ( pPlayer->m_Shared.GetPercentInvisible() > 0.5 ) return false; // Keep shooting at spies that disguise after we acquire them as at a target. if ( pPlayer->m_Shared.InCond( TF_COND_DISGUISED ) && pPlayer->m_Shared.GetDisguiseTeam() == GetTeamNumber() && pPlayer != m_hEnemy ) return false; // Not across water boundary. if ( ( GetWaterLevel() == 0 && pPlayer->GetWaterLevel() >= 3 ) || ( GetWaterLevel() == 3 && pPlayer->GetWaterLevel() <= 0 ) ) return false; // Ray trace!!! return FVisible( pPlayer, MASK_SHOT | CONTENTS_GRATE ); }
bool CSDKPlayer::ClientCommand( const CCommand &args ) { const char *pcmd = args[0]; if ( FStrEq( pcmd, "jointeam" ) ) { if ( args.ArgC() < 2 ) { Warning( "Player sent bad jointeam syntax\n" ); } int iTeam = atoi( args[1] ); HandleCommand_JoinTeam( iTeam ); return true; } else if( !Q_strncmp( pcmd, "cls_", 4 ) ) { #if defined ( SDK_USE_PLAYERCLASSES ) CSDKTeam *pTeam = GetGlobalSDKTeam( GetTeamNumber() ); Assert( pTeam ); int iClassIndex = PLAYERCLASS_UNDEFINED; if( pTeam->IsClassOnTeam( pcmd, iClassIndex ) ) { HandleCommand_JoinClass( iClassIndex ); } else { DevMsg( "player tried to join a class that isn't on this team ( %s )\n", pcmd ); ShowClassSelectMenu(); } #endif return true; } else if ( FStrEq( pcmd, "spectate" ) ) { // instantly join spectators HandleCommand_JoinTeam( TEAM_SPECTATOR ); return true; } else if ( FStrEq( pcmd, "joingame" ) ) { // player just closed MOTD dialog if ( m_iPlayerState == STATE_WELCOME ) { //Tony; using teams, go to picking team. #if defined( SDK_USE_TEAMS ) State_Transition( STATE_PICKINGTEAM ); //Tony; not using teams, but we are using classes, so go straight to class picking. #elif !defined ( SDK_USE_TEAMS ) && defined ( SDK_USE_PLAYERCLASSES ) State_Transition( STATE_PICKINGCLASS ); //Tony; not using teams or classes, go straight to active. #else State_Transition( STATE_ACTIVE ); #endif } return true; } else if ( FStrEq( pcmd, "joinclass" ) ) { #if defined ( SDK_USE_PLAYERCLASSES ) if ( args.ArgC() < 2 ) { Warning( "Player sent bad joinclass syntax\n" ); } int iClass = atoi( args[1] ); HandleCommand_JoinClass( iClass ); #endif return true; } else if ( FStrEq( pcmd, "menuopen" ) ) { #if defined ( SDK_USE_PLAYERCLASSES ) SetClassMenuOpen( true ); #endif return true; } else if ( FStrEq( pcmd, "menuclosed" ) ) { #if defined ( SDK_USE_PLAYERCLASSES ) SetClassMenuOpen( false ); #endif return true; } else if ( FStrEq( pcmd, "droptest" ) ) { ThrowActiveWeapon(); return true; } return BaseClass::ClientCommand( args ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_BaseObject::HighlightBuildPoints( int flags ) { C_TFPlayer *pLocal = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocal ) return; if ( !GetNumBuildPoints() || !InLocalTeam() ) return; C_TFWeaponBuilder *pBuilderWpn = dynamic_cast< C_TFWeaponBuilder * >( pLocal->GetActiveWeaponForSelection() ); if ( !pBuilderWpn ) return; if ( !pBuilderWpn->IsPlacingObject() ) return; C_BaseObject *pPlacementObj = pBuilderWpn->GetPlacementModel(); if ( !pPlacementObj || pPlacementObj == this ) return; // Near enough? if ( (GetAbsOrigin() - pLocal->GetAbsOrigin()).LengthSqr() < MAX_VISIBLE_BUILDPOINT_DISTANCE ) { bool bRestoreModel = false; Vector vecPrevAbsOrigin = pPlacementObj->GetAbsOrigin(); QAngle vecPrevAbsAngles = pPlacementObj->GetAbsAngles(); Vector orgColor; render->GetColorModulation( orgColor.Base() ); float orgBlend = render->GetBlend(); bool bSameTeam = ( pPlacementObj->GetTeamNumber() == GetTeamNumber() ); if ( pPlacementObj->IsHostileUpgrade() && bSameTeam ) { // Don't hilight hostile upgrades on friendly objects return; } else if ( !bSameTeam ) { // Don't hilight upgrades on enemy objects return; } // Any empty buildpoints? for ( int i = 0; i < GetNumBuildPoints(); i++ ) { // Can this object build on this point? if ( CanBuildObjectOnBuildPoint( i, pPlacementObj->GetType() ) ) { Vector vecBPOrigin; QAngle vecBPAngles; if ( GetBuildPoint(i, vecBPOrigin, vecBPAngles) ) { pPlacementObj->InvalidateBoneCaches(); Vector color( 0, 255, 0 ); render->SetColorModulation( color.Base() ); float frac = fmod( gpGlobals->curtime, 3 ); frac *= 2 * M_PI; frac = cos( frac ); render->SetBlend( (175 + (int)( frac * 75.0f )) / 255.0 ); // FIXME: This truly sucks! The bone cache should use // render location for this computation instead of directly accessing AbsAngles // Necessary for bone cache computations to work pPlacementObj->SetAbsOrigin( vecBPOrigin ); pPlacementObj->SetAbsAngles( vecBPAngles ); modelrender->DrawModel( flags, pPlacementObj, pPlacementObj->GetModelInstance(), pPlacementObj->index, pPlacementObj->GetModel(), vecBPOrigin, vecBPAngles, pPlacementObj->m_nSkin, pPlacementObj->m_nBody, pPlacementObj->m_nHitboxSet ); bRestoreModel = true; } } } if ( bRestoreModel ) { pPlacementObj->SetAbsOrigin(vecPrevAbsOrigin); pPlacementObj->SetAbsAngles(vecPrevAbsAngles); pPlacementObj->InvalidateBoneCaches(); render->SetColorModulation( orgColor.Base() ); render->SetBlend( orgBlend ); } } }
//Tony; we don't have to check anything special for SDK_USE_TEAMS here; it's all pretty generic, except for the one assert. bool CSDKPlayer::HandleCommand_JoinClass( int iClass ) { Assert( GetTeamNumber() != TEAM_SPECTATOR ); #if defined ( SDK_USE_TEAMS ) Assert( GetTeamNumber() != TEAM_UNASSIGNED ); #endif if( GetTeamNumber() == TEAM_SPECTATOR ) return false; if( iClass == PLAYERCLASS_UNDEFINED ) return false; //they typed in something weird int iOldPlayerClass = m_Shared.DesiredPlayerClass(); // See if we're joining the class we already are if( iClass == iOldPlayerClass ) return true; if( !SDKGameRules()->IsPlayerClassOnTeam( iClass, GetTeamNumber() ) ) return false; const char *classname = SDKGameRules()->GetPlayerClassName( iClass, GetTeamNumber() ); if( SDKGameRules()->CanPlayerJoinClass( this, iClass ) ) { m_Shared.SetDesiredPlayerClass( iClass ); //real class value is set when the player spawns //Tony; don't do this until we have a spawn timer!! // if( State_Get() == STATE_PICKINGCLASS ) // State_Transition( STATE_OBSERVER_MODE ); if( iClass == PLAYERCLASS_RANDOM ) { if( IsAlive() ) { ClientPrint(this, HUD_PRINTTALK, "#game_respawn_asrandom" ); } else { ClientPrint(this, HUD_PRINTTALK, "#game_spawn_asrandom" ); } } else { if( IsAlive() ) { ClientPrint(this, HUD_PRINTTALK, "#game_respawn_as", classname ); } else { ClientPrint(this, HUD_PRINTTALK, "#game_spawn_as", classname ); } } IGameEvent * event = gameeventmanager->CreateEvent( "player_changeclass" ); if ( event ) { event->SetInt( "userid", GetUserID() ); event->SetInt( "class", iClass ); gameeventmanager->FireEvent( event ); } } else { ClientPrint(this, HUD_PRINTTALK, "#game_class_limit", classname ); ShowClassSelectMenu(); } // Incase we don't get the class menu message before the spawn timer // comes up, fake that we've closed the menu. SetClassMenuOpen( false ); //Tony; TODO; this is temp, I may integrate with the teamplayroundrules; If I do, there will be wavespawn too. if ( State_Get() == STATE_PICKINGCLASS /*|| IsDead()*/ ) //Tony; undone, don't transition if dead; only go into active state at this point if we were picking class. State_Transition( STATE_ACTIVE ); //Done picking stuff and we're in the pickingclass state, or dead, so we can spawn now. return true; }
int CSDKPlayer::OnTakeDamage( const CTakeDamageInfo &inputInfo ) { CTakeDamageInfo info = inputInfo; CBaseEntity *pInflictor = info.GetInflictor(); if ( !pInflictor ) return 0; if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) return 0; float flArmorBonus = 0.5f; float flArmorRatio = 0.5f; float flDamage = info.GetDamage(); bool bCheckFriendlyFire = false; bool bFriendlyFire = friendlyfire.GetBool(); //Tony; only check teams in teamplay if ( gpGlobals->teamplay ) bCheckFriendlyFire = true; if ( bFriendlyFire || ( bCheckFriendlyFire && pInflictor->GetTeamNumber() != GetTeamNumber() ) || pInflictor == this || info.GetAttacker() == this ) { if ( bFriendlyFire && (info.GetDamageType() & DMG_BLAST) == 0 ) { if ( pInflictor->GetTeamNumber() == GetTeamNumber() && bCheckFriendlyFire) { flDamage *= 0.35; // bullets hurt teammates less } } // keep track of amount of damage last sustained m_lastDamageAmount = flDamage; // Deal with Armour if ( ArmorValue() && !( info.GetDamageType() & (DMG_FALL | DMG_DROWN)) ) { float flNew = flDamage * flArmorRatio; float flArmor = (flDamage - flNew) * flArmorBonus; // Does this use more armor than we have? if (flArmor > ArmorValue() ) { //armorHit = (int)(flArmor); flArmor = ArmorValue(); flArmor *= (1/flArmorBonus); flNew = flDamage - flArmor; SetArmorValue( 0 ); } else { int oldValue = (int)(ArmorValue()); if ( flArmor < 0 ) flArmor = 1; SetArmorValue( oldValue - flArmor ); //armorHit = oldValue - (int)(pev->armorvalue); } flDamage = flNew; info.SetDamage( flDamage ); } // round damage to integer info.SetDamage( (int)flDamage ); if ( info.GetDamage() <= 0 ) return 0; CSingleUserRecipientFilter user( this ); user.MakeReliable(); UserMessageBegin( user, "Damage" ); WRITE_BYTE( (int)info.GetDamage() ); WRITE_VEC3COORD( info.GetInflictor()->WorldSpaceCenter() ); MessageEnd(); // Do special explosion damage effect if ( info.GetDamageType() & DMG_BLAST ) { OnDamagedByExplosion( info ); } gamestats->Event_PlayerDamage( this, info ); return CBaseCombatCharacter::OnTakeDamage( info ); } else { return 0; } }
// returns true if the selection has been handled and the player's menu // can be closed...false if the menu should be displayed again bool CSDKPlayer::HandleCommand_JoinTeam( int team ) { CSDKGameRules *mp = SDKGameRules(); int iOldTeam = GetTeamNumber(); if ( !GetGlobalTeam( team ) ) { Warning( "HandleCommand_JoinTeam( %d ) - invalid team index.\n", team ); return false; } #if defined ( SDK_USE_TEAMS ) // If we already died and changed teams once, deny if( m_bTeamChanged && team != TEAM_SPECTATOR && iOldTeam != TEAM_SPECTATOR ) { ClientPrint( this, HUD_PRINTCENTER, "game_switch_teams_once" ); return true; } #endif if ( team == TEAM_UNASSIGNED ) { // Attempt to auto-select a team, may set team to T, CT or SPEC team = mp->SelectDefaultTeam(); if ( team == TEAM_UNASSIGNED ) { // still team unassigned, try to kick a bot if possible ClientPrint( this, HUD_PRINTTALK, "#All_Teams_Full" ); team = TEAM_SPECTATOR; } } if ( team == iOldTeam ) return true; // we wouldn't change the team #if defined ( SDK_USE_TEAMS ) if ( mp->TeamFull( team ) ) { if ( team == SDK_TEAM_BLUE ) { ClientPrint( this, HUD_PRINTTALK, "#BlueTeam_Full" ); } else if ( team == SDK_TEAM_RED ) { ClientPrint( this, HUD_PRINTTALK, "#RedTeam_Full" ); } ShowViewPortPanel( PANEL_TEAM ); return false; } #endif if ( team == TEAM_SPECTATOR ) { // Prevent this if the cvar is set if ( !mp_allowspectators.GetInt() && !IsHLTV() ) { ClientPrint( this, HUD_PRINTTALK, "#Cannot_Be_Spectator" ); ShowViewPortPanel( PANEL_TEAM ); return false; } ChangeTeam( TEAM_SPECTATOR ); return true; } // If the code gets this far, the team is not TEAM_UNASSIGNED // Player is switching to a new team (It is possible to switch to the // same team just to choose a new appearance) #if defined ( SDK_USE_TEAMS ) if (mp->TeamStacked( team, GetTeamNumber() ))//players are allowed to change to their own team so they can just change their model { // The specified team is full ClientPrint( this, HUD_PRINTCENTER, ( team == SDK_TEAM_BLUE ) ? "#BlueTeam_full" : "#RedTeam_full" ); ShowViewPortPanel( PANEL_TEAM ); return false; } #endif // Switch their actual team... ChangeTeam( team ); #if defined ( SDK_USE_PLAYERCLASSES ) // Force them to choose a new class m_Shared.SetDesiredPlayerClass( PLAYERCLASS_UNDEFINED ); m_Shared.SetPlayerClass( PLAYERCLASS_UNDEFINED ); #endif return true; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponKritzkrieg::UpdateEffects( void ) { CTFPlayer *pFiringPlayer = ToTFPlayer( GetOwnerEntity() ); if ( !pFiringPlayer ) return; C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); C_BaseEntity *pEffectOwner = this; if ( pLocalPlayer == pFiringPlayer ) { pEffectOwner = pLocalPlayer->GetViewModel(); if ( !pEffectOwner ) return; } // Remove all the effects if ( pEffectOwner ) { pEffectOwner->ParticleProp()->StopEmission( m_hHealingTargetEffect.pEffect ); } else { m_hHealingTargetEffect.pEffect->StopEmission(); } m_hHealingTargetEffect.pTarget = NULL; m_hHealingTargetEffect.pEffect = NULL; // Don't add targets if the medic is dead if ( !pEffectOwner || pFiringPlayer->IsPlayerDead() || !pFiringPlayer->IsPlayerClass( TF_CLASS_MEDIC ) ) return; // Add our targets // Loops through the healing targets, and make sure we have an effect for each of them if ( m_hHealingTarget ) { if ( m_hHealingTargetEffect.pTarget == m_hHealingTarget ) return; const char *pszEffectName; if (m_bChargeRelease) { switch (GetTeamNumber()) { case TF_TEAM_BLUE: pszEffectName = "kritz_beam_blue_invun"; break; case TF_TEAM_RED: pszEffectName = "kritz_beam_red_invun"; break; case TF_TEAM_GREEN: pszEffectName = "kritz_beam_green_invun"; break; case TF_TEAM_YELLOW: pszEffectName = "kritz_beam_yellow_invun"; break; default: pszEffectName = "kritz_beam_blue"; break; } } else { switch (GetTeamNumber()) { case TF_TEAM_BLUE: pszEffectName = "kritz_beam_blue"; break; case TF_TEAM_RED: pszEffectName = "kritz_beam_red"; break; case TF_TEAM_GREEN: pszEffectName = "kritz_beam_green"; break; case TF_TEAM_YELLOW: pszEffectName = "kritz_beam_yellow"; break; default: pszEffectName = "kritz_beam_blue"; break; } } CNewParticleEffect *pEffect = pEffectOwner->ParticleProp()->Create( pszEffectName, PATTACH_POINT_FOLLOW, "muzzle" ); pEffectOwner->ParticleProp()->AddControlPoint( pEffect, 1, m_hHealingTarget, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector(0,0,50) ); m_hHealingTargetEffect.pTarget = m_hHealingTarget; m_hHealingTargetEffect.pEffect = pEffect; } }
void C_CFPlayer::Spawn() { BaseClass::Spawn(); if (GetTeamNumber() == TEAM_SPECTATOR || GetTeamNumber() == TEAM_UNASSIGNED) cfgui::CRootPanel::SetArmament(m_pArmament); else cfgui::CRootPanel::SetArmament(m_pCurrentArmament); if (IsLocalPlayer()) { switch (cvar->FindVar("cl_thirdperson")->GetInt()) { case 0: CFInput()->CAM_ToFirstPerson(); break; case 1: CFInput()->CAM_ToThirdPerson(); break; case 2: if (GetActiveArmament()->GetWeaponData(0) && GetActiveArmament()->GetWeaponData(0)->m_eWeaponType == WEAPONTYPE_MELEE) CFInput()->CAM_ToThirdPerson(); else CFInput()->CAM_ToFirstPerson(); break; } } m_flLastRespawn = gpGlobals->curtime; m_flLastEnemySeen = 0; m_flLastCameraTargetTime = 0; Instructor_Respawn(); m_hDrawingDirectTarget = NULL; m_hDrawingRecursedTarget = NULL; m_flReceivedDirectTarget = 0; m_flReceivedRecursedTarget = 0; m_eLHEffectElementsOld = ELEMENT_TYPELESS; m_eRHEffectElementsOld = ELEMENT_TYPELESS; m_iLastCombo = 0; m_pLHChargeEffect = m_pRHChargeEffect = NULL; for (int i = 0; i < m_apLHComboEffects.Count(); i++) { ParticleProp()->StopEmission(m_apLHComboEffects[i]); ParticleProp()->StopEmission(m_apRHComboEffects[i]); } m_apLHComboEffects.RemoveAll(); m_apRHComboEffects.RemoveAll(); if (!m_pBarrier) { m_pBarrier = new C_BaseAnimatingOverlay(); m_pBarrier->InitializeAsClientEntity( "models/magic/barrier.mdl", RENDER_GROUP_OPAQUE_ENTITY ); m_pBarrier->UseClientSideAnimation(); m_pBarrier->SetModel("models/magic/barrier.mdl"); m_pBarrier->AddEffects( EF_NODRAW ); // don't let the renderer draw the model normally m_pBarrier->SetOwnerEntity(this); } m_flShieldTime = 0; m_flShieldStrength = 0; }
void CDODPlayer::FireBullets( const FireBulletsInfo_t &info ) { trace_t tr; trace_t reverseTr; //Used to find exit points static int iMaxPenetrations = 6; int iPenetrations = 0; float flDamage = info.m_iDamage; //Remaining damage in the bullet Vector vecSrc = info.m_vecSrc; Vector vecEnd = vecSrc + info.m_vecDirShooting * info.m_flDistance; static int iTraceMask = ( ( MASK_SOLID | CONTENTS_DEBRIS | CONTENTS_HITBOX | CONTENTS_PRONE_HELPER ) & ~CONTENTS_GRATE ); CBaseEntity *pLastHitEntity = this; // start with us so we don't trace ourselves int iDamageType = GetAmmoDef()->DamageType( info.m_iAmmoType ); int iCollisionGroup = COLLISION_GROUP_NONE; #ifdef GAME_DLL bool iNumHeadshots = 0; #endif while ( flDamage > 0 && iPenetrations < iMaxPenetrations ) { //DevMsg( 2, "penetration: %d, starting dmg: %.1f\n", iPenetrations, flDamage ); CBaseEntity *pPreviousHit = pLastHitEntity; // skip the shooter always CTraceFilterSkipTwoEntities ignoreShooterAndPrevious( this, pPreviousHit, iCollisionGroup ); UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &ignoreShooterAndPrevious, &tr ); const float rayExtension = 40.0f; UTIL_ClipTraceToPlayers( vecSrc, vecEnd + info.m_vecDirShooting * rayExtension, iTraceMask, &ignoreShooterAndPrevious, &tr ); if ( tr.fraction == 1.0f ) break; // we didn't hit anything, stop tracing shoot // New hitbox code that uses hitbox groups instead of trying to trace // through the player if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { switch( tr.hitgroup ) { #ifdef GAME_DLL case HITGROUP_HEAD: { if ( tr.m_pEnt->GetTeamNumber() != GetTeamNumber() ) { iNumHeadshots++; } } break; #endif case HITGROUP_LEFTARM: case HITGROUP_RIGHTARM: { //DevMsg( 2, "Hit arms, tracing against alt hitboxes.. \n" ); CDODPlayer *pPlayer = ToDODPlayer( tr.m_pEnt ); // set hitbox set to "dod_no_arms" pPlayer->SetHitboxSet( 1 ); trace_t newTr; // re-fire the trace UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &ignoreShooterAndPrevious, &newTr ); // if we hit the same player in the chest if ( tr.m_pEnt == newTr.m_pEnt ) { //DevMsg( 2, ".. and we hit the chest.\n" ); Assert( tr.hitgroup != newTr.hitgroup ); // If we hit this, hitbox sets are broken // use that damage instead tr = newTr; } // set hitboxes back to "dod" pPlayer->SetHitboxSet( 0 ); } break; default: break; } } pLastHitEntity = tr.m_pEnt; if ( sv_showimpacts.GetBool() ) { #ifdef CLIENT_DLL // draw red client impact markers debugoverlay->AddBoxOverlay( tr.endpos, Vector(-1,-1,-1), Vector(1,1,1), QAngle(0,0,0), 255, 0, 0, 127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawClientHitboxes( 4, true ); } #else // draw blue server impact markers NDebugOverlay::Box( tr.endpos, Vector(-1,-1,-1), Vector(1,1,1), 0,0,255,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawServerHitboxes( 4, true ); } #endif } #ifdef CLIENT_DLL // See if the bullet ended up underwater + started out of the water if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) { trace_t waterTrace; UTIL_TraceLine( vecSrc, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), this, iCollisionGroup, &waterTrace ); if( waterTrace.allsolid != 1 ) { CEffectData data; data.m_vOrigin = waterTrace.endpos; data.m_vNormal = waterTrace.plane.normal; data.m_flScale = random->RandomFloat( 8, 12 ); if ( waterTrace.contents & CONTENTS_SLIME ) { data.m_fFlags |= FX_WATER_IN_SLIME; } DispatchEffect( "gunshotsplash", data ); } } else { //Do Regular hit effects // Don't decal nodraw surfaces if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) { CBaseEntity *pEntity = tr.m_pEnt; if ( !( !friendlyfire.GetBool() && pEntity && pEntity->GetTeamNumber() == GetTeamNumber() ) ) { UTIL_ImpactTrace( &tr, iDamageType ); } } } #endif // Get surface where the bullet entered ( if it had different surfaces on enter and exit ) surfacedata_t *pSurfaceData = physprops->GetSurfaceData( tr.surface.surfaceProps ); Assert( pSurfaceData ); float flMaterialMod = GetDensityFromMaterial(pSurfaceData); if ( iDamageType & DMG_MACHINEGUN ) { flMaterialMod *= 0.65; } // try to penetrate object Vector penetrationEnd; float flMaxDistance = flDamage / flMaterialMod; #ifndef CLIENT_DLL ClearMultiDamage(); float flActualDamage = flDamage; CTakeDamageInfo dmgInfo( info.m_pAttacker, info.m_pAttacker, flActualDamage, iDamageType ); CalculateBulletDamageForce( &dmgInfo, info.m_iAmmoType, info.m_vecDirShooting, tr.endpos ); tr.m_pEnt->DispatchTraceAttack( dmgInfo, info.m_vecDirShooting, &tr ); DevMsg( 2, "Giving damage ( %.1f ) to entity of type %s\n", flActualDamage, tr.m_pEnt->GetClassname() ); TraceAttackToTriggers( dmgInfo, tr.startpos, tr.endpos, info.m_vecDirShooting ); #endif int stepsize = 16; // displacement always stops the bullet if ( tr.IsDispSurface() ) { DevMsg( 2, "bullet was stopped by displacement\n" ); ApplyMultiDamage(); break; } // trace through the solid to find the exit point and how much material we went through if ( !TraceToExit( tr.endpos, info.m_vecDirShooting, penetrationEnd, stepsize, flMaxDistance ) ) { DevMsg( 2, "bullet was stopped\n" ); ApplyMultiDamage(); break; } // find exact penetration exit CTraceFilterSimple ignoreShooter( this, iCollisionGroup ); UTIL_TraceLine( penetrationEnd, tr.endpos, iTraceMask, &ignoreShooter, &reverseTr ); // Now we can apply the damage, after we have traced the entity // so it doesn't break or die before we have a change to test against it #ifndef CLIENT_DLL ApplyMultiDamage(); #endif // Continue looking for the exit point if( reverseTr.m_pEnt != tr.m_pEnt && reverseTr.m_pEnt != NULL ) { // something was blocking, trace again CTraceFilterSkipTwoEntities ignoreShooterAndBlocker( this, reverseTr.m_pEnt, iCollisionGroup ); UTIL_TraceLine( penetrationEnd, tr.endpos, iTraceMask, &ignoreShooterAndBlocker, &reverseTr ); } if ( sv_showimpacts.GetBool() ) { debugoverlay->AddLineOverlay( penetrationEnd, reverseTr.endpos, 255, 0, 0, true, 3.0 ); } // penetration was successful #ifdef CLIENT_DLL // bullet did penetrate object, exit Decal if ( !( reverseTr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) { CBaseEntity *pEntity = reverseTr.m_pEnt; if ( !( !friendlyfire.GetBool() && pEntity && pEntity->GetTeamNumber() == GetTeamNumber() ) ) { UTIL_ImpactTrace( &reverseTr, iDamageType ); } } #endif //setup new start end parameters for successive trace // New start point is our last exit point vecSrc = reverseTr.endpos + /* 1.0 * */ info.m_vecDirShooting; // Reduce bullet damage by material and distanced travelled through that material // if it is < 0 we won't go through the loop again float flTraceDistance = VectorLength( reverseTr.endpos - tr.endpos ); flDamage -= flMaterialMod * flTraceDistance; if( flDamage > 0 ) { DevMsg( 2, "Completed penetration, new damage is %.1f\n", flDamage ); } else { DevMsg( 2, "bullet was stopped\n" ); } iPenetrations++; } #ifdef GAME_DLL HandleHeadshotAchievement( iNumHeadshots ); #endif }
void CTeamTrainWatcher::WatcherThink( void ) { if ( m_bWaitingToRecede ) { if ( m_flRecedeTime < gpGlobals->curtime ) { m_bWaitingToRecede = false; // don't actually recede in overtime if ( TeamplayRoundBasedRules() && !TeamplayRoundBasedRules()->InOvertime() ) { // fire recede output m_OnTrainStartRecede.FireOutput( this, this ); HandleTrainMovement( true ); } } } bool bDisableAlarm = (TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->State_Get() != GR_STATE_RND_RUNNING); if ( bDisableAlarm ) { StopCaptureAlarm(); } // given its next node, we can walk the nodes and find the linear // distance to the next cp node, or to the goal node CFuncTrackTrain *pTrain = m_hTrain; if ( pTrain ) { int iOldTrainSpeedLevel = m_iTrainSpeedLevel; // how fast is the train moving? float flSpeed = pTrain->GetDesiredSpeed(); // divide speed into regions // anything negative is -1 if ( flSpeed < 0 ) { m_iTrainSpeedLevel = -1; // even though our desired speed might be negative, // our actual speed might be zero if we're at a dead end... // this will turn off the < image when the train is done moving backwards if ( pTrain->GetCurrentSpeed() == 0 ) { m_iTrainSpeedLevel = 0; } } else if ( flSpeed > m_flSpeedLevels[2] ) { m_iTrainSpeedLevel = 3; } else if ( flSpeed > m_flSpeedLevels[1] ) { m_iTrainSpeedLevel = 2; } else if ( flSpeed > m_flSpeedLevels[0] ) { m_iTrainSpeedLevel = 1; } else { m_iTrainSpeedLevel = 0; } if ( m_iTrainSpeedLevel != iOldTrainSpeedLevel ) { // make sure the sparks are off if we're not moving backwards anymore if ( m_bHandleTrainMovement ) { if ( m_iTrainSpeedLevel == 0 && iOldTrainSpeedLevel != 0 ) { HandleSparks( false ); } } // play any concepts that we might need to play if ( TeamplayRoundBasedRules() ) { if ( m_iTrainSpeedLevel == 0 && iOldTrainSpeedLevel != 0 ) { TeamplayRoundBasedRules()->HaveAllPlayersSpeakConceptIfAllowed( MP_CONCEPT_CART_STOP ); m_flNextSpeakForwardConceptTime = 0; } else if ( m_iTrainSpeedLevel < 0 && iOldTrainSpeedLevel == 0 ) { TeamplayRoundBasedRules()->HaveAllPlayersSpeakConceptIfAllowed( MP_CONCEPT_CART_MOVING_BACKWARD ); m_flNextSpeakForwardConceptTime = 0; } } } if ( m_iTrainSpeedLevel > 0 && m_flNextSpeakForwardConceptTime < gpGlobals->curtime ) { if ( m_hAreaCap.Get() ) { for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( i ) ); if ( pPlayer ) { if ( m_hAreaCap->IsTouching( pPlayer ) ) { pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_CART_MOVING_FORWARD ); } } } } m_flNextSpeakForwardConceptTime = gpGlobals->curtime + 3.0; } // what percent progress are we at? CPathTrack *pNode = ( pTrain->m_ppath ) ? pTrain->m_ppath->GetNext() : NULL; // if we're moving backwards, GetNext is going to be wrong if ( flSpeed < 0 ) { pNode = pTrain->m_ppath; } if ( pNode ) { float flDistanceToGoal = 0; // distance to next node Vector vecDir = pNode->GetLocalOrigin() - pTrain->GetLocalOrigin(); flDistanceToGoal = vecDir.Length(); // distance of next node to goal node if ( pNode && pNode != m_hGoalNode ) { // walk this until we get to goal node, or a dead end CPathTrack *pPrev = pNode; pNode = pNode->GetNext(); while ( pNode ) { vecDir = pNode->GetLocalOrigin() - pPrev->GetLocalOrigin(); flDistanceToGoal += vecDir.Length(); if ( pNode == m_hGoalNode ) break; pPrev = pNode; pNode = pNode->GetNext(); } } if ( m_flTotalPathDistance <= 0 ) { Assert( !"No path distance in team_train_watcher\n" ); m_flTotalPathDistance = 1; } m_flTotalProgress = clamp( 1.0 - ( flDistanceToGoal / m_flTotalPathDistance ), 0.0, 1.0 ); m_flTrainDistanceFromStart = m_flTotalPathDistance - flDistanceToGoal; // play alert sounds if necessary for ( int iCount = 0 ; iCount < m_iNumCPLinks ; iCount++ ) { if ( m_flTrainDistanceFromStart < m_CPLinks[iCount].flDistanceFromStart - TEAM_TRAIN_ALERT_DISTANCE ) { // back up twice the alert distance before resetting our flag to play the warning again if ( ( m_flTrainDistanceFromStart < m_CPLinks[iCount].flDistanceFromStart - ( TEAM_TRAIN_ALERT_DISTANCE * 2 ) ) || // has receded back twice the alert distance or... ( !m_bTrainCanRecede ) ) // used to catch the case where the train doesn't normally recede but has rolled back down a hill away from the CP { // reset our alert flag m_CPLinks[iCount].bAlertPlayed = false; } } else { if ( m_flTrainDistanceFromStart < m_CPLinks[iCount].flDistanceFromStart && !m_CPLinks[iCount].bAlertPlayed ) { m_CPLinks[iCount].bAlertPlayed = true; bool bFinalPointInMap = false; CTeamControlPoint *pCurrentPoint = m_CPLinks[iCount].hCP.Get(); CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; if ( pMaster ) { // if we're not playing mini-rounds if ( !pMaster->PlayingMiniRounds() ) { for ( int i = FIRST_GAME_TEAM ; i < MAX_CONTROL_POINT_TEAMS ; i++ ) { if ( ObjectiveResource() && ObjectiveResource()->TeamCanCapPoint( pCurrentPoint->GetPointIndex(), i ) ) { if ( pMaster->WouldNewCPOwnerWinGame( pCurrentPoint, i ) ) { bFinalPointInMap = true; } } } } else { // or this is the last round if ( pMaster->NumPlayableControlPointRounds() == 1 ) { CTeamControlPointRound *pRound = pMaster->GetCurrentRound(); if ( pRound ) { for ( int i = FIRST_GAME_TEAM ; i < MAX_CONTROL_POINT_TEAMS ; i++ ) { if ( ObjectiveResource() && ObjectiveResource()->TeamCanCapPoint( pCurrentPoint->GetPointIndex(), i ) ) { if ( pRound->WouldNewCPOwnerWinGame( pCurrentPoint, i ) ) { bFinalPointInMap = true; } } } } } } } PlayCaptureAlert( pCurrentPoint, bFinalPointInMap ); } } } // check to see if we need to start or stop the alarm if ( flDistanceToGoal <= TEAM_TRAIN_ALARM_DISTANCE ) { if ( ObjectiveResource() ) { ObjectiveResource()->SetTrackAlarm( GetTeamNumber(), true ); } if ( !bDisableAlarm ) { if ( !m_pAlarm ) { if ( m_iNumCPLinks > 0 && !m_bAlarmPlayed ) { // start the alarm at the final point StartCaptureAlarm( m_CPLinks[m_iNumCPLinks-1].hCP.Get() ); m_bAlarmPlayed = true; // used to prevent the alarm from starting again on maps where the train doesn't recede (alarm loops for short time then only plays singles) } } else { if ( !m_bTrainCanRecede ) // if the train won't recede, we only want to play the alarm for a short time { if ( m_flAlarmEndTime > 0 && m_flAlarmEndTime < gpGlobals->curtime ) { StopCaptureAlarm(); SetContextThink( &CTeamTrainWatcher::WatcherAlarmThink, gpGlobals->curtime + TW_ALARM_THINK_INTERVAL, TW_ALARM_THINK ); } } } } } else { if ( ObjectiveResource() ) { ObjectiveResource()->SetTrackAlarm( GetTeamNumber(), false ); } StopCaptureAlarm(); m_bAlarmPlayed = false; } } if ( tf_show_train_path.GetBool() ) { CPathTrack *nextNode = NULL; CPathTrack *node = m_hStartNode; CPathTrack::BeginIteration(); while( node ) { node->Visit(); nextNode = node->GetNext(); if ( !nextNode || nextNode->HasBeenVisited() ) break; NDebugOverlay::Line( node->GetAbsOrigin(), nextNode->GetAbsOrigin(), 255, 255, 0, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); node = nextNode; } CPathTrack::EndIteration(); // show segment of path train is actually on node = pTrain->m_ppath; if ( node && node->GetNext() ) { NDebugOverlay::HorzArrow( node->GetAbsOrigin(), node->GetNext()->GetAbsOrigin(), 5.0f, 255, 0, 0, 255, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } } } SetContextThink( &CTeamTrainWatcher::WatcherThink, gpGlobals->curtime + 0.1, TW_THINK ); }
//----------------------------------------------------------------------------- // Purpose: Render a tesla beam in the veiw model. // // NOTE: This is a big ugly mess that will get cleaned up when I nail down // the effect. //----------------------------------------------------------------------------- void CWeaponCombatShield::DrawBeams( C_BaseViewModel *pViewModel ) { // Verify data. if ( !pViewModel ) return; // Only humans have the tesla effects if ( GetTeamNumber() == TEAM_ALIENS ) return; // Init if ( !m_pTeslaBeam ) { InitTeslaBeam(); } if ( !m_pShieldBeam ) { InitShieldBeam(); } if ( !m_pShieldBeam || !m_pTeslaBeam ) return; // Variables BeamInfo_t beamInfo; QAngle vecAngle; int iAttachment; // Setup a color reflecting the health float flShieldHealth = GetShieldHealth(); color32 color; color.r = 206; color.g = flShieldHealth * 182; color.b = flShieldHealth * 127; color.a = 255; // Tesla Effect Vector vecRightTop, vecRightBottom; Vector vecLeftTop, vecLeftBottom; iAttachment = pViewModel->LookupAttachment( "LeftBottom" ); pViewModel->GetAttachment( iAttachment, vecLeftBottom, vecAngle ); pViewModel->UncorrectViewModelAttachment( vecLeftBottom ); iAttachment = pViewModel->LookupAttachment( "LeftTip" ); pViewModel->GetAttachment( iAttachment, vecLeftTop, vecAngle ); pViewModel->UncorrectViewModelAttachment( vecLeftTop ); iAttachment = pViewModel->LookupAttachment( "RightBottom" ); pViewModel->GetAttachment( iAttachment, vecRightBottom, vecAngle ); pViewModel->UncorrectViewModelAttachment( vecRightBottom ); iAttachment = pViewModel->LookupAttachment( "RightTip" ); pViewModel->GetAttachment( iAttachment, vecRightTop, vecAngle ); pViewModel->UncorrectViewModelAttachment( vecRightTop ); m_flTeslaLeftInc += weapon_combat_shield_teslaspeed.GetFloat(); m_flTeslaRightInc += weapon_combat_shield_teslaspeed.GetFloat(); if ( m_flTeslaLeftInc > 1.0f ) { m_flTeslaLeftInc = 0.0f; } if ( m_flTeslaRightInc > 1.0f ) { m_flTeslaRightInc = 0.0f; } Vector vecLeft = vecLeftTop - vecLeftBottom; Vector vecRight = vecRightTop - vecRightBottom; Vector vecStart = vecLeftBottom + ( m_flTeslaLeftInc * vecLeft ); Vector vecEnd = vecRightBottom + ( m_flTeslaRightInc * vecRight ); beamInfo.m_vecStart = vecStart; beamInfo.m_vecEnd = vecEnd; beamInfo.m_flRed = color.r; beamInfo.m_flGreen = color.g; beamInfo.m_flBlue = color.b; beams->UpdateBeamInfo( m_pTeslaBeam, beamInfo ); beams->UpdateBeamInfo( m_pTeslaBeam2, beamInfo ); beams->DrawBeam( m_pTeslaBeam ); beams->DrawBeam( m_pTeslaBeam2 ); // Draw a sprite at the tip of the tesla coil. float flSize = 4.0f; materials->Bind( m_hShieldSpriteMaterial, this ); DrawSprite( vecStart, flSize, flSize, color ); DrawSprite( vecEnd, flSize, flSize, color ); // Shield Effect float flPercentage = random->RandomFloat( 0.0f, 1.0f ); if ( flPercentage < weapon_combat_shield_teslaskitter.GetFloat() ) { char szShieldJoint[16]; int nJoint = random->RandomInt( 1, 8 ); Q_snprintf( szShieldJoint, 16, "Shield%d", nJoint ); Vector vecJoint; int iAttachment = pViewModel->LookupAttachment( &szShieldJoint[0] ); pViewModel->GetAttachment( iAttachment, vecJoint, vecAngle ); pViewModel->UncorrectViewModelAttachment( vecJoint ); if ( nJoint < 5 ) { beamInfo.m_vecStart = vecLeftTop; } else { beamInfo.m_vecStart = vecRightTop; } beamInfo.m_vecEnd = vecJoint; beams->UpdateBeamInfo( m_pTeslaBeam, beamInfo ); beams->UpdateBeamInfo( m_pTeslaBeam2, beamInfo ); beams->DrawBeam( m_pTeslaBeam ); beams->DrawBeam( m_pTeslaBeam2 ); float flSize = 7.0f; color32 color = { 206, 181, 127, 255 }; materials->Bind( m_hShieldSpriteMaterial, this ); DrawSprite( beamInfo.m_vecStart, flSize, flSize, color ); } #if 0 // Shield Effect char szShieldJoint[16]; Vector vecShieldJoints[8]; for( int iJoint = 0; iJoint < 8; ++iJoint ) { Q_snprintf( szShieldJoint, 16, "Shield%d", iJoint+1 ); iAttachment = pViewModel->LookupAttachment( &szShieldJoint[0] ); pViewModel->GetAttachment( iAttachment, vecShieldJoints[iJoint], vecAngle ); pViewModel->UncorrectViewModelAttachment( vecShieldJoints[iJoint] ); } // Shield Internal if ( m_flShieldInc < 1.0f ) { Vector vecEdge, vecEnd; if ( m_bLeftToRight ) { vecEdge = vecShieldJoints[((m_nShieldEdge+1)%8)] - vecShieldJoints[m_nShieldEdge]; vecEnd = vecShieldJoints[m_nShieldEdge] + ( m_flShieldInc * vecEdge ); } else { vecEdge = vecShieldJoints[m_nShieldEdge] - vecShieldJoints[((m_nShieldEdge+1)%8)]; vecEnd = vecShieldJoints[((m_nShieldEdge+1)%8)] + ( m_flShieldInc * vecEdge ); } if ( m_nShieldEdge < 5 ) { beamInfo.m_vecStart = vecLeftTop; } else { beamInfo.m_vecStart = vecRightTop; } beamInfo.m_vecEnd = vecEnd; beams->UpdateBeamPoints( m_pShieldBeam2, beamInfo ); beams->UpdateBeamPoints( m_pShieldBeam3, beamInfo ); beams->DrawBeam( m_pShieldBeam2 ); beams->DrawBeam( m_pShieldBeam3 ); m_flShieldInc += m_flShieldSpeed; } else { m_flShieldInc = 0.0f; m_flShieldSpeed = random->RandomFloat( 0.015f, 0.15f ); m_nShieldEdge = random->RandomInt( 0, 7 ); float flSide = random->RandomFloat( 0.0f, 1.0f ); m_bLeftToRight = ( flSide < 0.5f ); } // Shield Outline for( iJoint = 0; iJoint < 8; ++iJoint ) { beamInfo.m_vecStart = vecShieldJoints[iJoint]; beamInfo.m_vecEnd = vecShieldJoints[(iJoint+1)%8]; beams->UpdateBeamPoints( m_pShieldBeam, beamInfo ); beams->UpdateBeamPoints( m_pShieldBeam2, beamInfo ); beams->DrawBeam( m_pShieldBeam ); beams->DrawBeam( m_pShieldBeam2 ); // Draw a sprite at the tip of the tesla coil. float flSize = 3.0f; color32 color = { 255, 255, 0, 255 }; materials->Bind( m_hShieldSpriteMaterial, this ); DrawSprite( vecShieldJoints[iJoint], flSize, flSize, color ); } #endif }
// ========================================================== // given a start node and a list of goal nodes // calculate the distance between each // ========================================================== void CTeamTrainWatcher::WatcherActivate( void ) { m_flRecedeTime = 0; m_bWaitingToRecede = false; m_bCapBlocked = false; m_flNextSpeakForwardConceptTime = 0; m_hAreaCap = NULL; m_flTrainDistanceFromStart = 0.0f; m_bAlarmPlayed = false; m_Sparks.Purge(); StopCaptureAlarm(); // init our train m_hTrain = dynamic_cast<CFuncTrackTrain*>( gEntList.FindEntityByName( NULL, m_iszTrain ) ); if ( !m_hTrain ) { Warning("%s failed to find train named '%s'\n", GetClassname(), STRING( m_iszTrain ) ); } // find the trigger area that will give us movement updates and find the sparks (if we're going to handle the train movement) if ( m_bHandleTrainMovement ) { if ( m_hTrain ) { CTriggerAreaCapture *pArea = dynamic_cast<CTriggerAreaCapture *>( gEntList.FindEntityByClassname( NULL, "trigger_capture_area" ) ); while( pArea ) { if ( pArea->GetParent() == m_hTrain.Get() ) { // this is the capture area we care about, so let it know that we want updates on the capture numbers pArea->SetTrainWatcher( this ); break; } pArea = dynamic_cast<CTriggerAreaCapture *>( gEntList.FindEntityByClassname( pArea, "trigger_capture_area" ) ); } } // init the sprites (if any) CEnvSpark *pSpark = dynamic_cast<CEnvSpark*>( gEntList.FindEntityByName( NULL, m_iszSparkName ) ); while ( pSpark ) { m_Sparks.AddToTail( pSpark ); pSpark = dynamic_cast<CEnvSpark*>( gEntList.FindEntityByName( pSpark, m_iszSparkName ) ); } } // init our array of path_tracks linked to control points m_iNumCPLinks = 0; int i; for ( i = 0 ; i < MAX_CONTROL_POINTS ; i++ ) { CPathTrack *pPathTrack = dynamic_cast<CPathTrack*>( gEntList.FindEntityByName( NULL, m_iszLinkedPathTracks[i] ) ); CTeamControlPoint *pCP = dynamic_cast<CTeamControlPoint*>( gEntList.FindEntityByName( NULL, m_iszLinkedCPs[i] ) ); if ( pPathTrack && pCP ) { m_CPLinks[m_iNumCPLinks].hPathTrack = pPathTrack; m_CPLinks[m_iNumCPLinks].hCP = pCP; m_CPLinks[m_iNumCPLinks].flDistanceFromStart = 0; // filled in when we parse the nodes m_CPLinks[m_iNumCPLinks].bAlertPlayed = false; m_iNumCPLinks++; } } // init our start and goal nodes m_hStartNode = dynamic_cast<CPathTrack*>( gEntList.FindEntityByName( NULL, m_iszStartNode ) ); if ( !m_hStartNode ) { Warning("%s failed to find path_track named '%s'\n", GetClassname(), STRING(m_iszStartNode) ); } m_hGoalNode = dynamic_cast<CPathTrack*>( gEntList.FindEntityByName( NULL, m_iszGoalNode ) ); if ( !m_hGoalNode ) { Warning("%s failed to find path_track named '%s'\n", GetClassname(), STRING(m_iszGoalNode) ); } m_flTotalPathDistance = 0.0f; CUtlVector< float > hillData; bool bOnHill = false; bool bDownHillData[TEAM_TRAIN_MAX_HILLS]; Q_memset( bDownHillData, 0, sizeof( bDownHillData ) ); int iHillCount = 0; if( m_hStartNode.Get() && m_hGoalNode.Get() ) { CPathTrack *pNode = m_hStartNode; CPathTrack *pPrev = pNode; CPathTrack *pHillStart = NULL; pNode = pNode->GetNext(); int iHillType = HILL_TYPE_NONE; // don't check the start node for links. If it's linked, it will have 0 distance anyway while ( pNode ) { Vector dir = pNode->GetLocalOrigin() - pPrev->GetLocalOrigin(); float length = dir.Length(); m_flTotalPathDistance += length; // gather our hill data for the HUD if ( pNode->GetHillType() != iHillType ) { if ( !bOnHill ) // we're at the start of a hill { hillData.AddToTail( m_flTotalPathDistance ); bOnHill = true; pHillStart = pNode; if ( iHillCount < TEAM_TRAIN_MAX_HILLS ) { bDownHillData[iHillCount] = pNode->IsDownHill() ? true : false; iHillCount++; } } else // we're at the end of a hill { float flDistance = m_flTotalPathDistance - length; // subtract length because the prev node was the end of the hill (not this one) if ( pHillStart && ( pHillStart == pPrev ) ) { flDistance = m_flTotalPathDistance; // we had a single node marked as a hill, so we'll use the current distance as the next marker } hillData.AddToTail( flDistance ); // is our current node the start of another hill? if ( pNode->GetHillType() != HILL_TYPE_NONE ) { hillData.AddToTail( m_flTotalPathDistance ); bOnHill = true; pHillStart = pNode; if ( iHillCount < TEAM_TRAIN_MAX_HILLS ) { bDownHillData[iHillCount] = pNode->IsDownHill() ? true : false; iHillCount++; } } else { bOnHill = false; pHillStart = NULL; } } iHillType = pNode->GetHillType(); } // if pNode is one of our cp nodes, store its distance from m_hStartNode for ( i = 0 ; i < m_iNumCPLinks ; i++ ) { if ( m_CPLinks[i].hPathTrack == pNode ) { m_CPLinks[i].flDistanceFromStart = m_flTotalPathDistance; break; } } if ( pNode == m_hGoalNode ) break; pPrev = pNode; pNode = pNode->GetNext(); } } // if we don't have an even number of entries in our hill data (beginning/end) add the final distance if ( ( hillData.Count() % 2 ) != 0 ) { hillData.AddToTail( m_flTotalPathDistance ); } if ( ObjectiveResource() ) { ObjectiveResource()->ResetHillData( GetTeamNumber() ); // convert our hill data into 0-1 percentages for networking if ( m_flTotalPathDistance > 0 && hillData.Count() > 0 ) { i = 0; while ( i < hillData.Count() ) { if ( i < TEAM_TRAIN_HILLS_ARRAY_SIZE - 1 ) // - 1 because we want to use 2 entries { // add/subtract to the hill start/end to fix rounding errors in the HUD when the train // stops at the bottom/top of a hill but the HUD thinks the train is still on the hill ObjectiveResource()->SetHillData( GetTeamNumber(), (hillData[i] / m_flTotalPathDistance) + 0.005f, (hillData[i+1] / m_flTotalPathDistance) - 0.005f, bDownHillData[i/2] ); } i = i + 2; } } } // We have total distance and increments in our links array for ( i=0;i<m_iNumCPLinks;i++ ) { int iCPIndex = m_CPLinks[i].hCP.Get()->GetPointIndex(); // This can be pulled once DoD includes team_objectiveresource.* and c_team_objectiveresource.* #ifndef DOD_DLL ObjectiveResource()->SetTrainPathDistance( iCPIndex, m_CPLinks[i].flDistanceFromStart / m_flTotalPathDistance ); #endif } #ifdef GLOWS_ENABLE FindGlowEntity(); #endif // GLOWS_ENABLE InternalSetSpeedForwardModifier( m_flSpeedForwardModifier ); SetContextThink( &CTeamTrainWatcher::WatcherThink, gpGlobals->curtime + 0.1, TW_THINK ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBasePlasmaProjectile::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs) { m_pParticleMgr = pParticleMgr; m_pParticleMgr->AddEffect( &m_ParticleEffect, this ); PMaterialHandle HeadMaterial, TrailMaterial; // Load the projectile material if ( GetTeamNumber() == TEAM_HUMANS ) { HeadMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/human_tracers/human_sparksprite_A1" ); TrailMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/human_tracers/human_sparktracer_A_" ); } else { HeadMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/alien_tracers/alien_pbsprite_A1" ); TrailMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/alien_tracers/alien_pbtracer_A_" ); } // Create the head & trail m_pHeadParticle = (SimpleParticle *)m_ParticleEffect.AddParticle(sizeof(SimpleParticle), HeadMaterial ); m_pTrailParticle = (TrailParticle *)m_ParticleEffect.AddParticle(sizeof(TrailParticle), TrailMaterial ); if ( !m_pHeadParticle || !m_pTrailParticle ) return; // 3rd person particles are larger bool bFirst = (GetOwnerEntity() == C_BasePlayer::GetLocalPlayer()); m_pHeadParticle->m_Pos = GetRenderOrigin(); m_pHeadParticle->m_uchColor[0] = 255; m_pHeadParticle->m_uchColor[1] = 255; m_pHeadParticle->m_uchColor[2] = 255; if ( bFirst ) { m_pHeadParticle->m_uchStartSize = 6; } else { m_pHeadParticle->m_uchStartSize = shot_head_size.GetInt(); } m_pHeadParticle->m_uchEndSize = m_pHeadParticle->m_uchStartSize; m_pHeadParticle->m_uchStartAlpha = 255; m_pHeadParticle->m_uchEndAlpha = 255; m_pHeadParticle->m_flRoll = 0; m_pHeadParticle->m_flRollDelta = 10; m_pHeadParticle->m_iFlags = 0; m_pTrailParticle->m_flLifetime = 0; m_pTrailParticle->m_Pos = GetRenderOrigin(); if ( bFirst ) { m_pTrailParticle->m_flWidth = 25; m_pTrailParticle->m_flLength = 140; } else { m_pTrailParticle->m_flWidth = shot_width.GetFloat(); m_pTrailParticle->m_flLength = shot_length.GetFloat(); } Color32Init( m_pTrailParticle->m_color, 255, 255, 255, 255 ); m_flNextSparkEffect = gpGlobals->curtime + RandomFloat( 0.05, 0.4 ); }
void CSDKPlayer::FireBullet( Vector vecSrc, // shooting postion const QAngle &shootAngles, //shooting angle float vecSpread, // spread vector int iDamage, // base damage int iBulletType, // ammo type CBaseEntity *pevAttacker, // shooter bool bDoEffects, // create impact effect ? float x, // spread x factor float y // spread y factor ) { float fCurrentDamage = iDamage; // damage of the bullet at it's current trajectory float flCurrentDistance = 0.0; //distance that the bullet has traveled so far Vector vecDirShooting, vecRight, vecUp; AngleVectors( shootAngles, &vecDirShooting, &vecRight, &vecUp ); if ( !pevAttacker ) pevAttacker = this; // the default attacker is ourselves // add the spray Vector vecDir = vecDirShooting + x * vecSpread * vecRight + y * vecSpread * vecUp; VectorNormalize( vecDir ); float flMaxRange = 8000; Vector vecEnd = vecSrc + vecDir * flMaxRange; // max bullet range is 10000 units trace_t tr; // main enter bullet trace UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction == 1.0f ) return; // we didn't hit anything, stop tracing shoot if ( sv_showimpacts.GetBool() ) { #ifdef CLIENT_DLL // draw red client impact markers debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawClientHitboxes( 4, true ); } #else // draw blue server impact markers NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, 4 ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawServerHitboxes( 4, true ); } #endif } //calculate the damage based on the distance the bullet travelled. flCurrentDistance += tr.fraction * flMaxRange; // damage get weaker of distance fCurrentDamage *= pow ( 0.85f, (flCurrentDistance / 500)); int iDamageType = DMG_BULLET | DMG_NEVERGIB; if( bDoEffects ) { // See if the bullet ended up underwater + started out of the water if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) { trace_t waterTrace; UTIL_TraceLine( vecSrc, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), this, COLLISION_GROUP_NONE, &waterTrace ); if( waterTrace.allsolid != 1 ) { CEffectData data; data.m_vOrigin = waterTrace.endpos; data.m_vNormal = waterTrace.plane.normal; data.m_flScale = random->RandomFloat( 8, 12 ); if ( waterTrace.contents & CONTENTS_SLIME ) { data.m_fFlags |= FX_WATER_IN_SLIME; } DispatchEffect( "gunshotsplash", data ); } } else { //Do Regular hit effects // Don't decal nodraw surfaces if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) { CBaseEntity *pEntity = tr.m_pEnt; //Tony; only while using teams do we check for friendly fire. if ( pEntity && pEntity->IsPlayer() && (pEntity->GetBaseAnimating() && !pEntity->GetBaseAnimating()->IsRagdoll()) ) { #if defined ( SDK_USE_TEAMS ) if ( pEntity->GetTeamNumber() == GetTeamNumber() ) { if ( !friendlyfire.GetBool() ) UTIL_ImpactTrace( &tr, iDamageType ); } #else UTIL_ImpactTrace( &tr, iDamageType ); #endif } //Tony; non player, just go nuts, else { UTIL_ImpactTrace( &tr, iDamageType ); } } } } // bDoEffects // add damage to entity that we hit #ifdef GAME_DLL ClearMultiDamage(); CTakeDamageInfo info( pevAttacker, pevAttacker, fCurrentDamage, iDamageType ); CalculateBulletDamageForce( &info, iBulletType, vecDir, tr.endpos ); tr.m_pEnt->DispatchTraceAttack( info, vecDir, &tr ); TraceAttackToTriggers( info, tr.startpos, tr.endpos, vecDir ); ApplyMultiDamage(); #endif }
//----------------------------------------------------------------------------- // This is called by the base object when it's time to spawn the control panels //----------------------------------------------------------------------------- void CPlantedC4::SpawnControlPanels() { char buf[64]; // FIXME: Deal with dynamically resizing control panels? // If we're attached to an entity, spawn control panels on it instead of use CBaseAnimating *pEntityToSpawnOn = this; char *pOrgLL = "controlpanel%d_ll"; char *pOrgUR = "controlpanel%d_ur"; char *pAttachmentNameLL = pOrgLL; char *pAttachmentNameUR = pOrgUR; Assert( pEntityToSpawnOn ); // Lookup the attachment point... int nPanel; for ( nPanel = 0; true; ++nPanel ) { Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel ); int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) { // Try and use my panels then pEntityToSpawnOn = this; Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel ); nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) return; } Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel ); int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) { // Try and use my panels then Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel ); nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) return; } const char *pScreenName; GetControlPanelInfo( nPanel, pScreenName ); if (!pScreenName) continue; const char *pScreenClassname; GetControlPanelClassName( nPanel, pScreenClassname ); if ( !pScreenClassname ) continue; // Compute the screen size from the attachment points... matrix3x4_t panelToWorld; pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld ); matrix3x4_t worldToPanel; MatrixInvert( panelToWorld, worldToPanel ); // Now get the lower right position + transform into panel space Vector lr, lrlocal; pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld ); MatrixGetColumn( panelToWorld, 3, lr ); VectorTransform( lr, worldToPanel, lrlocal ); float flWidth = lrlocal.x; float flHeight = lrlocal.y; CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex ); pScreen->ChangeTeam( GetTeamNumber() ); pScreen->SetActualSize( flWidth, flHeight ); pScreen->SetActive( true ); pScreen->MakeVisibleOnlyToTeammates( false ); int nScreen = m_hScreens.AddToTail( ); m_hScreens[nScreen].Set( pScreen ); } }
//----------------------------------------------------------------------------- // Purpose: Plasma sentrygun's fire //----------------------------------------------------------------------------- void CObjectMannedPlasmagun::Fire( ) { if (m_flNextAttack > gpGlobals->curtime) return; // Because the plasma sentrygun always thinks it has ammo (see below) // we might not have ammo here, in which case we should just abort. if ( !m_nAmmoCount ) return; // Make sure we think soon enough in case of firing... float flNextRecharge = gpGlobals->curtime + (HasPowerup(POWERUP_EMP) ? MANNED_PLASMAGUN_RECHARGE_TIME * 1.5 : MANNED_PLASMAGUN_RECHARGE_TIME); SetNextThink( gpGlobals->curtime + flNextRecharge ); // We have to flush the bone cache because it's possible that only the bone controllers // have changed since the bonecache was generated, and bone controllers aren't checked. InvalidateBoneCache(); QAngle vecAng; Vector vecSrc, vecAim; // Alternate barrels when firing if ( m_bFiringLeft ) { // Aliens permanently fire left barrel because they have no right if ( GetTeamNumber() == TEAM_HUMANS ) { m_bFiringLeft = false; } GetAttachment( m_nBarrelAttachment, vecSrc, vecAng ); SetActivity( ACT_VM_PRIMARYATTACK ); } else { m_bFiringLeft = true; GetAttachment( m_nRightBarrelAttachment, vecSrc, vecAng ); SetActivity( ACT_VM_SECONDARYATTACK ); } // Get the distance to the target AngleVectors( vecAng, &vecAim, 0, 0 ); int damageType = GetAmmoDef()->DamageType( m_nAmmoType ); CBasePlasmaProjectile *pPlasma = CBasePlasmaProjectile::CreatePredicted( vecSrc, vecAim, Vector( 0, 0, 0 ), damageType, GetDriverPlayer() ); if ( pPlasma ) { pPlasma->SetDamage( obj_manned_plasmagun_damage.GetFloat() ); pPlasma->m_hOwner = GetDriverPlayer(); //pPlasma->SetOwnerEntity( this ); pPlasma->SetMaxRange( m_flMaxRange ); if ( obj_manned_plasmagun_radius.GetFloat() ) { pPlasma->SetExplosive( obj_manned_plasmagun_radius.GetFloat() ); } } CSoundParameters params; if ( GetParametersForSound( "ObjectMannedPlasmagun.Fire", params, NULL ) ) { CPASAttenuationFilter filter( this, params.soundlevel ); if ( IsPredicted() ) { filter.UsePredictionRules(); } EmitSound( filter, entindex(), "ObjectMannedPlasmagun.Fire" ); } // SetSentryAnim( TFTURRET_ANIM_FIRE ); DoMuzzleFlash(); --m_nAmmoCount; m_flNextIdleTime = gpGlobals->curtime + MANNED_PLASMAGUN_IDLE_TIME; // If I'm EMPed, slow the firing rate down m_flNextAttack = gpGlobals->curtime + ( HasPowerup(POWERUP_EMP) ? 0.3f : 0.1f ); }
void CTFBaseRocket::FlyThink( void ) { if ( gpGlobals->curtime > m_flCollideWithTeammatesTime && m_bCollideWithTeammates == false ) { m_bCollideWithTeammates = true; } if ( tf2c_homing_rockets.GetBool() || ( tf2c_homing_deflected_rockets.GetBool() && m_iDeflected ) ) { // Find the closest visible enemy player. CUtlVector<CTFPlayer *> vecPlayers; int count = CollectPlayers( &vecPlayers, TEAM_ANY, true ); float flClosest = FLT_MAX; Vector vecClosestTarget = vec3_origin; for ( int i = 0; i < count; i++ ) { CTFPlayer *pPlayer = vecPlayers[i]; if ( pPlayer == GetOwnerEntity() ) continue; if ( pPlayer->GetTeamNumber() == GetTeamNumber() && !TFGameRules()->IsDeathmatch() ) continue; Vector vecTarget; QAngle angTarget; if ( GetWeaponID() == TF_WEAPON_COMPOUND_BOW ) { int iBone = pPlayer->LookupBone( "bip_head" ); pPlayer->GetBonePosition( iBone, vecTarget, angTarget );; } else { vecTarget = pPlayer->EyePosition(); } if ( FVisible( vecTarget ) ) { float flDistSqr = ( vecTarget - GetAbsOrigin() ).LengthSqr(); if ( flDistSqr < flClosest ) { flClosest = flDistSqr; vecClosestTarget = vecTarget; } } } // Head towards him. if ( vecClosestTarget != vec3_origin ) { Vector vecTarget = vecClosestTarget; Vector vecDir = vecTarget - GetAbsOrigin(); VectorNormalize( vecDir ); float flSpeed = GetAbsVelocity().Length(); QAngle angForward; VectorAngles( vecDir, angForward ); SetAbsAngles( angForward ); SetAbsVelocity( vecDir * flSpeed ); } } SetNextThink( gpGlobals->curtime + 0.1f ); }
void CObjectMannedPlasmagun::PreDataUpdate( DataUpdateType_t updateType ) { BaseClass::PreDataUpdate( updateType ); m_nPreviousTeam = GetTeamNumber(); }
//----------------------------------------------------------------------------- // This is called by the base object when it's time to spawn the control panels //----------------------------------------------------------------------------- void CBaseViewModel::SpawnControlPanels() { #if defined( VGUI_CONTROL_PANELS ) char buf[64]; // Destroy existing panels DestroyControlPanels(); CBaseCombatWeapon *weapon = m_hWeapon.Get(); if ( weapon == NULL ) { return; } MDLCACHE_CRITICAL_SECTION(); // FIXME: Deal with dynamically resizing control panels? // If we're attached to an entity, spawn control panels on it instead of use CBaseAnimating *pEntityToSpawnOn = this; char *pOrgLL = "controlpanel%d_ll"; char *pOrgUR = "controlpanel%d_ur"; char *pAttachmentNameLL = pOrgLL; char *pAttachmentNameUR = pOrgUR; /* if ( IsBuiltOnAttachment() ) { pEntityToSpawnOn = dynamic_cast<CBaseAnimating*>((CBaseEntity*)m_hBuiltOnEntity.Get()); if ( pEntityToSpawnOn ) { char sBuildPointLL[64]; char sBuildPointUR[64]; Q_snprintf( sBuildPointLL, sizeof( sBuildPointLL ), "bp%d_controlpanel%%d_ll", m_iBuiltOnPoint ); Q_snprintf( sBuildPointUR, sizeof( sBuildPointUR ), "bp%d_controlpanel%%d_ur", m_iBuiltOnPoint ); pAttachmentNameLL = sBuildPointLL; pAttachmentNameUR = sBuildPointUR; } else { pEntityToSpawnOn = this; } } */ Assert( pEntityToSpawnOn ); // Lookup the attachment point... int nPanel; for ( nPanel = 0; true; ++nPanel ) { Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel ); int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) { // Try and use my panels then pEntityToSpawnOn = this; Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel ); nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) return; } Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel ); int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) { // Try and use my panels then Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel ); nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) return; } const char *pScreenName; weapon->GetControlPanelInfo( nPanel, pScreenName ); if (!pScreenName) continue; const char *pScreenClassname; weapon->GetControlPanelClassName( nPanel, pScreenClassname ); if ( !pScreenClassname ) continue; // Compute the screen size from the attachment points... matrix3x4_t panelToWorld; pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld ); matrix3x4_t worldToPanel; MatrixInvert( panelToWorld, worldToPanel ); // Now get the lower right position + transform into panel space Vector lr, lrlocal; pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld ); MatrixGetColumn( panelToWorld, 3, lr ); VectorTransform( lr, worldToPanel, lrlocal ); float flWidth = lrlocal.x; float flHeight = lrlocal.y; CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex ); pScreen->ChangeTeam( GetTeamNumber() ); pScreen->SetActualSize( flWidth, flHeight ); pScreen->SetActive( false ); pScreen->MakeVisibleOnlyToTeammates( false ); pScreen->SetAttachedToViewModel( true ); int nScreen = m_hScreens.AddToTail( ); m_hScreens[nScreen].Set( pScreen ); } #endif }
void CHL2MP_Player::SetPlayerModel( void ) { const char *szModelName = NULL; const char *pszCurrentModelName = modelinfo->GetModelName( GetModel()); szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); if ( ValidatePlayerModel( szModelName ) == false ) { char szReturnString[512]; if ( ValidatePlayerModel( pszCurrentModelName ) == false ) pszCurrentModelName = "models/player/carebear.mdl"; Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", pszCurrentModelName ); engine->ClientCommand ( edict(), szReturnString ); szModelName = pszCurrentModelName; } if ( GetTeamNumber() == TEAM_PINK ) { m_nSkin = 0; m_iModelType = TEAM_PINK; szModelName = g_ppszRandomCitizenModels[0]; } else if ( GetTeamNumber() == TEAM_GREEN ) { m_nSkin = 2; m_iModelType = TEAM_GREEN; szModelName = g_ppszRandomCitizenModels[0]; } else { if ( Q_strlen( szModelName ) == 0 ) szModelName = g_ppszRandomCitizenModels[0]; if ( m_nSkin == 2 ) m_iModelType = TEAM_GREEN; else m_iModelType = TEAM_PINK; } int modelIndex = modelinfo->GetModelIndex( szModelName ); if ( modelIndex == -1 ) { szModelName = "models/player/carebear.mdl"; m_iModelType = TEAM_PINK; m_nSkin = 0; char szReturnString[512]; Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", szModelName ); engine->ClientCommand ( edict(), szReturnString ); } SetModel( szModelName ); SetupPlayerSoundsByModel( szModelName ); m_flNextModelChangeTime = gpGlobals->curtime + MODEL_CHANGE_INTERVAL; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CFuncRespawnRoom::Activate( void ) { BaseClass::Activate(); m_iOriginalTeam = GetTeamNumber(); SetActive( true ); }
void CHL2MP_Player::SetPlayerModel( void ) { const char *szModelName = NULL; const char *pszCurrentModelName = modelinfo->GetModelName( GetModel()); szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); if ( ValidatePlayerModel( szModelName ) == false ) { char szReturnString[512]; if ( ValidatePlayerModel( pszCurrentModelName ) == false ) { pszCurrentModelName = "models/Combine_Soldier.mdl"; } Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", pszCurrentModelName ); engine->ClientCommand ( edict(), szReturnString ); szModelName = pszCurrentModelName; } if ( GetTeamNumber() == TEAM_COMBINE ) { int nHeads = ARRAYSIZE( g_ppszRandomCombineModels ); g_iLastCombineModel = ( g_iLastCombineModel + 1 ) % nHeads; szModelName = g_ppszRandomCombineModels[g_iLastCombineModel]; m_iModelType = TEAM_COMBINE; } else if ( GetTeamNumber() == TEAM_REBELS ) { int nHeads = ARRAYSIZE( g_ppszRandomCitizenModels ); g_iLastCitizenModel = ( g_iLastCitizenModel + 1 ) % nHeads; szModelName = g_ppszRandomCitizenModels[g_iLastCitizenModel]; m_iModelType = TEAM_REBELS; } else { if ( Q_strlen( szModelName ) == 0 ) { szModelName = g_ppszRandomCitizenModels[0]; } if ( Q_stristr( szModelName, "models/human") ) { m_iModelType = TEAM_REBELS; } else { m_iModelType = TEAM_COMBINE; } } int modelIndex = modelinfo->GetModelIndex( szModelName ); if ( modelIndex == -1 ) { szModelName = "models/Combine_Soldier.mdl"; m_iModelType = TEAM_COMBINE; char szReturnString[512]; Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", szModelName ); engine->ClientCommand ( edict(), szReturnString ); } SetModel( szModelName ); SetupPlayerSoundsByModel( szModelName ); m_flNextModelChangeTime = gpGlobals->curtime + MODEL_CHANGE_INTERVAL; }
void CHL2MP_Player::SetPlayerTeamModel( void ) { const char *szModelName = NULL; szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); int modelIndex = modelinfo->GetModelIndex( szModelName ); if ( modelIndex == -1 || ValidatePlayerModel( szModelName ) == false ) { //DHL - Skillet - Changed from combine soldier szModelName = DHL_DEFAULTMODEL; m_iModelType = TEAM_PROS; char szReturnString[512]; Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", szModelName ); engine->ClientCommand ( edict(), szReturnString ); } //DHL - Skillet if ( GetTeamNumber() == TEAM_MOBSTERS ) { if ( !Q_stristr( szModelName, "models/player/dhl/mobsters" ) ) szModelName = DHL_DEFAULTMODEL_MOB; } if ( GetTeamNumber() == TEAM_PROS ) { if ( !Q_stristr( szModelName, "models/player/dhl/professionals" ) ) szModelName = DHL_DEFAULTMODEL_PRO; } //DHL - Skillet - Obselete //if ( GetTeamNumber() == TEAM_COMBINE ) //{ // if ( Q_stristr( szModelName, "models/human") ) // { // int nHeads = ARRAYSIZE( g_ppszRandomCombineModels ); // // g_iLastCombineModel = ( g_iLastCombineModel + 1 ) % nHeads; // szModelName = g_ppszRandomCombineModels[g_iLastCombineModel]; // } // m_iModelType = TEAM_COMBINE; //} //else if ( GetTeamNumber() == TEAM_REBELS ) //{ // if ( !Q_stristr( szModelName, "models/human") ) // { // int nHeads = ARRAYSIZE( g_ppszRandomCitizenModels ); // g_iLastCitizenModel = ( g_iLastCitizenModel + 1 ) % nHeads; // szModelName = g_ppszRandomCitizenModels[g_iLastCitizenModel]; // } // m_iModelType = TEAM_REBELS; //} SetModel( szModelName ); SetupPlayerSoundsByModel( szModelName ); m_flNextModelChangeTime = gpGlobals->curtime + MODEL_CHANGE_INTERVAL; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CObjectResupply::CalculatePlacement( CBaseTFPlayer *pPlayer ) { trace_t tr; Vector vecAiming; // Get an aim vector. Don't use GetAimVector() because we don't want autoaiming. Vector vecSrc = pPlayer->Weapon_ShootPosition( ); pPlayer->EyeVectors( &vecAiming ); Vector vecTarget; VectorMA( vecSrc, 90, vecAiming, vecTarget ); m_vecBuildOrigin = vecTarget; // Angle it towards me Vector vecForward = pPlayer->WorldSpaceCenter() - m_vecBuildOrigin; SetLocalAngles( QAngle( 0, UTIL_VecToYaw( vecForward ), 0 ) ); // Is there something to attach to? // Use my bounding box, not the build box, so I fit to the wall UTIL_TraceLine( vecSrc, vecTarget, MASK_SOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr); //UTIL_TraceHull( vecSrc, vecTarget, WorldAlignMins(), WorldAlignMaxs(), MASK_SOLID, pPlayer, TFCOLLISION_GROUP_OBJECT, &tr ); m_vecBuildOrigin = tr.endpos; bool bTryToPlaceGroundVersion = false; if ( tr.allsolid || (tr.fraction == 1.0) ) { bTryToPlaceGroundVersion = true; } else { // Make sure we're planting on the world CBaseEntity *pEntity = tr.m_pEnt; if ( pEntity != GetWorldEntity() ) { bTryToPlaceGroundVersion = true; } } // Make sure the wall we've touched is vertical if ( !bTryToPlaceGroundVersion && fabs(tr.plane.normal.z) > 0.3 ) { bTryToPlaceGroundVersion = true; } // Aborting? if ( bTryToPlaceGroundVersion ) { // We couldn't find a wall, so try and place a ground version instead if ( GetTeamNumber() == TEAM_HUMANS ) { SetModel( RESUPPLY_GROUND_MODEL_HUMAN ); } else { SetModel( RESUPPLY_GROUND_MODEL ); } UTIL_SetSize(this, RESUPPLY_GROUND_MINS, RESUPPLY_GROUND_MAXS); m_vecBuildMins = WorldAlignMins() - Vector( 4,4,0 ); m_vecBuildMaxs = WorldAlignMaxs() + Vector( 4,4,0 ); return BaseClass::CalculatePlacement( pPlayer ); } SetupAttachedVersion(); m_vecBuildMins = WorldAlignMins() - Vector( 4,4,0 ); m_vecBuildMaxs = WorldAlignMaxs() + Vector( 4,4,0 ); // Set the angles vecForward = tr.plane.normal; SetLocalAngles( QAngle( 0, UTIL_VecToYaw( vecForward ), 0 ) ); // Trace back from the corners Vector vecMins, vecMaxs, vecModelMins, vecModelMaxs; const model_t *pModel = GetModel(); modelinfo->GetModelBounds( pModel, vecModelMins, vecModelMaxs ); // Check the four build points Vector vecPointCheck = (vecForward * 32); Vector vecUp = Vector(0,0,1); Vector vecRight; CrossProduct( vecUp, vecForward, vecRight ); float flWidth = fabs(vecModelMaxs.y - vecModelMins.y) * 0.5; float flHeight = fabs(vecModelMaxs.z - vecModelMins.z) * 0.5; bool bResult = true; if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin + (vecRight * flWidth) + (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin + (vecRight * flWidth) - (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin - (vecRight * flWidth) + (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin - (vecRight * flWidth) - (vecUp * flHeight), vecPointCheck ); } AttemptToFindPower(); return bResult; }