//---------------------------------------------------------- // // MODULE : BloodClientShell.cpp // // PURPOSE : Blood 2 Client shell // // CREATED : 9/21/97 // //---------------------------------------------------------- // includes... #include #include #include "BloodClientShell.h" #include "ViewWeapon.h" #include "Commands.h" #include "VKDefs.h" #include "ClientRes.h" #include "SfxMsgIds.h" #include "ClientUtilities.h" #include "LoadSave.h" #include "VolumeBrushFX.h" #include "CameraFX.h" #include "client_physics.h" #include "NetStart.h" #include "TheVoice.h" #include "WinUtil.h" #include "ClientRes.h" #include "LoadScreenData.h" #include "Splash.h" #include "MoveMgr.h" #include "WeaponDefs.h" #include "GameWeapons.h" #include "SoundTypes.h" #include "physics_lt.h" PhysicsState g_normalPhysicsState; PhysicsState g_waterPhysicsState; //#define FLAG_BASECHARACTER 1 // defines... #define BOBV_WALKING 24.0f #define BOBH_WALKING 16.0f #define SWAYV_WALKING 32.0f #define SWAYH_WALKING 80.0f #define BOBV_CRAWLING 24.0f #define BOBH_CRAWLING 16.0f #define SWAYV_CRAWLING 16.0f #define SWAYH_CRAWLING 40.0f #define FOV_NORMAL 90.0f #define FOV_SEEING_EYE 120.0f #define FOV_ZOOMED 12.5f #define MOVIE_STARTLITH 1 #define MOVIE_PLAYINGLITH 2 #define MOVIE_STARTGTI 3 #define MOVIE_PLAYINGGTI 4 #define MOVIE_STARTINTRO 5 #define MOVIE_PLAYINGINTRO 6 #define MOVIE_FINISHED 7 #define min(a,b) (a < b ? a : b) #define max(a,b) (a > b ? a : b) #define SOUND_REVERB_UPDATE_PERIOD 0.33f #define PLAYER_MULTI_UPDATE_TIMER 0.14f #define MSG_SOUND_STRING "sounds\\events\\woodclank2a.wav" // Guids... #ifdef _ADDON DGUID BLOOD2GUID = { /* Add-On */ 0xc13e628, 0x418c, 0x11d2, 0x86, 0xa, 0x0, 0x60, 0x97, 0x18, 0xa9, 0x42 }; #else DGUID BLOOD2GUID = { /* 0C13E629-419C-11D2-860A-00609719A842 */ 0xc13e629, 0x419c, 0x11d2, 0x86, 0xa, 0x0, 0x60, 0x97, 0x19, 0xa8, 0x42 }; #endif // Misc... char msgbuf[513]; DBOOL g_bAborting = DFALSE; DBOOL g_bIsHost = DFALSE; DBOOL g_bLevelChange3rdPersonCam = DFALSE; DBOOL g_bLevelChangeNoUpdate = DFALSE; DBOOL g_bPlayerInvReset = DFALSE; DFLOAT g_fPlayerUpdateTimer = 0.0f; #ifdef _ADDON static char *s_szCheerSounds[] = { "sounds_ao\\events\\cheer1.wav", "sounds_ao\\events\\cheer2.wav" }; #define NUMCHEERSOUNDS ( sizeof( s_szCheerSounds ) / sizeof( s_szCheerSounds[0] )) static char *s_szBooSounds[] = { "sounds_ao\\events\\boo1.wav", "sounds_ao\\events\\boo2.wav", "sounds_ao\\events\\boo3.wav" }; #define NUMBOOSOUNDS ( sizeof( s_szBooSounds ) / sizeof( s_szBooSounds[0] )) #endif // _ADDON // Global pointer to the client shell.. CBloodClientShell *g_pBloodClientShell = DNULL; // Prototypes.. DBOOL ConnectToTcpIpAddress(CClientDE* pClientDE, char* sAddress); // Setup.. SETUP_CLIENTSHELL(); ClientShellDE* CreateClientShell(ClientDE *pClientDE) { g_pClientDE = pClientDE; return (ClientShellDE*)(new CBloodClientShell); } void DeleteClientShell(ClientShellDE *pInputShell) { if (pInputShell) { delete ((CBloodClientShell*)pInputShell); } } void CShell_GetConsoleString(char* sKey, char* sDest, char* sDefault) { if (g_pClientDE) { HCONSOLEVAR hVar = g_pClientDE->GetConsoleVar(sKey); if (hVar) { char* sValue = g_pClientDE->GetVarValueString(hVar); if (sValue) { strcpy(sDest, sValue); return; } } } strcpy(sDest, sDefault); } static DBOOL LoadLeakFile(ClientDE *pClientDE, char *pFilename); void LeakFileFn(int argc, char **argv) { if (argc < 0) { g_pBloodClientShell->GetClientDE()->CPrint("LeakFile "); return; } if (LoadLeakFile(g_pBloodClientShell->GetClientDE(), argv[0])) { g_pBloodClientShell->GetClientDE()->CPrint("Leak file %s loaded successfully!", argv[0]); } else { g_pBloodClientShell->GetClientDE()->CPrint("Unable to load leak file %s", argv[0]); } } void ConnectFn(int argc, char **argv) { if (argc <= 0) { g_pBloodClientShell->GetClientDE()->CPrint("Connect (use '*' for local net)"); return; } ConnectToTcpIpAddress(g_pBloodClientShell->GetClientDE(), argv[0]); } void NextLevelFn(int argc, char **argv) { if (g_bIsHost) { ClientDE *pClientDE; HMESSAGEWRITE hWrite; pClientDE = g_pBloodClientShell->GetClientDE(); hWrite = pClientDE->StartMessage(CMSG_NEXTLEVEL); pClientDE->EndMessage(hWrite); } else { g_pBloodClientShell->GetClientDE()->CPrint("Only the host can change levels"); } } void LoadLevelFn(int argc, char **argv) { if (argc >= 1 && argv[0]) { g_pBloodClientShell->StartNewGame(argv[0]); } else { g_pBloodClientShell->GetClientDE()->CPrint("Usage: load "); } } void CBloodClientShell::StartNewGame(char *pszWorld) { if (!pszWorld) return; if (m_bInWorld) { StartNewWorld(pszWorld, m_nGameType, LOADTYPE_NEW_LEVEL); } else { StartNewGame(pszWorld, STARTGAME_NORMAL, GAMETYPE_CUSTOM, LOADTYPE_NEW_GAME, DIFFICULTY_MEDIUM); m_bFirstWorld = DTRUE; } } void FragSelfFn(int argc, char **argv) { ClientDE *pClientDE; HMESSAGEWRITE hWrite; pClientDE = g_pBloodClientShell->GetClientDE(); hWrite = pClientDE->StartMessage(CMSG_FRAGSELF); pClientDE->EndMessage(hWrite); } void InitSoundFn(int argc, char **argv) { if( g_pBloodClientShell ) g_pBloodClientShell->InitSound( ); } /* // --------------------------------------------------------------------------- // // // ROUTINE: AuraModelHook // // PURPOSE: Special Rendering Code for Aura spell // // --------------------------------------------------------------------------- // void AuraModelHook (struct ModelHookData_t *pData, void *pUser) { CClientDE* pClientDE = (CClientDE*) pUser; if (!pClientDE ) return; DDWORD nUserFlags = 0; pClientDE->GetObjectUserFlags (pData->m_hObject, &nUserFlags); if (nUserFlags & FLAG_BASECHARACTER) { pData->m_Flags &= ~MHF_USETEXTURE; if (pData->m_LightAdd) { VEC_SET (*pData->m_LightAdd, 255.0f, 255.0f, 255.0f); } } } */ // --------------------------------------------------------------------------- // // // ROUTINE: DefaultModelHook // // PURPOSE: Default model hook function // // --------------------------------------------------------------------------- // void DefaultModelHook (struct ModelHookData_t *pData, void *pUser) { DDWORD nUserFlags; DFLOAT fGlowValue, fGlowFactor; g_pClientDE->GetObjectUserFlags( pData->m_hObject, &nUserFlags ); if( g_pBloodClientShell->NightGogglesActive( ) && nUserFlags & USERFLG_NIGHTGOGGLESGLOW ) { pData->m_Flags &= ~MHF_USETEXTURE; if (pData->m_LightAdd) { VEC_SET (*pData->m_LightAdd, 0.0f, 255.0f, 0.0f); } } else if( nUserFlags & USRFLG_GLOW ) { if( pData->m_LightAdd ) { // Cycle the glow with a period of 2 seconds... fGlowFactor = ( DFLOAT )sin( g_pClientDE->GetTime( ) * MATH_CIRCLE / 2.0f ); fGlowValue = 128.0f + 128.0f * fGlowFactor; fGlowValue = DCLAMP( fGlowValue, 0.0f, 255.0f ); VEC_SET( *pData->m_LightAdd, fGlowValue, fGlowValue, fGlowValue ); } } // Glow red for anger else if (nUserFlags & USRFLG_ANGERGLOW) { if( pData->m_LightAdd ) { // Cycle the glow with a period of 0.5 seconds... fGlowFactor = ( DFLOAT )sin( g_pClientDE->GetTime( ) * MATH_CIRCLE * 6.0f ); fGlowValue = 192.0f + 64.0f * fGlowFactor; fGlowValue = DCLAMP( fGlowValue, 0.0f, 255.0f ); VEC_SET( *pData->m_LightAdd, fGlowValue, 255.0 - fGlowValue, 255.0 - fGlowValue ); } } // Glow green for willpower else if (nUserFlags & USRFLG_WILLPOWERGLOW) { if( pData->m_LightAdd ) { // Cycle the glow with a period of 0.5 seconds... fGlowFactor = ( DFLOAT )sin( g_pClientDE->GetTime( ) * MATH_CIRCLE * 6.0f ); fGlowValue = 192.0f + 64.0f * fGlowFactor; fGlowValue = DCLAMP( fGlowValue, 0.0f, 255.0f ); VEC_SET( *pData->m_LightAdd, 255.0 - fGlowValue, fGlowValue, 255.0 - fGlowValue ); } } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::CBloodClientShell() // // PURPOSE: constructor // // ----------------------------------------------------------------------- // CBloodClientShell::CBloodClientShell() { m_pMoveMgr = DNULL; m_hCamera = NULL; m_fPitch = m_fYaw = cdata.fPitch = cdata.fYaw = 0.0f; for (int i=0;iFreeString( m_hCurrentItemName ); if( m_hCurrentItemIcon ) pClientDE->FreeString( m_hCurrentItemIcon ); if( m_hCurrentItemIconH ) pClientDE->FreeString( m_hCurrentItemIconH ); if( m_hPrevItemIcon ) pClientDE->FreeString( m_hPrevItemIcon ); if( m_hNextItemIcon ) pClientDE->FreeString( m_hNextItemIcon ); if( m_hNightGogglesSound ) { g_pClientDE->KillSound( m_hNightGogglesSound ); } if( m_hTheEyeLoopingSound ) { g_pClientDE->KillSound( m_hTheEyeLoopingSound ); } if( m_hContainerSound) { g_pClientDE->KillSound( m_hContainerSound ); } if( m_hstrTitle ) g_pClientDE->FreeString( m_hstrTitle ); if( m_hstrLoadScreen ) g_pClientDE->FreeString( m_hstrLoadScreen ); if( m_hstrObjectivesText ) g_pClientDE->FreeString( m_hstrObjectivesText ); if( m_hstrObjectivesTitle ) g_pClientDE->FreeString( m_hstrObjectivesTitle ); if (m_hCtfCapturedString1) g_pClientDE->FreeString(m_hCtfCapturedString1); if (m_hCtfCapturedString2) g_pClientDE->FreeString(m_hCtfCapturedString2); #ifdef _ADDON if (m_hSoccerGoalString1) g_pClientDE->FreeString(m_hSoccerGoalString1); if (m_hSoccerGoalString2) g_pClientDE->FreeString(m_hSoccerGoalString2); #endif // _ADDON } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::InitSound // // PURPOSE: Initialize the sounds // // ----------------------------------------------------------------------- // DRESULT CBloodClientShell::InitSound() { Sound3DProvider *pSound3DProviderList, *pSound3DProvider; InitSoundInfo soundInfo; ReverbProperties reverbProperties; HCONSOLEVAR hVar; DDWORD dwProviderID; char sz3dSoundProviderName[_MAX_PATH + 1]; DRESULT res; CClientDE* pClientDE = GetClientDE(); if( !pClientDE ) return LT_ERROR; INITSOUNDINFO_INIT(soundInfo); // Reload the sounds if there are any soundInfo.m_dwFlags = INITSOUNDINFOFLAG_RELOADSOUNDS; // Get the 3d sound provider id. hVar = pClientDE->GetConsoleVar( "3DSoundProvider" ); if( hVar ) { dwProviderID = ( DDWORD )pClientDE->GetVarValueFloat( hVar ); } else dwProviderID = SOUND3DPROVIDERID_NONE; // Can also be set by provider name, in which case the id will be set to UNKNOWN. if( dwProviderID == SOUND3DPROVIDERID_NONE || dwProviderID == SOUND3DPROVIDERID_UNKNOWN ) { sz3dSoundProviderName[0] = 0; hVar = pClientDE->GetConsoleVar( "3DSoundProviderName" ); if( hVar ) { SAFE_STRCPY( sz3dSoundProviderName, pClientDE->GetVarValueString( hVar )); dwProviderID = SOUND3DPROVIDERID_UNKNOWN; } } // See if the provider exists. if( dwProviderID != SOUND3DPROVIDERID_NONE ) { pClientDE->GetSound3DProviderLists( pSound3DProviderList, DFALSE ); if( !pSound3DProviderList ) return LT_NO3DSOUNDPROVIDER; pSound3DProvider = pSound3DProviderList; while( pSound3DProvider ) { // If the provider is selected by name, then compare the names. if( dwProviderID == SOUND3DPROVIDERID_UNKNOWN ) { if( _mbscmp(( const unsigned char * )sz3dSoundProviderName, ( const unsigned char * )pSound3DProvider->m_szProvider ) == 0 ) break; } // Or compare by the id's. else if( pSound3DProvider->m_dwProviderID == dwProviderID ) break; // Not this one, try next one. pSound3DProvider = pSound3DProvider->m_pNextProvider; } // Check if we found one. if( pSound3DProvider ) { // Use this provider. SAFE_STRCPY( soundInfo.m_sz3DProvider, pSound3DProvider->m_szProvider ); // Get the maximum number of 3d voices to use. hVar = pClientDE->GetConsoleVar( "Max3DVoices" ); if( hVar ) { soundInfo.m_nNum3DVoices = ( DBYTE )g_pClientDE->GetVarValueFloat( hVar ); } else soundInfo.m_nNum3DVoices = 16; } pClientDE->ReleaseSound3DProviderList( pSound3DProviderList ); } // Get the maximum number of sw voices to use. hVar = pClientDE->GetConsoleVar( "MaxSWVoices" ); if( hVar ) { soundInfo.m_nNumSWVoices = ( DBYTE )g_pClientDE->GetVarValueFloat( hVar ); } else soundInfo.m_nNumSWVoices = 32; soundInfo.m_nSampleRate = 22050; soundInfo.m_nBitsPerSample = 16; if ((hVar = pClientDE->GetConsoleVar("soundvolume"))) { soundInfo.m_nVolume = (unsigned short)(pClientDE->GetVarValueFloat(hVar)); } DBOOL b8bitOnly = DFALSE; hVar = pClientDE->GetConsoleVar("sound16bit"); if (hVar) { b8bitOnly = (pClientDE->GetVarValueFloat(hVar) == 0.0f) ? DTRUE : DFALSE; } if( b8bitOnly ) soundInfo.m_dwFlags |= INITSOUNDINFOFLAG_CONVERT16TO8; DFLOAT fMinStreamSoundTime = 0.5f; hVar = pClientDE->GetConsoleVar ("MinStreamTime"); if (hVar) { fMinStreamSoundTime = pClientDE->GetVarValueFloat (hVar); fMinStreamSoundTime = (fMinStreamSoundTime < 0.2f ? 0.2f : (fMinStreamSoundTime > 1.5f ? 1.5f : fMinStreamSoundTime)); } soundInfo.m_fMinStreamTime = fMinStreamSoundTime; soundInfo.m_fDistanceFactor = 1.0f / 64.0f; // Go initialize the sounds. m_bUseReverb = DFALSE; if(( res = pClientDE->InitSound(&soundInfo)) == LT_OK ) { if( soundInfo.m_dwResults & INITSOUNDINFORESULTS_REVERB ) { m_bUseReverb = DTRUE; } hVar = pClientDE->GetConsoleVar( "ReverbLevel" ); if( hVar ) { m_fReverbLevel = g_pClientDE->GetVarValueFloat( hVar ); } else m_fReverbLevel = 1.0f; reverbProperties.m_dwParams = REVERBPARAM_VOLUME; reverbProperties.m_fVolume = m_fReverbLevel; pClientDE->SetReverbProperties( &reverbProperties ); } return res; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::CSPrint // // PURPOSE: Displays a line of text on the client // // ----------------------------------------------------------------------- // void CBloodClientShell::CSPrint (char* msg, ...) { CClientDE* pClientDE = GetClientDE(); // parse the message char pMsg[256]; va_list marker; va_start (marker, msg); int nSuccess = vsprintf (pMsg, msg, marker); va_end (marker); if (nSuccess < 0) return; // now display the message m_MessageMgr.AddLine(pMsg); pClientDE->CPrint(pMsg); } void CBloodClientShell::CSPrint(int nStringID) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; HSTRING hString = pClientDE->FormatString(nStringID); if (!hString) return; CSPrint(pClientDE->GetStringData(hString)); pClientDE->FreeString(hString); } void CBloodClientShell::CSPrint2(char* msg) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; m_MessageMgr.AddLine(msg); pClientDE->CPrint(msg); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnEvent() // // PURPOSE: Engine event handler // // --------------------------------------------------------------------------- // void CBloodClientShell::OnEvent(DDWORD dwEventID, DDWORD dwParam) { // Handle any events we want to deal with... switch (dwEventID) { case LTEVENT_DISCONNECT: { if (!g_bIsHost) { CSPrint(IDS_SERVERDISCONNECT); PlaySound(MSG_SOUND_STRING); } break; } } // Let the base class handle the even too... CClientShellDE::OnEvent(dwEventID, dwParam); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnEngineInitialized() // // PURPOSE: Called upon engine initialization. // // --------------------------------------------------------------------------- // DRESULT CBloodClientShell::OnEngineInitialized(RMode *pMode, DGUID *pAppGuid) { // Local variables... HCONSOLEVAR hVar; CClientDE* pClientDE = GetClientDE(); DBOOL bPlayingMovies = DFALSE; DRESULT resInitSound; HSTRING hstrError; char *pszError; // Set the guid... *pAppGuid = BLOOD2GUID; // Init Move mgr... m_pMoveMgr = new CMoveMgr(this); if(!m_pMoveMgr) return LT_ERROR; m_pMoveMgr->Init(pClientDE); // Initialize The Voice data... TheVoice_Init(pClientDE); // Initialize the physics states... g_normalPhysicsState.m_pClientDE = pClientDE; VEC_SET(g_normalPhysicsState.m_GravityAccel, 0.0f, -1000.0f, 0.0f); g_normalPhysicsState.m_VelocityDampen = 0.35f; g_waterPhysicsState.m_pClientDE = pClientDE; VEC_SET(g_waterPhysicsState.m_GravityAccel, 0.0f, -500.0f, 0.0f); g_waterPhysicsState.m_VelocityDampen = 0.20f; // Initialize sound... resInitSound = InitSound(); // Add to NumRuns count... float nNumRuns = 0.0f; hVar = pClientDE->GetConsoleVar ("NumRuns"); if (hVar) { nNumRuns = pClientDE->GetVarValueFloat (hVar); } nNumRuns++; char strConsole[64]; sprintf (strConsole, "+NumRuns %f", nNumRuns); pClientDE->RunConsoleString (strConsole); // Format some strings... m_hCtfCapturedString1 = pClientDE->FormatString(IDS_CTF_CAPTURED_1); m_hCtfCapturedString2 = pClientDE->FormatString(IDS_CTF_CAPTURED_2); #ifdef _ADDON m_hSoccerGoalString1 = pClientDE->FormatString(IDS_SOCCER_GOAL_1); m_hSoccerGoalString2 = pClientDE->FormatString(IDS_SOCCER_GOAL_2); #endif // _ADDON // check advanced options... hVar = pClientDE->GetConsoleVar ("DisableMusic"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableMusic = DTRUE; hVar = pClientDE->GetConsoleVar ("DisableSound"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableSound = DTRUE; hVar = pClientDE->GetConsoleVar ("DisableMovies"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableMovies = DTRUE; hVar = pClientDE->GetConsoleVar ("DisableJoystick"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableJoystick = DTRUE; hVar = pClientDE->GetConsoleVar ("EnableOptSurf"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedEnableOptSurf = DTRUE; hVar = pClientDE->GetConsoleVar ("DisableLightMap"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableLightMap = DTRUE; hVar = pClientDE->GetConsoleVar ("EnableTripBuf"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedEnableTripBuf = DTRUE; hVar = pClientDE->GetConsoleVar ("DisableDx6Cmds"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableDx6Cmds = DTRUE; hVar = pClientDE->GetConsoleVar ("EnableTJuncs"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedEnableTJuncs = DTRUE; hVar = pClientDE->GetConsoleVar ("DisableFog"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableFog = DTRUE; hVar = pClientDE->GetConsoleVar ("DisableLines"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableLines = DTRUE; hVar = pClientDE->GetConsoleVar ("DisableModelFB"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedDisableModelFB = DTRUE; hVar = pClientDE->GetConsoleVar ("EnablePixDub"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedEnablePixelDoubling = DTRUE; hVar = pClientDE->GetConsoleVar ("EnableMultiTex"); if (hVar && pClientDE->GetVarValueFloat (hVar)) m_bAdvancedEnableMultiTexturing = DTRUE; // Set the detail console variables MenuSetDetail(); // Set the player cursor display hVar = pClientDE->GetConsoleVar ("Crosshair"); if(hVar && pClientDE->GetVarValueFloat(hVar)) { m_bShowCrosshair = DTRUE; m_bCrosshairOriginallyOn = DTRUE; } else { m_bShowCrosshair = DFALSE; m_bCrosshairOriginallyOn = DFALSE; } hVar = pClientDE->GetConsoleVar ("CrosshairNum"); m_nCrosshair = (DBYTE)pClientDE->GetVarValueFloat(hVar); if(m_nCrosshair > 41) m_nCrosshair = 0; m_nCrosshairOriginalNum = m_nCrosshair; // Set the player movement variables (mouselook) hVar = pClientDE->GetConsoleVar ("MouseLook"); if(hVar && pClientDE->GetVarValueFloat(hVar)) { m_bMouseLook = DTRUE; // cdata.byFlags |= CDATA_MOUSEAIMING; } else { m_bMouseLook = DFALSE; // cdata.byFlags &= ~CDATA_MOUSEAIMING; } // Set the player movement variables (lookspring) hVar = pClientDE->GetConsoleVar ("LookSpring"); if(hVar && pClientDE->GetVarValueFloat(hVar)) { m_bLookSpring = DTRUE; } else { m_bLookSpring = DFALSE; } // Set the player movement variables (runlock) hVar = pClientDE->GetConsoleVar ("RunLock"); if(hVar && pClientDE->GetVarValueFloat(hVar)) cdata.byFlags |= CDATA_RUNLOCK; else cdata.byFlags &= ~CDATA_RUNLOCK; // Turn on client side prediction pClientDE->RunConsoleString("Prediction 1"); // Determine if we were lobby launched... DBOOL bNetworkGameStarted = DFALSE; DBOOL bLobbyLaunched = DFALSE; #ifndef _DEMO DRESULT dr = pClientDE->IsLobbyLaunched("dplay2"); if (dr == LT_OK) { DBOOL bRet = NetStart_DoLobbyLaunchWizard(pClientDE); if (bRet) { bLobbyLaunched = DTRUE; bNetworkGameStarted = DTRUE; } else { pClientDE->Shutdown(); return LT_ERROR; } } #endif // Check for console vars that say we should do networking setup stuff... DBOOL bDoNetStuff = DFALSE; hVar = pClientDE->GetConsoleVar("Multiplayer"); if (hVar) { if ((DBOOL)pClientDE->GetVarValueFloat(hVar)) bDoNetStuff = DTRUE; } hVar = pClientDE->GetConsoleVar("ConnectPlr"); if (hVar) { char* sVar = pClientDE->GetVarValueString(hVar); if (sVar && sVar[0] != '\0' && _mbscmp((const unsigned char*)sVar, (const unsigned char*)"0") != 0) bDoNetStuff = DTRUE; } hVar = pClientDE->GetConsoleVar("Connect"); if (hVar) { char* sVar = pClientDE->GetVarValueString(hVar); if (sVar && sVar[0] != '\0' && _mbscmp((const unsigned char*)sVar, (const unsigned char*)"0") != 0) bDoNetStuff = DTRUE; } if (bLobbyLaunched) bDoNetStuff = DFALSE; #ifdef _DEMO bDoNetStuff = DFALSE; #endif // Determine if we should display the networking dialogs... if (bDoNetStuff) { bNetworkGameStarted = NetStart_DoWizard (pClientDE); if (!bNetworkGameStarted) { pClientDE->Shutdown(); return LT_ERROR; } } // Pass RMode on to SetRenderMode... DRESULT hResult = pClientDE->SetRenderMode(pMode); if (hResult != LT_OK) { // If an error occurred, try 640x480x16... RMode rMode; rMode.m_Width = 640; rMode.m_Height = 480; rMode.m_BitDepth = 16; rMode.m_bHardware = pMode->m_bHardware; sprintf(rMode.m_RenderDLL, "%s", pMode->m_RenderDLL); sprintf(rMode.m_InternalName, "%s", pMode->m_InternalName); sprintf(rMode.m_Description, "%s", pMode->m_Description); if (pClientDE->SetRenderMode(&rMode) != LT_OK) { // Okay, that didn't work, looks like we're stuck with software... rMode.m_bHardware = DFALSE; sprintf(rMode.m_RenderDLL, "soft.ren"); sprintf(rMode.m_InternalName, ""); sprintf(rMode.m_Description, ""); if (pClientDE->SetRenderMode(&rMode) != LT_OK) { Abort(IDS_ERR_SETVIDMODE, 6929314); return LT_ERROR; } } } // Draw the loading screen if we are hosting a network game already... if (bNetworkGameStarted && g_bIsHost) { DrawLoadingScreen(); pClientDE->FlipScreen(FLIPSCREEN_CANDRAWCONSOLE); DrawLoadingScreen(); } // Register console commands pClientDE->RegisterConsoleProgram("LeakFile", LeakFileFn); pClientDE->RegisterConsoleProgram("Connect", ConnectFn); pClientDE->RegisterConsoleProgram("FragSelf", FragSelfFn); pClientDE->RegisterConsoleProgram("InitSound", InitSoundFn); pClientDE->RegisterConsoleProgram("NextLevel", NextLevelFn); pClientDE->RegisterConsoleProgram("Load", LoadLevelFn); // Try to initialize the level manager (including // if (!m_LevelMgr.Init(pClientDE)) // { // PrintError("Could not init LevelMgr"); // return LT_ERROR; // } // Setup the music stuff... if( !m_Music.IsInitialized( )) { HCONSOLEVAR hConsoleVar; hConsoleVar = pClientDE->GetConsoleVar( "musictype" ); // Default to ima if music never set before... if( !hConsoleVar ) m_Music.Init( pClientDE, DTRUE ); else { // See if they want cdaudio or ima... if(_mbsicmp((const unsigned char*)pClientDE->GetVarValueString( hConsoleVar ), (const unsigned char*)"cdaudio" ) == 0 ) m_Music.Init( pClientDE, DFALSE ); else m_Music.Init( pClientDE, DTRUE ); } } // Set the sound volume hVar = pClientDE->GetConsoleVar("SoundVolume"); if (hVar) { pClientDE->SetSoundVolume((int)pClientDE->GetVarValueFloat(hVar)); } else { pClientDE->SetSoundVolume(35); } // Set the music volume hVar = pClientDE->GetConsoleVar("MusicVolume"); if (hVar) { pClientDE->SetMusicVolume((int)pClientDE->GetVarValueFloat(hVar)); } else { pClientDE->SetMusicVolume(35); } // Set the mouse sensitivity m_fOriginalMouseSensitivity = GetMouseSensitivity(); // SetMouseSensitivity(m_fOriginalMouseSensitivity); m_fOriginalKeyTurnRate = GetKeyboardTurnRate(); // SetKeyboardTurnRate(m_fOriginalKeyTurnRate); // Set the invert y-axis variable hVar=pClientDE->GetConsoleVar("MouseInvertYAxis"); if (hVar && (int)pClientDE->GetVarValueFloat(hVar) != 0) { m_bMouseInvertYAxis=DTRUE; } else { m_bMouseInvertYAxis=DFALSE; } // Set the use joystick variable hVar=pClientDE->GetConsoleVar("UseJoystick"); if (hVar && (int)pClientDE->GetVarValueFloat(hVar) != 0) { m_bUseJoystick=DTRUE; } else { m_bUseJoystick=DFALSE; } // Set the keyboard turn rate hVar=pClientDE->GetConsoleVar("KeyboardTurnRate"); if (hVar) { m_fKeyboardTurnRate=pClientDE->GetVarValueFloat(hVar); } else { m_fKeyboardTurnRate=1.0f; } /* if (m_Music.IsInitialized()) { // Only re-init if not already using ima... if (!m_Music.UsingIMA()) { // preserve the music level, just in case we come back to ima... CMusic::EMusicLevel level; level = m_Music.GetMusicLevel(); if (m_Music.Init (pClientDE, DTRUE)) { // Only start the music if we are in a world... if (IsInWorld() && !pClientShell->IsFirstUpdate()) { m_Music.InitPlayLists(); m_Music.PlayMusicLevel (level); } } } } */ // Set the model hook function to do special model rendering... pClientDE->SetModelHook((ModelHookFn)DefaultModelHook, this); // Initialize the Message Mgr (T option) m_MessageMgr.Init(pClientDE); m_MessageMgr.Enable(DTRUE); // Initialize the Cheat Manager m_CheatMgr.Init(pClientDE); #ifndef _DEMO m_FragInfo.Init(pClientDE, GetTeamMgr()); #endif HSTRING szErrorStr = 0; // Initialize the Status bar if (!m_NewStatusBar.Init(pClientDE)) { szErrorStr = pClientDE->FormatString(IDS_INITERR_STATUS); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); Abort(IDS_ERR_INITSTATUSBAR, 6929318); return LT_ERROR; } // Initialize the Status bar if (!m_CommLink.Init(pClientDE)) { szErrorStr = pClientDE->FormatString(IDS_INITERR_COMMLINK); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); Abort(IDS_ERR_INITSTATUSBAR, 6929317); return LT_ERROR; } // Initialize the Menu if (!m_Menu.Init (pClientDE)) { szErrorStr = pClientDE->FormatString(IDS_INITERR_MENUS); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); Abort(IDS_ERR_INITMENU, 6929316); return LT_ERROR; } // Init the special fx mgr... if (!m_sfxMgr.Init(pClientDE)) { szErrorStr = pClientDE->FormatString(IDS_INITERR_SFX); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); Abort(IDS_ERR_INITSFXMGR, 6929315); return LT_ERROR; } // Init the voice manager... if (!m_VoiceMgr.Init(pClientDE)) { szErrorStr = pClientDE->FormatString(IDS_INITERR_VOICE); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); Abort(IDS_ERR_INITVOICEMGR, 61011701); return LT_ERROR; } if (!m_playerCamera.Init(pClientDE)) { szErrorStr = pClientDE->FormatString(IDS_INITERR_CAMERA); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); Abort(IDS_ERR_INITPLAYERCAMERA, 6929318); return LT_ERROR; } else { DVector vOffset; VEC_SET(vOffset, 0.0f, 30.0f, 0.0f); // m_playerCamera.SetDistUp(1000.0f); // m_playerCamera.SetPointAtOffset(vOffset); // m_playerCamera.SetChaseOffset(vOffset); m_playerCamera.SetDeathOffset(vOffset); m_playerCamera.SetFirstPerson(); m_b3rdPerson = DFALSE; } if (!bNetworkGameStarted) { StartGameRequest request; memset( &request, 0, sizeof( StartGameRequest )); NetStart_ClearGameStruct(); // Start with clean slate request.m_pGameInfo = NetStart_GetGameStruct(); request.m_GameInfoLen = sizeof(NetGame_t); HCONSOLEVAR hVar; // Set the Console lines if (hVar = pClientDE->GetConsoleVar("NumConsoleLines")) { DFLOAT fLines = pClientDE->GetVarValueFloat(hVar); // m_MessageMgr.SetMaxMessages((int)fLines); m_MessageMgr.SetMaxMessages((int)6); pClientDE->RunConsoleString("NumConsoleLines 0"); } // Get the command line world, if found if (hVar = pClientDE->GetConsoleVar("runworld")) { char *pWorldName = pClientDE->GetVarValueString(hVar); StartNewGame(pWorldName, STARTGAME_NORMAL, GAMETYPE_CUSTOM, LOADTYPE_NEW_GAME, DIFFICULTY_MEDIUM); m_bFirstWorld = DTRUE; } else { if (!StartMovies(pClientDE)) { bPlayingMovies = DFALSE; SetGameState(GS_MENU); m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU); } else { bPlayingMovies = DTRUE; } } } else { // Set the game state for a net game that is loading... SetGameState(GS_MPLOADINGLEVEL); } // Display the title screen if we're not playing movies... HSURFACE hTitleSurface = DNULL; DFLOAT fTitleTime = CWinUtil::GetTime(); if (!bPlayingMovies && !bNetworkGameStarted) { #ifndef _DEBUG #ifdef _ADDON hTitleSurface = Splash_Display(pClientDE, "\\screens_ao\\title.pcx", DTRUE); #else hTitleSurface = Splash_Display(pClientDE, "\\screens\\title.pcx", DTRUE); #endif fTitleTime = CWinUtil::GetTime(); #endif } // Read the player.cfg file, or defaultplayer.cfg if you can't find it. // if (!LoadConfig("player.cfg", &m_Config)) // LoadConfig("defaultplayer.cfg", &m_Config); #ifdef BRANDED // Initialize brand stuff CreateBrandSurface(); #endif // Seed the random number generator if ( pClientDE ) { int nSeed=(int)(CWinUtil::GetTime() * 1000.0f); srand(nSeed); } // Initialize the message box font m_messageFont.Init(pClientDE, "interface/fonts/MenuFont1.pcx", "interface/fonts/MenuFont1.fnt"); // Initialize the message box m_messageBox.Create(pClientDE, "interface/mainmenus/dialog.pcx", &m_messageFont, DNULL, DNULL); m_messageBox.SetTextColor(SETRGB(255, 255, 255)); // Make sure the title screen has been up long enough... if (hTitleSurface) { #ifndef _DEBUG CWinUtil::TimedKeyWait(VK_ESCAPE, VK_RETURN, VK_SPACE, 6.0f); #endif pClientDE->DeleteSurface(hTitleSurface); hTitleSurface = DNULL; CWinUtil::Sleep(50); } // Remove any stray keypresses... CWinUtil::RemoveKeyDownMessages(); // Show error if sound didn't initialize properly if( resInitSound != LT_OK ) { if( resInitSound == LT_NO3DSOUNDPROVIDER ) { hstrError = pClientDE->FormatString( IDS_MESSAGE_INVALID3DSOUNDPROVIDER ); } else { hstrError = pClientDE->FormatString( IDS_MESSAGE_SOUNDERROR ); } pszError = pClientDE->GetStringData( hstrError ); DoMessageBox( pszError ); pClientDE->FreeString( hstrError ); } // All done... return LT_OK; } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnEngineTerm() // // PURPOSE: Called upon engine termination. // // --------------------------------------------------------------------------- // void CBloodClientShell::OnEngineTerm() { CClientDE* pClientDE = GetClientDE(); m_Menu.Term(); m_MessageMgr.Term(); m_VoiceMgr.Term(); m_NewStatusBar.Term(); m_CommLink.Term(); m_Music.Term( ); if (m_Credits.IsInited()) m_Credits.Term(); if (m_hCrosshair) pClientDE->DeleteSurface(m_hCrosshair); // Terminate the message box and its font m_messageFont.Term(); m_messageBox.Destroy(); // Deal with some advanced options... if (m_bSoundOriginallyEnabled && AdvancedDisableSound()) { pClientDE->RunConsoleString ("SoundEnable 1"); } if (m_bMusicOriginallyEnabled && AdvancedDisableMusic()) { pClientDE->RunConsoleString ("MusicEnable 1"); } if (m_bModelFBOriginallyEnabled) { pClientDE->RunConsoleString ("ModelFullbrite 1"); } if (m_bLightmappingOriginallyEnabled) { pClientDE->RunConsoleString ("LightMap 1"); } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnEnterWorld() // // PURPOSE: Function called when the client first enters the world. // // --------------------------------------------------------------------------- // void CBloodClientShell::OnEnterWorld() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; m_bInWorld = DTRUE; m_bHandledStartup = DFALSE; m_bFadeIn = m_bFadeOut = DFALSE; if (!m_hCamera) { ObjectCreateStruct cocStruct; INIT_OBJECTCREATESTRUCT(cocStruct); cocStruct.m_ObjectType = OT_CAMERA; VEC_INIT(cocStruct.m_Pos) ROT_INIT(cocStruct.m_Rotation) cocStruct.m_Flags = 0; m_hCamera = pClientDE->CreateObject(&cocStruct); } pClientDE->GetSurfaceDims(pClientDE->GetScreenSurface(), &m_dwScreenWidth, &m_dwScreenHeight); m_fovX = DEG2RAD(m_DefFovX); m_fovY = m_fovX * m_fovYScale; pClientDE->SetCameraFOV(m_hCamera, m_fovX, m_fovY); // Initialize various variables m_SpinAmount = 0; m_bZeroXAngle = DFALSE; m_fBobPhase = m_fSwayPhase = 0; m_fBobHeight = m_fBobWidth = m_fBobCant = m_fShakeCant = 0; m_fViewKick = m_fKickTime = 0; // m_fVelY = 0.0f; m_fViewY = m_fViewYVel = 0.0f; m_fWeaponY = m_fWeaponYVel = 0.0f; m_fVelMagnitude = 0; m_fEyeLevel = 0; VEC_INIT(m_vMyLastPos); m_bDead = DFALSE; m_bDeadNoHide = DFALSE; m_bWonkyVision = DFALSE; m_bWonkyNoMove = DFALSE; m_fWonkyTime = 0.0f; m_bShakeScreen = DFALSE; m_fShakeTime = 0.0f; m_fShakeStart = 0.0f; VEC_INIT(m_vShakeMagnitude); m_bFlashScreen = DFALSE; m_fFlashTime = 0.0f; m_fFlashStart = 0.0f; m_fFlashRampUp = 0.0f; VEC_INIT(m_vFlashColor); ROT_INIT(m_Rotation) // Sky panning m_bPanSky = DFALSE; m_fPanSkyOffsetX = 1.0f; m_fPanSkyOffsetZ = 1.0f; m_fPanSkyScaleX = 1.0f; m_fPanSkyScaleZ = 1.0f; m_fCurSkyXOffset = 0.0f; m_fCurSkyZOffset = 0.0f; // Send initial update message // SendPlayerUpdateMessage(DTRUE); m_fCameraZoom = 0; m_b3rdPerson = DFALSE; m_playerCamera.SetFirstPerson(); m_bFirstUpdate = DTRUE; g_pClientDE->SetInputState(DTRUE); m_bDrawFragBar = DFALSE; g_bLevelChange3rdPersonCam = DFALSE; g_bLevelChangeNoUpdate = DFALSE; cdataLast.byFlags = 0; // Stuff to initialize/send if this is the first world if (m_bFirstWorld) { m_nCurGun = 0; m_bSpectatorMode = DFALSE; m_bZoomView = DFALSE; // m_bStoneView = DFALSE; // m_bAuraView = DFALSE; if( m_hNightGogglesSound ) { g_pClientDE->KillSound( m_hNightGogglesSound ); m_hNightGogglesSound = DNULL; } if( m_hTheEyeLoopingSound ) { g_pClientDE->KillSound( m_hTheEyeLoopingSound ); m_hTheEyeLoopingSound = DNULL; } int mode = 0; if (pClientDE->GetGameMode(&mode) == DE_OK) { if (mode == STARTGAME_NORMAL) // Single player game name irrelevant _mbscpy((unsigned char*)m_Config.szName, (const unsigned char*)""); } m_nLastExitType = -1; m_CheatMgr.Reset(); } // Reset the status bar m_NewStatusBar.Reset(); //SCHLEGZ 4/27/98 5:45:03 PM: automatically turn on vis lsit deactivation pClientDE->RunConsoleString("serv autodeactivate 1"); m_Music.TermPlayLists(); m_Music.InitPlayLists( ); if ( !m_Music.UsingIMA( )) m_Music.PlayCDList( ); else m_Music.PlayMusicLevel( m_eMusicLevel ); VEC_INIT( m_vLastReverbPos ); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnExitWorld() // // PURPOSE: Called when the client leaves the world. Perform cleanup here. // // --------------------------------------------------------------------------- // void CBloodClientShell::OnExitWorld() { CClientDE* pClientDE = GetClientDE(); m_sfxMgr.RemoveAll(); // Remove all the sfx // Kill the music... pClientDE->StopMusic (MUSIC_IMMEDIATE); m_Music.TermPlayLists(); m_eMusicLevel = CMusic::MUSICLEVEL_SILENCE; // Pause sounds (this will only pause currently playing sounds, then they'll get removed) pClientDE->PauseSounds(); m_playerCamera.AttachToObject(DNULL); // Detatch camera if (m_hCamera) { pClientDE->DeleteObject(m_hCamera); m_hCamera = DNULL; } for (int i=0;iKillSound(m_hContainerSound); m_hContainerSound = DNULL; } m_FragInfo.RemoveAllClients(); m_bInWorld = DFALSE; m_bRollCredits = DFALSE; m_Credits.Term(); m_bNightGogglesActive = DFALSE; if( m_hNightGogglesSound ) { g_pClientDE->KillSound( m_hNightGogglesSound ); m_hNightGogglesSound = DNULL; } m_bBinocularsActive = DFALSE; m_hSeeingEyeObj = m_hOrbObj = m_hLastOrbObj = DNULL; if( m_hTheEyeLoopingSound ) { g_pClientDE->KillSound( m_hTheEyeLoopingSound ); m_hTheEyeLoopingSound = DNULL; } if( m_hstrObjectivesText ) { g_pClientDE->FreeString( m_hstrObjectivesText ); m_hstrObjectivesText = DNULL; } if( m_hstrObjectivesTitle ) { g_pClientDE->FreeString( m_hstrObjectivesTitle ); m_hstrObjectivesTitle = DNULL; } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SendPlayerUpdateMessage() // // PURPOSE: Sends player info to the server // // --------------------------------------------------------------------------- // void CBloodClientShell::SendPlayerUpdateMessage(DBOOL bSendAll) { // Get our client pointer... CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; // Determine if it's time to update if we're in multiplayer... if (!bSendAll && IsMultiplayerGame()) { g_fPlayerUpdateTimer -= pClientDE->GetFrameTime(); if (g_fPlayerUpdateTimer > 0.0f) return; g_fPlayerUpdateTimer = PLAYER_MULTI_UPDATE_TIMER; } // Determine the update flags we want... DBYTE byUpdateFlags = 0; // HACK - send container code to server that is just below our eye DVector vPos; pClientDE->GetObjectPos(m_hCamera, &vPos); vPos.y -= 15.0f; HLOCALOBJ objList[1]; DDWORD dwNum = pClientDE->GetPointContainers(&vPos, objList, 1); if (dwNum > 0) { D_WORD wCode; pClientDE->GetContainerCode(objList[0], &wCode ); cdata.eContainer = ( ContainerCode )wCode; } else cdata.eContainer = m_eCurContainerCode; // HACK - send container code to server that is at our feet HOBJECT hPlayerObj; DVector vDims; hPlayerObj = m_pMoveMgr->GetObject( ); if( hPlayerObj && !m_bDead ) { pClientDE->GetObjectPos( hPlayerObj, &vPos ); pClientDE->Physics( )->GetObjectDims( hPlayerObj, &vDims ); vPos.y -= vDims.y; HLOCALOBJ objList[1]; DDWORD dwNum = pClientDE->GetPointContainers( &vPos, objList, 1 ); if (dwNum > 0) { cdata.hContainerAtBottom = objList[0]; } else cdata.hContainerAtBottom = DNULL; } else cdata.hContainerAtBottom = DNULL; // Set mouse aiming if (m_bMouseLook || pClientDE->IsCommandOn(COMMAND_MOUSEAIMTOGGLE)) cdata.byFlags |= CDATA_MOUSEAIMING; else cdata.byFlags &= ~CDATA_MOUSEAIMING; // Determine what we want to send.. if (!bSendAll) { if (cdata.byFlags != cdataLast.byFlags) byUpdateFlags |= PLAYERUPDATE_FLAGS; if (cdata.fPitch != cdataLast.fPitch) byUpdateFlags |= PLAYERUPDATE_PITCH; if (cdata.fYaw != cdataLast.fYaw) byUpdateFlags |= PLAYERUPDATE_YAW; if (!VEC_EQU(cdata.GunMuzzlePos, cdataLast.GunMuzzlePos)) byUpdateFlags |= PLAYERUPDATE_MUZZLE; if (!VEC_EQU(cdata.lGunMuzzlePos, cdataLast.lGunMuzzlePos)) byUpdateFlags |= PLAYERUPDATE_LMUZZLE; if (cdata.MouseAxis0 != cdataLast.MouseAxis0 || cdata.MouseAxis1 != cdataLast.MouseAxis1) { byUpdateFlags |= PLAYERUPDATE_MOUSE; } if (cdata.eContainer != cdataLast.eContainer) byUpdateFlags |= PLAYERUPDATE_CONTAINER; if (cdata.hContainerAtBottom != cdataLast.hContainerAtBottom) byUpdateFlags |= PLAYERUPDATE_CONTAINERATBOTTOM; } else // Send all params. { byUpdateFlags = 0xff; } // Send the stuff. if (byUpdateFlags) { HMESSAGEWRITE hMsg = pClientDE->StartMessage(CMSG_PLAYERUPDATE); pClientDE->WriteToMessageByte(hMsg, byUpdateFlags); // Tell what we are updating if (byUpdateFlags & PLAYERUPDATE_FLAGS) pClientDE->WriteToMessageByte(hMsg, cdata.byFlags); // Flags if (byUpdateFlags & PLAYERUPDATE_PITCH) pClientDE->WriteToMessageFloat(hMsg, cdata.fPitch); // Rotation if (byUpdateFlags & PLAYERUPDATE_YAW) pClientDE->WriteToMessageFloat(hMsg, cdata.fYaw); if (byUpdateFlags & PLAYERUPDATE_MUZZLE) pClientDE->WriteToMessageCompVector(hMsg, &cdata.GunMuzzlePos); // Muzzle pos if (byUpdateFlags & PLAYERUPDATE_LMUZZLE) pClientDE->WriteToMessageCompVector(hMsg, &cdata.lGunMuzzlePos); // Muzzle pos if (byUpdateFlags & PLAYERUPDATE_MOUSE) { DFLOAT fMouse0 = cdata.MouseAxis0 * 512; CLIPLOWHIGH(fMouse0, -128, 127); fMouse0 += 128; DFLOAT fMouse1 = cdata.MouseAxis1 * 512; CLIPLOWHIGH(fMouse1, -128, 127); fMouse1 += 128; pClientDE->WriteToMessageByte(hMsg, (DBYTE)fMouse0); // Mouse axis pClientDE->WriteToMessageByte(hMsg, (DBYTE)fMouse1); } if (byUpdateFlags & PLAYERUPDATE_CONTAINER) { DBYTE nContainerCode; nContainerCode = (DBYTE) cdata.eContainer; if( m_pExternalCamera || m_hSeeingEyeObj || m_hOrbObj ) nContainerCode |= 0x80; pClientDE->WriteToMessageByte(hMsg, nContainerCode ); // Container code } if (byUpdateFlags & PLAYERUPDATE_CONTAINERATBOTTOM ) { pClientDE->WriteToMessageObject(hMsg, cdata.hContainerAtBottom ); } pClientDE->EndMessage(hMsg); } // Save current cdata memcpy(&cdataLast, &cdata, sizeof(ClientData)); // Send position packet HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_PLAYERPOSITION); // Write position info. m_pMoveMgr->WritePositionInfo(hMessage); pClientDE->EndMessage2(hMessage, 0); // Send unguaranteed. // m_fLastSentYaw = m_fYaw; // m_fLastSentCamCant = m_fCamCant; // m_fPlayerInfoLastSendTime = pClientDE->GetTime(); // m_nPlayerInfoChangeFlags = 0; } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SendPlayerInitMessage() // // PURPOSE: Sends a message to the server. // // --------------------------------------------------------------------------- // void CBloodClientShell::SendPlayerInitMessage(DBYTE messageID) { HMESSAGEWRITE hMsg; CClientDE* pClientDE = GetClientDE(); if (messageID != CMSG_SINGLEPLAYER_INIT && messageID != CMSG_MULTIPLAYER_INIT) return; // Only send this if it's a new game. if (messageID == CMSG_SINGLEPLAYER_INIT && m_nLastLoadType != LOADTYPE_NEW_GAME) return; // Start the message hMsg = pClientDE->StartMessage(messageID); // Send the appropriate data for this message switch(messageID) { case CMSG_SINGLEPLAYER_INIT: case CMSG_MULTIPLAYER_INIT: { int i; HSTRING hstrName = DNULL; // Load in a B2C file if it's a multiplayer game if (IsMultiplayerGame()) { NetPlayer* pPlayerInfo = NetStart_GetPlayerStruct(); if (!pPlayerInfo) return; hstrName = pClientDE->CreateString(pPlayerInfo->m_sName); B2C b2cFile; FILE *file = 0; char filename[128]; if (strlen(pPlayerInfo->m_sConfig) <= 0) { CShell_GetConsoleString("NetConfigFile", pPlayerInfo->m_sConfig, "caleb.b2c"); } sprintf(filename, "players\\%s", pPlayerInfo->m_sConfig); if(file = fopen(filename, "rb")) { fread(&b2cFile, sizeof(B2C), 1, file); fclose(file); } else // just set default stuff { CSPrint("Warning - Unable to load .b2c file"); b2cFile.dwCharacter = CHARACTER_CALEB; b2cFile.dwColor = 1; b2cFile.dwStrength = 5; b2cFile.dwSpeed = 3; b2cFile.dwResist = 3; b2cFile.dwFocus = 1; b2cFile.dwWeap1 = 1; b2cFile.dwWeap2 = 2; b2cFile.dwWeap3 = 3; b2cFile.dwWeap4 = 4; b2cFile.dwWeap5 = 5; b2cFile.dwWeap6 = 6; b2cFile.dwWeap7 = 7; b2cFile.dwWeap8 = 8; b2cFile.dwWeap9 = 9; } m_Config.nCharacter = (DBYTE)b2cFile.dwCharacter; m_Config.nSkin = (DBYTE)b2cFile.dwColor; m_Config.nStrength = (DBYTE)b2cFile.dwStrength; m_Config.nSpeed = (DBYTE)b2cFile.dwSpeed; m_Config.nResistance = (DBYTE)b2cFile.dwResist; m_Config.nMagic = (DBYTE)b2cFile.dwFocus; m_Config.nWeaponSlots[1] = (DBYTE)b2cFile.dwWeap1; m_Config.nWeaponSlots[2] = (DBYTE)b2cFile.dwWeap2; m_Config.nWeaponSlots[3] = (DBYTE)b2cFile.dwWeap3; m_Config.nWeaponSlots[4] = (DBYTE)b2cFile.dwWeap4; m_Config.nWeaponSlots[5] = (DBYTE)b2cFile.dwWeap5; m_Config.nWeaponSlots[6] = (DBYTE)b2cFile.dwWeap6; m_Config.nWeaponSlots[7] = (DBYTE)b2cFile.dwWeap7; m_Config.nWeaponSlots[8] = (DBYTE)b2cFile.dwWeap8; m_Config.nWeaponSlots[9] = (DBYTE)b2cFile.dwWeap9; } else { // first gun is the beretta m_Config.nWeaponSlots[1] = WEAP_BERETTA; m_Config.nWeaponSlots[2] = WEAP_NONE; m_Config.nWeaponSlots[3] = WEAP_NONE; m_Config.nWeaponSlots[4] = WEAP_NONE; m_Config.nWeaponSlots[5] = WEAP_NONE; m_Config.nWeaponSlots[6] = WEAP_NONE; m_Config.nWeaponSlots[7] = WEAP_NONE; m_Config.nWeaponSlots[8] = WEAP_NONE; m_Config.nWeaponSlots[9] = WEAP_NONE; hstrName = pClientDE->CreateString(m_Config.szName); } if (!hstrName) return; pClientDE->WriteToMessageHString(hMsg, hstrName); pClientDE->FreeString(hstrName); pClientDE->WriteToMessageByte(hMsg, m_Config.nCharacter); pClientDE->WriteToMessageByte(hMsg, m_Config.nSkin); pClientDE->WriteToMessageByte(hMsg, m_Config.nStrength); pClientDE->WriteToMessageByte(hMsg, m_Config.nSpeed); pClientDE->WriteToMessageByte(hMsg, m_Config.nResistance); pClientDE->WriteToMessageByte(hMsg, m_Config.nMagic); // for(i = 0; i < 3; i++) // pClientDE->WriteToMessageByte(hMsg, m_Config.nBindingSlots[i]); for (i=1;iWriteToMessageByte(hMsg, m_Config.nWeaponSlots[i]); /* for (i=0;iWriteToMessageByte(hMsg, m_Config.nItemSlots[i]); pClientDE->WriteToMessageByte(hMsg, m_Config.nProximityBombs); pClientDE->WriteToMessageByte(hMsg, m_Config.nRemoteBombs); pClientDE->WriteToMessageByte(hMsg, m_Config.nTimeBombs); // for (i=0;i<6;i++) // pClientDE->WriteToMessageByte(hMsg, m_Config.nSpellSlots[i]); */ } break; } // Finish it off.. pClientDE->EndMessage(hMsg); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateSoundReverb // // PURPOSE: Update the reverb info // // ----------------------------------------------------------------------- // void CBloodClientShell::UpdateSoundReverb( ) { DVector vPlayerDims; ClientIntersectInfo info; ClientIntersectQuery query; DVector vPos[6], vSegs[6]; int i; float fVolume, fReverbLevel; DBOOL bOpen; HLOCALOBJ hPlayerObj; ReverbProperties reverbProperties; HCONSOLEVAR hVar; if( !m_bUseReverb ) return; hPlayerObj = g_pClientDE->GetClientObject(); if( !hPlayerObj ) return; hVar = g_pClientDE->GetConsoleVar( "ReverbLevel" ); if( hVar ) { fReverbLevel = g_pClientDE->GetVarValueFloat( hVar ); } else fReverbLevel = 1.0f; // Check if reverb was off and is still off if( fReverbLevel < 0.001f && m_fReverbLevel < 0.001f ) return; m_fReverbLevel = fReverbLevel; // Check if it's time yet if( g_pClientDE->GetTime( ) < m_fNextSoundReverbTime ) return; // Update timer m_fNextSoundReverbTime = g_pClientDE->GetTime( ) + SOUND_REVERB_UPDATE_PERIOD; HOBJECT hFilterList[] = {hPlayerObj, m_pMoveMgr->GetObject(), DNULL}; memset( &query, 0, sizeof( query )); query.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; query.m_FilterFn = ObjListFilterFn; query.m_pUserData = hFilterList; g_pClientDE->GetObjectPos( hPlayerObj, &query.m_From ); g_pClientDE->Physics( )->GetObjectDims( hPlayerObj, &vPlayerDims ); // Player must move at least 2x his dims mag before reverb is checked again. if( VEC_DISTSQR( query.m_From, m_vLastReverbPos ) < 4 * VEC_MAGSQR( vPlayerDims )) return; VEC_COPY( m_vLastReverbPos, query.m_From ); VEC_SET( vSegs[0], query.m_From.x + 2000.0f, query.m_From.y, query.m_From.z ); VEC_SET( vSegs[1], query.m_From.x - 2000.0f, query.m_From.y, query.m_From.z ); VEC_SET( vSegs[2], query.m_From.x, query.m_From.y + 2000.0f, query.m_From.z ); VEC_SET( vSegs[3], query.m_From.x, query.m_From.y - 2000.0f, query.m_From.z ); VEC_SET( vSegs[4], query.m_From.x, query.m_From.y, query.m_From.z + 2000.0f ); VEC_SET( vSegs[5], query.m_From.x, query.m_From.y, query.m_From.z - 2000.0f ); bOpen = DFALSE; for( i = 0; i < 6; i++ ) { VEC_COPY( query.m_To, vSegs[i] ); if( g_pClientDE->IntersectSegment( &query, &info )) { VEC_COPY( vPos[i], info.m_Point ); if( info.m_SurfaceFlags == SURFTYPE_SKY ) { bOpen = DTRUE; } } else { VEC_COPY( vPos[i], vSegs[i] ); bOpen = DTRUE; } } fVolume = VEC_DIST( vPos[0], vPos[1] ); fVolume *= VEC_DIST( vPos[2], vPos[3] ); fVolume *= VEC_DIST( vPos[4], vPos[5] ); // Use room types that are not completely enclosed rooms if( bOpen ) { if( fVolume < 100.0f*100.0f*100.0f ) { reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_SEWERPIPE; reverbProperties.m_fReflectTime = 0.005f; reverbProperties.m_fDecayTime = 1.493f; reverbProperties.m_fVolume = 0.1f * m_fReverbLevel; } else if( fVolume < 500.0f*500.0f*500.0f ) { reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_PLAIN; reverbProperties.m_fReflectTime = 0.005f; reverbProperties.m_fDecayTime = 1.493f; reverbProperties.m_fVolume = 0.2f * m_fReverbLevel; } else if( fVolume < 1000.0f*1000.0f*1000.0f ) { reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_ARENA; reverbProperties.m_fReflectTime = 0.01f; reverbProperties.m_fDecayTime = 4.236f; reverbProperties.m_fVolume = 0.1f * m_fReverbLevel; } else { reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_MOUNTAINS; reverbProperties.m_fReflectTime = 0.0f; reverbProperties.m_fDecayTime = 3.0f; reverbProperties.m_fVolume = 0.1f * m_fReverbLevel; } } // Use room types that are enclosed rooms else { if( fVolume < 100.0f*100.0f*100.0f ) { reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_STONEROOM; reverbProperties.m_fReflectTime = 0.005f; reverbProperties.m_fDecayTime = 0.6f; reverbProperties.m_fVolume = 0.3f * m_fReverbLevel; } else if( fVolume < 500.0f*500.0f*500.0f ) { reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_HALLWAY; reverbProperties.m_fReflectTime = 0.01f; reverbProperties.m_fDecayTime = 1.3f; reverbProperties.m_fVolume = 0.1f * m_fReverbLevel; } else if( fVolume < 1500.0f*1500.0f*1500.0f ) { reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_CONCERTHALL; reverbProperties.m_fReflectTime = 0.02f; reverbProperties.m_fDecayTime = 2.2f; reverbProperties.m_fVolume = 0.1f * m_fReverbLevel; } else { reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_AUDITORIUM; reverbProperties.m_fReflectTime = 0.02f; reverbProperties.m_fDecayTime = 3.5f; reverbProperties.m_fVolume = 0.1f * m_fReverbLevel; } } // Override to water if in it. if( IsLiquid( m_eCurContainerCode )) reverbProperties.m_dwAcoustics = REVERB_ACOUSTICS_UNDERWATER; reverbProperties.m_dwParams = REVERBPARAM_VOLUME | REVERBPARAM_ACOUSTICS | REVERBPARAM_REFLECTTIME | REVERBPARAM_DECAYTIME; g_pClientDE->SetReverbProperties( &reverbProperties ); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateCamera() // // PURPOSE: Updates the camera position and status // // --------------------------------------------------------------------------- // void CBloodClientShell::UpdateCamera() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; HLOCALOBJ hPlayerObj = pClientDE->GetClientObject(); if (!hPlayerObj || !m_hCamera) return; if (!m_bHandledStartup) { m_bRenderCamera = DTRUE; // pClientDE->SetCameraZOrder(m_hCamera, 0); // Okay, we can render now m_bHandledStartup = DTRUE; } // Update the player camera... if (!UpdatePlayerCamera()) return; m_pExternalCamera = DNULL; // See if we should use a cutscene camera... if (!m_hSeeingEyeObj && !m_hOrbObj) { CSpecialFXList* pCameraList = m_sfxMgr.GetCameraFXList(); if (pCameraList) { int nNumCameras = pCameraList->GetNumItems(); for (int i=0; i < nNumCameras; i++) { CCameraFX* pCameraFX = (CCameraFX*)(*pCameraList)[i]; if (!pCameraFX) continue; if ( HOBJECT hObj = pCameraFX->GetServerObj() ) { DDWORD dwUsrFlags; pClientDE->GetObjectUserFlags(hObj, &dwUsrFlags); // USRFLG_VISIBLE means the camera is active if (dwUsrFlags & USRFLG_VISIBLE) { m_pExternalCamera = pCameraFX; break; } } } } } if ((m_pExternalCamera && !m_pExternalCamera->GetHidePlayer()) || m_hSeeingEyeObj || m_hOrbObj) { ShowPlayer(DTRUE); } else { if (m_bDead && m_bDeadNoHide) { ShowPlayer(TRUE); } else { ShowPlayer((m_bDead) ? DFALSE : !m_playerCamera.IsFirstPerson()); } } CalculateCameraRotation(); UpdateCameraPosition(); UpdateCameraRotation(); // Adjust camera for current resolution SetCameraStuff(hPlayerObj, m_hCamera); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::FirstUpdate() // // PURPOSE: Special stuff to do on the first update after entering a world. // // --------------------------------------------------------------------------- // void CBloodClientShell::FirstUpdate() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; char buf[100]; char *pStrParam; ShowPlayer(m_b3rdPerson ? DTRUE : DFALSE); // Check for add-on special case stuff... #ifdef _ADDON if (g_bPlayerInvReset) { ResetPlayerInventory(); g_bPlayerInvReset = DFALSE; } #endif // Display the world name if any // if (pStrParam = pClientDE->GetServerConVarValueString("WorldName")) // { // CSPrint("Entering %s", pStrParam); // } // Set the FarZ setting for the world... DFLOAT fVal = pClientDE->GetServerConVarValueFloat("FarZ"); if (fVal > 0.0f) { sprintf(buf, "FarZ %d", (int)fVal); pClientDE->RunConsoleString(buf); } ResetGlobalFog(); // Set up the environment map texture... pStrParam = pClientDE->GetServerConVarValueString("EnvironmentMap"); if (pStrParam && (m_nGlobalDetail == DETAIL_HIGH)) { sprintf(buf, "EnvMap %s", pStrParam); pClientDE->RunConsoleString(buf); pClientDE->RunConsoleString("EnvMapEnable 1"); } else { pClientDE->RunConsoleString("EnvMapEnable 0"); } pClientDE->RunConsoleString("ModelWarble 0"); pClientDE->RunConsoleString("WarbleSpeed 15"); pClientDE->RunConsoleString("WarbleScale .95"); // Sky panning... m_bPanSky = (DBOOL) pClientDE->GetServerConVarValueFloat("PanSky"); m_fPanSkyOffsetX = pClientDE->GetServerConVarValueFloat("PanSkyOffsetX"); m_fPanSkyOffsetZ = pClientDE->GetServerConVarValueFloat("PanSkyOffsetZ"); m_fPanSkyScaleX = pClientDE->GetServerConVarValueFloat("PanSkyScaleX"); m_fPanSkyScaleZ = pClientDE->GetServerConVarValueFloat("PanSkyScaleZ"); pStrParam = pClientDE->GetServerConVarValueString("PanSkyTexture"); if (m_bPanSky) { pClientDE->SetGlobalPanTexture(GLOBALPAN_SKYSHADOW, pStrParam); } // Initialize the music playlists... if ( m_Music.IsInitialized( ) ) { // CMusic::EMusicLevel level; // level = m_Music.GetMusicLevel( ); /* m_Music.TermPlayLists(); m_Music.InitPlayLists( ); if ( !m_Music.UsingIMA( )) m_Music.PlayCDList( ); else m_Music.PlayMusicLevel( m_eMusicLevel ); */ } // Set up the soft renderer sky map... char* pSoftSky = pClientDE->GetServerConVarValueString("SoftSky"); if (pSoftSky) { sprintf(buf, "SoftSky %s", pSoftSky); pClientDE->RunConsoleString(buf); } // Send initial update message SendPlayerUpdateMessage(DTRUE); m_bFirstUpdate = DFALSE; } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::ResetGlobalFog // // PURPOSE: Reset the global fog value... // // --------------------------------------------------------------------------- // void CBloodClientShell::ResetGlobalFog() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; DFLOAT fVal = pClientDE->GetServerConVarValueFloat("FogEnable"); char buf[30]; sprintf(buf, "FogEnable %d", (int)fVal); pClientDE->RunConsoleString(buf); if (fVal) { fVal = pClientDE->GetServerConVarValueFloat("FogNearZ"); sprintf(buf, "FogNearZ %d", (int)fVal); pClientDE->RunConsoleString(buf); fVal = pClientDE->GetServerConVarValueFloat("FogFarZ"); sprintf(buf, "FogFarZ %d", (int)fVal); pClientDE->RunConsoleString(buf); fVal = pClientDE->GetServerConVarValueFloat("FogR"); sprintf(buf, "FogR %d", (int)fVal); pClientDE->RunConsoleString(buf); fVal = pClientDE->GetServerConVarValueFloat("FogG"); sprintf(buf, "FogG %d", (int)fVal); pClientDE->RunConsoleString(buf); fVal = pClientDE->GetServerConVarValueFloat("FogB"); sprintf(buf, "FogB %d", (int)fVal); pClientDE->RunConsoleString(buf); } // ModelAdd DFLOAT fR, fG, fB; fR = pClientDE->GetServerConVarValueFloat("ModelAddR"); fG = pClientDE->GetServerConVarValueFloat("ModelAddG"); fB = pClientDE->GetServerConVarValueFloat("ModelAddB"); sprintf(buf, "ModelAdd %d %d %d", (int)fR, (int)fG, (int)fB); pClientDE->RunConsoleString(buf); // ModelDirAdd fR = pClientDE->GetServerConVarValueFloat("ModelDirAddR"); fG = pClientDE->GetServerConVarValueFloat("ModelDirAddG"); fB = pClientDE->GetServerConVarValueFloat("ModelDirAddB"); sprintf(buf, "ModelDirAdd %d %d %d", (int)fR, (int)fG, (int)fB); pClientDE->RunConsoleString(buf); fVal = pClientDE->GetServerConVarValueFloat("SkyFog"); sprintf(buf, "SkyFog %d", (int)fVal); pClientDE->RunConsoleString(buf); if (fVal) { fVal = pClientDE->GetServerConVarValueFloat("SkyFogNearZ"); sprintf(buf, "SkyFogNearZ %d", (int)fVal); pClientDE->RunConsoleString(buf); fVal = pClientDE->GetServerConVarValueFloat("SkyFogFarZ"); sprintf(buf, "SkyFogFarZ %d", (int)fVal); pClientDE->RunConsoleString(buf); } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::Update() // // PURPOSE: the client shell update function. // // --------------------------------------------------------------------------- // void CBloodClientShell::Update() { HLOCALOBJ hPlayerObj; CClientDE* pClientDE = GetClientDE(); m_pMoveMgr->Update(); UpdateSoundReverb( ); switch (GetGameState()) { case GS_PLAYING: case GS_MENUANIM: { if (!m_bInWorld || !pClientDE) return; if (g_bLevelChangeNoUpdate) return; // Make sure server is still running if (!pClientDE->IsConnected()) { HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_SHUTDOWN); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); m_bInWorld = DFALSE; return; } hPlayerObj = pClientDE->GetClientObject(); if (!hPlayerObj) return; if (m_bFirstUpdate) { FirstUpdate(); } // Update weapons firing.. HandleFiring(); // Initialize cameraadd and lightscale.. VEC_SET(m_vLightScale, 1.0f, 1.0f, 1.0f); VEC_SET(m_vCameraAdd, 0.0f, 0.0f, 0.0f); // Update sky panning if (m_bPanSky) { DFLOAT fFrameTime = pClientDE->GetFrameTime(); m_fCurSkyXOffset += fFrameTime * m_fPanSkyOffsetX; m_fCurSkyZOffset += fFrameTime * m_fPanSkyOffsetZ; pClientDE->SetGlobalPanInfo(GLOBALPAN_SKYSHADOW, m_fCurSkyXOffset, m_fCurSkyZOffset, m_fPanSkyScaleX, m_fPanSkyScaleZ); } // Update the camera UpdateCamera(); // Update the screen shake if (m_bShakeScreen) UpdateScreenShake(); // Update the screen flash if (m_bFlashScreen) UpdateScreenFlash(); // Update container effects... UpdateContainerFX(); if(m_pCreature && m_pCreature->GetType() == SMSG_THIEF_ATTACH || IsWonky()) { // Update the wonkyvision timer. if (IsWonky()) { m_fWonkyTime -= pClientDE->GetFrameTime(); if (m_fWonkyTime <= 0) { EndWonkyVision(); } } UpdateWonkyVision(); } else { pClientDE->RunConsoleString("ModelWarble 0"); m_fOffsetY = 0.0f; m_fOffsetX = 0.0f; m_fOffsetRot = 0.0f; } // Update night goggles sounds... if( m_bNightGogglesActive ) { // Start the sound... if( !m_hNightGogglesSound ) { m_hNightGogglesSound = PlaySoundLocal( "sounds\\powerups\\nightgogglesloop1.wav", SOUNDPRIORITY_PLAYER_LOW, DTRUE, DTRUE ); } } else { // Kill the sound... if( m_hNightGogglesSound ) { g_pClientDE->KillSound( m_hNightGogglesSound ); m_hNightGogglesSound = DNULL; } } SetPhysicsStateTimeStep(&g_normalPhysicsState, pClientDE->GetFrameTime()); SetPhysicsStateTimeStep(&g_waterPhysicsState, pClientDE->GetFrameTime()); // Update any client-side special effects... m_sfxMgr.UpdateSpecialFX(); // Check for Burn // Set the light scale if (m_bBlind) { if (pClientDE->GetTime() > m_fBlindTime) m_bBlind = DFALSE; } // Set the light scale depending on the state DVector vLightScale; if (m_bBlind) { VEC_SET(vLightScale, 0.0f, 0.0f, 0.0f) } else if (m_bFadeIn) // 4 second fade-in { m_fFadeVal += 100 * pClientDE->GetFrameTime(); if (m_fFadeVal > 255) { m_fFadeVal = 255; m_bFadeIn = DFALSE; } DFLOAT fScale = m_fFadeVal / 255.0f; VEC_SET(vLightScale, fScale, fScale, fScale); } else if (m_bFadeOut) // 4 second fade-out { m_fFadeVal -= 100 * pClientDE->GetFrameTime(); if (m_fFadeVal < 0) { m_fFadeVal = 0; } DFLOAT fScale = m_fFadeVal / 255.0f; VEC_SET(vLightScale, fScale, fScale, fScale); } // else if (m_bStoneView) // { // VEC_SET(vLightScale, 0.0f, 0.0f, 1.0f) // } else if (m_hSeeingEyeObj) { VEC_SET(vLightScale, 1.0f, 0.0f, 0.5f) } else if(m_pCreature) { VEC_COPY(vLightScale, m_pCreature->GetLightScale()); } else if(m_bNightGogglesActive) { VEC_SET(vLightScale, 0.1f, 1.0f, 0.1f); } else // Default { VEC_COPY(vLightScale, m_vLightScale); } pClientDE->SetGlobalLightScale(&vLightScale); pClientDE->SetCameraLightAdd(m_hCamera, &m_vCameraAdd); // Update the server with player info SendPlayerUpdateMessage(DFALSE); // Roll the credits if necessary if (m_bRollCredits) { if (m_Credits.IsInited()) { m_Credits.Update(); } else { m_Credits.Init(pClientDE, this, CM_CREDITS, DFALSE); } } // Zoom camera out if (m_CheatMgr.IsCheatActive(CHEAT_CHASEVIEW) || g_bLevelChange3rdPersonCam) { if (!m_b3rdPerson) Set3rdPersonCamera(DTRUE); } // Zoom camera in else { if (m_b3rdPerson) Set3rdPersonCamera(DFALSE); } break; } // Nothing to do if we're in menu mode.. case GS_MENU: break; case GS_LOADINGLEVEL: case GS_MPLOADINGLEVEL: case GS_WAITING: break; case GS_CREDITS : { UpdateCredits(); return; } case GS_MOVIES: { UpdateMoviesState(); return; } case GS_SPLASH: { Splash_Update(); return; } break; } pClientDE->ClearScreen(DNULL, CLEARSCREEN_SCREEN | CLEARSCREEN_RENDER); if (m_bRenderCamera) { pClientDE->Start3D(); if( pClientDE->GetClientObject()) pClientDE->ProcessAttachments(pClientDE->GetClientObject()); // [blg] pClientDE->RenderCamera(m_hCamera); if (m_bRollCredits && m_Credits.IsInited()) m_Credits.Update(); // [blg] pClientDE->End3D(); } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateCredits() // // PURPOSE: Update the credits // // ----------------------------------------------------------------------- // void CBloodClientShell::UpdateCredits() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; pClientDE->Start3D(); m_Credits.Update(); pClientDE->End3D(); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnObjectMove() // // PURPOSE: // // --------------------------------------------------------------------------- // DRESULT CBloodClientShell::OnObjectMove(HOBJECT hObj, DBOOL bTeleport, DVector *pPos) { m_pMoveMgr->OnObjectMove(hObj, bTeleport, pPos); return LT_OK; } DRESULT CBloodClientShell::OnObjectRotate(HOBJECT hObj, DBOOL bTeleport, DRotation *pNewRot) { return m_pMoveMgr->OnObjectRotate(hObj, bTeleport, pNewRot); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::PreLoadWorld() // // PURPOSE: Display a loading screen right before loading the next world. // // --------------------------------------------------------------------------- // void CBloodClientShell::PreLoadWorld(char *pWorldName) { CClientDE* pClientDE = GetClientDE(); DrawLoadingScreen(); pClientDE->FlipScreen(FLIPSCREEN_CANDRAWCONSOLE); DrawLoadingScreen(); g_bLevelChangeNoUpdate = DFALSE; // Re-Init the team manager... m_TeamMgr.Term(); m_TeamMgr.Init(); HSTRING hTeam1String = pClientDE->FormatString(IDS_TEAM1NAME); HSTRING hTeam2String = pClientDE->FormatString(IDS_TEAM2NAME); if (hTeam1String) { m_TeamMgr.AddTeam(TEAM_1, pClientDE->GetStringData(hTeam1String)); } else { m_TeamMgr.AddTeam(TEAM_1, "Team Blue"); } if (hTeam2String) { m_TeamMgr.AddTeam(TEAM_2, pClientDE->GetStringData(hTeam2String)); } else { m_TeamMgr.AddTeam(TEAM_2, "Team Blue"); } if (hTeam1String) pClientDE->FreeString(hTeam1String); if (hTeam2String) pClientDE->FreeString(hTeam2String); // Stop any voice sounds... GetVoiceMgr()->StopAll(); // Check if we should roll the credits on top of this world... strupr(pWorldName); m_bRollCredits = DFALSE; if (pWorldName) { if (_mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"END") == 0 || _mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"WORLDS\\END") == 0) { m_bRollCredits = DTRUE; } if (_mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"CREDITS") == 0 || _mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"WORLDS\\CREDITS") == 0) { m_bRollCredits = DTRUE; } #ifdef _ADDON if (_mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"WORLDS_AO\\END") == 0) { m_bRollCredits = DTRUE; } if (_mbsicmp((const unsigned char*)pWorldName, (const unsigned char*)"WORLDS_AO\\CREDITS") == 0) { m_bRollCredits = DTRUE; } #endif } m_Credits.Term(); // Check if this is an add-on level that wants a character change... g_bPlayerInvReset = DFALSE; #ifdef _ADDON char sUpr[256]; strncpy(sUpr, pWorldName, 255); strupr(sUpr); if (strstr(sUpr, "_AO")) // is this an add-on level? { if (strstr(sUpr, "_CC_C")) // switch to caleb? { SetCharacterInfo(CHARACTER_CALEB, MULTIPLAY_SKIN_NORMAL); g_bPlayerInvReset = DTRUE; } else if (strstr(sUpr, "_CC_I")) // switch to ishmael? { SetCharacterInfo(CHARACTER_ISHMAEL, MULTIPLAY_SKIN_NORMAL); g_bPlayerInvReset = DTRUE; } else if (strstr(sUpr, "_CC_O")) // switch to ophelia? { SetCharacterInfo(CHARACTER_OPHELIA, MULTIPLAY_SKIN_NORMAL); g_bPlayerInvReset = DTRUE; } else if (strstr(sUpr, "_CC_G")) // switch to gabby? { SetCharacterInfo(CHARACTER_GABREILLA, MULTIPLAY_SKIN_NORMAL); g_bPlayerInvReset = DTRUE; } } if (m_nLastLoadType == LOADTYPE_RESTORESAVE || m_nLastLoadType == LOADTYPE_RESTOREAUTOSAVE) { g_bPlayerInvReset = DFALSE; } if (strstr(sUpr, "ENDBOSS_CC_C")) // check for final caleb nightmare level { g_bPlayerInvReset = DFALSE; } #endif } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::PostUpdate() // // PURPOSE: Called after client object update functions. // // --------------------------------------------------------------------------- // void CBloodClientShell::PostUpdate() { CClientDE* pClientDE = GetClientDE(); HSURFACE hScreen = pClientDE->GetScreenSurface(); // Delete the loading screen if there is one. if (GetGameState() == GS_LOADINGLEVEL || GetGameState() == GS_MPLOADINGLEVEL || GetGameState() == GS_WAITING) { DrawLoadingScreen(); pClientDE->FlipScreen(FLIPSCREEN_CANDRAWCONSOLE); return; } else if (m_hLoadingScreen) { pClientDE->DeleteSurface(m_hLoadingScreen); m_hLoadingScreen = DNULL; m_bPlayedWaitingSound = DFALSE; } if (GetGameState() == GS_MENU) { m_Menu.Draw(); } else if (GetGameState() == GS_PLAYING) { if (g_bLevelChangeNoUpdate) { return; } m_MessageMgr.Draw(); DBOOL bDraw = m_bDrawStatusBar && !(m_pExternalCamera); m_NewStatusBar.Draw(bDraw); m_CommLink.Draw(DTRUE); if (m_bDrawFragBar && IsMultiplayerGame()) { m_FragInfo.Draw (DTRUE, DTRUE); } if (m_bShowCrosshair && !m_pExternalCamera && !m_bDead && !m_hSeeingEyeObj && !m_hOrbObj && !g_bLevelChange3rdPersonCam && !m_bDrawFragBar) { if(m_nLastCrosshair != m_nCrosshair) { if(m_hCrosshair) pClientDE->DeleteSurface(m_hCrosshair); m_hCrosshair = 0; m_nLastCrosshair = m_nCrosshair; } if (!m_hCrosshair) { char file[128]; if(m_nCrosshair < 10) sprintf(file, "Interface/Crosshairs/Crosshair0%d.pcx", m_nCrosshair); else sprintf(file, "Interface/Crosshairs/Crosshair%d.pcx", m_nCrosshair); m_hCrosshair = pClientDE->CreateSurfaceFromBitmap(file); pClientDE->GetSurfaceDims (m_hCrosshair, &m_cxCrosshair, &m_cyCrosshair); } DBOOL bFullScreen = DFALSE; int nLeft = 0; int nTop = 0; int nRight = 0; int nBottom = 0; pClientDE->GetCameraRect (m_hCamera, &bFullScreen, &nLeft, &nTop, &nRight, &nBottom); if (bFullScreen) { pClientDE->GetSurfaceDims (hScreen, &m_dwScreenWidth, &m_dwScreenHeight); nRight = (int)m_dwScreenWidth; nBottom = (int)m_dwScreenHeight; } int x = nLeft + (((nRight - nLeft) - m_cxCrosshair) >> 1); int y = nTop + (((nBottom - nTop) - m_cyCrosshair) >> 1); pClientDE->DrawSurfaceToSurfaceTransparent (hScreen, m_hCrosshair, NULL, x, y, NULL); } } // Draw the message box if it is up if (m_bInMessageBox) { m_messageBox.Render(hScreen); } #ifdef BRANDED if (m_hBrandSurface && m_fBrandCounter > 0) { DrawBrandString(hScreen); m_fBrandCounter -= pClientDE->GetFrameTime(); } #endif pClientDE->FlipScreen(FLIPSCREEN_CANDRAWCONSOLE); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateBob // // PURPOSE: Adjusts the head bobbing & swaying // // --------------------------------------------------------------------------- // void CBloodClientShell::UpdateBob() { DFLOAT bobH; DFLOAT bobV; DFLOAT swayH; DFLOAT swayV; DFLOAT pace; DBOOL bRunning; DFLOAT moveDist; CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; HLOCALOBJ hPlayerObj = pClientDE->GetClientObject(); if (!hPlayerObj) return; // Calculate velocities DVector vMyPos; pClientDE->GetObjectPos(hPlayerObj, &vMyPos); // Calculate Y velocity for camera dampening DFLOAT fVelY = (vMyPos.y - m_vMyLastPos.y) / (pClientDE->GetFrameTime() * 100.0f); CLIPLOWHIGH(fVelY, -20, 20); VEC_COPY(m_vMyLastPos, vMyPos); bRunning = (cdata.byFlags & CDATA_RUNLOCK || pClientDE->IsCommandOn(COMMAND_RUN)); moveDist = (m_fVelMagnitude) * pClientDE->GetFrameTime(); // Running if (bRunning) { pace = PIx2 * 0.5f; bobH = BOBH_WALKING / 500.0f; bobV = BOBV_WALKING / 500.0f; swayH = SWAYH_WALKING / 10000.0f; swayV = SWAYV_WALKING / 10000.0f; } else { pace = PIx2 * 0.25f; bobH = BOBH_WALKING / 500.0f; bobV = BOBV_WALKING / 500.0f; swayH = SWAYH_WALKING / 5000.0f; swayV = SWAYV_WALKING / 5000.0f; } m_fBobPhase += (pClientDE->GetFrameTime() * pace); if (m_fBobPhase > PIx2) m_fBobPhase -= PIx2; m_fSwayPhase += (pClientDE->GetFrameTime() * pace) / 2; if (m_fSwayPhase > PIx2) m_fSwayPhase -= PIx2; // decay the amplitude m_fBobAmp = m_fBobAmp - pClientDE->GetFrameTime() * 150; if (m_fBobAmp < 0) m_fBobAmp = 0; if (m_fBobAmp < 30) { m_fBobAmp += moveDist; if (m_fBobAmp > 30) m_fBobAmp = 30; } // Head bobbing m_fBobHeight = bobV * m_fBobAmp * (float)sin(m_fBobPhase * 2); m_fBobWidth = bobH * m_fBobAmp * (float)sin(m_fBobPhase * 1 - (PI/4)); m_fBobCant = m_fBobWidth / 200.0f; // Weapon swaying m_fSwayHeight = -swayV * m_fBobAmp * (float)sin(m_fSwayPhase * 4) / 3; m_fSwayWidth = swayH * m_fBobAmp * (float)sin(m_fSwayPhase * 2 - (PI/3)) / 3; // Adjust camera velocity #define kViewDamping 0.43f #define kViewStiffnessA 0.625f // return force when above goal y #define kViewStiffnessB 0.112f // return force when below goal y DFLOAT fLast = m_fViewYVel; m_fViewYVel = INTERPOLATE(m_fViewYVel, fVelY, kViewDamping); DFLOAT dz = m_fEyeLevel - m_fViewY; if ( dz < 0 ) m_fViewYVel += dz * kViewStiffnessA; else m_fViewYVel += dz * kViewStiffnessB; if (fabs(m_fViewYVel) < 0.1f) m_fViewYVel = 0; m_fViewY += m_fViewYVel; #define kWeapDamping 0.312f #define kWeapStiffnessA 0.5f // return force when above goal y #define kWeapStiffnessB 0.047f // return force when below goal y m_fWeaponYVel = INTERPOLATE(m_fWeaponYVel, -(fVelY/80.0f), kWeapDamping); dz = -m_fWeaponY; if ( dz < 0 ) m_fWeaponYVel += dz * kWeapStiffnessA; else m_fWeaponYVel += dz * kWeapStiffnessB; m_fWeaponY += m_fWeaponYVel; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateHeadCant() // // PURPOSE: Update head tilt when strafing // // ----------------------------------------------------------------------- // void CBloodClientShell::UpdateHeadCant() { CClientDE* pClientDE = GetClientDE(); // If we are strafing, cant our head as we move.. // Strafe.. Check for strafe modifier first if ((pClientDE->IsCommandOn(COMMAND_STRAFE) && pClientDE->IsCommandOn(COMMAND_LEFT)) || pClientDE->IsCommandOn(COMMAND_STRAFELEFT)) { m_fCamCant -= m_fCantIncrement; if(m_fCamCant < -m_fCantMaxDist) m_fCamCant = -m_fCantMaxDist; } else if ((pClientDE->IsCommandOn(COMMAND_STRAFE) && pClientDE->IsCommandOn(COMMAND_RIGHT)) || pClientDE->IsCommandOn(COMMAND_STRAFERIGHT)) { m_fCamCant += m_fCantIncrement; if(m_fCamCant > m_fCantMaxDist) m_fCamCant = m_fCantMaxDist; } else { // We are not canting so move us toward zero... if(m_fCamCant != 0.0f) { if(m_fCamCant < 0.0f) { m_fCamCant += m_fCantIncrement; } else { m_fCamCant -= m_fCantIncrement; } if(fabs(m_fCamCant) < m_fCantIncrement) m_fCamCant = 0.0f; } } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdatePlayerCamera() // // PURPOSE: Update the player camera // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::UpdatePlayerCamera() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !m_hCamera || !m_pMoveMgr) return DFALSE; // Make sure our player camera is attached... m_playerCamera.AttachToObject(m_pMoveMgr->GetObject()); // Update our camera position based on the player camera... m_playerCamera.CameraUpdate(pClientDE->GetFrameTime()); return DTRUE; } void CBloodClientShell::GetCameraRotation(DRotation *pRot) { GetClientDE()->SetupEuler(pRot, m_fPitch, m_fYaw, m_fCamCant); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SetCameraStuff // // PURPOSE: Sets the camera field of view, rect & zoom mode. // // --------------------------------------------------------------------------- // void CBloodClientShell::SetCameraStuff(HLOCALOBJ hPlayerObj, HLOCALOBJ hCamera) { float oldFovX; float zoomSpeed; float fFOVx, fFOVy; int nLeft, nTop, nBottom, nRight; CClientDE* pClientDE = GetClientDE(); pClientDE->GetSurfaceDims (pClientDE->GetScreenSurface(), &m_dwScreenWidth, &m_dwScreenHeight); cdata.byFlags |= CDATA_CANMOVE; if (m_hSeeingEyeObj) { nLeft = 0; nTop = 0; nRight = m_dwScreenWidth - 1; nBottom = m_dwScreenHeight - 1; fFOVx = DEG2RAD(m_DefFovX + 45); fFOVy = fFOVx * m_fovYScale; cdata.byFlags &= ~CDATA_CANMOVE; } else if (m_hOrbObj) { nLeft = 0; nTop = 0; nRight = m_dwScreenWidth - 1; nBottom = m_dwScreenHeight - 1; fFOVx = DEG2RAD(m_DefFovX + 45); fFOVy = fFOVx * m_fovYScale; cdata.byFlags &= ~CDATA_CANMOVE; } else if (m_pExternalCamera) { if (m_pExternalCamera->GetType() == CAMTYPE_LETTERBOX) { nLeft = 0; nTop = m_dwScreenHeight / 6; nRight = m_dwScreenWidth - 1; nBottom = m_dwScreenHeight - nTop - 1; fFOVx = DEG2RAD(m_DefFovX); fFOVy = fFOVx * 0.55f; } else { m_fovY = m_fovX * m_fovYScale; nLeft = 0; nTop = 0; nRight = m_dwScreenWidth - 1; nBottom = m_dwScreenHeight - 1; fFOVx = m_fovX; fFOVy = m_fovY; } if (!m_pExternalCamera->GetPlayerMovement()) cdata.byFlags &= ~CDATA_CANMOVE; } else { zoomSpeed = 8 * pClientDE->GetFrameTime(); // pClientDE->GetSurfaceDims(pClientDE->GetScreenSurface(), &Width, &Height); // pClientDE->GetCameraFOV(m_hCamera, &fovX, &fovY); oldFovX = m_fovX; if (!m_fovX) { m_fovX = DEG2RAD(m_DefFovX); } // Need to zoom camera if (m_bZoomView && m_fovX > DEG2RAD(FOV_ZOOMED)) { m_fovX -= zoomSpeed; if (m_fovX < DEG2RAD(FOV_ZOOMED)) { m_fovX = DEG2RAD(FOV_ZOOMED); } m_fovY = m_fovX * m_fovYScale; } else if (!m_bZoomView && m_fovX < DEG2RAD(m_DefFovX)) { m_fovX += zoomSpeed; if (m_fovX > DEG2RAD(m_DefFovX)) m_fovX = DEG2RAD(m_DefFovX); m_fovY = m_fovX * m_fovYScale; } else if (!m_bZoomView && m_fovX > DEG2RAD(m_DefFovX)) { m_fovX -= zoomSpeed; if (m_fovX < DEG2RAD(m_DefFovX)) m_fovX = DEG2RAD(m_DefFovX); m_fovY = m_fovX * m_fovYScale; } nLeft = 0; nTop = 0; nRight = m_dwScreenWidth - 1; nBottom = m_dwScreenHeight - 1; fFOVx = m_fovX; fFOVy = m_fovY; } pClientDE->SetCameraRect(m_hCamera, DFALSE, nLeft, nTop, nRight, nBottom); pClientDE->SetCameraFOV(m_hCamera, fFOVx, fFOVy); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnCommandOn() // // PURPOSE: Called upon command activation. // // --------------------------------------------------------------------------- // void CBloodClientShell::OnCommandOn(int command) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; switch(command) { // Auto Run case COMMAND_RUNLOCK: if (!m_MessageMgr.GetEditingState()) { HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_AUTORUN); if(szErrorStr) { _mbscpy((unsigned char*)msgbuf, (const unsigned char*)pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); } // Toggle runlock flag if (cdata.byFlags & CDATA_RUNLOCK) { cdata.byFlags &= ~CDATA_RUNLOCK; szErrorStr = pClientDE->FormatString(IDS_GENERAL_OFF); if(szErrorStr) { _mbscat((unsigned char*)msgbuf, (const unsigned char*)pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); } pClientDE->RunConsoleString("+RunLock 0"); } else { cdata.byFlags |= CDATA_RUNLOCK; szErrorStr = pClientDE->FormatString(IDS_GENERAL_ON); if(szErrorStr) { _mbscat((unsigned char*)msgbuf, (const unsigned char*)pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); } pClientDE->RunConsoleString("+RunLock 1"); } CSPrint(msgbuf); } break; // Mouse aiming toggle /* case COMMAND_MOUSEAIMTOGGLE: if (!m_MessageMgr.GetEditingState()) { _mbscpy(msgbuf, "MOUSE AIMING "); if (cdata.byFlags & CDATA_MOUSEAIMING) { cdata.byFlags &= ~CDATA_MOUSEAIMING; _mbscat((unsigned char*)msgbuf, (const unsigned char*)"OFF"); m_bZeroXAngle = DTRUE; pClientDE->RunConsoleString("+MouseLook 0"); } else { cdata.byFlags |= CDATA_MOUSEAIMING; _mbscat((unsigned char*)msgbuf, (const unsigned char*)"ON"); pClientDE->RunConsoleString("+MouseLook 1"); } CSPrint(msgbuf); } break; */ case COMMAND_LOOKUP: if (!m_MessageMgr.GetEditingState()) { m_bZeroXAngle = DFALSE; } break; case COMMAND_LOOKDOWN: if (!m_MessageMgr.GetEditingState()) { m_bZeroXAngle = DFALSE; } break; case COMMAND_CROSSHAIR: if (!m_MessageMgr.GetEditingState() && !m_bZoomView) { if(m_bShiftState == DTRUE) { m_nCrosshair++; if(m_nCrosshair > 41) m_nCrosshair = 0; m_nCrosshairOriginalNum = m_nCrosshair; char str[64]; sprintf(str, "+CrosshairNum %d", m_nCrosshair); pClientDE->RunConsoleString(str); } else { m_bShowCrosshair = !m_bShowCrosshair; m_bCrosshairOriginallyOn = m_bShowCrosshair; if(m_bShowCrosshair) pClientDE->RunConsoleString("+Crosshair 1"); else pClientDE->RunConsoleString("+Crosshair 0"); } } break; case COMMAND_SCREENSHRINK: //m_NewStatusBar.StatLevelUp(); break; case COMMAND_SCREENENLARGE: //m_NewStatusBar.StatLevelDown(); break; case COMMAND_USE: if(m_bDead && GetGameState() == GS_PLAYING) { if(IsMultiplayerGame()) { m_pMoveMgr->ClearControlFlags(); if (m_pWeapon) m_pWeapon->CancelFiringState(); if (m_pLWeapon) m_pLWeapon->CancelFiringState(); if (m_pWeapon) { delete m_pWeapon; m_pWeapon = DNULL; } if (m_pLWeapon) { delete m_pLWeapon; m_pLWeapon = DNULL; } if (m_abyWeaponID[m_nCurGun]) m_pWeapon = CreateWeapon(m_abyWeaponID[m_nCurGun], DFALSE); if (m_abyLWeaponID[m_nCurGun]) m_pLWeapon = CreateWeapon(m_abyLWeaponID[m_nCurGun], DTRUE); } else { pClientDE->RunConsoleString("NumConsoleLines 0"); SetGameState(GS_MENU); PauseGame(DTRUE); SetGameState(GS_MENU); #ifdef _DEMO m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU); #else m_Menu.SetCurrentMenu(MENU_ID_LOAD_GAME, MENU_ID_LOAD_GAME); #endif } } break; } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnCommandOff() // // PURPOSE: Called upon command deactivation. // // --------------------------------------------------------------------------- // void CBloodClientShell::OnCommandOff(int command) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; if (!m_MessageMgr.GetEditingState()) { switch(command) { // Mouse aiming toggle case COMMAND_MOUSEAIMTOGGLE: { if (!m_MessageMgr.GetEditingState() && m_bLookSpring && !m_bMouseLook) m_bZeroXAngle = DTRUE; } break; case COMMAND_LOOKUP: case COMMAND_LOOKDOWN: { if (m_bLookSpring) m_bZeroXAngle = DTRUE; } break; case COMMAND_USE: { if(m_pCreature) m_pCreature->UseKeyHit(); } break; case COMMAND_MESSAGE: { if(GetGameState() == GS_PLAYING) { m_MessageMgr.SetEditingState(DTRUE); pClientDE->SetInputState(DFALSE); } } break; default: return; } } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnKeyDown() // // PURPOSE: Called upon a key down message from Windows. // // --------------------------------------------------------------------------- // void CBloodClientShell::OnKeyDown(int key, int rep) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; // This is used to ignore a keyboard message which is used while // configuring the keys on the keyboard. if (m_bIgnoreKeyboardMessage) { m_bIgnoreKeyboardMessage=DFALSE; return; } // Track shift keys. if (key == VK_SHIFT || key == VK_LSHIFT || key == VK_RSHIFT) m_bShiftState = DTRUE; // The message box will receive all keyboard input if it is up if (m_bInMessageBox) { m_messageBox.HandleKeyDown(key, rep); return; } if (m_bRollCredits && GetGameState() != GS_CREDITS) { m_Credits.HandleInput(key); } if (m_MessageMgr.GetEditingState()) { m_MessageMgr.HandleKeyDown(key, rep); } else if (GetGameState() == GS_SPLASH) { Splash_OnKeyDown(key); return; } else if (GetGameState() == GS_MOVIES) { if (key == VK_ESCAPE) { AdvanceMovies(pClientDE); } return; } else if (GetGameState() == GS_CREDITS) { if (key == VK_ESCAPE) { m_Credits.Term(); if (m_bInWorld) { SetGameState(GS_PLAYING); PauseGame(DFALSE); } else { SetGameState(GS_MENU); m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU); } } else { m_Credits.HandleInput (key); } } else if (GetGameState() == GS_WAITING) { SetGameState(GS_PLAYING); PauseGame(DFALSE); } else if (GetGameState() == GS_MENU) { // Process the keyboard commands in the menu class m_Menu.HandleKeyDown(key, rep); } else if (key == VK_ESCAPE) { if (GetGameState() == GS_MENU && m_bInWorld) { SetGameState(GS_PLAYING); PauseGame(DFALSE); if (g_bLevelChange3rdPersonCam) { pClientDE->SetInputState(DFALSE); if (!m_b3rdPerson) Set3rdPersonCamera(DTRUE); m_bDrawFragBar = DTRUE; } } else if (GetGameState() == GS_PLAYING) { pClientDE->RunConsoleString("NumConsoleLines 0"); SetGameState(GS_MENU); PauseGame(DTRUE); m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU); } } else if ((key == VK_F1) && !m_bShiftState) { m_NewStatusBar.ToggleWeapons(); } else if (key == VK_TAB) { if(IsMultiplayerGame()) { m_bDrawFragBar = !m_bDrawFragBar; if (m_bDrawFragBar) m_FragInfo.TurnOn(); else m_FragInfo.TurnOff(); } else { if (GetGameType() == GAMETYPE_SINGLE || GetGameType() == GAMETYPE_CUSTOM) { m_NewStatusBar.ToggleObjectives(); } } } else if (m_bShiftState) // Special functions for these keys.. { if (key >= VK_F1 && key <= VK_F12) // Text macros.. { int n = key - VK_F1 + 1; sprintf(msgbuf, "macro%d", n); HCONSOLEVAR hVar; if (hVar = pClientDE->GetConsoleVar (msgbuf)) { char* sVar = pClientDE->GetVarValueString(hVar); if (sVar && sVar[0] != '\0') { // Send the macro... HMESSAGEWRITE hMsg = pClientDE->StartMessage(CMSG_PLAYERMESSAGE); pClientDE->WriteToMessageString(hMsg, sVar); pClientDE->EndMessage(hMsg); } } } /* else if (key == VK_ADD || key == 0x00BB) { m_fovYScale += .01f; HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVY, m_fovYScale); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); // CSPrint("FOV Y Scale: %.2f", m_fovYScale); } else if (key == VK_SUBTRACT || key == 0x00BD) { m_fovYScale -= .01f; HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVY, m_fovYScale); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); // CSPrint("FOV Y Scale: %.2f", m_fovYScale); } else if (key == 0x00DB) { m_DefFovX -= 0.25f; HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVX, m_DefFovX); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); // CSPrint("FOV X: %.2f deg.", m_DefFovX); } else if (key == 0x00DD) { m_DefFovX += 0.25f; HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVX, m_DefFovX); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); // CSPrint("FOV X: %.2f deg.", m_DefFovX); }*/ #ifdef _DEBUG // 09/12/97 // Add option to move weapon in the game... viewing of the weapon // Move Weapon X,Y,Z if (m_pWeapon) { DVector offset = m_pWeapon->GetGunOffset(); if (key == 'B') { offset.x += 0.1f; HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_FOVY, offset.x); // CSPrint(szErrorStr); pClientDE->FreeString(szErrorStr); sprintf(msgbuf, "Gun: m_GunOffset.x %.1f", offset.x); CSPrint(msgbuf); } // Move Weapon X,Y,Z if (key == 'N') { offset.y += 0.1f; sprintf(msgbuf, "Gun: m_GunOffset.y %.1f", offset.y); CSPrint(msgbuf); } // Move Weapon X,Y,Z if (key == 'M') { offset.z += 0.1f; sprintf(msgbuf, "Gun: m_GunOffset.z %.1f", offset.z); CSPrint(msgbuf); } // Move Weapon X,Y,Z if (key == 'H') { offset.x -= 0.1f; sprintf(msgbuf, "Gun: m_GunOffset.x %.1f", offset.x); CSPrint(msgbuf); } // Move Weapon X,Y,Z if (key == 'J') { offset.y -= 0.1f; sprintf(msgbuf, "Gun: m_GunOffset.y %.1f", offset.y); CSPrint(msgbuf); } // Move Weapon X,Y,Z if (key == 'K') { offset.z -= 0.1f; sprintf(msgbuf, "Gun: m_GunOffset.z %.1f", offset.z); CSPrint(msgbuf); } if (m_pWeapon) { m_pWeapon->SetGunOffset(offset); } if (m_pLWeapon) { offset.x = -offset.x; m_pLWeapon->SetGunOffset(offset); } } #endif } else if(key == VK_F2) // Save Game { if (GetGameState() == GS_PLAYING) { #ifndef _DEMO PauseGame(DTRUE); SetGameState(GS_MENU); m_Menu.SetCurrentMenu(MENU_ID_SAVE_GAME, MENU_ID_SAVE_GAME); #endif } } else if(key == VK_F3) // Load Game { if (GetGameState() == GS_PLAYING) { #ifndef _DEMO PauseGame(DTRUE); SetGameState(GS_MENU); m_Menu.SetCurrentMenu(MENU_ID_LOAD_GAME, MENU_ID_LOAD_GAME); #endif } } else if(key == VK_F4) // Options { if (GetGameState() == GS_PLAYING) { PauseGame(DTRUE); SetGameState(GS_MENU); m_Menu.SetCurrentMenu(MENU_ID_OPTIONS, MENU_ID_OPTIONS); } } else if(key == VK_F5) // Quicksave { if (GetGameState() == GS_PLAYING && m_bInWorld && !m_bDead && !IsMultiplayerGame()) { #ifndef _DEMO MenuSaveGame(SLOT_QUICK); DoMessageBox("Quicksave...", DFALSE); #endif } } else if (key == VK_F6) // Quickload { if (GetGameState() == GS_PLAYING && !IsMultiplayerGame()) { #ifndef _DEMO if (MenuLoadGame(SLOT_QUICK)) DoMessageBox("Quickload...", DFALSE); #endif } } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::StartNewGame() // // PURPOSE: Starts a new game // // --------------------------------------------------------------------------- // DBOOL CBloodClientShell::StartNewGame(char *pszWorldName, DBYTE nStartType, DBYTE nGameType, DBYTE nLoadType, DBYTE nDifficulty) { CClientDE* pClientDE = GetClientDE(); HCONSOLEVAR hVar; // Initialize some stuff m_nCurGun = 0; m_bSpectatorMode = DFALSE; m_fEyeLevel = 0; m_bZoomView = DFALSE; m_hSeeingEyeObj = DNULL; m_hOrbObj = DNULL; m_hLastOrbObj = DNULL; if( m_hNightGogglesSound ) { g_pClientDE->KillSound( m_hNightGogglesSound ); m_hNightGogglesSound = DNULL; } if( m_hTheEyeLoopingSound ) { g_pClientDE->KillSound( m_hTheEyeLoopingSound ); m_hTheEyeLoopingSound = DNULL; } m_bNightGogglesActive = DFALSE; m_bBinocularsActive = DFALSE; hVar = pClientDE->GetConsoleVar ("CrosshairNum"); m_nCrosshair = (DBYTE)pClientDE->GetVarValueFloat(hVar); if(m_nCrosshair > 41) m_nCrosshair = 0; m_nCrosshairOriginalNum = m_nCrosshair; m_playerCamera.SetFirstPerson(); m_b3rdPerson = DFALSE; memset(&m_Request, 0, sizeof(StartGameRequest)); m_Request.m_Type = nStartType; pClientDE->StartGame(&m_Request); // Reset the voice manager... GetVoiceMgr()->Reset(); m_eMusicLevel = CMusic::MUSICLEVEL_SILENCE; // Send a message to the server to restore the autosave if (pszWorldName) _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)pszWorldName); return StartNewWorld(m_szFilename, nGameType, nLoadType, nDifficulty); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnKeyUp() // // PURPOSE: Called upon a key up message from Windows. // // --------------------------------------------------------------------------- // void CBloodClientShell::OnKeyUp(int key) { // Track shift keys. if (key == VK_SHIFT || key == VK_LSHIFT || key == VK_RSHIFT) m_bShiftState = DFALSE; m_MessageMgr.HandleKeyUp(key); if (GetGameState() == GS_MENU) { m_Menu.HandleKeyUp(key); } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnMessage() // // PURPOSE: Called when a message is received from the server. // // --------------------------------------------------------------------------- // void CBloodClientShell::OnMessage(DBYTE messageID, HMESSAGEREAD hMessage) { DBYTE tbyte; CClientDE* pClientDE = GetClientDE(); switch(messageID) { case SMSG_BOOTED: { CSPrint(IDS_BOOTED); PlaySound(MSG_SOUND_STRING); break; } case SMSG_SERVERSHUTDOWN: { CSPrint(IDS_SERVERSHUTDOWN); PlaySound(MSG_SOUND_STRING); break; } case SMSG_PINGTIMES: { while(1) { D_WORD id, ping; id = pClientDE->ReadFromMessageWord(hMessage); if(id == 0xFFFF) break; ping = pClientDE->ReadFromMessageWord(hMessage); m_FragInfo.UpdatePlayerPing(id, ping); } } break; case SMSG_PHYSICS_UPDATE: { if(m_pMoveMgr) m_pMoveMgr->OnPhysicsUpdate(hMessage); } break; case SMSG_FORCEPOS: { if(m_pMoveMgr) m_pMoveMgr->OnServerForcePos(hMessage); } break; case SMSG_PLAYERSTATSUPDATE: { DBYTE nStatsFlags = pClientDE->ReadFromMessageByte(hMessage); if( nStatsFlags & PLAYERSTATS_HEALTH ) { DDWORD nHealth = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); DDWORD nMaxHealth = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); m_NewStatusBar.SetHealth(nHealth, nMaxHealth); m_nHealth = nHealth; if (m_bDead && m_nHealth >= 0) { m_playerCamera.SetFirstPerson(); m_bDead = DFALSE; m_bDeadNoHide = DFALSE; m_bDrawFragBar = DFALSE; m_bBlind = DFALSE; m_nTrapped = 0; // Turn off wonkyvision if it was on. EndWonkyVision(); } } if( nStatsFlags & PLAYERSTATS_AMMO ) { DDWORD dwAmmo = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); m_NewStatusBar.SetAmmo(dwAmmo); m_dwAmmo = dwAmmo; } if( nStatsFlags & PLAYERSTATS_ALTAMMO ) { DDWORD dwAltAmmo = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); m_dwAltAmmo = dwAltAmmo; if(m_pWeapon && (m_pWeapon->GetAmmoType(DTRUE) != m_pWeapon->GetAmmoType(DFALSE))) m_NewStatusBar.SetAltAmmo(dwAltAmmo); else m_NewStatusBar.SetAltAmmo(0); } if( nStatsFlags & PLAYERSTATS_ARMOR ) { DDWORD nArmor = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); DDWORD nMaxArmor = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); m_NewStatusBar.SetArmor(nArmor, nMaxArmor); } if( nStatsFlags & PLAYERSTATS_FOCUS ) { DDWORD nAmmo = pClientDE->ReadFromMessageWord(hMessage); } if( nStatsFlags & PLAYERSTATS_TOOKDAMAGE ) { DFLOAT fDamage = (DFLOAT)pClientDE->ReadFromMessageByte(hMessage); DBYTE nDamageType = pClientDE->ReadFromMessageByte(hMessage); if (nDamageType != DAMAGE_TYPE_FREEFALL) { // Flash the screen up to 1 seconds depending on damage DFLOAT fTime = (fDamage/200.0f); // Ramp up = 0.2f // Ramp down = 0.2f DVector vFlashColor; DFLOAT fRed = fDamage / 200.0f; // minimum flash should be 0.2 if (m_vFlashColor.x < 0.2f && fRed < 0.2f) fRed = 0.2f; VEC_SET(vFlashColor, fRed, 0.0f, 0.0f); FlashScreen(&vFlashColor, fTime, 0.1f); } } if( nStatsFlags & PLAYERSTATS_AIRLEVEL ) { DFLOAT fPercent = pClientDE->ReadFromMessageFloat(hMessage); if((fPercent <= 0.0f) || (fPercent >= 1.0f)) m_NewStatusBar.TurnOffPowerBar(); else m_NewStatusBar.SetPowerBarLevel(BARTAB_AIR, fPercent); } } break; case SMSG_THROWDISTANCE: { DFLOAT fPercent = pClientDE->ReadFromMessageFloat(hMessage); if((fPercent <= 0.0f) || (fPercent >= 1.0f)) m_NewStatusBar.TurnOffPowerBar(); else m_NewStatusBar.SetPowerBarLevel(BARTAB_THROW, fPercent); } break; case SMSG_BOSSHEALTH: { DFLOAT fPercent = pClientDE->ReadFromMessageFloat(hMessage); if((fPercent <= 0.0f) || (fPercent >= 1.0f)) m_NewStatusBar.TurnOffPowerBar(); else m_NewStatusBar.SetPowerBarLevel(BARTAB_BOSS, fPercent); } break; case SMSG_HEALTH: { DDWORD nHealth = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); DDWORD nMaxHealth = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); m_NewStatusBar.SetHealth(nHealth, nMaxHealth); m_nHealth = nHealth; if (m_bDead && m_nHealth >= 0) { m_playerCamera.Reset(); m_bDead = DFALSE; m_bDrawFragBar = DFALSE; m_bBlind = DFALSE; m_nTrapped = 0; } } break; case SMSG_ARMOR: { DDWORD nArmor = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); DDWORD nMaxArmor = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); m_NewStatusBar.SetArmor(nArmor, nMaxArmor); break; } case SMSG_AMMO: { DDWORD nAmmo = (DDWORD)pClientDE->ReadFromMessageWord(hMessage); m_NewStatusBar.SetAmmo(nAmmo); break; } case SMSG_FOCUS: { DDWORD nAmmo = pClientDE->ReadFromMessageWord(hMessage); break; } case SMSG_EYELEVEL: m_fEyeLevel = pClientDE->ReadFromMessageFloat(hMessage); break; #ifdef _DEBUG case STC_BPRINT: #endif case SMSG_CONSOLEMESSAGE: { CSPrint2(pClientDE->ReadFromMessageString(hMessage)); break; } case SMSG_CONSOLEMESSAGE_ALL: { CSPrint2(pClientDE->ReadFromMessageString(hMessage)); PlaySound(MSG_SOUND_STRING); break; } case SMSG_FIREDWEAPON: { tbyte = pClientDE->ReadFromMessageByte(hMessage); if (m_pWeapon && !m_pExternalCamera) { // m_pWeapon->Fire(tbyte); if (m_pWeapon->IsCumulativeKick()) { m_fViewKick += m_pWeapon->GetViewKick(); if (m_fViewKick > 45.0f) m_fViewKick = 44.5f; m_fKickTime = __max(pClientDE->GetFrameTime() * 5, 0.3f); } else if (m_fViewKick < m_pWeapon->GetViewKick()) { m_fViewKick = m_pWeapon->GetViewKick(); m_fKickTime = 0.001f; } } // Also fire the left hand weapon if we've got one if (m_pLWeapon && !m_pExternalCamera) { // m_pLWeapon->Fire(tbyte); if (m_pLWeapon->IsCumulativeKick()) { m_fViewKick += m_pLWeapon->GetViewKick(); if (m_fViewKick > 45.0f) m_fViewKick = 44.5f; m_fKickTime = __max(pClientDE->GetFrameTime() * 5, 0.3f); } else if (m_fViewKick < m_pLWeapon->GetViewKick()) { m_fViewKick = m_pLWeapon->GetViewKick(); m_fKickTime = 0.001f; } } } break; case SMSG_TOOKDAMAGE: { DFLOAT fDamage = (DFLOAT)pClientDE->ReadFromMessageByte(hMessage); DBYTE nDamageType = pClientDE->ReadFromMessageByte(hMessage); if (nDamageType != DAMAGE_TYPE_FREEFALL) { // Flash the screen up to 1 seconds depending on damage DFLOAT fTime = (fDamage/200.0f); // Ramp up = 0.2f // Ramp down = 0.2f DVector vFlashColor; DFLOAT fRed = fDamage / 200.0f; // minimum flash should be 0.2 if (m_vFlashColor.x < 0.2f && fRed < 0.2f) fRed = 0.2f; VEC_SET(vFlashColor, fRed, 0.0f, 0.0f); FlashScreen(&vFlashColor, fTime, 0.1f); } } break; case SMSG_SPECTATORMODE: m_bSpectatorMode = pClientDE->ReadFromMessageByte(hMessage); /* if (m_bSpectatorMode) { DVector vLS; VEC_SET(vLS, -.5f, -.5f, -.5f); // pClientDE->SetGlobalLightScale(&vLS); pClientDE->OffsetGlobalLightScale(&vLS); } else { DVector vLS; VEC_SET(vLS, 1.0f, 1.0f, 1.0f); // pClientDE->SetGlobalLightScale(&vLS); pClientDE->OffsetGlobalLightScale(&vLS); } */ break; case SMSG_NEWWEAPON: { HLOCALOBJ hWeapObj = DNULL; DBYTE bySlot = pClientDE->ReadFromMessageByte(hMessage); DBYTE byWeaponID = pClientDE->ReadFromMessageByte(hMessage); DBOOL bLeftHand = (DBOOL)pClientDE->ReadFromMessageByte(hMessage); /* hWeapObj = pClientDE->ReadFromMessageObject(hMessage); wd.m_szWeaponName = pClientDE->ReadFromMessageString(hMessage); wd.m_szFlashSprite = pClientDE->ReadFromMessageString(hMessage); wd.m_szAltFlashSprite = pClientDE->ReadFromMessageString(hMessage); wd.m_fFlashDuration = pClientDE->ReadFromMessageFloat(hMessage); wd.m_fFlashScale = pClientDE->ReadFromMessageFloat(hMessage); pClientDE->ReadFromMessageVector(hMessage, &wd.m_GunOffset); pClientDE->ReadFromMessageVector(hMessage, &wd.m_MuzzleOffset); pClientDE->ReadFromMessageVector(hMessage, &wd.m_FlashPos); wd.m_EjectInterval = pClientDE->ReadFromMessageFloat(hMessage); wd.m_fViewKick = pClientDE->ReadFromMessageFloat(hMessage); wd.m_bCumulativeKick = (DBOOL)pClientDE->ReadFromMessageByte(hMessage); wd.m_bLeftHand = (DBOOL)pClientDE->ReadFromMessageByte(hMessage); HSTRING weap = pClientDE->ReadFromMessageHString(hMessage); HSTRING weapH = pClientDE->ReadFromMessageHString(hMessage); */ WeaponData *wd = &g_WeaponDefaults[byWeaponID-1]; HSTRING weap = DNULL, weapH = DNULL; if(wd->m_szStatusIcon) weap = pClientDE->CreateString(wd->m_szStatusIcon); if(wd->m_szStatusIconH) weapH = pClientDE->CreateString(wd->m_szStatusIconH); if(bySlot < 10) { m_NewStatusBar.UpdateWeap(weap, weapH, bySlot); m_NewStatusBar.UpdateCurrentWeap(m_nCurGun); } if (weap) pClientDE->FreeString(weap); if (weapH) pClientDE->FreeString(weapH); // New gun in the current slot? Get rid of what is there now.. // See if we already have a weapon in this slot if (!bLeftHand) { if (m_nCurGun == bySlot) { if (m_pWeapon) delete m_pWeapon; m_pWeapon = CreateWeapon(byWeaponID, DFALSE); } m_abyWeaponID[bySlot] = byWeaponID; } else // bLeftHand == TRUE { if (m_nCurGun == bySlot) { if (m_pLWeapon) delete m_pLWeapon; m_pLWeapon = CreateWeapon(byWeaponID, DTRUE); } m_abyLWeaponID[bySlot] = byWeaponID; } } break; case SMSG_DELETESPECIFICWEAPON: case SMSG_DELETEWEAPON: { DBYTE slot = pClientDE->ReadFromMessageByte(hMessage); // First see if we have a left handed model, and it's the current gun.. if (m_abyLWeaponID[slot] && slot == m_nCurGun) { if (m_pLWeapon) { m_pLWeapon->Hide(); m_pLWeapon->Term(); delete m_pLWeapon; m_pLWeapon = NULL; } m_abyLWeaponID[slot] = WEAP_NONE; } // Or else check for a right handed model else if (m_abyWeaponID[slot] && slot == m_nCurGun) { if(slot < 10) { m_NewStatusBar.UpdateWeap(0, 0, slot); } if (m_pWeapon) { m_pWeapon->Hide(); m_pWeapon->Term(); delete m_pWeapon; m_pWeapon = NULL; } m_abyWeaponID[slot] = WEAP_NONE; } } break; case SMSG_CHANGEWEAPON: { DBYTE slot = pClientDE->ReadFromMessageByte(hMessage); ChangeWeapon(slot); } break; case SMSG_ITEMCHANGED: { DBYTE nChangeFlags; DBOOL bShow; char *pCurName; nChangeFlags = pClientDE->ReadFromMessageByte(hMessage); bShow = ( nChangeFlags & ITEMF_SHOWITEMS ) ? DTRUE : DFALSE; if ( nChangeFlags & ITEMF_CURRENTITEM ) { if( m_hCurrentItemName ) { pClientDE->FreeString( m_hCurrentItemName ); m_hCurrentItemName = DNULL; } if( m_hCurrentItemIcon ) { pClientDE->FreeString( m_hCurrentItemIcon ); m_hCurrentItemIcon = DNULL; } if( m_hCurrentItemIconH ) { pClientDE->FreeString( m_hCurrentItemIconH ); m_hCurrentItemIconH = DNULL; } pCurName = pClientDE->ReadFromMessageString(hMessage); if( pCurName[0] ) { m_hCurrentItemName = pClientDE->CreateString( pCurName ); m_hCurrentItemIcon = pClientDE->ReadFromMessageHString(hMessage); m_hCurrentItemIconH = pClientDE->ReadFromMessageHString(hMessage); } } if ( nChangeFlags & ITEMF_PREVITEM ) { if( m_hPrevItemIcon ) pClientDE->FreeString( m_hPrevItemIcon ); m_hPrevItemIcon = pClientDE->ReadFromMessageHString(hMessage); } if ( nChangeFlags & ITEMF_NEXTITEM ) { if( m_hNextItemIcon ) pClientDE->FreeString( m_hNextItemIcon ); m_hNextItemIcon = pClientDE->ReadFromMessageHString(hMessage); } if ( nChangeFlags & ITEMF_CURRENTITEMCHARGE ) { m_nCurrentItemCharge = pClientDE->ReadFromMessageByte(hMessage); } if ( nChangeFlags & ITEMF_PREVITEMCHARGE ) { m_nPrevItemCharge = pClientDE->ReadFromMessageByte(hMessage); } if ( nChangeFlags & ITEMF_NEXTITEMCHARGE ) { m_nNextItemCharge = pClientDE->ReadFromMessageByte(hMessage); } m_NewStatusBar.UpdateInv( bShow, m_hCurrentItemName, m_hCurrentItemIcon, m_hCurrentItemIconH, m_nCurrentItemCharge, m_hPrevItemIcon, m_nPrevItemCharge, m_hNextItemIcon, m_nNextItemCharge); } break; case SMSG_CONVERSATION: { GetVoiceMgr()->StopAll(); HSTRING file = pClientDE->ReadFromMessageHString(hMessage); HSTRING text = pClientDE->ReadFromMessageHString(hMessage); DBYTE chosen = pClientDE->ReadFromMessageByte(hMessage); m_CommLink.StartCommunication(chosen, pClientDE->GetStringData(file), pClientDE->GetStringData(text)); pClientDE->FreeString( file ); pClientDE->FreeString( text ); } break; case SMSG_OBJECTIVES: { if ((m_nGameType == GAMETYPE_SINGLE) || (m_nGameType == GAMETYPE_CUSTOM)) { DDWORD resNum = pClientDE->ReadFromMessageDWord(hMessage); if (m_hstrObjectivesText) { pClientDE->FreeString(m_hstrObjectivesText); m_hstrObjectivesText = DNULL; } if (m_hstrObjectivesTitle) { pClientDE->FreeString(m_hstrObjectivesTitle); m_hstrObjectivesTitle = DNULL; } if(resNum) { m_hstrObjectivesTitle = pClientDE->FormatString(IDS_OBJECTIVE_TITLE_1_1 + resNum - 1); m_hstrObjectivesText = pClientDE->FormatString(IDS_OBJECTIVE_1_1 + resNum - 1); } else { m_hstrObjectivesTitle = pClientDE->ReadFromMessageHString(hMessage); m_hstrObjectivesText = pClientDE->ReadFromMessageHString(hMessage); } m_NewStatusBar.UpdateObjectives(pClientDE->GetStringData(m_hstrObjectivesTitle), pClientDE->GetStringData(m_hstrObjectivesText)); } } break; case SMSG_ZOOMVIEW: { m_bZoomView = pClientDE->ReadFromMessageByte(hMessage); DBYTE nType = pClientDE->ReadFromMessageByte(hMessage); if(m_bZoomView) { // m_fOriginalKeyTurnRate = GetKeyboardTurnRate(); // SetKeyboardTurnRate(m_fOriginalKeyTurnRate / 4.0f); // m_fOriginalMouseSensitivity = GetMouseSensitivity(); // SetMouseSensitivity(m_fOriginalMouseSensitivity / 4.0f, DTRUE); m_bCrosshairOriginallyOn = m_bShowCrosshair; m_nCrosshairOriginalNum = m_nCrosshair; if(nType) { m_bShowCrosshair = DTRUE; m_nCrosshair = nType; } } else { // SetKeyboardTurnRate(m_fOriginalKeyTurnRate); // SetMouseSensitivity(m_fOriginalMouseSensitivity); m_bShowCrosshair = m_bCrosshairOriginallyOn; m_nCrosshair = m_nCrosshairOriginalNum; } } break; case SMSG_ADDPLAYER: { if (IsMultiplayerGame()) { HSTRING hstrName = pClientDE->ReadFromMessageHString (hMessage); DDWORD nID = pClientDE->ReadFromMessageDWord (hMessage); DBYTE byCharacter = pClientDE->ReadFromMessageByte (hMessage); int nFrags = (int) pClientDE->ReadFromMessageFloat (hMessage); DBYTE byTeamID = pClientDE->ReadFromMessageByte (hMessage); if (m_FragInfo.GetClientInfo(nID)) { pClientDE->FreeString(hstrName); return; } m_FragInfo.AddClient (hstrName, nID, nFrags, byCharacter); DDWORD dwLocalID = 0; pClientDE->GetLocalClientID(&dwLocalID); if (dwLocalID == nID) { m_NewStatusBar.SetTeamID((int)byTeamID); } m_TeamMgr.AddPlayer(byTeamID, nID); m_TeamMgr.AddPlayerFrags(byTeamID, nID, nFrags); CTeam* pTeam = m_TeamMgr.GetTeam(byTeamID); if (IsMultiplayerTeamBasedGame() && pTeam) { HSTRING hStr = pClientDE->FormatString(IDS_ADDPLAYERTEAM, pClientDE->GetStringData(hstrName), pTeam->GetName()); CSPrint(pClientDE->GetStringData(hStr)); pClientDE->FreeString (hStr); } else { HSTRING hStr = pClientDE->FormatString (IDS_ADDPLAYER, pClientDE->GetStringData (hstrName)); CSPrint (pClientDE->GetStringData (hStr)); pClientDE->FreeString (hStr); } pClientDE->FreeString(hstrName); } } break; case SMSG_REMOVEPLAYER: { if (IsMultiplayerGame()) { DDWORD nID = pClientDE->ReadFromMessageDWord(hMessage); char* sName = m_FragInfo.GetPlayerName(nID); if (sName && strlen(sName) > 0) { DDWORD dwLocalID = 0xFFFFFFFF; pClientDE->GetLocalClientID(&dwLocalID); if (dwLocalID != nID) { HSTRING hStr = pClientDE->FormatString(IDS_REMOVEPLAYER, sName); CSPrint (pClientDE->GetStringData(hStr)); pClientDE->FreeString(hStr); } } m_FragInfo.RemoveClient (nID); m_TeamMgr.RemovePlayer(nID); if (g_bLevelChange3rdPersonCam) { g_bLevelChangeNoUpdate = DTRUE; } } } break; case SMSG_PLAYER_FRAGGED: { if (IsMultiplayerGame()) { DDWORD nLocalID = 0; _mbscpy((unsigned char*)msgbuf, (const unsigned char*)""); pClientDE->GetLocalClientID (&nLocalID); DDWORD nVictim = pClientDE->ReadFromMessageDWord (hMessage); DDWORD nKiller = pClientDE->ReadFromMessageDWord (hMessage); D_WORD wIndex = pClientDE->ReadFromMessageWord (hMessage); AssignFrags(nLocalID, nVictim, nKiller); VoiceEntry *pve = DNULL; char *pKiller = m_FragInfo.GetPlayerName(nKiller); char *pVictim = m_FragInfo.GetPlayerName(nVictim); if (pKiller && pVictim) { DBYTE byFlags = 0; switch(m_FragInfo.GetPlayerCharacter(nKiller)) { case CHARACTER_GABREILLA: case CHARACTER_OPHELIA: byFlags |= VOICEFLAG_FEMALE_ATTACKER; break; default: byFlags |= VOICEFLAG_MALE_ATTACKER; break; } switch(m_FragInfo.GetPlayerCharacter(nVictim)) { case CHARACTER_GABREILLA: case CHARACTER_OPHELIA: byFlags |= VOICEFLAG_FEMALE_VICTIM; break; default: byFlags |= VOICEFLAG_MALE_VICTIM; break; } // Display a message if (nVictim == nKiller) // Suicide { pve = GetVoiceEntry(g_aVoiceSuicide, NUM_VOICE_SUICIDE, wIndex, byFlags); // pve = &g_aVoiceSuicide[wIndex % NUM_VOICE_SUICIDE]; if (pve) sprintf(msgbuf, pve->m_szText, pKiller); } else // Frag { pve = GetVoiceEntry(g_aVoiceKill, NUM_VOICE_KILL, wIndex, byFlags); // pve = &g_aVoiceKill[wIndex % NUM_VOICE_KILL]; if (pve) sprintf(msgbuf, pve->m_szText, pKiller, pVictim); } if (nKiller == nLocalID) { char szSoundFile[MAX_CS_FILENAME_LEN]; _mbscpy((unsigned char*)szSoundFile, (const unsigned char*)"Sounds\\Voice\\"); _mbscat((unsigned char*)szSoundFile, (const unsigned char*)pve->m_szFile); m_CommLink.StartCommunication(4, szSoundFile, msgbuf); } else CSPrint(msgbuf); } } } break; case SMSG_GRABBEDTHEFLAG: { DisplayStatusBarFlagIcon(DTRUE); PlaySound("sounds_multipatch\\CtfFlagGrab.wav"); CSPrint(IDS_CTF_GRABBED); break; } case SMSG_RETURNEDTHEFLAG: { PlaySound("sounds_multipatch\\CtfFlagGrab.wav"); CSPrint(IDS_CTF_RETURNED); break; } case SMSG_DROPPEDTHEFLAG: { DisplayStatusBarFlagIcon(DFALSE); break; } case SMSG_NEEDYOURFLAG: { static DFLOAT fLastTime = 0; DFLOAT fCurTime = g_pClientDE->GetTime(); if ((fLastTime + 20) < fCurTime) { CSPrint(IDS_CTF_RETURNYOURFLAG); fLastTime = fCurTime; } break; } case SMSG_CAPTUREDTHEFLAG: { DisplayStatusBarFlagIcon(DFALSE); DDWORD dwLocalID = 0; pClientDE->GetLocalClientID(&dwLocalID); DDWORD dwFlagger = pClientDE->ReadFromMessageDWord(hMessage); int nFrags = (int)pClientDE->ReadFromMessageDWord(hMessage); m_FragInfo.AddFrags(dwLocalID, dwFlagger, nFrags); m_TeamMgr.AddPlayerFrags(dwFlagger, nFrags); char* sFlagger = m_FragInfo.GetPlayerName(dwFlagger); if (sFlagger) { char sMsg[256]; CTeam* pTeam = m_TeamMgr.GetTeamFromPlayerID(dwFlagger); if (pTeam) sprintf(sMsg, pClientDE->GetStringData(m_hCtfCapturedString1), sFlagger, pTeam->GetName()); else sprintf(sMsg, pClientDE->GetStringData(m_hCtfCapturedString2), sFlagger); if (dwLocalID == dwFlagger) { CSPrint(IDS_CTF_CAPTURED_3); } else { CSPrint(sMsg); } } } break; #ifdef _ADDON case SMSG_SOCCERGOAL: { DDWORD dwLocalID, dwScorer; int nFrags; DBYTE nTeamID; char *sScorer; char sMsg[256]; CTeam *pTeam; char *pszSound; DisplayStatusBarFlagIcon(DFALSE); dwLocalID = 0; pClientDE->GetLocalClientID(&dwLocalID); dwScorer = pClientDE->ReadFromMessageDWord(hMessage); nFrags = (int)pClientDE->ReadFromMessageDWord(hMessage); nTeamID = pClientDE->ReadFromMessageByte( hMessage ); m_FragInfo.AddFrags( dwLocalID, dwScorer, nFrags ); m_TeamMgr.AddPlayerFrags( dwScorer, nFrags ); pszSound = DNULL; if( nFrags >= 0 ) { pszSound = s_szCheerSounds[ GetRandom( 0, NUMCHEERSOUNDS - 1 ) ]; } else { pszSound = s_szBooSounds[ GetRandom( 0, NUMBOOSOUNDS - 1 ) ]; } if( pszSound ) PlaySoundLocal( pszSound, SOUNDPRIORITY_MISC_MEDIUM ); if( dwLocalID == dwScorer ) { // Made a good goal if( nFrags >= 0 ) CSPrint(IDS_SOCCER_GOAL_3); // Wrong goal! else CSPrint(IDS_SOCCER_GOAL_4); } else { sScorer = m_FragInfo.GetPlayerName( dwScorer ); if( sScorer ) { pTeam = m_TeamMgr.GetTeam(( nTeamID == TEAM_1 ) ? TEAM_2 : TEAM_1 ); if( pTeam ) sprintf( sMsg, pClientDE->GetStringData( m_hSoccerGoalString1 ), sScorer, pTeam->GetName( )); else sprintf( sMsg, pClientDE->GetStringData( m_hSoccerGoalString2 ), sScorer ); CSPrint(sMsg); } } } break; case SMSG_TRAPPED: { m_nTrapped = (int)pClientDE->ReadFromMessageByte(hMessage); DBYTE byType = pClientDE->ReadFromMessageByte(hMessage); } break; #endif // _ADDON case SMSG_THEVOICE: { if (IsMultiplayerGame()) { TheVoice eVoice = (TheVoice)pClientDE->ReadFromMessageByte(hMessage); D_WORD wIndex = pClientDE->ReadFromMessageWord(hMessage); DBYTE byFlags = pClientDE->ReadFromMessageByte(hMessage); VoiceEntry *pve = DNULL; switch(eVoice) { case VOICE_START_BB: pve = GetVoiceEntry(g_aVoiceStartBB, NUM_VOICE_START_BB, wIndex, byFlags); break; case VOICE_START_CTF: pve = GetVoiceEntry(g_aVoiceStartCTF, NUM_VOICE_START_CTF, wIndex, byFlags); break; case VOICE_FINISHHIM: pve = GetVoiceEntryWithExtraChecks(g_aVoiceHumiliation, NUM_VOICE_HUMILIATION, wIndex, byFlags); break; } if (pve) { sprintf(msgbuf, "Sounds\\Voice\\%s", pve->m_szFile); m_CommLink.StartCommunication(4, msgbuf, pve->m_szText); } } } break; case SMSG_MP_CHANGING_LEVELS : { // we're about to change levels - we don't really care if we're not in a multiplayer game if (!IsMultiplayerGame()) return; pClientDE->SetInputState(DFALSE); if (!m_b3rdPerson) Set3rdPersonCamera(DTRUE); CSPrint(IDS_MP_CHANGINGLEVELS); PlaySound("sounds\\events\\bellding1.wav"); m_bDrawFragBar = DTRUE; g_bLevelChange3rdPersonCam = DTRUE; m_bZoomView = DFALSE; m_bShowCrosshair = m_bCrosshairOriginallyOn; m_nCrosshair = m_nCrosshairOriginalNum; m_bBlind = DFALSE; m_nTrapped = 0; // Reset the inventory tabs m_NewStatusBar.UpdateInv(0, 0, 0, 0, 0, 0, 0, 0, 0); // Handle clearing out data for movement and weapon states m_pMoveMgr->ClearControlFlags(); if (m_pWeapon) m_pWeapon->CancelFiringState(); if (m_pLWeapon) m_pLWeapon->CancelFiringState(); } break; case SMSG_EXITWORLD: { HandleExitWorld(hMessage); // Reset the inventory tabs m_NewStatusBar.UpdateInv(0, 0, 0, 0, 0, 0, 0, 0, 0); } break; /* case SMSG_CUTSCENE_START : { GetVoiceMgr()->StopAll(); m_bDrawStatusBar = DFALSE; } break; case SMSG_CUTSCENE_END : { m_bSpectatorMode = DFALSE; m_pExternalCamera = DNULL; m_bRenderCamera = DFALSE; if (m_pWeapon[m_nCurGun]) m_pWeapon[m_nCurGun]->Show(); if (m_pLWeapon[m_nCurGun]) m_pLWeapon[m_nCurGun]->Show(); // Turn on the Status bar m_bDrawStatusBar = DTRUE; m_bRenderCamera = DTRUE; } break; */ case SMSG_BURN : { DFLOAT fTheTime = pClientDE->ReadFromMessageFloat(hMessage); if (fTheTime > 0.0f) { m_bBurn = DTRUE; m_fBurnTime = pClientDE->GetTime() + fTheTime; } else { m_bBurn = DFALSE; } } break; case SMSG_BLIND: { if (m_bDead) // [blg] don't go blind if we're already dead { m_bBlind = DFALSE; return; } DFLOAT fTheTime = pClientDE->ReadFromMessageFloat(hMessage); if (fTheTime > 0.0f) { HSTRING szErrorStr = pClientDE->FormatString(IDS_GENERAL_BLIND); CSPrint(pClientDE->GetStringData(szErrorStr)); pClientDE->FreeString(szErrorStr); m_bBlind = DTRUE; m_fBlindTime = pClientDE->GetTime() + fTheTime; } else { m_bBlind = DFALSE; } } break; case SMSG_ALL_SEEING_EYE: { DBOOL bOn = (DBOOL)pClientDE->ReadFromMessageByte(hMessage); HLOCALOBJ hObj = pClientDE->ReadFromMessageObject(hMessage); // Kill any old instance of the sound... if( m_hTheEyeLoopingSound ) { pClientDE->KillSound( m_hTheEyeLoopingSound ); m_hTheEyeLoopingSound = DNULL; } if (bOn && hObj) { m_hSeeingEyeObj = hObj; pClientDE->SetObjectClientFlags(hObj, CF_NOTIFYREMOVE); m_hTheEyeLoopingSound = PlaySoundLocal("sounds\\powerups\\eyeloop1.wav", SOUNDPRIORITY_MISC_HIGH, DTRUE, DTRUE ); } else { m_hSeeingEyeObj = DNULL; } } break; case SMSG_ORBCAM: { m_hOrbObj = DNULL; } break; case SMSG_DISPLAYTEXT: { DFLOAT fTime = pClientDE->ReadFromMessageFloat(hMessage); CSPrint(pClientDE->ReadFromMessageString(hMessage)); // Need to send the Font, Height, Color, Position on the Screen x,y // // m_hFont = pClientDE->CreateFont("Arial", 6, 16, DFALSE, DFALSE, DFALSE); // m_nFontHeight = 16; // HDECOLOR hForeground = pClientDE->SetupColor1 (1.0f, 1.0f, 1.0f, DFALSE); // hSurface = pClientDE->CreateSurfaceFromString (m_hFont, hMsg, hForeground, NULL, 10, 0); // if (hSurface) // Error // { // return; // } } break; case SMSG_SCREENFADE: { DBYTE m_nFadeMode = pClientDE->ReadFromMessageByte(hMessage); if (m_nFadeMode == 1) { m_bFadeIn = DTRUE; m_bFadeOut = DFALSE; m_fFadeVal = 0.0f; } else { m_bFadeOut = DTRUE; m_bFadeIn = DFALSE; m_fFadeVal = 255.0f; } } break; /* case SMSG_STONEVIEW: { m_bStoneView = pClientDE->ReadFromMessageByte(hMessage); break; } case SMSG_AURAVIEW: { m_bAuraView = pClientDE->ReadFromMessageByte(hMessage); if (m_bAuraView) pClientDE->SetModelHook ((ModelHookFn)AuraModelHook, pClientDE); else pClientDE->SetModelHook (DNULL, DNULL); break; } */ case SMSG_FORCEROTATION: { m_fPitch = pClientDE->ReadFromMessageFloat(hMessage); m_fYaw = pClientDE->ReadFromMessageFloat(hMessage); break; } case SMSG_MUSIC: { if( m_Music.IsInitialized( )) { m_Music.HandleMusicMessage( hMessage ); m_eMusicLevel = m_Music.GetMusicLevel( ); } break; } // Returned when the server has successfully saved a game // Copy save data from the Current slot into the case SMSG_SAVEGAME_ACK: { if (GetGameState() == GS_SAVING) { // Save the current world filename for future restoration int nSlot = m_SavedGameInfo.GetReservedSlot(); if (nSlot == SLOT_QUICK) _mbscpy((unsigned char*)m_SavedGameInfo.gQuickSaveInfo.szCurrentLevel, (const unsigned char*)m_szFilename); else _mbscpy((unsigned char*)m_SavedGameInfo.gSaveSlotInfo[nSlot].szCurrentLevel, (const unsigned char*)m_szFilename); if (nSlot != SLOT_NONE) { m_SavedGameInfo.CopySlot(SLOT_CURRENT, nSlot); m_SavedGameInfo.SetSlotName(nSlot, DNULL); m_SavedGameInfo.SaveInfo(nSlot, m_nGameType, GetCharacter()); } m_SavedGameInfo.SetReservedSlot(SLOT_NONE); SetGameState(GS_PLAYING); PauseGame(DFALSE); } break; } // Successfully loaded a world, keep track of it for autosave case SMSG_LOADWORLD_ACK: { DBOOL bSuccess = (DBOOL)pClientDE->ReadFromMessageByte(hMessage); if (bSuccess) { // Set the world name if (m_hstrTitle) m_SavedGameInfo.SetSlotName(SLOT_CURRENT, pClientDE->GetStringData(m_hstrTitle)); // Save the current world filename for future restoration _mbscpy((unsigned char*)m_SavedGameInfo.gCurrentSaveInfo.szCurrentLevel, (const unsigned char*)m_szFilename); m_SavedGameInfo.SaveInfo(SLOT_CURRENT, m_nGameType, GetCharacter()); } else // Abort! Abort! { SetGameState(GS_MENU); // pClientDE->Disconnect(); } break; } case SMSG_CLIENTSAVEDATA: { LoadClientData( hMessage ); break; } case SMSG_PLAYERINIT_SINGLEPLAYER: { InitSinglePlayer(); } break; case SMSG_PLAYERINIT_MULTIPLAYER: { BYTE byGameType = pClientDE->ReadFromMessageByte(hMessage); m_nGameType = byGameType; m_bNetFriendlyFire = pClientDE->ReadFromMessageByte(hMessage); m_bNetNegTeamFrags = pClientDE->ReadFromMessageByte(hMessage); m_bNetOnlyFlagScores = pClientDE->ReadFromMessageByte(hMessage); m_bNetOnlyGoalScores = pClientDE->ReadFromMessageByte(hMessage); InitMultiPlayer(); if (m_pWeapon) m_pWeapon->CancelFiringState(); if (m_pLWeapon) m_pLWeapon->CancelFiringState(); } break; case SMSG_THIEF_ATTACH: { HOBJECT hServObj = pClientDE->ReadFromMessageObject(hMessage); HOBJECT hEnemyObj = pClientDE->ReadFromMessageObject(hMessage); if(m_pCreature && hServObj && hEnemyObj) { HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_DETACH_AI); pClientDE->WriteToMessageObject(hMessage, hServObj); pClientDE->EndMessage(hMessage); } else { m_pCreature = new CViewCreature; m_pCreature->Create(pClientDE, SMSG_THIEF_ATTACH, hServObj, hEnemyObj); HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_ATTACH_ACK); pClientDE->WriteToMessageObject(hMessage, hServObj); pClientDE->EndMessage(hMessage); } break; } case SMSG_HAND_ATTACH: { HOBJECT hServObj = pClientDE->ReadFromMessageObject(hMessage); HOBJECT hEnemyObj = pClientDE->ReadFromMessageObject(hMessage); if(m_pCreature && hServObj && hEnemyObj) { HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_DETACH_AI); pClientDE->WriteToMessageObject(hMessage, hServObj); pClientDE->EndMessage(hMessage); } else { m_pCreature = new CViewCreature; m_pCreature->Create(pClientDE, SMSG_HAND_ATTACH, hServObj, hEnemyObj); HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_ATTACH_ACK); pClientDE->WriteToMessageObject(hMessage, hServObj); pClientDE->EndMessage(hMessage); } break; } case SMSG_BONELEECH_ATTACH: { HOBJECT hServObj = pClientDE->ReadFromMessageObject(hMessage); HOBJECT hEnemyObj = pClientDE->ReadFromMessageObject(hMessage); if(m_pCreature && hServObj && hEnemyObj) { HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_DETACH_AI); pClientDE->WriteToMessageObject(hMessage, hServObj); pClientDE->EndMessage(hMessage); } else { m_pCreature = new CViewCreature; m_pCreature->Create(pClientDE, SMSG_BONELEECH_ATTACH, hServObj, hEnemyObj); HMESSAGEWRITE hMessage = pClientDE->StartMessage(CMSG_ATTACH_ACK); pClientDE->WriteToMessageObject(hMessage, hServObj); pClientDE->EndMessage(hMessage); } break; } case SMSG_DETACH_AI: { if(m_pCreature) { m_pCreature->Detach(); } break; } case SMSG_DEAD: { // Just died.. m_bDead = DTRUE; m_bBlind = DFALSE; m_nTrapped = 0; m_playerCamera.GoDeathMode(); if (IsWonkyNoMove()) m_bDeadNoHide = DTRUE; EndWonkyVision(); if(IsMultiplayerGame()) m_bDrawFragBar = DTRUE; } break; case SMSG_WONKYVISION: // Set to WonkyVision for a period of time. { DFLOAT fWonkyTime = pClientDE->ReadFromMessageFloat(hMessage); DBYTE bWonkyNoMove = pClientDE->ReadFromMessageByte(hMessage); if (m_bDead) fWonkyTime = 0; // [blg] no wonky if we're dead! if (fWonkyTime > m_fWonkyTime) { if (bWonkyNoMove) CSPrint(IDS_EDGEOFDEATH); StartWonkyVision(fWonkyTime, bWonkyNoMove); } else if (fWonkyTime == 0) { EndWonkyVision(); } break; } case SMSG_VOICEMGR: { DBOOL bEvent = (DBOOL)pClientDE->ReadFromMessageByte(hMessage); int iCharacter = (int)pClientDE->ReadFromMessageWord(hMessage); int iEvent = (int)pClientDE->ReadFromMessageWord(hMessage); if (bEvent) { GetVoiceMgr()->PlayEventSound(iCharacter, iEvent); } else { GetVoiceMgr()->PlayUniqueSound(iCharacter, iEvent); } break; } case SMSG_VOICEMGR_STOPALL: { GetVoiceMgr()->StopAll(); break; } case SMSG_INVITEMACTION: { DBYTE nType; DBOOL bActivate; nType = g_pClientDE->ReadFromMessageByte( hMessage ); bActivate = ( nType & 0x80 ); nType &= 0x7F; HandleInvAction( nType, bActivate ); break; } /* case SMSG_WEAPONHANDMODEL: { HLOCALOBJ hObj = g_pClientDE->ReadFromMessageObject(hMessage); DBOOL bLeft = g_pClientDE->ReadFromMessageByte(hMessage); DBOOL bVisible = g_pClientDE->ReadFromMessageByte(hMessage); if (!hObj) break; DDWORD dwFlags = pClientDE->GetObjectFlags(hObj); if (bVisible) { pClientDE->SetObjectFlags(hObj, dwFlags | FLAG_VISIBLE); pClientDE->SetObjectClientFlags(hObj, 0); } else { pClientDE->SetObjectFlags(hObj, dwFlags & ~FLAG_VISIBLE); pClientDE->SetObjectClientFlags(hObj, CF_NOTIFYREMOVE); } if (bLeft) m_hLWeapHandObj = (bVisible) ? NULL : hObj; else m_hWeapHandObj = (bVisible) ? NULL : hObj; break; }*/ case SMSG_DOAUTOSAVE: { MenuSaveGame(SLOT_NONE, SAVETYPE_AUTO); } break; } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::InitSinglePlayer // // PURPOSE: Initializes a single player game // // --------------------------------------------------------------------------- // void CBloodClientShell::InitSinglePlayer() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; // Init player info only on the first world... if (m_bFirstWorld) SendPlayerInitMessage(CMSG_SINGLEPLAYER_INIT); // Send autosave message HMESSAGEWRITE hWrite = pClientDE->StartMessage(CMSG_AUTOSAVE); pClientDE->EndMessage(hWrite); if(m_bPaused) SetGameState(GS_WAITING); else SetGameState(GS_PLAYING); pClientDE->SetInputState(DTRUE); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::InitMultiPlayer // // PURPOSE: Send the server the initial player info // // --------------------------------------------------------------------------- // void CBloodClientShell::InitMultiPlayer() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; // Init multiplayer info on server... SendPlayerInitMessage(CMSG_MULTIPLAYER_INIT); SetGameState(GS_PLAYING); pClientDE->SetInputState (DTRUE); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateGun() // // PURPOSE: Updates the view gun info // // --------------------------------------------------------------------------- // void CBloodClientShell::UpdateGun(DRotation *rot, DVector *pos) { CClientDE* pClientDE = GetClientDE(); // Determine whether we should be showing the weapon or not. // Hide gun if spectator mode, or health is 0. if (m_bSpectatorMode || m_bDead || !m_playerCamera.IsFirstPerson() || m_pExternalCamera || m_hSeeingEyeObj || m_hOrbObj ) { if (m_pWeapon) m_pWeapon->Hide(); if (m_pLWeapon) m_pLWeapon->Hide(); } else { if (m_pWeapon) m_pWeapon->Show(); if (m_pLWeapon) m_pLWeapon->Show(); } if (!m_bSpectatorMode) { DVector vGunMuzzlePos, vPos; if (m_pWeapon) { m_pWeapon->UpdateBob(m_fSwayHeight + m_fWeaponY, m_fSwayWidth); m_pWeapon->Update(cdata.fPitch, cdata.fYaw, pos); pClientDE->GetObjectPos(pClientDE->GetClientObject(), &vPos); VEC_COPY(vGunMuzzlePos, m_pWeapon->GetMuzzlePos()); VEC_SUB(cdata.GunMuzzlePos, vGunMuzzlePos, vPos); } if (m_pLWeapon) { m_pLWeapon->UpdateBob(m_fSwayHeight + m_fWeaponY, m_fSwayWidth); m_pLWeapon->Update(cdata.fPitch, cdata.fYaw, pos); pClientDE->GetObjectPos(pClientDE->GetClientObject(), &vPos); VEC_COPY(vGunMuzzlePos, m_pLWeapon->GetMuzzlePos()); VEC_SUB(cdata.lGunMuzzlePos, vGunMuzzlePos, vPos); } } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::ChangeWeapon() // // PURPOSE: Selects a new weapon // // --------------------------------------------------------------------------- // void CBloodClientShell::ChangeWeapon(DBYTE slot) { // Are we switching weapons? // If so, set our flags and get rid of the old one. if(slot != m_nCurGun) { m_nCurGun = slot; if (m_pWeapon) { delete m_pWeapon; m_pWeapon = DNULL; } if (m_pLWeapon) { delete m_pLWeapon; m_pLWeapon = DNULL; } if (m_abyWeaponID[m_nCurGun]) { m_pWeapon = CreateWeapon(m_abyWeaponID[m_nCurGun], DFALSE); } if (m_abyLWeaponID[m_nCurGun]) { m_pLWeapon = CreateWeapon(m_abyLWeaponID[m_nCurGun], DTRUE); } } // Update the status bar stuff to reflect the new weapon m_NewStatusBar.UpdateCurrentWeap(m_nCurGun); if(m_pWeapon && (m_pWeapon->GetAmmoType(DTRUE) != m_pWeapon->GetAmmoType(DFALSE))) m_NewStatusBar.SetAltAmmo(m_dwAltAmmo); else m_NewStatusBar.SetAltAmmo(0); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SpecialEffectNotify() // // PURPOSE: Handle creation of a special fx // // ----------------------------------------------------------------------- // void CBloodClientShell::SpecialEffectNotify(HLOCALOBJ hObj, HMESSAGEREAD hMessage) { DDWORD dwClientFlags; CClientDE* pClientDE = GetClientDE(); if(!pClientDE) return; if(hObj) pClientDE->SetObjectClientFlags(hObj, CF_NOTIFYREMOVE); DDWORD dwLocalID; pClientDE->GetLocalClientID(&dwLocalID); DBYTE nId = pClientDE->ReadFromMessageByte(hMessage); switch(nId) { case SFX_WEAPONHANDMODEL_ID: { DDWORD cID = g_pClientDE->ReadFromMessageDWord(hMessage); DBYTE byFlags = g_pClientDE->ReadFromMessageByte(hMessage); DBOOL bLeft = byFlags >> 1; DBOOL bVisible = byFlags & 0x01; if(cID != dwLocalID) break; DDWORD dwFlags = pClientDE->GetObjectFlags(hObj); if (bVisible) { pClientDE->SetObjectFlags(hObj, dwFlags | FLAG_VISIBLE); pClientDE->SetObjectClientFlags(hObj, 0); } else pClientDE->SetObjectFlags(hObj, dwFlags & ~FLAG_VISIBLE); if (bLeft) m_hLWeapHandObj = (bVisible) ? NULL : hObj; else m_hWeapHandObj = (bVisible) ? NULL : hObj; break; } case SFX_ORBCAM_ID: { DDWORD cID = g_pClientDE->ReadFromMessageDWord(hMessage); DBYTE bOn = g_pClientDE->ReadFromMessageByte(hMessage); if(cID != dwLocalID) break; if(m_hOrbObj == hObj) { if(!bOn) { m_hOrbObj = DNULL; break; } } else { if(bOn) m_hOrbObj = hObj; } break; } case SFX_DESTRUCTABLEMODEL: { DVector vDims; dwClientFlags = pClientDE->GetObjectClientFlags( hObj ); dwClientFlags |= CF_DONTSETDIMS; pClientDE->SetObjectClientFlags( hObj, dwClientFlags ); pClientDE->ReadFromMessageCompVector( hMessage, &vDims ); pClientDE->Physics( )->SetObjectDims( hObj, &vDims, 0 ); } break; default: m_sfxMgr.HandleSFXMsg(hObj, hMessage, nId); break; } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnObjectRemove() // // PURPOSE: Handle removal of a special fx // // ----------------------------------------------------------------------- // void CBloodClientShell::OnObjectRemove(HLOCALOBJ hObj) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; if (!hObj) return; if (hObj == m_hWeapHandObj) m_hWeapHandObj = DNULL; else if (hObj == m_hLWeapHandObj) m_hLWeapHandObj = DNULL; else if (hObj == m_hSeeingEyeObj) m_hSeeingEyeObj = DNULL; else if (hObj == m_hOrbObj) m_hOrbObj = DNULL; else if (m_pCreature) { if(hObj == m_pCreature->m_hEnemyObject || hObj == m_pCreature->m_hServerObject) m_pCreature->Detach(); } else m_sfxMgr.RemoveSpecialFX(hObj); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::OnModelKey // // PURPOSE: Handle weapon model keys // // --------------------------------------------------------------------------- // void CBloodClientShell::OnModelKey(HLOCALOBJ hObj, ArgList *pArgs) { if (m_pWeapon && m_pWeapon->GetWeapObj() == hObj) m_pWeapon->OnModelKey(hObj, pArgs); if (m_pLWeapon && m_pLWeapon->GetWeapObj() == hObj) m_pLWeapon->OnModelKey(hObj, pArgs); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::PauseGame() // // PURPOSE: Pauses/Unpauses the server // // ----------------------------------------------------------------------- // void CBloodClientShell::PauseGame (DBOOL bPause) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; m_bRenderCamera = !bPause; m_bPaused = bPause; if (!IsMultiplayerGame()) { HMESSAGEWRITE hWrite = pClientDE->StartMessage(CMSG_GAME_PAUSE); pClientDE->WriteToMessageByte(hWrite, (DBYTE)bPause); pClientDE->EndMessage(hWrite); } pClientDE->SetInputState(!bPause); if (bPause) pClientDE->PauseMusic(); else pClientDE->ResumeMusic(); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateScreenShake // // PURPOSE: Update the screen shaking // // --------------------------------------------------------------------------- // void CBloodClientShell::UpdateScreenShake() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !m_hCamera) return; // Decay... DFLOAT fDecayAmount = 2.0f * pClientDE->GetFrameTime(); m_vShakeMagnitude.x -= fDecayAmount; m_vShakeMagnitude.y -= fDecayAmount; m_vShakeMagnitude.z -= fDecayAmount; if (m_vShakeMagnitude.x < 0.0f) m_vShakeMagnitude.x = 0.0f; if (m_vShakeMagnitude.y < 0.0f) m_vShakeMagnitude.y = 0.0f; if (m_vShakeMagnitude.z < 0.0f) m_vShakeMagnitude.z = 0.0f; if (m_vShakeMagnitude.x <= 0.0f && m_vShakeMagnitude.y <= 0.0f && m_vShakeMagnitude.z <= 0.0f) { m_bShakeScreen = DFALSE; return; } // Apply... DFLOAT faddX = GetRandom(-1.0f, 1.0f) * m_vShakeMagnitude.x * 3.0f; DFLOAT faddY = GetRandom(-1.0f, 1.0f) * m_vShakeMagnitude.y * 3.0f; DFLOAT faddZ = GetRandom(-1.0f, 1.0f) * m_vShakeMagnitude.z * 3.0f; m_fShakeCant = DEG2RAD(GetRandom(-0.5f, 0.5f) * m_vShakeMagnitude.x); DVector vPos, vAdd; VEC_SET(vAdd, faddX, faddY, faddZ); pClientDE->GetObjectPos(m_hCamera, &vPos); VEC_ADD(vPos, vPos, vAdd); pClientDE->SetObjectPos(m_hCamera, &vPos); // Shake the guns too.. if (m_pWeapon && m_pWeapon->GetWeapObj()) { pClientDE->GetObjectPos(m_pWeapon->GetWeapObj(), &vPos); VEC_MULSCALAR(vAdd, vAdd, 0.95f); VEC_ADD(vPos, vPos, vAdd); pClientDE->SetObjectPos(m_pWeapon->GetWeapObj(), &vPos); } if (m_pLWeapon && m_pLWeapon->GetWeapObj()) { pClientDE->GetObjectPos(m_pLWeapon->GetWeapObj(), &vPos); VEC_MULSCALAR(vAdd, vAdd, 0.95f); VEC_ADD(vPos, vPos, vAdd); pClientDE->SetObjectPos(m_pLWeapon->GetWeapObj(), &vPos); } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateScreenFlash // // PURPOSE: Update the screen Flash // // --------------------------------------------------------------------------- // void CBloodClientShell::UpdateScreenFlash() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !m_bFlashScreen) return; DVector vLightAdd; VEC_INIT(vLightAdd); DFLOAT fTime = pClientDE->GetTime(); // ramp up if ((m_fFlashRampUp > 0.0f) && (fTime < m_fFlashStart + m_fFlashRampUp)) { DFLOAT fDelta = (fTime - m_fFlashStart); vLightAdd.x = fDelta * (m_vFlashColor.x) / m_fFlashRampUp; vLightAdd.y = fDelta * (m_vFlashColor.y) / m_fFlashRampUp; vLightAdd.z = fDelta * (m_vFlashColor.z) / m_fFlashRampUp; } // full tint else if (fTime < m_fFlashStart + m_fFlashRampUp + m_fFlashTime) { VEC_COPY(vLightAdd, m_vFlashColor); } // ramp down else if (VEC_MAGSQR(m_vFlashColor) > 0) { DVector vSub; DFLOAT fScale = pClientDE->GetFrameTime() * 2; VEC_SET(vSub, fScale, fScale, fScale); VEC_SUB(m_vFlashColor, m_vFlashColor, vSub); VEC_CLAMP(m_vFlashColor, 0, 2.0f); VEC_COPY(vLightAdd, m_vFlashColor); // Add it to any additional camera light we're adding.. } else { m_bFlashScreen = DFALSE; } VEC_CLAMP(vLightAdd, 0, 1.0f); VEC_ADD(m_vCameraAdd, m_vCameraAdd, vLightAdd); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateContainerFX // // PURPOSE: Update any client side container fx // // --------------------------------------------------------------------------- // void CBloodClientShell::UpdateContainerFX() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !m_hCamera) return; DVector vPos; pClientDE->GetObjectPos(m_hCamera, &vPos); HLOCALOBJ objList[1]; DDWORD dwNum = pClientDE->GetPointContainers(&vPos, objList, 1); char* pCurSound = DNULL; DBOOL bUpdateScale = DFALSE; ContainerCode eCode = CC_NOTHING; DDWORD dwUserFlags = FLAG_VISIBLE; DBOOL bUseWorldFog = DTRUE; // Get the user flags associated with the container, and make sure that // the container isn't hidden... if (dwNum > 0 && objList[0]) { pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags); } if (dwNum > 0 && (dwUserFlags & FLAG_VISIBLE)) { D_WORD code; if (pClientDE->GetContainerCode(objList[0], &code)) { eCode = (ContainerCode)code; // See if we have entered/left a container... DFLOAT fTime = pClientDE->GetTime(); if (m_eCurContainerCode != eCode) { m_fContainerStartTime = fTime; // See if this container has fog associated with it.. CVolumeBrushFX* pFX = (CVolumeBrushFX*)m_sfxMgr.FindStaticSpecialFX(objList[0]); if (pFX) { bUseWorldFog = DFALSE; DBOOL bFog = pFX->IsFogEnable(); char buf[30]; sprintf(buf, "FogEnable %d", (int)bFog); pClientDE->RunConsoleString(buf); if (bFog) { sprintf(buf, "FogNearZ %d", (int)pFX->GetFogNearZ()); pClientDE->RunConsoleString(buf); sprintf(buf, "FogFarZ %d", (int)pFX->GetFogFarZ()); pClientDE->RunConsoleString(buf); DVector vFogColor = pFX->GetFogColor(); sprintf(buf, "FogR %d", (int)vFogColor.x); pClientDE->RunConsoleString(buf); sprintf(buf, "FogG %d", (int)vFogColor.y); pClientDE->RunConsoleString(buf); sprintf(buf, "FogB %d", (int)vFogColor.z); pClientDE->RunConsoleString(buf); } } } char *pWaterSound = "Sounds\\Player\\Underwaterloop1.wav"; switch (eCode) { case CC_WATER: { VEC_SET(m_vLightScale, 0.3f, 0.8f, 0.8f); pCurSound = pWaterSound; } break; case CC_BLOOD: { VEC_SET(m_vLightScale, 1.0f, 0.0f, 0.0f); pCurSound = pWaterSound; } break; case CC_ACID: { VEC_SET(m_vLightScale, 0.0f, 0.8f, 0.4f); pCurSound = pWaterSound; } break; case CC_FREEFALL: { DFLOAT fFallTime = 1.5f; DFLOAT fScale = 0.0f; if (fTime < m_fContainerStartTime + fFallTime) { DFLOAT fTimeLeft = (m_fContainerStartTime + fFallTime) - fTime; fScale = fTimeLeft/fFallTime; } VEC_SET(m_vLightScale, fScale, fScale, fScale); } break; default : break; } } } // See if we have entered/left a container... if (m_eCurContainerCode != eCode || bUpdateScale) { // Adjust Fog as necessary... if (bUseWorldFog) { ResetGlobalFog(); } // See if we are coming out of water... if (IsLiquid(m_eCurContainerCode) && !IsLiquid(eCode)) { UpdateUnderWaterFX(DFALSE); } m_eCurContainerCode = eCode; if (m_hContainerSound) { pClientDE->KillSound(m_hContainerSound); m_hContainerSound = DNULL; } if (pCurSound) { PlaySoundInfo playSoundInfo; PLAYSOUNDINFO_INIT(playSoundInfo); playSoundInfo.m_dwFlags = PLAYSOUND_CLIENT | PLAYSOUND_LOCAL | PLAYSOUND_LOOP | PLAYSOUND_GETHANDLE; _mbscpy((unsigned char*)playSoundInfo.m_szSoundName, (const unsigned char*)pCurSound); playSoundInfo.m_nVolume = 20; if( pClientDE->PlaySound(&playSoundInfo) == LT_OK ) m_hContainerSound = playSoundInfo.m_hSound; } // pClientDE->SetCameraLightAdd(m_hCamera, &vLightAdd); } // See if we are under water (under any liquid)... if (IsLiquid(m_eCurContainerCode)) { UpdateUnderWaterFX(); } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateUnderWaterFX // // PURPOSE: Update under water fx // // --------------------------------------------------------------------------- // void CBloodClientShell::UpdateUnderWaterFX(DBOOL bUpdate) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !m_hCamera || m_bZoomView) return; // DDWORD dwWidth = 640, dwHeight = 480; // pClientDE->GetSurfaceDims(pClientDE->GetScreenSurface(), &dwWidth, &dwHeight); if (m_dwScreenWidth < 0 || m_dwScreenHeight < 0) return; // Initialize to default fov x and y... DFLOAT fFovX = m_fovX; DFLOAT fFovY = fFovX * m_fovYScale; if (bUpdate) { pClientDE->GetCameraFOV(m_hCamera, &fFovX, &fFovY); DFLOAT fSpeed = .02f * pClientDE->GetFrameTime(); if (m_fFovXFXDir > 0) { fFovY += fSpeed; fFovX -= fSpeed; if (fFovY > m_fovX * m_fovYScale) { fFovY = m_fovX * m_fovYScale; m_fFovXFXDir = -m_fFovXFXDir; } } else { fFovY -= fSpeed; fFovX += fSpeed; if (fFovY < (m_fovX * m_dwScreenHeight - 40) / m_dwScreenWidth) { fFovY = (m_fovX * m_dwScreenHeight - 40) / m_dwScreenWidth; m_fFovXFXDir = -m_fFovXFXDir; } } } pClientDE->SetCameraFOV(m_hCamera, fFovX, fFovY); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateWonkyVision // // PURPOSE: Update WonkyVision (baddest LCD trip in da mofo) // // --------------------------------------------------------------------------- // void CBloodClientShell::UpdateWonkyVision(DBOOL bUpdate) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !m_hCamera || m_bZoomView) return; if (m_dwScreenWidth < 0 || m_dwScreenHeight < 0) return; DFLOAT fovX = m_fovX; DFLOAT fovY = m_fovY; DVector vU, vF, vR; pClientDE->GetRotationVectors(&m_Rotation, &vU, &vR, &vF); pClientDE->RunConsoleString("ModelWarble 1"); pClientDE->RunConsoleString("WarbleSpeed 15"); pClientDE->RunConsoleString("WarbleScale .90"); DFLOAT fSpeed = 0.2f * pClientDE->GetFrameTime(); fSpeed = DCLAMP( fSpeed, 0.0f, 0.010f ); // FOV if (m_fFovXFXDir > 0) { m_fOffsetY += fSpeed; m_fOffsetX -= fSpeed; fovY += m_fOffsetY; fovX += m_fOffsetX; if (fovY > fovX * m_fovYScale) { fovY = fovX * m_fovYScale; m_fFovXFXDir = -m_fFovXFXDir; } } else { m_fOffsetY -= fSpeed; m_fOffsetX += fSpeed; fovY += m_fOffsetY; fovX += m_fOffsetX; if (fovY < (fovX * m_dwScreenHeight - 120) / m_dwScreenWidth) { fovY = (fovX * m_dwScreenHeight - 120) / m_dwScreenWidth; m_fFovXFXDir = -m_fFovXFXDir; } } // ROTATION if(m_fRotDir > 0) { m_fOffsetRot += fSpeed * 1.5f; if(m_fOffsetRot >= m_fMaxRot) { m_fRotDir = -m_fRotDir; m_fMaxRot = -0.55f * GetRandom(1.0f, 2.0f); } } else { m_fOffsetRot -= fSpeed * 1.5f; if(m_fOffsetRot <= m_fMaxRot) { m_fRotDir = -m_fRotDir; m_fMaxRot = 0.55f * GetRandom(1.0f, 2.0f); } } if (fovX < 1.3f) fovX = 1.3f; if (fovX > 1.8f) fovX = 1.8f; if (fovY < 1.0f) fovY = 1.0f; if (fovY > 1.3f) fovY = 1.3f; pClientDE->SetCameraFOV(m_hCamera, fovX, fovY); pClientDE->RotateAroundAxis(&m_Rotation, &vF, m_fOffsetRot); pClientDE->SetObjectRotation(m_hCamera, &m_Rotation); return; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::ShakeScreen() // // PURPOSE: Shake screen // // ----------------------------------------------------------------------- // void CBloodClientShell::ShakeScreen(DVector *vShake, DFLOAT fTime) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; m_fShakeStart = GetClientDE()->GetTime(); m_fShakeTime = fTime; VEC_ADD(m_vShakeMagnitude, m_vShakeMagnitude, *vShake); if (m_vShakeMagnitude.x > 3.5f) m_vShakeMagnitude.x = 3.5f; if (m_vShakeMagnitude.y > 3.5f) m_vShakeMagnitude.y = 3.5f; if (m_vShakeMagnitude.z > 3.5f) m_vShakeMagnitude.z = 3.5f; m_bShakeScreen = DTRUE; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::FlashScreen() // // PURPOSE: Flash screen // // ----------------------------------------------------------------------- // void CBloodClientShell::FlashScreen(DVector *vFlashColor, DFLOAT fTime, DFLOAT fRampUp) { if (!GetClientDE()) return; m_fFlashStart = GetClientDE()->GetTime(); m_fFlashTime = fTime; m_vFlashColor.x += vFlashColor->x; m_vFlashColor.y += vFlashColor->y; m_vFlashColor.z += vFlashColor->z; // Scale lowest value to max of 1.0 (so we don't oversaturate) DFLOAT fMin = m_vFlashColor.x; fMin = (m_vFlashColor.y < fMin) ? m_vFlashColor.y : fMin; fMin = (m_vFlashColor.z < fMin) ? m_vFlashColor.z : fMin; if (fMin > 1.0f) { fMin = 1.0f/fMin; m_vFlashColor.x *= fMin; m_vFlashColor.y *= fMin; m_vFlashColor.z *= fMin; } // if screen is already flashing, don't ramp up.. if (!m_bFlashScreen) m_fFlashRampUp = fRampUp; else m_fFlashRampUp = 0.0f; m_bFlashScreen = DTRUE; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::HandleExitWorld() // // PURPOSE: The player has hit an exit trigger. // // ----------------------------------------------------------------------- // void CBloodClientShell::HandleExitWorld(HMESSAGEREAD hMessage) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; // don't go to the next level if you are dead if (m_bDead) return; // Stop the music m_Music.TermPlayLists(); pClientDE->StopMusic (MUSIC_IMMEDIATE); // Stop the music m_eMusicLevel = CMusic::MUSICLEVEL_SILENCE; // kill the sounds if (m_hContainerSound) { pClientDE->KillSound(m_hContainerSound); m_hContainerSound = DNULL; } if( m_hNightGogglesSound ) { g_pClientDE->KillSound( m_hNightGogglesSound ); } if( m_hTheEyeLoopingSound ) { g_pClientDE->KillSound( m_hTheEyeLoopingSound ); } // Get the new world HSTRING hstrNextWorld = pClientDE->ReadFromMessageHString(hMessage); m_nLastExitType = pClientDE->ReadFromMessageByte(hMessage); if (!hstrNextWorld) { PrintError("Invalid data in CBloodClientShell::HandleExitWorld()!"); return; } #ifdef _DEMO if (_mbsicmp((const unsigned char*)"EndGame", (const unsigned char*)pClientDE->GetStringData(hstrNextWorld)) == 0) { m_bInWorld = DFALSE; PauseGame(DTRUE); m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU); PlaySoundLocal("sounds\\interface\\mainmenus\\enter01.wav", SOUNDPRIORITY_MISC_HIGH, DFALSE, DFALSE, DFALSE, DFALSE, 100); Splash_SetState(pClientDE, "\\screens\\info.pcx"); return; } #endif _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)pClientDE->GetStringData(hstrNextWorld)); StartNewWorld(m_szFilename, m_nGameType, LOADTYPE_NEW_LEVEL); pClientDE->FreeString(hstrNextWorld); m_bFirstWorld = DFALSE; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::StartNewWorld() // // PURPOSE: Start the new world // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::StartNewWorld(char *pszWorld, DBYTE nGameType, DBYTE nLoadType, DBYTE nDifficulty) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return DFALSE; if (pszWorld) { // Set up the world title string if (m_hstrTitle) { pClientDE->FreeString(m_hstrTitle); m_hstrTitle = 0; } if (m_hstrLoadScreen) { pClientDE->FreeString(m_hstrLoadScreen); m_hstrLoadScreen = 0; } if (m_nLoadScreenID) m_nLoadScreenID = 0; GetWorldTitle(pszWorld); if(m_nLoadScreenID) PauseGame(DTRUE); else PauseGame(DFALSE); // Clear the current objective... m_NewStatusBar.InitObjectivesTab(); // Send a message to the server to load a new world HMESSAGEWRITE hMsg; hMsg = pClientDE->StartMessage(CMSG_LOADWORLD); pClientDE->WriteToMessageString(hMsg, pszWorld); // Filename pClientDE->WriteToMessageByte(hMsg, nGameType); // Game type pClientDE->WriteToMessageByte(hMsg, nLoadType); // Load type pClientDE->WriteToMessageByte(hMsg, nDifficulty); // Difficulty level pClientDE->EndMessage(hMsg); SetGameState(GS_LOADINGLEVEL); m_nGameType = nGameType; m_nLastLoadType = nLoadType; m_bInWorld = DFALSE; m_bZoomView = DFALSE; m_bShowCrosshair = m_bCrosshairOriginallyOn; m_nCrosshair = m_nCrosshairOriginalNum; m_bBlind = DFALSE; m_nTrapped = 0; } else { PrintError("Error invalid world!"); return DFALSE; } return DTRUE; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SaveClientData // // PURPOSE: Send client save data to server so it can be put into save file. // // ----------------------------------------------------------------------- // void CBloodClientShell::SaveClientData( HMESSAGEWRITE hMsg ) { HMESSAGEWRITE hSaveMsg; hSaveMsg = g_pClientDE->StartHMessageWrite( ); m_eMusicLevel = m_Music.GetMusicLevel(); // Start save data... g_pClientDE->WriteToMessageByte( hSaveMsg, m_bNightGogglesActive ); g_pClientDE->WriteToMessageFloat( hSaveMsg, m_fWonkyTime ); g_pClientDE->WriteToMessageByte( hSaveMsg, m_bWonkyVision ); g_pClientDE->WriteToMessageByte( hSaveMsg, m_bWonkyNoMove ); g_pClientDE->WriteToMessageFloat( hSaveMsg, m_fBlindTime ); g_pClientDE->WriteToMessageByte( hSaveMsg, m_bBlind ); g_pClientDE->WriteToMessageByte( hSaveMsg, m_bFadeIn ); g_pClientDE->WriteToMessageByte( hSaveMsg, m_bFadeOut ); g_pClientDE->WriteToMessageFloat( hSaveMsg, m_fFadeVal ); // g_pClientDE->WriteToMessageByte( hSaveMsg, m_nCrosshair ); g_pClientDE->WriteToMessageByte( hSaveMsg, m_eMusicLevel ); g_pClientDE->WriteToMessageFloat( hSaveMsg, (float)m_nLastLoadType ); g_pClientDE->WriteToMessageFloat( hSaveMsg, (float)m_nGameType ); g_pClientDE->WriteToMessageHString( hSaveMsg, m_hstrObjectivesTitle ); g_pClientDE->WriteToMessageHString( hSaveMsg, m_hstrObjectivesText ); // End save data... g_pClientDE->WriteToMessageHMessageWrite( hMsg, hSaveMsg ); g_pClientDE->EndHMessageWrite( hSaveMsg ); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::LoadClientData // // PURPOSE: Send client save data to server so it can be put into save file. // // ----------------------------------------------------------------------- // void CBloodClientShell::LoadClientData( HMESSAGEREAD hMsg ) { HMESSAGEREAD hLoadMsg; DBOOL bNightVisionActive; if (m_hstrObjectivesTitle) { g_pClientDE->FreeString(m_hstrObjectivesTitle); m_hstrObjectivesTitle = DNULL; } if (m_hstrObjectivesText) { g_pClientDE->FreeString(m_hstrObjectivesText); m_hstrObjectivesText = DNULL; } hLoadMsg = g_pClientDE->ReadFromMessageHMessageRead( hMsg ); bNightVisionActive = g_pClientDE->ReadFromMessageByte( hLoadMsg ); m_fWonkyTime = g_pClientDE->ReadFromMessageFloat( hLoadMsg ); m_bWonkyVision = g_pClientDE->ReadFromMessageByte( hLoadMsg ); m_bWonkyNoMove = g_pClientDE->ReadFromMessageByte( hLoadMsg ); m_fBlindTime = g_pClientDE->ReadFromMessageFloat( hLoadMsg ); m_bBlind = g_pClientDE->ReadFromMessageByte( hLoadMsg ); m_bFadeIn = g_pClientDE->ReadFromMessageByte( hLoadMsg ); m_bFadeOut = g_pClientDE->ReadFromMessageByte( hLoadMsg ); m_fFadeVal = g_pClientDE->ReadFromMessageFloat( hLoadMsg ); // m_nCrosshair = g_pClientDE->ReadFromMessageByte( hLoadMsg ); m_eMusicLevel = (CMusic::EMusicLevel) g_pClientDE->ReadFromMessageByte( hLoadMsg ); int nTmp = (int)g_pClientDE->ReadFromMessageFloat( hLoadMsg ); m_nGameType = (int)g_pClientDE->ReadFromMessageFloat( hLoadMsg ); m_hstrObjectivesTitle = g_pClientDE->ReadFromMessageHString( hLoadMsg ); m_hstrObjectivesText = g_pClientDE->ReadFromMessageHString( hLoadMsg ); if (m_hstrObjectivesTitle && m_hstrObjectivesText) m_NewStatusBar.UpdateObjectives(g_pClientDE->GetStringData(m_hstrObjectivesTitle), g_pClientDE->GetStringData(m_hstrObjectivesText)); g_pClientDE->EndHMessageRead( hLoadMsg ); g_pClientDE->RunConsoleString("maxfps 0"); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::ShowPlayer() // // PURPOSE: Show or hide the player object // // --------------------------------------------------------------------------- // HLOCALOBJ m_hLastWeapHandObj = DNULL; HLOCALOBJ m_hLastLWeapHandObj = DNULL; void CBloodClientShell::ShowPlayer(DBOOL bShow) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; HLOCALOBJ hPlayerObj = pClientDE->GetClientObject(); if (!hPlayerObj) return; DDWORD dwFlags = pClientDE->GetObjectFlags(hPlayerObj); if (bShow) { dwFlags |= FLAG_VISIBLE; cdata.byFlags &= ~CDATA_SHOWGUN; } else { dwFlags &= ~FLAG_VISIBLE; cdata.byFlags |= CDATA_SHOWGUN; } pClientDE->SetObjectFlags(hPlayerObj, dwFlags); if((m_hLastWeapHandObj != m_hWeapHandObj) || (m_hLastLWeapHandObj != m_hLWeapHandObj)) { m_hLastWeapHandObj = m_hWeapHandObj; m_hLastLWeapHandObj = m_hLWeapHandObj; } if (m_hWeapHandObj) { DDWORD dwFlags = pClientDE->GetObjectFlags(m_hWeapHandObj); if(bShow) dwFlags |= FLAG_VISIBLE; else dwFlags &= ~FLAG_VISIBLE; pClientDE->SetObjectFlags(m_hWeapHandObj, dwFlags); } if (m_hLWeapHandObj) { DDWORD dwFlags = pClientDE->GetObjectFlags(m_hLWeapHandObj); if (bShow) dwFlags |= FLAG_VISIBLE; else dwFlags &= ~FLAG_VISIBLE; pClientDE->SetObjectFlags(m_hLWeapHandObj, dwFlags); } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::DrawLoadingScreen() // // PURPOSE: Update the loading screen // // ----------------------------------------------------------------------- // void CBloodClientShell::DrawLoadingScreen() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; HSURFACE hScreen = pClientDE->GetScreenSurface(); if (!hScreen) return; HSURFACE hTemp = DNULL; DDWORD screenWidth, screenHeight; pClientDE->GetSurfaceDims(hScreen, &screenWidth, &screenHeight); // If we don't have a loading screen, create one if(!m_hLoadingScreen) { // Create the loading screen surface the same size as the screen m_hLoadingScreen = pClientDE->CreateSurface(screenWidth, screenHeight); if(m_hstrLoadScreen) hTemp = pClientDE->CreateSurfaceFromBitmap(pClientDE->GetStringData(m_hstrLoadScreen)); else { hTemp = pClientDE->CreateSurfaceFromBitmap("Interface\\LoadScreens\\LoadScreen.pcx"); pClientDE->DrawBitmapToSurface(hTemp, "Interface\\LoadScreens\\LoadingText\\Loading_01.pcx", DNULL, 215, 321); } // Scale the bitmap to the loading screen and dump the temp surface pClientDE->ScaleSurfaceToSurface(m_hLoadingScreen, hTemp, DNULL, DNULL); pClientDE->DeleteSurface(hTemp); hTemp = DNULL; } // Init the fonts and cursor CoolFontCursor *m_hLoadCursor = 0; CoolFont *m_hLoadTitleFont = 0; CoolFont *m_hLoadTextFont = 0; m_hLoadCursor = new CoolFontCursor(); m_hLoadTitleFont = new CoolFont(); m_hLoadTextFont = new CoolFont(); m_hLoadTitleFont->Init(pClientDE, "interface/statusbar/fonts/stat_font_1.pcx"); m_hLoadTitleFont->LoadXWidths("interface/statusbar/fonts/stat_font_1.fnt"); m_hLoadTextFont->Init(pClientDE, "interface/objectives/obj_font_1.pcx"); m_hLoadTextFont->LoadXWidths("interface/objectives/obj_font_1.fnt"); #ifdef _DEMO // Draw the title of the level m_hLoadCursor->SetFont(m_hLoadTitleFont); m_hLoadCursor->SetDest(m_hLoadingScreen); m_hLoadCursor->SetJustify(CF_JUSTIFY_CENTER); m_hLoadCursor->SetLoc((short)(screenWidth * 0.5f), (short)(m_hLoadTitleFont->height * 2)); if(m_hstrTitle) { m_hLoadCursor->Draw(pClientDE->GetStringData(m_hstrTitle)); m_hLoadCursor->NewLine(); } #else if(!m_nLoadScreenID) { // Draw the title of the level m_hLoadCursor->SetFont(m_hLoadTitleFont); m_hLoadCursor->SetDest(m_hLoadingScreen); m_hLoadCursor->SetJustify(CF_JUSTIFY_CENTER); m_hLoadCursor->SetLoc((short)(screenWidth * 0.5f), (short)(m_hLoadTitleFont->height * 2)); if(m_hstrTitle) { m_hLoadCursor->Draw(pClientDE->GetStringData(m_hstrTitle)); m_hLoadCursor->NewLine(); } // Draw the loading screen... pClientDE->DrawSurfaceToSurface(hScreen, m_hLoadingScreen, DNULL, 0, 0); } else { HSTRING hStr; LoadScreenData *lsd = &(g_LoadScreenData[m_nLoadScreenID]); DFLOAT ratioX = (float)screenWidth / 640.0f; DFLOAT ratioY = (float)screenHeight / 480.0f; short newX, newY; m_hLoadCursor->SetFont(m_hLoadTitleFont); m_hLoadCursor->SetDest(m_hLoadingScreen); m_hLoadCursor->SetJustify(CF_JUSTIFY_CENTER); // Find the scaled location for the title and draw it center justified newX = (short)(lsd->nTitleX * ratioX); newY = (short)(lsd->nTitleY * ratioY); // Draw the title of the level m_hLoadCursor->SetLoc(newX, (short)(m_hLoadTitleFont->height * 2)); if(m_hstrTitle) m_hLoadCursor->Draw(pClientDE->GetStringData(m_hstrTitle)); m_hLoadCursor->SetLoc(newX, (short)(m_hLoadTitleFont->height * 3)); hStr = pClientDE->FormatString(lsd->nTitle); m_hLoadCursor->Draw(pClientDE->GetStringData(hStr)); pClientDE->FreeString(hStr); if(m_nGameType != GAMETYPE_ACTION && screenWidth >= 512 && screenHeight >= 384) { // Find the scaled location for the text and draw it in formatted mode newX = (short)(lsd->nTextX * ratioX); newY = (short)(lsd->nTextY * ratioY); m_hLoadCursor->SetFont(m_hLoadTextFont); m_hLoadCursor->SetLoc(newX, (short)(m_hLoadTitleFont->height * 5)); hStr = pClientDE->FormatString(lsd->nText); m_hLoadCursor->DrawFormat(pClientDE->GetStringData(hStr), (short)(lsd->nTextWrapWidth * ratioX)); pClientDE->FreeString(hStr); } // Draw the loading screen... pClientDE->DrawSurfaceToSurface(hScreen, m_hLoadingScreen, DNULL, 0, 0); // Draw a loading message at the bottom of the screen m_hLoadCursor->SetDest(hScreen); m_hLoadCursor->SetFont(m_hLoadTitleFont); m_hLoadCursor->SetLoc((short)(screenWidth * 0.5f), (short)(screenHeight - m_hLoadTitleFont->height)); if(GetGameState() == GS_WAITING) { DFLOAT r, g, b, time = pClientDE->GetTime(); DFLOAT calc; if(!m_bPlayedWaitingSound) { PlaySoundLocal( "sounds\\interface\\mainmenus\\esc01.wav", SOUNDPRIORITY_MISC_HIGH); m_bPlayedWaitingSound = DTRUE; } if(time - m_fLoadingFadeTime >= 1.0f) { m_fLoadingFadeTime = time; m_bLoadingFadeUp = !m_bLoadingFadeUp; } calc = (time - m_fLoadingFadeTime) / 1.0f; if(m_bLoadingFadeUp) { r = 0.776f + (0.224f * calc); g = 0.647f - (0.647f * calc); b = 0.518f - (0.518f * calc); } else { r = 1.000f - (0.224f * calc); g = 0.647f * calc; b = 0.518f * calc; } m_hLoadCursor->DrawSolid("Press a key to continue...", pClientDE->SetupColor2(r, g, b, DFALSE)); } else { hStr = pClientDE->FormatString(g_LoadScreenMessages[GetRandom(0,MAX_LOADING_MESSAGES-1)]); m_hLoadCursor->Draw(pClientDE->GetStringData(hStr)); pClientDE->FreeString(hStr); } } #endif // Free the fonts and cursor if(m_hLoadCursor) { delete m_hLoadCursor; m_hLoadCursor = 0; } if(m_hLoadTitleFont) { m_hLoadTitleFont->Free(); delete m_hLoadTitleFont; m_hLoadTitleFont = 0; } if(m_hLoadTextFont) { m_hLoadTextFont->Free(); delete m_hLoadTextFont; m_hLoadTextFont = 0; } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::Set3rdPersonCamera() // // PURPOSE: Turn on/off 3rd person camera mode // // ----------------------------------------------------------------------- // void CBloodClientShell::Set3rdPersonCamera(DBOOL bExternal) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !m_hCamera) return; if (bExternal && m_playerCamera.IsFirstPerson()) { // m_weaponModel.SetVisible(DFALSE); m_b3rdPerson = DTRUE; m_playerCamera.GoChaseMode(); m_bZoomView = DFALSE; // Can't zoom in 3rd person... } else if (!bExternal && !m_playerCamera.IsFirstPerson()) // Go Internal { // m_weaponModel.SetVisible(DTRUE); m_b3rdPerson = DFALSE; m_playerCamera.GoFirstPerson(); } ShowPlayer(m_b3rdPerson ? DTRUE : DFALSE); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateCameraPosition() // // PURPOSE: Update the camera position // // ----------------------------------------------------------------------- // void CBloodClientShell::UpdateCameraPosition() { DBOOL bCameraIsListener; CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; HLOCALOBJ hPlayerObj = m_pMoveMgr->GetObject(); // HLOCALOBJ hPlayerObj = pClientDE->GetClientObject(); if (!hPlayerObj || !m_hCamera) return; DVector vPos; pClientDE->GetObjectPos(hPlayerObj, &vPos); // External camera if (m_pExternalCamera || m_hSeeingEyeObj || m_hOrbObj) { DRotation rRot; HLOCALOBJ hCameraObj = DNULL; bCameraIsListener = DTRUE; // Determine the object to use if (m_hSeeingEyeObj) hCameraObj = m_hSeeingEyeObj; else if (m_hOrbObj) hCameraObj = m_hOrbObj; else if (m_pExternalCamera) { hCameraObj = m_pExternalCamera->GetServerObj(); bCameraIsListener = m_pExternalCamera->IsListener( ); } if (hCameraObj) { // Get position pClientDE->GetObjectPos(hCameraObj, &vPos); pClientDE->SetObjectPos(m_hCamera, &vPos); if (!m_hOrbObj && !m_hSeeingEyeObj) { // Get Rotation pClientDE->GetObjectRotation(hCameraObj, &rRot); pClientDE->SetObjectRotation(m_hCamera, &rRot); } else { ROT_INIT( rRot ); } if( bCameraIsListener ) { // Set the listener for sounds pClientDE->SetListener( DFALSE, &vPos, &rRot ); } else pClientDE->SetListener( DTRUE, DNULL, DNULL ); } } else { // Player camera - first person if (m_playerCamera.IsFirstPerson()) { DVector up; DVector forward; DVector right; if (cdata.byFlags & CDATA_CANMOVE) { UpdateBob(); UpdateHeadCant(); } pClientDE->GetRotationVectors(&m_Rotation, &up, &right, &forward); VEC_MULSCALAR(right, right, m_fBobWidth) VEC_ADD(vPos, vPos, right) // HACK - remove eventually //#ifdef _DEBUG // VEC_MULSCALAR(forward, forward, m_fCameraZoom); // VEC_SUB(pos, pos, forward); //#endif vPos.y += m_fViewY + m_fBobHeight; pClientDE->SetObjectPos(m_hCamera, &vPos); //#ifdef _DEBUG // HACK - remove eventually // VEC_ADD(pos, pos, forward); //#endif // Set the listener for sounds pClientDE->SetListener( DTRUE, DNULL, DNULL ); } // Player camera - 3rd person else { VEC_COPY(vPos, m_playerCamera.GetPos()); pClientDE->SetObjectPos(m_hCamera, &vPos); ROT_COPY(m_Rotation, m_playerCamera.GetRotation()); // Set the listener for sounds pClientDE->SetListener( DFALSE, &vPos, &m_Rotation ); } // Update the create that's on your face if(m_pCreature) m_pCreature->Update(cdata.fPitch, cdata.fYaw, &vPos); } UpdateGun(&m_Rotation, &vPos); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::CalculateCameraRotation() // // PURPOSE: Calculate the new camera rotation // // ----------------------------------------------------------------------- // void CBloodClientShell::CalculateCameraRotation() { DFLOAT offsets[3]; DFLOAT rotateSpeed; // DRotation newRot; DFLOAT newPitch; DFLOAT newYaw; DFLOAT addPitch; DFLOAT addYaw; CClientDE* pClientDE = GetClientDE(); newPitch = m_fPitch; newYaw = m_fYaw; addPitch = 0; addYaw = 0; rotateSpeed = 3 * pClientDE->GetFrameTime(); pClientDE->GetAxisOffsets(offsets); HCONSOLEVAR hVar; float fAxisForwardBackward = 0.0f; float fAxisLeftRight = 0.0f; float fAxisYaw = 0.0f; float fAxisPitch = 0.0f; DBOOL bUseAxisForwardBackward = FALSE; DBOOL bUseAxisLeftRight = FALSE; DBOOL bFixedAxisPitch = FALSE; float fAxisYawDeadZone = 0.10f; float fAxisPitchDeadZone = 0.10f; float fAxisForwardBackwardDeadZone = 0.10f; float fAxisLeftRightDeadZone = 0.10f; if (m_bUseJoystick && !m_bAdvancedDisableJoystick) { hVar = pClientDE->GetConsoleVar( "AxisYawDeadZone"); if (hVar != NULL) fAxisYawDeadZone = pClientDE->GetVarValueFloat(hVar); hVar = pClientDE->GetConsoleVar( "AxisPitchDeadZone"); if (hVar != NULL) fAxisPitchDeadZone = pClientDE->GetVarValueFloat(hVar); hVar = pClientDE->GetConsoleVar( "AxisForwardBackwardDeadZone"); if (hVar != NULL) fAxisForwardBackwardDeadZone = pClientDE->GetVarValueFloat(hVar); hVar = pClientDE->GetConsoleVar( "AxisLeftRightDeadZone"); if (hVar != NULL) fAxisLeftRightDeadZone = pClientDE->GetVarValueFloat(hVar); hVar = pClientDE->GetConsoleVar( "AxisYaw"); if (hVar != NULL) { fAxisYaw = pClientDE->GetVarValueFloat(hVar); if ((fAxisYaw > fAxisYawDeadZone) || ((fAxisYaw < -fAxisYawDeadZone))) offsets[0] += fAxisYaw; } hVar = pClientDE->GetConsoleVar( "AxisPitch"); if (hVar != NULL) { fAxisPitch = pClientDE->GetVarValueFloat(hVar); if ((fAxisPitch > fAxisPitchDeadZone) || (fAxisPitch < -fAxisPitchDeadZone)) offsets[1] += fAxisPitch; } hVar = pClientDE->GetConsoleVar( "AxisLeftRight"); if (hVar != NULL) { fAxisLeftRight = pClientDE->GetVarValueFloat(hVar); bUseAxisLeftRight = TRUE; } hVar = pClientDE->GetConsoleVar( "AxisForwardBackward"); if (hVar != NULL) { fAxisForwardBackward = pClientDE->GetVarValueFloat(hVar); bUseAxisForwardBackward = TRUE; } hVar = pClientDE->GetConsoleVar( "FixedAxisPitch"); if (hVar != NULL) if (pClientDE->GetVarValueFloat(hVar) == 1) { newPitch = fAxisPitch; bFixedAxisPitch = TRUE; // pClientDE->CPrint("FixedAxisPitch==1 AxisPitch=%14.6f",(double)fAxisPitch); // BLB TEMP } } m_pMoveMgr->UpdateAxisMovement(bUseAxisForwardBackward, fAxisForwardBackward, fAxisForwardBackwardDeadZone, bUseAxisLeftRight, fAxisLeftRight, fAxisLeftRightDeadZone); cdata.MouseAxis0 = offsets[0]; cdata.MouseAxis1 = offsets[1]; // if (cdata.byFlags & CDATA_MOUSEAIMING) if (m_bMouseLook || pClientDE->IsCommandOn(COMMAND_MOUSEAIMTOGGLE)) { DFLOAT addPitch = m_bZoomView ? (offsets[1] / 4.0f) : (offsets[1]); addPitch *= (IsMouseInvertYAxis() ? -1 : 1); newPitch += addPitch; } // Only allow input if not editing and movement is not blocked if (!m_MessageMgr.GetEditingState() && (cdata.byFlags & CDATA_CANMOVE || m_hOrbObj || m_hSeeingEyeObj)) { // Rotate if not strafe state if (!pClientDE->IsCommandOn(COMMAND_STRAFE)) { newYaw += (m_bZoomView) ? (offsets[0] / 4.0f) : offsets[0]; if (pClientDE->IsCommandOn(COMMAND_LEFT)) newYaw -= rotateSpeed * GetKeyboardTurnRate(); else if (pClientDE->IsCommandOn(COMMAND_RIGHT)) newYaw += rotateSpeed * GetKeyboardTurnRate(); } // Turn around if (pClientDE->IsCommandOn(COMMAND_TURNAROUND) && m_SpinAmount == 0) { m_SpinAmount = - PI; } else if (m_SpinAmount != 0) { DFLOAT nSpin; nSpin = pClientDE->GetFrameTime() * 15; m_SpinAmount += nSpin; if (m_SpinAmount > 0) { nSpin -= m_SpinAmount; m_SpinAmount = 0; } newYaw += nSpin; } // Aim Up/Down if (pClientDE->IsCommandOn(COMMAND_AIMUP) && !m_bZeroXAngle) newPitch -= rotateSpeed; else if (pClientDE->IsCommandOn(COMMAND_AIMDOWN) && !m_bZeroXAngle) newPitch += rotateSpeed; // Look Up/Down if (pClientDE->IsCommandOn(COMMAND_LOOKUP)) newPitch -= rotateSpeed; else if (pClientDE->IsCommandOn(COMMAND_LOOKDOWN)) newPitch += rotateSpeed; } // Zero X Angle (if we just let go of a look key) if (m_bZeroXAngle) { if (newPitch != 0) { DFLOAT nSpin; DFLOAT nNewX; if (newPitch <= 0) nSpin = rotateSpeed; else nSpin = -rotateSpeed; nNewX = newPitch + nSpin; if (newPitch > 0 && nNewX <= 0) newPitch = 0; else if (newPitch < 0 && nNewX >= 0) newPitch = 0; else newPitch = nNewX; } if (newPitch == 0) m_bZeroXAngle = DFALSE; } if (m_fViewKick) { addPitch -= DEG2RAD(m_fViewKick); } if (m_fKickTime) { m_fKickTime -= pClientDE->GetFrameTime(); if (m_fKickTime <= 0) { m_fKickTime = 0.001f; m_fViewKick -= RAD2DEG(rotateSpeed); if (m_fViewKick <= 0) { m_fViewKick = 0; m_fKickTime = 0; } } } DFLOAT minY = (PI / 2) - 0.01f; if (newPitch < -minY) newPitch = -minY; if (newPitch > minY) newPitch = minY; if (newPitch + addPitch != cdata.fPitch || newYaw + addYaw != cdata.fYaw) { cdata.fPitch = newPitch + addPitch; m_fPitch = newPitch; cdata.fYaw = newYaw + addYaw; m_fYaw = newYaw; // pClientDE->CPrint("Pitch=%14.6f Yaw=%14.6f",(double)m_fPitch,(double)m_fYaw); // BLB TEMP } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::UpdateCameraRotation() // // PURPOSE: Set the new camera rotation // // ----------------------------------------------------------------------- // void CBloodClientShell::UpdateCameraRotation() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !m_hCamera) return; HLOCALOBJ hPlayerObj = pClientDE->GetClientObject(); if (!hPlayerObj) return; if (m_bDemoPlayback) { // Just get camera angles from the object... pClientDE->GetObjectRotation(hPlayerObj, &m_Rotation); pClientDE->SetObjectRotation(m_hCamera, &m_Rotation); return; } // Setup the pitch and roll pClientDE->SetupEuler(&m_Rotation, cdata.fPitch, cdata.fYaw, 0); // Rotate the head canting amount around vF DVector vU, vF, vR; pClientDE->GetRotationVectors(&m_Rotation, &vU, &vR, &vF); pClientDE->RotateAroundAxis(&m_Rotation, &vF, m_fCamCant + m_fBobCant + m_fShakeCant); if (m_pExternalCamera) { // Just calculate the correct player rotation... } else if (m_playerCamera.IsFirstPerson()) { pClientDE->SetObjectRotation(m_hCamera, &m_Rotation); } else { // Set the camera to use the rotation calculated by the player camera, // however we still need to calculate the correct rotation to be sent // to the player... DRotation rRot = m_playerCamera.GetRotation(); pClientDE->SetObjectRotation(m_hCamera, &rRot); } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::GetWorldTitle() // // PURPOSE: Parse the world title from the WorldInfo string // // ----------------------------------------------------------------------- // void CBloodClientShell::GetWorldTitle(char *pWorldFile) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE || !pWorldFile) return; HSTRING hstrTitle = DNULL; char szFilename[MAX_CS_FILENAME_LEN+1]; char szWorldInfo[255]; #ifdef _ADDON char sUpr[256]; strncpy(sUpr, pWorldFile, 255); strupr(sUpr); if (strstr(sUpr, "WORLDS_AO")) { strncpy(szFilename, pWorldFile, MAX_CS_FILENAME_LEN); if (!strstr(sUpr, ".DAT")) { strcat(szFilename, ".dat"); } } else { sprintf(szFilename, "Worlds\\%s.dat", pWorldFile); } #else sprintf(szFilename, "Worlds\\%s.dat", pWorldFile); #endif DDWORD dwInfoLen; if(pClientDE->GetWorldInfoString(szFilename, szWorldInfo, 255, &dwInfoLen) == LT_OK) { int nArgs; char tokenSpace[64*20]; char *pTokens[64]; char *pCommand = szWorldInfo; char *pCommandPos; DBOOL bDone = DFALSE; while (!bDone) { if (!pClientDE->Parse(pCommand, &pCommandPos, tokenSpace, pTokens, &nArgs)) bDone = DTRUE; else pCommand = pCommandPos; for(int i = 0; i < nArgs; i++) { if(pTokens[i]) { if((_mbsicmp((const unsigned char*)"worldname", (const unsigned char*)pTokens[i]) == 0) && pTokens[i+1]) { m_hstrTitle = pClientDE->CreateString(pTokens[i+1]); } else if((_mbsicmp((const unsigned char*)"loadscreen", (const unsigned char*)pTokens[i]) == 0) && pTokens[i+1]) { #ifdef _DEMO strupr(szFilename); if (_mbsstr((const unsigned char*)szFilename, (const unsigned char*)"DEMO_02")) m_hstrLoadScreen = pClientDE->CreateString("\\screens\\loading2.pcx"); else m_hstrLoadScreen = pClientDE->CreateString("\\screens\\loading1.pcx"); #else char szLoadScreen[128]; sprintf(szLoadScreen, "Interface\\LoadScreens\\%s", pTokens[i+1]); m_hstrLoadScreen = pClientDE->CreateString(szLoadScreen); #endif } else if((_mbsicmp((const unsigned char*)"loadscreenID", (const unsigned char*)pTokens[i]) == 0) && pTokens[i+1]) { m_nLoadScreenID = (DDWORD)atoi(pTokens[i+1]); } } } } } // Make sure we have a title... if(!m_hstrTitle) m_hstrTitle = pClientDE->CreateString(pWorldFile); // Change the loading screen string if this is a nightmare level... #ifdef _ADDON strupr(szFilename); if (strstr(szFilename, "WORLDS_AO")) { if (m_hstrLoadScreen) { pClientDE->FreeString(m_hstrLoadScreen); m_hstrLoadScreen = 0; } m_hstrLoadScreen = pClientDE->CreateString("Screens_ao\\Bumper.pcx"); } #endif } // --------------------------------------------------------------------------- // // // ROUTINE: LoadLeakFile // // PURPOSE: Loads a leak file and creates a line system for it. // // --------------------------------------------------------------------------- // DBOOL LoadLeakFile(ClientDE *pClientDE, char *pFilename) { FILE *fp; char line[256]; HLOCALOBJ hObj; ObjectCreateStruct cStruct; DELine theLine; int nRead; fp = fopen(pFilename, "rt"); if(fp) { INIT_OBJECTCREATESTRUCT(cStruct); cStruct.m_ObjectType = OT_LINESYSTEM; cStruct.m_Flags = FLAG_VISIBLE; hObj = pClientDE->CreateObject(&cStruct); if(!hObj) { fclose(fp); return DFALSE; } while(fgets(line, 256, fp)) { nRead = sscanf(line, "%f %f %f %f %f %f", &theLine.m_Points[0].m_Pos.x, &theLine.m_Points[0].m_Pos.y, &theLine.m_Points[0].m_Pos.z, &theLine.m_Points[1].m_Pos.x, &theLine.m_Points[1].m_Pos.y, &theLine.m_Points[1].m_Pos.z); theLine.m_Points[0].r = theLine.m_Points[0].g = theLine.m_Points[0].b = 1; theLine.m_Points[0].a = 1; theLine.m_Points[1].r = 1; theLine.m_Points[1].g = theLine.m_Points[1].b = 0; theLine.m_Points[1].a = 1; pClientDE->AddLine(hObj, &theLine); } fclose(fp); return DTRUE; } else { return DFALSE; } } /* // ----------------------------------------------------------------------- // // // ROUTINE: LoadConfig // // PURPOSE: Reads player config data // // ----------------------------------------------------------------------- // DBOOL LoadConfig(char* pfilename, ConfigStruct *pConfig) { FILE *infile; char line[256]; char *tokenname; char *tokenvalue; if (!(infile = fopen(pfilename, "r"))) return DFALSE; while (fgets(line, 256, infile) != NULL) { // Get tokens, see if first one is a comment if (!(tokenname = strtok(line, " \t")) || tokenname[0] == ';') continue; if (!(tokenvalue = strtok(NULL, " \t\r\n"))) continue; _strupr(tokenname); // Check for attributes if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"STRENGTH")) pConfig->nStrength = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"MAGIC")) pConfig->nMagic = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPEED")) pConfig->nSpeed = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"RESISTANCE")) pConfig->nResistance = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"NAME")) _mbscpy(pConfig->szName, tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"CHARACTER")) pConfig->nCharacter = atoi(tokenvalue); // Check for bindings else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"BINDING1")) pConfig->nBindingSlots[0] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"BINDING2")) pConfig->nBindingSlots[1] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"BINDING3")) pConfig->nBindingSlots[2] = atoi(tokenvalue); // Check for weapons // Slot 1 is always melee // else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP1")) // pConfig->nWeaponSlots[0] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP2")) pConfig->nWeaponSlots[1] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP3")) pConfig->nWeaponSlots[2] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP4")) pConfig->nWeaponSlots[3] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP5")) pConfig->nWeaponSlots[4] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP6")) pConfig->nWeaponSlots[5] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP7")) pConfig->nWeaponSlots[6] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP8")) pConfig->nWeaponSlots[7] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP9")) pConfig->nWeaponSlots[8] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"WEAP0")) pConfig->nWeaponSlots[9] = atoi(tokenvalue); // Check for inventory items else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"INV1")) pConfig->nItemSlots[0] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"INV2")) pConfig->nItemSlots[1] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"INV3")) pConfig->nItemSlots[2] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"INV4")) pConfig->nItemSlots[3] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"PROXIMITYBOMBS")) pConfig->nProximityBombs = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"REMOTEBOMBS")) pConfig->nRemoteBombs = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SMOKEBOMBS")) pConfig->nSmokeBombs = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"TIMEBOMBS")) pConfig->nTimeBombs = atoi(tokenvalue); // Check for spells else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL1")) pConfig->nSpellSlots[0] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL2")) pConfig->nSpellSlots[1] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL3")) pConfig->nSpellSlots[2] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL4")) pConfig->nSpellSlots[3] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL5")) pConfig->nSpellSlots[4] = atoi(tokenvalue); else if (!_mbscmp((const unsigned char*)tokenname, (const unsigned char*)"SPELL6")) pConfig->nSpellSlots[5] = atoi(tokenvalue); } fclose(infile); return DTRUE; } */ /* void CBloodClientShell::ImplementMusicSource (CClientDE* pClientDE) { if (!pClientDE || !pClientShell) return; char str[64]; switch (nMusicSource) { // Disable music... case 0: { _mbscpy (str, "musicenable 0"); pClientDE->RunConsoleString (str); } break; // Use IMA... case 1: { _mbscpy (str, "musicenable 1"); pClientDE->RunConsoleString (str); if (GetMusic()->IsInitialized()) { // Only re-init if not already using ima... if (!GetMusic()->UsingIMA()) { // preserve the music level, just in case we come back to ima... CMusic::EMusicLevel level; level = GetMusic()->GetMusicLevel(); if (GetMusic()->Init (pClientDE, DTRUE)) { // Only start the music if we are in a world... if (IsInWorld() && !pClientShell->IsFirstUpdate()) { GetMusic()->InitPlayLists(); GetMusic()->PlayMusicLevel (level); } } } } // music should already be inited, but let try again... else if (pClientShell->GetMusic()->Init (pClientDE, DTRUE)) { // Only re-init the play lists if we have been in world for a while... if (pClientShell->IsInWorld() && !pClientShell->IsFirstUpdate()) pClientShell->GetMusic()->InitPlayLists(); } } break; // Use CD Audio... case 2: { _mbscpy (str, "musicenable 1"); pClientDE->RunConsoleString (str); if (pClientShell) { if (pClientShell->GetMusic()->IsInitialized()) { if (pClientShell->GetMusic()->UsingIMA()) { // preserve the music level, just in case we come back to ima... CMusic::EMusicLevel level; level = pClientShell->GetMusic()->GetMusicLevel(); if (pClientShell->GetMusic()->Init (pClientDE, DFALSE)) { // Only start the music if we are in a world... if (pClientShell->IsInWorld() && !pClientShell->IsFirstUpdate()) { pClientShell->GetMusic()->InitPlayLists(); pClientShell->GetMusic()->SetMusicLevel (level); pClientShell->GetMusic()->PlayCDList(); } } } } // music should already be inited, but let try again... else if (pClientShell->GetMusic()->Init (pClientDE, DTRUE)) { // Only re-init the play lists if we have been in world for a while... if (pClientShell->IsInWorld() && !pClientShell->IsFirstUpdate()) { pClientShell->GetMusic()->InitPlayLists(); pClientShell->GetMusic()->PlayCDList(); } } } } break; } } void CBloodClientShell::ImplementMusicVolume (CClientDE* pClientDE) { if (!pClientDE) return; pClientDE->SetMusicVolume (nMusicVolume); char strConsole[64]; sprintf (strConsole, "MusicVolume %d", nMusicVolume); pClientDE->RunConsoleString (strConsole); } void CBloodClientShell::ImplementSoundVolume (CClientDE* pClientDE) { if (!pClientDE) return; pClientDE->SetSoundVolume (nSoundVolume); char strConsole[64]; sprintf (strConsole, "SoundVolume %d", nSoundVolume); pClientDE->RunConsoleString (strConsole); } */ #ifdef BRANDED void CBloodClientShell::CreateBrandSurface() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; if (!m_hBrandSurface) { HSTRING hString = pClientDE->FormatString(IDS_BRAND, "Review Copy:"); if (hString) { HDECOLOR hForeground = pClientDE->SetupColor1 (1.0f, 1.0f, 1.0f, DFALSE); HDECOLOR hTrans = pClientDE->SetupColor2 (0, 0, 0, DFALSE); HDEFONT hFont = pClientDE->CreateFont ("Arial", 6, 12, DFALSE, DFALSE, DTRUE); m_hBrandSurface = pClientDE->CreateSurfaceFromString (hFont, hString, hForeground, hTrans, 10, 0); pClientDE->FreeString(hString); pClientDE->DeleteFont (hFont); } } } void CBloodClientShell::DrawBrandString(HSURFACE hScreenSurface) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; if (m_hBrandSurface) { HDECOLOR hForeground = pClientDE->SetupColor1 (1.0f, 1.0f, 1.0f, DFALSE); HDECOLOR hTrans = pClientDE->SetupColor2 (0, 0, 0, DFALSE); DDWORD dwWidth, dwHeight; DDWORD dwScreenWidth, dwScreenHeight; pClientDE->GetSurfaceDims(m_hBrandSurface, &dwWidth, &dwHeight); pClientDE->GetSurfaceDims(hScreenSurface, &dwScreenWidth, &dwScreenHeight); pClientDE->DrawSurfaceToSurfaceTransparent (hScreenSurface, m_hBrandSurface, NULL, (dwScreenWidth - dwWidth - 1), (dwScreenHeight - dwHeight - 1), hTrans); } } #endif // BRANDED // --------------------------------------------------------------------------- // // // ROUTINE: ConnectToTcpIpAddress // // PURPOSE: Connects (joins) to the given tcp/ip address // // --------------------------------------------------------------------------- // DBOOL ConnectToTcpIpAddress(CClientDE* pClientDE, char* sAddress) { // Sanity checks... if (!pClientDE) return(DFALSE); if (!sAddress) return(DFALSE); // Try to connect to the given address... DBOOL db = NetStart_DoConsoleConnect(pClientDE, sAddress); if (!db) { if (_mbstrlen(sAddress) <= 0) pClientDE->CPrint("Unable to connect"); else pClientDE->CPrint("Unable to connect to %s", sAddress); return(DFALSE); } // All done... if (_mbstrlen(sAddress) > 0) pClientDE->CPrint("Connected to %s", sAddress); else pClientDE->CPrint("Connected"); g_pBloodClientShell->SetGameState(GS_MPLOADINGLEVEL); return(DTRUE); } DBOOL CBloodClientShell::DoMultiplayer(DBOOL bMinimize, DBOOL bHost) { CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return(DFALSE); pClientDE->PauseSounds(); if (bMinimize) { NetStart_MinimizeMainWnd(pClientDE); } NetStart ns; DBOOL bRet = NetStart_DoWizard(pClientDE, &ns, bHost ? NET_HOST : NET_JOIN); pClientDE->ResumeSounds(); if (bRet) { if (m_hstrTitle) { pClientDE->FreeString(m_hstrTitle); m_hstrTitle = 0; } if (m_hstrLoadScreen) { pClientDE->FreeString(m_hstrLoadScreen); m_hstrLoadScreen = 0; } if (m_nLoadScreenID) m_nLoadScreenID = 0; StartGameRequest req; memset(&req, 0, sizeof(req)); if (ns.m_bHost) { req.m_Type = STARTGAME_HOST; _mbscpy((unsigned char*)req.m_WorldName, (const unsigned char*)ns.m_sLevel); memcpy(&req.m_HostInfo, &ns.m_NetHost, sizeof(NetHost)); g_bIsHost = DTRUE; } else { req.m_Type = STARTGAME_CLIENT; req.m_pNetSession = ns.m_pNetSession; if (ns.m_bHaveTcpIp) { req.m_Type = STARTGAME_CLIENTTCP; _mbscpy((unsigned char*)req.m_TCPAddress, (const unsigned char*)ns.m_sAddress); } g_bIsHost = DFALSE; } req.m_pGameInfo = NetStart_GetGameStruct(); req.m_GameInfoLen = sizeof(NetGame_t); req.m_pClientData = NetStart_GetClientDataStruct(); req.m_ClientDataLen = sizeof(NetClientData_t); DRESULT dr = pClientDE->StartGame(&req); if (bMinimize) { NetStart_RestoreMainWnd(); } if (dr != LT_OK) { return(DFALSE); } } else { if (bMinimize) { NetStart_RestoreMainWnd(); } return(DFALSE); } NetStart_RunServerOptions(pClientDE); SetGameState(GS_MPLOADINGLEVEL); // All done... return(DTRUE); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::IsMultiplayerGame() // // PURPOSE: Are we playing a multiplayer game? // // --------------------------------------------------------------------------- // DBOOL CBloodClientShell::IsMultiplayerGame() { CClientDE* pClientDE = GetClientDE(); if (!pClientDE ) return DFALSE; int nGameMode = 0; pClientDE->GetGameMode(&nGameMode); if (nGameMode == STARTGAME_NORMAL || nGameMode == GAMEMODE_NONE) return DFALSE; return DTRUE; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::PlayMovie() // // PURPOSE: Plays the given movie // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::PlayMovie(CClientDE* pClientDE, char* sMovie, DBOOL bCheckExistOnly) { // Sanity checks... if (!pClientDE) return(DFALSE); if (!sMovie) return(DFALSE); // Check if movies are disabled... if (AdvancedDisableMovies()) { return(DFALSE); } // Check if we got a full path... char sMoviePath[256]; if (_mbsstr((const unsigned char*)sMovie, (const unsigned char*)"\\")) { _mbscpy((unsigned char*)sMoviePath, (const unsigned char*)sMovie); } else { sMoviePath[0] = '\0'; } // Check if we need to look for this movie... if (sMoviePath[0] == '\0') { // Check if the movie file exists locally... if (CWinUtil::FileExist(sMovie)) { _mbscpy((unsigned char*)sMoviePath, (const unsigned char*)sMovie); } else { // Look in a movies folder on the hard disk... char sTemp[256]; sprintf(sTemp, "Movies\\%s", sMovie); if (CWinUtil::FileExist(sTemp)) { _mbscpy((unsigned char*)sMoviePath, (const unsigned char*)sTemp); } else { // Look on the cd-rom... char chCdRom = CWinUtil::GetCdRomDriveWithGame(); if (chCdRom == 0) return(DFALSE); sprintf(sMoviePath, "%c:\\Movies\\%s", chCdRom, sMovie); if (!CWinUtil::FileExist(sMoviePath)) return(DFALSE); } } } if (sMoviePath[0] == '\0') return(DFALSE); // If we are only checking for existence, return now... if (bCheckExistOnly) { return(DTRUE); } // Play the movie... DDWORD nFlags = PLAYBACK_FULLSCREEN; DRESULT nResult = pClientDE->StartVideo(sMoviePath, nFlags); if (nResult != DE_OK) { return(DFALSE); } // All done... return(DTRUE); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::StartMovies() // // PURPOSE: Starts the movies and sets up the movie state for updating // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::StartMovies(CClientDE* pClientDE) { // Sanity checks... if (!pClientDE) return(DFALSE); #ifdef _DEMO return(DFALSE); #endif // Check if movies are disabled... if (AdvancedDisableMovies()) { return(DFALSE); } // Make sure the movies actually exist... if (!PlayMovie(pClientDE, "Monolith.smk", DTRUE)) { return(DFALSE); } // Set the movie state to the starting state... m_nMovieState = MOVIE_STARTLITH; // Set the game state... SetGameState(GS_MOVIES); // All done... return(DTRUE); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::EndMovies() // // PURPOSE: Ends the movies and returns the game state // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::EndMovies(CClientDE* pClientDE, DBOOL bShowTitle) { // Sanity checks... if (!pClientDE) return(DFALSE); // Stop the movies... pClientDE->StopVideo(); m_nMovieState = MOVIE_FINISHED; // Show the title screen if requested... #ifdef _DEBUG bShowTitle = DFALSE; #endif if (bShowTitle) { #ifdef _ADDON HSURFACE hTitleSurface = Splash_Display(pClientDE, "\\screens_ao\\title.pcx", DTRUE); #else HSURFACE hTitleSurface = Splash_Display(pClientDE, "\\screens\\title.pcx", DTRUE); #endif if (hTitleSurface) { CWinUtil::TimedKeyWait(VK_ESCAPE, VK_RETURN, VK_SPACE, 6.0f); pClientDE->DeleteSurface(hTitleSurface); hTitleSurface = DNULL; CWinUtil::Sleep(50); } } // Reset the menu game state... CWinUtil::RemoveKeyDownMessages(); SetGameState(GS_MENU); m_Menu.SetCurrentMenu(MENU_ID_MAINMENU, MENU_ID_MAINMENU); // All done... return(DTRUE); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::AdvanceMovies() // // PURPOSE: Advanced to the next movie // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::AdvanceMovies(CClientDE* pClientDE) { // Sanity checks... if (!pClientDE) return(DFALSE); // Stop the current movies... pClientDE->StopVideo(); // All done... return(DTRUE); } // ----------------------------------------------------------------------- // // // ROUTINE: CRiotClientShell::UpdateMoviesState() // // PURPOSE: Update movies // // ----------------------------------------------------------------------- // void CBloodClientShell::UpdateMoviesState() { // Sanity checks... CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return; // Update based on our current movie state... switch (m_nMovieState) { case MOVIE_STARTLITH: { if (!PlayMovie(pClientDE, "Monolith.smk")) { EndMovies(pClientDE); return; } m_nMovieState = MOVIE_PLAYINGLITH; break; } case MOVIE_PLAYINGLITH: { pClientDE->UpdateVideo(); if (pClientDE->IsVideoPlaying() != VIDEO_PLAYING) { m_nMovieState = MOVIE_STARTGTI; } break; } case MOVIE_STARTGTI: { if (!PlayMovie(pClientDE, "Gti.smk")) { EndMovies(pClientDE); return; } m_nMovieState = MOVIE_PLAYINGGTI; break; } case MOVIE_PLAYINGGTI: { pClientDE->UpdateVideo(); if (pClientDE->IsVideoPlaying() != VIDEO_PLAYING) { m_nMovieState = MOVIE_STARTINTRO; #ifdef _ADDON m_nMovieState = MOVIE_FINISHED; #endif } break; } case MOVIE_STARTINTRO: { if (!PlayMovie(pClientDE, "Intro.smk")) { EndMovies(pClientDE); return; } m_nMovieState = MOVIE_PLAYINGINTRO; break; } case MOVIE_PLAYINGINTRO: { pClientDE->UpdateVideo(); if (pClientDE->IsVideoPlaying() != VIDEO_PLAYING) { m_nMovieState = MOVIE_FINISHED; } break; } case MOVIE_FINISHED: default: { EndMovies(pClientDE, DTRUE); } } } // ----------------------------------------------------------------------- // // // ROUTINE: Abort // // PURPOSE: Aborts the game with a message and/or code // // ----------------------------------------------------------------------- // void Abort(char* sErrorMsg, DDWORD dwCode) { // Sanity checks... if (!g_pBloodClientShell) return; if (!g_pBloodClientShell->GetClientDE()) return; // Check if we've already aborted... if (g_bAborting) { return; } g_bAborting = DTRUE; // Build the error string... char sText[256]; if (dwCode != 0) { sprintf(sText, "%s (%lu)", sErrorMsg, dwCode); } else { _mbscpy((unsigned char*)sText, (const unsigned char*)sErrorMsg); } // Shutdown the engine with an error message... g_pBloodClientShell->GetClientDE()->ShutdownWithMessage(sText); } void Abort(int nErrorID, DDWORD dwCode) { // Sanity checks... if (!g_pBloodClientShell) return; if (!g_pBloodClientShell->GetClientDE()) return; // Load the string... char sText[256]; HSTRING hString = g_pBloodClientShell->GetClientDE()->FormatString(nErrorID); if (!hString) { hString = g_pBloodClientShell->GetClientDE()->FormatString(IDS_ERR_GENERIC); } if (hString) { _mbscpy((unsigned char*)sText, (const unsigned char*)g_pBloodClientShell->GetClientDE()->GetStringData(hString)); g_pBloodClientShell->GetClientDE()->FreeString(hString); } else { _mbscpy((unsigned char*)sText, (const unsigned char*)"ERROR - Unable to continue the game."); } // Let the main function do the real work... Abort(sText, dwCode); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuQuit // // PURPOSE: Quits the game immediately // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuQuit() { // Shutdown everything... CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return(DFALSE); pClientDE->Shutdown(); // All done... return(DTRUE); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuNewGame // // PURPOSE: Starts new game at the given difficulty level // // COMMENT: nDifficulty must be one of: DIFFICULTY_EASY, // DIFFICULTY_MEDIUM, or DIFFICULTY_HARD. // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuNewGame(int nDifficulty, int nCharacter, int nGameType) { // Remove the current save info... m_SavedGameInfo.ClearSaveSlot(SLOT_CURRENT); // Set the starting level... #ifdef _DEMO char* sFirstLevel = "Demo_01"; #else char* sFirstLevel = "01_SubwayA"; #endif // Set some starting flags... m_bFirstWorld = DTRUE; g_pClientDE->RunConsoleString("maxfps 0"); // Fill in the character info... if (!SetCharacterInfo(nCharacter, MULTIPLAY_SKIN_NORMAL)) { return(DFALSE); } // Start the game at the given character and difficulty... return(StartNewGame(sFirstLevel, STARTGAME_NORMAL, nGameType, LOADTYPE_NEW_GAME, nDifficulty)); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuNewNightmaresGame // // PURPOSE: Starts new nightmares game at the given difficulty level // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuNewNightmaresGame(int nDifficulty) { // Remove the current save info... m_SavedGameInfo.ClearSaveSlot(SLOT_CURRENT); // Set the starting level... char* sFirstLevel = "worlds_ao\\caleb1_cc_c"; // Set some starting flags... m_bFirstWorld = DTRUE; g_pClientDE->RunConsoleString("maxfps 0"); // Fill in the character info... if (!SetCharacterInfo(CHARACTER_CALEB, MULTIPLAY_SKIN_NORMAL)) { return(DFALSE); } // Start the game at the given character and difficulty... return(StartNewGame(sFirstLevel, STARTGAME_NORMAL, GAMETYPE_SINGLE, LOADTYPE_NEW_GAME, nDifficulty)); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuHostGame // // PURPOSE: Hosts a multiplayer network game // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuHostGame() { // Do the multipalyer wizard and host a net game... return(DoMultiplayer(DTRUE, DTRUE)); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuJoinGame // // PURPOSE: Joins a multiplayer network game // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuJoinGame() { // Do the multipalyer wizard and join a net game... return(DoMultiplayer(DTRUE, DFALSE)); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuCredits // // PURPOSE: Displays the credits // // COMMENT: The "lame" credits will be used if we're currently // in the middle of a game. // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuCredits() { // If we're currently in a game, do the lame credits... if (m_bInWorld) { m_Credits.Term(); CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return(DFALSE); if (!m_Credits.Init(pClientDE, this)) { return(DFALSE); } PauseGame(DTRUE); SetGameState(GS_CREDITS); return(DTRUE); } // If we're not in a game, do the cool credits... return(StartNewGame("Credits", STARTGAME_NORMAL, GAMETYPE_CUSTOM, LOADTYPE_NEW_GAME, DIFFICULTY_MEDIUM)); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuHelp // // PURPOSE: Display the help info // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuHelp() { // All done... return(DTRUE); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuLoadGame // // PURPOSE: Loads the given game slot // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuLoadGame(int nSlot) { // As we go, figure out the gametype... int nGameType = GAMETYPE_SINGLE; int nCharacter = GetCharacter(); // Check for the quick slot... if (nSlot == SLOT_QUICK) { _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)m_SavedGameInfo.gQuickSaveInfo.szCurrentLevel); nGameType = m_SavedGameInfo.gQuickSaveInfo.nGameType; nCharacter = m_SavedGameInfo.gQuickSaveInfo.nCharacter; } if (nSlot == SLOT_CURRENT) { _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)m_SavedGameInfo.gCurrentSaveInfo.szCurrentLevel); nGameType = m_SavedGameInfo.gCurrentSaveInfo.nGameType; nCharacter = m_SavedGameInfo.gCurrentSaveInfo.nCharacter; } // Check for a valid regular slot... if (nSlot != SLOT_QUICK && nSlot != SLOT_CURRENT) { if (nSlot < 0) return(DFALSE); if (nSlot >= MAX_SAVESLOTS) return(DFALSE); _mbscpy((unsigned char*)m_szFilename, (const unsigned char*)m_SavedGameInfo.gSaveSlotInfo[nSlot].szCurrentLevel); nGameType = m_SavedGameInfo.gSaveSlotInfo[nSlot].nGameType; nCharacter = m_SavedGameInfo.gSaveSlotInfo[nSlot].nCharacter; } // Make sure we have a level to load... if (_mbstrlen(m_szFilename) <= 0) { return(DFALSE); } // Copy slot to the current slot if (nSlot != SLOT_NONE && nSlot != SLOT_CURRENT) { m_SavedGameInfo.CopySlot(nSlot, SLOT_CURRENT); } // Special load type for current slot (autosave) DBYTE byLoadType = (nSlot == SLOT_CURRENT) ? LOADTYPE_RESTOREAUTOSAVE : LOADTYPE_RESTORESAVE; // Fill in the character info... if (!SetCharacterInfo(nCharacter, MULTIPLAY_SKIN_NORMAL)) { return(DFALSE); } // Validate the game type... if (nGameType != GAMETYPE_SINGLE && nGameType != GAMETYPE_ACTION && nGameType != GAMETYPE_CUSTOM) { nGameType = GAMETYPE_SINGLE; } // Load the game... return(StartNewGame(m_szFilename, STARTGAME_NORMAL, nGameType, byLoadType, DIFFICULTY_MEDIUM)); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuSaveGame // // PURPOSE: Saves the given game slot // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuSaveGame(int nSlot, DBYTE bySaveType) { // Make sure we are actually in a game & still alive... if (!m_bInWorld || m_bDead) return(DFALSE); if (bySaveType == SAVETYPE_CURRENT) { // Make sure this is a valid slot... if (nSlot < SLOT_QUICK || nSlot >= MAX_SAVESLOTS) return(DFALSE); // Set the saved game info data so we can copy to a save slot once the server // tells us the save is complete (see SMSG_SAVEGAME_ACK). m_SavedGameInfo.SetReservedSlot(nSlot); // Change the game state to reflect the fact that we are saving the game... SetGameState(GS_SAVING); } // Tell the server to save our game... CClientDE* pClientDE = GetClientDE(); if (!pClientDE) return(DFALSE); HMESSAGEWRITE hMsg = pClientDE->StartMessage(CMSG_SAVEGAME); pClientDE->WriteToMessageString(hMsg, m_szFilename); pClientDE->WriteToMessageByte(hMsg, bySaveType); SaveClientData( hMsg ); pClientDE->EndMessage(hMsg); // All done... return(DTRUE); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuLoadCustomLevel // // PURPOSE: Loads the given custom level // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuLoadCustomLevel(char* sLevel, int nDifficulty) { // Sanity checks... if (!sLevel) return(DFALSE); if (_mbstrlen(sLevel) <= 0) return(DFALSE); // Flag that we are starting a new game world... m_bFirstWorld = DTRUE; // Start a new game with the specified level and difficulty... return(StartNewGame(sLevel, STARTGAME_NORMAL, GAMETYPE_CUSTOM, LOADTYPE_NEW_GAME, nDifficulty)); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuReturnToGame // // PURPOSE: Returns from the menus to the game // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuReturnToGame() { if (IsInWorld()) { SetGameState(GS_PLAYING); PauseGame(DFALSE); if (g_bLevelChange3rdPersonCam) { if (g_pClientDE) g_pClientDE->SetInputState(DFALSE); if (!m_b3rdPerson) Set3rdPersonCamera(DTRUE); m_bDrawFragBar = DTRUE; } return DTRUE; } return DFALSE; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::MenuSetDetail // // PURPOSE: Sets the detail file cfg and checks the launcher settings // // ----------------------------------------------------------------------- // DBOOL CBloodClientShell::MenuSetDetail() { CClientDE* pClientDE = GetClientDE(); HCONSOLEVAR hVar; // General detail settings hVar = pClientDE->GetConsoleVar("GlobalDetail"); m_nGlobalDetail = (DBYTE)pClientDE->GetVarValueFloat (hVar); switch(m_nGlobalDetail) { case DETAIL_LOW: pClientDE->ReadConfigFile("detaillo.cfg"); break; case DETAIL_MEDIUM: pClientDE->ReadConfigFile("detailmd.cfg"); break; case DETAIL_HIGH: pClientDE->ReadConfigFile("detailhi.cfg"); break; } // record the original state of sound and music hVar = pClientDE->GetConsoleVar ("SoundEnable"); m_bSoundOriginallyEnabled = (DBOOL) pClientDE->GetVarValueFloat (hVar); hVar = pClientDE->GetConsoleVar ("MusicEnable"); m_bMusicOriginallyEnabled = (DBOOL) pClientDE->GetVarValueFloat (hVar); hVar = pClientDE->GetConsoleVar ("ModelFullbrite"); m_bModelFBOriginallyEnabled = (DBOOL) pClientDE->GetVarValueFloat (hVar); hVar = pClientDE->GetConsoleVar ("LightMap"); m_bLightmappingOriginallyEnabled = (DBOOL) pClientDE->GetVarValueFloat (hVar); // implement any advanced options here (before renderer is started) hVar = pClientDE->GetConsoleVar ("SoundEnable"); if (!hVar && !AdvancedDisableSound()) { pClientDE->RunConsoleString ("SoundEnable 1"); } else if (AdvancedDisableSound()) { pClientDE->RunConsoleString ("SoundEnable 0"); // [blg] is this ok? } hVar = pClientDE->GetConsoleVar ("MusicEnable"); if (!hVar && !AdvancedDisableMusic()) { pClientDE->RunConsoleString ("MusicEnable 1"); } else if (AdvancedDisableMusic()) { pClientDE->RunConsoleString ("MusicEnable 0"); // [blg] is this ok? } if (AdvancedDisableLightMap()) { pClientDE->RunConsoleString ("LightMap 0"); } if (AdvancedEnableOptSurf()) { pClientDE->RunConsoleString ("OptimizeSurfaces 1"); } if (AdvancedEnableTripBuf()) { pClientDE->RunConsoleString ("TripleBuffer 1"); } if (AdvancedDisableDx6Cmds()) { pClientDE->RunConsoleString ("UseDX6Commands 0"); } if (AdvancedEnableTJuncs()) { pClientDE->RunConsoleString ("FixTJunc 1"); } if (AdvancedDisableFog()) { pClientDE->RunConsoleString ("FogEnable 0"); } if (AdvancedDisableLines()) { pClientDE->RunConsoleString ("DrawLineSystems 0"); } if (AdvancedDisableModelFB()) { pClientDE->RunConsoleString ("ModelFullBrite 0"); } if (AdvancedDisableJoystick()) { pClientDE->RunConsoleString ("JoystickDisable 1"); } if (AdvancedEnablePixelDoubling()) { pClientDE->RunConsoleString ("PixelDouble 1"); } if (AdvancedEnableMultiTexturing()) { pClientDE->RunConsoleString ("Force1Pass 1"); } return DTRUE; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::HandleInvAction() // // PURPOSE: The player has hit an exit trigger. // // ----------------------------------------------------------------------- // void CBloodClientShell::HandleInvAction( DBYTE nType, DBOOL bActivate ) { switch( nType ) { case INV_BINOCULARS: PlaySoundLocal( "sounds\\powerups\\binoculars.wav", SOUNDPRIORITY_PLAYER_LOW ); m_bBinocularsActive = bActivate; break; case INV_MEDKIT: PlaySoundLocal( "sounds\\powerups\\medikit.wav", SOUNDPRIORITY_PLAYER_LOW ); break; case INV_FLASHLIGHT: PlaySoundLocal( "sounds\\powerups\\flashlight.wav", SOUNDPRIORITY_PLAYER_LOW ); break; case INV_NIGHTGOGGLES: m_bNightGogglesActive = bActivate; break; default: break; } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SetMouseSensitivity() // // PURPOSE: Sets the mouse sensitivity // // ----------------------------------------------------------------------- // void CBloodClientShell::SetMouseSensitivity(float fSensitivity) { CClientDE *pClientDE=GetClientDE(); if (!pClientDE) { return; } char szDeviceName[256]; char szXAxis[256]; char szYAxis[256]; memset(szDeviceName, 0, sizeof(szDeviceName)); memset(szXAxis, 0, sizeof(szXAxis)); memset(szYAxis, 0, sizeof(szYAxis)); // Get the mouse device information GetMouseDeviceInfo(szDeviceName, sizeof(szDeviceName), szXAxis, sizeof(szXAxis), szYAxis, sizeof(szYAxis)); if (_mbstrlen(szDeviceName) == 0) { return; } // Run the console strings char strConsole[256]; if (_mbstrlen(szXAxis) > 0) { sprintf (strConsole, "scale \"%s\" \"%s\" %f", szDeviceName, szXAxis, 0.00125f + (fSensitivity * 0.001125f)); pClientDE->RunConsoleString (strConsole); } if (_mbstrlen(szYAxis) > 0) { sprintf (strConsole, "scale \"%s\" \"%s\" %f", szDeviceName, szYAxis, 0.00125f + (fSensitivity * 0.001125f)); pClientDE->RunConsoleString (strConsole); } sprintf(strConsole, "MouseSensitivity %f", fSensitivity); pClientDE->RunConsoleString(strConsole); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::GetMouseDeviceInfo() // // PURPOSE: Get the mouse device name and axis names // // ----------------------------------------------------------------------- // void CBloodClientShell::GetMouseDeviceInfo(char *lpszDeviceName, int nDeviceBufferSize, char *lpszXAxis, int nXAxisBufferSize, char *lpszYAxis, int nYAxisBufferSize) { // Most of this code was taken from Shogo... CClientDE *pClientDE=GetClientDE(); if (!pClientDE) { return; } // get the mouse device name DRESULT result = pClientDE->GetDeviceName (DEVICETYPE_MOUSE, lpszDeviceName, nDeviceBufferSize); if (result == LT_OK) { DeviceObject* pList = pClientDE->GetDeviceObjects (DEVICETYPE_MOUSE); DeviceObject* ptr = pList; while (ptr) { if (ptr->m_ObjectType == CONTROLTYPE_XAXIS) { _mbsncpy((unsigned char*)lpszXAxis, (const unsigned char*)ptr->m_ObjectName, nXAxisBufferSize); } if (ptr->m_ObjectType == CONTROLTYPE_YAXIS) { _mbsncpy((unsigned char*)lpszYAxis, (const unsigned char*)ptr->m_ObjectName, nYAxisBufferSize); } ptr = ptr->m_pNext; } if (pList) { pClientDE->FreeDeviceObjects (pList); } } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::GetMouseSensitivity() // // PURPOSE: Gets the mouse sensitivity // // ----------------------------------------------------------------------- // float CBloodClientShell::GetMouseSensitivity() { CClientDE *pClientDE=GetClientDE(); if (!pClientDE) { return 1.5f; } // Load the mouse sensitivity HCONSOLEVAR hVar=pClientDE->GetConsoleVar("MouseSensitivity"); if (hVar) { return pClientDE->GetVarValueFloat(hVar); } else { return 1.5f; } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SetUseJoystick() // // PURPOSE: Turns the "UseJoystick" console variable on and off // // ----------------------------------------------------------------------- // void CBloodClientShell::SetUseJoystick(DBOOL bUseJoystick) { m_bUseJoystick=bUseJoystick; CClientDE *pClientDE=GetClientDE(); if (!pClientDE) { return; } if (m_bUseJoystick) { pClientDE->RunConsoleString("+usejoystick 1"); // probably don't need this, should remove and just use joystickdisable everywhere! pClientDE->RunConsoleString("+joystickdisable 0"); // the engine looks at this one } else { pClientDE->RunConsoleString("+usejoystick 0"); // probably don't need this, should remove and just use joystickdisable everywhere! pClientDE->RunConsoleString("+joystickdisable 1"); // the engine looks at this one } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SetKeyboardTurnRate() // // PURPOSE: Sets the keyboard turn rate // // ----------------------------------------------------------------------- // void CBloodClientShell::SetKeyboardTurnRate(float fRate) { m_fKeyboardTurnRate=fRate; CClientDE *pClientDE=GetClientDE(); if (!pClientDE) { return; } char szTemp[256]; sprintf(szTemp, "+KeyboardTurnRate %f", m_fKeyboardTurnRate); pClientDE->RunConsoleString(szTemp); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::DoMessageBox() // // PURPOSE: Puts a message box on the screen. It is removed when ENTER, ESC, // or SPACE is pressed or on the next page flip if bAsync is FALSE. // // ----------------------------------------------------------------------- // void CBloodClientShell::DoMessageBox(char *lpszMessage, DBOOL bAsync) { // TODO: Make this localizable ClientDE *pClientDE=GetClientDE(); HSTRING hString=pClientDE->CreateString(lpszMessage); m_messageBox.SetText(hString); pClientDE->FreeString(hString); m_messageBox.SetCommandHandler(&m_messageBoxHandler); m_messageBox.RemoveKeys(); m_messageBox.AddKey(VK_ESCAPE, MESSAGE_BOX_ID_KILL); m_messageBox.AddKey(VK_RETURN, MESSAGE_BOX_ID_KILL); m_messageBox.AddKey(VK_SPACE, MESSAGE_BOX_ID_KILL); m_bInMessageBox=DTRUE; if (!bAsync) { // Render the message box to the screen PostUpdate(); PostUpdate(); m_bInMessageBox=DFALSE; } } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::KillMessageBox() // // PURPOSE: Kills the message box // // ----------------------------------------------------------------------- // void CBloodClientShell::KillMessageBox() { m_bInMessageBox=DFALSE; } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::ShowInfoBox // // PURPOSE: Displays an informational message box. // Params: lpszMessage: The message to be displayed // bAddOkButton: TRUE if the box should have an OK button to close // // ----------------------------------------------------------------------- // void CBloodClientShell::ShowInfoBox(char *lpszMessage, DBOOL bAddOkButton) { if (!lpszMessage) return; CSPrint(lpszMessage); } // ----------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::KillInfoBox // // PURPOSE: Stops the display of any info message box. // // ----------------------------------------------------------------------- // void CBloodClientShell::KillInfoBox() { } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::HandleFiring() // // PURPOSE: Checks for firing commands and updates the weapon object // // --------------------------------------------------------------------------- // DBOOL CBloodClientShell::HandleFiring() { ClientDE *pClientDE=GetClientDE(); DRotation rotGun; DVector vRGunPos, vLGunPos, vMyPos; HLOCALOBJ hPlayerObj = pClientDE->GetClientObject(); pClientDE->GetObjectPos(hPlayerObj, &vMyPos); VEC_ADD(vRGunPos, vMyPos, cdata.GunMuzzlePos); VEC_ADD(vLGunPos, vMyPos, cdata.lGunMuzzlePos); ROT_COPY(rotGun, m_Rotation); if (!m_bDead && !m_bSpectatorMode) { DBOOL bFiring = DFALSE; DBOOL bAltFiring = DFALSE; if (cdata.byFlags & CDATA_CANMOVE) { bFiring = (m_pMoveMgr->GetControlFlags() & CTRLFLAG_FIRE) != 0; bAltFiring = (!bFiring && (m_pMoveMgr->GetControlFlags() & CTRLFLAG_ALTFIRE)); } // If we have duel weapons, make the altfire the same as the primary if (m_pWeapon && m_pLWeapon && bAltFiring) { bFiring = DTRUE; bAltFiring = DFALSE; } if (m_pWeapon) m_pWeapon->UpdateFiringState(&vRGunPos, &rotGun, bFiring, bAltFiring); if (m_pLWeapon) m_pLWeapon->UpdateFiringState(&vLGunPos, &rotGun, bFiring, bAltFiring); } else if (m_bDead) { if (m_pWeapon) m_pWeapon->CancelFiringState(); if (m_pLWeapon) m_pLWeapon->CancelFiringState(); /* if (m_pWeapon) m_pWeapon->UpdateFiringState(&vRGunPos, &rotGun, DFALSE, DFALSE); if (m_pLWeapon) m_pLWeapon->UpdateFiringState(&vLGunPos, &rotGun, DFALSE, DFALSE); */ } return DTRUE; } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::CreateWeapon() // // PURPOSE: Creates a view weapon model. // // --------------------------------------------------------------------------- // CViewWeapon* CBloodClientShell::CreateWeapon(DBYTE byType, DBOOL bLeftHand) { ClientDE *pClientDE = GetClientDE(); CViewWeapon *w = DNULL; switch (byType) { case WEAP_BERETTA: w = new CBeretta; break; case WEAP_SHOTGUN: w = new CShotgun; break; case WEAP_SNIPERRIFLE: w = new CSniperRifle; break; case WEAP_ASSAULTRIFLE: w = new CAssaultRifle; break; case WEAP_SUBMACHINEGUN: w = new CSubMachineGun; break; case WEAP_FLAREGUN: w = new CFlareGun; break; case WEAP_HOWITZER: w = new CHowitzer; break; case WEAP_BUGSPRAY: w = new CBugSpray; break; case WEAP_NAPALMCANNON: w = new CNapalmCannon; break; case WEAP_MINIGUN: w = new CMiniGun; break; case WEAP_VOODOO: w = new CVoodooDoll; break; case WEAP_ORB: w = new COrb; break; case WEAP_DEATHRAY: w = new CDeathRay; break; case WEAP_LIFELEECH: w = new CLifeLeech; break; case WEAP_TESLACANNON: w = new CTeslaCannon; break; case WEAP_SINGULARITY: w = new CSingularity; break; case WEAP_MELEE: w = new CMelee; break; #ifdef _ADD_ON case WEAP_COMBATSHOTGUN: w = new CCombatShotgun; break; case WEAP_FLAYER: w = new CFlayer; break; #endif #ifndef _DEMO case WEAP_PROXIMITYBOMB: w = new CWeapProximityBomb; break; case WEAP_REMOTEBOMB: w = new CWeapRemoteBomb; break; case WEAP_TIMEBOMB: w = new CWeapTimeBomb; break; #endif } if (w) w->Create(pClientDE, byType, bLeftHand); return w; } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::CreateWeapon() // // PURPOSE: Creates a view weapon model. // // --------------------------------------------------------------------------- // void CBloodClientShell::SetPowerBarLevel(DFLOAT fPercent) { ClientDE *pClientDE = GetClientDE(); if((fPercent <= 0.0f) || (fPercent >= 1.0f)) m_NewStatusBar.TurnOffPowerBar(); else m_NewStatusBar.SetPowerBarLevel(BARTAB_THROW, fPercent); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::PlaySound // // PURPOSE: Plays the given sound // // --------------------------------------------------------------------------- // HSOUNDDE CBloodClientShell::PlaySound(char* sSound, DBOOL bStream, DBOOL bLoop, DBOOL bGetHandle) { // Sanity checks... if (!g_pClientDE) return(NULL); // Fill out the structure... PlaySoundInfo playSoundInfo; PLAYSOUNDINFO_INIT(playSoundInfo); playSoundInfo.m_dwFlags = PLAYSOUND_LOCAL; if (bStream) { playSoundInfo.m_dwFlags |= PLAYSOUND_FILESTREAM; } if (bLoop) { playSoundInfo.m_dwFlags |= PLAYSOUND_LOOP; } if (bGetHandle) { playSoundInfo.m_dwFlags |= PLAYSOUND_GETHANDLE; } _mbsncpy((unsigned char*)playSoundInfo.m_szSoundName, (const unsigned char*)sSound, sizeof(playSoundInfo.m_szSoundName) - 1); playSoundInfo.m_nPriority = SOUNDPRIORITY_MISC_MEDIUM; // Play the sound... if(g_pClientDE->PlaySound(&playSoundInfo) != LT_OK ) return NULL; return playSoundInfo.m_hSound; } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::DisplayStatusBarFlagIcon // // PURPOSE: Controls the display of the status bar flag icon // // --------------------------------------------------------------------------- // void CBloodClientShell::DisplayStatusBarFlagIcon(DBOOL bDisplay) { // Check if we should turn if off... if (!bDisplay) { m_NewStatusBar.DisplayFlag(MULTIFLAG_NONE); return; } // Figure out which team we're on... if (!g_pClientDE) return; DDWORD dwLocalID = 0; g_pClientDE->GetLocalClientID(&dwLocalID); CTeam* pTeam = m_TeamMgr.GetTeamFromPlayerID(dwLocalID); if (!pTeam) return; BYTE byFlagType = MULTIFLAG_NONE; if (pTeam->GetID() == TEAM_1) byFlagType = MULTIFLAG_RED; // show the other teams flag! if (pTeam->GetID() == TEAM_2) byFlagType = MULTIFLAG_BLUE; m_NewStatusBar.DisplayFlag(byFlagType); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::AssignFrags // // PURPOSE: Assigns frags as necessary based on the game options // // --------------------------------------------------------------------------- // void CBloodClientShell::AssignFrags(DDWORD dwLocalID, DDWORD dwVictim, DDWORD dwKiller) { if (dwVictim == dwKiller) { m_FragInfo.RemoveFrag(dwLocalID, dwKiller); m_TeamMgr.AddPlayerFrags(dwKiller, -1); } else { if (IsMultiplayerTeamBasedGame()) { if (!m_TeamMgr.IsOnSameTeam(dwKiller, dwVictim)) // not on same team { if (!IsNetOnlyFlagScores() && !IsNetOnlyGoalScores()) { m_FragInfo.AddFrag(dwLocalID, dwKiller); m_TeamMgr.AddPlayerFrags(dwKiller, +1); } } else // on the same team { if (IsNetFriendlyFire() && IsNetNegTeamFrags()) { m_FragInfo.RemoveFrag(dwLocalID, dwKiller); m_TeamMgr.AddPlayerFrags(dwKiller, -1); } } } else { m_FragInfo.AddFrag(dwLocalID, dwKiller); } } } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::StartWonkyVision // // PURPOSE: Turns on wonky vision // // --------------------------------------------------------------------------- // void CBloodClientShell::StartWonkyVision(DFLOAT fWonkyTime, DBOOL bWonkyNoMove) { if (fWonkyTime == 0) return; m_fWonkyTime = fWonkyTime; m_bWonkyVision = DTRUE; m_bWonkyNoMove = bWonkyNoMove; } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::EndWonkyVision // // PURPOSE: Turns off wonky vision // // --------------------------------------------------------------------------- // void CBloodClientShell::EndWonkyVision() { m_fWonkyTime = 0; m_bWonkyVision = DFALSE; m_bWonkyNoMove = DFALSE; } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::SetCharacterInfo // // PURPOSE: Sets the character info for the given character // // --------------------------------------------------------------------------- // DBOOL CBloodClientShell::SetCharacterInfo(int nCharacter, int nSkin) { m_Config.nCharacter = nCharacter; m_Config.nSkin = nSkin; switch (m_Config.nCharacter) { case CHARACTER_CALEB: { m_Config.nStrength = 5; m_Config.nSpeed = 3; m_Config.nResistance = 3; m_Config.nMagic = 1; break; } case CHARACTER_OPHELIA: { m_Config.nStrength = 2; m_Config.nSpeed = 5; m_Config.nResistance = 1; m_Config.nMagic = 4; break; } case CHARACTER_ISHMAEL: { m_Config.nStrength = 1; m_Config.nSpeed = 3; m_Config.nResistance = 3; m_Config.nMagic = 5; break; } case CHARACTER_GABREILLA: { m_Config.nStrength = 5; m_Config.nSpeed = 1; m_Config.nResistance = 5; m_Config.nMagic = 1; break; } #ifdef _ADDON case CHARACTER_M_CULTIST: { m_Config.nStrength = 5; m_Config.nSpeed = 3; m_Config.nResistance = 3; m_Config.nMagic = 1; break; } case CHARACTER_F_CULTIST: { m_Config.nStrength = 2; m_Config.nSpeed = 5; m_Config.nResistance = 1; m_Config.nMagic = 4; break; } case CHARACTER_SOULDRUDGE: { m_Config.nStrength = 1; m_Config.nSpeed = 3; m_Config.nResistance = 3; m_Config.nMagic = 5; break; } case CHARACTER_PROPHET: { m_Config.nStrength = 5; m_Config.nSpeed = 1; m_Config.nResistance = 5; m_Config.nMagic = 1; break; } #endif default: return(DFALSE); } // All done... return(DTRUE); } // --------------------------------------------------------------------------- // // // ROUTINE: CBloodClientShell::ResetPlayerInventory // // PURPOSE: // // --------------------------------------------------------------------------- // void CBloodClientShell::ResetPlayerInventory() { ClientDE *pClientDE=GetClientDE(); // Clear the weapon info for (int i=0;iStartMessage(CMSG_RESETPLAYERINVENTORY); pClientDE->EndMessage(hMessage); }