Initial commit: ROW Client source code
Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
536
Library/dxx8/samples/Multimedia/Demos/Duel/duel.cpp
Normal file
536
Library/dxx8/samples/Multimedia/Demos/Duel/duel.cpp
Normal file
@@ -0,0 +1,536 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// File: Duel.cpp
|
||||
//
|
||||
// Desc: Multi-player game
|
||||
//
|
||||
// Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "duel.h"
|
||||
#include "gameproc.h"
|
||||
#include "gfx.h"
|
||||
#include "DPUtil.h"
|
||||
#include "diutil.h"
|
||||
#include "dsutil.h"
|
||||
#include "lobby.h"
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Globals
|
||||
//-----------------------------------------------------------------------------
|
||||
// This GUID allows DirectPlay to find other instances of the same game on
|
||||
// the network. So it must be unique for every game, and the same for
|
||||
// every instance of that game. // {33925241-05F8-11d0-8063-00A0C90AE891}
|
||||
GUID g_AppGUID = { 0x33925241, 0x5f8, 0x11d0, { 0x80, 0x63, 0x0, 0xa0, 0xc9, 0xa, 0xe8, 0x91 } };
|
||||
|
||||
extern DWORD g_dwFrameCount;
|
||||
extern DWORD g_dwFrameTime;
|
||||
extern int g_nProgramState;
|
||||
extern SHIP g_OurShip;
|
||||
extern DPID g_LocalPlayerDPID;
|
||||
|
||||
static BOOL g_bReinitialize; // Used for switching display modes
|
||||
|
||||
TCHAR g_strAppName[256] = "Duel"; // The name of the sample
|
||||
HANDLE g_hDPMessageEvent = NULL; // Not used in this sample, needed for DPConnect.cpp
|
||||
TCHAR g_strLocalPlayerName[MAX_PLAYER_NAME]; // Local player name
|
||||
TCHAR g_strSessionName[MAX_SESSION_NAME]; // Default session name
|
||||
TCHAR g_strPreferredProvider[MAX_SESSION_NAME]; // Default preferred provider
|
||||
|
||||
LPDPLCONNECTION g_pDPLConnection = NULL;
|
||||
LPDIRECTPLAYLOBBY3 g_pDPLobby = NULL;
|
||||
|
||||
HWND g_hwndMain; // Main application window handle
|
||||
HKEY g_hDuelKey = NULL; // Duel registry key handle
|
||||
HINSTANCE g_hInst; // Application instance handle
|
||||
BOOL g_bShowFrameCount=TRUE; // Show FPS ?
|
||||
BOOL g_bIsActive; // Is the application active ?
|
||||
BOOL g_bHostPlayer; // Are we hosting or joining a game
|
||||
DWORD g_dwKeys; // User keyboard input
|
||||
DWORD g_dwOldKeys; // Last frame's keyboard input
|
||||
BOOL g_bFullscreen=FALSE; // Window or FullScreen mode ?
|
||||
RECT g_rcWindow; // client rectangle of main window
|
||||
BOOL g_bReliable; // sends are reliable
|
||||
BOOL g_bAsync; // asynchronous sends
|
||||
BOOL g_bAsyncSupported; // asynchronous sends supported
|
||||
BOOL g_bUseProtocol; // DirectPlay Protocol messaging
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Function prototypes
|
||||
//-----------------------------------------------------------------------------
|
||||
extern int DPConnect_StartDirectPlayConnect( HINSTANCE hInst, BOOL bBackTrack = FALSE );
|
||||
extern HRESULT DPConnect_CheckForLobbyLaunch( BOOL* pbLaunchedByLobby );
|
||||
|
||||
LRESULT CALLBACK MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
|
||||
HRESULT InitApplication( HINSTANCE hInst );
|
||||
HRESULT ReadRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue, DWORD dwLength, TCHAR* strDefault );
|
||||
HRESULT WriteRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue );
|
||||
VOID CleanupApplication();
|
||||
BOOL WasLaunchedByLobby();
|
||||
BOOL FinishLobbyLaunch();
|
||||
VOID DoHelp();
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: WinMain()
|
||||
// Desc:
|
||||
//-----------------------------------------------------------------------------
|
||||
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
|
||||
{
|
||||
MSG msg;
|
||||
BOOL bLaunchedByLobby;
|
||||
HRESULT hr;
|
||||
|
||||
g_hInst = hInstance;
|
||||
|
||||
// Read information from registry
|
||||
RegCreateKeyEx( HKEY_CURRENT_USER, DUEL_KEY, 0, NULL,
|
||||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
|
||||
&g_hDuelKey, NULL );
|
||||
|
||||
ReadRegKey( g_hDuelKey, "Player Name",
|
||||
g_strLocalPlayerName, MAX_PLAYER_NAME, "" );
|
||||
ReadRegKey( g_hDuelKey, "Session Name",
|
||||
g_strSessionName, MAX_SESSION_NAME, "" );
|
||||
ReadRegKey( g_hDuelKey, "Preferred Provider",
|
||||
g_strPreferredProvider, MAX_SESSION_NAME, "" );
|
||||
|
||||
CoInitialize( NULL );
|
||||
|
||||
if( FAILED( InitApplication( hInstance ) ) )
|
||||
return 0;
|
||||
|
||||
// See if we were launched from a lobby server
|
||||
hr = DPConnect_CheckForLobbyLaunch( &bLaunchedByLobby );
|
||||
if( FAILED(hr) )
|
||||
return 1;
|
||||
|
||||
if( bLaunchedByLobby )
|
||||
{
|
||||
// Start game
|
||||
PostMessage( g_hwndMain, UM_LAUNCH, 0, 0 );
|
||||
g_bIsActive = TRUE;
|
||||
}
|
||||
|
||||
g_dwFrameTime = timeGetTime();
|
||||
|
||||
while( TRUE )
|
||||
{
|
||||
if( g_bIsActive )
|
||||
{
|
||||
// Any windows messages ? (returns immediately)
|
||||
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
|
||||
{
|
||||
if( !GetMessage( &msg, NULL, 0, 0 ) )
|
||||
break;
|
||||
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Poll our receive queue. Polling is used in the sample only for simplicity.
|
||||
// Receiving messages using an event is the recommended way.
|
||||
if( g_nProgramState != PS_SPLASH )
|
||||
{
|
||||
ReceiveMessages();
|
||||
LobbyMessageReceive(LMR_PROPERTIES);
|
||||
}
|
||||
|
||||
// update screen
|
||||
if( !UpdateFrame() )
|
||||
ExitGame(); // posts QUIT msg
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Any windows messages ? (blocks until a message arrives)
|
||||
if( !GetMessage( &msg, NULL, 0, 0 ) )
|
||||
break;
|
||||
|
||||
TranslateMessage( &msg );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
}
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
// Write information to the registry
|
||||
WriteRegKey( g_hDuelKey, "Player Name", g_strLocalPlayerName );
|
||||
WriteRegKey( g_hDuelKey, "Session Name", g_strSessionName );
|
||||
WriteRegKey( g_hDuelKey, "Preferred Provider", g_strPreferredProvider );
|
||||
|
||||
return (int)msg.wParam;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: MainWndproc()
|
||||
// Desc: Callback for all Windows messages
|
||||
//-----------------------------------------------------------------------------
|
||||
LRESULT CALLBACK MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
case WM_SIZE:
|
||||
case WM_MOVE:
|
||||
// Get the client rectangle
|
||||
if( g_bFullscreen )
|
||||
{
|
||||
SetRect( &g_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN),
|
||||
GetSystemMetrics(SM_CYSCREEN) );
|
||||
}
|
||||
else
|
||||
{
|
||||
GetClientRect( hWnd, &g_rcWindow );
|
||||
ClientToScreen( hWnd, (POINT*)&g_rcWindow );
|
||||
ClientToScreen( hWnd, (POINT*)&g_rcWindow+1 );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
// Ignore this message during reinitializing graphics
|
||||
if( g_bReinitialize )
|
||||
return 0;
|
||||
|
||||
// When we are deactivated, although we don't update our screen, we
|
||||
// still need to to empty our receive queue periodically as
|
||||
// messages will pile up otherwise. Polling the receive queue
|
||||
// continuously even when we are deactivated causes our app to
|
||||
// consume all the CPU time. To avoid hogging the CPU, we block on
|
||||
// GetMessage() WIN API and setup a timer to wake ourselves up at
|
||||
// regular intervals to process our messages.
|
||||
|
||||
if( LOWORD(wParam) == WA_INACTIVE )
|
||||
{
|
||||
// Aeactivated
|
||||
g_bIsActive = FALSE;
|
||||
if( PS_ACTIVE == g_nProgramState )
|
||||
SetTimer( hWnd, RECEIVE_TIMER_ID, RECEIVE_TIMEOUT, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Activated
|
||||
g_bIsActive = TRUE;
|
||||
if( PS_ACTIVE == g_nProgramState )
|
||||
KillTimer( hWnd, RECEIVE_TIMER_ID );
|
||||
}
|
||||
|
||||
// set game palette, if activated in game mode
|
||||
if( g_bIsActive && (g_nProgramState != PS_SPLASH) )
|
||||
SetGamePalette();
|
||||
|
||||
DIUtil_ReacquireInputDevices();
|
||||
|
||||
return 0;
|
||||
|
||||
case WM_CREATE:
|
||||
break;
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
switch( wParam )
|
||||
{
|
||||
// Handle ALT+ENTER (fullscreen/window mode)
|
||||
case VK_RETURN:
|
||||
// Mode switch is allowed only during the game
|
||||
if( g_nProgramState == PS_ACTIVE )
|
||||
{
|
||||
g_bReinitialize = TRUE;
|
||||
ReleaseLocalData(); //only sound buffers have to be rels'd anyway.
|
||||
CleanupGameSounds();
|
||||
DIUtil_CleanupInput();
|
||||
CleanupGraphics();
|
||||
DestroyWindow( g_hwndMain );
|
||||
g_bFullscreen = !g_bFullscreen;
|
||||
InitGraphics();
|
||||
DIUtil_InitInput( g_hwndMain );
|
||||
InitializeGameSounds();
|
||||
InitLocalSoundData();
|
||||
g_bReinitialize = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
switch( wParam )
|
||||
{
|
||||
case 'a':
|
||||
case 'A':
|
||||
// Toggle Async sends on/off
|
||||
if( g_bAsyncSupported )
|
||||
{
|
||||
g_bAsync = !g_bAsync;
|
||||
UpdateTitle(); // caption bar status
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
case 'R':
|
||||
// Toggle reliable sends
|
||||
g_bReliable = !g_bReliable;
|
||||
UpdateTitle();
|
||||
break;
|
||||
|
||||
case VK_F1:
|
||||
// Display help
|
||||
DoHelp();
|
||||
break;
|
||||
|
||||
case VK_F5:
|
||||
// Toggle frame rate display
|
||||
g_bShowFrameCount = !g_bShowFrameCount;
|
||||
if( g_bShowFrameCount )
|
||||
{
|
||||
g_dwFrameCount = 0;
|
||||
g_dwFrameTime = timeGetTime();
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_RETURN:
|
||||
// Launch game setup wizard
|
||||
if( (g_nProgramState == PS_SPLASH) && !g_bFullscreen )
|
||||
{
|
||||
int nExitCode;
|
||||
nExitCode = DPConnect_StartDirectPlayConnect( g_hInst, FALSE );
|
||||
|
||||
// Figure out what happened, and post a reflecting message
|
||||
if( nExitCode == EXITCODE_FORWARD )
|
||||
PostMessage(g_hwndMain, UM_LAUNCH, 0, 0);
|
||||
|
||||
if( nExitCode == EXITCODE_QUIT )
|
||||
PostMessage(g_hwndMain, UM_ABORT, 0, 0);
|
||||
|
||||
if( nExitCode == EXITCODE_LOBBYCONNECT )
|
||||
PostMessage( g_hwndMain, UM_LAUNCH, 0, 0 );
|
||||
|
||||
if( nExitCode == EXITCODE_ERROR )
|
||||
{
|
||||
MessageBox( g_hwndMain, TEXT("Mutliplayer connect failed. "
|
||||
"The sample will now quit."),
|
||||
TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
|
||||
PostMessage(g_hwndMain, UM_ABORT, 0, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_ESCAPE:
|
||||
case VK_F12:
|
||||
// Exit the game
|
||||
ExitGame();
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
return 1;
|
||||
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint( hWnd, &ps );
|
||||
if( g_nProgramState == PS_SPLASH )
|
||||
{
|
||||
// Display the splash screen
|
||||
BltSplashScreen( NULL );
|
||||
}
|
||||
|
||||
EndPaint( hWnd, &ps );
|
||||
return 1;
|
||||
|
||||
case UM_LAUNCH:
|
||||
case UM_ABORT:
|
||||
// if we were launched by the lobby and not (failed to finish a lobby launch)
|
||||
// where wParam is bLobbyLaunched
|
||||
if( msg == UM_LAUNCH )
|
||||
{
|
||||
// Init lobby msg support for reporting score
|
||||
// Note that we don't release the lobby object
|
||||
LobbyMessageInit();
|
||||
|
||||
// Start the game in rest mode
|
||||
g_nProgramState = PS_REST;
|
||||
LaunchGame();
|
||||
return 1;
|
||||
}
|
||||
// Else aborting
|
||||
ExitGame();
|
||||
return 1;
|
||||
|
||||
case WM_TIMER:
|
||||
ReceiveMessages();
|
||||
LobbyMessageReceive( LMR_PROPERTIES );
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
// If g_bReinitialize is TRUE don't quit, we are just switching
|
||||
// display modes
|
||||
if( !g_bReinitialize )
|
||||
{
|
||||
CleanupApplication();
|
||||
PostQuitMessage( 0 );
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc( hWnd, msg, wParam, lParam );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: InitApplication()
|
||||
// Desc: Do that initialization stuff...
|
||||
//-----------------------------------------------------------------------------
|
||||
HRESULT InitApplication( HINSTANCE hInst )
|
||||
{
|
||||
WNDCLASS wndClass = { CS_DBLCLKS, MainWndproc, 0, 0, hInst,
|
||||
LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN)),
|
||||
LoadCursor(NULL, IDC_ARROW),
|
||||
(HBRUSH)GetStockObject(BLACK_BRUSH),
|
||||
NULL, TEXT("DuelClass") };
|
||||
RegisterClass( &wndClass );
|
||||
|
||||
// Initialize all components
|
||||
if( FAILED( InitGraphics() ) )
|
||||
return E_FAIL;
|
||||
|
||||
if( FAILED( DIUtil_InitInput( g_hwndMain ) ) )
|
||||
return E_FAIL;
|
||||
|
||||
if( FAILED( InitializeGameSounds() ) )
|
||||
{
|
||||
// Can play game without sound. Do not exit
|
||||
}
|
||||
|
||||
// Start in splash mode
|
||||
g_nProgramState = PS_SPLASH;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: CleanupApplication()
|
||||
// Desc: Calls clean up on all components
|
||||
//-----------------------------------------------------------------------------
|
||||
VOID CleanupApplication()
|
||||
{
|
||||
CleanupComm();
|
||||
CleanupGameSounds();
|
||||
CleanupGraphics();
|
||||
DIUtil_CleanupInput();
|
||||
DPLobbyRelease(); // in case we were doing lobby messages
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: ShowError()
|
||||
// Desc: Displays error to the user
|
||||
//-----------------------------------------------------------------------------
|
||||
VOID ShowError( int iStrID )
|
||||
{
|
||||
TCHAR strMsg[MAX_ERRORMSG];
|
||||
LoadString( g_hInst, iStrID, strMsg, MAX_ERRORMSG );
|
||||
MessageBox( g_hwndMain, strMsg, TEXT("Duel Message"), MB_OK );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: UpdateTitle()
|
||||
// Desc: Updates the window title based on application status
|
||||
//-----------------------------------------------------------------------------
|
||||
VOID UpdateTitle()
|
||||
{
|
||||
// Build the window title
|
||||
TCHAR strTitle[MAX_WINDOWTITLE] = TEXT("Duel");
|
||||
|
||||
// State options in window title
|
||||
if( g_bHostPlayer | g_bUseProtocol | g_bReliable | g_bAsync )
|
||||
{
|
||||
strcat( strTitle, " - |" );
|
||||
if( g_bHostPlayer )
|
||||
_tcscat( strTitle, TEXT(" Host |") );
|
||||
if( g_bUseProtocol )
|
||||
_tcscat( strTitle, TEXT(" Protocol |") );
|
||||
if( g_bReliable )
|
||||
_tcscat( strTitle, TEXT(" Reliable |") );
|
||||
if( g_bAsync )
|
||||
_tcscat( strTitle, TEXT(" Async |") );
|
||||
}
|
||||
|
||||
// Change window title
|
||||
SetWindowText( g_hwndMain, strTitle );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: DoHelp()
|
||||
// Desc: Display a Help summary in a message box.
|
||||
//-----------------------------------------------------------------------------
|
||||
VOID DoHelp()
|
||||
{
|
||||
TCHAR strHelpMsg[MAX_HELPMSG];
|
||||
LoadString( g_hInst, IDS_DUEL_HELP, strHelpMsg, MAX_HELPMSG );
|
||||
MessageBox( g_hwndMain, strHelpMsg, TEXT("DUEL"), MB_OK );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: ReadRegKey()
|
||||
// Desc: Read a registry key
|
||||
//-----------------------------------------------------------------------------
|
||||
HRESULT ReadRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue,
|
||||
DWORD dwLength, TCHAR* strDefault )
|
||||
{
|
||||
DWORD dwType;
|
||||
LONG bResult;
|
||||
|
||||
bResult = RegQueryValueEx( hKey, strName, 0, &dwType,
|
||||
(LPBYTE) strValue, &dwLength );
|
||||
if ( bResult != ERROR_SUCCESS )
|
||||
strcpy( strValue, strDefault );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Name: WriteRegKey()
|
||||
// Desc: Writes a registry key
|
||||
//-----------------------------------------------------------------------------
|
||||
HRESULT WriteRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue )
|
||||
{
|
||||
LONG bResult;
|
||||
|
||||
bResult = RegSetValueEx( hKey, strName, 0, REG_SZ,
|
||||
(LPBYTE) strValue, strlen(strValue) + 1 );
|
||||
if ( bResult != ERROR_SUCCESS )
|
||||
return E_FAIL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user