#include "cbase.h" #include "c_user_message_register.h" #include "iclientvehicle.h" #include "input.h" #include "c_basetempentity.h" #include "hud_macros.h" #include "engine/ivdebugoverlay.h" #include "bone_setup.h" #include "in_buttons.h" #include "r_efx.h" #include "cl_animevent.h" #include "c_asw_point_camera.h" #include "soundenvelope.h" #include #include "materialsystem/imesh.h" //for materials->FindMaterial #include "iviewrender.h" //for view-> #include "tier0/vprof.h" #include "prediction.h" #include "c_env_ambient_light.h" #include "game_timescale_shared.h" // effects #include "ivieweffects.h" #include "view.h" #include "ieffects.h" #include "fx.h" #include "smoke_fog_overlay.h" #include "dlight.h" #include "shake.h" // VGUI #include #include #include "vgui_controls/frame.h" #include "vgui_controls/Label.h" #include #include #include "controller_focus.h" #include "iclientmode.h" // ASW HUD #include "vgui\asw_vgui_info_message.h" #include "vgui\FadeInPanel.h" #include "vgui\asw_vgui_ingame_panel.h" #include "asw_vgui_stylin_cam.h" #include "asw_hud_crosshair.h" #include "asw_hud_chat.h" #include "PlayerListPanel.h" #include "asw_vgui_frame.h" #include "MedalCollectionPanel.h" #include "CreditsPanel.h" #include "CainMailPanel.h" #include "asw_vgui_skip_intro.h" #include "CampaignFrame.h" #include "OutroFrame.h" #include "MissionCompleteFrame.h" #include "BriefingFrame.h" #include "clientmode_asw.h" #include "vgui\PlayerListContainer.h" #include "asw_loading_panel.h" // ASW Game #include "c_asw_player.h" #include "c_asw_game_resource.h" #include "c_asw_objective.h" #include "asw_marine_profile.h" #include "c_asw_marine_resource.h" #include "c_asw_marine.h" #include "c_asw_mesh_emitter_entity.h" #include "c_asw_generic_emitter_entity.h" #include "asw_weapon_parse.h" #include "c_asw_pickup.h" #include "c_asw_door_area.h" #include "asw_gamerules.h" #include "asw_equipment_list.h" #include "c_asw_weapon.h" #include "asw_marineandobjectenumerator.h" #include "asw_usableobjectsenumerator.h" #include "c_asw_jeep_clientside.h" #include "obstacle_pushaway.h" #include "asw_shareddefs.h" #include "asw_campaign_info.h" #include "c_asw_voting_missions.h" #include "c_asw_camera_volume.h" #include "asw_medal_store.h" #include "asw_remote_turret_shared.h" #include "c_asw_snow_volume.h" #include "c_asw_snow_emitter.h" #include "asw_util_shared.h" #include "c_asw_flare_projectile.h" #include "c_asw_flamer_projectile.h" #include "collisionutils.h" #include "asw_input.h" #include "c_asw_sentry_base.h" #include "asw_weapon_sniper_rifle.h" #include "asw_melee_system.h" #include "c_asw_jukebox.h" #include "missionchooser/iasw_mission_chooser.h" #include "missionchooser/iasw_random_missions.h" #if defined( CASW_Player ) #undef CASW_Player #endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" extern ConVar asw_controls; extern ConVar asw_marine_collision; ConVar g_DrawPlayer("asw_drawplayermesh", "0", FCVAR_ARCHIVE, "Draw the player entity or not"); ConVar asw_clientside_avoidance("asw_clientside_avoidance", "1", FCVAR_CHEAT); ConVar asw_debug_clientside_avoidance("asw_debug_clientside_avoidance", "0", FCVAR_CHEAT); ConVar asw_clientside_avoidance_scale("asw_clientside_avoidance_scale", "1.0", FCVAR_CHEAT); // stim cams: (p/y/r) (x/y/z) // (0/-10/0) (-60 60 30) - foot level forward looking // (40/180/0) (50 0 70) - close marine view cam ConVar asw_stim_cam_pitch("asw_stim_cam_pitch", "10", 0, "Controls angle of the small in-picture Stim camera"); ConVar asw_stim_cam_yaw("asw_stim_cam_yaw", "15", 0, "Controls angle of the small in-picture Stim camera"); ConVar asw_stim_cam_roll("asw_stim_cam_roll", "0", 0, "Controls angle of the small in-picture Stim camera"); ConVar asw_stim_cam_x("asw_stim_cam_x", "-20", 0, "Controls offset of the small in-picture Stim camera"); ConVar asw_stim_cam_y("asw_stim_cam_y", "-30", 0, "Controls offset of the small in-picture Stim camera"); ConVar asw_stim_cam_z("asw_stim_cam_z", "70", 0, "Controls offset of the small in-picture Stim camera"); ConVar asw_stim_cam_rotate_speed("asw_stim_cam_rotate_speed", "0", 0, "Rotation speed of the stim camera"); ConVar asw_spinning_stim_cam("asw_spinning_stim_cam", "1", 0, "If set, slow motion will display a small spinning camera view"); ConVar asw_show_mouse_entity("asw_show_mouse_entity", "0", FCVAR_CHEAT, "Show entity under the mouse cursor"); ConVar asw_marine_switch_blend_speed("asw_marine_switch_blend_speed", "2.5", 0, "How quickly the camera blends between marines when switching"); ConVar asw_marine_switch_blend_max_dist("asw_marine_switch_blend_max_dist", "1500", 0, "Maximum distance apart marines can be for a camera blend to occur"); // default inventory convars ConVar asw_default_primary_0("asw_default_primary_0", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_0("asw_default_secondary_0", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_0("asw_default_extra_0", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_default_primary_1("asw_default_primary_1", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_1("asw_default_secondary_1", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_1("asw_default_extra_1", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_default_primary_2("asw_default_primary_2", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_2("asw_default_secondary_2", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_2("asw_default_extra_2", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_default_primary_3("asw_default_primary_3", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_3("asw_default_secondary_3", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_3("asw_default_extra_3", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_default_primary_4("asw_default_primary_4", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_4("asw_default_secondary_4", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_4("asw_default_extra_4", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_default_primary_5("asw_default_primary_5", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_5("asw_default_secondary_5", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_5("asw_default_extra_5", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_default_primary_6("asw_default_primary_6", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_6("asw_default_secondary_6", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_6("asw_default_extra_6", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_default_primary_7("asw_default_primary_7", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_7("asw_default_secondary_7", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_7("asw_default_extra_7", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_default_primary_8("asw_default_primary_8", "-1", FCVAR_NONE, "Default primary equip for marine with this number"); ConVar asw_default_secondary_8("asw_default_secondary_8", "-1", FCVAR_NONE, "Default secondary equip for marine with this number"); ConVar asw_default_extra_8("asw_default_extra_8", "-1", FCVAR_NONE, "Default extra equip for marine with this number"); ConVar asw_particle_count("asw_particle_count", "0", 0, "Shows how many particles are being drawn"); ConVar asw_dlight_list("asw_dlight_list", "0", 0, "Lists dynamic lights"); ConVar asw_stim_music( "asw_stim_music", "", FCVAR_ARCHIVE, "Custom music file used for stim music" ); ConVar asw_player_avoidance( "asw_player_avoidance", "1", FCVAR_CHEAT, "Enable/Disable player avoidance." ); ConVar asw_player_avoidance_force( "asw_player_avoidance_force", "1024", FCVAR_CHEAT, "Marine avoidance separation force." ); ConVar asw_player_avoidance_bounce( "asw_player_avoidance_bounce", "1.0", FCVAR_CHEAT, "Marine avoidance bounce." ); ConVar asw_player_avoidance_fakehull( "asw_player_avoidance_fakehull", "25.0", FCVAR_CHEAT, "Marine avoidance hull size." ); ConVar asw_roster_select_bypass_steam( "asw_roster_select_bypass_steam", "0", FCVAR_CHEAT, "Bypass checking if data has been downloaded from steam when selecting a Marine." ); void fnAutoReloadChangedCallback(IConVar *var, const char *pOldString, float flOldValue ) { if ( engine->IsInGame() ) { engine->ClientCmd( VarArgs( "cl_autoreload %d\n", ((ConVar *)var)->GetInt() ) ); } } ConVar asw_auto_reload("asw_auto_reload", "1", FCVAR_ARCHIVE, "Whether your marines should autoreload when reaching 0 bullets", true, 0, true, 1, fnAutoReloadChangedCallback); ConVar asw_turret_fog_start("asw_turret_fog_start", "900", 0, "Fog start distance for turret view"); ConVar asw_turret_fog_end("asw_turret_fog_end", "1200", 0, "Fog end distance for turret view"); extern ConVar asw_allow_detach; extern ConVar asw_stim_cam_time; extern ConVar asw_rts_controls; extern ConVar asw_hud_alpha; extern ConVar asw_building_room_thumbnails; // How fast to avoid collisions with center of other object, in units per second #define AVOID_SPEED 2000.0f extern ConVar cl_forwardspeed; extern ConVar cl_backspeed; extern ConVar cl_sidespeed; extern ConVar asw_marine_death_cam_time; extern ConVar asw_time_scale_delay; extern float g_fMarinePoisonDuration; // -------------------------------------------------------------------------------- // // Player animation event. Sent to the client when a player fires, jumps, reloads, etc.. // -------------------------------------------------------------------------------- // class C_TEPlayerAnimEvent : public C_BaseTempEntity { public: DECLARE_CLASS( C_TEPlayerAnimEvent, C_BaseTempEntity ); DECLARE_CLIENTCLASS(); virtual void PostDataUpdate( DataUpdateType_t updateType ) { // Create the effect. C_ASW_Player *pPlayer = dynamic_cast< C_ASW_Player* >( m_hPlayer.Get() ); if ( pPlayer && !pPlayer->IsDormant() ) { pPlayer->DoAnimationEvent( (PlayerAnimEvent_t)m_iEvent.Get() ); } } public: CNetworkHandle( CBasePlayer, m_hPlayer ); CNetworkVar( int, m_iEvent ); }; IMPLEMENT_CLIENTCLASS_EVENT( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent, CTEPlayerAnimEvent ); BEGIN_RECV_TABLE_NOBASE( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent ) RecvPropEHandle( RECVINFO( m_hPlayer ) ), RecvPropInt( RECVINFO( m_iEvent ) ) END_RECV_TABLE() // marine anim events class C_TEMarineAnimEvent : public C_BaseTempEntity { public: DECLARE_CLASS( C_TEMarineAnimEvent, C_BaseTempEntity ); DECLARE_CLIENTCLASS(); virtual void PostDataUpdate( DataUpdateType_t updateType ) { // ignore events we've already predicted if (C_BasePlayer::IsLocalPlayer( m_hExcludePlayer.Get() )) // !engine->IsPlayingDemo() && return; // play anim event C_ASW_Marine *pMarine = dynamic_cast< C_ASW_Marine* >( m_hMarine.Get() ); if ( pMarine && !pMarine->IsDormant() ) { pMarine->DoAnimationEvent( (PlayerAnimEvent_t)m_iEvent.Get() ); } } public: CNetworkHandle( C_BasePlayer, m_hExcludePlayer ); CNetworkHandle( C_ASW_Marine, m_hMarine ); CNetworkVar( int, m_iEvent ); }; IMPLEMENT_CLIENTCLASS_EVENT( C_TEMarineAnimEvent, DT_TEMarineAnimEvent, CTEMarineAnimEvent ); BEGIN_RECV_TABLE_NOBASE( C_TEMarineAnimEvent, DT_TEMarineAnimEvent ) RecvPropEHandle( RECVINFO( m_hMarine ) ), RecvPropEHandle( RECVINFO( m_hExcludePlayer ) ), RecvPropInt( RECVINFO( m_iEvent ) ) END_RECV_TABLE() IMPLEMENT_NETWORKCLASS_ALIASED( ASW_Player, DT_ASW_Player ) BEGIN_NETWORK_TABLE( C_ASW_Player, DT_ASW_Player ) RecvPropBool( RECVINFO( m_fIsWalking ) ), RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ), RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ), RecvPropFloat( RECVINFO( m_angEyeAngles[2] ) ), RecvPropEHandle( RECVINFO( m_hMarine ) ), RecvPropEHandle( RECVINFO( m_hSpectatingMarine ) ), RecvPropInt (RECVINFO(m_iHealth)), RecvPropEHandle( RECVINFO ( m_pCurrentInfoMessage ) ), RecvPropEHandle( RECVINFO ( m_hVotingMissions ) ), RecvPropEHandle( RECVINFO ( m_hOrderingMarine ) ), RecvPropInt(RECVINFO(m_iLeaderVoteIndex) ), RecvPropInt(RECVINFO(m_iKickVoteIndex) ), RecvPropFloat(RECVINFO(m_fMapGenerationProgress) ), RecvPropTime( RECVINFO( m_flUseKeyDownTime ) ), RecvPropEHandle( RECVINFO ( m_hUseKeyDownEnt ) ), RecvPropInt (RECVINFO(m_nChangingSlot)), RecvPropInt (RECVINFO(m_iMapVoted)), RecvPropInt (RECVINFO(m_iNetworkedXP)), RecvPropInt (RECVINFO(m_iNetworkedPromotion)), END_RECV_TABLE() BEGIN_PREDICTION_DATA( C_ASW_Player ) DEFINE_PRED_FIELD( m_fIsWalking, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), DEFINE_PRED_FIELD( m_iHealth, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), DEFINE_PRED_FIELD( m_hHighlightEntity, FIELD_EHANDLE, FTYPEDESC_NOERRORCHECK ), DEFINE_PRED_FIELD( m_flUseKeyDownTime, FIELD_FLOAT, FTYPEDESC_NOERRORCHECK ), DEFINE_PRED_FIELD( m_hUseKeyDownEnt, FIELD_EHANDLE, FTYPEDESC_NOERRORCHECK ), END_PREDICTION_DATA() vgui::DHANDLE g_hBriefingFrame; C_ASW_Player::C_ASW_Player() : m_iv_angEyeAngles( "C_ASW_Player::m_iv_angEyeAngles" ) #if !defined(NO_STEAM) , m_CallbackUserStatsReceived( this, &C_ASW_Player::Steam_OnUserStatsReceived ) , m_CallbackUserStatsStored( this, &C_ASW_Player::Steam_OnUserStatsStored ) #endif { m_PlayerAnimState = CreatePlayerAnimState(this, this, LEGANIM_9WAY, false); AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR ); // create the profile list for clients // (server creates it in the game rules constructor serverside) MarineProfileList(); ASWEquipmentList(); m_pStimMusic = NULL; m_bCheckedLevel = false; m_vecLastMarineOrigin = vec3_origin; m_pCurrentInfoMessage = NULL; m_fNextThinkPushAway = 0; m_vecLastCameraPosition = vec3_origin; m_angLastCamera = QAngle(0,0,0); m_nLastCameraFrame = -1; m_hLastMarine = NULL; m_hLastTurningMarine = NULL; m_hLastAimingFloorZMarine = NULL; m_fLastVehicleYaw = 0; m_bLastInVehicle = false; m_fLastFloorZ = 0; m_fLastRestartTime = 0; m_fStimYaw = 0; m_Local.m_vecPunchAngle.Set( ROLL, 0 ); m_Local.m_vecPunchAngle.Set( PITCH, 0 ); m_Local.m_vecPunchAngle.Set( YAW, 0 ); m_fMarineChangeSmooth = 0.0f; m_vecMarineChangeCameraPos = vec3_origin; m_bGuidingMarine = false; m_bPlayingSingleBreathSound = false; m_bStartedStimMusic = false; m_iExperience = 0; m_iExperienceBeforeDebrief = 0; m_iPromotion = 0; m_bPendingSteamStats = false; m_flPendingSteamStatsStart = 0.0f; m_hUseKeyDownEnt = NULL; m_flUseKeyDownTime = 0.0f; m_roomDetailsCheckTimer.Invalidate(); m_szSoundscape[0] = 0; for ( int i = 0; i < ASW_NUM_XP_TYPES; i++ ) { m_iEarnedXP[ i ] = 0; m_iStatNumXP[ i ] = 0; } m_nChangingSlot = 0; } C_ASW_Player::~C_ASW_Player() { m_PlayerAnimState->Release(); if (m_bPlayingSingleBreathSound) { StopStimSound(); } if (m_pStimCam) delete m_pStimCam; } void C_ASW_Player::Precache() { BaseClass::Precache(); } void C_ASW_Player::StopStimSound() { StopSound("noslow.SingleBreath"); m_bPlayingSingleBreathSound = false; if (ASWGameRules()->GetGameState() == ASW_GS_INGAME) EmitSound("noslow.BulletTimeOut"); } C_ASW_Player* C_ASW_Player::GetLocalASWPlayer( int nSlot ) { return ToASW_Player( C_BasePlayer::GetLocalPlayer( nSlot ) ); } const QAngle& C_ASW_Player::GetRenderAngles() { if ( IsRagdoll() ) { return vec3_angle; } else { return m_PlayerAnimState->GetRenderAngles(); } } void C_ASW_Player::UpdateClientSideAnimation() { // We do this in a different order than the base class. // We need our cycle to be valid for when we call the playeranimstate update code, // or else it'll synchronize the upper body anims with the wrong cycle. // if ( GetSequence() != -1 ) /// { // // move frame forward // FrameAdvance( gpGlobals->frametime ); // } // Update the animation data. It does the local check here so this works when using // a third-person camera (and we don't have valid player angles). if (IsLocalPlayer(this)) { ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( this ); //m_PlayerAnimState->Update( EyeAngles()[YAW], m_angEyeAngles[PITCH] ); g_IngamePanelManager.UpdateMouseOvers(); } //else //m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] ); if ( GetSequence() != -1 ) { // latch old values OnLatchInterpolatedVariables( LATCH_ANIMATION_VAR ); } } void C_ASW_Player::PostDataUpdate( DataUpdateType_t updateType ) { // C_BaseEntity assumes we're networking the entity's angles, so pretend that it // networked the same value we already have. SetNetworkAngles( GetLocalAngles() ); BaseClass::PostDataUpdate( updateType ); } void C_ASW_Player::DoAnimationEvent( PlayerAnimEvent_t event ) { // m_PlayerAnimState->DoAnimationEvent( event ); } CBaseCombatWeapon* C_ASW_Player::ASWAnim_GetActiveWeapon() { return GetActiveWeapon(); } bool C_ASW_Player::ASWAnim_CanMove() { return true; } // stops the player's current marine from using a computer console or other duration use object in the world void C_ASW_Player::StopUsing() { char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "cl_stopusing"); engine->ClientCmd(buffer); } void C_ASW_Player::SelectHackOption(int iHackOption) { char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "cl_selecthack %d", iHackOption); engine->ClientCmd(buffer); } void C_ASW_Player::SelectTumbler(int iTumblerImpulse) { char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "impulse %d", iTumblerImpulse); Msg("Sending %s\n", buffer); engine->ClientCmd(buffer); } void C_ASW_Player::SendRosterSelectCommand( const char *command, int index, int nPreferredSlot ) { //if ( m_bPendingSteamStats && !asw_roster_select_bypass_steam.GetBool() && ( gpGlobals->curtime - m_flPendingSteamStatsStart ) < 2.0f ) //return; char buffer[64]; if ( index >= 0 && index < ASW_NUM_MARINE_PROFILES ) { // grab default inventory numbers char primarybuf[24]; char secondarybuf[26]; char extrabuf[24]; Q_snprintf(primarybuf, sizeof(primarybuf), "asw_default_primary_%d", index); Q_snprintf(secondarybuf, sizeof(secondarybuf), "asw_default_secondary_%d", index); Q_snprintf(extrabuf, sizeof(extrabuf), "asw_default_extra_%d", index); int default_primary = -1; int default_secondary = -1; int default_extra = -1; ConVar *pCVar = cvar->FindVar(primarybuf); if (pCVar) default_primary = pCVar->GetInt(); pCVar = cvar->FindVar(secondarybuf); if (pCVar) default_secondary = pCVar->GetInt(); pCVar = cvar->FindVar(extrabuf); if (pCVar) default_extra = pCVar->GetInt(); CASW_EquipItem *pPrimary = ASWEquipmentList()->GetRegular( default_primary ); if ( pPrimary ) { if ( !IsWeaponUnlocked( STRING( pPrimary->m_EquipClass ) ) ) { default_primary = 0; } } CASW_EquipItem *pSecondary = ASWEquipmentList()->GetRegular( default_secondary ); if ( pSecondary ) { if ( !IsWeaponUnlocked( STRING( pSecondary->m_EquipClass ) ) ) { default_secondary = 0; } } CASW_EquipItem *pExtra = ASWEquipmentList()->GetExtra( default_extra ); if ( pExtra ) { if ( !IsWeaponUnlocked( STRING( pExtra->m_EquipClass ) ) ) { default_extra = ASWEquipmentList()->GetExtraIndex( "asw_weapon_medkit" ); } } Q_snprintf(buffer, sizeof(buffer), "%s %d %d %d %d %d", command, index, nPreferredSlot, default_primary, default_secondary, default_extra ); engine->ServerCmd(buffer); } else { Q_snprintf(buffer, sizeof(buffer), "%s %d %d", command, index, nPreferredSlot); engine->ServerCmd(buffer); } } void C_ASW_Player::RosterSelectMarine( int index ) { SendRosterSelectCommand( "cl_selectm", index ); } void C_ASW_Player::RosterSelectSingleMarine( int index ) { SendRosterSelectCommand( "cl_selectsinglem", index ); } void C_ASW_Player::RosterSelectMarineForSlot( int index, int nPreferredSlot ) { SendRosterSelectCommand( "cl_selectm", index, nPreferredSlot ); } void C_ASW_Player::RosterDeselectMarine(int iProfileIndex) { char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "cl_dselectm %d", iProfileIndex); engine->ClientCmd(buffer); } void C_ASW_Player::RosterSpendSkillPoint( int iProfileIndex, int nSkillSlot ) { if (!ASWGameResource()) return; if (iProfileIndex < 0 || iProfileIndex >= ASW_NUM_MARINE_PROFILES ) { //Msg("bad profile index\n"); return; } if (nSkillSlot < 0 || nSkillSlot >= ASW_SKILL_SLOT_SPARE ) { //Msg("bad skill index\n"); return; } CLocalPlayerFilter filter; C_BaseEntity::EmitSound( filter, -1 /*SOUND_FROM_LOCAL_PLAYER*/, "ASWInterface.SkillUpgrade2" ); char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "cl_spendskill %d %d", iProfileIndex, nSkillSlot); //Msg("Sending command %s\n", buffer); engine->ClientCmd(buffer); } void C_ASW_Player::LoadoutSelectEquip(int iMarineIndex, int iInvSlot, int iEquipIndex) { CASW_EquipItem *pWeapon = ASWEquipmentList()->GetItemForSlot( iInvSlot, iEquipIndex ); if ( pWeapon ) { if ( !IsWeaponUnlocked( STRING( pWeapon->m_EquipClass ) ) ) { if ( iInvSlot == ASW_INVENTORY_SLOT_EXTRA ) { iEquipIndex = ASWEquipmentList()->GetExtraIndex( "asw_weapon_medkit" ); } else { iEquipIndex = 0; } } } int iProfileIndex = -1; if ( ASWGameResource() ) { C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource(iMarineIndex); if (pMR) { // save this loadout selection, to be autoselected next time we pick this marine iProfileIndex = pMR->GetProfileIndex(); if (iProfileIndex >=0 &&iProfileIndex=0 && iInvSlot <=2) { char buffer[32]; if (iInvSlot == 0) Q_snprintf(buffer, sizeof(buffer), "asw_default_primary_%d", iProfileIndex); else if (iInvSlot == 1) Q_snprintf(buffer, sizeof(buffer), "asw_default_secondary_%d", iProfileIndex); else if (iInvSlot == 2) Q_snprintf(buffer, sizeof(buffer), "asw_default_extra_%d", iProfileIndex); ConVar *pCVar = cvar->FindVar(buffer); if (pCVar) { pCVar->SetValue(iEquipIndex); } } } } if (iProfileIndex != -1) { char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "cl_loadout %d %d %d", iProfileIndex, iInvSlot, iEquipIndex); engine->ClientCmd(buffer); } } void C_ASW_Player::LoadoutSendStored(C_ASW_Marine_Resource *pMR) { if (!pMR) return; C_ASW_Game_Resource *pGameResource = ASWGameResource(); if (!pGameResource) return; // find our index in the list of marine infos int iMarineResourceIndex= -1; for (int i=0;iGetMaxMarineResources();i++) { C_ASW_Marine_Resource *pOtherResource = pGameResource->GetMarineResource(i); if (pOtherResource == pMR) { iMarineResourceIndex = i; break; } } if (iMarineResourceIndex == -1) return; int iRosterIndex = pMR->m_MarineProfileIndex; int iPrimary = -1; int iSecondary = -1; int iExtra = -1; ConVar *pCVar = NULL; char buffer[32]; Q_snprintf(buffer, sizeof(buffer), "asw_default_primary_%d", iRosterIndex); pCVar = cvar->FindVar(buffer); if (pCVar) iPrimary = pCVar->GetInt(); Q_snprintf(buffer, sizeof(buffer), "asw_default_secondary_%d", iRosterIndex); pCVar = cvar->FindVar(buffer); if (pCVar) iSecondary = pCVar->GetInt(); Q_snprintf(buffer, sizeof(buffer), "asw_default_extra_%d", iRosterIndex); pCVar = cvar->FindVar(buffer); if (pCVar) iExtra = pCVar->GetInt(); CASW_EquipItem *pPrimary = ASWEquipmentList()->GetRegular( iPrimary ); if ( pPrimary ) { if ( !IsWeaponUnlocked( STRING( pPrimary->m_EquipClass ) ) ) { iPrimary = 0; } } CASW_EquipItem *pSecondary = ASWEquipmentList()->GetRegular( iSecondary ); if ( pSecondary ) { if ( !IsWeaponUnlocked( STRING( pSecondary->m_EquipClass ) ) ) { iSecondary = 0; } } CASW_EquipItem *pExtra = ASWEquipmentList()->GetExtra( iExtra ); if ( pExtra ) { if ( !IsWeaponUnlocked( STRING( pExtra->m_EquipClass ) ) ) { iExtra = ASWEquipmentList()->GetExtraIndex( "asw_weapon_medkit" ); } } char mbuffer[64]; Q_snprintf(mbuffer, sizeof(mbuffer), "cl_loadouta %d %d %d %d", iRosterIndex, iPrimary, iSecondary, iExtra); engine->ClientCmd(mbuffer); } void C_ASW_Player::StartReady() { // todo: if we're not the leader, do a cl_ready if (ASWGameResource() && ASWGameResource()->GetLeader() == this) engine->ClientCmd("cl_start"); else engine->ClientCmd("cl_ready"); } void C_ASW_Player::CampaignSaveAndShow() { engine->ClientCmd("cl_campaignsas"); } void C_ASW_Player::NextCampaignMission(int iTargetMission) { char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "cl_campaignnext %d", iTargetMission); engine->ClientCmd(buffer); } void C_ASW_Player::CampaignLaunchMission(int iTargetMission) { char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "cl_campaignlaunch %d", iTargetMission); engine->ClientCmd(buffer); } bool C_ASW_Player::ShouldDraw() // we don't draw the player at all (only the npc's that he's remote controlling) { if (m_hMarine.Get()!=NULL) return false; return (g_DrawPlayer.GetBool()); } // inventory void C_ASW_Player::ActivateInventoryItem(int slot) { C_ASW_Marine* pMarine = GetMarine(); if (!pMarine || pMarine->GetHealth()<=0) return; if (pMarine->GetFlags() & FL_FROZEN) // don't allow this if the marine is frozen return; // check we have an item in that slot C_ASW_Weapon* pWeapon = pMarine->GetASWWeapon(slot); if (!pWeapon) return; // if it's an offhand activate, tell the server we want to activate it if (pWeapon->GetWeaponInfo() && pWeapon->GetWeaponInfo()->m_bOffhandActivate) { char buffer[64]; Q_snprintf(buffer, sizeof(buffer), "cl_offhand %d", slot); engine->ClientCmd(buffer); // and predict it? if ( prediction->InPrediction() && pWeapon->IsPredicted() ) pWeapon->OffhandActivate(); return; } // otherwise, make it our selected weapon if (pWeapon != pMarine->GetActiveWeapon()) ::input->MakeWeaponSelection( pWeapon ); } void C_ASW_Player::LaunchMissionCompleteFrame(bool bSuccess) { // create the basic frame which holds our briefing panels if (!GetClientModeASW()) return; GetClientModeASW()->m_hMissionCompleteFrame = new MissionCompleteFrame( bSuccess, GetClientMode()->GetViewport(), "m_MissionCompleteFrame" ); } void C_ASW_Player::LaunchBriefingFrame(void) { using namespace vgui; if (engine->IsLevelMainMenuBackground()) // don't show briefing on main menu { ::input->CAM_ToFirstPerson(); return; } else if (ASWGameRules()) { if (ASWGameRules()->IsIntroMap()) { ::input->CAM_ToFirstPerson(); new CASW_VGUI_Skip_Intro(GetClientMode()->GetViewport(), "SkipIntro"); return; } else if (ASWGameRules()->IsOutroMap()) { ::input->CAM_ToFirstPerson(); new CASW_VGUI_Skip_Intro(GetClientMode()->GetViewport(), "SkipIntro"); return; } } // create the basic frame which holds our briefing panels //Msg("[%d] Assigning briefing frame\n", entindex()); g_hBriefingFrame = new BriefingFrame( GetClientMode()->GetViewport(), "g_BriefingFrame" ); if (!g_hBriefingFrame.Get()) { Msg("Error: Briefing frame was closed immediately on opening - game isn't in briefing state?\n"); } } /* void C_ASW_Player::StopAllMusic() { CUtlVector< SndInfo_t > sndlist; enginesound->GetActiveSounds(sndlist); for (int i=0;im_hOutroFrame.Get()) { GetClientModeASW()->m_hOutroFrame->Close(); GetClientModeASW()->m_hOutroFrame = NULL; } // create the basic frame which holds our briefing panels Msg("[%d] Assigning outro frame\n", entindex()); GetClientModeASW()->m_hOutroFrame = new OutroFrame( GetClientMode()->GetViewport(), "m_OutroFrame" ); } void C_ASW_Player::LaunchCampaignFrame(void) { if (GetClientModeASW()->m_hCampaignFrame.Get()) { GetClientModeASW()->m_hCampaignFrame->Close(); GetClientModeASW()->m_hCampaignFrame = NULL; } FadeInPanel *pFadeIn = dynamic_cast(GetClientMode()->GetViewport()->FindChildByName("FadeIn", true)); char mapName[255]; Q_FileBase( engine->GetLevelName(), mapName, sizeof(mapName) ); if (!pFadeIn && UTIL_ASW_MissionHasBriefing(mapName)) // don't create one of these if there's already one around, or in the intro { Msg("%f: creating fadein panel\n", gpGlobals->curtime); new FadeInPanel(GetClientMode()->GetViewport(), "FadeIn"); } else if (pFadeIn) { pFadeIn->MoveToFront(); } // create the basic frame which holds our briefing panels Msg("[%d] Assigning campaign frame\n", entindex()); GetClientModeASW()->m_hCampaignFrame = new CampaignFrame( GetClientMode()->GetViewport(), "m_CampaignFrame" ); } void C_ASW_Player::CloseBriefingFrame() { if (g_hBriefingFrame.Get()) { Msg("C_ASW_Player::CloseBriefingFrame stopping music\n"); if (GetClientModeASW()) GetClientModeASW()->StopBriefingMusic(); g_hBriefingFrame->SetDeleteSelfOnClose(true); g_hBriefingFrame->Close(); g_hBriefingFrame = NULL; FadeInPanel *pFadeIn = dynamic_cast(GetClientMode()->GetViewport()->FindChildByName("FadeIn", true)); if (pFadeIn) { pFadeIn->AllowFastRemove(); } // clear the currently visible part of the chat CHudChat *pChat = GET_HUDELEMENT( CHudChat ); if (pChat && pChat->GetChatHistory()) pChat->GetChatHistory()->ResetAllFades( false, false, 0 ); } } C_ASW_Marine* C_ASW_Player::GetMarine() { return m_hMarine.Get(); } C_ASW_Marine* C_ASW_Player::GetMarine() const { return m_hMarine.Get(); } C_ASW_Marine* C_ASW_Player::GetSpectatingMarine() { return m_hSpectatingMarine.Get(); } Vector C_ASW_Player::GetAutoaimVectorForMarine( C_ASW_Marine* marine, float flDelta, float flNearMissDelta ) { // Never autoaim a predicted weapon (for now) Vector forward; AngleVectors( EyeAngles(), &forward ); // + m_Local.m_vecPunchAngle return forward; } void C_ASW_Player::PreThink( void ) { BaseClass::PreThink(); HandleSpeedChanges(); } void C_ASW_Player::ClientThink() { VPROF_BUDGET( "C_ASW_Player::ClientThink", VPROF_BUDGETGROUP_ASW_CLIENT ); BaseClass::ClientThink(); if (!IsLocalPlayer( this )) return; ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( this ); // check for stims if ( ASWGameRules() ) { bool bDeathCam = ( gpGlobals->curtime >= ASWGameRules()->m_fMarineDeathTime && gpGlobals->curtime <= ASWGameRules()->m_fMarineDeathTime + asw_time_scale_delay.GetFloat() + asw_marine_death_cam_time.GetFloat() + 1.5f ); // This isn't a death cam slowdown float f = GameTimescale()->GetCurrentTimescale(); static float lastTimescale = -1; if ( f != lastTimescale ) { if ( !m_bStartedStimMusic && f < lastTimescale && ASWGameRules()->GetGameState() == ASW_GS_INGAME ) { if ( !m_bPlayingSingleBreathSound ) { EmitSound("noslow.BulletTimeIn"); EmitSound("noslow.SingleBreath"); } if ( !bDeathCam ) { StartStimMusic(); } m_bPlayingSingleBreathSound = true; } else { if ( lastTimescale <= 0.35f && f > lastTimescale ) { StopStimSound(); StopStimMusic(); } if ( lastTimescale < 1.0f && f >= 1.0f ) { // if the stim has completely faded out, then clear the pointer to the music so the music is restarted from the beginning next time ClearStimMusic(); } } lastTimescale = f; engine->SetPitchScale(f); if ( f > asw_stim_cam_time.GetFloat() ) { if (GetStimCam()) GetStimCam()->SetActive( false ); } } if (f < 1.0f && !ASWGameRules()->ShouldPlayStimMusic()) // check for stopping stim music if level music kicks in while we're rocking out to stims { StopStimMusic(true); } // we're in slomo, so make sure our stimcam is on if (f < asw_stim_cam_time.GetFloat()) { // enable the stylin' cam if (GetMarine()) { // check if there's a mapper designed camera turned on C_PointCamera *pCameraEnt = GetPointCameraList(); bool bMapperCam = false; for ( int cameraNum = 0; pCameraEnt != NULL; pCameraEnt = pCameraEnt->m_pNext ) { if ( pCameraEnt != GetStimCam() && pCameraEnt->IsActive() && !pCameraEnt->IsDormant()) { bMapperCam = true; break; } ++cameraNum; } if (!bMapperCam) { if (asw_spinning_stim_cam.GetBool()) { if (!GetStimCam()) CreateStimCamera(); if (GetStimCam()) { // no mapper cam, turn on our stim one GetStimCam()->SetActive( true ); Vector offset = Vector(asw_stim_cam_x.GetFloat(), asw_stim_cam_y.GetFloat(), asw_stim_cam_z.GetFloat()); Vector offset_r; VectorRotate(offset, QAngle(0, GetMarine()->GetAbsAngles()[YAW] + m_fStimYaw, 0), offset_r); if (GetMarine()) GetStimCam()->SetAbsOrigin(GetMarine()->GetAbsOrigin() + offset_r); // rotate it around us GetStimCam()->SetAbsAngles(QAngle(asw_stim_cam_pitch.GetFloat(), m_fStimYaw + GetMarine()->GetAbsAngles()[YAW]+asw_stim_cam_yaw.GetFloat(), asw_stim_cam_roll.GetFloat())); m_fStimYaw += gpGlobals->frametime * asw_stim_cam_rotate_speed.GetFloat(); //Msg("Showing marine's cam\n"); } } } else { // make sure the stim cam is off, so the mapper placed cam can work if (GetStimCam()) GetStimCam()->SetActive( false ); //Msg("Showing mapper's cam\n"); } } } // check for launching the briefing static int last_state=1; if (ASWGameRules()->GetGameState() != last_state) Msg("[%d] Game rules state changed to %d\n", entindex(), ASWGameRules()->GetGameState()); last_state = ASWGameRules()->GetGameState(); if (ASWGameRules()->GetGameState() == ASW_GS_BRIEFING && !g_hBriefingFrame.Get() && !GetClientModeASW()->m_bLaunchedBriefing) { GetClientModeASW()->m_bLaunchedBriefing = true; //Msg("[%d] Launching briefing frame\n", entindex()); LaunchBriefingFrame(); } else if (ASWGameRules()->GetGameState() == ASW_GS_INGAME) { if (!m_bCheckedLevel) { m_bCheckedLevel = true; } } else if (ASWGameRules()->GetGameState() == ASW_GS_DEBRIEF) { if (m_bPlayingSingleBreathSound) StopStimSound(); if (!GetClientModeASW()->m_hMissionCompleteFrame.Get() && !GetClientModeASW()->m_bLaunchedDebrief) { if (ASWGameRules()->GetMissionSuccess()) { GetClientModeASW()->m_bLaunchedDebrief = true; LaunchMissionCompleteFrame(true); } else if (ASWGameRules()->GetMissionFailed()) { GetClientModeASW()->m_bLaunchedDebrief = true; LaunchMissionCompleteFrame(false); } } } else if (ASWGameRules()->GetGameState() == ASW_GS_CAMPAIGNMAP) { if (m_bPlayingSingleBreathSound) StopStimSound(); if (!GetClientModeASW()->m_bLaunchedCampaignMap) { GetClientModeASW()->m_bLaunchedCampaignMap = true; LaunchCampaignFrame(); } } } else { Msg("can't check briefing stuff, no game rules present\n"); } if (m_pCurrentInfoMessage.Get() != GetClientModeASW()->m_hLastInfoMessage.Get()) { GetClientModeASW()->m_hLastInfoMessage = m_pCurrentInfoMessage; // todo: launch a window with this message if (GetClientModeASW()->m_hLastInfoMessage.Get()) { Msg("Launching window cos the info message changed!\n"); // add it to the message log if we haven't seen it before bool bOldMessage = false; for (int i=0;im_InfoMessageLog.Count();i++) { if (GetClientModeASW()->m_InfoMessageLog[i].Get() == m_pCurrentInfoMessage.Get()) { bOldMessage = true; break; } } if (!bOldMessage) { ClientModeASW::InfoMessageHandle_t handle = m_pCurrentInfoMessage.Get(); GetClientModeASW()->m_InfoMessageLog.AddToTail(handle); } CASW_VGUI_Info_Message *pInfoWindow = new CASW_VGUI_Info_Message( GetClientMode()->GetViewport(), "InfoMessageWindow", m_pCurrentInfoMessage.Get()); vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew"); pInfoWindow->SetScheme(scheme); pInfoWindow->InvalidateLayout(true); //pInfoWindow->ASWInit(); } else Msg("info message cleared!\n"); } if ( gpGlobals->curtime >= m_fNextThinkPushAway ) { if (GetMarine() && !GetMarine()->IsInVehicle()) { PerformObstaclePushaway( GetMarine() ); } m_fNextThinkPushAway = gpGlobals->curtime + PUSHAWAY_THINK_INTERVAL; } int nprintIndex = 0; if ( asw_show_mouse_entity.GetBool() ) { engine->Con_NPrintf( nprintIndex, "Mouse over entity:"); nprintIndex++; if ( ASWInput() && ASWInput()->GetMouseOverEntity() ) { engine->Con_NPrintf( nprintIndex, "(%d) %s", ASWInput()->GetMouseOverEntity()->entindex(), ASWInput()->GetMouseOverEntity()->GetClassname() ); nprintIndex++; } else { engine->Con_NPrintf( nprintIndex, "None"); nprintIndex++; } } if (asw_particle_count.GetBool()) { if (ParticleMgr()) { engine->Con_NPrintf( nprintIndex, "Num Particles: %d / 2048", ParticleMgr()->GetNumParticles() ); nprintIndex++; } else { engine->Con_NPrintf( nprintIndex, "Num Particles: ??? / 2048" ); nprintIndex++; } } if (asw_dlight_list.GetBool()) { dlight_t *lights[MAX_DLIGHTS]; int nLights = effects->CL_GetActiveDLights( lights ); for (int i=0;i= nLights) { engine->Con_NPrintf( nprintIndex, "Light: %d - off", i ); nprintIndex++; } else { const char *szLightType = "Generic"; if (lights[i]->key == 0) szLightType = "Explosion/Sparks"; else if (lights[i]->key < 0) szLightType = "Spotlight end"; else if (lights[i]->key == LIGHT_INDEX_TE_DYNAMIC) szLightType = "Legacy TE"; else if (lights[i]->key >= ASW_LIGHT_INDEX_FIRES) szLightType = "env_fire"; else if (lights[i]->key >= LIGHT_INDEX_MUZZLEFLASH) szLightType = "muzzleflash"; if (lights[i]->key >= 0 && lights[i]->key < MAX_EDICTS) { C_BaseEntity *pEnt = C_BaseEntity::Instance(lights[i]->key); C_ASW_Flare_Projectile *pFlare = dynamic_cast(pEnt); if (pFlare) szLightType = "Flare"; C_ASW_Flamer_Projectile *pFlamer = dynamic_cast(pEnt); if (pFlamer) szLightType = "Flamer"; } engine->Con_NPrintf( nprintIndex, "Light: %d - %s (key:%d)", i, szLightType, lights[i]->key); nprintIndex++; } } } if (m_hVotingMissions.Get()) m_hVotingMissions->Update(); // update snow C_ASW_Snow_Volume::UpdateSnow(this); UpdateLocalMarineGlow(); if ( missionchooser->RandomMissions() && missionchooser->RandomMissions()->ValidMapLayout() ) { UpdateRoomDetails(); } } void ForceSoundscape( const char *pSoundscapeName, float radius ); void C_ASW_Player::UpdateRoomDetails() { VPROF("C_ASW_Player::UpdateRoomDetails"); if ( m_roomDetailsCheckTimer.HasStarted() && !m_roomDetailsCheckTimer.IsElapsed() ) return; m_roomDetailsCheckTimer.Start( 1.0f ); // check soundscape every second if ( !missionchooser || !missionchooser->RandomMissions() || !ASWGameRules() || ASWGameRules()->GetGameState() != ASW_GS_INGAME ) { return; } C_ASW_Marine *pMarine = GetMarine(); if ( !pMarine ) { pMarine = GetSpectatingMarine(); } Vector vecAmbientPos = vec3_origin; if ( pMarine ) { vecAmbientPos = pMarine->GetAbsOrigin(); } else { vecAmbientPos = GetAbsOrigin(); } IASW_Random_Missions *pRandomMissions = missionchooser->RandomMissions(); IASW_Room_Details* pRoom = pRandomMissions->GetRoomDetails( vecAmbientPos ); if ( pRoom ) { // update soundscape static char szSoundscape[64]; pRoom->GetSoundscape( szSoundscape, 64 ); if ( szSoundscape[0] && Q_stricmp( szSoundscape, m_szSoundscape ) ) { Q_strcpy( m_szSoundscape, szSoundscape ); ForceSoundscape( m_szSoundscape, 36.0f ); } // update ambient light if ( !m_hAmbientLight.Get() ) { C_EnvAmbientLight *pAmbient = new C_EnvAmbientLight; if ( pAmbient ) { if ( pAmbient->InitializeAsClientEntity( NULL, false ) ) { pAmbient->InitSpatialEntity(); pAmbient->SetFalloff( -1, -1 ); // make it global pAmbient->SetColor( Vector( 1, 1, 1 ) ); pAmbient->SetCurWeight( 1.0f ); pAmbient->SetEnabled( true ); m_hAmbientLight = pAmbient; } } } if ( m_hAmbientLight.Get() ) { Vector vecTargetColor = m_hAmbientLight->GetTargetColor(); Vector vecNewColor = pRoom->GetAmbientLight(); if ( vecTargetColor != vecNewColor ) { // change to the new ambient light setting //Msg( "player set local ambient light to %f %f %f\n", VectorExpand( vecNewColor ) ); m_hAmbientLight->SetColor( vecNewColor, 2.0f ); } } } } void C_ASW_Player::ShowMessageLog() { Msg("Launching window to show message log\n"); CASW_VGUI_Message_Log *pInfoWindow = new CASW_VGUI_Message_Log( GetClientMode()->GetViewport(), "InfoMessageLog"); vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew"); pInfoWindow->SetScheme(scheme); pInfoWindow->InvalidateLayout(true); } void C_ASW_Player::ShowPreviousInfoMessage(C_ASW_Info_Message *pMessage) { if (!pMessage) return; bool bOldMessage = false; for (int i=0;im_InfoMessageLog.Count();i++) { if (GetClientModeASW()->m_InfoMessageLog[i].Get() == pMessage) { bOldMessage = true; break; } } if (!bOldMessage) return; Msg("Launching window to show old info message\n"); CASW_VGUI_Info_Message *pInfoWindow = new CASW_VGUI_Info_Message( GetClientMode()->GetViewport(), "InfoMessageWindow", pMessage); vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew"); pInfoWindow->SetScheme(scheme); pInfoWindow->InvalidateLayout(true); } void C_ASW_Player::OnDataChanged( DataUpdateType_t updateType ) { BaseClass::OnDataChanged( updateType ); if ( updateType == DATA_UPDATE_CREATED ) { if ( GASWLoadingPanel() ) { GASWLoadingPanel()->SetLoadingMapName( NULL ); } if ( asw_building_room_thumbnails.GetBool() ) { engine->ClientCmd( "mat_fullbright 1; wait; asw_buildroomthumbnails" ); asw_building_room_thumbnails.SetValue( 0 ); } if ( IsLocalPlayer( this ) ) { int nSlot = C_BasePlayer::GetSplitScreenSlotForPlayer( this ); ACTIVE_SPLITSCREEN_PLAYER_GUARD( nSlot ); #ifdef USE_MEDAL_STORE // inform server of our persistent counts int iKills, iMissions, iCampaigns; GetMedalStore()->GetCounts(iMissions, iCampaigns, iKills, (gpGlobals->maxClients <= 1)); char buffer[48]; Q_snprintf(buffer, sizeof(buffer), "cl_ccounts %d %d %d", iMissions, iCampaigns, iKills); engine->ClientCmd(buffer); #endif // inform server of our autoreload preferences engine->ClientCmd( VarArgs( "cl_autoreload %d\n", asw_auto_reload.GetInt() ) ); // tell other players that we're fully connected engine->ClientCmd( "cl_fullyjoined\n" ); GetClientModeASW()->ClearCurrentColorCorrection(); } RequestExperience(); #ifndef USE_XP_FROM_STEAM if ( IsLocalPlayer( this ) ) { KeyValues *kv = new KeyValues( "XPUpdate" ); kv->SetInt( "xp", m_iExperience ); kv->SetInt( "pro", m_iPromotion ); engine->ServerCmdKeyValues( kv ); // kv gets deleted in here } #endif // We want to think every frame. SetNextClientThink( CLIENT_THINK_ALWAYS ); return; } // update snow immediately upon changing marine if (g_hSnowEmitter.IsValid() && IsLocalPlayer(this)) { C_ASW_Marine *pMarine = GetSpectatingMarine(); if (!pMarine) pMarine = GetMarine(); if (g_hSnowEmitter->m_hLastMarine.Get() != pMarine) { // update snow C_ASW_Snow_Volume::UpdateSnow(this); } } } C_BaseEntity* C_ASW_Player::GetUseEntity( void ) const { if ( m_iUseEntities > 0 && m_hUseEntities[ 0 ].Get() ) return m_hUseEntities[ 0 ].Get(); return BaseClass::GetUseEntity(); } C_BaseEntity* C_ASW_Player::GetPotentialUseEntity( void ) const { C_BaseEntity *pHighlightEntity = ASWInput()->GetHighlightEntity(); if ( pHighlightEntity ) { return pHighlightEntity; } return GetUseEntity(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CalculateBouncePlane( const Vector &vecMarineCenter, const Vector &vecIntersectingCenter, float flHalfExtent, Vector &vecBouncePlane ) { vecBouncePlane.Init( 0.0f, 0.0f, 0.0f ); if ( vecMarineCenter.x < vecIntersectingCenter.x - flHalfExtent ) { vecBouncePlane.x = -1.0f; } else if ( vecMarineCenter.x > vecIntersectingCenter.x + flHalfExtent ) { vecBouncePlane.x = 1.0f; } if ( vecMarineCenter.y < vecIntersectingCenter.y - flHalfExtent ) { vecBouncePlane.y = -1.0f; } else if ( vecMarineCenter.y > vecIntersectingCenter.y + flHalfExtent ) { vecBouncePlane.y = 1.0f; } VectorNormalize( vecBouncePlane ); } #define ATTACH_ATTRACTION_FORCE 512.0f //----------------------------------------------------------------------------- // Purpose: Avoid marines and their sentry guns //----------------------------------------------------------------------------- void C_ASW_Player::AvoidMarines( CUserCmd *pCmd ) { // Turn off the player avoidance code. if ( !asw_player_avoidance.GetBool() ) return; // Get the Alien Swarm game resource. C_ASW_Game_Resource *pGameResource = ASWGameResource(); if ( !pGameResource ) return; // Get the player controlled marine. // TODO: There may be more than one marine per player at some point. C_ASW_Marine *pMarine = GetMarine(); if ( !pMarine ) return; // Get the marine's collision properties. CCollisionProperty *pMarineCollision = pMarine->CollisionProp(); if ( !pMarineCollision ) return; // Test to see if the player controlled marine is dead. if ( !pMarine->IsAlive() ) return; // Up vector. static Vector vecUp( 0.0f, 0.0f, 1.0f ); // Get the player marine position and hull size. Vector vecMarineCenter = pMarineCollision->WorldSpaceCenter(); Vector vecMarineMin, vecMarineMax; pMarineCollision->WorldSpaceAABB( &vecMarineMin, &vecMarineMax ); // Find a marine to avoid - we only avoid one at a time. C_BaseEntity *pIntersectingEntity = NULL; CCollisionProperty *pIntersectingEntityCollision = NULL; Vector vecAvoidCenter, vecAvoidMin, vecAvoidMax; int nMarineCount = pGameResource->GetMaxMarineResources(); for ( int iMarine = 0; iMarine < nMarineCount; ++iMarine ) { // Get the marine resource - if it exists. C_ASW_Marine_Resource *pTestMarineResource = pGameResource->GetMarineResource( iMarine ); if ( !pTestMarineResource ) continue; // Get the marine - if it exists. C_ASW_Marine *pTestMarine = pTestMarineResource->GetMarineEntity(); if ( !pTestMarine ) continue; // Is the player controlled marines? if ( pMarine == pTestMarine ) continue; // Check to see if the avoid player is dormant. if ( pTestMarine->IsDormant() ) continue; // Is the avoid player solid? if ( pTestMarine->IsSolidFlagSet( FSOLID_NOT_SOLID ) ) continue; // Get the test marines collision properties. CCollisionProperty *pTestMarineCollision = pTestMarine->CollisionProp(); if ( pTestMarineCollision ) { vecAvoidCenter = pTestMarineCollision->WorldSpaceCenter(); pTestMarineCollision->WorldSpaceAABB( &vecAvoidMin, &vecAvoidMax ); // Collision? if ( IsBoxIntersectingBox( vecMarineMin, vecMarineMax, vecAvoidMin, vecAvoidMax ) ) { pIntersectingEntity = pTestMarine; pIntersectingEntityCollision = pTestMarineCollision; break; } } } // No marines to avoid. Check for sentry guns if ( !pIntersectingEntity ) { for ( int i = 0; i < g_SentryGuns.Count(); i++ ) { // Get the marine - if it exists. C_ASW_Sentry_Base *pTestSentry = g_SentryGuns[i]; if ( !pTestSentry ) continue; // Check to see if the avoid sentry is dormant. if ( pTestSentry->IsDormant() ) continue; // Is the avoid sentry solid? if ( pTestSentry->IsSolidFlagSet( FSOLID_NOT_SOLID ) ) continue; // Get the test sentry collision properties. CCollisionProperty *pTestSentryCollision = pTestSentry->CollisionProp(); if ( pTestSentryCollision ) { vecAvoidCenter = pTestSentryCollision->WorldSpaceCenter(); pTestSentryCollision->WorldSpaceAABB( &vecAvoidMin, &vecAvoidMax ); // Collision? if ( IsBoxIntersectingBox( vecMarineMin, vecMarineMax, vecAvoidMin, vecAvoidMax ) ) { pIntersectingEntity = pTestSentry; pIntersectingEntityCollision = pTestSentryCollision; break; } } } } if ( !pIntersectingEntity ) return; // Get marine speeds. float flMarineSpeed = pMarine->GetAbsVelocity().Length2D(); float flIntersectingMarineSpeed = pIntersectingEntity->GetAbsVelocity().Length2D(); // If the local marine is not moving and the intersecting marine is, then do nothing. if ( flMarineSpeed < 0.1f && flIntersectingMarineSpeed > 0.1f ) return; // Find the distance between marines and scale the extraction push by the marine bounds. Vector vecDelta; Vector vecIntersectingMarineCenter = pIntersectingEntityCollision->WorldSpaceCenter(); VectorSubtract( vecMarineCenter, vecIntersectingMarineCenter, vecDelta ); float flAvoidRadius = pIntersectingEntityCollision->BoundingRadius(); float flPushStrength = RemapValClamped( vecDelta.Length(), flAvoidRadius, 0, 0, asw_player_avoidance_force.GetInt() ); if ( flPushStrength < 0.01f ) return; Vector vecSeparationVelocity; Vector vecPush; Vector vecBouncePlane; CalculateBouncePlane( vecMarineCenter, vecIntersectingMarineCenter, asw_player_avoidance_fakehull.GetFloat(), vecBouncePlane ); // The player marine is moving. float flPushThreshold = ASW_MOVEMENT_NORM_SPEED * 0.90f; if ( flMarineSpeed > flPushThreshold ) { Vector vecVelocity = pMarine->GetAbsVelocity(); VectorNormalize( vecVelocity ); Vector vecDeltaNorm = vecDelta; VectorNormalize( vecDeltaNorm ); float flBackoff = DotProduct( vecVelocity, vecDeltaNorm ) * asw_player_avoidance_bounce.GetFloat(); for ( int iAxis = 0; iAxis < 3; ++iAxis ) { vecPush[iAxis] = ( vecVelocity[iAxis] - ( vecDeltaNorm[iAxis] * flBackoff ) ); } VectorNormalize( vecPush ); vecSeparationVelocity = vecPush * flPushStrength * 0.25f; } else { if ( vecBouncePlane.Length2DSqr() < 0.1f ) { vecBouncePlane = vecDelta; VectorNormalize( vecBouncePlane ); } vecPush = vecBouncePlane; VectorNormalize( vecPush ); vecSeparationVelocity = vecPush * flPushStrength; // Debug! // debugoverlay->AddLineOverlay( vecDelta + vecMarineCenter, ( vecBouncePlane * 225.0f ) + vecMarineCenter, 255, 0, 0, true, 0.05f ); // debugoverlay->AddLineOverlay( vecPush + vecMarineCenter, ( vecPush * 225.0f ) + vecMarineCenter, 255, 255, 0, true, 0.05f ); // debugoverlay->AddLineOverlay( vecVelocity + vecMarineCenter, ( vecVelocity * 225.0f ) + vecMarineCenter, 0, 0, 255, true, 0.05f ); } // Don't allow the max push speed to be greater than the max player speed. float flMaxPlayerSpeed = ASW_MOVEMENT_NORM_SPEED; if ( IsWalking() ) { flMaxPlayerSpeed = ASW_MOVEMENT_WALK_SPEED; } float flMaxPlayerSpeedSqr = flMaxPlayerSpeed * flMaxPlayerSpeed; if ( vecSeparationVelocity.LengthSqr() > flMaxPlayerSpeedSqr ) { vecSeparationVelocity.NormalizeInPlace(); VectorScale( vecSeparationVelocity, flMaxPlayerSpeed, vecSeparationVelocity ); } Vector currentdir; Vector rightdir; AngleVectors( ASW_MOVEMENT_AXIS, ¤tdir, &rightdir, NULL ); Vector vDirection = vecSeparationVelocity; VectorNormalize( vDirection ); float fwd = currentdir.Dot( vDirection ); float rt = rightdir.Dot( vDirection ); float forward = fwd * flPushStrength; float side = rt * flPushStrength; //Msg( "fwd: %f - rt: %f - forward: %f - side: %f\n", fwd, rt, forward, side ); pCmd->forwardmove += forward; pCmd->sidemove += side; // Clamp the move to within legal limits, preserving direction. This is a little // complicated because we have different limits for forward, back, and side //Msg( "PRECLAMP: forwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove ); float flForwardScale = 1.0f; if ( pCmd->forwardmove > fabs( cl_forwardspeed.GetFloat() ) ) { flForwardScale = fabs( cl_forwardspeed.GetFloat() ) / pCmd->forwardmove; } else if ( pCmd->forwardmove < -fabs( cl_backspeed.GetFloat() ) ) { flForwardScale = fabs( cl_backspeed.GetFloat() ) / fabs( pCmd->forwardmove ); } float flSideScale = 1.0f; if ( fabs( pCmd->sidemove ) > fabs( cl_sidespeed.GetFloat() ) ) { flSideScale = fabs( cl_sidespeed.GetFloat() ) / fabs( pCmd->sidemove ); } float flScale = MIN( flForwardScale, flSideScale ); pCmd->forwardmove *= flScale; pCmd->sidemove *= flScale; //Msg( "Pforwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove ); } bool C_ASW_Player::CreateMove( float flInputSampleTime, CUserCmd *pCmd ) { bool bResult = BaseClass::CreateMove( flInputSampleTime, pCmd ); AvoidMarines( pCmd ); if ( !IsInAVehicle() && asw_clientside_avoidance.GetBool() && !asw_marine_collision.GetBool()) { MarinePerformClientSideObstacleAvoidance( TICK_INTERVAL, pCmd ); } C_ASW_Marine* pMarine = GetMarine(); // if we're using a turret, clamp view angles to the ones set in the turret if (pMarine && pMarine->IsControllingTurret() && pMarine->GetRemoteTurret()) { pMarine->GetRemoteTurret()->CreateMove( flInputSampleTime, pCmd ); } // check if the marine is meant to be standing still if (pMarine && (gpGlobals->curtime < pMarine->GetStopTime() || pMarine->m_bPreventMovement || CASW_VGUI_Info_Message::HasInfoMessageOpen() || ( ASWInput()->ControllerModeActive() && pMarine->IsUsingComputerOrButtonPanel() ) || pMarine->IsUsingComputerOrButtonPanel() )) { // asw temp comment /* pCmd->forwardmove = 0; pCmd->sidemove = 0; */ } if (!pMarine && asw_rts_controls.GetBool()) { // set forward/side move to scroll the screen when mouse is at the edges int current_posx, current_posy; ::input->GetFullscreenMousePos(¤t_posx, ¤t_posy); //Msg("Cursor pos = %d %d ", current_posx, current_posy); if (current_posx <= 0) { //Msg("Scrolling left "); pCmd->sidemove = -cl_sidespeed.GetFloat(); } else if (current_posx >= ScreenWidth()-1) { //Msg("Scrolling right "); pCmd->sidemove = cl_sidespeed.GetFloat(); } if (current_posy <= 0) { //Msg("Scrolling up "); pCmd->forwardmove = cl_sidespeed.GetFloat(); } else if (current_posy >= ScreenHeight()-1) { //Msg("Scrolling down "); pCmd->forwardmove = -cl_sidespeed.GetFloat(); } //Msg("\n"); } if ( pMarine && pMarine->GetCurrentMeleeAttack() ) { ASWMeleeSystem()->CreateMove( flInputSampleTime, pCmd, pMarine ); } return bResult; } #define LOOK_AHEAD 3.0f void C_ASW_Player::MarineStopMoveIfBlocked(float flFrameTime, CUserCmd *pCmd, C_ASW_Marine* pMarine) { C_ASW_Game_Resource *pGameResource = ASWGameResource(); if (!pGameResource) return; Vector size = pMarine->WorldAlignSize(); //float radius = 1.0f * sqrt( size.x * size.x + size.y * size.y ); size *= 2; Vector currentdir; Vector rightdir; QAngle vAngles = pCmd->viewangles; vAngles.x = 0; if ( asw_controls.GetInt() == 1 ) AngleVectors( ASW_MOVEMENT_AXIS, ¤tdir, &rightdir, NULL ); else AngleVectors( vAngles, ¤tdir, &rightdir, NULL ); Vector vel = pMarine->GetLocalVelocity(); // our current velocity, will it take us inside an NPC? bool bStill = (vel.Length2D() == 0); if (pCmd->sidemove == 00 && pCmd->forwardmove == 0) m_bGuidingMarine = false; // make sure to stop all guiding if the player lets go of movement keys Vector vecPlayerPushing(pCmd->sidemove, pCmd->forwardmove, 0); if (m_bGuidingMarine) { // make the marine move in the direction we want to guide in pCmd->forwardmove = m_vecGuiding.y; pCmd->sidemove = m_vecGuiding.x; if ( pCmd->forwardmove > 0.0f ) { pCmd->forwardmove *= cl_forwardspeed.GetFloat(); } else { pCmd->forwardmove *= cl_backspeed.GetFloat(); } pCmd->sidemove *= cl_sidespeed.GetFloat(); } //Msg("vel %f, %f, %f 2dlen %f still %d\n", vel.x, vel.y, vel.z, vel.Length2D(), bStill); //INetChannelInfo *nci = engine->GetNetChannelInfo(); // check if we're stuck inside any NPCS and push ourselves out if we are Vector vecMarinePos = pMarine->GetAbsOrigin(); Vector vecMarineSize = pMarine->WorldAlignSize(); //float fMarineRadius = 1.0f * sqrt( vecMarineSize.x * vecMarineSize.x + vecMarineSize.y * vecMarineSize.y ); int c = pGameResource->EnumerateMarinesInBox(vecMarinePos - (vecMarineSize * 0.5f), vecMarinePos + (vecMarineSize * 0.5f)); //CASW_MarineAndObjectEnumerator stuckcheck( fMarineRadius ); //partition->EnumerateElementsInBox(PARTITION_CLIENT_SOLID_EDICTS, //vecMarinePos - (vecMarineSize * 0.5f), //vecMarinePos + (vecMarineSize * 0.5f), false, &stuckcheck ); if (asw_debug_clientside_avoidance.GetBool()) debugoverlay->AddBoxOverlay( vecMarinePos, -vecMarineSize * 0.5f, vecMarineSize * 0.5f, vec3_angle, 0, 255, 0, true, 0 ); float adjustforwardmove = 0.0f; float adjustsidemove = 0.0f; //int c = stuckcheck.GetObjectCount(); //bool bStuckInside = (c > 0); //if ( c <= 0 ) //return; int i = 0; for ( i = 0; i < c; i++ ) { //C_AI_BaseNPC *obj = dynamic_cast< C_AI_BaseNPC *>(stuckcheck.GetObject( i )); C_ASW_Marine *obj = pGameResource->EnumeratedMarine(i); if( !obj || obj == pMarine ) continue; // don't avoid aliens laying dead on the floor if (!obj->IsAlive() || obj->GetHealth() <= 0) continue; Vector vecToObject = obj->GetAbsOrigin() - pMarine->GetAbsOrigin(); Vector vRayDir = vecToObject; VectorNormalize( vRayDir ); adjustforwardmove -= vRayDir.y * AVOID_SPEED; adjustsidemove -= vRayDir.x * AVOID_SPEED; //Msg("inside an npc %f %f %f\n", vRayDir.x, vRayDir.y, vRayDir.z); } pCmd->forwardmove += adjustforwardmove; pCmd->sidemove += adjustsidemove; if ( pCmd->forwardmove > 0.0f ) { pCmd->forwardmove = clamp( pCmd->forwardmove, -cl_forwardspeed.GetFloat(), cl_forwardspeed.GetFloat() ); } else { pCmd->forwardmove = clamp( pCmd->forwardmove, -cl_backspeed.GetFloat(), cl_backspeed.GetFloat() ); } pCmd->sidemove = clamp( pCmd->sidemove, -cl_sidespeed.GetFloat(), cl_sidespeed.GetFloat() ); Vector forward_vel = pCmd->forwardmove * currentdir; Vector side_vel = pCmd->sidemove * rightdir; if (bStill) vel = forward_vel + side_vel; float fVelScale = flFrameTime * LOOK_AHEAD; //fVelScale = nci->GetLatency( FLOW_OUTGOING ); ////int lerpTicks = TIME_TO_TICKS( 0.1f ); // fix: hardcoded 0.1f amount of lerptime! ////fVelScale += TICKS_TO_TIME( lerpTicks ); Vector vel_norm = vel; if (!bStill) vel_norm.NormalizeInPlace(); Vector dest = pMarine->GetAbsOrigin() + (vel_norm * fVelScale); // if our new position puts us inside an NPC, make a move to get rid of our current velocity c = pGameResource->EnumerateMarinesInBox(dest - (size * 0.5f), dest + (size * 0.5f)); //CASW_MarineAndObjectEnumerator avoid( radius ); //partition->EnumerateElementsInBox(PARTITION_CLIENT_SOLID_EDICTS, dest - (size * 0.5f), dest + (size * 0.5f), false, &avoid ); if (asw_debug_clientside_avoidance.GetBool()) debugoverlay->AddBoxOverlay( dest, -size * 0.5f, size * 0.5f, vec3_angle, 0, 255, 255, true, 0 ); //c = avoid.GetObjectCount(); for ( i = 0; i < c; i++ ) { //C_AI_BaseNPC *obj = dynamic_cast< C_AI_BaseNPC *>(avoid.GetObject( i )); C_ASW_Marine *obj = pGameResource->EnumeratedMarine(i); if( !obj || obj == pMarine ) continue; // don't avoid aliens laying dead on the floor if (!obj->IsAlive() || obj->GetHealth() <= 0) continue; if (asw_debug_clientside_avoidance.GetBool()) { Vector vecOtherSize = obj->WorldAlignSize(); debugoverlay->AddBoxOverlay( obj->GetAbsOrigin(), -vecOtherSize * 0.5f, vecOtherSize * 0.5f, vec3_angle, 255, 0, 0, true, 5.0f ); } // this velocity would put us inside an NPC. Construct a move to cancel the velocity //pCmd->forwardmove = 0; //pCmd->sidemove = 0; Vector moveDir = vel; VectorNormalize( moveDir ); Vector vecToObject = obj->GetAbsOrigin() - pMarine->GetAbsOrigin(); Vector vRayDir = vecToObject; VectorNormalize( vRayDir ); if (bStill) { // okay, we're still, but trying to push into a marine, start the guiding code to walk us around him instead m_bGuidingMarine = true; Vector velCopy(vel); velCopy.NormalizeInPlace(); float vel_yaw = UTIL_VecToYaw(velCopy); float object_yaw = UTIL_VecToYaw(vRayDir); float yaw_diff = UTIL_AngleDiff(vel_yaw, object_yaw); if (yaw_diff > 0) // the object is ? of our current direction, so let's push 45 degrees to the ? { //Msg("travelling at %f degrees, will go left to %f degrees\n", vel_yaw, vel_yaw + 90); m_vecGuiding.x = cos(DEG2RAD(vel_yaw + 90)); m_vecGuiding.y = sin(DEG2RAD(vel_yaw + 90)); } else { //Msg("travelling at %f degrees, will go right to %f degrees\n", vel_yaw, vel_yaw - 90); m_vecGuiding.x = cos(DEG2RAD(vel_yaw - 90)); m_vecGuiding.y = sin(DEG2RAD(vel_yaw - 90)); } return; } float fMinDot = 0.6f; // todo: make this depend on how far away we are if (moveDir.Dot(vRayDir) < fMinDot) // is our velocity taking us away from the npc? if so, it's okay { // but should check our command move isn't taking it towards it if (bStill) continue; vel = forward_vel + side_vel; moveDir = vel; VectorNormalize( moveDir ); if (moveDir.Dot(vRayDir) > fMinDot) // we're moving away from the NPC, but the player is trying to push back into it, stop him { pCmd->forwardmove = 0; pCmd->sidemove = 0; } continue; } // otherwise, assume we're trying to run into the NPC and need to stop, like now //if (!bStill) { pCmd->forwardmove = 0; pCmd->sidemove = 0; // IN_ASW_STOP removed //pCmd->buttons |= IN_ASW_STOP; return; } /*float fwd = currentdir.Dot( -moveDir ); float rt = rightdir.Dot( -moveDir ); if (bStill) { pCmd->forwardmove = 0; pCmd->sidemove = 0; } else { pCmd->forwardmove = fwd * cl_forwardspeed.GetFloat(); pCmd->sidemove = rt * cl_forwardspeed.GetFloat(); } pCmd->forwardmove = clamp( pCmd->forwardmove, -cl_forwardspeed.GetFloat(), cl_forwardspeed.GetFloat() ); pCmd->sidemove = clamp( pCmd->sidemove, -cl_sidespeed.GetFloat(), cl_sidespeed.GetFloat() ); return;*/ } if (m_bGuidingMarine) { // check if the original way is safe to revert to dest = pMarine->GetAbsOrigin() + (vecPlayerPushing * fVelScale); // if our new position puts us inside an NPC, make a move to get rid of our current velocity c = pGameResource->EnumerateMarinesInBox(dest - (size * 0.5f), dest + (size * 0.5f)); //CASW_MarineAndObjectEnumerator avoidoriginal( radius ); //partition->EnumerateElementsInBox(PARTITION_CLIENT_SOLID_EDICTS, dest - (size * 0.5f), dest + (size * 0.5f), false, &avoidoriginal ); if (asw_debug_clientside_avoidance.GetBool()) debugoverlay->AddBoxOverlay( dest, -size * 0.5f, size * 0.5f, vec3_angle, 0, 0, 255, true, 0 ); //c = avoidoriginal.GetObjectCount(); if ( c <= 0 ) { m_bGuidingMarine = false; // if we're moving freely, no need to guide anymore return; } for ( i = 0; i < c; i++ ) { //C_AI_BaseNPC *obj = dynamic_cast< C_AI_BaseNPC *>(avoidoriginal.GetObject( i )); C_ASW_Marine *obj = pGameResource->EnumeratedMarine(i); if( !obj || obj == pMarine ) continue; // don't avoid aliens laying dead on the floor if (!obj->IsAlive() || obj->GetHealth() <= 0) continue; return; } m_bGuidingMarine = false; // if we're moving freely and the original way is clear, no need to guide anymore } // if we got here, it means we didn't have to do any emergency stopping //if (!bStill) // if we're moving somewhere and we're didn't have to emergency stop, chances are we're okay //return; } void C_ASW_Player::MarinePerformClientSideObstacleAvoidance( float flFrameTime, CUserCmd *pCmd ) { C_ASW_Marine* pMarine = GetMarine(); if (! pMarine) { return; } // Don't avoid if noclipping or in movetype none switch ( pMarine->GetMoveType() ) { case MOVETYPE_NOCLIP: case MOVETYPE_NONE: case MOVETYPE_OBSERVER: return; default: break; } // if (gpGlobals->maxClients > 1) // MarineStopMoveIfBlocked(flFrameTime, pCmd, pMarine); return; // Try to steer away from any objects/players we might interpenetrate Vector size = pMarine->WorldAlignSize(); float radius = 0.7f * sqrt( size.x * size.x + size.y * size.y ); float curspeed = pMarine->GetLocalVelocity().Length2D(); // int slot = 1; // engine->Con_NPrintf( slot++, "speed %f\n", curspeed ); // engine->Con_NPrintf( slot++, "radius %f\n", radius ); // If running, use a larger radius float factor = 1.0f; if ( curspeed > 150.0f ) { factor = ( 1.0f + ( curspeed - 150.0f ) / 150.0f ); // engine->Con_NPrintf( slot++, "scaleup (%f) to radius %f\n", factor, radius * factor ); radius = radius * factor; } Vector currentdir; Vector rightdir; QAngle vAngles = pCmd->viewangles; vAngles.x = 0; if (asw_controls.GetBool()) { AngleVectors( ASW_MOVEMENT_AXIS, ¤tdir, &rightdir, NULL ); } else { AngleVectors( vAngles, ¤tdir, &rightdir, NULL ); } bool istryingtomove = false; bool ismovingforward = false; if ( fabs( pCmd->forwardmove ) > 0.0f || fabs( pCmd->sidemove ) > 0.0f ) { istryingtomove = true; if ( pCmd->forwardmove > 1.0f ) { ismovingforward = true; } } // asw - no.. //if ( istryingtomove == true ) //radius *= 1.3f; CASW_MarineAndObjectEnumerator avoid( radius ); partition->EnumerateElementsInSphere( PARTITION_CLIENT_SOLID_EDICTS, pMarine->GetAbsOrigin(), radius, false, &avoid ); // Okay, decide how to avoid if there's anything close by int c = avoid.GetObjectCount(); if ( c <= 0 ) return; //engine->Con_NPrintf( slot++, "moving %s forward %s\n", istryingtomove ? "true" : "false", ismovingforward ? "true" : "false" ); float adjustforwardmove = 0.0f; float adjustsidemove = 0.0f; int i; for ( i = 0; i < c; i++ ) { C_AI_BaseNPC *obj = dynamic_cast< C_AI_BaseNPC *>(avoid.GetObject( i )); if( !obj || obj == pMarine ) continue; // don't avoid aliens laying dead on the floor if (!obj->IsAlive() || obj->GetHealth() <= 0) continue; Vector vecToObject = obj->GetAbsOrigin() - pMarine->GetAbsOrigin(); float flDist = vecToObject.Length2D(); // Figure out a 2D radius for the object Vector vecWorldMins, vecWorldMaxs; obj->CollisionProp()->WorldSpaceAABB( &vecWorldMins, &vecWorldMaxs ); Vector objSize = vecWorldMaxs - vecWorldMins; //float objectradius = 0.5f * sqrt( objSize.x * objSize.x + objSize.y * objSize.y ); float objectradius = 1.0f * sqrt( objSize.x * objSize.x + objSize.y * objSize.y ) * asw_clientside_avoidance_scale.GetFloat(); //Don't run this code if the NPC is not moving UNLESS we are in stuck inside of them. //if ( !obj->IsMoving() && flDist > objectradius ) // continue; float flHit1, flHit2; Vector vRayDir = vecToObject; VectorNormalize( vRayDir ); if ( !IntersectInfiniteRayWithSphere( pMarine->GetAbsOrigin(), vRayDir, obj->GetAbsOrigin(), radius, &flHit1, &flHit2 ) ) continue; float force = 1.0f; float forward = 0.0f, side = 0.0f; Vector vNPCForward, vNPCRight; AngleVectors( obj->GetAbsAngles(), &vNPCForward, &vNPCRight, NULL ); Vector moveDir = -vecToObject; VectorNormalize( moveDir ); float fwd = currentdir.Dot( moveDir ); float rt = rightdir.Dot( moveDir ); float sidescale = 2.0f; float forwardscale = 1.0f; if ( flDist < objectradius ) { fwd = currentdir.Dot( -vNPCForward ); rt = rightdir.Dot( -vNPCForward ); //obj->SetEffects( EF_NODRAW ); } // If running, then do a lot more sideways veer since we're not going to do anything to // forward velocity // asw - no, looks weird when you don't get pushed when still, but do when moving away //if ( istryingtomove ) //{ //sidescale = 6.0f; //} // engine->Con_NPrintf( slot++, "sqrt(force) == %f\n", force ); // engine->Con_NPrintf( slot++, "fwd %f right %f\n", fwd, rt ); forward = forwardscale * fwd * force * AVOID_SPEED; side = sidescale * rt * force * AVOID_SPEED; // engine->Con_NPrintf( slot++, "forward %f side %f\n", forward, side ); adjustforwardmove += forward; adjustsidemove += side; } pCmd->forwardmove += adjustforwardmove; pCmd->sidemove += adjustsidemove; if ( pCmd->forwardmove > 0.0f ) { pCmd->forwardmove = clamp( pCmd->forwardmove, -cl_forwardspeed.GetFloat(), cl_forwardspeed.GetFloat() ); } else { pCmd->forwardmove = clamp( pCmd->forwardmove, -cl_backspeed.GetFloat(), cl_backspeed.GetFloat() ); } pCmd->sidemove = clamp( pCmd->sidemove, -cl_sidespeed.GetFloat(), cl_sidespeed.GetFloat() ); } void C_ASW_Player::OnMissionRestart() { GetClientModeASW()->m_bLaunchedBriefing = false; GetClientModeASW()->m_bLaunchedDebrief = false; m_fLastRestartTime = gpGlobals->curtime; // remove all decals engine->ClientCmd( "r_cleardecals\n" ); // is this needed? // recreate all client side physics props // check for physenv, because we sometimes crash on changelevel // if we get this message before fully connecting //if ( physenv ) //{ //C_PhysPropClientside::RecreateAll(); //} // todo: remove other clientside effects from the map? // reset vehicle cam yaw m_fLastVehicleYaw = 0; } void C_ASW_Player::SendBlipSpeech(int iMarine) { char buffer[64]; sprintf(buffer, "cl_blipspeech %d", iMarine); engine->ClientCmd(buffer); } void C_ASW_Player::CreateStimCamera() { m_pStimCam = new C_ASW_PointCamera; if (m_pStimCam) { if (!m_pStimCam->InitializeAsClientEntity( NULL, false )) { UTIL_Remove( m_pStimCam ); return; } m_pStimCam->ApplyStimCamSettings(); } } // smooth the Z motion of the camera #define ASW_CAMERA_Z_SPEED 60 void C_ASW_Player::SmoothCameraZ(Vector &CameraPos) { // no change if we have no marine or just starting out or just changed marine if (!GetMarine() || GetMarine()!=m_hLastMarine.Get() || m_vecLastCameraPosition == vec3_origin) { // clear any poison effects - bad place for this! g_fMarinePoisonDuration = 0; return; } float fAmountToMove = abs(CameraPos.z - m_vecLastCameraPosition.z) / 10.0f; fAmountToMove *= gpGlobals->frametime * ASW_CAMERA_Z_SPEED; if (CameraPos.z > m_vecLastCameraPosition.z) { //CameraPos.z = MIN(m_vecLastCameraPosition.z + gpGlobals->frametime * ASW_CAMERA_Z_SPEED, CameraPos.z); CameraPos.z = MIN(m_vecLastCameraPosition.z + fAmountToMove, CameraPos.z); } else if (CameraPos.z < m_vecLastCameraPosition.z) { //CameraPos.z = MAX(m_vecLastCameraPosition.z - gpGlobals->frametime * ASW_CAMERA_Z_SPEED, CameraPos.z); CameraPos.z = MAX(m_vecLastCameraPosition.z - fAmountToMove, CameraPos.z); } } // smooth the camera's overall coords when the player changes from marine to marine bool C_ASW_Player::SmoothMarineChangeCamera(Vector &CameraPos) { if (GetMarine() && GetMarine() != m_hLastMarine.Get() && m_hLastMarine.Get()) { // we changed, need to setup our smoothing vector if (m_fMarineChangeSmooth <= 0 && GetMarine()->GetAbsOrigin().DistTo(m_vecMarineChangeCameraPos) < asw_marine_switch_blend_max_dist.GetFloat()) { // check the camera can slide between the two camera positions without going inside a solid trace_t tr; UTIL_TraceLine(CameraPos, m_vecMarineChangeCameraPos, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr); if (tr.fraction >= 1.0f) m_fMarineChangeSmooth = 1.0f; } } if (m_fMarineChangeSmooth > 0) // we're in the middle of a smooth, transition between the two { Vector diff = m_vecMarineChangeCameraPos - CameraPos; float f = 1.0f - ( ( sin(m_fMarineChangeSmooth * DEG2RAD(180) + DEG2RAD(90)) * 0.5f )+ 0.5f); diff *= f; CameraPos += diff; m_fMarineChangeSmooth -= gpGlobals->frametime * asw_marine_switch_blend_speed.GetFloat(); } else // store the current camera pos incase we do a switch next frame { m_vecMarineChangeCameraPos = CameraPos; return false; } return true; } // smooth the Yaw motion of the camera when driving a vehicle #define ASW_CAMERA_YAW_SPEED 60 float C_ASW_Player::ASW_ClampYaw( float yawSpeedPerSec, float current, float target, float time ) { if (current != target) { float speed = yawSpeedPerSec * time; float move = target - current; if (target > current) { if (move >= 180) move = move - 360; } else { if (move <= -180) move = move + 360; } speed *= abs(move) / 360.0f; if (move > 0) {// turning to the npc's left if (move > speed) move = speed; } else {// turning to the npc's right if (move < -speed) move = -speed; } return anglemod(current + move); } return target; } // smoothly rotates the camera yaw to the desired value, to give the camera a nice springy feeling when driving void C_ASW_Player::SmoothCameraYaw(float &yaw) { if (!GetMarine()) return; // no change if we have no marine or just starting out or just changed marine if (GetMarine()->IsInVehicle()!=m_bLastInVehicle || m_fLastVehicleYaw == 0) { m_bLastInVehicle = GetMarine()->IsInVehicle(); m_fLastVehicleYaw = yaw; return; } float dt = MIN( 0.2, gpGlobals->frametime ); yaw = ASW_ClampYaw( 1000.0f, m_fLastVehicleYaw, yaw, dt ); m_bLastInVehicle = GetMarine()->IsInVehicle(); m_fLastVehicleYaw = yaw;//GetMarine()->EyeAngles()[YAW]; } // smooth the simulated floo rused for aiming #define ASW_FLOOR_Z_SPEED 100 void C_ASW_Player::SmoothAimingFloorZ(float &FloorZ) { if (m_fLastFloorZ == 0 || m_hLastAimingFloorZMarine.Get() != GetMarine()) { m_fLastFloorZ = FloorZ; m_hLastAimingFloorZMarine = GetMarine(); return; } float fAmountToMove = abs(FloorZ - m_fLastFloorZ) / 10.0f; fAmountToMove *= gpGlobals->frametime * ASW_FLOOR_Z_SPEED; if (FloorZ > m_fLastFloorZ) { FloorZ = MIN(m_fLastFloorZ + fAmountToMove, FloorZ); } else if (FloorZ < m_fLastFloorZ) { FloorZ = MAX(m_fLastFloorZ - fAmountToMove, FloorZ); } m_fLastFloorZ = FloorZ; } void C_ASW_Player::RequestMissionRestart() { char buffer[20]; Q_snprintf(buffer, sizeof(buffer), "cl_restart_mission"); engine->ClientCmd(buffer); } void C_ASW_Player::RequestSkillUp() { char buffer[20]; Q_snprintf(buffer, sizeof(buffer), "cl_skill_up"); engine->ClientCmd(buffer); } void C_ASW_Player::RequestSkillDown() { char buffer[20]; Q_snprintf(buffer, sizeof(buffer), "cl_skill_down"); engine->ClientCmd(buffer); } bool C_ASW_Player::ShouldAutoReload() { return asw_auto_reload.GetBool(); } C_BaseCombatWeapon *C_ASW_Player::GetActiveWeapon( void ) const { const C_ASW_Marine *pMarine = GetMarine(); if ( !pMarine ) { return BaseClass::GetActiveWeapon(); } return pMarine->GetActiveWeapon(); } C_BaseCombatWeapon *C_ASW_Player::GetWeapon( int i ) const { const C_ASW_Marine *pMarine = GetMarine(); if ( !pMarine ) { return BaseClass::GetWeapon( i ); } return pMarine->GetWeapon( i ); } int C_ASW_Player::GetHealth() const { const C_ASW_Marine *pMarine = GetMarine(); if ( !pMarine ) { return BaseClass::GetHealth(); } return pMarine->GetHealth(); } int C_ASW_Player::GetMaxHealth() const { const C_ASW_Marine *pMarine = GetMarine(); if ( !pMarine ) { return BaseClass::GetMaxHealth(); } return pMarine->GetMaxHealth(); } C_ASW_Marine* C_ASW_Player::FindMarineToHoldOrder(const Vector &pos) { C_ASW_Game_Resource *pGameResource = ASWGameResource(); if (!pGameResource) return NULL; C_ASW_Marine *pMyMarine = GetMarine(); if (!pMyMarine) return NULL; // check if we preselected a specific marine to order C_ASW_Marine *pTarget = m_hOrderingMarine.Get(); // find the nearest marine if (!pTarget) { float nearest_dist = 9999; for (int i=0;iGetMaxMarineResources();i++) { C_ASW_Marine_Resource* pMR = pGameResource->GetMarineResource(i); if (!pMR) continue; C_ASW_Marine* pMarine = pMR->GetMarineEntity(); if (!pMarine || pMarine == pMyMarine || pMarine->GetHealth() <= 0 || pMarine->GetCommander()!=this) // skip if dead continue; float distance = pos.DistTo(pMarine->GetAbsOrigin()); //if (pMarine->GetASWOrders() != ASW_ORDER_FOLLOW) // bias against marines that are already holding position somewhere //distance += 5000; if (distance < nearest_dist) { nearest_dist = distance; pTarget = pMarine; } } } return pTarget; } C_ASW_Marine* C_ASW_Player::FindMarineToFollowOrder(const Vector &pos) { C_ASW_Game_Resource *pGameResource = ASWGameResource(); if (!pGameResource) return NULL; C_ASW_Marine *pMyMarine = GetMarine(); if (!pMyMarine) return NULL; // check if we preselected a specific marine to order C_ASW_Marine *pTarget = m_hOrderingMarine.Get(); // find the nearest marine if (!pTarget) { float nearest_dist = 9999; for (int i=0;iGetMaxMarineResources();i++) { C_ASW_Marine_Resource* pMR = pGameResource->GetMarineResource(i); if (!pMR) continue; C_ASW_Marine* pMarine = pMR->GetMarineEntity(); if (!pMarine || pMarine == pMyMarine || pMarine->GetHealth() <= 0 || pMarine->GetCommander()!=this) // skip if dead continue; if (pMarine->GetASWOrders() == ASW_ORDER_FOLLOW) continue; float distance = pos.DistTo(pMarine->GetAbsOrigin()); if (distance < nearest_dist) { nearest_dist = distance; pTarget = pMarine; } } } return pTarget; } ConVar asw_local_dlight_radius("asw_local_dlight_radius", "0", FCVAR_CHEAT, "Radius of the light around the marine."); ConVar asw_local_dlight_offsetx("asw_local_dlight_offsetx", "0", FCVAR_CHEAT, "Offset of the local dlight"); ConVar asw_local_dlight_offsety("asw_local_dlight_offsety", "-15", FCVAR_CHEAT, "Offset of the local local"); ConVar asw_local_dlight_offsetz("asw_local_dlight_offsetz", "95", FCVAR_CHEAT, "Offset of the flashlight dlight"); ConVar asw_local_dlight_r("asw_local_dlight_r", "250", FCVAR_CHEAT, "Red component of local colour"); ConVar asw_local_dlight_g("asw_local_dlight_g", "250", FCVAR_CHEAT, "Green component of local colour"); ConVar asw_local_dlight_b("asw_local_dlight_b", "250", FCVAR_CHEAT, "Blue component of local colour"); ConVar asw_local_dlight_exponent("asw_local_dlight_exponent", "3", FCVAR_CHEAT, "Exponent of local colour"); ConVar asw_local_dlight_rotate("asw_local_dlight_rotate", "0", FCVAR_CHEAT, "Whether local dlight's offset is rotated by marine facing"); void C_ASW_Player::UpdateLocalMarineGlow() { C_ASW_Marine *pMarine = GetMarine(); if ( !pMarine ) { pMarine = GetSpectatingMarine(); } if ( !pMarine ) { if ( m_pLocalMarineGlow ) { m_pLocalMarineGlow->die = gpGlobals->curtime + 0.001; m_pLocalMarineGlow = NULL; } } else if ( asw_local_dlight_radius.GetFloat() > 0 ) { if ( !m_pLocalMarineGlow ) { m_pLocalMarineGlow = effects->CL_AllocDlight ( index ); } if ( m_pLocalMarineGlow ) { if ( asw_local_dlight_rotate.GetBool() ) { Vector vecForward, vecRight, vecUp; AngleVectors( pMarine->GetLocalAngles(), &vecForward, &vecRight, &vecUp ); m_pLocalMarineGlow->origin = pMarine->GetAbsOrigin() + vecForward * asw_local_dlight_offsetx.GetFloat() + vecRight * asw_local_dlight_offsety.GetFloat() + vecUp * asw_local_dlight_offsetz.GetFloat(); } else { m_pLocalMarineGlow->origin = pMarine->GetAbsOrigin(); m_pLocalMarineGlow->origin.x += asw_local_dlight_offsetx.GetFloat(); m_pLocalMarineGlow->origin.y += asw_local_dlight_offsety.GetFloat(); m_pLocalMarineGlow->origin.z += asw_local_dlight_offsetz.GetFloat(); } m_pLocalMarineGlow->color.r = asw_local_dlight_r.GetInt(); m_pLocalMarineGlow->color.g = asw_local_dlight_g.GetInt(); m_pLocalMarineGlow->color.b = asw_local_dlight_b.GetInt(); m_pLocalMarineGlow->radius = asw_local_dlight_radius.GetFloat(); m_pLocalMarineGlow->color.exponent = asw_local_dlight_exponent.GetInt(); m_pLocalMarineGlow->die = gpGlobals->curtime + 30.0f; } } } #ifdef PLATFORM_WINDOWS_PC // Instead of including windows.h extern "C" { extern int __stdcall CopyFileA( char *pszSource, char *pszDest, int bFailIfExists ); }; namespace { // hacky function from mp3player to copy the custom sound file into the game folder so the filesystem can access it void GetLocalCopyOfStimMusic( const char *filename, char *outsong, size_t outlen ) { char fn[ 512 ]; Q_snprintf( fn, sizeof( fn ), "%s", filename ); outsong[ 0 ] = 0; // Get temp filename from crc CRC32_t crc; CRC32_Init( &crc ); CRC32_ProcessBuffer( &crc, fn, Q_strlen( fn ) ); CRC32_Final( &crc ); char hexname[ 16 ]; Q_binarytohex( (const byte *)&crc, sizeof( crc ), hexname, sizeof( hexname ) ); char hexfilename[ 512 ]; Q_snprintf( hexfilename, sizeof( hexfilename ), "sound/_mp3/%s.mp3", hexname ); Q_FixSlashes( hexfilename ); if ( g_pFullFileSystem->FileExists( hexfilename, "MOD" ) ) { Q_snprintf( outsong, outlen, "_mp3/%s.mp3", hexname ); } else { // Make a local copy char mp3_temp_path[ 512 ]; Q_snprintf( mp3_temp_path, sizeof( mp3_temp_path ), "sound/_mp3" ); g_pFullFileSystem->CreateDirHierarchy( mp3_temp_path, "MOD" ); char destpath[ 512 ]; Q_snprintf( destpath, sizeof( destpath ), "%s/%s", engine->GetGameDirectory(), hexfilename ); Q_FixSlashes( destpath ); // !!!HACK HACK: // Total hack right now, using windows OS calls to copy file to full destination int success = ::CopyFileA( fn, destpath, TRUE ); if ( success > 0 ) { Q_snprintf( outsong, outlen, "_mp3/%s.mp3", hexname ); } } Q_FixSlashes( outsong ); } } #else static void GetLocalCopyOfStimMusic( const char *filename, char *outsong, size_t outlen ) {}; #pragma message("TODO: GetLocalCopyOfStimMusic is a hack that must go away!") #endif void C_ASW_Player::StartStimMusic() { if (ASWGameRules() && !ASWGameRules()->ShouldPlayStimMusic()) return; CLocalPlayerFilter filter; if (!m_pStimMusic) { // Check if custom combat music is playing if( g_ASWJukebox.IsMusicPlaying() ) return; if ( Q_strlen( asw_stim_music.GetString() ) > 0 ) { char soundname[ 512 ]; soundname[0] = '#'; soundname[1] = 0; GetLocalCopyOfStimMusic( asw_stim_music.GetString(), &soundname[1], sizeof( soundname ) - 1 ); if ( soundname[ 1 ] ) { m_pStimMusic = CSoundEnvelopeController::GetController().SoundCreate( filter, 0, CHAN_STATIC, soundname, SNDLVL_NONE ); } } if ( !m_pStimMusic ) { m_pStimMusic = CSoundEnvelopeController::GetController().SoundCreate( filter, 0, "asw_song.stims" ); } if (m_pStimMusic) { CSoundEnvelopeController::GetController().Play( m_pStimMusic, 1.0, 100 ); } } else { // already playing the stim music, make sure it's at full volume CSoundEnvelopeController::GetController().SoundChangeVolume( m_pStimMusic, 1.0, 0.3f ); } m_bStartedStimMusic = true; } void C_ASW_Player::StopStimMusic(bool bInstantly) { if (m_pStimMusic) { if (bInstantly) { CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); controller.SoundDestroy( m_pStimMusic ); m_pStimMusic = NULL; } else { CSoundEnvelopeController::GetController().SoundChangeVolume( m_pStimMusic, 0.0, 1.0f ); } } m_bStartedStimMusic = false; } void C_ASW_Player::ClearStimMusic() { if ( m_pStimMusic ) { CSoundEnvelopeController::GetController().CommandAdd( m_pStimMusic, 1.0f, SOUNDCTRL_DESTROY, 0.0f, 0.0f ); m_pStimMusic = NULL; } } void C_ASW_Player::UpdateOnRemove() { BaseClass::UpdateOnRemove(); StopStimMusic(); ClearStimMusic(); if (m_bPlayingSingleBreathSound) { StopStimSound(); } } fogparams_t* C_ASW_Player::GetFogParams( void ) { static fogparams_t RemoteTurretFog; if (GetMarine() && GetMarine()->IsControllingTurret()) { RemoteTurretFog.enable = true; RemoteTurretFog.colorPrimary.SetR(0); RemoteTurretFog.colorPrimary.SetG(0); RemoteTurretFog.colorPrimary.SetB(0); RemoteTurretFog.colorPrimary.SetA(255); RemoteTurretFog.colorSecondary = RemoteTurretFog.colorPrimary; RemoteTurretFog.start = asw_turret_fog_start.GetFloat(); RemoteTurretFog.end = asw_turret_fog_end.GetFloat(); RemoteTurretFog.farz = asw_turret_fog_end.GetFloat(); return &RemoteTurretFog; } return &m_CurrentFog; } // used by the intro to launch the campaign map when the intro finishes void __MsgFunc_LaunchCampaignMap( bf_read &msg ) { char mapName[255]; Q_FileBase( engine->GetLevelName(), mapName, sizeof(mapName) ); // check if this is the intro map, if so then launch the campaign page if ( !Q_strnicmp( mapName, "intro", 5 ) ) { C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); if (pPlayer) { pPlayer->LaunchCampaignFrame(); } } } USER_MESSAGE_REGISTER( LaunchCampaignMap ); void C_ASW_Player::LaunchCredits( vgui::Panel *pParent /*= NULL*/ ) { if ( !pParent ) { pParent = GetClientMode()->GetViewport(); } CreditsPanel *pPanel = new CreditsPanel( pParent, "Credits" ); vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew"); pPanel->SetScheme(scheme); pPanel->SetZPos( 200 ); //pPanel->MakePopup(); //pPanel->MoveToFront(); } void C_ASW_Player::LaunchCainMail() { CainMailPanel *pPanel = new CainMailPanel( GetClientMode()->GetViewport(), "Credits" ); vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew"); pPanel->SetScheme(scheme); vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( scheme ); pPanel->StartFadeIn(pScheme); } void __MsgFunc_LaunchCredits( bf_read &msg ) { Msg("__MsgFunc_LaunchCredits\n"); C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); if (pPlayer) { Msg(" so launching credits\n"); pPlayer->LaunchCredits(); } } USER_MESSAGE_REGISTER( LaunchCredits ); void __MsgFunc_LaunchCainMail( bf_read &msg ) { C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); if (pPlayer) { pPlayer->LaunchCainMail(); } } USER_MESSAGE_REGISTER( LaunchCainMail ); bool C_ASW_Player::ShouldRegenerateOriginFromCellBits() const { return true; } bool C_ASW_Player::IsSniperScopeActive() { C_ASW_Marine *pMarine = GetMarine(); if ( !pMarine ) return false; C_BaseCombatWeapon* pWeapon = pMarine->GetActiveWeapon(); if ( pWeapon && pWeapon->Classify() == CLASS_ASW_SNIPER_RIFLE ) { C_ASW_Weapon_Sniper_Rifle *pSniper = assert_cast( pWeapon ); return pSniper->IsZoomed(); } return false; } CSteamID C_ASW_Player::GetSteamID() { int iIndex = entindex(); player_info_t pi; if ( engine->GetPlayerInfo(iIndex, &pi) ) { if ( pi.friendsID ) { CSteamID steamIDForPlayer( pi.friendsID, 1, steamapicontext->SteamUtils()->GetConnectedUniverse(), k_EAccountTypeIndividual ); return steamIDForPlayer; } } CSteamID invalid; return invalid; }